PageRenderTime 840ms CodeModel.GetById 167ms app.highlight 492ms RepoModel.GetById 171ms app.codeStats 0ms

/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
  39
  40#include "stdafx.h"
  41#include "Context.h"
  42#include <string.h>
  43#include "fixed.h"
  44#include "Surface.h"
  45
  46
  47using namespace EGL;
  48
  49
  50// --------------------------------------------------------------------------
  51// Setup mesh arrays
  52// --------------------------------------------------------------------------
  53
  54void Context :: ToggleClientState(GLenum array, bool value) { 
  55	switch (array) {
  56	case GL_TEXTURE_COORD_ARRAY:
  57		m_TexCoordArrayEnabled[m_ClientActiveTexture] = value;
  58		break;
  59
  60	case GL_COLOR_ARRAY:
  61		m_ColorArrayEnabled = value;
  62		break;
  63
  64	case GL_NORMAL_ARRAY:
  65		m_NormalArrayEnabled = value;
  66		break;
  67
  68	case GL_VERTEX_ARRAY:
  69		m_VertexArrayEnabled = value;
  70		break;
  71
  72	case GL_POINT_SIZE_ARRAY_OES:
  73		m_PointSizeArrayEnabled = value;
  74		break;
  75
  76	case GL_WEIGHT_ARRAY_OES:
  77		m_WeightArrayEnabled = value;
  78		break;
  79
  80	case GL_MATRIX_INDEX_ARRAY_OES:
  81		m_MatrixIndexArrayEnabled = value;
  82		break;
  83
  84	default:
  85		RecordError(GL_INVALID_ENUM);
  86	}
  87}
  88
  89void Context :: DisableClientState(GLenum array) { 
  90	ToggleClientState(array, false);
  91}
  92
  93void Context :: EnableClientState(GLenum array) { 
  94	ToggleClientState(array, true);
  95}
  96
  97void Context :: ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { 
  98
  99	if (type != GL_UNSIGNED_BYTE && type != GL_FIXED && type != GL_FLOAT) {
 100		RecordError(GL_INVALID_ENUM);
 101		return;
 102	}
 103
 104	if (size != 4) {
 105		RecordError(GL_INVALID_VALUE);
 106		return;
 107	}
 108
 109	if (stride < 0) {
 110		RecordError(GL_INVALID_VALUE);
 111		return;
 112	}
 113
 114	if (stride == 0) {
 115		switch (type) {
 116		case GL_UNSIGNED_BYTE:
 117			stride = sizeof (GLubyte) * size;
 118			break;
 119
 120		case GL_FIXED:
 121			stride = sizeof (GLfixed) * size;
 122			break;
 123
 124		case GL_FLOAT:
 125			stride = sizeof (GLfloat) * size;
 126			break;
 127		}
 128	}
 129
 130	m_ColorArray.pointer = pointer;
 131	m_ColorArray.stride = stride;
 132	m_ColorArray.type = type;
 133	m_ColorArray.size = size;
 134	m_ColorArray.boundBuffer = m_CurrentArrayBuffer;
 135}
 136
 137void Context :: NormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer) { 
 138
 139	if (type != GL_BYTE && type != GL_SHORT && type != GL_FIXED && type != GL_FLOAT) {
 140		RecordError(GL_INVALID_ENUM);
 141		return;
 142	}
 143
 144	GLsizei size = 3;
 145
 146	if (stride < 0) {
 147		RecordError(GL_INVALID_VALUE);
 148		return;
 149	}
 150
 151	if (stride == 0) {
 152		switch (type) {
 153		case GL_BYTE:
 154			stride = sizeof (GLbyte) * size;
 155			break;
 156
 157		case GL_SHORT:
 158			stride = sizeof (GLshort) * size;
 159			break;
 160
 161		case GL_FIXED:
 162			stride = sizeof (GLfixed) * size;
 163			break;
 164
 165		case GL_FLOAT:
 166			stride = sizeof (GLfloat) * size;
 167			break;
 168
 169		}
 170	}
 171
 172	m_NormalArray.pointer = pointer;
 173	m_NormalArray.stride = stride;
 174	m_NormalArray.type = type;
 175	m_NormalArray.size = size;
 176	m_NormalArray.boundBuffer = m_CurrentArrayBuffer;
 177}
 178
 179void Context :: VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { 
 180
 181	if (type != GL_BYTE && type != GL_SHORT && type != GL_FIXED && type != GL_FLOAT) {
 182		RecordError(GL_INVALID_ENUM);
 183		return;
 184	}
 185
 186	if (size < 2 || size > 4) {
 187		RecordError(GL_INVALID_VALUE);
 188		return;
 189	}
 190
 191	if (stride < 0) {
 192		RecordError(GL_INVALID_VALUE);
 193		return;
 194	}
 195
 196	if (stride == 0) {
 197		switch (type) {
 198		case GL_BYTE:
 199			stride = sizeof (GLbyte) * size;
 200			break;
 201
 202		case GL_SHORT:
 203			stride = sizeof (GLshort) * size;
 204			break;
 205
 206		case GL_FIXED:
 207			stride = sizeof (GLfixed) * size;
 208			break;
 209
 210		case GL_FLOAT:
 211			stride = sizeof (GLfloat) * size;
 212			break;
 213
 214		}
 215	}
 216
 217	m_VertexArray.pointer = pointer;
 218	m_VertexArray.stride = stride;
 219	m_VertexArray.type = type;
 220	m_VertexArray.size = size;
 221	m_VertexArray.boundBuffer = m_CurrentArrayBuffer;
 222}
 223
 224void Context :: TexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { 
 225
 226	if (type != GL_BYTE && type != GL_SHORT && type != GL_FIXED && type != GL_FLOAT) {
 227		RecordError(GL_INVALID_ENUM);
 228		return;
 229	}
 230
 231	if (size < 2 || size > 4) {
 232		RecordError(GL_INVALID_VALUE);
 233		return;
 234	}
 235
 236	if (stride < 0) {
 237		RecordError(GL_INVALID_VALUE);
 238		return;
 239	}
 240
 241	if (stride == 0) {
 242		switch (type) {
 243		case GL_BYTE:
 244			stride = sizeof (GLbyte) * size;
 245			break;
 246
 247		case GL_SHORT:
 248			stride = sizeof (GLshort) * size;
 249			break;
 250
 251		case GL_FIXED:
 252			stride = sizeof (GLfixed) * size;
 253			break;
 254
 255		case GL_FLOAT:
 256			stride = sizeof (GLfloat) * size;
 257			break;
 258
 259		}
 260	}
 261
 262	m_TexCoordArray[m_ClientActiveTexture].pointer = pointer;
 263	m_TexCoordArray[m_ClientActiveTexture].stride = stride;
 264	m_TexCoordArray[m_ClientActiveTexture].type = type;
 265	m_TexCoordArray[m_ClientActiveTexture].size = size;
 266	m_TexCoordArray[m_ClientActiveTexture].boundBuffer = m_CurrentArrayBuffer;
 267}
 268
 269
 270// --------------------------------------------------------------------------
 271// Default values of array is disabled
 272// --------------------------------------------------------------------------
 273
 274
 275void Context :: Color4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) { 
 276	m_DefaultRGBA.r = red;
 277	m_DefaultRGBA.g = green;
 278	m_DefaultRGBA.b = blue;
 279	m_DefaultRGBA.a = alpha;
 280}
 281
 282
 283void Context :: MultiTexCoord4x(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) { 
 284	
 285	if (target < GL_TEXTURE0 || target >= GL_TEXTURE0 + EGL_NUM_TEXTURE_UNITS) {
 286		// only have one texture unit
 287		RecordError(GL_INVALID_VALUE);
 288		return;
 289	}
 290
 291	size_t unit = target - GL_TEXTURE0;
 292
 293	m_DefaultTextureCoords[unit] = Vec4D(s, t, r, q);
 294
 295	I32 inverse = EGL_Inverse(q);
 296	m_DefaultScaledTextureCoords[unit].tu = EGL_Mul(s, inverse);
 297	m_DefaultScaledTextureCoords[unit].tv = EGL_Mul(t, inverse);
 298}
 299
 300
 301void Context :: Normal3x(GLfixed nx, GLfixed ny, GLfixed nz) { 
 302	m_DefaultNormal = Vec3D(nx, ny, nz);
 303}
 304
 305
 306// --------------------------------------------------------------------------
 307// Actual array rendering
 308// --------------------------------------------------------------------------
 309
 310
 311void Context :: DrawArrays(GLenum mode, GLint first, GLsizei count) { 
 312
 313	if (count < 0) {
 314		RecordError(GL_INVALID_VALUE);
 315		return;
 316	}
 317
 318	if (!m_VertexArrayEnabled ||
 319		(m_MatrixPaletteEnabled && (!m_MatrixIndexArrayEnabled || !m_WeightArrayEnabled))) {
 320		RecordError(GL_INVALID_OPERATION);
 321		return;
 322	}
 323
 324	PrepareRendering();
 325
 326	switch (mode) {
 327	case GL_POINTS:
 328		RenderPoints(first, count);
 329		break;
 330
 331	case GL_LINES:
 332		RenderLines(first, count);
 333		break;
 334
 335	case GL_LINE_STRIP:
 336		RenderLineStrip(first, count);
 337		break;
 338
 339	case GL_LINE_LOOP:
 340		RenderLineLoop(first, count);
 341		break;
 342
 343	case GL_TRIANGLES:
 344		RenderTriangles(first, count);
 345		break;
 346
 347	case GL_TRIANGLE_STRIP:
 348		RenderTriangleStrip(first, count);
 349		break;
 350
 351	case GL_TRIANGLE_FAN:
 352		RenderTriangleFan(first, count);
 353		break;
 354
 355	default:
 356		RecordError(GL_INVALID_ENUM);
 357		return;
 358	}
 359}
 360
 361
 362void Context :: DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) { 
 363	
 364	if (count < 0) {
 365		RecordError(GL_INVALID_VALUE);
 366		return;
 367	}
 368
 369	if (!m_VertexArrayEnabled ||
 370		(m_MatrixPaletteEnabled && (!m_MatrixIndexArrayEnabled || !m_WeightArrayEnabled))) {
 371		RecordError(GL_INVALID_OPERATION);
 372		return;
 373	}
 374
 375	if (m_CurrentElementArrayBuffer) {
 376		U8 * bufferBase =
 377			static_cast<U8 *>(m_Buffers.GetObject(m_CurrentElementArrayBuffer)->GetData());
 378
 379		if (!bufferBase) {
 380			RecordError(GL_INVALID_OPERATION);
 381			return;
 382		}
 383
 384		size_t offset = static_cast<const U8 *>(indices) - static_cast<const U8 *>(0);
 385		indices = bufferBase + offset;
 386	}
 387
 388	if (!indices) {
 389		return;
 390	}
 391
 392	PrepareRendering();
 393
 394	switch (mode) {
 395	case GL_POINTS:
 396		if (type == GL_UNSIGNED_BYTE) {
 397			RenderPoints(count, reinterpret_cast<const GLubyte *>(indices));
 398		} else if (type == GL_UNSIGNED_SHORT) {
 399			RenderPoints(count, reinterpret_cast<const GLushort *>(indices));
 400		} else {
 401			RecordError(GL_INVALID_ENUM);
 402		}
 403
 404		break;
 405
 406	case GL_LINES:
 407		if (type == GL_UNSIGNED_BYTE) {
 408			RenderLines(count, reinterpret_cast<const GLubyte *>(indices));
 409		} else if (type == GL_UNSIGNED_SHORT) {
 410			RenderLines(count, reinterpret_cast<const GLushort *>(indices));
 411		} else {
 412			RecordError(GL_INVALID_ENUM);
 413		}
 414
 415		break;
 416
 417	case GL_LINE_STRIP:
 418		if (type == GL_UNSIGNED_BYTE) {
 419			RenderLineStrip(count, reinterpret_cast<const GLubyte *>(indices));
 420		} else if (type == GL_UNSIGNED_SHORT) {
 421			RenderLineStrip(count, reinterpret_cast<const GLushort *>(indices));
 422		} else {
 423			RecordError(GL_INVALID_ENUM);
 424		}
 425
 426		break;
 427
 428	case GL_LINE_LOOP:
 429		if (type == GL_UNSIGNED_BYTE) {
 430			RenderLineLoop(count, reinterpret_cast<const GLubyte *>(indices));
 431		} else if (type == GL_UNSIGNED_SHORT) {
 432			RenderLineLoop(count, reinterpret_cast<const GLushort *>(indices));
 433		} else {
 434			RecordError(GL_INVALID_ENUM);
 435		}
 436
 437		break;
 438
 439	case GL_TRIANGLES:
 440		if (type == GL_UNSIGNED_BYTE) {
 441			RenderTriangles(count, reinterpret_cast<const GLubyte *>(indices));
 442		} else if (type == GL_UNSIGNED_SHORT) {
 443			RenderTriangles(count, reinterpret_cast<const GLushort *>(indices));
 444		} else {
 445			RecordError(GL_INVALID_ENUM);
 446		}
 447
 448		break;
 449
 450	case GL_TRIANGLE_STRIP:
 451		if (type == GL_UNSIGNED_BYTE) {
 452			RenderTriangleStrip(count, reinterpret_cast<const GLubyte *>(indices));
 453		} else if (type == GL_UNSIGNED_SHORT) {
 454			RenderTriangleStrip(count, reinterpret_cast<const GLushort *>(indices));
 455		} else {
 456			RecordError(GL_INVALID_ENUM);
 457		}
 458
 459		break;
 460
 461	case GL_TRIANGLE_FAN:
 462		if (type == GL_UNSIGNED_BYTE) {
 463			RenderTriangleFan(count, reinterpret_cast<const GLubyte *>(indices));
 464		} else if (type == GL_UNSIGNED_SHORT) {
 465			RenderTriangleFan(count, reinterpret_cast<const GLushort *>(indices));
 466		} else {
 467			RecordError(GL_INVALID_ENUM);
 468		}
 469
 470		break;
 471
 472	default:
 473		RecordError(GL_INVALID_ENUM);
 474		return;
 475	}
 476}
 477
 478
 479// --------------------------------------------------------------------------
 480// Load all the current coordinates from either a specific array or from
 481// the common settings.
 482//
 483// Parameters:
 484//	index		-	The array index from which any array coordinates should
 485//					be retrieved.
 486// --------------------------------------------------------------------------
 487void Context :: SelectArrayElement(int index) {
 488
 489	if (m_MatrixPaletteEnabled) {
 490		if (m_WeightArray.effectivePointer) {
 491			m_WeightArray.FetchValues(index, m_CurrentWeights);
 492		}
 493
 494		if (m_MatrixIndexArray.effectivePointer) {
 495			m_MatrixIndexArray.FetchUnsignedByteValues(index, m_PaletteMatrixIndex);
 496		}
 497	}
 498
 499	assert(m_VertexArray.effectivePointer);
 500
 501	{
 502		EGL_Fixed coords[4];
 503
 504		m_VertexArray.FetchValues(index, coords);
 505
 506		if (m_VertexArray.size == 3) {
 507			m_CurrentVertex = Vec4D(coords[0], coords[1], coords[2]);
 508		} else if (m_VertexArray.size == 2) {
 509			m_CurrentVertex = Vec4D(coords[0], coords[1], 0);
 510		} else {
 511			m_CurrentVertex = Vec4D(coords);
 512		}
 513	}
 514
 515	if (m_NormalArray.effectivePointer) {
 516		EGL_Fixed coords[3];
 517
 518		m_NormalArray.FetchValues(index, coords);
 519		m_CurrentNormal = Vec3D(coords);
 520	}
 521
 522	if (m_ColorArray.effectivePointer) {
 523		EGL_Fixed coords[4];
 524
 525		m_ColorArray.FetchValues(index, coords);
 526		m_CurrentRGBA = FractionalColor(coords);
 527	}
 528
 529	for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
 530		if (m_TexCoordArray[unit].effectivePointer) {
 531			EGL_Fixed coords[4];
 532
 533			m_TexCoordArray[unit].FetchValues(index, coords);
 534
 535			if (m_TexCoordArray[unit].size < 4) {
 536				m_CurrentTextureCoords[unit].tu = coords[0];
 537				m_CurrentTextureCoords[unit].tv = coords[1];
 538			} else {
 539				I32 factor = EGL_Inverse(coords[3]);
 540				m_CurrentTextureCoords[unit].tu = EGL_Mul(coords[0], factor);
 541				m_CurrentTextureCoords[unit].tv = EGL_Mul(coords[1], factor);
 542			}
 543		}
 544	}
 545}
 546
 547
 548namespace {
 549
 550	inline EGL_Fixed Exp(EGL_Fixed value) {
 551		return EGL_FixedFromFloat(exp(EGL_FloatFromFixed(-value)));
 552	}
 553
 554	inline EGL_Fixed Exp2(EGL_Fixed value) {
 555		return Exp(EGL_Mul(value, value));
 556	}
 557}
 558
 559
 560// --------------------------------------------------------------------------
 561// Calculate the fog density for a vertex at the given distance
 562// --------------------------------------------------------------------------
 563EGL_Fixed Context :: FogDensity(EGL_Fixed eyeDistance) const {
 564
 565	switch (m_FogMode) {
 566		default:
 567		case FogLinear:
 568			return EGL_CLAMP(EGL_Mul((m_FogEnd - eyeDistance) >> m_FogGradientShift, m_FogGradient) + 128, 0, EGL_ONE);
 569
 570		case FogModeExp:
 571			return EGL_CLAMP(Exp(EGL_Mul(m_FogDensity, eyeDistance)) + 128, 0, EGL_ONE);
 572
 573		case FogModeExp2:
 574			return EGL_CLAMP(Exp2(EGL_Mul(m_FogDensity, eyeDistance)) + 128, 0, EGL_ONE);
 575	}
 576
 577}
 578
 579
 580void Context :: PrepareArray(VertexArray & array, bool enabled, bool isColor) {
 581
 582	array.effectivePointer = 0;
 583
 584	if (enabled) {
 585		if (array.boundBuffer) {
 586			if (m_Buffers.IsObject(array.boundBuffer)) {
 587				U8 * bufferBase =
 588					static_cast<U8 *>(m_Buffers.GetObject(array.boundBuffer)->GetData());
 589
 590				if (!bufferBase) {
 591					return;
 592				}
 593
 594				size_t offset = static_cast<const U8 *>(array.pointer) - static_cast<const U8 *>(0);
 595				array.effectivePointer = bufferBase + offset;
 596			} 
 597		} else {
 598			array.effectivePointer = array.pointer;
 599		}
 600	}
 601
 602	array.PrepareFetchValues(isColor);
 603}
 604
 605
 606void Context :: PrepareRendering() {
 607
 608	if (m_LightingEnabled) {
 609		if (m_ColorMaterialEnabled) {
 610			if (m_TwoSidedLightning) {
 611                m_GeometryFunction = &Context::CurrentValuesToRasterPosTwoSidedTrack;
 612			} else {
 613				m_GeometryFunction = &Context::CurrentValuesToRasterPosOneSidedTrack;
 614			}
 615		} else {
 616			if (m_TwoSidedLightning) {
 617				m_GeometryFunction = &Context::CurrentValuesToRasterPosTwoSidedNoTrack;
 618			} else {
 619				m_GeometryFunction = &Context::CurrentValuesToRasterPosOneSidedNoTrack;
 620			}
 621		}
 622	} else {
 623		m_GeometryFunction = &Context::CurrentValuesToRasterPosNoLight;
 624	}
 625
 626	PrepareArray(m_VertexArray,   m_VertexArrayEnabled);
 627
 628	PrepareArray(m_NormalArray,	  m_NormalArrayEnabled);
 629
 630	if (!m_NormalArray.effectivePointer) {
 631		m_CurrentNormal = m_DefaultNormal;
 632	}
 633
 634	PrepareArray(m_ColorArray,    m_ColorArrayEnabled, true);
 635
 636	if (!m_ColorArray.effectivePointer) {
 637		m_CurrentRGBA = m_DefaultRGBA;
 638	}
 639
 640	for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
 641		PrepareArray(m_TexCoordArray[unit], m_TexCoordArrayEnabled[unit]);
 642
 643		if (!m_TexCoordArray[unit].effectivePointer) {
 644			m_CurrentTextureCoords[unit].tu = m_DefaultScaledTextureCoords[unit].tu;
 645			m_CurrentTextureCoords[unit].tv = m_DefaultScaledTextureCoords[unit].tv;
 646		}
 647	}
 648
 649	PrepareArray(m_PointSizeArray,m_PointSizeArrayEnabled);
 650
 651	if (m_MatrixPaletteEnabled) {
 652		PrepareArray(m_WeightArray,	  m_WeightArrayEnabled);
 653		PrepareArray(m_MatrixIndexArray,m_MatrixIndexArrayEnabled);
 654		memset(m_CurrentWeights, 0, sizeof m_CurrentWeights);
 655		memset(m_PaletteMatrixIndex, 0, sizeof m_PaletteMatrixIndex);
 656	}
 657
 658}
 659
 660
 661inline void Context :: CurrentTextureValuesToRasterPos(RasterPos * rasterPos) {
 662	for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
 663		if (m_TextureMatrixStack[unit].CurrentMatrix().IsIdentity()) {
 664			rasterPos->m_TextureCoords[unit].tu = m_CurrentTextureCoords[unit].tu;
 665			rasterPos->m_TextureCoords[unit].tv = m_CurrentTextureCoords[unit].tv;
 666		} else {
 667			Vec3D inCoords(m_CurrentTextureCoords[unit].tu, m_CurrentTextureCoords[unit].tv, 0);
 668			Vec4D outCoords = m_TextureMatrixStack[unit].CurrentMatrix() * inCoords;
 669			rasterPos->m_TextureCoords[unit].tu = outCoords.x();
 670			rasterPos->m_TextureCoords[unit].tv = outCoords.y();
 671		}
 672	}
 673}
 674
 675
 676// --------------------------------------------------------------------------
 677// Perform lightning and geometry transformation on the current vertex
 678// and store the results in buffer for the rasterization stage of the
 679// pipeline.
 680//
 681// Parameters:
 682//	rasterPos	-	A pointer to a vertex parameter buffer for the
 683//					rasterization stage
 684// --------------------------------------------------------------------------
 685
 686
 687void Context :: CurrentValuesToRasterPosNoLight(RasterPos * rasterPos) {
 688	FractionalColor color;
 689	FractionalColor backColor;
 690
 691	// apply projection matrix to eye coordinates 
 692	if (!m_MatrixPaletteEnabled) {
 693		m_ModelViewMatrixStack.CurrentMatrix().Multiply(m_CurrentVertex, rasterPos->m_EyeCoords);
 694	} else {
 695		rasterPos->m_EyeCoords = m_MatrixPalette[m_PaletteMatrixIndex[0]] * (m_CurrentVertex * m_CurrentWeights[0]);
 696
 697		for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
 698			rasterPos->m_EyeCoords += m_MatrixPalette[m_PaletteMatrixIndex[index]] * (m_CurrentVertex * m_CurrentWeights[index]);
 699		}
 700	}
 701
 702	rasterPos->m_ClipCoords = m_ProjectionMatrixStack.CurrentMatrix() * rasterPos->m_EyeCoords;
 703
 704	//	copy current colors to raster pos
 705	rasterPos->m_FrontColor = rasterPos->m_BackColor = m_CurrentRGBA;
 706
 707	if (m_RasterizerState.IsEnabledFog()) {
 708		// populate fog density here...
 709		rasterPos->m_FogDensity = FogDensity(EGL_Abs(rasterPos->m_EyeCoords.z()));
 710	} else {
 711		rasterPos->m_FogDensity = 0;
 712	}
 713
 714	CurrentTextureValuesToRasterPos(rasterPos);
 715}
 716
 717
 718void Context :: CurrentValuesToRasterPosOneSidedNoTrack(RasterPos * rasterPos) {
 719
 720	FractionalColor color;
 721	FractionalColor backColor;
 722
 723	// apply projection matrix to eye coordinates 
 724	if (!m_MatrixPaletteEnabled) {
 725		m_ModelViewMatrixStack.CurrentMatrix().Multiply(m_CurrentVertex, rasterPos->m_EyeCoords);
 726	} else {
 727		rasterPos->m_EyeCoords = m_MatrixPalette[m_PaletteMatrixIndex[0]] * (m_CurrentVertex * m_CurrentWeights[0]);
 728
 729		for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
 730			rasterPos->m_EyeCoords += m_MatrixPalette[m_PaletteMatrixIndex[index]] * (m_CurrentVertex * m_CurrentWeights[index]);
 731		}
 732	}
 733
 734	rasterPos->m_ClipCoords = m_ProjectionMatrixStack.CurrentMatrix() * rasterPos->m_EyeCoords;
 735
 736	// populate fog density here...
 737	rasterPos->m_FogDensity = FogDensity(EGL_Abs(rasterPos->m_EyeCoords.z()));
 738
 739	// apply inverse of model view matrix to normals -> eye coordinates normals
 740	Vec3D eyeNormal;
 741	
 742	if (!m_MatrixPaletteEnabled) {
 743		eyeNormal = m_InverseModelViewMatrix.Multiply3x3(m_CurrentNormal);
 744	} else {
 745		eyeNormal = m_MatrixPaletteInverse[m_PaletteMatrixIndex[0]] * (m_CurrentNormal * m_CurrentWeights[0]);
 746
 747		for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
 748			eyeNormal += m_MatrixPaletteInverse[m_PaletteMatrixIndex[index]] * (m_CurrentNormal * m_CurrentWeights[index]);
 749		}
 750	}
 751
 752	if (m_NormalizeEnabled) {
 753		eyeNormal.Normalize();
 754	}
 755
 756	// for each light that is turned on, call into calculation
 757	int mask = 1;
 758
 759	color = m_FrontMaterial.GetAmbientColor() * m_LightModelAmbient;
 760	color.a = m_FrontMaterial.GetDiffuseColor().a;
 761	color += m_FrontMaterial.GetEmissiveColor();
 762
 763	for (int index = 0; index < EGL_NUMBER_LIGHTS; ++index, mask <<= 1) {
 764		if (m_LightEnabled & mask) {
 765			m_Lights[index].AccumulateLight(rasterPos->m_EyeCoords, eyeNormal, 
 766				m_FrontMaterial, color);
 767		}
 768	}
 769
 770	color.Clamp();
 771	rasterPos->m_FrontColor = color;
 772
 773	CurrentTextureValuesToRasterPos(rasterPos);
 774}
 775
 776
 777void Context :: CurrentValuesToRasterPosOneSidedTrack(RasterPos * rasterPos) {
 778	FractionalColor color;
 779	FractionalColor backColor;
 780
 781	// apply projection matrix to eye coordinates 
 782	if (!m_MatrixPaletteEnabled) {
 783		m_ModelViewMatrixStack.CurrentMatrix().Multiply(m_CurrentVertex, rasterPos->m_EyeCoords);
 784	} else {
 785		rasterPos->m_EyeCoords = m_MatrixPalette[m_PaletteMatrixIndex[0]] * (m_CurrentVertex * m_CurrentWeights[0]);
 786
 787		for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
 788			rasterPos->m_EyeCoords += m_MatrixPalette[m_PaletteMatrixIndex[index]] * (m_CurrentVertex * m_CurrentWeights[index]);
 789		}
 790	}
 791
 792	rasterPos->m_ClipCoords = m_ProjectionMatrixStack.CurrentMatrix() * rasterPos->m_EyeCoords;
 793
 794	// populate fog density here...
 795	rasterPos->m_FogDensity = FogDensity(EGL_Abs(rasterPos->m_EyeCoords.z()));
 796
 797	// apply inverse of model view matrix to normals -> eye coordinates normals
 798	Vec3D eyeNormal;
 799	
 800	if (!m_MatrixPaletteEnabled) {
 801		eyeNormal = m_InverseModelViewMatrix.Multiply3x3(m_CurrentNormal);
 802	} else {
 803		eyeNormal = m_MatrixPaletteInverse[m_PaletteMatrixIndex[0]] * (m_CurrentNormal * m_CurrentWeights[0]);
 804
 805		for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
 806			eyeNormal += m_MatrixPaletteInverse[m_PaletteMatrixIndex[index]] * (m_CurrentNormal * m_CurrentWeights[index]);
 807		}
 808	}
 809
 810	if (m_NormalizeEnabled) {
 811		eyeNormal.Normalize();
 812	}
 813
 814	// for each light that is turned on, call into calculation
 815	int mask = 1;
 816
 817	color = m_CurrentRGBA * m_LightModelAmbient;
 818	color += m_FrontMaterial.GetEmissiveColor();
 819
 820	for (int index = 0; index < EGL_NUMBER_LIGHTS; ++index, mask <<= 1) {
 821		if (m_LightEnabled & mask) {
 822			m_Lights[index].AccumulateLight(rasterPos->m_EyeCoords, eyeNormal, 
 823				m_FrontMaterial, m_CurrentRGBA, color);
 824		}
 825	}
 826
 827	color.Clamp();
 828	rasterPos->m_FrontColor = color;
 829
 830	CurrentTextureValuesToRasterPos(rasterPos);
 831}
 832
 833
 834void Context :: CurrentValuesToRasterPosTwoSidedNoTrack(RasterPos * rasterPos) {
 835	FractionalColor color;
 836	FractionalColor backColor;
 837
 838	// apply projection matrix to eye coordinates 
 839	if (!m_MatrixPaletteEnabled) {
 840		m_ModelViewMatrixStack.CurrentMatrix().Multiply(m_CurrentVertex, rasterPos->m_EyeCoords);
 841	} else {
 842		rasterPos->m_EyeCoords = m_MatrixPalette[m_PaletteMatrixIndex[0]] * (m_CurrentVertex * m_CurrentWeights[0]);
 843
 844		for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
 845			rasterPos->m_EyeCoords += m_MatrixPalette[m_PaletteMatrixIndex[index]] * (m_CurrentVertex * m_CurrentWeights[index]);
 846		}
 847	}
 848
 849	rasterPos->m_ClipCoords = m_ProjectionMatrixStack.CurrentMatrix() * rasterPos->m_EyeCoords;
 850
 851	// populate fog density here...
 852	rasterPos->m_FogDensity = FogDensity(EGL_Abs(rasterPos->m_EyeCoords.z()));
 853
 854	// apply inverse of model view matrix to normals -> eye coordinates normals
 855	Vec3D eyeNormal;
 856	
 857	if (!m_MatrixPaletteEnabled) {
 858		eyeNormal = m_InverseModelViewMatrix.Multiply3x3(m_CurrentNormal);
 859	} else {
 860		eyeNormal = m_MatrixPaletteInverse[m_PaletteMatrixIndex[0]] * (m_CurrentNormal * m_CurrentWeights[0]);
 861
 862		for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
 863			eyeNormal += m_MatrixPaletteInverse[m_PaletteMatrixIndex[index]] * (m_CurrentNormal * m_CurrentWeights[index]);
 864		}
 865	}
 866
 867	if (m_NormalizeEnabled) {
 868		eyeNormal.Normalize();
 869	}
 870
 871	// for each light that is turned on, call into calculation
 872	int mask = 1;
 873
 874	color = m_FrontMaterial.GetAmbientColor() * m_LightModelAmbient;
 875	color.a = m_FrontMaterial.GetDiffuseColor().a;
 876	color += m_FrontMaterial.GetEmissiveColor();
 877
 878	backColor = color;		
 879
 880	for (int index = 0; index < EGL_NUMBER_LIGHTS; ++index, mask <<= 1) {
 881		if (m_LightEnabled & mask) {
 882			m_Lights[index].AccumulateLight2(rasterPos->m_EyeCoords, eyeNormal, 
 883				m_FrontMaterial, color, backColor);
 884		}
 885	}
 886
 887	color.Clamp();
 888	backColor.Clamp();
 889	
 890	rasterPos->m_FrontColor = color;
 891	rasterPos->m_BackColor = backColor;
 892
 893	CurrentTextureValuesToRasterPos(rasterPos);
 894}
 895
 896
 897void Context :: CurrentValuesToRasterPosTwoSidedTrack(RasterPos * rasterPos) {
 898	FractionalColor color;
 899	FractionalColor backColor;
 900
 901	// apply projection matrix to eye coordinates 
 902	if (!m_MatrixPaletteEnabled) {
 903		m_ModelViewMatrixStack.CurrentMatrix().Multiply(m_CurrentVertex, rasterPos->m_EyeCoords);
 904	} else {
 905		rasterPos->m_EyeCoords = m_MatrixPalette[m_PaletteMatrixIndex[0]] * (m_CurrentVertex * m_CurrentWeights[0]);
 906
 907		for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
 908			rasterPos->m_EyeCoords += m_MatrixPalette[m_PaletteMatrixIndex[index]] * (m_CurrentVertex * m_CurrentWeights[index]);
 909		}
 910	}
 911
 912	rasterPos->m_ClipCoords = m_ProjectionMatrixStack.CurrentMatrix() * rasterPos->m_EyeCoords;
 913
 914	// populate fog density here...
 915	rasterPos->m_FogDensity = FogDensity(EGL_Abs(rasterPos->m_EyeCoords.z()));
 916
 917	// apply inverse of model view matrix to normals -> eye coordinates normals
 918	Vec3D eyeNormal;
 919	
 920	if (!m_MatrixPaletteEnabled) {
 921		eyeNormal = m_InverseModelViewMatrix.Multiply3x3(m_CurrentNormal);
 922	} else {
 923		eyeNormal = m_MatrixPaletteInverse[m_PaletteMatrixIndex[0]] * (m_CurrentNormal * m_CurrentWeights[0]);
 924
 925		for (size_t index = 1; index < m_MatrixIndexArray.size; ++index) {
 926			eyeNormal += m_MatrixPaletteInverse[m_PaletteMatrixIndex[index]] * (m_CurrentNormal * m_CurrentWeights[index]);
 927		}
 928	}
 929
 930	if (m_NormalizeEnabled) {
 931		eyeNormal.Normalize();
 932	}
 933
 934	// for each light that is turned on, call into calculation
 935	int mask = 1;
 936
 937	color = m_CurrentRGBA * m_LightModelAmbient;
 938	color += m_FrontMaterial.GetEmissiveColor();
 939
 940	backColor = color;		
 941
 942	for (int index = 0; index < EGL_NUMBER_LIGHTS; ++index, mask <<= 1) {
 943		if (m_LightEnabled & mask) {
 944			m_Lights[index].AccumulateLight2(rasterPos->m_EyeCoords, eyeNormal, 
 945				m_FrontMaterial, m_CurrentRGBA, color, backColor);
 946		}
 947	}
 948
 949	color.Clamp();
 950	backColor.Clamp();
 951	
 952	rasterPos->m_FrontColor = color;
 953	rasterPos->m_BackColor = backColor;
 954
 955	CurrentTextureValuesToRasterPos(rasterPos);
 956}
 957
 958
 959void Context :: ClipCoordsToWindowCoords(RasterPos & pos) {
 960
 961	// perform depth division
 962	EGL_Fixed x = pos.m_ClipCoords.x();
 963	EGL_Fixed y = pos.m_ClipCoords.y();
 964	EGL_Fixed z = pos.m_ClipCoords.z();
 965	EGL_Fixed w = pos.m_ClipCoords.w();
 966
 967	// fix possible rounding problems
 968	if (x < -w)	x = -w;
 969	if (x >= w)	x = w - 1;
 970	if (y < -w)	y = -w;
 971	if (y >= w)	y = w - 1;
 972	if (z < -w)	z = -w;
 973	if (z >= w)	z = w - 1;
 974
 975	if ((w >> 24) && (w >> 24) + 1) {
 976		// keep this value around for perspective-correct texturing
 977		EGL_Fixed invDenominator = EGL_Inverse(w >> 8);
 978
 979		// Scale 1/Z by 2^2 to avoid rounding problems during prespective correct
 980		// interpolation
 981		// See book by LaMothe for more detailed discussion on this
 982		pos.m_WindowCoords.invZ = invDenominator << 2;
 983
 984		pos.m_WindowCoords.x = 
 985			EGL_Mul(EGL_Mul(x >> 8, invDenominator), m_ViewportScale.x()) + m_ViewportOrigin.x();
 986		pos.m_WindowCoords.y = 
 987			EGL_Mul(EGL_Mul(y >> 8, invDenominator), m_ViewportScale.y()) + m_ViewportOrigin.y();
 988		pos.m_WindowCoords.depth = 
 989			EGL_CLAMP(EGL_Mul(z >> 8, EGL_Mul(m_DepthRangeFactor, invDenominator))  + m_DepthRangeBase, 0, 0xffff);
 990
 991	} else {
 992		// keep this value around for perspective-correct texturing
 993		EGL_Fixed invDenominator = w ? EGL_Inverse(w) : 0;
 994
 995		// Scale 1/Z by 2^10 to avoid rounding problems during prespective correct
 996		// interpolation
 997		// See book by LaMothe for more detailed discussion on this
 998		pos.m_WindowCoords.invZ = invDenominator << 10;
 999
1000		pos.m_WindowCoords.x = 
1001			EGL_Mul(EGL_Mul(x, invDenominator), m_ViewportScale.x()) + m_ViewportOrigin.x();
1002		pos.m_WindowCoords.y = 
1003			EGL_Mul(EGL_Mul(y, invDenominator), m_ViewportScale.y()) + m_ViewportOrigin.y();
1004		pos.m_WindowCoords.depth = 
1005			EGL_CLAMP(EGL_Mul(EGL_Mul(z, invDenominator), m_DepthRangeFactor)  + m_DepthRangeBase, 0, 0xffff);
1006
1007	}
1008
1009	pos.m_WindowCoords.x = ((pos.m_WindowCoords.x + 0x80) & ~0xff);
1010	pos.m_WindowCoords.y = ((pos.m_WindowCoords.y + 0x80) & ~0xff);
1011}
1012
1013void Context :: GetClipPlanex(GLenum plane, GLfixed eqn[4]) {
1014	if (plane < GL_CLIP_PLANE0 || plane >= GL_CLIP_PLANE0 + NUM_CLIP_PLANES) {
1015		RecordError(GL_INVALID_ENUM);
1016		return;
1017	}
1018
1019	size_t index = plane - GL_CLIP_PLANE0;
1020	eqn[0] = m_ClipPlanes[index].x();
1021	eqn[1] = m_ClipPlanes[index].y();
1022	eqn[2] = m_ClipPlanes[index].z();
1023	eqn[3] = m_ClipPlanes[index].w();
1024}
1025
1026void Context :: ClipPlanex(GLenum plane, const GLfixed *equation) {
1027	
1028	if (plane < GL_CLIP_PLANE0 || plane >= GL_CLIP_PLANE0 + NUM_CLIP_PLANES) {
1029		RecordError(GL_INVALID_ENUM);
1030		return;
1031	}
1032
1033	size_t index = plane - GL_CLIP_PLANE0;
1034	m_ClipPlanes[index] = m_FullInverseModelViewMatrix.Transpose() * Vec4D(equation);
1035}
1036
1037// --------------------------------------------------------------------------
1038// Additional array pointers for matrix palette support
1039// --------------------------------------------------------------------------
1040
1041void Context :: MatrixIndexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
1042	if (type != GL_UNSIGNED_BYTE) {
1043		RecordError(GL_INVALID_ENUM);
1044		return;
1045	}
1046
1047	if (size < 1 || size > MATRIX_PALETTE_SIZE) {
1048		RecordError(GL_INVALID_VALUE);
1049		return;
1050	}
1051
1052	if (stride < 0) {
1053		RecordError(GL_INVALID_VALUE);
1054		return;
1055	}
1056
1057	if (stride == 0) {
1058		stride = sizeof (GLubyte) * size;
1059	}
1060
1061	m_MatrixIndexArray.pointer = pointer;
1062	m_MatrixIndexArray.stride = stride;
1063	m_MatrixIndexArray.type = type;
1064	m_MatrixIndexArray.size = size;
1065	m_MatrixIndexArray.boundBuffer = m_CurrentArrayBuffer;
1066}
1067
1068
1069void Context :: WeightPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
1070	if (type != GL_FIXED && type != GL_FLOAT) {
1071		RecordError(GL_INVALID_ENUM);
1072		return;
1073	}
1074
1075	if (size < 1 || size > MATRIX_PALETTE_SIZE) {
1076		RecordError(GL_INVALID_VALUE);
1077		return;
1078	}
1079
1080	if (stride < 0) {
1081		RecordError(GL_INVALID_VALUE);
1082		return;
1083	}
1084
1085	if (stride == 0) {
1086		switch (type) {
1087		case GL_FIXED:
1088			stride = sizeof (GLfixed) * size;
1089			break;
1090
1091		case GL_FLOAT:
1092			stride = sizeof (GLfloat) * size;
1093			break;
1094
1095		}
1096	}
1097
1098	m_WeightArray.pointer = pointer;
1099	m_WeightArray.stride = stride;
1100	m_WeightArray.type = type;
1101	m_WeightArray.size = size;
1102	m_WeightArray.boundBuffer = m_CurrentArrayBuffer;
1103}