02061d74c2
(as received from Jonas Echterhoff)
996 lines
34 KiB
C++
Executable File
996 lines
34 KiB
C++
Executable File
//models.cpp
|
|
//3d model drawing code
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <OpenGL/gl.h>
|
|
#include <OpenGL/glext.h>
|
|
#include <math.h>
|
|
#include "fileio.h"
|
|
#include "gamemem.h"
|
|
#include "vectors.h"
|
|
#include "entities.h"
|
|
#include "textures.h"
|
|
#include "renderframe.h"
|
|
#include "environment.h"
|
|
#include "transparency.h"
|
|
#include "config.h"
|
|
#include "modeltypes.h"
|
|
#include "models.h"
|
|
#include "stencil.h"
|
|
#include "network.h"
|
|
|
|
//#define __USEDISPLAYLISTS
|
|
#ifndef __TARGET_TOOLAPP
|
|
#define __USEVERTEXARRAYS
|
|
#endif
|
|
|
|
typedef struct{
|
|
void *next;
|
|
tFileRef model;
|
|
} tModelList;
|
|
|
|
tModelList *gModelList=NULL;
|
|
|
|
#define kShadowZoom 0.99
|
|
|
|
//When a model is loaded it won't neccesaryly have the correct
|
|
//file reference IDs for the texture files, as file reference IDs
|
|
//are redefined each time at application startup.
|
|
//this function inserts the correct file reference IDs for a model's
|
|
//textures based on file names.
|
|
void ModelInsertTextureRefs(tFileRef modelRef)
|
|
{
|
|
tModelData *modelData=((tModel*)gFileTable[modelRef].parsedData)->data;
|
|
tVector3 *vertices=(tVector3*)&modelData->data;
|
|
tVector3 *normals=vertices+modelData->vertexCount;
|
|
tVector2 *texels=(tVector2*)(normals+modelData->normalCount);
|
|
tFaceData *faces=(tFaceData*)(texels+modelData->texelCount);
|
|
tMaterial *materials=(tMaterial*)(faces+modelData->faceCount);
|
|
if(modelData->modelFlags&kFlagMultiTextureFlag)
|
|
materials=(tMaterial*)((tFaceDataMT*)faces+modelData->faceCount);
|
|
for(int i=0;i<modelData->materialCount;i++)
|
|
materials[i].m.texRef=FileGetReference(materials[i].texName);
|
|
}
|
|
|
|
void StoreFaceVertices(tVector3 *vertices,tVector3 *normals,tVector2 *texels,tFaceData *faces,int i,tVertexArrayElement *store,int mt)
|
|
{
|
|
if(mt)
|
|
if(((tFaceDataMT*)faces)[i].vertices->normal!=-1)
|
|
for(int vertex=0;vertex<3;vertex++){
|
|
if(((tFaceDataMT*)faces)[i].vertices->texel!=-1)
|
|
store[0][vertex].texel=texels[((tFaceDataMT*)faces)[i].vertices[vertex].texel];
|
|
else
|
|
store[0][vertex].texel=Vector(0,0);
|
|
if(((tFaceDataMT*)faces)[i].vertices->texel2!=-1)
|
|
store[0][vertex].texel2=texels[((tFaceDataMT*)faces)[i].vertices[vertex].texel2];
|
|
else
|
|
store[0][vertex].texel2=Vector(0,0);
|
|
store[0][vertex].normal=normals[((tFaceDataMT*)faces)[i].vertices[vertex].normal];
|
|
store[0][vertex].vertex=vertices[((tFaceDataMT*)faces)[i].vertices[vertex].vertex];
|
|
}
|
|
else{
|
|
//otherwise, calculate a normal.
|
|
tVector3 *a=vertices+(((tFaceDataMT*)faces)[i].vertices[0].vertex);
|
|
tVector3 *b=vertices+(((tFaceDataMT*)faces)[i].vertices[1].vertex);
|
|
tVector3 *c=vertices+(((tFaceDataMT*)faces)[i].vertices[2].vertex);
|
|
tVector3 n=!((*b-*a)%(*c-*a));
|
|
for(int vertex=0;vertex<3;vertex++)
|
|
{
|
|
if(((tFaceDataMT*)faces)[i].vertices->texel!=-1)
|
|
store[0][vertex].texel=texels[((tFaceDataMT*)faces)[i].vertices[vertex].texel];
|
|
else
|
|
store[0][vertex].texel=Vector(0,0);
|
|
if(((tFaceDataMT*)faces)[i].vertices->texel2!=-1)
|
|
store[0][vertex].texel2=texels[((tFaceDataMT*)faces)[i].vertices[vertex].texel2];
|
|
else
|
|
store[0][vertex].texel2=Vector(0,0);
|
|
store[0][vertex].normal=n;
|
|
store[0][vertex].vertex=vertices[((tFaceDataMT*)faces)[i].vertices[vertex].vertex];
|
|
}
|
|
}
|
|
else if(faces[i].vertices->normal!=-1)
|
|
for(int vertex=0;vertex<3;vertex++){
|
|
if(faces[i].vertices->texel!=-1)
|
|
store[0][vertex].texel=texels[faces[i].vertices[vertex].texel];
|
|
else
|
|
store[0][vertex].texel=Vector(0,0);
|
|
store[0][vertex].normal=normals[faces[i].vertices[vertex].normal];
|
|
store[0][vertex].vertex=vertices[faces[i].vertices[vertex].vertex];
|
|
}
|
|
else{
|
|
//otherwise, calculate a normal.
|
|
tVector3 *a=vertices+(faces[i].vertices[0].vertex);
|
|
tVector3 *b=vertices+(faces[i].vertices[1].vertex);
|
|
tVector3 *c=vertices+(faces[i].vertices[2].vertex);
|
|
tVector3 n=!((*b-*a)%(*c-*a));
|
|
for(int vertex=0;vertex<3;vertex++)
|
|
{
|
|
if(faces[i].vertices->texel!=-1)
|
|
store[0][vertex].texel=texels[faces[i].vertices[vertex].texel];
|
|
else
|
|
store[0][vertex].texel=Vector(0,0);
|
|
store[0][vertex].normal=n;
|
|
store[0][vertex].vertex=vertices[faces[i].vertices[vertex].vertex];
|
|
}
|
|
}
|
|
}
|
|
|
|
void ModelInitArrays(tFileRef modelRef)
|
|
{
|
|
tModelData *modelData=((tModel*)gFileTable[modelRef].parsedData)->data;
|
|
int mt=modelData->modelFlags&kFlagMultiTextureFlag;
|
|
tVector3 *vertices=(tVector3*)&modelData->data;
|
|
tVector3 *normals=vertices+modelData->vertexCount;
|
|
tVector2 *texels=(tVector2*)(normals+modelData->normalCount);
|
|
tFaceData *faces=(tFaceData*)(texels+modelData->texelCount);
|
|
tFaceDataMT *facesMT=(tFaceDataMT*)(texels+modelData->texelCount);
|
|
tMaterial *materials=(tMaterial*)(faces+modelData->faceCount);
|
|
if(mt)
|
|
materials=(tMaterial*)(facesMT+modelData->faceCount);
|
|
int matCount=mt?modelData->materialCount/2:modelData->materialCount;
|
|
|
|
((tModel*)gFileTable[modelRef].parsedData)->indices=(tMaterialArrayIndices*)MemoryAllocateZeroedBlock(sizeof(tMaterialArrayIndices)*matCount);
|
|
tMaterialArrayIndices *indices=((tModel*)gFileTable[modelRef].parsedData)->indices;
|
|
((tModel*)gFileTable[modelRef].parsedData)->array=(tVertexArrayElement*)MemoryAllocateBlock(sizeof(tVertexArrayElement)*modelData->faceCount);
|
|
tVertexArrayElement *array=((tModel*)gFileTable[modelRef].parsedData)->array;
|
|
|
|
//arrays are indexed starting with 1, so we shift all arrays
|
|
//down by one index.
|
|
vertices--;
|
|
normals--;
|
|
texels--;
|
|
materials--;
|
|
|
|
//for each face
|
|
for(int i=0;i<modelData->faceCount;i++)
|
|
{
|
|
int mat=mt?facesMT[i].material:faces[i].material;
|
|
int faceMaterial=mat&kMaterialMask;
|
|
if(faceMaterial!=-1&&faceMaterial!=0)
|
|
if((!(materials[faceMaterial].m.flags&kMaterialUseAlphaChannel))||mat&kDisableTransparencyFlag)
|
|
indices[faceMaterial-1].num++;
|
|
else
|
|
indices[faceMaterial-1].numTransparent++;
|
|
}
|
|
|
|
int arrayVertexCount=0;
|
|
for(int material=1;material<=matCount;material++)
|
|
{
|
|
indices[material-1].start=arrayVertexCount;
|
|
for(int i=0;i<modelData->faceCount;i++)
|
|
{
|
|
int mat=mt?facesMT[i].material:faces[i].material;
|
|
int faceMaterial=mat&kMaterialMask;
|
|
if(material==faceMaterial)
|
|
if((!(materials[faceMaterial].m.flags&kMaterialUseAlphaChannel))||mat&kDisableTransparencyFlag)
|
|
StoreFaceVertices(vertices,normals,texels,faces,i,array+arrayVertexCount++,mt);
|
|
}
|
|
for(int i=0;i<modelData->faceCount;i++)
|
|
{
|
|
int mat=mt?facesMT[i].material:faces[i].material;
|
|
int faceMaterial=mat&kMaterialMask;
|
|
if(material==faceMaterial)
|
|
if(materials[faceMaterial].m.flags&kMaterialUseAlphaChannel&&!(mat&kDisableTransparencyFlag))
|
|
StoreFaceVertices(vertices,normals,texels,faces,i,array+arrayVertexCount++,mt);
|
|
}
|
|
}
|
|
|
|
glGenVertexArraysAPPLE(1,&(((tModel*)gFileTable[modelRef].parsedData)->arrayRef));
|
|
glBindVertexArrayAPPLE(((tModel*)gFileTable[modelRef].parsedData)->arrayRef);
|
|
glInterleavedArrays(GL_T2F_N3F_V3F,sizeof(tVertexArrayVertex),array);
|
|
|
|
if(mt){
|
|
glClientActiveTextureARB(GL_TEXTURE1_ARB);
|
|
glTexCoordPointer(2,GL_FLOAT,sizeof(tVertexArrayVertex),((char*)array)+sizeof(tVector2)+2*sizeof(tVector3));
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
|
}
|
|
}
|
|
|
|
enum{
|
|
kModeDrawNormal,
|
|
kModeDrawEverythingSolid,
|
|
kModeDrawOnlyTransparent,
|
|
kModeDrawOnlyTransparentSolid,
|
|
kModeDrawOnlySolid,
|
|
kModeDrawEverythingGhosted
|
|
};
|
|
|
|
|
|
void ModelAddGhostedArrays(tFileRef modelRef,int textureSet)
|
|
{
|
|
tModelData *modelData=((tModel*)gFileTable[modelRef].parsedData)->data;
|
|
tVector3 *vertices=(tVector3*)&modelData->data;
|
|
tVector3 *normals=vertices+modelData->vertexCount;
|
|
tVector2 *texels=(tVector2*)(normals+modelData->normalCount);
|
|
tFaceData *faces=(tFaceData*)(texels+modelData->texelCount);
|
|
tMaterial *materials=(tMaterial*)(faces+modelData->faceCount);
|
|
|
|
tMaterialArrayIndices *indices=((tModel*)gFileTable[modelRef].parsedData)->indices;
|
|
tVertexArrayElement *array=((tModel*)gFileTable[modelRef].parsedData)->array;
|
|
//arrays are indexed starting with 1, so we shift all arrays
|
|
//down by one index.
|
|
materials--;
|
|
|
|
for(int i=0;i<modelData->materialCount;i++)
|
|
for(int j=indices[i].start;j<indices[i].start+indices[i].num+indices[i].numTransparent;j++)
|
|
if(tTransparentPoly *p=GetNextTransparentPoly(false))
|
|
{
|
|
p->mat=&(materials+i+1)->m;
|
|
p->ghost=true;
|
|
p->textureSet=textureSet;
|
|
for(int v=0;v<3;v++)
|
|
{
|
|
p->v[v]=array[j][v];
|
|
p->v[v].vertex=p->v[v].vertex*gTransformDir+gTransformPos;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ModelAddTransparentArrays(tFileRef modelRef,int textureSet)
|
|
{
|
|
tModelData *modelData=((tModel*)gFileTable[modelRef].parsedData)->data;
|
|
tVector3 *vertices=(tVector3*)&modelData->data;
|
|
tVector3 *normals=vertices+modelData->vertexCount;
|
|
tVector2 *texels=(tVector2*)(normals+modelData->normalCount);
|
|
tFaceData *faces=(tFaceData*)(texels+modelData->texelCount);
|
|
tMaterial *materials=(tMaterial*)(faces+modelData->faceCount);
|
|
|
|
tMaterialArrayIndices *indices=((tModel*)gFileTable[modelRef].parsedData)->indices;
|
|
tVertexArrayElement *array=((tModel*)gFileTable[modelRef].parsedData)->array;
|
|
//arrays are indexed starting with 1, so we shift all arrays
|
|
//down by one index.
|
|
materials--;
|
|
|
|
for(int i=0;i<modelData->materialCount;i++)
|
|
for(int j=indices[i].start+indices[i].num;j<indices[i].start+indices[i].num+indices[i].numTransparent;j++)
|
|
if(tTransparentPoly *p=GetNextTransparentPoly(false))
|
|
{
|
|
p->mat=&(materials+i+1)->m;
|
|
p->textureSet=textureSet;
|
|
for(int v=0;v<3;v++)
|
|
{
|
|
p->v[v]=array[j][v];
|
|
p->v[v].normal=p->v[v].normal*gTransformDir;
|
|
p->v[v].vertex=p->v[v].vertex*gTransformDir+gTransformPos;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ModelDrawArrays(tFileRef modelRef,int mode,int textureSet)
|
|
{
|
|
tModelData *modelData=((tModel*)gFileTable[modelRef].parsedData)->data;
|
|
int mt=modelData->modelFlags&kFlagMultiTextureFlag;
|
|
tVector3 *vertices=(tVector3*)&modelData->data;
|
|
tVector3 *normals=vertices+modelData->vertexCount;
|
|
tVector2 *texels=(tVector2*)(normals+modelData->normalCount);
|
|
tFaceData *faces=(tFaceData*)(texels+modelData->texelCount);
|
|
tFaceDataMT *facesMT=(tFaceDataMT*)(texels+modelData->texelCount);
|
|
tMaterial *materials=(tMaterial*)(faces+modelData->faceCount);
|
|
if(mt)
|
|
materials=(tMaterial*)(facesMT+modelData->faceCount);
|
|
int matCount=mt?modelData->materialCount/2:modelData->materialCount;
|
|
|
|
tMaterialArrayIndices *indices=((tModel*)gFileTable[modelRef].parsedData)->indices;
|
|
|
|
//arrays are indexed starting with 1, so we shift all arrays
|
|
//down by one index.
|
|
materials--;
|
|
|
|
glBindVertexArrayAPPLE(((tModel*)gFileTable[modelRef].parsedData)->arrayRef);
|
|
//glInterleavedArrays(GL_T2F_N3F_V3F,0,((tModel*)gFileTable[modelRef].parsedData)->array);
|
|
|
|
//glLockArraysEXT(0,modelData->faceCount*3);
|
|
|
|
/* if(TexturesSelectTextureUnit(1))
|
|
{
|
|
glTexCoordPointer(2,GL_FLOAT,sizeof(tVertexArrayVertex),((char*)((tModel*)gFileTable[modelRef].parsedData)->array)+sizeof(tVector2)+2*sizeof(tVector3));
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
TexturesSelectTextureUnit(0);
|
|
}
|
|
glTexCoordPointer(2,GL_FLOAT,sizeof(tVertexArrayVertex),((char*)((tModel*)gFileTable[modelRef].parsedData)->array));
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
glNormalPointer(GL_FLOAT,sizeof(tVertexArrayVertex),((char*)((tModel*)gFileTable[modelRef].parsedData)->array)+sizeof(tVector2));
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glVertexPointer(3,GL_FLOAT,sizeof(tVertexArrayVertex),((char*)((tModel*)gFileTable[modelRef].parsedData)->array)+sizeof(tVector2)+sizeof(tVector3));
|
|
glEnableClientState(GL_VERTEX_ARRAY);*/
|
|
|
|
|
|
if(mode!=kModeDrawOnlyTransparent)
|
|
for(int i=0;i<matCount;i++)
|
|
{
|
|
int start=indices[i].start;
|
|
if(mode==kModeDrawOnlyTransparentSolid)
|
|
start+=indices[i].num;
|
|
int num;
|
|
if(mode==kModeDrawNormal||mode==kModeDrawOnlySolid)
|
|
num=indices[i].num;
|
|
else if(mode==kModeDrawOnlyTransparentSolid)
|
|
num=indices[i].numTransparent;
|
|
else if(mode==kModeDrawEverythingSolid)
|
|
num=indices[i].num+indices[i].numTransparent;
|
|
|
|
if(mt)
|
|
UseMaterial2((&(materials+i+1)->m),(&(materials+i+1+matCount)->m),textureSet);
|
|
else
|
|
UseMaterial((&(materials+i+1)->m),false,textureSet);
|
|
glDrawArrays(GL_TRIANGLES,start*3,num*3);
|
|
}
|
|
//glUnlockArraysEXT();
|
|
|
|
if((mode==kModeDrawNormal||mode==kModeDrawOnlyTransparent)&&!mt)
|
|
ModelAddTransparentArrays(modelRef,textureSet);
|
|
}
|
|
|
|
void ModelCompileDisplayList(tFileRef modelRef);
|
|
|
|
void ModelCalcClipInfo(tFileRef modelRef)
|
|
{
|
|
tVector3 minv=Vector(INFINITY,INFINITY,INFINITY);
|
|
tVector3 maxv=Vector(-INFINITY,-INFINITY,-INFINITY);
|
|
|
|
tModelData *modelData=((tModel*)gFileTable[modelRef].parsedData)->data;
|
|
tVector3 *vertices=(tVector3*)&modelData->data;
|
|
for(int i=0;i<modelData->vertexCount;i++)
|
|
{
|
|
if(vertices[i].x<minv.x)minv.x=vertices[i].x;
|
|
if(vertices[i].y<minv.y)minv.y=vertices[i].y;
|
|
if(vertices[i].z<minv.z)minv.z=vertices[i].z;
|
|
if(vertices[i].x>maxv.x)maxv.x=vertices[i].x;
|
|
if(vertices[i].y>maxv.y)maxv.y=vertices[i].y;
|
|
if(vertices[i].z>maxv.z)maxv.z=vertices[i].z;
|
|
}
|
|
if(modelData->vertexCount)
|
|
{
|
|
((tModel*)gFileTable[modelRef].parsedData)->center=(minv+maxv)*0.5;
|
|
((tModel*)gFileTable[modelRef].parsedData)->centerMaxExtends=~(minv-((tModel*)gFileTable[modelRef].parsedData)->center);
|
|
}
|
|
else
|
|
{
|
|
((tModel*)gFileTable[modelRef].parsedData)->center=Vector(0,0,0);
|
|
((tModel*)gFileTable[modelRef].parsedData)->centerMaxExtends=0;
|
|
}
|
|
}
|
|
|
|
void ModelSwitchEndianess(tFileRef modelRef)
|
|
{
|
|
tModelData *modelData=((tModel*)gFileTable[modelRef].parsedData)->data;
|
|
S32Swap(modelData->vertexCount);
|
|
S32Swap(modelData->normalCount);
|
|
S32Swap(modelData->faceCount);
|
|
S32Swap(modelData->materialCount);
|
|
S32Swap(modelData->modelFlags);
|
|
S32Swap(modelData->texelCount);
|
|
|
|
S32Swap(*((SInt32*)(&modelData->maxExtends)));
|
|
|
|
int mt=modelData->modelFlags&kFlagMultiTextureFlag;
|
|
tVector3 *vertices=(tVector3*)&modelData->data;
|
|
tVector3 *normals=vertices+modelData->vertexCount;
|
|
tVector2 *texels=(tVector2*)(normals+modelData->normalCount);
|
|
tFaceData *faces=(tFaceData*)(texels+modelData->texelCount);
|
|
tFaceDataMT *facesMT=(tFaceDataMT*)(texels+modelData->texelCount);
|
|
tMaterial *materials=(tMaterial*)(faces+modelData->faceCount);
|
|
if(mt)
|
|
materials=(tMaterial*)(facesMT+modelData->faceCount);
|
|
|
|
for(int i=0;i<modelData->vertexCount;i++)
|
|
{
|
|
S32Swap(*((SInt32*)(&(vertices[i].x))));
|
|
S32Swap(*((SInt32*)(&(vertices[i].y))));
|
|
S32Swap(*((SInt32*)(&(vertices[i].z))));
|
|
}
|
|
|
|
for(int i=0;i<modelData->normalCount;i++)
|
|
{
|
|
S32Swap(*((SInt32*)(&(normals[i].x))));
|
|
S32Swap(*((SInt32*)(&(normals[i].y))));
|
|
S32Swap(*((SInt32*)(&(normals[i].z))));
|
|
}
|
|
|
|
for(int i=0;i<modelData->texelCount;i++)
|
|
{
|
|
S32Swap(*((SInt32*)(&(texels[i].x))));
|
|
S32Swap(*((SInt32*)(&(texels[i].y))));
|
|
}
|
|
|
|
|
|
if(mt)
|
|
for(int i=0;i<modelData->faceCount;i++)
|
|
{
|
|
S32Swap(facesMT[i].material);
|
|
for(int j=0;j<3;j++)
|
|
{
|
|
S32Swap(facesMT[i].vertices[j].vertex);
|
|
S32Swap(facesMT[i].vertices[j].normal);
|
|
S32Swap(facesMT[i].vertices[j].texel);
|
|
S32Swap(facesMT[i].vertices[j].texel2);
|
|
S32Swap(facesMT[i].vertices[j].neighbor);
|
|
}
|
|
}
|
|
else
|
|
for(int i=0;i<modelData->faceCount;i++)
|
|
{
|
|
S32Swap(faces[i].material);
|
|
for(int j=0;j<3;j++)
|
|
{
|
|
S32Swap(faces[i].vertices[j].vertex);
|
|
S32Swap(faces[i].vertices[j].normal);
|
|
S32Swap(faces[i].vertices[j].texel);
|
|
S32Swap(faces[i].vertices[j].neighbor);
|
|
}
|
|
}
|
|
for(int i=0;i<modelData->materialCount;i++)
|
|
{
|
|
S32Swap(materials[i].m.flags);
|
|
S32Swap(*((SInt32*)(&(materials[i].m.shininess))));
|
|
S32Swap(*((SInt32*)(&(materials[i].m.specular.x))));
|
|
S32Swap(*((SInt32*)(&(materials[i].m.specular.y))));
|
|
S32Swap(*((SInt32*)(&(materials[i].m.specular.z))));
|
|
S32Swap(*((SInt32*)(&(materials[i].m.ambient.x))));
|
|
S32Swap(*((SInt32*)(&(materials[i].m.ambient.y))));
|
|
S32Swap(*((SInt32*)(&(materials[i].m.ambient.z))));
|
|
S32Swap(*((SInt32*)(&(materials[i].m.diffuse.x))));
|
|
S32Swap(*((SInt32*)(&(materials[i].m.diffuse.y))));
|
|
S32Swap(*((SInt32*)(&(materials[i].m.diffuse.z))));
|
|
}
|
|
}
|
|
|
|
//Load a model from disk
|
|
void ModelLoad(tFileRef modelRef)
|
|
{
|
|
gFileTable[modelRef].parsedData=MemoryAllocateBlock(sizeof(tModel));
|
|
((tModel*)gFileTable[modelRef].parsedData)->data=(tModelData*)FileGetDataPtr(modelRef);
|
|
|
|
#if TARGET_RT_LITTLE_ENDIAN
|
|
ModelSwitchEndianess(modelRef);
|
|
#endif
|
|
|
|
ModelInsertTextureRefs(modelRef);
|
|
#ifdef __USEVERTEXARRAYS
|
|
ModelInitArrays(modelRef);
|
|
#endif
|
|
#ifdef __USEDISPLAYLISTS
|
|
ModelCompileDisplayList(modelRef);
|
|
#endif
|
|
gFileTable[modelRef].parsed=true;
|
|
ModelCalcClipInfo(modelRef);
|
|
|
|
tModelList *modelList=gModelList;
|
|
gModelList=(tModelList*)MemoryAllocateBlock(sizeof(tModelList));
|
|
gModelList->next=(void*)modelList;
|
|
gModelList->model=modelRef;
|
|
|
|
}
|
|
|
|
tVector3 ModelGetCenter(tFileRef modelRef)
|
|
{
|
|
if(!gFileTable[modelRef].parsed)
|
|
ModelLoad(modelRef);
|
|
return ((tModel*)gFileTable[modelRef].parsedData)->center;
|
|
}
|
|
|
|
float ModelGetCenterMaxExtends(tFileRef modelRef)
|
|
{
|
|
if(!gFileTable[modelRef].parsed)
|
|
ModelLoad(modelRef);
|
|
return ((tModel*)gFileTable[modelRef].parsedData)->centerMaxExtends;
|
|
}
|
|
|
|
//Dispose all data structures associated with a model.
|
|
void ModelDispose(tFileRef modelRef)
|
|
{
|
|
MemoryFreeBlock(((tModel*)gFileTable[modelRef].parsedData)->data);
|
|
MemoryFreeBlock(((tModel*)gFileTable[modelRef].parsedData)->indices);
|
|
MemoryFreeBlock(((tModel*)gFileTable[modelRef].parsedData)->array);
|
|
if(gFileTable[modelRef].data!=((tModel*)gFileTable[modelRef].parsedData)->data)
|
|
MemoryFreeBlock(gFileTable[modelRef].data);
|
|
|
|
#ifdef __USEDISPLAYLISTS
|
|
glDeleteLists(((tModel*)gFileTable[modelRef].parsedData)->ref,1);
|
|
#endif
|
|
glDeleteVertexArraysAPPLE(1,&((tModel*)gFileTable[modelRef].parsedData)->arrayRef);
|
|
MemoryFreeBlock(((tModel*)gFileTable[modelRef].parsedData));
|
|
|
|
gFileTable[modelRef].parsed=false;
|
|
gFileTable[modelRef].loaded=false;
|
|
}
|
|
|
|
void ModelsUnloadAll()
|
|
{
|
|
while(gModelList!=NULL)
|
|
{
|
|
tModelList *next=(tModelList*)gModelList->next;
|
|
ModelDispose(gModelList->model);
|
|
MemoryFreeBlock(gModelList);
|
|
gModelList=next;
|
|
}
|
|
}
|
|
|
|
//return the maximum extends of a model. (the distance from
|
|
//the furthest vertex from center).
|
|
float ModelGetMaxExtends(tFileRef modelRef)
|
|
{
|
|
if(!gFileTable[modelRef].parsed)
|
|
ModelLoad(modelRef);
|
|
if(!gFileTable[modelRef].parsed)
|
|
return 0;
|
|
tModelData *modelData=((tModel*)gFileTable[modelRef].parsedData)->data;
|
|
|
|
if(!modelData->maxExtends)
|
|
{
|
|
tVector3 *vertices=(tVector3*)&modelData->data;
|
|
tVector3 maxExtends=Vector(0,0,0);
|
|
for(int i=0;i<modelData->vertexCount;i++)
|
|
{
|
|
if(fabs(vertices[i].x)>maxExtends.x)maxExtends.x=fabs(vertices[i].x);
|
|
if(fabs(vertices[i].y)>maxExtends.y)maxExtends.y=fabs(vertices[i].y);
|
|
if(fabs(vertices[i].z)>maxExtends.z)maxExtends.z=fabs(vertices[i].z);
|
|
}
|
|
modelData->maxExtends=~maxExtends;
|
|
}
|
|
return modelData->maxExtends;
|
|
}
|
|
|
|
//Draw a model
|
|
void ModelDraw(tFileRef modelRef,int mode,int textureSet)
|
|
{
|
|
tModelData *modelData=((tModel*)gFileTable[modelRef].parsedData)->data;
|
|
tVector3 *vertices=(tVector3*)&modelData->data;
|
|
tVector3 *normals=vertices+modelData->vertexCount;
|
|
tVector2 *texels=(tVector2*)(normals+modelData->normalCount);
|
|
tFaceData *faces=(tFaceData*)(texels+modelData->texelCount);
|
|
tMaterial *materials=(tMaterial*)(faces+modelData->faceCount);
|
|
|
|
//arrays are indexed starting with 1, so we shift all arrays
|
|
//down by one index.
|
|
vertices--;
|
|
normals--;
|
|
texels--;
|
|
materials--;
|
|
|
|
int material=-1;//currently used material
|
|
int transparent;
|
|
|
|
//for each face
|
|
for(int i=0;i<modelData->faceCount;i++)
|
|
{
|
|
int faceMaterial=faces[i].material&kMaterialMask;
|
|
//check if the material is the same as we were using
|
|
if(faceMaterial!=material){
|
|
//if not, change material
|
|
transparent=UseMaterial(&((materials+faceMaterial)->m),false,textureSet);
|
|
if(mode==kModeDrawEverythingSolid)
|
|
transparent=false;
|
|
material=faceMaterial;
|
|
}
|
|
|
|
//if the face isn't transparent, draw it
|
|
int drawTransparent=transparent&&!(faces[i].material&kDisableTransparencyFlag);
|
|
if(!drawTransparent||(drawTransparent&&mode==kModeDrawOnlyTransparentSolid))
|
|
{
|
|
if(mode!=kModeDrawOnlyTransparent)
|
|
{
|
|
glBegin(GL_TRIANGLES);
|
|
//do we have a normal?
|
|
if(faces[i].vertices->normal!=-1)
|
|
for(int vertex=0;vertex<3;vertex++){
|
|
if(faces[i].vertices->texel!=-1)
|
|
glTexCoord2fv(&texels[faces[i].vertices[vertex].texel].x);
|
|
glNormal3fv(&normals[faces[i].vertices[vertex].normal].x);
|
|
glVertex3fv(&vertices[faces[i].vertices[vertex].vertex].x);
|
|
}
|
|
else{
|
|
//otherwise, calculate a normal.
|
|
tVector3 *a=vertices+(faces[i].vertices[0].vertex);
|
|
tVector3 *b=vertices+(faces[i].vertices[1].vertex);
|
|
tVector3 *c=vertices+(faces[i].vertices[2].vertex);
|
|
tVector3 n=!((*b-*a)%(*c-*a));
|
|
glNormal3fv(&n.x);
|
|
for(int vertex=0;vertex<3;vertex++)
|
|
{
|
|
if(faces[i].vertices->texel!=-1)
|
|
glTexCoord2fv(&texels[faces[i].vertices[vertex].texel].x);
|
|
glVertex3fv(&vertices[faces[i].vertices[vertex].vertex].x);
|
|
}
|
|
}
|
|
glEnd();
|
|
}
|
|
}
|
|
//if the face is transparent, add it to the list of transparent faces
|
|
else if(mode!=kModeDrawOnlySolid)
|
|
if(tTransparentPoly *p=GetNextTransparentPoly(false)){
|
|
if(faces[i].vertices->normal!=-1)
|
|
for(int vertex=0;vertex<3;vertex++){
|
|
if(faces[i].vertices->texel!=-1)
|
|
p->v[vertex].texel=texels[faces[i].vertices[vertex].texel];
|
|
else
|
|
p->v[vertex].texel=Vector(0,0);
|
|
p->v[vertex].normal=normals[faces[i].vertices[vertex].normal]*gTransformDir;
|
|
p->v[vertex].vertex=vertices[faces[i].vertices[vertex].vertex]*gTransformDir+gTransformPos;
|
|
}
|
|
else{
|
|
tVector3 *a=vertices+(faces[i].vertices[0].vertex);
|
|
tVector3 *b=vertices+(faces[i].vertices[1].vertex);
|
|
tVector3 *c=vertices+(faces[i].vertices[2].vertex);
|
|
tVector3 n=!((*b-*a)%(*c-*a));
|
|
for(int vertex=0;vertex<3;vertex++)
|
|
{
|
|
if(faces[vertex].vertices->texel!=-1)
|
|
p->v[vertex].texel=texels[faces[i].vertices[vertex].texel];
|
|
else
|
|
p->v[vertex].texel=Vector(0,0);
|
|
p->v[vertex].normal=n*gTransformDir;
|
|
p->v[vertex].vertex=vertices[faces[i].vertices[vertex].vertex]*gTransformDir+gTransformPos;
|
|
}
|
|
}
|
|
p->mat=&(materials+faces[i].material)->m;
|
|
p->textureSet=textureSet;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ModelDrawMultiTextured(tFileRef modelRef,int textureSet)
|
|
{
|
|
tModelData *modelData=((tModel*)gFileTable[modelRef].parsedData)->data;
|
|
tVector3 *vertices=(tVector3*)&modelData->data;
|
|
tVector3 *normals=vertices+modelData->vertexCount;
|
|
tVector2 *texels=(tVector2*)(normals+modelData->normalCount);
|
|
tFaceDataMT *faces=(tFaceDataMT*)(texels+modelData->texelCount);
|
|
tMaterial *materials=(tMaterial*)(faces+modelData->faceCount);
|
|
|
|
//arrays are indexed starting with 1, so we shift all arrays
|
|
//down by one index.
|
|
vertices--;
|
|
normals--;
|
|
texels--;
|
|
materials--;
|
|
|
|
int material=-1;//currently used material
|
|
|
|
//for each face
|
|
for(int i=0;i<modelData->faceCount;i++)
|
|
{
|
|
int faceMaterial=faces[i].material&kMaterialMask;
|
|
//check if the material is the same as we were using
|
|
if(faceMaterial!=material){
|
|
//if not, change material
|
|
UseMaterial2(&((materials+faceMaterial)->m),&((materials+faceMaterial+modelData->materialCount/2)->m),textureSet);
|
|
material=faceMaterial;
|
|
}
|
|
|
|
glBegin(GL_TRIANGLES);
|
|
//do we have a normal?
|
|
if(faces[i].vertices->normal!=-1)
|
|
for(int vertex=0;vertex<3;vertex++){
|
|
if(faces[i].vertices->texel!=-1)
|
|
glTexCoord2fv(&texels[faces[i].vertices[vertex].texel].x);
|
|
if(faces[i].vertices->texel2!=-1)
|
|
glMultiTexCoord2fv(GL_TEXTURE1,&texels[faces[i].vertices[vertex].texel2].x);
|
|
glNormal3fv(&normals[faces[i].vertices[vertex].normal].x);
|
|
glVertex3fv(&vertices[faces[i].vertices[vertex].vertex].x);
|
|
}
|
|
else{
|
|
//otherwise, calculate a normal.
|
|
tVector3 *a=vertices+(faces[i].vertices[0].vertex);
|
|
tVector3 *b=vertices+(faces[i].vertices[1].vertex);
|
|
tVector3 *c=vertices+(faces[i].vertices[2].vertex);
|
|
tVector3 n=!((*b-*a)%(*c-*a));
|
|
glNormal3fv(&n.x);
|
|
for(int vertex=0;vertex<3;vertex++)
|
|
{
|
|
if(faces[i].vertices->texel!=-1)
|
|
glTexCoord2fv(&texels[faces[i].vertices[vertex].texel].x);
|
|
if(faces[i].vertices->texel2!=-1)
|
|
glMultiTexCoord2fv(GL_TEXTURE1,&texels[faces[i].vertices[vertex].texel2].x);
|
|
glVertex3fv(&vertices[faces[i].vertices[vertex].vertex].x);
|
|
}
|
|
}
|
|
glEnd();
|
|
}
|
|
}
|
|
|
|
void ModelLoadTextures(tFileRef modelRef)
|
|
{
|
|
tModelData *modelData=((tModel*)gFileTable[modelRef].parsedData)->data;
|
|
tVector3 *vertices=(tVector3*)&modelData->data;
|
|
tVector3 *normals=vertices+modelData->vertexCount;
|
|
tVector2 *texels=(tVector2*)(normals+modelData->normalCount);
|
|
tFaceData *faces=(tFaceData*)(texels+modelData->texelCount);
|
|
tMaterial *materials=(tMaterial*)(faces+modelData->faceCount);
|
|
for(int i=0;i<modelData->materialCount;i++)
|
|
UseMaterial(&((materials+i)->m),false,0);
|
|
}
|
|
|
|
void ModelCompileDisplayList(tFileRef modelRef)
|
|
{
|
|
//create an OpenGL display list for a model
|
|
((tModel*)gFileTable[modelRef].parsedData)->ref=glGenLists(1);
|
|
ModelLoadTextures(modelRef);
|
|
glNewList(((tModel*)gFileTable[modelRef].parsedData)->ref,GL_COMPILE);
|
|
#ifdef __USEVERTEXARRAYS
|
|
ModelDrawArrays(modelRef,kModeDrawOnlySolid,0);
|
|
#else
|
|
ModelDraw(modelRef,kModeDrawOnlySolid,0);
|
|
#endif
|
|
glEndList();
|
|
}
|
|
|
|
void ModelShadowPassZFail(tFileRef modelRef,tVector3 shadowVector,char *faceSide)
|
|
{
|
|
tModelData *modelData=((tModel*)gFileTable[modelRef].parsedData)->data;
|
|
tVector3 *vertices=(tVector3*)&modelData->data;
|
|
tVector3 *normals=vertices+modelData->vertexCount;
|
|
tVector2 *texels=(tVector2*)(normals+modelData->normalCount);
|
|
vertices--;
|
|
tFaceData *faces=(tFaceData*)(texels+modelData->texelCount);
|
|
tMaterial *materials=(tMaterial*)(faces+modelData->faceCount);
|
|
materials--;
|
|
tVector3 sw=0.05*!shadowVector;
|
|
|
|
for(int i=0;i<modelData->faceCount;i++)
|
|
if(!((materials+(faces[i].material&kMaterialMask))->m.flags&kMaterialDisableShadow))
|
|
if(modelData->modelFlags&kFlagShadowFlag)
|
|
{
|
|
for(int n=0;n<3;n++)
|
|
if(faces[i].vertices[n].neighbor<=-1)
|
|
{
|
|
glBegin(GL_TRIANGLE_STRIP);
|
|
glVertex3fv(&(vertices[faces[i].vertices[n].vertex]*gStencilZoom-sw).x);
|
|
glVertex3fv(&(vertices[faces[i].vertices[(n+1)%3].vertex]*gStencilZoom-sw).x);
|
|
glVertex3fv(&(vertices[faces[i].vertices[n].vertex]*gStencilZoom-shadowVector).x);
|
|
glVertex3fv(&(vertices[faces[i].vertices[(n+1)%3].vertex]*gStencilZoom-shadowVector).x);
|
|
glEnd();
|
|
#ifdef __POLYCOUNT
|
|
gPolyCount+=2;
|
|
#endif
|
|
}
|
|
|
|
if(faceSide[i]||1)
|
|
{
|
|
glBegin(GL_TRIANGLES);
|
|
for(int j=2;j>=0;j--)
|
|
glVertex3fv(&(vertices[faces[i].vertices[j].vertex]*gStencilZoom-sw).x);
|
|
|
|
for(int j=0;j<=2;j++)
|
|
glVertex3fv(&(vertices[faces[i].vertices[j].vertex]*gStencilZoom-shadowVector).x);
|
|
glEnd();
|
|
}
|
|
else
|
|
{
|
|
glBegin(GL_TRIANGLES);
|
|
for(int j=2;j>=0;j--)
|
|
glVertex3fv(&(vertices[faces[i].vertices[j].vertex]*gStencilZoom-shadowVector).x);
|
|
|
|
for(int j=0;j<=2;j++)
|
|
glVertex3fv(&(vertices[faces[i].vertices[j].vertex]*gStencilZoom-sw).x);
|
|
glEnd();
|
|
}
|
|
}
|
|
else
|
|
if(faceSide[i])
|
|
{
|
|
for(int n=0;n<3;n++)
|
|
if(faces[i].vertices[n].neighbor!=-1)
|
|
{
|
|
if(faceSide[faces[i].vertices[n].neighbor]!=faceSide[i])
|
|
{
|
|
glBegin(GL_TRIANGLE_STRIP);
|
|
glVertex3fv(&(vertices[faces[i].vertices[n].vertex]*(kShadowZoom*gStencilZoom)).x);
|
|
glVertex3fv(&(vertices[faces[i].vertices[(n+1)%3].vertex]*(kShadowZoom*gStencilZoom)).x);
|
|
glVertex3fv(&(vertices[faces[i].vertices[n].vertex]*(kShadowZoom*gStencilZoom)-shadowVector).x);
|
|
glVertex3fv(&(vertices[faces[i].vertices[(n+1)%3].vertex]*(kShadowZoom*gStencilZoom)-shadowVector).x);
|
|
glEnd();
|
|
#ifdef __POLYCOUNT
|
|
gPolyCount+=2;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
glBegin(GL_TRIANGLES);
|
|
for(int j=2;j>=0;j--)
|
|
glVertex3fv(&(vertices[faces[i].vertices[j].vertex]*(kShadowZoom*gStencilZoom)).x);
|
|
glEnd();
|
|
}
|
|
else
|
|
{
|
|
glBegin(GL_TRIANGLES);
|
|
for(int j=2;j>=0;j--)
|
|
glVertex3fv(&(vertices[faces[i].vertices[j].vertex]*(kShadowZoom*gStencilZoom)-shadowVector).x);
|
|
glEnd();
|
|
}
|
|
#ifdef __POLYCOUNT
|
|
gPolyCount+=modelData->faceCount;
|
|
#endif
|
|
}
|
|
|
|
|
|
void ModelShadowPassZPass(tFileRef modelRef,tVector3 shadowVector,char *faceSide)
|
|
{
|
|
tModelData *modelData=((tModel*)gFileTable[modelRef].parsedData)->data;
|
|
tVector3 *vertices=(tVector3*)&modelData->data;
|
|
tVector3 *normals=vertices+modelData->vertexCount;
|
|
tVector2 *texels=(tVector2*)(normals+modelData->normalCount);
|
|
vertices--;
|
|
tFaceData *faces=(tFaceData*)(texels+modelData->texelCount);
|
|
tMaterial *materials=(tMaterial*)(faces+modelData->faceCount);
|
|
materials--;
|
|
|
|
if(modelData->modelFlags&kFlagShadowFlag)
|
|
{
|
|
tVector3 sw=0.05*!shadowVector;
|
|
for(int i=0;i<modelData->faceCount;i++)
|
|
if(!((materials+(faces[i].material&kMaterialMask))->m.flags&kMaterialDisableShadow))
|
|
{
|
|
for(int n=0;n<3;n++)
|
|
if(faces[i].vertices[n].neighbor==-1)
|
|
{
|
|
glBegin(GL_TRIANGLE_STRIP);
|
|
glVertex3fv(&(vertices[faces[i].vertices[n].vertex]*gStencilZoom-sw).x);
|
|
glVertex3fv(&(vertices[faces[i].vertices[(n+1)%3].vertex]*gStencilZoom-sw).x);
|
|
glVertex3fv(&(vertices[faces[i].vertices[n].vertex]*gStencilZoom-shadowVector).x);
|
|
glVertex3fv(&(vertices[faces[i].vertices[(n+1)%3].vertex]*gStencilZoom-shadowVector).x);
|
|
glEnd();
|
|
#ifdef __POLYCOUNT
|
|
gPolyCount+=2;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
else for(int i=0;i<modelData->faceCount;i++)
|
|
if(!((materials+(faces[i].material&kMaterialMask))->m.flags&kMaterialDisableShadow))
|
|
if(faceSide[i]||(modelData->modelFlags&kFlagShadowFlag))
|
|
for(int n=0;n<3;n++)
|
|
if(faces[i].vertices[n].neighbor!=-1)
|
|
if(faceSide[faces[i].vertices[n].neighbor]!=faceSide[i])
|
|
{
|
|
glBegin(GL_TRIANGLE_STRIP);
|
|
glVertex3fv(&(vertices[faces[i].vertices[n].vertex]*(kShadowZoom*gStencilZoom)).x);
|
|
glVertex3fv(&(vertices[faces[i].vertices[(n+1)%3].vertex]*(kShadowZoom*gStencilZoom)).x);
|
|
glVertex3fv(&(vertices[faces[i].vertices[n].vertex]*(kShadowZoom*gStencilZoom)-shadowVector).x);
|
|
glVertex3fv(&(vertices[faces[i].vertices[(n+1)%3].vertex]*(kShadowZoom*gStencilZoom)-shadowVector).x);
|
|
glEnd();
|
|
#ifdef __POLYCOUNT
|
|
gPolyCount+=2;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//for each face of a model, calculate whether it faces the light or not.
|
|
//return the results in the array faceSide
|
|
void CalcFaceSides(tFileRef modelRef,tVector3 lightDir,char **faceSide)
|
|
{
|
|
tModelData *modelData=((tModel*)gFileTable[modelRef].parsedData)->data;
|
|
tVector3 *vertices=(tVector3*)&modelData->data;
|
|
tVector3 *normals=vertices+modelData->vertexCount;
|
|
tVector2 *texels=(tVector2*)(normals+modelData->normalCount);
|
|
vertices--;
|
|
tFaceData *faces=(tFaceData*)(texels+modelData->texelCount);
|
|
*faceSide=(char*)MemoryAllocateBlock(sizeof(char)*modelData->faceCount+10);
|
|
|
|
for(int i=0;i<modelData->faceCount;i++){
|
|
tVector3 *a=vertices+(faces[i].vertices[0].vertex);
|
|
tVector3 *b=vertices+(faces[i].vertices[1].vertex);
|
|
tVector3 *c=vertices+(faces[i].vertices[2].vertex);
|
|
|
|
//calculate a normal to the face
|
|
tVector3 n=((*b-*a)%(*c-*a));
|
|
|
|
//use dot product to determine if the face faces the light
|
|
(*faceSide)[i]=n*lightDir>0;
|
|
}
|
|
}
|
|
|
|
//Draw the shadow of a model
|
|
//Uses s stencil buffer-based shadow volume algorithm
|
|
void ModelCastShadow(tFileRef modelRef,float shadowLength)
|
|
{
|
|
tVector3 lightDir=gEnvironment->lightDir;
|
|
if(gMapEnv)
|
|
if(!VectorZero(gMapEnv->lightDir))
|
|
lightDir=gMapEnv->lightDir;
|
|
|
|
tMatrix3 tr;
|
|
MatrixTranspose(gTransformDir,tr);
|
|
lightDir=lightDir*tr;
|
|
|
|
char *faceSide;
|
|
CalcFaceSides(modelRef,lightDir,&faceSide);
|
|
|
|
//disable actual drawing
|
|
glDisable(GL_LIGHTING);
|
|
glDisable(GL_FOG);
|
|
glDepthMask(GL_FALSE);
|
|
glColorMask(0, 0, 0, 0);
|
|
|
|
//enable stencil buffer drawing
|
|
glEnable(GL_STENCIL_TEST);
|
|
glStencilFunc(GL_ALWAYS, 0, 0xffffffff);
|
|
|
|
tVector3 lightNormal1=!((gTransformPos-gCameraEntity->pos)%lightDir);
|
|
tVector3 lightNormal2=lightNormal1%lightDir;
|
|
tVector3 shadowVector=lightDir*shadowLength;
|
|
//is the camera possibly in the shadow volume?
|
|
if(-lightNormal2*(gTransformPos-gCameraEntity->pos)<ModelGetMaxExtends(modelRef)+shadowLength)
|
|
{
|
|
//if the camera is possibly inside the shadow volume,
|
|
//we have to use zFail rendering, as normal zPass rendering
|
|
//won't work if the camera is inside the shadow volume.
|
|
glFrontFace(GL_CW);
|
|
glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
|
|
ModelShadowPassZFail(modelRef,shadowVector,faceSide);
|
|
|
|
glFrontFace(GL_CCW);
|
|
glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
|
|
ModelShadowPassZFail(modelRef,shadowVector,faceSide);
|
|
}
|
|
else
|
|
{//zPass Rendering
|
|
glFrontFace(GL_CCW);
|
|
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
|
|
ModelShadowPassZPass(modelRef,shadowVector,faceSide);
|
|
|
|
glFrontFace(GL_CW);
|
|
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
|
|
ModelShadowPassZPass(modelRef,shadowVector,faceSide);
|
|
}
|
|
MemoryFreeBlock(faceSide);
|
|
glDepthMask(GL_TRUE);
|
|
glColorMask(1, 1, 1, 1);
|
|
}
|
|
|
|
//draw a model
|
|
void DrawModel(tFileRef modelRef,int allowTransparency,int textureSet)
|
|
{
|
|
if(!gFileTable[modelRef].parsed)
|
|
ModelLoad(modelRef);
|
|
if(!gFileTable[modelRef].parsed)
|
|
return;
|
|
|
|
#ifdef __USEDISPLAYLISTS
|
|
glCallList(((tModel*)gFileTable[modelRef].parsedData)->ref);
|
|
#ifdef __USEVERTEXARRAYS
|
|
ModelDrawArrays(modelRef,allowTransparency?kModeDrawOnlyTransparent:kModeDrawOnlyTransparentSolid,textureSet);
|
|
#else
|
|
ModelDraw(modelRef,allowTransparency?kModeDrawOnlyTransparent:kModeDrawOnlyTransparentSolid,textureSet);
|
|
#endif
|
|
#else
|
|
#ifdef __USEVERTEXARRAYS
|
|
if(allowTransparency==kTransparencyGhost)
|
|
ModelAddGhostedArrays(modelRef,textureSet);
|
|
else
|
|
ModelDrawArrays(modelRef,allowTransparency?kModeDrawNormal:kModeDrawEverythingSolid,textureSet);
|
|
#else
|
|
if((((tModel*)gFileTable[modelRef].parsedData)->data)->modelFlags&kFlagMultiTextureFlag)
|
|
ModelDrawMultiTextured(modelRef,textureSet);
|
|
else
|
|
ModelDraw(modelRef,allowTransparency?kModeDrawNormal:kModeDrawEverythingSolid,textureSet);
|
|
#endif
|
|
#endif
|
|
#ifdef __POLYCOUNT
|
|
gPolyCount+=((tModelData*)((tModel*)gFileTable[modelRef].parsedData)->data)->faceCount;
|
|
#endif
|
|
if(TexturesSelectTextureUnit(1)){
|
|
glDisable(GL_TEXTURE_2D);
|
|
glDisable(GL_TEXTURE_3D);
|
|
glDisable(GL_TEXTURE_GEN_S);
|
|
glDisable(GL_TEXTURE_GEN_T);
|
|
TexturesSelectTextureUnit(0);
|
|
}
|
|
}
|
|
|
|
//draw a model's shadow
|
|
void DrawModelShadow(tFileRef modelRef,float shadowLength)
|
|
{
|
|
if(!gFileTable[modelRef].parsed)
|
|
ModelLoad(modelRef);
|
|
if(!gFileTable[modelRef].parsed)
|
|
return;
|
|
if((((tModel*)gFileTable[modelRef].parsedData)->data)->modelFlags&kFlagMultiTextureFlag)
|
|
return;
|
|
if(shadowLength>0)
|
|
ModelCastShadow(modelRef,shadowLength);
|
|
}
|
|
|