Просмотр исходного кода

Update FF7NameLookup to use XML to make it more data driven/avoid recompiles. Edited FF7 PC model exporter so it actually runs. Hacked in some of its code to the data installer to convert field models, currently crashes when loading the mesh as the ogre technique index is out of bounds

Paul 11 лет назад
Родитель
Сommit
f15ab2f156

+ 1 - 1
QGearsMain/src/data/QGearsLGPArchive.cpp

@@ -66,7 +66,7 @@ namespace QGears
             file_info.uncompressedSize = it->data_size;
             file_info.compressedSize = file_info.uncompressedSize;
 
-            LOG_DEBUG( "add file:" + file_info.filename );
+            //LOG_DEBUG( "add file:" + file_info.filename );
             m_file_infos.push_back( file_info );
             ++it;
         }

+ 94 - 43
SupportedGames/FinalFantasy7/include/common/FF7NameLookup.h

@@ -18,72 +18,123 @@ GNU General Public License for more details.
 #define __FF7NameLookup_H__
 
 #include "common/TypeDefine.h"
+#include "common/QGearsStringUtil.h"
+#include "core/XmlFile.h"
 
 namespace QGears
 {
     namespace FF7
     {
-        class NameLookup
+        class FF7FiledModelsAndAnimationMetadata : public XmlFile
         {
         public:
-            NameLookup() = default;
-            virtual ~NameLookup() = default;
-
-            static const String& animation(const String &key)
+            FF7FiledModelsAndAnimationMetadata(Ogre::String file)
+                : XmlFile(file)
             {
-                return lookup(key, ms_animations);
+                TiXmlNode* node = m_File.RootElement();
+
+                if (node == nullptr || node->ValueStr() != "metadata")
+                {
+                    throw std::runtime_error("FF7FiledModelsAndAnimationMetadata: " + m_File.ValueStr() + " is not a valid metadata file! No <metadata> in root.");
+                }
+
+                node = node->FirstChild();
+                while (node)
+                {
+                    if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "models")
+                    {
+                        ReadModels(node->FirstChild());
+                    }
+                    else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "animations")
+                    {
+                        ReadAnimations(node->FirstChild());
+                    }
+                    node = node->NextSibling();
+                }
             }
 
-            static const String& model(const String &key)
+            const String& Animation(const String &key) const
             {
-                return lookup(key, ms_models);
+                auto it = mAnimations.find(key);
+                if (it != std::end(mAnimations))
+                {
+                    return it->second;
+                }
+
+                String base_name;
+                StringUtil::splitBase(key, base_name);
+                it = mAnimations.find(base_name);
+                if (it != std::end(mAnimations))
+                {
+                    return it->second;
+                }
+
+                return key;
             }
 
-        protected:
-            typedef std::map<const String, const String>    LookupMap;
-
-            static LookupMap createAnimations()
+            const String& Model(const String &key) const
             {
-                LookupMap lookup;
-                lookup.insert(LookupMap::value_type("acfe", "Idle"));
-                lookup.insert(LookupMap::value_type("aaff", "Walk"));
-                lookup.insert(LookupMap::value_type("aaga", "Run"));
-                lookup.insert(LookupMap::value_type("bvjf", "JumpFromTrain"));
-
-                // barret
-                lookup.insert(LookupMap::value_type("adcb", "Idle"));
-                lookup.insert(LookupMap::value_type("adcc", "Walk"));
-                lookup.insert(LookupMap::value_type("adcd", "Run"));
-                lookup.insert(LookupMap::value_type("bwaa", "Invitation"));
-
-                // sd_red
-                lookup.insert(LookupMap::value_type("aeae", "Idle"));
-                lookup.insert(LookupMap::value_type("aeaf", "Walk"));
-                lookup.insert(LookupMap::value_type("aeba", "Run"));
-
-                return lookup;
+                auto it = mModels.find(key);
+                if (it != std::end(mModels))
+                {
+                    return it->second;
+                }
+
+                String base_name;
+                StringUtil::splitBase(key, base_name);
+                it = mModels.find(base_name);
+                if (it != std::end(mModels))
+                {
+                    return it->second;
+                }
+
+                return key;
             }
 
-            static LookupMap createModels()
+        private:
+            void ReadModels(TiXmlNode* node)
             {
-                LookupMap lookup;
-                lookup.insert(LookupMap::value_type("aaaa", "n_cloud"));
-                lookup.insert(LookupMap::value_type("adda", "sd_red"));
-
-                return lookup;
+                while (node)
+                {
+                    const auto src = GetString(node, "name");
+                    const auto dst = GetString(node, "target");
+                    mModels[src] = dst;
+                    node = node->NextSibling();
+                }
             }
 
-            static const String& lookup(const String &key, const LookupMap &data)
+            void ReadAnimations(TiXmlNode* node)
             {
-                LookupMap::const_iterator found(data.find(key));
-                if (found == data.end()) return key;
+                while (node)
+                {
+                    const auto src = GetString(node, "name");
+                    const auto dst = GetString(node, "target");
+                    mAnimations[src] = dst;
+                    node = node->NextSibling();
+                }
+            }
+
+            typedef std::map<String, String> LookupMap;
+            LookupMap mModels;
+            LookupMap mAnimations;
+        };
 
