Browse Source

Merge pull request #254 from AtomicGameEngine/JME-ATOMIC-MDLIMPORT

Store animation data on model, instead of on AnimationController component, MDL import
JoshEngebretson 10 years ago
parent
commit
93d6847b51

+ 2 - 1
Script/AtomicEditor/ui/frames/inspector/CreateComponentButton.ts

@@ -23,7 +23,8 @@ _2DCreateSource.addItem(new Atomic.UIMenuItem("TileMap2D", "TileMap2D"));
 var geometryCreateSource = new Atomic.UIMenuItemSource();
 var geometryCreateSource = new Atomic.UIMenuItemSource();
 
 
 geometryCreateSource.addItem(new Atomic.UIMenuItem("StaticModel", "StaticModel"));
 geometryCreateSource.addItem(new Atomic.UIMenuItem("StaticModel", "StaticModel"));
-geometryCreateSource.addItem(new Atomic.UIMenuItem("AnimatedModel", "create component"));
+geometryCreateSource.addItem(new Atomic.UIMenuItem("AnimatedModel", "AnimatedModel"));
+geometryCreateSource.addItem(new Atomic.UIMenuItem("AnimationController", "AnimationController"));
 geometryCreateSource.addItem(new Atomic.UIMenuItem("BillboardSet", "create component"));
 geometryCreateSource.addItem(new Atomic.UIMenuItem("BillboardSet", "create component"));
 geometryCreateSource.addItem(new Atomic.UIMenuItem("CustomGeometry", "create component"));
 geometryCreateSource.addItem(new Atomic.UIMenuItem("CustomGeometry", "create component"));
 geometryCreateSource.addItem(new Atomic.UIMenuItem("ParticleEmitter", "create component"));
 geometryCreateSource.addItem(new Atomic.UIMenuItem("ParticleEmitter", "create component"));

+ 16 - 19
Source/Atomic/Atomic3D/AnimationController.cpp

@@ -51,8 +51,7 @@ static const unsigned MAX_NODE_ANIMATION_STATES = 256;
 extern const char* LOGIC_CATEGORY;
 extern const char* LOGIC_CATEGORY;
 
 
 AnimationController::AnimationController(Context* context) :
 AnimationController::AnimationController(Context* context) :
-    Component(context),
-    animationsResourcesAttr_(Animation::GetTypeStatic())
+    Component(context)
 {
 {
 }
 }
 
 
@@ -72,8 +71,6 @@ void AnimationController::RegisterObject(Context* context)
     MIXED_ACCESSOR_ATTRIBUTE("Node Animation States", GetNodeAnimationStatesAttr, SetNodeAnimationStatesAttr, VariantVector,
     MIXED_ACCESSOR_ATTRIBUTE("Node Animation States", GetNodeAnimationStatesAttr, SetNodeAnimationStatesAttr, VariantVector,
         Variant::emptyVariantVector, AM_FILE | AM_NOEDIT);
         Variant::emptyVariantVector, AM_FILE | AM_NOEDIT);
 
 
-    ACCESSOR_ATTRIBUTE("Animation Resources", GetAnimationResourcesAttr, SetAnimationResourcesAttr, ResourceRefList, ResourceRefList(Animation::GetTypeStatic()), AM_FILE | AM_NOEDIT);
-
 }
 }
 
 
 void AnimationController::OnSetEnabled()
 void AnimationController::OnSetEnabled()
@@ -894,25 +891,25 @@ void AnimationController::ClearAnimationResources()
     animationsResources_.Clear();
     animationsResources_.Clear();
 }
 }
 
 
