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

OpenGL

开发平台:

Visual C++

  1. // 3dstocmod.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. //
  10. // Convert a 3DS file to a Celestia mesh (.cmod) file
  11. #include <celengine/modelfile.h>
  12. #include <celengine/tokenizer.h>
  13. #include <celengine/texmanager.h>
  14. #include <cel3ds/3dsread.h>
  15. #include <cstring>
  16. #include <cassert>
  17. #include <cmath>
  18. #include <cstdio>
  19. static Model* Convert3DSModel(const M3DScene& scene, const string& texPath);
  20. void usage()
  21. {
  22.     cerr << "Usage: 3dstocmod <input 3ds file>n";
  23. }
  24. int main(int argc, char* argv[])
  25. {
  26.     if (argc != 2)
  27.     {
  28.         usage();
  29.         return 1;
  30.     }
  31.     string inputFileName = argv[1];
  32.     M3DScene* scene = Read3DSFile(inputFileName);
  33.     if (scene == NULL)
  34.     {
  35.         cerr << "Error reading 3DS file '" << inputFileName << "'n";
  36.         return 1;
  37.     }
  38.     Model* model = Convert3DSModel(*scene, ".");
  39.     if (!model)
  40.     {
  41.         cerr << "Error converting 3DS file to Celestia modeln";
  42.         return 1;
  43.     }
  44.     for (uint32 i = 0; model->getMesh(i); i++)
  45.     {
  46.         const Mesh* mesh = model->getMesh(i);
  47.         for (uint32 j = 0; mesh->getGroup(j); j++)
  48.         {
  49.             const Mesh::PrimitiveGroup* group = mesh->getGroup(j);
  50.             cerr << "Group: #" << i << ", indices=" << group->nIndices << 'n';
  51.         }
  52.     }
  53.     SaveModelAscii(model, cout);
  54.     return 0;
  55. }
  56. void
  57. Convert3DSMesh(Model& model,
  58.                M3DTriangleMesh& mesh3ds,
  59.                const M3DScene& scene,
  60.                const string& meshName)
  61. {
  62.     int nFaces = mesh3ds.getFaceCount();
  63.     int nVertices = mesh3ds.getVertexCount();
  64.     int nTexCoords = mesh3ds.getTexCoordCount();
  65.     bool smooth = (mesh3ds.getSmoothingGroupCount() == nFaces);
  66.     bool hasTexCoords = (nTexCoords >= nVertices);
  67.     int vertexSize = hasTexCoords ? 8 : 6;
  68.     int i;
  69.     Vec3f* faceNormals = new Vec3f[nFaces];
  70.     Vec3f* vertexNormals = new Vec3f[nFaces * 3];
  71.     int* faceCounts = new int[nVertices];
  72.     int** vertexFaces = new int*[nVertices];
  73.     int nOutputVertices = nFaces * 3;
  74.     float* vertices = new float[nOutputVertices * vertexSize];
  75.     
  76.     for (i = 0; i < nVertices; i++)
  77.     {
  78.         faceCounts[i] = 0;
  79.         vertexFaces[i] = NULL;
  80.     }
  81.     // generate face normals
  82.     for (i = 0; i < nFaces; i++)
  83.     {
  84.         uint16 v0, v1, v2;
  85.         mesh3ds.getFace(i, v0, v1, v2);
  86.         faceCounts[v0]++;
  87.         faceCounts[v1]++;
  88.         faceCounts[v2]++;
  89.         Point3f p0 = mesh3ds.getVertex(v0);
  90.         Point3f p1 = mesh3ds.getVertex(v1);
  91.         Point3f p2 = mesh3ds.getVertex(v2);
  92.         faceNormals[i] = cross(p1 - p0, p2 - p1);
  93.         faceNormals[i].normalize();
  94.     }
  95.     if (!smooth && 0)
  96.     {
  97.         for (i = 0; i < nFaces; i++)
  98.         {
  99.             vertexNormals[i * 3] = faceNormals[i];
  100.             vertexNormals[i * 3 + 1] = faceNormals[i];
  101.             vertexNormals[i * 3 + 2] = faceNormals[i];
  102.         }
  103.     }
  104.     else
  105.     {
  106.         // allocate space for vertex face indices
  107.         for (i = 0; i < nVertices; i++)
  108.         {
  109.             vertexFaces[i] = new int[faceCounts[i] + 1];
  110.             vertexFaces[i][0] = faceCounts[i];
  111.         }
  112.         for (i = 0; i < nFaces; i++)
  113.         {
  114.             uint16 v0, v1, v2;
  115.             mesh3ds.getFace(i, v0, v1, v2);
  116.             vertexFaces[v0][faceCounts[v0]--] = i;
  117.             vertexFaces[v1][faceCounts[v1]--] = i;
  118.             vertexFaces[v2][faceCounts[v2]--] = i;
  119.         }
  120.         // average face normals to compute the vertex normals
  121.         for (i = 0; i < nFaces; i++)
  122.         {
  123.             uint16 v0, v1, v2;
  124.             mesh3ds.getFace(i, v0, v1, v2);
  125.             // uint32 smoothingGroups = mesh3ds.getSmoothingGroups(i);
  126.             int j;
  127.             Vec3f v = Vec3f(0, 0, 0);
  128.             for (j = 1; j <= vertexFaces[v0][0]; j++)
  129.             {
  130.                 int k = vertexFaces[v0][j];
  131.                 // if (k == i || (smoothingGroups & mesh3ds.getSmoothingGroups(k)) != 0)
  132.                 if (faceNormals[i] * faceNormals[k] > 0.5f)
  133.                     v += faceNormals[k];
  134.             }
  135.             if (v * v == 0.0f)
  136.                 v = Vec3f(1.0f, 0.0f, 0.0f);
  137.             v.normalize();
  138.             vertexNormals[i * 3] = v;
  139.             v = Vec3f(0, 0, 0);
  140.             for (j = 1; j <= vertexFaces[v1][0]; j++)
  141.             {
  142.                 int k = vertexFaces[v1][j];
  143.                 // if (k == i || (smoothingGroups & mesh3ds.getSmoothingGroups(k)) != 0)
  144.                 if (faceNormals[i] * faceNormals[k] > 0.5f)
  145.                     v += faceNormals[k];
  146.             }
  147.             if (v * v == 0.0f)
  148.                 v = Vec3f(1.0f, 0.0f, 0.0f);
  149.             v.normalize();
  150.             vertexNormals[i * 3 + 1] = v;
  151.             v = Vec3f(0, 0, 0);
  152.             for (j = 1; j <= vertexFaces[v2][0]; j++)
  153.             {
  154.                 int k = vertexFaces[v2][j];
  155.                 // if (k == i || (smoothingGroups & mesh3ds.getSmoothingGroups(k)) != 0)
  156.                 if (faceNormals[i] * faceNormals[k] > 0.5f)
  157.                     v += faceNormals[k];
  158.             }
  159.             if (v * v == 0.0f)
  160.                 v = Vec3f(1.0f, 0.0f, 0.0f);
  161.             v.normalize();
  162.             vertexNormals[i * 3 + 2] = v;
  163.         }
  164.     }
  165.     // build the triangle list
  166.     for (i = 0; i < nFaces; i++)
  167.     {
  168.         uint16 triVert[3];
  169.         mesh3ds.getFace(i, triVert[0], triVert[1], triVert[2]);
  170.         for (int j = 0; j < 3; j++)
  171.         {
  172.             Point3f pos = mesh3ds.getVertex(triVert[j]);
  173.             Vec3f norm = vertexNormals[i * 3 + j];
  174.             int k = (i * 3 + j) * vertexSize;
  175.             vertices[k + 0] = pos.x;
  176.             vertices[k + 1] = pos.y;
  177.             vertices[k + 2] = pos.z;
  178.             vertices[k + 3] = norm.x;
  179.             vertices[k + 4] = norm.y;
  180.             vertices[k + 5] = norm.z;
  181.             if (hasTexCoords)
  182.             {
  183.                 vertices[k + 6] = mesh3ds.getTexCoord(triVert[j]).x;
  184.                 vertices[k + 7] = mesh3ds.getTexCoord(triVert[j]).y;
  185.             }
  186.         }
  187.     }
  188.     // clean up
  189.     if (faceNormals != NULL)
  190.         delete[] faceNormals;
  191.     if (vertexNormals != NULL)
  192.         delete[] vertexNormals;
  193.     if (faceCounts != NULL)
  194.         delete[] faceCounts;
  195.     if (vertexFaces != NULL)
  196.     {
  197.         for (i = 0; i < nVertices; i++)
  198.         {
  199.             if (vertexFaces[i] != NULL)
  200.                 delete[] vertexFaces[i];
  201.         }
  202.         delete[] vertexFaces;
  203.     }
  204.     Mesh::VertexAttribute attributes[8];
  205.     uint32 nAttributes = 0;
  206.     uint32 offset = 0;
  207.     // Position attribute is always present
  208.     attributes[nAttributes] = Mesh::VertexAttribute(Mesh::Position, Mesh::Float3, 0);
  209.     nAttributes++;
  210.     offset += 12;
  211.     // Normal attribute is always present
  212.     attributes[nAttributes] = Mesh::VertexAttribute(Mesh::Normal, Mesh::Float3, offset);
  213.     nAttributes++;
  214.     offset += 12;
  215.     if (hasTexCoords)
  216.     {
  217.         attributes[nAttributes] = Mesh::VertexAttribute(Mesh::Texture0, Mesh::Float2, offset);
  218.         nAttributes++;
  219.         offset += 8;
  220.     }
  221.     // Create the Celestia mesh
  222.     Mesh* mesh = new Mesh();
  223.     mesh->setVertexDescription(Mesh::VertexDescription(offset, nAttributes, attributes));
  224.     mesh->setVertices(nOutputVertices, vertices);
  225.     mesh->setName(meshName);
  226.     // Vertex lists are not indexed, so the conversion to an indexed format is
  227.     // trivial (although much space is wasted storing unnecessary indices.)
  228.     uint32* indices = new uint32[nOutputVertices];
  229.     for (int i = 0; i < nOutputVertices; i++)
  230.         indices[i] = i;
  231.     // Convert the 3DS mesh's material
  232.     Mesh::Material* material = new Mesh::Material();
  233.     string material3dsName = mesh3ds.getMaterialName();
  234.     if (material3dsName.length() > 0)
  235.     {
  236.         int nMaterials = scene.getMaterialCount();
  237.         for (int i = 0; i < nMaterials; i++)
  238.         {
  239.             M3DMaterial* material3ds = scene.getMaterial(i);
  240.             if (material3dsName == material3ds->getName())
  241.             {
  242.                 M3DColor diffuse = material3ds->getDiffuseColor();
  243.                 material->diffuse = Color(diffuse.red, diffuse.green, diffuse.blue);
  244.                 M3DColor specular = material3ds->getSpecularColor();
  245.                 material->specular = Color(specular.red, specular.green, specular.blue);
  246.                 // Map the shininess from the 3DS file into the 0-128
  247.                 // range that OpenGL uses for the specular exponent.
  248.                 float specPow = (float) pow(2.0, 1.0 + 0.1 * material3ds->getShininess());
  249.                 if (specPow > 128.0f)
  250.                     specPow = 128.0f;
  251.                 material->specularPower = specPow;
  252.                 material->opacity = material3ds->getOpacity();
  253.                 if (material3ds->getTextureMap() != "")
  254.                 {
  255.                     material->maps[Mesh::DiffuseMap] = GetTextureManager()->getHandle(TextureInfo(material3ds->getTextureMap(), ".", TextureInfo::WrapTexture));
  256.                 }
  257.             }
  258.         }
  259.     }
  260.     uint32 materialIndex = model.addMaterial(material) - 1;
  261.     mesh->addGroup(Mesh::TriList, materialIndex, nOutputVertices, indices);
  262.     model.addMesh(mesh);
  263. }
  264. static Model*
  265. Convert3DSModel(const M3DScene& scene, const string& texPath)
  266. {
  267.     Model* model = new Model();
  268.     uint32 materialIndex = 0;
  269.     for (unsigned int i = 0; i < scene.getModelCount(); i++)
  270.     {
  271.         M3DModel* model3ds = scene.getModel(i);
  272.         if (model3ds != NULL)
  273.         {
  274.             for (unsigned int j = 0; j < model3ds->getTriMeshCount(); j++)
  275.             {
  276.                 M3DTriangleMesh* mesh = model3ds->getTriMesh(j);
  277.                 if (mesh != NULL && mesh->getFaceCount() > 0)
  278.                 {
  279.                     Convert3DSMesh(*model, *mesh, scene, model3ds->getName());
  280.                 }
  281.             }
  282.         }
  283.     }
  284.     return model;
  285. #if 0
  286.     // Sort the vertex lists to make sure that the transparent ones are
  287.     // rendered after the opaque ones and material state changes are minimized.
  288.     sort(vertexLists.begin(), vertexLists.end(), compareVertexLists);
  289. #endif
  290. }