-                return found->second;
+        class NameLookup
+        {
+        public:
+            NameLookup() = delete;
+
+            static const String& animation(const String &key)
+            {
+                static FF7FiledModelsAndAnimationMetadata data("field_models_and_animation_metadata.xml");
+                return data.Animation(key);
             }
 
-        private:
-            static LookupMap  ms_animations;
-            static LookupMap  ms_models;
+            static const String& model(const String &key)
+            {
+                static FF7FiledModelsAndAnimationMetadata data("field_models_and_animation_metadata.xml");
+                return data.Model(key);
+            }
         };
     }
 }

+ 0 - 3
SupportedGames/FinalFantasy7/src/common/FF7NameLookup.cpp

@@ -15,6 +15,3 @@ GNU General Public License for more details.
 -----------------------------------------------------------------------------
 */
 #include "common/FF7NameLookup.h"
-
-QGears::FF7::NameLookup::LookupMap QGears::FF7::NameLookup::ms_animations(NameLookup::createAnimations());
-QGears::FF7::NameLookup::LookupMap QGears::FF7::NameLookup::ms_models(NameLookup::createModels());

+ 23 - 0
output/field_models_and_animation_metadata.xml

@@ -0,0 +1,23 @@
+<metadata>
+	<models>
+		<model name="aaaa" target="n_cloud"></model>
+		<model name="adda" target="sd_red"></model>
+	</models>
+    
+	<animations>
+		<animation name="acfe" target="Idle"></animation>
+		<animation name="aaff" target="Walk"></animation>
+		<animation name="aaga" target="Run"></animation>
+		<animation name="bvjf" target="JumpFromTrain"></animation>
+		
+		<animation name="adcb" target="Idle"></animation>
+		<animation name="adcc" target="Walk"></animation>
+		<animation name="adcd" target="Run"></animation>
+		<animation name="bwaa" target="Invitation"></animation>
+		
+		<animation name="aeae" target="Idle"></animation>
+		<animation name="aeaf" target="Walk"></animation>
+		<animation name="aeba" target="Run"></animation>
+	</animations>
+	
+</metadata>

+ 84 - 61
utilities/ffvii_field_model_exporter_pc/src/main.cpp

@@ -35,6 +35,7 @@ THE SOFTWARE.
 #include "data/QGearsAFileManager.h"
 #include "data/QGearsHRCFileManager.h"
 #include "data/QGearsLZSFLevelFileManager.h"
