--- Irrlicht.org/CCOBMeshFileLoader.h 2006-04-09 00:35:53.740035472 +0200 +++ Irrlicht.new/CCOBMeshFileLoader.h 2006-04-08 22:43:49.431481622 +0200 @@ -0,0 +1,89 @@ +#ifndef __C_COB_MESH_FILE_LOADER_H_INCLUDED__ +#define __C_COB_MESH_FILE_LOADER_H_INCLUDED__ + +#include "IMeshLoader.h" +#include "IFileSystem.h" +#include "IVideoDriver.h" +#include "irrString.h" +#include "SMesh.h" + +namespace irr +{ +namespace scene +{ + +struct tFace +{ + core::array vertIndex; // indicies for the verts that make up this triangle + core::array coordIndex; // indicies for the tex coords to texture this face +}; + +struct tMaterialInfo +{ + core::stringc Filename[3]; // The texture file name (If this is set it's a texture map) + video::SMaterial Material; + s16 matId; + s32 parent; + float uTile; // u tiling of texture + float vTile; // v tiling of texture + float uOffset; // u offset of texture + float vOffset; // v offset of texture +} ; + +struct t3DObject +{ + int numOfVerts; // The number of verts in the model + int numOfFaces; // The number of faces in the model + int numTexVertex; // The number of texture coordinates + int Id; // The object ID + int materialID; // The texture ID to use + core::stringc Name; // The name of the object + core::vector3df *pVerts; // The object's vertices + core::vector2df *pTexVerts; // The texture's UV coordinates + tFace *pFaces; // The faces information of the object +}; + +//! Meshloader capable of loading COB meshes. +class CCOBMeshFileLoader : public IMeshLoader +{ +public: + + //! Constructor + CCOBMeshFileLoader(io::IFileSystem* fs, video::IVideoDriver* driver); + + //! destructor + virtual ~CCOBMeshFileLoader(); + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".cob") + virtual bool isALoadableFileExtension(const c8* fileName); + + //! creates/loads an animated mesh from the file. + //! \return Pointer to the created mesh. Returns 0 if loading failed. + //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). + //! See IUnknown::drop() for more information. + virtual IAnimatedMesh* createMesh(io::IReadFile* file); + +private: + bool readFileHeader(); + bool readHeaders(); + bool readChunk(unsigned int type, int id, int parent, int size); + void readPolH(int id); + void readMat(int parent, int size); + bool writeToMesh(); + + io::IFileSystem* FileSystem; + video::IVideoDriver* Driver; + io::IReadFile* File; + FILE *mFilePointer; + SMesh* Mesh; + + bool binary; + core::array mCurObjects; + core::array mMaterials; +}; + +} // end namespace scene +} // end namespace irr + +#endif --- Irrlicht.org/CCOBMeshFileLoader.cpp 2006-04-09 00:35:51.729357802 +0200 +++ Irrlicht.new/CCOBMeshFileLoader.cpp 2006-04-09 00:35:13.505640455 +0200 @@ -0,0 +1,583 @@ +#include "CCOBMeshFileLoader.h" +#include +#include +#include "os.h" +#include "SMeshBuffer.h" +#include "SAnimatedMesh.h" + +using namespace std; + +namespace irr +{ +namespace scene +{ + +#define charsToUIntD(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | d) +inline unsigned int charsToUInt(const char *str) +{ + return (str[0] << 24) | (str[1] << 16) | (str[2] << 8) | str[3]; +} + +//! Constructor +CCOBMeshFileLoader::CCOBMeshFileLoader(io::IFileSystem* fs, video::IVideoDriver* driver) +: FileSystem(fs), Driver(driver), Mesh(0), File(0), binary(true), mFilePointer(0) +{ + if (FileSystem) + FileSystem->grab(); + + if (Driver) + Driver->grab(); +} + + + +//! destructor +CCOBMeshFileLoader::~CCOBMeshFileLoader() +{ + if (FileSystem) + FileSystem->drop(); + + if (Driver) + Driver->drop(); + + if (Mesh) + Mesh->drop(); +} + + + +//! returns true if the file maybe is able to be loaded by this class +//! based on the file extension (e.g. ".bsp") +bool CCOBMeshFileLoader::isALoadableFileExtension(const c8* filename) +{ + return strstr(filename, ".cob")!=0; +} + + + +//! creates/loads an animated mesh from the file. +//! \return Pointer to the created mesh. Returns 0 if loading failed. +//! If you no longer need the mesh, you should call IAnimatedMesh::drop(). +//! See IUnknown::drop() for more information. +IAnimatedMesh* CCOBMeshFileLoader::createMesh(io::IReadFile* file) +{ + os::Printer::log("Attempting to load COB..."); + file->seek(0); + + File = file; + mCurObjects.clear(); + mMaterials.clear(); + + if (Mesh) + Mesh->drop(); + + Mesh = new SMesh(); + + if (!readFileHeader()) + return false; + + mFilePointer = fopen(File->getFileName(), "rb"); + fseek(mFilePointer, 32, SEEK_SET); + + if(!readHeaders()) + return false; + + if(!writeToMesh()) + return false; + + SAnimatedMesh* am = new SAnimatedMesh(); + am->Type = EAMT_X; + + for (s32 j=0; jgetMeshBufferCount(); ++j) + ((SMeshBuffer*)Mesh->getMeshBuffer(j))->recalculateBoundingBox(); + + Mesh->recalculateBoundingBox(); + + am->addMesh(Mesh); + am->recalculateBoundingBox(); + Mesh->drop(); + Mesh = 0; + + return am; +} + + +bool CCOBMeshFileLoader::readHeaders() +{ + int lastPos; + int size, major, minor, id, parent; + unsigned int uiType; + char type[5]; + type[4]=0; + + while(!feof(mFilePointer)) + { + //Read Chunk Header + if (binary) { + s16 maj, min; + + fread(type, 1, 4, mFilePointer); + fread(&maj, 2, 1, mFilePointer); + fread(&min, 2, 1, mFilePointer); + major=maj; + minor=min; + fread(&id, 4, 1, mFilePointer); + fread(&parent, 4, 1, mFilePointer); + fread(&size, 4, 1, mFilePointer); + } else { + fscanf( mFilePointer, "%4c V%d.%d Id %d Parent %d Size %d", + type, &major, &minor, &id, &parent, &size); + } + + //Convert 4-char string to 4-byte integer + //Makes it possible to do a switch statement + uiType = charsToUInt(type); + lastPos = ftell(mFilePointer); //Read !after! chunk header + + if(!readChunk(uiType, id, parent, size)) //read the chunk + break; //if false then we reached an end chunk + + //Go to next chunk + if( fseek(mFilePointer, lastPos + size, SEEK_SET)) + break; + } + return true; +} + +bool CCOBMeshFileLoader::readChunk(unsigned int type, int id, int parent, int size) +{ + switch(type) + { + case charsToUIntD('E','N','D',' '): + return false; + break; + + case charsToUIntD('P','o','l','H'): + readPolH(id); + break; + + case charsToUIntD('U','n','i','t'): + { + s16 unit; + if (binary) + fread(&unit, 2, 1, mFilePointer); + else + fscanf(mFilePointer, "\nUnits %hd", &unit); + } + break; + + case charsToUIntD('M','a','t','1'): + readMat(parent, size); + break; + } + + return true; +} + +void CCOBMeshFileLoader::readMat(int parent, int size) +{ + int iTemp; + char shader[1024], facet[1024]; + float r, g, b, a, ka, ks, eXP, ior, f; + tMaterialInfo tempMat; + char sTemp[1024]; + s32 cpTemp; + + tempMat.Filename[0] = ""; + tempMat.Filename[1] = ""; + tempMat.Filename[2] = ""; + tempMat.uOffset = tempMat.uTile = tempMat.vOffset = tempMat.vTile = 0.0f; + tempMat.parent=parent; + + // This is all of the basic material info (non-optional) + if (binary) { + fread(&tempMat.matId, 2, 1, mFilePointer); + size -=2; + } else + fscanf(mFilePointer, "\nmat# %hd", &tempMat.matId); + if (binary) { + fread(shader, 1, 1, mFilePointer); + // facet mode and angle (two bytes) + fread(facet, 1, 2, mFilePointer); + size -=3; + } else + fscanf(mFilePointer, "\nshader: %s facet: %s", shader, facet); + if (binary) { + fread(&r, 4, 1, mFilePointer); + fread(&g, 4, 1, mFilePointer); + fread(&b, 4, 1, mFilePointer); + size -=12; + } else + fscanf(mFilePointer, "\nrgb %g,%g,%g", &r, &g, &b); + if (binary) { + fread(&a, 4, 1, mFilePointer); + fread(&ka, 4, 1, mFilePointer); + fread(&ks, 4, 1, mFilePointer); + fread(&eXP, 4, 1, mFilePointer); + fread(&ior, 4, 1, mFilePointer); + size -=20; + } else + fscanf(mFilePointer, "\nalpha %g ka %g ks %g exp %g ior %g", &a, &ka, &ks, &eXP, &ior); + tempMat.Material.AmbientColor=video::SColorf(r,g,b,a).toSColor(); +// if (a<1.0f) +// tempMat.Material.MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL; +// tempMat.Material.AmbientColor=tempMat.Material.AmbientColor.getInterpolated(video::SColor(0,0,0,0), 1.0f-ka); + tempMat.Material.SpecularColor=tempMat.Material.SpecularColor.getInterpolated(video::SColor(0,0,0,0), 1.0f-ks); + tempMat.Material.Shininess=eXP; + + //Read all maps, we ignore all of them except the texture + if (binary) { + char mapID[2]; + char mapFlags; + short int stringSize; + float discard; + while (size>0) { + fread(mapID, 1, 2, mFilePointer); + fread(&mapFlags, 1, 1, mFilePointer); + fread(&stringSize, 2, 1, mFilePointer); + fread(sTemp, 1, stringSize, mFilePointer); + sTemp[stringSize]=0; + size -=5+stringSize; + switch (mapID[0]) { + case 'e': + { + tempMat.Filename[2]=sTemp; + } + break; + case 't': + { + tempMat.Filename[0]=sTemp; + fread(&(tempMat.uOffset), 4, 1, mFilePointer); + fread(&(tempMat.vOffset), 4, 1, mFilePointer); + fread(&(tempMat.uTile), 4, 1, mFilePointer); + fread(&(tempMat.vTile), 4, 1, mFilePointer); + } + break; + case 'b': + { + tempMat.Filename[1]=sTemp; + fread(&discard, 4, 1, mFilePointer); + fread(&discard, 4, 1, mFilePointer); + fread(&discard, 4, 1, mFilePointer); + fread(&discard, 4, 1, mFilePointer); + fread(&discard, 4, 1, mFilePointer); + } + break; + } + } + } else { + if(fscanf(mFilePointer, "\nenvironment: %d", &iTemp)) + { + fread(sTemp, 1, iTemp, mFilePointer); + fscanf(mFilePointer, "\nflags %d", &iTemp); + } + + if(fscanf(mFilePointer, "\ntexture: %d", &iTemp)) + { + fread(sTemp, 1, iTemp, mFilePointer); + sTemp[iTemp] = 0; + tempMat.Filename[0]=sTemp; + fscanf(mFilePointer, "\noffset %g,%g repeats %g,%g flags %d", &(tempMat.uOffset), &(tempMat.vOffset), &(tempMat.uTile), &(tempMat.vTile), &iTemp); + } + + if(fscanf(mFilePointer, "\nbump: %d", &iTemp)) + { + fread(sTemp, 1, iTemp, mFilePointer); + fscanf(mFilePointer, "\noffset %g,%g repeats %g,%g amp %g flags %d", &f, &ka, &ks, &eXP, &ior, &iTemp); + } + } + + for (u32 i=0; i<3; ++i) { + if (!tempMat.Filename[i].size()) + continue; + cpTemp = tempMat.Filename[i].findLast('\\'); + if(cpTemp == -1) + cpTemp = tempMat.Filename[i].findLast('/'); + ++cpTemp; + tempMat.Filename[i]=tempMat.Filename[i].subString(cpTemp,tempMat.Filename[i].size()-cpTemp); + } + + mMaterials.push_back(tempMat); +} + +void CCOBMeshFileLoader::readPolH(int id) +{ + core::vector2df biVectorTemp; + tFace tempFace; + float fTempA, fTempB, fTempC; + char meshName[1024]; + s32 vCount, tCount, fCount, i; + short int j, a, b; + long int c, d; + core::array > polys; + core::array verts; + core::array texVerts; + + //Read name + if (binary) { + fread(&j, 1, 2, mFilePointer); + fread(&j, 1, 2, mFilePointer); + fread(meshName, 1, j, mFilePointer); + meshName[j]=0; + } else + fscanf(mFilePointer, "\nName %s", meshName); + + //We will only obey the transformation matrix + //The axes can be useful, but to make things simple I ignore them + //So I still read them to get to the right file position and to + //leave the code open in case I ever want the axes. + if (binary) + fseek(mFilePointer, 48, SEEK_CUR); + else { + fscanf(mFilePointer, "\ncenter %g %g %g", &fTempA, &fTempB, &fTempC); + fscanf(mFilePointer, "\nx axis %g %g %g", &fTempA, &fTempB, &fTempC); + fscanf(mFilePointer, "\ny axis %g %g %g", &fTempA, &fTempB, &fTempC); + fscanf(mFilePointer, "\nz axis %g %g %g", &fTempA, &fTempB, &fTempC); + } + + //Read Transformation Matrix + core::matrix4 mat; + if (binary) { +// fread(mat.M, 4, 12, mFilePointer); + fread(&mat.M[0], 4, 1, mFilePointer); + fread(&mat.M[4], 4, 1, mFilePointer); + fread(&mat.M[8], 4, 1, mFilePointer); + fread(&mat.M[12], 4, 1, mFilePointer); + fread(&mat.M[1], 4, 1, mFilePointer); + fread(&mat.M[5], 4, 1, mFilePointer); + fread(&mat.M[9], 4, 1, mFilePointer); + fread(&mat.M[13], 4, 1, mFilePointer); + fread(&mat.M[2], 4, 1, mFilePointer); + fread(&mat.M[6], 4, 1, mFilePointer); + fread(&mat.M[10], 4, 1, mFilePointer); + fread(&mat.M[14], 4, 1, mFilePointer); + mat.M[3]=0.0f; + mat.M[7]=0.0f; + mat.M[11]=0.0f; + mat.M[15]=1.0f; +// mat.M[12]=0.0f; +// mat.M[13]=0.0f; +// mat.M[14]=0.0f; +// mat.M[15]=1.0f; + mat=mat.getTransposed(); + } else { + fscanf(mFilePointer, "\nTransform\n%g %g %g %g", &(mat.M[0]), &(mat.M[4]), &(mat.M[8]), &(mat.M[12])); + fscanf(mFilePointer, "\n%g %g %g %g", &(mat.M[1]), &(mat.M[5]), &(mat.M[9]), &(mat.M[13])); + fscanf(mFilePointer, "\n%g %g %g %g", &(mat.M[2]), &(mat.M[6]), &(mat.M[10]), &(mat.M[14])); + fscanf(mFilePointer, "\n%g %g %g %g", &(mat.M[3]), &(mat.M[7]), &(mat.M[11]), &(mat.M[15])); + } + + if (binary) + fread(&vCount, 4, 1, mFilePointer); + else + fscanf(mFilePointer, "\nWorld Vertices %d", &vCount); + + core::vector3df vec; + for(i = 0; i < vCount; ++i) + { + //Read 1 Point + if (binary) { + fread(&vec.X, 1, 4, mFilePointer); + fread(&vec.Y, 1, 4, mFilePointer); + fread(&vec.Z, 1, 4, mFilePointer); + } else + fscanf(mFilePointer, "\n%f %f %f", &(vec.X), &(vec.Y), &(vec.Z)); + //Now we apply the matrix + mat.transformVect(vec); + //Add vertex to list + verts.push_back(vec); + } + + if (binary) + fread(&tCount, 4, 1, mFilePointer); + else + fscanf(mFilePointer, "\nTexture Vertices %d", &tCount); + + for(i = 0; i < tCount; ++i) + { + //Read 1 Point + if (binary) { + fread(&biVectorTemp.X, 1, 4, mFilePointer); + fread(&biVectorTemp.Y, 1, 4, mFilePointer); + } else + fscanf(mFilePointer, "\n%f %f", &(biVectorTemp.X), &(biVectorTemp.Y)); + texVerts.push_back(biVectorTemp); //Add texture coord to list + } + + if (binary) + fread(&fCount, 4, 1, mFilePointer); + else + fscanf(mFilePointer, "\nFaces %d", &fCount); + + for(i = 0; i < fCount; ++i) + { + tempFace.coordIndex.clear(); + tempFace.vertIndex.clear(); + + if (binary) { + char flags; + fread(&flags, 1, 1, mFilePointer); + fread(&a, 2, 1, mFilePointer); + // skip holes + if (flags & 0x08) { + fseek(mFilePointer, 8*a, SEEK_CUR); + continue; + } + fread(&b, 1, 2, mFilePointer); + } else + fscanf(mFilePointer, "\nFace verts %hd flags %hd mat %hd\n", &a, &j, &b); + //"a" is the number of verts, "b" is the material # + tempFace.vertIndex.set_used(a); + tempFace.coordIndex.set_used(a); + for(j = a-1; j >= 0; --j) + { + //Read in index and texIndex + if (binary) { + fread(&c, 1, 4, mFilePointer); + fread(&d, 1, 4, mFilePointer); + } else + fscanf(mFilePointer, "<%ld,%ld> ", &c, &d); + tempFace.vertIndex[j]=c; + tempFace.coordIndex[j]=d; + } + if (b>=polys.size()) + polys.set_used(b+1); + polys[b].push_back(tempFace); + } + + t3DObject tempObject; + + for(u32 iter = 0; iter < polys.size(); ++iter) + { + //This may be changed later in the code, depending on what materials are loaded + tempObject.materialID = iter; + tempObject.Id = id; + tempObject.numOfFaces = fCount; + tempObject.numOfVerts = vCount; + tempObject.numTexVertex = tCount; + tempObject.pFaces = new tFace[fCount]; + for(u32 num = 0; num < polys[iter].size(); ++num) + tempObject.pFaces[num] = polys[iter][num]; + tempObject.pTexVerts = new core::vector2df[tCount]; + for(i = 0; i < tCount; ++i) + tempObject.pTexVerts[i] = texVerts[i]; + tempObject.pVerts = new core::vector3df[vCount]; + for(i = 0; i < vCount; ++i) + tempObject.pVerts[i] = verts[i]; + tempObject.Name=meshName; + + mCurObjects.push_back(tempObject); + } +} + +bool CCOBMeshFileLoader::writeToMesh() +{ + for(u32 i = 0; i < mCurObjects.size(); ++i) + { + tMaterialInfo *mat_info=0; + for(u32 j = 0; j < mMaterials.size(); ++j) + { + if ((mMaterials[j].parent==mCurObjects[i].Id) && + (mMaterials[j].matId==mCurObjects[i].materialID)) { + mat_info = &mMaterials[j]; + break; + } + } + video::SMaterial mat=mat_info->Material; + + if (mat_info->Filename[0] != "") + { + mat.Texture1 = Driver->getTexture(mat_info->Filename[0].c_str()); + //modify the uv's, such that the offset/tiling is applied + for(int w = 0; w < mCurObjects[i].numTexVertex; ++w) + { + mCurObjects[i].pTexVerts[w].X = (mCurObjects[i].pTexVerts[w].X * mat_info->uTile) + mat_info->uOffset; + mCurObjects[i].pTexVerts[w].Y = (mCurObjects[i].pTexVerts[w].Y * mat_info->vTile) + mat_info->vOffset; + } + } + if (mat_info->Filename[1] != "") + { + mat.Texture2 = Driver->getTexture(mat_info->Filename[1].c_str()); + if (mat.Texture2) + mat.MaterialType=video::EMT_PARALLAX_MAP_SOLID; + } + if (mat_info->Filename[2] != "") + { + video::ITexture* reflTexture = Driver->getTexture(mat_info->Filename[2].c_str()); + if (reflTexture) { + mat.Texture2 = mat.Texture1; + mat.Texture1 = reflTexture; + mat.MaterialType=video::EMT_REFLECTION_2_LAYER; + } + } + + SMeshBuffer* mb = new scene::SMeshBuffer(); + Mesh->addMeshBuffer(mb); + mb->Material = mat; + mb->drop(); + + for(int j = 0; j < mCurObjects[i].numOfFaces; ++j) + { + int vertSize = mCurObjects[i].pFaces[j].vertIndex.size(); + if (!vertSize) + continue; + + int index0 = mCurObjects[i].pFaces[j].vertIndex[0]; + int tIndex0 = mCurObjects[i].pFaces[j].coordIndex[0]; + for(int whichVertex = 1; whichVertex < vertSize-1; ++whichVertex) + { + video::S3DVertex vtx; + s32 mbSize=mb->Vertices.size(); + int index = mCurObjects[i].pFaces[j].vertIndex[whichVertex]; + int tIndex = mCurObjects[i].pFaces[j].coordIndex[whichVertex]; + + vtx.Color.set(255,255,255,255); + + vtx.TCoords = core::vector2df(mCurObjects[i].pTexVerts[tIndex0].X, mCurObjects[i].pTexVerts[tIndex0].Y); + vtx.Pos = core::vector3df(mCurObjects[i].pVerts[index0].X, mCurObjects[i].pVerts[index0].Y, mCurObjects[i].pVerts[index0].Z); + mb->Vertices.push_back(vtx); + + vtx.TCoords = core::vector2df(mCurObjects[i].pTexVerts[tIndex].X, mCurObjects[i].pTexVerts[tIndex].Y); + vtx.Pos = core::vector3df(mCurObjects[i].pVerts[index].X, mCurObjects[i].pVerts[index].Y, mCurObjects[i].pVerts[index].Z); + mb->Vertices.push_back(vtx); + + index = mCurObjects[i].pFaces[j].vertIndex[whichVertex+1]; + tIndex = mCurObjects[i].pFaces[j].coordIndex[whichVertex+1]; + vtx.TCoords = core::vector2df(mCurObjects[i].pTexVerts[tIndex].X, mCurObjects[i].pTexVerts[tIndex].Y); + vtx.Pos = core::vector3df(mCurObjects[i].pVerts[index].X, mCurObjects[i].pVerts[index].Y, mCurObjects[i].pVerts[index].Z); + mb->Vertices.push_back(vtx); + + mb->Indices.push_back(mbSize); + mb->Indices.push_back(mbSize+1); + mb->Indices.push_back(mbSize+2); + } //for(verts) + } //for(faces) + } //for(objects) + return true; +} + +bool CCOBMeshFileLoader::readFileHeader() +{ + char sTemp[9]; + + File->read(sTemp, 9); + + if(strncmp(sTemp, "Caligari ",9)) + return false; + + //skip the version, cause I don't check + File->read(sTemp, 6); + // ascii or binary flag + File->read(sTemp, 1); + binary=(sTemp[0] == 'B'); + + //skip everything else! + File->seek(16, true); + + return ((sTemp[0] == 'A') || (sTemp[0] == 'B')); +} + + + +} // end namespace scene +} // end namespace irr --- Irrlicht.org/CSceneManager.cpp 2006-04-04 16:44:55.000000000 +0200 +++ Irrlicht.new/CSceneManager.cpp 2006-04-03 17:57:51.000000000 +0200 @@ -20,6 +20,7 @@ #include "CXMeshFileLoader.h" #include "COCTLoader.h" #include "CCSMLoader.h" +#include "CCOBMeshFileLoader.h" #include "CLMTSMeshFileLoader.h" #include "CMY3DMeshFileLoader.h" #include "CColladaFileLoader.h" @@ -107,6 +108,7 @@ MeshLoaderList.push_back(new CXMeshFileLoader(MeshManipulator, Driver)); MeshLoaderList.push_back(new COCTLoader(Driver)); MeshLoaderList.push_back(new CCSMLoader(this, FileSystem)); + MeshLoaderList.push_back(new CCOBMeshFileLoader(FileSystem, Driver)); MeshLoaderList.push_back(new CLMTSMeshFileLoader(FileSystem, Driver, &Parameters)); MeshLoaderList.push_back(new CMY3DMeshFileLoader(FileSystem, Driver, this)); MeshLoaderList.push_back(new CColladaFileLoader(Driver, this, FileSystem));