modelfile.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:47k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // modelfile.cpp
  2. //
  3. // Copyright (C) 2004, Chris Laurel <claurel@shatters.net>
  4. //
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. #include "modelfile.h"
  10. #include "tokenizer.h"
  11. #include "texmanager.h"
  12. #include <celutil/bytes.h>
  13. #include <cstring>
  14. #include <cassert>
  15. #include <cmath>
  16. #include <cstdio>
  17. using namespace std;
  18. // Material default values
  19. static Color DefaultDiffuse(0.0f, 0.0f, 0.0f);
  20. static Color DefaultSpecular(0.0f, 0.0f, 0.0f);
  21. static Color DefaultEmissive(0.0f, 0.0f, 0.0f);
  22. static float DefaultSpecularPower = 1.0f;
  23. static float DefaultOpacity = 1.0f;
  24. static Mesh::BlendMode DefaultBlend = Mesh::NormalBlend;
  25. /*!
  26. This is an approximate Backus Naur form for the contents of ASCII cmod
  27. files. For brevity, the categories &lt;unsigned_int&gt; and &lt;float&gt; aren't
  28. defined here--they have the obvious definitions.
  29. code
  30. <modelfile>           ::= <header> <model>
  31. <header>              ::= #celmodel__ascii
  32. <model>               ::= { <material_definition> } { <mesh_definition> }
  33. <material_definition> ::= material
  34.                           { <material_attribute> }
  35.                           end_material
  36. <texture_semantic>    ::= texture0       |
  37.                           normalmap      |
  38.                           specularmap    |
  39.                           emissivemap
  40. <texture>             ::= <texture_semantic> <string>
  41. <material_attribute>  ::= diffuse <color>   |
  42.                           specular <color>  |
  43.                           emissive <color>  |
  44.                           specpower <float> |
  45.                           opacity <float>   |
  46.                           blend <blendmode> |
  47.                           <texture>
  48. <color>               ::= <float> <float> <float>
  49. <string>              ::= """ { letter } """
  50. <blendmode>           ::= normal | add | premultiplied
  51. <mesh_definition>     ::= mesh
  52.                           <vertex_description>
  53.                           <vertex_pool>
  54.                           { <prim_group> }
  55.                           end_mesh
  56. <vertex_description>  ::= vertexdesc
  57.                           { <vertex_attribute> }
  58.                           end_vertexdesc
  59. <vertex_attribute>    ::= <vertex_semantic> <vertex_format>
  60. <vertex_semantic>     ::= position | normal | color0 | color1 | tangent |
  61.                           texcoord0 | texcoord1 | texcoord2 | texcoord3 |
  62.                           pointsize
  63. <vertex_format>       ::= f1 | f2 | f3 | f4 | ub4
  64. <vertex_pool>         ::= vertices <count>
  65.                           { <float> }
  66. <count>               ::= <unsigned_int>
  67. <prim_group>          ::= <prim_group_type> <material_index> <count>
  68.                           { <unsigned_int> }
  69. <prim_group_type>     ::= trilist | tristrip | trifan |
  70.                           linelist | linestrip | points |
  71.                           sprites
  72. <material_index>      :: <unsigned_int> | -1
  73. endcode
  74. */
  75. class AsciiModelLoader : public ModelLoader
  76. {
  77. public:
  78.     AsciiModelLoader(istream& _in);
  79.     ~AsciiModelLoader();
  80.     virtual Model* load();
  81.     virtual void reportError(const string&);
  82.     Mesh::Material*          loadMaterial();
  83.     Mesh::VertexDescription* loadVertexDescription();
  84.     Mesh*                    loadMesh();
  85.     char*                    loadVertices(const Mesh::VertexDescription& vertexDesc,
  86.                                           uint32& vertexCount);
  87. private:
  88.     Tokenizer tok;
  89. };
  90. class AsciiModelWriter : public ModelWriter
  91. {
  92. public:
  93.     AsciiModelWriter(ostream&);
  94.     ~AsciiModelWriter();
  95.     virtual bool write(const Model&);
  96. private:
  97.     void writeMesh(const Mesh&);
  98.     void writeMaterial(const Mesh::Material&);
  99.     void writeGroup(const Mesh::PrimitiveGroup&);
  100.     void writeVertexDescription(const Mesh::VertexDescription&);
  101.     void writeVertices(const void* vertexData,
  102.                        uint32 nVertices,
  103.                        uint32 stride,
  104.                        const Mesh::VertexDescription& desc);
  105.     ostream& out;
  106. };
  107. class BinaryModelLoader : public ModelLoader
  108. {
  109. public:
  110.     BinaryModelLoader(istream& _in);
  111.     ~BinaryModelLoader();
  112.     virtual Model* load();
  113.     virtual void reportError(const string&);
  114.     Mesh::Material*          loadMaterial();
  115.     Mesh::VertexDescription* loadVertexDescription();
  116.     Mesh*                    loadMesh();
  117.     char*                    loadVertices(const Mesh::VertexDescription& vertexDesc,
  118.                                           uint32& vertexCount);
  119. private:
  120.     istream& in;
  121. };
  122. class BinaryModelWriter : public ModelWriter
  123. {
  124. public:
  125.     BinaryModelWriter(ostream&);
  126.     ~BinaryModelWriter();
  127.     virtual bool write(const Model&);
  128. private:
  129.     void writeMesh(const Mesh&);
  130.     void writeMaterial(const Mesh::Material&);
  131.     void writeGroup(const Mesh::PrimitiveGroup&);
  132.     void writeVertexDescription(const Mesh::VertexDescription&);
  133.     void writeVertices(const void* vertexData,
  134.                        uint32 nVertices,
  135.                        uint32 stride,
  136.                        const Mesh::VertexDescription& desc);
  137.     ostream& out;
  138. };
  139. ModelLoader::ModelLoader()
  140. {
  141. }
  142. ModelLoader::~ModelLoader()
  143. {
  144. }
  145. void
  146. ModelLoader::reportError(const string& msg)
  147. {
  148.     errorMessage = msg;
  149. }
  150. const string&
  151. ModelLoader::getErrorMessage() const
  152. {
  153.     return errorMessage;
  154. }
  155. void
  156. ModelLoader::setTexturePath(const string& _texPath)
  157. {
  158.     texPath = _texPath;
  159. }
  160. const string&
  161. ModelLoader::getTexturePath() const
  162. {
  163.     return texPath;
  164. }
  165. Model* LoadModel(istream& in)
  166. {
  167.     return LoadModel(in, "");
  168. }
  169. Model* LoadModel(istream& in, const string& texPath)
  170. {
  171.     ModelLoader* loader = ModelLoader::OpenModel(in);
  172.     if (loader == NULL)
  173.         return NULL;
  174.     loader->setTexturePath(texPath);
  175.     Model* model = loader->load();
  176.     if (model == NULL)
  177.         cerr << "Error in model file: " << loader->getErrorMessage() << 'n';
  178.     delete loader;
  179.     return model;
  180. }
  181. ModelLoader*
  182. ModelLoader::OpenModel(istream& in)
  183. {
  184.     char header[CEL_MODEL_HEADER_LENGTH + 1];
  185.     memset(header, '', sizeof(header));
  186.     in.read(header, CEL_MODEL_HEADER_LENGTH);
  187.     if (strcmp(header, CEL_MODEL_HEADER_ASCII) == 0)
  188.     {
  189.         return new AsciiModelLoader(in);
  190.     }
  191.     else if (strcmp(header, CEL_MODEL_HEADER_BINARY) == 0)
  192.     {
  193.         return new BinaryModelLoader(in);
  194.     }
  195.     else
  196.     {
  197.         cerr << "Model file has invalid header.n";
  198.         return NULL;
  199.     }
  200. }
  201. bool SaveModelAscii(const Model* model, std::ostream& out)
  202. {
  203.     if (model == NULL)
  204.         return false;
  205.     AsciiModelWriter(out).write(*model);
  206.     return true;
  207. }
  208. bool SaveModelBinary(const Model* model, std::ostream& out)
  209. {
  210.     if (model == NULL)
  211.         return false;
  212.     BinaryModelWriter(out).write(*model);
  213.     return true;
  214. }
  215. AsciiModelLoader::AsciiModelLoader(istream& _in) :
  216.     tok(&_in)
  217. {
  218. }
  219. AsciiModelLoader::~AsciiModelLoader()
  220. {
  221. }
  222. void
  223. AsciiModelLoader::reportError(const string& msg)
  224. {
  225.     char buf[32];
  226.     sprintf(buf, " (line %d)", tok.getLineNumber());
  227.     ModelLoader::reportError(msg + string(buf));
  228. }
  229. Mesh::Material*
  230. AsciiModelLoader::loadMaterial()
  231. {
  232.     if (tok.nextToken() != Tokenizer::TokenName ||
  233.         tok.getNameValue() != "material")
  234.     {
  235.         reportError("Material definition expected");
  236.         return NULL;
  237.     }
  238.     Mesh::Material* material = new Mesh::Material();
  239.     material->diffuse = DefaultDiffuse;
  240.     material->specular = DefaultSpecular;
  241.     material->emissive = DefaultEmissive;
  242.     material->specularPower = DefaultSpecularPower;
  243.     material->opacity = DefaultOpacity;
  244.     while (tok.nextToken() == Tokenizer::TokenName &&
  245.            tok.getNameValue() != "end_material")
  246.     {
  247.         string property = tok.getNameValue();
  248.         Mesh::TextureSemantic texType = Mesh::parseTextureSemantic(property);
  249.         if (texType != Mesh::InvalidTextureSemantic)
  250.         {
  251.             if (tok.nextToken() != Tokenizer::TokenString)
  252.             {
  253.                 reportError("Texture name expected");
  254.                 delete material;
  255.                 return NULL;
  256.             }
  257.             ResourceHandle tex = GetTextureManager()->getHandle(TextureInfo(tok.getStringValue(), getTexturePath(), TextureInfo::WrapTexture));
  258.             material->maps[texType] = tex;
  259.         }
  260.         else if (property == "blend")
  261.         {
  262.             Mesh::BlendMode blendMode = Mesh::InvalidBlend;
  263.             if (tok.nextToken() == Tokenizer::TokenName)
  264.             {
  265.                 string blendModeName = tok.getNameValue();
  266.                 if (blendModeName == "normal")
  267.                     blendMode = Mesh::NormalBlend;
  268.                 else if (blendModeName == "add")
  269.                     blendMode = Mesh::AdditiveBlend;
  270.                 else if (blendModeName == "premultiplied")
  271.                     blendMode = Mesh::PremultipliedAlphaBlend;
  272.             }
  273.             if (blendMode == Mesh::InvalidBlend)
  274.             {
  275.                 reportError("Bad blend mode in material");
  276.                 delete material;
  277.                 return NULL;
  278.             }
  279.             material->blend = blendMode;
  280.         }
  281.         else
  282.         {
  283.             // All non-texture material properties are 3-vectors except
  284.             // specular power and opacity
  285.             double data[3];
  286.             int nValues = 3;
  287.             if (property == "specpower" || property == "opacity")
  288.                 nValues = 1;
  289.             for (int i = 0; i < nValues; i++)
  290.             {
  291.                 if (tok.nextToken() != Tokenizer::TokenNumber)
  292.                 {
  293.                     reportError("Bad property value in material");
  294.                     delete material;
  295.                     return NULL;
  296.                 }
  297.                 data[i] = tok.getNumberValue();
  298.             }
  299.             Color colorVal;
  300.             if (nValues == 3)
  301.                 colorVal = Color((float) data[0], (float) data[1], (float) data[2]);
  302.             if (property == "diffuse")
  303.                 material->diffuse = colorVal;
  304.             else if (property == "specular")
  305.                 material->specular = colorVal;
  306.             else if (property == "emissive")
  307.                 material->emissive = colorVal;
  308.             else if (property == "opacity")
  309.                 material->opacity = (float) data[0];
  310.             else if (property == "specpower")
  311.                 material->specularPower = (float) data[0];
  312.         }
  313.     }
  314.     if (tok.getTokenType() != Tokenizer::TokenName)
  315.     {
  316.         delete material;
  317.         return NULL;
  318.     }
  319.     else
  320.     {
  321.         return material;
  322.     }
  323. }
  324. Mesh::VertexDescription*
  325. AsciiModelLoader::loadVertexDescription()
  326. {
  327.     if (tok.nextToken() != Tokenizer::TokenName ||
  328.         tok.getNameValue() != "vertexdesc")
  329.     {
  330.         reportError("Vertex description expected");
  331.         return NULL;
  332.     }
  333.     int maxAttributes = 16;
  334.     int nAttributes = 0;
  335.     uint32 offset = 0;
  336.     Mesh::VertexAttribute* attributes = new Mesh::VertexAttribute[maxAttributes];
  337.     while (tok.nextToken() == Tokenizer::TokenName &&
  338.            tok.getNameValue() != "end_vertexdesc")
  339.     {
  340.         string semanticName;
  341.         string formatName;
  342.         bool valid = false;
  343.         if (nAttributes == maxAttributes)
  344.         {
  345.             // TODO: Should eliminate the attribute limit, though no real vertex
  346.             // will ever exceed it.
  347.             reportError("Attribute limit exceeded in vertex description");
  348.             delete[] attributes;
  349.             return NULL;
  350.         }
  351.         semanticName = tok.getNameValue();
  352.         if (tok.nextToken() == Tokenizer::TokenName)
  353.         {
  354.             formatName = tok.getNameValue();
  355.             valid = true;
  356.         }
  357.         if (!valid)
  358.         {
  359.             reportError("Invalid vertex description");
  360.             delete[] attributes;
  361.             return NULL;
  362.         }
  363.         Mesh::VertexAttributeSemantic semantic =
  364.             Mesh::parseVertexAttributeSemantic(semanticName);
  365.         if (semantic == Mesh::InvalidSemantic)
  366.         {
  367.             reportError(string("Invalid vertex attribute semantic '") +
  368.                         semanticName + "'");
  369.             delete[] attributes;
  370.             return NULL;
  371.         }
  372.         Mesh::VertexAttributeFormat format =
  373.             Mesh::parseVertexAttributeFormat(formatName);
  374.         if (format == Mesh::InvalidFormat)
  375.         {
  376.             reportError(string("Invalid vertex attribute format '") +
  377.                         formatName + "'");
  378.             delete[] attributes;
  379.             return NULL;
  380.         }
  381.         attributes[nAttributes].semantic = semantic;
  382.         attributes[nAttributes].format = format;
  383.         attributes[nAttributes].offset = offset;
  384.         offset += Mesh::getVertexAttributeSize(format);
  385.         nAttributes++;
  386.     }
  387.     if (tok.getTokenType() != Tokenizer::TokenName)
  388.     {
  389.         reportError("Invalid vertex description");
  390.         delete[] attributes;
  391.         return NULL;
  392.     }
  393.     if (nAttributes == 0)
  394.     {
  395.         reportError("Vertex definitition cannot be empty");
  396.         delete[] attributes;
  397.         return NULL;
  398.     }
  399.     Mesh::VertexDescription *vertexDesc =
  400.         new Mesh::VertexDescription(offset, nAttributes, attributes);
  401.     delete[] attributes;
  402.     return vertexDesc;
  403. }
  404. char*
  405. AsciiModelLoader::loadVertices(const Mesh::VertexDescription& vertexDesc,
  406.                                uint32& vertexCount)
  407. {
  408.     if (tok.nextToken() != Tokenizer::TokenName ||
  409.         tok.getNameValue() != "vertices")
  410.     {
  411.         reportError("Vertex data expected");
  412.         return NULL;
  413.     }
  414.     if (tok.nextToken() != Tokenizer::TokenNumber)
  415.     {
  416.         reportError("Vertex count expected");
  417.         return NULL;
  418.     }
  419.     double num = tok.getNumberValue();
  420.     if (num != floor(num) || num <= 0.0)
  421.     {
  422.         reportError("Bad vertex count for mesh");
  423.         return NULL;
  424.     }
  425.     vertexCount = (uint32) num;
  426.     uint32 vertexDataSize = vertexDesc.stride * vertexCount;
  427.     char* vertexData = new char[vertexDataSize];
  428.     if (vertexData == NULL)
  429.     {
  430.         reportError("Not enough memory to hold vertex data");
  431.         return NULL;
  432.     }
  433.     uint32 offset = 0;
  434.     double data[4];
  435.     for (uint32 i = 0; i < vertexCount; i++, offset += vertexDesc.stride)
  436.     {
  437.         assert(offset < vertexDataSize);
  438.         for (uint32 attr = 0; attr < vertexDesc.nAttributes; attr++)
  439.         {
  440.             Mesh::VertexAttributeFormat fmt = vertexDesc.attributes[attr].format;
  441.             /*uint32 nBytes = Mesh::getVertexAttributeSize(fmt);    Unused*/
  442.             int readCount = 0;
  443.             switch (fmt)
  444.             {
  445.             case Mesh::Float1:
  446.                 readCount = 1;
  447.                 break;
  448.             case Mesh::Float2:
  449.                 readCount = 2;
  450.                 break;
  451.             case Mesh::Float3:
  452.                 readCount = 3;
  453.                 break;
  454.             case Mesh::Float4:
  455.             case Mesh::UByte4:
  456.                 readCount = 4;
  457.                 break;
  458.             default:
  459.                 assert(0);
  460.                 delete[] vertexData;
  461.                 return NULL;
  462.             }
  463.             for (int j = 0; j < readCount; j++)
  464.             {
  465.                 if (tok.nextToken() != Tokenizer::TokenNumber)
  466.                 {
  467.                     reportError("Error in vertex data");
  468.                     data[j] = 0.0;
  469.                 }
  470.                 else
  471.                 {
  472.                     data[j] = tok.getNumberValue();
  473.                 }
  474.                 // TODO: range check unsigned byte values
  475.             }
  476.             uint32 base = offset + vertexDesc.attributes[attr].offset;
  477.             if (fmt == Mesh::UByte4)
  478.             {
  479.                 for (int k = 0; k < readCount; k++)
  480.                 {
  481.                     reinterpret_cast<unsigned char*>(vertexData + base)[k] =
  482.                         (unsigned char) (data[k]);
  483.                 }
  484.             }
  485.             else
  486.             {
  487.                 for (int k = 0; k < readCount; k++)
  488.                     reinterpret_cast<float*>(vertexData + base)[k] = (float) data[k];
  489.             }
  490.         }
  491.     }
  492.     return vertexData;
  493. }
  494. Mesh*
  495. AsciiModelLoader::loadMesh()
  496. {
  497.     if (tok.nextToken() != Tokenizer::TokenName ||
  498.         tok.getNameValue() != "mesh")
  499.     {
  500.         reportError("Mesh definition expected");
  501.         return NULL;
  502.     }
  503.     Mesh::VertexDescription* vertexDesc = loadVertexDescription();
  504.     if (vertexDesc == NULL)
  505.         return NULL;
  506.     uint32 vertexCount = 0;
  507.     char* vertexData = loadVertices(*vertexDesc, vertexCount);
  508.     if (vertexData == NULL)
  509.     {
  510.         delete vertexDesc;
  511.         return NULL;
  512.     }
  513.     Mesh* mesh = new Mesh();
  514.     mesh->setVertexDescription(*vertexDesc);
  515.     mesh->setVertices(vertexCount, vertexData);
  516.     delete vertexDesc;
  517.     while (tok.nextToken() == Tokenizer::TokenName &&
  518.            tok.getNameValue() != "end_mesh")
  519.     {
  520.         Mesh::PrimitiveGroupType type =
  521.             Mesh::parsePrimitiveGroupType(tok.getNameValue());
  522.         if (type == Mesh::InvalidPrimitiveGroupType)
  523.         {
  524.             reportError("Bad primitive group type: " + tok.getNameValue());
  525.             delete mesh;
  526.             return NULL;
  527.         }
  528.         if (tok.nextToken() != Tokenizer::TokenNumber)
  529.         {
  530.             reportError("Material index expected in primitive group");
  531.             delete mesh;
  532.             return NULL;
  533.         }
  534.         uint32 materialIndex;
  535.         if (tok.getNumberValue() == -1.0)
  536.             materialIndex = ~0u;
  537.         else
  538.             materialIndex = (uint32) tok.getNumberValue();
  539.         if (tok.nextToken() != Tokenizer::TokenNumber)
  540.         {
  541.             reportError("Index count expected in primitive group");
  542.             delete mesh;
  543.             return NULL;
  544.         }
  545.         uint32 indexCount = (uint32) tok.getNumberValue();
  546.         uint32* indices = new uint32[indexCount];
  547.         if (indices == NULL)
  548.         {
  549.             reportError("Not enough memory to hold indices");
  550.             delete mesh;
  551.             return NULL;
  552.         }
  553.         for (uint32 i = 0; i < indexCount; i++)
  554.         {
  555.             if (tok.nextToken() != Tokenizer::TokenNumber)
  556.             {
  557.                 reportError("Incomplete index list in primitive group");
  558.                 delete indices;
  559.                 delete mesh;
  560.                 return NULL;
  561.             }
  562.             uint32 index = (uint32) tok.getNumberValue();
  563.             if (index >= vertexCount)
  564.             {
  565.                 reportError("Index out of range");
  566.                 delete indices;
  567.                 delete mesh;
  568.                 return NULL;
  569.             }
  570.             indices[i] = index;
  571.         }
  572.         mesh->addGroup(type, materialIndex, indexCount, indices);
  573.     }
  574.     return mesh;
  575. }
  576. Model*
  577. AsciiModelLoader::load()
  578. {
  579.     Model* model = new Model();
  580.     bool seenMeshes = false;
  581.     if (model == NULL)
  582.     {
  583.         reportError("Unable to allocate memory for model");
  584.         return NULL;
  585.     }
  586.     // Parse material and mesh definitions
  587.     for (;;)
  588.     {
  589.         Tokenizer::TokenType ttype = tok.nextToken();
  590.         if (ttype == Tokenizer::TokenEnd)
  591.         {
  592.             break;
  593.         }
  594.         else if (ttype == Tokenizer::TokenName)
  595.         {
  596.             string name = tok.getNameValue();
  597.             tok.pushBack();
  598.             if (name == "material")
  599.             {
  600.                 if (seenMeshes)
  601.                 {
  602.                     reportError("Materials must be defined before meshes");
  603.                     delete model;
  604.                     return NULL;
  605.                 }
  606.                 Mesh::Material* material = loadMaterial();
  607.                 if (material == NULL)
  608.                 {
  609.                     delete model;
  610.                     return NULL;
  611.                 }
  612.                 model->addMaterial(material);
  613.             }
  614.             else if (name == "mesh")
  615.             {
  616.                 seenMeshes = true;
  617.                 Mesh* mesh = loadMesh();
  618.                 if (mesh == NULL)
  619.                 {
  620.                     delete model;
  621.                     return NULL;
  622.                 }
  623.                 model->addMesh(mesh);
  624.             }
  625.             else
  626.             {
  627.                 reportError(string("Error: Unknown block type ") + name);
  628.                 delete model;
  629.                 return NULL;
  630.             }
  631.         }
  632.         else
  633.         {
  634.             reportError("Block name expected");
  635.             return NULL;
  636.         }
  637.     }
  638.     return model;
  639. }
  640. AsciiModelWriter::AsciiModelWriter(ostream& _out) :
  641.     out(_out)
  642. {
  643. }
  644. AsciiModelWriter::~AsciiModelWriter()
  645. {
  646. }
  647. bool
  648. AsciiModelWriter::write(const Model& model)
  649. {
  650.     out << CEL_MODEL_HEADER_ASCII << "nn";
  651.     for (uint32 matIndex = 0; model.getMaterial(matIndex); matIndex++)
  652.     {
  653.         writeMaterial(*model.getMaterial(matIndex));
  654.         out << 'n';
  655.     }
  656.     for (uint32 meshIndex = 0; model.getMesh(meshIndex); meshIndex++)
  657.     {
  658.         writeMesh(*model.getMesh(meshIndex));
  659.         out << 'n';
  660.     }
  661.     return true;
  662. }
  663. void
  664. AsciiModelWriter::writeGroup(const Mesh::PrimitiveGroup& group)
  665. {
  666.     switch (group.prim)
  667.     {
  668.     case Mesh::TriList:
  669.         out << "trilist"; break;
  670.     case Mesh::TriStrip:
  671.         out << "tristrip"; break;
  672.     case Mesh::TriFan:
  673.         out << "trifan"; break;
  674.     case Mesh::LineList:
  675.         out << "linelist"; break;
  676.     case Mesh::LineStrip:
  677.         out << "linestrip"; break;
  678.     case Mesh::PointList:
  679.         out << "points"; break;
  680.     case Mesh::SpriteList:
  681.         out << "sprites"; break;
  682.     default:
  683.         return;
  684.     }
  685.     out << ' ' << group.materialIndex << ' ' << group.nIndices << 'n';
  686.     // Print the indices, twelve per line
  687.     for (uint32 i = 0; i < group.nIndices; i++)
  688.     {
  689.         out << group.indices[i];
  690.         if (i % 12 == 11 || i == group.nIndices - 1)
  691.             out << 'n';
  692.         else
  693.             out << ' ';
  694.     }
  695. }
  696. void
  697. AsciiModelWriter::writeMesh(const Mesh& mesh)
  698. {
  699.     out << "meshn";
  700.     if (!mesh.getName().empty())
  701.         out << "# " << mesh.getName() << 'n';
  702.     writeVertexDescription(mesh.getVertexDescription());
  703.     out << 'n';
  704.     writeVertices(mesh.getVertexData(),
  705.                   mesh.getVertexCount(),
  706.                   mesh.getVertexStride(),
  707.                   mesh.getVertexDescription());
  708.     out << 'n';
  709.     for (uint32 groupIndex = 0; mesh.getGroup(groupIndex); groupIndex++)
  710.     {
  711.         writeGroup(*mesh.getGroup(groupIndex));
  712.         out << 'n';
  713.     }
  714.     out << "end_meshn";
  715. }
  716. void
  717. AsciiModelWriter::writeVertices(const void* vertexData,
  718.                                 uint32 nVertices,
  719.                                 uint32 stride,
  720.                                 const Mesh::VertexDescription& desc)
  721. {
  722.     const unsigned char* vertex = reinterpret_cast<const unsigned char*>(vertexData);
  723.     out << "vertices " << nVertices << 'n';
  724.     for (uint32 i = 0; i < nVertices; i++, vertex += stride)
  725.     {
  726.         for (uint32 attr = 0; attr < desc.nAttributes; attr++)
  727.         {
  728.             const unsigned char* ubdata = vertex + desc.attributes[attr].offset;
  729.             const float* fdata = reinterpret_cast<const float*>(ubdata);
  730.             switch (desc.attributes[attr].format)
  731.             {
  732.             case Mesh::Float1:
  733.                 out << fdata[0];
  734.                 break;
  735.             case Mesh::Float2:
  736.                 out << fdata[0] << ' ' << fdata[1];
  737.                 break;
  738.             case Mesh::Float3:
  739.                 out << fdata[0] << ' ' << fdata[1] << ' ' << fdata[2];
  740.                 break;
  741.             case Mesh::Float4:
  742.                 out << fdata[0] << ' ' << fdata[1] << ' ' <<
  743.                        fdata[2] << ' ' << fdata[3];
  744.                 break;
  745.             case Mesh::UByte4:
  746.                 out << (int) ubdata[0] << ' ' << (int) ubdata[1] << ' ' <<
  747.                        (int) ubdata[2] << ' ' << (int) ubdata[3];
  748.                 break;
  749.             default:
  750.                 assert(0);
  751.                 break;
  752.             }
  753.             out << ' ';
  754.         }
  755.         out << 'n';
  756.     }
  757. }
  758. void
  759. AsciiModelWriter::writeVertexDescription(const Mesh::VertexDescription& desc)
  760. {
  761.     out << "vertexdescn";
  762.     for (uint32 attr = 0; attr < desc.nAttributes; attr++)
  763.     {
  764.         // We should never have a vertex description with invalid
  765.         // fields . . .
  766.         switch (desc.attributes[attr].semantic)
  767.         {
  768.         case Mesh::Position:
  769.             out << "position";
  770.             break;
  771.         case Mesh::Color0:
  772.             out << "color0";
  773.             break;
  774.         case Mesh::Color1:
  775.             out << "color1";
  776.             break;
  777.         case Mesh::Normal:
  778.             out << "normal";
  779.             break;
  780.         case Mesh::Tangent:
  781.             out << "tangent";
  782.             break;
  783.         case Mesh::Texture0:
  784.             out << "texcoord0";
  785.             break;
  786.         case Mesh::Texture1:
  787.             out << "texcoord1";
  788.             break;
  789.         case Mesh::Texture2:
  790.             out << "texcoord2";
  791.             break;
  792.         case Mesh::Texture3:
  793.             out << "texcoord3";
  794.             break;
  795.         case Mesh::PointSize:
  796.             out << "pointsize";
  797.             break;
  798.         default:
  799.             assert(0);
  800.             break;
  801.         }
  802.         out << ' ';
  803.         switch (desc.attributes[attr].format)
  804.         {
  805.         case Mesh::Float1:
  806.             out << "f1";
  807.             break;
  808.         case Mesh::Float2:
  809.             out << "f2";
  810.             break;
  811.         case Mesh::Float3:
  812.             out << "f3";
  813.             break;
  814.         case Mesh::Float4:
  815.             out << "f4";
  816.             break;
  817.         case Mesh::UByte4:
  818.             out << "ub4";
  819.             break;
  820.         default:
  821.             assert(0);
  822.             break;
  823.         }
  824.         out << 'n';
  825.     }
  826.     out << "end_vertexdescn";
  827. }
  828. void
  829. AsciiModelWriter::writeMaterial(const Mesh::Material& material)
  830. {
  831.     out << "materialn";
  832.     if (material.diffuse != DefaultDiffuse)
  833.     {
  834.         out << "diffuse " <<
  835.             material.diffuse.red() << ' ' <<
  836.             material.diffuse.green() << ' ' <<
  837.             material.diffuse.blue() << 'n';
  838.     }
  839.     if (material.emissive != DefaultEmissive)
  840.     {
  841.         out << "emissive " <<
  842.             material.emissive.red() << ' ' <<
  843.             material.emissive.green() << ' ' <<
  844.             material.emissive.blue() << 'n';
  845.     }
  846.     if (material.specular != DefaultSpecular)
  847.     {
  848.         out << "specular " <<
  849.             material.specular.red() << ' ' <<
  850.             material.specular.green() << ' ' <<
  851.             material.specular.blue() << 'n';
  852.     }
  853.     if (material.specularPower != DefaultSpecularPower)
  854.         out << "specpower " << material.specularPower << 'n';
  855.     if (material.opacity != DefaultOpacity)
  856.         out << "opacity " << material.opacity << 'n';
  857.     if (material.blend != DefaultBlend)
  858.     {
  859.         out << "blend ";
  860.         switch (material.blend)
  861.         {
  862.         case Mesh::NormalBlend:
  863.             out << "normal";
  864.             break;
  865.         case Mesh::AdditiveBlend:
  866.             out << "add";
  867.             break;
  868.         case Mesh::PremultipliedAlphaBlend:
  869.             out << "premultiplied";
  870.             break;
  871.         default:
  872.             assert(0);
  873.             break;
  874.         }
  875.         out << "n";
  876.     }
  877.     for (int i = 0; i < Mesh::TextureSemanticMax; i++)
  878.     {
  879.         const TextureInfo* texInfo = GetTextureManager()->getResourceInfo(material.maps[i]);
  880.         if (texInfo != NULL)
  881.         {
  882.             switch (Mesh::TextureSemantic(i))
  883.             {
  884.             case Mesh::DiffuseMap:
  885.                 out << "texture0";
  886.                 break;
  887.             case Mesh::NormalMap:
  888.                 out << "normalmap";
  889.                 break;
  890.             case Mesh::SpecularMap:
  891.                 out << "specularmap";
  892.                 break;
  893.             case Mesh::EmissiveMap:
  894.                 out << "emissivemap";
  895.                 break;
  896.             default:
  897.                 assert(0);
  898.             }
  899.             out << " "" << texInfo->source << ""n";
  900.         }
  901.     }
  902. #if 0
  903.     if (material.maps[Mesh::DiffuseMap] != InvalidResource)
  904.     {
  905.         const TextureInfo* texInfo = GetTextureManager()->getResourceInfo(material.tex0);
  906.         if (texInfo != NULL)
  907.             out << "texture0 "" << texInfo->source << ""n";
  908.     }
  909.     if (material.tex1 != InvalidResource)
  910.     {
  911.         const TextureInfo* texInfo = GetTextureManager()->getResourceInfo(material.tex1);
  912.         if (texInfo != NULL)
  913.             out << "texture1 "" << texInfo->source << ""n";
  914.     }
  915. #endif
  916.     out << "end_materialn";
  917. }
  918. /***** Binary loader *****/
  919. BinaryModelLoader::BinaryModelLoader(istream& _in) :
  920.     in(_in)
  921. {
  922. }
  923. BinaryModelLoader::~BinaryModelLoader()
  924. {
  925. }
  926. void
  927. BinaryModelLoader::reportError(const string& msg)
  928. {
  929.     char buf[32];
  930.     sprintf(buf, " (offset %d)", 0);
  931.     ModelLoader::reportError(msg + string(buf));
  932. }
  933. // Read a big-endian 32-bit unsigned integer
  934. static int32 readUint(istream& in)
  935. {
  936.     int32 ret;
  937.     in.read((char*) &ret, sizeof(int32));
  938.     LE_TO_CPU_INT32(ret, ret);
  939.     return (uint32) ret;
  940. }
  941. static float readFloat(istream& in)
  942. {
  943.     float f;
  944.     in.read((char*) &f, sizeof(float));
  945.     LE_TO_CPU_FLOAT(f, f);
  946.     return f;
  947. }
  948. static int16 readInt16(istream& in)
  949. {
  950.     int16 ret;
  951.     in.read((char *) &ret, sizeof(int16));
  952.     LE_TO_CPU_INT16(ret, ret);
  953.     return ret;
  954. }
  955. static ModelFileToken readToken(istream& in)
  956. {
  957.     return (ModelFileToken) readInt16(in);
  958. }
  959. static ModelFileType readType(istream& in)
  960. {
  961.     return (ModelFileType) readInt16(in);
  962. }
  963. static bool readTypeFloat1(istream& in, float& f)
  964. {
  965.     if (readType(in) != CMOD_Float1)
  966.         return false;
  967.     f = readFloat(in);
  968.     return true;
  969. }
  970. static bool readTypeColor(istream& in, Color& c)
  971. {
  972.     if (readType(in) != CMOD_Color)
  973.         return false;
  974.     float r = readFloat(in);
  975.     float g = readFloat(in);
  976.     float b = readFloat(in);
  977.     c = Color(r, g, b);
  978.     return true;
  979. }
  980. static bool readTypeString(istream& in, string& s)
  981. {
  982.     if (readType(in) != CMOD_String)
  983.         return false;
  984.     uint16 len;
  985.     in.read((char*) &len, sizeof(uint16));
  986.     LE_TO_CPU_INT16(len, len);
  987.     if (len == 0)
  988.     {
  989.         s = "";
  990.     }
  991.     else
  992.     {
  993.         char* buf = new char[len];
  994.         in.read(buf, len);
  995.         s = string(buf, len);
  996.         delete[] buf;
  997.     }
  998.     return true;
  999. }
  1000. static bool ignoreValue(istream& in)
  1001. {
  1002.     ModelFileType type = readType(in);
  1003.     int size = 0;
  1004.     switch (type)
  1005.     {
  1006.     case CMOD_Float1:
  1007.         size = 4;
  1008.         break;
  1009.     case CMOD_Float2:
  1010.         size = 8;
  1011.         break;
  1012.     case CMOD_Float3:
  1013.         size = 12;
  1014.         break;
  1015.     case CMOD_Float4:
  1016.         size = 16;
  1017.         break;
  1018.     case CMOD_Uint32:
  1019.         size = 4;
  1020.         break;
  1021.     case CMOD_Color:
  1022.         size = 12;
  1023.         break;
  1024.     case CMOD_String:
  1025.         {
  1026.             uint16 len;
  1027.             in.read((char*) &len, sizeof(uint16));
  1028.             LE_TO_CPU_INT16(len, len);
  1029.             size = len;
  1030.         }
  1031.         break;
  1032.     default:
  1033.         return false;
  1034.     }
  1035.     in.ignore(size);
  1036.     return true;
  1037. }
  1038. Model*
  1039. BinaryModelLoader::load()
  1040. {
  1041.     Model* model = new Model();
  1042.     bool seenMeshes = false;
  1043.     if (model == NULL)
  1044.     {
  1045.         reportError("Unable to allocate memory for model");
  1046.         return NULL;
  1047.     }
  1048.     // Parse material and mesh definitions
  1049.     for (;;)
  1050.     {
  1051.         ModelFileToken tok = readToken(in);
  1052.         if (in.eof())
  1053.         {
  1054.             break;
  1055.         }
  1056.         else if (tok == CMOD_Material)
  1057.         {
  1058.             if (seenMeshes)
  1059.             {
  1060.                 reportError("Materials must be defined before meshes");
  1061.                 delete model;
  1062.                 return NULL;
  1063.             }
  1064.             Mesh::Material* material = loadMaterial();
  1065.             if (material == NULL)
  1066.             {
  1067.                 delete model;
  1068.                 return NULL;
  1069.             }
  1070.             model->addMaterial(material);
  1071.         }
  1072.         else if (tok == CMOD_Mesh)
  1073.         {
  1074.             seenMeshes = true;
  1075.             Mesh* mesh = loadMesh();
  1076.             if (mesh == NULL)
  1077.             {
  1078.                 delete model;
  1079.                 return NULL;
  1080.             }
  1081.             model->addMesh(mesh);
  1082.         }
  1083.         else
  1084.         {
  1085.             reportError("Error: Unknown block type in model");
  1086.             delete model;
  1087.             return NULL;
  1088.         }
  1089.     }
  1090.     return model;
  1091. }
  1092. Mesh::Material*
  1093. BinaryModelLoader::loadMaterial()
  1094. {
  1095.     Mesh::Material* material = new Mesh::Material();
  1096.     material->diffuse = DefaultDiffuse;
  1097.     material->specular = DefaultSpecular;
  1098.     material->emissive = DefaultEmissive;
  1099.     material->specularPower = DefaultSpecularPower;
  1100.     material->opacity = DefaultOpacity;
  1101.     for (;;)
  1102.     {
  1103.         ModelFileToken tok = readToken(in);
  1104.         switch (tok)
  1105.         {
  1106.         case CMOD_Diffuse:
  1107.             if (!readTypeColor(in, material->diffuse))
  1108.             {
  1109.                 reportError("Incorrect type for diffuse color");
  1110.                 delete material;
  1111.                 return NULL;
  1112.             }
  1113.             break;
  1114.         case CMOD_Specular:
  1115.             if (!readTypeColor(in, material->specular))
  1116.             {
  1117.                 reportError("Incorrect type for specular color");
  1118.                 delete material;
  1119.                 return NULL;
  1120.             }
  1121.             break;
  1122.         case CMOD_Emissive:
  1123.             if (!readTypeColor(in, material->emissive))
  1124.             {
  1125.                 reportError("Incorrect type for emissive color");
  1126.                 delete material;
  1127.                 return NULL;
  1128.             }
  1129.             break;
  1130.         case CMOD_SpecularPower:
  1131.             if (!readTypeFloat1(in, material->specularPower))
  1132.             {
  1133.                 reportError("Float expected for specularPower");
  1134.                 delete material;
  1135.                 return NULL;
  1136.             }
  1137.             break;
  1138.         case CMOD_Opacity:
  1139.             if (!readTypeFloat1(in, material->opacity))
  1140.             {
  1141.                 reportError("Float expected for opacity");
  1142.                 delete material;
  1143.                 return NULL;
  1144.             }
  1145.             break;
  1146.         case CMOD_Blend:
  1147.             {
  1148.                 int16 blendMode = readInt16(in);
  1149.                 if (blendMode < 0 || blendMode >= Mesh::BlendMax)
  1150.                 {
  1151.                     reportError("Bad blend mode");
  1152.                     delete material;
  1153.                     return NULL;
  1154.                 }
  1155.                 material->blend = (Mesh::BlendMode) blendMode;
  1156.             }
  1157.             break;
  1158.         case CMOD_Texture:
  1159.             {
  1160.                 int16 texType = readInt16(in);
  1161.                 if (texType < 0 || texType >= Mesh::TextureSemanticMax)
  1162.                 {
  1163.                     reportError("Bad texture type");
  1164.                     delete material;
  1165.                     return NULL;
  1166.                 }
  1167.                 string texfile;
  1168.                 if (!readTypeString(in, texfile))
  1169.                 {
  1170.                     reportError("String expected for texture filename");
  1171.                     delete material;
  1172.                     return NULL;
  1173.                 }
  1174.                 if (texfile.empty())
  1175.                 {
  1176.                     reportError("Zero length texture name in material definition");
  1177.                     delete material;
  1178.                     return NULL;
  1179.                 }
  1180.                 ResourceHandle tex = GetTextureManager()->getHandle(TextureInfo(texfile, getTexturePath(), TextureInfo::WrapTexture));
  1181.                 material->maps[texType] = tex;
  1182.             }
  1183.             break;
  1184.         case CMOD_EndMaterial:
  1185.             return material;
  1186.         default:
  1187.             // Skip unrecognized tokens
  1188.             if (!ignoreValue(in))
  1189.             {
  1190.                 delete material;
  1191.                 return NULL;
  1192.             }
  1193.         } // switch
  1194.     } // for
  1195. }
  1196. Mesh::VertexDescription*
  1197. BinaryModelLoader::loadVertexDescription()
  1198. {
  1199.     if (readToken(in) != CMOD_VertexDesc)
  1200.     {
  1201.         reportError("Vertex description expected");
  1202.         return NULL;
  1203.     }
  1204.     int maxAttributes = 16;
  1205.     int nAttributes = 0;
  1206.     uint32 offset = 0;
  1207.     Mesh::VertexAttribute* attributes = new Mesh::VertexAttribute[maxAttributes];
  1208.     for (;;)
  1209.     {
  1210.         int16 tok = readInt16(in);
  1211.         if (tok == CMOD_EndVertexDesc)
  1212.         {
  1213.             break;
  1214.         }
  1215.         else if (tok >= 0 && tok < Mesh::SemanticMax)
  1216.         {
  1217.             int16 fmt = readInt16(in);
  1218.             if (fmt < 0 || fmt >= Mesh::FormatMax)
  1219.             {
  1220.                 reportError("Invalid vertex attribute type");
  1221.                 delete[] attributes;
  1222.                 return NULL;
  1223.             }
  1224.             else
  1225.             {
  1226.                 if (nAttributes == maxAttributes)
  1227.                 {
  1228.                     reportError("Too many attributes in vertex description");
  1229.                     delete[] attributes;
  1230.                     return NULL;
  1231.                 }
  1232.                 attributes[nAttributes].semantic =
  1233.                     static_cast<Mesh::VertexAttributeSemantic>(tok);
  1234.                 attributes[nAttributes].format =
  1235.                     static_cast<Mesh::VertexAttributeFormat>(fmt);
  1236.                 attributes[nAttributes].offset = offset;
  1237.                 offset += Mesh::getVertexAttributeSize(attributes[nAttributes].format);
  1238.                 nAttributes++;
  1239.             }
  1240.         }
  1241.         else
  1242.         {
  1243.             reportError("Invalid semantic in vertex description");
  1244.             delete[] attributes;
  1245.             return NULL;
  1246.         }
  1247.     }
  1248.     if (nAttributes == 0)
  1249.     {
  1250.         reportError("Vertex definitition cannot be empty");
  1251.         delete[] attributes;
  1252.         return NULL;
  1253.     }
  1254.     Mesh::VertexDescription *vertexDesc =
  1255.         new Mesh::VertexDescription(offset, nAttributes, attributes);
  1256.     delete[] attributes;
  1257.     return vertexDesc;
  1258. }
  1259. Mesh*
  1260. BinaryModelLoader::loadMesh()
  1261. {
  1262.     Mesh::VertexDescription* vertexDesc = loadVertexDescription();
  1263.     if (vertexDesc == NULL)
  1264.         return NULL;
  1265.     uint32 vertexCount = 0;
  1266.     char* vertexData = loadVertices(*vertexDesc, vertexCount);
  1267.     if (vertexData == NULL)
  1268.     {
  1269.         delete vertexDesc;
  1270.         return NULL;
  1271.     }
  1272.     Mesh* mesh = new Mesh();
  1273.     mesh->setVertexDescription(*vertexDesc);
  1274.     mesh->setVertices(vertexCount, vertexData);
  1275.     delete vertexDesc;
  1276.     for (;;)
  1277.     {
  1278.         int16 tok = readInt16(in);
  1279.         if (tok == CMOD_EndMesh)
  1280.         {
  1281.             break;
  1282.         }
  1283.         else if (tok < 0 || tok >= Mesh::PrimitiveTypeMax)
  1284.         {
  1285.             reportError("Bad primitive group type");
  1286.             delete mesh;
  1287.             return NULL;
  1288.         }
  1289.         Mesh::PrimitiveGroupType type =
  1290.             static_cast<Mesh::PrimitiveGroupType>(tok);
  1291.         uint32 materialIndex = readUint(in);
  1292.         uint32 indexCount = readUint(in);
  1293.         uint32* indices = new uint32[indexCount];
  1294.         if (indices == NULL)
  1295.         {
  1296.             reportError("Not enough memory to hold indices");
  1297.             delete mesh;
  1298.             return NULL;
  1299.         }
  1300.         for (uint32 i = 0; i < indexCount; i++)
  1301.         {
  1302.             uint32 index = readUint(in);
  1303.             if (index >= vertexCount)
  1304.             {
  1305.                 reportError("Index out of range");
  1306.                 delete indices;
  1307.                 delete mesh;
  1308.                 return NULL;
  1309.             }
  1310.             indices[i] = index;
  1311.         }
  1312.         mesh->addGroup(type, materialIndex, indexCount, indices);
  1313.     }
  1314.     return mesh;
  1315. }
  1316. char*
  1317. BinaryModelLoader::loadVertices(const Mesh::VertexDescription& vertexDesc,
  1318.                                 uint32& vertexCount)
  1319. {
  1320.     if (readToken(in) != CMOD_Vertices)
  1321.     {
  1322.         reportError("Vertex data expected");
  1323.         return NULL;
  1324.     }
  1325.     vertexCount = readUint(in);
  1326.     uint32 vertexDataSize = vertexDesc.stride * vertexCount;
  1327.     char* vertexData = new char[vertexDataSize];
  1328.     if (vertexData == NULL)
  1329.     {
  1330.         reportError("Not enough memory to hold vertex data");
  1331.         return NULL;
  1332.     }
  1333.     uint32 offset = 0;
  1334.     for (uint32 i = 0; i < vertexCount; i++, offset += vertexDesc.stride)
  1335.     {
  1336.         assert(offset < vertexDataSize);
  1337.         for (uint32 attr = 0; attr < vertexDesc.nAttributes; attr++)
  1338.         {
  1339.             uint32 base = offset + vertexDesc.attributes[attr].offset;
  1340.             Mesh::VertexAttributeFormat fmt = vertexDesc.attributes[attr].format;
  1341.             /*int readCount = 0;    Unused*/
  1342.             switch (fmt)
  1343.             {
  1344.             case Mesh::Float1:
  1345.                 reinterpret_cast<float*>(vertexData + base)[0] = readFloat(in);
  1346.                 break;
  1347.             case Mesh::Float2:
  1348.                 reinterpret_cast<float*>(vertexData + base)[0] = readFloat(in);
  1349.                 reinterpret_cast<float*>(vertexData + base)[1] = readFloat(in);
  1350.                 break;
  1351.             case Mesh::Float3:
  1352.                 reinterpret_cast<float*>(vertexData + base)[0] = readFloat(in);
  1353.                 reinterpret_cast<float*>(vertexData + base)[1] = readFloat(in);
  1354.                 reinterpret_cast<float*>(vertexData + base)[2] = readFloat(in);
  1355.                 break;
  1356.             case Mesh::Float4:
  1357.                 reinterpret_cast<float*>(vertexData + base)[0] = readFloat(in);
  1358.                 reinterpret_cast<float*>(vertexData + base)[1] = readFloat(in);
  1359.                 reinterpret_cast<float*>(vertexData + base)[2] = readFloat(in);
  1360.                 reinterpret_cast<float*>(vertexData + base)[3] = readFloat(in);
  1361.                 break;
  1362.             case Mesh::UByte4:
  1363.                 in.get(reinterpret_cast<char*>(vertexData + base), 4);
  1364.                 break;
  1365.             default:
  1366.                 assert(0);
  1367.                 delete[] vertexData;
  1368.                 return NULL;
  1369.             }
  1370.         }
  1371.     }
  1372.     return vertexData;
  1373. }
  1374. /***** Binary writer *****/
  1375. BinaryModelWriter::BinaryModelWriter(ostream& _out) :
  1376.     out(_out)
  1377. {
  1378. }
  1379. BinaryModelWriter::~BinaryModelWriter()
  1380. {
  1381. }
  1382. // Utility functions for writing binary values to a file
  1383. static void writeUint(ostream& out, uint32 val)
  1384. {
  1385.     LE_TO_CPU_INT32(val, val);
  1386.     out.write(reinterpret_cast<char*>(&val), sizeof(uint32));
  1387. }
  1388. static void writeFloat(ostream& out, float val)
  1389. {
  1390.     LE_TO_CPU_FLOAT(val, val);
  1391.     out.write(reinterpret_cast<char*>(&val), sizeof(float));
  1392. }
  1393. static void writeInt16(ostream& out, int16 val)
  1394. {
  1395.     LE_TO_CPU_INT16(val, val);
  1396.     out.write(reinterpret_cast<char*>(&val), sizeof(int16));
  1397. }
  1398. static void writeToken(ostream& out, ModelFileToken val)
  1399. {
  1400.     writeInt16(out, static_cast<int16>(val));
  1401. }
  1402. static void writeType(ostream& out, ModelFileType val)
  1403. {
  1404.     writeInt16(out, static_cast<int16>(val));
  1405. }
  1406. static void writeTypeFloat1(ostream& out, float f)
  1407. {
  1408.     writeType(out, CMOD_Float1);
  1409.     writeFloat(out, f);
  1410. }
  1411. static void writeTypeColor(ostream& out, const Color& c)
  1412. {
  1413.     writeType(out, CMOD_Color);
  1414.     writeFloat(out, c.red());
  1415.     writeFloat(out, c.green());
  1416.     writeFloat(out, c.blue());
  1417. }
  1418. static void writeTypeString(ostream& out, const string& s)
  1419. {
  1420.     writeType(out, CMOD_String);
  1421.     writeInt16(out, static_cast<int16>(s.length()));
  1422.     out.write(s.c_str(), s.length());
  1423. }
  1424. bool
  1425. BinaryModelWriter::write(const Model& model)
  1426. {
  1427.     out << CEL_MODEL_HEADER_BINARY;
  1428.     for (uint32 matIndex = 0; model.getMaterial(matIndex); matIndex++)
  1429.         writeMaterial(*model.getMaterial(matIndex));
  1430.     for (uint32 meshIndex = 0; model.getMesh(meshIndex); meshIndex++)
  1431.         writeMesh(*model.getMesh(meshIndex));
  1432.     return true;
  1433. }
  1434. void
  1435. BinaryModelWriter::writeGroup(const Mesh::PrimitiveGroup& group)
  1436. {
  1437.     writeInt16(out, static_cast<int16>(group.prim));
  1438.     writeUint(out, group.materialIndex);
  1439.     writeUint(out, group.nIndices);
  1440.     // Print the indices, twelve per line
  1441.     for (uint32 i = 0; i < group.nIndices; i++)
  1442.         writeUint(out, group.indices[i]);
  1443. }
  1444. void
  1445. BinaryModelWriter::writeMesh(const Mesh& mesh)
  1446. {
  1447.     writeToken(out, CMOD_Mesh);
  1448.     writeVertexDescription(mesh.getVertexDescription());
  1449.     writeVertices(mesh.getVertexData(),
  1450.                   mesh.getVertexCount(),
  1451.                   mesh.getVertexStride(),
  1452.                   mesh.getVertexDescription());
  1453.     for (uint32 groupIndex = 0; mesh.getGroup(groupIndex); groupIndex++)
  1454.         writeGroup(*mesh.getGroup(groupIndex));
  1455.     writeToken(out, CMOD_EndMesh);
  1456. }
  1457. void
  1458. BinaryModelWriter::writeVertices(const void* vertexData,
  1459.                                  uint32 nVertices,
  1460.                                  uint32 stride,
  1461.                                  const Mesh::VertexDescription& desc)
  1462. {
  1463.     const char* vertex = reinterpret_cast<const char*>(vertexData);
  1464.     writeToken(out, CMOD_Vertices);
  1465.     writeUint(out, nVertices);
  1466.     for (uint32 i = 0; i < nVertices; i++, vertex += stride)
  1467.     {
  1468.         for (uint32 attr = 0; attr < desc.nAttributes; attr++)
  1469.         {
  1470.             const char* cdata = vertex + desc.attributes[attr].offset;
  1471.             const float* fdata = reinterpret_cast<const float*>(cdata);
  1472.             switch (desc.attributes[attr].format)
  1473.             {
  1474.             case Mesh::Float1:
  1475.                 writeFloat(out, fdata[0]);
  1476.                 break;
  1477.             case Mesh::Float2:
  1478.                 writeFloat(out, fdata[0]);
  1479.                 writeFloat(out, fdata[1]);
  1480.                 break;
  1481.             case Mesh::Float3:
  1482.                 writeFloat(out, fdata[0]);
  1483.                 writeFloat(out, fdata[1]);
  1484.                 writeFloat(out, fdata[2]);
  1485.                 break;
  1486.             case Mesh::Float4:
  1487.                 writeFloat(out, fdata[0]);
  1488.                 writeFloat(out, fdata[1]);
  1489.                 writeFloat(out, fdata[2]);
  1490.                 writeFloat(out, fdata[3]);
  1491.                 break;
  1492.             case Mesh::UByte4:
  1493.                 out.write(cdata, 4);
  1494.                 break;
  1495.             default:
  1496.                 assert(0);
  1497.                 break;
  1498.             }
  1499.         }
  1500.     }
  1501. }
  1502. void
  1503. BinaryModelWriter::writeVertexDescription(const Mesh::VertexDescription& desc)
  1504. {
  1505.     writeToken(out, CMOD_VertexDesc);
  1506.     for (uint32 attr = 0; attr < desc.nAttributes; attr++)
  1507.     {
  1508.         writeInt16(out, static_cast<int16>(desc.attributes[attr].semantic));
  1509.         writeInt16(out, static_cast<int16>(desc.attributes[attr].format));
  1510.     }
  1511.     writeToken(out, CMOD_EndVertexDesc);
  1512. }
  1513. void
  1514. BinaryModelWriter::writeMaterial(const Mesh::Material& material)
  1515. {
  1516.     writeToken(out, CMOD_Material);
  1517.     if (material.diffuse != DefaultDiffuse)
  1518.     {
  1519.         writeToken(out, CMOD_Diffuse);
  1520.         writeTypeColor(out, material.diffuse);
  1521.     }
  1522.     if (material.emissive != DefaultEmissive)
  1523.     {
  1524.         writeToken(out, CMOD_Emissive);
  1525.         writeTypeColor(out, material.emissive);
  1526.     }
  1527.     if (material.specular != DefaultSpecular)
  1528.     {
  1529.         writeToken(out, CMOD_Specular);
  1530.         writeTypeColor(out, material.specular);
  1531.     }
  1532.     if (material.specularPower != DefaultSpecularPower)
  1533.     {
  1534.         writeToken(out, CMOD_SpecularPower);
  1535.         writeTypeFloat1(out, material.specularPower);
  1536.     }
  1537.     if (material.opacity != DefaultOpacity)
  1538.     {
  1539.         writeToken(out, CMOD_Opacity);
  1540.         writeTypeFloat1(out, material.opacity);
  1541.     }
  1542.     if (material.blend != DefaultBlend)
  1543.     {
  1544.         writeToken(out, CMOD_Blend);
  1545.         writeInt16(out, (int16) material.blend);
  1546.     }
  1547.     for (int i = 0; i < Mesh::TextureSemanticMax; i++)
  1548.     {
  1549.         if (material.maps[i] != InvalidResource)
  1550.         {
  1551.             const TextureInfo* texInfo = GetTextureManager()->getResourceInfo(material.maps[i]);
  1552.             if (texInfo != NULL)
  1553.             {
  1554.                 writeToken(out, CMOD_Texture);
  1555.                 writeInt16(out, (int16) i);
  1556.                 writeTypeString(out, texInfo->source);
  1557.             }
  1558.         }
  1559.     }
  1560. #if 0
  1561.     if (material.tex1 != InvalidResource)
  1562.     {
  1563.         const TextureInfo* texInfo = GetTextureManager()->getResourceInfo(material.tex1);
  1564.         if (texInfo != NULL)
  1565.         {
  1566.             writeToken(out, CMOD_Texture1);
  1567.             writeTypeString(out, texInfo->source);
  1568.         }
  1569.     }
  1570. #endif
  1571.     writeToken(out, CMOD_EndMaterial);
  1572. }