Jason McKesson avatar Jason McKesson committed 53e623a

Partial scene graph stuff.

Comments (0)

Files changed (8)

Documents/sceneFormat.rnc

+datatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+namespace scn = "http://www.arcsynthesis.com/gltut/scene"
+
+##Structure and elements
+div
+{
+    start = sc.rootelements
+    
+    sc.rootelements =
+        sc.scene
+        
+    sc.scene =
+        ##The root element. Contains the meshes, programs, and nodes.
+        element scn:scene { sc.scene.content }
+
+    sc.scene.content =
+        (sc.mesh | sc.prog | sc.node)+
+        
+    sc.mesh =
+        ##A mesh to load. Meshes have names and filenames.
+        element scn:mesh { sc.mesh.content }
+        
+    sc.mesh.content =
+        sc.mesh.attlist
+        
+    sc.prog =
+        ##A shader program. It represents a number of shaders, as well as uniforms and pre-4.20
+        ##bindings.
+        element scn:prog { sc.prog.content }
+        
+    sc.prog.content =
+        sc.prog.attlist, (sc.sampler | sc.block)*
+    
+    sc.sampler =
+        ##Associates a sampler uniform with a texture unit.
+        element scn:sampler { sc.sampler.content }
+        
+    sc.sampler.content =
+        sc.sampler.attlist
+        
+    sc.block =
+        ##Associates a uniform block with a block binding
+        element scn:block { sc.block.content }
+        
+    sc.block.content =
+        sc.block.attlist
+        
+    sc.node =
+        ##Defines a named instance of a mesh, program, and other node attributes. 
+        element scn:node { sc.node.content }
+        
+    sc.node.content =
+        sc.node.attlist, (sc.note)*
+        
+    sc.note =
+        ##User-defined strings that can be queried.
+        element scn:note { sc.note.content }
+        
+    sc.note.content =
+        sc.note.attlist, text
+}
+
+##Attributes
+div
+{
+    sc.mesh.attlist =
+        sc.xml.id.attribute, sc.mesh.file.attribute
+    
+    sc.prog.attlist =
+        sc.xml.id.attribute,
+        sc.prog.vert.attribute,
+        sc.prog.frag.attribute,
+        sc.prog.geom.attribute?,
+        sc.prog.model-to-camera.attribute,
+        sc.prog.normal-model-to-camera.attribute?
+        
+    sc.sampler.attlist =
+        sc.sampler.name.attribute, sc.sampler.unit.attribute
+        
+    sc.block.attlist =
+        sc.block.name.attribute, sc.block.binding.attribute
+    
+    sc.node.attlist =
+        sc.node.name.attribute,
+        sc.node.mesh.attribute,
+        sc.node.prog.attribute,
+        sc.node.pos.attribute,
+        sc.node.orient.attribute?,
+        sc.node.scale.attribute?
+    
+    sc.note.attlist =
+        sc.note.name.attribute
+    
+    sc.xml.id.attribute =
+        ##Uniquely named object
+        attribute xml:id { xsd:ID }
+    
+    sc.mesh.file.attribute =
+        ##The mesh's filename.
+        attribute file { acc.filename.type }
+    
+    sc.prog.vert.attribute =
+        ##The vertex shader filename for this program
+        attribute vert { acc.filename.type }
+    
+    sc.prog.frag.attribute =
+        ##The fragment shader filename for this program
+        attribute frag { acc.filename.type }
+    
+    sc.prog.geom.attribute =
+        ##The geometry shader filename for this program
+        attribute geom { acc.filename.type }
+
+    sc.prog.model-to-camera.attribute =
+        ##The uniform name of a mat4 that represents the model-to-camera transform.
+        attribute model-to-camera { acc.uniform.type }
+    
+    sc.prog.normal-model-to-camera.attribute =
+        ##The uniform name of a mat3 that represents the normal model-to-camera transform.
+        attribute normal-model-to-camera { acc.uniform.type }
+
+    sc.sampler.name.attribute =
+        ##The name of a sampler uniform.
+        attribute name { acc.uniform.type }
+    
+    sc.sampler.unit.attribute =
+        ##The texture unit to use with the uniform sampler
+        attribute unit { acc.texture-unit.type }
+    
+    sc.block.name.attribute =
+        ##The name of a uniform block.
+        attribute name { acc.uniform.type }
+
+    sc.block.binding.attribute =
+        ##The uniform buffer binding point to use with this uniform block name. 
+        attribute binding { acc.block-binding.type }
+        
+    sc.node.name.attribute =
+        ##The name of a node. It must be unique.
+        attribute name { text }
+        
+    sc.node.mesh.attribute =
+        ##The name of a mesh. If no mesh is found with this name, an error results.
+        attribute mesh { xsd:IDREF }
+        
+    sc.node.prog.attribute =
+        ##The name of a program. If no program is found, an error rsults.
+        attribute prog { xsd:IDREF }
+        
+    sc.node.pos.attribute =
+        ##The position of the object in world-space.
+        attribute pos { text }
+        
+    sc.node.orient.attribute =
+        ##The orientation of the object in world-space, as a quaternion. In XYZW format.
+        attribute orient { text }
+        
+    sc.node.scale.attribute =
+        ##The scale of the object in world-space. Can be one float or 3.
+        attribute scale { text }
+        
+    sc.note.name.attribute =
+        ##The name of an annotation in a node. The note name must be unique within the node.
+        attribute name { text }
+}
+
+## Accessories
+div
+{
+    acc.texture-unit.type = xsd:nonNegativeInteger { minInclusive = "0" maxExclusive = "80"}
+    acc.block-binding.type = xsd:nonNegativeInteger { minInclusive = "0" maxExclusive = "80"}
+    acc.uniform.type = text
+    acc.filename.type = text
+    acc.attribute.type =
+        xsd:nonNegativeInteger { minInclusive = "0" maxExclusive = "16"}
+}

Tut 17 Spotlight on Textures/Double Projection.cpp

