Browse Source

Initial model conversion & save in AssetImporter.
Initialize the GeometryBoneMappings of a Model when the number of geometries is set.

Lasse Öörni 15 years ago
parent
commit
039aa0c73a

+ 2 - 2
Engine/Renderer/AnimatedModel.cpp

@@ -519,10 +519,10 @@ void AnimatedModel::updateNode(const FrameInfo& frame)
         // If distance is greater than draw distance, no need to update at all
         // If distance is greater than draw distance, no need to update at all
         if ((mDrawDistance != 0.0f) && (distance > mDrawDistance))
         if ((mDrawDistance != 0.0f) && (distance > mDrawDistance))
             return;
             return;
-        // Multiply the distance by 2 so that invisible nodes don't update that often
+        // Multiply the distance by a constant so that invisible nodes don't update that often
         static const Vector3 dotScale(1 / 3.0f, 1 / 3.0f, 1 / 3.0f);
         static const Vector3 dotScale(1 / 3.0f, 1 / 3.0f, 1 / 3.0f);
         float scale = getWorldScale().dotProduct(dotScale);
         float scale = getWorldScale().dotProduct(dotScale);
-        mAnimationLodDistance = frame.mCamera->getLodDistance(2.0f * distance, scale, mLodBias);
+        mAnimationLodDistance = frame.mCamera->getLodDistance(ANIMATION_LOD_INVISIBLE_FACTOR * distance, scale, mLodBias);
     }
     }
     
     
     updateAnimation(frame);
     updateAnimation(frame);

+ 1 - 0
Engine/Renderer/Model.cpp

@@ -331,6 +331,7 @@ void Model::setBoundingBox(const BoundingBox& box)
 void Model::setNumGeometries(unsigned num)
 void Model::setNumGeometries(unsigned num)
 {
 {
     mGeometries.resize(num);
     mGeometries.resize(num);
+    mGeometryBoneMappings.resize(num);
 }
 }
 
 
 bool Model::setNumGeometryLodLevels(unsigned index, unsigned num)
 bool Model::setNumGeometryLodLevels(unsigned index, unsigned num)

+ 1 - 0
Engine/Renderer/RendererDefs.h

@@ -215,6 +215,7 @@ static const unsigned MASK_DEFAULT = 0xffffffff;
 static const unsigned NO_ELEMENT = 0xffffffff;
 static const unsigned NO_ELEMENT = 0xffffffff;
 
 
 static const float ANIMATION_LOD_BASESCALE = 2500.0f;
 static const float ANIMATION_LOD_BASESCALE = 2500.0f;
+static const float ANIMATION_LOD_INVISIBLE_FACTOR = 2.0f;
 
 
 static const unsigned MAX_VERTEX_LIGHTS = 4;
 static const unsigned MAX_VERTEX_LIGHTS = 4;
 
 

+ 172 - 22
Tools/AssetImporter/AssetImporter.cpp

@@ -23,9 +23,13 @@
 
 
 #include "Exception.h"
 #include "Exception.h"
 #include "File.h"
 #include "File.h"
+#include "Geometry.h"
+#include "IndexBuffer.h"
+#include "Model.h"
 #include "Quaternion.h"
 #include "Quaternion.h"
 #include "StringUtils.h"
 #include "StringUtils.h"
 #include "Vector3.h"
 #include "Vector3.h"
+#include "VertexBuffer.h"
 #include "XMLFile.h"
 #include "XMLFile.h"
 
 
 #include <algorithm>
 #include <algorithm>
@@ -40,14 +44,35 @@
 
 
 #include "DebugNew.h"
 #include "DebugNew.h"
 
 
+struct ExportModel
+{
+    ExportModel() :
+        mTotalVertices(0),
+        mTotalIndices(0)
+    {
+    }
+    
+    std::string mOutName;
+    const aiScene* mScene;
+    aiNode* mRootNode;
+    std::vector<aiMesh*> mMeshes;
+    std::vector<aiNode*> mMeshNodes;
+    unsigned mTotalVertices;
+    unsigned mTotalIndices;
+};
+
 int main(int argc, char** argv);
 int main(int argc, char** argv);
 void run(const std::vector<std::string>& arguments);
 void run(const std::vector<std::string>& arguments);
 void errorExit(const std::string& error);
 void errorExit(const std::string& error);
-void processNode(const aiScene* scene, aiNode* node);
+void exportModel(ExportModel& model);
+void collectMeshes(ExportModel& model, aiNode* node);
+void buildModel(ExportModel& model);
 std::string toStdString(const aiString& str);
 std::string toStdString(const aiString& str);
 Vector3 toVector3(const aiVector3D& vec);
 Vector3 toVector3(const aiVector3D& vec);
 Vector2 toVector2(const aiVector2D& vec);
 Vector2 toVector2(const aiVector2D& vec);
 Quaternion toQuaternion(const aiQuaternion& quat);
 Quaternion toQuaternion(const aiQuaternion& quat);
