I find c++ cleaner. And what makes is cleaner are classes.
This is the same demo in C++ using devcpp. The ascaris demo:
Code:
/*
Ascaris
Relsoft (Richard Eric M. Lope BSN RN)
Generates a tunnel based from BlackPawn's article
Added:
Ring undulation, band undulation, texturing, normals, etc.
*/
#ifndef ASCARIS_CPP
#define ASCARIS_CPP
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "cvertexbuffer.h"
#include "cvector.h"
#include "ascaris.h"
#define TWOPI 2 * 3.141593f
CVertexbuffer *init_ascaris ( int rings, // rings
int bands, // bands
float radius, // radius of each ring from center
float center_offset, // swirl offset
float ring_fold_off, //
float ring_fold_scale, //
int ring_fold_num, //
float band_fold_off, //
float band_fold_scale, //
int band_fold_num, //
float cam_speed, // camera speed
float gtimer, // timer
float tex_off, // motion of texture
int uscale,
int vscale)
{
CVertexbuffer *vb = new CVertexbuffer;
int max_point = (rings) * (bands + 1); //+1 for last band duplicate
CVector3 *vertex = new CVector3[max_point]; //
CVector3 *color = new CVector3[max_point]; //
CVector3 *normal = new CVector3[max_point]; //
CTexcoord *texture = new CTexcoord[max_point]; //
CPolygon *poly = new CPolygon[max_point * 2]; //
vb->ps_vertex = vertex;
vb->ps_color = color;
vb->ps_normal = normal;
vb->ps_texture = texture;
vb->ps_poly = poly;
vb->i_max_vertex = max_point;
vb->i_max_poly = max_point * 2;
vb->i_primitive_type = GL_TRIANGLES;
//lathing
unsigned int s, u, slice, maxvert;
maxvert = max_point;
int i = 0;
for (s = 0; s < (rings); s++)
{
slice = s * bands;
for (u = 0; u <= bands; u++) //duplicate texture ( not bands - 1)
{
poly[i].v1=(u+bands+1+(slice)) % maxvert;
poly[i].v2=(u+bands+(slice)) % maxvert;
poly[i].v3=(u+(slice)) % maxvert;
poly[i+1].v1=(u+(slice)) % maxvert;
poly[i+1].v2=(u+1+(slice)) % maxvert;
poly[i+1].v3=(u+bands+1+(slice)) % maxvert;
i += 2;
}
}
int k = 0;
float xc, yc, zc;
for (int i = 0; i < rings; i++)
{
zc = i + gtimer * cam_speed;
xc = cos(TWOPI * zc / rings)* center_offset;
yc = sin(TWOPI * zc / rings)* center_offset;
for (int j = 0; j <= bands; j++)
{
float x = xc + cos(j * TWOPI / bands ) * radius
* ((sin(band_fold_off + band_fold_num * j * TWOPI / bands) * band_fold_scale) + 1);
float y = yc + sin(j * TWOPI / bands ) * radius
* ((sin(band_fold_off + band_fold_num * j * TWOPI / bands) * band_fold_scale) + 1);
float z = 15 - i;
vertex[k].x = x * ((sin(ring_fold_off + ring_fold_num * i * TWOPI / rings) * ring_fold_scale) + 1);
vertex[k].y = y * ((sin(ring_fold_off + ring_fold_num * i * TWOPI / rings) * ring_fold_scale) + 1);
vertex[k].z = z;
normal[k].x = xc - vertex[k].x;
normal[k].y = yc - vertex[k].y;
normal[k].z = 0;
normal[k].normalize();
color[k].x = 1.0f - (i / (float)rings);
color[k].y = 1.0f - (i / (float)rings);
color[k].z = 1.0f - (i / (float)rings);
texture[k].v = ((float)j / bands ) * vscale;
texture[k].u = (((float)i / rings ) * uscale) + tex_off;
k++;
}
}
return vb;
}
#endif
Code:
/*
Vertex buffer class
Relsoft (Richard Eric M. Lope BSN RN)
Wrapper for vertex buffers
Can only do Vertex arrays for now due to my crap hardware not
supporting extensions
*/
#ifndef CVERTEXBUFFER_CPP
#define CVERTEXBUFFER_CPP
#include <windows.h>
#include <GL/gl.h>
#include "cvector.h"
#include "cvertexbuffer.h"
CVertexbuffer::CVertexbuffer()
{
ps_vertex = NULL;
ps_color = NULL;
ps_normal = NULL;
ps_poly = NULL;
ps_texture = NULL;
i_max_poly = 0;
i_primitive_type = 0;
}
CVertexbuffer::~CVertexbuffer()
{
delete[] ps_vertex;
ps_vertex = NULL;
delete[] ps_color;
ps_color = NULL;
delete[] ps_normal;
ps_normal = NULL;
delete[] ps_poly;
ps_poly = NULL;
i_max_poly = 0;
i_primitive_type = 0;
delete[] ps_texture;
ps_texture = NULL;
}
void CVertexbuffer::initialize()
{
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, 0, ps_color);
glVertexPointer(3, GL_FLOAT, 0, ps_vertex);
glTexCoordPointer(2, GL_FLOAT, 0, ps_texture);
glNormalPointer(GL_FLOAT, 0, ps_normal);
}
void CVertexbuffer::render()
{
//mult maxpoly by 3
glDrawElements(i_primitive_type, i_max_poly * 3, GL_UNSIGNED_INT, ps_poly);
}
void CVertexbuffer::disable()
{
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
void CVertexbuffer::render_normals(float scale)
{
CVector3 *verts = new CVector3[i_max_vertex * 2];
for (int i = 0; i < (i_max_vertex * 2); i += 2)
{
verts[i] = ps_vertex[i];
verts[i+1] = ps_vertex[i] + (ps_normal[i] * scale);
}
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisable(GL_TEXTURE_2D);
glVertexPointer(3, GL_FLOAT, 0, verts);
glDrawArrays(GL_LINES,0, i_max_vertex * 2);
delete[] verts;
}
#endif
Code:
/*
Ascaris
Another Tunnel by Relsoft (Richard Eric M. Lope BSN RN)
Rel.Betterwebber.com
If you thought I'd stop with Jejunum then you're wrong. :*)
I love tunnels. To date I have made tunnels using PQtoruses,
raytracing, fake2d tunnels, etc. I just couldn't help making the tunnel
when I saw blackpawn's text. :*)
Special thanks to black_pawn for the text. :*) And the texture. :*)
BlackPawn.com
Dev kit = DevCPP
API = OpenGL + SDL
*/
#include <stdio.h>
#include <stdlib.h>
#include <SDL\SDL.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include "cvector.h"
#include "cvertexbuffer.h"
#include "ctexture.h"
#include "ascaris.h"
int setup_sdl( SDL_Surface *screen);
void setup_opengl( int width, int height );
int get_sdl_events();
void setup_gl_material_light();
void setup_gl_light(float *light_position);
void draw_scene();
const int SCREEN_W = 640;
const int SCREEN_H = 480;
const int BPP = 32;
const int ARINGS = 128;
const int ABANDS = 64;
const float ARADIUS = 3.5f;
const int ARING_FOLD = 16;
const int ABAND_FOLD = 7;
const float CAMSPEED = 0.03f;
const float PI = 3.141593f;
int main (int argc, char *argv[])
{
SDL_Surface *screen = NULL;
float light_pos[4] = {0.0f, 0.0f, -113.0f, 1.0}; //world lighting
float *light = light_pos;
int done;
if (!setup_sdl( screen ))
{
exit (1);
}
setup_opengl( SCREEN_W, SCREEN_H );
setup_gl_material_light();
setup_gl_light(light);
CTexture Texture;
if ( Texture.load("organ.bmp") == 0)
{
fprintf( stderr, "Can't load texture!!!%s\n",
SDL_GetError( ) );
SDL_Quit( );
exit (3);
}
int frames = 0;
int stime, t;
int fps2;
stime = (int)(SDL_GetTicks() * 0.001);
done = 0;
while (!done)
{
done = get_sdl_events();
draw_scene();
SDL_GL_SwapBuffers();
frames++;
t = (int)(SDL_GetTicks() * 0.001) - stime;
if (t > 2)
{
fps2 = (int)frames/t;
char szTitle[256]={0}; // Build The Title String
sprintf( szTitle, "*Ascaris* by Relsoft [Rel.Betterwebber.com] FPS: %d", fps2 );
SDL_WM_SetCaption ( szTitle, NULL);
stime = (int)(SDL_GetTicks() * 0.001);
frames = 0;
}
}
return 0;
}
//********************************************************************
//
//********************************************************************
int setup_sdl( SDL_Surface *screen)
{
/* Initialize SDL */
if (SDL_Init (SDL_INIT_VIDEO) < 0)
{
fprintf( stderr, "Video initialization failed: %s\n",
SDL_GetError( ) );
SDL_Quit( );
exit (1);
}
atexit (SDL_Quit);
int flags = 0;
flags = SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_OPENGL;
//flags |= SDL_FULLSCREEN;
screen = SDL_SetVideoMode (SCREEN_W, SCREEN_H, BPP, flags);
if (screen == NULL)
{
fprintf( stderr, "Video initialization failed: %s\n",
SDL_GetError( ) );
SDL_Quit( );
exit (2);
}
SDL_WM_SetCaption ("Ascaris by Relsoft Rel.Betterwebber.com", NULL);
}
//********************************************************************
//
//********************************************************************
void setup_opengl( int width, int height )
{
float ratio = (float) width / (float) height;
glShadeModel( GL_SMOOTH );
/* Culling. */
//glCullFace( GL_BACK );
//glFrontFace( GL_CCW );
//glEnable( GL_CULL_FACE );
glClearColor( 0, 0, 0, 0 );
glViewport( 0, 0, width, height );
glClearDepth (1.0);
glEnable (GL_DEPTH_TEST);
glDepthFunc (GL_LEQUAL);
glEnable (GL_COLOR_MATERIAL);
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
gluPerspective( 45.0, ratio, 1.0, 200.0 );
}
//********************************************************************
//
//********************************************************************
int get_sdl_events()
{
SDL_Event event;
int done = 0;
/* Check for events */
while (SDL_PollEvent (&event))
{
switch (event.type)
{
case SDL_KEYDOWN:
done = 1;
break;
case SDL_QUIT:
done = 1;
break;
default:
break;
}
}
return done;
}
//********************************************************************
//draw scene
//********************************************************************
void draw_scene()
{
float gtimer = SDL_GetTicks();
CVertexbuffer *vb = init_ascaris (
ARINGS,
ABANDS,
ARADIUS,
2.8f,
0.02f,
0.07f * sin(gtimer * CAMSPEED / 512.0f),
ARING_FOLD,
0.02f,
0.15f * sin(gtimer * CAMSPEED / 64.0f),
ABAND_FOLD,
CAMSPEED,
gtimer,
gtimer * CAMSPEED / (float)ARINGS,
32,
8);
glMatrixMode( GL_MODELVIEW );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glLoadIdentity();
float cz = 0 + gtimer * CAMSPEED;
CVector3 pos( cos(2 * PI * cz / (float)ARINGS) * 2.8f,
sin(2 * PI * cz / (float)ARINGS) * 2.8f,
0 );
gluLookAt ( pos.x, pos.y, 0.0f,
0.0f,0.0f, -10.0f,
0.0f,1.0f,0.0f );
glEnable(GL_TEXTURE_2D);
vb->initialize();
vb->render();
//vb->render_normals();
vb->disable();
/*glBegin (GL_TRIANGLES);
for (int i=0; i < (vb->i_max_poly); i++)
{
glColor3fv (&vb->ps_color[vb->ps_poly[i].v1].x);
glNormal3fv (&vb->ps_normal[vb->ps_poly[i].v1].x);
glTexCoord2fv (&vb->ps_texture[vb->ps_poly[i].v1].u);
glVertex3fv (&vb->ps_vertex[vb->ps_poly[i].v1].x);
glColor3fv (&vb->ps_color[vb->ps_poly[i].v2].x);
glNormal3fv (&vb->ps_normal[vb->ps_poly[i].v2].x);
glTexCoord2fv (&vb->ps_texture[vb->ps_poly[i].v2].u);
glVertex3fv (&vb->ps_vertex[vb->ps_poly[i].v2].x);
glColor3fv (&vb->ps_color[vb->ps_poly[i].v3].x);
glNormal3fv (&vb->ps_normal[vb->ps_poly[i].v3].x);
glTexCoord2fv (&vb->ps_texture[vb->ps_poly[i].v3].u);
glVertex3fv (&vb->ps_vertex[vb->ps_poly[i].v3].x);
}
glEnd();
*/
glDisable(GL_TEXTURE_2D);
glPopMatrix();
glFlush();
delete vb;
}
void setup_gl_material_light()
{
float ambient[4] = {0.5f, 0.5f, 0.5f, 1.0};
float specular[4] = {1.0f, 1.0f, 1.0f, 1.0};
float shine[1] = {50.0f};
glMaterialfv (GL_FRONT, GL_AMBIENT, ambient);
glMaterialfv (GL_FRONT, GL_SPECULAR, specular);
glMaterialfv (GL_FRONT, GL_SHININESS, shine);
}
void setup_gl_light(float *light_position)
{
float ambient[4] = {0.3f, 0.3f, 0.3f, 1.0}; //world lighting
float diffuse[4] = {0.5f, 0.5f, 0.5f, 1.0}; //position light
float specular[4] = {0.3f, 0.9f, 0.7f, 1.0}; //position light
float model_ambient[4] = {0.5f, 0.5f, 0.5f, 1.0};
glLightfv( GL_LIGHT0, GL_AMBIENT, ambient );
glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse );
glLightfv( GL_LIGHT0, GL_DIFFUSE, specular );
glLightfv( GL_LIGHT0, GL_POSITION, light_position );
glLightModelfv (GL_LIGHT_MODEL_AMBIENT, model_ambient);
glEnable( GL_LIGHT0 );
glEnable( GL_LIGHTING );
}
See, the vertex buffer code can be reused on any of my upcoming projects. Now I would also do it this way when FB gets to support classes. :*)