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) {
529 if (curve_segment ==
nullptr ||
530 !point.almost_equal(last_point)) {
534 curve_segments.push_back(CurveSegment());
535 curve_segment = &curve_segments.back();
540 if (use_vertex_color) {
545 if (use_vertex_thickness) {
551 curve_segment->push_back(vtx);
556 for (
int i = 1; i < num_verts; ++i) {
557 PN_stdfloat t = (PN_stdfloat)i / (PN_stdfloat)(num_verts - 1);
562 if (use_vertex_color) {
567 if (use_vertex_thickness) {
573 curve_segment->push_back(vtx);
580 return num_curve_verts;
590 int num_curve_verts)
const {
602 PN_stdfloat dist = 0.0f;
603 CurveSegments::const_iterator si;
604 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
605 const CurveSegment &segment = (*si);
606 for (
size_t j = 0; j < segment.size(); ++j) {
607 vertex.add_data3(segment[j]._p);
609 if (use_vertex_color) {
610 color.add_data4(segment[j]._c);
613 PN_stdfloat uv_t = compute_uv_t(dist, uv_mode, uv_scale, segment, j);
615 if (uv_mode != UV_none) {
617 texcoord.add_data2(uv_t, 0.0f);
619 texcoord.add_data2(0.0f, uv_t);
634 const LVector3 &camera_vec,
638 int expected_num_verts = num_curve_verts * 2;
646 PN_stdfloat overall_radius = thickness * 0.5f;
647 PN_stdfloat radius = overall_radius;
654 PN_stdfloat dist = 0.0f;
655 CurveSegments::const_iterator si;
656 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
657 const CurveSegment &segment = (*si);
658 for (
size_t j = 0; j < segment.size(); ++j) {
660 compute_tangent(tangent, segment, j, result);
662 LVector3 norm = cross(tangent, camera_vec);
665 if (use_vertex_thickness) {
666 radius = overall_radius * segment[j]._thickness;
669 vertex.add_data3(segment[j]._p + norm * radius);
670 vertex.add_data3(segment[j]._p - norm * radius);
672 if (use_vertex_color) {
673 color.add_data4(segment[j]._c);
674 color.add_data4(segment[j]._c);
677 PN_stdfloat uv_t = compute_uv_t(dist, uv_mode, uv_scale, segment, j);
679 if (uv_mode != UV_none) {
681 texcoord.add_data2(uv_t, 1.0f);
682 texcoord.add_data2(uv_t, 0.0f);
684 texcoord.add_data2(1.0f, uv_t);
685 texcoord.add_data2(0.0f, uv_t);
700 int &num_verts_per_slice,
705 num_verts_per_slice = num_slices;
708 PN_stdfloat overall_radius = thickness * 0.5f;
709 PN_stdfloat radius = overall_radius;
720 if (uv_mode != UV_none) {
721 ++num_verts_per_slice;
724 int expected_num_verts = num_curve_verts * num_verts_per_slice;
734 PN_stdfloat dist = 0.0f;
735 CurveSegments::const_iterator si;
736 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
737 const CurveSegment &segment = (*si);
738 for (
size_t j = 0; j < segment.size(); ++j) {
740 compute_tangent(tangent, segment, j, result);
742 LVector3 norm = cross(tangent, up);
746 if (IS_NEARLY_ZERO(norm.length_squared())) {
748 if (IS_NEARLY_ZERO(tangent.get_y()) && IS_NEARLY_ZERO(tangent.get_z())) {
750 norm = cross(tangent, LVector3(0, 1, 0));
752 norm = cross(tangent, LVector3(1, 0, 0));
757 up = cross(norm, tangent);
759 LMatrix3 rotate = LMatrix3::rotate_mat(360.0f / (PN_stdfloat)num_slices,
762 PN_stdfloat uv_t = compute_uv_t(dist, uv_mode, uv_scale, segment, j);
764 for (
int s = 0; s < num_verts_per_slice; ++s) {
765 if (use_vertex_thickness) {
766 radius = overall_radius * segment[j]._thickness;
769 vertex.add_data3(segment[j]._p + norm * radius);
771 if (normal_mode == NM_vertex) {
772 normal.add_data3(norm);
775 if (use_vertex_color) {
776 color.add_data4(segment[j]._c);
779 norm = norm * rotate;
781 if (uv_mode != UV_none) {
782 PN_stdfloat uv_s = (PN_stdfloat)s / (PN_stdfloat)num_slices;
784 texcoord.add_data2(uv_t, uv_s);
786 texcoord.add_data2(uv_s, uv_t);
819 tangent = segment[j + 1]._p - segment[j]._p;
820 }
else if (j == segment.size() - 1) {
821 tangent = segment[j]._p - segment[j - 1]._p;
823 tangent = segment[j + 1]._p - segment[j - 1]._p;
828 if (IS_NEARLY_ZERO(tangent.length_squared())) {
829 tangent.set(0, 0, 1);