#include "camera.h" #include "color.h" #include "engine.h" #include "geometry.h" #include "light.h" #include "loader.h" #include "matrix.h" #include "transform.h" #include "util.h" #include "vec.h" #include // GLOBALS static Mesh mesh; static Camera camera; static LightList lights; // PRIVATE PROTOTYPES static void CheckInputs(uint32_t input); // PUBLIC FUNCTIONS int Engine_Init(Engine_Buffer &buffer, char *filename) { int result = LoadMesh(filename, mesh); if (result < 0) { return -1; } mesh.position.z = 250; mesh.material.kDiffuse = {1.0,1.0,1.0,1.0}; mesh.material.kAmbient = {1.0,1.0,1.0,1.0}; camera.SetFOV(90.0f, buffer.width, buffer.height); lights.diffuse = (LightDiffuse*)malloc(sizeof(LightDiffuse)); lights.diffuseCount = 1; lights.ambient.intensity = 1.0; lights.diffuse[0].intensity = 0.5; lights.diffuse[0].direction = Vector(1,1,1); return 0; } void Engine_Render(Engine_Buffer &buffer, uint32_t input) { CheckInputs(input); // Clear the z-buffer unsigned long bufferSize = (unsigned long)(buffer.width * buffer.height); memset(buffer.zbuffer, 0, bufferSize * sizeof(float)); // Local space to world space Matrix tTranslate = Transform_Translate( mesh.position.x, mesh.position.y, mesh.position.z); Matrix tRotate = Transform_Rotate( mesh.rotation[0], mesh.rotation[1], mesh.rotation[2]); Matrix tScale = Transform_Scale(mesh.scale); for (size_t v = 0; v < mesh.verts.size(); ++v) { mesh.vertsTransformed[v] = mesh.verts[v] * tScale * tRotate * tTranslate; } // Cull backfaces before computing colors mesh.CullBackfaces(camera.position); // Color the faces (flat shading) for (size_t f = 0; f < mesh.culledFaces.size(); ++f) { unsigned int v0 = mesh.culledFaces[f].vertIndex[0]; unsigned int v1 = mesh.culledFaces[f].vertIndex[1]; unsigned int v2 = mesh.culledFaces[f].vertIndex[2]; Vector v01 = mesh.vertsTransformed[v1] - mesh.vertsTransformed[v0]; Vector v02 = mesh.vertsTransformed[v2] - mesh.vertsTransformed[v0]; Vector normal = Vector::Cross(v01, v02); normal.Normalize(); ColorF32 totalColor = lights.ambient.ComputeColor(mesh.material.kAmbient); for (int c = 0; c < lights.diffuseCount; ++c) { totalColor += lights.diffuse[c].ComputeColor( mesh.material.kDiffuse, normal); } mesh.faces[f].color = ColorF32::ConvertToU32(totalColor); } // World space to camera (view) space Matrix tView = Transform_View(camera.position, camera.rotation); // Camera space to perspective Matrix tPersp = Transform_Perspective( camera.xZoom, camera.yZoom, camera.nearClip, camera.farClip); // Perspective to screen Matrix tScreen = Transform_Screen(camera.xScale, camera.yScale); for (size_t v = 0; v < mesh.verts.size(); ++v) { mesh.vertsTransformed[v] *= tView * tPersp * tScreen; mesh.vertsTransformed[v] /= mesh.vertsTransformed[v].w; } // Fill each face with its respective color for(size_t f = 0; f < mesh.culledFaces.size(); ++f) { unsigned int v0 = mesh.culledFaces[f].vertIndex[0]; unsigned int v1 = mesh.culledFaces[f].vertIndex[1]; unsigned int v2 = mesh.culledFaces[f].vertIndex[2]; FillTriangle( buffer, mesh.faces[f].color, mesh.vertsTransformed[v0], mesh.vertsTransformed[v1], mesh.vertsTransformed[v2]); } } void Engine_Shutdown(void) { } // PRIVATE FUNCTIONS static void CheckInputs(uint32_t input) { if (CHECK_BIT(input, TRANSLATE_X_POS)) { mesh.position.x += 10; } else if (CHECK_BIT(input, TRANSLATE_X_NEG)) { mesh.position.x -= 10; } if (CHECK_BIT(input, TRANSLATE_Z_POS)) { mesh.position.z += 10; } else if (CHECK_BIT(input, TRANSLATE_Z_NEG)) { mesh.position.z -= 10; } if (CHECK_BIT(input, TRANSLATE_Y_POS)) { mesh.position.y += 10; } else if (CHECK_BIT(input, TRANSLATE_Y_NEG)) { mesh.position.y -= 10; } if (CHECK_BIT(input, ROTATE_X_POS)) { mesh.rotation[0] += .10; } else if (CHECK_BIT(input, ROTATE_X_NEG)) { mesh.rotation[0] -= .10; } if (CHECK_BIT(input, ROTATE_Z_POS)) { mesh.rotation[1] += .10; } else if (CHECK_BIT(input, ROTATE_Z_NEG)) { mesh.rotation[1] -= .10; } if (CHECK_BIT(input, ROTATE_Y_POS)) { mesh.rotation[2] += .10; } else if (CHECK_BIT(input, ROTATE_Y_NEG)) { mesh.rotation[2] -= .10; } if (CHECK_BIT(input, SCALE_UP)) { mesh.scale += 0.1f; } else if (CHECK_BIT(input, SCALE_DOWN)) { mesh.scale -= 0.1f; } }