pointgr.cpp 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program 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. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***************************************************************************
  21. * *
  22. * Project Name : G *
  23. * *
  24. * $Archive:: /VSS_Sync/ww3d2/pointgr.cpp $*
  25. * *
  26. * $Author:: Vss_sync $*
  27. * *
  28. * $Modtime:: 9/12/01 10:01p $*
  29. * *
  30. * $Revision:: 38 $*
  31. * *
  32. *-------------------------------------------------------------------------*
  33. * Functions: *
  34. * PointGroupClass::PointGroupClass -- PointGroupClass CTor. *
  35. * PointGroupClass::~PointGroupClass -- PointGroupClass DTor. *
  36. * PointGroupClass::operator = -- PointGroupClass assignment operator. *
  37. * PointGroupClass::Set_Arrays -- Set point location/color/enable arrays.*
  38. * PointGroupClass::Set_Point_Size -- Set default point size. *
  39. * PointGroupClass::Get_Point_Size -- Get default point size. *
  40. * PointGroupClass::Set_Point_Color -- Set default point color. *
  41. * PointGroupClass::Get_Point_Color -- Get default point color. *
  42. * PointGroupClass::Set_Point_Alpha -- Set default point alpha. *
  43. * PointGroupClass::Get_Point_Alpha -- Get default point alpha. *
  44. * PointGroupClass::Set_Point_Orientation -- Set default point orientatio*
  45. * PointGroupClass::Get_Point_Orientation -- Get default point orientatio*
  46. * PointGroupClass::Set_Point_Frame -- Set default point frame. *
  47. * PointGroupClass::Get_Point_Frame -- Get default point frame. *
  48. * PointGroupClass::Set_Point_Mode -- Set point rendering method. *
  49. * PointGroupClass::Get_Point_Mode -- Get point rendering method. *
  50. * PointGroupClass::Set_Flag -- Set given flag to on or off. *
  51. * PointGroupClass::Get_Flag -- Get current value (on/off) of given flag.*
  52. * PointGroupClass::Set_Texture -- Set texture used. *
  53. * PointGroupClass::Get_Texture -- Get texture used. *
  54. * PointGroupClass::Set_Shader -- Set shader used. *
  55. * PointGroupClass::Get_Shader -- Get shader used. *
  56. * PointGroupClass::Get_Discrete_Orientation_Count_Log2 -- what it says *
  57. * PointGroupClass::Set_Discrete_Orientation_Count_Log2 -- what it says. *
  58. * PointGroupClass::Get_Frame_Row_Column_Count_Log2 -- what it says *
  59. * PointGroupClass::Set_Frame_Row_Column_Count_Log2 -- what it says. *
  60. * PointGroupClass::Get_Polygon_Count -- Get estimated polygon count. *
  61. * PointGroupClass::Render -- draw point group. *
  62. * PointGroupClass::vInstance -- Create instance of class. *
  63. * PointGroupClass::sGetClassName -- Get name of class. *
  64. * PointGroupClass::Update_Arrays -- Update all arrays used in rendering *
  65. * PointGroupClass::Peek_Texture -- Peeks texture *
  66. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  67. #include "pointgr.h"
  68. #include "vertmaterial.h"
  69. #include "ww3d.h"
  70. #include "aabox.h"
  71. #include "statistics.h"
  72. #include "simplevec.h"
  73. #include "texture.h"
  74. #include "vector.h"
  75. #include "vp.h"
  76. #include "matrix4.h"
  77. #include "dx8wrapper.h"
  78. #include "dx8vertexbuffer.h"
  79. #include "dx8indexbuffer.h"
  80. #include "rinfo.h"
  81. #include "camera.h"
  82. #include "dx8fvf.h"
  83. #include "sortingrenderer.h"
  84. // Upgraded to DX8 2/2/01 HY
  85. // static data members
  86. Vector3 PointGroupClass::_TriVertexLocationOrientationTable[256][3];
  87. Vector3 PointGroupClass::_QuadVertexLocationOrientationTable[256][4];
  88. Vector2 *PointGroupClass::_TriVertexUVFrameTable[5] = { NULL, NULL, NULL, NULL, NULL};
  89. Vector2 *PointGroupClass::_QuadVertexUVFrameTable[5] = { NULL, NULL, NULL, NULL, NULL};
  90. VertexMaterialClass *PointGroupClass::PointMaterial=NULL;
  91. // This array has vertex locations for screenspace mode - calculated to cover exactly 1x1 and 2x2 pixels.
  92. Vector3 PointGroupClass::_ScreenspaceVertexLocationSizeTable[2][3] =
  93. {
  94. Vector3(0.5f, 0.0f, -1.0f),
  95. Vector3(1.0f, 1.0f, -1.0f),
  96. Vector3(0.0f, 1.0f, -1.0f),
  97. Vector3(1.0f, -0.5f, -1.0f),
  98. Vector3(2.7f, 2.0f, -1.0f),
  99. Vector3(-0.7f, 2.0f, -1.0f)
  100. };
  101. // Some internal variables
  102. VectorClass<Vector3> VertexLoc; // camera-space vertex locations
  103. VectorClass<Vector4> VertexDiffuse; // vertex diffuse/alpha colors
  104. VectorClass<Vector2> VertexUV; // vertex texture coords
  105. // Some DX 8 variables
  106. #define MAX_VB_SIZE 1200
  107. #define MAX_TRI_POINTS MAX_VB_SIZE/3
  108. #define MAX_TRI_IB_SIZE 3*MAX_TRI_POINTS
  109. #define MAX_QUAD_POINTS MAX_VB_SIZE/4
  110. #define MAX_QUAD_IB_SIZE 6*MAX_QUAD_POINTS
  111. DX8IndexBufferClass *Tris, *Quads; // Index buffers.
  112. SortingIndexBufferClass *SortingTris, *SortingQuads; // Sorting index buffers.
  113. /**************************************************************************
  114. * PointGroupClass::PointGroupClass -- PointGroupClass CTor. *
  115. * *
  116. * INPUT: *
  117. * *
  118. * OUTPUT: *
  119. * *
  120. * WARNINGS: *
  121. * *
  122. * HISTORY: *
  123. * 11/17/1998 NH : Created. *
  124. *========================================================================*/
  125. PointGroupClass::PointGroupClass(void) :
  126. PointLoc(NULL),
  127. PointDiffuse(NULL),
  128. APT(NULL),
  129. PointSize(NULL),
  130. PointOrientation(NULL),
  131. PointFrame(NULL),
  132. PointCount(0),
  133. FrameRowColumnCountLog2(0),
  134. Texture(NULL),
  135. Flags(0),
  136. Shader(ShaderClass::_PresetAdditiveSpriteShader),
  137. PointMode(TRIS),
  138. DefaultPointSize(0.0f),
  139. DefaultPointColor(1.0f, 1.0f, 1.0f),
  140. DefaultPointAlpha(1.0f),
  141. DefaultPointOrientation(0),
  142. DefaultPointFrame(0),
  143. VPXMin(0.0f),
  144. VPYMin(0.0f),
  145. VPXMax(0.0f),
  146. VPYMax(0.0f)
  147. {
  148. }
  149. /**************************************************************************
  150. * PointGroupClass::~PointGroupClass -- PointGroupClass DTor. *
  151. * *
  152. * INPUT: *
  153. * *
  154. * OUTPUT: *
  155. * *
  156. * WARNINGS: *
  157. * *
  158. * HISTORY: *
  159. * 11/17/1998 NH : Created. *
  160. *========================================================================*/
  161. PointGroupClass::~PointGroupClass(void)
  162. {
  163. if (PointLoc) {
  164. PointLoc->Release_Ref();
  165. PointLoc = NULL;
  166. }
  167. if (PointDiffuse) {
  168. PointDiffuse->Release_Ref();
  169. PointDiffuse=NULL;
  170. }
  171. if (APT) {
  172. APT->Release_Ref();
  173. APT = NULL;
  174. }
  175. if (PointSize) {
  176. PointSize->Release_Ref();
  177. PointSize = NULL;
  178. }
  179. if (PointOrientation) {
  180. PointOrientation->Release_Ref();
  181. PointOrientation = NULL;
  182. }
  183. if (PointFrame) {
  184. PointFrame->Release_Ref();
  185. PointFrame = NULL;
  186. }
  187. if (Texture) {
  188. REF_PTR_RELEASE(Texture);
  189. Texture = NULL;
  190. }
  191. }
  192. /**************************************************************************
  193. * PointGroupClass::operator = -- PointGroupClass assignment operator. *
  194. * *
  195. * INPUT: *
  196. * *
  197. * OUTPUT: *
  198. * *
  199. * WARNINGS: *
  200. * *
  201. * HISTORY: *
  202. * 11/17/1998 NH : Created. *
  203. *========================================================================*/
  204. PointGroupClass & PointGroupClass::operator = (const PointGroupClass & that)
  205. {
  206. if (this != &that) {
  207. WWASSERT(0); // If you hit this assert implement the function!
  208. }
  209. return *this;
  210. }
  211. /**************************************************************************
  212. * PointGroupClass::Set_Arrays -- Set point location/color/enable arrays. *
  213. * *
  214. * INPUT: *
  215. * *
  216. * OUTPUT: *
  217. * *
  218. * WARNINGS: *
  219. * *
  220. * NOTES: colors, alphas, APT, sizes, orientations and frames are *
  221. * optional. active_point_count can also be used with a NULL apt.*
  222. * In this case active_point_count is ignored if it is -1 *
  223. * (default value) and otherwise it indicates the first N active *
  224. * points in the arrays. *
  225. * The view plane rectangle may optionally be passed as well - *
  226. * this is only used in SCREENSPACE mode. *
  227. * *
  228. * HISTORY: *
  229. * 11/17/1998 NH : Created. *
  230. * 08/25/1999 NH : Alphas added. *
  231. * 06/28/2000 NH : Orientations and frames added. *
  232. * 02/08/2001 HY : Upgraded to DX8 *
  233. *========================================================================*/
  234. void PointGroupClass::Set_Arrays(
  235. ShareBufferClass<Vector3> *locs,
  236. ShareBufferClass<Vector4> *diffuse,
  237. ShareBufferClass<unsigned int> *apt,
  238. ShareBufferClass<float> *sizes,
  239. ShareBufferClass<unsigned char> *orientations,
  240. ShareBufferClass<unsigned char> *frames,
  241. int active_point_count,
  242. float vpxmin,
  243. float vpymin,
  244. float vpxmax,
  245. float vpymax)
  246. {
  247. // The point locations array is NOT optional!
  248. WWASSERT(locs);
  249. // Ensure lengths of all arrays are the same:
  250. WWASSERT(!diffuse || locs->Get_Count() == diffuse->Get_Count());
  251. WWASSERT(!apt || locs->Get_Count() == apt->Get_Count());
  252. WWASSERT(!sizes || locs->Get_Count() == sizes->Get_Count());
  253. WWASSERT(!orientations || locs->Get_Count() == orientations->Get_Count());
  254. WWASSERT(!frames || locs->Get_Count() == frames->Get_Count());
  255. REF_PTR_SET(PointLoc,locs);
  256. REF_PTR_SET(PointDiffuse,diffuse);
  257. REF_PTR_SET(APT,apt);
  258. REF_PTR_SET(PointSize,sizes);
  259. REF_PTR_SET(PointOrientation,orientations);
  260. REF_PTR_SET(PointFrame,frames);
  261. if (APT) {
  262. PointCount = active_point_count;
  263. } else {
  264. PointCount = (active_point_count >= 0) ? active_point_count : PointLoc->Get_Count();
  265. }
  266. // Store view plane rectangle (only used in SCREENSPACE mode)
  267. VPXMin = vpxmin;
  268. VPYMin = vpymin;
  269. VPXMax = vpxmax;
  270. VPYMax = vpymax;
  271. }
  272. /**************************************************************************
  273. * PointGroupClass::Set_Point_Size -- Set default point size. *
  274. * *
  275. * INPUT: *
  276. * *
  277. * OUTPUT: *
  278. * *
  279. * WARNINGS: This size is ignored if a size array is present. *
  280. * *
  281. * HISTORY: *
  282. * 11/17/1998 NH : Created. *
  283. *========================================================================*/
  284. void PointGroupClass::Set_Point_Size(float size)
  285. {
  286. DefaultPointSize = size;
  287. }
  288. /**************************************************************************
  289. * PointGroupClass::Get_Point_Size -- Get default point size. *
  290. * *
  291. * INPUT: *
  292. * *
  293. * OUTPUT: *
  294. * *
  295. * WARNINGS: This size is ignored if a size array is present. *
  296. * *
  297. * HISTORY: *
  298. * 11/17/1998 NH : Created. *
  299. *========================================================================*/
  300. float PointGroupClass::Get_Point_Size(void)
  301. {
  302. return DefaultPointSize;
  303. }
  304. /**************************************************************************
  305. * PointGroupClass::Set_Point_Color -- Set default point color. *
  306. * *
  307. * INPUT: *
  308. * *
  309. * OUTPUT: *
  310. * *
  311. * WARNINGS: This color is ignored if a color array is present. *
  312. * *
  313. * HISTORY: *
  314. * 04/20/1999 NH : Created. *
  315. *========================================================================*/
  316. void PointGroupClass::Set_Point_Color(Vector3 color)
  317. {
  318. DefaultPointColor = color;
  319. }
  320. /**************************************************************************
  321. * PointGroupClass::Get_Point_Color -- Get default point color. *
  322. * *
  323. * INPUT: *
  324. * *
  325. * OUTPUT: *
  326. * *
  327. * WARNINGS: This color is ignored if a color array is present. *
  328. * *
  329. * HISTORY: *
  330. * 04/20/1999 NH : Created. *
  331. *========================================================================*/
  332. Vector3 PointGroupClass::Get_Point_Color(void)
  333. {
  334. return DefaultPointColor;
  335. }
  336. /**************************************************************************
  337. * PointGroupClass::Set_Point_Alpha -- Set default point alpha. *
  338. * *
  339. * INPUT: *
  340. * *
  341. * OUTPUT: *
  342. * *
  343. * WARNINGS: This alpha is ignored if an alpha array is present. *
  344. * *
  345. * HISTORY: *
  346. * 08/25/1999 NH : Created. *
  347. *========================================================================*/
  348. void PointGroupClass::Set_Point_Alpha(float alpha)
  349. {
  350. DefaultPointAlpha = alpha;
  351. }
  352. /**************************************************************************
  353. * PointGroupClass::Get_Point_Alpha -- Get default point alpha. *
  354. * *
  355. * INPUT: *
  356. * *
  357. * OUTPUT: *
  358. * *
  359. * WARNINGS: This alpha is ignored if an alpha array is present. *
  360. * *
  361. * HISTORY: *
  362. * 08/25/1999 NH : Created. *
  363. *========================================================================*/
  364. float PointGroupClass::Get_Point_Alpha(void)
  365. {
  366. return DefaultPointAlpha;
  367. }
  368. /**************************************************************************
  369. * PointGroupClass::Set_Point_Orientation -- Set default point orientation*
  370. * *
  371. * INPUT: *
  372. * *
  373. * OUTPUT: *
  374. * *
  375. * WARNINGS: This is ignored if an orientation array is present. *
  376. * *
  377. * NOTE: No need to ensure value in valid range - it will be masked later.*
  378. * *
  379. * HISTORY: *
  380. * 06/28/2000 NH : Created. *
  381. *========================================================================*/
  382. void PointGroupClass::Set_Point_Orientation(unsigned char orientation)
  383. {
  384. DefaultPointOrientation = orientation;
  385. }
  386. /**************************************************************************
  387. * PointGroupClass::Get_Point_Orientation -- Get default point orientation*
  388. * *
  389. * INPUT: *
  390. * *
  391. * OUTPUT: *
  392. * *
  393. * WARNINGS: This is ignored if an orientation array is present. *
  394. * *
  395. * HISTORY: *
  396. * 06/28/2000 NH : Created. *
  397. *========================================================================*/
  398. unsigned char PointGroupClass::Get_Point_Orientation(void)
  399. {
  400. return DefaultPointOrientation;
  401. }
  402. /**************************************************************************
  403. * PointGroupClass::Set_Point_Frame -- Set default point frame. *
  404. * *
  405. * INPUT: *
  406. * *
  407. * OUTPUT: *
  408. * *
  409. * WARNINGS: This frame is ignored if an frame array is present. *
  410. * *
  411. * NOTE: No need to ensure value in valid range - it will be masked later.*
  412. * *
  413. * HISTORY: *
  414. * 06/28/2000 NH : Created. *
  415. *========================================================================*/
  416. void PointGroupClass::Set_Point_Frame(unsigned char frame)
  417. {
  418. DefaultPointFrame = frame;
  419. }
  420. /**************************************************************************
  421. * PointGroupClass::Get_Point_Frame -- Get default point frame. *
  422. * *
  423. * INPUT: *
  424. * *
  425. * OUTPUT: *
  426. * *
  427. * WARNINGS: This frame is ignored if an frame array is present. *
  428. * *
  429. * HISTORY: *
  430. * 06/28/2000 NH : Created. *
  431. *========================================================================*/
  432. unsigned char PointGroupClass::Get_Point_Frame(void)
  433. {
  434. return DefaultPointFrame;
  435. }
  436. /**************************************************************************
  437. * PointGroupClass::Set_Point_Mode -- Set point rendering method. *
  438. * *
  439. * INPUT: *
  440. * *
  441. * OUTPUT: *
  442. * *
  443. * WARNINGS: *
  444. * *
  445. * HISTORY: *
  446. * 11/17/1998 NH : Created. *
  447. *========================================================================*/
  448. void PointGroupClass::Set_Point_Mode(PointModeEnum mode)
  449. {
  450. PointMode = mode;
  451. }
  452. /**************************************************************************
  453. * PointGroupClass::Get_Point_Mode -- Get point rendering method. *
  454. * *
  455. * INPUT: *
  456. * *
  457. * OUTPUT: *
  458. * *
  459. * WARNINGS: *
  460. * *
  461. * HISTORY: *
  462. * 11/17/1998 NH : Created. *
  463. *========================================================================*/
  464. PointGroupClass::PointModeEnum PointGroupClass::Get_Point_Mode(void)
  465. {
  466. return PointMode;
  467. }
  468. /**************************************************************************
  469. * Set_Flag -- PointGroupClass::Set given flag to on or off. *
  470. * *
  471. * INPUT: *
  472. * *
  473. * OUTPUT: *
  474. * *
  475. * WARNINGS: *
  476. * *
  477. * HISTORY: *
  478. * 11/17/1998 NH : Created. *
  479. *========================================================================*/
  480. void PointGroupClass::Set_Flag(FlagsType flag, bool onoff)
  481. {
  482. if (onoff) Flags|=1<<flag;
  483. else
  484. Flags&=~(1<<flag);
  485. }
  486. /**************************************************************************
  487. * PointGroupClass::Get_Flag -- Get current value (on/off) of given flag. *
  488. * *
  489. * INPUT: *
  490. * *
  491. * OUTPUT: *
  492. * *
  493. * WARNINGS: *
  494. * *
  495. * HISTORY: *
  496. * 11/17/1998 NH : Created. *
  497. *========================================================================*/
  498. int PointGroupClass::Get_Flag(FlagsType flag)
  499. {
  500. return (Flags>>flag) & 0x1;
  501. }
  502. /**************************************************************************
  503. * PointGroupClass::Set_Texture -- Set texture used. *
  504. * *
  505. * INPUT: *
  506. * *
  507. * OUTPUT: *
  508. * *
  509. * WARNINGS: *
  510. * *
  511. * HISTORY: *
  512. * 11/17/1998 NH : Created. *
  513. * 02/08/2001 HY : Upgraded to DX8 *
  514. *========================================================================*/
  515. void PointGroupClass::Set_Texture(TextureClass* texture)
  516. {
  517. REF_PTR_SET(Texture,texture);
  518. }
  519. /**************************************************************************
  520. * PointGroupClass::Get_Texture -- Get texture used. *
  521. * *
  522. * INPUT: *
  523. * *
  524. * OUTPUT: *
  525. * *
  526. * WARNINGS: *
  527. * *
  528. * HISTORY: *
  529. * 11/17/1998 NH : Created. *
  530. * 02/08/2001 HY : Upgraded to DX8 *
  531. *========================================================================*/
  532. TextureClass * PointGroupClass::Get_Texture(void)
  533. {
  534. if (Texture) Texture->Add_Ref();
  535. return Texture;
  536. }
  537. /***********************************************************************************************
  538. * PointGroupClass::Peek_Texture -- Peeks texture *
  539. * *
  540. * *
  541. * *
  542. * *
  543. * INPUT: *
  544. * *
  545. * OUTPUT: *
  546. * *
  547. * WARNINGS: *
  548. * *
  549. * HISTORY: *
  550. * 4/12/2001 hy : Created. *
  551. *=============================================================================================*/
  552. TextureClass * PointGroupClass::Peek_Texture(void)
  553. {
  554. return Texture;
  555. }
  556. /**************************************************************************
  557. * PointGroupClass::Set_Shader -- Set shader used. *
  558. * *
  559. * INPUT: *
  560. * *
  561. * OUTPUT: *
  562. * *
  563. * WARNINGS: the primary gradient will be set to MODULATE/DISABLE in *
  564. * the shader depending on whether a color or alpha array was *
  565. * passed in Set_Point_Arrays. also, texturing will be *
  566. * enabled or disabled dependent on whether a non-NULL *
  567. * texture was set. *
  568. * these will override the primary gradient/texturing *
  569. * settings in the given shader. *
  570. * *
  571. * HISTORY: *
  572. * 11/17/1998 NH : Created. *
  573. * 02/08/2001 HY : Upgraded to DX8 *
  574. *========================================================================*/
  575. void PointGroupClass::Set_Shader(ShaderClass shader)
  576. {
  577. Shader = shader;
  578. }
  579. /**************************************************************************
  580. * PointGroupClass::Get_Shader -- Get shader used. *
  581. * *
  582. * INPUT: *
  583. * *
  584. * OUTPUT: *
  585. * *
  586. * WARNINGS: *
  587. * *
  588. * HISTORY: *
  589. * 11/17/1998 NH : Created. *
  590. * 02/08/2001 HY : Upgraded to DX8 *
  591. *========================================================================*/
  592. ShaderClass PointGroupClass::Get_Shader(void)
  593. {
  594. return Shader;
  595. }
  596. /**************************************************************************
  597. * PointGroupClass::Get_Frame_Row_Column_Count_Log2 -- what it says *
  598. * *
  599. * INPUT: *
  600. * *
  601. * OUTPUT: *
  602. * *
  603. * WARNINGS: *
  604. * *
  605. * HISTORY: *
  606. * 06/28/2000 NH : Created. *
  607. * 02/08/2001 HY : Upgraded to DX8 *
  608. *========================================================================*/
  609. unsigned char PointGroupClass::Get_Frame_Row_Column_Count_Log2(void)
  610. {
  611. return FrameRowColumnCountLog2;
  612. }
  613. /**************************************************************************
  614. * PointGroupClass::Set_Frame_Row_Column_Count_Log2 -- what it says. *
  615. * *
  616. * INPUT: *
  617. * *
  618. * OUTPUT: *
  619. * *
  620. * WARNINGS: *
  621. * *
  622. * HISTORY: *
  623. * 06/28/2000 NH : Created. *
  624. * 02/08/2001 HY : Upgraded to DX8 *
  625. *========================================================================*/
  626. void PointGroupClass::Set_Frame_Row_Column_Count_Log2(unsigned char frccl2)
  627. {
  628. FrameRowColumnCountLog2 = MIN(frccl2, 4);
  629. }
  630. /**************************************************************************
  631. * PointGroupClass::Get_Polygon_Count -- Get estimated polygon count. *
  632. * *
  633. * INPUT: *
  634. * *
  635. * OUTPUT: *
  636. * *
  637. * WARNINGS: *
  638. * *
  639. * HISTORY: *
  640. * 11/18/1998 NH : Created. *
  641. * 02/08/2001 HY : Upgraded to DX8 *
  642. *========================================================================*/
  643. int PointGroupClass::Get_Polygon_Count(void)
  644. {
  645. switch (PointMode) {
  646. case TRIS:
  647. case SCREENSPACE:
  648. return PointCount;
  649. break;
  650. case QUADS:
  651. return PointCount * 2;
  652. break;
  653. }
  654. WWASSERT(0);
  655. return 0;
  656. }
  657. /**************************************************************************
  658. * PointGroupClass::Render -- draw point group. *
  659. * *
  660. * INPUT: *
  661. * *
  662. * OUTPUT: *
  663. * *
  664. * WARNINGS: *
  665. * *
  666. * HISTORY: *
  667. * 12/10/1998 NH : Created. *
  668. * 02/08/2001 HY : Upgraded to DX8 *
  669. *========================================================================*/
  670. static SimpleVecClass<unsigned long> remap;
  671. void PointGroupClass::Render(RenderInfoClass &rinfo)
  672. {
  673. // NB: the winding for pointgroups is wrong, but we
  674. // are disabling culling for particles anyway
  675. Shader.Set_Cull_Mode(ShaderClass::CULL_MODE_DISABLE);
  676. // If no points, do nothing:
  677. if (PointCount == 0) return;
  678. WWASSERT(PointLoc && PointLoc->Get_Array());
  679. // Process texture reductions:
  680. // if (Texture) Texture->Process_Reduction();
  681. // Static arrays for intermediate calcs (never resized down, just up):
  682. static VectorClass<Vector3> compressed_loc; // point locations 'compressed' by APT
  683. static VectorClass<Vector4> compressed_diffuse; // point colors 'compressed' by APT
  684. static VectorClass<float> compressed_size; // point sizes 'compressed' by APT
  685. static VectorClass<unsigned char> compressed_orient; // point orientations 'compressed' by APT
  686. static VectorClass<unsigned char> compressed_frame; // point frames 'compressed' by APT
  687. static VectorClass<Vector3> transformed_loc; // transformed point locations
  688. // Pointers which point into existing buffers (member or static):
  689. Vector3 *current_loc = NULL;
  690. Vector4 *current_diffuse = NULL;
  691. float *current_size = NULL;
  692. unsigned char *current_orient = NULL;
  693. unsigned char *current_frame = NULL;
  694. // If there is a color or alpha array enable gradient in shader - otherwise disable.
  695. float value_255 = 0.9961f; //254 / 255
  696. bool default_white_opaque = ( DefaultPointColor.X > value_255 &&
  697. DefaultPointColor.Y > value_255 &&
  698. DefaultPointColor.Z > value_255 &&
  699. DefaultPointAlpha > value_255);
  700. // The reason we check for lack of texture here is that SR seems to render black triangles
  701. // rather than white triangles as would be expected) when there is no texture AND no gradient.
  702. if (PointDiffuse || !default_white_opaque || !Texture) {
  703. Shader.Set_Primary_Gradient(ShaderClass::GRADIENT_MODULATE);
  704. } else {
  705. Shader.Set_Primary_Gradient(ShaderClass::GRADIENT_DISABLE);
  706. }
  707. // If Texture is non-NULL enable texturing in shader - otherwise disable.
  708. if (Texture) {
  709. Shader.Set_Texturing(ShaderClass::TEXTURING_ENABLE);
  710. } else {
  711. Shader.Set_Texturing(ShaderClass::TEXTURING_DISABLE);
  712. }
  713. // If there is an active point table, use it to compress the point
  714. // locations/colors/alphas/sizes/orientations/frames.
  715. if (APT) {
  716. // Resize compressed result arrays if needed (2x guardband to prevent
  717. // frequent reallocations):
  718. if (compressed_loc.Length() < PointCount) {
  719. compressed_loc.Resize(PointCount * 2);
  720. }
  721. VectorProcessorClass::CopyIndexed(&compressed_loc[0],
  722. PointLoc->Get_Array(), APT->Get_Array(), PointCount);
  723. current_loc = &compressed_loc[0];
  724. if (PointDiffuse) {
  725. if (compressed_diffuse.Length() < PointCount) {
  726. compressed_diffuse.Resize(PointCount * 2);
  727. }
  728. VectorProcessorClass::CopyIndexed(&compressed_diffuse[0],
  729. PointDiffuse->Get_Array(), APT->Get_Array(), PointCount);
  730. current_diffuse = &compressed_diffuse[0];
  731. }
  732. if (PointSize) {
  733. if (compressed_size.Length() < PointCount) {
  734. compressed_size.Resize(PointCount * 2);
  735. }
  736. VectorProcessorClass::CopyIndexed(&compressed_size[0],
  737. PointSize->Get_Array(), APT->Get_Array(), PointCount);
  738. current_size = &compressed_size[0];
  739. }
  740. if (PointOrientation) {
  741. if (compressed_orient.Length() < PointCount) {
  742. compressed_orient.Resize(PointCount * 2);
  743. }
  744. VectorProcessorClass::CopyIndexed(&compressed_orient[0],
  745. PointOrientation->Get_Array(), APT->Get_Array(), PointCount);
  746. current_orient = &compressed_orient[0];
  747. }
  748. if (PointFrame) {
  749. if (compressed_frame.Length() < PointCount) {
  750. compressed_frame.Resize(PointCount * 2);
  751. }
  752. VectorProcessorClass::CopyIndexed(&compressed_frame[0],
  753. PointFrame->Get_Array(), APT->Get_Array(), PointCount);
  754. current_frame = &compressed_frame[0];
  755. }
  756. } else {
  757. current_loc = PointLoc->Get_Array();
  758. if (PointDiffuse) {
  759. current_diffuse = PointDiffuse->Get_Array();
  760. }
  761. if (PointSize) {
  762. current_size = PointSize->Get_Array();
  763. }
  764. if (PointOrientation) {
  765. current_orient = PointOrientation->Get_Array();
  766. }
  767. if (PointFrame) {
  768. current_frame = PointFrame->Get_Array();
  769. }
  770. }
  771. // Get the world and view matrices
  772. Matrix4 view;
  773. DX8Wrapper::Get_Transform(D3DTS_VIEW,view);
  774. // Transform the point locations from worldspace to camera space if needed
  775. // (i.e. if they are not already in camera space):
  776. if (Get_Flag(TRANSFORM)) {
  777. // Resize transformed location array if needed (2x guardband to prevent
  778. // frequent reallocations):
  779. if (transformed_loc.Length() < PointCount) {
  780. transformed_loc.Resize(PointCount * 2);
  781. }
  782. // Not using vector processor class because we are discarding w
  783. // Not using T&L in DX8 because we don't want DX8 to transform
  784. // 3 times per particle when we can do it once
  785. for (int i=0; i<PointCount; i++)
  786. {
  787. Vector4 result=view*current_loc[i];
  788. transformed_loc[i].X=result.X;
  789. transformed_loc[i].Y=result.Y;
  790. transformed_loc[i].Z=result.Z;
  791. }
  792. current_loc = &transformed_loc[0];
  793. } // if transform
  794. // Update the arrays with the offsets.
  795. int vnum, pnum;
  796. Update_Arrays(current_loc, current_diffuse, current_size, current_orient, current_frame,
  797. PointCount, PointLoc->Get_Count(), vnum, pnum);
  798. // the locations are now in view space
  799. // so set world and view matrices to identity and render
  800. Matrix4 identity(true);
  801. DX8Wrapper::Set_Transform(D3DTS_WORLD,identity);
  802. DX8Wrapper::Set_Transform(D3DTS_VIEW,identity);
  803. DX8Wrapper::Set_Material(PointMaterial);
  804. DX8Wrapper::Set_Shader(Shader);
  805. DX8Wrapper::Set_Texture(0,Texture);
  806. // Enable sorting if the primitives are translucent and alpha testing is not enabled.
  807. const bool sort = (Shader.Get_Dst_Blend_Func() != ShaderClass::DSTBLEND_ZERO) && (Shader.Get_Alpha_Test() == ShaderClass::ALPHATEST_DISABLE) && (WW3D::Is_Sorting_Enabled());
  808. IndexBufferClass *indexbuffer;
  809. int verticesperprimitive, current, delta;
  810. if (PointMode == QUADS) {
  811. verticesperprimitive = 2;
  812. indexbuffer = sort ? static_cast <IndexBufferClass*> (SortingQuads) : static_cast <IndexBufferClass*> (Quads);
  813. } else {
  814. verticesperprimitive = 3;
  815. indexbuffer = sort ? static_cast <IndexBufferClass*> (SortingTris) : static_cast <IndexBufferClass*> (Tris);
  816. }
  817. current = 0;
  818. while (current<vnum)
  819. {
  820. delta=MIN(vnum-current,MAX_VB_SIZE);
  821. DynamicVBAccessClass PointVerts (sort ? BUFFER_TYPE_DYNAMIC_SORTING : BUFFER_TYPE_DYNAMIC_DX8, dynamic_fvf_type, delta);
  822. // Copy in the data to the VB
  823. {
  824. DynamicVBAccessClass::WriteLockClass Lock(&PointVerts);
  825. int i;
  826. unsigned char *vb=(unsigned char*)Lock.Get_Formatted_Vertex_Array();
  827. const FVFInfoClass& fvfinfo=PointVerts.FVF_Info();
  828. for (i = current; i < current + delta; i++)
  829. {
  830. // Copy Locations
  831. *(Vector3*)(vb+fvfinfo.Get_Location_Offset())=VertexLoc[i];
  832. if (current_diffuse) {
  833. unsigned color=DX8Wrapper::Convert_Color_Clamp(VertexDiffuse[i]);
  834. *(unsigned int*)(vb+fvfinfo.Get_Diffuse_Offset())=color;
  835. }
  836. else
  837. *(unsigned int*)(vb+fvfinfo.Get_Diffuse_Offset())=
  838. DX8Wrapper::Convert_Color_Clamp(Vector4(DefaultPointColor[0],DefaultPointColor[1],DefaultPointColor[2],DefaultPointAlpha));
  839. *(Vector2*)(vb+fvfinfo.Get_Tex_Offset(0))=VertexUV[i];
  840. vb+=fvfinfo.Get_FVF_Size();
  841. }
  842. } // copy
  843. DX8Wrapper::Set_Index_Buffer (indexbuffer, 0);
  844. DX8Wrapper::Set_Vertex_Buffer (PointVerts);
  845. if (sort) {
  846. SortingRendererClass::Insert_Triangles (0, delta / verticesperprimitive, 0, delta);
  847. } else {
  848. DX8Wrapper::Draw_Triangles (0, delta / verticesperprimitive, 0, delta);
  849. }
  850. current+=delta;
  851. }
  852. // restore the matrices
  853. DX8Wrapper::Set_Transform(D3DTS_VIEW,view);
  854. }
  855. /**************************************************************************
  856. * PointGroupClass::Update_Arrays -- Update all arrays used in rendering *
  857. * *
  858. * INPUT: *
  859. * *
  860. * OUTPUT: *
  861. * *
  862. * WARNINGS: *
  863. * *
  864. * HISTORY: *
  865. * 11/17/1998 NH : Created. *
  866. *========================================================================*/
  867. void PointGroupClass::Update_Arrays(
  868. Vector3 *point_loc,
  869. Vector4 *point_diffuse,
  870. float *point_size,
  871. unsigned char *point_orientation,
  872. unsigned char *point_frame,
  873. int active_points,
  874. int total_points,
  875. int &vnum,
  876. int &pnum)
  877. {
  878. int verts_per_point = (PointMode == QUADS) ? 4 : 3;
  879. int polys_per_point = (PointMode == QUADS) ? 2 : 1;
  880. // total_vnum/pnum reflect the size of the point arrays passed to the
  881. // point group. These (instead of vnum/pnum, which reflect the number of
  882. // active points) are used for the resize logic - the idea is that these
  883. // numbers will vary less often than the active numbers.
  884. int total_vnum = verts_per_point * total_points;
  885. vnum = verts_per_point * active_points;
  886. pnum = polys_per_point * active_points;
  887. // Resize the arrays if they are too small. We only need to check the length of one array
  888. // since they always all have the same length.
  889. if (VertexLoc.Length() < total_vnum) {
  890. // Resize arrays (2x guardband to prevent frequent reallocations).
  891. VertexLoc.Resize(total_vnum * 2, false);
  892. VertexUV.Resize(total_vnum * 2, false);
  893. VertexDiffuse.Resize(total_vnum * 2, false);
  894. }
  895. int vert, i, j;
  896. /*
  897. ** Generate the vertex locations from the point locations (note that both are in camera space).
  898. ** Vertex locations depend on the point mode and the points' orientation and size
  899. */
  900. // This defines the loop we run: the LSB indicates whether there is a size override array, the
  901. // next bit indicates whether there is an orientation override array, and the higher bits
  902. // indicate the point mode.
  903. enum LoopSelectionEnum {
  904. TRIS_NOSIZE_NOORIENT = ((int)TRIS << 2) + 0,
  905. TRIS_SIZE_NOORIENT = ((int)TRIS << 2) + 1,
  906. TRIS_NOSIZE_ORIENT = ((int)TRIS << 2) + 2,
  907. TRIS_SIZE_ORIENT = ((int)TRIS << 2) + 3,
  908. QUADS_NOSIZE_NOORIENT = ((int)QUADS << 2) + 0,
  909. QUADS_SIZE_NOORIENT = ((int)QUADS << 2) + 1,
  910. QUADS_NOSIZE_ORIENT = ((int)QUADS << 2) + 2,
  911. QUADS_SIZE_ORIENT = ((int)QUADS << 2) + 3,
  912. SCREEN_NOSIZE_NOORIENT = ((int)SCREENSPACE << 2) + 0,
  913. SCREEN_SIZE_NOORIENT = ((int)SCREENSPACE << 2) + 1,
  914. SCREEN_NOSIZE_ORIENT = ((int)SCREENSPACE << 2) + 2,
  915. SCREEN_SIZE_ORIENT = ((int)SCREENSPACE << 2) + 3,
  916. };
  917. LoopSelectionEnum loop_sel = (LoopSelectionEnum)(((int)PointMode << 2) +
  918. (point_orientation ? 2 : 0) + (point_size ? 1 : 0));
  919. vert = 0;
  920. Vector3 *vertex_loc = &VertexLoc[0];
  921. switch (loop_sel) {
  922. case TRIS_NOSIZE_NOORIENT:
  923. {
  924. // Setup constant vertex offsets (since size and orientation are invariants)
  925. Vector3 scaled_offset[3];
  926. scaled_offset[0] = _TriVertexLocationOrientationTable[DefaultPointOrientation][0] * DefaultPointSize;
  927. scaled_offset[1] = _TriVertexLocationOrientationTable[DefaultPointOrientation][1] * DefaultPointSize;
  928. scaled_offset[2] = _TriVertexLocationOrientationTable[DefaultPointOrientation][2] * DefaultPointSize;
  929. // Add vertex offsets to point locations to get vertex locations
  930. for (i = 0; i < active_points; i++) {
  931. vertex_loc[vert + 0] = point_loc[i] + scaled_offset[0];
  932. vertex_loc[vert + 1] = point_loc[i] + scaled_offset[1];
  933. vertex_loc[vert + 2] = point_loc[i] + scaled_offset[2];
  934. vert += 3;
  935. }
  936. }
  937. break;
  938. case TRIS_SIZE_NOORIENT:
  939. {
  940. // Scale vertex offsets and add them to point locations to get vertex locations
  941. for (i = 0; i < active_points; i++) {
  942. vertex_loc[vert + 0] = point_loc[i] +
  943. _TriVertexLocationOrientationTable[DefaultPointOrientation][0] * point_size[i];
  944. vertex_loc[vert + 1] = point_loc[i] +
  945. _TriVertexLocationOrientationTable[DefaultPointOrientation][1] * point_size[i];
  946. vertex_loc[vert + 2] = point_loc[i] +
  947. _TriVertexLocationOrientationTable[DefaultPointOrientation][2] * point_size[i];
  948. vert += 3;
  949. }
  950. }
  951. break;
  952. case TRIS_NOSIZE_ORIENT:
  953. {
  954. // Scale vertex offsets and add them to point locations to get vertex locations
  955. for (i = 0; i < active_points; i++) {
  956. vertex_loc[vert + 0] = point_loc[i] +
  957. _TriVertexLocationOrientationTable[point_orientation[i]][0] * DefaultPointSize;
  958. vertex_loc[vert + 1] = point_loc[i] +
  959. _TriVertexLocationOrientationTable[point_orientation[i]][1] * DefaultPointSize;
  960. vertex_loc[vert + 2] = point_loc[i] +
  961. _TriVertexLocationOrientationTable[point_orientation[i]][2] * DefaultPointSize;
  962. vert += 3;
  963. }
  964. }
  965. break;
  966. case TRIS_SIZE_ORIENT:
  967. {
  968. // Scale vertex offsets and add them to point locations to get vertex locations
  969. for (i = 0; i < active_points; i++) {
  970. vertex_loc[vert + 0] = point_loc[i] +
  971. _TriVertexLocationOrientationTable[point_orientation[i]][0] * point_size[i];
  972. vertex_loc[vert + 1] = point_loc[i] +
  973. _TriVertexLocationOrientationTable[point_orientation[i]][1] * point_size[i];
  974. vertex_loc[vert + 2] = point_loc[i] +
  975. _TriVertexLocationOrientationTable[point_orientation[i]][2] * point_size[i];
  976. vert += 3;
  977. }
  978. }
  979. break;
  980. case QUADS_NOSIZE_NOORIENT:
  981. {
  982. // Setup constant vertex offsets (since size and orientation are invariants)
  983. Vector3 scaled_offset[4];
  984. scaled_offset[0] = _QuadVertexLocationOrientationTable[DefaultPointOrientation][0] * DefaultPointSize;
  985. scaled_offset[1] = _QuadVertexLocationOrientationTable[DefaultPointOrientation][1] * DefaultPointSize;
  986. scaled_offset[2] = _QuadVertexLocationOrientationTable[DefaultPointOrientation][2] * DefaultPointSize;
  987. scaled_offset[3] = _QuadVertexLocationOrientationTable[DefaultPointOrientation][3] * DefaultPointSize;
  988. // Add vertex offsets to point locations to get vertex locations
  989. for (i = 0; i < active_points; i++) {
  990. vertex_loc[vert + 0] = point_loc[i] + scaled_offset[0];
  991. vertex_loc[vert + 1] = point_loc[i] + scaled_offset[1];
  992. vertex_loc[vert + 2] = point_loc[i] + scaled_offset[2];
  993. vertex_loc[vert + 3] = point_loc[i] + scaled_offset[3];
  994. vert += 4;
  995. }
  996. }
  997. break;
  998. case QUADS_SIZE_NOORIENT:
  999. {
  1000. // Scale vertex offsets and add them to point locations to get vertex locations
  1001. for (i = 0; i < active_points; i++) {
  1002. vertex_loc[vert + 0] = point_loc[i] +
  1003. _QuadVertexLocationOrientationTable[DefaultPointOrientation][0] * point_size[i];
  1004. vertex_loc[vert + 1] = point_loc[i] +
  1005. _QuadVertexLocationOrientationTable[DefaultPointOrientation][1] * point_size[i];
  1006. vertex_loc[vert + 2] = point_loc[i] +
  1007. _QuadVertexLocationOrientationTable[DefaultPointOrientation][2] * point_size[i];
  1008. vertex_loc[vert + 3] = point_loc[i] +
  1009. _QuadVertexLocationOrientationTable[DefaultPointOrientation][3] * point_size[i];
  1010. vert += 4;
  1011. }
  1012. }
  1013. break;
  1014. case QUADS_NOSIZE_ORIENT:
  1015. {
  1016. // Scale vertex offsets and add them to point locations to get vertex locations
  1017. for (i = 0; i < active_points; i++) {
  1018. vertex_loc[vert + 0] = point_loc[i] +
  1019. _QuadVertexLocationOrientationTable[point_orientation[i]][0] * DefaultPointSize;
  1020. vertex_loc[vert + 1] = point_loc[i] +
  1021. _QuadVertexLocationOrientationTable[point_orientation[i]][1] * DefaultPointSize;
  1022. vertex_loc[vert + 2] = point_loc[i] +
  1023. _QuadVertexLocationOrientationTable[point_orientation[i]][2] * DefaultPointSize;
  1024. vertex_loc[vert + 3] = point_loc[i] +
  1025. _QuadVertexLocationOrientationTable[point_orientation[i]][3] * DefaultPointSize;
  1026. vert += 4;
  1027. }
  1028. }
  1029. break;
  1030. case QUADS_SIZE_ORIENT:
  1031. {
  1032. // Scale vertex offsets and add them to point locations to get vertex locations
  1033. for (i = 0; i < active_points; i++) {
  1034. vertex_loc[vert + 0] = point_loc[i] +
  1035. _QuadVertexLocationOrientationTable[point_orientation[i]][0] * point_size[i];
  1036. vertex_loc[vert + 1] = point_loc[i] +
  1037. _QuadVertexLocationOrientationTable[point_orientation[i]][1] * point_size[i];
  1038. vertex_loc[vert + 2] = point_loc[i] +
  1039. _QuadVertexLocationOrientationTable[point_orientation[i]][2] * point_size[i];
  1040. vertex_loc[vert + 3] = point_loc[i] +
  1041. _QuadVertexLocationOrientationTable[point_orientation[i]][3] * point_size[i];
  1042. vert += 4;
  1043. }
  1044. }
  1045. break;
  1046. // Orientations are ignored for screensize pointgroups
  1047. case SCREEN_NOSIZE_NOORIENT:
  1048. case SCREEN_NOSIZE_ORIENT:
  1049. {
  1050. // Offsets need to be scaled to the current screen resolution
  1051. // First find x and y scale factors (sizes in pixels need to be
  1052. // normalized to 2D cam viewplane of -1,-1 to 1,1)
  1053. int xres, yres, bitdepth;
  1054. bool windowed;
  1055. WW3D::Get_Render_Target_Resolution(xres, yres, bitdepth, windowed);
  1056. float x_scale = (VPXMax - VPXMin) / xres;
  1057. float y_scale = (VPYMax - VPYMin) / yres;
  1058. Vector3 scaled_locs[2][3];
  1059. for (int i = 0; i < 2; i++) {
  1060. for (int j = 0; j < 3; j++) {
  1061. scaled_locs[i][j].X = _ScreenspaceVertexLocationSizeTable[i][j].X * x_scale;
  1062. scaled_locs[i][j].Y = _ScreenspaceVertexLocationSizeTable[i][j].Y * y_scale;
  1063. scaled_locs[i][j].Z = _ScreenspaceVertexLocationSizeTable[i][j].Z;
  1064. }
  1065. }
  1066. // Add vertex offsets to point locations to get vertex locations
  1067. int size_idx = (DefaultPointSize <= 1.0f) ? 0 : 1;
  1068. for (i = 0; i < active_points; i++) {
  1069. vertex_loc[vert + 0] = point_loc[i] + scaled_locs[size_idx][0];
  1070. vertex_loc[vert + 1] = point_loc[i] + scaled_locs[size_idx][1];
  1071. vertex_loc[vert + 2] = point_loc[i] + scaled_locs[size_idx][2];
  1072. vert += 3;
  1073. }
  1074. }
  1075. break;
  1076. case SCREEN_SIZE_NOORIENT:
  1077. case SCREEN_SIZE_ORIENT:
  1078. {
  1079. // Offsets need to be scaled to the current screen resolution
  1080. // First find x and y scale factors (sizes in pixels need to be
  1081. // normalized to 2D cam viewplane of -1,-1 to 1,1)
  1082. int xres, yres, bitdepth;
  1083. bool windowed;
  1084. WW3D::Get_Render_Target_Resolution(xres, yres, bitdepth, windowed);
  1085. float x_scale = (VPXMax - VPXMin) / xres;
  1086. float y_scale = (VPYMax - VPYMin) / yres;
  1087. Vector3 scaled_locs[2][3];
  1088. for (int i = 0; i < 2; i++) {
  1089. for (int j = 0; j < 3; j++) {
  1090. scaled_locs[i][j].X = _ScreenspaceVertexLocationSizeTable[i][j].X * x_scale;
  1091. scaled_locs[i][j].Y = _ScreenspaceVertexLocationSizeTable[i][j].Y * y_scale;
  1092. scaled_locs[i][j].Z = _ScreenspaceVertexLocationSizeTable[i][j].Z;
  1093. }
  1094. }
  1095. // Add vertex offsets to point locations to get vertex locations
  1096. for (i = 0; i < active_points; i++) {
  1097. int size_idx = (point_size[i] <= 1.0f) ? 0 : 1;
  1098. vertex_loc[vert + 0] = point_loc[i] + scaled_locs[size_idx][0];
  1099. vertex_loc[vert + 1] = point_loc[i] + scaled_locs[size_idx][1];
  1100. vertex_loc[vert + 2] = point_loc[i] + scaled_locs[size_idx][2];
  1101. vert += 3;
  1102. }
  1103. }
  1104. break;
  1105. default:
  1106. WWASSERT(0);
  1107. break;
  1108. }
  1109. /*
  1110. ** Fill the UV vertex array
  1111. */
  1112. unsigned int frame_mask = ~(0xFFFFFFFF << (FrameRowColumnCountLog2 + FrameRowColumnCountLog2));// To ensure frames in range
  1113. if (point_frame) {
  1114. // Fill UV array according to frame override array:
  1115. Vector2 *vertex_uv = &VertexUV[0];
  1116. if (PointMode != QUADS) {
  1117. // Modes with three vertices per point:
  1118. Vector2 *uv_ptr = _TriVertexUVFrameTable[FrameRowColumnCountLog2];
  1119. int vert = 0;
  1120. for (int i = 0; i < active_points; i++) {
  1121. int uv_idx = (point_frame[i] & frame_mask) * 3;
  1122. vertex_uv[vert++] = uv_ptr[uv_idx + 0];
  1123. vertex_uv[vert++] = uv_ptr[uv_idx + 1];
  1124. vertex_uv[vert++] = uv_ptr[uv_idx + 2];
  1125. }
  1126. } else {
  1127. // Modes with four vertices per point:
  1128. Vector2 *uv_ptr = _QuadVertexUVFrameTable[FrameRowColumnCountLog2];
  1129. int vert = 0;
  1130. for (int i = 0; i < active_points; i++) {
  1131. int uv_idx = (point_frame[i] & frame_mask) * 4;
  1132. vertex_uv[vert++] = uv_ptr[uv_idx + 0];
  1133. vertex_uv[vert++] = uv_ptr[uv_idx + 1];
  1134. vertex_uv[vert++] = uv_ptr[uv_idx + 2];
  1135. vertex_uv[vert++] = uv_ptr[uv_idx + 3];
  1136. }
  1137. }
  1138. } else {
  1139. // Fill UV array according to frame state:
  1140. Vector2 *vertex_uv = &VertexUV[0];
  1141. if (PointMode != QUADS) {
  1142. // Modes with three vertices per point:
  1143. Vector2 *uv_ptr = _TriVertexUVFrameTable[FrameRowColumnCountLog2] + ((DefaultPointFrame & frame_mask) * 3);
  1144. int vert = 0;
  1145. for (int i = 0; i < active_points; i++) {
  1146. vertex_uv[vert++] = uv_ptr[0];
  1147. vertex_uv[vert++] = uv_ptr[1];
  1148. vertex_uv[vert++] = uv_ptr[2];
  1149. }
  1150. } else {
  1151. // Modes with four vertices per point:
  1152. Vector2 *uv_ptr = _QuadVertexUVFrameTable[FrameRowColumnCountLog2] + ((DefaultPointFrame & frame_mask) * 4);
  1153. int vert = 0;
  1154. for (int i = 0; i < active_points; i++) {
  1155. vertex_uv[vert++] = uv_ptr[0];
  1156. vertex_uv[vert++] = uv_ptr[1];
  1157. vertex_uv[vert++] = uv_ptr[2];
  1158. vertex_uv[vert++] = uv_ptr[3];
  1159. }
  1160. }
  1161. }
  1162. /*
  1163. ** If we have a point color array, fill the vertex diffuse array from it.
  1164. */
  1165. vert = 0;
  1166. if (point_diffuse) {
  1167. Vector4* vertex_color = &VertexDiffuse[0];
  1168. for (i = 0; i < active_points; i++) {
  1169. for (j = 0; j < verts_per_point; j++) {
  1170. vertex_color[vert + j] = point_diffuse[i];
  1171. }
  1172. vert += verts_per_point;
  1173. }
  1174. }
  1175. }
  1176. /**************************************************************************
  1177. * PointGroupClass::_Init -- Create static data. *
  1178. * *
  1179. * INPUT: *
  1180. * *
  1181. * OUTPUT: *
  1182. * *
  1183. * WARNINGS: *
  1184. * *
  1185. * HISTORY: *
  1186. * 06/28/2000 NH : Created. *
  1187. *========================================================================*/
  1188. void PointGroupClass::_Init(void)
  1189. {
  1190. int i, j;
  1191. /*
  1192. ** Fill vertex location orientation tables
  1193. */
  1194. // Unrotated locations
  1195. Vector3 tri_locs[3] = {
  1196. Vector3(0.0f, -2.0f, 0.0f),
  1197. Vector3(-1.732f, 1.0f, 0.0f),
  1198. Vector3(1.732f, 1.0f, 0.0f)
  1199. };
  1200. Vector3 quad_locs[4] = {
  1201. Vector3(-0.5f, 0.5f, 0.0f),
  1202. Vector3(-0.5f, -0.5f, 0.0f),
  1203. Vector3(0.5f, -0.5f, 0.0f),
  1204. Vector3(0.5f, 0.5f, 0.0f)
  1205. };
  1206. float angle = 0.0f; // In radians
  1207. float angle_step = (WWMATH_PI * 2.0f) / 256.0f; // In radians
  1208. for (i = 0; i < 256; i++) {
  1209. float c = WWMath::Fast_Cos(angle);
  1210. float s = WWMath::Fast_Sin(angle);
  1211. for (j = 0; j < 3; j++) {
  1212. _TriVertexLocationOrientationTable[i][j].X = tri_locs[j].X * c - tri_locs[j].Y * s;
  1213. _TriVertexLocationOrientationTable[i][j].Y = tri_locs[j].X * s + tri_locs[j].Y * c;
  1214. _TriVertexLocationOrientationTable[i][j].Z = tri_locs[j].Z;
  1215. }
  1216. for (j = 0; j < 4; j++) {
  1217. _QuadVertexLocationOrientationTable[i][j].X = quad_locs[j].X * c - quad_locs[j].Y * s;
  1218. _QuadVertexLocationOrientationTable[i][j].Y = quad_locs[j].X * s + quad_locs[j].Y * c;
  1219. _QuadVertexLocationOrientationTable[i][j].Z = quad_locs[j].Z;
  1220. }
  1221. angle += angle_step;
  1222. }
  1223. /*
  1224. ** Fill frame UV tables
  1225. */
  1226. // Unscaled / untranslated UVs
  1227. Vector2 tri_uvs[3] = {
  1228. Vector2(0.5f, 0.0f),
  1229. Vector2(0.0f, 0.866f),
  1230. Vector2(1.0f, 0.866f)
  1231. };
  1232. Vector2 quad_uvs[4] = {
  1233. Vector2(0.0f, 0.0f),
  1234. Vector2(0.0f, 1.0f),
  1235. Vector2(1.0f, 1.0f),
  1236. Vector2(1.0f, 0.0f)
  1237. };
  1238. for (i = 0; i < 5; i++) {
  1239. unsigned int rows = 1 << i;
  1240. unsigned int count = rows * rows;
  1241. Vector2 *tri_table = _TriVertexUVFrameTable[i] = new Vector2[count * 3];
  1242. Vector2 *quad_table = _QuadVertexUVFrameTable[i] = new Vector2[count * 4];
  1243. Vector2 corner(0.0f, 0.0f);
  1244. float scale = 1.0f / (float)rows;
  1245. int tri_idx = 0;
  1246. int quad_idx = 0;
  1247. for (unsigned int v = 0; v < rows; v++) {
  1248. for (unsigned int u = 0; u < rows; u++) {
  1249. tri_table[tri_idx++] = corner + (tri_uvs[0] * scale);
  1250. tri_table[tri_idx++] = corner + (tri_uvs[1] * scale);
  1251. tri_table[tri_idx++] = corner + (tri_uvs[2] * scale);
  1252. quad_table[quad_idx++] = corner + (quad_uvs[0] * scale);
  1253. quad_table[quad_idx++] = corner + (quad_uvs[1] * scale);
  1254. quad_table[quad_idx++] = corner + (quad_uvs[2] * scale);
  1255. quad_table[quad_idx++] = corner + (quad_uvs[3] * scale);
  1256. corner.X += scale;
  1257. }
  1258. corner.Y += scale;
  1259. corner.X = 0.0f;
  1260. }
  1261. }
  1262. // Create the IBs
  1263. Tris=NEW_REF(DX8IndexBufferClass,(MAX_TRI_IB_SIZE));
  1264. Quads=NEW_REF(DX8IndexBufferClass,(MAX_QUAD_IB_SIZE));
  1265. SortingTris=NEW_REF(SortingIndexBufferClass,(MAX_TRI_IB_SIZE));
  1266. SortingQuads=NEW_REF(SortingIndexBufferClass,(MAX_QUAD_IB_SIZE));
  1267. // Fill up the IBs
  1268. {
  1269. DX8IndexBufferClass::WriteLockClass locktris(Tris);
  1270. unsigned short *ib=locktris.Get_Index_Array();
  1271. for (i=0; i<MAX_TRI_IB_SIZE; i++) ib[i]=(unsigned short) i;
  1272. }
  1273. {
  1274. unsigned short vert=0;
  1275. DX8IndexBufferClass::WriteLockClass lockquads(Quads);
  1276. unsigned short *ib=lockquads.Get_Index_Array();
  1277. vert=0;
  1278. for (i=0; i<MAX_QUAD_IB_SIZE; i+=6)
  1279. {
  1280. ib[i]=vert;
  1281. ib[i+1]=vert+1;
  1282. ib[i+2]=vert+2;
  1283. ib[i+3]=vert+2;
  1284. ib[i+4]=vert+3;
  1285. ib[i+5]=vert;
  1286. vert+=4;
  1287. }
  1288. }
  1289. {
  1290. SortingIndexBufferClass::WriteLockClass locktris(SortingTris);
  1291. unsigned short *ib=locktris.Get_Index_Array();
  1292. for (i=0; i<MAX_TRI_IB_SIZE; i++) ib[i]=(unsigned short) i;
  1293. }
  1294. {
  1295. unsigned short vert=0;
  1296. SortingIndexBufferClass::WriteLockClass lockquads(SortingQuads);
  1297. unsigned short *ib=lockquads.Get_Index_Array();
  1298. vert=0;
  1299. for (i=0; i<MAX_QUAD_IB_SIZE; i+=6)
  1300. {
  1301. ib[i]=vert;
  1302. ib[i+1]=vert+1;
  1303. ib[i+2]=vert+2;
  1304. ib[i+3]=vert+2;
  1305. ib[i+4]=vert+3;
  1306. ib[i+5]=vert;
  1307. vert+=4;
  1308. }
  1309. }
  1310. PointMaterial=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
  1311. }
  1312. /**************************************************************************
  1313. * PointGroupClass::_Shutdown -- Destroy static data. *
  1314. * *
  1315. * INPUT: *
  1316. * *
  1317. * OUTPUT: *
  1318. * *
  1319. * WARNINGS: *
  1320. * *
  1321. * HISTORY: *
  1322. * 06/28/2000 NH : Created. *
  1323. *========================================================================*/
  1324. void PointGroupClass::_Shutdown(void)
  1325. {
  1326. for (int i = 0; i < 5; i++) {
  1327. delete [] _TriVertexUVFrameTable[i];
  1328. delete [] _QuadVertexUVFrameTable[i];
  1329. }
  1330. REF_PTR_RELEASE(PointMaterial);
  1331. REF_PTR_RELEASE(SortingQuads);
  1332. REF_PTR_RELEASE(SortingTris);
  1333. REF_PTR_RELEASE(Quads);
  1334. REF_PTR_RELEASE(Tris);
  1335. }