/opengles/src/ContextRender.cpp

http://ftk.googlecode.com/ · C++ · 1103 lines · 746 code · 258 blank · 99 comment · 218 complexity · 254e08d29199eb5f4cc4ffabd758fc9b MD5 · raw file

  1. // ==========================================================================
  2. //
  3. // render.cpp Rendering Context Class for 3D Rendering Library
  4. //
  5. // Rendering Operations
  6. //
  7. // --------------------------------------------------------------------------
  8. //
  9. // 08-07-2003 Hans-Martin Will initial version
  10. //
  11. // --------------------------------------------------------------------------
  12. //
  13. // Copyright (c) 2004, Hans-Martin Will. All rights reserved.
  14. //
  15. // Redistribution and use in source and binary forms, with or without
  16. // modification, are permitted provided that the following conditions are
  17. // met:
  18. //
  19. // * Redistributions of source code must retain the above copyright
  20. // notice, this list of conditions and the following disclaimer.
  21. // * Redistributions in binary form must reproduce the above copyright
  22. // notice, this list of conditions and the following disclaimer in the
  23. // documentation and/or other materials provided with the distribution.
  24. //
  25. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  26. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  29. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  30. // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  31. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  32. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  33. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  35. // THE POSSIBILITY OF SUCH DAMAGE.
  36. //
  37. // ==========================================================================
  38. #include "stdafx.h"
  39. #include "Context.h"
  40. #include <string.h>
  41. #include "fixed.h"
  42. #include "Surface.h"
  43. using namespace EGL;
  44. // --------------------------------------------------------------------------
  45. // Setup mesh arrays
  46. // --------------------------------------------------------------------------
  47. void Context :: ToggleClientState(GLenum array, bool value) {
  48. switch (array) {
  49. case GL_TEXTURE_COORD_ARRAY:
  50. m_TexCoordArrayEnabled[m_ClientActiveTexture] = value;
  51. break;
  52. case GL_COLOR_ARRAY:
  53. m_ColorArrayEnabled = value;
  54. break;
  55. case GL_NORMAL_ARRAY:
  56. m_NormalArrayEnabled = value;
  57. break;
  58. case GL_VERTEX_ARRAY:
  59. m_VertexArrayEnabled = value;
  60. break;
  61. case GL_POINT_SIZE_ARRAY_OES:
  62. m_PointSizeArrayEnabled = value;
  63. break;
  64. case GL_WEIGHT_ARRAY_OES:
  65. m_WeightArrayEnabled = value;
  66. break;
  67. case GL_MATRIX_INDEX_ARRAY_OES:
  68. m_MatrixIndexArrayEnabled = value;
  69. break;
  70. default:
  71. RecordError(GL_INVALID_ENUM);
  72. }
  73. }
  74. void Context :: DisableClientState(GLenum array) {
  75. ToggleClientState(array, false);
  76. }
  77. void Context :: EnableClientState(GLenum array) {
  78. ToggleClientState(array, true);
  79. }
  80. void Context :: ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
  81. if (type != GL_UNSIGNED_BYTE && type != GL_FIXED && type != GL_FLOAT) {
  82. RecordError(GL_INVALID_ENUM);
  83. return;
  84. }
  85. if (size != 4) {
  86. RecordError(GL_INVALID_VALUE);
  87. return;
  88. }
  89. if (stride < 0) {
  90. RecordError(GL_INVALID_VALUE);
  91. return;
  92. }
  93. if (stride == 0) {
  94. switch (type) {
  95. case GL_UNSIGNED_BYTE:
  96. stride = sizeof (GLubyte) * size;
  97. break;
  98. case GL_FIXED:
  99. stride = sizeof (GLfixed) * size;
  100. break;
  101. case GL_FLOAT:
  102. stride = sizeof (GLfloat) * size;
  103. break;
  104. }
  105. }
  106. m_ColorArray.pointer = pointer;
  107. m_ColorArray.stride = stride;
  108. m_ColorArray.type = type;
  109. m_ColorArray.size = size;
  110. m_ColorArray.boundBuffer = m_CurrentArrayBuffer;
  111. }
  112. void Context :: NormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer) {
  113. if (type != GL_BYTE && type != GL_SHORT && type != GL_FIXED && type != GL_FLOAT) {
  114. RecordError(GL_INVALID_ENUM);
  115. return;
  116. }
  117. GLsizei size = 3;
  118. if (stride < 0) {
  119. RecordError(GL_INVALID_VALUE);
  120. return;
  121. }
  122. if (stride == 0) {
  123. switch (type) {
  124. case GL_BYTE:
  125. stride = sizeof (GLbyte) * size;
  126. break;
  127. case GL_SHORT:
  128. stride = sizeof (GLshort) * size;
  129. break;
  130. case GL_FIXED:
  131. stride = sizeof (GLfixed) * size;
  132. break;
  133. case GL_FLOAT:
  134. stride = sizeof (GLfloat) * size;
  135. break;
  136. }
  137. }
  138. m_NormalArray.pointer = pointer;
  139. m_NormalArray.stride = stride;
  140. m_NormalArray.type = type;
  141. m_NormalArray.size = size;
  142. m_NormalArray.boundBuffer = m_CurrentArrayBuffer;
  143. }
  144. void Context :: VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
  145. if (type != GL_BYTE && type != GL_SHORT && type != GL_FIXED && type != GL_FLOAT) {
  146. RecordError(GL_INVALID_ENUM);
  147. return;
  148. }
  149. if (size < 2 || size > 4) {
  150. RecordError(GL_INVALID_VALUE);
  151. return;
  152. }
  153. if (stride < 0) {
  154. RecordError(GL_INVALID_VALUE);
  155. return;
  156. }
  157. if (stride == 0) {
  158. switch (type) {
  159. case GL_BYTE:
  160. stride = sizeof (GLbyte) * size;
  161. break;
  162. case GL_SHORT:
  163. stride = sizeof (GLshort) * size;
  164. break;
  165. case GL_FIXED:
  166. stride = sizeof (GLfixed) * size;
  167. break;
  168. case GL_FLOAT:
  169. stride = sizeof (GLfloat) * size;
  170. break;
  171. }
  172. }
  173. m_VertexArray.pointer = pointer;
  174. m_VertexArray.stride = stride;
  175. m_VertexArray.type = type;
  176. m_VertexArray.size = size;
  177. m_VertexArray.boundBuffer = m_CurrentArrayBuffer;
  178. }
  179. void Context :: TexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
  180. if (type != GL_BYTE && type != GL_SHORT && type != GL_FIXED && type != GL_FLOAT) {
  181. RecordError(GL_INVALID_ENUM);
  182. return;
  183. }
  184. if (size < 2 || size > 4) {
  185. RecordError(GL_INVALID_VALUE);
  186. return;
  187. }
  188. if (stride < 0) {
  189. RecordError(GL_INVALID_VALUE);
  190. return;
  191. }
  192. if (stride == 0) {
  193. switch (type) {
  194. case GL_BYTE:
  195. stride = sizeof (GLbyte) * size;
  196. break;
  197. case GL_SHORT:
  198. stride = sizeof (GLshort) * size;
  199. break;
  200. case GL_FIXED:
  201. stride = sizeof (GLfixed) * size;
  202. break;
  203. case GL_FLOAT:
  204. stride = sizeof (GLfloat) * size;
  205. break;
  206. }
  207. }
  208. m_TexCoordArray[m_ClientActiveTexture].pointer = pointer;
  209. m_TexCoordArray[m_ClientActiveTexture].stride = stride;
  210. m_TexCoordArray[m_ClientActiveTexture].type = type;
  211. m_TexCoordArray[m_ClientActiveTexture].size = size;
  212. m_TexCoordArray[m_ClientActiveTexture].boundBuffer = m_CurrentArrayBuffer;
  213. }
  214. // --------------------------------------------------------------------------
  215. // Default values of array is disabled
  216. // --------------------------------------------------------------------------
  217. void Context :: Color4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) {
  218. m_DefaultRGBA.r = red;
  219. m_DefaultRGBA.g = green;
  220. m_DefaultRGBA.b = blue;
  221. m_DefaultRGBA.a = alpha;
  222. }
  223. void Context :: MultiTexCoord4x(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) {
  224. if (target < GL_TEXTURE0 || target >= GL_TEXTURE0 + EGL_NUM_TEXTURE_UNITS) {
  225. // only have one texture unit
  226. RecordError(GL_INVALID_VALUE);
  227. return;
  228. }
  229. size_t unit = target - GL_TEXTURE0;
  230. m_DefaultTextureCoords[unit] = Vec4D(s, t, r, q);
  231. I32 inverse = EGL_Inverse(q);
  232. m_DefaultScaledTextureCoords[unit].tu = EGL_Mul(s, inverse);
  233. m_DefaultScaledTextureCoords[unit].tv = EGL_Mul(t, inverse);
  234. }
  235. void Context :: Normal3x(GLfixed nx, GLfixed ny, GLfixed nz) {
  236. m_DefaultNormal = Vec3D(nx, ny, nz);
  237. }
  238. // --------------------------------------------------------------------------
  239. // Actual array rendering
  240. // --------------------------------------------------------------------------
  241. void Context :: DrawArrays(GLenum mode, GLint first, GLsizei count) {
  242. if (count < 0) {
  243. RecordError(GL_INVALID_VALUE);
  244. return;
  245. }
  246. if (!m_VertexArrayEnabled ||
  247. (m_MatrixPaletteEnabled && (!m_MatrixIndexArrayEnabled || !m_WeightArrayEnabled))) {
  248. RecordError(GL_INVALID_OPERATION);
  249. return;
  250. }
  251. PrepareRendering();
  252. switch (mode) {
  253. case GL_POINTS:
  254. RenderPoints(first, count);
  255. break;
  256. case GL_LINES:
  257. RenderLines(first, count);
  258. break;
  259. case GL_LINE_STRIP:
  260. RenderLineStrip(first, count);
  261. break;
  262. case GL_LINE_LOOP:
  263. RenderLineLoop(first, count);
  264. break;
  265. case GL_TRIANGLES:
  266. RenderTriangles(first, count);
  267. break;
  268. case GL_TRIANGLE_STRIP:
  269. RenderTriangleStrip(first, count);
  270. break;
  271. case GL_TRIANGLE_FAN:
  272. RenderTriangleFan(first, count);
  273. break;
  274. default:
  275. RecordError(GL_INVALID_ENUM);
  276. return;
  277. }
  278. }
  279. void Context :: DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {
  280. if (count < 0) {
  281. RecordError(GL_INVALID_VALUE);
  282. return;
  283. }
  284. if (!m_VertexArrayEnabled ||
  285. (m_MatrixPaletteEnabled && (!m_MatrixIndexArrayEnabled || !m_WeightArrayEnabled))) {
  286. RecordError(GL_INVALID_OPERATION);
  287. return;
  288. }
  289. if (m_CurrentElementArrayBuffer) {
  290. U8 * bufferBase =
  291. static_cast<U8 *>(m_Buffers.GetObject(m_CurrentElementArrayBuffer)->GetData());
  292. if (!bufferBase) {
  293. RecordError(GL_INVALID_OPERATION);
  294. return;
  295. }
  296. size_t offset = static_cast<const U8 *>(indices) - static_cast<const U8 *>(0);
  297. indices = bufferBase + offset;
  298. }
  299. if (!indices) {
  300. return;
  301. }
  302. PrepareRendering();
  303. switch (mode) {
  304. case GL_POINTS:
  305. if (type == GL_UNSIGNED_BYTE) {
  306. RenderPoints(count, reinterpret_cast<const GLubyte *>(indices));
  307. } else if (type == GL_UNSIGNED_SHORT) {
  308. RenderPoints(count, reinterpret_cast<const GLushort *>(indices));
  309. } else {
  310. RecordError(GL_INVALID_ENUM);
  311. }
  312. break;
  313. case GL_LINES:
  314. if (type == GL_UNSIGNED_BYTE) {
  315. RenderLines(count, reinterpret_cast<const GLubyte *>(indices));
  316. } else if (type == GL_UNSIGNED_SHORT) {
  317. RenderLines(count, reinterpret_cast<const GLushort *>(indices));
  318. } else {
  319. RecordError(GL_INVALID_ENUM);
  320. }
  321. break;
  322. case GL_LINE_STRIP:
  323. if (type == GL_UNSIGNED_BYTE) {
  324. RenderLineStrip(count, reinterpret_cast<const GLubyte *>(indices));
  325. } else if (type == GL_UNSIGNED_SHORT) {
  326. RenderLineStrip(count, reinterpret_cast<const GLushort *>(indices));
  327. } else {
  328. RecordError(GL_INVALID_ENUM);
  329. }
  330. break;
  331. case GL_LINE_LOOP:
  332. if (type == GL_UNSIGNED_BYTE) {
  333. RenderLineLoop(count, reinterpret_cast<const GLubyte *>(indices));
  334. } else if (type == GL_UNSIGNED_SHORT) {
  335. RenderLineLoop(count, reinterpret_cast<const GLushort *>(indices));
  336. } else {
  337. RecordError(GL_INVALID_ENUM);
  338. }
  339. break;
  340. case GL_TRIANGLES:
  341. if (type == GL_UNSIGNED_BYTE) {
  342. RenderTriangles(count, reinterpret_cast<const GLubyte *>(indices));
  343. } else if (type == GL_UNSIGNED_SHORT) {
  344. RenderTriangles(count, reinterpret_cast<const GLushort *>(indices));
  345. } else {
  346. RecordError(GL_INVALID_ENUM);
  347. }
  348. break;
  349. case GL_TRIANGLE_STRIP:
  350. if (type == GL_UNSIGNED_BYTE) {
  351. RenderTriangleStrip(count, reinterpret_cast<const GLubyte *>(indices));
  352. } else if (type == GL_UNSIGNED_SHORT) {
  353. RenderTriangleStrip(count, reinterpret_cast<const GLushort *>(indices));
  354. } else {
  355. RecordError(GL_INVALID_ENUM);
  356. }
  357. break;
  358. case GL_TRIANGLE_FAN:
  359. if (type == GL_UNSIGNED_BYTE) {
  360. RenderTriangleFan(count, reinterpret_cast<const GLubyte *>(indices));
  361. } else if (type == GL_UNSIGNED_SHORT) {
  362. RenderTriangleFan(count, reinterpret_cast<const GLushort *>(indices));
  363. } else {
  364. RecordError(GL_INVALID_ENUM);
  365. }
  366. break;
  367. default:
  368. RecordError(GL_INVALID_ENUM);
  369. return;
  370. }
  371. }
  372. // --------------------------------------------------------------------------
  373. // Load all the current coordinates from either a specific array or from
  374. // the common settings.
  375. //
  376. // Parameters:
  377. // index - The array index from which any array coordinates should
  378. // be retrieved.
  379. // --------------------------------------------------------------------------
  380. void Context :: SelectArrayElement(int index) {
  381. if (m_MatrixPaletteEnabled) {
  382. if (m_WeightArray.effectivePointer) {
  383. m_WeightArray.FetchValues(index, m_CurrentWeights);
  384. }
  385. if (m_MatrixIndexArray.effectivePointer) {
  386. m_MatrixIndexArray.FetchUnsignedByteValues(index, m_PaletteMatrixIndex);
  387. }
  388. }
  389. assert(m_VertexArray.effectivePointer);
  390. {
  391. EGL_Fixed coords[4];
  392. m_VertexArray.FetchValues(index, coords);
  393. if (m_VertexArray.size == 3) {
  394. m_CurrentVertex = Vec4D(coords[0], coords[1], coords[2]);
  395. } else if (m_VertexArray.size == 2) {
  396. m_CurrentVertex = Vec4D(coords[0], coords[1], 0);
  397. } else {
  398. m_CurrentVertex = Vec4D(coords);
  399. }
  400. }
  401. if (m_NormalArray.effectivePointer) {
  402. EGL_Fixed coords[3];
  403. m_NormalArray.FetchValues(index, coords);
  404. m_CurrentNormal = Vec3D(coords);
  405. }
  406. if (m_ColorArray.effectivePointer) {
  407. EGL_Fixed coords[4];
  408. m_ColorArray.FetchValues(index, coords);
  409. m_CurrentRGBA = FractionalColor(coords);
  410. }
  411. for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  412. if (m_TexCoordArray[unit].effectivePointer) {
  413. EGL_Fixed coords[4];
  414. m_TexCoordArray[unit].FetchValues(index, coords);
  415. if (m_TexCoordArray[unit].size < 4) {
  416. m_CurrentTextureCoords[unit].tu = coords[0];
  417. m_CurrentTextureCoords[unit].tv = coords[1];
  418. } else {
  419. I32 factor = EGL_Inverse(coords[3]);
  420. m_CurrentTextureCoords[unit].tu = EGL_Mul(coords[0], factor);
  421. m_CurrentTextureCoords[unit].tv = EGL_Mul(coords[1], factor);
  422. }
  423. }
  424. }
  425. }
  426. namespace {
  427. inline EGL_Fixed Exp(EGL_Fixed value) {
  428. return EGL_FixedFromFloat(exp(EGL_FloatFromFixed(-value)));
  429. }
  430. inline EGL_Fixed Exp2(EGL_Fixed value) {
  431. return Exp(EGL_Mul(value, value));
  432. }
  433. }
  434. // --------------------------------------------------------------------------
  435. // Calculate the fog density for a vertex at the given distance
  436. // --------------------------------------------------------------------------
  437. EGL_Fixed Context :: FogDensity(EGL_Fixed eyeDistance) const {
  438. switch (m_FogMode) {
  439. default:
  440. case FogLinear:
  441. return EGL_CLAMP(EGL_Mul((m_FogEnd - eyeDistance) >> m_FogGradientShift, m_FogGradient) + 128, 0, EGL_ONE);
  442. case FogModeExp:
  443. return EGL_CLAMP(Exp(EGL_Mul(m_FogDensity, eyeDistance)) + 128, 0, EGL_ONE);
  444. case FogModeExp2:
  445. return EGL_CLAMP(Exp2(EGL_Mul(m_FogDensity, eyeDistance)) + 128, 0, EGL_ONE);
  446. }
  447. }
  448. void Context :: PrepareArray(VertexArray & array, bool enabled, bool isColor) {
  449. array.effectivePointer = 0;
  450. if (enabled) {
  451. if (array.boundBuffer) {
  452. if (m_Buffers.IsObject(array.boundBuffer)) {
  453. U8 * bufferBase =
  454. static_cast<U8 *>(m_Buffers.GetObject(array.boundBuffer)->GetData());
  455. if (!bufferBase) {
  456. return;
  457. }
  458. size_t offset = static_cast<const U8 *>(array.pointer) - static_cast<const U8 *>(0);
  459. array.effectivePointer = bufferBase + offset;
  460. }
  461. } else {
  462. array.effectivePointer = array.pointer;
  463. }
  464. }
  465. array.PrepareFetchValues(isColor);
  466. }
  467. void Context :: PrepareRendering() {
  468. if (m_LightingEnabled) {
  469. if (m_ColorMaterialEnabled) {
  470. if (m_TwoSidedLightning) {
  471. m_GeometryFunction = &Context::CurrentValuesToRasterPosTwoSidedTrack;
  472. } else {
  473. m_GeometryFunction = &Context::CurrentValuesToRasterPosOneSidedTrack;
  474. }
  475. } else {
  476. if (m_TwoSidedLightning) {
  477. m_GeometryFunction = &Context::CurrentValuesToRasterPosTwoSidedNoTrack;
  478. } else {
  479. m_GeometryFunction = &Context::CurrentValuesToRasterPosOneSidedNoTrack;
  480. }
  481. }
  482. } else {
  483. m_GeometryFunction = &Context::CurrentValuesToRasterPosNoLight;
  484. }
  485. PrepareArray(m_VertexArray, m_VertexArrayEnabled);
  486. PrepareArray(m_NormalArray, m_NormalArrayEnabled);
  487. if (!m_NormalArray.effectivePointer) {
  488. m_CurrentNormal = m_DefaultNormal;
  489. }
  490. PrepareArray(m_ColorArray, m_ColorArrayEnabled, true);
  491. if (!m_ColorArray.effectivePointer) {
  492. m_CurrentRGBA = m_DefaultRGBA;
  493. }
  494. for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  495. PrepareArray(m_TexCoordArray[unit], m_TexCoordArrayEnabled[unit]);
  496. if (!m_TexCoordArray[unit].effectivePointer) {
  497. m_CurrentTextureCoords[unit].tu = m_DefaultScaledTextureCoords[unit].tu;
  498. m_CurrentTextureCoords[unit].tv = m_DefaultScaledTextureCoords[unit].tv;
  499. }
  500. }
  501. PrepareArray(m_PointSizeArray,m_PointSizeArrayEnabled);
  502. if (m_MatrixPaletteEnabled) {
  503. PrepareArray(m_WeightArray, m_WeightArrayEnabled);
  504. PrepareArray(m_MatrixIndexArray,m_MatrixIndexArrayEnabled);
  505. memset(m_CurrentWeights, 0, sizeof m_CurrentWeights);
  506. memset(m_PaletteMatrixIndex, 0, sizeof m_PaletteMatrixIndex);
  507. }
  508. }
  509. inline void Context :: CurrentTextureValuesToRasterPos(RasterPos * rasterPos) {
  510. for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  511. if (m_TextureMatrixStack[unit].CurrentMatrix().IsIdentity()) {
  512. rasterPos->m_TextureCoords[unit].tu = m_CurrentTextureCoords[unit].tu;
  513. rasterPos->m_TextureCoords[unit].tv = m_CurrentTextureCoords[unit].tv;
  514. } else {
  515. Vec3D inCoords(m_CurrentTextureCoords[unit].tu, m_CurrentTextureCoords[unit].tv, 0);
  516. Vec4D outCoords = m_TextureMatrixStack[unit].CurrentMatrix() * inCoords;
  517. rasterPos->m_TextureCoords[unit].tu = outCoords.x();
  518. rasterPos->m_TextureCoords[unit].tv = outCoords.y();
  519. }
  520. }
  521. }
  522. // --------------------------------------------------------------------------
  523. // Perform lightning and geometry transformation on the current vertex
  524. // and store the results in buffer for the rasterization stage of the
  525. // pipeline.
  526. //
  527. // Parameters:
  528. // rasterPos - A pointer to a vertex parameter buffer for the
  529. // rasterization stage
  530. // --------------------------------------------------------------------------
  531. void Context :: CurrentValuesToRasterPosNoLight(RasterPos * rasterPos) {
  532. FractionalColor color;
  533. FractionalColor backColor;
  534. // apply projection matrix to eye coordinates
  535. if (!m_MatrixPaletteEnabled) {
  536. m_ModelViewMatrixStack.CurrentMatrix().Multiply(m_CurrentVertex, rasterPos->m_EyeCoords);
  537. } else {
  538. rasterPos->m_EyeCoords = m_MatrixPalette[m_PaletteMatrixIndex[0]] * (m_CurrentVertex * m_CurrentWeights[0]);
  539. for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
  540. rasterPos->m_EyeCoords += m_MatrixPalette[m_PaletteMatrixIndex[index]] * (m_CurrentVertex * m_CurrentWeights[index]);
  541. }
  542. }
  543. rasterPos->m_ClipCoords = m_ProjectionMatrixStack.CurrentMatrix() * rasterPos->m_EyeCoords;
  544. // copy current colors to raster pos
  545. rasterPos->m_FrontColor = rasterPos->m_BackColor = m_CurrentRGBA;
  546. if (m_RasterizerState.IsEnabledFog()) {
  547. // populate fog density here...
  548. rasterPos->m_FogDensity = FogDensity(EGL_Abs(rasterPos->m_EyeCoords.z()));
  549. } else {
  550. rasterPos->m_FogDensity = 0;
  551. }
  552. CurrentTextureValuesToRasterPos(rasterPos);
  553. }
  554. void Context :: CurrentValuesToRasterPosOneSidedNoTrack(RasterPos * rasterPos) {
  555. FractionalColor color;
  556. FractionalColor backColor;
  557. // apply projection matrix to eye coordinates
  558. if (!m_MatrixPaletteEnabled) {
  559. m_ModelViewMatrixStack.CurrentMatrix().Multiply(m_CurrentVertex, rasterPos->m_EyeCoords);
  560. } else {
  561. rasterPos->m_EyeCoords = m_MatrixPalette[m_PaletteMatrixIndex[0]] * (m_CurrentVertex * m_CurrentWeights[0]);
  562. for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
  563. rasterPos->m_EyeCoords += m_MatrixPalette[m_PaletteMatrixIndex[index]] * (m_CurrentVertex * m_CurrentWeights[index]);
  564. }
  565. }
  566. rasterPos->m_ClipCoords = m_ProjectionMatrixStack.CurrentMatrix() * rasterPos->m_EyeCoords;
  567. // populate fog density here...
  568. rasterPos->m_FogDensity = FogDensity(EGL_Abs(rasterPos->m_EyeCoords.z()));
  569. // apply inverse of model view matrix to normals -> eye coordinates normals
  570. Vec3D eyeNormal;
  571. if (!m_MatrixPaletteEnabled) {
  572. eyeNormal = m_InverseModelViewMatrix.Multiply3x3(m_CurrentNormal);
  573. } else {
  574. eyeNormal = m_MatrixPaletteInverse[m_PaletteMatrixIndex[0]] * (m_CurrentNormal * m_CurrentWeights[0]);
  575. for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
  576. eyeNormal += m_MatrixPaletteInverse[m_PaletteMatrixIndex[index]] * (m_CurrentNormal * m_CurrentWeights[index]);
  577. }
  578. }
  579. if (m_NormalizeEnabled) {
  580. eyeNormal.Normalize();
  581. }
  582. // for each light that is turned on, call into calculation
  583. int mask = 1;
  584. color = m_FrontMaterial.GetAmbientColor() * m_LightModelAmbient;
  585. color.a = m_FrontMaterial.GetDiffuseColor().a;
  586. color += m_FrontMaterial.GetEmissiveColor();
  587. for (int index = 0; index < EGL_NUMBER_LIGHTS; ++index, mask <<= 1) {
  588. if (m_LightEnabled & mask) {
  589. m_Lights[index].AccumulateLight(rasterPos->m_EyeCoords, eyeNormal,
  590. m_FrontMaterial, color);
  591. }
  592. }
  593. color.Clamp();
  594. rasterPos->m_FrontColor = color;
  595. CurrentTextureValuesToRasterPos(rasterPos);
  596. }
  597. void Context :: CurrentValuesToRasterPosOneSidedTrack(RasterPos * rasterPos) {
  598. FractionalColor color;
  599. FractionalColor backColor;
  600. // apply projection matrix to eye coordinates
  601. if (!m_MatrixPaletteEnabled) {
  602. m_ModelViewMatrixStack.CurrentMatrix().Multiply(m_CurrentVertex, rasterPos->m_EyeCoords);
  603. } else {
  604. rasterPos->m_EyeCoords = m_MatrixPalette[m_PaletteMatrixIndex[0]] * (m_CurrentVertex * m_CurrentWeights[0]);
  605. for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
  606. rasterPos->m_EyeCoords += m_MatrixPalette[m_PaletteMatrixIndex[index]] * (m_CurrentVertex * m_CurrentWeights[index]);
  607. }
  608. }
  609. rasterPos->m_ClipCoords = m_ProjectionMatrixStack.CurrentMatrix() * rasterPos->m_EyeCoords;
  610. // populate fog density here...
  611. rasterPos->m_FogDensity = FogDensity(EGL_Abs(rasterPos->m_EyeCoords.z()));
  612. // apply inverse of model view matrix to normals -> eye coordinates normals
  613. Vec3D eyeNormal;
  614. if (!m_MatrixPaletteEnabled) {
  615. eyeNormal = m_InverseModelViewMatrix.Multiply3x3(m_CurrentNormal);
  616. } else {
  617. eyeNormal = m_MatrixPaletteInverse[m_PaletteMatrixIndex[0]] * (m_CurrentNormal * m_CurrentWeights[0]);
  618. for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
  619. eyeNormal += m_MatrixPaletteInverse[m_PaletteMatrixIndex[index]] * (m_CurrentNormal * m_CurrentWeights[index]);
  620. }
  621. }
  622. if (m_NormalizeEnabled) {
  623. eyeNormal.Normalize();
  624. }
  625. // for each light that is turned on, call into calculation
  626. int mask = 1;
  627. color = m_CurrentRGBA * m_LightModelAmbient;
  628. color += m_FrontMaterial.GetEmissiveColor();
  629. for (int index = 0; index < EGL_NUMBER_LIGHTS; ++index, mask <<= 1) {
  630. if (m_LightEnabled & mask) {
  631. m_Lights[index].AccumulateLight(rasterPos->m_EyeCoords, eyeNormal,
  632. m_FrontMaterial, m_CurrentRGBA, color);
  633. }
  634. }
  635. color.Clamp();
  636. rasterPos->m_FrontColor = color;
  637. CurrentTextureValuesToRasterPos(rasterPos);
  638. }
  639. void Context :: CurrentValuesToRasterPosTwoSidedNoTrack(RasterPos * rasterPos) {
  640. FractionalColor color;
  641. FractionalColor backColor;
  642. // apply projection matrix to eye coordinates
  643. if (!m_MatrixPaletteEnabled) {
  644. m_ModelViewMatrixStack.CurrentMatrix().Multiply(m_CurrentVertex, rasterPos->m_EyeCoords);
  645. } else {
  646. rasterPos->m_EyeCoords = m_MatrixPalette[m_PaletteMatrixIndex[0]] * (m_CurrentVertex * m_CurrentWeights[0]);
  647. for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
  648. rasterPos->m_EyeCoords += m_MatrixPalette[m_PaletteMatrixIndex[index]] * (m_CurrentVertex * m_CurrentWeights[index]);
  649. }
  650. }
  651. rasterPos->m_ClipCoords = m_ProjectionMatrixStack.CurrentMatrix() * rasterPos->m_EyeCoords;
  652. // populate fog density here...
  653. rasterPos->m_FogDensity = FogDensity(EGL_Abs(rasterPos->m_EyeCoords.z()));
  654. // apply inverse of model view matrix to normals -> eye coordinates normals
  655. Vec3D eyeNormal;
  656. if (!m_MatrixPaletteEnabled) {
  657. eyeNormal = m_InverseModelViewMatrix.Multiply3x3(m_CurrentNormal);
  658. } else {
  659. eyeNormal = m_MatrixPaletteInverse[m_PaletteMatrixIndex[0]] * (m_CurrentNormal * m_CurrentWeights[0]);
  660. for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
  661. eyeNormal += m_MatrixPaletteInverse[m_PaletteMatrixIndex[index]] * (m_CurrentNormal * m_CurrentWeights[index]);
  662. }
  663. }
  664. if (m_NormalizeEnabled) {
  665. eyeNormal.Normalize();
  666. }
  667. // for each light that is turned on, call into calculation
  668. int mask = 1;
  669. color = m_FrontMaterial.GetAmbientColor() * m_LightModelAmbient;
  670. color.a = m_FrontMaterial.GetDiffuseColor().a;
  671. color += m_FrontMaterial.GetEmissiveColor();
  672. backColor = color;
  673. for (int index = 0; index < EGL_NUMBER_LIGHTS; ++index, mask <<= 1) {
  674. if (m_LightEnabled & mask) {
  675. m_Lights[index].AccumulateLight2(rasterPos->m_EyeCoords, eyeNormal,
  676. m_FrontMaterial, color, backColor);
  677. }
  678. }
  679. color.Clamp();
  680. backColor.Clamp();
  681. rasterPos->m_FrontColor = color;
  682. rasterPos->m_BackColor = backColor;
  683. CurrentTextureValuesToRasterPos(rasterPos);
  684. }
  685. void Context :: CurrentValuesToRasterPosTwoSidedTrack(RasterPos * rasterPos) {
  686. FractionalColor color;
  687. FractionalColor backColor;
  688. // apply projection matrix to eye coordinates
  689. if (!m_MatrixPaletteEnabled) {
  690. m_ModelViewMatrixStack.CurrentMatrix().Multiply(m_CurrentVertex, rasterPos->m_EyeCoords);
  691. } else {
  692. rasterPos->m_EyeCoords = m_MatrixPalette[m_PaletteMatrixIndex[0]] * (m_CurrentVertex * m_CurrentWeights[0]);
  693. for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
  694. rasterPos->m_EyeCoords += m_MatrixPalette[m_PaletteMatrixIndex[index]] * (m_CurrentVertex * m_CurrentWeights[index]);
  695. }
  696. }
  697. rasterPos->m_ClipCoords = m_ProjectionMatrixStack.CurrentMatrix() * rasterPos->m_EyeCoords;
  698. // populate fog density here...
  699. rasterPos->m_FogDensity = FogDensity(EGL_Abs(rasterPos->m_EyeCoords.z()));
  700. // apply inverse of model view matrix to normals -> eye coordinates normals
  701. Vec3D eyeNormal;
  702. if (!m_MatrixPaletteEnabled) {
  703. eyeNormal = m_InverseModelViewMatrix.Multiply3x3(m_CurrentNormal);
  704. } else {
  705. eyeNormal = m_MatrixPaletteInverse[m_PaletteMatrixIndex[0]] * (m_CurrentNormal * m_CurrentWeights[0]);
  706. for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
  707. eyeNormal += m_MatrixPaletteInverse[m_PaletteMatrixIndex[index]] * (m_CurrentNormal * m_CurrentWeights[index]);
  708. }
  709. }
  710. if (m_NormalizeEnabled) {
  711. eyeNormal.Normalize();
  712. }
  713. // for each light that is turned on, call into calculation
  714. int mask = 1;
  715. color = m_CurrentRGBA * m_LightModelAmbient;
  716. color += m_FrontMaterial.GetEmissiveColor();
  717. backColor = color;
  718. for (int index = 0; index < EGL_NUMBER_LIGHTS; ++index, mask <<= 1) {
  719. if (m_LightEnabled & mask) {
  720. m_Lights[index].AccumulateLight2(rasterPos->m_EyeCoords, eyeNormal,
  721. m_FrontMaterial, m_CurrentRGBA, color, backColor);
  722. }
  723. }
  724. color.Clamp();
  725. backColor.Clamp();
  726. rasterPos->m_FrontColor = color;
  727. rasterPos->m_BackColor = backColor;
  728. CurrentTextureValuesToRasterPos(rasterPos);
  729. }
  730. void Context :: ClipCoordsToWindowCoords(RasterPos & pos) {
  731. // perform depth division
  732. EGL_Fixed x = pos.m_ClipCoords.x();
  733. EGL_Fixed y = pos.m_ClipCoords.y();
  734. EGL_Fixed z = pos.m_ClipCoords.z();
  735. EGL_Fixed w = pos.m_ClipCoords.w();
  736. // fix possible rounding problems
  737. if (x < -w) x = -w;
  738. if (x >= w) x = w - 1;
  739. if (y < -w) y = -w;
  740. if (y >= w) y = w - 1;
  741. if (z < -w) z = -w;
  742. if (z >= w) z = w - 1;
  743. if ((w >> 24) && (w >> 24) + 1) {
  744. // keep this value around for perspective-correct texturing
  745. EGL_Fixed invDenominator = EGL_Inverse(w >> 8);
  746. // Scale 1/Z by 2^2 to avoid rounding problems during prespective correct
  747. // interpolation
  748. // See book by LaMothe for more detailed discussion on this
  749. pos.m_WindowCoords.invZ = invDenominator << 2;
  750. pos.m_WindowCoords.x =
  751. EGL_Mul(EGL_Mul(x >> 8, invDenominator), m_ViewportScale.x()) + m_ViewportOrigin.x();
  752. pos.m_WindowCoords.y =
  753. EGL_Mul(EGL_Mul(y >> 8, invDenominator), m_ViewportScale.y()) + m_ViewportOrigin.y();
  754. pos.m_WindowCoords.depth =
  755. EGL_CLAMP(EGL_Mul(z >> 8, EGL_Mul(m_DepthRangeFactor, invDenominator)) + m_DepthRangeBase, 0, 0xffff);
  756. } else {
  757. // keep this value around for perspective-correct texturing
  758. EGL_Fixed invDenominator = w ? EGL_Inverse(w) : 0;
  759. // Scale 1/Z by 2^10 to avoid rounding problems during prespective correct
  760. // interpolation
  761. // See book by LaMothe for more detailed discussion on this
  762. pos.m_WindowCoords.invZ = invDenominator << 10;
  763. pos.m_WindowCoords.x =
  764. EGL_Mul(EGL_Mul(x, invDenominator), m_ViewportScale.x()) + m_ViewportOrigin.x();
  765. pos.m_WindowCoords.y =
  766. EGL_Mul(EGL_Mul(y, invDenominator), m_ViewportScale.y()) + m_ViewportOrigin.y();
  767. pos.m_WindowCoords.depth =
  768. EGL_CLAMP(EGL_Mul(EGL_Mul(z, invDenominator), m_DepthRangeFactor) + m_DepthRangeBase, 0, 0xffff);
  769. }
  770. pos.m_WindowCoords.x = ((pos.m_WindowCoords.x + 0x80) & ~0xff);
  771. pos.m_WindowCoords.y = ((pos.m_WindowCoords.y + 0x80) & ~0xff);
  772. }
  773. void Context :: GetClipPlanex(GLenum plane, GLfixed eqn[4]) {
  774. if (plane < GL_CLIP_PLANE0 || plane >= GL_CLIP_PLANE0 + NUM_CLIP_PLANES) {
  775. RecordError(GL_INVALID_ENUM);
  776. return;
  777. }
  778. size_t index = plane - GL_CLIP_PLANE0;
  779. eqn[0] = m_ClipPlanes[index].x();
  780. eqn[1] = m_ClipPlanes[index].y();
  781. eqn[2] = m_ClipPlanes[index].z();
  782. eqn[3] = m_ClipPlanes[index].w();
  783. }
  784. void Context :: ClipPlanex(GLenum plane, const GLfixed *equation) {
  785. if (plane < GL_CLIP_PLANE0 || plane >= GL_CLIP_PLANE0 + NUM_CLIP_PLANES) {
  786. RecordError(GL_INVALID_ENUM);
  787. return;
  788. }
  789. size_t index = plane - GL_CLIP_PLANE0;
  790. m_ClipPlanes[index] = m_FullInverseModelViewMatrix.Transpose() * Vec4D(equation);
  791. }
  792. // --------------------------------------------------------------------------
  793. // Additional array pointers for matrix palette support
  794. // --------------------------------------------------------------------------
  795. void Context :: MatrixIndexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
  796. if (type != GL_UNSIGNED_BYTE) {
  797. RecordError(GL_INVALID_ENUM);
  798. return;
  799. }
  800. if (size < 1 || size > MATRIX_PALETTE_SIZE) {
  801. RecordError(GL_INVALID_VALUE);
  802. return;
  803. }
  804. if (stride < 0) {
  805. RecordError(GL_INVALID_VALUE);
  806. return;
  807. }
  808. if (stride == 0) {
  809. stride = sizeof (GLubyte) * size;
  810. }
  811. m_MatrixIndexArray.pointer = pointer;
  812. m_MatrixIndexArray.stride = stride;
  813. m_MatrixIndexArray.type = type;
  814. m_MatrixIndexArray.size = size;
  815. m_MatrixIndexArray.boundBuffer = m_CurrentArrayBuffer;
  816. }
  817. void Context :: WeightPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
  818. if (type != GL_FIXED && type != GL_FLOAT) {
  819. RecordError(GL_INVALID_ENUM);
  820. return;
  821. }
  822. if (size < 1 || size > MATRIX_PALETTE_SIZE) {
  823. RecordError(GL_INVALID_VALUE);
  824. return;
  825. }
  826. if (stride < 0) {
  827. RecordError(GL_INVALID_VALUE);
  828. return;
  829. }
  830. if (stride == 0) {
  831. switch (type) {
  832. case GL_FIXED:
  833. stride = sizeof (GLfixed) * size;
  834. break;
  835. case GL_FLOAT:
  836. stride = sizeof (GLfloat) * size;
  837. break;
  838. }
  839. }
  840. m_WeightArray.pointer = pointer;
  841. m_WeightArray.stride = stride;
  842. m_WeightArray.type = type;
  843. m_WeightArray.size = size;
  844. m_WeightArray.boundBuffer = m_CurrentArrayBuffer;
  845. }