-void AnimationController::SetAnimationResourcesAttr(const ResourceRefList& value)
+void AnimationController::ApplyAttributes()
 {
 {
-    animationsResources_.Clear();
 
 
-    ResourceCache* cache = GetSubsystem<ResourceCache>();
-    for (unsigned i = 0; i < value.names_.Size(); ++i)
-    {
-        AddAnimationResource(cache->GetResource<Animation>(value.names_[i]));
-    }
-}
+    // This currently requires that the AnimationController is after the AnimatedModel
+    // component on the node, look into removing the requirement
 
 
-const ResourceRefList& AnimationController::GetAnimationResourcesAttr() const
-{
-    animationsResourcesAttr_.names_.Resize(animationsResources_.Size());
-    for (unsigned i = 0; i < animationsResources_.Size(); ++i)
-        animationsResourcesAttr_.names_[i] = GetResourceName(animationsResources_[i]);
+    AnimatedModel* animatedModel = GetComponent<AnimatedModel>();
 
 
-    return animationsResourcesAttr_;
-}
+    if (!animatedModel)
+        return;
+
+    Model* model = animatedModel->GetModel();
+
+    if (!model)
+        return;
+
+    animationsResources_ = model->GetAnimationResources();
 
 
 
 
 }
 }
+
+}

+ 5 - 6
Source/Atomic/Atomic3D/AnimationController.h

@@ -178,12 +178,15 @@ public:
     void AddAnimationResource(Animation* animation);
     void AddAnimationResource(Animation* animation);
     void RemoveAnimationResource(Animation* animation);
     void RemoveAnimationResource(Animation* animation);
     void ClearAnimationResources();
     void ClearAnimationResources();
-    void SetAnimationResourcesAttr(const ResourceRefList& value);
-    const ResourceRefList& GetAnimationResourcesAttr() const;
+
 protected:
 protected:
     /// Handle scene being assigned.
     /// Handle scene being assigned.
     virtual void OnSceneSet(Scene* scene);
     virtual void OnSceneSet(Scene* scene);
 
 
+    // ATOMIC BEGIN
+    void ApplyAttributes();
+    // ATOMIC END
+
 private:
 private:
     /// Add an animation state either to AnimatedModel or as a node animation.
     /// Add an animation state either to AnimatedModel or as a node animation.
     AnimationState* AddAnimationState(Animation* animation);
     AnimationState* AddAnimationState(Animation* animation);
@@ -203,10 +206,6 @@ private:
 
 
     /// animation resources
     /// animation resources
     Vector<SharedPtr<Animation> > animationsResources_;
     Vector<SharedPtr<Animation> > animationsResources_;
-
-    /// Material list attribute.
-    mutable ResourceRefList animationsResourcesAttr_;
-    ;
 };
 };
 
 
 }
 }

+ 74 - 2
Source/Atomic/Atomic3D/Model.cpp

@@ -33,6 +33,9 @@
 
 
 #include "../DebugNew.h"
 #include "../DebugNew.h"
 
 
