00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "modelfile.h"
00011 #include "tokenizer.h"
00012 #include "texmanager.h"
00013 #include <celutil/bytes.h>
00014 #include <cstring>
00015 #include <cassert>
00016 #include <cmath>
00017 #include <cstdio>
00018
00019 using namespace std;
00020
00021
00022
00023
00024 static Color DefaultDiffuse(0.0f, 0.0f, 0.0f);
00025 static Color DefaultSpecular(0.0f, 0.0f, 0.0f);
00026 static Color DefaultEmissive(0.0f, 0.0f, 0.0f);
00027 static float DefaultSpecularPower = 1.0f;
00028 static float DefaultOpacity = 1.0f;
00029
00030
00095 class AsciiModelLoader : public ModelLoader
00096 {
00097 public:
00098 AsciiModelLoader(istream& _in);
00099 ~AsciiModelLoader();
00100
00101 virtual Model* load();
00102 virtual void reportError(const string&);
00103
00104 Mesh::Material* loadMaterial();
00105 Mesh::VertexDescription* loadVertexDescription();
00106 Mesh* loadMesh();
00107 char* loadVertices(const Mesh::VertexDescription& vertexDesc,
00108 uint32& vertexCount);
00109
00110 private:
00111 Tokenizer tok;
00112 };
00113
00114
00115 class AsciiModelWriter : public ModelWriter
00116 {
00117 public:
00118 AsciiModelWriter(ostream&);
00119 ~AsciiModelWriter();
00120
00121 virtual bool write(const Model&);
00122
00123 private:
00124 void writeMesh(const Mesh&);
00125 void writeMaterial(const Mesh::Material&);
00126 void writeGroup(const Mesh::PrimitiveGroup&);
00127 void writeVertexDescription(const Mesh::VertexDescription&);
00128 void writeVertices(const void* vertexData,
00129 uint32 nVertices,
00130 uint32 stride,
00131 const Mesh::VertexDescription& desc);
00132
00133 ostream& out;
00134 };
00135
00136
00137 class BinaryModelLoader : public ModelLoader
00138 {
00139 public:
00140 BinaryModelLoader(istream& _in);
00141 ~BinaryModelLoader();
00142
00143 virtual Model* load();
00144 virtual void reportError(const string&);
00145
00146 Mesh::Material* loadMaterial();
00147 Mesh::VertexDescription* loadVertexDescription();
00148 Mesh* loadMesh();
00149 char* loadVertices(const Mesh::VertexDescription& vertexDesc,
00150 uint32& vertexCount);
00151
00152 private:
00153 istream& in;
00154 };
00155
00156
00157 class BinaryModelWriter : public ModelWriter
00158 {
00159 public:
00160 BinaryModelWriter(ostream&);
00161 ~BinaryModelWriter();
00162
00163 virtual bool write(const Model&);
00164
00165 private:
00166 void writeMesh(const Mesh&);
00167 void writeMaterial(const Mesh::Material&);
00168 void writeGroup(const Mesh::PrimitiveGroup&);
00169 void writeVertexDescription(const Mesh::VertexDescription&);
00170 void writeVertices(const void* vertexData,
00171 uint32 nVertices,
00172 uint32 stride,
00173 const Mesh::VertexDescription& desc);
00174
00175 ostream& out;
00176 };
00177
00178
00179 ModelLoader::ModelLoader()
00180 {
00181 }
00182
00183
00184 ModelLoader::~ModelLoader()
00185 {
00186 }
00187
00188
00189 void
00190 ModelLoader::reportError(const string& msg)
00191 {
00192 errorMessage = msg;
00193 }
00194
00195
00196 const string&
00197 ModelLoader::getErrorMessage() const
00198 {
00199 return errorMessage;
00200 }
00201
00202
00203 void
00204 ModelLoader::setTexturePath(const string& _texPath)
00205 {
00206 texPath = _texPath;
00207 }
00208
00209
00210 const string&
00211 ModelLoader::getTexturePath() const
00212 {
00213 return texPath;
00214 }
00215
00216
00217 Model* LoadModel(istream& in)
00218 {
00219 return LoadModel(in, "");
00220 }
00221
00222
00223 Model* LoadModel(istream& in, const string& texPath)
00224 {
00225 ModelLoader* loader = ModelLoader::OpenModel(in);
00226 if (loader == NULL)
00227 return NULL;
00228
00229 loader->setTexturePath(texPath);
00230
00231 Model* model = loader->load();
00232 if (model == NULL)
00233 cerr << "Error in model file: " << loader->getErrorMessage() << '\n';
00234
00235 delete loader;
00236
00237 return model;
00238 }
00239
00240
00241 ModelLoader*
00242 ModelLoader::OpenModel(istream& in)
00243 {
00244 char header[CEL_MODEL_HEADER_LENGTH + 1];
00245 memset(header, '\0', sizeof(header));
00246
00247 in.read(header, CEL_MODEL_HEADER_LENGTH);
00248 if (strcmp(header, CEL_MODEL_HEADER_ASCII) == 0)
00249 {
00250 return new AsciiModelLoader(in);
00251 }
00252 else if (strcmp(header, CEL_MODEL_HEADER_BINARY) == 0)
00253 {
00254 return new BinaryModelLoader(in);
00255 }
00256 else
00257 {
00258 cerr << "Model file has invalid header.\n";
00259 return NULL;
00260 }
00261 }
00262
00263
00264 bool SaveModelAscii(const Model* model, std::ostream& out)
00265 {
00266 if (model == NULL)
00267 return false;
00268
00269 AsciiModelWriter(out).write(*model);
00270
00271 return true;
00272 }
00273
00274
00275 bool SaveModelBinary(const Model* model, std::ostream& out)
00276 {
00277 if (model == NULL)
00278 return false;
00279
00280 BinaryModelWriter(out).write(*model);
00281
00282 return true;
00283 }
00284
00285
00286 AsciiModelLoader::AsciiModelLoader(istream& _in) :
00287 tok(&_in)
00288 {
00289 }
00290
00291
00292 AsciiModelLoader::~AsciiModelLoader()
00293 {
00294 }
00295
00296
00297 void
00298 AsciiModelLoader::reportError(const string& msg)
00299 {
00300 char buf[32];
00301 sprintf(buf, " (line %d)", tok.getLineNumber());
00302 ModelLoader::reportError(msg + string(buf));
00303 }
00304
00305
00306 Mesh::Material*
00307 AsciiModelLoader::loadMaterial()
00308 {
00309 if (tok.nextToken() != Tokenizer::TokenName ||
00310 tok.getNameValue() != "material")
00311 {
00312 reportError("Material definition expected");
00313 return NULL;
00314 }
00315
00316 Mesh::Material* material = new Mesh::Material();
00317
00318 material->diffuse = DefaultDiffuse;
00319 material->specular = DefaultSpecular;
00320 material->emissive = DefaultEmissive;
00321 material->specularPower = DefaultSpecularPower;
00322 material->opacity = DefaultOpacity;
00323
00324 while (tok.nextToken() == Tokenizer::TokenName &&
00325 tok.getNameValue() != "end_material")
00326 {
00327 string property = tok.getNameValue();
00328 Mesh::TextureSemantic texType = Mesh::parseTextureSemantic(property);
00329
00330 if (texType != Mesh::InvalidTextureSemantic)
00331 {
00332 if (tok.nextToken() != Tokenizer::TokenString)
00333 {
00334 reportError("Texture name expected");
00335 delete material;
00336 return NULL;
00337 }
00338
00339 ResourceHandle tex = GetTextureManager()->getHandle(TextureInfo(tok.getStringValue(), getTexturePath(), TextureInfo::WrapTexture));
00340
00341 material->maps[texType] = tex;
00342 }
00343 else
00344 {
00345
00346
00347 double data[3];
00348 int nValues = 3;
00349 if (property == "specpower" || property == "opacity")
00350 nValues = 1;
00351
00352 for (int i = 0; i < nValues; i++)
00353 {
00354 if (tok.nextToken() != Tokenizer::TokenNumber)
00355 {
00356 reportError("Bad property value in material");
00357 delete material;
00358 return NULL;
00359 }
00360 data[i] = tok.getNumberValue();
00361 }
00362
00363 Color colorVal;
00364 if (nValues == 3)
00365 colorVal = Color((float) data[0], (float) data[1], (float) data[2]);
00366
00367 if (property == "diffuse")
00368 material->diffuse = colorVal;
00369 else if (property == "specular")
00370 material->specular = colorVal;
00371 else if (property == "emissive")
00372 material->emissive = colorVal;
00373 else if (property == "opacity")
00374 material->opacity = (float) data[0];
00375 else if (property == "specpower")
00376 material->specularPower = (float) data[0];
00377 }
00378 }
00379
00380 if (tok.getTokenType() != Tokenizer::TokenName)
00381 {
00382 delete material;
00383 return NULL;
00384 }
00385 else
00386 {
00387 return material;
00388 }
00389 }
00390
00391
00392 Mesh::VertexDescription*
00393 AsciiModelLoader::loadVertexDescription()
00394 {
00395 if (tok.nextToken() != Tokenizer::TokenName ||
00396 tok.getNameValue() != "vertexdesc")
00397 {
00398 reportError("Vertex description expected");
00399 return NULL;
00400 }
00401
00402 int maxAttributes = 16;
00403 int nAttributes = 0;
00404 uint32 offset = 0;
00405 Mesh::VertexAttribute* attributes = new Mesh::VertexAttribute[maxAttributes];
00406
00407 while (tok.nextToken() == Tokenizer::TokenName &&
00408 tok.getNameValue() != "end_vertexdesc")
00409 {
00410 string semanticName;
00411 string formatName;
00412 bool valid = false;
00413
00414 if (nAttributes == maxAttributes)
00415 {
00416
00417
00418 reportError("Attribute limit exceeded in vertex description");
00419 delete[] attributes;
00420 return NULL;
00421 }
00422
00423 semanticName = tok.getNameValue();
00424
00425 if (tok.nextToken() == Tokenizer::TokenName)
00426 {
00427 formatName = tok.getNameValue();
00428 valid = true;
00429 }
00430
00431 if (!valid)
00432 {
00433 reportError("Invalid vertex description");
00434 delete[] attributes;
00435 return NULL;
00436 }
00437
00438 Mesh::VertexAttributeSemantic semantic =
00439 Mesh::parseVertexAttributeSemantic(semanticName);
00440 if (semantic == Mesh::InvalidSemantic)
00441 {
00442 reportError(string("Invalid vertex attribute semantic '") +
00443 semanticName + "'");
00444 delete[] attributes;
00445 return NULL;
00446 }
00447
00448 Mesh::VertexAttributeFormat format =
00449 Mesh::parseVertexAttributeFormat(formatName);
00450 if (format == Mesh::InvalidFormat)
00451 {
00452 reportError(string("Invalid vertex attribute format '") +
00453 formatName + "'");
00454 delete[] attributes;
00455 return NULL;
00456 }
00457
00458 attributes[nAttributes].semantic = semantic;
00459 attributes[nAttributes].format = format;
00460 attributes[nAttributes].offset = offset;
00461
00462 offset += Mesh::getVertexAttributeSize(format);
00463 nAttributes++;
00464 }
00465
00466 if (tok.getTokenType() != Tokenizer::TokenName)
00467 {
00468 reportError("Invalid vertex description");
00469 delete[] attributes;
00470 return NULL;
00471 }
00472
00473 if (nAttributes == 0)
00474 {
00475 reportError("Vertex definitition cannot be empty");
00476 delete[] attributes;
00477 return NULL;
00478 }
00479
00480 return new Mesh::VertexDescription(offset, nAttributes, attributes);
00481 }
00482
00483
00484 char*
00485 AsciiModelLoader::loadVertices(const Mesh::VertexDescription& vertexDesc,
00486 uint32& vertexCount)
00487 {
00488 if (tok.nextToken() != Tokenizer::TokenName ||
00489 tok.getNameValue() != "vertices")
00490 {
00491 reportError("Vertex data expected");
00492 return NULL;
00493 }
00494
00495 if (tok.nextToken() != Tokenizer::TokenNumber)
00496 {
00497 reportError("Vertex count expected");
00498 return NULL;
00499 }
00500
00501 double num = tok.getNumberValue();
00502 if (num != floor(num) || num <= 0.0)
00503 {
00504 reportError("Bad vertex count for mesh");
00505 return NULL;
00506 }
00507
00508 vertexCount = (uint32) num;
00509 uint32 vertexDataSize = vertexDesc.stride * vertexCount;
00510 char* vertexData = new char[vertexDataSize];
00511 if (vertexData == NULL)
00512 {
00513 reportError("Not enough memory to hold vertex data");
00514 return NULL;
00515 }
00516
00517 uint32 offset = 0;
00518 double data[4];
00519 for (uint32 i = 0; i < vertexCount; i++, offset += vertexDesc.stride)
00520 {
00521 assert(offset < vertexDataSize);
00522 for (uint32 attr = 0; attr < vertexDesc.nAttributes; attr++)
00523 {
00524 Mesh::VertexAttributeFormat fmt = vertexDesc.attributes[attr].format;
00525 uint32 nBytes = Mesh::getVertexAttributeSize(fmt);
00526 int readCount = 0;
00527 switch (fmt)
00528 {
00529 case Mesh::Float1:
00530 readCount = 1;
00531 break;
00532 case Mesh::Float2:
00533 readCount = 2;
00534 break;
00535 case Mesh::Float3:
00536 readCount = 3;
00537 break;
00538 case Mesh::Float4:
00539 case Mesh::UByte4:
00540 readCount = 4;
00541 break;
00542 default:
00543 assert(0);
00544 delete[] vertexData;
00545 return NULL;
00546 }
00547
00548 for (int j = 0; j < readCount; j++)
00549 {
00550 if (tok.nextToken() != Tokenizer::TokenNumber)
00551 {
00552 reportError("Error in vertex data");
00553 delete[] vertexData;
00554 }
00555 data[j] = tok.getNumberValue();
00556
00557
00558 }
00559
00560 uint32 base = offset + vertexDesc.attributes[attr].offset;
00561 if (fmt == Mesh::UByte4)
00562 {
00563 for (int k = 0; k < readCount; k++)
00564 {
00565 reinterpret_cast<unsigned char*>(vertexData + base)[k] =
00566 (unsigned char) (data[k]);
00567 }
00568 }
00569 else
00570 {
00571 for (int k = 0; k < readCount; k++)
00572 reinterpret_cast<float*>(vertexData + base)[k] = (float) data[k];
00573 }
00574 }
00575 }
00576
00577 return vertexData;
00578 }
00579
00580
00581 Mesh*
00582 AsciiModelLoader::loadMesh()
00583 {
00584 if (tok.nextToken() != Tokenizer::TokenName ||
00585 tok.getNameValue() != "mesh")
00586 {
00587 reportError("Mesh definition expected");
00588 return NULL;
00589 }
00590
00591 Mesh::VertexDescription* vertexDesc = loadVertexDescription();
00592 if (vertexDesc == NULL)
00593 return NULL;
00594
00595 uint32 vertexCount = 0;
00596 char* vertexData = loadVertices(*vertexDesc, vertexCount);
00597 if (vertexData == NULL)
00598 return NULL;
00599
00600 Mesh* mesh = new Mesh();
00601 mesh->setVertexDescription(*vertexDesc);
00602 mesh->setVertices(vertexCount, vertexData);
00603
00604 while (tok.nextToken() == Tokenizer::TokenName &&
00605 tok.getNameValue() != "end_mesh")
00606 {
00607 Mesh::PrimitiveGroupType type =
00608 Mesh::parsePrimitiveGroupType(tok.getNameValue());
00609 if (type == Mesh::InvalidPrimitiveGroupType)
00610 {
00611 reportError("Bad primitive group type: " + tok.getNameValue());
00612 delete mesh;
00613 return NULL;
00614 }
00615
00616 if (tok.nextToken() != Tokenizer::TokenNumber)
00617 {
00618 reportError("Material index expected in primitive group");
00619 delete mesh;
00620 return NULL;
00621 }
00622
00623 uint32 materialIndex;
00624 if (tok.getNumberValue() == -1.0)
00625 materialIndex = ~0;
00626 else
00627 materialIndex = (uint32) tok.getNumberValue();
00628
00629 if (tok.nextToken() != Tokenizer::TokenNumber)
00630 {
00631 reportError("Index count expected in primitive group");
00632 delete mesh;
00633 return NULL;
00634 }
00635
00636 uint32 indexCount = (uint32) tok.getNumberValue();
00637
00638 uint32* indices = new uint32[indexCount];
00639 if (indices == NULL)
00640 {
00641 reportError("Not enough memory to hold indices");
00642 delete mesh;
00643 return NULL;
00644 }
00645
00646 for (uint32 i = 0; i < indexCount; i++)
00647 {
00648 if (tok.nextToken() != Tokenizer::TokenNumber)
00649 {
00650 reportError("Incomplete index list in primitive group");
00651 delete indices;
00652 delete mesh;
00653 return NULL;
00654 }
00655
00656 uint32 index = (uint32) tok.getNumberValue();
00657 if (index >= vertexCount)
00658 {
00659 reportError("Index out of range");
00660 delete indices;
00661 delete mesh;
00662 return NULL;
00663 }
00664
00665 indices[i] = index;
00666 }
00667
00668 mesh->addGroup(type, materialIndex, indexCount, indices);
00669 }
00670
00671 return mesh;
00672 }
00673
00674
00675 Model*
00676 AsciiModelLoader::load()
00677 {
00678 Model* model = new Model();
00679 bool seenMeshes = false;
00680
00681 if (model == NULL)
00682 {
00683 reportError("Unable to allocate memory for model");
00684 return NULL;
00685 }
00686
00687
00688 for (;;)
00689 {
00690 Tokenizer::TokenType ttype = tok.nextToken();
00691
00692 if (ttype == Tokenizer::TokenEnd)
00693 {
00694 break;
00695 }
00696 else if (ttype == Tokenizer::TokenName)
00697 {
00698 string name = tok.getNameValue();
00699 tok.pushBack();
00700
00701 if (name == "material")
00702 {
00703 if (seenMeshes)
00704 {
00705 reportError("Materials must be defined before meshes");
00706 delete model;
00707 return NULL;
00708 }
00709
00710 Mesh::Material* material = loadMaterial();
00711 if (material == NULL)
00712 {
00713 delete model;
00714 return NULL;
00715 }
00716
00717 model->addMaterial(material);
00718 }
00719 else if (name == "mesh")
00720 {
00721 seenMeshes = true;
00722
00723 Mesh* mesh = loadMesh();
00724 if (mesh == NULL)
00725 {
00726 delete model;
00727 return NULL;
00728 }
00729
00730 model->addMesh(mesh);
00731 }
00732 else
00733 {
00734 reportError(string("Error: Unknown block type ") + name);
00735 delete model;
00736 return NULL;
00737 }
00738 }
00739 else
00740 {
00741 reportError("Block name expected");
00742 return NULL;
00743 }
00744 }
00745
00746 return model;
00747 }
00748
00749
00750
00751 AsciiModelWriter::AsciiModelWriter(ostream& _out) :
00752 out(_out)
00753 {
00754 }
00755
00756
00757 AsciiModelWriter::~AsciiModelWriter()
00758 {
00759 }
00760
00761
00762 bool
00763 AsciiModelWriter::write(const Model& model)
00764 {
00765 out << CEL_MODEL_HEADER_ASCII << "\n\n";
00766
00767 for (uint32 matIndex = 0; model.getMaterial(matIndex); matIndex++)
00768 {
00769 writeMaterial(*model.getMaterial(matIndex));
00770 out << '\n';
00771 }
00772
00773 for (uint32 meshIndex = 0; model.getMesh(meshIndex); meshIndex++)
00774 {
00775 writeMesh(*model.getMesh(meshIndex));
00776 out << '\n';
00777 }
00778
00779 return true;
00780 }
00781
00782
00783 void
00784 AsciiModelWriter::writeGroup(const Mesh::PrimitiveGroup& group)
00785 {
00786 switch (group.prim)
00787 {
00788 case Mesh::TriList:
00789 out << "trilist"; break;
00790 case Mesh::TriStrip:
00791 out << "tristrip"; break;
00792 case Mesh::TriFan:
00793 out << "trifan"; break;
00794 case Mesh::LineList:
00795 out << "linelist"; break;
00796 case Mesh::LineStrip:
00797 out << "linestrip"; break;
00798 case Mesh::PointList:
00799 out << "points"; break;
00800 default:
00801 return;
00802 }
00803
00804 out << ' ' << group.materialIndex << ' ' << group.nIndices << '\n';
00805
00806
00807 for (uint32 i = 0; i < group.nIndices; i++)
00808 {
00809 out << group.indices[i];
00810 if (i % 12 == 11 || i == group.nIndices - 1)
00811 out << '\n';
00812 else
00813 out << ' ';
00814 }
00815 }
00816
00817
00818 void
00819 AsciiModelWriter::writeMesh(const Mesh& mesh)
00820 {
00821 out << "mesh\n";
00822
00823 if (!mesh.getName().empty())
00824 out << "# " << mesh.getName() << '\n';
00825
00826 writeVertexDescription(mesh.getVertexDescription());
00827 out << '\n';
00828
00829 writeVertices(mesh.getVertexData(),
00830 mesh.getVertexCount(),
00831 mesh.getVertexStride(),
00832 mesh.getVertexDescription());
00833 out << '\n';
00834
00835 for (uint32 groupIndex = 0; mesh.getGroup(groupIndex); groupIndex++)
00836 {
00837 writeGroup(*mesh.getGroup(groupIndex));
00838 out << '\n';
00839 }
00840
00841 out << "end_mesh\n";
00842 }
00843
00844
00845 void
00846 AsciiModelWriter::writeVertices(const void* vertexData,
00847 uint32 nVertices,
00848 uint32 stride,
00849 const Mesh::VertexDescription& desc)
00850 {
00851 const unsigned char* vertex = reinterpret_cast<const unsigned char*>(vertexData);
00852
00853 out << "vertices " << nVertices << '\n';
00854 for (uint32 i = 0; i < nVertices; i++, vertex += stride)
00855 {
00856 for (uint32 attr = 0; attr < desc.nAttributes; attr++)
00857 {
00858 const unsigned char* ubdata = vertex + desc.attributes[attr].offset;
00859 const float* fdata = reinterpret_cast<const float*>(ubdata);
00860
00861 switch (desc.attributes[attr].format)
00862 {
00863 case Mesh::Float1:
00864 out << fdata[0];
00865 break;
00866 case Mesh::Float2:
00867 out << fdata[0] << ' ' << fdata[1];
00868 break;
00869 case Mesh::Float3:
00870 out << fdata[0] << ' ' << fdata[1] << ' ' << fdata[2];
00871 break;
00872 case Mesh::Float4:
00873 out << fdata[0] << ' ' << fdata[1] << ' ' <<
00874 fdata[2] << ' ' << fdata[3];
00875 break;
00876 case Mesh::UByte4:
00877 out << (int) ubdata[0] << ' ' << (int) ubdata[1] << ' ' <<
00878 (int) ubdata[2] << ' ' << (int) ubdata[3];
00879 break;
00880 default:
00881 assert(0);
00882 break;
00883 }
00884
00885 out << ' ';
00886 }
00887
00888 out << '\n';
00889 }
00890 }
00891
00892
00893 void
00894 AsciiModelWriter::writeVertexDescription(const Mesh::VertexDescription& desc)
00895 {
00896 out << "vertexdesc\n";
00897 for (uint32 attr = 0; attr < desc.nAttributes; attr++)
00898 {
00899
00900
00901
00902 switch (desc.attributes[attr].semantic)
00903 {
00904 case Mesh::Position:
00905 out << "position";
00906 break;
00907 case Mesh::Color0:
00908 out << "color0";
00909 break;
00910 case Mesh::Color1:
00911 out << "color1";
00912 break;
00913 case Mesh::Normal:
00914 out << "normal";
00915 break;
00916 case Mesh::Tangent:
00917 out << "tangent";
00918 break;
00919 case Mesh::Texture0:
00920 out << "texcoord0";
00921 break;
00922 case Mesh::Texture1:
00923 out << "texcoord1";
00924 break;
00925 case Mesh::Texture2:
00926 out << "texcoord2";
00927 break;
00928 case Mesh::Texture3:
00929 out << "texcoord3";
00930 break;
00931 default:
00932 assert(0);
00933 break;
00934 }
00935
00936 out << ' ';
00937
00938 switch (desc.attributes[attr].format)
00939 {
00940 case Mesh::Float1:
00941 out << "f1";
00942 break;
00943 case Mesh::Float2:
00944 out << "f2";
00945 break;
00946 case Mesh::Float3:
00947 out << "f3";
00948 break;
00949 case Mesh::Float4:
00950 out << "f4";
00951 break;
00952 case Mesh::UByte4:
00953 out << "ub4";
00954 break;
00955 default:
00956 assert(0);
00957 break;
00958 }
00959
00960 out << '\n';
00961 }
00962 out << "end_vertexdesc\n";
00963 }
00964
00965
00966 void
00967 AsciiModelWriter::writeMaterial(const Mesh::Material& material)
00968 {
00969 out << "material\n";
00970 if (material.diffuse != DefaultDiffuse)
00971 {
00972 out << "diffuse " <<
00973 material.diffuse.red() << ' ' <<
00974 material.diffuse.green() << ' ' <<
00975 material.diffuse.blue() << '\n';
00976 }
00977
00978 if (material.emissive != DefaultEmissive)
00979 {
00980 out << "emissive " <<
00981 material.emissive.red() << ' ' <<
00982 material.emissive.green() << ' ' <<
00983 material.emissive.blue() << '\n';
00984 }
00985
00986 if (material.specular != DefaultSpecular)
00987 {
00988 out << "specular " <<
00989 material.specular.red() << ' ' <<
00990 material.specular.green() << ' ' <<
00991 material.specular.blue() << '\n';
00992 }
00993
00994 if (material.specularPower != DefaultSpecularPower)
00995 out << "specpower " << material.specularPower << '\n';
00996
00997 if (material.opacity != DefaultOpacity)
00998 out << "opacity " << material.opacity << '\n';
00999
01000 for (int i = 0; i < Mesh::TextureSemanticMax; i++)
01001 {
01002 const TextureInfo* texInfo = GetTextureManager()->getResourceInfo(material.maps[i]);
01003 if (texInfo != NULL)
01004 {
01005 switch (Mesh::TextureSemantic(i))
01006 {
01007 case Mesh::DiffuseMap:
01008 out << "texture0";
01009 break;
01010 case Mesh::NormalMap:
01011 out << "normalmap";
01012 break;
01013 case Mesh::SpecularMap:
01014 out << "specularmap";
01015 break;
01016 case Mesh::EmissiveMap:
01017 out << "emissivemap";
01018 break;
01019 default:
01020 assert(0);
01021 }
01022
01023 out << " \"" << texInfo->source << "\"\n";
01024 }
01025 }
01026
01027 #if 0
01028 if (material.maps[Mesh::DiffuseMap] != InvalidResource)
01029 {
01030 const TextureInfo* texInfo = GetTextureManager()->getResourceInfo(material.tex0);
01031 if (texInfo != NULL)
01032 out << "texture0 \"" << texInfo->source << "\"\n";
01033 }
01034
01035 if (material.tex1 != InvalidResource)
01036 {
01037 const TextureInfo* texInfo = GetTextureManager()->getResourceInfo(material.tex1);
01038 if (texInfo != NULL)
01039 out << "texture1 \"" << texInfo->source << "\"\n";
01040 }
01041 #endif
01042
01043
01044 out << "end_material\n";
01045 }
01046
01047
01048
01049
01050 BinaryModelLoader::BinaryModelLoader(istream& _in) :
01051 in(_in)
01052 {
01053 }
01054
01055
01056 BinaryModelLoader::~BinaryModelLoader()
01057 {
01058 }
01059
01060
01061 void
01062 BinaryModelLoader::reportError(const string& msg)
01063 {
01064 char buf[32];
01065 sprintf(buf, " (offset %d)", 0);
01066 ModelLoader::reportError(msg + string(buf));
01067 }
01068
01069
01070
01071 static int32 readUint(istream& in)
01072 {
01073 int32 ret;
01074 in.read((char*) &ret, sizeof(int32));
01075 LE_TO_CPU_INT32(ret, ret);
01076 return (uint32) ret;
01077 }
01078
01079
01080 static float readFloat(istream& in)
01081 {
01082 int i = readUint(in);
01083 return *((float*) &i);
01084 }
01085
01086
01087 static int16 readInt16(istream& in)
01088 {
01089 int16 ret;
01090 in.read((char *) &ret, sizeof(int16));
01091 LE_TO_CPU_INT16(ret, ret);
01092 return ret;
01093 }
01094
01095
01096 static ModelFileToken readToken(istream& in)
01097 {
01098 return (ModelFileToken) readInt16(in);
01099 }
01100
01101
01102 static ModelFileType readType(istream& in)
01103 {
01104 return (ModelFileType) readInt16(in);
01105 }
01106
01107
01108 static bool readTypeFloat1(istream& in, float& f)
01109 {
01110 if (readType(in) != CMOD_Float1)
01111 return false;
01112 f = readFloat(in);
01113 return true;
01114 }
01115
01116
01117 static bool readTypeColor(istream& in, Color& c)
01118 {
01119 if (readType(in) != CMOD_Color)
01120 return false;
01121
01122 float r = readFloat(in);
01123 float g = readFloat(in);
01124 float b = readFloat(in);
01125 c = Color(r, g, b);
01126
01127 return true;
01128 }
01129
01130
01131 static bool readTypeString(istream& in, string& s)
01132 {
01133 if (readType(in) != CMOD_String)
01134 return false;
01135
01136 uint16 len;
01137 in.read((char*) &len, sizeof(uint16));
01138 LE_TO_CPU_INT16(len, len);
01139
01140 if (len == 0)
01141 {
01142 s = "";
01143 }
01144 else
01145 {
01146 char* buf = new char[len];
01147 in.read(buf, len);
01148 s = string(buf, len);
01149 delete[] buf;
01150 }
01151
01152 return true;
01153 }
01154
01155
01156 static bool ignoreValue(istream& in)
01157 {
01158 ModelFileType type = readType(in);
01159 int size = 0;
01160
01161 switch (type)
01162 {
01163 case CMOD_Float1:
01164 size = 4;
01165 break;
01166 case CMOD_Float2:
01167 size = 8;
01168 break;
01169 case CMOD_Float3:
01170 size = 12;
01171 break;
01172 case CMOD_Float4:
01173 size = 16;
01174 break;
01175 case CMOD_Uint32:
01176 size = 4;
01177 break;
01178 case CMOD_Color:
01179 size = 12;
01180 break;
01181 case CMOD_String:
01182 {
01183 uint16 len;
01184 in.read((char*) &len, sizeof(uint16));
01185 LE_TO_CPU_INT16(len, len);
01186 size = len;
01187 }
01188 break;
01189
01190 default:
01191 return false;
01192 }
01193
01194 in.ignore(size);
01195
01196 return true;
01197 }
01198
01199
01200 Model*
01201 BinaryModelLoader::load()
01202 {
01203 Model* model = new Model();
01204 bool seenMeshes = false;
01205
01206 if (model == NULL)
01207 {
01208 reportError("Unable to allocate memory for model");
01209 return NULL;
01210 }
01211
01212
01213 for (;;)
01214 {
01215 ModelFileToken tok = readToken(in);
01216
01217 if (in.eof())
01218 {
01219 break;
01220 }
01221 else if (tok == CMOD_Material)
01222 {
01223 if (seenMeshes)
01224 {
01225 reportError("Materials must be defined before meshes");
01226 delete model;
01227 return NULL;
01228 }
01229
01230 Mesh::Material* material = loadMaterial();
01231 if (material == NULL)
01232 {
01233 delete model;
01234 return NULL;
01235 }
01236
01237 model->addMaterial(material);
01238 }
01239 else if (tok == CMOD_Mesh)
01240 {
01241 seenMeshes = true;
01242
01243 Mesh* mesh = loadMesh();
01244 if (mesh == NULL)
01245 {
01246 delete model;
01247 return NULL;
01248 }
01249
01250 model->addMesh(mesh);
01251 }
01252 else
01253 {
01254 reportError("Error: Unknown block type in model");
01255 delete model;
01256 return NULL;
01257 }
01258 }
01259
01260 return model;
01261 }
01262
01263
01264 Mesh::Material*
01265 BinaryModelLoader::loadMaterial()
01266 {
01267 Mesh::Material* material = new Mesh::Material();
01268
01269 material->diffuse = DefaultDiffuse;
01270 material->specular = DefaultSpecular;
01271 material->emissive = DefaultEmissive;
01272 material->specularPower = DefaultSpecularPower;
01273 material->opacity = DefaultOpacity;
01274
01275 for (;;)
01276 {
01277 ModelFileToken tok = readToken(in);
01278 switch (tok)
01279 {
01280 case CMOD_Diffuse:
01281 if (!readTypeColor(in, material->diffuse))
01282 {
01283 reportError("Incorrect type for diffuse color");
01284 delete material;
01285 return NULL;
01286 }
01287 break;
01288
01289 case CMOD_Specular:
01290 if (!readTypeColor(in, material->specular))
01291 {
01292 reportError("Incorrect type for specular color");
01293 delete material;
01294 return NULL;
01295 }
01296 break;
01297
01298 case CMOD_Emissive:
01299 if (!readTypeColor(in, material->emissive))
01300 {
01301 reportError("Incorrect type for emissive color");
01302 delete material;
01303 return NULL;
01304 }
01305 break;
01306
01307 case CMOD_SpecularPower:
01308 if (!readTypeFloat1(in, material->specularPower))
01309 {
01310 reportError("Float expected for specularPower");
01311 delete material;
01312 return NULL;
01313 }
01314 break;
01315
01316 case CMOD_Opacity:
01317 if (!readTypeFloat1(in, material->opacity))
01318 {
01319 reportError("Float expected for opacity");
01320 delete material;
01321 return NULL;
01322 }
01323 break;
01324
01325 case CMOD_Texture:
01326 {
01327 int16 texType = readInt16(in);
01328 if (texType < 0 || texType >= Mesh::TextureSemanticMax)
01329 {
01330 reportError("Bad texture type");
01331 delete material;
01332 return NULL;
01333 }
01334
01335 string texfile;
01336 if (!readTypeString(in, texfile))
01337 {
01338 reportError("String expected for texture filename");
01339 delete material;
01340 return NULL;
01341 }
01342
01343 if (texfile.empty())
01344 {
01345 reportError("Zero length texture name in material definition");
01346 delete material;
01347 return NULL;
01348 }
01349
01350 ResourceHandle tex = GetTextureManager()->getHandle(TextureInfo(texfile, getTexturePath(), TextureInfo::WrapTexture));
01351
01352 material->maps[texType] = tex;
01353 }
01354 break;
01355
01356 case CMOD_EndMaterial:
01357 return material;
01358
01359 default:
01360
01361 if (!ignoreValue(in))
01362 {
01363 delete material;
01364 return NULL;
01365 }
01366 }
01367 }
01368 }
01369
01370
01371 Mesh::VertexDescription*
01372 BinaryModelLoader::loadVertexDescription()
01373 {
01374 if (readToken(in) != CMOD_VertexDesc)
01375 {
01376 reportError("Vertex description expected");
01377 return NULL;
01378 }
01379
01380 int maxAttributes = 16;
01381 int nAttributes = 0;
01382 uint32 offset = 0;
01383 Mesh::VertexAttribute* attributes = new Mesh::VertexAttribute[maxAttributes];
01384
01385 for (;;)
01386 {
01387 int16 tok = readInt16(in);
01388
01389 if (tok == CMOD_EndVertexDesc)
01390 {
01391 break;
01392 }
01393 else if (tok >= 0 && tok < Mesh::SemanticMax)
01394 {
01395 int16 fmt = readInt16(in);
01396 if (fmt < 0 || fmt >= Mesh::FormatMax)
01397 {
01398 reportError("Invalid vertex attribute type");
01399 delete[] attributes;
01400 return NULL;
01401 }
01402 else
01403 {
01404 if (nAttributes == maxAttributes)
01405 {
01406 reportError("Too many attributes in vertex description");
01407 delete[] attributes;
01408 return NULL;
01409 }
01410
01411 attributes[nAttributes].semantic =
01412 static_cast<Mesh::VertexAttributeSemantic>(tok);
01413 attributes[nAttributes].format =
01414 static_cast<Mesh::VertexAttributeFormat>(fmt);
01415 attributes[nAttributes].offset = offset;
01416
01417 offset += Mesh::getVertexAttributeSize(attributes[nAttributes].format);
01418 nAttributes++;
01419 }
01420 }
01421 else
01422 {
01423 reportError("Invalid semantic in vertex description");
01424 delete[] attributes;
01425 return NULL;
01426 }
01427 }
01428
01429 if (nAttributes == 0)
01430 {
01431 reportError("Vertex definitition cannot be empty");
01432 delete[] attributes;
01433 return NULL;
01434 }
01435
01436 return new Mesh::VertexDescription(offset, nAttributes, attributes);
01437 }
01438
01439
01440 Mesh*
01441 BinaryModelLoader::loadMesh()
01442 {
01443 Mesh::VertexDescription* vertexDesc = loadVertexDescription();
01444 if (vertexDesc == NULL)
01445 return NULL;
01446
01447 uint32 vertexCount = 0;
01448 char* vertexData = loadVertices(*vertexDesc, vertexCount);
01449 if (vertexData == NULL)
01450 return NULL;
01451
01452 Mesh* mesh = new Mesh();
01453 mesh->setVertexDescription(*vertexDesc);
01454 mesh->setVertices(vertexCount, vertexData);
01455
01456 for (;;)
01457 {
01458 int16 tok = readInt16(in);
01459
01460 if (tok == CMOD_EndMesh)
01461 {
01462 break;
01463 }
01464 else if (tok < 0 || tok >= Mesh::PrimitiveTypeMax)
01465 {
01466 reportError("Bad primitive group type");
01467 delete mesh;
01468 return NULL;
01469 }
01470
01471 Mesh::PrimitiveGroupType type =
01472 static_cast<Mesh::PrimitiveGroupType>(tok);
01473 uint32 materialIndex = readUint(in);
01474 uint32 indexCount = readUint(in);
01475
01476 uint32* indices = new uint32[indexCount];
01477 if (indices == NULL)
01478 {
01479 reportError("Not enough memory to hold indices");
01480 delete mesh;
01481 return NULL;
01482 }
01483
01484 for (uint32 i = 0; i < indexCount; i++)
01485 {
01486 uint32 index = readUint(in);
01487 if (index >= vertexCount)
01488 {
01489 reportError("Index out of range");
01490 delete indices;
01491 delete mesh;
01492 return NULL;
01493 }
01494
01495 indices[i] = index;
01496 }
01497
01498 mesh->addGroup(type, materialIndex, indexCount, indices);
01499 }
01500
01501 return mesh;
01502 }
01503
01504
01505 char*
01506 BinaryModelLoader::loadVertices(const Mesh::VertexDescription& vertexDesc,
01507 uint32& vertexCount)
01508 {
01509 if (readToken(in) != CMOD_Vertices)
01510 {
01511 reportError("Vertex data expected");
01512 return NULL;
01513 }
01514
01515 vertexCount = readUint(in);
01516 uint32 vertexDataSize = vertexDesc.stride * vertexCount;
01517 char* vertexData = new char[vertexDataSize];
01518 if (vertexData == NULL)
01519 {
01520 reportError("Not enough memory to hold vertex data");
01521 return NULL;
01522 }
01523
01524 uint32 offset = 0;
01525
01526 for (uint32 i = 0; i < vertexCount; i++, offset += vertexDesc.stride)
01527 {
01528 assert(offset < vertexDataSize);
01529 for (uint32 attr = 0; attr < vertexDesc.nAttributes; attr++)
01530 {
01531 uint32 base = offset + vertexDesc.attributes[attr].offset;
01532 Mesh::VertexAttributeFormat fmt = vertexDesc.attributes[attr].format;
01533 int readCount = 0;
01534 switch (fmt)
01535 {
01536 case Mesh::Float1:
01537 reinterpret_cast<float*>(vertexData + base)[0] = readFloat(in);
01538 break;
01539 case Mesh::Float2:
01540 reinterpret_cast<float*>(vertexData + base)[0] = readFloat(in);
01541 reinterpret_cast<float*>(vertexData + base)[1] = readFloat(in);
01542 break;
01543 case Mesh::Float3:
01544 reinterpret_cast<float*>(vertexData + base)[0] = readFloat(in);
01545 reinterpret_cast<float*>(vertexData + base)[1] = readFloat(in);
01546 reinterpret_cast<float*>(vertexData + base)[2] = readFloat(in);
01547 break;
01548 case Mesh::Float4:
01549 reinterpret_cast<float*>(vertexData + base)[0] = readFloat(in);
01550 reinterpret_cast<float*>(vertexData + base)[1] = readFloat(in);
01551 reinterpret_cast<float*>(vertexData + base)[2] = readFloat(in);
01552 reinterpret_cast<float*>(vertexData + base)[3] = readFloat(in);
01553 break;
01554 case Mesh::UByte4:
01555 in.get(reinterpret_cast<char*>(vertexData + base), 4);
01556 break;
01557 default:
01558 assert(0);
01559 delete[] vertexData;
01560 return NULL;
01561 }
01562 }
01563 }
01564
01565 return vertexData;
01566 }
01567
01568
01569
01570
01571
01572 BinaryModelWriter::BinaryModelWriter(ostream& _out) :
01573 out(_out)
01574 {
01575 }
01576
01577
01578 BinaryModelWriter::~BinaryModelWriter()
01579 {
01580 }
01581
01582
01583
01584 static void writeUint(ostream& out, uint32 val)
01585 {
01586 LE_TO_CPU_INT32(val, val);
01587 out.write(reinterpret_cast<char*>(&val), sizeof(uint32));
01588 }
01589
01590 static void writeFloat(ostream& out, float val)
01591 {
01592 LE_TO_CPU_FLOAT(val, val);
01593 out.write(reinterpret_cast<char*>(&val), sizeof(float));
01594 }
01595
01596 static void writeInt16(ostream& out, int16 val)
01597 {
01598 LE_TO_CPU_INT16(val, val);
01599 out.write(reinterpret_cast<char*>(&val), sizeof(int16));
01600 }
01601
01602 static void writeToken(ostream& out, ModelFileToken val)
01603 {
01604 writeInt16(out, static_cast<int16>(val));
01605 }
01606
01607 static void writeType(ostream& out, ModelFileType val)
01608 {
01609 writeInt16(out, static_cast<int16>(val));
01610 }
01611
01612
01613 static void writeTypeFloat1(ostream& out, float f)
01614 {
01615 writeType(out, CMOD_Float1);
01616 writeFloat(out, f);
01617 }
01618
01619
01620 static void writeTypeColor(ostream& out, const Color& c)
01621 {
01622 writeType(out, CMOD_Color);
01623 writeFloat(out, c.red());
01624 writeFloat(out, c.green());
01625 writeFloat(out, c.blue());
01626 }
01627
01628
01629 static void writeTypeString(ostream& out, const string& s)
01630 {
01631 writeType(out, CMOD_String);
01632 writeInt16(out, static_cast<int16>(s.length()));
01633 out.write(s.c_str(), s.length());
01634 }
01635
01636
01637 bool
01638 BinaryModelWriter::write(const Model& model)
01639 {
01640 out << CEL_MODEL_HEADER_BINARY;
01641
01642 for (uint32 matIndex = 0; model.getMaterial(matIndex); matIndex++)
01643 writeMaterial(*model.getMaterial(matIndex));
01644
01645 for (uint32 meshIndex = 0; model.getMesh(meshIndex); meshIndex++)
01646 writeMesh(*model.getMesh(meshIndex));
01647
01648 return true;
01649 }
01650
01651
01652 void
01653 BinaryModelWriter::writeGroup(const Mesh::PrimitiveGroup& group)
01654 {
01655 writeInt16(out, static_cast<int16>(group.prim));
01656 writeUint(out, group.materialIndex);
01657 writeUint(out, group.nIndices);
01658
01659
01660 for (uint32 i = 0; i < group.nIndices; i++)
01661 writeUint(out, group.indices[i]);
01662 }
01663
01664
01665 void
01666 BinaryModelWriter::writeMesh(const Mesh& mesh)
01667 {
01668 writeToken(out, CMOD_Mesh);
01669
01670 writeVertexDescription(mesh.getVertexDescription());
01671
01672 writeVertices(mesh.getVertexData(),
01673 mesh.getVertexCount(),
01674 mesh.getVertexStride(),
01675 mesh.getVertexDescription());
01676
01677 for (uint32 groupIndex = 0; mesh.getGroup(groupIndex); groupIndex++)
01678 writeGroup(*mesh.getGroup(groupIndex));
01679
01680 writeToken(out, CMOD_EndMesh);
01681 }
01682
01683
01684 void
01685 BinaryModelWriter::writeVertices(const void* vertexData,
01686 uint32 nVertices,
01687 uint32 stride,
01688 const Mesh::VertexDescription& desc)
01689 {
01690 const char* vertex = reinterpret_cast<const char*>(vertexData);
01691
01692 writeToken(out, CMOD_Vertices);
01693 writeUint(out, nVertices);
01694
01695 for (uint32 i = 0; i < nVertices; i++, vertex += stride)
01696 {
01697 for (uint32 attr = 0; attr < desc.nAttributes; attr++)
01698 {
01699 const char* cdata = vertex + desc.attributes[attr].offset;
01700 const float* fdata = reinterpret_cast<const float*>(cdata);
01701
01702 switch (desc.attributes[attr].format)
01703 {
01704 case Mesh::Float1:
01705 writeFloat(out, fdata[0]);
01706 break;
01707 case Mesh::Float2:
01708 writeFloat(out, fdata[0]);
01709 writeFloat(out, fdata[1]);
01710 break;
01711 case Mesh::Float3:
01712 writeFloat(out, fdata[0]);
01713 writeFloat(out, fdata[1]);
01714 writeFloat(out, fdata[2]);
01715 break;
01716 case Mesh::Float4:
01717 writeFloat(out, fdata[0]);
01718 writeFloat(out, fdata[1]);
01719 writeFloat(out, fdata[2]);
01720 writeFloat(out, fdata[3]);
01721 break;
01722 case Mesh::UByte4:
01723 out.write(cdata, 4);
01724 break;
01725 default:
01726 assert(0);
01727 break;
01728 }
01729 }
01730 }
01731 }
01732
01733
01734 void
01735 BinaryModelWriter::writeVertexDescription(const Mesh::VertexDescription& desc)
01736 {
01737 writeToken(out, CMOD_VertexDesc);
01738
01739 for (uint32 attr = 0; attr < desc.nAttributes; attr++)
01740 {
01741 writeInt16(out, static_cast<int16>(desc.attributes[attr].semantic));
01742 writeInt16(out, static_cast<int16>(desc.attributes[attr].format));
01743 }
01744
01745 writeToken(out, CMOD_EndVertexDesc);
01746 }
01747
01748
01749 void
01750 BinaryModelWriter::writeMaterial(const Mesh::Material& material)
01751 {
01752 writeToken(out, CMOD_Material);
01753
01754 if (material.diffuse != DefaultDiffuse)
01755 {
01756 writeToken(out, CMOD_Diffuse);
01757 writeTypeColor(out, material.diffuse);
01758 }
01759
01760 if (material.emissive != DefaultEmissive)
01761 {
01762 writeToken(out, CMOD_Emissive);
01763 writeTypeColor(out, material.emissive);
01764 }
01765
01766 if (material.specular != DefaultSpecular)
01767 {
01768 writeToken(out, CMOD_Specular);
01769 writeTypeColor(out, material.specular);
01770 }
01771
01772 if (material.specularPower != DefaultSpecularPower)
01773 {
01774 writeToken(out, CMOD_SpecularPower);
01775 writeTypeFloat1(out, material.specularPower);
01776 }
01777
01778 if (material.opacity != DefaultOpacity)
01779 {
01780 writeToken(out, CMOD_Opacity);
01781 writeTypeFloat1(out, material.opacity);
01782 }
01783
01784 for (int i = 0; i < Mesh::TextureSemanticMax; i++)
01785 {
01786 if (material.maps[i] != InvalidResource)
01787 {
01788 const TextureInfo* texInfo = GetTextureManager()->getResourceInfo(material.maps[i]);
01789 if (texInfo != NULL)
01790 {
01791 writeToken(out, CMOD_Texture);
01792 writeInt16(out, (int16) i);
01793 writeTypeString(out, texInfo->source);
01794 }
01795 }
01796 }
01797 #if 0
01798 if (material.tex1 != InvalidResource)
01799 {
01800 const TextureInfo* texInfo = GetTextureManager()->getResourceInfo(material.tex1);
01801 if (texInfo != NULL)
01802 {
01803 writeToken(out, CMOD_Texture1);
01804 writeTypeString(out, texInfo->source);
01805 }
01806 }
01807 #endif
01808
01809 writeToken(out, CMOD_EndMaterial);
01810 }