src/model.cpp

Go to the documentation of this file.
00001 #define GL_GLEXT_PROTOTYPES
00002 
00003 #include "model.h"
00004 
00005 JOEMODEL::JOEMODEL()
00006 {
00007         // Set the pointers to null
00008         pObject = NULL;
00009         loadedfile = false;
00010 //      has_paint = false;
00011         
00012         radius = 0.0;
00013         radiusxz = 0.0;
00014         
00015         int i;
00016         for (i = 0; i < MAX_TEXTURE_UNITS; i++)
00017         {
00018                 texturemode[i] = TEXTUREMODE_NOTEX;
00019                 tuenable[i] = true;
00020                 autounload[i] = true;
00021         }
00022         
00023         collidecachepos = 0;
00024         for (i = 0; i < NUM_COLLIDE_CACHE; i++)
00025                 collidecache[i] = 0;
00026 }
00027 
00028 int JOEMODEL::BinaryRead(void * buffer, unsigned int size, unsigned int count, FILE * f, JOEPACK * pack)
00029 {
00030         if (pack == NULL)
00031         {
00032                 return fread(buffer, size, count, f);
00033         }
00034         else
00035         {
00036                 return pack->Pack_fread(buffer, size, count);
00037         }
00038 }
00039 
00040 bool JOEMODEL::Load(string strFileName, bool autoloadtexture) 
00041 {
00042      return this->Load(strFileName, autoloadtexture, NULL);
00043 }
00044 
00045 bool JOEMODEL::Load(string strFileName, bool autoloadtexture, JOEPACK * pack)
00046 {
00047         modelpath = strFileName;
00048         
00049         if (loadedfile)
00050         {
00051                 int i;
00052                 
00053                 for (i = 0; i < MAX_TEXTURE_UNITS; i++)
00054                 {
00055                         /*if (texturemode[i] != TEXTUREMODE_NOTEX && autounload[i])
00056                         {
00057                                 glDeleteTextures(1, &textureid[i]);
00058                         }*/
00059                         
00060                         textureid[i].Unload();
00061                         
00062                         texturemode[i] = TEXTUREMODE_NOTEX;
00063                 }
00064                 
00065                 for (i = 0; i < MAX_TEXTURE_UNITS; i++)
00066                 {
00067                         texturemode[i] = TEXTUREMODE_NOTEX;
00068                         tuenable[i] = true;
00069                         autounload[i] = true;
00070                 }
00071                 
00072                 loadedfile = false;
00073                 
00074                 if (pObject != NULL)
00075                 {       
00076                         for (i = 0; i < pObject->info.num_frames; i++)
00077                         {
00078                                 delete [] pObject->frames[i].faces;
00079                                 delete [] pObject->frames[i].verts;
00080                                 delete [] pObject->frames[i].normals;
00081                                 delete [] pObject->frames[i].texcoords;
00082                         }
00083                         
00084                         delete [] pObject->frames;
00085                         
00086                         delete pObject;
00087                 }
00088                 
00089                 pObject = NULL;
00090                 
00091                 glDeleteLists(static_list, 1);
00092                 static_list = 0;
00093         }
00094         
00095         collidecachepos = 0;
00096         
00097         char strMessage[255] = {0};
00098 
00099         string filename = strFileName;
00100 
00101         FILE * m_FilePointer = NULL;
00102         
00103     //open file
00104         bool fileinpack = false;
00105         if (pack == NULL)
00106         m_FilePointer = fopen(filename.c_str(), "rb");
00107         else
00108                 fileinpack = pack->Pack_fopen(filename);
00109 
00110     // Make sure we have a valid file pointer (we found the file)
00111     if ((pack == NULL && !m_FilePointer) || (pack != NULL && !fileinpack))
00112     {
00113         // Display an error message and don't load anything if no file was found
00114         sprintf(strMessage, "Unable to find the file: %s!", strFileName.c_str());
00115                 loadedfile = false;
00116         cerr << strMessage << endl;
00117                 return false;
00118     }
00119 
00120         if (autoloadtexture)
00121         {
00122                 if (utility.FileExists(FileToPNG(filename)))
00123                 {
00124                         textureid[0].Load(FileToPNG(filename), true);
00125                         
00126                         texturemode[0] = TEXTUREMODE_TEX;
00127                 }
00128                 else
00129                 {
00130                         if (utility.FileExists(FileToTexturesizePNG(filename)))
00131                         {
00132                                 textureid[0].Load(FileToTexturesizePNG(filename), true);
00133                                 texturemode[0] = TEXTUREMODE_TEX;
00134                         }
00135                 }
00136         }
00137         
00138         bool val = LoadFromHandle(m_FilePointer, pack);
00139         
00140         // Clean up after everything
00141     CleanUp(m_FilePointer, pack);
00142         
00143         return val;
00144 }
00145 
00146 bool JOEMODEL::LoadFromHandle(FILE * m_FilePointer, JOEPACK * pack)
00147 {       
00148         char strMessage[255] = {0};
00149         
00150         //create a new object
00151         pObject = new JOEObject;
00152 
00153     // Read the header data and store it in our variable
00154     BinaryRead(&pObject->info, sizeof(JOEHeader), 1, m_FilePointer, pack);
00155         
00156         pObject->info.magic = ENDIAN_SWAP_32(pObject->info.magic);
00157         pObject->info.version = ENDIAN_SWAP_32(pObject->info.version);
00158         pObject->info.num_faces = ENDIAN_SWAP_32(pObject->info.num_faces);
00159         pObject->info.num_frames = ENDIAN_SWAP_32(pObject->info.num_frames);
00160         
00161     // Make sure the version is what we expect or else it's a bad egg
00162     if(pObject->info.version != JOE_VERSION)
00163     {
00164         // Display an error message for bad file format, then stop loading
00165         sprintf(strMessage, "Invalid file format (Version is %d not %d): %s!", pObject->info.version, JOE_VERSION, modelpath.c_str());
00166                 loadedfile = false;
00167         cerr << strMessage << endl;
00168                 delete [] pObject;
00169                 pObject = NULL;
00170                 return false;
00171     }
00172         
00173         if (pObject->info.num_faces > 32000)
00174         {
00175                 cout << modelpath << " has " << pObject->info.num_faces << " faces (max 32768), crashing or other problems may occur." << endl;
00176         }
00177         
00178         loadedfile = true;
00179 
00180         //cout << pObject->info.version << "," << pObject->info.num_faces << endl;
00181         
00182     // Read in the model and animation data
00183         ReadData(m_FilePointer, pack);
00184 
00185         //optimize frame zero into a static display list
00186         static_list = glGenLists(1);
00187         glNewList (static_list, GL_COMPILE);
00188         Draw(0,0,0);
00189         glEndList ();
00190         
00191     // Return a success
00192     return true;
00193 }
00194 
00195 void JOEMODEL::ReadData(FILE *m_FilePointer, JOEPACK * pack)
00196 {
00197         int num_frames = pObject->info.num_frames;
00198         int num_faces = pObject->info.num_faces;
00199         
00200         pObject->frames = new JOEFrame [num_frames];
00201         
00202         int i;
00203         for (i = 0; i < num_frames; i++)
00204         //for (i = 0; i < 1; i++)
00205         {
00206                 pObject->frames[i].faces = new JOEFace [num_faces];
00207                 
00208                 BinaryRead(pObject->frames[i].faces, sizeof(JOEFace), num_faces, m_FilePointer, pack);
00209                 CorrectEndian(pObject->frames[i].faces, num_faces);
00210                 
00211                 BinaryRead(&pObject->frames[i].num_verts, sizeof(int), 1, m_FilePointer, pack);
00212                 pObject->frames[i].num_verts = ENDIAN_SWAP_32(pObject->frames[i].num_verts);
00213                 BinaryRead(&pObject->frames[i].num_texcoords, sizeof(int), 1, m_FilePointer, pack);
00214                 pObject->frames[i].num_texcoords = ENDIAN_SWAP_32(pObject->frames[i].num_texcoords);
00215                 BinaryRead(&pObject->frames[i].num_normals, sizeof(int), 1, m_FilePointer, pack);
00216                 pObject->frames[i].num_normals = ENDIAN_SWAP_32(pObject->frames[i].num_normals);
00217                 //cout << pObject->frames[i].num_verts << "," << pObject->frames[i].num_texcoords << "," << pObject->frames[i].num_normals << endl;
00218                 
00219                 pObject->frames[i].verts = new JOEVertex [pObject->frames[i].num_verts];
00220                 pObject->frames[i].normals = new JOEVertex [pObject->frames[i].num_normals];
00221                 pObject->frames[i].texcoords = new JOETexCoord [pObject->frames[i].num_texcoords];
00222                 
00223                 BinaryRead(pObject->frames[i].verts, sizeof(JOEVertex), pObject->frames[i].num_verts, m_FilePointer, pack);
00224                 CorrectEndian(pObject->frames[i].verts, pObject->frames[i].num_verts);
00225                 BinaryRead(pObject->frames[i].normals, sizeof(JOEVertex), pObject->frames[i].num_normals, m_FilePointer, pack);
00226                 CorrectEndian(pObject->frames[i].normals, pObject->frames[i].num_normals);
00227                 BinaryRead(pObject->frames[i].texcoords, sizeof(JOETexCoord), pObject->frames[i].num_texcoords, m_FilePointer, pack);
00228                 CorrectEndian(pObject->frames[i].texcoords, pObject->frames[i].num_texcoords);
00229                 
00230                 //cout << pObject->frames[i].texcoords[0].u << "," << pObject->frames[i].texcoords[0].v << endl;
00231         }
00232         
00233         float maxv[3];
00234         float minv[3];
00235         bool havevals[6];
00236         int n = 0;
00237         for (n = 0; n < 6; n++)
00238                 havevals[n] = false;
00239         
00240         //go do scaling and flip axes
00241         for (i = 0; i < num_frames; i++)
00242         {
00243                 int v;
00244                 
00245                 for (v = 0; v < pObject->frames[i].num_verts; v++)
00246                 {
00247                         VERTEX temp;
00248                         
00249                         temp.Set(pObject->frames[i].verts[v].vertex);
00250                         temp.Scale(MODEL_SCALE);
00251                         
00252                         //cache for bbox stuff
00253                         for (n = 0; n < 3; n++)
00254                         {
00255                                 if (temp.v3()[n] > maxv[n] || !havevals[n])
00256                                 {
00257                                         maxv[n] = temp.v3()[n];
00258                                         havevals[n] = true;
00259                                 }
00260                                 if (temp.v3()[n] < minv[n] || !havevals[n+3])
00261                                 {
00262                                         minv[n] = temp.v3()[n];
00263                                         havevals[n+3] = true;
00264                                 }
00265                         }
00266                         
00267                         float r = temp.len();
00268                         float rxz = sqrt(temp.x*temp.x+temp.z*temp.z);
00269                         if (r > radius)
00270                                 radius = r;
00271                         if (rxz > radiusxz)
00272                                 radiusxz = rxz;
00273                         pObject->frames[i].verts[v].vertex[0] = temp.y;
00274                         pObject->frames[i].verts[v].vertex[1] = temp.z;
00275                         pObject->frames[i].verts[v].vertex[2] = -temp.x;
00276                 }
00277         }
00278         
00279         //make sure vertex ordering is consistent with normals
00280         for (i = 0; i < pObject->info.num_faces; i++)
00281         {
00282                 short vi[3];
00283                 VERTEX tri[3];
00284                 VERTEX norms[3];
00285                 for (unsigned int v = 0; v < 3; v++)
00286                 {
00287                         vi[v] = GetFace(i)[v];
00288                         tri[v].Set(GetVert(vi[v]));
00289                         norms[v].Set(GetNorm(GetNormIdx(i)[v]));
00290                 }
00291                 VERTEX norm;
00292                 for (unsigned int v = 0; v < 3; v++)
00293                         norm = norm + norms[v];
00294                 norm = norm.normalize();
00295                 VERTEX tnorm = (tri[2] - tri[0]).cross(tri[1] - tri[0]);
00296                 if (norm.dot(tnorm) > 0)
00297                 {
00298                         /*short tvi = pObject->frames[0].faces[i].vertexIndex[1];
00299                         pObject->frames[0].faces[i].vertexIndex[1] = pObject->frames[0].faces[i].vertexIndex[2];
00300                         pObject->frames[0].faces[i].vertexIndex[2] = tvi;
00301                         
00302                         tvi = pObject->frames[0].faces[i].normalIndex[1];
00303                         pObject->frames[0].faces[i].normalIndex[1] = pObject->frames[0].faces[i].normalIndex[2];
00304                         pObject->frames[0].faces[i].normalIndex[2] = tvi;
00305                         
00306                         tvi = pObject->frames[0].faces[i].textureIndex[1];
00307                         pObject->frames[0].faces[i].textureIndex[1] = pObject->frames[0].faces[i].textureIndex[2];
00308                         pObject->frames[0].faces[i].textureIndex[2] = tvi;*/
00309                         
00310                         /*short tvi = vi[1];
00311                         vi[1] = vi[2];
00312                         vi[2] = tvi;*/
00313                 }
00314         }
00315         
00316         VERTEX minvals, maxvals;
00317         minvals.Set(minv);
00318         maxvals.Set(maxv);
00319         bbox.SetFromCorners(minvals, maxvals);
00320         
00321         VERTEX center;
00322         center = bbox.GetCenter();
00323         radius = (minvals - center).len();
00324         VERTEX mvnoy;
00325         mvnoy = minvals;
00326         mvnoy.y = 0;
00327         center.y = 0;
00328         radiusxz = (mvnoy - center).len();
00329         
00330     //cout << m_Header.numTriangles << endl;
00331     //cout << m_Header.numFrames << endl;
00332     
00333     // Here we allocate all of our memory from the header's information
00334     /*m_pSkins     = new tMd2Skin [m_Header.numSkins];
00335     m_pTexCoords = new tMd2TexCoord [m_Header.numTexCoords];
00336     m_pTriangles = new tMd2Face [m_Header.numTriangles];
00337     m_pFrames    = new tMd2Frame [m_Header.numFrames];
00338 
00339     // Next, we start reading in the data by seeking to our skin names offset
00340     fseek(m_FilePointer, m_Header.offsetSkins, SEEK_SET);
00341     
00342     // Depending on the skin count, we read in each skin for this model
00343     fread(m_pSkins, sizeof(tMd2Skin), m_Header.numSkins, m_FilePointer);
00344     
00345     // Move the file pointer to the position in the file for texture coordinates
00346     fseek(m_FilePointer, m_Header.offsetTexCoords, SEEK_SET);
00347     
00348     // Read in all the texture coordinates in one fell swoop
00349     fread(m_pTexCoords, sizeof(tMd2TexCoord), m_Header.numTexCoords, m_FilePointer);
00350 
00351     // Move the file pointer to the triangles/face data offset
00352     fseek(m_FilePointer, m_Header.offsetTriangles, SEEK_SET);
00353     
00354     // Read in the face data for each triangle (vertex and texCoord indices)
00355     fread(m_pTriangles, sizeof(tMd2Face), m_Header.numTriangles, m_FilePointer);
00356             
00357     // Move the file pointer to the vertices (frames)
00358     fseek(m_FilePointer, m_Header.offsetFrames, SEEK_SET);
00359 
00361 
00362     // In the last tutorial we just read in one frame of animation here.  Now we are going
00363     // to extract every key frame from the .MD2 model.  These key frames will be used to
00364     // interpolate between each other to form the somewhat smooth animation.
00365     // The only thing different is that we are putting a for loop in front, then changing
00366     // the '0' for the m_pFrames[0] in the last tutorial, to a 'i'.  The loop will
00367     // continue until 'i' has reached the number of key frames for this model.
00368 
00369         int i;
00370     for (i=0; i < m_Header.numFrames; i++)
00371     {
00372         // Assign our alias frame to our buffer memory
00373         tMd2AliasFrame *pFrame = (tMd2AliasFrame *) buffer;
00374 
00375         // Allocate the memory for the first frame of animation's vertices
00376         m_pFrames[i].pVertices = new tMd2Triangle [m_Header.numVertices];
00377 
00378                 //cout << "about to read raw data" << endl;
00379                 
00380         // Read in the first frame of animation
00381         int numread = fread(pFrame, m_Header.frameSize, 1, m_FilePointer);
00382                 
00383                 //cout << "read raw data: " << m_Header.frameSize << "," << numread << endl;
00384 
00385         // Copy the name of the animation to our frames array
00386         strcpy(m_pFrames[i].strName, pFrame->name);
00387             
00388         // Store off a vertex array pointer to cut down large lines of code
00389         tMd2Triangle *pVertices = m_pFrames[i].pVertices;
00390                 
00391                 //cout << "reading verts: " << m_Header.numVertices << endl;
00392                 
00393                 int j;
00394 
00395         // Go through all of the number of vertices and assign the scale and translations.
00396         // Store the vertices in our current frame's vertex list array, while swapping Y and Z.
00397         // Notice we also negate the Z axis as well to make the swap correctly.
00398         for (j=0; j < m_Header.numVertices; j++)
00399         {
00400                         //cout << "verts" << endl;
00401                         float temp = pFrame->aliasVertices[j].vertex[0];
00402                         //cout << "read temp: " << temp << endl;
00403                         pVertices[j].vertex[0] = temp;
00404                         //cout << "assigned temp" << endl;
00405             pVertices[j].vertex[2] = (pFrame->aliasVertices[j].vertex[1]);
00406             pVertices[j].vertex[1] = pFrame->aliasVertices[j].vertex[2];
00407                         //cout << "norms" << endl;
00408                         pVertices[j].normal[0] = pFrame->aliasVertices[j].normal[0];
00409             pVertices[j].normal[2] = (pFrame->aliasVertices[j].normal[1]);
00410             pVertices[j].normal[1] = pFrame->aliasVertices[j].normal[2];
00411                         
00412                         //cout << pVertices[j].vertex[0] << "," << pVertices[j].vertex[1] << "," << pVertices[j].vertex[2] << endl;
00413         }
00414                 //cout << "finished reading verts" << endl;
00415     }
00416         */
00417         //cout << "done" << endl;
00418 }
00419 
00420 void JOEMODEL::CleanUp(FILE *m_FilePointer, JOEPACK * pack)
00421 {
00422     // This just just the regular cleanup or our md2 model class.  We can free
00423     // all of this data because we already have it stored in our own structures.
00424 
00425         if (pack == NULL)
00426         fclose(m_FilePointer);                      // Close the current file pointer
00427         else
00428                 pack->Pack_fclose();
00429 }
00430 
00431 extern bool verbose_output;
00432 JOEMODEL::~JOEMODEL()
00433 {
00434         if (verbose_output)
00435                 cout << "joemodel deinit" << endl;
00436         
00437         int i;
00438         
00439         // Free the faces, normals, vertices, and texture coordinates.
00440         /*
00441         delete [] pObject[i].pFaces;
00442         delete [] pObject[i].pNormals;
00443         delete [] pObject[i].pVerts;
00444         delete [] pObject[i].pTexVerts;*/
00445         
00446         if (pObject != NULL)
00447         {       
00448                 for (i = 0; i < pObject->info.num_frames; i++)
00449                 {
00450                         delete [] pObject->frames[i].faces;
00451                         delete [] pObject->frames[i].verts;
00452                         delete [] pObject->frames[i].normals;
00453                         delete [] pObject->frames[i].texcoords;
00454                 }
00455                 
00456                 delete [] pObject->frames;
00457                 
00458                 delete pObject;
00459         }
00460         
00461 //      int i;
00462         
00463         /*glDeleteTextures(1, &texid);
00464         
00465         if (has_illum)
00466                 glDeleteTextures(1, &illum_tex);*/
00467         
00468         for (i = 0; i < MAX_TEXTURE_UNITS; i++)
00469         {
00470                 /*if (texturemode[i] != TEXTUREMODE_NOTEX && autounload[i])
00471                 {
00472                         glDeleteTextures(1, &textureid[i]);
00473                 }*/
00474                 
00475                 textureid[i].Unload();
00476                 
00477                 texturemode[i] = TEXTUREMODE_NOTEX;
00478         }
00479         
00480         glDeleteLists(static_list, 1);
00481 }
00482 
00488 
00489 void JOEMODEL::Draw(int currentFrame, float t)
00490 {
00491         Draw(currentFrame, currentFrame+1, t);
00492 }
00493 
00494 void JOEMODEL::NewDraw(int currentFrame, float t, VERTEX lightdir, QUATERNION rotation, int pass)
00495 {
00496         NewDraw(currentFrame, currentFrame+1, t, lightdir, rotation, pass);
00497 }
00498 
00499 void JOEMODEL::Draw(int currentFrame, int nextframe, float t)
00500 {
00501         utility.SelectTU(0);
00502         glEnable(GL_TEXTURE_2D);
00503         
00504         int num_frames = pObject->info.num_frames;
00505         int num_faces = pObject->info.num_faces;
00506         JOEFrame * pFrame, * pNextFrame;
00507         
00508         if (currentFrame >= num_frames)
00509         {
00510                 currentFrame = num_frames-1;
00511         }
00512         
00513         if (nextframe >= num_frames)
00514                 nextframe = num_frames-1;
00515         
00516         //cout << currentFrame << "," << nextframe << endl;
00517         
00518         pFrame = &pObject->frames[currentFrame];
00519         pNextFrame = &pObject->frames[nextframe];
00520         
00521         // Start rendering triangles
00522     glBegin(GL_TRIANGLES);
00523 
00524         // Go through all of the faces (polygons) of the current frame and draw them
00525         for(int j = 0; j < num_faces; j++)
00526         {
00527                 
00528                         //calculate normals for flat shading
00529                         VERTEX a, b, c;
00530                         a.Set(pFrame->verts[pFrame->faces[j].vertexIndex[0]].vertex);
00531                         b.Set(pFrame->verts[pFrame->faces[j].vertexIndex[1]].vertex);
00532                         c.Set(pFrame->verts[pFrame->faces[j].vertexIndex[2]].vertex);
00533                         
00534                         float v0[3], v1[3], v2[3];
00535                         v0[0] = a.x; v0[1] = a.y; v0[2] = a.z;
00536                         v1[0] = b.x; v1[1] = b.y; v1[2] = b.z;
00537                         v2[0] = c.x; v2[1] = c.y; v2[2] = c.z;
00538                         
00539                         float vb[3], va[3];
00540                         int i;
00541                         for (i = 0; i < 3; i++)
00542                         {
00543                                 va[i] = v0[i]-v1[i];    
00544                                 vb[i] = v2[i]-v1[i];
00545                         }
00546                         float norm[3];
00547                         norm[0] = va[1]*vb[2]-vb[1]*va[2];
00548                         norm[1] = va[2]*vb[0]-vb[2]*va[0];
00549                         norm[2] = va[0]*vb[1]-vb[0]*va[1];
00550                         float normmag = sqrt(norm[0]*norm[0]+norm[1]*norm[1]+norm[2]*norm[2]);
00551                         for (i = 0; i < 3; i++)
00552                         {
00553                                 norm[i]=norm[i]/normmag;
00554                         }
00555                         
00556                         //glNormal3fv(norm);
00557                         
00558                         
00559             // Go through each corner of the triangle and draw it.
00560             for(int whichVertex = 0; whichVertex < 3; whichVertex++)
00561             {
00562                                 
00563                 // Get the index for each point of the face
00564                 int vertIndex = pFrame->faces[j].vertexIndex[whichVertex];
00565                                 int nextvertIndex = pNextFrame->faces[j].vertexIndex[whichVertex];
00566 
00567                 // Get the index for each texture coordinate for this face
00568                 int texIndex  = pFrame->faces[j].textureIndex[whichVertex];                             
00569                                 
00570                                 int normIndex = pFrame->faces[j].normalIndex[whichVertex];
00571                                 int nextnormIndex = pNextFrame->faces[j].normalIndex[whichVertex];
00572                                                      
00573                                 // Pass in the texture coordinate for this vertex
00574                                 //glTexCoord2f(pFrame->texcoords[ texIndex ].u, pFrame->texcoords[ texIndex ].v);
00575                                 utility.TexCoord2d2f(0, pFrame->texcoords[ texIndex ].u, pFrame->texcoords[ texIndex ].v);
00576                                 utility.TexCoord2d2f(1, pFrame->texcoords[ texIndex ].u, pFrame->texcoords[ texIndex ].v);
00577                                 utility.TexCoord2d2f(2, pFrame->texcoords[ texIndex ].u, pFrame->texcoords[ texIndex ].v);
00578                                 utility.TexCoord2d2f(3, pFrame->texcoords[ texIndex ].u, pFrame->texcoords[ texIndex ].v);
00579                                 
00580                                 //JGL_2MTEXCOORD(GL_TEXTURE0_ARB, pFrame->texcoords[ texIndex ].u, pFrame->texcoords[ texIndex ].v);
00581                                 //JGL_2MTEXCOORD(GL_TEXTURE1_ARB, pFrame->texcoords[ texIndex ].u, pFrame->texcoords[ texIndex ].v);
00582                                 //JGL_2MTEXCOORD(GL_TEXTURE2_ARB, pFrame->texcoords[ texIndex ].u, pFrame->texcoords[ texIndex ].v);
00583                                 //JGL_2MTEXCOORD(GL_TEXTURE3_ARB, pFrame->texcoords[ texIndex ].u, pFrame->texcoords[ texIndex ].v);
00584 
00585                 // Now we get to the interpolation part! (*Bites his nails*)
00586                 // Below, we first store the vertex we are working on for the current
00587                 // frame and the frame we are interpolating too.  Next, we use the
00588                 // linear interpolation equation to smoothly transition from one
00589                 // key frame to the next.
00590                 
00591                                 VERTEX vPoint1, vPoint2;
00592                                 vPoint1.Set(pFrame->normals[ normIndex ].vertex);
00593                 vPoint2.Set(pNextFrame->normals[ nextnormIndex ].vertex);
00594                                 vPoint1 = vPoint1.normalize();
00595                                 vPoint2 = vPoint2.normalize();
00596                                 //glNormal3f(vPoint1.x + t * (vPoint2.x - vPoint1.x), // Find the interpolated X
00597                 //           vPoint1.y + t * (vPoint2.y - vPoint1.y), // Find the interpolated Y
00598                 //           vPoint1.z + t * (vPoint2.z - vPoint1.z));// Find the interpolated Z
00599                         
00600                                 VERTEX n;
00601                                 n.x = vPoint1.x + t * (vPoint2.x - vPoint1.x);
00602                                 n.y = vPoint1.y + t * (vPoint2.y - vPoint1.y);
00603                                 n.z = vPoint1.z + t * (vPoint2.z - vPoint1.z);
00604                                 
00605                                 //n.Set(norm[0], norm[1], norm[2]);
00606                                 n = n.normalize();
00607                                 //n = rotation.RotateVec(n);
00608                                 
00609                                 //if (pass == 1)
00610                                 /*if (1)
00611                                         TexCoordFromNormal(n, lightdir);
00612                                 else
00613                                 {
00614                                         if (pass == 1)
00615                                                 ColorFromNormal(n, lightdir);
00616                                         else
00617                                                 TexCoordFromNormal(n, lightdir);
00618                                 }*/
00619 
00620                                 /*QUATERNION goofyfoot;
00621                                 goofyfoot.Rotate(-3.141593/2.0, 1,0,0);
00622                                 n = goofyfoot.ReturnConjugate().RotateVec(n);*/
00623                                 //glNormal3fv(n.v3());
00624                                 glNormal3f(n.y,-n.x,n.z);
00625                                 
00626                                 //if (pass == 2)
00627                                 
00628                                 
00629                 // Store the current and next frame's vertex
00630                 vPoint1.Set(pFrame->verts[ vertIndex ].vertex);
00631                 vPoint2.Set(pNextFrame->verts[ nextvertIndex ].vertex);
00632                                 
00633                                 //CVector3 vNorm1 = pFrame->pNormals[ vertIndex ];
00634                 //CVector3 vNorm2 = pNextFrame->pNormals[ vertIndex ];
00635                                 
00636                                 //glNormal3f(vNorm1.x + t * (vNorm2.x - vNorm1.x), // Find the interpolated X
00637                 //           vNorm1.y + t * (vNorm2.y - vNorm1.y), // Find the interpolated Y
00638                 //           vNorm1.z + t * (vNorm2.z - vNorm1.z));// Find the interpolated Z
00639 
00640                                 //cout << vNorm1.x << "," << vNorm1.y << "," << vNorm1.z << endl;
00641 
00642                                 //glNormal3f(pFirstFrame->pNormals[vertIndex].x,pFirstFrame->pNormals[vertIndex].y,pFirstFrame->pNormals[vertIndex].z);
00643                                 
00644                 // By using the equation: p(t) = p0 + t(p1 - p0), with a time t
00645                 // passed in, we create a new vertex that is closer to the next key frame.
00646                                 VERTEX finv;
00647                                 finv.x = vPoint1.x + t * (vPoint2.x - vPoint1.x);
00648                                 finv.y = vPoint1.y + t * (vPoint2.y - vPoint1.y);
00649                                 finv.z = vPoint1.z + t * (vPoint2.z - vPoint1.z);
00650                                 
00651                                 //tree shadows
00652                                 //utility.TexCoord2d2f(3, (finv.x-terrain.GetOffset().x)/terrain.GetSize().x, (finv.y-terrain.GetOffset().z)/terrain.GetSize().z);
00653                                 //utility.TexCoord2d2f(3, pFrame->texcoords[ texIndex ].u, pFrame->texcoords[ texIndex ].v);
00654                 glVertex3f(finv.x, finv.z, finv.y); //required for compatibility with goofy vamos z=up
00655                                                    
00656                                 
00657             }
00658         }
00659 
00660     // Stop rendering the triangles
00661     glEnd();
00662 }
00663 
00664 void JOEMODEL::NewDraw(int currentFrame, int nextframe, float t, VERTEX lightdir, QUATERNION rotation, int pass)
00665 {
00666 /*      int num_frames = pObject->info.num_frames;
00667         int num_faces = pObject->info.num_faces;
00668         JOEFrame * pFrame, * pNextFrame;
00669         
00670         if (currentFrame >= num_frames)
00671         {
00672                 currentFrame = num_frames-1;
00673         }
00674         
00675         if (nextframe >= num_frames)
00676                 nextframe = num_frames-1;
00677         
00678         //cout << currentFrame << "," << nextframe << endl;
00679         
00680         pFrame = &pObject->frames[currentFrame];
00681         pNextFrame = &pObject->frames[nextframe];
00682         
00683         // Start rendering triangles
00684     glBegin(GL_TRIANGLES);
00685 
00686         // Go through all of the faces (polygons) of the current frame and draw them
00687         for(int j = 0; j < num_faces; j++)
00688         {
00689                 
00690                         //calculate normals for flat shading
00691                         VERTEX a, b, c;
00692                         a.Set(pFrame->verts[pFrame->faces[j].vertexIndex[0]].vertex);
00693                         b.Set(pFrame->verts[pFrame->faces[j].vertexIndex[1]].vertex);
00694                         c.Set(pFrame->verts[pFrame->faces[j].vertexIndex[2]].vertex);
00695                         
00696                         float v0[3], v1[3], v2[3];
00697                         v0[0] = a.x; v0[1] = a.y; v0[2] = a.z;
00698                         v1[0] = b.x; v1[1] = b.y; v1[2] = b.z;
00699                         v2[0] = c.x; v2[1] = c.y; v2[2] = c.z;
00700                         
00701                         float vb[3], va[3];
00702                         int i;
00703                         for (i = 0; i < 3; i++)
00704                         {
00705                                 va[i] = v0[i]-v1[i];    
00706                                 vb[i] = v2[i]-v1[i];
00707                         }
00708                         float norm[3];
00709                         norm[0] = va[1]*vb[2]-vb[1]*va[2];
00710                         norm[1] = va[2]*vb[0]-vb[2]*va[0];
00711                         norm[2] = va[0]*vb[1]-vb[0]*va[1];
00712                         float normmag = sqrt(norm[0]*norm[0]+norm[1]*norm[1]+norm[2]*norm[2]);
00713                         for (i = 0; i < 3; i++)
00714                         {
00715                                 norm[i]=norm[i]/normmag;
00716                         }
00717                         
00718                         //glNormal3fv(norm);
00719                         
00720                         
00721             // Go through each corner of the triangle and draw it.
00722             for(int whichVertex = 0; whichVertex < 3; whichVertex++)
00723             {
00724                                 
00725                 // Get the index for each point of the face
00726                 int vertIndex = pFrame->faces[j].vertexIndex[whichVertex];
00727                                 int nextvertIndex = pNextFrame->faces[j].vertexIndex[whichVertex];
00728 
00729                 // Get the index for each texture coordinate for this face
00730                 int texIndex  = pFrame->faces[j].textureIndex[whichVertex];                             
00731                                 
00732                                 int normIndex = pFrame->faces[j].normalIndex[whichVertex];
00733                                 int nextnormIndex = pNextFrame->faces[j].normalIndex[whichVertex];
00734                                                      
00735                                 // Pass in the texture coordinate for this vertex
00736                                 //glTexCoord2f(pFrame->texcoords[ texIndex ].u, pFrame->texcoords[ texIndex ].v);
00737                                 
00738                                 JGL_2MTEXCOORD(GL_TEXTURE0_ARB, pFrame->texcoords[ texIndex ].u, pFrame->texcoords[ texIndex ].v);
00739                                 JGL_2MTEXCOORD(GL_TEXTURE1_ARB, pFrame->texcoords[ texIndex ].u, pFrame->texcoords[ texIndex ].v);
00740                                 JGL_2MTEXCOORD(GL_TEXTURE2_ARB, pFrame->texcoords[ texIndex ].u, pFrame->texcoords[ texIndex ].v);
00741                                 JGL_2MTEXCOORD(GL_TEXTURE3_ARB, pFrame->texcoords[ texIndex ].u, pFrame->texcoords[ texIndex ].v);
00742 
00743                 // Now we get to the interpolation part! (*Bites his nails*)
00744                 // Below, we first store the vertex we are working on for the current
00745                 // frame and the frame we are interpolating too.  Next, we use the
00746                 // linear interpolation equation to smoothly transition from one
00747                 // key frame to the next.
00748                 
00749                                 VERTEX vPoint1, vPoint2;
00750                                 vPoint1.Set(pFrame->normals[ normIndex ].vertex);
00751                 vPoint2.Set(pNextFrame->normals[ nextnormIndex ].vertex);
00752                                 vPoint1 = vPoint1.normalize();
00753                                 vPoint2 = vPoint2.normalize();
00754                                 //glNormal3f(vPoint1.x + t * (vPoint2.x - vPoint1.x), // Find the interpolated X
00755                 //           vPoint1.y + t * (vPoint2.y - vPoint1.y), // Find the interpolated Y
00756                 //           vPoint1.z + t * (vPoint2.z - vPoint1.z));// Find the interpolated Z
00757                         
00758                                 VERTEX n;
00759                                 n.x = vPoint1.x + t * (vPoint2.x - vPoint1.x);
00760                                 n.y = vPoint1.y + t * (vPoint2.y - vPoint1.y);
00761                                 n.z = vPoint1.z + t * (vPoint2.z - vPoint1.z);
00762                                 
00763                                 //n.Set(norm[0], norm[1], norm[2]);
00764                                 n = n.normalize();
00765                                 n = rotation.RotateVec(n);
00766                                 
00767                                 //if (pass == 1)
00768                                 if (1)
00769                                         TexCoordFromNormal(n, lightdir);
00770                                 else
00771                                 {
00772                                         if (pass == 1)
00773                                                 ColorFromNormal(n, lightdir);
00774                                         else
00775                                                 TexCoordFromNormal(n, lightdir);
00776                                 }
00777                                 
00778                                 //glNormal3fv(n.v3());
00779                                 
00780                                 //if (pass == 2)
00781                                 
00782                                 
00783                 // Store the current and next frame's vertex
00784                 vPoint1.Set(pFrame->verts[ vertIndex ].vertex);
00785                 vPoint2.Set(pNextFrame->verts[ nextvertIndex ].vertex);
00786                                 
00787                                 //CVector3 vNorm1 = pFrame->pNormals[ vertIndex ];
00788                 //CVector3 vNorm2 = pNextFrame->pNormals[ vertIndex ];
00789                                 
00790                                 //glNormal3f(vNorm1.x + t * (vNorm2.x - vNorm1.x), // Find the interpolated X
00791                 //           vNorm1.y + t * (vNorm2.y - vNorm1.y), // Find the interpolated Y
00792                 //           vNorm1.z + t * (vNorm2.z - vNorm1.z));// Find the interpolated Z
00793 
00794                                 //cout << vNorm1.x << "," << vNorm1.y << "," << vNorm1.z << endl;
00795 
00796                                 //glNormal3f(pFirstFrame->pNormals[vertIndex].x,pFirstFrame->pNormals[vertIndex].y,pFirstFrame->pNormals[vertIndex].z);
00797                                 
00798                 // By using the equation: p(t) = p0 + t(p1 - p0), with a time t
00799                 // passed in, we create a new vertex that is closer to the next key frame.
00800                 glVertex3f(vPoint1.x + t * (vPoint2.x - vPoint1.x), // Find the interpolated X
00801                            vPoint1.y + t * (vPoint2.y - vPoint1.y), // Find the interpolated Y
00802                            vPoint1.z + t * (vPoint2.z - vPoint1.z));// Find the interpolated Z
00803                                                    
00804                                 
00805             }
00806         }
00807 
00808     // Stop rendering the triangles
00809     glEnd();
00810         */
00811         /*
00812     // Now comes the juice of our tutorial.  Fear not, this is actually very intuitive
00813     // if you drool over it for a while (stay away from the keyboard though...).
00814     // What's going on here is, we are getting our current animation that we are
00815     // on, finding the current frame of that animation that we are on, then interpolating
00816     // between that frame and the next frame.  To make a smooth constant animation when
00817     // we get to the end frame, we interpolate between the last frame of the animation 
00818     // and the first frame of the animation.  That way, if we are doing the running 
00819     // animation let's say, when the last frame of the running animation is hit, we don't
00820     // have a huge jerk when going back to the first frame of that animation.  Remember,
00821     // because we have the texture and face information stored in the first frame of our
00822     // animation, we need to reference back to this frame every time when drawing the
00823     // model.  The only thing the other frames store is the vertices, but no information
00824     // about them.
00825     
00826     // Make sure we have valid objects just in case. (size() is in the vector class)
00827     if(pObject.size() <= 0) return;
00828 
00829     // Here we grab the current animation that we are on from our model's animation list
00830     //tAnimationInfo *pAnim = &(pAnimations[0]);
00831 
00832     // This gives us the current frame we are on.  We mod the current frame plus
00833     // 1 by the current animations end frame to make sure the next frame is valid.
00834     // If the next frame is past our end frame, then we go back to zero.  We check this next.
00835     //int nextFrame = (currentFrame + 1) % pAnim->endFrame;
00836         int nextFrame = nextframe;
00837 
00838         //cout << currentFrame << "," << nextFrame << endl;
00839         
00840     // If the next frame is zero, that means that we need to start the animation over.
00841     // To do this, we set nextFrame to the starting frame of this animation.
00842     //if(nextFrame == 0) 
00843     //    nextFrame =  pAnim->startFrame;
00844 
00845     // Get the current key frame we are on
00846     t3DObject *pFrame =      &pObject[currentFrame];
00847 
00848     // Get the next key frame we are interpolating too
00849     t3DObject *pNextFrame =  &pObject[nextFrame];
00850 
00851     // Get the first key frame so we have an address to the texture and face information
00852     t3DObject *pFirstFrame = &pObject[0];
00853 
00854     // Next, we want to get the current time that we are interpolating by.  Remember,
00855     // if t = 0 then we are at the beginning of the animation, where if t = 1 we are at the end.
00856     // Anyhing from 0 to 1 can be thought of as a percentage from 0 to 100 percent complete.
00857     //float t = ReturnCurrentTime(pModel, nextFrame);
00858 
00859     // Start rendering lines or triangles, depending on our current rendering mode (Lft Mouse Btn)
00860     glBegin(GL_TRIANGLES);
00861 
00862         // Go through all of the faces (polygons) of the current frame and draw them
00863         for(int j = 0; j < pFrame->numOfFaces; j++)
00864         {
00865                         //calculate normals for flat shading
00866                         CVector3 a = pFrame->pVerts[pFirstFrame->pFaces[j].vertIndex[0]];
00867                         CVector3 b = pFrame->pVerts[pFirstFrame->pFaces[j].vertIndex[1]];
00868                         CVector3 c = pFrame->pVerts[pFirstFrame->pFaces[j].vertIndex[2]];
00869                         
00870                         float v0[3], v1[3], v2[3];
00871                         v0[0] = a.x; v0[1] = a.y; v0[2] = a.z;
00872                         v1[0] = b.x; v1[1] = b.y; v1[2] = b.z;
00873                         v2[0] = c.x; v2[1] = c.y; v2[2] = c.z;
00874                         
00875                         float vb[3], va[3];
00876                         int i;
00877                         for (i = 0; i < 3; i++)
00878                         {
00879                                 va[i] = v0[i]-v1[i];    
00880                                 vb[i] = v2[i]-v1[i];
00881                         }
00882                         float norm[3];
00883                         norm[0] = va[1]*vb[2]-vb[1]*va[2];
00884                         norm[1] = va[2]*vb[0]-vb[2]*va[0];
00885                         norm[2] = va[0]*vb[1]-vb[0]*va[1];
00886                         float normmag = sqrt(norm[0]*norm[0]+norm[1]*norm[1]+norm[2]*norm[2]);
00887                         for (i = 0; i < 3; i++)
00888                         {
00889                                 norm[i]=norm[i]/normmag;
00890                         }
00891                         
00892                         //glNormal3fv(norm);
00893                         
00894                         
00895             // Go through each corner of the triangle and draw it.
00896             for(int whichVertex = 0; whichVertex < 3; whichVertex++)
00897             {
00898                 // Get the index for each point of the face
00899                 int vertIndex = pFirstFrame->pFaces[j].vertIndex[whichVertex];
00900 
00901                 // Get the index for each texture coordinate for this face
00902                 int texIndex  = pFirstFrame->pFaces[j].coordIndex[whichVertex];
00903                                 
00904                                 //int normIndex = pFirstFrame->pFaces[j].normalIndex[whichVertex];
00905                         
00906                 // Make sure there was a UVW map applied to the object.  Notice that
00907                 // we use the first frame to check if we have texture coordinates because
00908                 // none of the other frames hold this information, just the first by design.
00909                 if(pFirstFrame->pTexVerts) 
00910                 {
00911                     // Pass in the texture coordinate for this vertex
00912                     //glTexCoord2f(pFirstFrame->pTexVerts[ texIndex ].x, pFirstFrame->pTexVerts[ texIndex ].y);
00913                                         
00914                                         JGL_2MTEXCOORD(GL_TEXTURE0_ARB, pFirstFrame->pTexVerts[ texIndex ].x, pFirstFrame->pTexVerts[ texIndex ].y);
00915                                         JGL_2MTEXCOORD(GL_TEXTURE1_ARB, pFirstFrame->pTexVerts[ texIndex ].x, pFirstFrame->pTexVerts[ texIndex ].y);
00916                                         JGL_2MTEXCOORD(GL_TEXTURE2_ARB, pFirstFrame->pTexVerts[ texIndex ].x, pFirstFrame->pTexVerts[ texIndex ].y);
00917                                         JGL_2MTEXCOORD(GL_TEXTURE3_ARB, pFirstFrame->pTexVerts[ texIndex ].x, pFirstFrame->pTexVerts[ texIndex ].y);
00918                 }
00919 
00920                 // Now we get to the interpolation part! (*Bites his nails*)
00921                 // Below, we first store the vertex we are working on for the current
00922                 // frame and the frame we are interpolating too.  Next, we use the
00923                 // linear interpolation equation to smoothly transition from one
00924                 // key frame to the next.
00925                 
00926                                 CVector3 vPoint1 = pFrame->pNormals[ vertIndex ];
00927                 CVector3 vPoint2 = pNextFrame->pNormals[ vertIndex ];
00928                                 vPoint1.normalize();
00929                                 vPoint2.normalize();
00930                                 //glNormal3f(vPoint1.x + t * (vPoint2.x - vPoint1.x), // Find the interpolated X
00931                 //           vPoint1.y + t * (vPoint2.y - vPoint1.y), // Find the interpolated Y
00932                 //           vPoint1.z + t * (vPoint2.z - vPoint1.z));// Find the interpolated Z
00933                                 
00934                                 VERTEX n;
00935                                 n.x = vPoint1.x + t * (vPoint2.x - vPoint1.x);
00936                                 n.y = vPoint1.y + t * (vPoint2.y - vPoint1.y);
00937                                 n.z = vPoint1.z + t * (vPoint2.z - vPoint1.z);
00938                                 
00939                                 //n.Set(norm[0], norm[1], norm[2]);
00940                                 n = n.normalize();
00941                                 n = rotation.RotateVec(n);
00942                                 
00943                                 ColorFromNormal(n, lightdir);
00944                                 
00945                 // Store the current and next frame's vertex
00946                 vPoint1 = pFrame->pVerts[ vertIndex ];
00947                 vPoint2 = pNextFrame->pVerts[ vertIndex ];
00948 */                              
00949                                 /*CVector3 vNorm1 = pFrame->pNormals[ vertIndex ];
00950                 CVector3 vNorm2 = pNextFrame->pNormals[ vertIndex ];
00951                                 
00952                                 glNormal3f(vNorm1.x + t * (vNorm2.x - vNorm1.x), // Find the interpolated X
00953                            vNorm1.y + t * (vNorm2.y - vNorm1.y), // Find the interpolated Y
00954                            vNorm1.z + t * (vNorm2.z - vNorm1.z));// Find the interpolated Z
00955 
00956                                 cout << vNorm1.x << "," << vNorm1.y << "," << vNorm1.z << endl;*/
00957 /*                              
00958                                 //glNormal3f(pFirstFrame->pNormals[vertIndex].x,pFirstFrame->pNormals[vertIndex].y,pFirstFrame->pNormals[vertIndex].z);
00959                                 
00960                 // By using the equation: p(t) = p0 + t(p1 - p0), with a time t
00961                 // passed in, we create a new vertex that is closer to the next key frame.
00962                 glVertex3f(vPoint1.x + t * (vPoint2.x - vPoint1.x), // Find the interpolated X
00963                            vPoint1.y + t * (vPoint2.y - vPoint1.y), // Find the interpolated Y
00964                            vPoint1.z + t * (vPoint2.z - vPoint1.z));// Find the interpolated Z
00965             }
00966         }
00967 
00968     // Stop rendering the triangles
00969     glEnd();*/
00970 }
00971 
00972 inline void JOEMODEL::ColorFromNormal(VERTEX &norm, VERTEX &ldir)
00973 {
00974 /*      VERTEX lpos;
00975         norm.z = 1.0f;
00976         
00977         lpos = norm.ScaleR(2*ldir.dot(norm))-ldir;
00978         //glColor3fv(lpos.normalize().v3());
00979         
00980         lpos = lpos.normalize();
00981         VERTEX tmp;
00982         tmp.Set(0.5,0.5,0.5);
00983         lpos = lpos.ScaleR(0.5)+tmp;
00984         glColor3fv(lpos.v3());*/
00985 }
00986 
00987 inline void JOEMODEL::TexCoordFromNormal(VERTEX &norm, VERTEX &ldir)
00988 {
00989 /*      VERTEX lpos;
00990         //norm.z = 1.0f;
00991         
00992         //lpos = norm.ScaleR(2*ldir.dot(norm))-ldir;
00993         //R = 2 ( N [dot] V ) V - N
00994         lpos = ldir.ScaleR(2*norm.dot(ldir))-norm;
00995         //R = N - ( 2 * N [dot] V ) V
00996         //lpos = norm - ldir.ScaleR(2*norm.dot(ldir));
00997         //lpos = norm;
00998         
00999         JGL_3MTEXCOORD(GL_TEXTURE0_ARB, lpos.x, lpos.y, lpos.z);*/
01000 }
01001 
01002 void JOEMODEL::DrawStatic() //draw frame 0, optimized for speed
01003 {
01004         int i;
01005         
01006         for (i = 0; i < MAX_TEXTURE_UNITS && i < utility.numTUs(); i++)
01007         {
01008                 utility.SelectTU(i);
01009                 glDisable(GL_TEXTURE_2D);
01010         }
01011         
01012         for (i = 0; i < MAX_TEXTURE_UNITS && i < utility.numTUs(); i++)
01013         {
01014                 if (texturemode[i] != TEXTUREMODE_NOTEX)
01015                 {       
01016                         utility.SelectTU(i);
01017                         //glBindTexture(GL_TEXTURE_2D, textureid[i]);
01018                         textureid[i].Activate();
01019                         if (tuenable[i])
01020                         {
01021                                 glEnable(GL_TEXTURE_2D);
01022                                 
01023                                 //glColor4f(0,1,0,0.5);
01024                                 
01025                                 //default texture environment:  modulate w/ previous.                           
01026                                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
01027                                 
01028                                 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
01029                                 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB,GL_SRC_COLOR);
01030                                 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
01031                                 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB,GL_SRC_COLOR);
01032                                 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
01033                                 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
01034                                 
01035                                 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
01036                                 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB,GL_SRC_ALPHA);
01037                                 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE);
01038                                 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB,GL_SRC_ALPHA);
01039                                 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
01040                                 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
01041                                 
01042                                 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);
01043                                 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);
01044                                 
01045                                 if (texturemode[i] == TEXTUREMODE_ADD)
01046                                 {
01047                                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
01048                                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
01049                                         glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_ARB,GL_SRC_COLOR);
01050                                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
01051                                         glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_ARB,GL_SRC_COLOR);
01052                                         //if (i > 0)
01053                                                 glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB, GL_ADD);
01054