Skip to content

Commit

Permalink
#5576: Create a separate AseModelLoader to be able to refactor the AS…
Browse files Browse the repository at this point in the history
…E importer code.
  • Loading branch information
codereader committed Apr 4, 2021
1 parent f2996fc commit 8b669ca
Show file tree
Hide file tree
Showing 10 changed files with 208 additions and 67 deletions.
69 changes: 69 additions & 0 deletions radiantcore/model/picomodel/AseModelLoader.cpp
@@ -0,0 +1,69 @@
#include "AseModelLoader.h"

#include "lib/picomodel.h"
#include "os/path.h"
#include "string/case_conv.h"
#include "StaticModel.h"

extern "C"
{
extern const picoModule_t picoModuleASE;
}

namespace model
{

namespace
{

size_t picoInputStreamReam(void* inputStream, unsigned char* buffer, size_t length)
{
return reinterpret_cast<InputStream*>(inputStream)->read(buffer, length);
}

}

AseModelLoader::AseModelLoader() :
ModelImporterBase("ASE")
{}

IModelPtr AseModelLoader::loadModelFromPath(const std::string& path)
{
// Open an ArchiveFile to load
auto file = path_is_absolute(path.c_str()) ?
GlobalFileSystem().openFileInAbsolutePath(path) :
GlobalFileSystem().openFile(path);

if (!file)
{
rError() << "Failed to load model " << path << std::endl;
return IModelPtr();
}

auto* model = PicoModuleLoadModelStream(
&picoModuleASE,
&file->getInputStream(),
picoInputStreamReam,
file->size(),
0
);

// greebo: Check if the model load was successful
if (!model || model->numSurfaces == 0)
{
// Model is either NULL or has no surfaces, this must've failed
return IModelPtr();
}

auto modelObj = std::make_shared<StaticModel>(model, string::to_lower_copy(getExtension()));

// Set the filename
modelObj->setFilename(os::getFilename(file->getName()));
modelObj->setModelPath(path);

PicoFreeModel(model);

return modelObj;
}

}
18 changes: 18 additions & 0 deletions radiantcore/model/picomodel/AseModelLoader.h
@@ -0,0 +1,18 @@
#pragma once

#include "ModelImporterBase.h"

namespace model
{

class AseModelLoader :
public ModelImporterBase
{
public:
AseModelLoader();

// Load the given model from the path, VFS or absolute
IModelPtr loadModelFromPath(const std::string& name) override;
};

} // namespace model
69 changes: 69 additions & 0 deletions radiantcore/model/picomodel/ModelImporterBase.cpp
@@ -0,0 +1,69 @@
#include "ModelImporterBase.h"

#include "ifilesystem.h"
#include "itextstream.h"
#include "imodelcache.h"
#include "string/case_conv.h"
#include "os/path.h"
#include "StaticModelNode.h"
#include "StaticModel.h"

namespace model
{

namespace
{
// name may be absolute or relative
inline std::string rootPath(const std::string& name)
{
return GlobalFileSystem().findRoot(
path_is_absolute(name.c_str()) ? name : GlobalFileSystem().findFile(name)
);
}
}

ModelImporterBase::ModelImporterBase(const std::string& extension) :
_extension(string::to_upper_copy(extension))
{

}

const std::string& ModelImporterBase::getExtension() const
{
return _extension;
}

scene::INodePtr ModelImporterBase::loadModel(const std::string& modelName)
{
// Initialise the paths, this is all needed for realisation
std::string path = rootPath(modelName);
std::string name = os::getRelativePath(modelName, path);

// greebo: Path is empty for models in PK4 files, don't check this

// Try to load the model from the given VFS path
IModelPtr model = GlobalModelCache().getModel(name);

if (!model)
{
rError() << "ModelImporterBase: Could not load model << " << modelName << std::endl;
return scene::INodePtr();
}

// The cached model should be a StaticModel, otherwise we're in the wrong movie
auto picoModel = std::dynamic_pointer_cast<StaticModel>(model);

if (picoModel)
{
// Load was successful, construct a modelnode using this resource
return std::make_shared<StaticModelNode>(picoModel);
}
else
{
rError() << "ModelImporterBase: Cached model is not a PicoModel?" << std::endl;
}

return scene::INodePtr();
}

}
24 changes: 24 additions & 0 deletions radiantcore/model/picomodel/ModelImporterBase.h
@@ -0,0 +1,24 @@
#pragma once