+#include "Animation.h"
+#include "../Resource/ResourceCache.h"
+
 namespace Atomic
 namespace Atomic
 {
 {
 
 
@@ -73,7 +76,13 @@ void Model::RegisterObject(Context* context)
 bool Model::BeginLoad(Deserializer& source)
 bool Model::BeginLoad(Deserializer& source)
 {
 {
     // Check ID
     // Check ID
-    if (source.ReadFileID() != "UMDL")
+
+    String id = source.ReadFileID();
+    bool umdl = false;
+    if (id == "UMDL") // we only support UMDL for some current legacy mdl's (ToonTown)
+        umdl = true;
+
+    if (!umdl && id != "AMDL")
     {
     {
         LOGERROR(source.GetName() + " is not a valid model file");
         LOGERROR(source.GetName() + " is not a valid model file");
         return false;
         return false;
@@ -284,6 +293,25 @@ bool Model::BeginLoad(Deserializer& source)
         geometryCenters_.Push(Vector3::ZERO);
         geometryCenters_.Push(Vector3::ZERO);
     memoryUse += sizeof(Vector3) * geometries_.Size();
     memoryUse += sizeof(Vector3) * geometries_.Size();
 
 
+    if (umdl)
+    {
+        SetMemoryUse(memoryUse);
+        return true;
+    }
+
+    // MODEL_VERSION
+    unsigned version = source.ReadUInt();
+
+    ResourceRefList animList = source.ReadResourceRefList();
+
+    animationsResources_.Clear();
+
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+    for (unsigned i = 0; i < animList.names_.Size(); ++i)
+    {
+        AddAnimationResource(cache->GetResource<Animation>(animList.names_[i]));
+    }
+
     SetMemoryUse(memoryUse);
     SetMemoryUse(memoryUse);
     return true;
     return true;
 }
 }
@@ -338,7 +366,7 @@ bool Model::EndLoad()
 bool Model::Save(Serializer& dest) const
 bool Model::Save(Serializer& dest) const
 {
 {
     // Write ID
     // Write ID
-    if (!dest.WriteFileID("UMDL"))
+    if (!dest.WriteFileID("AMDL")) // atomic model specifier
         return false;
         return false;
 
 
     // Write vertex buffers
     // Write vertex buffers
@@ -423,6 +451,21 @@ bool Model::Save(Serializer& dest) const
     for (unsigned i = 0; i < geometryCenters_.Size(); ++i)
     for (unsigned i = 0; i < geometryCenters_.Size(); ++i)
         dest.WriteVector3(geometryCenters_[i]);
         dest.WriteVector3(geometryCenters_[i]);
 
 
+    // ATOMIC BEGIN
+
+    dest.WriteUInt(MODEL_VERSION);
+
+    // animation resources
+
+    ResourceRefList animList(Animation::GetTypeStatic());
+    animList.names_.Resize(animationsResources_.Size());
+    for (unsigned i = 0; i < animationsResources_.Size(); ++i)
+        animList.names_[i] = GetResourceName(animationsResources_[i]);
+    dest.WriteResourceRefList(animList);
+
+    // ATOMIC END
+
+
     return true;
     return true;
 }
 }
 
 
@@ -724,4 +767,33 @@ unsigned Model::GetMorphRangeCount(unsigned bufferIndex) const
     return bufferIndex < vertexBuffers_.Size() ? morphRangeCounts_[bufferIndex] : 0;
     return bufferIndex < vertexBuffers_.Size() ? morphRangeCounts_[bufferIndex] : 0;
 }
 }
 
 
+// ATOMIC BEGIN
+
+void Model::AddAnimationResource(Animation* animation)
+{
+    if (!animation)
+        return;
+
+    SharedPtr<Animation> anim(animation);
+
+    if (!animationsResources_.Contains(anim))
+        animationsResources_.Push(anim);
+}
+
+void Model::RemoveAnimationResource(Animation* animation)
+{
+    if (!animation)
+        return;
+
+    animationsResources_.Remove(SharedPtr<Animation>(animation));
+
+}
+
+void Model::ClearAnimationResources()
+{
+    animationsResources_.Clear();
+}
+
+// ATOMIC END
+
 }
 }

+ 25 - 0
Source/Atomic/Atomic3D/Model.h

@@ -29,6 +29,8 @@
 #include "../Math/BoundingBox.h"
 #include "../Math/BoundingBox.h"
 #include "../Resource/Resource.h"
 #include "../Resource/Resource.h"
 
 
+#include "Animation.h"
+
 namespace Atomic
 namespace Atomic
 {
 {
 
 
@@ -104,6 +106,12 @@ struct GeometryDesc
     unsigned indexCount_;
     unsigned indexCount_;
 };
 };
 
 
+// ATOMIC BEGIN
+
+static const unsigned MODEL_VERSION = 1;
+
+// ATOMIC END
+
 /// 3D model resource.
 /// 3D model resource.
 class ATOMIC_API Model : public Resource
 class ATOMIC_API Model : public Resource
 {
 {
@@ -201,6 +209,16 @@ public:
     /// Return vertex buffer morph range vertex count.
     /// Return vertex buffer morph range vertex count.
     unsigned GetMorphRangeCount(unsigned bufferIndex) const;
     unsigned GetMorphRangeCount(unsigned bufferIndex) const;
 
 
+    // ATOMIC BEGIN
+
+    void AddAnimationResource(Animation* animation);
+    void RemoveAnimationResource(Animation* animation);
+    void ClearAnimationResources();
+    unsigned GetAnimationCount() const { return animationsResources_.Size(); }
+    const Vector<SharedPtr<Animation>>& GetAnimationResources() { return animationsResources_; }
+
+    // ATOMIC END
+
 private:
 private:
     /// Bounding box.
     /// Bounding box.
     BoundingBox boundingBox_;
     BoundingBox boundingBox_;
@@ -228,6 +246,13 @@ private:
     Vector<IndexBufferDesc> loadIBData_;
     Vector<IndexBufferDesc> loadIBData_;
     /// Geometry definitions for asynchronous loading.
     /// Geometry definitions for asynchronous loading.
     Vector<PODVector<GeometryDesc> > loadGeometries_;
     Vector<PODVector<GeometryDesc> > loadGeometries_;
+
+    // ATOMIC BEGIN
+
+    /// animation resources
+    Vector<SharedPtr<Animation> > animationsResources_;
+
+    // ATOMIC END
 };
 };
 
 
 }
 }

