Browse Source

Fixed potential infinite loop when setting morphs.
Added script API function to query morph names.
Unified AssetImporter & OgreImporter command line options regarding animations.

Lasse Öörni 13 years ago
parent
commit
38fd976aa9

+ 8 - 8
Docs/Reference.dox

@@ -1318,8 +1318,8 @@ Usage:
 AssetImporter <command> <input file> <output file> [options]
 AssetImporter <command> <input file> <output file> [options]
 
 
 Commands:
 Commands:
-model Export a model
-scene Export a scene
+model Output a model
+scene Output a scene
 dump  Dump scene node structure. No output file is generated
 dump  Dump scene node structure. No output file is generated
 lod   Combine several Urho3D models as LOD levels of the output model
 lod   Combine several Urho3D models as LOD levels of the output model
       Syntax: lod <dist0> <mdl0> <dist1 <mdl1> ... <output file>
       Syntax: lod <dist0> <mdl0> <dist1 <mdl1> ... <output file>
@@ -1328,8 +1328,8 @@ Options:
 -b    Save scene in binary format, default format is XML
 -b    Save scene in binary format, default format is XML
 -i    Use local ID's for scene nodes
 -i    Use local ID's for scene nodes
 -mX   Output a material list file X (model mode only)
 -mX   Output a material list file X (model mode only)
--na   Do not export animations
--nm   Do not export materials
+-na   Do not output animations
+-nm   Do not output materials
 -ns   Do not create subdirectories for resources
 -ns   Do not create subdirectories for resources
 -nz   Do not create a zone and a directional light (scene mode only)
 -nz   Do not create a zone and a directional light (scene mode only)
 -pX   Set path X for scene resources. Default is output file path
 -pX   Set path X for scene resources. Default is output file path
@@ -1347,14 +1347,14 @@ Usage:
 OgreImporter <input file> <output file> [options]
 OgreImporter <input file> <output file> [options]
 
 
 Options:
 Options:
--a   Export animations
--m   Export morphs
--r   Export only rotations from animations
+-na  Do not output animations
+-nm  Do not output morphs
+-r   Output only rotations from animations
 -s   Split each submesh into own vertex buffer
 -s   Split each submesh into own vertex buffer
 -t   Generate tangents
 -t   Generate tangents
 \endverbatim
 \endverbatim
 
 
-Note: exporting only bone rotations may help when using an animation in a different model, but if bone position changes have been used for effect, the animation may become less lively. Unpredictable mutilations might result from using an animation in a model not originally intended for, as Urho3D does not specifically attempt to retarget animations.
+Note: outputting only bone rotations may help when using an animation in a different model, but if bone position changes have been used for effect, the animation may become less lively. Unpredictable mutilations might result from using an animation in a model not originally intended for, as Urho3D does not specifically attempt to retarget animations.
 
 
 \section Tools_PackageTool PackageTool
 \section Tools_PackageTool PackageTool
 
 

+ 1 - 0
Docs/ScriptAPI.dox

@@ -2115,6 +2115,7 @@ Properties:<br>
 - uint numAnimationStates (readonly)
 - uint numAnimationStates (readonly)
 - AnimationState@[] animationStates (readonly)
 - AnimationState@[] animationStates (readonly)
 - uint numMorphs (readonly)
 - uint numMorphs (readonly)
+- String[] morphNames (readonly)
 - float[] morphWeights
 - float[] morphWeights
 - Zone@ zone (readonly)
 - Zone@ zone (readonly)
 
 

+ 7 - 0
Engine/Engine/GraphicsAPI.cpp

@@ -613,6 +613,12 @@ static void AnimatedModelSetModel(Model* model, AnimatedModel* ptr)
     ptr->SetModel(model);
     ptr->SetModel(model);
 }
 }
 
 
