00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "ropeNode.h"
00016 #include "cullTraverser.h"
00017 #include "cullTraverserData.h"
00018 #include "cullableObject.h"
00019 #include "cullHandler.h"
00020 #include "renderState.h"
00021 #include "renderModeAttrib.h"
00022 #include "colorAttrib.h"
00023 #include "bamWriter.h"
00024 #include "bamReader.h"
00025 #include "datagram.h"
00026 #include "datagramIterator.h"
00027 #include "pStatTimer.h"
00028 #include "geom.h"
00029 #include "geomLines.h"
00030 #include "geomTristrips.h"
00031 #include "geomVertexWriter.h"
00032 #include "boundingSphere.h"
00033
00034 TypeHandle RopeNode::_type_handle;
00035
00036 PStatCollector RopeNode::_rope_node_pcollector("*:RopeNode");
00037
00038
00039
00040
00041
00042
00043 CycleData *RopeNode::CData::
00044 make_copy() const {
00045 return new CData(*this);
00046 }
00047
00048
00049
00050
00051
00052
00053
00054 void RopeNode::CData::
00055 write_datagram(BamWriter *writer, Datagram &dg) const {
00056
00057
00058 writer->write_pointer(dg, (TypedWritable *)NULL);
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068 void RopeNode::CData::
00069 fillin(DatagramIterator &scan, BamReader *reader) {
00070
00071 reader->skip_pointer(scan);
00072 }
00073
00074
00075
00076
00077
00078
00079 RopeNode::
00080 RopeNode(const string &name) :
00081 PandaNode(name)
00082 {
00083 set_cull_callback();
00084 }
00085
00086
00087
00088
00089
00090
00091 RopeNode::
00092 RopeNode(const RopeNode ©) :
00093 PandaNode(copy),
00094 _cycler(copy._cycler)
00095 {
00096 }
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 PandaNode *RopeNode::
00107 make_copy() const {
00108 return new RopeNode(*this);
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 bool RopeNode::
00120 safe_to_transform() const {
00121 return false;
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 bool RopeNode::
00150 cull_callback(CullTraverser *trav, CullTraverserData &data) {
00151
00152 PStatTimer timer(_rope_node_pcollector);
00153
00154
00155 if (get_num_subdiv() > 0) {
00156 NurbsCurveEvaluator *curve = get_curve();
00157 if (curve != (NurbsCurveEvaluator *)NULL) {
00158 PT(NurbsCurveResult) result;
00159 if (has_matrix()) {
00160 result = curve->evaluate(data._node_path.get_node_path(), get_matrix());
00161 } else {
00162 result = curve->evaluate(data._node_path.get_node_path());
00163 }
00164
00165 if (result->get_num_segments() > 0) {
00166 switch (get_render_mode()) {
00167 case RM_thread:
00168 render_thread(trav, data, result);
00169 break;
00170
00171 case RM_tape:
00172 render_tape(trav, data, result);
00173 break;
00174
00175 case RM_billboard:
00176 render_billboard(trav, data, result);
00177 break;
00178
00179 case RM_tube:
00180 render_tube(trav, data, result);
00181 break;
00182 }
00183 }
00184 }
00185 }
00186
00187 return true;
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 bool RopeNode::
00201 is_renderable() const {
00202 return true;
00203 }
00204
00205
00206
00207
00208
00209
00210 void RopeNode::
00211 output(ostream &out) const {
00212 PandaNode::output(out);
00213 NurbsCurveEvaluator *curve = get_curve();
00214 if (curve != (NurbsCurveEvaluator *)NULL) {
00215 out << " " << *curve;
00216 } else {
00217 out << " (no curve)";
00218 }
00219 }
00220
00221
00222
00223
00224
00225
00226 void RopeNode::
00227 write(ostream &out, int indent_level) const {
00228 PandaNode::write(out, indent_level);
00229 indent(out, indent_level) << *get_curve() << "\n";
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 void RopeNode::
00241 reset_bound(const NodePath &rel_to) {
00242 Thread *current_thread = Thread::get_current_thread();
00243 int pipeline_stage = current_thread->get_pipeline_stage();
00244 do_recompute_bounds(rel_to, pipeline_stage, current_thread);
00245 mark_internal_bounds_stale(current_thread);
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 void RopeNode::
00257 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
00258 int &internal_vertices,
00259 int pipeline_stage,
00260 Thread *current_thread) const {
00261 PT(BoundingVolume) bounds =
00262 do_recompute_bounds(NodePath((PandaNode *)this), pipeline_stage,
00263 current_thread);
00264
00265 internal_bounds = bounds;
00266 internal_vertices = 0;
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276 CPT(GeomVertexFormat) RopeNode::
00277 get_format(bool support_normals) const {
00278 PT(GeomVertexArrayFormat) array_format = new GeomVertexArrayFormat
00279 (InternalName::get_vertex(), 3, Geom::NT_stdfloat,
00280 Geom::C_point);
00281
00282 if (support_normals && get_normal_mode() == NM_vertex) {
00283 array_format->add_column
00284 (InternalName::get_normal(), 3, Geom::NT_stdfloat,
00285 Geom::C_vector);
00286 }
00287 if (get_use_vertex_color()) {
00288 array_format->add_column
00289 (InternalName::get_color(), 1, Geom::NT_packed_dabc,
00290 Geom::C_color);
00291 }
00292 if (get_uv_mode() != UV_none) {
00293 array_format->add_column
00294 (InternalName::get_texcoord(), 2, Geom::NT_stdfloat,
00295 Geom::C_texcoord);
00296 }
00297
00298 return GeomVertexFormat::register_format(array_format);
00299 }
00300
00301
00302
00303
00304
00305
00306 PT(BoundingVolume) RopeNode::
00307 do_recompute_bounds(const NodePath &rel_to, int pipeline_stage,
00308 Thread *current_thread) const {
00309
00310
00311
00312
00313
00314 PT(BoundingVolume) bound = new BoundingSphere;
00315
00316 NurbsCurveEvaluator *curve = get_curve();
00317 if (curve != (NurbsCurveEvaluator *)NULL) {
00318 NurbsCurveEvaluator::Vert3Array verts;
00319 get_curve()->get_vertices(verts, rel_to);
00320
00321 if (has_matrix()) {
00322
00323 const LMatrix4 &mat = get_matrix();
00324 NurbsCurveEvaluator::Vert3Array::iterator vi;
00325 for (vi = verts.begin(); vi != verts.end(); ++vi) {
00326 (*vi) = LPoint3(*vi) * mat;
00327 }
00328 }
00329
00330 GeometricBoundingVolume *gbv;
00331 DCAST_INTO_R(gbv, bound, bound);
00332 gbv->around(&verts[0], &verts[0] + verts.size());
00333 }
00334 return bound;
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 void RopeNode::
00352 render_thread(CullTraverser *trav, CullTraverserData &data,
00353 NurbsCurveResult *result) const {
00354 CurveSegments curve_segments;
00355 int num_curve_verts = get_connected_segments(curve_segments, result);
00356
00357
00358
00359 PT(GeomVertexData) vdata = new GeomVertexData
00360 ("rope", get_format(false), Geom::UH_stream);
00361 compute_thread_vertices(vdata, curve_segments, num_curve_verts);
00362
00363
00364
00365 PT(GeomLines) lines = new GeomLines(Geom::UH_stream);
00366 lines->reserve_num_vertices((num_curve_verts - 1) * 2);
00367
00368 for (int vi = 0; vi < num_curve_verts - 1; ++vi) {
00369 lines->add_vertex(vi);
00370 lines->add_vertex(vi + 1);
00371 lines->close_primitive();
00372 }
00373
00374 PT(Geom) geom = new Geom(vdata);
00375 geom->add_primitive(lines);
00376
00377 CPT(RenderAttrib) thick = RenderModeAttrib::make(RenderModeAttrib::M_unchanged, get_thickness());
00378 CPT(RenderState) state = data._state->add_attrib(thick);
00379 if (get_use_vertex_color()) {
00380 state = state->add_attrib(ColorAttrib::make_vertex());
00381 }
00382
00383 CullableObject *object =
00384 new CullableObject(geom, state,
00385 data.get_net_transform(trav),
00386 data.get_modelview_transform(trav),
00387 trav->get_gsg());
00388 trav->get_cull_handler()->record_object(object, trav);
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 void RopeNode::
00402 render_tape(CullTraverser *trav, CullTraverserData &data,
00403 NurbsCurveResult *result) const {
00404 CurveSegments curve_segments;
00405 int num_curve_verts = get_connected_segments(curve_segments, result);
00406
00407
00408
00409
00410 PT(GeomVertexData) vdata = new GeomVertexData
00411 ("rope", get_format(false), Geom::UH_stream);
00412
00413 compute_billboard_vertices(vdata, -get_tube_up(),
00414 curve_segments, num_curve_verts, result);
00415
00416
00417
00418 PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream);
00419 CurveSegments::const_iterator si;
00420 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
00421 const CurveSegment &segment = (*si);
00422
00423 strip->add_next_vertices(segment.size() * 2);
00424 strip->close_primitive();
00425 }
00426
00427 PT(Geom) geom = new Geom(vdata);
00428 geom->add_primitive(strip);
00429
00430 CPT(RenderState) state = data._state;
00431 if (get_use_vertex_color()) {
00432 state = state->add_attrib(ColorAttrib::make_vertex());
00433 }
00434
00435 CullableObject *object =
00436 new CullableObject(geom, state,
00437 data.get_net_transform(trav),
00438 data.get_modelview_transform(trav),
00439 trav->get_gsg());
00440 trav->get_cull_handler()->record_object(object, trav);
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 void RopeNode::
00454 render_billboard(CullTraverser *trav, CullTraverserData &data,
00455 NurbsCurveResult *result) const {
00456 const TransformState *net_transform = data.get_net_transform(trav);
00457 const TransformState *camera_transform = trav->get_camera_transform();
00458
00459 CPT(TransformState) rel_transform =
00460 net_transform->invert_compose(camera_transform);
00461 LVector3 camera_vec = LVector3::forward() * rel_transform->get_mat();
00462
00463 CurveSegments curve_segments;
00464 int num_curve_verts = get_connected_segments(curve_segments, result);
00465
00466
00467
00468
00469 PT(GeomVertexData) vdata = new GeomVertexData
00470 ("rope", get_format(false), Geom::UH_stream);
00471
00472 compute_billboard_vertices(vdata, camera_vec,
00473 curve_segments, num_curve_verts, result);
00474
00475
00476
00477 PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream);
00478 CurveSegments::const_iterator si;
00479 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
00480 const CurveSegment &segment = (*si);
00481
00482 strip->add_next_vertices(segment.size() * 2);
00483 strip->close_primitive();
00484 }
00485
00486 PT(Geom) geom = new Geom(vdata);
00487 geom->add_primitive(strip);
00488
00489 CPT(RenderState) state = data._state;
00490 if (get_use_vertex_color()) {
00491 state = state->add_attrib(ColorAttrib::make_vertex());
00492 }
00493
00494 CullableObject *object =
00495 new CullableObject(geom, state,
00496 data.get_net_transform(trav),
00497 data.get_modelview_transform(trav),
00498 trav->get_gsg());
00499 trav->get_cull_handler()->record_object(object, trav);
00500 }
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 void RopeNode::
00512 render_tube(CullTraverser *trav, CullTraverserData &data,
00513 NurbsCurveResult *result) const {
00514 CurveSegments curve_segments;
00515 int num_curve_verts = get_connected_segments(curve_segments, result);
00516
00517
00518
00519
00520 int num_slices = get_num_slices();
00521 int num_verts_per_slice;
00522
00523 PT(GeomVertexData) vdata = new GeomVertexData
00524 ("rope", get_format(true), Geom::UH_stream);
00525
00526 compute_tube_vertices(vdata, num_verts_per_slice,
00527 curve_segments, num_curve_verts, result);
00528
00529
00530
00531
00532
00533 PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream);
00534 int vi = 0;
00535 CurveSegments::const_iterator si;
00536 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
00537 const CurveSegment &segment = (*si);
00538
00539 for (int s = 0; s < num_slices; ++s) {
00540 int s1 = (s + 1) % num_verts_per_slice;
00541
00542 for (size_t j = 0; j < segment.size(); ++j) {
00543 strip->add_vertex((vi + j) * num_verts_per_slice + s);
00544 strip->add_vertex((vi + j) * num_verts_per_slice + s1);
00545 }
00546
00547 strip->close_primitive();
00548 }
00549 vi += (int)segment.size();
00550 }
00551
00552 PT(Geom) geom = new Geom(vdata);
00553 geom->add_primitive(strip);
00554
00555 CPT(RenderState) state = data._state;
00556 if (get_use_vertex_color()) {
00557 state = state->add_attrib(ColorAttrib::make_vertex());
00558 }
00559
00560 CullableObject *object =
00561 new CullableObject(geom, state,
00562 data.get_net_transform(trav),
00563 data.get_modelview_transform(trav),
00564 trav->get_gsg());
00565 trav->get_cull_handler()->record_object(object, trav);
00566 }
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 int RopeNode::
00585 get_connected_segments(RopeNode::CurveSegments &curve_segments,
00586 const NurbsCurveResult *result) const {
00587 int num_curve_verts = 0;
00588
00589 int num_verts = get_num_subdiv() + 1;
00590 int num_segments = result->get_num_segments();
00591 bool use_vertex_color = get_use_vertex_color();
00592 bool use_vertex_thickness = get_use_vertex_thickness();
00593
00594 CurveSegment *curve_segment = NULL;
00595 LPoint3 last_point;
00596
00597 for (int segment = 0; segment < num_segments; ++segment) {
00598 LPoint3 point;
00599 result->eval_segment_point(segment, 0.0f, point);
00600
00601 if (curve_segment == (CurveSegment *)NULL ||
00602 !point.almost_equal(last_point)) {
00603
00604
00605
00606 curve_segments.push_back(CurveSegment());
00607 curve_segment = &curve_segments.back();
00608
00609 CurveVertex vtx;
00610 vtx._p = point;
00611 vtx._t = result->get_segment_t(segment, 0.0f);
00612 if (use_vertex_color) {
00613 result->eval_segment_extended_points(segment, 0.0f,
00614 get_vertex_color_dimension(),
00615 &vtx._c[0], 4);
00616 }
00617 if (use_vertex_thickness) {
00618 vtx._thickness =
00619 result->eval_segment_extended_point(segment, 0.0f,
00620 get_vertex_thickness_dimension());
00621 }
00622
00623 curve_segment->push_back(vtx);
00624 ++num_curve_verts;
00625 }
00626
00627
00628 for (int i = 1; i < num_verts; ++i) {
00629 PN_stdfloat t = (PN_stdfloat)i / (PN_stdfloat)(num_verts - 1);
00630
00631 CurveVertex vtx;
00632 result->eval_segment_point(segment, t, vtx._p);
00633 vtx._t = result->get_segment_t(segment, t);
00634 if (use_vertex_color) {
00635 result->eval_segment_extended_points(segment, t,
00636 get_vertex_color_dimension(),
00637 &vtx._c[0], 4);
00638 }
00639 if (use_vertex_thickness) {
00640 vtx._thickness =
00641 result->eval_segment_extended_point(segment, t,
00642 get_vertex_thickness_dimension());
00643 }
00644
00645 curve_segment->push_back(vtx);
00646 ++num_curve_verts;
00647
00648 last_point = vtx._p;
00649 }
00650 }
00651
00652 return num_curve_verts;
00653 }
00654
00655
00656
00657
00658
00659
00660
00661
00662 void RopeNode::
00663 compute_thread_vertices(GeomVertexData *vdata,
00664 const RopeNode::CurveSegments &curve_segments,
00665 int num_curve_verts) const {
00666 vdata->set_num_rows(num_curve_verts);
00667
00668 GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00669 GeomVertexWriter color(vdata, InternalName::get_color());
00670 GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
00671
00672 UVMode uv_mode = get_uv_mode();
00673 PN_stdfloat uv_scale = get_uv_scale();
00674 bool u_dominant = get_uv_direction();
00675 bool use_vertex_color = get_use_vertex_color();
00676
00677 PN_stdfloat dist = 0.0f;
00678 CurveSegments::const_iterator si;
00679 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
00680 const CurveSegment &segment = (*si);
00681 for (size_t j = 0; j < segment.size(); ++j) {
00682 vertex.add_data3(segment[j]._p);
00683
00684 if (use_vertex_color) {
00685 color.add_data4(segment[j]._c);
00686 }
00687
00688 PN_stdfloat uv_t = compute_uv_t(dist, uv_mode, uv_scale, segment, j);
00689
00690 if (uv_mode != UV_none) {
00691 if (u_dominant) {
00692 texcoord.add_data2(uv_t, 0.0f);
00693 } else {
00694 texcoord.add_data2(0.0f, uv_t);
00695 }
00696 }
00697 }
00698 }
00699
00700 nassertv(vdata->get_num_rows() == num_curve_verts);
00701 }
00702
00703
00704
00705
00706
00707
00708
00709
00710 void RopeNode::
00711 compute_billboard_vertices(GeomVertexData *vdata,
00712 const LVector3 &camera_vec,
00713 const RopeNode::CurveSegments &curve_segments,
00714 int num_curve_verts,
00715 NurbsCurveResult *result) const {
00716 int expected_num_verts = num_curve_verts * 2;
00717 vdata->set_num_rows(expected_num_verts);
00718
00719 GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00720 GeomVertexWriter color(vdata, InternalName::get_color());
00721 GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
00722
00723 PN_stdfloat thickness = get_thickness();
00724 PN_stdfloat overall_radius = thickness * 0.5f;
00725 PN_stdfloat radius = overall_radius;
00726 UVMode uv_mode = get_uv_mode();
00727 PN_stdfloat uv_scale = get_uv_scale();
00728 bool u_dominant = get_uv_direction();
00729 bool use_vertex_color = get_use_vertex_color();
00730 bool use_vertex_thickness = get_use_vertex_thickness();
00731
00732 PN_stdfloat dist = 0.0f;
00733 CurveSegments::const_iterator si;
00734 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
00735 const CurveSegment &segment = (*si);
00736 for (size_t j = 0; j < segment.size(); ++j) {
00737 LVector3 tangent;
00738 compute_tangent(tangent, segment, j, result);
00739
00740 LVector3 norm = cross(tangent, camera_vec);
00741 norm.normalize();
00742
00743 if (use_vertex_thickness) {
00744 radius = overall_radius * segment[j]._thickness;
00745 }
00746
00747 vertex.add_data3(segment[j]._p + norm * radius);
00748 vertex.add_data3(segment[j]._p - norm * radius);
00749
00750 if (use_vertex_color) {
00751 color.add_data4(segment[j]._c);
00752 color.add_data4(segment[j]._c);
00753 }
00754
00755 PN_stdfloat uv_t = compute_uv_t(dist, uv_mode, uv_scale, segment, j);
00756
00757 if (uv_mode != UV_none) {
00758 if (u_dominant) {
00759 texcoord.add_data2(uv_t, 1.0f);
00760 texcoord.add_data2(uv_t, 0.0f);
00761 } else {
00762 texcoord.add_data2(1.0f, uv_t);
00763 texcoord.add_data2(0.0f, uv_t);
00764 }
00765 }
00766 }
00767 }
00768
00769 nassertv(vdata->get_num_rows() == expected_num_verts);
00770 }
00771
00772
00773
00774
00775
00776
00777
00778
00779 void RopeNode::
00780 compute_tube_vertices(GeomVertexData *vdata,
00781 int &num_verts_per_slice,
00782 const RopeNode::CurveSegments &curve_segments,
00783 int num_curve_verts,
00784 NurbsCurveResult *result) const {
00785 int num_slices = get_num_slices();
00786 num_verts_per_slice = num_slices;
00787
00788 PN_stdfloat thickness = get_thickness();
00789 PN_stdfloat overall_radius = thickness * 0.5f;
00790 PN_stdfloat radius = overall_radius;
00791 UVMode uv_mode = get_uv_mode();
00792 PN_stdfloat uv_scale = get_uv_scale();
00793 bool u_dominant = get_uv_direction();
00794 NormalMode normal_mode = get_normal_mode();
00795 bool use_vertex_color = get_use_vertex_color();
00796 bool use_vertex_thickness = get_use_vertex_thickness();
00797
00798
00799
00800
00801 if (uv_mode != UV_none) {
00802 ++num_verts_per_slice;
00803 }
00804
00805 int expected_num_verts = num_curve_verts * num_verts_per_slice;
00806 vdata->set_num_rows(expected_num_verts);
00807
00808 GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00809 GeomVertexWriter normal(vdata, InternalName::get_normal());
00810 GeomVertexWriter color(vdata, InternalName::get_color());
00811 GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
00812
00813 LVector3 up = get_tube_up();
00814
00815 PN_stdfloat dist = 0.0f;
00816 CurveSegments::const_iterator si;
00817 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
00818 const CurveSegment &segment = (*si);
00819 for (size_t j = 0; j < segment.size(); ++j) {
00820 LVector3 tangent;
00821 compute_tangent(tangent, segment, j, result);
00822
00823 LVector3 norm = cross(tangent, up);
00824 norm.normalize();
00825 up = cross(norm, tangent);
00826
00827 LMatrix3 rotate = LMatrix3::rotate_mat(360.0f / (PN_stdfloat)num_slices,
00828 tangent);
00829
00830 PN_stdfloat uv_t = compute_uv_t(dist, uv_mode, uv_scale, segment, j);
00831
00832 for (int s = 0; s < num_verts_per_slice; ++s) {
00833 if (use_vertex_thickness) {
00834 radius = overall_radius * segment[j]._thickness;
00835 }
00836
00837 vertex.add_data3(segment[j]._p + norm * radius);
00838
00839 if (normal_mode == NM_vertex) {
00840 normal.add_data3(norm);
00841 }
00842
00843 if (use_vertex_color) {
00844 color.add_data4(segment[j]._c);
00845 }
00846
00847 norm = norm * rotate;
00848
00849 if (uv_mode != UV_none) {
00850 PN_stdfloat uv_s = (PN_stdfloat)s / (PN_stdfloat)num_slices;
00851 if (u_dominant) {
00852 texcoord.add_data2(uv_t, uv_s);
00853 } else {
00854 texcoord.add_data2(uv_s, uv_t);
00855 }
00856 }
00857 }
00858 }
00859 }
00860
00861 nassertv(vdata->get_num_rows() == expected_num_verts);
00862 }
00863
00864
00865
00866
00867
00868
00869
00870 void RopeNode::
00871 compute_tangent(LVector3 &tangent, const RopeNode::CurveSegment &segment,
00872 size_t j, NurbsCurveResult *result) {
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889 if (j == 0) {
00890 tangent = segment[j + 1]._p - segment[j]._p;
00891 } else if (j == segment.size() - 1) {
00892 tangent = segment[j]._p - segment[j - 1]._p;
00893 } else {
00894 tangent = segment[j + 1]._p - segment[j - 1]._p;
00895 }
00896 }
00897
00898
00899
00900
00901
00902
00903
00904 PN_stdfloat RopeNode::
00905 compute_uv_t(PN_stdfloat &dist, const RopeNode::UVMode &uv_mode,
00906 PN_stdfloat uv_scale, const RopeNode::CurveSegment &segment,
00907 size_t j) {
00908 switch (uv_mode) {
00909 case UV_none:
00910 return 0.0f;
00911
00912 case UV_parametric:
00913 return segment[j]._t * uv_scale;
00914
00915 case UV_distance:
00916 if (j != 0) {
00917 LVector3 vec = segment[j]._p - segment[j - 1]._p;
00918 dist += vec.length();
00919 }
00920 return dist * uv_scale;
00921
00922 case UV_distance2:
00923 if (j != 0) {
00924 LVector3 vec = segment[j]._p - segment[j - 1]._p;
00925 dist += vec.length_squared();
00926 }
00927 return dist * uv_scale;
00928 }
00929
00930 return 0.0f;
00931 }
00932
00933
00934
00935
00936
00937
00938
00939 void RopeNode::
00940 register_with_read_factory() {
00941 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00942 }
00943
00944
00945
00946
00947
00948
00949
00950 void RopeNode::
00951 write_datagram(BamWriter *manager, Datagram &dg) {
00952 PandaNode::write_datagram(manager, dg);
00953 manager->write_cdata(dg, _cycler);
00954 }
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964 TypedWritable *RopeNode::
00965 make_from_bam(const FactoryParams ¶ms) {
00966 RopeNode *node = new RopeNode("");
00967 DatagramIterator scan;
00968 BamReader *manager;
00969
00970 parse_params(params, scan, manager);
00971 node->fillin(scan, manager);
00972
00973 return node;
00974 }
00975
00976
00977
00978
00979
00980
00981
00982
00983 void RopeNode::
00984 fillin(DatagramIterator &scan, BamReader *manager) {
00985 PandaNode::fillin(scan, manager);
00986 manager->read_cdata(scan, _cycler);
00987 }