1 #include "lc_global.h"
2 #include "lc_context.h"
3 #include "lc_glextensions.h"
4 #include "lc_mesh.h"
5 #include "lc_texture.h"
6 #include "lc_colors.h"
7 #include "lc_mainwindow.h"
8 #include "lc_library.h"
9 #include "texfont.h"
10 #include "lc_view.h"
11 #include "lc_viewsphere.h"
12 #include "lc_stringcache.h"
13 #include "lc_partselectionwidget.h"
14 #include <QOpenGLFunctions_3_2_Core>
15 
16 #ifdef LC_OPENGLES
17 #define glEnableClientState(...)
18 #define glDisableClientState(...)
19 #define glVertexPointer(...)
20 #define glTexCoordPointer(...)
21 #define glColorPointer(...)
22 #define GL_ARRAY_BUFFER_ARB GL_ARRAY_BUFFER
23 #define GL_ELEMENT_ARRAY_BUFFER_ARB GL_ELEMENT_ARRAY_BUFFER
24 #define GL_STATIC_DRAW_ARB GL_STATIC_DRAW
25 #endif
26 
27 std::unique_ptr<QOpenGLContext> lcContext::mOffscreenContext;
28 std::unique_ptr<QOffscreenSurface> lcContext::mOffscreenSurface;
29 std::unique_ptr<lcContext> lcContext::mGlobalOffscreenContext;
30 lcProgram lcContext::mPrograms[static_cast<int>(lcMaterialType::Count)];
31 
lcContext()32 lcContext::lcContext()
33 {
34 	mVertexBufferObject = 0;
35 	mIndexBufferObject = 0;
36 	mVertexBufferPointer = nullptr;
37 	mIndexBufferPointer = nullptr;
38 	mVertexBufferOffset = (char*)~0;
39 
40 	mNormalEnabled = false;
41 	mTexCoordEnabled = false;
42 	mColorEnabled = false;
43 
44 	mTexture2D = 0;
45 	mTextureCubeMap = 0;
46 	mPolygonOffset = lcPolygonOffset::None;
47 	mDepthWrite = true;
48 	mDepthFunction = lcDepthFunction::LessEqual;
49 	mCullFace = false;
50 	mLineWidth = 1.0f;
51 #ifndef LC_OPENGLES
52 	mMatrixMode = GL_MODELVIEW;
53 	mTextureEnabled = false;
54 #endif
55 
56 	mColor = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
57 	mWorldMatrix = lcMatrix44Identity();
58 	mViewMatrix = lcMatrix44Identity();
59 	mProjectionMatrix = lcMatrix44Identity();
60 	mViewProjectionMatrix = lcMatrix44Identity();
61 	mHighlightParams[0] = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
62 	mHighlightParams[1] = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
63 	mHighlightParams[2] = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
64 	mHighlightParams[3] = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
65 	mColorDirty = false;
66 	mWorldMatrixDirty = false;
67 	mViewMatrixDirty = false;
68 	mProjectionMatrixDirty = false;
69 	mViewProjectionMatrixDirty = false;
70 	mHighlightParamsDirty = false;
71 
72 	mMaterialType = lcMaterialType::Count;
73 }
74 
~lcContext()75 lcContext::~lcContext()
76 {
77 }
78 
InitializeRenderer()79 bool lcContext::InitializeRenderer()
80 {
81 	if (!CreateOffscreenContext())
82 		return false;
83 
84 	mGlobalOffscreenContext = std::unique_ptr<lcContext>(new(lcContext));
85 
86 	lcContext* Context = mGlobalOffscreenContext.get();
87 	Context->SetOffscreenContext();
88 
89 	lcInitializeGLExtensions(mOffscreenContext.get());
90 
91 	// TODO: Find a better place for the grid texture and font
92 	gStringCache.Initialize(Context);
93 	gTexFont.Initialize(Context);
94 
95 	Context->CreateResources();
96 	lcView::CreateResources(Context);
97 	lcViewSphere::CreateResources(Context);
98 
99 	if (!gSupportsShaderObjects && lcGetPreferences().mShadingMode == lcShadingMode::DefaultLights)
100 		lcGetPreferences().mShadingMode = lcShadingMode::Flat;
101 
102 	if (!gSupportsShaderObjects && lcGetPreferences().mDrawConditionalLines)
103 		lcGetPreferences().mDrawConditionalLines = false;
104 
105 	if (!gSupportsFramebufferObject)
106 		gMainWindow->GetPartSelectionWidget()->DisableIconMode();
107 
108 	return true;
109 }
110 
ShutdownRenderer()111 void lcContext::ShutdownRenderer()
112 {
113 	if (!mGlobalOffscreenContext)
114 		return;
115 
116 	mGlobalOffscreenContext->MakeCurrent();
117 	lcContext* Context = mGlobalOffscreenContext.get();
118 
119 	gStringCache.Reset();
120 	gTexFont.Reset();
121 
122 	lcView::DestroyResources(Context);
123 	Context->DestroyResources();
124 	lcViewSphere::DestroyResources(Context);
125 
126 	mGlobalOffscreenContext.reset();
127 
128 	lcContext::DestroyOffscreenContext();
129 }
130 
GetGlobalOffscreenContext()131 lcContext* lcContext::GetGlobalOffscreenContext()
132 {
133 	return mGlobalOffscreenContext.get();
134 }
135 
CreateOffscreenContext()136 bool lcContext::CreateOffscreenContext()
137 {
138 	std::unique_ptr<QOpenGLContext> OffscreenContext(new QOpenGLContext());
139 
140 	if (!OffscreenContext)
141 		return false;
142 
143 	OffscreenContext->setShareContext(QOpenGLContext::globalShareContext());
144 
145 	if (!OffscreenContext->create() || !OffscreenContext->isValid())
146 		return false;
147 
148 	std::unique_ptr<QOffscreenSurface> OffscreenSurface(new QOffscreenSurface());
149 
150 	if (!OffscreenSurface)
151 		return false;
152 
153 	OffscreenSurface->create();
154 
155 	if (!OffscreenSurface->isValid())
156 		return false;
157 
158 	if (!OffscreenContext->makeCurrent(OffscreenSurface.get()))
159 		return false;
160 
161 	mOffscreenContext = std::move(OffscreenContext);
162 	mOffscreenSurface = std::move(OffscreenSurface);
163 
164 	return true;
165 }
166 
DestroyOffscreenContext()167 void lcContext::DestroyOffscreenContext()
168 {
169 	mOffscreenSurface.reset();
170 	mOffscreenContext.reset();
171 }
172 
CreateShaderPrograms()173 void lcContext::CreateShaderPrograms()
174 {
175 	const char* ShaderPrefix =
176 	{
177 #ifndef LC_OPENGLES
178 "#version 110\n"
179 "#define mediump\n"
180 "#define LC_VERTEX_INPUT attribute\n"
181 "#define LC_VERTEX_OUTPUT varying\n"
182 "#define LC_PIXEL_INPUT varying\n"
183 "#define LC_PIXEL_OUTPUT\n"
184 "#define LC_SHADER_PRECISION\n"
185 #else
186 "#version 300 es\n"
187 "#define texture2D texture\n"
188 "#define LC_VERTEX_INPUT in\n"
189 "#define LC_VERTEX_OUTPUT out\n"
190 "#define LC_PIXEL_INPUT in mediump\n"
191 "#define gl_FragColor FragColor\n"
192 "#define LC_PIXEL_OUTPUT out mediump vec4 gl_FragColor;\n"
193 "#define LC_SHADER_PRECISION mediump\n"
194 #endif
195 
196 "#define LC_PIXEL_FAKE_LIGHTING \\\n"
197 "		LC_SHADER_PRECISION vec3 Normal = normalize(PixelNormal); \\\n"
198 "		LC_SHADER_PRECISION vec3 LightDirection = normalize(PixelPosition - LightPosition); \\\n"
199 "		LC_SHADER_PRECISION vec3 VertexToEye = normalize(EyePosition - PixelPosition); \\\n"
200 "		LC_SHADER_PRECISION vec3 LightReflect = normalize(reflect(-LightDirection, Normal)); \\\n"
201 "		LC_SHADER_PRECISION float Specular = abs(dot(VertexToEye, LightReflect)); \\\n"
202 "		Specular = min(pow(Specular, 8.0), 1.0) * 0.25; \\\n"
203 "		LC_SHADER_PRECISION vec3 SpecularColor = vec3(Specular, Specular, Specular); \\\n"
204 "		LC_SHADER_PRECISION float Diffuse = min(abs(dot(Normal, LightDirection)) * 0.6 + 0.65, 1.0);\n"
205 	};
206 
207 	const char* const VertexShaders[] =
208 	{
209 		":/resources/shaders/unlit_color_vs.glsl",             // UnlitColor
210 		":/resources/shaders/unlit_color_conditional_vs.glsl", // UnlitColorConditional
211 		":/resources/shaders/unlit_texture_modulate_vs.glsl",  // UnlitTextureModulate
212 		":/resources/shaders/unlit_texture_decal_vs.glsl",     // UnlitTextureDecal
213 		":/resources/shaders/unlit_vertex_color_vs.glsl",      // UnlitVertexColor
214 		":/resources/shaders/unlit_view_sphere_vs.glsl",       // UnlitViewSphere
215 		":/resources/shaders/fakelit_color_vs.glsl",           // FakeLitColor
216 		":/resources/shaders/fakelit_texture_decal_vs.glsl"    // FakeLitTextureDecal
217 	};
218 
219 	LC_ARRAY_SIZE_CHECK(VertexShaders, lcMaterialType::Count);
220 
221 	const char* const FragmentShaders[] =
222 	{
223 		":/resources/shaders/unlit_color_ps.glsl",             // UnlitColor
224 		":/resources/shaders/unlit_color_conditional_ps.glsl", // UnlitColorConditional
225 		":/resources/shaders/unlit_texture_modulate_ps.glsl",  // UnlitTextureModulate
226 		":/resources/shaders/unlit_texture_decal_ps.glsl",     // UnlitTextureDecal
227 		":/resources/shaders/unlit_vertex_color_ps.glsl",      // UnlitVertexColor
228 		":/resources/shaders/unlit_view_sphere_ps.glsl",       // UnlitViewSphere
229 		":/resources/shaders/fakelit_color_ps.glsl",           // FakeLitColor
230 		":/resources/shaders/fakelit_texture_decal_ps.glsl"    // FakeLitTextureDecal
231 	};
232 
233 	LC_ARRAY_SIZE_CHECK(FragmentShaders, lcMaterialType::Count);
234 
235 	const auto LoadShader = [this, ShaderPrefix](const char* FileName, GLuint ShaderType) -> GLuint
236 	{
237 		QFile ShaderFile(FileName);
238 
239 		if (!ShaderFile.open(QIODevice::ReadOnly))
240 			return 0;
241 
242 		QByteArray Data = ShaderPrefix + ShaderFile.readAll();
243 		const char* Source = Data.constData();
244 
245 		const GLuint Shader = glCreateShader(ShaderType);
246 		glShaderSource(Shader, 1, &Source, nullptr);
247 		glCompileShader(Shader);
248 
249 #ifndef QT_NO_DEBUG
250 		GLint ShaderCompiled = 0;
251 		glGetShaderiv(Shader, GL_COMPILE_STATUS, &ShaderCompiled);
252 
253 		if (ShaderCompiled == GL_FALSE)
254 		{
255 			GLint Length = 0;
256 			glGetShaderiv(Shader, GL_INFO_LOG_LENGTH, &Length);
257 
258 			QByteArray InfoLog;
259 			InfoLog.resize(Length);
260 			glGetShaderInfoLog(Shader, Length, &Length, InfoLog.data());
261 
262 			qDebug() << InfoLog;
263 		}
264 #endif
265 
266 		return Shader;
267 	};
268 
269 	for (int MaterialType = 0; MaterialType < static_cast<int>(lcMaterialType::Count); MaterialType++)
270 	{
271 		const GLuint VertexShader = LoadShader(VertexShaders[MaterialType], GL_VERTEX_SHADER);
272 		const GLuint FragmentShader = LoadShader(FragmentShaders[MaterialType], GL_FRAGMENT_SHADER);
273 
274 		GLuint Program = glCreateProgram();
275 
276 		glAttachShader(Program, VertexShader);
277 		glAttachShader(Program, FragmentShader);
278 
279 		glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::Position), "VertexPosition");
280 		glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::Normal), "VertexNormal");
281 		glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::TexCoord), "VertexTexCoord");
282 		glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::Color), "VertexColor");
283 
284 		glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::ControlPoint1), "VertexPosition1");
285 		glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::ControlPoint2), "VertexPosition2");
286 		glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::ControlPoint3), "VertexPosition3");
287 		glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::ControlPoint4), "VertexPosition4");
288 
289 		glLinkProgram(Program);
290 
291 		glDetachShader(Program, VertexShader);
292 		glDetachShader(Program, FragmentShader);
293 		glDeleteShader(VertexShader);
294 		glDeleteShader(FragmentShader);
295 
296 		GLint IsLinked = 0;
297 		glGetProgramiv(Program, GL_LINK_STATUS, &IsLinked);
298 
299 		if (IsLinked == GL_FALSE)
300 		{
301 			GLint Length = 0;
302 			glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &Length);
303 
304 			QByteArray InfoLog;
305 			InfoLog.resize(Length);
306 			glGetProgramInfoLog(Program, Length, &Length, InfoLog.data());
307 
308 			glDeleteProgram(Program);
309 			Program = 0;
310 		}
311 
312 		mPrograms[MaterialType].Object = Program;
313 		mPrograms[MaterialType].WorldViewProjectionMatrixLocation = glGetUniformLocation(Program, "WorldViewProjectionMatrix");
314 		mPrograms[MaterialType].WorldMatrixLocation = glGetUniformLocation(Program, "WorldMatrix");
315 		mPrograms[MaterialType].MaterialColorLocation = glGetUniformLocation(Program, "MaterialColor");
316 		mPrograms[MaterialType].LightPositionLocation = glGetUniformLocation(Program, "LightPosition");
317 		mPrograms[MaterialType].EyePositionLocation = glGetUniformLocation(Program, "EyePosition");
318 		mPrograms[MaterialType].HighlightParamsLocation = glGetUniformLocation(Program, "HighlightParams");
319 
320 		GLint TextureLocation = glGetUniformLocation(Program, "Texture");
321 
322 		if (TextureLocation != -1)
323 		{
324 			glUseProgram(Program);
325 			glUniform1i(TextureLocation, 0);
326 			glUseProgram(0);
327 		}
328 	}
329 }
330 
CreateResources()331 void lcContext::CreateResources()
332 {
333 	if (!gSupportsShaderObjects)
334 		return;
335 
336 	CreateShaderPrograms();
337 }
338 
DestroyResources()339 void lcContext::DestroyResources()
340 {
341 	if (!gSupportsShaderObjects)
342 		return;
343 
344 	for (int MaterialType = 0; MaterialType < static_cast<int>(lcMaterialType::Count); MaterialType++)
345 	{
346 		glDeleteProgram(mPrograms[MaterialType].Object);
347 		mPrograms[MaterialType].Object = 0;
348 	}
349 }
350 
MakeCurrent()351 void lcContext::MakeCurrent()
352 {
353 	if (mWidget)
354 		mWidget->makeCurrent();
355 	else
356 		mOffscreenContext->makeCurrent(mOffscreenSurface.get());
357 }
358 
SetGLContext(QOpenGLContext * Context,QOpenGLWidget * Widget)359 void lcContext::SetGLContext(QOpenGLContext* Context, QOpenGLWidget* Widget)
360 {
361 	mContext = Context;
362 	mWidget = Widget;
363 
364 	MakeCurrent();
365 	initializeOpenGLFunctions();
366 }
367 
SetOffscreenContext()368 void lcContext::SetOffscreenContext()
369 {
370 	SetGLContext(mOffscreenContext.get(), nullptr);
371 }
372 
SetDefaultState()373 void lcContext::SetDefaultState()
374 {
375 #ifndef LC_OPENGLES
376 	if (QSurfaceFormat::defaultFormat().samples() > 1)
377 		glEnable(GL_LINE_SMOOTH);
378 #endif
379 
380 	glEnable(GL_DEPTH_TEST);
381 	glDepthFunc(GL_LEQUAL);
382 	mDepthFunction = lcDepthFunction::LessEqual;
383 
384 	if (gSupportsBlendFuncSeparate)
385 		glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE);
386 	else
387 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
388 
389 	if (gSupportsVertexBufferObject)
390 	{
391 		glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
392 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
393 	}
394 
395 	if (gSupportsShaderObjects)
396 	{
397 		SetVertexAttribPointer(lcProgramAttrib::Position, 3, GL_FLOAT, false, 0, nullptr);
398 		EnableVertexAttrib(lcProgramAttrib::Position);
399 
400 		DisableVertexAttrib(lcProgramAttrib::Normal);
401 		SetVertexAttribPointer(lcProgramAttrib::Normal, 4, GL_BYTE, true, 0, nullptr);
402 		DisableVertexAttrib(lcProgramAttrib::TexCoord);
403 		SetVertexAttribPointer(lcProgramAttrib::TexCoord, 2, GL_FLOAT, false, 0, nullptr);
404 		DisableVertexAttrib(lcProgramAttrib::Color);
405 		SetVertexAttribPointer(lcProgramAttrib::Color, 4, GL_FLOAT, false, 0, nullptr);
406 	}
407 	else
408 	{
409 #ifndef LC_OPENGLES
410 		glEnableClientState(GL_VERTEX_ARRAY);
411 		glDisableClientState(GL_NORMAL_ARRAY);
412 		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
413 		glDisableClientState(GL_COLOR_ARRAY);
414 
415 		glVertexPointer(3, GL_FLOAT, 0, nullptr);
416 		glNormalPointer(GL_BYTE, 0, nullptr);
417 		glTexCoordPointer(2, GL_FLOAT, 0, nullptr);
418 		glColorPointer(4, GL_FLOAT, 0, nullptr);
419 
420 		mNormalEnabled = false;
421 		mTexCoordEnabled = false;
422 		mColorEnabled = false;
423 #endif
424 	}
425 
426 	mVertexBufferObject = 0;
427 	mIndexBufferObject = 0;
428 	mVertexBufferPointer = nullptr;
429 	mIndexBufferPointer = nullptr;
430 	mVertexBufferOffset = (char*)~0;
431 
432 	for (int AttribIndex = 0; AttribIndex < static_cast<int>(lcProgramAttrib::Count); AttribIndex++)
433 		mVertexAttribState[AttribIndex] = lcVertexAttribState();
434 
435 	glBindTexture(GL_TEXTURE_2D, 0);
436 	mTexture2D = 0;
437 	glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
438 	mTextureCubeMap = 0;
439 
440 	glDisable(GL_POLYGON_OFFSET_FILL);
441 	mPolygonOffset = lcPolygonOffset::None;
442 
443 	mDepthWrite = true;
444 	glDepthMask(GL_TRUE);
445 
446 	glDisable(GL_CULL_FACE);
447 	mCullFace = false;
448 
449 	glLineWidth(1.0f);
450 	mLineWidth = 1.0f;
451 
452 	if (gSupportsShaderObjects)
453 	{
454 		glUseProgram(0);
455 		mMaterialType = lcMaterialType::Count;
456 	}
457 	else
458 	{
459 #ifndef LC_OPENGLES
460 		glMatrixMode(GL_MODELVIEW);
461 		mMatrixMode = GL_MODELVIEW;
462 		glShadeModel(GL_FLAT);
463 
464 		glDisable(GL_TEXTURE_2D);
465 		mTextureEnabled = false;
466 #endif
467 	}
468 }
469 
ClearColorAndDepth(const lcVector4 & ClearColor)470 void lcContext::ClearColorAndDepth(const lcVector4& ClearColor)
471 {
472 	glClearColor(ClearColor[0], ClearColor[1], ClearColor[2], ClearColor[3]);
473 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
474 }
475 
ClearDepth()476 void lcContext::ClearDepth()
477 {
478 	glClear(GL_DEPTH_BUFFER_BIT);
479 }
480 
ClearResources()481 void lcContext::ClearResources()
482 {
483 	ClearVertexBuffer();
484 	ClearIndexBuffer();
485 	BindTexture2D(0);
486 }
487 
SetMaterial(lcMaterialType MaterialType)488 void lcContext::SetMaterial(lcMaterialType MaterialType)
489 {
490 	if (MaterialType == mMaterialType)
491 		return;
492 
493 	mMaterialType = MaterialType;
494 
495 	if (gSupportsShaderObjects)
496 	{
497 		glUseProgram(mPrograms[static_cast<int>(MaterialType)].Object);
498 		mColorDirty = true;
499 		mWorldMatrixDirty = true; // todo: change dirty to a bitfield and set the lighting constants dirty here
500 		mViewMatrixDirty = true;
501 		mHighlightParamsDirty = true;
502 	}
503 	else
504 	{
505 #ifndef LC_OPENGLES
506 		switch (MaterialType)
507 		{
508 		case lcMaterialType::UnlitTextureModulate:
509 			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
510 
511 			if (!mTextureEnabled)
512 			{
513 				glEnable(GL_TEXTURE_2D);
514 				mTextureEnabled = true;
515 			}
516 			break;
517 
518 		case lcMaterialType::FakeLitTextureDecal:
519 		case lcMaterialType::UnlitTextureDecal:
520 			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
521 
522 			if (!mTextureEnabled)
523 			{
524 				glEnable(GL_TEXTURE_2D);
525 				mTextureEnabled = true;
526 			}
527 			break;
528 
529 		case lcMaterialType::UnlitColor:
530 		case lcMaterialType::UnlitColorConditional:
531 		case lcMaterialType::UnlitVertexColor:
532 		case lcMaterialType::FakeLitColor:
533 			if (mTextureEnabled)
534 			{
535 				glDisable(GL_TEXTURE_2D);
536 				mTextureEnabled = false;
537 			}
538 			break;
539 
540 		case lcMaterialType::UnlitViewSphere:
541 		case lcMaterialType::Count:
542 			break;
543 		}
544 #endif
545 	}
546 }
547 
SetViewport(int x,int y,int Width,int Height)548 void lcContext::SetViewport(int x, int y, int Width, int Height)
549 {
550 	glViewport(x, y, Width, Height);
551 }
552 
SetPolygonOffset(lcPolygonOffset PolygonOffset)553 void lcContext::SetPolygonOffset(lcPolygonOffset PolygonOffset)
554 {
555 	if (mPolygonOffset == PolygonOffset)
556 		return;
557 
558 	switch (PolygonOffset)
559 	{
560 	case lcPolygonOffset::None:
561 		glDisable(GL_POLYGON_OFFSET_FILL);
562 		break;
563 
564 	case lcPolygonOffset::Opaque:
565 		glPolygonOffset(0.5f, 0.1f);
566 		glEnable(GL_POLYGON_OFFSET_FILL);
567 		break;
568 
569 	case lcPolygonOffset::Translucent:
570 		glPolygonOffset(0.25f, 0.1f);
571 		glEnable(GL_POLYGON_OFFSET_FILL);
572 		break;
573 	}
574 
575 	mPolygonOffset = PolygonOffset;
576 }
577 
SetDepthWrite(bool Enable)578 void lcContext::SetDepthWrite(bool Enable)
579 {
580 	if (Enable == mDepthWrite)
581 		return;
582 
583 	glDepthMask(Enable ? GL_TRUE : GL_FALSE);
584 	mDepthWrite = Enable;
585 }
586 
SetDepthFunction(lcDepthFunction DepthFunction)587 void lcContext::SetDepthFunction(lcDepthFunction DepthFunction)
588 {
589 	if (DepthFunction == mDepthFunction)
590 		return;
591 
592 	switch (DepthFunction)
593 	{
594 	case lcDepthFunction::Always:
595 		glDepthFunc(GL_ALWAYS);
596 		break;
597 
598 	case lcDepthFunction::LessEqual:
599 		glDepthFunc(GL_LEQUAL);
600 		break;
601 	}
602 
603 	mDepthFunction = DepthFunction;
604 }
605 
EnableCullFace(bool Enable)606 void lcContext::EnableCullFace(bool Enable)
607 {
608 	if (Enable == mCullFace)
609 		return;
610 
611 	if (Enable)
612 		glEnable(GL_CULL_FACE);
613 	else
614 		glDisable(GL_CULL_FACE);
615 
616 	mCullFace = Enable;
617 }
618 
SetLineWidth(float LineWidth)619 void lcContext::SetLineWidth(float LineWidth)
620 {
621 	if (LineWidth == mLineWidth)
622 		return;
623 
624 	glLineWidth(LineWidth);
625 	mLineWidth = LineWidth;
626 }
627 
SetSmoothShading(bool Smooth)628 void lcContext::SetSmoothShading(bool Smooth)
629 {
630 #ifndef LC_OPENGLES
631 	if (gSupportsShaderObjects)
632 		glShadeModel(Smooth ? GL_SMOOTH : GL_FLAT);
633 #endif
634 }
635 
BindTexture2D(GLuint Texture)636 void lcContext::BindTexture2D(GLuint Texture)
637 {
638 	if (mTexture2D == Texture)
639 		return;
640 
641 	glBindTexture(GL_TEXTURE_2D, Texture);
642 	mTexture2D = Texture;
643 }
644 
BindTextureCubeMap(GLuint Texture)645 void lcContext::BindTextureCubeMap(GLuint Texture)
646 {
647 	if (mTextureCubeMap == Texture)
648 		return;
649 
650 	glBindTexture(GL_TEXTURE_CUBE_MAP, Texture);
651 	mTextureCubeMap = Texture;
652 }
653 
UnbindTexture2D(GLuint Texture)654 void lcContext::UnbindTexture2D(GLuint Texture)
655 {
656 	if (mTexture2D != Texture)
657 		return;
658 
659 	glBindTexture(GL_TEXTURE_2D, 0);
660 	mTexture2D = 0;
661 }
662 
UnbindTextureCubeMap(GLuint Texture)663 void lcContext::UnbindTextureCubeMap(GLuint Texture)
664 {
665 	if (mTextureCubeMap != Texture)
666 		return;
667 
668 	glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
669 	mTextureCubeMap = 0;
670 }
671 
SetColor(float Red,float Green,float Blue,float Alpha)672 void lcContext::SetColor(float Red, float Green, float Blue, float Alpha)
673 {
674 	SetColor(lcVector4(Red, Green, Blue, Alpha));
675 }
676 
SetColorIndex(int ColorIndex)677 void lcContext::SetColorIndex(int ColorIndex)
678 {
679 	SetColor(gColorList[ColorIndex].Value);
680 }
681 
SetColorIndexTinted(int ColorIndex,lcInterfaceColor InterfaceColor,float Weight)682 void lcContext::SetColorIndexTinted(int ColorIndex, lcInterfaceColor InterfaceColor, float Weight)
683 {
684 	const lcVector3 Color(gColorList[ColorIndex].Value * Weight + gInterfaceColors[InterfaceColor] * (1.0f - Weight));
685 	SetColor(lcVector4(Color, gColorList[ColorIndex].Value.w));
686 }
687 
SetColorIndexTinted(int ColorIndex,const lcVector4 & Tint)688 void lcContext::SetColorIndexTinted(int ColorIndex, const lcVector4& Tint)
689 {
690 	SetColor(gColorList[ColorIndex].Value * Tint);
691 }
692 
SetEdgeColorIndex(int ColorIndex)693 void lcContext::SetEdgeColorIndex(int ColorIndex)
694 {
695 	SetColor(gColorList[ColorIndex].Edge);
696 }
697 
SetEdgeColorIndexTinted(int ColorIndex,const lcVector4 & Tint)698 void lcContext::SetEdgeColorIndexTinted(int ColorIndex, const lcVector4& Tint)
699 {
700 	SetColor(gColorList[ColorIndex].Edge * Tint);
701 }
702 
SetInterfaceColor(lcInterfaceColor InterfaceColor)703 void lcContext::SetInterfaceColor(lcInterfaceColor InterfaceColor)
704 {
705 	SetColor(gInterfaceColors[InterfaceColor]);
706 }
707 
CreateVertexBuffer(int Size,const void * Data)708 lcVertexBuffer lcContext::CreateVertexBuffer(int Size, const void* Data)
709 {
710 	lcVertexBuffer VertexBuffer;
711 
712 	if (gSupportsVertexBufferObject)
713 	{
714 		glGenBuffers(1, &VertexBuffer.Object);
715 		glBindBuffer(GL_ARRAY_BUFFER_ARB, VertexBuffer.Object);
716 		glBufferData(GL_ARRAY_BUFFER_ARB, Size, Data, GL_STATIC_DRAW_ARB);
717 
718 		glBindBuffer(GL_ARRAY_BUFFER_ARB, 0); // context remove
719 		mVertexBufferObject = 0;
720 	}
721 	else
722 	{
723 		VertexBuffer.Pointer = malloc(Size);
724 		if (VertexBuffer.Pointer)
725 			memcpy(VertexBuffer.Pointer, Data, Size);
726 	}
727 
728 	return VertexBuffer;
729 }
730 
DestroyVertexBuffer(lcVertexBuffer & VertexBuffer)731 void lcContext::DestroyVertexBuffer(lcVertexBuffer& VertexBuffer)
732 {
733 	if (!VertexBuffer.IsValid())
734 		return;
735 
736 	if (gSupportsVertexBufferObject)
737 	{
738 		if (mVertexBufferObject == VertexBuffer.Object)
739 		{
740 			glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
741 			mVertexBufferObject = 0;
742 		}
743 
744 		glDeleteBuffers(1, &VertexBuffer.Object);
745 	}
746 	else
747 	{
748 		free(VertexBuffer.Pointer);
749 	}
750 
751 	VertexBuffer.Pointer = nullptr;
752 }
753 
CreateIndexBuffer(int Size,const void * Data)754 lcIndexBuffer lcContext::CreateIndexBuffer(int Size, const void* Data)
755 {
756 	lcIndexBuffer IndexBuffer;
757 
758 	if (gSupportsVertexBufferObject)
759 	{
760 		glGenBuffers(1, &IndexBuffer.Object);
761 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, IndexBuffer.Object);
762 		glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, Size, Data, GL_STATIC_DRAW_ARB);
763 
764 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); // context remove
765 		mIndexBufferObject = 0;
766 	}
767 	else
768 	{
769 		IndexBuffer.Pointer = malloc(Size);
770 		if (IndexBuffer.Pointer)
771 			memcpy(IndexBuffer.Pointer, Data, Size);
772 	}
773 
774 	return IndexBuffer;
775 }
776 
DestroyIndexBuffer(lcIndexBuffer & IndexBuffer)777 void lcContext::DestroyIndexBuffer(lcIndexBuffer& IndexBuffer)
778 {
779 	if (!IndexBuffer.IsValid())
780 		return;
781 
782 	if (gSupportsVertexBufferObject)
783 	{
784 		if (mIndexBufferObject == IndexBuffer.Object)
785 		{
786 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
787 			mIndexBufferObject = 0;
788 		}
789 
790 		glDeleteBuffers(1, &IndexBuffer.Object);
791 	}
792 	else
793 	{
794 		free(IndexBuffer.Pointer);
795 	}
796 
797 	IndexBuffer.Pointer = nullptr;
798 }
799 
ClearVertexBuffer()800 void lcContext::ClearVertexBuffer()
801 {
802 	mVertexBufferPointer = nullptr;
803 	mVertexBufferOffset = (char*)~0;
804 
805 	if (mVertexBufferObject)
806 	{
807 		glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
808 		mVertexBufferObject = 0;
809 	}
810 
811 	if (gSupportsShaderObjects)
812 	{
813 		SetVertexAttribPointer(lcProgramAttrib::Position, 3, GL_FLOAT, false, 0, nullptr);
814 
815 		DisableVertexAttrib(lcProgramAttrib::Normal);
816 		SetVertexAttribPointer(lcProgramAttrib::Normal, 4, GL_BYTE, true, 0, nullptr);
817 		DisableVertexAttrib(lcProgramAttrib::TexCoord);
818 		SetVertexAttribPointer(lcProgramAttrib::TexCoord, 2, GL_FLOAT, false, 0, nullptr);
819 		DisableVertexAttrib(lcProgramAttrib::Color);
820 		SetVertexAttribPointer(lcProgramAttrib::Color, 4, GL_FLOAT, false, 0, nullptr);
821 	}
822 	else
823 	{
824 #ifndef LC_OPENGLES
825 		if (mNormalEnabled)
826 			glDisableClientState(GL_NORMAL_ARRAY);
827 
828 		if (mTexCoordEnabled)
829 			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
830 
831 		if (mColorEnabled)
832 			glDisableClientState(GL_COLOR_ARRAY);
833 
834 		glVertexPointer(3, GL_FLOAT, 0, nullptr);
835 		glNormalPointer(GL_BYTE, 0, nullptr);
836 		glTexCoordPointer(2, GL_FLOAT, 0, nullptr);
837 		glColorPointer(4, GL_FLOAT, 0, nullptr);
838 #endif
839 	}
840 }
841 
SetVertexBuffer(lcVertexBuffer VertexBuffer)842 void lcContext::SetVertexBuffer(lcVertexBuffer VertexBuffer)
843 {
844 	if (gSupportsVertexBufferObject)
845 	{
846 		const GLuint VertexBufferObject = VertexBuffer.Object;
847 		mVertexBufferPointer = nullptr;
848 
849 		if (VertexBufferObject != mVertexBufferObject)
850 		{
851 			glBindBuffer(GL_ARRAY_BUFFER_ARB, VertexBufferObject);
852 			mVertexBufferObject = VertexBufferObject;
853 			mVertexBufferOffset = (char*)~0;
854 		}
855 	}
856 	else
857 	{
858 		mVertexBufferPointer = (char*)VertexBuffer.Pointer;
859 		mVertexBufferOffset = (char*)~0;
860 	}
861 }
862 
SetVertexBufferPointer(const void * VertexBuffer)863 void lcContext::SetVertexBufferPointer(const void* VertexBuffer)
864 {
865 	if (gSupportsVertexBufferObject && mVertexBufferObject)
866 	{
867 		glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
868 		mVertexBufferObject = 0;
869 	}
870 
871 	mVertexBufferPointer = (char*)VertexBuffer;
872 	mVertexBufferOffset = (char*)~0;
873 }
874 
SetVertexAttribPointer(lcProgramAttrib Attrib,GLint Size,GLenum Type,GLboolean Normalized,GLsizei Stride,const void * Pointer)875 void lcContext::SetVertexAttribPointer(lcProgramAttrib Attrib, GLint Size, GLenum Type, GLboolean Normalized, GLsizei Stride, const void* Pointer)
876 {
877 	const int Index = static_cast<int>(Attrib);
878 	lcVertexAttribState& State = mVertexAttribState[Index];
879 
880 	if (State.Size != Size || State.Type != Type || State.Normalized != Normalized || State.Stride != Stride || State.Pointer != Pointer || State.VertexBufferObject != mVertexBufferObject)
881 	{
882 		glVertexAttribPointer(Index, Size, Type, Normalized, Stride, Pointer);
883 
884 		State.Size = Size;
885 		State.Type = Type;
886 		State.Normalized = Normalized;
887 		State.Stride = Stride;
888 		State.Pointer = Pointer;
889 		State.VertexBufferObject = mVertexBufferObject;
890 	}
891 }
892 
EnableVertexAttrib(lcProgramAttrib Attrib)893 void lcContext::EnableVertexAttrib(lcProgramAttrib Attrib)
894 {
895 	const int Index = static_cast<int>(Attrib);
896 	lcVertexAttribState& State = mVertexAttribState[Index];
897 
898 	if (!State.Enabled)
899 	{
900 		glEnableVertexAttribArray(Index);
901 		State.Enabled = true;
902 	}
903 }
904 
DisableVertexAttrib(lcProgramAttrib Attrib)905 void lcContext::DisableVertexAttrib(lcProgramAttrib Attrib)
906 {
907 	const int Index = static_cast<int>(Attrib);
908 	lcVertexAttribState& State = mVertexAttribState[Index];
909 
910 	if (State.Enabled)
911 	{
912 		glDisableVertexAttribArray(Index);
913 		State.Enabled = false;
914 	}
915 }
916 
SetVertexFormatPosition(int PositionSize)917 void lcContext::SetVertexFormatPosition(int PositionSize)
918 {
919 	const int VertexSize = PositionSize * sizeof(float);
920 	const char* VertexBufferPointer = mVertexBufferPointer;
921 
922 	if (gSupportsShaderObjects)
923 	{
924 		SetVertexAttribPointer(lcProgramAttrib::Position, PositionSize, GL_FLOAT, false, VertexSize, VertexBufferPointer);
925 		DisableVertexAttrib(lcProgramAttrib::Normal);
926 		DisableVertexAttrib(lcProgramAttrib::TexCoord);
927 		DisableVertexAttrib(lcProgramAttrib::Color);
928 	}
929 	else
930 	{
931 		if (mVertexBufferOffset != mVertexBufferPointer)
932 		{
933 			glVertexPointer(PositionSize, GL_FLOAT, VertexSize, VertexBufferPointer);
934 			mVertexBufferOffset = VertexBufferPointer;
935 		}
936 
937 		if (mNormalEnabled)
938 		{
939 			glDisableClientState(GL_NORMAL_ARRAY);
940 			mNormalEnabled = false;
941 		}
942 
943 		if (mTexCoordEnabled)
944 		{
945 			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
946 			mTexCoordEnabled = false;
947 		}
948 
949 		if (mColorEnabled)
950 		{
951 			glDisableClientState(GL_COLOR_ARRAY);
952 			mColorEnabled = false;
953 		}
954 	}
955 }
956 
SetVertexFormatConditional(int BufferOffset)957 void lcContext::SetVertexFormatConditional(int BufferOffset)
958 {
959 	const int VertexSize = 12 * sizeof(float);
960 	const char* VertexBufferPointer = mVertexBufferPointer + BufferOffset;
961 
962 	if (gSupportsShaderObjects)
963 	{
964 		SetVertexAttribPointer(lcProgramAttrib::ControlPoint1, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer);
965 		EnableVertexAttrib(lcProgramAttrib::ControlPoint1);
966 		SetVertexAttribPointer(lcProgramAttrib::ControlPoint2, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer + 3 * sizeof(float));
967 		EnableVertexAttrib(lcProgramAttrib::ControlPoint2);
968 		SetVertexAttribPointer(lcProgramAttrib::ControlPoint3, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer + 6 * sizeof(float));
969 		EnableVertexAttrib(lcProgramAttrib::ControlPoint3);
970 		SetVertexAttribPointer(lcProgramAttrib::ControlPoint4, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer + 9 * sizeof(float));
971 		EnableVertexAttrib(lcProgramAttrib::ControlPoint4);
972 	}
973 }
974 
SetVertexFormat(int BufferOffset,int PositionSize,int NormalSize,int TexCoordSize,int ColorSize,bool EnableNormals)975 void lcContext::SetVertexFormat(int BufferOffset, int PositionSize, int NormalSize, int TexCoordSize, int ColorSize, bool EnableNormals)
976 {
977 	const int VertexSize = (PositionSize + TexCoordSize) * sizeof(float) + NormalSize * sizeof(quint32) + ColorSize;
978 	const char* VertexBufferPointer = mVertexBufferPointer + BufferOffset;
979 
980 	if (gSupportsShaderObjects)
981 	{
982 		int Offset = 0;
983 
984 		SetVertexAttribPointer(lcProgramAttrib::Position, PositionSize, GL_FLOAT, false, VertexSize, VertexBufferPointer);
985 		EnableVertexAttrib(lcProgramAttrib::Position);
986 
987 		Offset += PositionSize * sizeof(float);
988 
989 		if (NormalSize && EnableNormals)
990 		{
991 			SetVertexAttribPointer(lcProgramAttrib::Normal, 4, GL_BYTE, true, VertexSize, VertexBufferPointer + Offset);
992 			EnableVertexAttrib(lcProgramAttrib::Normal);
993 		}
994 		else
995 			DisableVertexAttrib(lcProgramAttrib::Normal);
996 
997 		Offset += NormalSize * sizeof(quint32);
998 
999 		if (TexCoordSize)
1000 		{
1001 			SetVertexAttribPointer(lcProgramAttrib::TexCoord, TexCoordSize, GL_FLOAT, false, VertexSize, VertexBufferPointer + Offset);
1002 			EnableVertexAttrib(lcProgramAttrib::TexCoord);
1003 		}
1004 		else
1005 			DisableVertexAttrib(lcProgramAttrib::TexCoord);
1006 
1007 		Offset += TexCoordSize * sizeof(float);
1008 
1009 		if (ColorSize)
1010 		{
1011 			SetVertexAttribPointer(lcProgramAttrib::Color, ColorSize, GL_UNSIGNED_BYTE, true, VertexSize, VertexBufferPointer + Offset);
1012 			EnableVertexAttrib(lcProgramAttrib::Color);
1013 		}
1014 		else
1015 			DisableVertexAttrib(lcProgramAttrib::Color);
1016 	}
1017 	else
1018 	{
1019 #ifndef LC_OPENGLES
1020 		if (mVertexBufferOffset != VertexBufferPointer)
1021 		{
1022 			glVertexPointer(PositionSize, GL_FLOAT, VertexSize, VertexBufferPointer);
1023 			mVertexBufferOffset = VertexBufferPointer;
1024 		}
1025 
1026 		int Offset = PositionSize * sizeof(float);
1027 
1028 		if (NormalSize && EnableNormals)
1029 		{
1030 			glNormalPointer(GL_BYTE, VertexSize, VertexBufferPointer + Offset);
1031 
1032 			if (!mNormalEnabled)
1033 			{
1034 				glEnableClientState(GL_NORMAL_ARRAY);
1035 				mNormalEnabled = true;
1036 			}
1037 		}
1038 		else if (mNormalEnabled)
1039 		{
1040 			glDisableClientState(GL_NORMAL_ARRAY);
1041 			mNormalEnabled = false;
1042 		}
1043 
1044 		Offset += NormalSize * sizeof(quint32);
1045 
1046 		if (TexCoordSize)
1047 		{
1048 			glTexCoordPointer(TexCoordSize, GL_FLOAT, VertexSize, VertexBufferPointer + Offset);
1049 
1050 			if (!mTexCoordEnabled)
1051 			{
1052 				glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1053 				mTexCoordEnabled = true;
1054 			}
1055 
1056 			Offset += 2 * sizeof(float);
1057 		}
1058 		else if (mTexCoordEnabled)
1059 		{
1060 			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1061 			mTexCoordEnabled = false;
1062 		}
1063 
1064 		if (ColorSize)
1065 		{
1066 			glColorPointer(ColorSize, GL_FLOAT, VertexSize, VertexBufferPointer + Offset);
1067 
1068 			if (!mColorEnabled)
1069 			{
1070 				glEnableClientState(GL_COLOR_ARRAY);
1071 				mColorEnabled = true;
1072 			}
1073 		}
1074 		else if (mColorEnabled)
1075 		{
1076 			glDisableClientState(GL_COLOR_ARRAY);
1077 			mColorEnabled = false;
1078 		}
1079 #endif
1080 	}
1081 }
1082 
ClearIndexBuffer()1083 void lcContext::ClearIndexBuffer()
1084 {
1085 	if (mIndexBufferObject)
1086 	{
1087 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1088 		mIndexBufferObject = 0;
1089 	}
1090 }
1091 
SetIndexBuffer(lcIndexBuffer IndexBuffer)1092 void lcContext::SetIndexBuffer(lcIndexBuffer IndexBuffer)
1093 {
1094 	if (gSupportsVertexBufferObject)
1095 	{
1096 		const GLuint IndexBufferObject = IndexBuffer.Object;
1097 		mIndexBufferPointer = nullptr;
1098 
1099 		if (IndexBufferObject != mIndexBufferObject)
1100 		{
1101 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, IndexBufferObject);
1102 			mIndexBufferObject = IndexBufferObject;
1103 		}
1104 	}
1105 	else
1106 	{
1107 		mIndexBufferPointer = (char*)IndexBuffer.Pointer;
1108 	}
1109 }
1110 
SetIndexBufferPointer(const void * IndexBuffer)1111 void lcContext::SetIndexBufferPointer(const void* IndexBuffer)
1112 {
1113 	if (mIndexBufferObject)
1114 	{
1115 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1116 		mIndexBufferObject = 0;
1117 	}
1118 
1119 	mIndexBufferPointer = (char*)IndexBuffer;
1120 }
1121 
BindMesh(const lcMesh * Mesh)1122 void lcContext::BindMesh(const lcMesh* Mesh)
1123 {
1124 	const lcPiecesLibrary* const Library = lcGetPiecesLibrary();
1125 
1126 	if (Mesh->mVertexCacheOffset != -1)
1127 	{
1128 		const GLuint VertexBufferObject = Library->mVertexBuffer.Object;
1129 		const GLuint IndexBufferObject = Library->mIndexBuffer.Object;
1130 
1131 		if (VertexBufferObject != mVertexBufferObject)
1132 		{
1133 			glBindBuffer(GL_ARRAY_BUFFER_ARB, VertexBufferObject);
1134 			mVertexBufferObject = VertexBufferObject;
1135 			mVertexBufferPointer = nullptr;
1136 			mVertexBufferOffset = (char*)~0;
1137 		}
1138 
1139 		if (IndexBufferObject != mIndexBufferObject)
1140 		{
1141 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, IndexBufferObject);
1142 			mIndexBufferObject = IndexBufferObject;
1143 			mIndexBufferPointer = nullptr;
1144 		}
1145 	}
1146 	else
1147 	{
1148 		if (mVertexBufferObject)
1149 		{
1150 			glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
1151 			mVertexBufferObject = 0;
1152 		}
1153 
1154 		if (mIndexBufferObject)
1155 		{
1156 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1157 			mIndexBufferObject = 0;
1158 		}
1159 
1160 		mVertexBufferPointer = (char*)Mesh->mVertexData;
1161 		mIndexBufferPointer = (char*)Mesh->mIndexData;
1162 		mVertexBufferOffset = (char*)~0;
1163 	}
1164 }
1165 
FlushState()1166 void lcContext::FlushState()
1167 {
1168 	if (gSupportsShaderObjects)
1169 	{
1170 		const lcProgram& Program = mPrograms[static_cast<int>(mMaterialType)];
1171 
1172 		if (mWorldMatrixDirty || mViewMatrixDirty || mProjectionMatrixDirty)
1173 		{
1174 			if (mViewProjectionMatrixDirty)
1175 			{
1176 				mViewProjectionMatrix = lcMul(mViewMatrix, mProjectionMatrix);
1177 				mViewProjectionMatrixDirty = false;
1178 			}
1179 
1180 			if (mWorldMatrixDirty)
1181 			{
1182 				if (Program.WorldMatrixLocation != -1)
1183 					glUniformMatrix4fv(Program.WorldMatrixLocation, 1, false, mWorldMatrix);
1184 			}
1185 
1186 			if (mViewMatrixDirty)
1187 			{
1188 				const lcMatrix44 InverseViewMatrix = lcMatrix44AffineInverse(mViewMatrix);
1189 				lcVector3 ViewPosition = lcMul30(-mViewMatrix.GetTranslation(), InverseViewMatrix);
1190 
1191 				if (Program.LightPositionLocation != -1)
1192 				{
1193 					lcVector3 LightPosition = ViewPosition + lcMul30(lcVector3(300.0f, 300.0f, 0.0f), InverseViewMatrix);
1194 					glUniform3fv(Program.LightPositionLocation, 1, LightPosition);
1195 				}
1196 
1197 				if (Program.EyePositionLocation != -1)
1198 					glUniform3fv(Program.EyePositionLocation, 1, ViewPosition);
1199 			}
1200 
1201 			glUniformMatrix4fv(Program.WorldViewProjectionMatrixLocation, 1, false, lcMul(mWorldMatrix, mViewProjectionMatrix));
1202 			mWorldMatrixDirty = false;
1203 			mViewMatrixDirty = false;
1204 			mProjectionMatrixDirty = false;
1205 		}
1206 
1207 		if (mColorDirty && Program.MaterialColorLocation != -1)
1208 		{
1209 			glUniform4fv(Program.MaterialColorLocation, 1, mColor);
1210 			mColorDirty = false;
1211 		}
1212 
1213 		if (mHighlightParamsDirty && Program.HighlightParamsLocation != -1)
1214 		{
1215 			glUniform4fv(Program.HighlightParamsLocation, 4, mHighlightParams[0]);
1216 			mHighlightParamsDirty = false;
1217 		}
1218 	}
1219 	else
1220 	{
1221 #ifndef LC_OPENGLES
1222 		glColor4fv(mColor);
1223 
1224 		if (mWorldMatrixDirty || mViewMatrixDirty)
1225 		{
1226 			if (mMatrixMode != GL_MODELVIEW)
1227 			{
1228 				glMatrixMode(GL_MODELVIEW);
1229 				mMatrixMode = GL_MODELVIEW;
1230 			}
1231 
1232 			glLoadMatrixf(lcMul(mWorldMatrix, mViewMatrix));
1233 			mWorldMatrixDirty = false;
1234 			mViewMatrixDirty = false;
1235 		}
1236 
1237 		if (mProjectionMatrixDirty)
1238 		{
1239 			if (mMatrixMode != GL_PROJECTION)
1240 			{
1241 				glMatrixMode(GL_PROJECTION);
1242 				mMatrixMode = GL_PROJECTION;
1243 			}
1244 
1245 			glLoadMatrixf(mProjectionMatrix);
1246 			mProjectionMatrixDirty = false;
1247 		}
1248 #endif
1249 	}
1250 }
1251 
DrawPrimitives(GLenum Mode,GLint First,GLsizei Count)1252 void lcContext::DrawPrimitives(GLenum Mode, GLint First, GLsizei Count)
1253 {
1254 	FlushState();
1255 	glDrawArrays(Mode, First, Count);
1256 }
1257 
DrawIndexedPrimitives(GLenum Mode,GLsizei Count,GLenum Type,int Offset)1258 void lcContext::DrawIndexedPrimitives(GLenum Mode, GLsizei Count, GLenum Type, int Offset)
1259 {
1260 	FlushState();
1261 	glDrawElements(Mode, Count, Type, mIndexBufferPointer + Offset);
1262 }
1263