TraceModel.cpp 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493
  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 "../../idlib/precompiled.h"
  22. #include "TraceModel.h"
  23. /*
  24. ============
  25. idTraceModel::SetupBox
  26. ============
  27. */
  28. void idTraceModel::SetupBox( const idBounds &boxBounds ) {
  29. int i;
  30. if ( type != TRM_BOX ) {
  31. InitBox();
  32. }
  33. // offset to center
  34. offset = ( boxBounds[0] + boxBounds[1] ) * 0.5f;
  35. // set box vertices
  36. for ( i = 0; i < 8; i++ ) {
  37. verts[i][0] = boxBounds[(i^(i>>1))&1][0];
  38. verts[i][1] = boxBounds[(i>>1)&1][1];
  39. verts[i][2] = boxBounds[(i>>2)&1][2];
  40. }
  41. // set polygon plane distances
  42. polys[0].dist = -boxBounds[0][2];
  43. polys[1].dist = boxBounds[1][2];
  44. polys[2].dist = -boxBounds[0][1];
  45. polys[3].dist = boxBounds[1][0];
  46. polys[4].dist = boxBounds[1][1];
  47. polys[5].dist = -boxBounds[0][0];
  48. // set polygon bounds
  49. for ( i = 0; i < 6; i++ ) {
  50. polys[i].bounds = boxBounds;
  51. }
  52. polys[0].bounds[1][2] = boxBounds[0][2];
  53. polys[1].bounds[0][2] = boxBounds[1][2];
  54. polys[2].bounds[1][1] = boxBounds[0][1];
  55. polys[3].bounds[0][0] = boxBounds[1][0];
  56. polys[4].bounds[0][1] = boxBounds[1][1];
  57. polys[5].bounds[1][0] = boxBounds[0][0];
  58. bounds = boxBounds;
  59. }
  60. /*
  61. ============
  62. idTraceModel::SetupBox
  63. The origin is placed at the center of the cube.
  64. ============
  65. */
  66. void idTraceModel::SetupBox( const float size ) {
  67. idBounds boxBounds;
  68. float halfSize;
  69. halfSize = size * 0.5f;
  70. boxBounds[0].Set( -halfSize, -halfSize, -halfSize );
  71. boxBounds[1].Set( halfSize, halfSize, halfSize );
  72. SetupBox( boxBounds );
  73. }
  74. /*
  75. ============
  76. idTraceModel::InitBox
  77. Initialize size independent box.
  78. ============
  79. */
  80. void idTraceModel::InitBox() {
  81. int i;
  82. type = TRM_BOX;
  83. numVerts = 8;
  84. numEdges = 12;
  85. numPolys = 6;
  86. // set box edges
  87. for ( i = 0; i < 4; i++ ) {
  88. edges[ i + 1 ].v[0] = i;
  89. edges[ i + 1 ].v[1] = (i + 1) & 3;
  90. edges[ i + 5 ].v[0] = 4 + i;
  91. edges[ i + 5 ].v[1] = 4 + ((i + 1) & 3);
  92. edges[ i + 9 ].v[0] = i;
  93. edges[ i + 9 ].v[1] = 4 + i;
  94. }
  95. // all edges of a polygon go counter clockwise
  96. polys[0].numEdges = 4;
  97. polys[0].edges[0] = -4;
  98. polys[0].edges[1] = -3;
  99. polys[0].edges[2] = -2;
  100. polys[0].edges[3] = -1;
  101. polys[0].normal.Set( 0.0f, 0.0f, -1.0f );
  102. polys[1].numEdges = 4;
  103. polys[1].edges[0] = 5;
  104. polys[1].edges[1] = 6;
  105. polys[1].edges[2] = 7;
  106. polys[1].edges[3] = 8;
  107. polys[1].normal.Set( 0.0f, 0.0f, 1.0f );
  108. polys[2].numEdges = 4;
  109. polys[2].edges[0] = 1;
  110. polys[2].edges[1] = 10;
  111. polys[2].edges[2] = -5;
  112. polys[2].edges[3] = -9;
  113. polys[2].normal.Set( 0.0f, -1.0f, 0.0f );
  114. polys[3].numEdges = 4;
  115. polys[3].edges[0] = 2;
  116. polys[3].edges[1] = 11;
  117. polys[3].edges[2] = -6;
  118. polys[3].edges[3] = -10;
  119. polys[3].normal.Set( 1.0f, 0.0f, 0.0f );
  120. polys[4].numEdges = 4;
  121. polys[4].edges[0] = 3;
  122. polys[4].edges[1] = 12;
  123. polys[4].edges[2] = -7;
  124. polys[4].edges[3] = -11;
  125. polys[4].normal.Set( 0.0f, 1.0f, 0.0f );
  126. polys[5].numEdges = 4;
  127. polys[5].edges[0] = 4;
  128. polys[5].edges[1] = 9;
  129. polys[5].edges[2] = -8;
  130. polys[5].edges[3] = -12;
  131. polys[5].normal.Set( -1.0f, 0.0f, 0.0f );
  132. // convex model
  133. isConvex = true;
  134. GenerateEdgeNormals();
  135. }
  136. /*
  137. ============
  138. idTraceModel::SetupOctahedron
  139. ============
  140. */
  141. void idTraceModel::SetupOctahedron( const idBounds &octBounds ) {
  142. int i, e0, e1, v0, v1, v2;
  143. idVec3 v;
  144. if ( type != TRM_OCTAHEDRON ) {
  145. InitOctahedron();
  146. }
  147. offset = ( octBounds[0] + octBounds[1] ) * 0.5f;
  148. v[0] = octBounds[1][0] - offset[0];
  149. v[1] = octBounds[1][1] - offset[1];
  150. v[2] = octBounds[1][2] - offset[2];
  151. // set vertices
  152. verts[0].Set( offset.x + v[0], offset.y, offset.z );
  153. verts[1].Set( offset.x - v[0], offset.y, offset.z );
  154. verts[2].Set( offset.x, offset.y + v[1], offset.z );
  155. verts[3].Set( offset.x, offset.y - v[1], offset.z );
  156. verts[4].Set( offset.x, offset.y, offset.z + v[2] );
  157. verts[5].Set( offset.x, offset.y, offset.z - v[2] );
  158. // set polygons
  159. for ( i = 0; i < numPolys; i++ ) {
  160. e0 = polys[i].edges[0];
  161. e1 = polys[i].edges[1];
  162. v0 = edges[abs(e0)].v[INT32_SIGNBITSET(e0)];
  163. v1 = edges[abs(e0)].v[INT32_SIGNBITNOTSET(e0)];
  164. v2 = edges[abs(e1)].v[INT32_SIGNBITNOTSET(e1)];
  165. // polygon plane
  166. polys[i].normal = ( verts[v1] - verts[v0] ).Cross( verts[v2] - verts[v0] );
  167. polys[i].normal.Normalize();
  168. polys[i].dist = polys[i].normal * verts[v0];
  169. // polygon bounds
  170. polys[i].bounds[0] = polys[i].bounds[1] = verts[v0];
  171. polys[i].bounds.AddPoint( verts[v1] );
  172. polys[i].bounds.AddPoint( verts[v2] );
  173. }
  174. // trm bounds
  175. bounds = octBounds;
  176. GenerateEdgeNormals();
  177. }
  178. /*
  179. ============
  180. idTraceModel::SetupOctahedron
  181. The origin is placed at the center of the octahedron.
  182. ============
  183. */
  184. void idTraceModel::SetupOctahedron( const float size ) {
  185. idBounds octBounds;
  186. float halfSize;
  187. halfSize = size * 0.5f;
  188. octBounds[0].Set( -halfSize, -halfSize, -halfSize );
  189. octBounds[1].Set( halfSize, halfSize, halfSize );
  190. SetupOctahedron( octBounds );
  191. }
  192. /*
  193. ============
  194. idTraceModel::InitOctahedron
  195. Initialize size independent octahedron.
  196. ============
  197. */
  198. void idTraceModel::InitOctahedron() {
  199. type = TRM_OCTAHEDRON;
  200. numVerts = 6;
  201. numEdges = 12;
  202. numPolys = 8;
  203. // set edges
  204. edges[ 1].v[0] = 4; edges[ 1].v[1] = 0;
  205. edges[ 2].v[0] = 0; edges[ 2].v[1] = 2;
  206. edges[ 3].v[0] = 2; edges[ 3].v[1] = 4;
  207. edges[ 4].v[0] = 2; edges[ 4].v[1] = 1;
  208. edges[ 5].v[0] = 1; edges[ 5].v[1] = 4;
  209. edges[ 6].v[0] = 1; edges[ 6].v[1] = 3;
  210. edges[ 7].v[0] = 3; edges[ 7].v[1] = 4;
  211. edges[ 8].v[0] = 3; edges[ 8].v[1] = 0;
  212. edges[ 9].v[0] = 5; edges[ 9].v[1] = 2;
  213. edges[10].v[0] = 0; edges[10].v[1] = 5;
  214. edges[11].v[0] = 5; edges[11].v[1] = 1;
  215. edges[12].v[0] = 5; edges[12].v[1] = 3;
  216. // all edges of a polygon go counter clockwise
  217. polys[0].numEdges = 3;
  218. polys[0].edges[0] = 1;
  219. polys[0].edges[1] = 2;
  220. polys[0].edges[2] = 3;
  221. polys[1].numEdges = 3;
  222. polys[1].edges[0] = -3;
  223. polys[1].edges[1] = 4;
  224. polys[1].edges[2] = 5;
  225. polys[2].numEdges = 3;
  226. polys[2].edges[0] = -5;
  227. polys[2].edges[1] = 6;
  228. polys[2].edges[2] = 7;
  229. polys[3].numEdges = 3;
  230. polys[3].edges[0] = -7;
  231. polys[3].edges[1] = 8;
  232. polys[3].edges[2] = -1;
  233. polys[4].numEdges = 3;
  234. polys[4].edges[0] = 9;
  235. polys[4].edges[1] = -2;
  236. polys[4].edges[2] = 10;
  237. polys[5].numEdges = 3;
  238. polys[5].edges[0] = 11;
  239. polys[5].edges[1] = -4;
  240. polys[5].edges[2] = -9;
  241. polys[6].numEdges = 3;
  242. polys[6].edges[0] = 12;
  243. polys[6].edges[1] = -6;
  244. polys[6].edges[2] = -11;
  245. polys[7].numEdges = 3;
  246. polys[7].edges[0] = -10;
  247. polys[7].edges[1] = -8;
  248. polys[7].edges[2] = -12;
  249. // convex model
  250. isConvex = true;
  251. }
  252. /*
  253. ============
  254. idTraceModel::SetupDodecahedron
  255. ============
  256. */
  257. void idTraceModel::SetupDodecahedron( const idBounds &dodBounds ) {
  258. int i, e0, e1, e2, e3, v0, v1, v2, v3, v4;
  259. float s, d;
  260. idVec3 a, b, c;
  261. if ( type != TRM_DODECAHEDRON ) {
  262. InitDodecahedron();
  263. }
  264. a[0] = a[1] = a[2] = 0.5773502691896257f; // 1.0f / ( 3.0f ) ^ 0.5f;
  265. b[0] = b[1] = b[2] = 0.3568220897730899f; // ( ( 3.0f - ( 5.0f ) ^ 0.5f ) / 6.0f ) ^ 0.5f;
  266. c[0] = c[1] = c[2] = 0.9341723589627156f; // ( ( 3.0f + ( 5.0f ) ^ 0.5f ) / 6.0f ) ^ 0.5f;
  267. d = 0.5f / c[0];
  268. s = ( dodBounds[1][0] - dodBounds[0][0] ) * d;
  269. a[0] *= s;
  270. b[0] *= s;
  271. c[0] *= s;
  272. s = ( dodBounds[1][1] - dodBounds[0][1] ) * d;
  273. a[1] *= s;
  274. b[1] *= s;
  275. c[1] *= s;
  276. s = ( dodBounds[1][2] - dodBounds[0][2] ) * d;
  277. a[2] *= s;
  278. b[2] *= s;
  279. c[2] *= s;
  280. offset = ( dodBounds[0] + dodBounds[1] ) * 0.5f;
  281. // set vertices
  282. verts[ 0].Set( offset.x + a[0], offset.y + a[1], offset.z + a[2] );
  283. verts[ 1].Set( offset.x + a[0], offset.y + a[1], offset.z - a[2] );
  284. verts[ 2].Set( offset.x + a[0], offset.y - a[1], offset.z + a[2] );
  285. verts[ 3].Set( offset.x + a[0], offset.y - a[1], offset.z - a[2] );
  286. verts[ 4].Set( offset.x - a[0], offset.y + a[1], offset.z + a[2] );
  287. verts[ 5].Set( offset.x - a[0], offset.y + a[1], offset.z - a[2] );
  288. verts[ 6].Set( offset.x - a[0], offset.y - a[1], offset.z + a[2] );
  289. verts[ 7].Set( offset.x - a[0], offset.y - a[1], offset.z - a[2] );
  290. verts[ 8].Set( offset.x + b[0], offset.y + c[1], offset.z );
  291. verts[ 9].Set( offset.x - b[0], offset.y + c[1], offset.z );
  292. verts[10].Set( offset.x + b[0], offset.y - c[1], offset.z );
  293. verts[11].Set( offset.x - b[0], offset.y - c[1], offset.z );
  294. verts[12].Set( offset.x + c[0], offset.y , offset.z + b[2] );
  295. verts[13].Set( offset.x + c[0], offset.y , offset.z - b[2] );
  296. verts[14].Set( offset.x - c[0], offset.y , offset.z + b[2] );
  297. verts[15].Set( offset.x - c[0], offset.y , offset.z - b[2] );
  298. verts[16].Set( offset.x , offset.y + b[1], offset.z + c[2] );
  299. verts[17].Set( offset.x , offset.y - b[1], offset.z + c[2] );
  300. verts[18].Set( offset.x , offset.y + b[1], offset.z - c[2] );
  301. verts[19].Set( offset.x , offset.y - b[1], offset.z - c[2] );
  302. // set polygons
  303. for ( i = 0; i < numPolys; i++ ) {
  304. e0 = polys[i].edges[0];
  305. e1 = polys[i].edges[1];
  306. e2 = polys[i].edges[2];
  307. e3 = polys[i].edges[3];
  308. v0 = edges[abs(e0)].v[INT32_SIGNBITSET(e0)];
  309. v1 = edges[abs(e0)].v[INT32_SIGNBITNOTSET(e0)];
  310. v2 = edges[abs(e1)].v[INT32_SIGNBITNOTSET(e1)];
  311. v3 = edges[abs(e2)].v[INT32_SIGNBITNOTSET(e2)];
  312. v4 = edges[abs(e3)].v[INT32_SIGNBITNOTSET(e3)];
  313. // polygon plane
  314. polys[i].normal = ( verts[v1] - verts[v0] ).Cross( verts[v2] - verts[v0] );
  315. polys[i].normal.Normalize();
  316. polys[i].dist = polys[i].normal * verts[v0];
  317. // polygon bounds
  318. polys[i].bounds[0] = polys[i].bounds[1] = verts[v0];
  319. polys[i].bounds.AddPoint( verts[v1] );
  320. polys[i].bounds.AddPoint( verts[v2] );
  321. polys[i].bounds.AddPoint( verts[v3] );
  322. polys[i].bounds.AddPoint( verts[v4] );
  323. }
  324. // trm bounds
  325. bounds = dodBounds;
  326. GenerateEdgeNormals();
  327. }
  328. /*
  329. ============
  330. idTraceModel::SetupDodecahedron
  331. The origin is placed at the center of the octahedron.
  332. ============
  333. */
  334. void idTraceModel::SetupDodecahedron( const float size ) {
  335. idBounds dodBounds;
  336. float halfSize;
  337. halfSize = size * 0.5f;
  338. dodBounds[0].Set( -halfSize, -halfSize, -halfSize );
  339. dodBounds[1].Set( halfSize, halfSize, halfSize );
  340. SetupDodecahedron( dodBounds );
  341. }
  342. /*
  343. ============
  344. idTraceModel::InitDodecahedron
  345. Initialize size independent dodecahedron.
  346. ============
  347. */
  348. void idTraceModel::InitDodecahedron() {
  349. type = TRM_DODECAHEDRON;
  350. numVerts = 20;
  351. numEdges = 30;
  352. numPolys = 12;
  353. // set edges
  354. edges[ 1].v[0] = 0; edges[ 1].v[1] = 8;
  355. edges[ 2].v[0] = 8; edges[ 2].v[1] = 9;
  356. edges[ 3].v[0] = 9; edges[ 3].v[1] = 4;
  357. edges[ 4].v[0] = 4; edges[ 4].v[1] = 16;
  358. edges[ 5].v[0] = 16; edges[ 5].v[1] = 0;
  359. edges[ 6].v[0] = 16; edges[ 6].v[1] = 17;
  360. edges[ 7].v[0] = 17; edges[ 7].v[1] = 2;
  361. edges[ 8].v[0] = 2; edges[ 8].v[1] = 12;
  362. edges[ 9].v[0] = 12; edges[ 9].v[1] = 0;
  363. edges[10].v[0] = 2; edges[10].v[1] = 10;
  364. edges[11].v[0] = 10; edges[11].v[1] = 3;
  365. edges[12].v[0] = 3; edges[12].v[1] = 13;
  366. edges[13].v[0] = 13; edges[13].v[1] = 12;
  367. edges[14].v[0] = 9; edges[14].v[1] = 5;
  368. edges[15].v[0] = 5; edges[15].v[1] = 15;
  369. edges[16].v[0] = 15; edges[16].v[1] = 14;
  370. edges[17].v[0] = 14; edges[17].v[1] = 4;
  371. edges[18].v[0] = 3; edges[18].v[1] = 19;
  372. edges[19].v[0] = 19; edges[19].v[1] = 18;
  373. edges[20].v[0] = 18; edges[20].v[1] = 1;
  374. edges[21].v[0] = 1; edges[21].v[1] = 13;
  375. edges[22].v[0] = 7; edges[22].v[1] = 11;
  376. edges[23].v[0] = 11; edges[23].v[1] = 6;
  377. edges[24].v[0] = 6; edges[24].v[1] = 14;
  378. edges[25].v[0] = 15; edges[25].v[1] = 7;
  379. edges[26].v[0] = 1; edges[26].v[1] = 8;
  380. edges[27].v[0] = 18; edges[27].v[1] = 5;
  381. edges[28].v[0] = 6; edges[28].v[1] = 17;
  382. edges[29].v[0] = 11; edges[29].v[1] = 10;
  383. edges[30].v[0] = 19; edges[30].v[1] = 7;
  384. // all edges of a polygon go counter clockwise
  385. polys[0].numEdges = 5;
  386. polys[0].edges[0] = 1;
  387. polys[0].edges[1] = 2;
  388. polys[0].edges[2] = 3;
  389. polys[0].edges[3] = 4;
  390. polys[0].edges[4] = 5;
  391. polys[1].numEdges = 5;
  392. polys[1].edges[0] = -5;
  393. polys[1].edges[1] = 6;
  394. polys[1].edges[2] = 7;
  395. polys[1].edges[3] = 8;
  396. polys[1].edges[4] = 9;
  397. polys[2].numEdges = 5;
  398. polys[2].edges[0] = -8;
  399. polys[2].edges[1] = 10;
  400. polys[2].edges[2] = 11;
  401. polys[2].edges[3] = 12;
  402. polys[2].edges[4] = 13;
  403. polys[3].numEdges = 5;
  404. polys[3].edges[0] = 14;
  405. polys[3].edges[1] = 15;
  406. polys[3].edges[2] = 16;
  407. polys[3].edges[3] = 17;
  408. polys[3].edges[4] = -3;
  409. polys[4].numEdges = 5;
  410. polys[4].edges[0] = 18;
  411. polys[4].edges[1] = 19;
  412. polys[4].edges[2] = 20;
  413. polys[4].edges[3] = 21;
  414. polys[4].edges[4] = -12;
  415. polys[5].numEdges = 5;
  416. polys[5].edges[0] = 22;
  417. polys[5].edges[1] = 23;
  418. polys[5].edges[2] = 24;
  419. polys[5].edges[3] = -16;
  420. polys[5].edges[4] = 25;
  421. polys[6].numEdges = 5;
  422. polys[6].edges[0] = -9;
  423. polys[6].edges[1] = -13;
  424. polys[6].edges[2] = -21;
  425. polys[6].edges[3] = 26;
  426. polys[6].edges[4] = -1;
  427. polys[7].numEdges = 5;
  428. polys[7].edges[0] = -26;
  429. polys[7].edges[1] = -20;
  430. polys[7].edges[2] = 27;
  431. polys[7].edges[3] = -14;
  432. polys[7].edges[4] = -2;
  433. polys[8].numEdges = 5;
  434. polys[8].edges[0] = -4;
  435. polys[8].edges[1] = -17;
  436. polys[8].edges[2] = -24;
  437. polys[8].edges[3] = 28;
  438. polys[8].edges[4] = -6;
  439. polys[9].numEdges = 5;
  440. polys[9].edges[0] = -23;
  441. polys[9].edges[1] = 29;
  442. polys[9].edges[2] = -10;
  443. polys[9].edges[3] = -7;
  444. polys[9].edges[4] = -28;
  445. polys[10].numEdges = 5;
  446. polys[10].edges[0] = -25;
  447. polys[10].edges[1] = -15;
  448. polys[10].edges[2] = -27;
  449. polys[10].edges[3] = -19;
  450. polys[10].edges[4] = 30;
  451. polys[11].numEdges = 5;
  452. polys[11].edges[0] = -30;
  453. polys[11].edges[1] = -18;
  454. polys[11].edges[2] = -11;
  455. polys[11].edges[3] = -29;
  456. polys[11].edges[4] = -22;
  457. // convex model
  458. isConvex = true;
  459. }
  460. /*
  461. ============
  462. idTraceModel::SetupCylinder
  463. ============
  464. */
  465. void idTraceModel::SetupCylinder( const idBounds &cylBounds, const int numSides ) {
  466. int i, n, ii, n2;
  467. float angle;
  468. idVec3 halfSize;
  469. n = numSides;
  470. if ( n < 3 ) {
  471. n = 3;
  472. }
  473. if ( n * 2 > MAX_TRACEMODEL_VERTS ) {
  474. idLib::common->Printf( "WARNING: idTraceModel::SetupCylinder: too many vertices\n" );
  475. n = MAX_TRACEMODEL_VERTS / 2;
  476. }
  477. if ( n * 3 > MAX_TRACEMODEL_EDGES ) {
  478. idLib::common->Printf( "WARNING: idTraceModel::SetupCylinder: too many sides\n" );
  479. n = MAX_TRACEMODEL_EDGES / 3;
  480. }
  481. if ( n + 2 > MAX_TRACEMODEL_POLYS ) {
  482. idLib::common->Printf( "WARNING: idTraceModel::SetupCylinder: too many polygons\n" );
  483. n = MAX_TRACEMODEL_POLYS - 2;
  484. }
  485. type = TRM_CYLINDER;
  486. numVerts = n * 2;
  487. numEdges = n * 3;
  488. numPolys = n + 2;
  489. offset = ( cylBounds[0] + cylBounds[1] ) * 0.5f;
  490. halfSize = cylBounds[1] - offset;
  491. for ( i = 0; i < n; i++ ) {
  492. // verts
  493. angle = idMath::TWO_PI * i / n;
  494. verts[i].x = cos( angle ) * halfSize.x + offset.x;
  495. verts[i].y = sin( angle ) * halfSize.y + offset.y;
  496. verts[i].z = -halfSize.z + offset.z;
  497. verts[n+i].x = verts[i].x;
  498. verts[n+i].y = verts[i].y;
  499. verts[n+i].z = halfSize.z + offset.z;
  500. // edges
  501. ii = i + 1;
  502. n2 = n << 1;
  503. edges[ii].v[0] = i;
  504. edges[ii].v[1] = ii % n;
  505. edges[n+ii].v[0] = edges[ii].v[0] + n;
  506. edges[n+ii].v[1] = edges[ii].v[1] + n;
  507. edges[n2+ii].v[0] = i;
  508. edges[n2+ii].v[1] = n + i;
  509. // vertical polygon edges
  510. polys[i].numEdges = 4;
  511. polys[i].edges[0] = ii;
  512. polys[i].edges[1] = n2 + (ii % n) + 1;
  513. polys[i].edges[2] = -(n + ii);
  514. polys[i].edges[3] = -(n2 + ii);
  515. // bottom and top polygon edges
  516. polys[n].edges[i] = -(n - i);
  517. polys[n+1].edges[i] = n + ii;
  518. }
  519. // bottom and top polygon numEdges
  520. polys[n].numEdges = n;
  521. polys[n+1].numEdges = n;
  522. // polygons
  523. for ( i = 0; i < n; i++ ) {
  524. // vertical polygon plane
  525. polys[i].normal = (verts[(i+1)%n] - verts[i]).Cross( verts[n+i] - verts[i] );
  526. polys[i].normal.Normalize();
  527. polys[i].dist = polys[i].normal * verts[i];
  528. // vertical polygon bounds
  529. polys[i].bounds.Clear();
  530. polys[i].bounds.AddPoint( verts[i] );
  531. polys[i].bounds.AddPoint( verts[(i+1)%n] );
  532. polys[i].bounds[0][2] = -halfSize.z + offset.z;
  533. polys[i].bounds[1][2] = halfSize.z + offset.z;
  534. }
  535. // bottom and top polygon plane
  536. polys[n].normal.Set( 0.0f, 0.0f, -1.0f );
  537. polys[n].dist = -cylBounds[0][2];
  538. polys[n+1].normal.Set( 0.0f, 0.0f, 1.0f );
  539. polys[n+1].dist = cylBounds[1][2];
  540. // trm bounds
  541. bounds = cylBounds;
  542. // bottom and top polygon bounds
  543. polys[n].bounds = bounds;
  544. polys[n].bounds[1][2] = bounds[0][2];
  545. polys[n+1].bounds = bounds;
  546. polys[n+1].bounds[0][2] = bounds[1][2];
  547. // convex model
  548. isConvex = true;
  549. GenerateEdgeNormals();
  550. }
  551. /*
  552. ============
  553. idTraceModel::SetupCylinder
  554. The origin is placed at the center of the cylinder.
  555. ============
  556. */
  557. void idTraceModel::SetupCylinder( const float height, const float width, const int numSides ) {
  558. idBounds cylBounds;
  559. float halfHeight, halfWidth;
  560. halfHeight = height * 0.5f;
  561. halfWidth = width * 0.5f;
  562. cylBounds[0].Set( -halfWidth, -halfWidth, -halfHeight );
  563. cylBounds[1].Set( halfWidth, halfWidth, halfHeight );
  564. SetupCylinder( cylBounds, numSides );
  565. }
  566. /*
  567. ============
  568. idTraceModel::SetupCone
  569. ============
  570. */
  571. void idTraceModel::SetupCone( const idBounds &coneBounds, const int numSides ) {
  572. int i, n, ii;
  573. float angle;
  574. idVec3 halfSize;
  575. n = numSides;
  576. if ( n < 2 ) {
  577. n = 3;
  578. }
  579. if ( n + 1 > MAX_TRACEMODEL_VERTS ) {
  580. idLib::common->Printf( "WARNING: idTraceModel::SetupCone: too many vertices\n" );
  581. n = MAX_TRACEMODEL_VERTS - 1;
  582. }
  583. if ( n * 2 > MAX_TRACEMODEL_EDGES ) {
  584. idLib::common->Printf( "WARNING: idTraceModel::SetupCone: too many edges\n" );
  585. n = MAX_TRACEMODEL_EDGES / 2;
  586. }
  587. if ( n + 1 > MAX_TRACEMODEL_POLYS ) {
  588. idLib::common->Printf( "WARNING: idTraceModel::SetupCone: too many polygons\n" );
  589. n = MAX_TRACEMODEL_POLYS - 1;
  590. }
  591. type = TRM_CONE;
  592. numVerts = n + 1;
  593. numEdges = n * 2;
  594. numPolys = n + 1;
  595. offset = ( coneBounds[0] + coneBounds[1] ) * 0.5f;
  596. halfSize = coneBounds[1] - offset;
  597. verts[n].Set( 0.0f, 0.0f, halfSize.z + offset.z );
  598. for ( i = 0; i < n; i++ ) {
  599. // verts
  600. angle = idMath::TWO_PI * i / n;
  601. verts[i].x = cos( angle ) * halfSize.x + offset.x;
  602. verts[i].y = sin( angle ) * halfSize.y + offset.y;
  603. verts[i].z = -halfSize.z + offset.z;
  604. // edges
  605. ii = i + 1;
  606. edges[ii].v[0] = i;
  607. edges[ii].v[1] = ii % n;
  608. edges[n+ii].v[0] = i;
  609. edges[n+ii].v[1] = n;
  610. // vertical polygon edges
  611. polys[i].numEdges = 3;
  612. polys[i].edges[0] = ii;
  613. polys[i].edges[1] = n + (ii % n) + 1;
  614. polys[i].edges[2] = -(n + ii);
  615. // bottom polygon edges
  616. polys[n].edges[i] = -(n - i);
  617. }
  618. // bottom polygon numEdges
  619. polys[n].numEdges = n;
  620. // polygons
  621. for ( i = 0; i < n; i++ ) {
  622. // polygon plane
  623. polys[i].normal = (verts[(i+1)%n] - verts[i]).Cross( verts[n] - verts[i] );
  624. polys[i].normal.Normalize();
  625. polys[i].dist = polys[i].normal * verts[i];
  626. // polygon bounds
  627. polys[i].bounds.Clear();
  628. polys[i].bounds.AddPoint( verts[i] );
  629. polys[i].bounds.AddPoint( verts[(i+1)%n] );
  630. polys[i].bounds.AddPoint( verts[n] );
  631. }
  632. // bottom polygon plane
  633. polys[n].normal.Set( 0.0f, 0.0f, -1.0f );
  634. polys[n].dist = -coneBounds[0][2];
  635. // trm bounds
  636. bounds = coneBounds;
  637. // bottom polygon bounds
  638. polys[n].bounds = bounds;
  639. polys[n].bounds[1][2] = bounds[0][2];
  640. // convex model
  641. isConvex = true;
  642. GenerateEdgeNormals();
  643. }
  644. /*
  645. ============
  646. idTraceModel::SetupCone
  647. The origin is placed at the apex of the cone.
  648. ============
  649. */
  650. void idTraceModel::SetupCone( const float height, const float width, const int numSides ) {
  651. idBounds coneBounds;
  652. float halfWidth;
  653. halfWidth = width * 0.5f;
  654. coneBounds[0].Set( -halfWidth, -halfWidth, -height );
  655. coneBounds[1].Set( halfWidth, halfWidth, 0.0f );
  656. SetupCone( coneBounds, numSides );
  657. }
  658. /*
  659. ============
  660. idTraceModel::SetupBone
  661. The origin is placed at the center of the bone.
  662. ============
  663. */
  664. void idTraceModel::SetupBone( const float length, const float width ) {
  665. int i, j, edgeNum;
  666. float halfLength = length * 0.5f;
  667. if ( type != TRM_BONE ) {
  668. InitBone();
  669. }
  670. // offset to center
  671. offset.Set( 0.0f, 0.0f, 0.0f );
  672. // set vertices
  673. verts[0].Set( 0.0f, 0.0f, -halfLength );
  674. verts[1].Set( 0.0f, width * -0.5f, 0.0f );
  675. verts[2].Set( width * 0.5f, width * 0.25f, 0.0f );
  676. verts[3].Set( width * -0.5f, width * 0.25f, 0.0f );
  677. verts[4].Set( 0.0f, 0.0f, halfLength );
  678. // set bounds
  679. bounds[0].Set( width * -0.5f, width * -0.5f, -halfLength );
  680. bounds[1].Set( width * 0.5f, width * 0.25f, halfLength );
  681. // poly plane normals
  682. polys[0].normal = ( verts[2] - verts[0] ).Cross( verts[1] - verts[0] );
  683. polys[0].normal.Normalize();
  684. polys[2].normal.Set( -polys[0].normal[0], polys[0].normal[1], polys[0].normal[2] );
  685. polys[3].normal.Set( polys[0].normal[0], polys[0].normal[1], -polys[0].normal[2] );
  686. polys[5].normal.Set( -polys[0].normal[0], polys[0].normal[1], -polys[0].normal[2] );
  687. polys[1].normal = (verts[3] - verts[0]).Cross(verts[2] - verts[0]);
  688. polys[1].normal.Normalize();
  689. polys[4].normal.Set( polys[1].normal[0], polys[1].normal[1], -polys[1].normal[2] );
  690. // poly plane distances
  691. for ( i = 0; i < 6; i++ ) {
  692. polys[i].dist = polys[i].normal * verts[ edges[ abs(polys[i].edges[0]) ].v[0] ];
  693. polys[i].bounds.Clear();
  694. for ( j = 0; j < 3; j++ ) {
  695. edgeNum = polys[i].edges[ j ];
  696. polys[i].bounds.AddPoint( verts[ edges[abs(edgeNum)].v[edgeNum < 0] ] );
  697. }
  698. }
  699. GenerateEdgeNormals();
  700. }
  701. /*
  702. ============
  703. idTraceModel::InitBone
  704. Initialize size independent bone.
  705. ============
  706. */
  707. void idTraceModel::InitBone() {
  708. int i;
  709. type = TRM_BONE;
  710. numVerts = 5;
  711. numEdges = 9;
  712. numPolys = 6;
  713. // set bone edges
  714. for ( i = 0; i < 3; i++ ) {
  715. edges[ i + 1 ].v[0] = 0;
  716. edges[ i + 1 ].v[1] = i + 1;
  717. edges[ i + 4 ].v[0] = 1 + i;
  718. edges[ i + 4 ].v[1] = 1 + ((i + 1) % 3);
  719. edges[ i + 7 ].v[0] = i + 1;
  720. edges[ i + 7 ].v[1] = 4;
  721. }
  722. // all edges of a polygon go counter clockwise
  723. polys[0].numEdges = 3;
  724. polys[0].edges[0] = 2;
  725. polys[0].edges[1] = -4;
  726. polys[0].edges[2] = -1;
  727. polys[1].numEdges = 3;
  728. polys[1].edges[0] = 3;
  729. polys[1].edges[1] = -5;
  730. polys[1].edges[2] = -2;
  731. polys[2].numEdges = 3;
  732. polys[2].edges[0] = 1;
  733. polys[2].edges[1] = -6;
  734. polys[2].edges[2] = -3;
  735. polys[3].numEdges = 3;
  736. polys[3].edges[0] = 4;
  737. polys[3].edges[1] = 8;
  738. polys[3].edges[2] = -7;
  739. polys[4].numEdges = 3;
  740. polys[4].edges[0] = 5;
  741. polys[4].edges[1] = 9;
  742. polys[4].edges[2] = -8;
  743. polys[5].numEdges = 3;
  744. polys[5].edges[0] = 6;
  745. polys[5].edges[1] = 7;
  746. polys[5].edges[2] = -9;
  747. // convex model
  748. isConvex = true;
  749. }
  750. /*
  751. ============
  752. idTraceModel::SetupPolygon
  753. ============
  754. */
  755. void idTraceModel::SetupPolygon( const idVec3 *v, const int count ) {
  756. int i, j;
  757. idVec3 mid;
  758. type = TRM_POLYGON;
  759. numVerts = count;
  760. // times three because we need to be able to turn the polygon into a volume
  761. if ( numVerts * 3 > MAX_TRACEMODEL_EDGES ) {
  762. idLib::common->Printf( "WARNING: idTraceModel::SetupPolygon: too many vertices\n" );
  763. numVerts = MAX_TRACEMODEL_EDGES / 3;
  764. }
  765. numEdges = numVerts;
  766. numPolys = 2;
  767. // set polygon planes
  768. polys[0].numEdges = numEdges;
  769. polys[0].normal = ( v[1] - v[0] ).Cross( v[2] - v[0] );
  770. polys[0].normal.Normalize();
  771. polys[0].dist = polys[0].normal * v[0];
  772. polys[1].numEdges = numEdges;
  773. polys[1].normal = -polys[0].normal;
  774. polys[1].dist = -polys[0].dist;
  775. // setup verts, edges and polygons
  776. polys[0].bounds.Clear();
  777. mid = vec3_origin;
  778. for ( i = 0, j = 1; i < numVerts; i++, j++ ) {
  779. if ( j >= numVerts ) {
  780. j = 0;
  781. }
  782. verts[i] = v[i];
  783. edges[i+1].v[0] = i;
  784. edges[i+1].v[1] = j;
  785. edges[i+1].normal = polys[0].normal.Cross( v[i] - v[j] );
  786. edges[i+1].normal.Normalize();
  787. polys[0].edges[i] = i + 1;
  788. polys[1].edges[i] = -(numVerts - i);
  789. polys[0].bounds.AddPoint( verts[i] );
  790. mid += v[i];
  791. }
  792. polys[1].bounds = polys[0].bounds;
  793. // offset to center
  794. offset = mid * (1.0f / numVerts);
  795. // total bounds
  796. bounds = polys[0].bounds;
  797. // considered non convex because the model has no volume
  798. isConvex = false;
  799. }
  800. /*
  801. ============
  802. idTraceModel::SetupPolygon
  803. ============
  804. */
  805. void idTraceModel::SetupPolygon( const idWinding &w ) {
  806. int i;
  807. idVec3 *verts;
  808. verts = (idVec3 *) _alloca16( w.GetNumPoints() * sizeof( idVec3 ) );
  809. for ( i = 0; i < w.GetNumPoints(); i++ ) {
  810. verts[i] = w[i].ToVec3();
  811. }
  812. SetupPolygon( verts, w.GetNumPoints() );
  813. }
  814. /*
  815. ============
  816. idTraceModel::VolumeFromPolygon
  817. ============
  818. */
  819. void idTraceModel::VolumeFromPolygon( idTraceModel &trm, float thickness ) const {
  820. int i;
  821. trm = *this;
  822. trm.type = TRM_POLYGONVOLUME;
  823. trm.numVerts = numVerts * 2;
  824. trm.numEdges = numEdges * 3;
  825. trm.numPolys = numEdges + 2;
  826. for ( i = 0; i < numEdges; i++ ) {
  827. trm.verts[ numVerts + i ] = verts[i] - thickness * polys[0].normal;
  828. trm.edges[ numEdges + i + 1 ].v[0] = numVerts + i;
  829. trm.edges[ numEdges + i + 1 ].v[1] = numVerts + (i+1) % numVerts;
  830. trm.edges[ numEdges * 2 + i + 1 ].v[0] = i;
  831. trm.edges[ numEdges * 2 + i + 1 ].v[1] = numVerts + i;
  832. trm.polys[1].edges[i] = -(numEdges + i + 1);
  833. trm.polys[2+i].numEdges = 4;
  834. trm.polys[2+i].edges[0] = -(i + 1);
  835. trm.polys[2+i].edges[1] = numEdges*2 + i + 1;
  836. trm.polys[2+i].edges[2] = numEdges + i + 1;
  837. trm.polys[2+i].edges[3] = -(numEdges*2 + (i+1) % numEdges + 1);
  838. trm.polys[2+i].normal = (verts[(i + 1) % numVerts] - verts[i]).Cross( polys[0].normal );
  839. trm.polys[2+i].normal.Normalize();
  840. trm.polys[2+i].dist = trm.polys[2+i].normal * verts[i];
  841. }
  842. trm.polys[1].dist = trm.polys[1].normal * trm.verts[ numEdges ];
  843. trm.GenerateEdgeNormals();
  844. }
  845. /*
  846. ============
  847. idTraceModel::GenerateEdgeNormals
  848. ============
  849. */
  850. #define SHARP_EDGE_DOT -0.7f
  851. int idTraceModel::GenerateEdgeNormals() {
  852. int i, j, edgeNum, numSharpEdges;
  853. float dot;
  854. idVec3 dir;
  855. traceModelPoly_t *poly;
  856. traceModelEdge_t *edge;
  857. for ( i = 0; i <= numEdges; i++ ) {
  858. edges[i].normal.Zero();
  859. }
  860. numSharpEdges = 0;
  861. for ( i = 0; i < numPolys; i++ ) {
  862. poly = polys + i;
  863. for ( j = 0; j < poly->numEdges; j++ ) {
  864. edgeNum = poly->edges[j];
  865. edge = edges + abs( edgeNum );
  866. if ( edge->normal[0] == 0.0f && edge->normal[1] == 0.0f && edge->normal[2] == 0.0f ) {
  867. edge->normal = poly->normal;
  868. }
  869. else {
  870. dot = edge->normal * poly->normal;
  871. // if the two planes make a very sharp edge
  872. if ( dot < SHARP_EDGE_DOT ) {
  873. // max length normal pointing outside both polygons
  874. dir = verts[ edge->v[edgeNum > 0]] - verts[ edge->v[edgeNum < 0]];
  875. edge->normal = edge->normal.Cross( dir ) + poly->normal.Cross( -dir );
  876. edge->normal *= ( 0.5f / ( 0.5f + 0.5f * SHARP_EDGE_DOT ) ) / edge->normal.Length();
  877. numSharpEdges++;
  878. }
  879. else {
  880. edge->normal = ( 0.5f / ( 0.5f + 0.5f * dot ) ) * ( edge->normal + poly->normal );
  881. }
  882. }
  883. }
  884. }
  885. return numSharpEdges;
  886. }
  887. /*
  888. ============
  889. idTraceModel::Translate
  890. ============
  891. */
  892. void idTraceModel::Translate( const idVec3 &translation ) {
  893. int i;
  894. for ( i = 0; i < numVerts; i++ ) {
  895. verts[i] += translation;
  896. }
  897. for ( i = 0; i < numPolys; i++ ) {
  898. polys[i].dist += polys[i].normal * translation;
  899. polys[i].bounds[0] += translation;
  900. polys[i].bounds[1] += translation;
  901. }
  902. offset += translation;
  903. bounds[0] += translation;
  904. bounds[1] += translation;
  905. }
  906. /*
  907. ============
  908. idTraceModel::Rotate
  909. ============
  910. */
  911. void idTraceModel::Rotate( const idMat3 &rotation ) {
  912. int i, j, edgeNum;
  913. for ( i = 0; i < numVerts; i++ ) {
  914. verts[i] *= rotation;
  915. }
  916. bounds.Clear();
  917. for ( i = 0; i < numPolys; i++ ) {
  918. polys[i].normal *= rotation;
  919. polys[i].bounds.Clear();
  920. edgeNum = 0;
  921. for ( j = 0; j < polys[i].numEdges; j++ ) {
  922. edgeNum = polys[i].edges[j];
  923. polys[i].bounds.AddPoint( verts[edges[abs(edgeNum)].v[INT32_SIGNBITSET(edgeNum)]] );
  924. }
  925. polys[i].dist = polys[i].normal * verts[edges[abs(edgeNum)].v[INT32_SIGNBITSET(edgeNum)]];
  926. bounds += polys[i].bounds;
  927. }
  928. GenerateEdgeNormals();
  929. }
  930. /*
  931. ============
  932. idTraceModel::Shrink
  933. ============
  934. */
  935. void idTraceModel::Shrink( const float m ) {
  936. int i, j, edgeNum;
  937. traceModelEdge_t *edge;
  938. idVec3 dir;
  939. if ( type == TRM_POLYGON ) {
  940. for ( i = 0; i < numEdges; i++ ) {
  941. edgeNum = polys[0].edges[i];
  942. edge = &edges[abs(edgeNum)];
  943. dir = verts[ edge->v[ INT32_SIGNBITSET(edgeNum) ] ] - verts[ edge->v[ INT32_SIGNBITNOTSET(edgeNum) ] ];
  944. if ( dir.Normalize() < 2.0f * m ) {
  945. continue;
  946. }
  947. dir *= m;
  948. verts[ edge->v[ 0 ] ] -= dir;
  949. verts[ edge->v[ 1 ] ] += dir;
  950. }
  951. return;
  952. }
  953. for ( i = 0; i < numPolys; i++ ) {
  954. polys[i].dist -= m;
  955. for ( j = 0; j < polys[i].numEdges; j++ ) {
  956. edgeNum = polys[i].edges[j];
  957. edge = &edges[abs(edgeNum)];
  958. verts[ edge->v[ INT32_SIGNBITSET(edgeNum) ] ] -= polys[i].normal * m;
  959. }
  960. }
  961. }
  962. /*
  963. ============
  964. idTraceModel::Compare
  965. ============
  966. */
  967. bool idTraceModel::Compare( const idTraceModel &trm ) const {
  968. int i;
  969. if ( type != trm.type || numVerts != trm.numVerts ||
  970. numEdges != trm.numEdges || numPolys != trm.numPolys ) {
  971. return false;
  972. }
  973. if ( bounds != trm.bounds || offset != trm.offset ) {
  974. return false;
  975. }
  976. switch( type ) {
  977. case TRM_INVALID:
  978. case TRM_BOX:
  979. case TRM_OCTAHEDRON:
  980. case TRM_DODECAHEDRON:
  981. case TRM_CYLINDER:
  982. case TRM_CONE:
  983. break;
  984. case TRM_BONE:
  985. case TRM_POLYGON:
  986. case TRM_POLYGONVOLUME:
  987. case TRM_CUSTOM:
  988. for ( i = 0; i < trm.numVerts; i++ ) {
  989. if ( verts[i] != trm.verts[i] ) {
  990. return false;
  991. }
  992. }
  993. break;
  994. }
  995. return true;
  996. }
  997. /*
  998. ============
  999. idTraceModel::GetPolygonArea
  1000. ============
  1001. */
  1002. float idTraceModel::GetPolygonArea( int polyNum ) const {
  1003. int i;
  1004. idVec3 base, v1, v2, cross;
  1005. float total;
  1006. const traceModelPoly_t *poly;
  1007. if ( polyNum < 0 || polyNum >= numPolys ) {
  1008. return 0.0f;
  1009. }
  1010. poly = &polys[polyNum];
  1011. total = 0.0f;
  1012. base = verts[ edges[ abs(poly->edges[0]) ].v[ INT32_SIGNBITSET( poly->edges[0] ) ] ];
  1013. for ( i = 0; i < poly->numEdges; i++ ) {
  1014. v1 = verts[ edges[ abs(poly->edges[i]) ].v[ INT32_SIGNBITSET( poly->edges[i] ) ] ] - base;
  1015. v2 = verts[ edges[ abs(poly->edges[i]) ].v[ INT32_SIGNBITNOTSET( poly->edges[i] ) ] ] - base;
  1016. cross = v1.Cross( v2 );
  1017. total += cross.Length();
  1018. }
  1019. return total * 0.5f;
  1020. }
  1021. /*
  1022. ============
  1023. idTraceModel::GetOrderedSilhouetteEdges
  1024. ============
  1025. */
  1026. int idTraceModel::GetOrderedSilhouetteEdges( const int edgeIsSilEdge[MAX_TRACEMODEL_EDGES+1], int silEdges[MAX_TRACEMODEL_EDGES] ) const {
  1027. int i, j, edgeNum, numSilEdges, nextSilVert;
  1028. int unsortedSilEdges[MAX_TRACEMODEL_EDGES];
  1029. numSilEdges = 0;
  1030. for ( i = 1; i <= numEdges; i++ ) {
  1031. if ( edgeIsSilEdge[i] ) {
  1032. unsortedSilEdges[numSilEdges++] = i;
  1033. }
  1034. }
  1035. silEdges[0] = unsortedSilEdges[0];
  1036. unsortedSilEdges[0] = -1;
  1037. nextSilVert = edges[silEdges[0]].v[0];
  1038. for ( i = 1; i < numSilEdges; i++ ) {
  1039. for ( j = 1; j < numSilEdges; j++ ) {
  1040. edgeNum = unsortedSilEdges[j];
  1041. if ( edgeNum >= 0 ) {
  1042. if ( edges[edgeNum].v[0] == nextSilVert ) {
  1043. nextSilVert = edges[edgeNum].v[1];
  1044. silEdges[i] = edgeNum;
  1045. break;
  1046. }
  1047. if ( edges[edgeNum].v[1] == nextSilVert ) {
  1048. nextSilVert = edges[edgeNum].v[0];
  1049. silEdges[i] = -edgeNum;
  1050. break;
  1051. }
  1052. }
  1053. }
  1054. if ( j >= numSilEdges ) {
  1055. silEdges[i] = 1; // shouldn't happen
  1056. }
  1057. unsortedSilEdges[j] = -1;
  1058. }
  1059. return numSilEdges;
  1060. }
  1061. /*
  1062. ============
  1063. idTraceModel::GetProjectionSilhouetteEdges
  1064. ============
  1065. */
  1066. int idTraceModel::GetProjectionSilhouetteEdges( const idVec3 &projectionOrigin, int silEdges[MAX_TRACEMODEL_EDGES] ) const {
  1067. int i, j, edgeNum;
  1068. int edgeIsSilEdge[MAX_TRACEMODEL_EDGES+1];
  1069. const traceModelPoly_t *poly;
  1070. idVec3 dir;
  1071. memset( edgeIsSilEdge, 0, sizeof( edgeIsSilEdge ) );
  1072. for ( i = 0; i < numPolys; i++ ) {
  1073. poly = &polys[i];
  1074. edgeNum = poly->edges[0];
  1075. dir = verts[ edges[abs(edgeNum)].v[ INT32_SIGNBITSET(edgeNum) ] ] - projectionOrigin;
  1076. if ( dir * poly->normal < 0.0f ) {
  1077. for ( j = 0; j < poly->numEdges; j++ ) {
  1078. edgeNum = poly->edges[j];
  1079. edgeIsSilEdge[abs(edgeNum)] ^= 1;
  1080. }
  1081. }
  1082. }
  1083. return GetOrderedSilhouetteEdges( edgeIsSilEdge, silEdges );
  1084. }
  1085. /*
  1086. ============
  1087. idTraceModel::GetParallelProjectionSilhouetteEdges
  1088. ============
  1089. */
  1090. int idTraceModel::GetParallelProjectionSilhouetteEdges( const idVec3 &projectionDir, int silEdges[MAX_TRACEMODEL_EDGES] ) const {
  1091. int i, j, edgeNum;
  1092. int edgeIsSilEdge[MAX_TRACEMODEL_EDGES+1];
  1093. const traceModelPoly_t *poly;
  1094. memset( edgeIsSilEdge, 0, sizeof( edgeIsSilEdge ) );
  1095. for ( i = 0; i < numPolys; i++ ) {
  1096. poly = &polys[i];
  1097. if ( projectionDir * poly->normal < 0.0f ) {
  1098. for ( j = 0; j < poly->numEdges; j++ ) {
  1099. edgeNum = poly->edges[j];
  1100. edgeIsSilEdge[abs(edgeNum)] ^= 1;
  1101. }
  1102. }
  1103. }
  1104. return GetOrderedSilhouetteEdges( edgeIsSilEdge, silEdges );
  1105. }
  1106. /*
  1107. credits to Brian Mirtich for his paper "Fast and Accurate Computation of Polyhedral Mass Properties"
  1108. */
  1109. typedef struct projectionIntegrals_s {
  1110. float P1;
  1111. float Pa, Pb;
  1112. float Paa, Pab, Pbb;
  1113. float Paaa, Paab, Pabb, Pbbb;
  1114. } projectionIntegrals_t;
  1115. /*
  1116. ============
  1117. idTraceModel::ProjectionIntegrals
  1118. ============
  1119. */
  1120. void idTraceModel::ProjectionIntegrals( int polyNum, int a, int b, struct projectionIntegrals_s &integrals ) const {
  1121. const traceModelPoly_t *poly;
  1122. int i, edgeNum;
  1123. idVec3 v1, v2;
  1124. float a0, a1, da;
  1125. float b0, b1, db;
  1126. float a0_2, a0_3, a0_4, b0_2, b0_3, b0_4;
  1127. float a1_2, a1_3, b1_2, b1_3;
  1128. float C1, Ca, Caa, Caaa, Cb, Cbb, Cbbb;
  1129. float Cab, Kab, Caab, Kaab, Cabb, Kabb;
  1130. memset(&integrals, 0, sizeof(projectionIntegrals_t));
  1131. poly = &polys[polyNum];
  1132. for ( i = 0; i < poly->numEdges; i++ ) {
  1133. edgeNum = poly->edges[i];
  1134. v1 = verts[ edges[ abs(edgeNum) ].v[ edgeNum < 0 ] ];
  1135. v2 = verts[ edges[ abs(edgeNum) ].v[ edgeNum > 0 ] ];
  1136. a0 = v1[a];
  1137. b0 = v1[b];
  1138. a1 = v2[a];
  1139. b1 = v2[b];
  1140. da = a1 - a0;
  1141. db = b1 - b0;
  1142. a0_2 = a0 * a0;
  1143. a0_3 = a0_2 * a0;
  1144. a0_4 = a0_3 * a0;
  1145. b0_2 = b0 * b0;
  1146. b0_3 = b0_2 * b0;
  1147. b0_4 = b0_3 * b0;
  1148. a1_2 = a1 * a1;
  1149. a1_3 = a1_2 * a1;
  1150. b1_2 = b1 * b1;
  1151. b1_3 = b1_2 * b1;
  1152. C1 = a1 + a0;
  1153. Ca = a1 * C1 + a0_2;
  1154. Caa = a1 * Ca + a0_3;
  1155. Caaa = a1 * Caa + a0_4;
  1156. Cb = b1 * (b1 + b0) + b0_2;
  1157. Cbb = b1 * Cb + b0_3;
  1158. Cbbb = b1 * Cbb + b0_4;
  1159. Cab = 3 * a1_2 + 2 * a1 * a0 + a0_2;
  1160. Kab = a1_2 + 2 * a1 * a0 + 3 * a0_2;
  1161. Caab = a0 * Cab + 4 * a1_3;
  1162. Kaab = a1 * Kab + 4 * a0_3;
  1163. Cabb = 4 * b1_3 + 3 * b1_2 * b0 + 2 * b1 * b0_2 + b0_3;
  1164. Kabb = b1_3 + 2 * b1_2 * b0 + 3 * b1 * b0_2 + 4 * b0_3;
  1165. integrals.P1 += db * C1;
  1166. integrals.Pa += db * Ca;
  1167. integrals.Paa += db * Caa;
  1168. integrals.Paaa += db * Caaa;
  1169. integrals.Pb += da * Cb;
  1170. integrals.Pbb += da * Cbb;
  1171. integrals.Pbbb += da * Cbbb;
  1172. integrals.Pab += db * (b1 * Cab + b0 * Kab);
  1173. integrals.Paab += db * (b1 * Caab + b0 * Kaab);
  1174. integrals.Pabb += da * (a1 * Cabb + a0 * Kabb);
  1175. }
  1176. integrals.P1 *= (1.0f / 2.0f);
  1177. integrals.Pa *= (1.0f / 6.0f);
  1178. integrals.Paa *= (1.0f / 12.0f);
  1179. integrals.Paaa *= (1.0f / 20.0f);
  1180. integrals.Pb *= (1.0f / -6.0f);
  1181. integrals.Pbb *= (1.0f / -12.0f);
  1182. integrals.Pbbb *= (1.0f / -20.0f);
  1183. integrals.Pab *= (1.0f / 24.0f);
  1184. integrals.Paab *= (1.0f / 60.0f);
  1185. integrals.Pabb *= (1.0f / -60.0f);
  1186. }
  1187. typedef struct polygonIntegrals_s {
  1188. float Fa, Fb, Fc;
  1189. float Faa, Fbb, Fcc;
  1190. float Faaa, Fbbb, Fccc;
  1191. float Faab, Fbbc, Fcca;
  1192. } polygonIntegrals_t;
  1193. /*
  1194. ============
  1195. idTraceModel::PolygonIntegrals
  1196. ============
  1197. */
  1198. void idTraceModel::PolygonIntegrals( int polyNum, int a, int b, int c, struct polygonIntegrals_s &integrals ) const {
  1199. projectionIntegrals_t pi;
  1200. idVec3 n;
  1201. float w;
  1202. float k1, k2, k3, k4;
  1203. ProjectionIntegrals( polyNum, a, b, pi );
  1204. n = polys[polyNum].normal;
  1205. w = -polys[polyNum].dist;
  1206. k1 = 1 / n[c];
  1207. k2 = k1 * k1;
  1208. k3 = k2 * k1;
  1209. k4 = k3 * k1;
  1210. integrals.Fa = k1 * pi.Pa;
  1211. integrals.Fb = k1 * pi.Pb;
  1212. integrals.Fc = -k2 * (n[a] * pi.Pa + n[b] * pi.Pb + w * pi.P1);
  1213. integrals.Faa = k1 * pi.Paa;
  1214. integrals.Fbb = k1 * pi.Pbb;
  1215. integrals.Fcc = k3 * (Square(n[a]) * pi.Paa + 2 * n[a] * n[b] * pi.Pab + Square(n[b]) * pi.Pbb
  1216. + w * (2 * (n[a] * pi.Pa + n[b] * pi.Pb) + w * pi.P1));
  1217. integrals.Faaa = k1 * pi.Paaa;
  1218. integrals.Fbbb = k1 * pi.Pbbb;
  1219. integrals.Fccc = -k4 * (Cube(n[a]) * pi.Paaa + 3 * Square(n[a]) * n[b] * pi.Paab
  1220. + 3 * n[a] * Square(n[b]) * pi.Pabb + Cube(n[b]) * pi.Pbbb
  1221. + 3 * w * (Square(n[a]) * pi.Paa + 2 * n[a] * n[b] * pi.Pab + Square(n[b]) * pi.Pbb)
  1222. + w * w * (3 * (n[a] * pi.Pa + n[b] * pi.Pb) + w * pi.P1));
  1223. integrals.Faab = k1 * pi.Paab;
  1224. integrals.Fbbc = -k2 * (n[a] * pi.Pabb + n[b] * pi.Pbbb + w * pi.Pbb);
  1225. integrals.Fcca = k3 * (Square(n[a]) * pi.Paaa + 2 * n[a] * n[b] * pi.Paab + Square(n[b]) * pi.Pabb
  1226. + w * (2 * (n[a] * pi.Paa + n[b] * pi.Pab) + w * pi.Pa));
  1227. }
  1228. typedef struct volumeIntegrals_s {
  1229. float T0;
  1230. idVec3 T1;
  1231. idVec3 T2;
  1232. idVec3 TP;
  1233. } volumeIntegrals_t;
  1234. /*
  1235. ============
  1236. idTraceModel::VolumeIntegrals
  1237. ============
  1238. */
  1239. void idTraceModel::VolumeIntegrals( struct volumeIntegrals_s &integrals ) const {
  1240. const traceModelPoly_t *poly;
  1241. polygonIntegrals_t pi;
  1242. int i, a, b, c;
  1243. float nx, ny, nz;
  1244. memset( &integrals, 0, sizeof(volumeIntegrals_t) );
  1245. for ( i = 0; i < numPolys; i++ ) {
  1246. poly = &polys[i];
  1247. nx = idMath::Fabs( poly->normal[0] );
  1248. ny = idMath::Fabs( poly->normal[1] );
  1249. nz = idMath::Fabs( poly->normal[2] );
  1250. if ( nx > ny && nx > nz ) {
  1251. c = 0;
  1252. }
  1253. else {
  1254. c = (ny > nz) ? 1 : 2;
  1255. }
  1256. a = (c + 1) % 3;
  1257. b = (a + 1) % 3;
  1258. PolygonIntegrals( i, a, b, c, pi );
  1259. integrals.T0 += poly->normal[0] * ((a == 0) ? pi.Fa : ((b == 0) ? pi.Fb : pi.Fc));
  1260. integrals.T1[a] += poly->normal[a] * pi.Faa;
  1261. integrals.T1[b] += poly->normal[b] * pi.Fbb;
  1262. integrals.T1[c] += poly->normal[c] * pi.Fcc;
  1263. integrals.T2[a] += poly->normal[a] * pi.Faaa;
  1264. integrals.T2[b] += poly->normal[b] * pi.Fbbb;
  1265. integrals.T2[c] += poly->normal[c] * pi.Fccc;
  1266. integrals.TP[a] += poly->normal[a] * pi.Faab;
  1267. integrals.TP[b] += poly->normal[b] * pi.Fbbc;
  1268. integrals.TP[c] += poly->normal[c] * pi.Fcca;
  1269. }
  1270. integrals.T1 *= 0.5f;
  1271. integrals.T2 *= (1.0f / 3.0f);
  1272. integrals.TP *= 0.5f;
  1273. }
  1274. /*
  1275. ============
  1276. idTraceModel::GetMassProperties
  1277. ============
  1278. */
  1279. void idTraceModel::GetMassProperties( const float density, float &mass, idVec3 &centerOfMass, idMat3 &inertiaTensor ) const {
  1280. volumeIntegrals_t integrals;
  1281. // if polygon trace model
  1282. if ( type == TRM_POLYGON ) {
  1283. idTraceModel trm;
  1284. VolumeFromPolygon( trm, 1.0f );
  1285. trm.GetMassProperties( density, mass, centerOfMass, inertiaTensor );
  1286. return;
  1287. }
  1288. VolumeIntegrals( integrals );
  1289. // if no volume
  1290. if ( integrals.T0 == 0.0f ) {
  1291. mass = 1.0f;
  1292. centerOfMass.Zero();
  1293. inertiaTensor.Identity();
  1294. return;
  1295. }
  1296. // mass of model
  1297. mass = density * integrals.T0;
  1298. // center of mass
  1299. centerOfMass = integrals.T1 / integrals.T0;
  1300. // compute inertia tensor
  1301. inertiaTensor[0][0] = density * (integrals.T2[1] + integrals.T2[2]);
  1302. inertiaTensor[1][1] = density * (integrals.T2[2] + integrals.T2[0]);
  1303. inertiaTensor[2][2] = density * (integrals.T2[0] + integrals.T2[1]);
  1304. inertiaTensor[0][1] = inertiaTensor[1][0] = - density * integrals.TP[0];
  1305. inertiaTensor[1][2] = inertiaTensor[2][1] = - density * integrals.TP[1];
  1306. inertiaTensor[2][0] = inertiaTensor[0][2] = - density * integrals.TP[2];
  1307. // translate inertia tensor to center of mass
  1308. inertiaTensor[0][0] -= mass * (centerOfMass[1]*centerOfMass[1] + centerOfMass[2]*centerOfMass[2]);
  1309. inertiaTensor[1][1] -= mass * (centerOfMass[2]*centerOfMass[2] + centerOfMass[0]*centerOfMass[0]);
  1310. inertiaTensor[2][2] -= mass * (centerOfMass[0]*centerOfMass[0] + centerOfMass[1]*centerOfMass[1]);
  1311. inertiaTensor[0][1] = inertiaTensor[1][0] += mass * centerOfMass[0] * centerOfMass[1];
  1312. inertiaTensor[1][2] = inertiaTensor[2][1] += mass * centerOfMass[1] * centerOfMass[2];
  1313. inertiaTensor[2][0] = inertiaTensor[0][2] += mass * centerOfMass[2] * centerOfMass[0];
  1314. }