//
// Marching Cubes Example Program
// by Cory Bloyd (corysama@yahoo.com)
//
// A simple, portable and complete implementation of the Marching Cubes
// and Marching Tetrahedrons algorithms in a single source file.
// There are many ways that this code could be made faster, but the
// intent is for the code to be easy to understand.
//
// For a description of the algorithm go to
// http://astronomy.swin.edu.au/pbourke/modelling/polygonise/
//
// This code is public domain.
//
#include "stdio.h"
#include "math.h"
//This program requires the OpenGL and GLUT libraries
// You can obtain them for free from http://www.opengl.org
#include "C:\Program Files\Microsoft Visual Studio\VC98\Include\GL\glut.h"
struct GLvector
{
GLfloat fX;
GLfloat fY;
GLfloat fZ;
};
//These tables are used so that everything can be done in little loops that you can look at all at once
// rather than in pages and pages of unrolled code.
//a2fVertexOffset lists the positions, relative to vertex0, of each of the 8 vertices of a cube
static const GLfloat a2fVertexOffset[8][3] =
{
{0.0, 0.0, 0.0},{1.0, 0.0, 0.0},{1.0, 1.0, 0.0},{0.0, 1.0, 0.0},
{0.0, 0.0, 1.0},{1.0, 0.0, 1.0},{1.0, 1.0, 1.0},{0.0, 1.0, 1.0}
};
//a2iEdgeConnection lists the index of the endpoint vertices for each of the 12 edges of the cube
static const GLint a2iEdgeConnection[12][2] =
{
{0,1}, {1,2}, {2,3}, {3,0},
{4,5}, {5,6}, {6,7}, {7,4},
{0,4}, {1,5}, {2,6}, {3,7}
};
//a2fEdgeDirection lists the direction vector (vertex1-vertex0) for each edge in the cube
static const GLfloat a2fEdgeDirection[12][3] =
{
{1.0, 0.0, 0.0},{0.0, 1.0, 0.0},{-1.0, 0.0, 0.0},{0.0, -1.0, 0.0},
{1.0, 0.0, 0.0},{0.0, 1.0, 0.0},{-1.0, 0.0, 0.0},{0.0, -1.0, 0.0},
{0.0, 0.0, 1.0},{0.0, 0.0, 1.0},{ 0.0, 0.0, 1.0},{0.0, 0.0, 1.0}
};
//a2iTetrahedronEdgeConnection lists the index of the endpoint vertices for each of the 6 edges of the tetrahedron
static const GLint a2iTetrahedronEdgeConnection[6][2] =
{
{0,1}, {1,2}, {2,0}, {0,3}, {1,3}, {2,3}
};
//a2iTetrahedronEdgeConnection lists the index of verticies from a cube
// that made up each of the six tetrahedrons within the cube
static const GLint a2iTetrahedronsInACube[6][4] =
{
{0,5,1,6},
{0,1,2,6},
{0,2,3,6},
{0,3,7,6},
{0,7,4,6},
{0,4,5,6},
};
static const GLfloat afAmbientWhite [] = {0.25, 0.25, 0.25, 1.00};
static const GLfloat afAmbientRed [] = {0.25, 0.00, 0.00, 1.00};
static const GLfloat afAmbientGreen [] = {0.00, 0.25, 0.00, 1.00};
static const GLfloat afAmbientBlue [] = {0.00, 0.00, 0.25, 1.00};
static const GLfloat afDiffuseWhite [] = {0.75, 0.75, 0.75, 1.00};
static const GLfloat afDiffuseRed [] = {0.75, 0.00, 0.00, 1.00};
static const GLfloat afDiffuseGreen [] = {0.00, 0.75, 0.00, 1.00};
static const GLfloat afDiffuseBlue [] = {0.00, 0.00, 0.75, 1.00};
static const GLfloat afSpecularWhite[] = {1.00, 1.00, 1.00, 1.00};
static const GLfloat afSpecularRed [] = {1.00, 0.25, 0.25, 1.00};
static const GLfloat afSpecularGreen[] = {0.25, 1.00, 0.25, 1.00};
static const GLfloat afSpecularBlue [] = {0.25, 0.25, 1.00, 1.00};
GLenum ePolygonMode = GL_FILL;
GLint iDataSetSize = 16;
GLfloat fStepSize = 1.0/iDataSetSize;
GLfloat fTargetValue = 48.0;
GLfloat fTime = 0.0;
GLvector sSourcePoint[3];
GLboolean bSpin = true;
GLboolean bMove = true;
GLboolean bLight = true;
void vIdle();
void vDrawScene();
void vResize(GLsizei, GLsizei);
void vKeyboard(unsigned char cKey, int iX, int iY);
void vSpecial(int iKey, int iX, int iY);
GLvoid vPrintHelp();
GLvoid vSetTime(GLfloat fTime);
GLfloat fSample1(GLfloat fX, GLfloat fY, GLfloat fZ);
GLfloat fSample2(GLfloat fX, GLfloat fY, GLfloat fZ);
GLfloat fSample3(GLfloat fX, GLfloat fY, GLfloat fZ);
GLfloat (*fSample)(GLfloat fX, GLfloat fY, GLfloat fZ) = fSample1;
GLvoid vMarchingCubes();
GLvoid vMarchCube1(GLfloat fX, GLfloat fY, GLfloat fZ, GLfloat fScale);
GLvoid vMarchCube2(GLfloat fX, GLfloat fY, GLfloat fZ, GLfloat fScale);
GLvoid (*vMarchCube)(GLfloat fX, GLfloat fY, GLfloat fZ, GLfloat fScale) = vMarchCube1;
void main(int argc, char **argv)
{
GLfloat afPropertiesAmbient [] = {0.50, 0.50, 0.50, 1.00};
GLfloat afPropertiesDiffuse [] = {0.75, 0.75, 0.75, 1.00};
GLfloat afPropertiesSpecular[] = {1.00, 1.00, 1.00, 1.00};
GLsizei iWidth = 640.0;
GLsizei iHeight = 480.0;
glutInit(&argc, argv);
glutInitWindowPosition( 0, 0);
glutInitWindowSize(iWidth, iHeight);
glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE );
glutCreateWindow( "Marching Cubes" );
glutDisplayFunc( vDrawScene );
glutIdleFunc( vIdle );
glutReshapeFunc( vResize );
glutKeyboardFunc( vKeyboard );
glutSpecialFunc( vSpecial );
glClearColor( 0.0, 0.0, 0.0, 1.0 );
glClearDepth( 1.0 );
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glPolygonMode(GL_FRONT_AND_BACK, ePolygonMode);
glLightfv( GL_LIGHT0, GL_AMBIENT, afPropertiesAmbient);
glLightfv( GL_LIGHT0, GL_DIFFUSE, afPropertiesDiffuse);
glLightfv( GL_LIGHT0, GL_SPECULAR, afPropertiesSpecular);
glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1.0);
glEnable( GL_LIGHT0 );
glMaterialfv(GL_BACK, GL_AMBIENT, afAmbientGreen);
glMaterialfv(GL_BACK, GL_DIFFUSE, afDiffuseGreen);
glMaterialfv(GL_FRONT, GL_AMBIENT, afAmbientBlue);
glMaterialfv(GL_FRONT, GL_DIFFUSE, afDiffuseBlue);
glMaterialfv(GL_FRONT, GL_SPECULAR, afSpecularWhite);
glMaterialf( GL_FRONT, GL_SHININESS, 25.0);
vResize(iWidth, iHeight);
vPrintHelp();
glutMainLoop();
}
GLvoid vPrintHelp()
{
printf("Marching Cubes Example by Cory Bloyd (dejaspaminacan@my-deja.com)\n\n");
printf("+/- increase/decrease sample density\n");
printf("PageUp/PageDown increase/decrease surface value\n");
printf("s change sample function\n");
printf("c toggle marching cubes / marching tetrahedrons\n");
printf("w wireframe on/off\n");
printf("l toggle lighting / color-by-normal\n");
printf("Home spin scene on/off\n");
printf("End source point animation on/off\n");
}
void vResize( GLsizei iWidth, GLsizei iHeight )
{
GLfloat fAspect, fHalfWorldSize = (1.4142135623730950488016887242097/2);
glViewport( 0, 0, iWidth, iHeight );
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
if(iWidth <= iHeight)
{
fAspect = (GLfloat)iHeight / (GLfloat)iWidth;
glOrtho(-fHalfWorldSize, fHalfWorldSize, -fHalfWorldSize*fAspect,
fHalfWorldSize*fAspect, -10*fHalfWorldSize, 10*fHalfWorldSize);
}
else
{
fAspect = (GLfloat)iWidth / (GLfloat)iHeight;
glOrtho(-fHalfWorldSize*fAspect, fHalfWorldSize*fAspect, -fHalfWorldSize,
fHalfWorldSize, -10*fHalfWorldSize, 10*fHalfWorldSize);
}
glMatrixMode( GL_MODELVIEW );
}
void vKeyboard(unsigned char cKey, int iX, int iY)
{
switch(cKey)
{
case 'w' :
{
if(ePolygonMode == GL_LINE)
{
ePolygonMode = GL_FILL;
}
else
{
ePolygonMode = GL_LINE;
}
glPolygonMode(GL_FRONT_AND_BACK, ePolygonMode);
} break;