diff --git a/GL/clip.c b/GL/clip.c index a5c101d..4e436c0 100644 --- a/GL/clip.c +++ b/GL/clip.c @@ -1,5 +1,10 @@ #include +#include + +#include + #include "clip.h" +#include "../containers/aligned_vector.h" ClipResult clipLineToNearZ(const float* v1, const float* v2, const float dist, float* vout, float* t) { if(v1[2] < dist && v2[2] < dist) { @@ -32,3 +37,287 @@ ClipResult clipLineToNearZ(const float* v1, const float* v2, const float dist, f return CLIP_RESULT_ALL_ON_PLANE; } } + +static void interpolateFloat(const float v1, const float v2, const float t, float* out) { + *out = v1 + (v2 - v1) * t; +} + +static void interpolateVec2(const float* v1, const float* v2, const float t, float* out) { + /* FIXME: SH4 has an asm instruction for this */ + out[0] = v1[0] + (v2[0] - v1[0]) * t; + out[1] = v1[1] + (v2[1] - v1[1]) * t; +} + +static void interpolateVec3(const float* v1, const float* v2, const float t, float* out) { + /* FIXME: SH4 has an asm instruction for this */ + out[0] = v1[0] + (v2[0] - v1[0]) * t; + out[1] = v1[1] + (v2[1] - v1[1]) * t; + out[2] = v1[2] + (v2[2] - v1[2]) * t; +} + +static void interpolateColour(const uint32_t* c1, const uint32_t* c2, const float t, uint32_t* out) { + float r1 = (*c1 >> 16) & 0xFF; + float r2 = (*c2 >> 16) & 0xFF; + uint8_t r = (r1 + (r2 - r1) * t); + + r1 = (*c1 >> 24) & 0xFF; + r2 = (*c2 >> 24) & 0xFF; + uint8_t a = (r1 + (r2 - r1) * t); + + r1 = (*c1 >> 8) & 0xFF; + r2 = (*c2 >> 8) & 0xFF; + uint8_t g = (r1 + (r2 - r1) * t); + + r1 = (*c1 >> 0) & 0xFF; + r2 = (*c2 >> 0) & 0xFF; + uint8_t b = (r1 + (r2 - r1) * t); + + *out = (a << 24 | r << 16 | g << 8 | b); +} + +const uint32_t VERTEX_CMD_EOL = 0xf0000000; +const uint32_t VERTEX_CMD = 0xe0000000; + +void clipTriangleStrip(AlignedVector* vertices, AlignedVector* outBuffer) { + + /* Clipping triangle strips is *hard* this is the algorithm we follow: + * + * - Treat each triangle in the strip individually. + * - If we find a triangle that needs clipping, treat it in isolation. + * - End the strip at the triangle + * - Generate a new single-triangle strip for it + * - Begin a new strip for the remainder of the strip + * + * There is probably more efficient way but there are so many different cases to handle that it's + * difficult to even write them down! + */ + + /* FIXME: Why this value? This was copied from libGL because using zero wasn't working right. + * + * I think this is a hack. We should really be clipping against the W coordinate of each vertex... but I'm not sure + * how yet.. + */ + const float CLIP_DISTANCE = -0.2; + + uint32_t i; + + for(i = 2; i < vertices->size; ++i) { + ClipVertex* sourceTriangle[3] = { + aligned_vector_at(vertices, i - 2), + aligned_vector_at(vertices, i - 1), + aligned_vector_at(vertices, i) + }; + + /* If we're on an odd vertex, we need to swap the order of the first two vertices, as that's what + * triangle strips do */ + uint8_t even = i % 2 == 0; + ClipVertex* v1 = even ? sourceTriangle[0] : sourceTriangle[1]; + ClipVertex* v2 = even ? sourceTriangle[1] : sourceTriangle[0]; + ClipVertex* v3 = sourceTriangle[2]; + + uint8_t visible = ((v1->w > 0) ? 4 : 0) | ((v2->w > 0) ? 2 : 0) | ((v3->w > 0) ? 1 : 0); + uint8_t startOfStrip = (i == 2) || (outBuffer->size > 2 && ((ClipVertex*) aligned_vector_back(outBuffer))->flags == VERTEX_CMD_EOL); + + /* All visible, we're fine! */ + if(visible == 0b111) { + if(startOfStrip) { + aligned_vector_push_back(outBuffer, v1, 1); + aligned_vector_push_back(outBuffer, v2, 1); + } + + aligned_vector_push_back(outBuffer, v3, 1); + } else if(visible == 0b000) { + /* Do nothing */ + continue; + } else if(visible == 0b100) { + /* Only the first vertex is visible */ + float t1 = 0, t2 = 0; + + ClipVertex output[3]; + + clipLineToNearZ(v1->xyz, v2->xyz, CLIP_DISTANCE, output[1].xyz, &t1); + clipLineToNearZ(v1->xyz, v3->xyz, CLIP_DISTANCE, output[2].xyz, &t2); + + interpolateFloat(v1->w, v2->w, t1, &output[1].w); + interpolateFloat(v1->w, v3->w, t2, &output[2].w); + + output[0] = *v1; + + /* Interpolate normals */ + interpolateVec3(v1->nxyz, v2->nxyz, t1, output[1].nxyz); + interpolateVec3(v1->nxyz, v3->nxyz, t2, output[2].nxyz); + + /* Interpolate texcoords */ + interpolateVec2(v1->uv, v2->uv, t1, output[1].uv); + interpolateVec2(v1->uv, v3->uv, t2, output[2].uv); + + interpolateColour((uint32_t*) &v1->argb, (uint32_t*) &v2->argb, t1, (uint32_t*) &output[1].argb); + interpolateColour((uint32_t*) &v1->argb, (uint32_t*) &v3->argb, t2, (uint32_t*) &output[2].argb); + + output[0].flags = VERTEX_CMD; + output[1].flags = VERTEX_CMD; + output[2].flags = VERTEX_CMD_EOL; + + aligned_vector_push_back(outBuffer, output, 3); + } else if(visible == 0b010) { + /* Only the second vertex is visible */ + + float t1 = 0, t2 = 0; + + ClipVertex output[3]; + + clipLineToNearZ(v2->xyz, v1->xyz, CLIP_DISTANCE, output[0].xyz, &t1); + clipLineToNearZ(v2->xyz, v3->xyz, CLIP_DISTANCE, output[2].xyz, &t2); + + interpolateFloat(v2->w, v1->w, t1, &output[0].w); + interpolateFloat(v2->w, v3->w, t2, &output[2].w); + + output[1] = *v2; + + /* Interpolate normals */ + interpolateVec3(v2->nxyz, v1->nxyz, t1, output[0].nxyz); + interpolateVec3(v2->nxyz, v3->nxyz, t2, output[2].nxyz); + + /* Interpolate texcoords */ + interpolateVec2(v2->uv, v1->uv, t1, output[0].uv); + interpolateVec2(v2->uv, v3->uv, t2, output[2].uv); + + interpolateColour((uint32_t*) &v2->argb, (uint32_t*) &v1->argb, t1, (uint32_t*) &output[0].argb); + interpolateColour((uint32_t*) &v2->argb, (uint32_t*) &v3->argb, t2, (uint32_t*) &output[2].argb); + + output[0].flags = VERTEX_CMD; + output[1].flags = VERTEX_CMD; + output[2].flags = VERTEX_CMD_EOL; + + aligned_vector_push_back(outBuffer, output, 3); + } else if(visible == 0b001) { + /* Only the third vertex is visible */ + + float t1 = 0, t2 = 0; + + ClipVertex output[3]; + + clipLineToNearZ(v3->xyz, v1->xyz, CLIP_DISTANCE, output[0].xyz, &t1); + clipLineToNearZ(v3->xyz, v2->xyz, CLIP_DISTANCE, output[1].xyz, &t2); + + interpolateFloat(v3->w, v1->w, t1, &output[0].w); + interpolateFloat(v3->w, v2->w, t2, &output[1].w); + + output[2] = *v3; + + /* Interpolate normals */ + interpolateVec3(v3->nxyz, v1->nxyz, t1, output[0].nxyz); + interpolateVec3(v3->nxyz, v2->nxyz, t2, output[1].nxyz); + + /* Interpolate texcoords */ + interpolateVec2(v3->uv, v1->uv, t1, output[0].uv); + interpolateVec2(v3->uv, v2->uv, t2, output[1].uv); + + interpolateColour((uint32_t*) &v3->argb, (uint32_t*) &v1->argb, t1, (uint32_t*) &output[0].argb); + interpolateColour((uint32_t*) &v3->argb, (uint32_t*) &v2->argb, t2, (uint32_t*) &output[1].argb); + + output[0].flags = VERTEX_CMD; + output[1].flags = VERTEX_CMD; + output[2].flags = VERTEX_CMD_EOL; + + aligned_vector_push_back(outBuffer, output, 3); + } else if(visible == 0b110) { + /* Third vertex isn't visible */ + + float t1 = 0, t2 = 0; + + ClipVertex output[4]; + + clipLineToNearZ(v2->xyz, v3->xyz, CLIP_DISTANCE, output[2].xyz, &t1); + clipLineToNearZ(v1->xyz, v3->xyz, CLIP_DISTANCE, output[3].xyz, &t2); + + interpolateFloat(v2->w, v3->w, t1, &output[2].w); + interpolateFloat(v1->w, v3->w, t2, &output[3].w); + + output[0] = *v1; + output[1] = *v2; + + /* Interpolate normals */ + interpolateVec3(v2->nxyz, v3->nxyz, t1, output[2].nxyz); + interpolateVec3(v1->nxyz, v3->nxyz, t2, output[3].nxyz); + + /* Interpolate texcoords */ + interpolateVec2(v2->uv, v3->uv, t1, output[2].uv); + interpolateVec2(v1->uv, v3->uv, t2, output[3].uv); + + interpolateColour((uint32_t*) &v2->argb, (uint32_t*) &v3->argb, t1, (uint32_t*) &output[2].argb); + interpolateColour((uint32_t*) &v1->argb, (uint32_t*) &v3->argb, t2, (uint32_t*) &output[3].argb); + + output[0].flags = VERTEX_CMD; + output[1].flags = VERTEX_CMD; + output[2].flags = VERTEX_CMD; + output[3].flags = VERTEX_CMD_EOL; + + aligned_vector_push_back(outBuffer, output, 4); + } else if(visible == 0b011) { + /* First vertex isn't visible, so let's clip along the lines to the second and third */ + float t1 = 0, t2 = 0; + + ClipVertex output[4]; + + clipLineToNearZ(v1->xyz, v2->xyz, CLIP_DISTANCE, output[0].xyz, &t1); + clipLineToNearZ(v1->xyz, v3->xyz, CLIP_DISTANCE, output[2].xyz, &t2); + + interpolateFloat(v1->w, v2->w, t1, &output[0].w); + interpolateFloat(v1->w, v3->w, t2, &output[2].w); + + output[1] = *v2; + output[3] = *v3; + + /* Interpolate normals */ + interpolateVec3(v1->nxyz, v2->nxyz, t1, output[0].nxyz); + interpolateVec3(v1->nxyz, v3->nxyz, t2, output[2].nxyz); + + /* Interpolate texcoords */ + interpolateVec2(v1->uv, v2->uv, t1, output[0].uv); + interpolateVec2(v1->uv, v3->uv, t2, output[2].uv); + + interpolateColour((uint32_t*) &v1->argb, (uint32_t*) &v2->argb, t1, (uint32_t*) &output[0].argb); + interpolateColour((uint32_t*) &v1->argb, (uint32_t*) &v3->argb, t2, (uint32_t*) &output[2].argb); + + output[0].flags = VERTEX_CMD; + output[1].flags = VERTEX_CMD; + output[2].flags = VERTEX_CMD; + output[3].flags = VERTEX_CMD_EOL; + + aligned_vector_push_back(outBuffer, output, 4); + } else if(visible == 0b101) { + /* Second vertex isn't visible */ + float t1 = 0, t2 = 0; + + ClipVertex output[4]; + + clipLineToNearZ(v1->xyz, v2->xyz, CLIP_DISTANCE, output[1].xyz, &t1); + clipLineToNearZ(v3->xyz, v2->xyz, CLIP_DISTANCE, output[3].xyz, &t2); + + interpolateFloat(v1->w, v2->w, t1, &output[1].w); + interpolateFloat(v3->w, v2->w, t2, &output[3].w); + + output[0] = *v1; + output[2] = *v3; + + /* Interpolate normals */ + interpolateVec3(v1->nxyz, v2->nxyz, t1, output[1].nxyz); + interpolateVec3(v3->nxyz, v2->nxyz, t2, output[3].nxyz); + + /* Interpolate texcoords */ + interpolateVec2(v1->uv, v2->uv, t1, output[1].uv); + interpolateVec2(v3->uv, v2->uv, t2, output[3].uv); + + interpolateColour((uint32_t*) &v1->argb, (uint32_t*) &v2->argb, t1, (uint32_t*) &output[1].argb); + interpolateColour((uint32_t*) &v3->argb, (uint32_t*) &v2->argb, t2, (uint32_t*) &output[3].argb); + + output[0].flags = VERTEX_CMD; + output[1].flags = VERTEX_CMD; + output[2].flags = VERTEX_CMD; + output[3].flags = VERTEX_CMD_EOL; + + aligned_vector_push_back(outBuffer, output, 4); + } + } +} diff --git a/GL/clip.h b/GL/clip.h index c6a496b..40f362b 100644 --- a/GL/clip.h +++ b/GL/clip.h @@ -1,6 +1,10 @@ #ifndef CLIP_H #define CLIP_H +#include + +#include "../containers/aligned_vector.h" + #ifdef __cplusplus extern "C" { #endif @@ -13,8 +17,34 @@ typedef enum { CLIP_RESULT_BACK_TO_FRONT } ClipResult; +typedef struct { + uint8_t a; + uint8_t r; + uint8_t g; + uint8_t b; +} ClipColour; + +/* Note: This structure is the almost the same format as pvr_vertex_t aside from the offet + * (oargb) which is replaced by the floating point w value. This is so that we can + * simply zero it and memcpy the lot into the output */ +typedef struct { + uint32_t flags; + float xyz[3]; + float uv[2]; + ClipColour argb; + float nxyz[3]; + float w; + + float xyzES[3]; /* Coordinate in eye space */ + float nES[3]; /* Normal in eye space */ +} ClipVertex; + ClipResult clipLineToNearZ(const float* v1, const float* v2, const float dist, float* vout, float* t); + +void clipTriangleStrip(AlignedVector* vertices, AlignedVector* outBuffer); + + #ifdef __cplusplus } #endif diff --git a/GL/draw.c b/GL/draw.c index f601edf..2a79aaf 100644 --- a/GL/draw.c +++ b/GL/draw.c @@ -150,6 +150,8 @@ static void _parseIndex(GLshort* out, const GLubyte* in, GLenum type) { x = __x; y = __y; z = __z; \ } + +/* FIXME: Is this right? Shouldn't it be fr12->15? */ #undef mat_trans_normal3 #define mat_trans_normal3(x, y, z) { \ register float __x __asm__("fr8") = (x); \ @@ -165,42 +167,16 @@ static void _parseIndex(GLshort* out, const GLubyte* in, GLenum type) { } - -inline void transformToEyeSpace(GLfloat* point) { +static inline void transformToEyeSpace(GLfloat* point) { _matrixLoadModelView(); mat_trans_single3_nodiv(point[0], point[1], point[2]); } - -inline void transformNormalToEyeSpace(GLfloat* normal) { +static inline void transformNormalToEyeSpace(GLfloat* normal) { _matrixLoadNormal(); mat_trans_normal3(normal[0], normal[1], normal[2]); } - -typedef struct { - uint8_t a; - uint8_t r; - uint8_t g; - uint8_t b; -} Colour; - -/* Note: This structure is the almost the same format as pvr_vertex_t aside from the offet - * (oargb) which is replaced by the floating point w value. This is so that we can - * simply zero it and memcpy the lot into the output */ -typedef struct { - uint32_t flags; - float xyz[3]; - float uv[2]; - Colour argb; - float nxyz[3]; - float w; - - float xyzES[3]; /* Coordinate in eye space */ - float nES[3]; /* Normal in eye space */ -} ClipVertex; - - static void swapVertex(ClipVertex* v1, ClipVertex* v2) { ClipVertex tmp = *v1; *v1 = *v2; @@ -300,9 +276,10 @@ static void transform(AlignedVector* vertices) { register float __x __asm__("fr12") = (vertex->xyz[0]); register float __y __asm__("fr13") = (vertex->xyz[1]); register float __z __asm__("fr14") = (vertex->xyz[2]); - register float __w __asm__("fr15") = 1.0f; + register float __w __asm__("fr15"); __asm__ __volatile__( + "fldi1 fr15\n" "ftrv xmtrx,fv12\n" : "=f" (__x), "=f" (__y), "=f" (__z), "=f" (__w) : "0" (__x), "1" (__y), "2" (__z), "3" (__w) @@ -317,6 +294,27 @@ static void transform(AlignedVector* vertices) { static void clip(AlignedVector* vertices) { /* Perform clipping, generating new vertices as necessary */ + + static AlignedVector* CLIP_BUFFER = NULL; + + /* First entry into this, allocate the clip buffer */ + if(!CLIP_BUFFER) { + CLIP_BUFFER = (AlignedVector*) malloc(sizeof(AlignedVector)); + aligned_vector_init(CLIP_BUFFER, sizeof(ClipVertex)); + } + + /* Make sure we allocate roughly enough space */ + aligned_vector_reserve(CLIP_BUFFER, vertices->size); + + /* Start from empty */ + aligned_vector_resize(CLIP_BUFFER, 0); + + /* Now perform clipping! */ + clipTriangleStrip(vertices, CLIP_BUFFER); + + /* Copy the clip buffer over the vertices */ + aligned_vector_resize(vertices, CLIP_BUFFER->size); + memcpy(vertices->data, CLIP_BUFFER->data, CLIP_BUFFER->size * CLIP_BUFFER->element_size); } static void mat_transform3(const float* xyz, const float* xyzOut, const uint32_t count, const uint32_t stride) { @@ -385,7 +383,7 @@ static void light(AlignedVector* vertices) { } uint32_t final = PVR_PACK_COLOR(contribution[3], contribution[0], contribution[1], contribution[2]); - vertex->argb = *((Colour*) &final); + vertex->argb = *((ClipColour*) &final); } } @@ -397,7 +395,7 @@ static void divide(AlignedVector* vertices) { for(i = 0; i < vertices->size; ++i, ++vertex) { vertex->xyz[2] = 1.0f / vertex->w; vertex->xyz[0] *= vertex->xyz[2]; - vertex->xyz[1] *= vertex->xyz[2]; + vertex->xyz[1] *= vertex->xyz[2]; } } @@ -465,8 +463,8 @@ static void submitVertices(GLenum mode, GLsizei first, GLsizei count, GLenum typ generate(buffer, mode, first, count, (GLubyte*) indices, type, vptr, vstride, cptr, cstride, uvptr, uvstride, nptr, nstride); light(buffer); transform(buffer); + clip(buffer); divide(buffer); - push(buffer, activePolyList()); } diff --git a/GL/matrix.c b/GL/matrix.c index 406deab..d4ce3ff 100644 --- a/GL/matrix.c +++ b/GL/matrix.c @@ -1,6 +1,7 @@ #include #include +#include #include "../include/gl.h" #include "../containers/stack.h" @@ -19,7 +20,6 @@ static GLint gl_viewport_x1, gl_viewport_y1, gl_viewport_width, gl_viewport_heig static Stack MATRIX_STACKS[3]; // modelview, projection, texture static matrix_t NORMAL_MATRIX __attribute__((aligned(32))); static matrix_t SCREENVIEW_MATRIX __attribute__((aligned(32))); -static matrix_t RENDER_MATRIX __attribute__((aligned(32))); static GLenum MATRIX_MODE = GL_MODELVIEW; static GLubyte MATRIX_IDX = 0; @@ -163,9 +163,9 @@ void APIENTRY glOrtho(GLfloat left, GLfloat right, /* Ortho Matrix */ static matrix_t OrthoMatrix __attribute__((aligned(32))) = { - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 1.0f } }; @@ -275,27 +275,30 @@ void APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { gl_viewport_width = width; gl_viewport_height = height; - /* Calculate the viewport scale and offset */ - gl_viewport_scale[0] = (GLfloat)width / 2.0f; - gl_viewport_offset[0] = gl_viewport_scale[0] + (GLfloat)x; - gl_viewport_scale[1] = (GLfloat)height / 2.0f; - gl_viewport_offset[1] = gl_viewport_scale[1] + (GLfloat)y; - gl_viewport_scale[2] = (gl_depthrange_far - gl_depthrange_near) / 2.0f; - gl_viewport_offset[2] = (gl_depthrange_near + gl_depthrange_far) / 2.0f; + GLfloat rw = x + width; + GLfloat lw = x; + GLfloat tw = y + height; + GLfloat bw = y; - gl_viewport_offset[2] += 0.0001f; + GLfloat hw = ((GLfloat) width) / 2.0f; + GLfloat hh = ((GLfloat) height) / 2.0f; - /* Set the Screenview Matrix based on the viewport */ - SCREENVIEW_MATRIX[0][0] = gl_viewport_scale[0]; - SCREENVIEW_MATRIX[1][1] = -gl_viewport_scale[1]; - SCREENVIEW_MATRIX[2][2] = 1; - SCREENVIEW_MATRIX[3][0] = gl_viewport_offset[0]; - SCREENVIEW_MATRIX[3][1] = vid_mode->height - gl_viewport_offset[1]; + SCREENVIEW_MATRIX[0][0] = hw; + SCREENVIEW_MATRIX[1][1] = -hh; + SCREENVIEW_MATRIX[2][2] = 1; //(gl_depthrange_far - gl_depthrange_near) / 2.0f; + SCREENVIEW_MATRIX[3][0] = (rw + lw) / 2.0f; + SCREENVIEW_MATRIX[3][1] = (tw + bw) / 2.0f; + // SCREENVIEW_MATRIX[3][2] = (gl_depthrange_far + gl_depthrange_near) / 2.0f; } /* Set the depth range */ void APIENTRY glDepthRange(GLclampf n, GLclampf f) { - /* clamp the values... */ + /* FIXME: This currently does nothing because the SCREENVIEW_MATRIX is multiplied prior to perpective division + * and not after as traditional GL. See here for more info: http://www.thecodecrate.com/opengl-es/opengl-viewport-matrix/ + * + * We probably need to make tweaks to the SCREENVIEW matrix or clipping or whatever to make this work + */ + if(n < 0.0f) n = 0.0f; else if(n > 1.0f) n = 1.0f; @@ -304,10 +307,6 @@ void APIENTRY glDepthRange(GLclampf n, GLclampf f) { gl_depthrange_near = n; gl_depthrange_far = f; - - /* Adjust the viewport scale and offset for Z */ - gl_viewport_scale[2] = ((f - n) / 2.0f); - gl_viewport_offset[2] = (n + f) / 2.0f; } /* Vector Cross Product - Used by glhLookAtf2 */ @@ -386,11 +385,6 @@ void _applyRenderMatrix() { mat_load(&SCREENVIEW_MATRIX); mat_apply(stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF))); mat_apply(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF))); - mat_store(&RENDER_MATRIX); -} - -void _matrixLoadRender() { - mat_load(&RENDER_MATRIX); } void _matrixLoadTexture() { diff --git a/GL/private.h b/GL/private.h index eac62de..c5f64c3 100644 --- a/GL/private.h +++ b/GL/private.h @@ -74,7 +74,6 @@ void initFramebuffers(); void _matrixLoadNormal(); void _matrixLoadModelView(); void _matrixLoadTexture(); -void _matrixLoadRender(); void _applyRenderMatrix(); void wipeTextureOnFramebuffers(GLuint texture); diff --git a/containers/aligned_vector.c b/containers/aligned_vector.c index a8310a3..8ad7a80 100644 --- a/containers/aligned_vector.c +++ b/containers/aligned_vector.c @@ -70,6 +70,10 @@ void* aligned_vector_at(const AlignedVector* vector, const unsigned int index) { return &vector->data[index * vector->element_size]; } +void* aligned_vector_back(AlignedVector* vector) { + return aligned_vector_at(vector, vector->size - 1); +} + void* aligned_vector_extend(AlignedVector* vector, const unsigned int additional_count) { const unsigned int current = vector->size; aligned_vector_resize(vector, vector->size + additional_count); diff --git a/containers/aligned_vector.h b/containers/aligned_vector.h index 2ddf5ec..2b710d4 100644 --- a/containers/aligned_vector.h +++ b/containers/aligned_vector.h @@ -23,6 +23,7 @@ void* aligned_vector_extend(AlignedVector* vector, const unsigned int additional void aligned_vector_clear(AlignedVector* vector); void aligned_vector_shrink_to_fit(AlignedVector* vector); void aligned_vector_cleanup(AlignedVector* vector); +void* aligned_vector_back(AlignedVector* vector); #ifdef __cplusplus } diff --git a/samples/Makefile b/samples/Makefile index ca3c239..668e46d 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -14,3 +14,5 @@ all: $(KOS_MAKE) -C ortho2d all $(KOS_MAKE) -C lerabot01 all $(KOS_MAKE) -C zclip all + $(KOS_MAKE) -C zclip_triangle all + $(KOS_MAKE) -C zclip_trianglestrip all diff --git a/samples/zclip/main.c b/samples/zclip/main.c index 566ab25..b99f3a0 100644 --- a/samples/zclip/main.c +++ b/samples/zclip/main.c @@ -144,6 +144,7 @@ void InitGL(int Width, int Height) // We call this right after our OpenG gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); } /* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */ @@ -205,9 +206,9 @@ void RenderFloor() { glBindTexture(GL_TEXTURE_2D, road.texID); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); - glVertex3f(-100, 0, -0.0); + glVertex3f(-100, 0, 0); glTexCoord2f(50.0f, 0.0f); - glVertex3f( 100, 0, -0.0); + glVertex3f( 100, 0, 0); glTexCoord2f(50.0f, 100.0f); glVertex3f( 100, 0, -200.0); glTexCoord2f(0.0f, 100.0f); diff --git a/samples/zclip_triangle/Makefile b/samples/zclip_triangle/Makefile new file mode 100644 index 0000000..0be2fcc --- /dev/null +++ b/samples/zclip_triangle/Makefile @@ -0,0 +1,29 @@ +TARGET = zclip_triangle.elf +OBJS = main.o + +all: rm-elf $(TARGET) + +include $(KOS_BASE)/Makefile.rules + +clean: + -rm -f $(TARGET) $(OBJS) romdisk.* + +rm-elf: + -rm -f $(TARGET) romdisk.* + +$(TARGET): $(OBJS) romdisk.o + $(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(TARGET) $(KOS_START) \ + $(OBJS) romdisk.o $(OBJEXTRA) -lm -lkosutils $(KOS_LIBS) + +romdisk.img: + $(KOS_GENROMFS) -f romdisk.img -d romdisk -v + +romdisk.o: romdisk.img + $(KOS_BASE)/utils/bin2o/bin2o romdisk.img romdisk romdisk.o + +run: $(TARGET) + $(KOS_LOADER) $(TARGET) + +dist: + rm -f $(OBJS) romdisk.o romdisk.img + $(KOS_STRIP) $(TARGET) diff --git a/samples/zclip_triangle/main.c b/samples/zclip_triangle/main.c new file mode 100644 index 0000000..b1929a1 --- /dev/null +++ b/samples/zclip_triangle/main.c @@ -0,0 +1,98 @@ +#include +#include +#include + +#include "gl.h" +#include "glu.h" +#include "glkos.h" + + +/* A general OpenGL initialization function. Sets all of the initial parameters. */ +void InitGL(int Width, int Height) // We call this right after our OpenGL window is created. +{ + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black + glClearDepth(1.0); // Enables Clearing Of The Depth Buffer + glDepthFunc(GL_LEQUAL); // The Type Of Depth Test To Do + glEnable(GL_DEPTH_TEST); // Enables Depth Testing + glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading + glEnable(GL_TEXTURE_2D); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); // Reset The Projection Matrix + + gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */ +void ReSizeGLScene(int Width, int Height) +{ + if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small + Height = 1; + + glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); + glMatrixMode(GL_MODELVIEW); +} + +/* The main drawing function. */ +void DrawGLScene() +{ + static GLfloat movement = 0.0f; + static GLboolean increasing = GL_TRUE; + + if(movement > 10.0) { + increasing = GL_FALSE; + } else if(movement < -10.0f) { + increasing = GL_TRUE; + } + + if(increasing) { + movement += 0.05f; + } else { + movement -= 0.05f; + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer + glLoadIdentity(); // Reset The View + + glDisable(GL_CULL_FACE); + + glPushMatrix(); + glTranslatef(0.0f, -1.0f, movement); + + glBegin(GL_TRIANGLES); + glColor3f(1.0f, 0.0f, 0.0f); + glVertex3f(0.0f, 0.0f, -5.0f); + + glColor3f(1.0f, 0.0f, 0.0f); + glVertex3f(-2.5f, 0.0f, 5.0f); + + glColor3f(0.0f, 0.0f, 1.0f); + glVertex3f(2.5f, 0.0f, 5.0f); + glEnd(); + glPopMatrix(); + + // swap buffers to display, since we're double buffered. + glKosSwapBuffers(); +} + +int main(int argc, char **argv) +{ + glKosInit(); + + InitGL(640, 480); + ReSizeGLScene(640, 480); + + while(1) { + DrawGLScene(); + } + + return 0; +} diff --git a/samples/zclip_triangle/romdisk/PLACEHOLDER b/samples/zclip_triangle/romdisk/PLACEHOLDER new file mode 100644 index 0000000..e69de29 diff --git a/samples/zclip_triangle/romdisk/facade00.tga b/samples/zclip_triangle/romdisk/facade00.tga new file mode 100755 index 0000000..d061c48 Binary files /dev/null and b/samples/zclip_triangle/romdisk/facade00.tga differ diff --git a/samples/zclip_triangle/romdisk/facade01.tga b/samples/zclip_triangle/romdisk/facade01.tga new file mode 100755 index 0000000..fde4039 Binary files /dev/null and b/samples/zclip_triangle/romdisk/facade01.tga differ diff --git a/samples/zclip_triangle/romdisk/facade02.tga b/samples/zclip_triangle/romdisk/facade02.tga new file mode 100755 index 0000000..210393a Binary files /dev/null and b/samples/zclip_triangle/romdisk/facade02.tga differ diff --git a/samples/zclip_triangle/romdisk/floor.tga b/samples/zclip_triangle/romdisk/floor.tga new file mode 100644 index 0000000..1e2799c Binary files /dev/null and b/samples/zclip_triangle/romdisk/floor.tga differ diff --git a/samples/zclip_trianglestrip/Makefile b/samples/zclip_trianglestrip/Makefile new file mode 100644 index 0000000..613fffc --- /dev/null +++ b/samples/zclip_trianglestrip/Makefile @@ -0,0 +1,29 @@ +TARGET = zclip_trianglestrip.elf +OBJS = main.o + +all: rm-elf $(TARGET) + +include $(KOS_BASE)/Makefile.rules + +clean: + -rm -f $(TARGET) $(OBJS) romdisk.* + +rm-elf: + -rm -f $(TARGET) romdisk.* + +$(TARGET): $(OBJS) romdisk.o + $(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(TARGET) $(KOS_START) \ + $(OBJS) romdisk.o $(OBJEXTRA) -lm -lkosutils $(KOS_LIBS) + +romdisk.img: + $(KOS_GENROMFS) -f romdisk.img -d romdisk -v + +romdisk.o: romdisk.img + $(KOS_BASE)/utils/bin2o/bin2o romdisk.img romdisk romdisk.o + +run: $(TARGET) + $(KOS_LOADER) $(TARGET) + +dist: + rm -f $(OBJS) romdisk.o romdisk.img + $(KOS_STRIP) $(TARGET) diff --git a/samples/zclip_trianglestrip/main.c b/samples/zclip_trianglestrip/main.c new file mode 100644 index 0000000..3483191 --- /dev/null +++ b/samples/zclip_trianglestrip/main.c @@ -0,0 +1,99 @@ +#include +#include +#include + +#include "gl.h" +#include "glu.h" +#include "glkos.h" + + +/* A general OpenGL initialization function. Sets all of the initial parameters. */ +void InitGL(int Width, int Height) // We call this right after our OpenGL window is created. +{ + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black + glClearDepth(1.0); // Enables Clearing Of The Depth Buffer + glDepthFunc(GL_LEQUAL); // The Type Of Depth Test To Do + glEnable(GL_DEPTH_TEST); // Enables Depth Testing + glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading + glEnable(GL_TEXTURE_2D); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); // Reset The Projection Matrix + + gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */ +void ReSizeGLScene(int Width, int Height) +{ + if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small + Height = 1; + + glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); + glMatrixMode(GL_MODELVIEW); +} + +/* The main drawing function. */ +void DrawGLScene() +{ + static GLfloat movement = 0.0f; + static GLboolean increasing = GL_TRUE; + + if(movement > 10.0) { + increasing = GL_FALSE; + } else if(movement < -10.0f) { + increasing = GL_TRUE; + } + + if(increasing) { + movement += 0.05f; + } else { + movement -= 0.05f; + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer + glLoadIdentity(); // Reset The View + + glPushMatrix(); + glTranslatef(0.0f, -1.0f, movement); + + glBegin(GL_TRIANGLE_STRIP); + glColor3f(1.0f, 1.0f, 0.0f); + glVertex3f(-2.5f, 0.0f, -5.0f); + + glColor3f(1.0f, 0.0f, 0.0f); + glVertex3f(-2.5f, 0.0f, 5.0f); + + glColor3f(0.0f, 1.0f, 0.0f); + glVertex3f(2.5f, 0.0f, -5.0f); + + glColor3f(0.0f, 0.0f, 1.0f); + glVertex3f(2.5f, 0.0f, 5.0f); + glEnd(); + glPopMatrix(); + + // swap buffers to display, since we're double buffered. + glKosSwapBuffers(); +} + +int main(int argc, char **argv) +{ + glKosInit(); + + InitGL(640, 480); + ReSizeGLScene(640, 480); + + while(1) { + DrawGLScene(); + } + + return 0; +} diff --git a/samples/zclip_trianglestrip/romdisk/PLACEHOLDER b/samples/zclip_trianglestrip/romdisk/PLACEHOLDER new file mode 100644 index 0000000..e69de29 diff --git a/samples/zclip_trianglestrip/romdisk/facade00.tga b/samples/zclip_trianglestrip/romdisk/facade00.tga new file mode 100755 index 0000000..d061c48 Binary files /dev/null and b/samples/zclip_trianglestrip/romdisk/facade00.tga differ diff --git a/samples/zclip_trianglestrip/romdisk/facade01.tga b/samples/zclip_trianglestrip/romdisk/facade01.tga new file mode 100755 index 0000000..fde4039 Binary files /dev/null and b/samples/zclip_trianglestrip/romdisk/facade01.tga differ diff --git a/samples/zclip_trianglestrip/romdisk/facade02.tga b/samples/zclip_trianglestrip/romdisk/facade02.tga new file mode 100755 index 0000000..210393a Binary files /dev/null and b/samples/zclip_trianglestrip/romdisk/facade02.tga differ diff --git a/samples/zclip_trianglestrip/romdisk/floor.tga b/samples/zclip_trianglestrip/romdisk/floor.tga new file mode 100644 index 0000000..1e2799c Binary files /dev/null and b/samples/zclip_trianglestrip/romdisk/floor.tga differ