+ 1 - 1
Source/ToolCore/Assets/Asset.cpp

@@ -245,7 +245,7 @@ bool Asset::CreateImporter()
         textureFormats.Push(".dds");
         textureFormats.Push(".dds");
 
 
         // todo, externalize recognizers
         // todo, externalize recognizers
-        if (ext == ".fbx" || ext == ".blend" || ext == ".dae")
+        if (ext == ".fbx" || ext == ".blend" || ext == ".dae" || ext == ".mdl")
         {
         {
             importer_ = new ModelImporter(context_, this);
             importer_ = new ModelImporter(context_, this);
         }
         }

+ 75 - 13
Source/ToolCore/Assets/ModelImporter.cpp

@@ -5,8 +5,9 @@
 #include <Atomic/IO/FileSystem.h>
 #include <Atomic/IO/FileSystem.h>
 #include <Atomic/Scene/Node.h>
 #include <Atomic/Scene/Node.h>
 
 
-#include <Atomic/Atomic3D/AnimationController.h>
+#include <Atomic/Atomic3D/AnimatedModel.h>
 #include <Atomic/Atomic3D/Animation.h>
 #include <Atomic/Atomic3D/Animation.h>
+#include <Atomic/Atomic3D/StaticModel.h>
 #include <Atomic/Atomic3D/Model.h>
 #include <Atomic/Atomic3D/Model.h>
 
 
 #include <Atomic/Resource/ResourceCache.h>
 #include <Atomic/Resource/ResourceCache.h>
