DrawVert.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #ifndef __DRAWVERT_H__
  21. #define __DRAWVERT_H__
  22. // The hardware converts a byte to a float by division with 255 and in the
  23. // vertex programs we convert the floating-point value in the range [0, 1]
  24. // to the range [-1, 1] by multiplying with 2 and subtracting 1.
  25. #define VERTEX_BYTE_TO_FLOAT( x ) ( (x) * ( 2.0f / 255.0f ) - 1.0f )
  26. #define VERTEX_FLOAT_TO_BYTE( x ) idMath::Ftob( ( (x) + 1.0f ) * ( 255.0f / 2.0f ) + 0.5f )
  27. // The hardware converts a byte to a float by division with 255 and in the
  28. // fragment programs we convert the floating-point value in the range [0, 1]
  29. // to the range [-1, 1] by multiplying with 2 and subtracting 1.
  30. // This is the conventional OpenGL mapping which specifies an exact
  31. // representation for -1 and +1 but not 0. The DirectX 10 mapping is
  32. // in the comments which specifies a non-linear mapping with an exact
  33. // representation of -1, 0 and +1 but -1 is represented twice.
  34. #define NORMALMAP_BYTE_TO_FLOAT( x ) VERTEX_BYTE_TO_FLOAT( x ) //( (x) - 128.0f ) * ( 1.0f / 127.0f )
  35. #define NORMALMAP_FLOAT_TO_BYTE( x ) VERTEX_FLOAT_TO_BYTE( x ) //idMath::Ftob( 128.0f + 127.0f * (x) + 0.5f )
  36. /*
  37. ================================================
  38. halfFloat_t
  39. ================================================
  40. */
  41. typedef unsigned short halfFloat_t;
  42. // GPU half-float bit patterns
  43. #define HF_MANTISSA(x) (x&1023)
  44. #define HF_EXP(x) ((x&32767)>>10)
  45. #define HF_SIGN(x) ((x&32768)?-1:1)
  46. /*
  47. ========================
  48. F16toF32
  49. ========================
  50. */
  51. ID_INLINE float F16toF32( halfFloat_t x ) {
  52. int e = HF_EXP( x );
  53. int m = HF_MANTISSA( x );
  54. int s = HF_SIGN( x );
  55. if ( 0 < e && e < 31 ) {
  56. return s * powf( 2.0f, ( e - 15.0f ) ) * ( 1 + m / 1024.0f );
  57. } else if ( m == 0 ) {
  58. return s * 0.0f;
  59. }
  60. return s * powf( 2.0f, -14.0f ) * ( m / 1024.0f );
  61. }
  62. /*
  63. ========================
  64. F32toF16
  65. ========================
  66. */
  67. ID_INLINE halfFloat_t F32toF16( float a ) {
  68. unsigned int f = *(unsigned *)( &a );
  69. unsigned int signbit = ( f & 0x80000000 ) >> 16;
  70. int exponent = ( ( f & 0x7F800000 ) >> 23 ) - 112;
  71. unsigned int mantissa = ( f & 0x007FFFFF );
  72. if ( exponent <= 0 ) {
  73. return 0;
  74. }
  75. if ( exponent > 30 ) {
  76. return (halfFloat_t)( signbit | 0x7BFF );
  77. }
  78. return (halfFloat_t)( signbit | ( exponent << 10 ) | ( mantissa >> 13 ) );
  79. }
  80. /*
  81. ===============================================================================
  82. Draw Vertex.
  83. ===============================================================================
  84. */
  85. class idDrawVert {
  86. public:
  87. idVec3 xyz; // 12 bytes
  88. halfFloat_t st[2]; // 4 bytes
  89. byte normal[4]; // 4 bytes
  90. byte tangent[4]; // 4 bytes -- [3] is texture polarity sign
  91. byte color[4]; // 4 bytes
  92. byte color2[4]; // 4 bytes -- weights for skinning
  93. float operator[]( const int index ) const;
  94. float & operator[]( const int index );
  95. void Clear();
  96. const idVec3 GetNormal() const;
  97. const idVec3 GetNormalRaw() const; // not re-normalized for renderbump
  98. // must be normalized already!
  99. void SetNormal( float x, float y, float z );
  100. void SetNormal( const idVec3 & n );
  101. const idVec3 GetTangent() const;
  102. const idVec3 GetTangentRaw() const; // not re-normalized for renderbump
  103. // must be normalized already!
  104. void SetTangent( float x, float y, float z );
  105. void SetTangent( const idVec3 & t );
  106. // derived from normal, tangent, and tangent flag
  107. const idVec3 GetBiTangent() const;
  108. const idVec3 GetBiTangentRaw() const; // not re-normalized for renderbump
  109. void SetBiTangent( float x, float y, float z );
  110. ID_INLINE void SetBiTangent( const idVec3 & t );
  111. float GetBiTangentSign() const;
  112. byte GetBiTangentSignBit() const;
  113. void SetTexCoordNative( const halfFloat_t s, const halfFloat_t t );
  114. void SetTexCoord( const idVec2 & st );
  115. void SetTexCoord( float s, float t );
  116. void SetTexCoordS( float s );
  117. void SetTexCoordT( float t );
  118. const idVec2 GetTexCoord() const;
  119. const halfFloat_t GetTexCoordNativeS() const;
  120. const halfFloat_t GetTexCoordNativeT() const;
  121. // either 1.0f or -1.0f
  122. ID_INLINE void SetBiTangentSign( float sign );
  123. ID_INLINE void SetBiTangentSignBit( byte bit );
  124. void Lerp( const idDrawVert &a, const idDrawVert &b, const float f );
  125. void LerpAll( const idDrawVert &a, const idDrawVert &b, const float f );
  126. void SetColor( dword color );
  127. void SetNativeOrderColor( dword color );
  128. dword GetColor() const;
  129. void SetColor2( dword color );
  130. void SetNativeOrderColor2( dword color );
  131. void ClearColor2();
  132. dword GetColor2() const;
  133. static idDrawVert GetSkinnedDrawVert( const idDrawVert & vert, const idJointMat * joints );
  134. static idVec3 GetSkinnedDrawVertPosition( const idDrawVert & vert, const idJointMat * joints );
  135. };
  136. #define DRAWVERT_SIZE 32
  137. #define DRAWVERT_XYZ_OFFSET (0*4)
  138. #define DRAWVERT_ST_OFFSET (3*4)
  139. #define DRAWVERT_NORMAL_OFFSET (4*4)
  140. #define DRAWVERT_TANGENT_OFFSET (5*4)
  141. #define DRAWVERT_COLOR_OFFSET (6*4)
  142. #define DRAWVERT_COLOR2_OFFSET (7*4)
  143. assert_offsetof( idDrawVert, xyz, DRAWVERT_XYZ_OFFSET );
  144. assert_offsetof( idDrawVert, normal, DRAWVERT_NORMAL_OFFSET );
  145. assert_offsetof( idDrawVert, tangent, DRAWVERT_TANGENT_OFFSET );
  146. /*
  147. ========================
  148. VertexFloatToByte
  149. Assumes input is in the range [-1, 1]
  150. ========================
  151. */
  152. ID_INLINE void VertexFloatToByte( const float & x, const float & y, const float & z, byte * bval ) {
  153. assert_4_byte_aligned( bval ); // for __stvebx
  154. #ifdef ID_WIN_X86_SSE2_INTRIN
  155. const __m128 vector_float_one = { 1.0f, 1.0f, 1.0f, 1.0f };
  156. const __m128 vector_float_half = { 0.5f, 0.5f, 0.5f, 0.5f };
  157. const __m128 vector_float_255_over_2 = { 255.0f / 2.0f, 255.0f / 2.0f, 255.0f / 2.0f, 255.0f / 2.0f };
  158. const __m128 xyz = _mm_unpacklo_ps( _mm_unpacklo_ps( _mm_load_ss( &x ), _mm_load_ss( &z ) ), _mm_load_ss( &y ) );
  159. const __m128 xyzScaled = _mm_madd_ps( _mm_add_ps( xyz, vector_float_one ), vector_float_255_over_2, vector_float_half );
  160. const __m128i xyzInt = _mm_cvtps_epi32( xyzScaled );
  161. const __m128i xyzShort = _mm_packs_epi32( xyzInt, xyzInt );
  162. const __m128i xyzChar = _mm_packus_epi16( xyzShort, xyzShort );
  163. const __m128i xyz16 = _mm_unpacklo_epi8( xyzChar, _mm_setzero_si128() );
  164. bval[0] = (byte)_mm_extract_epi16( xyz16, 0 ); // cannot use _mm_extract_epi8 because it is an SSE4 instruction
  165. bval[1] = (byte)_mm_extract_epi16( xyz16, 1 );
  166. bval[2] = (byte)_mm_extract_epi16( xyz16, 2 );
  167. #else
  168. bval[0] = VERTEX_FLOAT_TO_BYTE( x );
  169. bval[1] = VERTEX_FLOAT_TO_BYTE( y );
  170. bval[2] = VERTEX_FLOAT_TO_BYTE( z );
  171. #endif
  172. }
  173. /*
  174. ========================
  175. idDrawVert::operator[]
  176. ========================
  177. */
  178. ID_INLINE float idDrawVert::operator[]( const int index ) const {
  179. assert( index >= 0 && index < 5 );
  180. return ((float *)(&xyz))[index];
  181. }
  182. /*
  183. ========================
  184. idDrawVert::operator[]
  185. ========================
  186. */
  187. ID_INLINE float &idDrawVert::operator[]( const int index ) {
  188. assert( index >= 0 && index < 5 );
  189. return ((float *)(&xyz))[index];
  190. }
  191. /*
  192. ========================
  193. idDrawVert::Clear
  194. ========================
  195. */
  196. ID_INLINE void idDrawVert::Clear() {
  197. *reinterpret_cast<dword *>(&this->xyz.x) = 0;
  198. *reinterpret_cast<dword *>(&this->xyz.y) = 0;
  199. *reinterpret_cast<dword *>(&this->xyz.z) = 0;
  200. *reinterpret_cast<dword *>(this->st) = 0;
  201. *reinterpret_cast<dword *>(this->normal) = 0x00FF8080; // x=0, y=0, z=1
  202. *reinterpret_cast<dword *>(this->tangent) = 0xFF8080FF; // x=1, y=0, z=0
  203. *reinterpret_cast<dword *>(this->color) = 0;
  204. *reinterpret_cast<dword *>(this->color2) = 0;
  205. }
  206. /*
  207. ========================
  208. idDrawVert::GetNormal
  209. ========================
  210. */
  211. ID_INLINE const idVec3 idDrawVert::GetNormal() const {
  212. idVec3 n( VERTEX_BYTE_TO_FLOAT( normal[0] ),
  213. VERTEX_BYTE_TO_FLOAT( normal[1] ),
  214. VERTEX_BYTE_TO_FLOAT( normal[2] ) );
  215. n.Normalize(); // after the normal has been compressed & uncompressed, it may not be normalized anymore
  216. return n;
  217. }
  218. /*
  219. ========================
  220. idDrawVert::GetNormalRaw
  221. ========================
  222. */
  223. ID_INLINE const idVec3 idDrawVert::GetNormalRaw() const {
  224. idVec3 n( VERTEX_BYTE_TO_FLOAT( normal[0] ),
  225. VERTEX_BYTE_TO_FLOAT( normal[1] ),
  226. VERTEX_BYTE_TO_FLOAT( normal[2] ) );
  227. // don't re-normalize just like we do in the vertex programs
  228. return n;
  229. }
  230. /*
  231. ========================
  232. idDrawVert::SetNormal
  233. must be normalized already!
  234. ========================
  235. */
  236. ID_INLINE void idDrawVert::SetNormal( const idVec3 & n ) {
  237. VertexFloatToByte( n.x, n.y, n.z, normal );
  238. }
  239. /*
  240. ========================
  241. idDrawVert::SetNormal
  242. ========================
  243. */
  244. ID_INLINE void idDrawVert::SetNormal( float x, float y, float z ) {
  245. VertexFloatToByte( x, y, z, normal );
  246. }
  247. /*
  248. ========================
  249. &idDrawVert::GetTangent
  250. ========================
  251. */
  252. ID_INLINE const idVec3 idDrawVert::GetTangent() const {
  253. idVec3 t( VERTEX_BYTE_TO_FLOAT( tangent[0] ),
  254. VERTEX_BYTE_TO_FLOAT( tangent[1] ),
  255. VERTEX_BYTE_TO_FLOAT( tangent[2] ) );
  256. t.Normalize();
  257. return t;
  258. }
  259. /*
  260. ========================
  261. &idDrawVert::GetTangentRaw
  262. ========================
  263. */
  264. ID_INLINE const idVec3 idDrawVert::GetTangentRaw() const {
  265. idVec3 t( VERTEX_BYTE_TO_FLOAT( tangent[0] ),
  266. VERTEX_BYTE_TO_FLOAT( tangent[1] ),
  267. VERTEX_BYTE_TO_FLOAT( tangent[2] ) );
  268. // don't re-normalize just like we do in the vertex programs
  269. return t;
  270. }
  271. /*
  272. ========================
  273. idDrawVert::SetTangent
  274. ========================
  275. */
  276. ID_INLINE void idDrawVert::SetTangent( float x, float y, float z ) {
  277. VertexFloatToByte( x, y, z, tangent );
  278. }
  279. /*
  280. ========================
  281. idDrawVert::SetTangent
  282. ========================
  283. */
  284. ID_INLINE void idDrawVert::SetTangent( const idVec3 & t ) {
  285. VertexFloatToByte( t.x, t.y, t.z, tangent );
  286. }
  287. /*
  288. ========================
  289. idDrawVert::GetBiTangent
  290. ========================
  291. */
  292. ID_INLINE const idVec3 idDrawVert::GetBiTangent() const {
  293. // derive from the normal, tangent, and bitangent direction flag
  294. idVec3 bitangent;
  295. bitangent.Cross( GetNormal(), GetTangent() );
  296. bitangent *= GetBiTangentSign();
  297. return bitangent;
  298. }
  299. /*
  300. ========================
  301. idDrawVert::GetBiTangentRaw
  302. ========================
  303. */
  304. ID_INLINE const idVec3 idDrawVert::GetBiTangentRaw() const {
  305. // derive from the normal, tangent, and bitangent direction flag
  306. // don't re-normalize just like we do in the vertex programs
  307. idVec3 bitangent;
  308. bitangent.Cross( GetNormalRaw(), GetTangentRaw() );
  309. bitangent *= GetBiTangentSign();
  310. return bitangent;
  311. }
  312. /*
  313. ========================
  314. idDrawVert::SetBiTangent
  315. ========================
  316. */
  317. ID_INLINE void idDrawVert::SetBiTangent( float x, float y, float z ) {
  318. SetBiTangent( idVec3( x, y, z ) );
  319. }
  320. /*
  321. ========================
  322. idDrawVert::SetBiTangent
  323. ========================
  324. */
  325. ID_INLINE void idDrawVert::SetBiTangent( const idVec3 &t ) {
  326. idVec3 bitangent;
  327. bitangent.Cross( GetNormal(), GetTangent() );
  328. SetBiTangentSign( bitangent * t );
  329. }
  330. /*
  331. ========================
  332. idDrawVert::GetBiTangentSign
  333. ========================
  334. */
  335. ID_INLINE float idDrawVert::GetBiTangentSign() const {
  336. return ( tangent[3] < 128 ) ? -1.0f : 1.0f;
  337. }
  338. /*
  339. ========================
  340. idDrawVert::GetBiTangentSignBit
  341. ========================
  342. */
  343. ID_INLINE byte idDrawVert::GetBiTangentSignBit() const {
  344. return ( tangent[3] < 128 ) ? 1 : 0;
  345. }
  346. /*
  347. ========================
  348. idDrawVert::SetBiTangentSign
  349. ========================
  350. */
  351. ID_INLINE void idDrawVert::SetBiTangentSign( float sign ) {
  352. tangent[3] = ( sign < 0.0f ) ? 0 : 255;
  353. }
  354. /*
  355. ========================
  356. idDrawVert::SetBiTangentSignBit
  357. ========================
  358. */
  359. ID_INLINE void idDrawVert::SetBiTangentSignBit( byte sign ) {
  360. tangent[3] = sign ? 0 : 255;
  361. }
  362. /*
  363. ========================
  364. idDrawVert::Lerp
  365. ========================
  366. */
  367. ID_INLINE void idDrawVert::Lerp( const idDrawVert &a, const idDrawVert &b, const float f ) {
  368. xyz = a.xyz + f * ( b.xyz - a.xyz );
  369. SetTexCoord( ::Lerp( a.GetTexCoord(), b.GetTexCoord(), f ) );
  370. }
  371. /*
  372. ========================
  373. idDrawVert::LerpAll
  374. ========================
  375. */
  376. ID_INLINE void idDrawVert::LerpAll( const idDrawVert &a, const idDrawVert &b, const float f ) {
  377. xyz = ::Lerp( a.xyz, b.xyz, f );
  378. SetTexCoord( ::Lerp( a.GetTexCoord(), b.GetTexCoord(), f ) );
  379. idVec3 normal = ::Lerp( a.GetNormal(), b.GetNormal(), f );
  380. idVec3 tangent = ::Lerp( a.GetTangent(), b.GetTangent(), f );
  381. idVec3 bitangent = ::Lerp( a.GetBiTangent(), b.GetBiTangent(), f );
  382. normal.Normalize();
  383. tangent.Normalize();
  384. bitangent.Normalize();
  385. SetNormal( normal );
  386. SetTangent( tangent );
  387. SetBiTangent( bitangent );
  388. color[0] = (byte)( a.color[0] + f * ( b.color[0] - a.color[0] ) );
  389. color[1] = (byte)( a.color[1] + f * ( b.color[1] - a.color[1] ) );
  390. color[2] = (byte)( a.color[2] + f * ( b.color[2] - a.color[2] ) );
  391. color[3] = (byte)( a.color[3] + f * ( b.color[3] - a.color[3] ) );
  392. color2[0] = (byte)( a.color2[0] + f * ( b.color2[0] - a.color2[0] ) );
  393. color2[1] = (byte)( a.color2[1] + f * ( b.color2[1] - a.color2[1] ) );
  394. color2[2] = (byte)( a.color2[2] + f * ( b.color2[2] - a.color2[2] ) );
  395. color2[3] = (byte)( a.color2[3] + f * ( b.color2[3] - a.color2[3] ) );
  396. }
  397. /*
  398. ========================
  399. idDrawVert::SetNativeOrderColor
  400. ========================
  401. */
  402. ID_INLINE void idDrawVert::SetNativeOrderColor( dword color ) {
  403. *reinterpret_cast<dword *>(this->color) = color;
  404. }
  405. /*
  406. ========================
  407. idDrawVert::SetColor
  408. ========================
  409. */
  410. ID_INLINE void idDrawVert::SetColor( dword color ) {
  411. *reinterpret_cast<dword *>(this->color) = color;
  412. }
  413. /*
  414. ========================
  415. idDrawVert::SetColor
  416. ========================
  417. */
  418. ID_INLINE dword idDrawVert::GetColor() const {
  419. return *reinterpret_cast<const dword *>(this->color);
  420. }
  421. /*
  422. ========================
  423. idDrawVert::SetTexCoordNative
  424. ========================
  425. */
  426. ID_INLINE void idDrawVert::SetTexCoordNative( const halfFloat_t s, const halfFloat_t t ) {
  427. st[0] = s;
  428. st[1] = t;
  429. }
  430. /*
  431. ========================
  432. idDrawVert::SetTexCoord
  433. ========================
  434. */
  435. ID_INLINE void idDrawVert::SetTexCoord( const idVec2 & st ) {
  436. SetTexCoordS( st.x );
  437. SetTexCoordT( st.y );
  438. }
  439. /*
  440. ========================
  441. idDrawVert::SetTexCoord
  442. ========================
  443. */
  444. ID_INLINE void idDrawVert::SetTexCoord( float s, float t ) {
  445. SetTexCoordS( s );
  446. SetTexCoordT( t );
  447. }
  448. /*
  449. ========================
  450. idDrawVert::SetTexCoordS
  451. ========================
  452. */
  453. ID_INLINE void idDrawVert::SetTexCoordS( float s ) {
  454. st[0] = F32toF16( s );
  455. }
  456. /*
  457. ========================
  458. idDrawVert::SetTexCoordT
  459. ========================
  460. */
  461. ID_INLINE void idDrawVert::SetTexCoordT( float t ) {
  462. st[1] = F32toF16( t );
  463. }
  464. /*
  465. ========================
  466. idDrawVert::GetTexCoord
  467. ========================
  468. */
  469. ID_INLINE const idVec2 idDrawVert::GetTexCoord() const {
  470. return idVec2( F16toF32( st[0] ), F16toF32( st[1] ) );
  471. }
  472. /*
  473. ========================
  474. idDrawVert::GetTexCoordNativeS
  475. ========================
  476. */
  477. ID_INLINE const halfFloat_t idDrawVert::GetTexCoordNativeS() const {
  478. return st[0];
  479. }
  480. /*
  481. ========================
  482. idDrawVert::GetTexCoordNativeT
  483. ========================
  484. */
  485. ID_INLINE const halfFloat_t idDrawVert::GetTexCoordNativeT() const {
  486. return st[1];
  487. }
  488. /*
  489. ========================
  490. idDrawVert::SetNativeOrderColor2
  491. ========================
  492. */
  493. ID_INLINE void idDrawVert::SetNativeOrderColor2( dword color2 ) {
  494. *reinterpret_cast<dword *>(this->color2) = color2;
  495. }
  496. /*
  497. ========================
  498. idDrawVert::SetColor
  499. ========================
  500. */
  501. ID_INLINE void idDrawVert::SetColor2( dword color2 ) {
  502. *reinterpret_cast<dword *>(this->color2) = color2;
  503. }
  504. /*
  505. ========================
  506. idDrawVert::ClearColor2
  507. ========================
  508. */
  509. ID_INLINE void idDrawVert::ClearColor2() {
  510. *reinterpret_cast<dword *>(this->color2) = 0x80808080;
  511. }
  512. /*
  513. ========================
  514. idDrawVert::GetColor2
  515. ========================
  516. */
  517. ID_INLINE dword idDrawVert::GetColor2() const {
  518. return *reinterpret_cast<const dword *>(this->color2);
  519. }
  520. /*
  521. ========================
  522. WriteDrawVerts16
  523. Use 16-byte in-order SIMD writes because the destVerts may live in write-combined memory
  524. ========================
  525. */
  526. ID_INLINE void WriteDrawVerts16( idDrawVert * destVerts, const idDrawVert * localVerts, int numVerts ) {
  527. assert_sizeof( idDrawVert, 32 );
  528. assert_16_byte_aligned( destVerts );
  529. assert_16_byte_aligned( localVerts );
  530. #ifdef ID_WIN_X86_SSE2_INTRIN
  531. for ( int i = 0; i < numVerts; i++ ) {
  532. __m128i v0 = _mm_load_si128( (const __m128i *)( (byte *)( localVerts + i ) + 0 ) );
  533. __m128i v1 = _mm_load_si128( (const __m128i *)( (byte *)( localVerts + i ) + 16 ) );
  534. _mm_stream_si128( (__m128i *)( (byte *)( destVerts + i ) + 0 ), v0 );
  535. _mm_stream_si128( (__m128i *)( (byte *)( destVerts + i ) + 16 ), v1 );
  536. }
  537. #else
  538. memcpy( destVerts, localVerts, numVerts * sizeof( idDrawVert ) );
  539. #endif
  540. }
  541. /*
  542. =====================
  543. idDrawVert::GetSkinnedDrawVert
  544. =====================
  545. */
  546. ID_INLINE idDrawVert idDrawVert::GetSkinnedDrawVert( const idDrawVert & vert, const idJointMat * joints ) {
  547. if ( joints == NULL ) {
  548. return vert;
  549. }
  550. const idJointMat & j0 = joints[vert.color[0]];
  551. const idJointMat & j1 = joints[vert.color[1]];
  552. const idJointMat & j2 = joints[vert.color[2]];
  553. const idJointMat & j3 = joints[vert.color[3]];
  554. const float w0 = vert.color2[0] * ( 1.0f / 255.0f );
  555. const float w1 = vert.color2[1] * ( 1.0f / 255.0f );
  556. const float w2 = vert.color2[2] * ( 1.0f / 255.0f );
  557. const float w3 = vert.color2[3] * ( 1.0f / 255.0f );
  558. idJointMat accum;
  559. idJointMat::Mul( accum, j0, w0 );
  560. idJointMat::Mad( accum, j1, w1 );
  561. idJointMat::Mad( accum, j2, w2 );
  562. idJointMat::Mad( accum, j3, w3 );
  563. idDrawVert outVert;
  564. outVert.xyz = accum * idVec4( vert.xyz.x, vert.xyz.y, vert.xyz.z, 1.0f );
  565. outVert.SetTexCoordNative( vert.GetTexCoordNativeS(), vert.GetTexCoordNativeT() );
  566. outVert.SetNormal( accum * vert.GetNormal() );
  567. outVert.SetTangent( accum * vert.GetTangent() );
  568. outVert.tangent[3] = vert.tangent[3];
  569. for ( int i = 0; i < 4; i++ ) {
  570. outVert.color[i] = vert.color[i];
  571. outVert.color2[i] = vert.color2[i];
  572. }
  573. return outVert;
  574. }
  575. /*
  576. =====================
  577. idDrawVert::GetSkinnedDrawVertPosition
  578. =====================
  579. */
  580. ID_INLINE idVec3 idDrawVert::GetSkinnedDrawVertPosition( const idDrawVert & vert, const idJointMat * joints ) {
  581. if ( joints == NULL ) {
  582. return vert.xyz;
  583. }
  584. const idJointMat & j0 = joints[vert.color[0]];
  585. const idJointMat & j1 = joints[vert.color[1]];
  586. const idJointMat & j2 = joints[vert.color[2]];
  587. const idJointMat & j3 = joints[vert.color[3]];
  588. const float w0 = vert.color2[0] * ( 1.0f / 255.0f );
  589. const float w1 = vert.color2[1] * ( 1.0f / 255.0f );
  590. const float w2 = vert.color2[2] * ( 1.0f / 255.0f );
  591. const float w3 = vert.color2[3] * ( 1.0f / 255.0f );
  592. idJointMat accum;
  593. idJointMat::Mul( accum, j0, w0 );
  594. idJointMat::Mad( accum, j1, w1 );
  595. idJointMat::Mad( accum, j2, w2 );
  596. idJointMat::Mad( accum, j3, w3 );
  597. return accum * idVec4( vert.xyz.x, vert.xyz.y, vert.xyz.z, 1.0f );
  598. }
  599. /*
  600. ===============================================================================
  601. Shadow Vertex
  602. ===============================================================================
  603. */
  604. class idShadowVert {
  605. public:
  606. idVec4 xyzw;
  607. void Clear();
  608. static int CreateShadowCache( idShadowVert * vertexCache, const idDrawVert *verts, const int numVerts );
  609. };
  610. #define SHADOWVERT_XYZW_OFFSET (0)
  611. assert_offsetof( idShadowVert, xyzw, SHADOWVERT_XYZW_OFFSET );
  612. ID_INLINE void idShadowVert::Clear() {
  613. xyzw.Zero();
  614. }
  615. /*
  616. ===============================================================================
  617. Skinned Shadow Vertex
  618. ===============================================================================
  619. */
  620. class idShadowVertSkinned {
  621. public:
  622. idVec4 xyzw;
  623. byte color[4];
  624. byte color2[4];
  625. byte pad[8]; // pad to multiple of 32-byte for glDrawElementsBaseVertex
  626. void Clear();
  627. static int CreateShadowCache( idShadowVertSkinned * vertexCache, const idDrawVert *verts, const int numVerts );
  628. };
  629. #define SHADOWVERTSKINNED_XYZW_OFFSET (0)
  630. #define SHADOWVERTSKINNED_COLOR_OFFSET (16)
  631. #define SHADOWVERTSKINNED_COLOR2_OFFSET (20)
  632. assert_offsetof( idShadowVertSkinned, xyzw, SHADOWVERTSKINNED_XYZW_OFFSET );
  633. assert_offsetof( idShadowVertSkinned, color, SHADOWVERTSKINNED_COLOR_OFFSET );
  634. assert_offsetof( idShadowVertSkinned, color2, SHADOWVERTSKINNED_COLOR2_OFFSET );
  635. ID_INLINE void idShadowVertSkinned::Clear() {
  636. xyzw.Zero();
  637. }
  638. #endif /* !__DRAWVERT_H__ */