#include "imodel.h"

namespace model
{

class ModelImporterBase :
public IModelImporter
{
private:
// Supported file extension in UPPERCASE (ASE, LWO, whatever)
std::string _extension;

public:
ModelImporterBase(const std::string& extension);

const std::string& getExtension() const override;

// Returns a new ModelNode for the given model name
scene::INodePtr loadModel(const std::string& modelName) override;
};

}
61 changes: 6 additions & 55 deletions radiantcore/model/picomodel/PicoModelLoader.cpp
Expand Up @@ -8,71 +8,24 @@

#include "os/path.h"

#include "StaticModelNode.h"

#include "idatastream.h"
#include "string/case_conv.h"
#include "StaticModel.h"

namespace model {

namespace {
// name may be absolute or relative
inline std::string rootPath(const std::string& name) {
return GlobalFileSystem().findRoot(
path_is_absolute(name.c_str()) ? name : GlobalFileSystem().findFile(name)
);
}

namespace
{
size_t picoInputStreamReam(void* inputStream, unsigned char* buffer, size_t length) {
return reinterpret_cast<InputStream*>(inputStream)->read(buffer, length);
}
} // namespace

PicoModelLoader::PicoModelLoader(const picoModule_t* module, const std::string& extension) :
_module(module),
_extension(string::to_upper_copy(extension))
ModelImporterBase(extension),
_module(module)
{}

const std::string& PicoModelLoader::getExtension() const
{
return _extension;
}

// Returns a new ModelNode for the given model name
scene::INodePtr PicoModelLoader::loadModel(const std::string& modelName)
{
// Initialise the paths, this is all needed for realisation
std::string path = rootPath(modelName);
std::string name = os::getRelativePath(modelName, path);

// greebo: Path is empty for models in PK4 files, don't check this

// Try to load the model from the given VFS path
IModelPtr model = GlobalModelCache().getModel(name);

if (!model)
{
rError() << "PicoModelLoader: Could not load model << " << modelName << std::endl;
return scene::INodePtr();
}

// The cached model should be an PicoModel, otherwise we're in the wrong movie
StaticModelPtr picoModel =
std::dynamic_pointer_cast<StaticModel>(model);

if (picoModel)
{
// Load was successful, construct a modelnode using this resource
return std::make_shared<StaticModelNode>(picoModel);
}
else
{
rError() << "PicoModelLoader: Cached model is not a PicoModel?" << std::endl;
}

return scene::INodePtr();
}

// Load the given model from the VFS path
IModelPtr PicoModelLoader::loadModelFromPath(const std::string& path)
{
Expand Down Expand Up @@ -107,9 +60,7 @@ IModelPtr PicoModelLoader::loadModelFromPath(const std::string& path)
return IModelPtr();
}

StaticModelPtr modelObj(
new StaticModel(model, fExt)
);
auto modelObj = std::make_shared<StaticModel>(model, fExt);

// Set the filename
modelObj->setFilename(os::getFilename(file->getName()));
Expand Down
13 changes: 2 additions & 11 deletions radiantcore/model/picomodel/PicoModelLoader.h
@@ -1,32 +1,23 @@
#pragma once

#include "imodel.h"
#include "ModelImporterBase.h"

typedef struct picoModule_s picoModule_t;

namespace model
{

class PicoModelLoader :
public IModelImporter
public ModelImporterBase
{
private:
const picoModule_t* _module;

// Supported file extension in UPPERCASE (ASE, LWO, whatever)
std::string _extension;

public:
PicoModelLoader(const picoModule_t* module, const std::string& extension);

const std::string& getExtension() const override;

// Returns a new ModelNode for the given model name
scene::INodePtr loadModel(const std::string& modelName) override;

// Load the given model from the path, VFS or absolute
IModelPtr loadModelFromPath(const std::string& name) override;
};
typedef std::shared_ptr<PicoModelLoader> PicoModelLoaderPtr;

} // namespace model
3 changes: 3 additions & 0 deletions radiantcore/model/picomodel/PicoModelModule.h
Expand Up @@ -13,6 +13,7 @@

#include "string/case_conv.h"
#include "PicoModelLoader.h"
#include "AseModelLoader.h"

namespace model
{
Expand Down Expand Up @@ -70,6 +71,8 @@ class PicoModelModule :
}
}
}

GlobalModelFormatManager().registerImporter(std::make_shared<AseModelLoader>());
}

