~zjm/Moon3D

ae42e2763cea737c9b142838acaea073420fe118 — Zack Michener a month ago 1b975b5
enforce snake-case variables
M src/clip.c => src/clip.c +11 -11
@@ 31,7 31,7 @@ The temporary polygon is erased each time after it's used to keep memory use low
	return polygonA;
}

void ClipPolygonPlane(int *srcPolygon, int *dstPolygon, Mesh *mesh, Plane clipBoundary, int *polygon_pool)
void ClipPolygonPlane(int *srcPolygon, int *dstPolygon, Mesh *mesh, Plane clip_boundary, int *polygon_pool)
/* Sutherland-Hodgeman clipping of a polygon against a plane.
srcPolygon and dstPolygon both reference vertices in mesh->vertices. Vertices
are added to the mesh as needed, and v-indices are added to dstPolygon as needed


@@ 44,19 44,19 @@ are added to the mesh as needed, and v-indices are added to dstPolygon as needed
	previous = LastPolygonVertex(srcPolygon, mesh->vertices);
	for (int i = 0; i < NumPolygonVertices(srcPolygon); i++) {
		current = PolygonVertex(srcPolygon, mesh->vertices, i);
		if (VertexInside(current, clipBoundary)) {
			if (VertexInside(previous, clipBoundary)) {
		if (VertexInside(current, clip_boundary)) {
			if (VertexInside(previous, clip_boundary)) {
				AddPolygonValue(dstPolygon, polygon_pool, PolygonValue(srcPolygon, i));
			} else {
				intersection = NewVertex(mesh->vertices);
				*intersection = ClipIntersect(previous, current, clipBoundary);
				*intersection = ClipIntersect(previous, current, clip_boundary);
				AddPolygonValue(dstPolygon, polygon_pool, PoolTotal(mesh->vertices)-1);
				AddPolygonValue(dstPolygon, polygon_pool, PolygonValue(srcPolygon, i));
			}
		} else {
			if (VertexInside(previous, clipBoundary)) {
			if (VertexInside(previous, clip_boundary)) {
				intersection = NewVertex(mesh->vertices);
				*intersection = ClipIntersect(previous, current, clipBoundary);
				*intersection = ClipIntersect(previous, current, clip_boundary);
				AddPolygonValue(dstPolygon, polygon_pool, PoolTotal(mesh->vertices)-1);
			}
		}


@@ 65,18 65,18 @@ are added to the mesh as needed, and v-indices are added to dstPolygon as needed
}

// TODO: profile & optimize
bool VertexInside(Vertex *v, Plane clipBoundary)
bool VertexInside(Vertex *v, Plane clip_boundary)
/* Tests whether a vertex is inside a plane. Planes have outward-facing normals */
{
	Vector n = clipBoundary.normal;
	Vector n = clip_boundary.normal;
	return DotProd4D(n, *v) <= 0;
}

Vertex ClipIntersect(Vertex *s, Vertex *p, Plane clipBoundary)
Vertex ClipIntersect(Vertex *s, Vertex *p, Plane clip_boundary)
/* Calculates the intersectino of a line segment with a plane */
{
	double d1 = DotProd4D(clipBoundary.normal, *s);
	double d2 = DotProd4D(clipBoundary.normal, *p);
	double d1 = DotProd4D(clip_boundary.normal, *s);
	double d2 = DotProd4D(clip_boundary.normal, *p);
	double x = (d1*p->x - d2*s->x) / (d1 - d2);
	double y = (d1*p->y - d2*s->y) / (d1 - d2);
	double z = (d1*p->z - d2*s->z) / (d1 - d2);

M src/clip.h => src/clip.h +3 -3
@@ 6,7 6,7 @@
#include "renderer.h"

int *ClipPolygon(int *polygon, Mesh *mesh, Renderer *renderer);
void ClipPolygonPlane(int *srcPolygon, int *dstPolygon, Mesh *mesh, Plane clipBoundary, int *polygon_pool);
bool VertexInside(Vertex *v, Plane clipBoundary);
Vertex ClipIntersect(Vertex *s, Vertex *p, Plane clipBoundary);
void ClipPolygonPlane(int *srcPolygon, int *dstPolygon, Mesh *mesh, Plane clip_boundary, int *polygon_pool);
bool VertexInside(Vertex *v, Plane clip_boundary);
Vertex ClipIntersect(Vertex *s, Vertex *p, Plane clip_boundary);
bool ClipPoint(Vector p, ClipPlanes clip_planes);

M src/game.c => src/game.c +9 -9
@@ 48,15 48,15 @@ int main(void)

			/* variables for perf statistics */
			long frames = 0;
			long gameMs = 0;
			long game_ms = 0;
			// long start = SDL_GetTicks();
			long dt = 0;
			long lastTime = SDL_GetTicks();
			long last_time = SDL_GetTicks();
			while (!done) {
				frames++;

				dt = SDL_GetTicks() - lastTime;
				lastTime = SDL_GetTicks();
				dt = SDL_GetTicks() - last_time;
				last_time = SDL_GetTicks();

				long start = SDL_GetTicks();
				/* main game loop */


@@ 64,7 64,7 @@ int main(void)
				ClearScreen(gameRenderer->viewport);
				RenderScene(scene, gameRenderer);
				long elapsed = SDL_GetTicks() - start;
				gameMs += elapsed;
				game_ms += elapsed;

				/* copy our framebuffer to SDL for display */
				SDL_UpdateTexture(texture, NULL, pixels, SCREEN_WIDTH*sizeof(uint32_t));


@@ 84,10 84,10 @@ int main(void)
				}
			}
			/* display perf stats */
			double gameSecs = (double)gameMs/1000;
			double fps = (double)frames/gameSecs;
			double frameTime = 1000/fps;
			printf("%.1f fps, %.1fms per frame\n", fps, frameTime);
			double game_secs = (double)game_ms/1000;
			double fps = (double)frames/game_secs;
			double frame_time = 1000/fps;
			printf("%.1f fps, %.1fms per frame\n", fps, frame_time);

			SDL_DestroyRenderer(renderer);
			SDL_DestroyWindow(window);

