3dstocmod.cpp

来自「celestia源代码」· C++ 代码 · 共 340 行

CPP
340
字号
// 3dstocmod.cpp//// Copyright (C) 2004, Chris Laurel <claurel@shatters.net>//// This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License// as published by the Free Software Foundation; either version 2// of the License, or (at your option) any later version.//// Convert a 3DS file to a Celestia mesh (.cmod) file#include <celengine/modelfile.h>#include <celengine/tokenizer.h>#include <celengine/texmanager.h>#include <cel3ds/3dsread.h>#include <cstring>#include <cassert>#include <cmath>#include <cstdio>static Model* Convert3DSModel(const M3DScene& scene, const string& texPath);void usage(){    cerr << "Usage: 3dstocmod <input 3ds file>\n";}int main(int argc, char* argv[]){    if (argc != 2)    {        usage();        return 1;    }    string inputFileName = argv[1];    M3DScene* scene = Read3DSFile(inputFileName);    if (scene == NULL)    {        cerr << "Error reading 3DS file '" << inputFileName << "'\n";        return 1;    }    Model* model = Convert3DSModel(*scene, ".");    if (!model)    {        cerr << "Error converting 3DS file to Celestia model\n";        return 1;    }    for (uint32 i = 0; model->getMesh(i); i++)    {        const Mesh* mesh = model->getMesh(i);        for (uint32 j = 0; mesh->getGroup(j); j++)        {            const Mesh::PrimitiveGroup* group = mesh->getGroup(j);            cerr << "Group: #" << i << ", indices=" << group->nIndices << '\n';        }    }    SaveModelAscii(model, cout);    return 0;}voidConvert3DSMesh(Model& model,               M3DTriangleMesh& mesh3ds,               const M3DScene& scene,               const string& meshName){    int nFaces = mesh3ds.getFaceCount();    int nVertices = mesh3ds.getVertexCount();    int nTexCoords = mesh3ds.getTexCoordCount();    bool smooth = (mesh3ds.getSmoothingGroupCount() == nFaces);    bool hasTexCoords = (nTexCoords == nVertices);    int vertexSize = hasTexCoords ? 8 : 6;    int i;    Vec3f* faceNormals = new Vec3f[nFaces];    Vec3f* vertexNormals = new Vec3f[nFaces * 3];    int* faceCounts = new int[nVertices];    int** vertexFaces = new int*[nVertices];    int nOutputVertices = nFaces * 3;    float* vertices = new float[nOutputVertices * vertexSize];        for (i = 0; i < nVertices; i++)    {        faceCounts[i] = 0;        vertexFaces[i] = NULL;    }    // generate face normals    for (i = 0; i < nFaces; i++)    {        uint16 v0, v1, v2;        mesh3ds.getFace(i, v0, v1, v2);        faceCounts[v0]++;        faceCounts[v1]++;        faceCounts[v2]++;        Point3f p0 = mesh3ds.getVertex(v0);        Point3f p1 = mesh3ds.getVertex(v1);        Point3f p2 = mesh3ds.getVertex(v2);        faceNormals[i] = cross(p1 - p0, p2 - p1);        faceNormals[i].normalize();    }    if (!smooth && 0)    {        for (i = 0; i < nFaces; i++)        {            vertexNormals[i * 3] = faceNormals[i];            vertexNormals[i * 3 + 1] = faceNormals[i];            vertexNormals[i * 3 + 2] = faceNormals[i];        }    }    else    {        // allocate space for vertex face indices        for (i = 0; i < nVertices; i++)        {            vertexFaces[i] = new int[faceCounts[i] + 1];            vertexFaces[i][0] = faceCounts[i];        }        for (i = 0; i < nFaces; i++)        {            uint16 v0, v1, v2;            mesh3ds.getFace(i, v0, v1, v2);            vertexFaces[v0][faceCounts[v0]--] = i;            vertexFaces[v1][faceCounts[v1]--] = i;            vertexFaces[v2][faceCounts[v2]--] = i;        }        // average face normals to compute the vertex normals        for (i = 0; i < nFaces; i++)        {            uint16 v0, v1, v2;            mesh3ds.getFace(i, v0, v1, v2);            // uint32 smoothingGroups = mesh3ds.getSmoothingGroups(i);            int j;            Vec3f v = Vec3f(0, 0, 0);            for (j = 1; j <= vertexFaces[v0][0]; j++)            {                int k = vertexFaces[v0][j];                // if (k == i || (smoothingGroups & mesh3ds.getSmoothingGroups(k)) != 0)                if (faceNormals[i] * faceNormals[k] > 0.5f)                    v += faceNormals[k];            }            if (v * v == 0.0f)                v = Vec3f(1.0f, 0.0f, 0.0f);            v.normalize();            vertexNormals[i * 3] = v;            v = Vec3f(0, 0, 0);            for (j = 1; j <= vertexFaces[v1][0]; j++)            {                int k = vertexFaces[v1][j];                // if (k == i || (smoothingGroups & mesh3ds.getSmoothingGroups(k)) != 0)                if (faceNormals[i] * faceNormals[k] > 0.5f)                    v += faceNormals[k];            }            if (v * v == 0.0f)                v = Vec3f(1.0f, 0.0f, 0.0f);            v.normalize();            vertexNormals[i * 3 + 1] = v;            v = Vec3f(0, 0, 0);            for (j = 1; j <= vertexFaces[v2][0]; j++)            {                int k = vertexFaces[v2][j];                // if (k == i || (smoothingGroups & mesh3ds.getSmoothingGroups(k)) != 0)                if (faceNormals[i] * faceNormals[k] > 0.5f)                    v += faceNormals[k];            }            if (v * v == 0.0f)                v = Vec3f(1.0f, 0.0f, 0.0f);            v.normalize();            vertexNormals[i * 3 + 2] = v;        }    }    // build the triangle list    for (i = 0; i < nFaces; i++)    {        uint16 triVert[3];        mesh3ds.getFace(i, triVert[0], triVert[1], triVert[2]);        for (int j = 0; j < 3; j++)        {            Point3f pos = mesh3ds.getVertex(triVert[j]);            Vec3f norm = vertexNormals[i * 3 + j];            int k = (i * 3 + j) * vertexSize;            vertices[k + 0] = pos.x;            vertices[k + 1] = pos.y;            vertices[k + 2] = pos.z;            vertices[k + 3] = norm.x;            vertices[k + 4] = norm.y;            vertices[k + 5] = norm.z;            if (hasTexCoords)            {                vertices[k + 6] = mesh3ds.getTexCoord(triVert[j]).x;                vertices[k + 7] = mesh3ds.getTexCoord(triVert[j]).y;            }        }    }    // clean up    if (faceNormals != NULL)        delete[] faceNormals;    if (vertexNormals != NULL)        delete[] vertexNormals;    if (faceCounts != NULL)        delete[] faceCounts;    if (vertexFaces != NULL)    {        for (i = 0; i < nVertices; i++)        {            if (vertexFaces[i] != NULL)                delete[] vertexFaces[i];        }        delete[] vertexFaces;    }    Mesh::VertexAttribute attributes[8];    uint32 nAttributes = 0;    uint32 offset = 0;    // Position attribute is always present    attributes[nAttributes] = Mesh::VertexAttribute(Mesh::Position, Mesh::Float3, 0);    nAttributes++;    offset += 12;    // Normal attribute is always present    attributes[nAttributes] = Mesh::VertexAttribute(Mesh::Normal, Mesh::Float3, offset);    nAttributes++;    offset += 12;    if (hasTexCoords)    {        attributes[nAttributes] = Mesh::VertexAttribute(Mesh::Texture0, Mesh::Float2, offset);        nAttributes++;        offset += 8;    }    // Create the Celestia mesh    Mesh* mesh = new Mesh();    mesh->setVertexDescription(Mesh::VertexDescription(offset, nAttributes, attributes));    mesh->setVertices(nOutputVertices, vertices);    mesh->setName(meshName);    // Vertex lists are not indexed, so the conversion to an indexed format is    // trivial (although much space is wasted storing unnecessary indices.)    uint32* indices = new uint32[nOutputVertices];    for (int i = 0; i < nOutputVertices; i++)        indices[i] = i;    // Convert the 3DS mesh's material    Mesh::Material* material = new Mesh::Material();    string material3dsName = mesh3ds.getMaterialName();    if (material3dsName.length() > 0)    {        int nMaterials = scene.getMaterialCount();        for (int i = 0; i < nMaterials; i++)        {            M3DMaterial* material3ds = scene.getMaterial(i);            if (material3dsName == material3ds->getName())            {                M3DColor diffuse = material3ds->getDiffuseColor();                material->diffuse = Color(diffuse.red, diffuse.green, diffuse.blue);                M3DColor specular = material3ds->getSpecularColor();                material->specular = Color(specular.red, specular.green, specular.blue);                // Map the shininess from the 3DS file into the 0-128                // range that OpenGL uses for the specular exponent.                float specPow = (float) pow(2, 10.0 * material3ds->getShininess());                if (specPow > 128.0f)                    specPow = 128.0f;                material->specularPower = specPow;                material->opacity = material3ds->getOpacity();                if (material3ds->getTextureMap() != "")                {                    material->maps[Mesh::DiffuseMap] = GetTextureManager()->getHandle(TextureInfo(material3ds->getTextureMap(), ".", TextureInfo::WrapTexture));                }            }        }    }    uint32 materialIndex = model.addMaterial(material) - 1;    mesh->addGroup(Mesh::TriList, materialIndex, nOutputVertices, indices);    model.addMesh(mesh);}static Model*Convert3DSModel(const M3DScene& scene, const string& texPath){    Model* model = new Model();    uint32 materialIndex = 0;    for (unsigned int i = 0; i < scene.getModelCount(); i++)    {        M3DModel* model3ds = scene.getModel(i);        if (model3ds != NULL)        {            for (unsigned int j = 0; j < model3ds->getTriMeshCount(); j++)            {                M3DTriangleMesh* mesh = model3ds->getTriMesh(j);                if (mesh != NULL && mesh->getFaceCount() > 0)                {                    Convert3DSMesh(*model, *mesh, scene, model3ds->getName());                }            }        }    }    return model;#if 0    // Sort the vertex lists to make sure that the transparent ones are    // rendered after the opaque ones and material state changes are minimized.    sort(vertexLists.begin(), vertexLists.end(), compareVertexLists);#endif}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?