1 /* bzflag
2 * Copyright (c) 1993-2021 Tim Riker
3 *
4 * This package is free software; you can redistribute it and/or
5 * modify it under the terms of the license found in the file
6 * named COPYING that should have accompanied this file.
7 *
8 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 */
12
13 // interface header
14 #include "MeshPolySceneNode.h"
15
16 // system headers
17 #include <assert.h>
18 #include <math.h>
19
20 // common implementation headers
21 #include "Intersect.h"
22
23 // FIXME (SceneRenderer.cxx is in src/bzflag)
24 #include "SceneRenderer.h"
25
26 // FIXME - no tesselation is done on for shot lighting
27
28
29 //
30 // MeshPolySceneNode::Geometry
31 //
32
Geometry(MeshPolySceneNode * _node,const GLfloat3Array & _vertices,const GLfloat3Array & _normals,const GLfloat2Array & _texcoords,const GLfloat * _normal)33 MeshPolySceneNode::Geometry::Geometry(MeshPolySceneNode* _node,
34 const GLfloat3Array& _vertices, const GLfloat3Array& _normals,
35 const GLfloat2Array& _texcoords, const GLfloat* _normal) :
36 vertices(_vertices), normals(_normals), texcoords(_texcoords)
37 {
38 sceneNode = _node;
39 normal = _normal;
40 style = 0;
41 return;
42 }
43
44
~Geometry()45 MeshPolySceneNode::Geometry::~Geometry()
46 {
47 // do nothing
48 return;
49 }
50
drawV() const51 inline void MeshPolySceneNode::Geometry::drawV() const
52 {
53 const int count = vertices.getSize();
54 glBegin(GL_TRIANGLE_FAN);
55 for (int i = 0; i < count; i++)
56 glVertex3fv(vertices[i]);
57 glEnd();
58 return;
59 }
60
61
drawVT() const62 inline void MeshPolySceneNode::Geometry::drawVT() const
63 {
64 const int count = vertices.getSize();
65 glBegin(GL_TRIANGLE_FAN);
66 for (int i = 0; i < count; i++)
67 {
68 glTexCoord2fv(texcoords[i]);
69 glVertex3fv(vertices[i]);
70 }
71 glEnd();
72 return;
73 }
74
75
drawVN() const76 inline void MeshPolySceneNode::Geometry::drawVN() const
77 {
78 const int count = vertices.getSize();
79 glBegin(GL_TRIANGLE_FAN);
80 for (int i = 0; i < count; i++)
81 {
82 glNormal3fv(normals[i]);
83 glVertex3fv(vertices[i]);
84 }
85 glEnd();
86 return;
87 }
88
89
drawVTN() const90 inline void MeshPolySceneNode::Geometry::drawVTN() const
91 {
92 const int count = vertices.getSize();
93 glBegin(GL_TRIANGLE_FAN);
94 for (int i = 0; i < count; i++)
95 {
96 glTexCoord2fv(texcoords[i]);
97 glNormal3fv(normals[i]);
98 glVertex3fv(vertices[i]);
99 }
100 glEnd();
101 return;
102 }
103
104
render()105 void MeshPolySceneNode::Geometry::render()
106 {
107 sceneNode->setColor();
108
109 if (normals.getSize() != 0)
110 {
111 if (style >= 2)
112 drawVTN();
113 else
114 drawVN();
115 }
116 else
117 {
118 glNormal3fv(normal);
119 if (style >= 2)
120 drawVT();
121 else
122 drawV();
123 }
124
125 addTriangleCount(vertices.getSize() - 2);
126 return;
127 }
128
129
renderRadar()130 void MeshPolySceneNode::Geometry::renderRadar()
131 {
132 drawV();
133 addTriangleCount(vertices.getSize() - 2);
134 return;
135 }
136
137
renderShadow()138 void MeshPolySceneNode::Geometry::renderShadow()
139 {
140 drawV();
141 addTriangleCount(vertices.getSize() - 2);
142 return;
143 }
144
145
146 //
147 // MeshPolySceneNode
148 //
149
MeshPolySceneNode(const float _plane[4],bool _noRadar,bool _noShadow,const GLfloat3Array & vertices,const GLfloat3Array & normals,const GLfloat2Array & texcoords)150 MeshPolySceneNode::MeshPolySceneNode(const float _plane[4],
151 bool _noRadar, bool _noShadow,
152 const GLfloat3Array& vertices,
153 const GLfloat3Array& normals,
154 const GLfloat2Array& texcoords) :
155 node(this, vertices, normals, texcoords, plane)
156 {
157 int i, j;
158 const int count = vertices.getSize();
159 assert(texcoords.getSize() == count);
160 assert((normals.getSize() == 0) || (normals.getSize() == count));
161
162 setPlane(_plane);
163
164 noRadar = _noRadar || (plane[2] <= 0.0f); // pre-cull if we can
165 noShadow = _noShadow;
166
167 // choose axis to ignore (the one with the largest normal component)
168 int ignoreAxis;
169 const auto normal = plane;
170 if (fabsf(normal[0]) > fabsf(normal[1]))
171 {
172 if (fabsf(normal[0]) > fabsf(normal[2]))
173 ignoreAxis = 0;
174 else
175 ignoreAxis = 2;
176 }
177 else
178 {
179 if (fabsf(normal[1]) > fabsf(normal[2]))
180 ignoreAxis = 1;
181 else
182 ignoreAxis = 2;
183 }
184
185 // project vertices onto plane
186 GLfloat2Array flat(count);
187 switch (ignoreAxis)
188 {
189 case 0:
190 for (i = 0; i < count; i++)
191 {
192 flat[i][0] = vertices[i][1];
193 flat[i][1] = vertices[i][2];
194 }
195 break;
196 case 1:
197 for (i = 0; i < count; i++)
198 {
199 flat[i][0] = vertices[i][2];
200 flat[i][1] = vertices[i][0];
201 }
202 break;
203 case 2:
204 for (i = 0; i < count; i++)
205 {
206 flat[i][0] = vertices[i][0];
207 flat[i][1] = vertices[i][1];
208 }
209 break;
210 }
211
212 // compute area of polygon
213 float* area = new float[1];
214 area[0] = 0.0f;
215 for (j = count - 1, i = 0; i < count; j = i, i++)
216 area[0] += flat[j][0] * flat[i][1] - flat[j][1] * flat[i][0];
217 area[0] = 0.5f * fabsf(area[0]) / normal[ignoreAxis];
218
219 // set lod info
220 setNumLODs(1, area);
221
222 // compute bounding sphere, put center at average of vertices
223 GLfloat mySphere[4];
224 mySphere[0] = mySphere[1] = mySphere[2] = mySphere[3] = 0.0f;
225 for (i = 0; i < count; i++)
226 {
227 mySphere[0] += vertices[i][0];
228 mySphere[1] += vertices[i][1];
229 mySphere[2] += vertices[i][2];
230 }
231 mySphere[0] /= (float)count;
232 mySphere[1] /= (float)count;
233 mySphere[2] /= (float)count;
234 for (i = 0; i < count; i++)
235 {
236 const float dx = mySphere[0] - vertices[i][0];
237 const float dy = mySphere[1] - vertices[i][1];
238 const float dz = mySphere[2] - vertices[i][2];
239 GLfloat r = ((dx * dx) + (dy * dy) + (dz * dz));
240 if (r > mySphere[3])
241 mySphere[3] = r;
242 }
243 setSphere(mySphere);
244
245 // record extents info
246 for (i = 0; i < count; i++)
247 extents.expandToPoint(vertices[i]);
248
249 return;
250 }
251
252
~MeshPolySceneNode()253 MeshPolySceneNode::~MeshPolySceneNode()
254 {
255 return;
256 }
257
258
cull(const ViewFrustum & frustum) const259 bool MeshPolySceneNode::cull(const ViewFrustum& frustum) const
260 {
261 // cull if eye is behind (or on) plane
262 const GLfloat* eye = frustum.getEye();
263 if (((eye[0] * plane[0]) + (eye[1] * plane[1]) + (eye[2] * plane[2]) +
264 plane[3]) <= 0.0f)
265 return true;
266
267 // if the Visibility culler tells us that we're
268 // fully visible, then skip the rest of these tests
269 if (octreeState == OctreeVisible)
270 return false;
271
272 const Frustum* f = (const Frustum *) &frustum;
273 if (testAxisBoxInFrustum(extents, f) == Outside)
274 return true;
275
276 // probably visible
277 return false;
278 }
279
280
inAxisBox(const Extents & exts) const281 bool MeshPolySceneNode::inAxisBox (const Extents& exts) const
282 {
283 if (!extents.touches(exts))
284 return false;
285
286 return testPolygonInAxisBox (getVertexCount(), getVertices(), plane, exts);
287 }
288
289
split(const float * splitPlane,SceneNode * & front,SceneNode * & back) const290 int MeshPolySceneNode::split(const float* splitPlane,
291 SceneNode*& front, SceneNode*& back) const
292 {
293 if (node.normals.getSize() > 0)
294 {
295 return splitWallVTN(splitPlane, node.vertices, node.normals, node.texcoords,
296 front, back);
297 }
298 else
299 return splitWallVT(splitPlane, node.vertices, node.texcoords, front, back);
300 }
301
302
addRenderNodes(SceneRenderer & renderer)303 void MeshPolySceneNode::addRenderNodes(SceneRenderer& renderer)
304 {
305 node.setStyle(getStyle());
306 const GLfloat* dyncol = getDynamicColor();
307 if ((dyncol == NULL) || (dyncol[3] != 0.0f))
308 renderer.addRenderNode(&node, getWallGState());
309 return;
310 }
311
312
addShadowNodes(SceneRenderer & renderer)313 void MeshPolySceneNode::addShadowNodes(SceneRenderer& renderer)
314 {
315 if (!noShadow)
316 {
317 const GLfloat* dyncol = getDynamicColor();
318 if ((dyncol == NULL) || (dyncol[3] != 0.0f))
319 renderer.addShadowNode(&node);
320 }
321 return;
322 }
323
324
renderRadar()325 void MeshPolySceneNode::renderRadar()
326 {
327 if (!noRadar)
328 node.renderRadar();
329 return;
330 }
331
332
splitWallVTN(const GLfloat * splitPlane,const GLfloat3Array & vertices,const GLfloat3Array & normals,const GLfloat2Array & texcoords,SceneNode * & front,SceneNode * & back) const333 int MeshPolySceneNode::splitWallVTN(const GLfloat* splitPlane,
334 const GLfloat3Array& vertices,
335 const GLfloat3Array& normals,
336 const GLfloat2Array& texcoords,
337 SceneNode*& front, SceneNode*& back) const
338 {
339 int i;
340 const int count = vertices.getSize();
341 const float fudgeFactor = 0.001f;
342 const unsigned char BACK_SIDE = (1 << 0);
343 const unsigned char FRONT_SIDE = (1 << 1);
344
345 // arrays for tracking each vertex's side
346 // and distance from the splitting plane
347 // (assuming stack allocation with be faster then heap, might be wrong)
348 // wonder how that compares to static vs. stack access speeds
349 const int staticSize = 64;
350 float* dists;
351 unsigned char* array;
352 float staticDists[staticSize];
353 unsigned char staticArray[staticSize];
354 if (count > staticSize)
355 {
356 array = new unsigned char[count];
357 dists = new float[count];
358 }
359 else
360 {
361 array = staticArray;
362 dists = staticDists;
363 }
364
365 // determine on which side of the plane each point lies
366 int bothCount = 0;
367 int backCount = 0;
368 int frontCount = 0;
369 for (i = 0; i < count; i++)
370 {
371 const GLfloat d = (vertices[i][0] * splitPlane[0]) +
372 (vertices[i][1] * splitPlane[1]) +
373 (vertices[i][2] * splitPlane[2]) + splitPlane[3];
374 if (d < -fudgeFactor)
375 {
376 array[i] = BACK_SIDE;
377 backCount++;
378 }
379 else if (d > fudgeFactor)
380 {
381 array[i] = FRONT_SIDE;
382 frontCount++;
383 }
384 else
385 {
386 array[i] = (BACK_SIDE | FRONT_SIDE);
387 bothCount++;
388 backCount++;
389 frontCount++;
390 }
391 dists[i] = d; // save for later
392 }
393
394 // see if we need to split
395 if ((frontCount == 0) || (frontCount == bothCount))
396 {
397 if (count > staticSize)
398 {
399 delete[] array;
400 delete[] dists;
401 }
402 return -1; // node is on the back side
403 }
404 if ((backCount == 0) || (backCount == bothCount))
405 {
406 if (count > staticSize)
407 {
408 delete[] array;
409 delete[] dists;
410 }
411 return +1; // node is on the front side
412 }
413
414 // get the first old front and back points
415 int firstFront = -1, firstBack = -1;
416
417 for (i = 0; i < count; i++)
418 {
419 const int next = (i + 1) % count; // the next index
420 if (array[next] & FRONT_SIDE)
421 {
422 if (!(array[i] & FRONT_SIDE))
423 firstFront = next;
424 }
425 if (array[next] & BACK_SIDE)
426 {
427 if (!(array[i] & BACK_SIDE))
428 firstBack = next;
429 }
430 }
431
432 // get the last old front and back points
433 int lastFront = (firstFront + frontCount - 1) % count;
434 int lastBack = (firstBack + backCount - 1) % count;
435
436 // add in extra counts for the splitting vertices
437 if (firstFront != lastBack)
438 {
439 frontCount++;
440 backCount++;
441 }
442 if (firstBack != lastFront)
443 {
444 frontCount++;
445 backCount++;
446 }
447
448 // make space for new polygons
449 GLfloat3Array vertexFront(frontCount);
450 GLfloat3Array normalFront(frontCount);
451 GLfloat2Array uvFront(frontCount);
452 GLfloat3Array vertexBack(backCount);
453 GLfloat3Array normalBack(backCount);
454 GLfloat2Array uvBack(backCount);
455
456 // fill in the splitting vertices
457 int frontIndex = 0;
458 int backIndex = 0;
459 if (firstFront != lastBack)
460 {
461 GLfloat splitVertex[3], splitNormal[3], splitUV[2];
462 splitEdgeVTN(dists[firstFront], dists[lastBack],
463 vertices[firstFront], vertices[lastBack],
464 normals[firstFront], normals[lastBack],
465 texcoords[firstFront], texcoords[lastBack],
466 splitVertex, splitNormal, splitUV);
467 memcpy(vertexFront[0], splitVertex, sizeof(GLfloat[3]));
468 memcpy(normalFront[0], splitNormal, sizeof(GLfloat[3]));
469 memcpy(uvFront[0], splitUV, sizeof(GLfloat[2]));
470 frontIndex++; // bump up the head
471 const int last = backCount - 1;
472 memcpy(vertexBack[last], splitVertex, sizeof(GLfloat[3]));
473 memcpy(normalBack[last], splitNormal, sizeof(GLfloat[3]));
474 memcpy(uvBack[last], splitUV, sizeof(GLfloat[2]));
475 }
476 if (firstBack != lastFront)
477 {
478 GLfloat splitVertex[3], splitNormal[3], splitUV[2];
479 splitEdgeVTN(dists[firstBack], dists[lastFront],
480 vertices[firstBack], vertices[lastFront],
481 normals[firstBack], normals[lastFront],
482 texcoords[firstBack], texcoords[lastFront],
483 splitVertex, splitNormal, splitUV);
484 memcpy(vertexBack[0], splitVertex, sizeof(GLfloat[3]));
485 memcpy(normalBack[0], splitNormal, sizeof(GLfloat[3]));
486 memcpy(uvBack[0], splitUV, sizeof(GLfloat[2]));
487 backIndex++; // bump up the head
488 const int last = frontCount - 1;
489 memcpy(vertexFront[last], splitVertex, sizeof(GLfloat[3]));
490 memcpy(normalFront[last], splitNormal, sizeof(GLfloat[3]));
491 memcpy(uvFront[last], splitUV, sizeof(GLfloat[2]));
492 }
493
494 // fill in the old front side vertices
495 const int endFront = (lastFront + 1) % count;
496 for (i = firstFront; i != endFront; i = (i + 1) % count)
497 {
498 memcpy(vertexFront[frontIndex], vertices[i], sizeof(GLfloat[3]));
499 memcpy(normalFront[frontIndex], normals[i], sizeof(GLfloat[3]));
500 memcpy(uvFront[frontIndex], texcoords[i], sizeof(GLfloat[2]));
501 frontIndex++;
502 }
503
504 // fill in the old back side vertices
505 const int endBack = (lastBack + 1) % count;
506 for (i = firstBack; i != endBack; i = (i + 1) % count)
507 {
508 memcpy(vertexBack[backIndex], vertices[i], sizeof(GLfloat[3]));
509 memcpy(normalBack[backIndex], normals[i], sizeof(GLfloat[3]));
510 memcpy(uvBack[backIndex], texcoords[i], sizeof(GLfloat[2]));
511 backIndex++;
512 }
513
514 // make new nodes
515 front = new MeshPolySceneNode(getPlane(), noRadar, noShadow,
516 vertexFront, normalFront, uvFront);
517 back = new MeshPolySceneNode(getPlane(), noRadar, noShadow,
518 vertexBack, normalBack, uvBack);
519
520 // free the arrays, if required
521 if (count > staticSize)
522 {
523 delete[] array;
524 delete[] dists;
525 }
526
527 return 0; // generated new front and back nodes
528 }
529
530
splitEdgeVTN(float d1,float d2,const GLfloat * p1,const GLfloat * p2,const GLfloat * n1,const GLfloat * n2,const GLfloat * uv1,const GLfloat * uv2,GLfloat * p,GLfloat * n,GLfloat * uv) const531 void MeshPolySceneNode::splitEdgeVTN(float d1, float d2,
532 const GLfloat* p1, const GLfloat* p2,
533 const GLfloat* n1, const GLfloat* n2,
534 const GLfloat* uv1, const GLfloat* uv2,
535 GLfloat* p, GLfloat* n, GLfloat* uv) const
536 {
537 // compute fraction along edge where split occurs
538 float t1 = (d2 - d1);
539 if (t1 != 0.0f) // shouldn't happen
540 t1 = -(d1 / t1);
541
542 // compute vertex
543 p[0] = p1[0] + (t1 * (p2[0] - p1[0]));
544 p[1] = p1[1] + (t1 * (p2[1] - p1[1]));
545 p[2] = p1[2] + (t1 * (p2[2] - p1[2]));
546
547 // compute normal
548 const float t2 = 1.0f - t1;
549 n[0] = (n1[0] * t2) + (n2[0] * t1);
550 n[1] = (n1[1] * t2) + (n2[1] * t1);
551 n[2] = (n1[2] * t2) + (n2[2] * t1);
552 // normalize
553 float len = ((n[0] * n[0]) + (n[1] * n[1]) + (n[2] * n[2]));
554 if (len > 1.0e-20f) // otherwise, let it go...
555 {
556 len = 1.0f / sqrtf(len);
557 n[0] = n[0] * len;
558 n[1] = n[1] * len;
559 n[2] = n[2] * len;
560 }
561
562 // compute texture coordinate
563 uv[0] = uv1[0] + (t1 * (uv2[0] - uv1[0]));
564 uv[1] = uv1[1] + (t1 * (uv2[1] - uv1[1]));
565
566 return;
567 }
568
569
splitWallVT(const GLfloat * splitPlane,const GLfloat3Array & vertices,const GLfloat2Array & texcoords,SceneNode * & front,SceneNode * & back) const570 int MeshPolySceneNode::splitWallVT(const GLfloat* splitPlane,
571 const GLfloat3Array& vertices,
572 const GLfloat2Array& texcoords,
573 SceneNode*& front, SceneNode*& back) const
574 {
575 int i;
576 const int count = vertices.getSize();
577 const float fudgeFactor = 0.001f;
578 const unsigned char BACK_SIDE = (1 << 0);
579 const unsigned char FRONT_SIDE = (1 << 1);
580
581 // arrays for tracking each vertex's side
582 // and distance from the splitting plane
583 // (assuming stack allocation with be faster then heap, might be wrong)
584 // wonder how that compares to static vs. stack access speeds
585 const int staticSize = 64;
586 float* dists;
587 unsigned char* array;
588 float staticDists[staticSize];
589 unsigned char staticArray[staticSize];
590 if (count > staticSize)
591 {
592 array = new unsigned char[count];
593 dists = new float[count];
594 }
595 else
596 {
597 array = staticArray;
598 dists = staticDists;
599 }
600
601 // determine on which side of the plane each point lies
602 int bothCount = 0;
603 int backCount = 0;
604 int frontCount = 0;
605 for (i = 0; i < count; i++)
606 {
607 const GLfloat d = (vertices[i][0] * splitPlane[0]) +
608 (vertices[i][1] * splitPlane[1]) +
609 (vertices[i][2] * splitPlane[2]) + splitPlane[3];
610 if (d < -fudgeFactor)
611 {
612 array[i] = BACK_SIDE;
613 backCount++;
614 }
615 else if (d > fudgeFactor)
616 {
617 array[i] = FRONT_SIDE;
618 frontCount++;
619 }
620 else
621 {
622 array[i] = (BACK_SIDE | FRONT_SIDE);
623 bothCount++;
624 backCount++;
625 frontCount++;
626 }
627 dists[i] = d; // save for later
628 }
629
630 // see if we need to split
631 if ((frontCount == 0) || (frontCount == bothCount))
632 {
633 if (count > staticSize)
634 {
635 delete[] array;
636 delete[] dists;
637 }
638 return -1; // node is on the back side
639 }
640 if ((backCount == 0) || (backCount == bothCount))
641 {
642 if (count > staticSize)
643 {
644 delete[] array;
645 delete[] dists;
646 }
647 return +1; // node is on the front side
648 }
649
650 // get the first old front and back points
651 int firstFront = -1, firstBack = -1;
652
653 for (i = 0; i < count; i++)
654 {
655 const int next = (i + 1) % count; // the next index
656 if (array[next] & FRONT_SIDE)
657 {
658 if (!(array[i] & FRONT_SIDE))
659 firstFront = next;
660 }
661 if (array[next] & BACK_SIDE)
662 {
663 if (!(array[i] & BACK_SIDE))
664 firstBack = next;
665 }
666 }
667
668 // get the last old front and back points
669 int lastFront = (firstFront + frontCount - 1) % count;
670 int lastBack = (firstBack + backCount - 1) % count;
671
672 // add in extra counts for the splitting vertices
673 if (firstFront != lastBack)
674 {
675 frontCount++;
676 backCount++;
677 }
678 if (firstBack != lastFront)
679 {
680 frontCount++;
681 backCount++;
682 }
683
684 // make space for new polygons
685 GLfloat3Array vertexFront(frontCount);
686 GLfloat3Array normalFront(0);
687 GLfloat2Array uvFront(frontCount);
688 GLfloat3Array vertexBack(backCount);
689 GLfloat3Array normalBack(0);
690 GLfloat2Array uvBack(backCount);
691
692 // fill in the splitting vertices
693 int frontIndex = 0;
694 int backIndex = 0;
695 if (firstFront != lastBack)
696 {
697 GLfloat splitVertex[3], splitUV[2];
698 splitEdgeVT(dists[firstFront], dists[lastBack],
699 vertices[firstFront], vertices[lastBack],
700 texcoords[firstFront], texcoords[lastBack],
701 splitVertex, splitUV);
702 memcpy(vertexFront[0], splitVertex, sizeof(GLfloat[3]));
703 memcpy(uvFront[0], splitUV, sizeof(GLfloat[2]));
704 frontIndex++; // bump up the head
705 const int last = backCount - 1;
706 memcpy(vertexBack[last], splitVertex, sizeof(GLfloat[3]));
707 memcpy(uvBack[last], splitUV, sizeof(GLfloat[2]));
708 }
709 if (firstBack != lastFront)
710 {
711 GLfloat splitVertex[3], splitUV[2];
712 splitEdgeVT(dists[firstBack], dists[lastFront],
713 vertices[firstBack], vertices[lastFront],
714 texcoords[firstBack], texcoords[lastFront],
715 splitVertex, splitUV);
716 memcpy(vertexBack[0], splitVertex, sizeof(GLfloat[3]));
717 memcpy(uvBack[0], splitUV, sizeof(GLfloat[2]));
718 backIndex++; // bump up the head
719 const int last = frontCount - 1;
720 memcpy(vertexFront[last], splitVertex, sizeof(GLfloat[3]));
721 memcpy(uvFront[last], splitUV, sizeof(GLfloat[2]));
722 }
723
724 // fill in the old front side vertices
725 const int endFront = (lastFront + 1) % count;
726 for (i = firstFront; i != endFront; i = (i + 1) % count)
727 {
728 memcpy(vertexFront[frontIndex], vertices[i], sizeof(GLfloat[3]));
729 memcpy(uvFront[frontIndex], texcoords[i], sizeof(GLfloat[2]));
730 frontIndex++;
731 }
732
733 // fill in the old back side vertices
734 const int endBack = (lastBack + 1) % count;
735 for (i = firstBack; i != endBack; i = (i + 1) % count)
736 {
737 memcpy(vertexBack[backIndex], vertices[i], sizeof(GLfloat[3]));
738 memcpy(uvBack[backIndex], texcoords[i], sizeof(GLfloat[2]));
739 backIndex++;
740 }
741
742 // make new nodes
743 front = new MeshPolySceneNode(getPlane(), noRadar, noShadow,
744 vertexFront, normalFront, uvFront);
745 back = new MeshPolySceneNode(getPlane(), noRadar, noShadow,
746 vertexBack, normalBack, uvBack);
747
748 // free the arrays, if required
749 if (count > staticSize)
750 {
751 delete[] array;
752 delete[] dists;
753 }
754
755 return 0; // generated new front and back nodes
756 }
757
758
splitEdgeVT(float d1,float d2,const GLfloat * p1,const GLfloat * p2,const GLfloat * uv1,const GLfloat * uv2,GLfloat * p,GLfloat * uv) const759 void MeshPolySceneNode::splitEdgeVT(float d1, float d2,
760 const GLfloat* p1, const GLfloat* p2,
761 const GLfloat* uv1, const GLfloat* uv2,
762 GLfloat* p, GLfloat* uv) const
763 {
764 // compute fraction along edge where split occurs
765 float t1 = (d2 - d1);
766 if (t1 != 0.0f) // shouldn't happen
767 t1 = -(d1 / t1);
768
769 // compute vertex
770 p[0] = p1[0] + (t1 * (p2[0] - p1[0]));
771 p[1] = p1[1] + (t1 * (p2[1] - p1[1]));
772 p[2] = p1[2] + (t1 * (p2[2] - p1[2]));
773
774 // compute texture coordinate
775 uv[0] = uv1[0] + (t1 * (uv2[0] - uv1[0]));
776 uv[1] = uv1[1] + (t1 * (uv2[1] - uv1[1]));
777
778 return;
779 }
780
781
getRenderNodes(std::vector<RenderSet> & rnodes)782 void MeshPolySceneNode::getRenderNodes(std::vector<RenderSet>& rnodes)
783 {
784 RenderSet rs = { &node, getWallGState() };
785 rnodes.push_back(rs);
786 return;
787 }
788
789
790 // Local Variables: ***
791 // mode: C++ ***
792 // tab-width: 4 ***
793 // c-basic-offset: 4 ***
794 // indent-tabs-mode: nil ***
795 // End: ***
796 // ex: shiftwidth=4 tabstop=4
797