M src/obj.c => src/obj.c +8 -8
@@ 5,17 5,17 @@ bool LoadObj(const char *filename, Mesh *mesh)
/* Loads an OBJ file into an empty Mesh. Returns success or failure. */
{
	FILE *fp;
	bool fileOk = true;
	bool file_ok = true;
	int line = 0;

	fp = fopen(filename, "r");
	while (!feof(fp) && fileOk) {
	while (!feof(fp) && file_ok) {
		line++;
		fileOk = ReadObjLine(fp, mesh);
		file_ok = ReadObjLine(fp, mesh);
	}
	fclose(fp);

	if (!fileOk) {
	if (!file_ok) {
		printf("Error reading \"%s\" on line %d\n", filename, line+1);
		return false;
	}


@@ 28,9 28,9 @@ bool ReadObjLine(FILE *fp, Mesh *mesh)
to subroutines. Right now we only support OBJ_VERTEX and OBJ_FACE.
*/
{
	char itemType[8];
	if (fscanf(fp, "%8s", itemType) == 1) {
		switch (ParseLineType(itemType)) {
	char item_type[8];
	if (fscanf(fp, "%8s", item_type) == 1) {
		switch (ParseLineType(item_type)) {
			case OBJ_VERTEX: 	return ReadObjVertex(fp, mesh);
			case OBJ_FACE: 		return ReadObjFace(fp, mesh);
			case OBJ_EMPTY: 	return true;


@@ 38,7 38,7 @@ to subroutines. Right now we only support OBJ_VERTEX and OBJ_FACE.
				fscanf(fp, "%*[^\n]\n"); // skip the rest of the line
				return true;
			case OBJ_UNKNOWN:
				printf("Unknown \"%s\"\n", itemType);
				printf("Unknown \"%s\"\n", item_type);
				return false;
			default:
				fscanf(fp, "%*[^\n]\n"); // skip the rest of the line

M src/particle.c => src/particle.c +1 -1
@@ 28,7 28,7 @@ void RenderParticle(Particle particle, Renderer *renderer, Transform camera_tran
	Vertex v = ApplyTransform(camera_transform, particle.position);
	if (ClipPoint(v, renderer->clip_planes)) {
		v = Homogenize(v);
		CommitTransform(renderer->deviceTransform, &v);
		CommitTransform(renderer->device_transform, &v);
		DrawPoint(v, particle.color, renderer->viewport);
	}
}

M src/renderable.c => src/renderable.c +1 -1
@@ 51,7 51,7 @@ void Render(Renderable renderable, Renderer *renderer, Transform camera_transfor
	// TODO: skip clipped vertices
	for (i = 0; i < PoolTotal(renderMesh.vertices); i++) {
		renderMesh.vertices[i] = Homogenize(renderMesh.vertices[i]);
		CommitTransform(renderer->deviceTransform, &renderMesh.vertices[i]);
		CommitTransform(renderer->device_transform, &renderMesh.vertices[i]);
	}

	/* rasterize all faces */

M src/renderer.c => src/renderer.c +2 -2
@@ 10,9 10,9 @@ aspect ratio.
{
	Renderer *r = malloc(sizeof(Renderer));
	r->viewport = NewViewport(pixels, WHITE, width, height);
	r->deviceTransform = Translation(V(1, 1, 0));
	r->device_transform = Translation(V(1, 1, 0));
	/* scale to viewport size */
	Scale(&(r->deviceTransform), 0.5*(width-1), 0.5*(height-1), 1);
	Scale(&(r->device_transform), 0.5*(width-1), 0.5*(height-1), 1);

	r->vertex_pool = NewPool(Vertex, MAX_RENDER_VERTICES);
	r->polygon_pool = NewPool(int, MAX_RENDER_POLYGONS);

M src/renderer.h => src/renderer.h +1 -1
@@ 16,7 16,7 @@ typedef struct ClipPlanes {

typedef struct Renderer {
	Viewport *viewport;
	Transform deviceTransform;
	Transform device_transform;
	Vertex *vertex_pool;
	int *polygon_pool;
	int *alt_polygon_pool;

M src/viewport.c => src/viewport.c +11 -11
@@ 8,7 8,7 @@ Viewport *NewViewport(Pixel *pixels, Color background_color, int width, int heig
	Viewport *viewport = malloc(sizeof(Viewport));
	viewport->pixels = pixels;
	viewport->background_color = background_color;
	viewport->depthBuffer = NewDepthBuffer(width, height);
	viewport->depth_buffer = NewDepthBuffer(width, height);
	viewport->width = width;
	viewport->height = height;
	return viewport;


@@ 39,16 39,16 @@ void ClearScreen(Viewport *viewport)

void RasterizePolygon(int *polygon, Vertex *vertices, Viewport *viewport)
{
	Rect boundingBox = PolygonBounds(polygon, vertices);
	DrawBoundingBox(boundingBox, viewport);
	Rect bounding_box = PolygonBounds(polygon, vertices);
	DrawBoundingBox(bounding_box, viewport);
}

void DrawBoundingBox(Rect boundingBox, Viewport *viewport)
void DrawBoundingBox(Rect bounding_box, Viewport *viewport)
{
	RasterLine(V(boundingBox.left, boundingBox.top, 0), V(boundingBox.right, boundingBox.top, 0), GRAY, viewport);
	RasterLine(V(boundingBox.right, boundingBox.top, 0), V(boundingBox.right, boundingBox.bottom, 0), GRAY, viewport);
	RasterLine(V(boundingBox.left, boundingBox.bottom, 0), V(boundingBox.right, boundingBox.bottom, 0), GRAY, viewport);
	RasterLine(V(boundingBox.left, boundingBox.top, 0), V(boundingBox.left, boundingBox.bottom, 0), GRAY, viewport);
	RasterLine(V(bounding_box.left, bounding_box.top, 0), V(bounding_box.right, bounding_box.top, 0), GRAY, viewport);
	RasterLine(V(bounding_box.right, bounding_box.top, 0), V(bounding_box.right, bounding_box.bottom, 0), GRAY, viewport);
	RasterLine(V(bounding_box.left, bounding_box.bottom, 0), V(bounding_box.right, bounding_box.bottom, 0), GRAY, viewport);
	RasterLine(V(bounding_box.left, bounding_box.top, 0), V(bounding_box.left, bounding_box.bottom, 0), GRAY, viewport);
}

// TODO: find a more efficient way to wireframe a mesh without duplicating edges


@@ 157,7 157,7 @@ void WriteDepth(int x, int y, DepthVal value, Viewport *viewport)
/* Writes a depth value into a viewport's depth buffer */
{
	if (x >= 0 && x < viewport->width && y >= 0 && y < viewport->height) {
		viewport->depthBuffer[(viewport->height - 1 - y)*viewport->width+x] = value;
		viewport->depth_buffer[(viewport->height - 1 - y)*viewport->width+x] = value;
	}
}



@@ 165,8 165,8 @@ bool UpdateDepthBuffer(int x, int y, double z, Viewport *viewport)
/* Returns whether z is in front of a depth value at an x, y position. Updates
the depth buffer with the z value if it is in front */
{
	if (z > viewport->depthBuffer[y*viewport->width+x]) {
		viewport->depthBuffer[y*viewport->width+x] = z;
	if (z > viewport->depth_buffer[y*viewport->width+x]) {
		viewport->depth_buffer[y*viewport->width+x] = z;
		return true;
	} else {
		return false;

M src/viewport.h => src/viewport.h +1 -1
@@ 23,7 23,7 @@ typedef double DepthVal;

typedef struct Viewport {
	Pixel *pixels;
	DepthVal *depthBuffer;
	DepthVal *depth_buffer;
	Color background_color;
	int width;
	int height;