+#include <string>
+#include <vector>
+#include <exception>
+#include <memory>
+#include <glimg/glimg.h>
+#include <glimg/TextureGenerator.h>
+#include <glload/gl_3_3.h>
+#include <GL/freeglut.h>
+#include <glutil/MatrixStack.h>
+#include <glutil/MousePoles.h>
+#include "../framework/framework.h"
+#include "../framework/Mesh.h"
+#include "../framework/Timer.h"
+#include "../framework/UniformBlockArray.h"
+#include "../framework/directories.h"
+#include "../framework/MousePole.h"
+#include "../framework/Interpolators.h"
+#include "../framework/Scene.h"
+#include <glm/glm.hpp>
+#include <glm/gtc/type_ptr.hpp>
+#include <glm/gtc/matrix_transform.hpp>
+
+#define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))
+
+struct ProgramData
+{
+	GLuint theProgram;
+
+	GLuint modelToCameraMatrixUnif;
+	GLuint numberOfLightsUnif;
+};
+
+struct UnlitProgData
+{
+	GLuint theProgram;
+
+	GLuint modelToCameraMatrixUnif;
+	GLuint objectColorUnif;
+};
+
+float g_fzNear = 1.0f;
+float g_fzFar = 1000.0f;
+
+ProgramData g_progStandard;
+UnlitProgData g_progUnlit;
+
+const int g_projectionBlockIndex = 0;
+const int g_lightBlockIndex = 1;
+const int g_colorTexUnit = 0;
+
+ProgramData LoadProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
+{
+	std::vector<GLuint> shaderList;
+
+	shaderList.push_back(Framework::LoadShader(GL_VERTEX_SHADER, strVertexShader));
+	shaderList.push_back(Framework::LoadShader(GL_FRAGMENT_SHADER, strFragmentShader));
+
+	ProgramData data;
+	data.theProgram = Framework::CreateProgram(shaderList);
+	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
+	data.numberOfLightsUnif = glGetUniformLocation(data.theProgram, "numberOfLights");
+
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
+	GLuint lightBlockIndex = glGetUniformBlockIndex(data.theProgram, "Light");
+	glUniformBlockBinding(data.theProgram, lightBlockIndex, g_lightBlockIndex);
+
+	GLuint colorTextureUnif = glGetUniformLocation(data.theProgram, "diffuseColorTex");
+	glUseProgram(data.theProgram);
+	glUniform1i(colorTextureUnif, g_colorTexUnit);
+	glUseProgram(0);
+
+	return data;
+}
+
+UnlitProgData LoadUnlitProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
+{
+	std::vector<GLuint> shaderList;
+
+	shaderList.push_back(Framework::LoadShader(GL_VERTEX_SHADER, strVertexShader));
+	shaderList.push_back(Framework::LoadShader(GL_FRAGMENT_SHADER, strFragmentShader));
+
+	UnlitProgData data;
+	data.theProgram = Framework::CreateProgram(shaderList);
+	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
+	data.objectColorUnif = glGetUniformLocation(data.theProgram, "objectColor");
+
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
+	return data;
+}
+
+void InitializePrograms()
+{
+	g_progStandard = LoadProgram("PNT.vert", "litTexture.frag");
+	g_progUnlit = LoadUnlitProgram("Unlit.vert", "Unlit.frag");
+}
+
+struct ProjectionBlock
+{
+	glm::mat4 cameraToClipMatrix;
+};
+
+GLuint g_projectionUniformBuffer = 0;
+GLuint g_lightUniformBuffer = 0;
+GLuint g_linearTexture = 0;
+// GLuint g_gammaTexture = 0;
+
+const int NUM_SAMPLERS = 2;
+GLuint g_samplers[NUM_SAMPLERS];
+
+void CreateSamplers()
+{
+	glGenSamplers(NUM_SAMPLERS, &g_samplers[0]);
+
+	for(int samplerIx = 0; samplerIx < NUM_SAMPLERS; samplerIx++)
+	{
+		glSamplerParameteri(g_samplers[samplerIx], GL_TEXTURE_WRAP_S, GL_REPEAT);
+		glSamplerParameteri(g_samplers[samplerIx], GL_TEXTURE_WRAP_T, GL_REPEAT);
+	}
+
+	//Linear mipmap linear
+	glSamplerParameteri(g_samplers[0], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	glSamplerParameteri(g_samplers[0], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+
+	//Max anisotropic
+	GLfloat maxAniso = 0.0f;
+	glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso);
+
+	glSamplerParameteri(g_samplers[1], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	glSamplerParameteri(g_samplers[1], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+	glSamplerParameterf(g_samplers[1], GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso);
+}
+
+void LoadTextures()
+{
+	try
+	{
+		std::string filename(Framework::FindFileOrThrow("terrain_tex.dds"));
+
+		std::auto_ptr<glimg::ImageSet> pImageSet(glimg::loaders::dds::LoadFromFile(filename.c_str()));
+
+		glGenTextures(1, &g_linearTexture);
+		glBindTexture(GL_TEXTURE_2D, g_linearTexture);
+
+		glimg::OpenGLPixelTransferParams xfer = glimg::GetUploadFormatType(pImageSet->GetFormat(), 0);
+
+		for(int mipmapLevel = 0; mipmapLevel < pImageSet->GetMipmapCount(); mipmapLevel++)
+		{
+			glimg::SingleImage image = pImageSet->GetImage(mipmapLevel, 0, 0);
+			glimg::Dimensions dims = image.GetDimensions();
+
+			glTexImage2D(GL_TEXTURE_2D, mipmapLevel, GL_SRGB8_ALPHA8, dims.width, dims.height, 0,
+				xfer.format, xfer.type, image.GetImageData());
+		}
+
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, pImageSet->GetMipmapCount() - 1);
+
+		glBindTexture(GL_TEXTURE_2D, 0);
+	}
+	catch(std::exception &e)
+	{
+		printf("%s\n", e.what());
+		throw;
+	}
+}
+
+////////////////////////////////
+//View setup.
+glutil::ViewData g_initialView =
+{
+	glm::vec3(-60.257084f, 10.947238f, 62.636356f),
+	glm::fquat(-0.972817f, -0.099283f, -0.211198f, -0.020028f),
+	30.0f,
+	0.0f
+};
+
+glutil::ViewScale g_initialViewScale =
+{
+	5.0f, 90.0f,
+	2.0f, 0.5f,
+	4.0f, 1.0f,
+	90.0f/250.0f
+};
+
+glutil::ViewPole g_viewPole(g_initialView, g_initialViewScale, glutil::MB_LEFT_BTN);
+
+namespace
+{
+	void MouseMotion(int x, int y) { Framework::ForwardMouseMotion(g_viewPole, x, y); }
+	void MouseButton(int button, int state, int x, int y) { Framework::ForwardMouseButton(g_viewPole, button, state, x, y); }
+	void MouseWheel(int wheel, int direction, int x, int y) { Framework::ForwardMouseWheel(g_viewPole, wheel, direction, x, y); }
+}
+
+Framework::Scene *g_pScene = NULL;
+
+//Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
+void init()
+{
+	try
+	{
+		g_pScene = new Framework::Scene("test.scene");
+//		InitializePrograms();
+	}
+	catch(std::exception &except)
+	{
+		printf("%s\n", except.what());
+		throw;
+	}
+
+	glutMouseFunc(MouseButton);
+	glutMotionFunc(MouseMotion);
+	glutMouseWheelFunc(MouseWheel);
+
+	glEnable(GL_CULL_FACE);
+	glCullFace(GL_BACK);
+	glFrontFace(GL_CW);
+
+	const float depthZNear = 0.0f;
+	const float depthZFar = 1.0f;
+
+	glEnable(GL_DEPTH_TEST);
+	glDepthMask(GL_TRUE);
+	glDepthFunc(GL_LEQUAL);
+	glDepthRange(depthZNear, depthZFar);
+	glEnable(GL_DEPTH_CLAMP);
+
+	//Setup our Uniform Buffers
+	glGenBuffers(1, &g_projectionUniformBuffer);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), NULL, GL_DYNAMIC_DRAW);
+
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_projectionBlockIndex, g_projectionUniformBuffer,
+		0, sizeof(ProjectionBlock));
+
+/*
+	glGenBuffers(1, &g_lightUniformBuffer);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_lightUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(LightBlock), NULL, GL_STREAM_DRAW);
+
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_lightBlockIndex, g_lightUniformBuffer,
+		0, sizeof(LightBlock));
+
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
+*/
+
+//	LoadTextures();
+//	CreateSamplers();
+}
+
+using Framework::Timer;
+
+int g_currSampler = 0;
+
+bool g_bDrawCameraPos = false;
+
+//Called to update the display.
+//You should call glutSwapBuffers after all of your rendering to display what you rendered.
+//If you need continuous updates of the screen, call glutPostRedisplay() at the end of the function.
+void display()
+{
+	if(!g_pScene)
+		return;
+
+	glClearColor(0.8f, 0.8f, 0.8f, 1.0f);
+	glClearDepth(1.0f);
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+/*
+    if(!g_pLightEnv)
+        return;
+
+	glEnable(GL_FRAMEBUFFER_SRGB);
+
+	g_pLightEnv->UpdateTime();
+
+	glm::vec4 bgColor = g_pLightEnv->GetBackgroundColor();
+	glClearColor(bgColor.x, bgColor.y, bgColor.z, bgColor.w);
+	glClearDepth(1.0f);
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	glutil::MatrixStack modelMatrix;
+	modelMatrix.ApplyMatrix(g_viewPole.CalcMatrix());
+
+	LightBlock lightData = g_pLightEnv->GetLightBlock(g_viewPole.CalcMatrix());
+
+	glBindBuffer(GL_UNIFORM_BUFFER, g_lightUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(LightBlock), &lightData, GL_STREAM_DRAW);
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+	if(g_pSphere && g_pTerrain)
+	{
+		glutil::PushStack push(modelMatrix);
+		modelMatrix.RotateX(-90.0f);
+
+		glUseProgram(g_progStandard.theProgram);
+		glUniformMatrix4fv(g_progStandard.modelToCameraMatrixUnif, 1, GL_FALSE,
+			glm::value_ptr(modelMatrix.Top()));
+		glUniform1i(g_progStandard.numberOfLightsUnif, g_pLightEnv->GetNumLights());
+
+		glActiveTexture(GL_TEXTURE0 + g_colorTexUnit);
+		glBindTexture(GL_TEXTURE_2D, g_linearTexture);
+		glBindSampler(g_colorTexUnit, g_samplers[g_currSampler]);
+
+		g_pTerrain->Render("lit-tex");
+
+		glBindSampler(g_colorTexUnit, 0);
+		glBindTexture(GL_TEXTURE_2D, 0);
+
+		glUseProgram(0);
+
+
+		push.ResetStack();
+
+		//Render the sun
+		{
+			glm::vec3 sunlightDir(g_pLightEnv->GetSunlightDirection());
+			modelMatrix.Translate(sunlightDir * 500.0f);
+			modelMatrix.Scale(30.0f, 30.0f, 30.0f);
+
+			glUseProgram(g_progUnlit.theProgram);
+			glUniformMatrix4fv(g_progUnlit.modelToCameraMatrixUnif, 1, GL_FALSE,
+				glm::value_ptr(modelMatrix.Top()));
+
+			glm::vec4 lightColor = g_pLightEnv->GetSunlightScaledIntensity(), gamma;
+			glUniform4fv(g_progUnlit.objectColorUnif, 1, glm::value_ptr(lightColor));
+			g_pSphere->Render("flat");
+		}
+
+		//Draw lights
+		for(int light = 0; light < g_pLightEnv->GetNumPointLights(); light++)
+		{
+			push.ResetStack();
+
+			modelMatrix.Translate(g_pLightEnv->GetPointLightWorldPos(light));
+
+			glUseProgram(g_progUnlit.theProgram);
+			glUniformMatrix4fv(g_progUnlit.modelToCameraMatrixUnif, 1, GL_FALSE,
+				glm::value_ptr(modelMatrix.Top()));
+
+			glm::vec4 lightColor = g_pLightEnv->GetPointLightScaledIntensity(light);
+			glUniform4fv(g_progUnlit.objectColorUnif, 1, glm::value_ptr(lightColor));
+			g_pSphere->Render("flat");
+		}
+
+
+		push.ResetStack();
+
+		if(g_bDrawCameraPos)
+		{
+			//Draw lookat point.
+			modelMatrix.SetIdentity();
+			modelMatrix.Translate(glm::vec3(0.0f, 0.0f, -g_viewPole.GetView().radius));
+
+			glDisable(GL_DEPTH_TEST);
+			glDepthMask(GL_FALSE);
+			glUseProgram(g_progUnlit.theProgram);
+			glUniformMatrix4fv(g_progUnlit.modelToCameraMatrixUnif, 1, GL_FALSE,
+				glm::value_ptr(modelMatrix.Top()));
+			glUniform4f(g_progUnlit.objectColorUnif, 0.25f, 0.25f, 0.25f, 1.0f);
+			g_pSphere->Render("flat");
+			glDepthMask(GL_TRUE);
+			glEnable(GL_DEPTH_TEST);
+			glUniform4f(g_progUnlit.objectColorUnif, 1.0f, 1.0f, 1.0f, 1.0f);
+			g_pSphere->Render("flat");
+		}
+	}
+
+	glutPostRedisplay();
+*/
+	glutSwapBuffers();
+}
+
+//Called whenever the window is resized. The new window size is given, in pixels.
+//This is an opportunity to call glViewport or glScissor to keep up with the change in size.
+void reshape (int w, int h)
+{
+	glutil::MatrixStack persMatrix;
+	persMatrix.Perspective(60.0f, (w / (float)h), g_fzNear, g_fzFar);
+
+	ProjectionBlock projData;
+	projData.cameraToClipMatrix = persMatrix.Top();
+
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
+	glutPostRedisplay();
+}
+
+
+//Called whenever a key on the keyboard was pressed.
+//The key is given by the ''key'' parameter, which is in ASCII.
+//It's often a good idea to have the escape key (ASCII value 27) call glutLeaveMainLoop() to
+//exit the program.
+void keyboard(unsigned char key, int x, int y)
+{
+	switch (key)
+	{
+	case 27:
+		delete g_pScene;
+		g_pScene = NULL;
+		glutLeaveMainLoop();
+		return;
+	case 32:
+		break;
+	}
+
+	g_viewPole.CharPress(key);
+}
+
+unsigned int defaults(unsigned int displayMode, int &width, int &height)
+{
+	width = 700;
+	height = 350;
+	return displayMode | GLUT_SRGB;
+}

