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