tr_deform.cpp 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 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 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 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. 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.
  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. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "tr_local.h"
  23. /*
  24. =================
  25. R_FinishDeform
  26. The ambientCache is on the stack, so we don't want to leave a reference
  27. to it that would try to be freed later. Create the ambientCache immediately.
  28. =================
  29. */
  30. static void R_FinishDeform( drawSurf_t *drawSurf, srfTriangles_t *newTri, idDrawVert *ac ) {
  31. if ( !newTri ) {
  32. return;
  33. }
  34. // generate current normals, tangents, and bitangents
  35. // We might want to support the possibility of deform functions generating
  36. // explicit normals, and we might also want to allow the cached deformInfo
  37. // optimization for these.
  38. // FIXME: this doesn't work, because the deformed surface is just the
  39. // ambient one, and there isn't an opportunity to generate light interactions
  40. if ( drawSurf->material->ReceivesLighting() ) {
  41. newTri->verts = ac;
  42. R_DeriveTangents( newTri, false );
  43. newTri->verts = NULL;
  44. }
  45. newTri->ambientCache = vertexCache.AllocFrameTemp( ac, newTri->numVerts * sizeof( idDrawVert ) );
  46. // if we are out of vertex cache, leave it the way it is
  47. if ( newTri->ambientCache ) {
  48. drawSurf->geo = newTri;
  49. }
  50. }
  51. /*
  52. =====================
  53. R_AutospriteDeform
  54. Assuming all the triangles for this shader are independant
  55. quads, rebuild them as forward facing sprites
  56. =====================
  57. */
  58. static void R_AutospriteDeform( drawSurf_t *surf ) {
  59. int i;
  60. const idDrawVert *v;
  61. idVec3 mid, delta;
  62. float radius;
  63. idVec3 left, up;
  64. idVec3 leftDir, upDir;
  65. const srfTriangles_t *tri;
  66. srfTriangles_t *newTri;
  67. tri = surf->geo;
  68. if ( tri->numVerts & 3 ) {
  69. common->Warning( "R_AutospriteDeform: shader had odd vertex count %f %f %f", tri->verts[0].xyz.x, tri->verts[0].xyz.y, tri->verts[0].xyz.z );
  70. return;
  71. }
  72. if ( tri->numIndexes != ( tri->numVerts >> 2 ) * 6 ) {
  73. common->Warning( "R_AutospriteDeform: autosprite had odd index count" );
  74. return;
  75. }
  76. R_GlobalVectorToLocal( surf->space->modelMatrix, tr.viewDef->renderView.viewaxis[1], leftDir );
  77. R_GlobalVectorToLocal( surf->space->modelMatrix, tr.viewDef->renderView.viewaxis[2], upDir );
  78. if ( tr.viewDef->isMirror ) {
  79. leftDir = vec3_origin - leftDir;
  80. }
  81. // this srfTriangles_t and all its indexes and caches are in frame
  82. // memory, and will be automatically disposed of
  83. newTri = (srfTriangles_t *)R_ClearedFrameAlloc( sizeof( *newTri ) );
  84. newTri->numVerts = tri->numVerts;
  85. newTri->numIndexes = tri->numIndexes;
  86. newTri->indexes = (glIndex_t *)R_FrameAlloc( newTri->numIndexes * sizeof( newTri->indexes[0] ) );
  87. idDrawVert *ac = (idDrawVert *)_alloca16( newTri->numVerts * sizeof( idDrawVert ) );
  88. for ( i = 0 ; i < tri->numVerts ; i+=4 ) {
  89. // find the midpoint
  90. v = &tri->verts[i];
  91. mid[0] = 0.25 * (v->xyz[0] + (v+1)->xyz[0] + (v+2)->xyz[0] + (v+3)->xyz[0]);
  92. mid[1] = 0.25 * (v->xyz[1] + (v+1)->xyz[1] + (v+2)->xyz[1] + (v+3)->xyz[1]);
  93. mid[2] = 0.25 * (v->xyz[2] + (v+1)->xyz[2] + (v+2)->xyz[2] + (v+3)->xyz[2]);
  94. delta = v->xyz - mid;
  95. radius = delta.Length() * 0.707; // / sqrt(2)
  96. left = leftDir * radius;
  97. up = upDir * radius;
  98. ac[i+0].xyz = mid + left + up;
  99. ac[i+0].st[0] = 0;
  100. ac[i+0].st[1] = 0;
  101. ac[i+1].xyz = mid - left + up;
  102. ac[i+1].st[0] = 1;
  103. ac[i+1].st[1] = 0;
  104. ac[i+2].xyz = mid - left - up;
  105. ac[i+2].st[0] = 1;
  106. ac[i+2].st[1] = 1;
  107. ac[i+3].xyz = mid + left - up;
  108. ac[i+3].st[0] = 0;
  109. ac[i+3].st[1] = 1;
  110. newTri->indexes[6*(i>>2)+0] = i;
  111. newTri->indexes[6*(i>>2)+1] = i+1;
  112. newTri->indexes[6*(i>>2)+2] = i+2;
  113. newTri->indexes[6*(i>>2)+3] = i;
  114. newTri->indexes[6*(i>>2)+4] = i+2;
  115. newTri->indexes[6*(i>>2)+5] = i+3;
  116. }
  117. R_FinishDeform( surf, newTri, ac );
  118. }
  119. /*
  120. =====================
  121. R_TubeDeform
  122. will pivot a rectangular quad along the center of its long axis
  123. Note that a geometric tube with even quite a few sides tube will almost certainly render much faster
  124. than this, so this should only be for faked volumetric tubes.
  125. Make sure this is used with twosided translucent shaders, because the exact side
  126. order may not be correct.
  127. =====================
  128. */
  129. static void R_TubeDeform( drawSurf_t *surf ) {
  130. int i, j;
  131. int indexes;
  132. const srfTriangles_t *tri;
  133. static int edgeVerts[6][2] = {
  134. { 0, 1 },
  135. { 1, 2 },
  136. { 2, 0 },
  137. { 3, 4 },
  138. { 4, 5 },
  139. { 5, 3 }
  140. };
  141. tri = surf->geo;
  142. if ( tri->numVerts & 3 ) {
  143. common->Error( "R_AutospriteDeform: shader had odd vertex count" );
  144. }
  145. if ( tri->numIndexes != ( tri->numVerts >> 2 ) * 6 ) {
  146. common->Error( "R_AutospriteDeform: autosprite had odd index count" );
  147. }
  148. // we need the view direction to project the minor axis of the tube
  149. // as the view changes
  150. idVec3 localView;
  151. R_GlobalPointToLocal( surf->space->modelMatrix, tr.viewDef->renderView.vieworg, localView );
  152. // this srfTriangles_t and all its indexes and caches are in frame
  153. // memory, and will be automatically disposed of
  154. srfTriangles_t *newTri = (srfTriangles_t *)R_ClearedFrameAlloc( sizeof( *newTri ) );
  155. newTri->numVerts = tri->numVerts;
  156. newTri->numIndexes = tri->numIndexes;
  157. newTri->indexes = (glIndex_t *)R_FrameAlloc( newTri->numIndexes * sizeof( newTri->indexes[0] ) );
  158. memcpy( newTri->indexes, tri->indexes, newTri->numIndexes * sizeof( newTri->indexes[0] ) );
  159. idDrawVert *ac = (idDrawVert *)_alloca16( newTri->numVerts * sizeof( idDrawVert ) );
  160. memset( ac, 0, sizeof( idDrawVert ) * newTri->numVerts );
  161. // this is a lot of work for two triangles...
  162. // we could precalculate a lot if it is an issue, but it would mess up
  163. // the shader abstraction
  164. for ( i = 0, indexes = 0 ; i < tri->numVerts ; i+=4, indexes+=6 ) {
  165. float lengths[2];
  166. int nums[2];
  167. idVec3 mid[2];
  168. idVec3 major, minor;
  169. const idDrawVert *v1, *v2;
  170. // identify the two shortest edges out of the six defined by the indexes
  171. nums[0] = nums[1] = 0;
  172. lengths[0] = lengths[1] = 999999;
  173. for ( j = 0 ; j < 6 ; j++ ) {
  174. float l;
  175. v1 = &tri->verts[tri->indexes[i+edgeVerts[j][0]]];
  176. v2 = &tri->verts[tri->indexes[i+edgeVerts[j][1]]];
  177. l = ( v1->xyz - v2->xyz ).Length();
  178. if ( l < lengths[0] ) {
  179. nums[1] = nums[0];
  180. lengths[1] = lengths[0];
  181. nums[0] = j;
  182. lengths[0] = l;
  183. } else if ( l < lengths[1] ) {
  184. nums[1] = j;
  185. lengths[1] = l;
  186. }
  187. }
  188. // find the midpoints of the two short edges, which
  189. // will give us the major axis in object coordinates
  190. for ( j = 0 ; j < 2 ; j++ ) {
  191. v1 = &tri->verts[tri->indexes[i+edgeVerts[nums[j]][0]]];
  192. v2 = &tri->verts[tri->indexes[i+edgeVerts[nums[j]][1]]];
  193. mid[j][0] = 0.5 * (v1->xyz[0] + v2->xyz[0]);
  194. mid[j][1] = 0.5 * (v1->xyz[1] + v2->xyz[1]);
  195. mid[j][2] = 0.5 * (v1->xyz[2] + v2->xyz[2]);
  196. }
  197. // find the vector of the major axis
  198. major = mid[1] - mid[0];
  199. // re-project the points
  200. for ( j = 0 ; j < 2 ; j++ ) {
  201. float l;
  202. int i1 = tri->indexes[i+edgeVerts[nums[j]][0]];
  203. int i2 = tri->indexes[i+edgeVerts[nums[j]][1]];
  204. idDrawVert *av1 = &ac[i1];
  205. idDrawVert *av2 = &ac[i2];
  206. *av1 = *(idDrawVert *)&tri->verts[i1];
  207. *av2 = *(idDrawVert *)&tri->verts[i2];
  208. l = 0.5 * lengths[j];
  209. // cross this with the view direction to get minor axis
  210. idVec3 dir = mid[j] - localView;
  211. minor.Cross( major, dir );
  212. minor.Normalize();
  213. if ( j ) {
  214. av1->xyz = mid[j] - l * minor;
  215. av2->xyz = mid[j] + l * minor;
  216. } else {
  217. av1->xyz = mid[j] + l * minor;
  218. av2->xyz = mid[j] - l * minor;
  219. }
  220. }
  221. }
  222. R_FinishDeform( surf, newTri, ac );
  223. }
  224. /*
  225. =====================
  226. R_WindingFromTriangles
  227. =====================
  228. */
  229. #define MAX_TRI_WINDING_INDEXES 16
  230. int R_WindingFromTriangles( const srfTriangles_t *tri, glIndex_t indexes[MAX_TRI_WINDING_INDEXES] ) {
  231. int i, j, k, l;
  232. indexes[0] = tri->indexes[0];
  233. int numIndexes = 1;
  234. int numTris = tri->numIndexes / 3;
  235. do {
  236. // find an edge that goes from the current index to another
  237. // index that isn't already used, and isn't an internal edge
  238. for ( i = 0 ; i < numTris ; i++ ) {
  239. for ( j = 0 ; j < 3 ; j++ ) {
  240. if ( tri->indexes[i*3+j] != indexes[numIndexes-1] ) {
  241. continue;
  242. }
  243. int next = tri->indexes[i*3+(j+1)%3];
  244. // make sure it isn't already used
  245. if ( numIndexes == 1 ) {
  246. if ( next == indexes[0] ) {
  247. continue;
  248. }
  249. } else {
  250. for ( k = 1 ; k < numIndexes ; k++ ) {
  251. if ( indexes[k] == next ) {
  252. break;
  253. }
  254. }
  255. if ( k != numIndexes ) {
  256. continue;
  257. }
  258. }
  259. // make sure it isn't an interior edge
  260. for ( k = 0 ; k < numTris ; k++ ) {
  261. if ( k == i ) {
  262. continue;
  263. }
  264. for ( l = 0 ; l < 3 ; l++ ) {
  265. int a, b;
  266. a = tri->indexes[k*3+l];
  267. if ( a != next ) {
  268. continue;
  269. }
  270. b = tri->indexes[k*3+(l+1)%3];
  271. if ( b != indexes[numIndexes-1] ) {
  272. continue;
  273. }
  274. // this is an interior edge
  275. break;
  276. }
  277. if ( l != 3 ) {
  278. break;
  279. }
  280. }
  281. if ( k != numTris ) {
  282. continue;
  283. }
  284. // add this to the list
  285. indexes[numIndexes] = next;
  286. numIndexes++;
  287. break;
  288. }
  289. if ( j != 3 ) {
  290. break;
  291. }
  292. }
  293. if ( numIndexes == tri->numVerts ) {
  294. break;
  295. }
  296. } while ( i != numTris );
  297. return numIndexes;
  298. }
  299. /*
  300. =====================
  301. R_FlareDeform
  302. =====================
  303. */
  304. /*
  305. static void R_FlareDeform( drawSurf_t *surf ) {
  306. const srfTriangles_t *tri;
  307. srfTriangles_t *newTri;
  308. idPlane plane;
  309. float dot;
  310. idVec3 localViewer;
  311. int j;
  312. tri = surf->geo;
  313. if ( tri->numVerts != 4 || tri->numIndexes != 6 ) {
  314. //FIXME: temp hack for flares on tripleted models
  315. common->Warning( "R_FlareDeform: not a single quad" );
  316. return;
  317. }
  318. // this srfTriangles_t and all its indexes and caches are in frame
  319. // memory, and will be automatically disposed of
  320. newTri = (srfTriangles_t *)R_ClearedFrameAlloc( sizeof( *newTri ) );
  321. newTri->numVerts = 4;
  322. newTri->numIndexes = 2*3;
  323. newTri->indexes = (glIndex_t *)R_FrameAlloc( newTri->numIndexes * sizeof( newTri->indexes[0] ) );
  324. idDrawVert *ac = (idDrawVert *)_alloca16( newTri->numVerts * sizeof( idDrawVert ) );
  325. // find the plane
  326. plane.FromPoints( tri->verts[tri->indexes[0]].xyz, tri->verts[tri->indexes[1]].xyz, tri->verts[tri->indexes[2]].xyz );
  327. // if viewer is behind the plane, draw nothing
  328. R_GlobalPointToLocal( surf->space->modelMatrix, tr.viewDef->renderView.vieworg, localViewer );
  329. float distFromPlane = localViewer * plane.Normal() + plane[3];
  330. if ( distFromPlane <= 0 ) {
  331. newTri->numIndexes = 0;
  332. surf->geo = newTri;
  333. return;
  334. }
  335. idVec3 center;
  336. center = tri->verts[0].xyz;
  337. for ( j = 1 ; j < tri->numVerts ; j++ ) {
  338. center += tri->verts[j].xyz;
  339. }
  340. center *= 1.0/tri->numVerts;
  341. idVec3 dir = localViewer - center;
  342. dir.Normalize();
  343. dot = dir * plane.Normal();
  344. // set vertex colors based on plane angle
  345. int color = (int)(dot * 8 * 256);
  346. if ( color > 255 ) {
  347. color = 255;
  348. }
  349. for ( j = 0 ; j < newTri->numVerts ; j++ ) {
  350. ac[j].color[0] =
  351. ac[j].color[1] =
  352. ac[j].color[2] = color;
  353. ac[j].color[3] = 255;
  354. }
  355. float spread = surf->shaderRegisters[ surf->material->GetDeformRegister(0) ] * r_flareSize.GetFloat();
  356. idVec3 edgeDir[4][3];
  357. glIndex_t indexes[MAX_TRI_WINDING_INDEXES];
  358. int numIndexes = R_WindingFromTriangles( tri, indexes );
  359. surf->material = declManager->FindMaterial( "textures/smf/anamorphicFlare" );
  360. // only deal with quads
  361. if ( numIndexes != 4 ) {
  362. return;
  363. }
  364. // compute centroid
  365. idVec3 centroid, toeye, forward, up, left;
  366. centroid.Set( 0, 0, 0 );
  367. for ( int i = 0; i < 4; i++ ) {
  368. centroid += tri->verts[ indexes[i] ].xyz;
  369. }
  370. centroid /= 4;
  371. // compute basis vectors
  372. up.Set( 0, 0, 1 );
  373. toeye = centroid - localViewer;
  374. toeye.Normalize();
  375. left = toeye.Cross( up );
  376. up = left.Cross( toeye );
  377. left = left * 40 * 6;
  378. up = up * 40;
  379. // compute flares
  380. struct flare_t {
  381. float angle;
  382. float length;
  383. };
  384. static flare_t flares[] = {
  385. { 0, 100 },
  386. { 90, 100 }
  387. };
  388. for ( int i = 0; i < 4; i++ ) {
  389. memset( ac + i, 0, sizeof( ac[i] ) );
  390. }
  391. ac[0].xyz = centroid - left;
  392. ac[0].st[0] = 0; ac[0].st[1] = 0;
  393. ac[1].xyz = centroid + up;
  394. ac[1].st[0] = 1; ac[1].st[1] = 0;
  395. ac[2].xyz = centroid + left;
  396. ac[2].st[0] = 1; ac[2].st[1] = 1;
  397. ac[3].xyz = centroid - up;
  398. ac[3].st[0] = 0; ac[3].st[1] = 1;
  399. // setup colors
  400. for ( j = 0 ; j < newTri->numVerts ; j++ ) {
  401. ac[j].color[0] =
  402. ac[j].color[1] =
  403. ac[j].color[2] = 255;
  404. ac[j].color[3] = 255;
  405. }
  406. // setup indexes
  407. static glIndex_t triIndexes[2*3] = {
  408. 0,1,2, 0,2,3
  409. };
  410. memcpy( newTri->indexes, triIndexes, sizeof( triIndexes ) );
  411. R_FinishDeform( surf, newTri, ac );
  412. }
  413. */
  414. static void R_FlareDeform( drawSurf_t *surf ) {
  415. const srfTriangles_t *tri;
  416. srfTriangles_t *newTri;
  417. idPlane plane;
  418. float dot;
  419. idVec3 localViewer;
  420. int j;
  421. tri = surf->geo;
  422. if ( tri->numVerts != 4 || tri->numIndexes != 6 ) {
  423. //FIXME: temp hack for flares on tripleted models
  424. common->Warning( "R_FlareDeform: not a single quad" );
  425. return;
  426. }
  427. // this srfTriangles_t and all its indexes and caches are in frame
  428. // memory, and will be automatically disposed of
  429. newTri = (srfTriangles_t *)R_ClearedFrameAlloc( sizeof( *newTri ) );
  430. newTri->numVerts = 16;
  431. newTri->numIndexes = 18*3;
  432. newTri->indexes = (glIndex_t *)R_FrameAlloc( newTri->numIndexes * sizeof( newTri->indexes[0] ) );
  433. idDrawVert *ac = (idDrawVert *)_alloca16( newTri->numVerts * sizeof( idDrawVert ) );
  434. // find the plane
  435. plane.FromPoints( tri->verts[tri->indexes[0]].xyz, tri->verts[tri->indexes[1]].xyz, tri->verts[tri->indexes[2]].xyz );
  436. // if viewer is behind the plane, draw nothing
  437. R_GlobalPointToLocal( surf->space->modelMatrix, tr.viewDef->renderView.vieworg, localViewer );
  438. float distFromPlane = localViewer * plane.Normal() + plane[3];
  439. if ( distFromPlane <= 0 ) {
  440. newTri->numIndexes = 0;
  441. surf->geo = newTri;
  442. return;
  443. }
  444. idVec3 center;
  445. center = tri->verts[0].xyz;
  446. for ( j = 1 ; j < tri->numVerts ; j++ ) {
  447. center += tri->verts[j].xyz;
  448. }
  449. center *= 1.0/tri->numVerts;
  450. idVec3 dir = localViewer - center;
  451. dir.Normalize();
  452. dot = dir * plane.Normal();
  453. // set vertex colors based on plane angle
  454. int color = (int)(dot * 8 * 256);
  455. if ( color > 255 ) {
  456. color = 255;
  457. }
  458. for ( j = 0 ; j < newTri->numVerts ; j++ ) {
  459. ac[j].color[0] =
  460. ac[j].color[1] =
  461. ac[j].color[2] = color;
  462. ac[j].color[3] = 255;
  463. }
  464. float spread = surf->shaderRegisters[ surf->material->GetDeformRegister(0) ] * r_flareSize.GetFloat();
  465. idVec3 edgeDir[4][3];
  466. glIndex_t indexes[MAX_TRI_WINDING_INDEXES];
  467. int numIndexes = R_WindingFromTriangles( tri, indexes );
  468. // only deal with quads
  469. if ( numIndexes != 4 ) {
  470. return;
  471. }
  472. int i;
  473. // calculate vector directions
  474. for ( i = 0 ; i < 4 ; i++ ) {
  475. ac[i].xyz = tri->verts[ indexes[i] ].xyz;
  476. ac[i].st[0] =
  477. ac[i].st[1] = 0.5;
  478. idVec3 toEye = tri->verts[ indexes[i] ].xyz - localViewer;
  479. toEye.Normalize();
  480. idVec3 d1 = tri->verts[ indexes[(i+1)%4] ].xyz - localViewer;
  481. d1.Normalize();
  482. edgeDir[i][1].Cross( toEye, d1 );
  483. edgeDir[i][1].Normalize();
  484. edgeDir[i][1] = vec3_origin - edgeDir[i][1];
  485. idVec3 d2 = tri->verts[ indexes[(i+3)%4] ].xyz - localViewer;
  486. d2.Normalize();
  487. edgeDir[i][0].Cross( toEye, d2 );
  488. edgeDir[i][0].Normalize();
  489. edgeDir[i][2] = edgeDir[i][0] + edgeDir[i][1];
  490. edgeDir[i][2].Normalize();
  491. }
  492. // build all the points
  493. ac[4].xyz = tri->verts[ indexes[0] ].xyz + spread * edgeDir[0][0];
  494. ac[4].st[0] = 0;
  495. ac[4].st[1] = 0.5;
  496. ac[5].xyz = tri->verts[ indexes[0] ].xyz + spread * edgeDir[0][2];
  497. ac[5].st[0] = 0;
  498. ac[5].st[1] = 0;
  499. ac[6].xyz = tri->verts[ indexes[0] ].xyz + spread * edgeDir[0][1];
  500. ac[6].st[0] = 0.5;
  501. ac[6].st[1] = 0;
  502. ac[7].xyz = tri->verts[ indexes[1] ].xyz + spread * edgeDir[1][0];
  503. ac[7].st[0] = 0.5;
  504. ac[7].st[1] = 0;
  505. ac[8].xyz = tri->verts[ indexes[1] ].xyz + spread * edgeDir[1][2];
  506. ac[8].st[0] = 1;
  507. ac[8].st[1] = 0;
  508. ac[9].xyz = tri->verts[ indexes[1] ].xyz + spread * edgeDir[1][1];
  509. ac[9].st[0] = 1;
  510. ac[9].st[1] = 0.5;
  511. ac[10].xyz = tri->verts[ indexes[2] ].xyz + spread * edgeDir[2][0];
  512. ac[10].st[0] = 1;
  513. ac[10].st[1] = 0.5;
  514. ac[11].xyz = tri->verts[ indexes[2] ].xyz + spread * edgeDir[2][2];
  515. ac[11].st[0] = 1;
  516. ac[11].st[1] = 1;
  517. ac[12].xyz = tri->verts[ indexes[2] ].xyz + spread * edgeDir[2][1];
  518. ac[12].st[0] = 0.5;
  519. ac[12].st[1] = 1;
  520. ac[13].xyz = tri->verts[ indexes[3] ].xyz + spread * edgeDir[3][0];
  521. ac[13].st[0] = 0.5;
  522. ac[13].st[1] = 1;
  523. ac[14].xyz = tri->verts[ indexes[3] ].xyz + spread * edgeDir[3][2];
  524. ac[14].st[0] = 0;
  525. ac[14].st[1] = 1;
  526. ac[15].xyz = tri->verts[ indexes[3] ].xyz + spread * edgeDir[3][1];
  527. ac[15].st[0] = 0;
  528. ac[15].st[1] = 0.5;
  529. for ( i = 4 ; i < 16 ; i++ ) {
  530. idVec3 dir = ac[i].xyz - localViewer;
  531. float len = dir.Normalize();
  532. float ang = dir * plane.Normal();
  533. // ac[i].xyz -= dir * spread * 2;
  534. float newLen = -( distFromPlane / ang );
  535. if ( newLen > 0 && newLen < len ) {
  536. ac[i].xyz = localViewer + dir * newLen;
  537. }
  538. ac[i].st[0] = 0;
  539. ac[i].st[1] = 0.5;
  540. }
  541. #if 1
  542. static glIndex_t triIndexes[18*3] = {
  543. 0,4,5, 0,5,6, 0,6,7, 0,7,1, 1,7,8, 1,8,9,
  544. 15,4,0, 15,0,3, 3,0,1, 3,1,2, 2,1,9, 2,9,10,
  545. 14,15,3, 14,3,13, 13,3,2, 13,2,12, 12,2,11, 11,2,10
  546. };
  547. #else
  548. newTri->numIndexes = 12;
  549. static glIndex_t triIndexes[4*3] = {
  550. 0,1,2, 0,2,3, 0,4,5,0,5,6
  551. };
  552. #endif
  553. memcpy( newTri->indexes, triIndexes, sizeof( triIndexes ) );
  554. R_FinishDeform( surf, newTri, ac );
  555. }
  556. /*
  557. =====================
  558. R_ExpandDeform
  559. Expands the surface along it's normals by a shader amount
  560. =====================
  561. */
  562. static void R_ExpandDeform( drawSurf_t *surf ) {
  563. int i;
  564. const srfTriangles_t *tri;
  565. srfTriangles_t *newTri;
  566. tri = surf->geo;
  567. // this srfTriangles_t and all its indexes and caches are in frame
  568. // memory, and will be automatically disposed of
  569. newTri = (srfTriangles_t *)R_ClearedFrameAlloc( sizeof( *newTri ) );
  570. newTri->numVerts = tri->numVerts;
  571. newTri->numIndexes = tri->numIndexes;
  572. newTri->indexes = tri->indexes;
  573. idDrawVert *ac = (idDrawVert *)_alloca16( newTri->numVerts * sizeof( idDrawVert ) );
  574. float dist = surf->shaderRegisters[ surf->material->GetDeformRegister(0) ];
  575. for ( i = 0 ; i < tri->numVerts ; i++ ) {
  576. ac[i] = *(idDrawVert *)&tri->verts[i];
  577. ac[i].xyz = tri->verts[i].xyz + tri->verts[i].normal * dist;
  578. }
  579. R_FinishDeform( surf, newTri, ac );
  580. }
  581. /*
  582. =====================
  583. R_MoveDeform
  584. Moves the surface along the X axis, mostly just for demoing the deforms
  585. =====================
  586. */
  587. static void R_MoveDeform( drawSurf_t *surf ) {
  588. int i;
  589. const srfTriangles_t *tri;
  590. srfTriangles_t *newTri;
  591. tri = surf->geo;
  592. // this srfTriangles_t and all its indexes and caches are in frame
  593. // memory, and will be automatically disposed of
  594. newTri = (srfTriangles_t *)R_ClearedFrameAlloc( sizeof( *newTri ) );
  595. newTri->numVerts = tri->numVerts;
  596. newTri->numIndexes = tri->numIndexes;
  597. newTri->indexes = tri->indexes;
  598. idDrawVert *ac = (idDrawVert *)_alloca16( newTri->numVerts * sizeof( idDrawVert ) );
  599. float dist = surf->shaderRegisters[ surf->material->GetDeformRegister(0) ];
  600. for ( i = 0 ; i < tri->numVerts ; i++ ) {
  601. ac[i] = *(idDrawVert *)&tri->verts[i];
  602. ac[i].xyz[0] += dist;
  603. }
  604. R_FinishDeform( surf, newTri, ac );
  605. }
  606. //=====================================================================================
  607. /*
  608. =====================
  609. R_TurbulentDeform
  610. Turbulently deforms the XYZ, S, and T values
  611. =====================
  612. */
  613. static void R_TurbulentDeform( drawSurf_t *surf ) {
  614. int i;
  615. const srfTriangles_t *tri;
  616. srfTriangles_t *newTri;
  617. tri = surf->geo;
  618. // this srfTriangles_t and all its indexes and caches are in frame
  619. // memory, and will be automatically disposed of
  620. newTri = (srfTriangles_t *)R_ClearedFrameAlloc( sizeof( *newTri ) );
  621. newTri->numVerts = tri->numVerts;
  622. newTri->numIndexes = tri->numIndexes;
  623. newTri->indexes = tri->indexes;
  624. idDrawVert *ac = (idDrawVert *)_alloca16( newTri->numVerts * sizeof( idDrawVert ) );
  625. idDeclTable *table = (idDeclTable *)surf->material->GetDeformDecl();
  626. float range = surf->shaderRegisters[ surf->material->GetDeformRegister(0) ];
  627. float timeOfs = surf->shaderRegisters[ surf->material->GetDeformRegister(1) ];
  628. float domain = surf->shaderRegisters[ surf->material->GetDeformRegister(2) ];
  629. float tOfs = 0.5;
  630. for ( i = 0 ; i < tri->numVerts ; i++ ) {
  631. float f = tri->verts[i].xyz[0] * 0.003 + tri->verts[i].xyz[1] * 0.007 + tri->verts[i].xyz[2] * 0.011;
  632. f = timeOfs + domain * f;
  633. f += timeOfs;
  634. ac[i] = *(idDrawVert *)&tri->verts[i];
  635. ac[i].st[0] += range * table->TableLookup( f );
  636. ac[i].st[1] += range * table->TableLookup( f + tOfs );
  637. }
  638. R_FinishDeform( surf, newTri, ac );
  639. }
  640. //=====================================================================================
  641. /*
  642. =====================
  643. AddTriangleToIsland_r
  644. =====================
  645. */
  646. #define MAX_EYEBALL_TRIS 10
  647. #define MAX_EYEBALL_ISLANDS 6
  648. typedef struct {
  649. int tris[MAX_EYEBALL_TRIS];
  650. int numTris;
  651. idBounds bounds;
  652. idVec3 mid;
  653. } eyeIsland_t;
  654. static void AddTriangleToIsland_r( const srfTriangles_t *tri, int triangleNum, bool *usedList, eyeIsland_t *island ) {
  655. int a, b, c;
  656. usedList[triangleNum] = true;
  657. // add to the current island
  658. if ( island->numTris == MAX_EYEBALL_TRIS ) {
  659. common->Error( "MAX_EYEBALL_TRIS" );
  660. }
  661. island->tris[island->numTris] = triangleNum;
  662. island->numTris++;
  663. // recurse into all neighbors
  664. a = tri->indexes[triangleNum*3];
  665. b = tri->indexes[triangleNum*3+1];
  666. c = tri->indexes[triangleNum*3+2];
  667. island->bounds.AddPoint( tri->verts[a].xyz );
  668. island->bounds.AddPoint( tri->verts[b].xyz );
  669. island->bounds.AddPoint( tri->verts[c].xyz );
  670. int numTri = tri->numIndexes / 3;
  671. for ( int i = 0 ; i < numTri ; i++ ) {
  672. if ( usedList[i] ) {
  673. continue;
  674. }
  675. if ( tri->indexes[i*3+0] == a
  676. || tri->indexes[i*3+1] == a
  677. || tri->indexes[i*3+2] == a
  678. || tri->indexes[i*3+0] == b
  679. || tri->indexes[i*3+1] == b
  680. || tri->indexes[i*3+2] == b
  681. || tri->indexes[i*3+0] == c
  682. || tri->indexes[i*3+1] == c
  683. || tri->indexes[i*3+2] == c ) {
  684. AddTriangleToIsland_r( tri, i, usedList, island );
  685. }
  686. }
  687. }
  688. /*
  689. =====================
  690. R_EyeballDeform
  691. Each eyeball surface should have an separate upright triangle behind it, long end
  692. pointing out the eye, and another single triangle in front of the eye for the focus point.
  693. =====================
  694. */
  695. static void R_EyeballDeform( drawSurf_t *surf ) {
  696. int i, j, k;
  697. const srfTriangles_t *tri;
  698. srfTriangles_t *newTri;
  699. eyeIsland_t islands[MAX_EYEBALL_ISLANDS];
  700. int numIslands;
  701. bool triUsed[MAX_EYEBALL_ISLANDS*MAX_EYEBALL_TRIS];
  702. tri = surf->geo;
  703. // separate all the triangles into islands
  704. int numTri = tri->numIndexes / 3;
  705. if ( numTri > MAX_EYEBALL_ISLANDS*MAX_EYEBALL_TRIS ) {
  706. common->Printf( "R_EyeballDeform: too many triangles in surface" );
  707. return;
  708. }
  709. memset( triUsed, 0, sizeof( triUsed ) );
  710. for ( numIslands = 0 ; numIslands < MAX_EYEBALL_ISLANDS ; numIslands++ ) {
  711. islands[numIslands].numTris = 0;
  712. islands[numIslands].bounds.Clear();
  713. for ( i = 0 ; i < numTri ; i++ ) {
  714. if ( !triUsed[i] ) {
  715. AddTriangleToIsland_r( tri, i, triUsed, &islands[numIslands] );
  716. break;
  717. }
  718. }
  719. if ( i == numTri ) {
  720. break;
  721. }
  722. }
  723. // assume we always have two eyes, two origins, and two targets
  724. if ( numIslands != 3 ) {
  725. common->Printf( "R_EyeballDeform: %i triangle islands\n", numIslands );
  726. return;
  727. }
  728. // this srfTriangles_t and all its indexes and caches are in frame
  729. // memory, and will be automatically disposed of
  730. // the surface cannot have more indexes or verts than the original
  731. newTri = (srfTriangles_t *)R_ClearedFrameAlloc( sizeof( *newTri ) );
  732. memset( newTri, 0, sizeof( *newTri ) );
  733. newTri->numVerts = tri->numVerts;
  734. newTri->numIndexes = tri->numIndexes;
  735. newTri->indexes = (glIndex_t *)R_FrameAlloc( tri->numIndexes * sizeof( newTri->indexes[0] ) );
  736. idDrawVert *ac = (idDrawVert *)_alloca16( tri->numVerts * sizeof( idDrawVert ) );
  737. newTri->numIndexes = 0;
  738. // decide which islands are the eyes and points
  739. for ( i = 0 ; i < numIslands ; i++ ) {
  740. islands[i].mid = islands[i].bounds.GetCenter();
  741. }
  742. for ( i = 0 ; i < numIslands ; i++ ) {
  743. eyeIsland_t *island = &islands[i];
  744. if ( island->numTris == 1 ) {
  745. continue;
  746. }
  747. // the closest single triangle point will be the eye origin
  748. // and the next-to-farthest will be the focal point
  749. idVec3 origin, focus;
  750. int originIsland = 0;
  751. float dist[MAX_EYEBALL_ISLANDS];
  752. int sortOrder[MAX_EYEBALL_ISLANDS];
  753. for ( j = 0 ; j < numIslands ; j++ ) {
  754. idVec3 dir = islands[j].mid - island->mid;
  755. dist[j] = dir.Length();
  756. sortOrder[j] = j;
  757. for ( k = j-1 ; k >= 0 ; k-- ) {
  758. if ( dist[k] > dist[k+1] ) {
  759. int temp = sortOrder[k];
  760. sortOrder[k] = sortOrder[k+1];
  761. sortOrder[k+1] = temp;
  762. float ftemp = dist[k];
  763. dist[k] = dist[k+1];
  764. dist[k+1] = ftemp;
  765. }
  766. }
  767. }
  768. originIsland = sortOrder[1];
  769. origin = islands[originIsland].mid;
  770. focus = islands[sortOrder[2]].mid;
  771. // determine the projection directions based on the origin island triangle
  772. idVec3 dir = focus - origin;
  773. dir.Normalize();
  774. const idVec3 &p1 = tri->verts[tri->indexes[islands[originIsland].tris[0]+0]].xyz;
  775. const idVec3 &p2 = tri->verts[tri->indexes[islands[originIsland].tris[0]+1]].xyz;
  776. const idVec3 &p3 = tri->verts[tri->indexes[islands[originIsland].tris[0]+2]].xyz;
  777. idVec3 v1 = p2 - p1;
  778. v1.Normalize();
  779. idVec3 v2 = p3 - p1;
  780. v2.Normalize();
  781. // texVec[0] will be the normal to the origin triangle
  782. idVec3 texVec[2];
  783. texVec[0].Cross( v1, v2 );
  784. texVec[1].Cross( texVec[0], dir );
  785. for ( j = 0 ; j < 2 ; j++ ) {
  786. texVec[j] -= dir * ( texVec[j] * dir );
  787. texVec[j].Normalize();
  788. }
  789. // emit these triangles, generating the projected texcoords
  790. for ( j = 0 ; j < islands[i].numTris ; j++ ) {
  791. for ( k = 0 ; k < 3 ; k++ ) {
  792. int index = islands[i].tris[j] * 3;
  793. index = tri->indexes[index+k];
  794. newTri->indexes[newTri->numIndexes++] = index;
  795. ac[index].xyz = tri->verts[index].xyz;
  796. idVec3 local = tri->verts[index].xyz - origin;
  797. ac[index].st[0] = 0.5 + local * texVec[0];
  798. ac[index].st[1] = 0.5 + local * texVec[1];
  799. }
  800. }
  801. }
  802. R_FinishDeform( surf, newTri, ac );
  803. }
  804. //==========================================================================================
  805. /*
  806. =====================
  807. R_ParticleDeform
  808. Emit particles from the surface instead of drawing it
  809. =====================
  810. */
  811. static void R_ParticleDeform( drawSurf_t *surf, bool useArea ) {
  812. const struct renderEntity_s *renderEntity = &surf->space->entityDef->parms;
  813. const struct viewDef_s *viewDef = tr.viewDef;
  814. const idDeclParticle *particleSystem = (idDeclParticle *)surf->material->GetDeformDecl();
  815. if ( r_skipParticles.GetBool() ) {
  816. return;
  817. }
  818. #if 0
  819. if ( renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] &&
  820. viewDef->renderView.time*0.001 >= renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] ) {
  821. // the entire system has faded out
  822. return NULL;
  823. }
  824. #endif
  825. //
  826. // calculate the area of all the triangles
  827. //
  828. int numSourceTris = surf->geo->numIndexes / 3;
  829. float totalArea = 0;
  830. float *sourceTriAreas = NULL;
  831. const srfTriangles_t *srcTri = surf->geo;
  832. if ( useArea ) {
  833. sourceTriAreas = (float *)_alloca( sizeof( *sourceTriAreas ) * numSourceTris );
  834. int triNum = 0;
  835. for ( int i = 0 ; i < srcTri->numIndexes ; i += 3, triNum++ ) {
  836. float area;
  837. area = idWinding::TriangleArea( srcTri->verts[srcTri->indexes[i]].xyz, srcTri->verts[srcTri->indexes[i+1]].xyz, srcTri->verts[srcTri->indexes[i+2]].xyz );
  838. sourceTriAreas[triNum] = totalArea;
  839. totalArea += area;
  840. }
  841. }
  842. //
  843. // create the particles almost exactly the way idRenderModelPrt does
  844. //
  845. particleGen_t g;
  846. g.renderEnt = renderEntity;
  847. g.renderView = &viewDef->renderView;
  848. g.origin.Zero();
  849. g.axis = mat3_identity;
  850. for ( int currentTri = 0; currentTri < ( ( useArea ) ? 1 : numSourceTris ); currentTri++ ) {
  851. for ( int stageNum = 0 ; stageNum < particleSystem->stages.Num() ; stageNum++ ) {
  852. idParticleStage *stage = particleSystem->stages[stageNum];
  853. if ( !stage->material ) {
  854. continue;
  855. }
  856. if ( !stage->cycleMsec ) {
  857. continue;
  858. }
  859. if ( stage->hidden ) { // just for gui particle editor use
  860. continue;
  861. }
  862. // we interpret stage->totalParticles as "particles per map square area"
  863. // so the systems look the same on different size surfaces
  864. int totalParticles = ( useArea ) ? stage->totalParticles * totalArea / 4096.0 : ( stage->totalParticles );
  865. int count = totalParticles * stage->NumQuadsPerParticle();
  866. // allocate a srfTriangles in temp memory that can hold all the particles
  867. srfTriangles_t *tri;
  868. tri = (srfTriangles_t *)R_ClearedFrameAlloc( sizeof( *tri ) );
  869. tri->numVerts = 4 * count;
  870. tri->numIndexes = 6 * count;
  871. tri->verts = (idDrawVert *)R_FrameAlloc( tri->numVerts * sizeof( tri->verts[0] ) );
  872. tri->indexes = (glIndex_t *)R_FrameAlloc( tri->numIndexes * sizeof( tri->indexes[0] ) );
  873. // just always draw the particles
  874. tri->bounds = stage->bounds;
  875. tri->numVerts = 0;
  876. idRandom steppingRandom, steppingRandom2;
  877. int stageAge = g.renderView->time + renderEntity->shaderParms[SHADERPARM_TIMEOFFSET] * 1000 - stage->timeOffset * 1000;
  878. int stageCycle = stageAge / stage->cycleMsec;
  879. int inCycleTime = stageAge - stageCycle * stage->cycleMsec;
  880. // some particles will be in this cycle, some will be in the previous cycle
  881. steppingRandom.SetSeed( (( stageCycle << 10 ) & idRandom::MAX_RAND) ^ (int)( renderEntity->shaderParms[SHADERPARM_DIVERSITY] * idRandom::MAX_RAND ) );
  882. steppingRandom2.SetSeed( (( (stageCycle-1) << 10 ) & idRandom::MAX_RAND) ^ (int)( renderEntity->shaderParms[SHADERPARM_DIVERSITY] * idRandom::MAX_RAND ) );
  883. for ( int index = 0 ; index < totalParticles ; index++ ) {
  884. g.index = index;
  885. // bump the random
  886. steppingRandom.RandomInt();
  887. steppingRandom2.RandomInt();
  888. // calculate local age for this index
  889. int bunchOffset = stage->particleLife * 1000 * stage->spawnBunching * index / totalParticles;
  890. int particleAge = stageAge - bunchOffset;
  891. int particleCycle = particleAge / stage->cycleMsec;
  892. if ( particleCycle < 0 ) {
  893. // before the particleSystem spawned
  894. continue;
  895. }
  896. if ( stage->cycles && particleCycle >= stage->cycles ) {
  897. // cycled systems will only run cycle times
  898. continue;
  899. }
  900. if ( particleCycle == stageCycle ) {
  901. g.random = steppingRandom;
  902. } else {
  903. g.random = steppingRandom2;
  904. }
  905. int inCycleTime = particleAge - particleCycle * stage->cycleMsec;
  906. if ( renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] &&
  907. g.renderView->time - inCycleTime >= renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME]*1000 ) {
  908. // don't fire any more particles
  909. continue;
  910. }
  911. // supress particles before or after the age clamp
  912. g.frac = (float)inCycleTime / ( stage->particleLife * 1000 );
  913. if ( g.frac < 0 ) {
  914. // yet to be spawned
  915. continue;
  916. }
  917. if ( g.frac > 1.0 ) {
  918. // this particle is in the deadTime band
  919. continue;
  920. }
  921. //---------------
  922. // locate the particle origin and axis somewhere on the surface
  923. //---------------
  924. int pointTri = currentTri;
  925. if ( useArea ) {
  926. // select a triangle based on an even area distribution
  927. pointTri = idBinSearch_LessEqual<float>( sourceTriAreas, numSourceTris, g.random.RandomFloat() * totalArea );
  928. }
  929. // now pick a random point inside pointTri
  930. const idDrawVert *v1 = &srcTri->verts[ srcTri->indexes[ pointTri * 3 + 0 ] ];
  931. const idDrawVert *v2 = &srcTri->verts[ srcTri->indexes[ pointTri * 3 + 1 ] ];
  932. const idDrawVert *v3 = &srcTri->verts[ srcTri->indexes[ pointTri * 3 + 2 ] ];
  933. float f1 = g.random.RandomFloat();
  934. float f2 = g.random.RandomFloat();
  935. float f3 = g.random.RandomFloat();
  936. float ft = 1.0f / ( f1 + f2 + f3 + 0.0001f );
  937. f1 *= ft;
  938. f2 *= ft;
  939. f3 *= ft;
  940. g.origin = v1->xyz * f1 + v2->xyz * f2 + v3->xyz * f3;
  941. g.axis[0] = v1->tangents[0] * f1 + v2->tangents[0] * f2 + v3->tangents[0] * f3;
  942. g.axis[1] = v1->tangents[1] * f1 + v2->tangents[1] * f2 + v3->tangents[1] * f3;
  943. g.axis[2] = v1->normal * f1 + v2->normal * f2 + v3->normal * f3;
  944. //-----------------------
  945. // this is needed so aimed particles can calculate origins at different times
  946. g.originalRandom = g.random;
  947. g.age = g.frac * stage->particleLife;
  948. // if the particle doesn't get drawn because it is faded out or beyond a kill region,
  949. // don't increment the verts
  950. tri->numVerts += stage->CreateParticle( &g, tri->verts + tri->numVerts );
  951. }
  952. if ( tri->numVerts > 0 ) {
  953. // build the index list
  954. int indexes = 0;
  955. for ( int i = 0 ; i < tri->numVerts ; i += 4 ) {
  956. tri->indexes[indexes+0] = i;
  957. tri->indexes[indexes+1] = i+2;
  958. tri->indexes[indexes+2] = i+3;
  959. tri->indexes[indexes+3] = i;
  960. tri->indexes[indexes+4] = i+3;
  961. tri->indexes[indexes+5] = i+1;
  962. indexes += 6;
  963. }
  964. tri->numIndexes = indexes;
  965. tri->ambientCache = vertexCache.AllocFrameTemp( tri->verts, tri->numVerts * sizeof( idDrawVert ) );
  966. if ( tri->ambientCache ) {
  967. // add the drawsurf
  968. R_AddDrawSurf( tri, surf->space, renderEntity, stage->material, surf->scissorRect );
  969. }
  970. }
  971. }
  972. }
  973. }
  974. //========================================================================================
  975. /*
  976. =================
  977. R_DeformDrawSurf
  978. =================
  979. */
  980. void R_DeformDrawSurf( drawSurf_t *drawSurf ) {
  981. if ( !drawSurf->material ) {
  982. return;
  983. }
  984. if ( r_skipDeforms.GetBool() ) {
  985. return;
  986. }
  987. switch ( drawSurf->material->Deform() ) {
  988. case DFRM_NONE:
  989. return;
  990. case DFRM_SPRITE:
  991. R_AutospriteDeform( drawSurf );
  992. break;
  993. case DFRM_TUBE:
  994. R_TubeDeform( drawSurf );
  995. break;
  996. case DFRM_FLARE:
  997. R_FlareDeform( drawSurf );
  998. break;
  999. case DFRM_EXPAND:
  1000. R_ExpandDeform( drawSurf );
  1001. break;
  1002. case DFRM_MOVE:
  1003. R_MoveDeform( drawSurf );
  1004. break;
  1005. case DFRM_TURB:
  1006. R_TurbulentDeform( drawSurf );
  1007. break;
  1008. case DFRM_EYEBALL:
  1009. R_EyeballDeform( drawSurf );
  1010. break;
  1011. case DFRM_PARTICLE:
  1012. R_ParticleDeform( drawSurf, true );
  1013. break;
  1014. case DFRM_PARTICLE2:
  1015. R_ParticleDeform( drawSurf, false );
  1016. break;
  1017. }
  1018. }