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"
32 #define POLYTOPE_VERTEX_EPSILON 0.1f
37 idSurface_Polytope::FromPlanes
40 void idSurface_Polytope::FromPlanes( const idPlane *planes, const int numPlanes ) {
41 int i, j, k, *windingVerts;
45 windingVerts = (int *) _alloca( MAX_POINTS_ON_WINDING * sizeof( int ) );
46 memset( &newVert, 0, sizeof( newVert ) );
48 for ( i = 0; i < numPlanes; i++ ) {
50 w.BaseForPlane( planes[i] );
52 for ( j = 0; j < numPlanes; j++ ) {
56 if ( !w.ClipInPlace( -planes[j], ON_EPSILON, true ) ) {
60 if ( !w.GetNumPoints() ) {
64 for ( j = 0; j < w.GetNumPoints(); j++ ) {
65 for ( k = 0; k < verts.Num(); j++ ) {
66 if ( verts[k].xyz.Compare( w[j].ToVec3(), POLYTOPE_VERTEX_EPSILON ) ) {
70 if ( k >= verts.Num() ) {
71 newVert.xyz = w[j].ToVec3();
72 k = verts.Append( newVert );
77 for ( j = 2; j < w.GetNumPoints(); j++ ) {
78 indexes.Append( windingVerts[0] );
79 indexes.Append( windingVerts[j-1] );
80 indexes.Append( windingVerts[j] );
84 GenerateEdgeIndexes();
89 idSurface_Polytope::SetupTetrahedron
92 void idSurface_Polytope::SetupTetrahedron( const idBounds &bounds ) {
100 center = bounds.GetCenter();
101 scale = bounds[1] - center;
104 verts[0].xyz = center + idVec3( 0.0f, 0.0f, scale.z );
105 verts[1].xyz = center + idVec3( 2.0f * c1 * scale.x, 0.0f, c3 * scale.z );
106 verts[2].xyz = center + idVec3( -c1 * scale.x, c2 * scale.y, c3 * scale.z );
107 verts[3].xyz = center + idVec3( -c1 * scale.x, -c2 * scale.y, c3 * scale.z );
109 indexes.SetNum( 4*3 );
123 GenerateEdgeIndexes();
128 idSurface_Polytope::SetupHexahedron
131 void idSurface_Polytope::SetupHexahedron( const idBounds &bounds ) {
132 idVec3 center, scale;
134 center = bounds.GetCenter();
135 scale = bounds[1] - center;
138 verts[0].xyz = center + idVec3( -scale.x, -scale.y, -scale.z );
139 verts[1].xyz = center + idVec3( scale.x, -scale.y, -scale.z );
140 verts[2].xyz = center + idVec3( scale.x, scale.y, -scale.z );
141 verts[3].xyz = center + idVec3( -scale.x, scale.y, -scale.z );
142 verts[4].xyz = center + idVec3( -scale.x, -scale.y, scale.z );
143 verts[5].xyz = center + idVec3( scale.x, -scale.y, scale.z );
144 verts[6].xyz = center + idVec3( scale.x, scale.y, scale.z );
145 verts[7].xyz = center + idVec3( -scale.x, scale.y, scale.z );
147 indexes.SetNum( 12*3 );
185 GenerateEdgeIndexes();
190 idSurface_Polytope::SetupOctahedron
193 void idSurface_Polytope::SetupOctahedron( const idBounds &bounds ) {
194 idVec3 center, scale;
196 center = bounds.GetCenter();
197 scale = bounds[1] - center;
200 verts[0].xyz = center + idVec3( scale.x, 0.0f, 0.0f );
201 verts[1].xyz = center + idVec3( -scale.x, 0.0f, 0.0f );
202 verts[2].xyz = center + idVec3( 0.0f, scale.y, 0.0f );
203 verts[3].xyz = center + idVec3( 0.0f, -scale.y, 0.0f );
204 verts[4].xyz = center + idVec3( 0.0f, 0.0f, scale.z );
205 verts[5].xyz = center + idVec3( 0.0f, 0.0f, -scale.z );
207 indexes.SetNum( 8*3 );
233 GenerateEdgeIndexes();
238 idSurface_Polytope::SetupDodecahedron
241 void idSurface_Polytope::SetupDodecahedron( const idBounds &bounds ) {
246 idSurface_Polytope::SetupIcosahedron
249 void idSurface_Polytope::SetupIcosahedron( const idBounds &bounds ) {
254 idSurface_Polytope::SetupCylinder
257 void idSurface_Polytope::SetupCylinder( const idBounds &bounds, const int numSides ) {
262 idSurface_Polytope::SetupCone
265 void idSurface_Polytope::SetupCone( const idBounds &bounds, const int numSides ) {
270 idSurface_Polytope::SplitPolytope
273 int idSurface_Polytope::SplitPolytope( const idPlane &plane, const float epsilon, idSurface_Polytope **front, idSurface_Polytope **back ) const {
274 int side, i, j, s, v0, v1, v2, edgeNum;
275 idSurface *surface[2];
276 idSurface_Polytope *polytopeSurfaces[2], *surf;
277 int *onPlaneEdges[2];
279 onPlaneEdges[0] = (int *) _alloca( indexes.Num() / 3 * sizeof( int ) );
280 onPlaneEdges[1] = (int *) _alloca( indexes.Num() / 3 * sizeof( int ) );
282 side = Split( plane, epsilon, &surface[0], &surface[1], onPlaneEdges[0], onPlaneEdges[1] );
284 *front = polytopeSurfaces[0] = new idSurface_Polytope;
285 *back = polytopeSurfaces[1] = new idSurface_Polytope;
287 for ( s = 0; s < 2; s++ ) {
289 polytopeSurfaces[s] = new idSurface_Polytope;
290 polytopeSurfaces[s]->SwapTriangles( *surface[s] );
296 *front = polytopeSurfaces[0];
297 *back = polytopeSurfaces[1];
299 if ( side != SIDE_CROSS ) {
303 // add triangles to close off the front and back polytope
304 for ( s = 0; s < 2; s++ ) {
306 surf = polytopeSurfaces[s];
308 edgeNum = surf->edgeIndexes[onPlaneEdges[s][0]];
309 v0 = surf->edges[abs(edgeNum)].verts[INTSIGNBITSET(edgeNum)];
310 v1 = surf->edges[abs(edgeNum)].verts[INTSIGNBITNOTSET(edgeNum)];
312 for ( i = 1; onPlaneEdges[s][i] >= 0; i++ ) {
313 for ( j = i+1; onPlaneEdges[s][j] >= 0; j++ ) {
314 edgeNum = surf->edgeIndexes[onPlaneEdges[s][j]];
315 if ( v1 == surf->edges[abs(edgeNum)].verts[INTSIGNBITSET(edgeNum)] ) {
316 v1 = surf->edges[abs(edgeNum)].verts[INTSIGNBITNOTSET(edgeNum)];
317 idSwap( onPlaneEdges[s][i], onPlaneEdges[s][j] );
323 for ( i = 2; onPlaneEdges[s][i] >= 0; i++ ) {
324 edgeNum = surf->edgeIndexes[onPlaneEdges[s][i]];
325 v1 = surf->edges[abs(edgeNum)].verts[INTSIGNBITNOTSET(edgeNum)];
326 v2 = surf->edges[abs(edgeNum)].verts[INTSIGNBITSET(edgeNum)];
327 surf->indexes.Append( v0 );
328 surf->indexes.Append( v1 );
329 surf->indexes.Append( v2 );
332 surf->GenerateEdgeIndexes();