MSModelFactory.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <3dsparse/MSModelFactory.h>
00022 #include <common/Defines.h>
00023 
00024 MSModelFactory::MSModelFactory() : lineNo_(0)
00025 {
00026 }
00027 
00028 MSModelFactory::~MSModelFactory()
00029 {
00030 }
00031 
00032 Model *MSModelFactory::createModel(const char *fileName)
00033 {
00034         Model *model = new Model();
00035 
00036         FILE *in = fopen(fileName, "r");
00037         if (!in)
00038         {
00039                 S3D::dialogExit("MSModelFactory", S3D::formatStringBuffer(
00040                         "Failed to open MS model \"%s\"",
00041                         fileName));
00042         }
00043         loadFile(in, fileName, model);
00044         model->setup();
00045         fclose(in);
00046 
00047         return model;
00048 }
00049 
00050 bool MSModelFactory::getNextLine(char *line, FILE *in)
00051 {
00052         char * wincr; 
00053         while (fgets(line, 256, in) != 0)
00054         {
00055                 lineNo_++;
00056                 if (wincr=strchr(line,'\r')) 
00057                 { 
00058                         *wincr='\n'; 
00059                         *(wincr + 1) = '\0'; 
00060                 } 
00061 
00062                 if ((line[0] == '\\' && line[1] == '\\') ||
00063                         (line[0] == '/' && line[1] == '/') ||
00064                         (line[0] == '\0') || 
00065                         (line[0] == '\n'))
00066                 {
00067                         // Skip this line
00068                 }
00069                 else return true;
00070         }
00071 
00072         return false;
00073 }
00074 
00075 void MSModelFactory::returnError(const char *fileName, const std::string &error)
00076 {
00077         S3D::dialogExit("MSModelFactory", S3D::formatStringBuffer("%s in file %i:%s", 
00078                 error.c_str(), lineNo_, fileName));
00079 }
00080 
00081 void MSModelFactory::loadFile(FILE *in, const char *fileName, Model *model)
00082 {
00083         char filePath[256];
00084         snprintf(filePath, sizeof(filePath), "%s", fileName);
00085 
00086         char *sep;
00087         while (sep=strchr(filePath, '\\')) *sep = '/';
00088         sep = strrchr(filePath, '/');
00089         if (sep) *sep = '\0';
00090 
00091         char buffer[256];
00092         int frames = 0;
00093         if (!getNextLine(buffer, in)) returnError(fileName, "No frames");
00094         if (sscanf(buffer, "Frames: %i", &frames) != 1) 
00095                 returnError(fileName, "Incorrect frames format");       
00096         model->setTotalFrames(frames);
00097 
00098         if (!getNextLine(buffer, in)) returnError(fileName, "No frame");
00099         if (sscanf(buffer, "Frame: %i", &frames) != 1) 
00100                 returnError(fileName, "Incorrect frame format");        
00101         model->setStartFrame(frames);
00102 
00103         // Read number meshes
00104         int noMeshes = 0;
00105         if (!getNextLine(buffer, in)) returnError(fileName, "No meshes");
00106         if (sscanf(buffer, "Meshes: %i", &noMeshes) != 1) 
00107                 returnError(fileName, "Incorrect meshes format");
00108 
00109         std::vector<int> meshMaterials;
00110         for (int i=0; i<noMeshes; i++)
00111         {
00112                 // Read the mesh name, flags and material indices
00113                 char meshName[256]; 
00114                 int meshFlags, meshMatIndex;
00115                 if (!getNextLine(buffer, in)) 
00116                         returnError(fileName, "No mesh name");
00117                 if (sscanf(buffer, "%s %i %i", meshName, &meshFlags, &meshMatIndex) != 3) 
00118                         returnError(fileName, "Incorrect mesh name format");
00119                 meshMaterials.push_back(meshMatIndex);
00120                 
00121                 // Create and add the new model
00122                 Mesh *mesh = new Mesh(meshName);
00123                 model->addMesh(mesh);
00124 
00125                 // Read no vertices
00126                 int noVertices = 0;
00127                 if (!getNextLine(buffer, in)) 
00128                         returnError(fileName, "No num vertices");
00129                 if (sscanf(buffer, "%i", &noVertices) != 1) 
00130                         returnError(fileName, "Incorrect num vertices format");
00131 
00132                 int j;
00133                 std::vector<Vector> tcoords;
00134                 for (j=0; j<noVertices; j++)
00135                 {
00136                         // Read the current vertex
00137                         int vertexFlags;
00138                         Vector texCoord;
00139                         Vertex vertex;
00140                         if (!getNextLine(buffer, in)) 
00141                                 returnError(fileName, "No vertices");
00142                         if (sscanf(buffer, "%i %f %f %f %f %f %i",
00143                                 &vertexFlags,
00144                                 &vertex.position[0], &vertex.position[2], &vertex.position[1], 
00145                                 &texCoord[0], &texCoord[1], &vertex.boneIndex) != 7)
00146                                 returnError(fileName, "Incorrect vertices format");
00147                         texCoord[1]=1.0f-texCoord[1];
00148 
00149                         tcoords.push_back(texCoord);
00150                         mesh->insertVertex(vertex);
00151                 }
00152 
00153                 // Read no normals
00154                 std::vector<Vector> normals;
00155                 int noNormals = 0;
00156                 if (!getNextLine(buffer, in)) 
00157                                 returnError(fileName, "No num normals");
00158                 if (sscanf(buffer, "%i", &noNormals) != 1)
00159                                 returnError(fileName, "Incorrect num normals format");
00160                 for (j=0; j<noNormals; j++)
00161                 {
00162                         // Read the current normal
00163                         Vector normal;
00164                         if (!getNextLine(buffer, in))
00165                                 returnError(fileName, "No normal");
00166                         if (sscanf(buffer, "%f %f %f",
00167                                 &normal[0], &normal[2], &normal[1]) != 3)
00168                                 returnError(fileName, "Incorrect normal format");
00169 
00170                         normals.push_back(normal.Normalize());
00171                 }
00172 
00173                 // Read no faces
00174                 int noFaces = 0;
00175                 if (!getNextLine(buffer, in)) 
00176                                 returnError(fileName, "No num faces");
00177                 if (sscanf(buffer, "%i", &noFaces) != 1) 
00178                                 returnError(fileName, "Incorrect num faces format");
00179                 for (j=0; j<noFaces; j++)
00180                 {
00181                         // Read the current face
00182                         int faceFlags, sGroup;
00183                         int nIndex1, nIndex2, nIndex3;
00184                         Face face;
00185                         if (!getNextLine(buffer, in))
00186                                 returnError(fileName, "No face");
00187                         if (sscanf(buffer, "%i %i %i %i %i %i %i %i",
00188                                 &faceFlags,
00189                                 &face.v[0], &face.v[2], &face.v[1],
00190                                 &nIndex1, &nIndex3, &nIndex2,
00191                                 &sGroup) != 8)
00192                                 returnError(fileName, "Incorrect face format");
00193 
00194                         mesh->insertFace(face);
00195                         DIALOG_ASSERT (nIndex1 < (int) normals.size());
00196                         mesh->setFaceNormal(normals[nIndex1], j, 0);
00197                         DIALOG_ASSERT (nIndex2 < (int) normals.size());
00198                         mesh->setFaceNormal(normals[nIndex2], j, 1);
00199                         DIALOG_ASSERT (nIndex3 < (int) normals.size());
00200                         mesh->setFaceNormal(normals[nIndex3], j, 2);
00201 
00202                         DIALOG_ASSERT (face.v[0] < (int) tcoords.size());
00203                         mesh->setFaceTCoord(tcoords[face.v[0]], j, 0);
00204                         DIALOG_ASSERT (face.v[1] < (int) tcoords.size());
00205                         mesh->setFaceTCoord(tcoords[face.v[1]], j, 1);
00206                         DIALOG_ASSERT (face.v[2] < (int) tcoords.size());
00207                         mesh->setFaceTCoord(tcoords[face.v[2]], j, 2);
00208                 }
00209         }
00210 
00211         // Read number materials
00212         int noMaterials = 0;
00213         if (!getNextLine(buffer, in))
00214                 returnError(fileName, "No num materials");
00215         if (sscanf(buffer, "Materials: %i", &noMaterials) != 1)
00216                 returnError(fileName, "Incorrect num materials format");
00217 
00218         for (int m=0; m<noMaterials; m++)
00219         {
00220                 // material: name
00221                 char materialName[256];
00222                 if (!getNextLine(buffer, in)) 
00223                         returnError(fileName, "No material name");
00224                 if (sscanf(buffer, "%s", materialName) != 1)
00225                         returnError(fileName, "Incorrect material name format");
00226 
00227                 // ambient
00228                 Vector4 ambient;
00229                 if (!getNextLine(buffer, in))
00230                         returnError(fileName, "No material ambient");
00231                 if (sscanf(buffer, "%f %f %f %f", 
00232                         &ambient[0], &ambient[1], &ambient[2], &ambient[3]) != 4) 
00233                         returnError(fileName, "Incorrect material ambient format");
00234 
00235                 // diffuse
00236                 Vector4 diffuse;
00237                 if (!getNextLine(buffer, in))
00238                         returnError(fileName, "No material diffuse");
00239                 if (sscanf(buffer, "%f %f %f %f", 
00240                         &diffuse[0], &diffuse[1], &diffuse[2], &diffuse[3]) != 4)
00241                         returnError(fileName, "Incorrect material diffuse format");
00242 
00243                 // specular
00244                 Vector4 specular;
00245                 if (!getNextLine(buffer, in))
00246                         returnError(fileName, "No material specular");
00247                 if (sscanf(buffer, "%f %f %f %f", 
00248                         &specular[0], &specular[1], &specular[2], &specular[3]) != 4)
00249                         returnError(fileName, "Incorrect material specular format");
00250 
00251                 // emissive
00252                 Vector4 emissive;
00253                 if (!getNextLine(buffer, in))
00254                         returnError(fileName, "No material emissive");
00255                 if (sscanf(buffer, "%f %f %f %f", 
00256                         &emissive[0], &emissive[1], &emissive[2], &emissive[3]) != 4)
00257                         returnError(fileName, "Incorrect material emissive format");
00258 
00259                 // shininess
00260                 float shininess;
00261                 if (!getNextLine(buffer, in)) 
00262                         returnError(fileName, "No material shininess");
00263                 if (sscanf(buffer, "%f", &shininess) != 1)
00264                         returnError(fileName, "Incorrect material shininess format");
00265 
00266                 // transparency
00267                 float transparency;
00268                 if (!getNextLine(buffer, in)) 
00269                         returnError(fileName, "No material transparency");
00270                 if (sscanf(buffer, "%f", &transparency) != 1)
00271                         returnError(fileName, "Incorrect material transparency format");
00272 
00273                 // color map
00274                 char textureName[256];
00275                 char fullTextureName[256];
00276                 if (!getNextLine(buffer, in)) 
00277                         returnError(fileName, "No material texture");
00278                 if (sscanf(buffer, "%s", textureName) != 1)
00279                         returnError(fileName, "No material texture format");
00280                 textureName[strlen(textureName)-1] = '\0';
00281                 snprintf(fullTextureName, 256, "%s/%s", filePath, &textureName[1]);
00282                 while (sep=strchr(fullTextureName, '\\')) *sep = '/';
00283 
00284                 // alphamap
00285                 char textureNameAlpha[256];
00286                 char fullTextureAlphaName[256];
00287                 if (!getNextLine(buffer, in)) 
00288                         returnError(fileName, "No material alpha texture");
00289                 if (sscanf(buffer, "%s", textureNameAlpha) != 1)
00290                         returnError(fileName, "No material alpha texture format");
00291                 textureNameAlpha[strlen(textureNameAlpha)-1] = '\0';
00292                 snprintf(fullTextureAlphaName, 256, "%s/%s", filePath, &textureNameAlpha[1]);
00293                 while (sep=strchr(fullTextureAlphaName, '\\')) *sep = '/';
00294 
00295                 // Assign this material to the appropriate meshes
00296                 int modelIndex = 0;
00297                 std::vector<Mesh *>::iterator mitor;
00298                 for (mitor = model->getMeshes().begin();
00299                         mitor != model->getMeshes().end();
00300                         mitor++, modelIndex++)
00301                 {
00302                         if (meshMaterials[modelIndex] == m)
00303                         {
00304                                 Mesh *mesh = *mitor;
00305                                 if (textureName[1]) // as the string starts with a "
00306                                 {
00307                                         mesh->setTextureName(fullTextureName);
00308                                         if (!S3D::fileExists(fullTextureName))
00309                                         {
00310                                                 returnError(fileName, 
00311                                                         S3D::formatStringBuffer("Failed to find texture \"%s\"",
00312                                                                 fullTextureName));
00313                                         }
00314                                 }
00315                                 if (textureNameAlpha[1])
00316                                 {
00317                                         mesh->setATextureName(fullTextureAlphaName);
00318                                         if (!S3D::fileExists(fullTextureAlphaName))
00319                                         {
00320                                                 returnError(fileName,
00321                                                         S3D::formatStringBuffer("Failed to find alpha texture \"%s\"",
00322                                                                 fullTextureAlphaName));
00323                                         }
00324                                 }
00325                                 mesh->getDiffuseColor() = diffuse;
00326                                 mesh->getAmbientColor() = ambient;
00327                                 mesh->getSpecularColor() = specular;
00328                                 mesh->getEmissiveColor() = emissive;
00329                                 mesh->getShininessColor() = shininess;
00330                                 mesh->getDiffuseNoTexColor() = diffuse;
00331                                 mesh->getAmbientNoTexColor() = ambient;
00332                                 mesh->getSpecularNoTexColor() = specular;
00333                                 mesh->getEmissiveNoTexColor() = emissive;
00334                         }
00335                 }
00336         }
00337 
00338         // Setup meshes with no materials
00339         int modelIndex = 0;
00340         std::vector<Mesh *>::iterator mitor;
00341         for (mitor = model->getMeshes().begin();
00342                 mitor != model->getMeshes().end();
00343                 mitor++, modelIndex++)
00344         {
00345                 int materialIndex = meshMaterials[modelIndex];
00346                 if (materialIndex == -1)
00347                 {
00348                         Mesh *mesh = *mitor;
00349 
00350                         Vector4 ambientColor(0.3f, 0.3f, 0.3f, 1.0f);
00351                         Vector4 diffuseColor(0.8f, 0.8f, 0.8f, 1.0f);
00352                         mesh->getAmbientColor() = ambientColor;
00353                         mesh->getDiffuseColor() = diffuseColor;
00354                         mesh->getEmissiveColor() = Vector::getNullVector();
00355                         mesh->getSpecularColor() = Vector::getNullVector();
00356 
00357                         mesh->getAmbientNoTexColor() = ambientColor;
00358                         mesh->getDiffuseNoTexColor() = diffuseColor;
00359                         mesh->getEmissiveNoTexColor() = Vector::getNullVector();
00360                         mesh->getSpecularNoTexColor() = Vector::getNullVector();
00361 
00362                         mesh->getShininessColor() = 0.0f;
00363                 }
00364         }
00365 
00366 
00367         ////////////////
00368         // The bone's position and rotation are left in the milkshape native xyz coord
00369         // system and are not read in translated into the S3D system.
00370         // The translation is done during the bone calculation at runtime
00371         ///////////////
00372 
00373         // Read number bones
00374         int noBones = 0;
00375         if (!getNextLine(buffer, in))
00376                 returnError(fileName, "No num bones");
00377         if (sscanf(buffer, "Bones: %i", &noBones) != 1)
00378                 returnError(fileName, "Incorrect num bones format");
00379 
00380         for (int b=0; b<noBones; b++)
00381         {
00382                 // bone: name
00383                 char boneName[256];
00384                 if (!getNextLine(buffer, in)) 
00385                         returnError(fileName, "No bone name");
00386                 if (sscanf(buffer, "%s", boneName) != 1)
00387                         returnError(fileName, "Incorrect bone name format");
00388 
00389                 // bone parent
00390                 char boneParentName[256];
00391                 if (!getNextLine(buffer, in)) 
00392                         returnError(fileName, "No bone parent name");
00393                 if (sscanf(buffer, "%s", boneParentName) != 1)
00394                         returnError(fileName, "Incorrect bone parent name format");
00395 
00396                 // flags, position, rotation
00397                 int boneFlags;
00398                 Vector bonePos, boneRot;
00399                 if (!getNextLine(buffer, in)) 
00400                         returnError(fileName, "No bone pos/rot");
00401                 if (sscanf(buffer, "%i %f %f %f %f %f %f",
00402                         &boneFlags,
00403                         &bonePos[0], &bonePos[1], &bonePos[2], 
00404                         &boneRot[0], &boneRot[1], &boneRot[2]) != 7)
00405                         returnError(fileName, "Incorrect bone pos/rot format");
00406 
00407                 Bone *bone = new Bone(boneName);
00408                 bone->setParentName(boneParentName);
00409                 bone->setPosition(bonePos);
00410                 bone->setRotation(boneRot);
00411 
00412                 // position key
00413                 int noPositionKeys = 0;
00414                 if (!getNextLine(buffer, in))
00415                         returnError(fileName, "No bone position keys");
00416                 if (sscanf(buffer, "%i", &noPositionKeys) != 1)
00417                         returnError(fileName, "Incorrect bone position keys format");
00418 
00419                 for (int p=0; p<noPositionKeys; p++)
00420                 {
00421                         float time;
00422                         Vector position;
00423                         if (!getNextLine(buffer, in)) 
00424                                 returnError(fileName, "No bone position key");
00425                         if (sscanf(buffer, "%f %f %f %f",
00426                                 &time,
00427                                 &position[0], &position[1], &position[2]) != 4)
00428                                 returnError(fileName, "Incorrect bone position key");
00429 
00430                         BonePositionKey *key = new BonePositionKey(time, position);
00431                         bone->addPositionKey(key);
00432                 }
00433 
00434                 // rotation key
00435                 int noRotationKeys = 0;
00436                 if (!getNextLine(buffer, in))
00437                         returnError(fileName, "No bone rotation keys");
00438                 if (sscanf(buffer, "%i", &noRotationKeys) != 1)
00439                         returnError(fileName, "Incorrect bone rotation keys format");
00440 
00441                 for (int r=0; r<noRotationKeys; r++)
00442                 {
00443                         float time;
00444                         Vector rotation;
00445                         if (!getNextLine(buffer, in)) 
00446                                 returnError(fileName, "No bone position key");
00447                         if (sscanf(buffer, "%f %f %f %f",
00448                                 &time,
00449                                 &rotation[0], &rotation[1], &rotation[2]) != 4)
00450                                 returnError(fileName, "Incorrect bone position key");
00451 
00452                         BoneRotationKey *key = new BoneRotationKey(time, rotation);
00453                         bone->addRotationKey(key);
00454                 }
00455 
00456                 // Add bone
00457                 model->addBone(bone);
00458         }
00459 }

Generated on Mon Feb 16 15:14:48 2009 for Scorched3D by  doxygen 1.5.3