⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bumpobject.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
字号:
/* Copyright (C) Dan Ginsburg ang Dave Gosselin, 2001. 
 * All rights reserved worldwide.
 *
 * This software is provided "as is" without express or implied
 * warranties. You may freely copy and compile this source into
 * applications you distribute provided that the copyright text
 * below is included in the resulting source code, for example:
 * "Portions Copyright (C) Dan Ginsburg ang Dave Gosselin, 2001"
 */
///////////////////////////////////////////////////////////////////////////////
//
//   BumpObject.cpp - This file contains the members of the BumpObject.
//                    The object draws bumpmapped POF obects.
//
/////////////////////////////////////////////////////////////////////

#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <glut.h>
#include <stdio.h>
#include <math.h>
#include "glati.h"
#include "wglati.h"

#include "BumpObject.h"

// Prototype needed
extern PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTexture;

extern void matrixIdentity(GLfloat matrix[16]);
extern void matrixInvert(GLfloat in[16], GLfloat out[16]);
extern void vecMatMult(GLfloat vecIn[3], GLfloat m[16], GLfloat vecOut[3]);
extern void vecMat3x3Mult(GLfloat vecIn[3], GLfloat m[16], GLfloat vecOut[3]);

//////////////////////////
// Constructor handled in base class
///////////////////////////
BumpObject::BumpObject() : pofObject()
{
}

//////////////////////////
// Destructor -- nothing needed
///////////////////////////
BumpObject::~BumpObject()
{
}

//////////////////////////
// Addtional loading to make sure that all the memory we need has been
// allocated.
///////////////////////////
void 
BumpObject::loadObject(char *fn)
{
  // Load up the POF file using baseclass.
  pofObject::loadObject(fn);

  // Allocate color so we can use it for passing the light in tangent space
  for (int i = 0; i < m_numObjects; i++) {
    vertexList *v = m_faces[i]->getVertexList();
    if (v->m_cSets == 0) {
      v->m_cSets = v->m_tSets;
      v->m_colors = new float* [v->m_cSets];
      v->m_cComponents = new int[v->m_cSets];
      v->m_cInstances = new unsigned int[v->m_cSets];
      for (int i = 0; i < v->m_cSets; i++){
        v->m_cComponents[i] = 3;
        v->m_cInstances[i] = v->m_tInstances[i];
        v->m_colors[i] = new float[v->m_count*3];
      }    
    }
  }
}

//////////////////////////
// This method computes the lighting vector at each vertex in tangent space
// and packs this into the color. This will be dotted with the pre-filtered
// bump texture.
//   lightpos -- Postion of the the light in OBJECT space.
//   forCubemap -- Flag to say we are using a cubemap for normalization.
//////////////////////////
void 
BumpObject::computeLighting(GLfloat lightpos[3], GLuint forCubemap)
{
  // Loop through all the objects in the file.
  for (int i = 0; i < m_numObjects; i++) {
    vertexList *v = m_faces[i]->getVertexList();
    float *vtx = v->getVertices();

    // Make sure the vertex has all the required data
    float *nrm, *binorm, *tangent, *color;
    if ((nrm = v->getNormals()) && 
        (tangent = v->getTexCoords(POF_TCI_TAN0)) &&
        (binorm =  v->getTexCoords(POF_TCI_BINORM0)) &&
        (color = v->getColors(POF_CI_DIFFUSE)) ) { 
      int szVert = v->m_vComponents;
      int szTan = v->getNumTexCoordComponents(POF_TCI_TAN0);
      int szBN = v->getNumTexCoordComponents(POF_TCI_BINORM0);
      int szClr = v->getNumColorComponents(POF_CI_DIFFUSE);
      int szNorm = 3;

      // Loop over all the vertices
      for (int j = 0; j < v->getNumVertices(); j++) {

        // Compute light vector in OBJECT space.
        GLfloat lv[3];
        lv[0] = (lightpos[0] - vtx[j*szVert + 0]);
        lv[1] = (lightpos[1] - vtx[j*szVert + 1]);
        lv[2] = (lightpos[2] - vtx[j*szVert + 2]);

        // Normalize light vector so the conversion is normalized.
        GLfloat lsz = sqrt((lv[0]*lv[0]) + (lv[1]*lv[1]) +
                           (lv[2]*lv[2]));
        if ((lsz > -0.0000001) && (lsz < 0.0000001)) { // Don't divide by zero
          lv[0] = 0.0f;
          lv[1] = 0.0f;
          lv[2] = 1.0f;
        } else {
          lv[0] = lv[0]/lsz;
          lv[1] = lv[1]/lsz;
          lv[2] = lv[2]/lsz;
        }

        // Convert the light vector into tangent space
        //
        // T - Tangent to surface
        // N - Normal to surface
        // B - Bi-Normal (T cross N)
        // color = lightvec  | T(x) B(x) N(x) |
        //                   | T(y) B(y) N(y) |
        //                   | T(z) B(z) N(z) |
        GLfloat m[16]; 
        matrixIdentity(m);
        m[0] = tangent[j*szTan + 0];
        m[1] = binorm[j*szBN + 0];
        m[2] = nrm[j*szNorm + 0];   
        m[4] = tangent[j*szTan + 1];
        m[5] = binorm[j*szBN + 1];  
        m[6] = nrm[j*szNorm + 1];  
        m[8] = tangent[j*szTan + 2];
        m[9] = binorm[j*szBN + 2];
        m[10]=nrm[j*szNorm + 2];
        GLfloat v[3];
        vecMat3x3Mult(lv,m,v);
        color[j*szClr + 0] = v[0];
        color[j*szClr + 1] = v[1];
        color[j*szClr + 2] = v[2];
        if (!forCubemap) {
          color[j*szClr + 0] = (color[j*szClr + 0] * 0.5) + 0.5;
          color[j*szClr + 1] = (color[j*szClr + 1] * 0.5) + 0.5;
          color[j*szClr + 2] = (color[j*szClr + 2] * 0.5) + 0.5;
        }
      } // end for j
    } // end if we have normals, tangents, binormals, and colors
  } // end for i
}