+aiMatrix4x4 getWorldTransform(aiNode* node, aiNode* baseNode);
+void getPosRotScale(const aiMatrix4x4& transform, Vector3& pos, Quaternion& rot, Vector3& scale);
 
 
 int main(int argc, char** argv)
 int main(int argc, char** argv)
 {
 {
@@ -69,11 +94,10 @@ int main(int argc, char** argv)
     return 0;
     return 0;
 }
 }
 
 
-
 void run(const std::vector<std::string>& arguments)
 void run(const std::vector<std::string>& arguments)
 {
 {
-    if (arguments.size() < 1)
-        errorExit("Usage: AssetImporter <inputfile>\n");
+    if (arguments.size() < 2)
+        errorExit("Usage: AssetImporter <inputfile> <outputfile>\n");
     
     
     Assimp::Importer importer;
     Assimp::Importer importer;
     const aiScene* scene = importer.ReadFile(arguments[0].c_str(),
     const aiScene* scene = importer.ReadFile(arguments[0].c_str(),
@@ -91,32 +115,135 @@ void run(const std::vector<std::string>& arguments)
     if (!scene)
     if (!scene)
         errorExit("Could not open input file " + arguments[0]);
         errorExit("Could not open input file " + arguments[0]);
     
     
-    aiNode* rootNode = scene->mRootNode;
-    if (rootNode)
-        processNode(scene, rootNode);
+    ExportModel model;
+    model.mOutName = arguments[1];
+    model.mScene = scene;
+    model.mRootNode = scene->mRootNode;
+    exportModel(model);
 }
 }
 
 
-void processNode(const aiScene* scene, aiNode* node)
+void exportModel(ExportModel& model)
+{
+    collectMeshes(model, model.mRootNode);
+    buildModel(model);
+}
+
+void collectMeshes(ExportModel& model, aiNode* node)
 {
 {
-    aiVector3D aiPos;
-    aiQuaternion aiRot;
-    aiVector3D aiScale;
-    node->mTransformation.Decompose(aiScale, aiRot, aiPos);
-    
-    std::cout << "Node name: " << toStdString(node->mName) << std::endl;
-    std::cout << "Pos: " << toString(toVector3(aiPos)) << std::endl;
-    std::cout << "Rot: " << toString(toQuaternion(aiRot)) << std::endl;
-    
     for (unsigned i = 0; i < node->mNumMeshes; ++i)
     for (unsigned i = 0; i < node->mNumMeshes; ++i)
     {
     {
-        aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
-        std::cout << "Mesh name: " << toStdString(mesh->mName) << std::endl;
-        std::cout << "Vertices: " << mesh->mNumVertices << std::endl;
-        std::cout << "Faces: " << mesh->mNumFaces << std::endl;
+        aiMesh* mesh = model.mScene->mMeshes[node->mMeshes[i]];
+        model.mMeshes.push_back(mesh);
+        model.mMeshNodes.push_back(node);
+        
+        model.mTotalVertices += mesh->mNumVertices;
+        model.mTotalIndices += mesh->mNumFaces * 3;
     }
     }
     
     
     for (unsigned i = 0; i < node->mNumChildren; ++i)
     for (unsigned i = 0; i < node->mNumChildren; ++i)
-        processNode(scene, node->mChildren[i]);
+        collectMeshes(model, node->mChildren[i]);
+}
+
+void buildModel(ExportModel& model)
+{
+    SharedPtr<Model> outModel(new Model(0));
+    outModel->setNumGeometries(model.mMeshes.size());
+    BoundingBox box;
+    
+    for (unsigned i = 0; i < model.mMeshes.size(); ++i)
+    {
+        SharedPtr<IndexBuffer> ib(new IndexBuffer(0));
+        SharedPtr<VertexBuffer> vb(new VertexBuffer(0));
+        SharedPtr<Geometry> geom(new Geometry());
+        
+        // Get the world transform of the mesh for baking into the vertices
+        Vector3 pos;
+        Quaternion rot;
+        Vector3 scale;
+        getPosRotScale(getWorldTransform(model.mMeshNodes[i], model.mRootNode), pos, rot, scale);
+        Matrix4x3 vertexTransform;
+        vertexTransform.define(pos, rot, scale);
+        Matrix3 normalTransform = rot.getRotationMatrix();
+        
+        aiMesh* mesh = model.mMeshes[i];
+        bool largeIndices = mesh->mNumVertices > 65535;
+        unsigned elementMask = MASK_POSITION;
+        if (mesh->HasNormals())
+            elementMask |= MASK_NORMAL;
+        //if (mesh->HasTangentsAndBitangents())
+        //    elementMask |= MASK_TANGENT;
+        //if (mesh->GetNumColorChannels() > 0)
+        //    elementMask |= MASK_COLOR;
+        if (mesh->GetNumUVChannels() > 0)
+            elementMask |= MASK_TEXCOORD1;
+        //if (mesh->GetNumUVChannels() > 1)
+        //    elementMask |= MASK_TEXCOORD2;
+        
+        ib->setSize(mesh->mNumFaces * 3, largeIndices);
+        vb->setSize(mesh->mNumVertices, elementMask);
+        
+        // Build the index data
+        void* indexData = ib->lock(0, ib->getIndexCount(), LOCK_NORMAL);
+        if (!largeIndices)
+        {
+            unsigned short* dest = (unsigned short*)indexData;
+            for (unsigned j = 0; j < mesh->mNumFaces; ++j)
+            {
+                *dest++ = mesh->mFaces[j].mIndices[0];
+                *dest++ = mesh->mFaces[j].mIndices[1];
+                *dest++ = mesh->mFaces[j].mIndices[2];
+            }
+        }
+        else
+        {
+            unsigned* dest = (unsigned*)indexData;
+            for (unsigned j = 0; j < mesh->mNumFaces; ++j)
+            {
+                *dest++ = mesh->mFaces[j].mIndices[0];
+                *dest++ = mesh->mFaces[j].mIndices[1];
+                *dest++ = mesh->mFaces[j].mIndices[2];
+            }
+        }
+        
+        // Build the vertex data
+        void* vertexData = vb->lock(0, vb->getVertexCount(), LOCK_NORMAL);
+        float* dest = (float*)vertexData;
+        for (unsigned j = 0; j < mesh->mNumVertices; ++j)
+        {
+            Vector3 vertex = vertexTransform * toVector3(mesh->mVertices[j]);
+            box.merge(vertex);
+            *dest++ = vertex.mX;
+            *dest++ = vertex.mY;
+            *dest++ = vertex.mZ;
+            if (elementMask & MASK_NORMAL)
+            {
+                Vector3 normal = normalTransform * toVector3(mesh->mNormals[j]);
+                *dest++ = normal.mX;
+                *dest++ = normal.mY;
+                *dest++ = normal.mZ;
+            }
+            if (elementMask & MASK_TEXCOORD1)
+            {
+                Vector3 texCoord = toVector3(mesh->mTextureCoords[0][j]);
+                *dest++ = texCoord.mX;
+                *dest++ = texCoord.mY;
+            }
+        }
+        
+        ib->unlock();
+        vb->unlock();
+        
+        // Define the geometry
+        geom->setIndexBuffer(ib);
+        geom->setVertexBuffer(0, vb);
+        geom->setDrawRange(TRIANGLE_LIST, 0, mesh->mNumFaces * 3, true);
+        outModel->setNumGeometryLodLevels(i, 1);
+        outModel->setGeometry(i, 0, geom);
+        outModel->setBoundingBox(box);
+    }
+    
+    File outFile(model.mOutName, FILE_WRITE);
+    outModel->save(outFile);
 }
 }
 
 
 void errorExit(const std::string& error)
 void errorExit(const std::string& error)
@@ -143,3 +270,26 @@ Quaternion toQuaternion(const aiQuaternion& quat)
 {
 {
     return Quaternion(quat.w, quat.x, quat.y, quat.z);
     return Quaternion(quat.w, quat.x, quat.y, quat.z);
 }
 }
+
+aiMatrix4x4 getWorldTransform(aiNode* node, aiNode* baseNode)
+{
+    aiMatrix4x4 current = node->mTransformation;
+    // If basenode is defined, go only up to it in the parent chain
+    while ((node->mParent) && (node != baseNode))
+    {
+        node = node->mParent;
+        current = node->mTransformation * current;
+    }
+    return current;
+}
+
+void getPosRotScale(const aiMatrix4x4& transform, Vector3& pos, Quaternion& rot, Vector3& scale)
+{
+    aiVector3D aiPos;
+    aiQuaternion aiRot;
+    aiVector3D aiScale;
+    transform.Decompose(aiScale, aiRot, aiPos);
+    pos = toVector3(aiPos);
+    rot = toQuaternion(aiRot);
+    scale = toVector3(aiScale);
+}

+ 3 - 3
Tools/AssetImporter/CMakeLists.txt

@@ -8,12 +8,12 @@ set (SOURCE_FILES ${CPP_FILES} ${H_FILES})
 
 
 # Include directories
 # Include directories
 include_directories (
 include_directories (
-    ../../Engine/Common ../../Engine/Event ../../Engine/Math ../../Engine/Physics ../../Engine/Renderer
-    ../../Engine/Resource ../../ThirdParty/TinyXML ../../ThirdParty/Assimp/include
+    ../../Engine/Common ../../Engine/Math ../../Engine/Renderer ../../Engine/Resource ../../Engine/Scene
+    ../../ThirdParty/Assimp/include
 )
 )
 
 
 # Define target & libraries to link
 # Define target & libraries to link
 add_executable (${TARGET_NAME} ${SOURCE_FILES})
 add_executable (${TARGET_NAME} ${SOURCE_FILES})
-target_link_libraries (${TARGET_NAME} Assimp Common Math Resource TinyXML)
+target_link_libraries (${TARGET_NAME} Assimp Common Math Renderer Scene Resource)
 finalize_exe ()
 finalize_exe ()