private:
Expand Down
2 changes: 1 addition & 1 deletion radiantcore/model/picomodel/lib/picomodules.c
Expand Up @@ -63,7 +63,7 @@ const picoModule_t *picoModules[] =
{
&picoModuleMD3, /* quake3 arena md3 */
&picoModule3DS, /* autodesk 3ds */
&picoModuleASE, /* autodesk ase */
//&picoModuleASE, /* autodesk ase */
&picoModuleMS3D, /* milkshape3d */
&picoModuleMDC, /* return to castle wolfenstein mdc */
&picoModuleMD2, /* quake2 md2 */
Expand Down
4 changes: 4 additions & 0 deletions tools/msvc/DarkRadiantCore.vcxproj
Expand Up @@ -163,6 +163,7 @@
<ClCompile Include="..\..\radiantcore\model\ModelFormatManager.cpp" />
<ClCompile Include="..\..\radiantcore\model\NullModel.cpp" />
<ClCompile Include="..\..\radiantcore\model\NullModelNode.cpp" />
<ClCompile Include="..\..\radiantcore\model\picomodel\AseModelLoader.cpp" />
<ClCompile Include="..\..\radiantcore\model\picomodel\lib\lwo\clip.c">
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CompileAsC</CompileAs>
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CompileAsC</CompileAs>
Expand Down Expand Up @@ -577,6 +578,7 @@
<ForcedIncludeFiles Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</ForcedIncludeFiles>
</ClCompile>
<ClCompile Include="..\..\radiantcore\model\picomodel\ModelImporterBase.cpp" />
<ClCompile Include="..\..\radiantcore\model\picomodel\PicoModelLoader.cpp" />
<ClCompile Include="..\..\radiantcore\model\picomodel\PicoModelModule.cpp" />
<ClCompile Include="..\..\radiantcore\model\picomodel\StaticModel.cpp" />
Expand Down Expand Up @@ -887,10 +889,12 @@
<ClInclude Include="..\..\radiantcore\model\NullModel.h" />
<ClInclude Include="..\..\radiantcore\model\NullModelLoader.h" />
<ClInclude Include="..\..\radiantcore\model\NullModelNode.h" />
<ClInclude Include="..\..\radiantcore\model\picomodel\AseModelLoader.h" />
<ClInclude Include="..\..\radiantcore\model\picomodel\lib\lwo\lwo2.h" />
<ClInclude Include="..\..\radiantcore\model\picomodel\lib\picointernal.h" />
<ClInclude Include="..\..\radiantcore\model\picomodel\lib\picomodel.h" />
<ClInclude Include="..\..\radiantcore\model\picomodel\lib\pm_fm.h" />
<ClInclude Include="..\..\radiantcore\model\picomodel\ModelImporterBase.h" />
<ClInclude Include="..\..\radiantcore\model\picomodel\PicoModelLoader.h" />
<ClInclude Include="..\..\radiantcore\model\picomodel\PicoModelModule.h" />
<ClInclude Include="..\..\radiantcore\model\picomodel\StaticModel.h" />
Expand Down
12 changes: 12 additions & 0 deletions tools/msvc/DarkRadiantCore.vcxproj.filters
Expand Up @@ -1027,6 +1027,12 @@
<ClCompile Include="..\..\radiantcore\shaders\MaterialSourceGenerator.cpp">
<Filter>src\shaders</Filter>
</ClCompile>
<ClCompile Include="..\..\radiantcore\model\picomodel\AseModelLoader.cpp">
<Filter>src\model\picomodel</Filter>
</ClCompile>
<ClCompile Include="..\..\radiantcore\model\picomodel\ModelImporterBase.cpp">
<Filter>src\model\picomodel</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\radiantcore\modulesystem\ModuleLoader.h">
Expand Down Expand Up @@ -2097,5 +2103,11 @@
<ClInclude Include="..\..\radiantcore\shaders\MaterialSourceGenerator.h">
<Filter>src\shaders</Filter>
</ClInclude>
<ClInclude Include="..\..\radiantcore\model\picomodel\AseModelLoader.h">
<Filter>src\model\picomodel</Filter>
</ClInclude>
<ClInclude Include="..\..\radiantcore\model\picomodel\ModelImporterBase.h">
<Filter>src\model\picomodel</Filter>
</ClInclude>
</ItemGroup>
</Project>

0 comments on commit 8b669ca

Please sign in to comment.