Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dave 2024-04-24 20:21:31 +02:00
commit dbafe1c3ab
5 changed files with 286 additions and 266 deletions

View File

@ -6,7 +6,7 @@
#include "../containers/stack.h"
#define DEG2RAD (0.01745329251994329576923690768489)
#define DEG2RAD (0.01745329251994329576923690768489f)
/* Depth range */
@ -174,8 +174,8 @@ void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
};
float r = DEG2RAD * angle;
float c = cos(r);
float s = sin(r);
float c = cosf(r);
float s = sinf(r);
VEC3_NORMALIZE(x, y, z);

View File

@ -445,7 +445,7 @@ static inline void CompilePolyHeader(PolyHeader *dst, const PolyContext *src) {
dst->d3 = dst->d4 = 0xffffffff;
}
#ifdef BACKEND_KOSPVR
#ifdef __DREAMCAST__
#include "platforms/sh4.h"
#else
#include "platforms/software.h"

View File

@ -1,3 +1,5 @@
#include <float.h>
#include "../platform.h"
#include "sh4.h"
@ -30,19 +32,32 @@ void InitGPU(_Bool autosort, _Bool fsaa) {
(autosort) ? 0 : 1 /* Disable translucent auto-sorting to match traditional GL */
};
/* Newer versions of KOS add an extra parameter to pvr_init_params_t
* called opb_overflow_count. To remain compatible we set that last
* parameter to something only if it exists */
const int opb_offset = offsetof(pvr_init_params_t, autosort_disabled) + 4;
if(sizeof(pvr_init_params_t) > opb_offset) {
int* opb_count = (int*)(((char*)&params) + opb_offset);
*opb_count = 2; // Two should be enough for anybody.. right?
}
pvr_init(&params);
#ifndef _arch_sub_naomi
/* If we're PAL and we're NOT VGA, then use 50hz by default. This is the safest
thing to do. If someone wants to force 60hz then they can call vid_set_mode later and hopefully
that'll work... */
int cable = vid_check_cable();
int region = flashrom_get_region();
if(region == FLASHROM_REGION_EUROPE && cable != CT_VGA) {
printf("PAL region without VGA - enabling 50hz");
vid_set_mode(DM_640x480_PAL_IL, PM_RGB565);
if(cable != CT_VGA) {
int region = flashrom_get_region();
if (region == FLASHROM_REGION_EUROPE) {
printf("PAL region without VGA - enabling 50hz");
vid_set_mode(DM_640x480_PAL_IL, PM_RGB565);
}
}
#endif
}
void SceneBegin() {
@ -93,6 +108,10 @@ static inline void _glFlushBuffer() {
static inline void _glPushHeaderOrVertex(Vertex* v) {
TRACE();
#if CLIP_DEBUG
fprintf(stderr, "{%f, %f, %f, %f}, // %x (%x)\n", v->xyz[0], v->xyz[1], v->xyz[2], v->w, v->flags, v);
#endif
uint32_t* s = (uint32_t*) v;
sq[0] = *(s++);
sq[1] = *(s++);
@ -110,12 +129,13 @@ static inline void _glClipEdge(const Vertex* const v1, const Vertex* const v2, V
const static float o = 0.003921569f; // 1 / 255
const float d0 = v1->w + v1->xyz[2];
const float d1 = v2->w + v2->xyz[2];
const float t = (fabs(d0) * (1.0f / sqrtf((d1 - d0) * (d1 - d0)))) + 0.000001f;
const float t = (fabs(d0) * (1.0f / sqrtf((d1 - d0) * (d1 - d0))));
const float invt = 1.0f - t;
vout->xyz[0] = invt * v1->xyz[0] + t * v2->xyz[0];
vout->xyz[1] = invt * v1->xyz[1] + t * v2->xyz[1];
vout->xyz[2] = invt * v1->xyz[2] + t * v2->xyz[2];
vout->xyz[2] = (vout->xyz[2] < FLT_EPSILON) ? FLT_EPSILON : vout->xyz[2];
vout->uv[0] = invt * v1->uv[0] + t * v2->uv[0];
vout->uv[1] = invt * v1->uv[1] + t * v2->uv[1];
@ -136,7 +156,22 @@ static volatile uint32_t* PVR_LMMODE0 = (uint32_t*) 0xA05F6884;
static volatile uint32_t *PVR_LMMODE1 = (uint32_t*) 0xA05F6888;
static volatile uint32_t *QACR = (uint32_t*) 0xFF000038;
void SceneListSubmit(Vertex* v2, int n) {
enum Visible {
NONE_VISIBLE = 0,
FIRST_VISIBLE = 1,
SECOND_VISIBLE = 2,
THIRD_VISIBLE = 4,
FIRST_AND_SECOND_VISIBLE = FIRST_VISIBLE | SECOND_VISIBLE,
SECOND_AND_THIRD_VISIBLE = SECOND_VISIBLE | THIRD_VISIBLE,
FIRST_AND_THIRD_VISIBLE = FIRST_VISIBLE | THIRD_VISIBLE,
ALL_VISIBLE = 7
};
static inline bool is_header(Vertex* v) {
return !(v->flags == GPU_CMD_VERTEX || v->flags == GPU_CMD_VERTEX_EOL);
}
void SceneListSubmit(Vertex* vertices, int n) {
TRACE();
/* You need at least a header, and 3 vertices to render anything */
@ -156,97 +191,111 @@ void SceneListSubmit(Vertex* v2, int n) {
QACR[1] = QACR[0] = 0x11;
#if CLIP_DEBUG
Vertex* vertex = (Vertex*) src;
for(int i = 0; i < n; ++i) {
fprintf(stderr, "{%f, %f, %f, %f}, // %x (%x)\n", vertex[i].xyz[0], vertex[i].xyz[1], vertex[i].xyz[2], vertex[i].w, vertex[i].flags, &vertex[i]);
}
fprintf(stderr, "----\n");
Vertex* vertex = (Vertex*) vertices;
for(int i = 0; i < n; ++i) {
fprintf(stderr, "IN: {%f, %f, %f, %f}, // %x (%x)\n", vertex[i].xyz[0], vertex[i].xyz[1], vertex[i].xyz[2], vertex[i].w, vertex[i].flags, &vertex[i]);
}
#endif
uint8_t visible_mask = 0;
uint8_t counter = 0;
/* This is a bit cumbersome - in some cases (particularly case 2)
we finish the vertex submission with a duplicated final vertex so
that the tri-strip can be continued. However, if the next triangle in the
strip is not visible then the duplicated vertex would've been sent without
the EOL flag. We won't know if we need the EOL flag or not when processing
case 2. To workaround this we may queue a vertex temporarily here, in the normal
case it will be submitted by the next iteration with the same flags it had, but
in the invisible case it will be overridden to submit with EOL */
static Vertex __attribute__((aligned(32))) qv;
Vertex* queued_vertex = NULL;
#define QUEUE_VERTEX(v) \
do { queued_vertex = &qv; *queued_vertex = *(v); } while(0)
#define SUBMIT_QUEUED_VERTEX(sflags) \
do { if(queued_vertex) { queued_vertex->flags = (sflags); _glPushHeaderOrVertex(queued_vertex); queued_vertex = NULL; } } while(0)
int visible_mask = 0;
sq = SQ_BASE_ADDRESS;
for(int i = 0; i < n; ++i, ++v2) {
PREFETCH(v2 + 1);
switch(v2->flags) {
case GPU_CMD_VERTEX_EOL:
if(counter < 2) {
continue;
}
counter = 0;
break;
case GPU_CMD_VERTEX:
++counter;
if(counter < 3) {
continue;
}
break;
default:
_glPushHeaderOrVertex(v2);
counter = 0;
Vertex* v0 = vertices;
for(int i = 0; i < n - 1; ++i, ++v0) {
if(is_header(v0)) {
_glPushHeaderOrVertex(v0);
visible_mask = 0;
continue;
};
Vertex* const v0 = v2 - 2;
Vertex* const v1 = v2 - 1;
visible_mask = (
(v0->xyz[2] > -v0->w) << 0 |
(v1->xyz[2] > -v1->w) << 1 |
(v2->xyz[2] > -v2->w) << 2 |
(counter == 0) << 3
);
switch(visible_mask) {
case 15: /* All visible, but final vertex in strip */
{
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(v1, h);
_glPushHeaderOrVertex(v1);
_glPerspectiveDivideVertex(v2, h);
_glPushHeaderOrVertex(v2);
}
break;
case 7:
/* All visible, push the first vertex and move on */
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
break;
case 9:
/* First vertex was visible, last in strip */
{
Vertex __attribute__((aligned(32))) scratch[2];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
Vertex* v1 = v0 + 1;
Vertex* v2 = (i < n - 2) ? v0 + 2 : NULL;
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX_EOL;
assert(!is_header(v1));
// We are trailing if we're on the penultimate vertex, or the next but one vertex is
// an EOL, or v1 is an EOL (FIXME: possibly unnecessary and coverted by the other case?)
bool is_trailing = (v1->flags == GPU_CMD_VERTEX_EOL) || ((v2) ? is_header(v2) : true);
if(is_trailing) {
// OK so we've hit a new context header
// we need to finalize this strip and move on
// If the last triangle was all visible, we need
// to submit the last two vertices, any clipped triangles
// would've
if(visible_mask == ALL_VISIBLE) {
SUBMIT_QUEUED_VERTEX(qv.flags);
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
v1->flags = GPU_CMD_VERTEX_EOL;
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPerspectiveDivideVertex(v1, h);
_glPushHeaderOrVertex(v1);
} else {
// If the previous triangle wasn't all visible, and we
// queued a vertex - we force it to be EOL and submit
SUBMIT_QUEUED_VERTEX(GPU_CMD_VERTEX_EOL);
}
break;
case 1:
/* First vertex was visible, but not last in strip */
{
Vertex __attribute__((aligned(32))) scratch[2];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
i++;
v0++;
visible_mask = 0;
continue;
}
visible_mask = (
(v0->xyz[2] >= -v0->w) << 0 |
(v1->xyz[2] >= -v1->w) << 1 |
(v2->xyz[2] >= -v2->w) << 2
);
/* If we've gone behind the plane, we finish the strip
otherwise we submit however it was */
if(visible_mask == NONE_VISIBLE) {
SUBMIT_QUEUED_VERTEX(GPU_CMD_VERTEX_EOL);
} else {
SUBMIT_QUEUED_VERTEX(qv.flags);
}
#if CLIP_DEBUG
fprintf(stderr, "0x%x 0x%x 0x%x -> %d\n", v0, v1, v2, visible_mask);
#endif
Vertex __attribute__((aligned(32))) scratch[4];
Vertex* a = &scratch[0], *b = &scratch[1], *c = &scratch[2], *d = &scratch[3];
switch(visible_mask) {
case ALL_VISIBLE:
_glPerspectiveDivideVertex(v0, h);
QUEUE_VERTEX(v0);
break;
case NONE_VISIBLE:
break;
break;
case FIRST_VISIBLE:
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
@ -261,19 +310,10 @@ void SceneListSubmit(Vertex* v2, int n) {
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPushHeaderOrVertex(b);
}
break;
case 10:
case 2:
/* Second vertex was visible. In self case we need to create a triangle and produce
two new vertices: 1-2, and 2-3. */
{
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
QUEUE_VERTEX(b);
break;
case SECOND_VISIBLE:
memcpy_vertex(c, v1);
_glClipEdge(v0, v1, a);
@ -289,48 +329,9 @@ void SceneListSubmit(Vertex* v2, int n) {
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
}
QUEUE_VERTEX(b);
break;
case 11:
case 3: /* First and second vertex were visible */
{
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
memcpy_vertex(c, v1);
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glClipEdge(v1, v2, a);
a->flags = v2->flags;
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(c);
_glPushHeaderOrVertex(a);
}
break;
case 12:
case 4:
/* Third vertex was visible. */
{
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
case THIRD_VISIBLE:
memcpy_vertex(c, v2);
_glClipEdge(v2, v0, a);
@ -340,117 +341,90 @@ void SceneListSubmit(Vertex* v2, int n) {
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(a, h);
//_glPushHeaderOrVertex(a);
_glPushHeaderOrVertex(a);
if(counter % 2 == 1) {
_glPushHeaderOrVertex(a);
}
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPerspectiveDivideVertex(c, h);
QUEUE_VERTEX(c);
break;
case FIRST_AND_SECOND_VISIBLE:
memcpy_vertex(c, v1);
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glClipEdge(v1, v2, a);
a->flags = v2->flags;
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
}
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(c);
QUEUE_VERTEX(a);
break;
case 13:
{
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
case SECOND_AND_THIRD_VISIBLE:
memcpy_vertex(c, v1);
memcpy_vertex(d, v2);
memcpy_vertex(c, v2);
c->flags = GPU_CMD_VERTEX;
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX;
_glClipEdge(v1, v2, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
c->flags = GPU_CMD_VERTEX_EOL;
_glPushHeaderOrVertex(c);
}
break;
case 5: /* First and third vertex were visible */
{
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
memcpy_vertex(c, v2);
c->flags = GPU_CMD_VERTEX;
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v1, v2, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPushHeaderOrVertex(c);
}
break;
case 14:
case 6: /* Second and third vertex were visible */
{
Vertex __attribute__((aligned(32))) scratch[4];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
Vertex* d = &scratch[3];
memcpy_vertex(c, v1);
memcpy_vertex(d, v2);
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(d, h);
_glPushHeaderOrVertex(d);
}
break;
case 8:
default:
_glPerspectiveDivideVertex(d, h);
QUEUE_VERTEX(d);
break;
case FIRST_AND_THIRD_VISIBLE:
memcpy_vertex(c, v2);
c->flags = GPU_CMD_VERTEX;
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v1, v2, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
QUEUE_VERTEX(c);
break;
default:
fprintf(stderr, "ERROR\n");
}
}
SUBMIT_QUEUED_VERTEX(GPU_CMD_VERTEX_EOL);
_glFlushBuffer();
}

View File

@ -1211,6 +1211,7 @@ static int _determineConversion(GLint internalFormat, GLenum format, GLenum type
{_a8_to_argb4444, GL_ARGB4444_KOS, GL_ALPHA, GL_UNSIGNED_BYTE, false, false},
{_rgba8888_to_argb4444, GL_ARGB4444_KOS, GL_RGBA, GL_UNSIGNED_BYTE, false, false},
{_rgba4444_to_argb4444, GL_ARGB4444_KOS, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, false, false},
{_rgba4444_to_argb4444, GL_ARGB4444_TWID_KOS, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, true, false},
{NULL, GL_ARGB4444_KOS, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, false, false},
{NULL, GL_ARGB4444_TWID_KOS, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS, false, false},
{_rgba8888_to_argb4444, GL_ARGB4444_TWID_KOS, GL_RGBA, GL_UNSIGNED_BYTE, true, false},
@ -2041,7 +2042,8 @@ GLuint _glFreeContiguousTextureMemory() {
return alloc_count_continuous(ALLOC_BASE);
}
static void update_data_pointer(void* src, void* dst, void*) {
static void update_data_pointer(void* src, void* dst, void* data) {
_GL_UNUSED(data);
for(size_t id = 0; id < MAX_TEXTURE_COUNT; id++){
TextureObject* txr = (TextureObject*) named_array_get(&TEXTURE_OBJECTS, id);
if(txr && txr->data == src) {

View File

@ -20,7 +20,7 @@ void InitGL(int Width, int Height) // We call this right after our OpenG
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glEnable(GL_TEXTURE_2D);
glEnable(GL_CULL_FACE);
glDisable(GL_CULL_FACE);
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
@ -64,30 +64,38 @@ int check_start() {
return 0;
}
static GLfloat movement = -10.0f;
static GLfloat rotation = 0.0f;
void update_movement() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state) {
if(state->buttons & CONT_DPAD_UP) {
movement += 0.5f;
} else if(state->buttons & CONT_DPAD_DOWN) {
movement -= 0.5f;
}
if(state->buttons & CONT_DPAD_LEFT) {
rotation += 0.5f;
} else if(state->buttons & CONT_DPAD_RIGHT) {
rotation -= 0.5f;
}
}
}
#endif
}
/* The main drawing function. */
void DrawGLScene()
{
static GLfloat movement = 0.0f;
static GLfloat rotation = 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;
}
rotation += 0.1f;
if(rotation > 360.0f) {
rotation -= 360.0f;
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
@ -95,24 +103,58 @@ void DrawGLScene()
glTranslatef(0.0f, -1.0f, movement);
glRotatef(rotation, 0.0f, 1.0, 0.0f);
glBegin(GL_TRIANGLE_STRIP);
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(-2.5f, 0.0f, 5.0f);
/* We create a horseshoe shape tri-strip here because that allows for situations where a strip
leaves and re-enters the viewport */
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(2.5f, 0.0f, 5.0f);
glBegin(GL_TRIANGLE_STRIP);
// Left side
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(-2.0f, 0.0f, 5.0f);
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, 0.0f, 5.0f);
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(-2.0f, 0.0f, 3.0f);
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, 0.0f, 3.0f);
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(-2.0f, 0.0f, 1.0f);
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, 0.0f, 1.0f);
// Curve
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, 0.0f, -1.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(-2.5f, 0.0f, -5.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(2.5f, 0.0f, -5.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 0.0f, -1.0f);
glColor3f(0.0f, 1.0f, 1.0f);
glVertex3f(-2.5f, 0.0f, -10.0f);
// Right side
// Degenerate to reverse ordering
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(2.0f, 0.0f, 1.0f);
glColor3f(1.0f, 0.0f, 1.0f);
glVertex3f(2.5f, 0.0f, -10.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 3.0f);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(2.0f, 0.0f, 3.0f);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 5.0f);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(2.0f, 0.0f, 5.0f);
glEnd();
glPopMatrix();
@ -131,6 +173,8 @@ int main(int argc, char **argv)
if(check_start())
break;
update_movement();
DrawGLScene();
}