+static const String& AnimatedModelGetMorphName(unsigned index, AnimatedModel* ptr)
+{
+    const Vector<ModelMorph>& morphs = ptr->GetMorphs();
+    return index < morphs.Size() ? morphs[index].name_ : String::EMPTY;
+}
+
 static void RegisterAnimatedModel(asIScriptEngine* engine)
 static void RegisterAnimatedModel(asIScriptEngine* engine)
 {
 {
     RegisterRefCounted<AnimationState>(engine, "AnimationState");
     RegisterRefCounted<AnimationState>(engine, "AnimationState");
@@ -660,6 +666,7 @@ static void RegisterAnimatedModel(asIScriptEngine* engine)
     engine->RegisterObjectMethod("AnimatedModel", "uint get_numAnimationStates() const", asMETHOD(AnimatedModel, GetNumAnimationStates), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "uint get_numAnimationStates() const", asMETHOD(AnimatedModel, GetNumAnimationStates), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "AnimationState@+ get_animationStates(const String&in) const", asMETHODPR(AnimatedModel, GetAnimationState, (const String&) const, AnimationState*), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "AnimationState@+ get_animationStates(const String&in) const", asMETHODPR(AnimatedModel, GetAnimationState, (const String&) const, AnimationState*), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "uint get_numMorphs() const", asMETHOD(AnimatedModel, GetNumMorphs), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "uint get_numMorphs() const", asMETHOD(AnimatedModel, GetNumMorphs), asCALL_THISCALL);
+    engine->RegisterObjectMethod("AnimatedModel", "const String& get_morphNames(uint) const", asFUNCTION(AnimatedModelGetMorphName), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("AnimatedModel", "void set_morphWeights(const String&in, float)", asMETHODPR(AnimatedModel, SetMorphWeight, (const String&, float), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "void set_morphWeights(const String&in, float)", asMETHODPR(AnimatedModel, SetMorphWeight, (const String&, float), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "float get_morphWeights(const String&in) const", asMETHODPR(AnimatedModel, GetMorphWeight, (const String&) const, float), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "float get_morphWeights(const String&in) const", asMETHODPR(AnimatedModel, GetMorphWeight, (const String&) const, float), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "Zone@+ get_zone() const", asMETHOD(AnimatedModel, GetZone), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "Zone@+ get_zone() const", asMETHOD(AnimatedModel, GetZone), asCALL_THISCALL);

+ 8 - 2
Engine/Graphics/AnimatedModel.cpp

@@ -490,7 +490,10 @@ void AnimatedModel::SetMorphWeight(unsigned index, float weight)
             
             
             // Indexing might not be the same, so use the name hash instead
             // Indexing might not be the same, so use the name hash instead
             for (unsigned i = 1; i < models.Size(); ++i)
             for (unsigned i = 1; i < models.Size(); ++i)
-                models[i]->SetMorphWeight(morphs_[index].nameHash_, weight);
+            {
+                if (!models[i]->isMaster_)
+                    models[i]->SetMorphWeight(morphs_[index].nameHash_, weight);
+            }
         }
         }
         
         
         MarkMorphsDirty();
         MarkMorphsDirty();
@@ -535,7 +538,10 @@ void AnimatedModel::ResetMorphWeights()
         
         
         // Indexing might not be the same, so use the name hash instead
         // Indexing might not be the same, so use the name hash instead
         for (unsigned i = 1; i < models.Size(); ++i)
         for (unsigned i = 1; i < models.Size(); ++i)
-            models[i]->ResetMorphWeights();
+        {
+            if (!models[i]->isMaster_)
+                models[i]->ResetMorphWeights();
+        }
     }
     }
     
     
     MarkMorphsDirty();
     MarkMorphsDirty();

+ 4 - 4
Tools/AssetImporter/AssetImporter.cpp

@@ -177,8 +177,8 @@ void Run(const Vector<String>& arguments)
             "Usage: AssetImporter <command> <input file> <output file> [options]\n"
             "Usage: AssetImporter <command> <input file> <output file> [options]\n"
             "See http://assimp.sourceforge.net/main_features_formats.html for input formats\n\n"
             "See http://assimp.sourceforge.net/main_features_formats.html for input formats\n\n"
             "Commands:\n"
             "Commands:\n"
-            "model Export a model\n"
-            "scene Export a scene\n"
+            "model Output a model\n"
+            "scene Output a scene\n"
             "dump  Dump scene node structure. No output file is generated\n"
             "dump  Dump scene node structure. No output file is generated\n"
             "lod   Combine several Urho3D models as LOD levels of the output model\n"
             "lod   Combine several Urho3D models as LOD levels of the output model\n"
             "      Syntax: lod <dist0> <mdl0> <dist1 <mdl1> ... <output file>\n"
             "      Syntax: lod <dist0> <mdl0> <dist1 <mdl1> ... <output file>\n"
@@ -187,8 +187,8 @@ void Run(const Vector<String>& arguments)
             "-b    Save scene in binary format, default format is XML\n"
             "-b    Save scene in binary format, default format is XML\n"
             "-i    Use local ID's for scene nodes\n"
             "-i    Use local ID's for scene nodes\n"
             "-mX   Output a material list file X (model mode only)\n"
             "-mX   Output a material list file X (model mode only)\n"
-            "-na   Do not export animations\n"
-            "-nm   Do not export materials\n"
+            "-na   Do not output animations\n"
+            "-nm   Do not output materials\n"
             "-ns   Do not create subdirectories for resources\n"
             "-ns   Do not create subdirectories for resources\n"
             "-nz   Do not create a zone and a directional light (scene mode only)\n"
             "-nz   Do not create a zone and a directional light (scene mode only)\n"
             "-pX   Set path X for scene resources. Default is output file path\n"
             "-pX   Set path X for scene resources. Default is output file path\n"

+ 21 - 17
Tools/OgreImporter/OgreImporter.cpp

@@ -56,7 +56,7 @@ bool useOneBuffer_ = true;
 int main(int argc, char** argv);
 int main(int argc, char** argv);
 void Run(const Vector<String>& arguments);
 void Run(const Vector<String>& arguments);
 void LoadSkeleton(const String& skeletonFileName);
 void LoadSkeleton(const String& skeletonFileName);
-void LoadMesh(const String& inputFileName, bool generateTangents, bool splitSubMeshes, bool GetMorphs);
+void LoadMesh(const String& inputFileName, bool generateTangents, bool splitSubMeshes, bool exportMorphs);
 void WriteOutput(const String& outputFileName, bool exportAnimations, bool rotationsOnly);
 void WriteOutput(const String& outputFileName, bool exportAnimations, bool rotationsOnly);
 void OptimizeIndices(ModelSubGeometryLodLevel* subGeom, ModelVertexBuffer* vb, ModelIndexBuffer* ib);
 void OptimizeIndices(ModelSubGeometryLodLevel* subGeom, ModelVertexBuffer* vb, ModelIndexBuffer* ib);
 void CalculateScore(ModelVertex& vertex);
 void CalculateScore(ModelVertex& vertex);
@@ -82,18 +82,18 @@ void Run(const Vector<String>& arguments)
         ErrorExit(
         ErrorExit(
             "Usage: OgreImporter <input file> <output file> [options]\n\n"
             "Usage: OgreImporter <input file> <output file> [options]\n\n"
             "Options:\n"
             "Options:\n"
-            "-a   Export animations\n"
-            "-m   Export morphs\n"
-            "-r   Export only rotations from animations\n"
+            "-na  Do not output animations\n"
+            "-nm  Do not output morphs\n"
+            "-r   Output only rotations from animations\n"
             "-s   Split each submesh into own vertex buffer\n"
             "-s   Split each submesh into own vertex buffer\n"
             "-t   Generate tangents\n"
             "-t   Generate tangents\n"
         );
         );
     }
     }
     
     
     bool generateTangents = false;
     bool generateTangents = false;
