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

OpenGL

开发平台:

Visual C++

  1. // meshmanager.cpp
  2. //
  3. // Copyright (C) 2001-2006 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. // Experimental particle system support
  10. #define PARTICLE_SYSTEM 0
  11. #include <iostream>
  12. #include <fstream>
  13. #include <cassert>
  14. #include "celestia.h"
  15. #include <celutil/debug.h>
  16. #include <celutil/filetype.h>
  17. #include <celutil/util.h>
  18. #include <celmath/mathlib.h>
  19. #include <celmath/perlin.h>
  20. #include <cel3ds/3dsread.h>
  21. #include "modelfile.h"
  22. #if PARTICLE_SYSTEM
  23. #include "particlesystem.h"
  24. #include "particlesystemfile.h"
  25. #endif
  26. #include "vertexlist.h"
  27. #include "parser.h"
  28. #include "spheremesh.h"
  29. #include "texmanager.h"
  30. #include "meshmanager.h"
  31. using namespace std;
  32. static Model* LoadCelestiaMesh(const string& filename);
  33. static Model* Convert3DSModel(const M3DScene& scene, const string& texPath);
  34. static GeometryManager* geometryManager = NULL;
  35. static const char UniqueSuffixChar = '!';
  36. GeometryManager* GetGeometryManager()
  37. {
  38.     if (geometryManager == NULL)
  39.         geometryManager = new GeometryManager("models");
  40.     return geometryManager;
  41. }
  42. string GeometryInfo::resolve(const string& baseDir)
  43. {
  44.     // Ensure that models with different centers get resolved to different objects by
  45.     // adding a 'uniquifying' suffix to the filename that encodes the center value.
  46.     // This suffix is stripped before the file is actually loaded.
  47.     char uniquifyingSuffix[128];
  48.     sprintf(uniquifyingSuffix, "%c%f,%f,%f,%f,%d", UniqueSuffixChar, center.x, center.y, center.z, scale, (int) isNormalized);
  49.     
  50.     if (!path.empty())
  51.     {
  52.         string filename = path + "/models/" + source;
  53.         ifstream in(filename.c_str());
  54.         if (in.good())
  55.         {
  56.             resolvedToPath = true;
  57.             return filename + uniquifyingSuffix;
  58.         }
  59.     }
  60.     return baseDir + "/" + source + uniquifyingSuffix;
  61. }
  62. Geometry* GeometryInfo::load(const string& resolvedFilename)
  63. {
  64.     // Strip off the uniquifying suffix
  65.     string::size_type uniquifyingSuffixStart = resolvedFilename.rfind(UniqueSuffixChar);
  66.     string filename(resolvedFilename, 0, uniquifyingSuffixStart);
  67.     
  68.     clog << _("Loading model: ") << filename << 'n';
  69.     Model* model = NULL;
  70.     ContentType fileType = DetermineFileType(filename);
  71.     if (fileType == Content_3DStudio)
  72.     {
  73.         M3DScene* scene = Read3DSFile(filename);
  74.         if (scene != NULL)
  75.         {
  76.             if (resolvedToPath)
  77.                 model = Convert3DSModel(*scene, path);
  78.             else
  79.                 model = Convert3DSModel(*scene, "");
  80.             if (isNormalized)
  81.                 model->normalize(center);
  82.             else
  83.                 model->transform(center, scale);
  84.             delete scene;
  85.         }
  86.     }
  87.     else if (fileType == Content_CelestiaModel)
  88.     {
  89.         ifstream in(filename.c_str(), ios::binary);
  90.         if (in.good())
  91.         {
  92.             model = LoadModel(in, path);
  93.             if (model != NULL)
  94.             {
  95.                 if (isNormalized)
  96.                     model->normalize(center);
  97.                 else
  98.                     model->transform(center, scale);
  99.             }
  100.         }
  101.     }
  102.     else if (fileType == Content_CelestiaMesh)
  103.     {
  104.         model = LoadCelestiaMesh(filename);
  105.         if (model != NULL)
  106.         {
  107.             if (isNormalized)
  108.                 model->normalize(center);
  109.             else
  110.                 model->transform(center, scale);
  111.         }
  112.     }
  113. #if PARTICLE_SYSTEM
  114.     else if (fileType == Content_CelestiaParticleSystem)
  115.     {
  116.         ifstream in(filename.c_str());
  117.         if (in.good())
  118.         {
  119.             return LoadParticleSystem(in, path);
  120.         }
  121.     }
  122. #endif
  123.         
  124.     // Condition the model for optimal rendering
  125.     if (model != NULL)
  126.     {
  127.         // Many models tend to have a lot of duplicate materials; eliminate
  128.         // them, since unnecessarily setting material parameters can adversely
  129.         // impact rendering performance. Ideally uniquification of materials
  130.         // would be performed just once when the model was created, but
  131.         // that's not the case.
  132.         uint32 originalMaterialCount = model->getMaterialCount();
  133.         model->uniquifyMaterials();
  134.         // Sort the submeshes roughly by opacity.  This will eliminate a
  135.         // good number of the errors caused when translucent triangles are
  136.         // rendered before geometry that they cover.
  137.         model->sortMeshes(Model::OpacityComparator());
  138.         model->determineOpacity();
  139.         // Display some statics for the model
  140.         clog << _("   Model statistics: ")
  141.              << model->getVertexCount() << _(" vertices, ")
  142.              << model->getPrimitiveCount() << _(" primitives, ")
  143.              << originalMaterialCount << _(" materials ")
  144.              << "(" << model->getMaterialCount() << _(" unique)n");
  145.     }
  146.     else
  147.     {
  148.         cerr << _("Error loading model '") << filename << "'n";
  149.     }
  150.     return model;
  151. }
  152. struct NoiseMeshParameters
  153. {
  154.     Vec3f size;
  155.     Vec3f offset;
  156.     float featureHeight;
  157.     float octaves;
  158.     float slices;
  159.     float rings;
  160. };
  161. static float NoiseDisplacementFunc(float u, float v, void* info)
  162. {
  163.     float theta = u * (float) PI * 2;
  164.     float phi = (v - 0.5f) * (float) PI;
  165.     float x = (float) (cos(phi) * cos(theta));
  166.     float y = (float) sin(phi);
  167.     float z = (float) (cos(phi) * sin(theta));
  168.     // assert(info != NULL);
  169.     NoiseMeshParameters* params = (NoiseMeshParameters*) info;
  170.     return fractalsum(Point3f(x, y, z) + params->offset,
  171.                       params->octaves) * params->featureHeight;
  172. }
  173. // TODO: The Celestia mesh format is deprecated
  174. Model* LoadCelestiaMesh(const string& filename)
  175. {
  176.     ifstream meshFile(filename.c_str(), ios::in);
  177.     if (!meshFile.good())
  178.     {
  179.         DPRINTF(0, "Error opening mesh file: %sn", filename.c_str());
  180.         return NULL;
  181.     }
  182.     Tokenizer tokenizer(&meshFile);
  183.     Parser parser(&tokenizer);
  184.     if (tokenizer.nextToken() != Tokenizer::TokenName)
  185.     {
  186.         DPRINTF(0, "Mesh file %s is invalid.n", filename.c_str());
  187.         return NULL;
  188.     }
  189.     if (tokenizer.getStringValue() != "SphereDisplacementMesh")
  190.     {
  191.         DPRINTF(0, "%s: Unrecognized mesh type %s.n",
  192.                 filename.c_str(),
  193.                 tokenizer.getStringValue().c_str());
  194.         return NULL;
  195.     }
  196.     Value* meshDefValue = parser.readValue();
  197.     if (meshDefValue == NULL)
  198.     {
  199.         DPRINTF(0, "%s: Bad mesh file.n", filename.c_str());
  200.         return NULL;
  201.     }
  202.     if (meshDefValue->getType() != Value::HashType)
  203.     {
  204.         DPRINTF(0, "%s: Bad mesh file.n", filename.c_str());
  205.         delete meshDefValue;
  206.         return NULL;
  207.     }
  208.     Hash* meshDef = meshDefValue->getHash();
  209.     NoiseMeshParameters params;
  210.     params.size = Vec3f(1, 1, 1);
  211.     params.offset = Vec3f(10, 10, 10);
  212.     params.featureHeight = 0.0f;
  213.     params.octaves = 1;
  214.     params.slices = 20;
  215.     params.rings = 20;
  216.     meshDef->getVector("Size", params.size);
  217.     meshDef->getVector("NoiseOffset", params.offset);
  218.     meshDef->getNumber("FeatureHeight", params.featureHeight);
  219.     meshDef->getNumber("Octaves", params.octaves);
  220.     meshDef->getNumber("Slices", params.slices);
  221.     meshDef->getNumber("Rings", params.rings);
  222.     delete meshDefValue;
  223.     Model* model = new Model();
  224.     SphereMesh* sphereMesh = new SphereMesh(params.size,
  225.                                             (int) params.rings, (int) params.slices,
  226.                                             NoiseDisplacementFunc,
  227.                                             (void*) &params);
  228.     if (sphereMesh != NULL)
  229.     {
  230.         Mesh* mesh = sphereMesh->convertToMesh();
  231.         model->addMesh(mesh);
  232.         delete sphereMesh;
  233.     }
  234.     return model;
  235. }
  236. static VertexList* ConvertToVertexList(M3DTriangleMesh& mesh,
  237.                                        const M3DScene& scene,
  238.                                        const string& texturePath)
  239. {
  240.     int nFaces = mesh.getFaceCount();
  241.     int nVertices = mesh.getVertexCount();
  242.     int nTexCoords = mesh.getTexCoordCount();
  243.     bool smooth = (mesh.getSmoothingGroupCount() == nFaces);
  244.     int i;
  245.     uint32 parts = VertexList::VertexNormal;
  246.     if (nTexCoords >= nVertices)
  247.         parts |= VertexList::TexCoord0;
  248.     VertexList* vl = new VertexList(parts);
  249.     Vec3f* faceNormals = new Vec3f[nFaces];
  250.     Vec3f* vertexNormals = new Vec3f[nFaces * 3];
  251.     int* faceCounts = new int[nVertices];
  252.     int** vertexFaces = new int*[nVertices];
  253.     for (i = 0; i < nVertices; i++)
  254.     {
  255.         faceCounts[i] = 0;
  256.         vertexFaces[i] = NULL;
  257.     }
  258.     // generate face normals
  259.     for (i = 0; i < nFaces; i++)
  260.     {
  261.         uint16 v0, v1, v2;
  262.         mesh.getFace(i, v0, v1, v2);
  263.         faceCounts[v0]++;
  264.         faceCounts[v1]++;
  265.         faceCounts[v2]++;
  266.         Point3f p0 = mesh.getVertex(v0);
  267.         Point3f p1 = mesh.getVertex(v1);
  268.         Point3f p2 = mesh.getVertex(v2);
  269.         faceNormals[i] = cross(p1 - p0, p2 - p1);
  270.         faceNormals[i].normalize();
  271.     }
  272.     if (!smooth && 0)
  273.     {
  274.         for (i = 0; i < nFaces; i++)
  275.         {
  276.             vertexNormals[i * 3] = faceNormals[i];
  277.             vertexNormals[i * 3 + 1] = faceNormals[i];
  278.             vertexNormals[i * 3 + 2] = faceNormals[i];
  279.         }
  280.     }
  281.     else
  282.     {
  283.         // allocate space for vertex face indices
  284.         for (i = 0; i < nVertices; i++)
  285.         {
  286.             vertexFaces[i] = new int[faceCounts[i] + 1];
  287.             vertexFaces[i][0] = faceCounts[i];
  288.         }
  289.         for (i = 0; i < nFaces; i++)
  290.         {
  291.             uint16 v0, v1, v2;
  292.             mesh.getFace(i, v0, v1, v2);
  293.             vertexFaces[v0][faceCounts[v0]--] = i;
  294.             vertexFaces[v1][faceCounts[v1]--] = i;
  295.             vertexFaces[v2][faceCounts[v2]--] = i;
  296.         }
  297.         // average face normals to compute the vertex normals
  298.         for (i = 0; i < nFaces; i++)
  299.         {
  300.             uint16 v0, v1, v2;
  301.             mesh.getFace(i, v0, v1, v2);
  302.             // uint32 smoothingGroups = mesh.getSmoothingGroups(i);
  303.             int j;
  304.             Vec3f v = Vec3f(0, 0, 0);
  305.             for (j = 1; j <= vertexFaces[v0][0]; j++)
  306.             {
  307.                 int k = vertexFaces[v0][j];
  308.                 // if (k == i || (smoothingGroups & mesh.getSmoothingGroups(k)) != 0)
  309.                 if (faceNormals[i] * faceNormals[k] > 0.5f)
  310.                     v += faceNormals[k];
  311.             }
  312.             v.normalize();
  313.             vertexNormals[i * 3] = v;
  314.             v = Vec3f(0, 0, 0);
  315.             for (j = 1; j <= vertexFaces[v1][0]; j++)
  316.             {
  317.                 int k = vertexFaces[v1][j];
  318.                 // if (k == i || (smoothingGroups & mesh.getSmoothingGroups(k)) != 0)
  319.                 if (faceNormals[i] * faceNormals[k] > 0.5f)
  320.                     v += faceNormals[k];
  321.             }
  322.             v.normalize();
  323.             vertexNormals[i * 3 + 1] = v;
  324.             v = Vec3f(0, 0, 0);
  325.             for (j = 1; j <= vertexFaces[v2][0]; j++)
  326.             {
  327.                 int k = vertexFaces[v2][j];
  328.                 // if (k == i || (smoothingGroups & mesh.getSmoothingGroups(k)) != 0)
  329.                 if (faceNormals[i] * faceNormals[k] > 0.5f)
  330.                     v += faceNormals[k];
  331.             }
  332.             v.normalize();
  333.             vertexNormals[i * 3 + 2] = v;
  334.         }
  335.     }
  336.     // build the triangle list
  337.     for (i = 0; i < nFaces; i++)
  338.     {
  339.         uint16 triVert[3];
  340.         mesh.getFace(i, triVert[0], triVert[1], triVert[2]);
  341.         for (int j = 0; j < 3; j++)
  342.         {
  343.             VertexList::Vertex v;
  344.             v.point = mesh.getVertex(triVert[j]);
  345.             v.normal = vertexNormals[i * 3 + j];
  346.             if ((parts & VertexList::TexCoord0) != 0)
  347.                 v.texCoords[0] = mesh.getTexCoord(triVert[j]);
  348.             vl->addVertex(v);
  349.         }
  350.     }
  351.     // Set the material properties
  352.     {
  353.         string materialName = mesh.getMaterialName();
  354.         if (materialName.length() > 0)
  355.         {
  356.             int nMaterials = scene.getMaterialCount();
  357.             for (i = 0; i < nMaterials; i++)
  358.             {
  359.                 M3DMaterial* material = scene.getMaterial(i);
  360.                 if (materialName == material->getName())
  361.                 {
  362.                     M3DColor diffuse = material->getDiffuseColor();
  363.                     vl->setDiffuseColor(Color(diffuse.red, diffuse.green, diffuse.blue, material->getOpacity()));
  364.                     M3DColor specular = material->getSpecularColor();
  365.                     vl->setSpecularColor(Color(specular.red, specular.green, specular.blue));
  366.                     float shininess = material->getShininess();
  367.                     // Map the 3DS file's shininess from percentage (0-100) to
  368.                     // range that OpenGL uses for the specular exponent. The
  369.                     // current equation is just a guess at the mapping that
  370.                     // 3DS actually uses.
  371.                     shininess = (float) pow(2.0, 1.0 + 0.1 * shininess);
  372.                     //shininess = 2.0f + shininess;
  373.                     //clog << materialName << ": shininess=" << shininess << ", color=" << specular.red << "," << specular.green << "," << specular.blue << 'n';
  374.                     if (shininess > 128.0f)
  375.                         shininess = 128.0f;
  376.                     vl->setShininess(shininess);
  377.                     if (material->getTextureMap() != "")
  378.                     {
  379.                         ResourceHandle tex = GetTextureManager()->getHandle(TextureInfo(material->getTextureMap(), texturePath, TextureInfo::WrapTexture));
  380.                         vl->setTexture(tex);
  381.                     }
  382.                     break;
  383.                 }
  384.             }
  385.         }
  386.     }
  387.     // clean up
  388.     if (faceNormals != NULL)
  389.         delete[] faceNormals;
  390.     if (vertexNormals != NULL)
  391.         delete[] vertexNormals;
  392.     if (faceCounts != NULL)
  393.         delete[] faceCounts;
  394.     if (vertexFaces != NULL)
  395.     {
  396.         for (i = 0; i < nVertices; i++)
  397.         {
  398.             if (vertexFaces[i] != NULL)
  399.                 delete[] vertexFaces[i];
  400.         }
  401.         delete[] vertexFaces;
  402.     }
  403.     return vl;
  404. }
  405. static Mesh*
  406. ConvertVertexListToMesh(VertexList* vlist,
  407.                         const string& /*texPath*/,      //TODO: remove parameter??
  408.                         uint32 material)
  409. {
  410.     Mesh::VertexAttribute attributes[8];
  411.     uint32 nAttributes = 0;
  412.     uint32 offset = 0;
  413.     uint32 parts = vlist->getVertexParts();
  414.     // Position attribute is always present in a vertex list
  415.     attributes[nAttributes] = Mesh::VertexAttribute(Mesh::Position, Mesh::Float3, 0);
  416.     nAttributes++;
  417.     offset += 12;
  418.     if ((parts & VertexList::VertexNormal) != 0)
  419.     {
  420.         attributes[nAttributes] = Mesh::VertexAttribute(Mesh::Normal, Mesh::Float3, offset);
  421.         nAttributes++;
  422.         offset += 12;
  423.     }
  424.     if ((parts & VertexList::VertexColor0) != 0)
  425.     {
  426.         attributes[nAttributes] = Mesh::VertexAttribute(Mesh::Color0, Mesh::UByte4, offset);
  427.         nAttributes++;
  428.         offset += 4;
  429.     }
  430.     if ((parts & VertexList::TexCoord0) != 0)
  431.     {
  432.         attributes[nAttributes] = Mesh::VertexAttribute(Mesh::Texture0, Mesh::Float2, offset);
  433.         nAttributes++;
  434.         offset += 8;
  435.     }
  436.     if ((parts & VertexList::TexCoord1) != 0)
  437.     {
  438.         attributes[nAttributes] = Mesh::VertexAttribute(Mesh::Texture1, Mesh::Float2, offset);
  439.         nAttributes++;
  440.         offset += 8;
  441.     }
  442.     uint32 nVertices = vlist->getVertexCount();
  443.     Mesh* mesh = new Mesh();
  444.     mesh->setVertexDescription(Mesh::VertexDescription(offset, nAttributes, attributes));
  445.     mesh->setVertices(nVertices, vlist->getVertexData());
  446.     // Vertex lists are not indexed, so the conversion to an indexed format is
  447.     // trivial (although much space is wasted storing unnecessary indices.)
  448.     uint32* indices = new uint32[nVertices];
  449.     for (uint32 i = 0; i < nVertices; i++)
  450.         indices[i] = i;
  451.     mesh->addGroup(Mesh::TriList, material, nVertices, indices);
  452.     return mesh;
  453. }
  454. static Model*
  455. Convert3DSModel(const M3DScene& scene, const string& texPath)
  456. {
  457.     Model* model = new Model();
  458.     uint32 materialIndex = 0;
  459.     for (unsigned int i = 0; i < scene.getModelCount(); i++)
  460.     {
  461.         M3DModel* model3ds = scene.getModel(i);
  462.         if (model3ds != NULL)
  463.         {
  464.             for (unsigned int j = 0; j < model3ds->getTriMeshCount(); j++)
  465.             {
  466.                 M3DTriangleMesh* mesh = model3ds->getTriMesh(j);
  467.                 if (mesh != NULL)
  468.                 {
  469.                     // The vertex list is just an intermediate stage in conversion
  470.                     // to a Celestia model structure.  Eventually, we should handle
  471.                     // the conversion in a single step.
  472.                     VertexList* vlist = ConvertToVertexList(*mesh, scene, texPath);
  473.                     Mesh* mesh = ConvertVertexListToMesh(vlist, texPath, materialIndex);
  474.                     // Convert the vertex list material
  475.                     Mesh::Material* material = new Mesh::Material();
  476.                     material->diffuse = vlist->getDiffuseColor();
  477.                     material->specular = vlist->getSpecularColor();
  478.                     material->specularPower = vlist->getShininess();
  479.                     material->opacity = vlist->getDiffuseColor().alpha();
  480.                     material->maps[Mesh::DiffuseMap] = vlist->getTexture();
  481.                     model->addMaterial(material);
  482.                     materialIndex++;
  483.                     model->addMesh(mesh);
  484.                     delete vlist;
  485.                 }
  486.             }
  487.         }
  488.     }
  489.     return model;
  490. #if 0
  491.     // Sort the vertex lists to make sure that the transparent ones are
  492.     // rendered after the opaque ones and material state changes are minimized.
  493.     sort(vertexLists.begin(), vertexLists.end(), compareVertexLists);
  494. #endif
  495. }