Commits

Jason McKesson committed 9de7175

Tutorial 7 main code almost done. Need to add a forest.

  • Participants
  • Parent commits 8385bbc

Comments (0)

Files changed (8)

File Tut 07 World in Motion/World Scene.cpp

 
 #define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))
 
-GLuint theProgram;
+struct ProgramData
+{
+	GLuint theProgram;
+	GLuint modelToWorldMatrixUnif;
+	GLuint worldToCameraMatrixUnif;
+	GLuint cameraToClipMatrixUnif;
+	GLuint baseColorUnif;
+};
 
-GLuint modelToWorldMatrixUnif;
-GLuint worldToCameraMatrixUnif;
-GLuint cameraToClipMatrixUnif;
+float g_fzNear = 1.0f;
+float g_fzFar = 1000.0f;
 
-glm::mat4 cameraToClipMatrix(0.0f);
+ProgramData UniformColor;
+ProgramData ObjectColor;
+ProgramData UniformColorTint;
 
-float CalcFrustumScale(float fFovDeg)
+ProgramData LoadProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
 {
-	const float degToRad = 3.14159f * 2.0f / 360.0f;
-	float fFovRad = fFovDeg * degToRad;
-	return 1.0f / tan(fFovRad / 2.0f);
+	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.modelToWorldMatrixUnif = glGetUniformLocation(data.theProgram, "modelToWorldMatrix");
+	data.worldToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "worldToCameraMatrix");
+	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
+	data.baseColorUnif = glGetUniformLocation(data.theProgram, "baseColor");
+
+	return data;
 }
 
-const float fFrustumScale = CalcFrustumScale(45.0f);
-
 void InitializeProgram()
 {
-	std::vector<GLuint> shaderList;
+	UniformColor = LoadProgram("PosOnlyWorldTransform.vert", "ColorUniform.frag");
+	ObjectColor = LoadProgram("PosColorWorldTransform.vert", "ColorPassthrough.frag");
+	UniformColorTint = LoadProgram("PosColorWorldTransform.vert", "ColorMultUniform.frag");
+}
 
-	shaderList.push_back(Framework::LoadShader(GL_VERTEX_SHADER, "PosColorWorldTransform.vert"));
-	shaderList.push_back(Framework::LoadShader(GL_FRAGMENT_SHADER, "ColorPassthrough.frag"));
+glm::mat4 CalcLookAtMatrix(const glm::vec3 &cameraPt, const glm::vec3 &lookPt, const glm::vec3 &upPt)
+{
+	glm::vec3 lookDir = glm::normalize(lookPt - cameraPt);
+	glm::vec3 upDir = glm::normalize(upPt);
 
-	theProgram = Framework::CreateProgram(shaderList);
+	glm::vec3 rightDir = glm::normalize(glm::cross(lookDir, upDir));
+	glm::vec3 perpUpDir = glm::cross(rightDir, lookDir);
 
-	modelToWorldMatrixUnif = glGetUniformLocation(theProgram, "modelToWorldMatrix");
-	worldToCameraMatrixUnif = glGetUniformLocation(theProgram, "worldToCameraMatrix");
-	cameraToClipMatrixUnif = glGetUniformLocation(theProgram, "cameraToClipMatrix");
+	glm::mat4 rotMat(1.0f);
+	rotMat[0] = glm::vec4(rightDir, 0.0f);
+	rotMat[1] = glm::vec4(perpUpDir, 0.0f);
+	rotMat[2] = glm::vec4(-lookDir, 0.0f);
 
-	float fzNear = 1.0f; float fzFar = 1000.0f;
+	rotMat = glm::transpose(rotMat);
 
-	cameraToClipMatrix[0].x = fFrustumScale;
-	cameraToClipMatrix[1].y = fFrustumScale;
-	cameraToClipMatrix[2].z = (fzFar + fzNear) / (fzNear - fzFar);
-	cameraToClipMatrix[2].w = -1.0f;
-	cameraToClipMatrix[3].z = (2 * fzFar * fzNear) / (fzNear - fzFar);
+	glm::mat4 transMat(1.0f);
+	transMat[3] = glm::vec4(-cameraPt, 1.0f);
 
-	glm::mat4 worldMat(1.0f);
-
-	glUseProgram(theProgram);
-	glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(cameraToClipMatrix));
-	glUniformMatrix4fv(worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(worldMat));
-	glUseProgram(0);
+	return rotMat * transMat;
 }
 
 Framework::Mesh *g_pConeMesh = NULL;