-    bool GetMorphs = false;
     bool splitSubMeshes = false;
     bool splitSubMeshes = false;
-    bool exportAnimations = false;
+    bool exportAnimations = true;
+    bool exportMorphs = true;
     bool rotationsOnly = false;
     bool rotationsOnly = false;
     
     
     if (arguments.Size() > 2)
     if (arguments.Size() > 2)
@@ -109,18 +109,20 @@ void Run(const Vector<String>& arguments)
                     generateTangents = true;
                     generateTangents = true;
                     break;
                     break;
                     
                     
-                case 'a':
-                    exportAnimations = true;
+                case 'n':
+                    if (arg.Length() > 1)
+                    {
+                        if (arg[1] == 'a')
+                            exportAnimations = false;
+                        if (arg[1] == 'm')
+                            exportMorphs = false;
+                    }
                     break;
                     break;
                     
                     
                 case 'r':
                 case 'r':
                     rotationsOnly = true;
                     rotationsOnly = true;
                     break;
                     break;
                     
                     
-                case 'm':
-                    GetMorphs = true;
-                    break;
-                    
                 case 's':
                 case 's':
                     splitSubMeshes = true;
                     splitSubMeshes = true;
                     break;
                     break;
@@ -129,7 +131,7 @@ void Run(const Vector<String>& arguments)
         }
         }
     }
     }
     
     