//////////////////////////
// Render the bumpmaped object. This member sets up the Vertex, Normal, Texture
// and Color arrays. The color array is special in the case of non-cubemapping
// it contains the the encoded (0.5 = 0.0) light vector in tangent space.
//   forCubemap -- Flag to say we are using a cubemap for normalization.
//   pass -- Which rendering pass we are using.
///////////////////////////
void 
BumpObject::renderObject(GLuint forCubemap, GLuint pass)
{
  glEnableClientState(GL_VERTEX_ARRAY);

  // Loop through all the objects in the file.
  for (int i = 0; i < m_numObjects; i++) {
    // Send the Vertex array
    vertexList *v = m_faces[i]->getVertexList();
    glVertexPointer(v->m_vComponents, GL_FLOAT, 0, v->m_verts);

    // Only set texture and color coordinates on the first pass.
    if (pass == 0) {
      // Send the Texture Coordinate array.
      float *tex;
      if (tex = v->getTexCoords(POF_TCI_BASE)){
        if (!forCubemap) {
          glClientActiveTexture(GL_TEXTURE0_ARB);
          glEnableClientState(GL_TEXTURE_COORD_ARRAY);
          glTexCoordPointer(v->getNumTexCoordComponents(POF_TCI_BASE), GL_FLOAT,
                            0, tex);
        }
        glClientActiveTexture(GL_TEXTURE1_ARB);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glTexCoordPointer(v->getNumTexCoordComponents(POF_TCI_BASE), GL_FLOAT,
                          0, tex);
        glClientActiveTexture(GL_TEXTURE2_ARB);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glTexCoordPointer(v->getNumTexCoordComponents(POF_TCI_BASE), GL_FLOAT,
                          0, tex);
      }

      // Send the color array (really the light vector in tangent space)
      float *binorm, *tangent, *color;
      if ((v->m_norms) && 
          (tangent = v->getTexCoords(POF_TCI_TAN0)) &&
          (binorm = v->getTexCoords(POF_TCI_BINORM0)) &&
          (color = v->getColors(POF_CI_DIFFUSE)) ) { 
        glClientActiveTexture(GL_TEXTURE0_ARB);
        if (forCubemap) {
          glEnableClientState(GL_TEXTURE_COORD_ARRAY);
          glTexCoordPointer(v->m_cComponents[0], GL_FLOAT, 0, color);
        } else {
          glEnableClientState(GL_COLOR_ARRAY);
          glColorPointer(v->m_cComponents[0], GL_FLOAT, 0, color);
        }
      }
    }

    // Draw the elements.
    glDrawElements(GL_TRIANGLES, m_faces[i]->m_count*3,
                   GL_UNSIGNED_INT, m_faces[i]->m_indices);

    // Disable Array states
    glClientActiveTexture(GL_TEXTURE0_ARB);
       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
       glDisableClientState(GL_COLOR_ARRAY);
    glClientActiveTexture(GL_TEXTURE1_ARB);
       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
       glDisableClientState(GL_COLOR_ARRAY);
    glClientActiveTexture(GL_TEXTURE2_ARB);
       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
       glDisableClientState(GL_COLOR_ARRAY);
  } // end for i

  // Disable Array state
  glDisableClientState(GL_VERTEX_ARRAY);
} // render object

