235get_format(
bool support_normals)
const {
237 (InternalName::get_vertex(), 3, Geom::NT_stdfloat,
241 array_format->add_column
242 (InternalName::get_normal(), 3, Geom::NT_stdfloat,
246 array_format->add_column
247 (InternalName::get_color(), 1, Geom::NT_packed_dabc,
251 array_format->add_column
252 (InternalName::get_texcoord(), 2, Geom::NT_stdfloat,
256 return GeomVertexFormat::register_format(array_format);
263do_recompute_bounds(
const NodePath &rel_to,
int pipeline_stage,
264 Thread *current_thread)
const {
273 if (curve !=
nullptr) {
275 get_curve()->get_vertices(verts, rel_to);
280 NurbsCurveEvaluator::Vert3Array::iterator vi;
281 for (vi = verts.begin(); vi != verts.end(); ++vi) {
282 (*vi) = LPoint3(*vi) * mat;
287 DCAST_INTO_R(gbv, bound, bound);
288 gbv->
around(&verts[0], &verts[0] + verts.size());
306 CurveSegments curve_segments;
307 int num_curve_verts = get_connected_segments(curve_segments, result);
312 (
"rope", get_format(
false), Geom::UH_stream);
313 compute_thread_vertices(vdata, curve_segments, num_curve_verts);
318 lines->reserve_num_vertices((num_curve_verts - 1) * 2);
320 for (
int vi = 0; vi < num_curve_verts - 1; ++vi) {
321 lines->add_vertex(vi);
322 lines->add_vertex(vi + 1);
323 lines->close_primitive();
327 geom->add_primitive(lines);
330 CPT(
RenderState) state = data._state->add_attrib(thick);
332 state = state->add_attrib(ColorAttrib::make_vertex());
337 data.get_internal_transform(trav));
351 CurveSegments curve_segments;
352 int num_curve_verts = get_connected_segments(curve_segments, result);
357 (
"rope", get_format(
false), Geom::UH_stream);
360 curve_segments, num_curve_verts, result);
365 CurveSegments::const_iterator si;
366 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
367 const CurveSegment &segment = (*si);
369 strip->add_next_vertices(segment.size() * 2);
370 strip->close_primitive();
374 geom->add_primitive(strip);
378 state = state->add_attrib(ColorAttrib::make_vertex());
383 data.get_internal_transform(trav));
397 const TransformState *net_transform = data.get_net_transform(trav);
401 net_transform->invert_compose(camera_transform);
402 LVector3 camera_vec = LVector3::forward() * rel_transform->
get_mat();
404 CurveSegments curve_segments;
405 int num_curve_verts = get_connected_segments(curve_segments, result);
410 (
"rope", get_format(
false), Geom::UH_stream);
412 compute_billboard_vertices(vdata, camera_vec,
413 curve_segments, num_curve_verts, result);
418 CurveSegments::const_iterator si;
419 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
420 const CurveSegment &segment = (*si);
422 strip->add_next_vertices(segment.size() * 2);
423 strip->close_primitive();
427 geom->add_primitive(strip);
431 state = state->add_attrib(ColorAttrib::make_vertex());
436 data.get_internal_transform(trav));
450 CurveSegments curve_segments;
451 int num_curve_verts = get_connected_segments(curve_segments, result);
457 int num_verts_per_slice;
460 (
"rope", get_format(
true), Geom::UH_stream);
462 compute_tube_vertices(vdata, num_verts_per_slice,
463 curve_segments, num_curve_verts, result);
470 CurveSegments::const_iterator si;
471 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
472 const CurveSegment &segment = (*si);
474 for (
int s = 0; s < num_slices; ++s) {
475 int s1 = (s + 1) % num_verts_per_slice;
477 for (
size_t j = 0; j < segment.size(); ++j) {
478 strip->add_vertex((vi + j) * num_verts_per_slice + s);
479 strip->add_vertex((vi + j) * num_verts_per_slice + s1);
482 strip->close_primitive();
484 vi += (int)segment.size();
488 geom->add_primitive(strip);
492 state = state->add_attrib(ColorAttrib::make_vertex());
497 data.get_internal_transform(trav));
515 int num_curve_verts = 0;
522 CurveSegment *curve_segment =
nullptr;
525 for (
int segment = 0; segment < num_segments; ++segment) {
531#ifdef STDFLOAT_DOUBLE
532 static const double threshold = 1.0e-8;
534 static const float threshold = 1.0e-4f;
537 if (curve_segment ==
nullptr ||
538 !point.almost_equal(last_point, threshold)) {
542 curve_segments.push_back(CurveSegment());
543 curve_segment = &curve_segments.back();
548 if (use_vertex_color) {
553 if (use_vertex_thickness) {
559 curve_segment->push_back(vtx);
564 for (
int i = 1; i < num_verts; ++i) {
565 PN_stdfloat t = (PN_stdfloat)i / (PN_stdfloat)(num_verts - 1);
570 if (use_vertex_color) {
575 if (use_vertex_thickness) {
581 curve_segment->push_back(vtx);
588 return num_curve_verts;
598 int num_curve_verts)
const {
610 PN_stdfloat dist = 0.0f;
611 CurveSegments::const_iterator si;
612 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
613 const CurveSegment &segment = (*si);
614 for (
size_t j = 0; j < segment.size(); ++j) {
615 vertex.add_data3(segment[j]._p);
617 if (use_vertex_color) {
618 color.add_data4(segment[j]._c);
621 PN_stdfloat uv_t = compute_uv_t(dist, uv_mode, uv_scale, segment, j);
623 if (uv_mode != UV_none) {
625 texcoord.add_data2(uv_t, 0.0f);
627 texcoord.add_data2(0.0f, uv_t);
642 const LVector3 &camera_vec,
646 int expected_num_verts = num_curve_verts * 2;
654 PN_stdfloat overall_radius = thickness * 0.5f;
655 PN_stdfloat radius = overall_radius;
662 PN_stdfloat dist = 0.0f;
663 CurveSegments::const_iterator si;
664 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
665 const CurveSegment &segment = (*si);
666 for (
size_t j = 0; j < segment.size(); ++j) {
668 compute_tangent(tangent, segment, j, result);
670 LVector3 norm = cross(tangent, camera_vec);
673 if (use_vertex_thickness) {
674 radius = overall_radius * segment[j]._thickness;
677 vertex.add_data3(segment[j]._p + norm * radius);
678 vertex.add_data3(segment[j]._p - norm * radius);
680 if (use_vertex_color) {
681 color.add_data4(segment[j]._c);
682 color.add_data4(segment[j]._c);
685 PN_stdfloat uv_t = compute_uv_t(dist, uv_mode, uv_scale, segment, j);
687 if (uv_mode != UV_none) {
689 texcoord.add_data2(uv_t, 1.0f);
690 texcoord.add_data2(uv_t, 0.0f);
692 texcoord.add_data2(1.0f, uv_t);
693 texcoord.add_data2(0.0f, uv_t);
708 int &num_verts_per_slice,
713 num_verts_per_slice = num_slices;
716 PN_stdfloat overall_radius = thickness * 0.5f;
717 PN_stdfloat radius = overall_radius;
728 if (uv_mode != UV_none) {
729 ++num_verts_per_slice;
732 int expected_num_verts = num_curve_verts * num_verts_per_slice;
742 PN_stdfloat dist = 0.0f;
743 CurveSegments::const_iterator si;
744 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
745 const CurveSegment &segment = (*si);
746 for (
size_t j = 0; j < segment.size(); ++j) {
748 compute_tangent(tangent, segment, j, result);
750 LVector3 norm = cross(tangent, up);
754 if (IS_NEARLY_ZERO(norm.length_squared())) {
756 if (IS_NEARLY_ZERO(tangent.get_y()) && IS_NEARLY_ZERO(tangent.get_z())) {
758 norm = cross(tangent, LVector3(0, 1, 0));
760 norm = cross(tangent, LVector3(1, 0, 0));
765 up = cross(norm, tangent);
767 LMatrix3 rotate = LMatrix3::rotate_mat(360.0f / (PN_stdfloat)num_slices,
770 PN_stdfloat uv_t = compute_uv_t(dist, uv_mode, uv_scale, segment, j);
772 for (
int s = 0; s < num_verts_per_slice; ++s) {
773 if (use_vertex_thickness) {
774 radius = overall_radius * segment[j]._thickness;
777 vertex.add_data3(segment[j]._p + norm * radius);
779 if (normal_mode == NM_vertex) {
780 normal.add_data3(norm);
783 if (use_vertex_color) {
784 color.add_data4(segment[j]._c);
787 norm = norm * rotate;
789 if (uv_mode != UV_none) {
790 PN_stdfloat uv_s = (PN_stdfloat)s / (PN_stdfloat)num_slices;
792 texcoord.add_data2(uv_t, uv_s);
794 texcoord.add_data2(uv_s, uv_t);
827 tangent = segment[j + 1]._p - segment[j]._p;
828 }
else if (j == segment.size() - 1) {
829 tangent = segment[j]._p - segment[j - 1]._p;
831 tangent = segment[j + 1]._p - segment[j - 1]._p;
836 if (IS_NEARLY_ZERO(tangent.length_squared())) {
837 tangent.set(0, 0, 1);