00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "meshDrawer.h"
00016
00017 #include "geomVertexFormat.h"
00018 #include "geomVertexArrayFormat.h"
00019 #include "geomVertexData.h"
00020 #include "geomVertexWriter.h"
00021 #include "geomVertexRewriter.h"
00022 #include "camera.h"
00023 #include "boundingSphere.h"
00024 #include "geomTristrips.h"
00025 #include "geomTriangles.h"
00026 #include "geom.h"
00027 #include "geomNode.h"
00028 #include "pnmPainter.h"
00029 #include "pnmBrush.h"
00030 #include "lvecBase4.h"
00031 #include "lvector3.h"
00032 #include "pandaNode.h"
00033
00034 TypeHandle MeshDrawer::_type_handle;
00035
00036 PN_stdfloat randFloat() {
00037 return ((PN_stdfloat) rand() / (PN_stdfloat) 0x7fffffff);
00038 }
00039
00040
00041
00042
00043
00044
00045 void MeshDrawer::generator(int budget) {
00046
00047 _vdata = new GeomVertexData(_root.get_name(), GeomVertexFormat::get_v3n3c4t2(), Geom::UH_static);
00048 GeomVertexWriter *tvertex = new GeomVertexWriter(_vdata, "vertex");
00049 GeomVertexWriter *tnormal = new GeomVertexWriter(_vdata, "normal");
00050 GeomVertexWriter *tuv = new GeomVertexWriter(_vdata, "texcoord");
00051 GeomVertexWriter *tcolor = new GeomVertexWriter(_vdata, "color");
00052 _prim = new GeomTriangles(Geom::UH_static);
00053
00054
00055
00056 for(int i = 0; i < budget; i++) {
00057 for( int vert = 0; vert < 3; vert++) {
00058 LVector3 vec3 = LVector3(randFloat()+1000,randFloat(),randFloat())*.001;
00059 LVector4 vec4 = LVector4(1,1,1,randFloat());
00060 LVector2 vec2 = LVector2(0,randFloat());
00061 tvertex->add_data3(vec3);
00062 tcolor->add_data4(vec4);
00063 tuv->add_data2(vec2);
00064 tnormal->add_data3(vec3);
00065 }
00066 _prim->add_vertices(i * 3, i * 3 + 1, i * 3 + 2);
00067 }
00068
00069 _prim->close_primitive();
00070 _geom = new Geom(_vdata);
00071 _geom->add_primitive(_prim);
00072 _geomnode = new GeomNode("__MeshDrawer_GeomNode");
00073 _geomnode->add_geom(_geom);
00074 _root.attach_new_node(_geomnode);
00075 _last_clear_index = budget;
00076
00077 delete tvertex;
00078 delete tnormal;
00079 delete tuv;
00080 delete tcolor;
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090 void MeshDrawer::begin(NodePath camera, NodePath render) {
00091
00092 assert(render.get_error_type() == NodePath::ET_ok);
00093 assert(camera.get_error_type() == NodePath::ET_ok);
00094
00095
00096 _camera = camera;
00097 _render = render;
00098
00099
00100 _eyePos = camera.get_pos();
00101 _up = _render.get_relative_vector(camera, LVector3(0, 0, 1));
00102 _right = _render.get_relative_vector(camera, LVector3(1, 0, 0));
00103 _b1 = - _right - _up;
00104 _b2 = _right - _up;
00105 _b3 = _right + _up;
00106 _b4 = - _right + _up;
00107
00108
00109 if (_vertex != NULL) delete _vertex;
00110 if (_normal != NULL) delete _normal;
00111 if (_uv != NULL) delete _uv;
00112 if (_color != NULL) delete _color;
00113 _vertex = new GeomVertexRewriter(_vdata, "vertex");
00114 _uv = new GeomVertexRewriter(_vdata, "texcoord");
00115 _normal = new GeomVertexRewriter(_vdata, "normal");
00116 _color = new GeomVertexRewriter(_vdata, "color");
00117 _dprim = _prim->decompose();
00118
00119
00120 _start_clear_index = 0;
00121 _end_clear_index = _budget;
00122 _clear_index = _start_clear_index;
00123
00124 }
00125
00126
00127
00128
00129
00130
00131
00132 void MeshDrawer::end() {
00133
00134
00135 for(int i = _clear_index ; i < _last_clear_index; i ++ ) {
00136 _vertex->add_data3(0,0,0);
00137 _vertex->add_data3(0,0,0);
00138 _vertex->add_data3(0,0,0);
00139 }
00140
00141 _last_clear_index = _clear_index;
00142
00143
00144 delete _vertex; _vertex = NULL;
00145 delete _uv; _uv = NULL;
00146 delete _normal; _normal = NULL;
00147 delete _color; _color = NULL;
00148
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158 void MeshDrawer::particle(const LVector3 &pos, const LVector4 &frame, PN_stdfloat size,
00159 const LVector4 &color, PN_stdfloat rotation) {
00160
00161 rotation = rotation / 57.29578;
00162
00163 LVector3 v1 = pos + _b1*size*sin(rotation) + _b2*size*cos(rotation);
00164 LVector3 v2 = pos + _b2*size*sin(rotation) + _b3*size*cos(rotation);
00165 LVector3 v3 = pos + _b3*size*sin(rotation) + _b4*size*cos(rotation);
00166 LVector3 v4 = pos + _b4*size*sin(rotation) + _b1*size*cos(rotation);
00167
00168 PN_stdfloat u = frame.get_x();
00169 PN_stdfloat v = frame.get_y();
00170 PN_stdfloat us = frame.get_z();
00171 PN_stdfloat vs = frame.get_w();
00172
00173 tri(
00174 v1, color, LVector2(u,v),
00175 v2, color, LVector2(u+us,v),
00176 v3, color, LVector2(u+us,v+vs));
00177 tri(
00178 v3, color, LVector2(u+us,v+vs),
00179 v4, color, LVector2(u,v+vs),
00180 v1, color, LVector2(u,v));
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190 void MeshDrawer::blended_particle(const LVector3 &pos, const LVector4 &frame1,
00191 const LVector4 &frame2, PN_stdfloat blend, PN_stdfloat size, const LVector4 &color, PN_stdfloat rotation) {
00192
00193 LVector4 c2 = color;
00194 PN_stdfloat original_w = c2.get_w();
00195 c2.set_w((1.f-blend)*original_w);
00196 particle(pos,frame1,size,c2,rotation);
00197 c2.set_w(blend*original_w);
00198 particle(pos,frame2,size,c2,rotation);
00199
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209 void MeshDrawer::billboard(const LVector3 &pos, const LVector4 &frame, PN_stdfloat size,
00210 const LVector4 &_color) {
00211
00212 LVector3 v1 = pos + _b1*size;
00213 LVector3 v2 = pos + _b2*size;
00214 LVector3 v3 = pos + _b3*size;
00215 LVector3 v4 = pos + _b4*size;
00216
00217 PN_stdfloat u = frame.get_x();
00218 PN_stdfloat v = frame.get_y();
00219 PN_stdfloat us = frame.get_z();
00220 PN_stdfloat vs = frame.get_w();
00221
00222 tri(
00223 v1, _color, LVector2(u,v),
00224 v2, _color, LVector2(u+us,v),
00225 v3, _color, LVector2(u+us,v+vs));
00226 tri(
00227 v3, _color, LVector2(u+us,v+vs),
00228 v4, _color, LVector2(u,v+vs),
00229 v1, _color, LVector2(u,v));
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 void MeshDrawer::segment(const LVector3 &start, const LVector3 &stop, const LVector4 &frame,
00241 PN_stdfloat thickness, const LVector4 &color) {
00242 link_segment(start, frame, thickness, color);
00243 link_segment(stop, frame, thickness, color);
00244 link_segment_end(frame, color);
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 void MeshDrawer::cross_segment(const LVector3 &start, const LVector3 &stop, const LVector4 &frame,
00256 PN_stdfloat thickness, const LVector4 &color) {
00257
00258 PN_stdfloat u = frame.get_x();
00259 PN_stdfloat v = frame.get_y();
00260 PN_stdfloat us = frame.get_z();
00261 PN_stdfloat vs = frame.get_w();
00262
00263 LVector3 v1 = start - _up*thickness;
00264 LVector3 v2 = stop - _up*thickness;
00265 LVector3 v3 = stop + _up*thickness;
00266 LVector3 v4 = start + _up*thickness;
00267
00268 tri(v1, color, LVector2(u,v),
00269 v2, color, LVector2(u+us,v),
00270 v3, color, LVector2(u+us,v+vs));
00271 tri(v3, color, LVector2(u+us,v+vs),
00272 v4, color, LVector2(u,v+vs),
00273 v1, color, LVector2(u,v));
00274
00275 v1 = start - _right*thickness;
00276 v2 = stop - _right*thickness;
00277 v3 = stop + _right*thickness;
00278 v4 = start + _right*thickness;
00279
00280 tri(v1, color, LVector2(u,v),
00281 v2, color, LVector2(u+us,v),
00282 v3, color, LVector2(u+us,v+vs));
00283 tri(v3, color, LVector2(u+us,v+vs),
00284 v4, color, LVector2(u,v+vs),
00285 v1, color, LVector2(u,v));
00286
00287 }
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 void MeshDrawer::uneven_segment(const LVector3 &start, const LVector3 &stop,
00301 const LVector4 &frame, PN_stdfloat thickness_start, const LVector4 &color_start,
00302 PN_stdfloat thickness_stop, const LVector4 &color_stop) {
00303
00304 PN_stdfloat u = frame.get_x();
00305 PN_stdfloat v = frame.get_y();
00306 PN_stdfloat us = frame.get_z();
00307 PN_stdfloat vs = frame.get_w();
00308
00309 LVector3 v1 = start - _up*thickness_start;
00310 LVector3 v2 = stop - _up*thickness_stop;
00311 LVector3 v3 = stop + _up*thickness_stop;
00312 LVector3 v4 = start + _up*thickness_start;
00313
00314 tri(v1, color_start, LVector2(u,v),
00315 v2, color_stop, LVector2(u+us,v),
00316 v3, color_stop, LVector2(u+us,v+vs));
00317 tri(v3, color_stop, LVector2(u+us,v+vs),
00318 v4, color_start, LVector2(u,v+vs),
00319 v1, color_start, LVector2(u,v));
00320
00321 v1 = start - _right*thickness_start;
00322 v2 = stop - _right*thickness_stop;
00323 v3 = stop + _right*thickness_stop;
00324 v4 = start + _right*thickness_start;
00325
00326 tri(v1, color_start, LVector2(u,v),
00327 v2, color_stop, LVector2(u+us,v),
00328 v3, color_stop, LVector2(u+us,v+vs));
00329 tri(v3, color_stop, LVector2(u+us,v+vs),
00330 v4, color_start, LVector2(u,v+vs),
00331 v1, color_start, LVector2(u,v));
00332 }
00333
00334
00335
00336
00337
00338
00339
00340 void MeshDrawer::explosion(
00341 const LVector3 &pos, const LVector4 &frame, PN_stdfloat size, const LVector4 &_color,
00342 int seed, int number, PN_stdfloat distance) {
00343 srand(seed);
00344 LVector3 relative_pos;
00345 for(int i = 0; i < number; i++) {
00346 relative_pos = LVector3(randFloat()-.5f,randFloat()-.5f,randFloat()-.5f);
00347 relative_pos.normalize();
00348 relative_pos *= randFloat()*distance;
00349 particle(relative_pos+pos,frame,size,_color,randFloat()*360.0f);
00350 }
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360 void MeshDrawer::stream(const LVector3 &start, const LVector3 &stop, const LVector4 &frame, PN_stdfloat size, const LVector4 &_color,
00361 int number, PN_stdfloat offset) {
00362
00363 offset = offset-floor(offset);
00364 LVector3 relative_pos = stop;
00365 LVector3 vec = stop - start;
00366 PN_stdfloat distance = vec.length();
00367 for(int i = 0; i < number; i++) {
00368 relative_pos = stop + vec * ((i-offset)*(distance/PN_stdfloat(number)));
00369 billboard(relative_pos,frame,size,_color);
00370 }
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 void MeshDrawer::geometry(NodePath draw_node) {
00386 assert(_render.get_error_type() == NodePath::ET_ok);
00387
00388 LVector4 color = LVector4(1,1,1,1);
00389 LVector3 vec[3];
00390 LVector2 uv[3];
00391
00392
00393 NodePathCollection geom_collection = draw_node.find_all_matches("**/+GeomNode");
00394 for(int i=0; i < geom_collection.get_num_paths(); i++ ) {
00395 NodePath current_node_path = geom_collection.get_path(i);
00396 PT(GeomNode) geomNode = DCAST(GeomNode, current_node_path.node());
00397
00398
00399 for(int j=0; j<geomNode->get_num_geoms(); j++) {
00400 CPT(Geom) geom = geomNode->get_geom(j);
00401 CPT(GeomVertexData) v_data = geom->get_vertex_data();
00402 GeomVertexReader *prim_vertex_reader = new GeomVertexReader(v_data, "vertex");
00403 GeomVertexReader *prim_uv_reader = new GeomVertexReader(v_data, "texcoord");
00404 for(int k=0; k <geom->get_num_primitives(); k++) {
00405 CPT(GeomPrimitive) prim1 = geom->get_primitive(k);
00406 CPT(GeomPrimitive) _prim = prim1->decompose();
00407
00408
00409 for(int p=0; p < _prim->get_num_primitives();p++) {
00410 int s = _prim->get_primitive_start(p);
00411 int e = _prim->get_primitive_end(p);
00412 int indx_over = 0;
00413
00414
00415 for(int idx=s; idx<e; idx++) {
00416 int vidx = _prim->get_vertex(idx);
00417 prim_vertex_reader->set_row_unsafe(vidx);
00418 prim_uv_reader->set_row_unsafe(vidx);
00419 vec[indx_over] = _render.get_relative_point(
00420 current_node_path,prim_vertex_reader->get_data3());
00421 uv[indx_over] = prim_uv_reader->get_data2();
00422 indx_over++;
00423 if (indx_over > 2) break;
00424 }
00425
00426
00427 tri(vec[0],color,uv[0],
00428 vec[1],color,uv[1],
00429 vec[2],color,uv[2]);
00430 }
00431
00432 if( _clear_index > _end_clear_index) return;
00433 }
00434
00435 delete prim_vertex_reader;
00436 delete prim_uv_reader;
00437 }
00438 }
00439 }
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 void MeshDrawer::
00452 link_segment(const LVector3 &pos, const LVector4 &frame,
00453 PN_stdfloat thickness, const LVector4 &color) {
00454 assert(_render.get_error_type() == NodePath::ET_ok);
00455 assert(_camera.get_error_type() == NodePath::ET_ok);
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 if(_at_start==0) {
00474 _last_pos = pos;
00475 _last_thickness = thickness;
00476 _last_color = color;
00477 _at_start=1;
00478 return;
00479 }
00480
00481 LVector3 start = _last_pos;
00482 LVector3 stop = pos;
00483
00484 LVector3 cam_start3d = _camera.get_relative_point(_render, start);
00485 LPoint2 cam_start2d = LVector2();
00486 LVector3 cam_stop3d = _camera.get_relative_point(_render, stop);
00487 LPoint2 cam_stop2d = LVector2();
00488
00489 PT(Camera) camera = DCAST(Camera, _camera.node());
00490 PT(Lens) lens = camera->get_lens();
00491
00492 lens->project(cam_start3d, cam_start2d);
00493 lens->project(cam_stop3d, cam_stop2d);
00494
00495 LVector2 dif = cam_stop2d - cam_start2d;
00496 PN_stdfloat rotation = atan2(dif.get_x(),dif.get_y());
00497
00498 LVector3 now_v1 = start + _b1*(PN_stdfloat)(thickness*sin(rotation)) + _b2*(PN_stdfloat)(thickness*cos(rotation));
00499 LVector3 now_v4 = start + _b4*(PN_stdfloat)(thickness*sin(rotation)) + _b1*(PN_stdfloat)(thickness*cos(rotation));
00500 LVector3 now_v2 = stop + _b2*(PN_stdfloat)(thickness*sin(rotation)) + _b3*(PN_stdfloat)(thickness*cos(rotation));
00501 LVector3 now_v3 = stop + _b3*(PN_stdfloat)(thickness*sin(rotation)) + _b4*(PN_stdfloat)(thickness*cos(rotation));
00502
00503
00504
00505
00506 if(_at_start==1) {
00507 _last_v1 = now_v1;
00508 _last_v2 = now_v2;
00509 _last_v3 = now_v3;
00510 _last_v4 = now_v4;
00511 _at_start = 2;
00512 return;
00513 }
00514
00515
00516 LVector3 v1 = _last_v1;
00517 LVector3 v2 = (_last_v2+now_v1)/2.0f;
00518 LVector3 v3 = (_last_v3+now_v4)/2.0f;
00519 LVector3 v4 = _last_v4;
00520
00521
00522 PN_stdfloat u = frame.get_x();
00523 PN_stdfloat v = frame.get_y();
00524 PN_stdfloat us = frame.get_z();
00525 PN_stdfloat vs = frame.get_w();
00526
00527 tri(v1, _last_color, LVector2(u,v),
00528 v2, color, LVector2(u+us,v),
00529 v3, color, LVector2(u+us,v+vs));
00530 tri(v3, color, LVector2(u+us,v+vs),
00531 v4, _last_color, LVector2(u,v+vs),
00532 v1, _last_color, LVector2(u,v));
00533
00534
00535 _last_v1 = v2;
00536 _last_v2 = now_v2;
00537 _last_v3 = now_v3;
00538 _last_v4 = v3;
00539
00540
00541 _last_pos = pos;
00542 _last_thickness = thickness;
00543 _last_color = color;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554 void MeshDrawer::link_segment_end(const LVector4 &frame, const LVector4 &color)
00555 {
00556 PN_stdfloat u = frame.get_x();
00557 PN_stdfloat v = frame.get_y();
00558 PN_stdfloat us = frame.get_z();
00559 PN_stdfloat vs = frame.get_w();
00560
00561 tri(_last_v1, _last_color, LVector2(u,v),
00562 _last_v2, color, LVector2(u+us,v),
00563 _last_v3, color, LVector2(u+us,v+vs));
00564 tri(_last_v3, color, LVector2(u+us,v+vs),
00565 _last_v4, _last_color, LVector2(u,v+vs),
00566 _last_v1, _last_color, LVector2(u,v));
00567
00568 _at_start = 0;
00569 }