+Framework::Mesh *g_pCylinderMesh = NULL;
+Framework::Mesh *g_pCubeTintMesh = NULL;
+Framework::Mesh *g_pCubeColorMesh = NULL;
+Framework::Mesh *g_pPlaneMesh = NULL;
 
 //Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
 void init()
 
 	try
 	{
-		g_pConeMesh = new Framework::Mesh("UnitCylinderTint.xml");
+		g_pConeMesh = new Framework::Mesh("UnitConeTint.xml");
+		g_pCylinderMesh = new Framework::Mesh("UnitCylinderTint.xml");
+		g_pCubeTintMesh = new Framework::Mesh("UnitCubeTint.xml");
+		g_pCubeColorMesh = new Framework::Mesh("UnitCubeColor.xml");
+		g_pPlaneMesh = new Framework::Mesh("UnitPlane.xml");
 	}
 	catch(std::exception &except)
 	{
 static float g_fYAngle = 0.0f;
 static float g_fXAngle = 0.0f;
 
+//Trees are 3x3 in X/Z, and fTrunkHeight+fConeHeight in the Y.
+void DrawTree(Framework::MatrixStack &modelMatrix, float fTrunkHeight = 2.0f, float fConeHeight = 3.0f)
+{
+	//Draw trunk.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Scale(glm::vec3(1.0f, fTrunkHeight, 1.0f));
+		modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f));
+
+		glUseProgram(UniformColorTint.theProgram);
+		glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(UniformColorTint.baseColorUnif, 0.694f, 0.4f, 0.106f, 1.0f);
+		g_pCylinderMesh->Render();
+		glUseProgram(0);
+	}
+
+	//Draw the treetop
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Translate(glm::vec3(0.0f, fTrunkHeight, 0.0f));
+		modelMatrix.Scale(glm::vec3(3.0f, fConeHeight, 3.0f));
+
+		glUseProgram(UniformColorTint.theProgram);
+		glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(UniformColorTint.baseColorUnif, 0.0f, 1.0f, 0.0f, 1.0f);
+		g_pConeMesh->Render();
+		glUseProgram(0);
+	}
+}
+
+const float g_fColumnBaseHeight = 0.25f;
+
+//Columns are 1x1 in the X/Z, and fHieght units in the Y.
+void DrawColumn(Framework::MatrixStack &modelMatrix, float fHeight = 5.0f)
+{
+	//Draw the bottom of the column.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Scale(glm::vec3(1.0f, g_fColumnBaseHeight, 1.0f));
+		modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f));
+
+		glUseProgram(UniformColorTint.theProgram);
+		glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(UniformColorTint.baseColorUnif, 1.0f, 1.0f, 1.0f, 1.0f);
+		g_pCubeTintMesh->Render();
+		glUseProgram(0);
+	}
+
+	//Draw the top of the column.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Translate(glm::vec3(0.0f, fHeight - g_fColumnBaseHeight, 0.0f));
+		modelMatrix.Scale(glm::vec3(1.0f, g_fColumnBaseHeight, 1.0f));
+		modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f));
+
+		glUseProgram(UniformColorTint.theProgram);
+		glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(UniformColorTint.baseColorUnif, 0.9f, 0.9f, 0.9f, 0.9f);
+		g_pCubeTintMesh->Render();
+		glUseProgram(0);
+	}
+
+	//Draw the main column.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Translate(glm::vec3(0.0f, g_fColumnBaseHeight, 0.0f));
+		modelMatrix.Scale(glm::vec3(0.8f, fHeight - (g_fColumnBaseHeight * 2.0f), 0.8f));
+		modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f));
+
+		glUseProgram(UniformColorTint.theProgram);
+		glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(UniformColorTint.baseColorUnif, 0.9f, 0.9f, 0.9f, 0.9f);
+		g_pCylinderMesh->Render();
+		glUseProgram(0);
+	}
+}
+
+const float g_fParthenonWidth = 14.0f;
+const float g_fParthenonLength = 20.0f;
+const float g_fParthenonColumnHeight = 5.0f;
+const float g_fParthenonBaseHeight = 1.0f;
+const float g_fParthenonTopHeight = 2.0f;
+
+void DrawParthenon(Framework::MatrixStack &modelMatrix)
+{
+	//Draw base.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Scale(glm::vec3(g_fParthenonWidth, g_fParthenonBaseHeight, g_fParthenonLength));
+		modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f));
+
+		glUseProgram(UniformColorTint.theProgram);
+		glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(UniformColorTint.baseColorUnif, 0.9f, 0.9f, 0.9f, 0.9f);
+		g_pCubeTintMesh->Render();
+		glUseProgram(0);
+	}
+
+	//Draw top.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Translate(glm::vec3(0.0f, g_fParthenonColumnHeight + g_fParthenonBaseHeight, 0.0f));
+		modelMatrix.Scale(glm::vec3(g_fParthenonWidth, g_fParthenonTopHeight, g_fParthenonLength));
+		modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f));
+
+		glUseProgram(UniformColorTint.theProgram);
+		glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(UniformColorTint.baseColorUnif, 0.9f, 0.9f, 0.9f, 0.9f);
+		g_pCubeTintMesh->Render();
+		glUseProgram(0);
+	}
+
+	//Draw columns.
+	const float fFrontZVal = (g_fParthenonLength / 2.0f) - 1.0f;
+	const float fRightXVal = (g_fParthenonWidth / 2.0f) - 1.0f;
+
+	for(int iColumnNum = 0; iColumnNum < int(g_fParthenonWidth / 2.0f); iColumnNum++)
+	{
+		{
+			Framework::MatrixStackPusher push(modelMatrix);
+			modelMatrix.Translate(glm::vec3((2.0f * iColumnNum) - (g_fParthenonWidth / 2.0f) + 1.0f,
+				g_fParthenonBaseHeight, fFrontZVal));
+
+			DrawColumn(modelMatrix, g_fParthenonColumnHeight);
+		}
+		{
+			Framework::MatrixStackPusher push(modelMatrix);
+			modelMatrix.Translate(glm::vec3((2.0f * iColumnNum) - (g_fParthenonWidth / 2.0f) + 1.0f,
+				g_fParthenonBaseHeight, -fFrontZVal));
+
+			DrawColumn(modelMatrix, g_fParthenonColumnHeight);
+		}
+	}
+
+	//Don't draw the first or last columns, since they've been drawn already.
+	for(int iColumnNum = 1; iColumnNum < int((g_fParthenonLength - 2.0f) / 2.0f); iColumnNum++)
+	{
+		{
+			Framework::MatrixStackPusher push(modelMatrix);
+			modelMatrix.Translate(glm::vec3(fRightXVal,
+				g_fParthenonBaseHeight, (2.0f * iColumnNum) - (g_fParthenonLength / 2.0f) + 1.0f));
+
+			DrawColumn(modelMatrix, g_fParthenonColumnHeight);
+		}
+		{
+			Framework::MatrixStackPusher push(modelMatrix);
+			modelMatrix.Translate(glm::vec3(-fRightXVal,
+				g_fParthenonBaseHeight, (2.0f * iColumnNum) - (g_fParthenonLength / 2.0f) + 1.0f));
+
+			DrawColumn(modelMatrix, g_fParthenonColumnHeight);
+		}
+	}
+
+	//Draw interior.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Translate(glm::vec3(0.0f, 1.0f, 0.0f));
+		modelMatrix.Scale(glm::vec3(g_fParthenonWidth - 6.0f, g_fParthenonColumnHeight,
+			g_fParthenonLength - 6.0f));
+		modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f));
+
+		glUseProgram(ObjectColor.theProgram);
+		glUniformMatrix4fv(ObjectColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		g_pCubeColorMesh->Render();
+		glUseProgram(0);
+	}
+
+	//Draw headpiece.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Translate(glm::vec3(
+			0.0f,
+			g_fParthenonColumnHeight + g_fParthenonBaseHeight + (g_fParthenonTopHeight / 2.0f),
+			g_fParthenonLength / 2.0f));
+		modelMatrix.RotateX(-135.0f);
+		modelMatrix.RotateY(45.0f);
+
+		glUseProgram(ObjectColor.theProgram);
+		glUniformMatrix4fv(ObjectColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		g_pCubeColorMesh->Render();
+		glUseProgram(0);
+	}
+}
+
+struct TreeData
+{
+	float fXPos;
+	float fZPos;
+	float fTrunkHeight;
+	float fConeHeight;
+};
+
+static const TreeData g_forest[] =
+{
+	{10.0f, 10.0f, 2.0f, 3.0f},
+};
+
+void DrawForest(Framework::MatrixStack &modelMatrix)
+{
+	for(int iTree = 0; iTree < ARRAY_COUNT(g_forest); iTree++)
+	{
+		const TreeData &currTree = g_forest[iTree];
+
+		Framework::MatrixStackPusher push(modelMatrix);
+		modelMatrix.Translate(glm::vec3(currTree.fXPos, 0.0f, currTree.fZPos));
+		DrawTree(modelMatrix, currTree.fTrunkHeight, currTree.fConeHeight);
+	}
+}
+
+static glm::vec3 g_camTarget(0.0f, 0.4f, 0.0f);
+
+//In spherical coordinates.
+static glm::vec3 g_sphereCamRelPos(67.5f, -46.0f, 150.0f);
+
+glm::vec3 ResolveCamPosition()
+{
+	Framework::MatrixStack tempMat;
+
+	float rho = Framework::DegToRad(g_sphereCamRelPos.x);
+	float theta = Framework::DegToRad(g_sphereCamRelPos.y + 90.0f);
+
+	float fSinTheta = sinf(theta);
+	float fCosTheta = cosf(theta);
+	float fCosRho = cosf(rho);
+	float fSinRho = sinf(rho);
+
+	glm::vec3 dirToCamera(fSinTheta * fCosRho, fCosTheta, fSinTheta * fSinRho);
+	return (dirToCamera * g_sphereCamRelPos.z) + g_camTarget;
+}
+
 //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.
 	glClearDepth(1.0f);
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
+	Framework::MatrixStack camMatrix;
+	camMatrix.SetMatrix(CalcLookAtMatrix(ResolveCamPosition(), g_camTarget, glm::vec3(0.0f, 1.0f, 0.0f)));
+
+	glUseProgram(UniformColor.theProgram);
+	glUniformMatrix4fv(UniformColor.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
+	glUseProgram(ObjectColor.theProgram);
+	glUniformMatrix4fv(ObjectColor.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
+	glUseProgram(UniformColorTint.theProgram);
+	glUniformMatrix4fv(UniformColorTint.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
+	glUseProgram(0);
+
 	if(g_pConeMesh)
 	{
-		Framework::MatrixStack theStack;
-		theStack.Translate(glm::vec3(0.0f, 0.0f, -4.0f));
-		theStack.RotateX(g_fXAngle);
-		theStack.RotateY(g_fYAngle);
-		glUseProgram(theProgram);
-		glUniformMatrix4fv(modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(theStack.Top()));
-		g_pConeMesh->Render();
-		glUseProgram(0);
+		Framework::MatrixStack modelMatrix;
+
+		//Render the ground.
+		{
+			Framework::MatrixStackPusher push(modelMatrix);
+
+			modelMatrix.Scale(glm::vec3(100.0f, 1.0f, 100.0f));
+
+			glUseProgram(UniformColor.theProgram);
+			glUniformMatrix4fv(UniformColor.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
+			glUniformMatrix4fv(UniformColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+			glUniform4f(UniformColor.baseColorUnif, 0.302f, 0.416f, 0.0589f, 1.0f);
+			g_pPlaneMesh->Render();
+			glUseProgram(0);
+		}
+
+		DrawForest(modelMatrix);
+
+		{
+			Framework::MatrixStackPusher push(modelMatrix);
+			modelMatrix.Translate(glm::vec3(20.0f, 0.0f, -10.0f));
+
+			DrawParthenon(modelMatrix);
+		}
 	}
 
 	glutSwapBuffers();
 //This is an opportunity to call glViewport or glScissor to keep up with the change in size.
 void reshape (int w, int h)
 {
-	cameraToClipMatrix[0].x = fFrustumScale * (h / (float)w);
-	cameraToClipMatrix[1].y = fFrustumScale;
+// 	cameraToClipMatrix[0].x = fFrustumScale * (h / (float)w);
+// 	cameraToClipMatrix[1].y = fFrustumScale;
+	Framework::MatrixStack persMatrix;
+	persMatrix.Perspective(45.0f, (h / (float)w), g_fzNear, g_fzFar);
 
-	glUseProgram(theProgram);
-	glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(cameraToClipMatrix));
+	glUseProgram(UniformColor.theProgram);
+	glUniformMatrix4fv(UniformColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
+	glUseProgram(ObjectColor.theProgram);
+	glUniformMatrix4fv(ObjectColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
+	glUseProgram(UniformColorTint.theProgram);
+	glUniformMatrix4fv(UniformColorTint.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
 	glUseProgram(0);
 
 	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
 	{
 	case 27:
 		delete g_pConeMesh;
+		delete g_pCylinderMesh;
+		delete g_pCubeTintMesh;
+		delete g_pCubeColorMesh;
 		glutLeaveMainLoop();
 		break;
-	case 'w': g_fXAngle += 11.25f; break;
-	case 's': g_fXAngle -= 11.25f; break;
-	case 'a': g_fYAngle -= 11.25f; break;
-	case 'd': g_fYAngle += 11.25f; break;
-	case 32: g_fYAngle = 0.0f; break;
+	case 'w': g_camTarget.z -= 4.0f; break;
+	case 's': g_camTarget.z += 4.0f; break;
+	case 'd': g_camTarget.x += 4.0f; break;
+	case 'a': g_camTarget.x -= 4.0f; break;
+	case 'e': g_camTarget.y -= 4.0f; break;
+	case 'q': g_camTarget.y += 4.0f; break;
+	case 'W': g_camTarget.z -= 0.4f; break;
+	case 'S': g_camTarget.z += 0.4f; break;
+	case 'D': g_camTarget.x += 0.4f; break;
+	case 'A': g_camTarget.x -= 0.4f; break;
+	case 'E': g_camTarget.y -= 0.4f; break;
+	case 'Q': g_camTarget.y += 0.4f; break;
+	case 'i': g_sphereCamRelPos.y -= 11.25f; break;
+	case 'k': g_sphereCamRelPos.y += 11.25f; break;
+	case 'j': g_sphereCamRelPos.x -= 11.25f; break;
+	case 'l': g_sphereCamRelPos.x += 11.25f; break;
+	case 'o': g_sphereCamRelPos.z -= 5.0f; break;
+	case 'u': g_sphereCamRelPos.z += 5.0f; break;
+	case 'I': g_sphereCamRelPos.y -= 1.125f; break;
+	case 'K': g_sphereCamRelPos.y += 1.125f; break;
+	case 'J': g_sphereCamRelPos.x -= 1.125f; break;
+	case 'L': g_sphereCamRelPos.x += 1.125f; break;
+	case 'O': g_sphereCamRelPos.z -= 0.5f; break;
+	case 'U': g_sphereCamRelPos.z += 0.5f; break;
+		
+	case 32:
+		printf("Target: %f, %f, %f\n", g_camTarget.x, g_camTarget.y, g_camTarget.z);
+		printf("Position: %f, %f, %f\n", g_sphereCamRelPos.x, g_sphereCamRelPos.y, g_sphereCamRelPos.z);
+		break;
 	}
+
+	g_sphereCamRelPos.y = glm::clamp(g_sphereCamRelPos.y, -78.75f, -1.0f);
+	g_camTarget.y = g_camTarget.y > 0.0f ? g_camTarget.y : 0.0f;
+	g_sphereCamRelPos.z = g_sphereCamRelPos.z > 5.0f ? g_sphereCamRelPos.z : 5.0f;
+
 	glutPostRedisplay();
 }
 

File Tut 07 World in Motion/data/ColorExactUniform.frag

-#version 330
-
-uniform vec4 baseColor;
-
-out vec4 outputColor;
-
-void main()
-{
-	outputColor = baseColor;
-}

File Tut 07 World in Motion/data/ColorUniform.frag

+#version 330
+
+uniform vec4 baseColor;
+
+out vec4 outputColor;
+
+void main()
+{
+	outputColor = baseColor;
+}

File Tut 07 World in Motion/data/GenCubes.lua

+require "XmlWriter"
+require "vmath"
+
+local function GenStringFromArray(theArray, bAsInt)
+	local array = {" "}
+	for i, vector in ipairs(theArray) do
+		local elements = vector;
+		if(bAsInt) then
+			elements = {};
+			for i, value in ipairs(vector) do
+				elements[#elements + 1] = string.format("%i", value);
+			end
+		end
+		
+		array[#array + 1] = "        " .. table.concat(vector, " ");
+	end
+	
+	return table.concat(array, "\n");
+end
+
+local positions =
+{
+	--Front
+	vmath.vec3( 0.5,  0.5,  0.5),
+	vmath.vec3( 0.5, -0.5,  0.5),
+	vmath.vec3(-0.5, -0.5,  0.5),
+	vmath.vec3(-0.5,  0.5,  0.5),
+
+	--Top
+	vmath.vec3( 0.5,  0.5,  0.5),
+	vmath.vec3(-0.5,  0.5,  0.5),
+	vmath.vec3(-0.5,  0.5, -0.5),
+	vmath.vec3( 0.5,  0.5, -0.5),
+
+	--Left
+	vmath.vec3( 0.5,  0.5,  0.5),
+	vmath.vec3( 0.5,  0.5, -0.5),
+	vmath.vec3( 0.5, -0.5, -0.5),
+	vmath.vec3( 0.5, -0.5,  0.5),
+
+	--Back
+	vmath.vec3( 0.5,  0.5, -0.5),
+	vmath.vec3(-0.5,  0.5, -0.5),
+	vmath.vec3(-0.5, -0.5, -0.5),
+	vmath.vec3( 0.5, -0.5, -0.5),
+
+	--Bottom
+	vmath.vec3( 0.5, -0.5,  0.5),
+	vmath.vec3( 0.5, -0.5, -0.5),
+	vmath.vec3(-0.5, -0.5, -0.5),
+	vmath.vec3(-0.5, -0.5,  0.5),
+
+	--Right
+	vmath.vec3(-0.5,  0.5,  0.5),
+	vmath.vec3(-0.5, -0.5,  0.5),
+	vmath.vec3(-0.5, -0.5, -0.5),
+	vmath.vec3(-0.5,  0.5, -0.5),
+};
+
+local tints =
+{
+	vmath.vec4(1.0, 1.0, 1.0, 1.0),
+	vmath.vec4(1.0, 1.0, 1.0, 1.0),
+	vmath.vec4(1.0, 1.0, 1.0, 1.0),
+	vmath.vec4(1.0, 1.0, 1.0, 1.0),
+
+	vmath.vec4(0.75, 0.75, 0.75, 1.0),
+	vmath.vec4(0.75, 0.75, 0.75, 1.0),
+	vmath.vec4(0.75, 0.75, 0.75, 1.0),
+	vmath.vec4(0.75, 0.75, 0.75, 1.0),
+
+	vmath.vec4(0.5, 0.5, 0.5, 1.0),
+	vmath.vec4(0.5, 0.5, 0.5, 1.0),
+	vmath.vec4(0.5, 0.5, 0.5, 1.0),
+	vmath.vec4(0.5, 0.5, 0.5, 1.0),
+
+	vmath.vec4(1.0, 1.0, 1.0, 1.0),
+	vmath.vec4(1.0, 1.0, 1.0, 1.0),
+	vmath.vec4(1.0, 1.0, 1.0, 1.0),
+	vmath.vec4(1.0, 1.0, 1.0, 1.0),
+
+	vmath.vec4(0.75, 0.75, 0.75, 1.0),
+	vmath.vec4(0.75, 0.75, 0.75, 1.0),
+	vmath.vec4(0.75, 0.75, 0.75, 1.0),
+	vmath.vec4(0.75, 0.75, 0.75, 1.0),
+
+	vmath.vec4(0.5, 0.5, 0.5, 1.0),
+	vmath.vec4(0.5, 0.5, 0.5, 1.0),
+	vmath.vec4(0.5, 0.5, 0.5, 1.0),
+	vmath.vec4(0.5, 0.5, 0.5, 1.0),
+}
+
+local colors =
+{
+	vmath.vec4(0.0, 1.0, 0.0, 1.0),
+	vmath.vec4(0.0, 1.0, 0.0, 1.0),
+	vmath.vec4(0.0, 1.0, 0.0, 1.0),
+	vmath.vec4(0.0, 1.0, 0.0, 1.0),
+
+	vmath.vec4(0.0, 0.0, 1.0, 1.0),
+	vmath.vec4(0.0, 0.0, 1.0, 1.0),
+	vmath.vec4(0.0, 0.0, 1.0, 1.0),
+	vmath.vec4(0.0, 0.0, 1.0, 1.0),
+
+	vmath.vec4(1.0, 0.0, 0.0, 1.0),
+	vmath.vec4(1.0, 0.0, 0.0, 1.0),
+	vmath.vec4(1.0, 0.0, 0.0, 1.0),
+	vmath.vec4(1.0, 0.0, 0.0, 1.0),
+
+	vmath.vec4(1.0, 1.0, 0.0, 1.0),
+	vmath.vec4(1.0, 1.0, 0.0, 1.0),
+	vmath.vec4(1.0, 1.0, 0.0, 1.0),
+	vmath.vec4(1.0, 1.0, 0.0, 1.0),
+
+	vmath.vec4(0.0, 1.0, 1.0, 1.0),
+	vmath.vec4(0.0, 1.0, 1.0, 1.0),
+	vmath.vec4(0.0, 1.0, 1.0, 1.0),
+	vmath.vec4(0.0, 1.0, 1.0, 1.0),
+
+	vmath.vec4(1.0, 0.0, 1.0, 1.0),
+	vmath.vec4(1.0, 0.0, 1.0, 1.0),
+	vmath.vec4(1.0, 0.0, 1.0, 1.0),
+	vmath.vec4(1.0, 0.0, 1.0, 1.0),
+}
+
+local indices =
+{
+	vmath.vec3(0, 1, 2),
+	vmath.vec3(2, 3, 0),
+
+	vmath.vec3(4, 5, 6),
+	vmath.vec3(6, 7, 4),
+
+	vmath.vec3(8, 9, 10),
+	vmath.vec3(10, 11, 8),
+
+	vmath.vec3(12, 13, 14),
+	vmath.vec3(14, 15, 12),
+
+	vmath.vec3(16, 17, 18),
+	vmath.vec3(18, 19, 16),
+
+	vmath.vec3(20, 21, 22),
+	vmath.vec3(22, 23, 20),
+};
+
+do
+	local writer = XmlWriter.XmlWriter("UnitCube.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("indices");
+			writer:AddAttribute("cmd", "triangles");
+			writer:AddAttribute("type", "ushort");
+			writer:AddText(GenStringFromArray(indices, true));
+		writer:PopElement();
+	writer:PopElement();
+	writer:Close();
+end
+
+do
+	local writer = XmlWriter.XmlWriter("UnitCubeTint.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(tints));
+		writer:PopElement();
+		writer:PushElement("indices");
+			writer:AddAttribute("cmd", "triangles");
+			writer:AddAttribute("type", "ushort");
+			writer:AddText(GenStringFromArray(indices, true));
+		writer:PopElement();
+	writer:PopElement();
+	writer:Close();
+end
+
+do
+	local writer = XmlWriter.XmlWriter("UnitCubeColor.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("indices");
+			writer:AddAttribute("cmd", "triangles");
+			writer:AddAttribute("type", "ushort");
+			writer:AddText(GenStringFromArray(indices, true));
+		writer:PopElement();
+	writer:PopElement();
+	writer:Close();
+end

File Tut 07 World in Motion/data/PosColorWorldTransform.vert

 void main()
 {
 	vec4 temp = modelToWorldMatrix * position;
-//	temp = worldToCameraMatrix * temp;
+	temp = worldToCameraMatrix * temp;
 	gl_Position = cameraToClipMatrix * temp;
 	interpColor = color;
 }

File Tut 07 World in Motion/tutorials.lua

 	"data/PosColorWorldTransform.vert",
 	"data/ColorPassthrough.frag",
 	"data/ColorMultUniform.frag",
-	"data/ColorExactUniform.frag")
+	"data/ColorUniform.frag")

File framework/framework.cpp

 		m_pData->oVAO = 0;
 	}
 
-	namespace
+	float DegToRad(float fAngDeg)
 	{
-		inline float DegToRad(float fAngDeg)
-		{
-			const float fDegToRad = 3.14159f * 2.0f / 360.0f;
-			return fAngDeg * fDegToRad;
-		}
+		const float fDegToRad = 3.14159f * 2.0f / 360.0f;
+		return fAngDeg * fDegToRad;
 	}
 
 	void MatrixStack::Rotate( glm::vec3 &axisOfRotation, float fAngDeg )
 
 		m_currMat *= translateMat;
 	}
+
+	void MatrixStack::ApplyMatrix( const glm::mat4 &theMatrix )
+	{
+		m_currMat *= theMatrix;
+	}
+
+	void MatrixStack::SetIdentity()
+	{
+		m_currMat = glm::mat4(1.0f);
+	}
+
+	void MatrixStack::Perspective( float fDegFOV, float fAspectRatio, float fZNear, float fZFar )
+	{
+		glm::mat4 persMat(0.0f);
+
+		const float degToRad = 3.14159f * 2.0f / 360.0f;
+		float fFovRad = fDegFOV * degToRad;
+		float fFrustumScale = 1.0f / tan(fFovRad / 2.0f);
+
+		persMat[0].x = fFrustumScale * fAspectRatio;
+		persMat[1].y = fFrustumScale;
+		persMat[2].z = (fZFar + fZNear) / (fZNear - fZFar);
+		persMat[2].w = -1.0f;
+		persMat[3].z = (2 * fZFar * fZNear) / (fZNear - fZFar);
+
+		m_currMat *= persMat;
+	}
+
+	void MatrixStack::SetMatrix( const glm::mat4 &theMatrix )
+	{
+		m_currMat = theMatrix;
+	}
 }
 
 
 int main(int argc, char** argv)
 {
 	glutInit(&argc, argv);
-	glutInitDisplayMode (GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL);
+	glutInitDisplayMode (GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL/* | GLUT_MULTISAMPLE | GLUT_SRGB*/);
 	glutInitContextVersion (3, 3);
 	glutInitContextProfile(GLUT_CORE_PROFILE);
 #ifdef DEBUG

File framework/framework.h

 
 namespace Framework
 {
+	float DegToRad(float fAngDeg);
+
 	GLuint CreateShader(GLenum eShaderType, const std::string &strShaderFile);
 	GLuint LoadShader(GLenum eShaderType, const std::string &strShaderFilename);
 	GLuint CreateProgram(const std::vector<GLuint> &shaderList);
 		void Scale(const glm::vec3 &scaleVec);
 		void Translate(const glm::vec3 &offsetVec);
 
+		void ApplyMatrix(const glm::mat4 &theMatrix);
+		void SetMatrix(const glm::mat4 &theMatrix);
+		void SetIdentity();
+		void Perspective(float fDegFOV, float fAspectRatio, float fZNear, float fZFar);
+
 	private:
 		glm::mat4 m_currMat;
 		std::stack<glm::mat4> m_matrices;