-    LoadMesh(arguments[0], generateTangents, splitSubMeshes, GetMorphs);
+    LoadMesh(arguments[0], generateTangents, splitSubMeshes, exportMorphs);
     WriteOutput(arguments[1], exportAnimations, rotationsOnly);
     WriteOutput(arguments[1], exportAnimations, rotationsOnly);
     
     
     PrintLine("Finished");
     PrintLine("Finished");
@@ -234,7 +236,7 @@ void LoadSkeleton(const String& skeletonFileName)
     }
     }
 }
 }
 
 
-void LoadMesh(const String& inputFileName, bool generateTangents, bool splitSubMeshes, bool GetMorphs)
+void LoadMesh(const String& inputFileName, bool generateTangents, bool splitSubMeshes, bool exportMorphs)
 {
 {
     File meshFileSource(context_);
     File meshFileSource(context_);
     meshFileSource.Open(inputFileName);
     meshFileSource.Open(inputFileName);
@@ -244,6 +246,8 @@ void LoadMesh(const String& inputFileName, bool generateTangents, bool splitSubM
     XMLElement root = meshFile_->GetRoot();
     XMLElement root = meshFile_->GetRoot();
     XMLElement subMeshes = root.GetChild("submeshes");
     XMLElement subMeshes = root.GetChild("submeshes");
     XMLElement skeletonLink = root.GetChild("skeletonlink");
     XMLElement skeletonLink = root.GetChild("skeletonlink");
+    if (root.IsNull())
+        ErrorExit("Could not load input file " + inputFileName);
     
     
     String skeletonName = skeletonLink.GetAttribute("name");
     String skeletonName = skeletonLink.GetAttribute("name");
     if (!skeletonName.Empty())
     if (!skeletonName.Empty())
@@ -470,7 +474,7 @@ void LoadMesh(const String& inputFileName, bool generateTangents, bool splitSubM
                 vBuf->elementMask_ |= MASK_BLENDWEIGHTS | MASK_BLENDINDICES;
                 vBuf->elementMask_ |= MASK_BLENDWEIGHTS | MASK_BLENDINDICES;
                 bool sorted = false;
                 bool sorted = false;
                 
                 
-                // If amount of bones_ is larger than supported by HW skinning, must remap per submesh
+                // If amount of bones is larger than supported by HW skinning, must remap per submesh
                 if (bones_.Size() > MAX_SKIN_MATRICES)
                 if (bones_.Size() > MAX_SKIN_MATRICES)
                 {
                 {
                     Map<unsigned, unsigned> usedBoneMap;
                     Map<unsigned, unsigned> usedBoneMap;
@@ -494,7 +498,7 @@ void LoadMesh(const String& inputFileName, bool generateTangents, bool splitSubM
                         }
                         }
                     }
                     }
                     
                     
-                    // If still too many bones_ in one subgeometry, error
+                    // If still too many bones in one subgeometry, error
                     if (usedBoneMap.Size() > MAX_SKIN_MATRICES)
                     if (usedBoneMap.Size() > MAX_SKIN_MATRICES)
                         ErrorExit("Too many bones in submesh " + String(subMeshIndex + 1));
                         ErrorExit("Too many bones in submesh " + String(subMeshIndex + 1));
                     
                     
@@ -646,7 +650,7 @@ void LoadMesh(const String& inputFileName, bool generateTangents, bool splitSubM
     
     
     // Process poses/morphs
     // Process poses/morphs
     // First find out all pose definitions
     // First find out all pose definitions
-    if (GetMorphs)
+    if (exportMorphs)
     {
     {
         try
         try
         {
         {