2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #include "../precompiled.h"
38 ID_INLINE int UpdateVertexIndex( int vertexIndexNum[2], int *vertexRemap, int *vertexCopyIndex, int vertNum ) {
39 int s = INTSIGNBITSET( vertexRemap[vertNum] );
40 vertexIndexNum[0] = vertexRemap[vertNum];
41 vertexRemap[vertNum] = vertexIndexNum[s];
42 vertexIndexNum[1] += s;
43 vertexCopyIndex[vertexRemap[vertNum]] = vertNum;
44 return vertexRemap[vertNum];
52 int idSurface::Split( const idPlane &plane, const float epsilon, idSurface **front, idSurface **back, int *frontOnPlaneEdges, int *backOnPlaneEdges ) const {
57 int * edgeSplitVertex;
58 int numEdgeSplitVertexes;
60 int vertexIndexNum[2][2];
61 int * vertexCopyIndex[2];
65 int * onPlaneEdges[2];
66 int numOnPlaneEdges[2];
69 idSurface * surface[2];
72 dists = (float *) _alloca( verts.Num() * sizeof( float ) );
73 sides = (byte *) _alloca( verts.Num() * sizeof( byte ) );
75 counts[0] = counts[1] = counts[2] = 0;
77 // determine side for each vertex
78 for ( i = 0; i < verts.Num(); i++ ) {
79 dists[i] = f = plane.Distance( verts[i].xyz );
81 sides[i] = SIDE_FRONT;
82 } else if ( f < -epsilon ) {
90 *front = *back = NULL;
92 // if coplanar, put on the front side if the normals match
93 if ( !counts[SIDE_FRONT] && !counts[SIDE_BACK] ) {
95 f = ( verts[indexes[1]].xyz - verts[indexes[0]].xyz ).Cross( verts[indexes[0]].xyz - verts[indexes[2]].xyz ) * plane.Normal();
96 if ( FLOATSIGNBITSET( f ) ) {
97 *back = new idSurface( *this );
100 *front = new idSurface( *this );
104 // if nothing at the front of the clipping plane
105 if ( !counts[SIDE_FRONT] ) {
106 *back = new idSurface( *this );
109 // if nothing at the back of the clipping plane
110 if ( !counts[SIDE_BACK] ) {
111 *front = new idSurface( *this );
115 // allocate front and back surface
116 *front = surface[0] = new idSurface();
117 *back = surface[1] = new idSurface();
119 edgeSplitVertex = (int *) _alloca( edges.Num() * sizeof( int ) );
120 numEdgeSplitVertexes = 0;
122 maxOnPlaneEdges = 4 * counts[SIDE_ON];
123 counts[SIDE_FRONT] = counts[SIDE_BACK] = counts[SIDE_ON] = 0;
126 for ( i = 0; i < edges.Num(); i++ ) {
127 int v0 = edges[i].verts[0];
128 int v1 = edges[i].verts[1];
129 int sidesOr = ( sides[v0] | sides[v1] );
131 // if both vertexes are on the same side or one is on the clipping plane
132 if ( !( sides[v0] ^ sides[v1] ) || ( sidesOr & SIDE_ON ) ) {
133 edgeSplitVertex[i] = -1;
134 counts[sidesOr & SIDE_BACK]++;
135 counts[SIDE_ON] += ( sidesOr & SIDE_ON ) >> 1;
137 f = dists[v0] / ( dists[v0] - dists[v1] );
138 v.LerpAll( verts[v0], verts[v1], f );
139 edgeSplitVertex[i] = numEdgeSplitVertexes++;
140 surface[0]->verts.Append( v );
141 surface[1]->verts.Append( v );
145 // each edge is shared by at most two triangles, as such there can never be more indexes than twice the number of edges
146 surface[0]->indexes.Resize( ( ( counts[SIDE_FRONT] + counts[SIDE_ON] ) * 2 ) + ( numEdgeSplitVertexes * 4 ) );
147 surface[1]->indexes.Resize( ( ( counts[SIDE_BACK] + counts[SIDE_ON] ) * 2 ) + ( numEdgeSplitVertexes * 4 ) );
149 // allocate indexes to construct the triangle indexes for the front and back surface
150 vertexRemap[0] = (int *) _alloca( verts.Num() * sizeof( int ) );
151 memset( vertexRemap[0], -1, verts.Num() * sizeof( int ) );
152 vertexRemap[1] = (int *) _alloca( verts.Num() * sizeof( int ) );
153 memset( vertexRemap[1], -1, verts.Num() * sizeof( int ) );
155 vertexCopyIndex[0] = (int *) _alloca( ( numEdgeSplitVertexes + verts.Num() ) * sizeof( int ) );
156 vertexCopyIndex[1] = (int *) _alloca( ( numEdgeSplitVertexes + verts.Num() ) * sizeof( int ) );
158 vertexIndexNum[0][0] = vertexIndexNum[1][0] = 0;
159 vertexIndexNum[0][1] = vertexIndexNum[1][1] = numEdgeSplitVertexes;
161 indexPtr[0] = surface[0]->indexes.Ptr();
162 indexPtr[1] = surface[1]->indexes.Ptr();
163 indexNum[0] = surface[0]->indexes.Num();
164 indexNum[1] = surface[1]->indexes.Num();
166 maxOnPlaneEdges += 4 * numEdgeSplitVertexes;
167 // allocate one more in case no triangles are actually split which may happen for a disconnected surface
168 onPlaneEdges[0] = (int *) _alloca( ( maxOnPlaneEdges + 1 ) * sizeof( int ) );
169 onPlaneEdges[1] = (int *) _alloca( ( maxOnPlaneEdges + 1 ) * sizeof( int ) );
170 numOnPlaneEdges[0] = numOnPlaneEdges[1] = 0;
172 // split surface triangles
173 for ( i = 0; i < edgeIndexes.Num(); i += 3 ) {
174 int e0, e1, e2, v0, v1, v2, s, n;
176 e0 = abs( edgeIndexes[i+0] );
177 e1 = abs( edgeIndexes[i+1] );
178 e2 = abs( edgeIndexes[i+2] );
184 switch( ( INTSIGNBITSET( edgeSplitVertex[e0] ) | ( INTSIGNBITSET( edgeSplitVertex[e1] ) << 1 ) | ( INTSIGNBITSET( edgeSplitVertex[e2] ) << 2 ) ) ^ 7 ) {
185 case 0: { // no edges split
186 if ( ( sides[v0] & sides[v1] & sides[v2] ) & SIDE_ON ) {
188 f = ( verts[v1].xyz - verts[v0].xyz ).Cross( verts[v0].xyz - verts[v2].xyz ) * plane.Normal();
189 s = FLOATSIGNBITSET( f );
191 s = ( sides[v0] | sides[v1] | sides[v2] ) & SIDE_BACK;
194 onPlaneEdges[s][numOnPlaneEdges[s]] = n;
195 numOnPlaneEdges[s] += ( sides[v0] & sides[v1] ) >> 1;
196 onPlaneEdges[s][numOnPlaneEdges[s]] = n+1;
197 numOnPlaneEdges[s] += ( sides[v1] & sides[v2] ) >> 1;
198 onPlaneEdges[s][numOnPlaneEdges[s]] = n+2;
199 numOnPlaneEdges[s] += ( sides[v2] & sides[v0] ) >> 1;
201 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
202 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
203 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
207 case 1: { // first edge split
208 s = sides[v0] & SIDE_BACK;
210 onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
212 index[n++] = edgeSplitVertex[e0];
213 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
214 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
218 onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
220 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
221 index[n++] = edgeSplitVertex[e0];
222 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
226 case 2: { // second edge split
227 s = sides[v1] & SIDE_BACK;
229 onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
231 index[n++] = edgeSplitVertex[e1];
232 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
233 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
237 onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
239 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
240 index[n++] = edgeSplitVertex[e1];
241 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
245 case 3: { // first and second edge split
246 s = sides[v1] & SIDE_BACK;
248 onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
250 index[n++] = edgeSplitVertex[e1];
251 index[n++] = edgeSplitVertex[e0];
252 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
256 onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
258 index[n++] = edgeSplitVertex[e0];
259 index[n++] = edgeSplitVertex[e1];
260 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
261 index[n++] = edgeSplitVertex[e1];
262 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
263 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
267 case 4: { // third edge split
268 s = sides[v2] & SIDE_BACK;
270 onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
272 index[n++] = edgeSplitVertex[e2];
273 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
274 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
278 onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
280 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
281 index[n++] = edgeSplitVertex[e2];
282 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
286 case 5: { // first and third edge split
287 s = sides[v0] & SIDE_BACK;
289 onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
291 index[n++] = edgeSplitVertex[e0];
292 index[n++] = edgeSplitVertex[e2];
293 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
297 onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
299 index[n++] = edgeSplitVertex[e2];
300 index[n++] = edgeSplitVertex[e0];
301 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
302 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
303 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
304 index[n++] = edgeSplitVertex[e2];
308 case 6: { // second and third edge split
309 s = sides[v2] & SIDE_BACK;
311 onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
313 index[n++] = edgeSplitVertex[e2];
314 index[n++] = edgeSplitVertex[e1];
315 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
319 onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
321 index[n++] = edgeSplitVertex[e1];
322 index[n++] = edgeSplitVertex[e2];
323 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
324 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
325 index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
326 index[n++] = edgeSplitVertex[e2];
333 surface[0]->indexes.SetNum( indexNum[0], false );
334 surface[1]->indexes.SetNum( indexNum[1], false );
337 surface[0]->verts.SetNum( vertexIndexNum[0][1], false );
338 index = vertexCopyIndex[0];
339 for ( i = numEdgeSplitVertexes; i < surface[0]->verts.Num(); i++ ) {
340 surface[0]->verts[i] = verts[index[i]];
342 surface[1]->verts.SetNum( vertexIndexNum[1][1], false );
343 index = vertexCopyIndex[1];
344 for ( i = numEdgeSplitVertexes; i < surface[1]->verts.Num(); i++ ) {
345 surface[1]->verts[i] = verts[index[i]];
348 // generate edge indexes
349 surface[0]->GenerateEdgeIndexes();
350 surface[1]->GenerateEdgeIndexes();
352 if ( frontOnPlaneEdges ) {
353 memcpy( frontOnPlaneEdges, onPlaneEdges[0], numOnPlaneEdges[0] * sizeof( int ) );
354 frontOnPlaneEdges[numOnPlaneEdges[0]] = -1;
357 if ( backOnPlaneEdges ) {
358 memcpy( backOnPlaneEdges, onPlaneEdges[1], numOnPlaneEdges[1] * sizeof( int ) );
359 backOnPlaneEdges[numOnPlaneEdges[1]] = -1;
367 idSurface::ClipInPlace
370 bool idSurface::ClipInPlace( const idPlane &plane, const float epsilon, const bool keepOn ) {
376 int * edgeSplitVertex;
378 int vertexIndexNum[2];
379 int * vertexCopyIndex;
382 int numEdgeSplitVertexes;
384 idList<idDrawVert> newVerts;
385 idList<int> newIndexes;
387 dists = (float *) _alloca( verts.Num() * sizeof( float ) );
388 sides = (byte *) _alloca( verts.Num() * sizeof( byte ) );
390 counts[0] = counts[1] = counts[2] = 0;
392 // determine side for each vertex
393 for ( i = 0; i < verts.Num(); i++ ) {
394 dists[i] = f = plane.Distance( verts[i].xyz );
396 sides[i] = SIDE_FRONT;
397 } else if ( f < -epsilon ) {
398 sides[i] = SIDE_BACK;
405 // if coplanar, put on the front side if the normals match
406 if ( !counts[SIDE_FRONT] && !counts[SIDE_BACK] ) {
408 f = ( verts[indexes[1]].xyz - verts[indexes[0]].xyz ).Cross( verts[indexes[0]].xyz - verts[indexes[2]].xyz ) * plane.Normal();
409 if ( FLOATSIGNBITSET( f ) ) {
416 // if nothing at the front of the clipping plane
417 if ( !counts[SIDE_FRONT] ) {
421 // if nothing at the back of the clipping plane
422 if ( !counts[SIDE_BACK] ) {
426 edgeSplitVertex = (int *) _alloca( edges.Num() * sizeof( int ) );
427 numEdgeSplitVertexes = 0;
429 counts[SIDE_FRONT] = counts[SIDE_BACK] = 0;
432 for ( i = 0; i < edges.Num(); i++ ) {
433 int v0 = edges[i].verts[0];
434 int v1 = edges[i].verts[1];
436 // if both vertexes are on the same side or one is on the clipping plane
437 if ( !( sides[v0] ^ sides[v1] ) || ( ( sides[v0] | sides[v1] ) & SIDE_ON ) ) {
438 edgeSplitVertex[i] = -1;
439 counts[(sides[v0]|sides[v1]) & SIDE_BACK]++;
441 f = dists[v0] / ( dists[v0] - dists[v1] );
442 v.LerpAll( verts[v0], verts[v1], f );
443 edgeSplitVertex[i] = numEdgeSplitVertexes++;
444 newVerts.Append( v );
448 // each edge is shared by at most two triangles, as such there can never be
449 // more indexes than twice the number of edges
450 newIndexes.Resize( ( counts[SIDE_FRONT] << 1 ) + ( numEdgeSplitVertexes << 2 ) );
452 // allocate indexes to construct the triangle indexes for the front and back surface
453 vertexRemap = (int *) _alloca( verts.Num() * sizeof( int ) );
454 memset( vertexRemap, -1, verts.Num() * sizeof( int ) );
456 vertexCopyIndex = (int *) _alloca( ( numEdgeSplitVertexes + verts.Num() ) * sizeof( int ) );
458 vertexIndexNum[0] = 0;
459 vertexIndexNum[1] = numEdgeSplitVertexes;
461 indexPtr = newIndexes.Ptr();
462 indexNum = newIndexes.Num();
464 // split surface triangles
465 for ( i = 0; i < edgeIndexes.Num(); i += 3 ) {
466 int e0, e1, e2, v0, v1, v2;
468 e0 = abs( edgeIndexes[i+0] );
469 e1 = abs( edgeIndexes[i+1] );
470 e2 = abs( edgeIndexes[i+2] );
476 switch( ( INTSIGNBITSET( edgeSplitVertex[e0] ) | ( INTSIGNBITSET( edgeSplitVertex[e1] ) << 1 ) | ( INTSIGNBITSET( edgeSplitVertex[e2] ) << 2 ) ) ^ 7 ) {
477 case 0: { // no edges split
478 if ( ( sides[v0] | sides[v1] | sides[v2] ) & SIDE_BACK ) {
481 if ( ( sides[v0] & sides[v1] & sides[v2] ) & SIDE_ON ) {
486 f = ( verts[v1].xyz - verts[v0].xyz ).Cross( verts[v0].xyz - verts[v2].xyz ) * plane.Normal();
487 if ( FLOATSIGNBITSET( f ) ) {
491 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
492 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
493 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
496 case 1: { // first edge split
497 if ( !( sides[v0] & SIDE_BACK ) ) {
498 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
499 indexPtr[indexNum++] = edgeSplitVertex[e0];
500 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
502 indexPtr[indexNum++] = edgeSplitVertex[e0];
503 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
504 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
508 case 2: { // second edge split
509 if ( !( sides[v1] & SIDE_BACK ) ) {
510 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
511 indexPtr[indexNum++] = edgeSplitVertex[e1];
512 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
514 indexPtr[indexNum++] = edgeSplitVertex[e1];
515 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
516 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
520 case 3: { // first and second edge split
521 if ( !( sides[v1] & SIDE_BACK ) ) {
522 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
523 indexPtr[indexNum++] = edgeSplitVertex[e1];
524 indexPtr[indexNum++] = edgeSplitVertex[e0];
526 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
527 indexPtr[indexNum++] = edgeSplitVertex[e0];
528 indexPtr[indexNum++] = edgeSplitVertex[e1];
529 indexPtr[indexNum++] = edgeSplitVertex[e1];
530 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
531 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
535 case 4: { // third edge split
536 if ( !( sides[v2] & SIDE_BACK ) ) {
537 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
538 indexPtr[indexNum++] = edgeSplitVertex[e2];
539 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
541 indexPtr[indexNum++] = edgeSplitVertex[e2];
542 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
543 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
547 case 5: { // first and third edge split
548 if ( !( sides[v0] & SIDE_BACK ) ) {
549 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
550 indexPtr[indexNum++] = edgeSplitVertex[e0];
551 indexPtr[indexNum++] = edgeSplitVertex[e2];
553 indexPtr[indexNum++] = edgeSplitVertex[e0];
554 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
555 indexPtr[indexNum++] = edgeSplitVertex[e2];
556 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
557 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
558 indexPtr[indexNum++] = edgeSplitVertex[e2];
562 case 6: { // second and third edge split
563 if ( !( sides[v2] & SIDE_BACK ) ) {
564 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
565 indexPtr[indexNum++] = edgeSplitVertex[e2];
566 indexPtr[indexNum++] = edgeSplitVertex[e1];
568 indexPtr[indexNum++] = edgeSplitVertex[e2];
569 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
570 indexPtr[indexNum++] = edgeSplitVertex[e1];
571 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
572 indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
573 indexPtr[indexNum++] = edgeSplitVertex[e2];
580 newIndexes.SetNum( indexNum, false );
583 newVerts.SetNum( vertexIndexNum[1], false );
584 for ( i = numEdgeSplitVertexes; i < newVerts.Num(); i++ ) {
585 newVerts[i] = verts[vertexCopyIndex[i]];
588 // copy back to this surface
589 indexes = newIndexes;
592 GenerateEdgeIndexes();
599 idSurface::IsConnected
602 bool idSurface::IsConnected( void ) const {
603 int i, j, numIslands, numTris;
604 int queueStart, queueEnd;
605 int *queue, *islandNum;
606 int curTri, nextTri, edgeNum;
610 numTris = indexes.Num() / 3;
611 islandNum = (int *) _alloca16( numTris * sizeof( int ) );
612 memset( islandNum, -1, numTris * sizeof( int ) );
613 queue = (int *) _alloca16( numTris * sizeof( int ) );
615 for ( i = 0; i < numTris; i++ ) {
617 if ( islandNum[i] != -1 ) {
624 islandNum[i] = numIslands;
626 for ( curTri = queue[queueStart]; queueStart < queueEnd; curTri = queue[++queueStart] ) {
628 index = &edgeIndexes[curTri * 3];
630 for ( j = 0; j < 3; j++ ) {
633 nextTri = edges[abs(edgeNum)].tris[INTSIGNBITNOTSET(edgeNum)];
635 if ( nextTri == -1 ) {
641 if ( islandNum[nextTri] != -1 ) {
645 queue[queueEnd++] = nextTri;
646 islandNum[nextTri] = numIslands;
652 return ( numIslands == 1 );
660 bool idSurface::IsClosed( void ) const {
661 for ( int i = 0; i < edges.Num(); i++ ) {
662 if ( edges[i].tris[0] < 0 || edges[i].tris[1] < 0 ) {
671 idSurface::IsPolytope
674 bool idSurface::IsPolytope( const float epsilon ) const {
682 for ( i = 0; i < indexes.Num(); i += 3 ) {
683 plane.FromPoints( verts[indexes[i+0]].xyz, verts[indexes[i+1]].xyz, verts[indexes[i+2]].xyz );
685 for ( j = 0; j < verts.Num(); j++ ) {
686 if ( plane.Side( verts[j].xyz, epsilon ) == SIDE_FRONT ) {
696 idSurface::PlaneDistance
699 float idSurface::PlaneDistance( const idPlane &plane ) const {
703 min = idMath::INFINITY;
705 for ( i = 0; i < verts.Num(); i++ ) {
706 d = plane.Distance( verts[i].xyz );
709 if ( FLOATSIGNBITSET( min ) & FLOATSIGNBITNOTSET( max ) ) {
715 if ( FLOATSIGNBITSET( min ) & FLOATSIGNBITNOTSET( max ) ) {
720 if ( FLOATSIGNBITNOTSET( min ) ) {
723 if ( FLOATSIGNBITSET( max ) ) {
734 int idSurface::PlaneSide( const idPlane &plane, const float epsilon ) const {
741 for ( i = 0; i < verts.Num(); i++ ) {
742 d = plane.Distance( verts[i].xyz );
743 if ( d < -epsilon ) {
750 else if ( d > epsilon ) {
770 idSurface::LineIntersection
773 bool idSurface::LineIntersection( const idVec3 &start, const idVec3 &end, bool backFaceCull ) const {
776 RayIntersection( start, end - start, scale, false );
777 return ( scale >= 0.0f && scale <= 1.0f );
782 idSurface::RayIntersection
785 bool idSurface::RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale, bool backFaceCull ) const {
786 int i, i0, i1, i2, s0, s1, s2;
789 idPluecker rayPl, pl;
792 sidedness = (byte *)_alloca( edges.Num() * sizeof(byte) );
793 scale = idMath::INFINITY;
795 rayPl.FromRay( start, dir );
797 // ray sidedness for edges
798 for ( i = 0; i < edges.Num(); i++ ) {
799 pl.FromLine( verts[ edges[i].verts[1] ].xyz, verts[ edges[i].verts[0] ].xyz );
800 d = pl.PermutedInnerProduct( rayPl );
801 sidedness[ i ] = FLOATSIGNBITSET( d );
805 for ( i = 0; i < edgeIndexes.Num(); i += 3 ) {
806 i0 = edgeIndexes[i+0];
807 i1 = edgeIndexes[i+1];
808 i2 = edgeIndexes[i+2];
809 s0 = sidedness[abs(i0)] ^ INTSIGNBITSET( i0 );
810 s1 = sidedness[abs(i1)] ^ INTSIGNBITSET( i1 );
811 s2 = sidedness[abs(i2)] ^ INTSIGNBITSET( i2 );
813 if ( s0 & s1 & s2 ) {
814 plane.FromPoints( verts[indexes[i+0]].xyz, verts[indexes[i+1]].xyz, verts[indexes[i+2]].xyz );
815 plane.RayIntersection( start, dir, s );
816 if ( idMath::Fabs( s ) < idMath::Fabs( scale ) ) {
819 } else if ( !backFaceCull && !(s0 | s1 | s2) ) {
820 plane.FromPoints( verts[indexes[i+0]].xyz, verts[indexes[i+1]].xyz, verts[indexes[i+2]].xyz );
821 plane.RayIntersection( start, dir, s );
822 if ( idMath::Fabs( s ) < idMath::Fabs( scale ) ) {
828 if ( idMath::Fabs( scale ) < idMath::INFINITY ) {
836 idSurface::GenerateEdgeIndexes
838 Assumes each edge is shared by at most two triangles.
841 void idSurface::GenerateEdgeIndexes( void ) {
842 int i, j, i0, i1, i2, s, v0, v1, edgeNum;
843 int *index, *vertexEdges, *edgeChain;
846 vertexEdges = (int *) _alloca16( verts.Num() * sizeof( int ) );
847 memset( vertexEdges, -1, verts.Num() * sizeof( int ) );
848 edgeChain = (int *) _alloca16( indexes.Num() * sizeof( int ) );
850 edgeIndexes.SetNum( indexes.Num(), true );
854 // the first edge is a dummy
855 e[0].verts[0] = e[0].verts[1] = e[0].tris[0] = e[0].tris[1] = 0;
856 edges.Append( e[0] );
858 for ( i = 0; i < indexes.Num(); i += 3 ) {
859 index = indexes.Ptr() + i;
864 // setup edges each with smallest vertex number first
865 s = INTSIGNBITSET(i1 - i0);
866 e[0].verts[0] = index[s];
867 e[0].verts[1] = index[s^1];
868 s = INTSIGNBITSET(i2 - i1) + 1;
869 e[1].verts[0] = index[s];
870 e[1].verts[1] = index[s^3];
871 s = INTSIGNBITSET(i2 - i0) << 1;
872 e[2].verts[0] = index[s];
873 e[2].verts[1] = index[s^2];
875 for ( j = 0; j < 3; j++ ) {
878 for ( edgeNum = vertexEdges[v0]; edgeNum >= 0; edgeNum = edgeChain[edgeNum] ) {
879 if ( edges[edgeNum].verts[1] == v1 ) {
883 // if the edge does not yet exist
885 e[j].tris[0] = e[j].tris[1] = -1;
886 edgeNum = edges.Append( e[j] );
887 edgeChain[edgeNum] = vertexEdges[v0];
888 vertexEdges[v0] = edgeNum;
890 // update edge index and edge tri references
891 if ( index[j] == v0 ) {
892 assert( edges[edgeNum].tris[0] == -1 ); // edge may not be shared by more than two triangles
893 edges[edgeNum].tris[0] = i;
894 edgeIndexes[i+j] = edgeNum;
896 assert( edges[edgeNum].tris[1] == -1 ); // edge may not be shared by more than two triangles
897 edges[edgeNum].tris[1] = i;
898 edgeIndexes[i+j] = -edgeNum;
909 int idSurface::FindEdge( int v1, int v2 ) const {
910 int i, firstVert, secondVert;
919 for ( i = 1; i < edges.Num(); i++ ) {
920 if ( edges[i].verts[0] == firstVert ) {
921 if ( edges[i].verts[1] == secondVert ) {
926 if ( i < edges.Num() ) {
927 return v1 < v2 ? i : -i;