Surface.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition 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 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. 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.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../precompiled.h"
  22. /*
  23. =================
  24. UpdateVertexIndex
  25. =================
  26. */
  27. ID_INLINE int UpdateVertexIndex( int vertexIndexNum[2], int *vertexRemap, int *vertexCopyIndex, int vertNum ) {
  28. int s = INT32_SIGNBITSET( vertexRemap[vertNum] );
  29. vertexIndexNum[0] = vertexRemap[vertNum];
  30. vertexRemap[vertNum] = vertexIndexNum[s];
  31. vertexIndexNum[1] += s;
  32. vertexCopyIndex[vertexRemap[vertNum]] = vertNum;
  33. return vertexRemap[vertNum];
  34. }
  35. /*
  36. =================
  37. idSurface::Split
  38. =================
  39. */
  40. int idSurface::Split( const idPlane &plane, const float epsilon, idSurface **front, idSurface **back, int *frontOnPlaneEdges, int *backOnPlaneEdges ) const {
  41. float * dists;
  42. float f;
  43. byte * sides;
  44. int counts[3];
  45. int * edgeSplitVertex;
  46. int numEdgeSplitVertexes;
  47. int * vertexRemap[2];
  48. int vertexIndexNum[2][2];
  49. int * vertexCopyIndex[2];
  50. int * indexPtr[2];
  51. int indexNum[2];
  52. int * index;
  53. int * onPlaneEdges[2];
  54. int numOnPlaneEdges[2];
  55. int maxOnPlaneEdges;
  56. int i;
  57. idSurface * surface[2];
  58. idDrawVert v;
  59. dists = (float *) _alloca( verts.Num() * sizeof( float ) );
  60. sides = (byte *) _alloca( verts.Num() * sizeof( byte ) );
  61. counts[0] = counts[1] = counts[2] = 0;
  62. // determine side for each vertex
  63. for ( i = 0; i < verts.Num(); i++ ) {
  64. dists[i] = f = plane.Distance( verts[i].xyz );
  65. if ( f > epsilon ) {
  66. sides[i] = SIDE_FRONT;
  67. } else if ( f < -epsilon ) {
  68. sides[i] = SIDE_BACK;
  69. } else {
  70. sides[i] = SIDE_ON;
  71. }
  72. counts[sides[i]]++;
  73. }
  74. *front = *back = NULL;
  75. // if coplanar, put on the front side if the normals match
  76. if ( !counts[SIDE_FRONT] && !counts[SIDE_BACK] ) {
  77. f = ( verts[indexes[1]].xyz - verts[indexes[0]].xyz ).Cross( verts[indexes[0]].xyz - verts[indexes[2]].xyz ) * plane.Normal();
  78. if ( IEEE_FLT_SIGNBITSET( f ) ) {
  79. *back = new (TAG_IDLIB_SURFACE) idSurface( *this );
  80. return SIDE_BACK;
  81. } else {
  82. *front = new (TAG_IDLIB_SURFACE) idSurface( *this );
  83. return SIDE_FRONT;
  84. }
  85. }
  86. // if nothing at the front of the clipping plane
  87. if ( !counts[SIDE_FRONT] ) {
  88. *back = new (TAG_IDLIB_SURFACE) idSurface( *this );
  89. return SIDE_BACK;
  90. }
  91. // if nothing at the back of the clipping plane
  92. if ( !counts[SIDE_BACK] ) {
  93. *front = new (TAG_IDLIB_SURFACE) idSurface( *this );
  94. return SIDE_FRONT;
  95. }
  96. // allocate front and back surface
  97. *front = surface[0] = new (TAG_IDLIB_SURFACE) idSurface();
  98. *back = surface[1] = new (TAG_IDLIB_SURFACE) idSurface();
  99. edgeSplitVertex = (int *) _alloca( edges.Num() * sizeof( int ) );
  100. numEdgeSplitVertexes = 0;
  101. maxOnPlaneEdges = 4 * counts[SIDE_ON];
  102. counts[SIDE_FRONT] = counts[SIDE_BACK] = counts[SIDE_ON] = 0;
  103. // split edges
  104. for ( i = 0; i < edges.Num(); i++ ) {
  105. int v0 = edges[i].verts[0];
  106. int v1 = edges[i].verts[1];
  107. int sidesOr = ( sides[v0] | sides[v1] );
  108. // if both vertexes are on the same side or one is on the clipping plane
  109. if ( !( sides[v0] ^ sides[v1] ) || ( sidesOr & SIDE_ON ) ) {
  110. edgeSplitVertex[i] = -1;
  111. counts[sidesOr & SIDE_BACK]++;
  112. counts[SIDE_ON] += ( sidesOr & SIDE_ON ) >> 1;
  113. } else {
  114. f = dists[v0] / ( dists[v0] - dists[v1] );
  115. v.LerpAll( verts[v0], verts[v1], f );
  116. edgeSplitVertex[i] = numEdgeSplitVertexes++;
  117. surface[0]->verts.Append( v );
  118. surface[1]->verts.Append( v );
  119. }
  120. }
  121. // each edge is shared by at most two triangles, as such there can never be more indexes than twice the number of edges
  122. surface[0]->indexes.Resize( ( ( counts[SIDE_FRONT] + counts[SIDE_ON] ) * 2 ) + ( numEdgeSplitVertexes * 4 ) );
  123. surface[1]->indexes.Resize( ( ( counts[SIDE_BACK] + counts[SIDE_ON] ) * 2 ) + ( numEdgeSplitVertexes * 4 ) );
  124. // allocate indexes to construct the triangle indexes for the front and back surface
  125. vertexRemap[0] = (int *) _alloca( verts.Num() * sizeof( int ) );
  126. memset( vertexRemap[0], -1, verts.Num() * sizeof( int ) );
  127. vertexRemap[1] = (int *) _alloca( verts.Num() * sizeof( int ) );
  128. memset( vertexRemap[1], -1, verts.Num() * sizeof( int ) );
  129. vertexCopyIndex[0] = (int *) _alloca( ( numEdgeSplitVertexes + verts.Num() ) * sizeof( int ) );
  130. vertexCopyIndex[1] = (int *) _alloca( ( numEdgeSplitVertexes + verts.Num() ) * sizeof( int ) );
  131. vertexIndexNum[0][0] = vertexIndexNum[1][0] = 0;
  132. vertexIndexNum[0][1] = vertexIndexNum[1][1] = numEdgeSplitVertexes;
  133. indexPtr[0] = surface[0]->indexes.Ptr();
  134. indexPtr[1] = surface[1]->indexes.Ptr();
  135. indexNum[0] = surface[0]->indexes.Num();
  136. indexNum[1] = surface[1]->indexes.Num();
  137. maxOnPlaneEdges += 4 * numEdgeSplitVertexes;
  138. // allocate one more in case no triangles are actually split which may happen for a disconnected surface
  139. onPlaneEdges[0] = (int *) _alloca( ( maxOnPlaneEdges + 1 ) * sizeof( int ) );
  140. onPlaneEdges[1] = (int *) _alloca( ( maxOnPlaneEdges + 1 ) * sizeof( int ) );
  141. numOnPlaneEdges[0] = numOnPlaneEdges[1] = 0;
  142. // split surface triangles
  143. for ( i = 0; i < edgeIndexes.Num(); i += 3 ) {
  144. int e0, e1, e2, v0, v1, v2, s, n;
  145. e0 = abs( edgeIndexes[i+0] );
  146. e1 = abs( edgeIndexes[i+1] );
  147. e2 = abs( edgeIndexes[i+2] );
  148. v0 = indexes[i+0];
  149. v1 = indexes[i+1];
  150. v2 = indexes[i+2];
  151. switch( ( INT32_SIGNBITSET( edgeSplitVertex[e0] ) | ( INT32_SIGNBITSET( edgeSplitVertex[e1] ) << 1 ) | ( INT32_SIGNBITSET( edgeSplitVertex[e2] ) << 2 ) ) ^ 7 ) {
  152. case 0: { // no edges split
  153. if ( ( sides[v0] & sides[v1] & sides[v2] ) & SIDE_ON ) {
  154. // coplanar
  155. f = ( verts[v1].xyz - verts[v0].xyz ).Cross( verts[v0].xyz - verts[v2].xyz ) * plane.Normal();
  156. s = IEEE_FLT_SIGNBITSET( f );
  157. } else {
  158. s = ( sides[v0] | sides[v1] | sides[v2] ) & SIDE_BACK;
  159. }
  160. n = indexNum[s];
  161. onPlaneEdges[s][numOnPlaneEdges[s]] = n;
  162. numOnPlaneEdges[s] += ( sides[v0] & sides[v1] ) >> 1;
  163. onPlaneEdges[s][numOnPlaneEdges[s]] = n+1;
  164. numOnPlaneEdges[s] += ( sides[v1] & sides[v2] ) >> 1;
  165. onPlaneEdges[s][numOnPlaneEdges[s]] = n+2;
  166. numOnPlaneEdges[s] += ( sides[v2] & sides[v0] ) >> 1;
  167. index = indexPtr[s];
  168. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
  169. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
  170. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
  171. indexNum[s] = n;
  172. break;
  173. }
  174. case 1: { // first edge split
  175. s = sides[v0] & SIDE_BACK;
  176. n = indexNum[s];
  177. onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
  178. index = indexPtr[s];
  179. index[n++] = edgeSplitVertex[e0];
  180. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
  181. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
  182. indexNum[s] = n;
  183. s ^= 1;
  184. n = indexNum[s];
  185. onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
  186. index = indexPtr[s];
  187. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
  188. index[n++] = edgeSplitVertex[e0];
  189. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
  190. indexNum[s] = n;
  191. break;
  192. }
  193. case 2: { // second edge split
  194. s = sides[v1] & SIDE_BACK;
  195. n = indexNum[s];
  196. onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
  197. index = indexPtr[s];
  198. index[n++] = edgeSplitVertex[e1];
  199. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
  200. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
  201. indexNum[s] = n;
  202. s ^= 1;
  203. n = indexNum[s];
  204. onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
  205. index = indexPtr[s];
  206. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
  207. index[n++] = edgeSplitVertex[e1];
  208. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
  209. indexNum[s] = n;
  210. break;
  211. }
  212. case 3: { // first and second edge split
  213. s = sides[v1] & SIDE_BACK;
  214. n = indexNum[s];
  215. onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
  216. index = indexPtr[s];
  217. index[n++] = edgeSplitVertex[e1];
  218. index[n++] = edgeSplitVertex[e0];
  219. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
  220. indexNum[s] = n;
  221. s ^= 1;
  222. n = indexNum[s];
  223. onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
  224. index = indexPtr[s];
  225. index[n++] = edgeSplitVertex[e0];
  226. index[n++] = edgeSplitVertex[e1];
  227. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
  228. index[n++] = edgeSplitVertex[e1];
  229. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
  230. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
  231. indexNum[s] = n;
  232. break;
  233. }
  234. case 4: { // third edge split
  235. s = sides[v2] & SIDE_BACK;
  236. n = indexNum[s];
  237. onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
  238. index = indexPtr[s];
  239. index[n++] = edgeSplitVertex[e2];
  240. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
  241. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
  242. indexNum[s] = n;
  243. s ^= 1;
  244. n = indexNum[s];
  245. onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
  246. index = indexPtr[s];
  247. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
  248. index[n++] = edgeSplitVertex[e2];
  249. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
  250. indexNum[s] = n;
  251. break;
  252. }
  253. case 5: { // first and third edge split
  254. s = sides[v0] & SIDE_BACK;
  255. n = indexNum[s];
  256. onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
  257. index = indexPtr[s];
  258. index[n++] = edgeSplitVertex[e0];
  259. index[n++] = edgeSplitVertex[e2];
  260. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
  261. indexNum[s] = n;
  262. s ^= 1;
  263. n = indexNum[s];
  264. onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
  265. index = indexPtr[s];
  266. index[n++] = edgeSplitVertex[e2];
  267. index[n++] = edgeSplitVertex[e0];
  268. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
  269. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
  270. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
  271. index[n++] = edgeSplitVertex[e2];
  272. indexNum[s] = n;
  273. break;
  274. }
  275. case 6: { // second and third edge split
  276. s = sides[v2] & SIDE_BACK;
  277. n = indexNum[s];
  278. onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
  279. index = indexPtr[s];
  280. index[n++] = edgeSplitVertex[e2];
  281. index[n++] = edgeSplitVertex[e1];
  282. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v2 );
  283. indexNum[s] = n;
  284. s ^= 1;
  285. n = indexNum[s];
  286. onPlaneEdges[s][numOnPlaneEdges[s]++] = n;
  287. index = indexPtr[s];
  288. index[n++] = edgeSplitVertex[e1];
  289. index[n++] = edgeSplitVertex[e2];
  290. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
  291. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v0 );
  292. index[n++] = UpdateVertexIndex( vertexIndexNum[s], vertexRemap[s], vertexCopyIndex[s], v1 );
  293. index[n++] = edgeSplitVertex[e2];
  294. indexNum[s] = n;
  295. break;
  296. }
  297. }
  298. }
  299. surface[0]->indexes.SetNum( indexNum[0] );
  300. surface[1]->indexes.SetNum( indexNum[1] );
  301. // copy vertexes
  302. surface[0]->verts.SetNum( vertexIndexNum[0][1] );
  303. index = vertexCopyIndex[0];
  304. for ( i = numEdgeSplitVertexes; i < surface[0]->verts.Num(); i++ ) {
  305. surface[0]->verts[i] = verts[index[i]];
  306. }
  307. surface[1]->verts.SetNum( vertexIndexNum[1][1] );
  308. index = vertexCopyIndex[1];
  309. for ( i = numEdgeSplitVertexes; i < surface[1]->verts.Num(); i++ ) {
  310. surface[1]->verts[i] = verts[index[i]];
  311. }
  312. // generate edge indexes
  313. surface[0]->GenerateEdgeIndexes();
  314. surface[1]->GenerateEdgeIndexes();
  315. if ( frontOnPlaneEdges ) {
  316. memcpy( frontOnPlaneEdges, onPlaneEdges[0], numOnPlaneEdges[0] * sizeof( int ) );
  317. frontOnPlaneEdges[numOnPlaneEdges[0]] = -1;
  318. }
  319. if ( backOnPlaneEdges ) {
  320. memcpy( backOnPlaneEdges, onPlaneEdges[1], numOnPlaneEdges[1] * sizeof( int ) );
  321. backOnPlaneEdges[numOnPlaneEdges[1]] = -1;
  322. }
  323. return SIDE_CROSS;
  324. }
  325. /*
  326. =================
  327. idSurface::ClipInPlace
  328. =================
  329. */
  330. bool idSurface::ClipInPlace( const idPlane &plane, const float epsilon, const bool keepOn ) {
  331. float * dists;
  332. float f;
  333. byte * sides;
  334. int counts[3];
  335. int i;
  336. int * edgeSplitVertex;
  337. int * vertexRemap;
  338. int vertexIndexNum[2];
  339. int * vertexCopyIndex;
  340. int * indexPtr;
  341. int indexNum;
  342. int numEdgeSplitVertexes;
  343. idDrawVert v;
  344. idList<idDrawVert, TAG_IDLIB_LIST_SURFACE> newVerts;
  345. idList<int, TAG_IDLIB_LIST_SURFACE> newIndexes;
  346. dists = (float *) _alloca( verts.Num() * sizeof( float ) );
  347. sides = (byte *) _alloca( verts.Num() * sizeof( byte ) );
  348. counts[0] = counts[1] = counts[2] = 0;
  349. // determine side for each vertex
  350. for ( i = 0; i < verts.Num(); i++ ) {
  351. dists[i] = f = plane.Distance( verts[i].xyz );
  352. if ( f > epsilon ) {
  353. sides[i] = SIDE_FRONT;
  354. } else if ( f < -epsilon ) {
  355. sides[i] = SIDE_BACK;
  356. } else {
  357. sides[i] = SIDE_ON;
  358. }
  359. counts[sides[i]]++;
  360. }
  361. // if coplanar, put on the front side if the normals match
  362. if ( !counts[SIDE_FRONT] && !counts[SIDE_BACK] ) {
  363. f = ( verts[indexes[1]].xyz - verts[indexes[0]].xyz ).Cross( verts[indexes[0]].xyz - verts[indexes[2]].xyz ) * plane.Normal();
  364. if ( IEEE_FLT_SIGNBITSET( f ) ) {
  365. Clear();
  366. return false;
  367. } else {
  368. return true;
  369. }
  370. }
  371. // if nothing at the front of the clipping plane
  372. if ( !counts[SIDE_FRONT] ) {
  373. Clear();
  374. return false;
  375. }
  376. // if nothing at the back of the clipping plane
  377. if ( !counts[SIDE_BACK] ) {
  378. return true;
  379. }
  380. edgeSplitVertex = (int *) _alloca( edges.Num() * sizeof( int ) );
  381. numEdgeSplitVertexes = 0;
  382. counts[SIDE_FRONT] = counts[SIDE_BACK] = 0;
  383. // split edges
  384. for ( i = 0; i < edges.Num(); i++ ) {
  385. int v0 = edges[i].verts[0];
  386. int v1 = edges[i].verts[1];
  387. // if both vertexes are on the same side or one is on the clipping plane
  388. if ( !( sides[v0] ^ sides[v1] ) || ( ( sides[v0] | sides[v1] ) & SIDE_ON ) ) {
  389. edgeSplitVertex[i] = -1;
  390. counts[(sides[v0]|sides[v1]) & SIDE_BACK]++;
  391. } else {
  392. f = dists[v0] / ( dists[v0] - dists[v1] );
  393. v.LerpAll( verts[v0], verts[v1], f );
  394. edgeSplitVertex[i] = numEdgeSplitVertexes++;
  395. newVerts.Append( v );
  396. }
  397. }
  398. // each edge is shared by at most two triangles, as such there can never be
  399. // more indexes than twice the number of edges
  400. newIndexes.Resize( ( counts[SIDE_FRONT] << 1 ) + ( numEdgeSplitVertexes << 2 ) );
  401. // allocate indexes to construct the triangle indexes for the front and back surface
  402. vertexRemap = (int *) _alloca( verts.Num() * sizeof( int ) );
  403. memset( vertexRemap, -1, verts.Num() * sizeof( int ) );
  404. vertexCopyIndex = (int *) _alloca( ( numEdgeSplitVertexes + verts.Num() ) * sizeof( int ) );
  405. vertexIndexNum[0] = 0;
  406. vertexIndexNum[1] = numEdgeSplitVertexes;
  407. indexPtr = newIndexes.Ptr();
  408. indexNum = newIndexes.Num();
  409. // split surface triangles
  410. for ( i = 0; i < edgeIndexes.Num(); i += 3 ) {
  411. int e0, e1, e2, v0, v1, v2;
  412. e0 = abs( edgeIndexes[i+0] );
  413. e1 = abs( edgeIndexes[i+1] );
  414. e2 = abs( edgeIndexes[i+2] );
  415. v0 = indexes[i+0];
  416. v1 = indexes[i+1];
  417. v2 = indexes[i+2];
  418. switch( ( INT32_SIGNBITSET( edgeSplitVertex[e0] ) | ( INT32_SIGNBITSET( edgeSplitVertex[e1] ) << 1 ) | ( INT32_SIGNBITSET( edgeSplitVertex[e2] ) << 2 ) ) ^ 7 ) {
  419. case 0: { // no edges split
  420. if ( ( sides[v0] | sides[v1] | sides[v2] ) & SIDE_BACK ) {
  421. break;
  422. }
  423. if ( ( sides[v0] & sides[v1] & sides[v2] ) & SIDE_ON ) {
  424. // coplanar
  425. if ( !keepOn ) {
  426. break;
  427. }
  428. f = ( verts[v1].xyz - verts[v0].xyz ).Cross( verts[v0].xyz - verts[v2].xyz ) * plane.Normal();
  429. if ( IEEE_FLT_SIGNBITSET( f ) ) {
  430. break;
  431. }
  432. }
  433. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
  434. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
  435. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
  436. break;
  437. }
  438. case 1: { // first edge split
  439. if ( !( sides[v0] & SIDE_BACK ) ) {
  440. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
  441. indexPtr[indexNum++] = edgeSplitVertex[e0];
  442. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
  443. } else {
  444. indexPtr[indexNum++] = edgeSplitVertex[e0];
  445. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
  446. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
  447. }
  448. break;
  449. }
  450. case 2: { // second edge split
  451. if ( !( sides[v1] & SIDE_BACK ) ) {
  452. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
  453. indexPtr[indexNum++] = edgeSplitVertex[e1];
  454. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
  455. } else {
  456. indexPtr[indexNum++] = edgeSplitVertex[e1];
  457. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
  458. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
  459. }
  460. break;
  461. }
  462. case 3: { // first and second edge split
  463. if ( !( sides[v1] & SIDE_BACK ) ) {
  464. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
  465. indexPtr[indexNum++] = edgeSplitVertex[e1];
  466. indexPtr[indexNum++] = edgeSplitVertex[e0];
  467. } else {
  468. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
  469. indexPtr[indexNum++] = edgeSplitVertex[e0];
  470. indexPtr[indexNum++] = edgeSplitVertex[e1];
  471. indexPtr[indexNum++] = edgeSplitVertex[e1];
  472. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
  473. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
  474. }
  475. break;
  476. }
  477. case 4: { // third edge split
  478. if ( !( sides[v2] & SIDE_BACK ) ) {
  479. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
  480. indexPtr[indexNum++] = edgeSplitVertex[e2];
  481. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
  482. } else {
  483. indexPtr[indexNum++] = edgeSplitVertex[e2];
  484. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
  485. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
  486. }
  487. break;
  488. }
  489. case 5: { // first and third edge split
  490. if ( !( sides[v0] & SIDE_BACK ) ) {
  491. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
  492. indexPtr[indexNum++] = edgeSplitVertex[e0];
  493. indexPtr[indexNum++] = edgeSplitVertex[e2];
  494. } else {
  495. indexPtr[indexNum++] = edgeSplitVertex[e0];
  496. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
  497. indexPtr[indexNum++] = edgeSplitVertex[e2];
  498. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
  499. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
  500. indexPtr[indexNum++] = edgeSplitVertex[e2];
  501. }
  502. break;
  503. }
  504. case 6: { // second and third edge split
  505. if ( !( sides[v2] & SIDE_BACK ) ) {
  506. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v2 );
  507. indexPtr[indexNum++] = edgeSplitVertex[e2];
  508. indexPtr[indexNum++] = edgeSplitVertex[e1];
  509. } else {
  510. indexPtr[indexNum++] = edgeSplitVertex[e2];
  511. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
  512. indexPtr[indexNum++] = edgeSplitVertex[e1];
  513. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v0 );
  514. indexPtr[indexNum++] = UpdateVertexIndex( vertexIndexNum, vertexRemap, vertexCopyIndex, v1 );
  515. indexPtr[indexNum++] = edgeSplitVertex[e2];
  516. }
  517. break;
  518. }
  519. }
  520. }
  521. newIndexes.SetNum( indexNum );
  522. // copy vertexes
  523. newVerts.SetNum( vertexIndexNum[1] );
  524. for ( i = numEdgeSplitVertexes; i < newVerts.Num(); i++ ) {
  525. newVerts[i] = verts[vertexCopyIndex[i]];
  526. }
  527. // copy back to this surface
  528. indexes = newIndexes;
  529. verts = newVerts;
  530. GenerateEdgeIndexes();
  531. return true;
  532. }
  533. /*
  534. =============
  535. idSurface::IsConnected
  536. =============
  537. */
  538. bool idSurface::IsConnected() const {
  539. int i, j, numIslands, numTris;
  540. int queueStart, queueEnd;
  541. int *queue, *islandNum;
  542. int curTri, nextTri, edgeNum;
  543. const int *index;
  544. numIslands = 0;
  545. numTris = indexes.Num() / 3;
  546. islandNum = (int *) _alloca16( numTris * sizeof( int ) );
  547. memset( islandNum, -1, numTris * sizeof( int ) );
  548. queue = (int *) _alloca16( numTris * sizeof( int ) );
  549. for ( i = 0; i < numTris; i++ ) {
  550. if ( islandNum[i] != -1 ) {
  551. continue;
  552. }
  553. queueStart = 0;
  554. queueEnd = 1;
  555. queue[0] = i;
  556. islandNum[i] = numIslands;
  557. for ( curTri = queue[queueStart]; queueStart < queueEnd; curTri = queue[++queueStart] ) {
  558. index = &edgeIndexes[curTri * 3];
  559. for ( j = 0; j < 3; j++ ) {
  560. edgeNum = index[j];
  561. nextTri = edges[abs(edgeNum)].tris[INT32_SIGNBITNOTSET(edgeNum)];
  562. if ( nextTri == -1 ) {
  563. continue;
  564. }
  565. nextTri /= 3;
  566. if ( islandNum[nextTri] != -1 ) {
  567. continue;
  568. }
  569. queue[queueEnd++] = nextTri;
  570. islandNum[nextTri] = numIslands;
  571. }
  572. }
  573. numIslands++;
  574. }
  575. return ( numIslands == 1 );
  576. }
  577. /*
  578. =================
  579. idSurface::IsClosed
  580. =================
  581. */
  582. bool idSurface::IsClosed() const {
  583. for ( int i = 0; i < edges.Num(); i++ ) {
  584. if ( edges[i].tris[0] < 0 || edges[i].tris[1] < 0 ) {
  585. return false;
  586. }
  587. }
  588. return true;
  589. }
  590. /*
  591. =============
  592. idSurface::IsPolytope
  593. =============
  594. */
  595. bool idSurface::IsPolytope( const float epsilon ) const {
  596. int i, j;
  597. idPlane plane;
  598. if ( !IsClosed() ) {
  599. return false;
  600. }
  601. for ( i = 0; i < indexes.Num(); i += 3 ) {
  602. plane.FromPoints( verts[indexes[i+0]].xyz, verts[indexes[i+1]].xyz, verts[indexes[i+2]].xyz );
  603. for ( j = 0; j < verts.Num(); j++ ) {
  604. if ( plane.Side( verts[j].xyz, epsilon ) == SIDE_FRONT ) {
  605. return false;
  606. }
  607. }
  608. }
  609. return true;
  610. }
  611. /*
  612. =============
  613. idSurface::PlaneDistance
  614. =============
  615. */
  616. float idSurface::PlaneDistance( const idPlane &plane ) const {
  617. int i;
  618. float d, min, max;
  619. min = idMath::INFINITY;
  620. max = -min;
  621. for ( i = 0; i < verts.Num(); i++ ) {
  622. d = plane.Distance( verts[i].xyz );
  623. if ( d < min ) {
  624. min = d;
  625. if ( IEEE_FLT_SIGNBITSET( min ) & IEEE_FLT_SIGNBITNOTSET( max ) ) {
  626. return 0.0f;
  627. }
  628. }
  629. if ( d > max ) {
  630. max = d;
  631. if ( IEEE_FLT_SIGNBITSET( min ) & IEEE_FLT_SIGNBITNOTSET( max ) ) {
  632. return 0.0f;
  633. }
  634. }
  635. }
  636. if ( IEEE_FLT_SIGNBITNOTSET( min ) ) {
  637. return min;
  638. }
  639. if ( IEEE_FLT_SIGNBITSET( max ) ) {
  640. return max;
  641. }
  642. return 0.0f;
  643. }
  644. /*
  645. =============
  646. idSurface::PlaneSide
  647. =============
  648. */
  649. int idSurface::PlaneSide( const idPlane &plane, const float epsilon ) const {
  650. bool front, back;
  651. int i;
  652. float d;
  653. front = false;
  654. back = false;
  655. for ( i = 0; i < verts.Num(); i++ ) {
  656. d = plane.Distance( verts[i].xyz );
  657. if ( d < -epsilon ) {
  658. if ( front ) {
  659. return SIDE_CROSS;
  660. }
  661. back = true;
  662. continue;
  663. }
  664. else if ( d > epsilon ) {
  665. if ( back ) {
  666. return SIDE_CROSS;
  667. }
  668. front = true;
  669. continue;
  670. }
  671. }
  672. if ( back ) {
  673. return SIDE_BACK;
  674. }
  675. if ( front ) {
  676. return SIDE_FRONT;
  677. }
  678. return SIDE_ON;
  679. }
  680. /*
  681. =================
  682. idSurface::LineIntersection
  683. =================
  684. */
  685. bool idSurface::LineIntersection( const idVec3 &start, const idVec3 &end, bool backFaceCull ) const {
  686. float scale;
  687. RayIntersection( start, end - start, scale, false );
  688. return ( scale >= 0.0f && scale <= 1.0f );
  689. }
  690. /*
  691. =================
  692. idSurface::RayIntersection
  693. =================
  694. */
  695. bool idSurface::RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale, bool backFaceCull ) const {
  696. int i, i0, i1, i2, s0, s1, s2;
  697. float d, s;
  698. byte *sidedness;
  699. idPluecker rayPl, pl;
  700. idPlane plane;
  701. sidedness = (byte *)_alloca( edges.Num() * sizeof(byte) );
  702. scale = idMath::INFINITY;
  703. rayPl.FromRay( start, dir );
  704. // ray sidedness for edges
  705. for ( i = 0; i < edges.Num(); i++ ) {
  706. pl.FromLine( verts[ edges[i].verts[1] ].xyz, verts[ edges[i].verts[0] ].xyz );
  707. d = pl.PermutedInnerProduct( rayPl );
  708. sidedness[ i ] = IEEE_FLT_SIGNBITSET( d );
  709. }
  710. // test triangles
  711. for ( i = 0; i < edgeIndexes.Num(); i += 3 ) {
  712. i0 = edgeIndexes[i+0];
  713. i1 = edgeIndexes[i+1];
  714. i2 = edgeIndexes[i+2];
  715. s0 = sidedness[abs(i0)] ^ INT32_SIGNBITSET( i0 );
  716. s1 = sidedness[abs(i1)] ^ INT32_SIGNBITSET( i1 );
  717. s2 = sidedness[abs(i2)] ^ INT32_SIGNBITSET( i2 );
  718. if ( s0 & s1 & s2 ) {
  719. plane.FromPoints( verts[indexes[i+0]].xyz, verts[indexes[i+1]].xyz, verts[indexes[i+2]].xyz );
  720. plane.RayIntersection( start, dir, s );
  721. if ( idMath::Fabs( s ) < idMath::Fabs( scale ) ) {
  722. scale = s;
  723. }
  724. } else if ( !backFaceCull && !(s0 | s1 | s2) ) {
  725. plane.FromPoints( verts[indexes[i+0]].xyz, verts[indexes[i+1]].xyz, verts[indexes[i+2]].xyz );
  726. plane.RayIntersection( start, dir, s );
  727. if ( idMath::Fabs( s ) < idMath::Fabs( scale ) ) {
  728. scale = s;
  729. }
  730. }
  731. }
  732. if ( idMath::Fabs( scale ) < idMath::INFINITY ) {
  733. return true;
  734. }
  735. return false;
  736. }
  737. /*
  738. =================
  739. idSurface::GenerateEdgeIndexes
  740. Assumes each edge is shared by at most two triangles.
  741. =================
  742. */
  743. void idSurface::GenerateEdgeIndexes() {
  744. int i, j, i0, i1, i2, s, v0, v1, edgeNum;
  745. int *index, *vertexEdges, *edgeChain;
  746. surfaceEdge_t e[3];
  747. vertexEdges = (int *) _alloca16( verts.Num() * sizeof( int ) );
  748. memset( vertexEdges, -1, verts.Num() * sizeof( int ) );
  749. edgeChain = (int *) _alloca16( indexes.Num() * sizeof( int ) );
  750. edgeIndexes.SetNum( indexes.Num() );
  751. edges.Clear();
  752. // the first edge is a dummy
  753. e[0].verts[0] = e[0].verts[1] = e[0].tris[0] = e[0].tris[1] = 0;
  754. edges.Append( e[0] );
  755. for ( i = 0; i < indexes.Num(); i += 3 ) {
  756. index = indexes.Ptr() + i;
  757. // vertex numbers
  758. i0 = index[0];
  759. i1 = index[1];
  760. i2 = index[2];
  761. // setup edges each with smallest vertex number first
  762. s = INT32_SIGNBITSET(i1 - i0);
  763. e[0].verts[0] = index[s];
  764. e[0].verts[1] = index[s^1];
  765. s = INT32_SIGNBITSET(i2 - i1) + 1;
  766. e[1].verts[0] = index[s];
  767. e[1].verts[1] = index[s^3];
  768. s = INT32_SIGNBITSET(i2 - i0) << 1;
  769. e[2].verts[0] = index[s];
  770. e[2].verts[1] = index[s^2];
  771. // get edges
  772. for ( j = 0; j < 3; j++ ) {
  773. v0 = e[j].verts[0];
  774. v1 = e[j].verts[1];
  775. for ( edgeNum = vertexEdges[v0]; edgeNum >= 0; edgeNum = edgeChain[edgeNum] ) {
  776. if ( edges[edgeNum].verts[1] == v1 ) {
  777. break;
  778. }
  779. }
  780. // if the edge does not yet exist
  781. if ( edgeNum < 0 ) {
  782. e[j].tris[0] = e[j].tris[1] = -1;
  783. edgeNum = edges.Append( e[j] );
  784. edgeChain[edgeNum] = vertexEdges[v0];
  785. vertexEdges[v0] = edgeNum;
  786. }
  787. // update edge index and edge tri references
  788. if ( index[j] == v0 ) {
  789. assert( edges[edgeNum].tris[0] == -1 ); // edge may not be shared by more than two triangles
  790. edges[edgeNum].tris[0] = i;
  791. edgeIndexes[i+j] = edgeNum;
  792. } else {
  793. assert( edges[edgeNum].tris[1] == -1 ); // edge may not be shared by more than two triangles
  794. edges[edgeNum].tris[1] = i;
  795. edgeIndexes[i+j] = -edgeNum;
  796. }
  797. }
  798. }
  799. }
  800. /*
  801. =================
  802. idSurface::FindEdge
  803. =================
  804. */
  805. int idSurface::FindEdge( int v1, int v2 ) const {
  806. int i, firstVert, secondVert;
  807. if ( v1 < v2 ) {
  808. firstVert = v1;
  809. secondVert = v2;
  810. } else {
  811. firstVert = v2;
  812. secondVert = v1;
  813. }
  814. for ( i = 1; i < edges.Num(); i++ ) {
  815. if ( edges[i].verts[0] == firstVert ) {
  816. if ( edges[i].verts[1] == secondVert ) {
  817. break;
  818. }
  819. }
  820. }
  821. if ( i < edges.Num() ) {
  822. return v1 < v2 ? i : -i;
  823. }
  824. return 0;
  825. }