Tut 17 Spotlight on Textures/premake4.lua

+
+dofile("../framework/framework.lua")
+
+SetupSolution("Tutorial17")
+dofile("tutorials.lua");

Tut 17 Spotlight on Textures/tutorials.lua

+
+SetupProject("Tut 17 Double Projection", "Double Projection.cpp"
+	)
+

data/GenSphere.lua

+require "XmlWriter"
+require "vmath"
+
+local function GenStringFromArray(theArray)
+	local array = {" "}
+	for i, vector in ipairs(theArray) do
+		array[#array + 1] = "        " .. table.concat(vector, " ");
+	end
+	
+	return table.concat(array, "\n");
+end
+
+local positions = {};
+local colors = {};
+local normals = {};
+local topFan = {};
+local botFan = {};
+local strips = {};
+local restartIndex = 65535;
+
+local iSegCount, iColorRepeatCount, iRingCount = ...;
+iSegCount = iSegCount or 15;
+iColorRepeatCount = iColorRepeatCount or 3;
+iRingCount = iRingCount or 8;
+
+local rhoAngle = math.pi * 2.0 / iSegCount;
+local thetaAngle = math.pi / (iRingCount + 1);
+local iColorCycleAngle = math.pi * 2.0 / iColorRepeatCount;
+local highColor = vmath.vec4(0.9, 0.5, 0.5, 1.0);
+local lowColor = vmath.vec4(0.5, 0.1, 0.1, 1.0)
+
+--Compute vertex attributes
+positions[#positions + 1] = vmath.vec3(0.0, 0.5, 0.0);
+colors[#colors + 1] = vmath.vec4(1.0, 1.0, 1.0, 1.0);
+normals[#normals + 1] = vmath.vec3(0.0, 1.0, 0.0);
+
+local firstSideIx = #positions;
+
+for iRing = 1, iRingCount do
+	local theta = (thetaAngle * iRing)
+	local sinTheta, cosTheta = math.sin(theta), math.cos(theta);
+
+	for iSeg = 0, (iSegCount - 1) do
+		local rho = rhoAngle * iSeg;
+		local sinRho, cosRho = math.sin(rho), math.cos(rho);
+		
+		local point = vmath.vec3(sinTheta * cosRho, cosTheta, sinTheta * sinRho);
+		positions[#positions + 1] = 0.5 * point;
+		normals[#normals + 1] = vmath.vec3(sinTheta * cosRho, cosTheta, sinTheta * sinRho);
+		colors[#colors + 1] = vmath.vec4(
+			vmath.vec3(sinTheta * cosRho, cosTheta, sinTheta * sinRho), 1.0);
+	end
+end
+
+positions[#positions + 1] = vmath.vec3(0.0, -0.5, 0.0);
+colors[#colors + 1] = vmath.vec4(1.0, 1.0, 1.0, 1.0);
+normals[#normals + 1] = vmath.vec3(0.0, -1.0, 0.0);
+
+--Compute cap fans.
+topFan[#topFan + 1] = 0;
+botFan[#botFan + 1] = #positions - 1;
+
+for iSeg = 1, iSegCount do
+	topFan[#topFan + 1] = iSeg;
+	botFan[#botFan + 1] = (#positions - 1) - iSeg;
+end
+
+topFan[#topFan + 1] = 1;
+botFan[#botFan + 1] = (#positions - 2);
+
+--Compute the strips.
+
+for iRing = 1, iRingCount - 1 do
+	local topRingStart = 1 + ((iRing - 1) * iSegCount);
+	local botRingStart = 1 + (iRing * iSegCount);
+	local strip = {};
+	strips[#strips + 1] = strip;
+	
+	for iSeg = 0, (iSegCount - 1) do
+		strip[#strip + 1] = topRingStart + iSeg;
+		strip[#strip + 1] = botRingStart + iSeg;
+	end
+
+	strip[#strip + 1] = topRingStart;
+	strip[#strip + 1] = botRingStart;
+end
+
+
+do
+	local writer = XmlWriter.XmlWriter("UnitSphere.xml");
+	writer:AddPI("oxygen", [[RNGSchema="../../Documents/meshFormat.rnc" type="compact"]]);
+	writer:PushElement("mesh", "http://www.arcsynthesis.com/gltut/mesh");
+		writer:PushElement("attribute");
+			writer:AddAttribute("index", "0");
+			writer:AddAttribute("type", "float");
+			writer:AddAttribute("size", "3");
+			writer:AddText(GenStringFromArray(positions));
+		writer:PopElement();
+		writer:PushElement("attribute");
+			writer:AddAttribute("index", "1");
+			writer:AddAttribute("type", "float");
+			writer:AddAttribute("size", "4");
+			writer:AddText(GenStringFromArray(colors));
+		writer:PopElement();
+		writer:PushElement("attribute");
+			writer:AddAttribute("index", "2");
+			writer:AddAttribute("type", "float");
+			writer:AddAttribute("size", "3");
+			writer:AddText(GenStringFromArray(normals));
+		writer:PopElement();
+		writer:PushElement("vao");
+			writer:AddAttribute("name", "lit-color");
+			writer:PushElement("source"); writer:AddAttribute("attrib", "0"); writer:PopElement();
+			writer:PushElement("source"); writer:AddAttribute("attrib", "1"); writer:PopElement();
+			writer:PushElement("source"); writer:AddAttribute("attrib", "2"); writer:PopElement();
+		writer:PopElement();
+		writer:PushElement("vao");
+			writer:AddAttribute("name", "lit");
+			writer:PushElement("source"); writer:AddAttribute("attrib", "0"); writer:PopElement();
+			writer:PushElement("source"); writer:AddAttribute("attrib", "2"); writer:PopElement();
+		writer:PopElement();
+		writer:PushElement("vao");
+			writer:AddAttribute("name", "color");
+			writer:PushElement("source"); writer:AddAttribute("attrib", "0"); writer:PopElement();
+			writer:PushElement("source"); writer:AddAttribute("attrib", "1"); writer:PopElement();
+		writer:PopElement();
+		writer:PushElement("vao");
+			writer:AddAttribute("name", "flat");
+			writer:PushElement("source"); writer:AddAttribute("attrib", "0"); writer:PopElement();
+		writer:PopElement();
+		writer:PushElement("indices");
+			writer:AddAttribute("cmd", "tri-fan");
+			writer:AddAttribute("type", "ushort");
+			writer:AddText(table.concat(topFan, " "));
+		writer:PopElement();
+		writer:PushElement("indices");
+			writer:AddAttribute("cmd", "tri-fan");
+			writer:AddAttribute("type", "ushort");
+			writer:AddText(table.concat(botFan, " "));
+		writer:PopElement();
+		for i, strip in ipairs(strips) do
+			writer:PushElement("indices");
+				writer:AddAttribute("cmd", "tri-strip");
+				writer:AddAttribute("type", "ushort");
+				writer:AddText(table.concat(strip, " "));
+			writer:PopElement();
+		end
+	writer:PopElement();
+	writer:Close();
+end

data/UnitSphere.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<?oxygen RNGSchema="../../Documents/meshFormat.rnc" type="compact"?>
+
+<mesh xmlns="http://www.arcsynthesis.com/gltut/mesh" >
+	<attribute index="0" type="float" size="3" > 
+        0 0.5 0
+        0.17101007166283 0.46984631039295 0
+        0.15622547417872 0.46984631039295 0.069556062480293
+        0.11442807294522 0.46984631039295 0.12708524986075
+        0.052845018353093 0.46984631039295 0.16264024300704
+        -0.017875419994207 0.46984631039295 0.17007326059719
+        -0.085505035831417 0.46984631039295 0.14809906636301
+        -0.13835005418451 0.46984631039295 0.10051719811689
+        -0.16727309129832 0.46984631039295 0.035554993146286
+        -0.16727309129832 0.46984631039295 -0.035554993146286
+        -0.13835005418451 0.46984631039295 -0.10051719811689
+        -0.085505035831417 0.46984631039295 -0.14809906636301
+        -0.017875419994207 0.46984631039295 -0.17007326059719
+        0.052845018353093 0.46984631039295 -0.16264024300704
+        0.11442807294522 0.46984631039295 -0.12708524986075
+        0.15622547417872 0.46984631039295 -0.069556062480293
+        0.32139380484327 0.38302222155949 0
+        0.29360785052904 0.38302222155949 0.13072263728731
+        0.21505443151476 0.38302222155949 0.23884214300977
+        0.099316147583396 0.38302222155949 0.30566367239308
+        -0.033594800524011 0.38302222155949 0.31963317595235
+        -0.16069690242163 0.38302222155949 0.27833519961321
+        -0.26001305000503 0.38302222155949 0.18891053866504
+        -0.31437057909815 0.38302222155949 0.066821529383317
+        -0.31437057909815 0.38302222155949 -0.066821529383317
+        -0.26001305000503 0.38302222155949 -0.18891053866504
+        -0.16069690242163 0.38302222155949 -0.27833519961321
+        -0.033594800524011 0.38302222155949 -0.31963317595235
+        0.099316147583396 0.38302222155949 -0.30566367239308
+        0.21505443151476 0.38302222155949 -0.23884214300977
+        0.29360785052904 0.38302222155949 -0.13072263728731
+        0.43301270189222 0.25 0
+        0.39557678691519 0.25 0.17612213277682
+        0.28974205177823 0.25 0.32179114877719
+        0.13380828366491 0.25 0.41181955177317
+        -0.045262152304168 0.25 0.43064061300439
+        -0.21650635094611 0.25 0.375
+        -0.35031463461102 0.25 0.25451848022756
+        -0.42355033544314 0.25 0.090028402995978
+        -0.42355033544314 0.25 -0.090028402995978
+        -0.35031463461102 0.25 -0.25451848022756
+        -0.21650635094611 0.25 -0.375
+        -0.045262152304169 0.25 -0.43064061300439
+        0.13380828366491 0.25 -0.41181955177317
+        0.28974205177823 0.25 -0.32179114877719
+        0.39557678691519 0.25 -0.17612213277682
+        0.4924038765061 0.086824088833465 0
+        0.44983332470776 0.086824088833465 0.2002786997676
+        0.32948250445998 0.086824088833465 0.36592739287052
+        0.15216116593649 0.086824088833465 0.46830391540012
+        -0.051470220518218 0.086824088833465 0.48970643654954
+        -0.24620193825305 0.086824088833465 0.42643426597622
+        -0.39836310418954 0.086824088833465 0.28942773678193
+        -0.48164367039647 0.086824088833465 0.1023765225296
+        -0.48164367039647 0.086824088833465 -0.1023765225296
+        -0.39836310418954 0.086824088833465 -0.28942773678193
+        -0.24620193825305 0.086824088833465 -0.42643426597622
+        -0.051470220518219 0.086824088833465 -0.48970643654954
+        0.15216116593649 0.086824088833465 -0.46830391540012
+        0.32948250445998 0.086824088833465 -0.36592739287052
+        0.44983332470776 0.086824088833465 -0.2002786997676
+        0.4924038765061 -0.086824088833465 0
+        0.44983332470776 -0.086824088833465 0.2002786997676
+        0.32948250445998 -0.086824088833465 0.36592739287052
+        0.15216116593649 -0.086824088833465 0.46830391540012
+        -0.051470220518218 -0.086824088833465 0.48970643654954
+        -0.24620193825305 -0.086824088833465 0.42643426597622
+        -0.39836310418954 -0.086824088833465 0.28942773678193
+        -0.48164367039647 -0.086824088833465 0.1023765225296
+        -0.48164367039647 -0.086824088833465 -0.1023765225296
+        -0.39836310418954 -0.086824088833465 -0.28942773678193
+        -0.24620193825305 -0.086824088833465 -0.42643426597622
+        -0.051470220518219 -0.086824088833465 -0.48970643654954
+        0.15216116593649 -0.086824088833465 -0.46830391540012
+        0.32948250445998 -0.086824088833465 -0.36592739287052
+        0.44983332470776 -0.086824088833465 -0.2002786997676
+        0.43301270189222 -0.25 0
+        0.39557678691519 -0.25 0.17612213277682
+        0.28974205177823 -0.25 0.32179114877719
+        0.13380828366491 -0.25 0.41181955177317
+        -0.045262152304168 -0.25 0.43064061300439
+        -0.21650635094611 -0.25 0.375
+        -0.35031463461102 -0.25 0.25451848022756
+        -0.42355033544314 -0.25 0.090028402995978
+        -0.42355033544314 -0.25 -0.090028402995978
+        -0.35031463461102 -0.25 -0.25451848022756
+        -0.21650635094611 -0.25 -0.375
+        -0.045262152304169 -0.25 -0.43064061300439
+        0.13380828366491 -0.25 -0.41181955177317
+        0.28974205177823 -0.25 -0.32179114877719
+        0.39557678691519 -0.25 -0.17612213277682
+        0.32139380484327 -0.38302222155949 0
+        0.29360785052904 -0.38302222155949 0.13072263728731
+        0.21505443151476 -0.38302222155949 0.23884214300977
+        0.099316147583396 -0.38302222155949 0.30566367239308
+        -0.033594800524011 -0.38302222155949 0.31963317595235
+        -0.16069690242163 -0.38302222155949 0.27833519961321
+        -0.26001305000503 -0.38302222155949 0.18891053866504
+        -0.31437057909815 -0.38302222155949 0.066821529383317
+        -0.31437057909815 -0.38302222155949 -0.066821529383317
+        -0.26001305000503 -0.38302222155949 -0.18891053866504
+        -0.16069690242164 -0.38302222155949 -0.27833519961321
+        -0.033594800524011 -0.38302222155949 -0.31963317595235
+        0.099316147583396 -0.38302222155949 -0.30566367239308
+        0.21505443151476 -0.38302222155949 -0.23884214300977
+        0.29360785052904 -0.38302222155949 -0.13072263728731
+        0.17101007166283 -0.46984631039295 0
+        0.15622547417872 -0.46984631039295 0.069556062480293
+        0.11442807294522 -0.46984631039295 0.12708524986075
+        0.052845018353093 -0.46984631039295 0.16264024300704
+        -0.017875419994207 -0.46984631039295 0.17007326059719
+        -0.085505035831417 -0.46984631039295 0.14809906636301
+        -0.13835005418451 -0.46984631039295 0.10051719811689
+        -0.16727309129832 -0.46984631039295 0.035554993146286
+        -0.16727309129832 -0.46984631039295 -0.035554993146286
+        -0.13835005418451 -0.46984631039295 -0.10051719811689
+        -0.085505035831417 -0.46984631039295 -0.14809906636301
+        -0.017875419994208 -0.46984631039295 -0.17007326059719
+        0.052845018353093 -0.46984631039295 -0.16264024300704
+        0.11442807294522 -0.46984631039295 -0.12708524986075
+        0.15622547417872 -0.46984631039295 -0.069556062480293
+        0 -0.5 0</attribute>
+	<attribute index="1" type="float" size="4" > 
+        1 1 1 1
+        0.34202014332567 0.93969262078591 0 1
+        0.31245094835744 0.93969262078591 0.13911212496059 1
+        0.22885614589045 0.93969262078591 0.25417049972151 1
+        0.10569003670619 0.93969262078591 0.32528048601408 1
+        -0.035750839988415 0.93969262078591 0.34014652119437 1
+        -0.17101007166283 0.93969262078591 0.29619813272602 1
+        -0.27670010836902 0.93969262078591 0.20103439623379 1
+        -0.33454618259664 0.93969262078591 0.071109986292572 1
+        -0.33454618259664 0.93969262078591 -0.071109986292572 1
+        -0.27670010836902 0.93969262078591 -0.20103439623379 1
+        -0.17101007166283 0.93969262078591 -0.29619813272602 1
+        -0.035750839988415 0.93969262078591 -0.34014652119437 1
+        0.10569003670619 0.93969262078591 -0.32528048601408 1
+        0.22885614589045 0.93969262078591 -0.25417049972151 1
+        0.31245094835744 0.93969262078591 -0.13911212496059 1
+        0.64278760968654 0.76604444311898 0 1
+        0.58721570105808 0.76604444311898 0.26144527457462 1
+        0.43010886302952 0.76604444311898 0.47768428601953 1
+        0.19863229516679 0.76604444311898 0.61132734478617 1
+        -0.067189601048022 0.76604444311898 0.6392663519047 1
+        -0.32139380484327 0.76604444311898 0.55667039922642 1
+        -0.52002610001006 0.76604444311898 0.37782107733008 1
+        -0.62874115819631 0.76604444311898 0.13364305876663 1
+        -0.62874115819631 0.76604444311898 -0.13364305876663 1
+        -0.52002610001006 0.76604444311898 -0.37782107733008 1
+        -0.32139380484327 0.76604444311898 -0.55667039922642 1
+        -0.067189601048023 0.76604444311898 -0.6392663519047 1
+        0.19863229516679 0.76604444311898 -0.61132734478617 1
+        0.43010886302951 0.76604444311898 -0.47768428601953 1
+        0.58721570105808 0.76604444311898 -0.26144527457462 1
+        0.86602540378444 0.5 0 1
+        0.79115357383037 0.5 0.35224426555365 1
+        0.57948410355646 0.5 0.64358229755438 1
+        0.26761656732982 0.5 0.82363910354633 1
+        -0.090524304608336 0.5 0.86128122600877 1
+        -0.43301270189222 0.5 0.75 1
+        -0.70062926922204 0.5 0.50903696045513 1
+        -0.84710067088627 0.5 0.18005680599196 1
+        -0.84710067088627 0.5 -0.18005680599196 1
+        -0.70062926922204 0.5 -0.50903696045513 1
+        -0.43301270189222 0.5 -0.75 1
+        -0.090524304608337 0.5 -0.86128122600877 1
+        0.26761656732982 0.5 -0.82363910354633 1
+        0.57948410355646 0.5 -0.64358229755438 1
+        0.79115357383037 0.5 -0.35224426555365 1
+        0.98480775301221 0.17364817766693 0 1
+        0.89966664941552 0.17364817766693 0.40055739953521 1
+        0.65896500891996 0.17364817766693 0.73185478574104 1
+        0.30432233187298 0.17364817766693 0.93660783080025 1
+        -0.10294044103644 0.17364817766693 0.97941287309907 1
+        -0.4924038765061 0.17364817766693 0.85286853195244 1
+        -0.79672620837908 0.17364817766693 0.57885547356386 1
+        -0.96328734079294 0.17364817766693 0.20475304505921 1
+        -0.96328734079294 0.17364817766693 -0.20475304505921 1
+        -0.79672620837908 0.17364817766693 -0.57885547356386 1
+        -0.4924038765061 0.17364817766693 -0.85286853195244 1
+        -0.10294044103644 0.17364817766693 -0.97941287309907 1
+        0.30432233187298 0.17364817766693 -0.93660783080025 1
+        0.65896500891996 0.17364817766693 -0.73185478574104 1
+        0.89966664941552 0.17364817766693 -0.40055739953521 1
+        0.98480775301221 -0.17364817766693 0 1
+        0.89966664941552 -0.17364817766693 0.40055739953521 1
+        0.65896500891996 -0.17364817766693 0.73185478574104 1
+        0.30432233187298 -0.17364817766693 0.93660783080025 1
+        -0.10294044103644 -0.17364817766693 0.97941287309907 1
+        -0.4924038765061 -0.17364817766693 0.85286853195244 1
+        -0.79672620837908 -0.17364817766693 0.57885547356386 1
+        -0.96328734079294 -0.17364817766693 0.20475304505921 1
+        -0.96328734079294 -0.17364817766693 -0.20475304505921 1
+        -0.79672620837908 -0.17364817766693 -0.57885547356386 1
+        -0.4924038765061 -0.17364817766693 -0.85286853195244 1
+        -0.10294044103644 -0.17364817766693 -0.97941287309907 1
+        0.30432233187298 -0.17364817766693 -0.93660783080025 1
+        0.65896500891996 -0.17364817766693 -0.73185478574104 1
+        0.89966664941552 -0.17364817766693 -0.40055739953521 1
+        0.86602540378444 -0.5 0 1
+        0.79115357383037 -0.5 0.35224426555365 1
+        0.57948410355646 -0.5 0.64358229755438 1
+        0.26761656732982 -0.5 0.82363910354633 1
+        -0.090524304608336 -0.5 0.86128122600877 1
+        -0.43301270189222 -0.5 0.75 1
+        -0.70062926922204 -0.5 0.50903696045513 1
+        -0.84710067088627 -0.5 0.18005680599196 1
+        -0.84710067088627 -0.5 -0.18005680599196 1
+        -0.70062926922204 -0.5 -0.50903696045513 1
+        -0.43301270189222 -0.5 -0.75 1
+        -0.090524304608337 -0.5 -0.86128122600877 1
+        0.26761656732982 -0.5 -0.82363910354633 1
+        0.57948410355646 -0.5 -0.64358229755438 1
+        0.79115357383037 -0.5 -0.35224426555365 1
+        0.64278760968654 -0.76604444311898 0 1
+        0.58721570105808 -0.76604444311898 0.26144527457462 1
+        0.43010886302952 -0.76604444311898 0.47768428601953 1
+        0.19863229516679 -0.76604444311898 0.61132734478617 1
+        -0.067189601048022 -0.76604444311898 0.6392663519047 1
+        -0.32139380484327 -0.76604444311898 0.55667039922642 1
+        -0.52002610001006 -0.76604444311898 0.37782107733008 1
+        -0.62874115819631 -0.76604444311898 0.13364305876663 1
+        -0.62874115819631 -0.76604444311898 -0.13364305876663 1
+        -0.52002610001006 -0.76604444311898 -0.37782107733008 1
+        -0.32139380484327 -0.76604444311898 -0.55667039922642 1
+        -0.067189601048023 -0.76604444311898 -0.6392663519047 1
+        0.19863229516679 -0.76604444311898 -0.61132734478617 1
+        0.43010886302951 -0.76604444311898 -0.47768428601954 1
+        0.58721570105808 -0.76604444311898 -0.26144527457462 1
+        0.34202014332567 -0.93969262078591 0 1
+        0.31245094835744 -0.93969262078591 0.13911212496059 1
+        0.22885614589045 -0.93969262078591 0.25417049972151 1
+        0.10569003670619 -0.93969262078591 0.32528048601408 1
+        -0.035750839988415 -0.93969262078591 0.34014652119437 1
+        -0.17101007166283 -0.93969262078591 0.29619813272602 1
+        -0.27670010836902 -0.93969262078591 0.20103439623379 1
+        -0.33454618259664 -0.93969262078591 0.071109986292572 1
+        -0.33454618259664 -0.93969262078591 -0.071109986292572 1
+        -0.27670010836902 -0.93969262078591 -0.20103439623379 1
+        -0.17101007166283 -0.93969262078591 -0.29619813272602 1
+        -0.035750839988415 -0.93969262078591 -0.34014652119437 1
+        0.10569003670619 -0.93969262078591 -0.32528048601408 1
+        0.22885614589045 -0.93969262078591 -0.25417049972151 1
+        0.31245094835744 -0.93969262078591 -0.13911212496059 1
+        1 1 1 1</attribute>
+	<attribute index="2" type="float" size="3" > 
+        0 1 0
+        0.34202014332567 0.93969262078591 0
+        0.31245094835744 0.93969262078591 0.13911212496059
+        0.22885614589045 0.93969262078591 0.25417049972151
+        0.10569003670619 0.93969262078591 0.32528048601408
+        -0.035750839988415 0.93969262078591 0.34014652119437
+        -0.17101007166283 0.93969262078591 0.29619813272602
+        -0.27670010836902 0.93969262078591 0.20103439623379
+        -0.33454618259664 0.93969262078591 0.071109986292572
+        -0.33454618259664 0.93969262078591 -0.071109986292572
+        -0.27670010836902 0.93969262078591 -0.20103439623379
+        -0.17101007166283 0.93969262078591 -0.29619813272602
+        -0.035750839988415 0.93969262078591 -0.34014652119437
+        0.10569003670619 0.93969262078591 -0.32528048601408
+        0.22885614589045 0.93969262078591 -0.25417049972151
+        0.31245094835744 0.93969262078591 -0.13911212496059
+        0.64278760968654 0.76604444311898 0
+        0.58721570105808 0.76604444311898 0.26144527457462
+        0.43010886302952 0.76604444311898 0.47768428601953
+        0.19863229516679 0.76604444311898 0.61132734478617
+        -0.067189601048022 0.76604444311898 0.6392663519047
+        -0.32139380484327 0.76604444311898 0.55667039922642
+        -0.52002610001006 0.76604444311898 0.37782107733008
+        -0.62874115819631 0.76604444311898 0.13364305876663
+        -0.62874115819631 0.76604444311898 -0.13364305876663
+        -0.52002610001006 0.76604444311898 -0.37782107733008
+        -0.32139380484327 0.76604444311898 -0.55667039922642
+        -0.067189601048023 0.76604444311898 -0.6392663519047
+        0.19863229516679 0.76604444311898 -0.61132734478617
+        0.43010886302951 0.76604444311898 -0.47768428601953
+        0.58721570105808 0.76604444311898 -0.26144527457462
+        0.86602540378444 0.5 0
+        0.79115357383037 0.5 0.35224426555365
+        0.57948410355646 0.5 0.64358229755438
+        0.26761656732982 0.5 0.82363910354633
+        -0.090524304608336 0.5 0.86128122600877
+        -0.43301270189222 0.5 0.75
+        -0.70062926922204 0.5 0.50903696045513
+        -0.84710067088627 0.5 0.18005680599196
+        -0.84710067088627 0.5 -0.18005680599196
+        -0.70062926922204 0.5 -0.50903696045513
+        -0.43301270189222 0.5 -0.75
+        -0.090524304608337 0.5 -0.86128122600877
+        0.26761656732982 0.5 -0.82363910354633
+        0.57948410355646 0.5 -0.64358229755438
+        0.79115357383037 0.5 -0.35224426555365
+        0.98480775301221 0.17364817766693 0
+        0.89966664941552 0.17364817766693 0.40055739953521
+        0.65896500891996 0.17364817766693 0.73185478574104
+        0.30432233187298 0.17364817766693 0.93660783080025
+        -0.10294044103644 0.17364817766693 0.97941287309907
+        -0.4924038765061 0.17364817766693 0.85286853195244
+        -0.79672620837908 0.17364817766693 0.57885547356386
+        -0.96328734079294 0.17364817766693 0.20475304505921
+        -0.96328734079294 0.17364817766693 -0.20475304505921
+        -0.79672620837908 0.17364817766693 -0.57885547356386
+        -0.4924038765061 0.17364817766693 -0.85286853195244
+        -0.10294044103644 0.17364817766693 -0.97941287309907
+        0.30432233187298 0.17364817766693 -0.93660783080025
+        0.65896500891996 0.17364817766693 -0.73185478574104
+        0.89966664941552 0.17364817766693 -0.40055739953521
+        0.98480775301221 -0.17364817766693 0
+        0.89966664941552 -0.17364817766693 0.40055739953521
+        0.65896500891996 -0.17364817766693 0.73185478574104
+        0.30432233187298 -0.17364817766693 0.93660783080025
+        -0.10294044103644 -0.17364817766693 0.97941287309907
+        -0.4924038765061 -0.17364817766693 0.85286853195244
+        -0.79672620837908 -0.17364817766693 0.57885547356386
+        -0.96328734079294 -0.17364817766693 0.20475304505921
+        -0.96328734079294 -0.17364817766693 -0.20475304505921
+        -0.79672620837908 -0.17364817766693 -0.57885547356386
+        -0.4924038765061 -0.17364817766693 -0.85286853195244
+        -0.10294044103644 -0.17364817766693 -0.97941287309907
+        0.30432233187298 -0.17364817766693 -0.93660783080025
+        0.65896500891996 -0.17364817766693 -0.73185478574104
+        0.89966664941552 -0.17364817766693 -0.40055739953521
+        0.86602540378444 -0.5 0
+        0.79115357383037 -0.5 0.35224426555365
+        0.57948410355646 -0.5 0.64358229755438
+        0.26761656732982 -0.5 0.82363910354633
+        -0.090524304608336 -0.5 0.86128122600877
+        -0.43301270189222 -0.5 0.75
+        -0.70062926922204 -0.5 0.50903696045513
+        -0.84710067088627 -0.5 0.18005680599196
+        -0.84710067088627 -0.5 -0.18005680599196
+        -0.70062926922204 -0.5 -0.50903696045513
+        -0.43301270189222 -0.5 -0.75
+        -0.090524304608337 -0.5 -0.86128122600877
+        0.26761656732982 -0.5 -0.82363910354633
+        0.57948410355646 -0.5 -0.64358229755438
+        0.79115357383037 -0.5 -0.35224426555365
+        0.64278760968654 -0.76604444311898 0
+        0.58721570105808 -0.76604444311898 0.26144527457462
+        0.43010886302952 -0.76604444311898 0.47768428601953
+        0.19863229516679 -0.76604444311898 0.61132734478617
+        -0.067189601048022 -0.76604444311898 0.6392663519047
+        -0.32139380484327 -0.76604444311898 0.55667039922642
+        -0.52002610001006 -0.76604444311898 0.37782107733008
+        -0.62874115819631 -0.76604444311898 0.13364305876663
+        -0.62874115819631 -0.76604444311898 -0.13364305876663
+        -0.52002610001006 -0.76604444311898 -0.37782107733008
+        -0.32139380484327 -0.76604444311898 -0.55667039922642
+        -0.067189601048023 -0.76604444311898 -0.6392663519047
+        0.19863229516679 -0.76604444311898 -0.61132734478617
+        0.43010886302951 -0.76604444311898 -0.47768428601954
+        0.58721570105808 -0.76604444311898 -0.26144527457462
+        0.34202014332567 -0.93969262078591 0
+        0.31245094835744 -0.93969262078591 0.13911212496059
+        0.22885614589045 -0.93969262078591 0.25417049972151
+        0.10569003670619 -0.93969262078591 0.32528048601408
+        -0.035750839988415 -0.93969262078591 0.34014652119437
+        -0.17101007166283 -0.93969262078591 0.29619813272602
+        -0.27670010836902 -0.93969262078591 0.20103439623379
+        -0.33454618259664 -0.93969262078591 0.071109986292572
+        -0.33454618259664 -0.93969262078591 -0.071109986292572
+        -0.27670010836902 -0.93969262078591 -0.20103439623379
+        -0.17101007166283 -0.93969262078591 -0.29619813272602
+        -0.035750839988415 -0.93969262078591 -0.34014652119437
+        0.10569003670619 -0.93969262078591 -0.32528048601408
+        0.22885614589045 -0.93969262078591 -0.25417049972151
+        0.31245094835744 -0.93969262078591 -0.13911212496059
+        0 -1 0</attribute>
+	<vao name="lit-color" >
+		<source attrib="0" />
+		<source attrib="1" />
+		<source attrib="2" />
+	</vao>
+	<vao name="lit" >
+		<source attrib="0" />
+		<source attrib="2" />
+	</vao>
+	<vao name="color" >
+		<source attrib="0" />
+		<source attrib="1" />
+	</vao>
+	<vao name="flat" >
+		<source attrib="0" />
+	</vao>
+	<indices cmd="tri-fan" type="ushort" >0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1</indices>
+	<indices cmd="tri-fan" type="ushort" >121 120 119 118 117 116 115 114 113 112 111 110 109 108 107 106 120</indices>
+	<indices cmd="tri-strip" type="ushort" >1 16 2 17 3 18 4 19 5 20 6 21 7 22 8 23 9 24 10 25 11 26 12 27 13 28 14 29 15 30 1 16</indices>
+	<indices cmd="tri-strip" type="ushort" >16 31 17 32 18 33 19 34 20 35 21 36 22 37 23 38 24 39 25 40 26 41 27 42 28 43 29 44 30 45 16 31</indices>
+	<indices cmd="tri-strip" type="ushort" >31 46 32 47 33 48 34 49 35 50 36 51 37 52 38 53 39 54 40 55 41 56 42 57 43 58 44 59 45 60 31 46</indices>
+	<indices cmd="tri-strip" type="ushort" >46 61 47 62 48 63 49 64 50 65 51 66 52 67 53 68 54 69 55 70 56 71 57 72 58 73 59 74 60 75 46 61</indices>
+	<indices cmd="tri-strip" type="ushort" >61 76 62 77 63 78 64 79 65 80 66 81 67 82 68 83 69 84 70 85 71 86 72 87 73 88 74 89 75 90 61 76</indices>
+	<indices cmd="tri-strip" type="ushort" >76 91 77 92 78 93 79 94 80 95 81 96 82 97 83 98 84 99 85 100 86 101 87 102 88 103 89 104 90 105 76 91</indices>
+	<indices cmd="tri-strip" type="ushort" >91 106 92 107 93 108 94 109 95 110 96 111 97 112 98 113 99 114 100 115 101 116 102 117 103 118 104 119 105 120 91 106</indices>
+</mesh>

framework/Scene.cpp

+#include <string>
+#include <vector>
+#include <exception>
+#include <memory>
+
+#include <istream>
+#include <fstream>
+#include <iostream>
+
+#include <glload/gl_all.h>
+#include "framework.h"
+#include "Scene.h"
+#include "Mesh.h"
+
+
+
+namespace Framework
+{
+	class SceneImpl
+	{
+	public:
+		SceneImpl(const std::string &filename)
+		{
+			std::string pathname = FindFileOrThrow(filename);
+
+			std::ifstream fileStream(pathname.c_str());
+			if(!fileStream.is_open())
+				throw std::runtime_error("Could not open the scene file.");
+
+			while(!fileStream.fail() && !fileStream.eof())
+				LoadElement(fileStream);
+
+			std::cout << "EOF" << std::endl;
+		}
+
+	private:
+		void LoadElement(std::istream &fileStream)
+		{
+		}
+
+		void ReadProgram(std::istream &fileStream)
+		{
+		}
+
+		void ReadMesh(std::istream &fileStream)
+		{
+		}
+
+		std::string ReadFilename(std::istream &fileStream)
+		{
+		}
+	};
+
+	Scene::Scene( const std::string &filename )
+		: m_pImpl(new SceneImpl(filename))
+	{}
+
+	Scene::~Scene()
+	{
+		delete m_pImpl;
+	}
+
+	void Scene::Render() const
+	{
+
+	}
+}

framework/Scene.h

+
+#ifndef FRAMEWORK_SCENE_H
+#define FRAMEWORK_SCENE_H
+
+#include <string>
+
+namespace Framework
+{
+	class SceneImpl;
+
+	class Scene
+	{
+	public:
+		Scene(const std::string &filename);
+		~Scene();
+
+		void Render() const;
+
+	private:
+		SceneImpl *m_pImpl;
+	};
+}
+
+#endif //FRAMEWORK_SCENE_H
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.