New model file format
- added new binary and text formats for models - fixes and improvements in CModelFile - tool for converting model files - minor additions and fixesdev-ui
parent
3e52ae4ca9
commit
e94e26ae1e
|
@ -1,5 +1,8 @@
|
|||
# CBot shared library is built separately
|
||||
add_subdirectory(CBot)
|
||||
add_subdirectory(CBot)
|
||||
|
||||
# Tools directory is built separately
|
||||
add_subdirectory(tools)
|
||||
|
||||
|
||||
# Configure options
|
||||
|
|
|
@ -113,6 +113,7 @@ CApplication::~CApplication()
|
|||
bool CApplication::ParseArguments(int argc, char *argv[])
|
||||
{
|
||||
bool waitDataDir = false;
|
||||
bool waitLogLevel = false;
|
||||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
|
@ -125,10 +126,34 @@ bool CApplication::ParseArguments(int argc, char *argv[])
|
|||
continue;
|
||||
}
|
||||
|
||||
if (waitLogLevel)
|
||||
{
|
||||
waitLogLevel = false;
|
||||
if (arg == "trace")
|
||||
GetLogger()->SetLogLevel(LOG_TRACE);
|
||||
else if (arg == "debug")
|
||||
GetLogger()->SetLogLevel(LOG_DEBUG);
|
||||
else if (arg == "info")
|
||||
GetLogger()->SetLogLevel(LOG_INFO);
|
||||
else if (arg == "warn")
|
||||
GetLogger()->SetLogLevel(LOG_WARN);
|
||||
else if (arg == "error")
|
||||
GetLogger()->SetLogLevel(LOG_ERROR);
|
||||
else if (arg == "none")
|
||||
GetLogger()->SetLogLevel(LOG_NONE);
|
||||
else
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "-debug")
|
||||
{
|
||||
SetDebugMode(true);
|
||||
}
|
||||
else if (arg == "-loglevel")
|
||||
{
|
||||
waitLogLevel = true;
|
||||
}
|
||||
else if (arg == "-datadir")
|
||||
{
|
||||
waitDataDir = true;
|
||||
|
@ -140,8 +165,8 @@ bool CApplication::ParseArguments(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
// Data dir not given?
|
||||
if (waitDataDir)
|
||||
// Args not given?
|
||||
if (waitDataDir || waitLogLevel)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -27,9 +27,10 @@ namespace IOUtils {
|
|||
|
||||
//! Writes a binary number to output stream
|
||||
/**
|
||||
\c T is a numeric type (int, unsigned int, etc.)
|
||||
\c N is number of bytes
|
||||
Write order is little-endian */
|
||||
* \c T is a numeric type (int, unsigned int, etc.)
|
||||
* \c N is number of bytes
|
||||
* Write order is little-endian
|
||||
*/
|
||||
template<int N, typename T>
|
||||
void WriteBinary(T value, std::ostream &ostr)
|
||||
{
|
||||
|
@ -42,9 +43,10 @@ void WriteBinary(T value, std::ostream &ostr)
|
|||
|
||||
//! Reads a binary number from input stream
|
||||
/**
|
||||
\c T is a numeric type (int, unsigned int, etc.)
|
||||
\c N is number of bytes
|
||||
Read order is little-endian */
|
||||
* \c T is a numeric type (int, unsigned int, etc.)
|
||||
* \c N is number of bytes
|
||||
* Read order is little-endian
|
||||
*/
|
||||
template<int N, typename T>
|
||||
T ReadBinary(std::istream &istr)
|
||||
{
|
||||
|
@ -58,10 +60,31 @@ T ReadBinary(std::istream &istr)
|
|||
return value;
|
||||
}
|
||||
|
||||
//! Writes a binary 1-byte boolean
|
||||
/**
|
||||
* false is 0; true is 1.
|
||||
*/
|
||||
void WriteBinaryBool(float value, std::ostream &ostr)
|
||||
{
|
||||
unsigned char v = value ? 1 : 0;
|
||||
IOUtils::WriteBinary<1, unsigned char>(v, ostr);
|
||||
}
|
||||
|
||||
//! Reads a binary 1-byte boolean
|
||||
/**
|
||||
* 0 is false; other values are true.
|
||||
*/
|
||||
bool ReadBinaryBool(std::istream &istr)
|
||||
{
|
||||
int v = IOUtils::ReadBinary<1, unsigned char>(istr);
|
||||
return v != 0;
|
||||
}
|
||||
|
||||
//! Writes a binary 32-bit float to output stream
|
||||
/**
|
||||
Write order is little-endian
|
||||
NOTE: code is probably not portable as there are platforms with other float representations. */
|
||||
* Write order is little-endian
|
||||
* NOTE: code is probably not portable as there are platforms with other float representations.
|
||||
*/
|
||||
void WriteBinaryFloat(float value, std::ostream &ostr)
|
||||
{
|
||||
union { float fValue; unsigned int iValue; } u;
|
||||
|
@ -72,8 +95,9 @@ void WriteBinaryFloat(float value, std::ostream &ostr)
|
|||
|
||||
//! Reads a binary 32-bit float from input stream
|
||||
/**
|
||||
Read order is little-endian
|
||||
NOTE: code is probably not portable as there are platforms with other float representations. */
|
||||
* Read order is little-endian
|
||||
* NOTE: code is probably not portable as there are platforms with other float representations.
|
||||
*/
|
||||
float ReadBinaryFloat(std::istream &istr)
|
||||
{
|
||||
union { float fValue; unsigned int iValue; } u;
|
||||
|
@ -82,4 +106,40 @@ float ReadBinaryFloat(std::istream &istr)
|
|||
return u.fValue;
|
||||
}
|
||||
|
||||
//! Writes a variable binary string to output stream
|
||||
/**
|
||||
* The string is written by first writing string length
|
||||
* in \c N byte binary number and then the string bytes.
|
||||
*/
|
||||
template<int N>
|
||||
void WriteBinaryString(const std::string &value, std::ostream &ostr)
|
||||
{
|
||||
int length = value.size();
|
||||
WriteBinary<N, int>(length, ostr);
|
||||
|
||||
for (int i = 0; i < length; ++i)
|
||||
ostr.put(value[i]);
|
||||
}
|
||||
|
||||
//! Reads a variable binary string from output stream
|
||||
/**
|
||||
* The string is read by first reading string length
|
||||
* in \c N byte binary number and then the string bytes.
|
||||
*/
|
||||
template<int N>
|
||||
std::string ReadBinaryString(std::istream &istr)
|
||||
{
|
||||
int length = ReadBinary<N, int>(istr);
|
||||
|
||||
std::string str;
|
||||
char c = 0;
|
||||
for (int i = 0; i < length; ++i)
|
||||
{
|
||||
istr.read(&c, 1);
|
||||
str += c;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
}; // namespace IOUtils
|
||||
|
|
|
@ -29,26 +29,26 @@ template<typename T> class CSingleton
|
|||
|
||||
public:
|
||||
static T& GetInstance() {
|
||||
assert(mInstance != NULL);
|
||||
assert(mInstance != nullptr);
|
||||
return *mInstance;
|
||||
}
|
||||
|
||||
static T* GetInstancePointer() {
|
||||
assert(mInstance != NULL);
|
||||
assert(mInstance != nullptr);
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
static bool IsCreated() {
|
||||
return mInstance != NULL;
|
||||
return mInstance != nullptr;
|
||||
}
|
||||
|
||||
CSingleton() {
|
||||
assert(mInstance == NULL);
|
||||
assert(mInstance == nullptr);
|
||||
mInstance = static_cast<T *>(this);
|
||||
}
|
||||
|
||||
virtual ~CSingleton() {
|
||||
mInstance = NULL;
|
||||
mInstance = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,7 +20,6 @@
|
|||
* \brief Model loading - Gfx::CModelFile class (aka modfile)
|
||||
*/
|
||||
|
||||
#include "graphics/engine/engine.h"
|
||||
#include "graphics/core/vertex.h"
|
||||
#include "graphics/core/material.h"
|
||||
#include "math/vector.h"
|
||||
|
@ -35,6 +34,9 @@ class CInstanceManager;
|
|||
|
||||
namespace Gfx {
|
||||
|
||||
class CEngine;
|
||||
|
||||
|
||||
/**
|
||||
\struct ModelTriangle
|
||||
\brief Triangle of a 3D model
|
||||
|
@ -53,14 +55,21 @@ struct ModelTriangle
|
|||
std::string tex1Name;
|
||||
//! Name of 2nd texture
|
||||
std::string tex2Name;
|
||||
//! If true, 2nd texture will be taken from current engine setting
|
||||
bool variableTex2;
|
||||
//! Min LOD threshold
|
||||
float min;
|
||||
//! Max LOD threshold
|
||||
float max;
|
||||
//! Rendering state to be set
|
||||
long state;
|
||||
int state;
|
||||
|
||||
ModelTriangle();
|
||||
ModelTriangle()
|
||||
{
|
||||
variableTex2 = true;
|
||||
min = max = 0.0f;
|
||||
state = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -75,27 +84,45 @@ public:
|
|||
CModelFile(CInstanceManager* iMan);
|
||||
~CModelFile();
|
||||
|
||||
//! Returns the last error encountered
|
||||
std::string GetError();
|
||||
//! Reads a model in text format from file
|
||||
bool ReadTextModel(const std::string &fileName);
|
||||
//! Reads a model in text format from stream
|
||||
bool ReadTextModel(std::istream &stream);
|
||||
|
||||
//! Writes the model in text format to a file
|
||||
bool WriteTextModel(const std::string &fileName);
|
||||
//! Writes the model in text format to a stream
|
||||
bool WriteTextModel(std::ostream &stream);
|
||||
|
||||
//! Reads a model in new binary format from file
|
||||
bool ReadBinaryModel(const std::string &fileName);
|
||||
//! Reads a model in new binary format from stream
|
||||
bool ReadBinaryModel(std::istream &stream);
|
||||
|
||||
//! Writes the model in binary format to a file
|
||||
bool WriteBinaryModel(const std::string &fileName);
|
||||
//! Writes the model in binary format to a stream
|
||||
bool WriteBinaryModel(std::ostream &stream);
|
||||
|
||||
//! Reads a binary Colobot model from file
|
||||
bool ReadModel(const std::string &filename, bool edit = false, bool meta = true);
|
||||
//! @deprecated
|
||||
bool ReadModel(const std::string &fileName);
|
||||
//! Reads a binary Colobot model from stream
|
||||
bool ReadModel(std::istream &stream, bool edit = false, bool meta = true);
|
||||
//! @deprecated
|
||||
bool ReadModel(std::istream &stream);
|
||||
//! Writes the model to Colobot binary model file
|
||||
bool WriteModel(const std::string &filename);
|
||||
//! @deprecated
|
||||
bool WriteModel(const std::string &fileName);
|
||||
//! Writes the model to Colobot binary model file
|
||||
//! @deprecated
|
||||
bool WriteModel(std::ostream &stream);
|
||||
|
||||
//! Reads a DXF model from file
|
||||
bool ReadDXF(const std::string &filename, float min, float max);
|
||||
//! Reads a DXF model from stream
|
||||
bool ReadDXF(std::istream &stream, float min, float max);
|
||||
|
||||
//! Returns the number of triangles in model
|
||||
int GetTriangleCount();
|
||||
|
||||
//! Returns the triangle vector
|
||||
std::vector<Gfx::ModelTriangle>& GetTriangles();
|
||||
const std::vector<Gfx::ModelTriangle>& GetTriangles();
|
||||
|
||||
//! Returns the height of model -- closest point to X and Z coords of \a pos
|
||||
float GetHeight(Math::Vector pos);
|
||||
|
||||
|
@ -103,7 +130,7 @@ public:
|
|||
void Mirror();
|
||||
|
||||
//! Creates an object in the graphics engine from the model
|
||||
bool CreateEngineObject(int objRank, int addState = 0);
|
||||
bool CreateEngineObject(int objRank);
|
||||
|
||||
protected:
|
||||
//! Adds a triangle to the list
|
||||
|
@ -113,9 +140,6 @@ protected:
|
|||
CInstanceManager* m_iMan;
|
||||
Gfx::CEngine* m_engine;
|
||||
|
||||
//! Last error
|
||||
std::string m_error;
|
||||
|
||||
//! Model triangles
|
||||
std::vector<Gfx::ModelTriangle> m_triangles;
|
||||
};
|
||||
|
|
|
@ -180,7 +180,7 @@ void Gfx::CTerrain::LevelFlush()
|
|||
LevelCloseTable();
|
||||
}
|
||||
|
||||
void Gfx::CTerrain::LevelMaterial(int id, std::string& baseName, float u, float v,
|
||||
void Gfx::CTerrain::LevelMaterial(int id, const std::string& baseName, float u, float v,
|
||||
int up, int right, int down, int left,
|
||||
float hardness)
|
||||
{
|
||||
|
|
|
@ -157,7 +157,7 @@ public:
|
|||
//! Empties level
|
||||
void LevelFlush();
|
||||
//! Initializes the names of textures to use for the land
|
||||
void LevelMaterial(int id, std::string& baseName, float u, float v, int up, int right, int down, int left, float hardness);
|
||||
void LevelMaterial(int id, const std::string& baseName, float u, float v, int up, int right, int down, int left, float hardness);
|
||||
//! Initializes all the ground with a material
|
||||
bool LevelInit(int id);
|
||||
//! Generates a level in the terrain
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
set(CONVERT_MODEL_SOURCES
|
||||
../common/iman.cpp
|
||||
../common/logger.cpp
|
||||
../common/stringutils.cpp
|
||||
../graphics/engine/modelfile.cpp
|
||||
convert_model.cpp
|
||||
)
|
||||
|
||||
include_directories(. ..)
|
||||
|
||||
add_definitions(-DMODELFILE_NO_ENGINE)
|
||||
|
||||
add_executable(convert_model ${CONVERT_MODEL_SOURCES})
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* \dir tools
|
||||
* \brief Various tools (separate programs)
|
||||
*/
|
|
@ -0,0 +1,285 @@
|
|||
#include "common/iman.h"
|
||||
#include "common/logger.h"
|
||||
#include "graphics/engine/modelfile.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
|
||||
bool EndsWith(std::string const &fullString, std::string const &ending)
|
||||
{
|
||||
if (fullString.length() >= ending.length()) {
|
||||
return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct Args
|
||||
{
|
||||
bool usage;
|
||||
bool dumpInfo;
|
||||
bool mirror;
|
||||
std::string inputFile;
|
||||
std::string outputFile;
|
||||
std::string inputFormat;
|
||||
std::string outputFormat;
|
||||
|
||||
Args()
|
||||
{
|
||||
usage = false;
|
||||
dumpInfo = false;
|
||||
mirror = false;
|
||||
}
|
||||
};
|
||||
|
||||
Args ARGS;
|
||||
|
||||
void PrintUsage(const std::string& program)
|
||||
{
|
||||
std::cerr << "Colobot model converter" << std::endl;
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "Usage:" << std::endl;
|
||||
std::cerr << std::endl;
|
||||
std::cerr << " Convert files:" << std::endl;
|
||||
std::cerr << " " << program << " -i input_file -if input_format -o output_file -of output_format [-m]" << std::endl;
|
||||
std::cerr << " -m => mirror" << std::endl;
|
||||
std::cerr << std::endl;
|
||||
std::cerr << " Dump info:" << std::endl;
|
||||
std::cerr << " " << program << " -d -i input_file -if input_format" << std::endl;
|
||||
std::cerr << std::endl;
|
||||
std::cerr << " Help:" << std::endl;
|
||||
std::cerr << " " << program << " -h" << std::endl;
|
||||
std::cerr << std::endl;
|
||||
|
||||
std::cerr << "Model formats:" << std::endl;
|
||||
std::cerr << " old => old binary format" << std::endl;
|
||||
std::cerr << " new_bin => new binary format" << std::endl;
|
||||
std::cerr << " new_txt => new text format" << std::endl;
|
||||
}
|
||||
|
||||
bool ParseArgs(int argc, char *argv[])
|
||||
{
|
||||
bool waitI = false, waitO = false;
|
||||
bool waitIf = false, waitOf = false;
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::string arg = std::string(argv[i]);
|
||||
|
||||
if (arg == "-i")
|
||||
{
|
||||
waitI = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-o")
|
||||
{
|
||||
waitO = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-if")
|
||||
{
|
||||
waitIf = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-of")
|
||||
{
|
||||
waitOf = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (waitI)
|
||||
{
|
||||
waitI = false;
|
||||
ARGS.inputFile = arg;
|
||||
}
|
||||
else if (waitO)
|
||||
{
|
||||
waitO = false;
|
||||
ARGS.outputFile = arg;
|
||||
}
|
||||
else if (waitIf)
|
||||
{
|
||||
waitIf = false;
|
||||
ARGS.inputFormat = arg;
|
||||
}
|
||||
else if (waitOf)
|
||||
{
|
||||
waitOf = false;
|
||||
ARGS.outputFormat = arg;
|
||||
}
|
||||
else if (arg == "-h")
|
||||
{
|
||||
PrintUsage(argv[0]);
|
||||
ARGS.usage = true;
|
||||
}
|
||||
else if (arg == "-d")
|
||||
{
|
||||
ARGS.dumpInfo = true;
|
||||
}
|
||||
else if (arg == "-m")
|
||||
{
|
||||
ARGS.mirror = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (waitI || waitO || waitIf || waitOf)
|
||||
return false;
|
||||
|
||||
if (ARGS.usage)
|
||||
return true;
|
||||
|
||||
if (ARGS.inputFile.empty() || (!ARGS.dumpInfo && ARGS.outputFile.empty() ))
|
||||
return false;
|
||||
|
||||
if (ARGS.inputFormat.empty() || (!ARGS.dumpInfo && ARGS.outputFormat.empty() ))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void PrintStats(const std::map<T, int>& stats, int total)
|
||||
{
|
||||
for (auto it = stats.begin(); it != stats.end(); ++it)
|
||||
{
|
||||
std::cerr << " " << (*it).first << " : " << (*it).second << " / " << total << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
CLogger logger;
|
||||
|
||||
if (!ParseArgs(argc, argv))
|
||||
{
|
||||
std::cerr << "Invalid arguments! Run with -h for usage info." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ARGS.usage)
|
||||
return 0;
|
||||
|
||||
CInstanceManager iMan;
|
||||
Gfx::CModelFile model(&iMan);
|
||||
|
||||
bool ok = true;
|
||||
|
||||
if (ARGS.inputFormat == "old")
|
||||
{
|
||||
ok = model.ReadModel(ARGS.inputFile);
|
||||
}
|
||||
else if (ARGS.inputFormat == "new_bin")
|
||||
{
|
||||
ok = model.ReadBinaryModel(ARGS.inputFile);
|
||||
}
|
||||
else if (ARGS.inputFormat == "new_txt")
|
||||
{
|
||||
ok = model.ReadTextModel(ARGS.inputFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Invalid input format" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
std::cerr << "Reading input model failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ARGS.dumpInfo)
|
||||
{
|
||||
const std::vector<Gfx::ModelTriangle>& triangles = model.GetTriangles();
|
||||
|
||||
Math::Vector min( Math::HUGE_NUM, Math::HUGE_NUM, Math::HUGE_NUM);
|
||||
Math::Vector max(-Math::HUGE_NUM, -Math::HUGE_NUM, -Math::HUGE_NUM);
|
||||
|
||||
std::map<std::string, int> texs1, texs2;
|
||||
std::map<int, int> states;
|
||||
std::map<float, int> mins, maxs;
|
||||
int variableTexs2 = 0;
|
||||
|
||||
for (int i = 0; i < static_cast<int>( triangles.size() ); ++i)
|
||||
{
|
||||
const Gfx::ModelTriangle& t = triangles[i];
|
||||
|
||||
min.x = Math::Min(t.p1.coord.x, t.p2.coord.x, t.p3.coord.x, min.x);
|
||||
min.y = Math::Min(t.p1.coord.y, t.p2.coord.y, t.p3.coord.y, min.y);
|
||||
min.z = Math::Min(t.p1.coord.z, t.p2.coord.z, t.p3.coord.z, min.z);
|
||||
|
||||
max.x = Math::Max(t.p1.coord.x, t.p2.coord.x, t.p3.coord.x, max.x);
|
||||
max.y = Math::Max(t.p1.coord.y, t.p2.coord.y, t.p3.coord.y, max.y);
|
||||
max.z = Math::Max(t.p1.coord.z, t.p2.coord.z, t.p3.coord.z, max.z);
|
||||
|
||||
texs1[t.tex1Name] += 1;
|
||||
if (! t.tex2Name.empty())
|
||||
texs2[t.tex2Name] += 1;
|
||||
if (t.variableTex2)
|
||||
variableTexs2 += 1;
|
||||
states[t.state] += 1;
|
||||
|
||||
mins[t.min] += 1;
|
||||
maxs[t.max] += 1;
|
||||
}
|
||||
|
||||
std::cerr << "---- Info ----" << std::endl;
|
||||
std::cerr << "Total triangles: " << triangles.size();
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "Bounding box:" << std::endl;
|
||||
std::cerr << " min: [" << min.x << ", " << min.y << ", " << min.z << "]" << std::endl;
|
||||
std::cerr << " max: [" << max.x << ", " << max.y << ", " << max.z << "]" << std::endl;
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "Textures:" << std::endl;
|
||||
std::cerr << " tex1:" << std::endl;
|
||||
PrintStats(texs1, triangles.size());
|
||||
std::cerr << " tex2:" << std::endl;
|
||||
PrintStats(texs2, triangles.size());
|
||||
std::cerr << " variable tex2: " << variableTexs2 << " / " << triangles.size() << std::endl;
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "States:" << std::endl;
|
||||
PrintStats(states, triangles.size());
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "LOD:" << std::endl;
|
||||
std::cerr << " min:" << std::endl;
|
||||
PrintStats(mins, triangles.size());
|
||||
std::cerr << " max:" << std::endl;
|
||||
PrintStats(maxs, triangles.size());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ARGS.mirror)
|
||||
model.Mirror();
|
||||
|
||||
if (ARGS.outputFormat == "old")
|
||||
{
|
||||
ok = model.WriteModel(ARGS.outputFile);
|
||||
}
|
||||
else if (ARGS.outputFormat == "new_bin")
|
||||
{
|
||||
ok = model.WriteBinaryModel(ARGS.outputFile);
|
||||
}
|
||||
else if (ARGS.outputFormat == "new_txt")
|
||||
{
|
||||
ok = model.WriteTextModel(ARGS.outputFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Invalid output format" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
std::cerr << "Writing output model failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue