diff --git a/GL/matrix.c b/GL/matrix.c index d95cd49..2744cb9 100644 --- a/GL/matrix.c +++ b/GL/matrix.c @@ -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); diff --git a/GL/platform.h b/GL/platform.h index 4e1e65b..f0a2f14 100644 --- a/GL/platform.h +++ b/GL/platform.h @@ -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" diff --git a/GL/platforms/sh4.c b/GL/platforms/sh4.c index acaf692..ba00148 100644 --- a/GL/platforms/sh4.c +++ b/GL/platforms/sh4.c @@ -1,3 +1,5 @@ +#include + #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*)¶ms) + opb_offset); + *opb_count = 2; // Two should be enough for anybody.. right? + } + pvr_init(¶ms); +#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(); } diff --git a/GL/texture.c b/GL/texture.c index b41313b..c6a0a0f 100644 --- a/GL/texture.c +++ b/GL/texture.c @@ -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) { diff --git a/samples/zclip_trianglestrip/main.c b/samples/zclip_trianglestrip/main.c index 7d4b698..064add8 100644 --- a/samples/zclip_trianglestrip/main.c +++ b/samples/zclip_trianglestrip/main.c @@ -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(); }