@@ -43,9 +44,12 @@ void ModelImporter::SetDefaults()
 
 
 bool ModelImporter::ImportModel()
 bool ModelImporter::ImportModel()
 {
 {
+
+    LOGDEBUGF("Importing Model: %s", asset_->GetPath().CString());
+
     SharedPtr<OpenAssetImporter> importer(new OpenAssetImporter(context_));
     SharedPtr<OpenAssetImporter> importer(new OpenAssetImporter(context_));
 
 
-    //importer->SetVerboseLog(true);
+    importer->SetVerboseLog(true);
 
 
     importer->SetScale(scale_);
     importer->SetScale(scale_);
     importer->SetExportAnimations(false);
     importer->SetExportAnimations(false);
@@ -92,13 +96,19 @@ bool ModelImporter::ImportAnimation(const String& filename, const String& name,
 
 
             ResourceCache* cache = GetSubsystem<ResourceCache>();
             ResourceCache* cache = GetSubsystem<ResourceCache>();
 
 
-            AnimationController* controller = importNode_->GetComponent<AnimationController>();
+            AnimatedModel* animatedModel = importNode_->GetComponent<AnimatedModel>();
 
 
-            if (controller)
+            if (animatedModel)
             {
             {
-                SharedPtr<Animation> animation = cache->GetTempResource<Animation>(fileName + extension);
-                if (animation)
-                    controller->AddAnimationResource(animation);
+                Model* model = animatedModel->GetModel();
+
+                if (model)
+                {
+                    SharedPtr<Animation> animation = cache->GetTempResource<Animation>(fileName + extension);
+                    if (animation)
+                        model->AddAnimationResource(animation);
+                }
+
             }
             }
 
 
             LOGINFOF("Import Info: %s : %s", info.name_.CString(), fileName.CString());
             LOGINFOF("Import Info: %s : %s", info.name_.CString(), fileName.CString());
@@ -183,22 +193,74 @@ bool ModelImporter::ImportAnimations()
 
 
 bool ModelImporter::Import()
 bool ModelImporter::Import()
 {
 {
+
+    String ext = asset_->GetExtension();
     String modelAssetFilename = asset_->GetPath();
     String modelAssetFilename = asset_->GetPath();
 
 
     importNode_ = new Node(context_);
     importNode_ = new Node(context_);
 
 
-    // skip external animations, they will be brought in when importing their
-    // corresponding model
-    if (!modelAssetFilename.Contains("@"))
+    if (ext == ".mdl")
     {
     {
-        ImportModel();
+        FileSystem* fs = GetSubsystem<FileSystem>();
+        ResourceCache* cache = GetSubsystem<ResourceCache>();
+
+        // mdl files are native file format that doesn't need to be converted
+        // doesn't allow scale, animations legacy primarily for ToonTown
 
 
-        if (importAnimations_)
+        if (!fs->Copy(asset_->GetPath(), asset_->GetCachePath() + ".mdl"))
         {
         {
-            ImportAnimations();
+            importNode_= 0;
+            return false;
         }
         }
 
 
+        Model* mdl = cache->GetResource<Model>( asset_->GetCachePath() + ".mdl");
+
+        if (!mdl)
+        {
+            importNode_= 0;
+            return false;
+        }
+
+        // Force a reload, though file watchers will catch this delayed and load again
+        cache->ReloadResource(mdl);
+
+        importNode_->CreateComponent<StaticModel>()->SetModel(mdl);
     }
     }
+    else
+    {
+        // skip external animations, they will be brought in when importing their
+        // corresponding model
+
+        if (!modelAssetFilename.Contains("@"))
+        {
+            ImportModel();
+
+            if (importAnimations_)
+            {
+                ImportAnimations();
+            }
+
+            AnimatedModel* animatedModel = importNode_->GetComponent<AnimatedModel>();
+            if (animatedModel)
+            {
+                Model* model = animatedModel->GetModel();
+                if (model && model->GetAnimationCount())
+                {
+                    // resave with animation info
+
+                    File mdlFile(context_);
+                    if (!mdlFile.Open(asset_->GetCachePath() + ".mdl", FILE_WRITE))
+                    {
+                        ErrorExit("Could not open output file " + asset_->GetCachePath() + ".mdl");
+                        return false;
+                    }
+
+                    model->Save(mdlFile);
+                }
+            }
+        }
+    }
+
 
 
     File outFile(context_);
     File outFile(context_);
 
 

+ 2 - 3
Source/ToolCore/Import/OpenAssetImporter.cpp

@@ -81,7 +81,7 @@ OpenAssetImporter::OpenAssetImporter(Context* context) : Object(context) ,
         aiProcess_Triangulate |
         aiProcess_Triangulate |
         aiProcess_GenSmoothNormals |
         aiProcess_GenSmoothNormals |
         aiProcess_LimitBoneWeights |
         aiProcess_LimitBoneWeights |
-        aiProcess_ImproveCacheLocality |        
+        aiProcess_ImproveCacheLocality |
         aiProcess_FixInfacingNormals |
         aiProcess_FixInfacingNormals |
         aiProcess_FindInvalidData |
         aiProcess_FindInvalidData |
         aiProcess_GenUVCoords |
         aiProcess_GenUVCoords |
@@ -248,7 +248,7 @@ bool OpenAssetImporter::ExportModel(const String& outName, const String &animNam
         return false;
         return false;
     }
     }
 
 
-    ResourceCache* cache = GetSubsystem<ResourceCache>();    
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
     Model* mdl = cache->GetResource<Model>( model.outName_);
     Model* mdl = cache->GetResource<Model>( model.outName_);
 
 
     // Force a reload, though file watchers will catch this delayed and load again
     // Force a reload, though file watchers will catch this delayed and load again
@@ -1320,4 +1320,3 @@ void OpenAssetImporter::DumpNodes(aiNode* rootNode, unsigned level)
 }
 }
 
 
 }
 }
-