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();
}