+#include "common/FF7NameLookup.h"
 
 void attachMesh( Ogre::MeshPtr &mesh )
 {
@@ -42,12 +43,12 @@ void attachMesh( Ogre::MeshPtr &mesh )
     Ogre::Entity* entity = scene_manager->createEntity( mesh );
     entity->setDisplaySkeleton( true );
     entity->setDebugDisplayEnabled( true );
-    entity->getAnimationState( "Idle" )->setEnabled( true );
-    entity->getAnimationState( "Idle" )->setLoop( true );
+   // entity->getAnimationState( "Idle" )->setEnabled( true );
+  //  entity->getAnimationState( "Idle" )->setLoop( true );
     Ogre::SceneNode* root_node = scene_manager->getRootSceneNode();
     root_node->showBoundingBox( true );
-    root_node->attachObject( entity );
-    entity->setVisible( false );
+   // root_node->attachObject( entity );
+    entity->setVisible( true );
 
     entitys.push_back( entity );
 }
@@ -79,62 +80,84 @@ void exportMesh( const Ogre::MeshPtr &mesh )
     mat_ser.exportQueued( base_name + QGears::EXT_MATERIAL );
 }
 
-int
-main( int argc, char *argv[] )
+
+
+int main( int argc, char *argv[] )
 {
-    QGears::FF7::FieldModelExporterPC app( argc, argv );
-    if( !app.initOgre() ) return 0;
-
-    Ogre::SceneManager*         scene_manager( Ogre::Root::getSingleton().getSceneManager( "Scene" ) );
-    QGears::AFilePtr            a;
-    QGears::HRCFilePtr          hrc = QGears::HRCFileManager::getSingleton().load( "adda.hrc", "FFVII" ).staticCast<QGears::HRCFile>();
-    QGears::AFileManager       &afl_mgr( QGears::AFileManager::getSingleton() );
-
-    Ogre::MeshPtr mesh( Ogre::MeshManager::getSingleton().load( "sd_red.mesh", "FFVII" ) );
-    Ogre::SkeletonPtr skeleton( mesh->getSkeleton() );
-
-    a = afl_mgr.load( "aeae.a", "FFVII" ).staticCast<QGears::AFile>();
-    a->addTo( skeleton, "Idle" );
-    a = afl_mgr.load( "aeaf.a", "FFVII" ).staticCast<QGears::AFile>();
-    a->addTo( skeleton, "Walk" );
-    a = afl_mgr.load( "aeba.a", "FFVII" ).staticCast<QGears::AFile>();
-    a->addTo( skeleton, "Run" );
-
-    attachMesh( mesh );
-    entitys[0]->setVisible( true );
-
-    QGears::LZSFLevelFileManager   &fmgr( QGears::LZSFLevelFileManager::getSingleton() );
-    QGears::FLevelFilePtr           f = fmgr.load( "ancnt1", "FFVII" ).staticCast<QGears::FLevelFile>();
-
-    mesh = Ogre::MeshManager::getSingleton().load( "n_cloud.mesh", "FFVII" );
-    skeleton = mesh->getSkeleton();
-    a = afl_mgr.load( "bvjf.a", "FFVII" ).staticCast<QGears::AFile>();
-    a->addTo( skeleton, "JumpFromTrain" );
-    attachMesh( mesh );
-
-    // Create background rectangle covering the whole screen
-    Ogre::Rectangle2D* rect = new Ogre::Rectangle2D(true);
-    rect->setCorners(-1.0, 1.0, 1.0, -1.0);
-    rect->setMaterial( "map" );
-
-    // Render the background before everything else
-    rect->setRenderQueueGroup( Ogre::RENDER_QUEUE_BACKGROUND );
-
-    // Use infinite AAB to always stay visible
-    Ogre::AxisAlignedBox aabInf;
-    aabInf.setInfinite();
-    rect->setBoundingBox( aabInf );
-
-    // Attach background to the scene
-    Ogre::SceneNode* node = scene_manager->getRootSceneNode()->createChildSceneNode("Background");
-    node->attachObject( rect );
-
-    Ogre::Root::getSingleton().startRendering();
-    skeleton.setNull();
-    mesh.setNull();
-    f.setNull();
-    hrc.setNull();
-    delete rect;
-
-    return 0;
+    try
+    {
+        QGears::FF7::FieldModelExporterPC app(argc, argv);
+        if (!app.initOgre()) return 0;
+
+        Ogre::SceneManager*         scene_manager(Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC, "Scene"));
+        QGears::AFilePtr            a;
+        QGears::HRCFilePtr          hrc = QGears::HRCFileManager::getSingleton().load("adda.hrc", "FFVII").staticCast<QGears::HRCFile>();
+        QGears::AFileManager       &afl_mgr(QGears::AFileManager::getSingleton());
+
+        auto meshName = QGears::FF7::NameLookup::model("adda.hrc") + ".mesh";
+
+        Ogre::MeshPtr mesh(Ogre::MeshManager::getSingleton().load(meshName, "FFVII"));
+        Ogre::SkeletonPtr skeleton(mesh->getSkeleton());
+
+
+        a = afl_mgr.load("aeae.a", "FFVII").staticCast<QGears::AFile>();
+        a->addTo(skeleton, "Idle");
+        a = afl_mgr.load("aeaf.a", "FFVII").staticCast<QGears::AFile>();
+        a->addTo(skeleton, "Walk");
+        a = afl_mgr.load("aeba.a", "FFVII").staticCast<QGears::AFile>();
+        a->addTo(skeleton, "Run");
+
+
+        attachMesh(mesh);
+        exportMesh(mesh);
+
+
+        entitys[0]->setVisible(true);
+
+        QGears::LZSFLevelFileManager   &fmgr(QGears::LZSFLevelFileManager::getSingleton());
+        // QGears::FLevelFilePtr           f = fmgr.load( "ancnt1", "FFVII" ).staticCast<QGears::FLevelFile>();
+
+        /*
+        mesh = Ogre::MeshManager::getSingleton().load(meshName, "FFVII");
+        skeleton = mesh->getSkeleton();
+        a = afl_mgr.load("bvjf.a", "FFVII").staticCast<QGears::AFile>();
+        a->addTo(skeleton, "JumpFromTrain");
+        */
+
+        //attachMesh( mesh );
+
+
+        // Create background rectangle covering the whole screen
+        //Ogre::Rectangle2D* rect = new Ogre::Rectangle2D(true);
+        //rect->setCorners(-1.0, 1.0, 1.0, -1.0);
+        // rect->setMaterial( "map" );
+
+        // Render the background before everything else
+        //rect->setRenderQueueGroup( Ogre::RENDER_QUEUE_BACKGROUND );
+
+        // Use infinite AAB to always stay visible
+        //Ogre::AxisAlignedBox aabInf;
+        //aabInf.setInfinite();
+        //rect->setBoundingBox( aabInf );
+
+        // Attach background to the scene
+        Ogre::SceneNode* node = scene_manager->getRootSceneNode()->createChildSceneNode("Background");
+
+        node->attachObject(entitys[0]);
+
+        //   node->attachObject( entitys[0] );
+
+        Ogre::Root::getSingleton().startRendering();
+        skeleton.setNull();
+        mesh.setNull();
+        //    f.setNull();
+        hrc.setNull();
+        //delete rect;
+        return 0;
+    }
+    catch (const Ogre::Exception& ex)
+    {
+        std::cout << "Ogre::Exception: " << ex.what() << std::endl;
+        return 1;
+    }
 }

