render2d.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  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 : WW3D *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/render2d.cpp $*
  25. * *
  26. * $Author:: Byon_g $Modtime:: 1/24/01 3:54p $*
  27. * *
  28. * $Revision:: 46 $*
  29. * *
  30. *---------------------------------------------------------------------------------------------*
  31. * Functions: *
  32. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  33. #include "render2d.h"
  34. #include "mutex.h"
  35. #include "ww3d.h"
  36. #include "refcount.h"
  37. #include "font3d.h"
  38. #include "rect.h"
  39. #include "texture.h"
  40. #include "matrix4.h"
  41. #include "matrix3d.h"
  42. #include "dx8wrapper.h"
  43. #include "dx8indexbuffer.h"
  44. #include "dx8vertexbuffer.h"
  45. #include "sortingrenderer.h"
  46. #include "vertmaterial.h"
  47. #include "dx8fvf.h"
  48. #include "wwprofile.h"
  49. #include "wwmemlog.h"
  50. #include "assetmgr.h"
  51. RectClass Render2DClass::ScreenResolution( 0,0,0,0 );
  52. /*
  53. ** Render2DClass
  54. */
  55. Render2DClass::Render2DClass( TextureClass* tex ) :
  56. CoordinateScale( 1, 1 ),
  57. CoordinateOffset( 0, 0 ),
  58. Texture(0),
  59. ZValue(0),
  60. IsHidden( false ),
  61. Indices(sizeof(PreAllocatedIndices)/sizeof(unsigned short),PreAllocatedIndices),
  62. Vertices(sizeof(PreAllocatedVertices)/sizeof(Vector2),PreAllocatedVertices),
  63. UVCoordinates(sizeof(PreAllocatedUVCoordinates)/sizeof(Vector2),PreAllocatedUVCoordinates),
  64. Colors(sizeof(PreAllocatedColors)/sizeof(unsigned long),PreAllocatedColors)
  65. {
  66. Set_Texture( tex );
  67. Shader = Get_Default_Shader();
  68. return ;
  69. }
  70. Render2DClass::~Render2DClass()
  71. {
  72. REF_PTR_RELEASE(Texture);
  73. }
  74. void Render2DClass::Set_Screen_Resolution( const RectClass & screen )
  75. {
  76. ScreenResolution = screen;
  77. #if 0
  78. // Fool into pixel doubling - Byon..
  79. if ( screen.Width() >= 1280 ) {
  80. ScreenResolution.Scale( 0.5f );
  81. }
  82. // ScreenResolution = RectClass( 0, 0, 800, 600 );
  83. #endif
  84. }
  85. ShaderClass
  86. Render2DClass::Get_Default_Shader( void )
  87. {
  88. ShaderClass shader;
  89. shader.Set_Depth_Mask( ShaderClass::DEPTH_WRITE_DISABLE );
  90. shader.Set_Depth_Compare( ShaderClass::PASS_ALWAYS );
  91. shader.Set_Dst_Blend_Func( ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA );
  92. shader.Set_Src_Blend_Func( ShaderClass::SRCBLEND_SRC_ALPHA );
  93. shader.Set_Fog_Func( ShaderClass::FOG_DISABLE );
  94. shader.Set_Primary_Gradient( ShaderClass::GRADIENT_MODULATE );
  95. shader.Set_Texturing( ShaderClass::TEXTURING_ENABLE );
  96. return shader;
  97. }
  98. void Render2DClass::Reset(void)
  99. {
  100. Vertices.Reset_Active();
  101. UVCoordinates.Reset_Active();
  102. Colors.Reset_Active();
  103. Indices.Reset_Active();
  104. Update_Bias(); // Keep the bias updated
  105. }
  106. void Render2DClass::Set_Texture(TextureClass* tex)
  107. {
  108. REF_PTR_SET(Texture,tex);
  109. }
  110. void Render2DClass::Set_Texture( const char * filename)
  111. {
  112. TextureClass * tex = WW3DAssetManager::Get_Instance()->Get_Texture( filename, TextureClass::MIP_LEVELS_1 );
  113. Set_Texture( tex );
  114. if ( tex != NULL ) {
  115. SET_REF_OWNER( tex );
  116. tex->Release_Ref();
  117. }
  118. }
  119. void Render2DClass::Enable_Alpha(bool b)
  120. {
  121. if (b) {
  122. Shader.Set_Dst_Blend_Func( ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA );
  123. Shader.Set_Src_Blend_Func( ShaderClass::SRCBLEND_SRC_ALPHA );
  124. }
  125. else {
  126. Shader.Set_Src_Blend_Func( ShaderClass::SRCBLEND_ONE);
  127. Shader.Set_Dst_Blend_Func( ShaderClass::DSTBLEND_ZERO );
  128. }
  129. }
  130. void Render2DClass::Enable_Additive(bool b)
  131. {
  132. if (b) {
  133. Shader.Set_Dst_Blend_Func( ShaderClass::DSTBLEND_ONE );
  134. Shader.Set_Src_Blend_Func( ShaderClass::SRCBLEND_ONE );
  135. }
  136. else {
  137. Shader.Set_Src_Blend_Func( ShaderClass::SRCBLEND_ONE);
  138. Shader.Set_Dst_Blend_Func( ShaderClass::DSTBLEND_ZERO );
  139. }
  140. }
  141. void Render2DClass::Enable_Texturing(bool b)
  142. {
  143. if (b) {
  144. Shader.Set_Texturing( ShaderClass::TEXTURING_ENABLE );
  145. }
  146. else {
  147. Shader.Set_Texturing( ShaderClass::TEXTURING_DISABLE );
  148. }
  149. }
  150. void Render2DClass::Set_Coordinate_Range( const RectClass & range )
  151. {
  152. // default range is (-1,1)-(1,-1)
  153. CoordinateScale.X = 2 / range.Width();
  154. CoordinateScale.Y = -2 / range.Height();
  155. CoordinateOffset.X = -(CoordinateScale.X * range.Left) - 1;
  156. CoordinateOffset.Y = -(CoordinateScale.Y * range.Top) + 1;
  157. Update_Bias();
  158. }
  159. void Render2DClass::Update_Bias( void )
  160. {
  161. BiasedCoordinateOffset = CoordinateOffset;
  162. if ( WW3D::Is_Screen_UV_Biased() ) { // Global bais setting
  163. Vector2 bais_add( -0.5f ,-0.5f ); // offset by -0.5,-0.5 in pixels
  164. // Convert from pixels to (-1,1)-(1,-1) units
  165. bais_add.X = bais_add.X / (Get_Screen_Resolution().Width() * 0.5f);
  166. bais_add.Y = bais_add.Y / (Get_Screen_Resolution().Height() * -0.5f);
  167. BiasedCoordinateOffset += bais_add;
  168. }
  169. }
  170. #if 0
  171. Vector2 Render2DClass::Convert_Vert( const Vector2 & v )
  172. {
  173. Vector2 out;
  174. // Convert to (-1,1)-(1,-1)
  175. out.X = v.X * CoordinateScale.X + CoordinateOffset.X;
  176. out.Y = v.Y * CoordinateScale.Y + CoordinateOffset.Y;
  177. // Convert to pixels
  178. out.X = (out.X + 1.0f) * (Get_Screen_Resolution().Width() * 0.5f);
  179. out.Y = (out.Y - 1.0f) * (Get_Screen_Resolution().Height() * -0.5f);
  180. // Round to nearest pixel
  181. out.X = WWMath::Floor( out.X + 0.5f );
  182. out.Y = WWMath::Floor( out.Y + 0.5f );
  183. // Bias
  184. if ( WW3D::Is_Screen_UV_Biased() ) { // Global bais setting
  185. out.X -= 0.5f;
  186. out.Y -= 0.5f;
  187. }
  188. // Convert back to (-1,1)-(1,-1)
  189. out.X = out.X / (Get_Screen_Resolution().Width() * 0.5f) - 1.0f;
  190. out.Y = out.Y / (Get_Screen_Resolution().Height() * -0.5f) + 1.0f;
  191. return out;
  192. }
  193. #else
  194. /*
  195. ** Convert Vert must convert from the convention defined by Set_Coordinate_Range
  196. ** into the convention (-1,1)-(1,-1), which is needed by the renderer.
  197. // NOPE ** In addition, it rounds all coordinates off to the nearest pixel
  198. ** Also, it offsets the coordinates as need for Screen_UV_Bias
  199. */
  200. void Render2DClass::Convert_Vert( Vector2 & vert_out, const Vector2 & vert_in )
  201. {
  202. // Convert to (-1,1)-(1,-1)
  203. vert_out.X = vert_in.X * CoordinateScale.X + BiasedCoordinateOffset.X;
  204. vert_out.Y = vert_in.Y * CoordinateScale.Y + BiasedCoordinateOffset.Y;
  205. }
  206. void Render2DClass::Convert_Vert( Vector2 & vert_out, float x_in, float y_in )
  207. {
  208. // Convert to (-1,1)-(1,-1)
  209. vert_out.X = x_in * CoordinateScale.X + BiasedCoordinateOffset.X;
  210. vert_out.Y = y_in * CoordinateScale.Y + BiasedCoordinateOffset.Y;
  211. }
  212. #endif
  213. void Render2DClass::Move( const Vector2 & move ) // Move all verts
  214. {
  215. Vector2 scaled_move;
  216. scaled_move.X = move.X * CoordinateScale.X;
  217. scaled_move.Y = move.Y * CoordinateScale.Y;
  218. for ( int i = 0; i < Vertices.Count(); i++ ) {
  219. Vertices[i] += scaled_move;
  220. }
  221. }
  222. void Render2DClass::Force_Alpha( float alpha ) // Force all alphas
  223. {
  224. unsigned long a = (unsigned)(WWMath::Clamp( alpha, 0, 1 ) * 255.0f);
  225. a <<= 24;
  226. for ( int i = 0; i < Colors.Count(); i++ ) {
  227. Colors[i] = (Colors[i] & 0x00FFFFFF) | a;
  228. }
  229. }
  230. void Render2DClass::Force_Color( int color ) // Force all alphas
  231. {
  232. for ( int i = 0; i < Colors.Count(); i++ ) {
  233. Colors[i] = color;
  234. }
  235. }
  236. /*
  237. ** Internal Add Quad Elements
  238. ** Caller must mutex lock
  239. */
  240. void Render2DClass::Internal_Add_Quad_Vertices( const Vector2 & v0, const Vector2 & v1, const Vector2 & v2, const Vector2 & v3 )
  241. {
  242. Convert_Vert( *Vertices.Uninitialized_Add(), v0 );
  243. Convert_Vert( *Vertices.Uninitialized_Add(), v1 );
  244. Convert_Vert( *Vertices.Uninitialized_Add(), v2 );
  245. Convert_Vert( *Vertices.Uninitialized_Add(), v3 );
  246. }
  247. void Render2DClass::Internal_Add_Quad_Vertices( const RectClass & screen )
  248. {
  249. Convert_Vert( *Vertices.Uninitialized_Add(), screen.Left, screen.Top );
  250. Convert_Vert( *Vertices.Uninitialized_Add(), screen.Left, screen.Bottom );
  251. Convert_Vert( *Vertices.Uninitialized_Add(), screen.Right, screen.Top );
  252. Convert_Vert( *Vertices.Uninitialized_Add(), screen.Right, screen.Bottom );
  253. }
  254. void Render2DClass::Internal_Add_Quad_UVs( const RectClass & uv )
  255. {
  256. Vector2* uvs;
  257. uvs=UVCoordinates.Uninitialized_Add();
  258. uvs->X = uv.Left; uvs->Y = uv.Top;
  259. uvs=UVCoordinates.Uninitialized_Add();
  260. uvs->X = uv.Left; uvs->Y = uv.Bottom;
  261. uvs=UVCoordinates.Uninitialized_Add();
  262. uvs->X = uv.Right; uvs->Y = uv.Top;
  263. uvs=UVCoordinates.Uninitialized_Add();
  264. uvs->X = uv.Right; uvs->Y = uv.Bottom;
  265. }
  266. void Render2DClass::Internal_Add_Quad_Colors( unsigned long color )
  267. {
  268. unsigned long* colors;
  269. colors=Colors.Uninitialized_Add();
  270. *colors=color;
  271. colors=Colors.Uninitialized_Add();
  272. *colors=color;
  273. colors=Colors.Uninitialized_Add();
  274. *colors=color;
  275. colors=Colors.Uninitialized_Add();
  276. *colors=color;
  277. }
  278. void Render2DClass::Internal_Add_Quad_VColors( unsigned long color1, unsigned long color2 )
  279. {
  280. unsigned long* colors;
  281. colors=Colors.Uninitialized_Add();
  282. *colors=color1;
  283. colors=Colors.Uninitialized_Add();
  284. *colors=color2;
  285. colors=Colors.Uninitialized_Add();
  286. *colors=color1;
  287. colors=Colors.Uninitialized_Add();
  288. *colors=color2;
  289. }
  290. void Render2DClass::Internal_Add_Quad_HColors( unsigned long color1, unsigned long color2 )
  291. {
  292. unsigned long* colors;
  293. colors=Colors.Uninitialized_Add();
  294. *colors=color1;
  295. colors=Colors.Uninitialized_Add();
  296. *colors=color1;
  297. colors=Colors.Uninitialized_Add();
  298. *colors=color2;
  299. colors=Colors.Uninitialized_Add();
  300. *colors=color2;
  301. }
  302. void Render2DClass::Internal_Add_Quad_Indicies( int start_vert_index, bool backfaced )
  303. {
  304. unsigned short * indices;
  305. if (backfaced ^ (CoordinateScale.X * CoordinateScale.Y > 0)) {
  306. indices=Indices.Uninitialized_Add();
  307. *indices = start_vert_index + 1;
  308. indices=Indices.Uninitialized_Add();
  309. *indices = start_vert_index + 0;
  310. indices=Indices.Uninitialized_Add();
  311. *indices = start_vert_index + 2;
  312. indices=Indices.Uninitialized_Add();
  313. *indices = start_vert_index + 1;
  314. indices=Indices.Uninitialized_Add();
  315. *indices = start_vert_index + 2;
  316. indices=Indices.Uninitialized_Add();
  317. *indices = start_vert_index + 3;
  318. } else {
  319. indices=Indices.Uninitialized_Add();
  320. *indices = start_vert_index + 0;
  321. indices=Indices.Uninitialized_Add();
  322. *indices = start_vert_index + 1;
  323. indices=Indices.Uninitialized_Add();
  324. *indices = start_vert_index + 2;
  325. indices=Indices.Uninitialized_Add();
  326. *indices = start_vert_index + 2;
  327. indices=Indices.Uninitialized_Add();
  328. *indices = start_vert_index + 1;
  329. indices=Indices.Uninitialized_Add();
  330. *indices = start_vert_index + 3;
  331. }
  332. }
  333. void Render2DClass::Add_Quad( const Vector2 & v0, const Vector2 & v1, const Vector2 & v2, const Vector2 & v3, const RectClass & uv, unsigned long color )
  334. {
  335. Internal_Add_Quad_Indicies( Vertices.Count() );
  336. Internal_Add_Quad_Vertices( v0, v1, v2, v3 );
  337. Internal_Add_Quad_UVs( uv );
  338. Internal_Add_Quad_Colors( color );
  339. }
  340. void Render2DClass::Add_Quad_Backfaced( const Vector2 & v0, const Vector2 & v1, const Vector2 & v2, const Vector2 & v3, const RectClass & uv, unsigned long color )
  341. {
  342. Internal_Add_Quad_Indicies( Vertices.Count(), true );
  343. Internal_Add_Quad_Vertices( v0, v1, v2, v3 );
  344. Internal_Add_Quad_UVs( uv );
  345. Internal_Add_Quad_Colors( color );
  346. }
  347. void Render2DClass::Add_Quad_VGradient( const RectClass & screen, unsigned long top_color, unsigned long bottom_color )
  348. {
  349. Internal_Add_Quad_Indicies( Vertices.Count() );
  350. Internal_Add_Quad_Vertices( screen );
  351. Internal_Add_Quad_UVs( RectClass( 0,0,1,1 ) );
  352. Internal_Add_Quad_VColors( top_color, bottom_color );
  353. }
  354. void Render2DClass::Add_Quad_HGradient( const RectClass & screen, unsigned long left_color, unsigned long right_color )
  355. {
  356. Internal_Add_Quad_Indicies( Vertices.Count() );
  357. Internal_Add_Quad_Vertices( screen );
  358. Internal_Add_Quad_UVs( RectClass( 0,0,1,1 ) );
  359. Internal_Add_Quad_HColors( left_color, right_color );
  360. }
  361. void Render2DClass::Add_Quad( const RectClass & screen, const RectClass & uv, unsigned long color )
  362. {
  363. Internal_Add_Quad_Indicies( Vertices.Count() );
  364. Internal_Add_Quad_Vertices( screen );
  365. Internal_Add_Quad_UVs( uv );
  366. Internal_Add_Quad_Colors( color );
  367. }
  368. void Render2DClass::Add_Quad( const Vector2 & v0, const Vector2 & v1, const Vector2 & v2, const Vector2 & v3, unsigned long color )
  369. {
  370. Internal_Add_Quad_Indicies( Vertices.Count() );
  371. Internal_Add_Quad_Vertices( v0, v1, v2, v3 );
  372. Internal_Add_Quad_UVs( RectClass( 0,0,1,1 ) );
  373. Internal_Add_Quad_Colors( color );
  374. }
  375. void Render2DClass::Add_Quad( const RectClass & screen, unsigned long color )
  376. {
  377. Internal_Add_Quad_Indicies( Vertices.Count() );
  378. Internal_Add_Quad_Vertices( screen );
  379. Internal_Add_Quad_UVs( RectClass( 0,0,1,1 ) );
  380. Internal_Add_Quad_Colors( color );
  381. }
  382. /*
  383. ** Add Tri
  384. */
  385. void Render2DClass::Add_Tri( const Vector2 & v0, const Vector2 & v1, const Vector2 & v2, const Vector2 & uv0, const Vector2 & uv1, const Vector2 & uv2, unsigned long color )
  386. {
  387. int old_vert_count = Vertices.Count();
  388. // Add the verticies (translated to new coordinates)
  389. #if 0
  390. Vertices.Add( Convert_Vert( v0 ), new_vert_count );
  391. Vertices.Add( Convert_Vert( v1 ), new_vert_count );
  392. Vertices.Add( Convert_Vert( v2 ), new_vert_count );
  393. #else
  394. Convert_Vert( *Vertices.Uninitialized_Add(), v0 );
  395. Convert_Vert( *Vertices.Uninitialized_Add(), v1 );
  396. Convert_Vert( *Vertices.Uninitialized_Add(), v2 );
  397. #endif
  398. // Add the uv coordinates
  399. *UVCoordinates.Uninitialized_Add()=uv0;
  400. *UVCoordinates.Uninitialized_Add()=uv1;
  401. *UVCoordinates.Uninitialized_Add()=uv2;
  402. // Add the colors
  403. *Colors.Uninitialized_Add()=color;
  404. *Colors.Uninitialized_Add()=color;
  405. *Colors.Uninitialized_Add()=color;
  406. // Add the faces
  407. *Indices.Uninitialized_Add()=old_vert_count + 0;
  408. *Indices.Uninitialized_Add()=old_vert_count + 1;
  409. *Indices.Uninitialized_Add()=old_vert_count + 2;
  410. }
  411. void Render2DClass::Add_Line( const Vector2 & a, const Vector2 & b, float width, unsigned long color )
  412. {
  413. Add_Line( a, b, width, RectClass( 0,0,1,1 ), color );
  414. }
  415. void Render2DClass::Add_Line( const Vector2 & a, const Vector2 & b, float width, const RectClass & uv, unsigned long color )
  416. {
  417. Vector2 corner_offset = a - b; // get line relative to b
  418. float temp = corner_offset.X; // Rotate 90
  419. corner_offset.X = corner_offset.Y;
  420. corner_offset.Y = -temp;
  421. corner_offset.Normalize(); // scale to length width/2
  422. corner_offset *= width / 2;
  423. Add_Quad( a - corner_offset, a + corner_offset, b - corner_offset, b + corner_offset, uv, color );
  424. }
  425. void Render2DClass::Add_Rect( const RectClass & rect, float border_width, uint32 border_color, uint32 fill_color )
  426. {
  427. //
  428. // First add the outline
  429. //
  430. Add_Outline( rect, border_width, border_color );
  431. //
  432. // Next, fill the contents
  433. //
  434. RectClass fill_rect = rect;
  435. fill_rect.Right -= border_width;
  436. fill_rect.Bottom -= border_width;
  437. Add_Quad (fill_rect, fill_color);
  438. return ;
  439. }
  440. void Render2DClass::Add_Outline( const RectClass & rect, float width, unsigned long color )
  441. {
  442. Add_Outline( rect, width, RectClass( 0,0,1,1 ), color );
  443. }
  444. void Render2DClass::Add_Outline( const RectClass & rect, float width, const RectClass & uv, unsigned long color )
  445. {
  446. //
  447. // Pretty straight forward, simply add the four side of the rectangle as lines.
  448. //
  449. Add_Line (Vector2 (rect.Left, rect.Bottom), Vector2 (rect.Left, rect.Top - 1), width, uv, color);
  450. Add_Line (Vector2 (rect.Left, rect.Top), Vector2 (rect.Right, rect.Top), width, uv, color);
  451. Add_Line (Vector2 (rect.Right, rect.Top), Vector2 (rect.Right, rect.Bottom), width, uv, color);
  452. Add_Line (Vector2 (rect.Right, rect.Bottom), Vector2 (rect.Left - 1, rect.Bottom), width, uv, color);
  453. }
  454. void Render2DClass::Render(void)
  455. {
  456. if ( !Indices.Count() || IsHidden) {
  457. return;
  458. }
  459. // save the view and projection matrices since we're nuking them
  460. Matrix4 view,proj;
  461. Matrix4 identity(true);
  462. DX8Wrapper::Get_Transform(D3DTS_VIEW,view);
  463. DX8Wrapper::Get_Transform(D3DTS_PROJECTION,proj);
  464. //
  465. // Configure the viewport for entire screen
  466. //
  467. int width, height, bits;
  468. bool windowed;
  469. WW3D::Get_Device_Resolution( width, height, bits, windowed );
  470. D3DVIEWPORT8 vp = { 0 };
  471. vp.X = 0;
  472. vp.Y = 0;
  473. vp.Width = width;
  474. vp.Height = height;
  475. vp.MinZ = 0;
  476. vp.MaxZ = 1;
  477. DX8Wrapper::Set_Viewport(&vp);
  478. DX8Wrapper::Set_Shader(Shader);
  479. DX8Wrapper::Set_Texture(0,Texture);
  480. VertexMaterialClass *vm=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
  481. DX8Wrapper::Set_Material(vm);
  482. REF_PTR_RELEASE(vm);
  483. DX8Wrapper::Set_World_Identity();
  484. DX8Wrapper::Set_View_Identity();
  485. DX8Wrapper::Set_Transform(D3DTS_PROJECTION,identity);
  486. DynamicVBAccessClass vb(BUFFER_TYPE_DYNAMIC_DX8,dynamic_fvf_type,Vertices.Count());
  487. {
  488. DynamicVBAccessClass::WriteLockClass Lock(&vb);
  489. const FVFInfoClass &fi=vb.FVF_Info();
  490. unsigned char *va=(unsigned char*)Lock.Get_Formatted_Vertex_Array();
  491. int i;
  492. for (i=0; i<Vertices.Count(); i++)
  493. {
  494. Vector3 temp(Vertices[i].X,Vertices[i].Y,ZValue);
  495. *(Vector3*)(va+fi.Get_Location_Offset())=temp;
  496. *(unsigned int*)(va+fi.Get_Diffuse_Offset())=Colors[i];
  497. *(Vector2*)(va+fi.Get_Tex_Offset(0))=UVCoordinates[i];
  498. va+=fi.Get_FVF_Size();
  499. }
  500. }
  501. DynamicIBAccessClass ib(BUFFER_TYPE_DYNAMIC_DX8,Indices.Count());
  502. {
  503. DynamicIBAccessClass::WriteLockClass Lock(&ib);
  504. unsigned short *mem=Lock.Get_Index_Array();
  505. for (int i=0; i<Indices.Count(); i++)
  506. mem[i]=Indices[i];
  507. }
  508. DX8Wrapper::Set_Vertex_Buffer(vb);
  509. DX8Wrapper::Set_Index_Buffer(ib,0);
  510. DX8Wrapper::Draw_Triangles(0,Indices.Count()/3,0,Vertices.Count());
  511. DX8Wrapper::Set_Transform(D3DTS_VIEW,view);
  512. DX8Wrapper::Set_Transform(D3DTS_PROJECTION,proj);
  513. }
  514. /*
  515. ** Render2DTextClass
  516. */
  517. Render2DTextClass::Render2DTextClass(Font3DInstanceClass *font) :
  518. Location(0.0f,0.0f),
  519. Cursor(0.0f,0.0f),
  520. Font(NULL),
  521. WrapWidth(0),
  522. ClipRect(0, 0, 0, 0),
  523. IsClippedEnabled(false)
  524. {
  525. Set_Coordinate_Range( RectClass( -320, -240, 320, 240 ) );
  526. Set_Font( font );
  527. Reset();
  528. }
  529. Render2DTextClass::~Render2DTextClass()
  530. {
  531. REF_PTR_RELEASE(Font);
  532. }
  533. void Render2DTextClass::Reset(void)
  534. {
  535. Render2DClass::Reset();
  536. Cursor = Location;
  537. WrapWidth = 0;
  538. DrawExtents = RectClass( 0,0,0,0 );
  539. TotalExtents = RectClass( 0,0,0,0 );
  540. ClipRect.Set (0, 0, 0, 0);
  541. IsClippedEnabled = false;
  542. }
  543. void Render2DTextClass::Set_Font( Font3DInstanceClass *font )
  544. {
  545. REF_PTR_SET(Font,font);
  546. if ( Font != NULL ) {
  547. Set_Texture( Font->Peek_Texture() );
  548. #define BLOCK_CHAR 0
  549. BlockUV = Font->Char_UV( BLOCK_CHAR );
  550. // Inset it a bit to be sure we have no edge problems
  551. BlockUV.Inflate( Vector2(-BlockUV.Width()/4, -BlockUV.Height()/4) );
  552. }
  553. }
  554. /*
  555. **
  556. */
  557. void Render2DTextClass::Draw_Char( WCHAR ch, unsigned long color )
  558. {
  559. float char_spacing = Font->Char_Spacing( ch );
  560. float char_height = Font->Char_Height();
  561. //
  562. // Check to see if this character is clipped
  563. //
  564. bool is_clipped = false;
  565. if ( IsClippedEnabled &&
  566. (Cursor.X < ClipRect.Left ||
  567. Cursor.X + char_spacing > ClipRect.Right ||
  568. Cursor.Y < ClipRect.Top ||
  569. Cursor.Y + char_height > ClipRect.Bottom))
  570. {
  571. is_clipped = true;
  572. }
  573. if ( ch != (WCHAR)' ' && !is_clipped ) {
  574. RectClass screen( Cursor.X, Cursor.Y, Cursor.X + Font->Char_Width(ch), Cursor.Y + char_height );
  575. Internal_Add_Quad_Indicies( Vertices.Count() );
  576. Internal_Add_Quad_Vertices( screen );
  577. Internal_Add_Quad_UVs( Font->Char_UV( ch ) );
  578. Internal_Add_Quad_Colors( color );
  579. DrawExtents += screen;
  580. TotalExtents += screen;
  581. }
  582. Cursor.X += char_spacing;
  583. }
  584. void Render2DTextClass::Draw_Text( const char * text, unsigned long color )
  585. {
  586. WWMEMLOG(MEM_GEOMETRY);
  587. WideStringClass wide(0,true);
  588. wide.Convert_From( text );
  589. Draw_Text( wide, color );
  590. }
  591. void Render2DTextClass::Draw_Text( const WCHAR * text, unsigned long color )
  592. {
  593. WWMEMLOG(MEM_GEOMETRY);
  594. // Reset the Extents
  595. DrawExtents = RectClass( Location, Location );
  596. if ( TotalExtents.Width() == 0 ) {
  597. TotalExtents = RectClass( Location, Location );
  598. }
  599. while (*text) {
  600. WCHAR ch = *text++;
  601. // Check to see if we need to move to a newline or not
  602. bool wrap = ( ch == (WCHAR)'\n' );
  603. // if the current char is a space, and the next word length puts us past our Width, wrap
  604. if ( ch == (WCHAR)' ' && WrapWidth > 0 ) {
  605. const WCHAR * word = text;
  606. float word_width = Font->Char_Spacing(ch);
  607. while ( (*word != (WCHAR)0) && (*word > (WCHAR)' ') ) {
  608. word_width += Font->Char_Spacing(*word++);
  609. }
  610. wrap = ( (Cursor.X + word_width) >= (Location.X + WrapWidth) );
  611. }
  612. if ( wrap ) {
  613. Cursor.Y += Font->Char_Height();
  614. Cursor.X = Location.X;
  615. } else {
  616. // Draw char at cursor, update cursor and extents
  617. Draw_Char( ch, color );
  618. }
  619. }
  620. }
  621. void Render2DTextClass::Draw_Block( const RectClass & screen, unsigned long color )
  622. {
  623. Internal_Add_Quad_Indicies( Vertices.Count() );
  624. Internal_Add_Quad_Vertices( screen );
  625. Internal_Add_Quad_UVs( BlockUV );
  626. Internal_Add_Quad_Colors( color );
  627. TotalExtents += screen;
  628. }
  629. Vector2 Render2DTextClass::Get_Text_Extents( const WCHAR * text )
  630. {
  631. Vector2 extent (0, Font->Char_Height());
  632. if (text) {
  633. while (*text) {
  634. WCHAR ch = *text++;
  635. if ( ch != (WCHAR)'\n' ) {
  636. extent.X += Font->Char_Spacing( ch );
  637. }
  638. }
  639. }
  640. return extent;
  641. }