289
GL/clip.c
|
@ -1,5 +1,10 @@
|
|||
#include <float.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <dc/pvr.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
30
GL/clip.h
|
@ -1,6 +1,10 @@
|
|||
#ifndef CLIP_H
|
||||
#define CLIP_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
||||
|
|
62
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());
|
||||
}
|
||||
|
||||
|
|
50
GL/matrix.c
|
@ -1,6 +1,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <dc/matrix.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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() {
|
||||
|
|
|
@ -74,7 +74,6 @@ void initFramebuffers();
|
|||
void _matrixLoadNormal();
|
||||
void _matrixLoadModelView();
|
||||
void _matrixLoadTexture();
|
||||
void _matrixLoadRender();
|
||||
void _applyRenderMatrix();
|
||||
|
||||
void wipeTextureOnFramebuffers(GLuint texture);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
29
samples/zclip_triangle/Makefile
Normal file
|
@ -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)
|
98
samples/zclip_triangle/main.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
}
|
0
samples/zclip_triangle/romdisk/PLACEHOLDER
Normal file
BIN
samples/zclip_triangle/romdisk/facade00.tga
Executable file
After Width: | Height: | Size: 192 KiB |
BIN
samples/zclip_triangle/romdisk/facade01.tga
Executable file
After Width: | Height: | Size: 192 KiB |
BIN
samples/zclip_triangle/romdisk/facade02.tga
Executable file
After Width: | Height: | Size: 192 KiB |
BIN
samples/zclip_triangle/romdisk/floor.tga
Normal file
After Width: | Height: | Size: 192 KiB |
29
samples/zclip_trianglestrip/Makefile
Normal file
|
@ -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)
|
99
samples/zclip_trianglestrip/main.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
}
|
0
samples/zclip_trianglestrip/romdisk/PLACEHOLDER
Normal file
BIN
samples/zclip_trianglestrip/romdisk/facade00.tga
Executable file
After Width: | Height: | Size: 192 KiB |
BIN
samples/zclip_trianglestrip/romdisk/facade01.tga
Executable file
After Width: | Height: | Size: 192 KiB |
BIN
samples/zclip_trianglestrip/romdisk/facade02.tga
Executable file
After Width: | Height: | Size: 192 KiB |
BIN
samples/zclip_trianglestrip/romdisk/floor.tga
Normal file
After Width: | Height: | Size: 192 KiB |