+ 2 - 0
utilities/installer/CMakeLists.txt

@@ -11,10 +11,12 @@ include_directories(
 # define header and source files
 set(HEADER_FILES
     src/mainwindow.h
+	src/ff7DataInstaller.h
 )
 set(SOURCE_FILES
     src/Main.cpp
     src/mainwindow.cpp
+	src/ff7DataInstaller.cpp
 )
 
 set(INSTALLER_FORMS

+ 110 - 0
utilities/installer/src/ff7DataInstaller.cpp

@@ -0,0 +1,110 @@
+#include "ff7DataInstaller.h"
+
+#include <boost/filesystem.hpp>
+#include <boost/program_options.hpp>
+#include <OgreConfigFile.h>
+#include <OgreArchiveManager.h>
+#include <OgreMeshSerializer.h>
+#include <OgreSkeletonSerializer.h>
+#include <OgreMeshManager.h>
+
+#include "QGearsGameState.h"
+#include "data/QGearsAFileManager.h"
+#include "data/QGearsBackgroundFileManager.h"
+#include "data/QGearsCameraMatrixFileManager.h"
+#include "data/QGearsHRCFileManager.h"
+#include "data/QGearsLZSFLevelFileManager.h"
+#include "data/QGearsPaletteFileManager.h"
+#include "data/QGearsPFileManager.h"
+#include "data/QGearsRSDFileManager.h"
+#include "data/QGearsTexCodec.h"
+#include "map/QGearsBackground2DFileManager.h"
+#include "map/QGearsWalkmeshFileManager.h"
+#include "data/FF7ModelListFileManager.h"
+#include "data/QGearsLGPArchiveFactory.h"
+#include "common/QGearsStringUtil.h"
+#include "common/FF7NameLookup.h"
+
+FF7DataInstaller::FF7DataInstaller()
+{
+    m_root = std::make_unique<Ogre::Root>("", "", "installer.log");
+    Ogre::ArchiveManager::getSingleton().addArchiveFactory(new QGears::LGPArchiveFactory());
+
+    mResourceManagers.emplace_back(std::make_shared<QGears::HRCFileManager>());
+    mResourceManagers.emplace_back(std::make_shared<QGears::LZSFLevelFileManager>());
+    mResourceManagers.emplace_back(std::make_shared<QGears::AFileManager>());
+    mResourceManagers.emplace_back(std::make_shared<QGears::RSDFileManager>());
+}
+
+FF7DataInstaller::~FF7DataInstaller()
+{
+
+}
+
+void FF7DataInstaller::Convert(std::string inputDir, std::string outputDir, const std::vector<std::string>& files)
+{
+    for (const auto& file : files)
+    {
+        if (file == "field\\char.lgp")
+        {
+            auto fullPath = inputDir + file;
+         //   m_root->addResourceLocation(inputDir, "FileSystem", "FFVII");
+            m_root->addResourceLocation(fullPath, "LGP", "FFVII");
+
+            ConvertFieldModels(fullPath, outputDir);
+        }
+    }
+}
+
+// TOOD: Share with pc model exporter
+static void exportMesh(std::string outdir, const Ogre::MeshPtr &mesh)
+{
+    Ogre::MeshSerializer        mesh_ser;
+    mesh_ser.exportMesh(mesh.getPointer(), outdir +  mesh->getName());
+
+    Ogre::SkeletonPtr           skeleton(mesh->getSkeleton());
+    Ogre::SkeletonSerializer    sk_ser;
+    sk_ser.exportSkeleton(skeleton.getPointer(), outdir +  skeleton->getName());
+
+    Ogre::Mesh::SubMeshIterator it(mesh->getSubMeshIterator());
+    Ogre::MaterialSerializer    mat_ser;
+    size_t i(0);
+    while (it.hasMoreElements())
+    {
+        Ogre::SubMesh *sub_mesh(it.getNext());
+        Ogre::MaterialPtr mat(Ogre::MaterialManager::getSingleton().getByName(sub_mesh->getMaterialName()));
+        if (!mat.isNull())
+        {
+            mat_ser.queueForExport(mat);
+        }
+        ++i;
+    }
+    QGears::String base_name;
+    QGears::StringUtil::splitFull(mesh->getName(), base_name);
+    mat_ser.exportQueued(outdir + base_name + QGears::EXT_MATERIAL);
+}
+
+
+void FF7DataInstaller::ConvertFieldModels(std::string archive, std::string outDir)
+{
+
+    //QGears::LZSFLevelFileManager   &fmgr(QGears::LZSFLevelFileManager::getSingleton());
+
+   // QGears::FLevelFilePtr           f = fmgr.load(archive, "FFVII").staticCast<QGears::FLevelFile>();
+
+    Ogre::SceneManager*         scene_manager(Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC, "Scene"));
+    QGears::AFilePtr            a;
+    Ogre::ResourcePtr hrc = QGears::HRCFileManager::getSingleton().load("adda.hrc", "FFVII");
+    QGears::HRCFilePtr r = hrc.staticCast<QGears::HRCFile>();
+    QGears::AFileManager       &afl_mgr(QGears::AFileManager::getSingleton());
+
+    auto meshName = QGears::FF7::NameLookup::model("adda.hrc") + ".mesh";
+
+    // TODO: Crashes as technique index out of bounds in the material
+    Ogre::MeshPtr mesh(Ogre::MeshManager::getSingleton().load(meshName, "FFVII"));
+    Ogre::SkeletonPtr skeleton(mesh->getSkeleton());
+
+
+    exportMesh(outDir, mesh);
+
+}

+ 20 - 0
utilities/installer/src/ff7DataInstaller.h

@@ -0,0 +1,20 @@
+#pragma once
+
+#include <string>
+#include <vector>
+#include "common/make_unique.h"
+#include <OgreRoot.h>
+
+class FF7DataInstaller
+{
+public:
+    FF7DataInstaller();
+    ~FF7DataInstaller();
+    void Convert(std::string inputDir, std::string outputDir, const std::vector<std::string>& files);
+
+private:
+    void ConvertFieldModels(std::string archive, std::string outDir);
+    std::unique_ptr<Ogre::Root> m_root;
+
+    std::vector<std::shared_ptr<Ogre::ResourceManager>> mResourceManagers;
+};

+ 18 - 1
utilities/installer/src/mainwindow.cpp

@@ -1,5 +1,6 @@
 #include "mainwindow.h"
 #include "ui_mainwindow.h"
+#include "ff7DataInstaller.h"
 
 MainWindow::MainWindow(QWidget *parent) :
     QMainWindow(parent),
@@ -9,7 +10,10 @@ MainWindow::MainWindow(QWidget *parent) :
     /*
      set any options here
      */
-
+#ifdef _DEBUG
+    ui->lineInput->setText("C:\\Games\\FF7\\data\\");
+    ui->lineOutput->setText("C:\\Users\\paul\\Desktop\\q-gears\\output\\_data\\");
+#endif
 }
 
 MainWindow::~MainWindow()
@@ -44,5 +48,18 @@ void MainWindow::on_btnGO_clicked()
     else
     {
         QMessageBox::information(this,tr("Converting Data"),tr("Attempt to convert with \n Input: %1 \n Output: %2").arg(ui->lineInput->text(),ui->lineOutput->text()));
+
+        FF7DataInstaller conversion;
+        std::vector<std::string> vec;
+
+        // TODO: Enumerate files or find some better way to do this :)
+        vec.push_back("field\\char.lgp");
+
+        // TODO: Debug build using release qt dlls so toStdString mixes heaps and crashes
+        auto qinput = ui->lineInput->text();
+        std::wstring input = reinterpret_cast<wchar_t*>(qinput.data());
+        auto qoutput = ui->lineOutput->text();
+        std::wstring output = reinterpret_cast<wchar_t*>(qoutput.data());
+        conversion.Convert(std::string(input.begin(), input.end()), std::string(output.begin(), output.end()), vec);
     }
 }