00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "ropeNode.h"
00020 #include "cullTraverser.h"
00021 #include "cullTraverserData.h"
00022 #include "cullableObject.h"
00023 #include "cullHandler.h"
00024 #include "geomLinestrip.h"
00025 #include "geomTristrip.h"
00026 #include "bamWriter.h"
00027 #include "bamReader.h"
00028 #include "datagram.h"
00029 #include "datagramIterator.h"
00030
00031 TypeHandle RopeNode::_type_handle;
00032
00033
00034
00035
00036
00037
00038 CycleData *RopeNode::CData::
00039 make_copy() const {
00040 return new CData(*this);
00041 }
00042
00043
00044
00045
00046
00047
00048
00049 void RopeNode::CData::
00050 write_datagram(BamWriter *writer, Datagram &dg) const {
00051
00052
00053 writer->write_pointer(dg, (TypedWritable *)NULL);
00054 }
00055
00056
00057
00058
00059
00060
00061
00062
00063 void RopeNode::CData::
00064 fillin(DatagramIterator &scan, BamReader *reader) {
00065
00066 reader->skip_pointer(scan);
00067 }
00068
00069
00070
00071
00072
00073
00074 RopeNode::
00075 RopeNode(const string &name) :
00076 PandaNode(name)
00077 {
00078 }
00079
00080
00081
00082
00083
00084
00085 RopeNode::
00086 RopeNode(const RopeNode ©) :
00087 PandaNode(copy),
00088 _cycler(copy._cycler)
00089 {
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 PandaNode *RopeNode::
00101 make_copy() const {
00102 return new RopeNode(*this);
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 bool RopeNode::
00114 safe_to_transform() const {
00115 return false;
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 bool RopeNode::
00128 has_cull_callback() const {
00129 return true;
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 bool RopeNode::
00152 cull_callback(CullTraverser *trav, CullTraverserData &data) {
00153
00154 if (get_num_segs() > 0) {
00155 NurbsCurveEvaluator *curve = get_curve();
00156 PT(NurbsCurveResult) result = curve->evaluate(data._node_path.get_node_path());
00157
00158 if (result->get_num_segments() > 0) {
00159 switch (get_render_mode()) {
00160 case RM_thread:
00161 render_thread(trav, data, result);
00162 break;
00163
00164 case RM_billboard:
00165 render_billboard(trav, data, result);
00166 break;
00167 }
00168 }
00169 }
00170
00171 return true;
00172 }
00173
00174
00175
00176
00177
00178
00179 void RopeNode::
00180 output(ostream &out) const {
00181 PandaNode::output(out);
00182 out << " " << get_curve();
00183 }
00184
00185
00186
00187
00188
00189
00190 void RopeNode::
00191 write(ostream &out, int indent_level) const {
00192 PandaNode::write(out, indent_level);
00193 indent(out, indent_level) << get_curve() << "\n";
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 void RopeNode::
00205 reset_bound(const NodePath &rel_to) {
00206 do_recompute_bound(rel_to);
00207 changed_internal_bound();
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 BoundingVolume *RopeNode::
00219 recompute_internal_bound() {
00220 return do_recompute_bound(NodePath(this));
00221 }
00222
00223
00224
00225
00226
00227
00228 BoundingVolume *RopeNode::
00229 do_recompute_bound(const NodePath &rel_to) {
00230
00231 BoundingVolume *bound = PandaNode::recompute_internal_bound();
00232 nassertr(bound != (BoundingVolume *)NULL, bound);
00233
00234 NurbsCurveEvaluator *curve = get_curve();
00235 if (curve != (NurbsCurveEvaluator *)NULL) {
00236 pvector<LPoint3f> verts;
00237 get_curve()->get_vertices(verts, rel_to);
00238
00239 GeometricBoundingVolume *gbv;
00240 DCAST_INTO_R(gbv, bound, bound);
00241 gbv->around(&verts[0], &verts[verts.size() - 1]);
00242 }
00243 return bound;
00244 }
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 void RopeNode::
00260 render_thread(CullTraverser *trav, CullTraverserData &data,
00261 NurbsCurveResult *result) {
00262 UVMode uv_mode = get_uv_mode();
00263 LVecBase2f uv_scale = get_uv_scale();
00264
00265 PTA_Vertexf verts;
00266 PTA_TexCoordf uvs;
00267 PTA_Colorf colors;
00268 PTA_int lengths;
00269
00270 int num_verts = get_num_segs() + 1;
00271 int num_segments = result->get_num_segments();
00272 float dist = 0.0f;
00273 for (int segment = 0; segment < num_segments; segment++) {
00274 LPoint3f last_point;
00275 for (int i = 0; i < num_verts; i++) {
00276 float t = (float)i / (float)(num_verts - 1);
00277 LPoint3f point;
00278 result->eval_segment_point(segment, t, point);
00279 verts.push_back(point);
00280
00281 t = result->get_segment_t(segment, t);
00282 switch (uv_mode) {
00283 case UV_none:
00284 break;
00285
00286 case UV_parametric:
00287 uvs.push_back(TexCoordf(t * uv_scale[0], 0.0f));
00288 break;
00289
00290 case UV_distance:
00291 if (i != 0) {
00292 LVector3f vec = point - last_point;
00293 dist += vec.length();
00294 }
00295 uvs.push_back(TexCoordf(dist * uv_scale[0], 0.0f));
00296 break;
00297
00298 case UV_distance2:
00299 if (i != 0) {
00300 LVector3f vec = point - last_point;
00301 dist += vec.length_squared();
00302 }
00303 uvs.push_back(TexCoordf(dist * uv_scale[0], 0.0f));
00304 break;
00305 }
00306
00307 last_point = point;
00308 }
00309 lengths.push_back(num_verts);
00310 }
00311
00312 colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f));
00313
00314 PT(GeomLinestrip) geom = new GeomLinestrip;
00315 geom->set_width(get_thickness());
00316 geom->set_num_prims(num_segments);
00317 geom->set_coords(verts);
00318 if (uv_mode != UV_none) {
00319 geom->set_texcoords(uvs, G_PER_VERTEX);
00320 }
00321 geom->set_colors(colors, G_OVERALL);
00322 geom->set_lengths(lengths);
00323
00324 CullableObject *object = new CullableObject(geom, data._state,
00325 data._render_transform);
00326 trav->get_cull_handler()->record_object(object);
00327 }
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 void RopeNode::
00340 render_billboard(CullTraverser *trav, CullTraverserData &data,
00341 NurbsCurveResult *result) {
00342 const TransformState *net_transform = data._net_transform;
00343 const TransformState *camera_transform = trav->get_camera_transform();
00344
00345 CPT(TransformState) rel_transform =
00346 net_transform->invert_compose(camera_transform);
00347 LVector3f camera_vec = LVector3f::forward() * rel_transform->get_mat();
00348
00349 float thickness = get_thickness();
00350 float radius = thickness * 0.5f;
00351 UVMode uv_mode = get_uv_mode();
00352 LVecBase2f uv_scale = get_uv_scale();
00353
00354
00355
00356
00357
00358 int num_verts = get_num_segs() + 1;
00359 int num_segments = result->get_num_segments();
00360
00361 vector_Vertexf center_verts;
00362 vector_int center_lengths;
00363 vector_float center_t;
00364
00365 LPoint3f point;
00366 int cur_length = 0;
00367 for (int segment = 0; segment < num_segments; segment++) {
00368 LPoint3f first_point;
00369 result->eval_segment_point(segment, 0.0f, first_point);
00370 if (cur_length == 0 || point != first_point) {
00371
00372
00373
00374 if (cur_length != 0) {
00375 center_lengths.push_back(cur_length);
00376 }
00377 center_verts.push_back(first_point);
00378 center_t.push_back(result->get_segment_t(segment, 0.0f));
00379 cur_length = 1;
00380 }
00381
00382
00383 for (int i = 1; i < num_verts; i++) {
00384 float t = (float)i / (float)(num_verts - 1);
00385 result->eval_segment_point(segment, t, point);
00386 center_verts.push_back(point);
00387 center_t.push_back(result->get_segment_t(segment, t));
00388 cur_length++;
00389 }
00390 }
00391 if (cur_length != 0) {
00392 center_lengths.push_back(cur_length);
00393 }
00394
00395
00396
00397
00398 PTA_Vertexf verts;
00399 PTA_TexCoordf uvs;
00400 PTA_Colorf colors;
00401 PTA_int lengths;
00402
00403 int vi = 0;
00404 int num_prims = 0;
00405 float dist = 0.0f;
00406 for (int i = 0; i < (int)center_lengths.size(); i++) {
00407 int length = center_lengths[i];
00408 for (int j = 0; j < length; j++) {
00409 const Vertexf &point = center_verts[vi + j];
00410 float t = center_t[vi + j];
00411 LVector3f tangent;
00412
00413
00414
00415
00416 if (j == 0) {
00417 tangent = center_verts[vi + j + 1] - point;
00418 } else if (j == length - 1) {
00419 tangent = point - center_verts[vi + j - 1];
00420 } else {
00421 tangent = center_verts[vi + j + 1] - center_verts[vi + j - 1];
00422 }
00423 LVector3f cross = normalize(tangent.cross(camera_vec));
00424 cross *= radius;
00425 verts.push_back(point + cross);
00426 verts.push_back(point - cross);
00427 switch (uv_mode) {
00428 case UV_none:
00429 break;
00430
00431 case UV_parametric:
00432 uvs.push_back(TexCoordf(t * uv_scale[0], uv_scale[1]));
00433 uvs.push_back(TexCoordf(t * uv_scale[0], 0.0f));
00434 break;
00435
00436 case UV_distance:
00437 if (j != 0) {
00438 LVector3f vec = point - center_verts[vi + j - 1];
00439 dist += vec.length();
00440 }
00441 uvs.push_back(TexCoordf(dist * uv_scale[0], thickness * uv_scale[1]));
00442 uvs.push_back(TexCoordf(dist * uv_scale[0], 0.0f));
00443 break;
00444
00445 case UV_distance2:
00446 if (j != 0) {
00447 LVector3f vec = point - center_verts[vi + j - 1];
00448 dist += vec.length_squared();
00449 }
00450 uvs.push_back(TexCoordf(dist * uv_scale[0], thickness * uv_scale[1]));
00451 uvs.push_back(TexCoordf(dist * uv_scale[0], 0.0f));
00452 break;
00453 }
00454 }
00455 vi += length;
00456 lengths.push_back(length * 2);
00457 num_prims++;
00458 }
00459
00460 colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f));
00461
00462 PT(Geom) geom = new GeomTristrip;
00463 geom->set_num_prims(num_prims);
00464 geom->set_coords(verts);
00465 if (uv_mode != UV_none) {
00466 geom->set_texcoords(uvs, G_PER_VERTEX);
00467 }
00468 geom->set_colors(colors, G_OVERALL);
00469 geom->set_lengths(lengths);
00470
00471 CullableObject *object = new CullableObject(geom, data._state,
00472 data._render_transform);
00473 trav->get_cull_handler()->record_object(object);
00474 }
00475
00476
00477
00478
00479
00480
00481
00482 void RopeNode::
00483 register_with_read_factory() {
00484 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00485 }
00486
00487
00488
00489
00490
00491
00492
00493 void RopeNode::
00494 write_datagram(BamWriter *manager, Datagram &dg) {
00495 PandaNode::write_datagram(manager, dg);
00496 manager->write_cdata(dg, _cycler);
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 TypedWritable *RopeNode::
00508 make_from_bam(const FactoryParams ¶ms) {
00509 RopeNode *node = new RopeNode("");
00510 DatagramIterator scan;
00511 BamReader *manager;
00512
00513 parse_params(params, scan, manager);
00514 node->fillin(scan, manager);
00515
00516 return node;
00517 }
00518
00519
00520
00521
00522
00523
00524
00525
00526 void RopeNode::
00527 fillin(DatagramIterator &scan, BamReader *manager) {
00528 PandaNode::fillin(scan, manager);
00529 manager->read_cdata(scan, _cycler);
00530 }