#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; static Texture texture; // 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.local.verts.size(); ++v) { mesh.transformed.verts[v].point = mesh.local.verts[v].point * tScale * tRotate * tTranslate; mesh.transformed.verts[v].normal = mesh.local.verts[v].normal * tScale * tRotate * tTranslate; } // Cull backfaces before computing colors CullBackfaces(mesh.local, mesh.transformed, camera.position); // Color the vertices for Gouraud shading if (mesh.smooth) { for (size_t f = 0; f < mesh.transformed.faces.size(); ++f) { for (int i = 0; i < 3; ++i) { unsigned int v = mesh.transformed.faces[f].vertIndex[i]; ColorF32 totalColor = lights.ambient.ComputeColor(mesh.material.kAmbient); for (int c = 0; c < lights.diffuseCount; ++c) { totalColor += lights.diffuse[c].ComputeColor( mesh.material.kDiffuse, mesh.transformed.verts[v].normal); } mesh.transformed.verts[v].color = totalColor; } } } // Color the face for flat shading else { for (size_t f = 0; f < mesh.transformed.faces.size(); ++f) { ColorF32 totalColor = lights.ambient.ComputeColor(mesh.material.kAmbient); for (int c = 0; c < lights.diffuseCount; ++c) { totalColor += lights.diffuse[c].ComputeColor( mesh.material.kDiffuse, mesh.transformed.faces[f].normal); } mesh.transformed.faces[f].color = 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.transformed.verts.size(); ++v) { mesh.transformed.verts[v].point *= tView * tPersp * tScreen; mesh.transformed.verts[v].point.x /= mesh.transformed.verts[v].point.w; mesh.transformed.verts[v].point.y /= mesh.transformed.verts[v].point.w; mesh.transformed.verts[v].point.z /= mesh.transformed.verts[v].point.w; } RenderMesh(buffer, mesh.transformed, mesh.smooth, texture, mesh.local.uvs); } 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; } if (CHECK_BIT(input, SHADING_TOGGLE)) { mesh.smooth = true; } else { mesh.smooth = false; } }