diff --git a/GL/draw.c b/GL/draw.c index 512017e..02a4c10 100644 --- a/GL/draw.c +++ b/GL/draw.c @@ -123,15 +123,36 @@ static void _parseIndex(GLshort* out, const GLubyte* in, GLenum type) { } } +/* +inline void mat_trans_float3_nodiv(const GLfloat* mat, GLfloat* v) { + GLfloat x = v[0] * mat[0] + v[1] * mat[4] + v[2] * mat[8] + mat[12]; + GLfloat y = v[0] * mat[1] + v[1] * mat[5] + v[2] * mat[9] + mat[13]; + GLfloat z = v[0] * mat[2] + v[1] * mat[6] + v[2] * mat[10] + mat[14]; + + v[0] = x; + v[1] = y; + v[2] = z; +} */ + +void transformToEyeSpace(GLfloat* point) { + _matrixLoadModelView(); + mat_trans_single3_nodiv(point[0], point[1], point[2]); +} + +void transformNormalToEyeSpace(GLfloat* normal) { + _matrixLoadNormal(); + mat_trans_normal3(normal[0], normal[1], normal[2]); +} + static void submitVertices(GLenum mode, GLsizei first, GLsizei count, GLenum type, const GLvoid* indices) { - static float normal[3]; + static GLfloat normal[3] = {0.0f, 0.0f, -1.0f}; + static GLfloat eye_P[3]; + static GLfloat eye_N[3]; if(!(ENABLED_VERTEX_ATTRIBUTES & VERTEX_ENABLED_FLAG)) { return; } - _glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */ - const GLsizei elements = (mode == GL_QUADS) ? 4 : (mode == GL_TRIANGLES) ? 3 : (mode == GL_LINES) ? 2 : count; // Make room for the element + the header @@ -185,7 +206,6 @@ static void submitVertices(GLenum mode, GLsizei first, GLsizei count, GLenum typ } _parseFloats(&vertex->x, vptr + (idx * vstride), VERTEX_POINTER.size, VERTEX_POINTER.type); - transformVertex(&vertex->x, &vertex->x, &vertex->y, &vertex->z); if(ENABLED_VERTEX_ATTRIBUTES & DIFFUSE_ENABLED_FLAG) { _parseColour(&vertex->argb, cptr + (idx * cstride), DIFFUSE_POINTER.size, DIFFUSE_POINTER.type); @@ -197,6 +217,9 @@ static void submitVertices(GLenum mode, GLsizei first, GLsizei count, GLenum typ if(ENABLED_VERTEX_ATTRIBUTES & NORMAL_ENABLED_FLAG) { _parseFloats(normal, nptr + (idx * nstride), NORMAL_POINTER.size, NORMAL_POINTER.type); + } else { + normal[0] = normal[1] = 0.0f; + normal[2] = -1.0f; } if(lighting_enabled) { @@ -205,12 +228,22 @@ static void submitVertices(GLenum mode, GLsizei first, GLsizei count, GLenum typ GLfloat contribution [] = {0.0f, 0.0f, 0.0f, 0.0f}; GLfloat to_add [] = {0.0f, 0.0f, 0.0f, 0.0f}; - /* FIXME!!! Transform the position to eye space */ + /* Transform the vertex and normal into eye-space */ + eye_P[0] = vertex->x; + eye_P[1] = vertex->y; + eye_P[2] = vertex->z; + + eye_N[0] = normal[0]; + eye_N[1] = normal[1]; + eye_N[2] = normal[2]; + + transformToEyeSpace(eye_P); + transformNormalToEyeSpace(eye_N); GLubyte j; for(j = 0; j < MAX_LIGHTS; ++j) { if(isLightEnabled(i)) { - calculateLightingContribution(j, &vertex->x, normal, to_add); + calculateLightingContribution(j, eye_P, eye_N, to_add); contribution[0] += to_add[0]; contribution[1] += to_add[1]; @@ -222,6 +255,9 @@ static void submitVertices(GLenum mode, GLsizei first, GLsizei count, GLenum typ vertex->argb = PVR_PACK_COLOR(contribution[3], contribution[0], contribution[1], contribution[2]); } + _applyRenderMatrix(); /* Apply the Render Matrix Stack */ + transformVertex(&vertex->x, &vertex->x, &vertex->y, &vertex->z); + ++dst; } } diff --git a/GL/flush.c b/GL/flush.c index b689156..d089779 100644 --- a/GL/flush.c +++ b/GL/flush.c @@ -64,12 +64,12 @@ void APIENTRY glKosInit() { _initPVR(); + initMatrices(); initAttributePointers(); initContext(); initLights(); initImmediateMode(); - _glKosInitMatrix(); _glKosInitTextures(); OP_LIST.list_type = PVR_LIST_OP_POLY; diff --git a/GL/lighting.c b/GL/lighting.c index 164d4f2..12a7686 100644 --- a/GL/lighting.c +++ b/GL/lighting.c @@ -1,3 +1,5 @@ +#include +#include #include "private.h" static GLfloat SCENE_AMBIENT [] = {0.2, 0.2, 0.2, 1.0}; @@ -107,7 +109,7 @@ void APIENTRY glLightfv(GLenum light, GLenum pname, const GLfloat *params) { case GL_POSITION: memcpy(LIGHTS[idx].position, params, sizeof(GLfloat) * 4); break; - case GL_CONSTANT_ATTENUATION: + case GL_CONSTANT_ATTENUATION: case GL_LINEAR_ATTENUATION: case GL_QUADRATIC_ATTENUATION: case GL_SPOT_CUTOFF: @@ -196,7 +198,69 @@ void APIENTRY glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) { } } -void calculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, GLfloat* colour) { - colour[0] = colour[3] = 0.0f; - colour[1] = colour[2] = 0.0f; +inline void initVec3(struct vec3f* v, const GLfloat* src) { + memcpy(v, src, sizeof(GLfloat) * 3); +} + +/* Fast POW Implementation - Less accurate, but much faster than math.h */ +#define EXP_A 184 +#define EXP_C 16249 + +static float FEXP(float y) { + union { + float d; + struct { + short j, i; + } n; + } eco; + eco.n.i = EXP_A * (y) + (EXP_C); + eco.n.j = 0; + return eco.d; +} + +static float FLOG(float y) { + int *nTemp = (int *)&y; + y = (*nTemp) >> 16; + return (y - EXP_C) / EXP_A; +} + +static float FPOW(float b, float p) { + return FEXP(FLOG(b) * p); +} + +void calculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, GLfloat* colour) { + LightSource* l = &LIGHTS[light]; + + struct vec3f L, N, V; + + L.x = l->position[0] - pos[0]; + L.y = l->position[1] - pos[1]; + L.z = l->position[2] - pos[2]; + + N.x = normal[0]; + N.y = normal[1]; + N.z = normal[2]; + + V.x = -pos[0]; + V.y = -pos[1]; + V.z = -pos[2]; + + vec3f_normalize(L.x, L.y, L.z); + vec3f_normalize(V.x, V.y, V.z); + + GLfloat LdotN; + vec3f_dot(L.x, L.y, L.z, N.x, N.y, N.z, LdotN); + + GLfloat f = (LdotN < 0) ? 0 : 1; + + GLfloat VdotN; + vec3f_dot(V.x, V.y, V.z, N.x, N.y, N.z, VdotN); + + GLfloat VdotR = VdotN - LdotN; + GLfloat specularPower = FPOW(VdotR > 0 ? VdotR : 0, MATERIAL.exponent); + + colour[0] = l->ambient[0] * MATERIAL.ambient[0] + f * (l->diffuse[0] * MATERIAL.diffuse[0] * LdotN); // + l->specular[0] * MATERIAL.specular[0] * specularPower); + colour[1] = l->ambient[1] * MATERIAL.ambient[1] + f * (l->diffuse[1] * MATERIAL.diffuse[1] * LdotN); // + l->specular[1] * MATERIAL.specular[1] * specularPower); + colour[2] = l->ambient[2] * MATERIAL.ambient[2] + f * (l->diffuse[2] * MATERIAL.diffuse[2] * LdotN); // + l->specular[2] * MATERIAL.specular[2] * specularPower); + colour[3] = MATERIAL.diffuse[3]; } diff --git a/GL/matrix.c b/GL/matrix.c new file mode 100644 index 0000000..81f52b2 --- /dev/null +++ b/GL/matrix.c @@ -0,0 +1,370 @@ +#include + +#include "../include/gl.h" +#include "../containers/stack.h" +#include "../gl-sh4.h" + +/* Viewport mapping */ +static GLfloat gl_viewport_scale[3], gl_viewport_offset[3]; + +/* Depth range */ +static GLclampf gl_depthrange_near, gl_depthrange_far; + +/* Viewport size */ +static GLint gl_viewport_x1, gl_viewport_y1, gl_viewport_width, gl_viewport_height; + +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; + +static const matrix_t IDENTITY = { + {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} +}; + +void APIENTRY glDepthRange(GLclampf n, GLclampf f); + +void initMatrices() { + init_stack(&MATRIX_STACKS[0], sizeof(matrix_t), 32); + init_stack(&MATRIX_STACKS[1], sizeof(matrix_t), 32); + init_stack(&MATRIX_STACKS[2], sizeof(matrix_t), 32); + + stack_push(&MATRIX_STACKS[0], IDENTITY); + stack_push(&MATRIX_STACKS[1], IDENTITY); + stack_push(&MATRIX_STACKS[2], IDENTITY); + + memcpy(NORMAL_MATRIX, IDENTITY, sizeof(matrix_t)); + memcpy(SCREENVIEW_MATRIX, IDENTITY, sizeof(matrix_t)); + + glDepthRange(0.0f, 1.0f); + glViewport(0, 0, vid_mode->width, vid_mode->height); +} + +static void recalculateNormalMatrix() { + +} + +void APIENTRY glMatrixMode(GLenum mode) { + MATRIX_MODE = mode; + MATRIX_IDX = mode & 0xF; +} + +void APIENTRY glPushMatrix() { + stack_push(MATRIX_STACKS + MATRIX_IDX, stack_top(MATRIX_STACKS + MATRIX_IDX)); +} + +void APIENTRY glPopMatrix() { + stack_pop(MATRIX_STACKS + MATRIX_IDX); + if(MATRIX_MODE == GL_MODELVIEW) { + recalculateNormalMatrix(); + } +} + +void APIENTRY glLoadIdentity() { + stack_replace(MATRIX_STACKS + MATRIX_IDX, IDENTITY); +} + +void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z) { + mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX)); + mat_translate(x, y, z); + mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX)); + + if(MATRIX_MODE == GL_MODELVIEW) { + recalculateNormalMatrix(); + } +} + + +void APIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z) { + mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX)); + mat_scale(x, y, z); + mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX)); + + if(MATRIX_MODE == GL_MODELVIEW) { + recalculateNormalMatrix(); + } +} + +void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { + float r = DEG2RAD * -angle; + + vec3f_normalize(x, y, z); + + mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX)); + mat_rotate(r * x, r * y, r * z); + mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX)); + + if(MATRIX_MODE == GL_MODELVIEW) { + recalculateNormalMatrix(); + } +} + +/* Load an arbitrary matrix */ +void APIENTRY glLoadMatrixf(const GLfloat *m) { + stack_replace(MATRIX_STACKS + MATRIX_IDX, m); + + if(MATRIX_MODE == GL_MODELVIEW) { + recalculateNormalMatrix(); + } +} + +/* Ortho */ +void APIENTRY glOrtho(GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat znear, GLfloat zfar) { + + /* 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 }, + { 0.0f, 0.0f, 0.0f, 1.0f } + }; + + OrthoMatrix[0][0] = 2.0f / (right - left); + OrthoMatrix[1][1] = 2.0f / (top - bottom); + OrthoMatrix[2][2] = -2.0f / (zfar - znear); + OrthoMatrix[3][0] = -(right + left) / (right - left);; + OrthoMatrix[3][1] = -(top + bottom) / (top - bottom); + OrthoMatrix[3][2] = -(zfar + znear) / (zfar - znear); + + mat_load(stack_top(MATRIX_STACKS + MATRIX_MODE)); + mat_apply(&OrthoMatrix); + mat_store(stack_top(MATRIX_STACKS + MATRIX_MODE)); +} + + +/* Set the GL frustum */ +void APIENTRY glFrustum(GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat znear, GLfloat zfar) { + + /* Frustum Matrix */ + static matrix_t FrustumMatrix __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, -1.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f } + }; + + FrustumMatrix[0][0] = (2.0f * znear) / (right - left); + FrustumMatrix[2][0] = (right + left) / (right - left); + FrustumMatrix[1][1] = (2.0f * znear) / (top - bottom); + FrustumMatrix[2][1] = (top + bottom) / (top - bottom); + FrustumMatrix[2][2] = zfar / (zfar - znear); + FrustumMatrix[3][2] = -(zfar * znear) / (zfar - znear); + + mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX)); + mat_apply(&FrustumMatrix); + mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX)); +} + +/* Set the Perspective */ +void gluPerspective(GLfloat angle, GLfloat aspect, + GLfloat znear, GLfloat zfar) { + GLfloat xmin, xmax, ymin, ymax; + + ymax = znear * ftan(angle * F_PI / 360.0f); + ymin = -ymax; + xmin = ymin * aspect; + xmax = ymax * aspect; + + glFrustum(xmin, xmax, ymin, ymax, znear, zfar); +} + +/* Multiply the current matrix by an arbitrary matrix */ +void glMultMatrixf(const GLfloat *m) { + static matrix_t TEMP __attribute__((aligned(32))) = { + { 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 } + }; + + memcpy(TEMP, m, sizeof(matrix_t)); + + mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX)); + mat_apply(&TEMP); + mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX)); + + if(MATRIX_MODE == GL_MODELVIEW) { + recalculateNormalMatrix(); + } +} + +/* Load an arbitrary transposed matrix */ +void glLoadTransposeMatrixf(const GLfloat *m) { + stack_replace(MATRIX_STACKS + MATRIX_IDX, m); + transpose(stack_top(MATRIX_STACKS + MATRIX_IDX)); + + if(MATRIX_MODE == GL_MODELVIEW) { + recalculateNormalMatrix(); + } +} + +/* Multiply the current matrix by an arbitrary transposed matrix */ +void glMultTransposeMatrixf(const GLfloat *m) { + static matrix_t ml; + + ml[0][0] = m[0]; + ml[0][1] = m[4]; + ml[0][2] = m[8]; + ml[0][3] = m[12]; + ml[1][0] = m[1]; + ml[1][1] = m[5]; + ml[1][2] = m[9]; + ml[1][3] = m[13]; + ml[2][0] = m[2]; + ml[2][1] = m[6]; + ml[2][2] = m[10]; + ml[2][3] = m[14]; + ml[3][0] = m[3]; + ml[3][1] = m[7]; + ml[3][2] = m[11]; + ml[3][3] = m[15]; + + mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX)); + mat_apply(&ml); + mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX)); +} + +/* Set the GL viewport */ +void APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { + gl_viewport_x1 = x; + gl_viewport_y1 = y; + 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; + + gl_viewport_offset[2] += 0.0001f; + + /* 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]; +} + +/* Set the depth range */ +void APIENTRY glDepthRange(GLclampf n, GLclampf f) { + /* clamp the values... */ + if(n < 0.0f) n = 0.0f; + else if(n > 1.0f) n = 1.0f; + + if(f < 0.0f) f = 0.0f; + else if(f > 1.0f) f = 1.0f; + + 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 */ +static inline void vec3f_cross(vector3f v1, vector3f v2, vector3f result) { + result[0] = v1[1] * v2[2] - v1[2] * v2[1]; + result[1] = v1[2] * v2[0] - v1[0] * v2[2]; + result[2] = v1[0] * v2[1] - v1[1] * v2[0]; +} + +/* glhLookAtf2 adapted from http://www.opengl.org/wiki/GluLookAt_code */ +void glhLookAtf2(vector3f eyePosition3D, + vector3f center3D, + vector3f upVector3D) { + + /* Look-At Matrix */ + static matrix4f MatrixLookAt __attribute__((aligned(32))) = { + { 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 } + }; + + vector3f forward, side, up; + + vec3f_sub_normalize(center3D[0], center3D[1], center3D[2], + eyePosition3D[0], eyePosition3D[1], eyePosition3D[2], + forward[0], forward[1], forward[2]); + + //Side = forward x up + vec3f_cross(forward, upVector3D, side); + vec3f_normalize(side[0], side[1], side[2]); + + //Recompute up as: up = side x forward + vec3f_cross(side, forward, up); + + MatrixLookAt[0][0] = side[0]; + MatrixLookAt[1][0] = side[1]; + MatrixLookAt[2][0] = side[2]; + MatrixLookAt[3][0] = 0; + + MatrixLookAt[0][1] = up[0]; + MatrixLookAt[1][1] = up[1]; + MatrixLookAt[2][1] = up[2]; + MatrixLookAt[3][1] = 0; + + MatrixLookAt[0][2] = -forward[0]; + MatrixLookAt[1][2] = -forward[1]; + MatrixLookAt[2][2] = -forward[2]; + MatrixLookAt[3][2] = 0; + + MatrixLookAt[0][3] = + MatrixLookAt[1][3] = + MatrixLookAt[2][3] = 0; + MatrixLookAt[3][3] = 1; + + // Does not modify internal Modelview matrix + mat_load(&MatrixLookAt); + mat_translate(-eyePosition3D[0], -eyePosition3D[1], -eyePosition3D[2]); + + mat_apply(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF))); + mat_store(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF))); +} + +void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat centerx, + GLfloat centery, GLfloat centerz, GLfloat upx, GLfloat upy, + GLfloat upz) { + vector3f eye = { eyex, eyey, eyez }; + vector3f point = { centerx, centery, centerz }; + vector3f up = { upx, upy, upz }; + glhLookAtf2(eye, point, up); +} + +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() { + mat_load(stack_top(MATRIX_STACKS + (GL_TEXTURE & 0xF))); +} + +void _matrixLoadModelView() { + mat_load(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF))); +} + +void _matrixLoadNormal() { + mat_load(&NORMAL_MATRIX); +} diff --git a/GL/private.h b/GL/private.h index 1ead5c5..6f081cd 100644 --- a/GL/private.h +++ b/GL/private.h @@ -72,6 +72,14 @@ void initAttributePointers(); void initContext(); void initLights(); void initImmediateMode(); +void initMatrices(); + +void _matrixLoadNormal(); +void _matrixLoadModelView(); +void _matrixLoadTexture(); +void _matrixLoadRender(); +void _applyRenderMatrix(); + GLubyte checkImmediateModeInactive(const char* func); pvr_poly_cxt_t* getPVRContext(); diff --git a/GL/state.c b/GL/state.c index ed91361..dac06cc 100644 --- a/GL/state.c +++ b/GL/state.c @@ -164,7 +164,7 @@ GLboolean isLightEnabled(unsigned char light) { static GLfloat CLEAR_COLOUR[3]; -void initContext() { +void initContext() { memset(&GL_CONTEXT, 0, sizeof(pvr_poly_cxt_t)); GL_CONTEXT.list_type = PVR_LIST_OP_POLY; diff --git a/containers/stack.h b/containers/stack.h new file mode 100644 index 0000000..4cc15f2 --- /dev/null +++ b/containers/stack.h @@ -0,0 +1,50 @@ +#ifndef STACK_H +#define STACK_H + +#include +#include + +typedef struct { + unsigned char* data; + unsigned int capacity; + unsigned int size; + unsigned int element_size; +} Stack; + +void init_stack(Stack* stack, unsigned int element_size, unsigned int capacity) { + stack->size = 0; + stack->capacity = capacity; + stack->element_size = element_size; + stack->data = (unsigned char*) memalign(0x20, element_size * capacity); +} + +void* stack_top(Stack* stack) { + return &stack->data[(stack->size - 1) * stack->element_size]; +} + +void* stack_replace(Stack* stack, const void* element) { + memcpy(stack->data + ((stack->size - 1) * stack->element_size), element, stack->element_size); + return stack_top(stack); +} + +void* stack_push(Stack* stack, const void* element) { + if(stack->size + 1 == stack->capacity) { + return NULL; + } + + memcpy(stack->data + (stack->size * stack->element_size), element, stack->element_size); + stack->size++; + + return stack_top(stack); +} + +void stack_pop(Stack* stack) { + if(stack->size == 0) { + return; + } + + stack->size--; +} + + +#endif // STACK_H diff --git a/gl-light.c b/gl-light.c index dc88e8d..2d91278 100644 --- a/gl-light.c +++ b/gl-light.c @@ -362,8 +362,3 @@ void _glKosVertexComputeLighting(pvr_vertex_t *v, int verts) { } } -void _glKosLightTransformScreenSpace(float *xyz) { - _glKosMatrixApplyScreenSpace(); - mat_trans_single(xyz[0], xyz[1], xyz[2]); - _glKosMatrixLoadRender(); -} diff --git a/gl-matrix.c b/gl-matrix.c deleted file mode 100644 index b840d2d..0000000 --- a/gl-matrix.c +++ /dev/null @@ -1,413 +0,0 @@ -/* KallistiGL for KallistiOS ##version## - - libgl/gl-matrix.c - Copyright (C) 2013-2014 Josh Pearson - Copyright (C) 2014 Lawrence Sebald - - Some functionality adapted from the original KOS libgl: - Copyright (C) 2001 Dan Potter - - The GL matrix operations use the KOS SH4 matrix operations. - Basically, we keep two seperate matrix stacks: - 1.) Internal GL API Matrix Stack ( screenview, modelview, etc. ) ( fixed stack size ) - 2.) External Matrix Stack for client to push / pop ( size of each stack is determined by MAX_MATRICES ) -*/ - -#include - -#include "gl.h" -#include "glu.h" -#include "gl-api.h" -#include "gl-sh4.h" - -/* This Matrix contains the GL Base Stack */ -static matrix4f Matrix[GL_MATRIX_COUNT] __attribute__((aligned(32))); -static GLsizei MatrixMode = 0; - -/* This Matrix contains the GL Push/Pop Stack ( fixed size per mode, 32 matrices )*/ -static const GLsizei MAX_MATRICES = 32; -static matrix4f MatrixStack[GL_MATRIX_COUNT][32] __attribute__((aligned(32))); -static GLsizei MatrixStackPos[GL_MATRIX_COUNT]; - -/* Viewport mapping */ -static GLfloat gl_viewport_scale[3], gl_viewport_offset[3]; - -/* Depth range */ -static GLclampf gl_depthrange_near, gl_depthrange_far; - -/* Viewport size */ -static GLint gl_viewport_x1, gl_viewport_y1, gl_viewport_width, gl_viewport_height; - -/* Frustum attributes */ -typedef struct { - float left, right, bottom, top, znear, zfar; -} gl_frustum_t; - -static gl_frustum_t gl_frustum; - -/* Frustum Matrix */ -static matrix4f FrustumMatrix __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, -1.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f } -}; - -/* Ortho Matrix */ -static matrix4f 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 }, - { 0.0f, 0.0f, 0.0f, 1.0f } -}; - -/* Matrix for user to submit externally, ensure 32byte allignment */ -static matrix4f ml __attribute__((aligned(32))); - -/* Look-At Matrix */ -static matrix4f MatrixLookAt __attribute__((aligned(32))) = { - { 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 } -}; - -/* Modelview Rotation Matrix - Applied to Vertex Normal when Lighting is Enabled */ -static matrix4f MatrixMdlRot __attribute__((aligned(32))) = { - { 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 } -}; - -void glMatrixMode(GLenum mode) { - if(mode >= GL_SCREENVIEW && mode <= GL_IDENTITY) - MatrixMode = mode; -} - -void glPushMatrix() { - if(MatrixStackPos[MatrixMode] < MAX_MATRICES - 1) { - mat_load(Matrix + MatrixMode); - mat_store(&MatrixStack[MatrixMode][MatrixStackPos[MatrixMode]]); - ++MatrixStackPos[MatrixMode]; - } -} - -void glPopMatrix() { - if(MatrixStackPos[MatrixMode]) { - --MatrixStackPos[MatrixMode]; - mat_load(&MatrixStack[MatrixMode][MatrixStackPos[MatrixMode]]); - mat_store(Matrix + MatrixMode); - } -} - -void glLoadIdentity() { - mat_load(Matrix + GL_IDENTITY); - mat_store(Matrix + MatrixMode); - - if(MatrixMode == GL_MODELVIEW) { - mat_store(&MatrixMdlRot); - mat_store(&MatrixLookAt); - } -} - -void glTranslatef(GLfloat x, GLfloat y, GLfloat z) { - mat_load(Matrix + MatrixMode); - mat_translate(x, y, z); - mat_store(Matrix + MatrixMode); -} - -void glScalef(GLfloat x, GLfloat y, GLfloat z) { - mat_load(Matrix + MatrixMode); - mat_scale(x, y, z); - mat_store(Matrix + MatrixMode); -} - -void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { - float r = DEG2RAD * -angle; - - vec3f_normalize(x, y, z); - - mat_load(Matrix + MatrixMode); - mat_rotate(r * x, r * y, r * z); - mat_store(Matrix + MatrixMode); - - if(MatrixMode == GL_MODELVIEW) { - mat_load(&MatrixMdlRot); - mat_rotate(r * x, r * y, r * z); - mat_store(&MatrixMdlRot); - } -} - -/* Load an arbitrary matrix */ -void glLoadMatrixf(const GLfloat *m) { - memcpy(ml, m, sizeof(matrix4f)); - mat_load(&ml); - mat_store(Matrix + MatrixMode); -} - -/* Load an arbitrary transposed matrix */ -void glLoadTransposeMatrixf(const GLfloat *m) { - ml[0][0] = m[0]; - ml[0][1] = m[4]; - ml[0][2] = m[8]; - ml[0][3] = m[12]; - ml[1][0] = m[1]; - ml[1][1] = m[5]; - ml[1][2] = m[9]; - ml[1][3] = m[13]; - ml[2][0] = m[2]; - ml[2][1] = m[6]; - ml[2][2] = m[10]; - ml[2][3] = m[14]; - ml[3][0] = m[3]; - ml[3][1] = m[7]; - ml[3][2] = m[11]; - ml[3][3] = m[15]; - - mat_load(&ml); - mat_store(Matrix + MatrixMode); -} - -/* Multiply the current matrix by an arbitrary matrix */ -void glMultMatrixf(const GLfloat *m) { - memcpy(ml, m, sizeof(matrix4f)); - mat_load(Matrix + MatrixMode); - mat_apply(&ml); - mat_store(Matrix + MatrixMode); -} - -/* Multiply the current matrix by an arbitrary transposed matrix */ -void glMultTransposeMatrixf(const GLfloat *m) { - ml[0][0] = m[0]; - ml[0][1] = m[4]; - ml[0][2] = m[8]; - ml[0][3] = m[12]; - ml[1][0] = m[1]; - ml[1][1] = m[5]; - ml[1][2] = m[9]; - ml[1][3] = m[13]; - ml[2][0] = m[2]; - ml[2][1] = m[6]; - ml[2][2] = m[10]; - ml[2][3] = m[14]; - ml[3][0] = m[3]; - ml[3][1] = m[7]; - ml[3][2] = m[11]; - ml[3][3] = m[15]; - - mat_load(Matrix + MatrixMode); - mat_apply(&ml); - mat_store(Matrix + MatrixMode); -} - -/* Set the depth range */ -void glDepthRange(GLclampf n, GLclampf f) { - /* clamp the values... */ - if(n < 0.0f) n = 0.0f; - else if(n > 1.0f) n = 1.0f; - - if(f < 0.0f) f = 0.0f; - else if(f > 1.0f) f = 1.0f; - - 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; -} - -/* Set the GL viewport */ -void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { - gl_viewport_x1 = x; - gl_viewport_y1 = y; - 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; - - gl_viewport_offset[2] += 0.0001f; - - /* Set the Screenview Matrix based on the viewport */ - Matrix[GL_SCREENVIEW][0][0] = gl_viewport_scale[0]; - Matrix[GL_SCREENVIEW][1][1] = -gl_viewport_scale[1]; - Matrix[GL_SCREENVIEW][2][2] = 1; - Matrix[GL_SCREENVIEW][3][0] = gl_viewport_offset[0]; - Matrix[GL_SCREENVIEW][3][1] = vid_mode->height - gl_viewport_offset[1]; -} - -/* Set the GL frustum */ -void glFrustum(GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat znear, GLfloat zfar) { - gl_frustum.left = left; - gl_frustum.right = right; - gl_frustum.bottom = bottom; - gl_frustum.top = top; - gl_frustum.znear = znear; - gl_frustum.zfar = zfar; - - FrustumMatrix[0][0] = (2.0f * znear) / (right - left); - FrustumMatrix[2][0] = (right + left) / (right - left); - FrustumMatrix[1][1] = (2.0f * znear) / (top - bottom); - FrustumMatrix[2][1] = (top + bottom) / (top - bottom); - FrustumMatrix[2][2] = zfar / (zfar - znear); - FrustumMatrix[3][2] = -(zfar * znear) / (zfar - znear); - - mat_load(Matrix + MatrixMode); - mat_apply(&FrustumMatrix); - mat_store(Matrix + MatrixMode); -} - -/* Ortho */ -void glOrtho(GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat znear, GLfloat zfar) { - OrthoMatrix[0][0] = 2.0f / (right - left); - OrthoMatrix[1][1] = 2.0f / (top - bottom); - OrthoMatrix[2][2] = -2.0f / (zfar - znear); - OrthoMatrix[3][0] = -(right + left) / (right - left);; - OrthoMatrix[3][1] = -(top + bottom) / (top - bottom); - OrthoMatrix[3][2] = -(zfar + znear) / (zfar - znear); - - mat_load(Matrix + MatrixMode); - mat_apply(&OrthoMatrix); - mat_store(Matrix + MatrixMode); -} - -/* Set the Perspective */ -void gluPerspective(GLfloat angle, GLfloat aspect, - GLfloat znear, GLfloat zfar) { - GLfloat xmin, xmax, ymin, ymax; - - ymax = znear * ftan(angle * F_PI / 360.0f); - ymin = -ymax; - xmin = ymin * aspect; - xmax = ymax * aspect; - - glFrustum(xmin, xmax, ymin, ymax, znear, zfar); -} - -/* Vector Cross Product - Used by glhLookAtf2 */ -void vec3f_cross(vector3f v1, vector3f v2, vector3f result) { - result[0] = v1[1] * v2[2] - v1[2] * v2[1]; - result[1] = v1[2] * v2[0] - v1[0] * v2[2]; - result[2] = v1[0] * v2[1] - v1[1] * v2[0]; -} - -/* glhLookAtf2 adapted from http://www.opengl.org/wiki/GluLookAt_code */ -void glhLookAtf2(vector3f eyePosition3D, - vector3f center3D, - vector3f upVector3D) { - vector3f forward, side, up; - - _glKosSetEyePosition(eyePosition3D); - - vec3f_sub_normalize(center3D[0], center3D[1], center3D[2], - eyePosition3D[0], eyePosition3D[1], eyePosition3D[2], - forward[0], forward[1], forward[2]); - - //Side = forward x up - vec3f_cross(forward, upVector3D, side); - vec3f_normalize(side[0], side[1], side[2]); - - //Recompute up as: up = side x forward - vec3f_cross(side, forward, up); - - MatrixLookAt[0][0] = side[0]; - MatrixLookAt[1][0] = side[1]; - MatrixLookAt[2][0] = side[2]; - MatrixLookAt[3][0] = 0; - - MatrixLookAt[0][1] = up[0]; - MatrixLookAt[1][1] = up[1]; - MatrixLookAt[2][1] = up[2]; - MatrixLookAt[3][1] = 0; - - MatrixLookAt[0][2] = -forward[0]; - MatrixLookAt[1][2] = -forward[1]; - MatrixLookAt[2][2] = -forward[2]; - MatrixLookAt[3][2] = 0; - - MatrixLookAt[0][3] = - MatrixLookAt[1][3] = - MatrixLookAt[2][3] = 0; - MatrixLookAt[3][3] = 1; - - // Does not modify internal Modelview matrix - mat_load(&MatrixLookAt); - mat_translate(-eyePosition3D[0], -eyePosition3D[1], -eyePosition3D[2]); - - mat_apply(Matrix + GL_MODELVIEW); - mat_store(Matrix + GL_MODELVIEW); -} - -void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat centerx, - GLfloat centery, GLfloat centerz, GLfloat upx, GLfloat upy, - GLfloat upz) { - vector3f eye = { eyex, eyey, eyez }; - vector3f point = { centerx, centery, centerz }; - vector3f up = { upx, upy, upz }; - glhLookAtf2(eye, point, up); -} - -void _glKosMatrixApplyRender() { - mat_load(Matrix + GL_SCREENVIEW); - mat_apply(Matrix + GL_PROJECTION); - mat_apply(Matrix + GL_MODELVIEW); - mat_store(Matrix + GL_RENDER); -} - -void _glKosMatrixLoadRender() { - mat_load(Matrix + GL_RENDER); -} - -void _glKosMatrixLoadTexture() { - mat_load(Matrix + GL_TEXTURE); -} - -void _glKosMatrixLoadModelView() { - mat_load(Matrix + GL_MODELVIEW); -} - -void _glKosMatrixLoadModelRot() { - mat_load(&MatrixMdlRot); -} - -void _glKosMatrixApplyScreenSpace() { - mat_load(Matrix + GL_SCREENVIEW); - mat_apply(Matrix + GL_PROJECTION); - mat_apply(&MatrixLookAt); -} - -void _glKosInitMatrix() { - mat_identity(); - mat_store(Matrix + GL_SCREENVIEW); - mat_store(Matrix + GL_PROJECTION); - mat_store(Matrix + GL_MODELVIEW); - mat_store(Matrix + GL_TEXTURE); - mat_store(Matrix + GL_IDENTITY); - mat_store(Matrix + GL_RENDER); - - int i; - - for(i = 0; i < GL_MATRIX_COUNT; i++) - MatrixStackPos[i] = 0; - - glDepthRange(0.0f, 1.0f); - glViewport(0, 0, vid_mode->width, vid_mode->height); -} - -void glKosGetMatrix(GLenum mode, GLfloat *params) { - if(mode < GL_SCREENVIEW || mode > GL_RENDER) - *params = (GLfloat)GL_INVALID_ENUM; - - memcpy(params, Matrix + mode, sizeof(GLfloat) * 16); -} diff --git a/include/gl.h b/include/gl.h index 2bbb566..38e3caa 100644 --- a/include/gl.h +++ b/include/gl.h @@ -56,13 +56,9 @@ __BEGIN_DECLS /* Matrix modes */ #define GL_MATRIX_MODE 0x0BA0 -#define GL_SCREENVIEW 0x00 -#define GL_MODELVIEW 0x01 -#define GL_PROJECTION 0x02 -#define GL_TEXTURE 0x03 -#define GL_IDENTITY 0x04 -#define GL_RENDER 0x05 -#define GL_MATRIX_COUNT 0x06 +#define GL_MODELVIEW 0x1700 +#define GL_PROJECTION 0x1701 +#define GL_TEXTURE 0x1702 #define GL_MODELVIEW_MATRIX 0x0BA6 #define GL_PROJECTION_MATRIX 0x0BA7