Listing 2
#include <GL/glut.h>
#include <Cg/cg.h>
#include <Cg/cgGL.h>
// Mesh objects and materials
vector<MeshObject> mesh_objects;
vector<Material> materials;
Matrix4x4 rotMatrix;
// Cg program data
CGcontext context;
CGprogram vertexProgram, fragmentProgram;
CGprofile vertexProfile, fragmentProfile;
// Cg parameters
CGparameter position, normal, modelView, modelViewProj;
CGparameter diffuseTex, lightPos, Kd;
// OpenGL texture
GLuint diffuseTexId;
GLfloat diffuse_tex[32][3];
void error_callback()
{
cerr << cgGetErrorString(cgGetError()) << endl;
}
void init(const char *filename)
{
// Set error callback
cgSetErrorCallback(error_callback);
// Initialize OpenGL state
glClearColor(0.8, 0.8, 0.8, 0.0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glFrontFace(GL_CCW);
glPolygonMode(GL_FRONT, GL_FILL);
glPolygonMode(GL_BACK, GL_LINE);
glLineWidth(2.0);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
// Load mesh
Mesh mesh;
mesh.loadAC3D(filename);
mesh_objects = mesh.getMeshObjects();
materials = mesh.getMaterials();
rotMatrix = ID_MATRIX;
// Create Cg context
context = cgCreateContext();
// Initialize Cg profiles
vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
cgGLSetOptimalOptions(vertexProfile);
fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
cgGLSetOptimalOptions(fragmentProfile);
// Create and load vertex program
vertexProgram = cgCreateProgramFromFile(context,
CG_SOURCE, "toon.cg", vertexProfile, "VertexProgram", 0);
cgGLLoadProgram(vertexProgram);
// Create and load fragment program
fragmentProgram = cgCreateProgramFromFile(context,
CG_SOURCE, "toon.cg", fragmentProfile, "FragmentProgram", 0);
cgGLLoadProgram(fragmentProgram);
// Setup vertex program parameters
position = cgGetNamedParameter(vertexProgram, "position");
normal = cgGetNamedParameter(vertexProgram, "normal");
lightPos = cgGetNamedParameter(vertexProgram, "lightPos");
modelView = cgGetNamedParameter(vertexProgram, "modelView");
modelViewProj = cgGetNamedParameter(vertexProgram, "modelViewProj");
cgGLSetParameter3f(lightPos, -10.0, 10.0, 15.0);
// Setup fragment program parameters
Kd = cgGetNamedParameter(fragmentProgram, "Kd");
diffuseTex = cgGetNamedParameter(fragmentProgram, "diffuseTex");
// Setup OpenGL texture, diffuse lighting step
for(int i = 0; i < 32; i++) {
if(i >= 0 && i <= 10) {
diffuse_tex[i][0] = 0.4;
diffuse_tex[i][1] = 0.4;
}
else if(i == 31) {
diffuse_tex[i][0] = 1.0;
diffuse_tex[i][1] = 1.0;
diffuse_tex[i][2] = 1.0;
}
else {
diffuse_tex[i][0] = 0.8;
diffuse_tex[i][1] = 0.8;
diffuse_tex[i][2] = 0.8;
}
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &diffuseTexId);
glBindTexture(GL_TEXTURE_1D, diffuseTexId);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32,
0, GL_RGB, GL_FLOAT, diffuse_tex);
cgGLSetTextureParameter(diffuseTex, diffuseTexId);
}
void display(void)
{
static float angle = 0.0;
static int count = 0;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Setup rotation matrix
rotMatrix = ID_MATRIX;
rotMatrix = setRPY(rotMatrix, 0.0, 0.0, angle);
glPushMatrix();
glMultMatrixf((float *)transpose(rotMatrix).m);
angle += 0.01;
int mat;
for(int i = 0; i < mesh_objects.size(); i++) {
// Draw silhouette
glVertexPointer(3, GL_FLOAT, 0, mesh_objects[i].vertices);
glNormalPointer(GL_FLOAT, 0, mesh_objects[i].normals);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glDepthFunc(GL_LEQUAL);
glCullFace(GL_FRONT);
glColor3f(0.0, 0.0, 0.0);
glDrawArrays(GL_TRIANGLES, 0, 3*mesh_objects[i].ntris);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
// Draw object
glDepthFunc(GL_LESS);
glCullFace(GL_BACK);
mat = mesh_objects[i].matid;
// Enable position and normal arrays
cgGLEnableClientState(position);
cgGLSetParameterPointer(position, 3, GL_FLOAT, 0,
mesh_objects[i].vertices);
cgGLEnableClientState(normal);
cgGLSetParameterPointer(normal, 3, GL_FLOAT, 0,
mesh_objects[i].normals);
// Grab state matrix values
cgGLSetStateMatrixParameter(modelView, CG_GL_MODELVIEW_MATRIX,
CG_GL_MATRIX_IDENTITY);
cgGLSetStateMatrixParameter(modelViewProj,
CG_GL_MODELVIEW_PROJECTION_MATRIX,
CG_GL_MATRIX_IDENTITY);
// Enable profiles
cgGLEnableProfile(vertexProfile);
cgGLEnableProfile(fragmentProfile);
// Bind programs
cgGLBindProgram(vertexProgram);
cgGLBindProgram(fragmentProgram);
// Enable texture
cgGLEnableTextureParameter(diffuseTex);
// Set diffuse material value
cgGLSetParameter4f(Kd, materials[mat].diffuse.r,
materials[mat].diffuse.g, materials[mat].diffuse.b,
materials[mat].diffuse.a);
// Draw geometry
glDrawArrays(GL_TRIANGLES, 0, 3*mesh_objects[i].ntris);
// Disable texture
cgGLDisableTextureParameter(diffuseTex);
// Disable profiles
cgGLDisableProfile(vertexProfile);
cgGLDisableProfile(fragmentProfile);
// Disable normals and vertices
cgGLDisableClientState(normal);
cgGLDisableClientState(position);
}
glPopMatrix();
glFlush();
glutSwapBuffers();
}