//////////////////////////
// Renders the light vectors and tangent space coordinate systems.
//  sf - scaling factor for how long to make the vectors/coord systems.
//  coordFlag - draw coord system if true.
//  lightFlag - draw light vector if true
//  forCubemap - Were the colors encoded for cubemaping?
//////////////////////////
void 
BumpObject::renderVectors(GLfloat sf, GLuint coordFlag, GLuint lightFlag, 
                          GLuint forCubemap)
{
  float *vtx;
  float *nrm;
  float *tan;
  float *binorm;
  float *color;
  vertexList *v;
  int ii,gg;

  // Loop over the objects in the file
  for (ii = 0; ii < m_numObjects; ii++){
    v = m_faces[ii]->getVertexList();
    vtx = v->getVertices();
    nrm = v->getNormals();
    tan = v->getTexCoords(POF_TCI_TAN0);
    binorm = v->getTexCoords(POF_TCI_BINORM0);
    color = v->getColors(POF_CI_DIFFUSE);
    int szVert = v->m_vComponents;

    // Draw Normals in red
    if (nrm && coordFlag){
      int szNorm = 3;
      glColor3f(1.0f, 0.0f, 0.0f);
      glBegin(GL_LINES);
      for (gg = 0; gg < v->getNumVertices(); gg++){
        glVertex3fv(&vtx[gg*szVert]);
        glVertex3f(vtx[gg*szVert + 0] + nrm[gg*szNorm + 0]*sf, 
                   vtx[gg*szVert + 1] + nrm[gg*szNorm + 1]*sf,
                   vtx[gg*szVert + 2] + nrm[gg*szNorm + 2]*sf);
      }
      glEnd();
    }

    // Draw Tangent in blue
    if (tan && coordFlag){
      int szTan = v->getNumTexCoordComponents(POF_TCI_TAN0);
      glColor3f(0.0f, 0.0f, 1.0f);
      glBegin(GL_LINES);
      for (gg = 0; gg < v->getNumVertices(); gg++){
        glVertex3fv(&vtx[gg*szVert]);
        glVertex3f(vtx[gg*szVert + 0] + tan[gg*szTan + 0]*sf, 
                   vtx[gg*szVert + 1] + tan[gg*szTan + 1]*sf,
                   vtx[gg*szVert + 2] + tan[gg*szTan + 2]*sf);
      }
      glEnd();
    }

    // Draw Binormal in green
    if (binorm && coordFlag){
      int szBN = v->getNumTexCoordComponents(POF_TCI_BINORM0);
      glColor3f(0.0f, 1.0f, 0.0f);
      glBegin(GL_LINES);
      for (gg = 0; gg < v->getNumVertices(); gg++){
        glVertex3fv(&vtx[gg*szVert]);
        glVertex3f(vtx[gg*szVert + 0] + binorm[gg*szBN + 0]*sf, 
                   vtx[gg*szVert + 1] + binorm[gg*szBN + 1]*sf,
                   vtx[gg*szVert + 2] + binorm[gg*szBN + 2]*sf);
      }
      glEnd();
    }

    // Draw light vector in yellow.
    if (color && lightFlag){
      glColor3f(1.0f, 1.0f, 0.0f);
      glBegin(GL_LINES);
      for (gg=0; gg < v->getNumVertices(); gg++){
        if (nrm && binorm && tan) {
          int szTan = v->getNumTexCoordComponents(POF_TCI_TAN0);
          int szBN = v->getNumTexCoordComponents(POF_TCI_BINORM0);
          int szClr = v->getNumColorComponents(POF_CI_DIFFUSE);
          int szNorm = 3;
          glVertex3fv(&vtx[gg*szVert]);

          // Unpack color (which represents light vector in object space)
          GLfloat cv[3];
          if (forCubemap) {
            cv[0] = color[gg*szClr + 0];
            cv[1] = color[gg*szClr + 1];
            cv[2] = color[gg*szClr + 2];
          } else {
            cv[0] = (color[gg*szClr + 0] - 0.5f) * 2.0f;
            cv[1] = (color[gg*szClr + 1] - 0.5f) * 2.0f;
            cv[2] = (color[gg*szClr + 2] - 0.5f) * 2.0f;
          }

          // Convert to screen space coords
          GLfloat m[16]; 
          GLfloat mi[16]; 
          matrixIdentity(m);
          matrixIdentity(mi);
          m[0]=tan[gg*szTan + 0];   
          m[1]=binorm[gg*szBN + 0];
          m[2]=nrm[gg*szNorm + 0];  
          m[4]=tan[gg*szTan + 1];   
          m[5]=binorm[gg*szBN + 1]; 
          m[6]=nrm[gg*szNorm + 1];  
          m[8]=tan[gg*szTan + 2];
          m[9]=binorm[gg*szBN + 2];
          m[10]=nrm[gg*szNorm + 2];
          matrixInvert(m,mi);
          GLfloat v[3];
          vecMat3x3Mult(cv,mi,v);

          // Draw
          glVertex3f(vtx[gg*szVert + 0] + v[0]*sf, 
                     vtx[gg*szVert + 1] + v[1]*sf,
                     vtx[gg*szVert + 2] + v[2]*sf);
        }
      }
      glEnd();
    } // end if color
  } // end for ii
} // render vectors

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -