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
|
# CBot shared library is built separately
|
||||||
add_subdirectory(CBot)
|
add_subdirectory(CBot)
|
||||||
|
|
||||||
|
# Tools directory is built separately
|
||||||
|
add_subdirectory(tools)
|
||||||
|
|
||||||
|
|
||||||
# Configure options
|
# Configure options
|
||||||
|
|
|
@ -113,6 +113,7 @@ CApplication::~CApplication()
|
||||||
bool CApplication::ParseArguments(int argc, char *argv[])
|
bool CApplication::ParseArguments(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
bool waitDataDir = false;
|
bool waitDataDir = false;
|
||||||
|
bool waitLogLevel = false;
|
||||||
|
|
||||||
for (int i = 1; i < argc; ++i)
|
for (int i = 1; i < argc; ++i)
|
||||||
{
|
{
|
||||||
|
@ -125,10 +126,34 @@ bool CApplication::ParseArguments(int argc, char *argv[])
|
||||||
continue;
|
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")
|
if (arg == "-debug")
|
||||||
{
|
{
|
||||||
SetDebugMode(true);
|
SetDebugMode(true);
|
||||||
}
|
}
|
||||||
|
else if (arg == "-loglevel")
|
||||||
|
{
|
||||||
|
waitLogLevel = true;
|
||||||
|
}
|
||||||
else if (arg == "-datadir")
|
else if (arg == "-datadir")
|
||||||
{
|
{
|
||||||
waitDataDir = true;
|
waitDataDir = true;
|
||||||
|
@ -140,8 +165,8 @@ bool CApplication::ParseArguments(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Data dir not given?
|
// Args not given?
|
||||||
if (waitDataDir)
|
if (waitDataDir || waitLogLevel)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -27,9 +27,10 @@ namespace IOUtils {
|
||||||
|
|
||||||
//! Writes a binary number to output stream
|
//! Writes a binary number to output stream
|
||||||
/**
|
/**
|
||||||
\c T is a numeric type (int, unsigned int, etc.)
|
* \c T is a numeric type (int, unsigned int, etc.)
|
||||||
\c N is number of bytes
|
* \c N is number of bytes
|
||||||
Write order is little-endian */
|
* Write order is little-endian
|
||||||
|
*/
|
||||||
template<int N, typename T>
|
template<int N, typename T>
|
||||||
void WriteBinary(T value, std::ostream &ostr)
|
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
|
//! Reads a binary number from input stream
|
||||||
/**
|
/**
|
||||||
\c T is a numeric type (int, unsigned int, etc.)
|
* \c T is a numeric type (int, unsigned int, etc.)
|
||||||
\c N is number of bytes
|
* \c N is number of bytes
|
||||||
Read order is little-endian */
|
* Read order is little-endian
|
||||||
|
*/
|
||||||
template<int N, typename T>
|
template<int N, typename T>
|
||||||
T ReadBinary(std::istream &istr)
|
T ReadBinary(std::istream &istr)
|
||||||
{
|
{
|
||||||
|
@ -58,10 +60,31 @@ T ReadBinary(std::istream &istr)
|
||||||
return value;
|
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
|
//! Writes a binary 32-bit float to output stream
|
||||||
/**
|
/**
|
||||||
Write order is little-endian
|
* Write order is little-endian
|
||||||
NOTE: code is probably not portable as there are platforms with other float representations. */
|
* NOTE: code is probably not portable as there are platforms with other float representations.
|
||||||
|
*/
|
||||||
void WriteBinaryFloat(float value, std::ostream &ostr)
|
void WriteBinaryFloat(float value, std::ostream &ostr)
|
||||||
{
|
{
|
||||||
union { float fValue; unsigned int iValue; } u;
|
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
|
//! Reads a binary 32-bit float from input stream
|
||||||
/**
|
/**
|
||||||
Read order is little-endian
|
* Read order is little-endian
|
||||||
NOTE: code is probably not portable as there are platforms with other float representations. */
|
* NOTE: code is probably not portable as there are platforms with other float representations.
|
||||||
|
*/
|
||||||
float ReadBinaryFloat(std::istream &istr)
|
float ReadBinaryFloat(std::istream &istr)
|
||||||
{
|
{
|
||||||
union { float fValue; unsigned int iValue; } u;
|
union { float fValue; unsigned int iValue; } u;
|
||||||
|
@ -82,4 +106,40 @@ float ReadBinaryFloat(std::istream &istr)
|
||||||
return u.fValue;
|
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
|
}; // namespace IOUtils
|
||||||
|
|
|
@ -29,26 +29,26 @@ template<typename T> class CSingleton
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static T& GetInstance() {
|
static T& GetInstance() {
|
||||||
assert(mInstance != NULL);
|
assert(mInstance != nullptr);
|
||||||
return *mInstance;
|
return *mInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static T* GetInstancePointer() {
|
static T* GetInstancePointer() {
|
||||||
assert(mInstance != NULL);
|
assert(mInstance != nullptr);
|
||||||
return mInstance;
|
return mInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsCreated() {
|
static bool IsCreated() {
|
||||||
return mInstance != NULL;
|
return mInstance != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSingleton() {
|
CSingleton() {
|
||||||
assert(mInstance == NULL);
|
assert(mInstance == nullptr);
|
||||||
mInstance = static_cast<T *>(this);
|
mInstance = static_cast<T *>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~CSingleton() {
|
virtual ~CSingleton() {
|
||||||
mInstance = NULL;
|
mInstance = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,7 +20,6 @@
|
||||||
* \brief Model loading - Gfx::CModelFile class (aka modfile)
|
* \brief Model loading - Gfx::CModelFile class (aka modfile)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "graphics/engine/engine.h"
|
|
||||||
#include "graphics/core/vertex.h"
|
#include "graphics/core/vertex.h"
|
||||||
#include "graphics/core/material.h"
|
#include "graphics/core/material.h"
|
||||||
#include "math/vector.h"
|
#include "math/vector.h"
|
||||||
|
@ -35,6 +34,9 @@ class CInstanceManager;
|
||||||
|
|
||||||
namespace Gfx {
|
namespace Gfx {
|
||||||
|
|
||||||
|
class CEngine;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\struct ModelTriangle
|
\struct ModelTriangle
|
||||||
\brief Triangle of a 3D model
|
\brief Triangle of a 3D model
|
||||||
|
@ -53,14 +55,21 @@ struct ModelTriangle
|
||||||
std::string tex1Name;
|
std::string tex1Name;
|
||||||
//! Name of 2nd texture
|
//! Name of 2nd texture
|
||||||
std::string tex2Name;
|
std::string tex2Name;
|
||||||
|
//! If true, 2nd texture will be taken from current engine setting
|
||||||
|
bool variableTex2;
|
||||||
//! Min LOD threshold
|
//! Min LOD threshold
|
||||||
float min;
|
float min;
|
||||||
//! Max LOD threshold
|
//! Max LOD threshold
|
||||||
float max;
|
float max;
|
||||||
//! Rendering state to be set
|
//! 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(CInstanceManager* iMan);
|
||||||
~CModelFile();
|
~CModelFile();
|
||||||
|
|
||||||
//! Returns the last error encountered
|
//! Reads a model in text format from file
|
||||||
std::string GetError();
|
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
|
//! 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
|
//! 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
|
//! 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
|
//! Writes the model to Colobot binary model file
|
||||||
|
//! @deprecated
|
||||||
bool WriteModel(std::ostream &stream);
|
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
|
//! Returns the number of triangles in model
|
||||||
int GetTriangleCount();
|
int GetTriangleCount();
|
||||||
|
|
||||||
//! Returns the triangle vector
|
//! 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
|
//! Returns the height of model -- closest point to X and Z coords of \a pos
|
||||||
float GetHeight(Math::Vector pos);
|
float GetHeight(Math::Vector pos);
|
||||||
|
|
||||||
|
@ -103,7 +130,7 @@ public:
|
||||||
void Mirror();
|
void Mirror();
|
||||||
|
|
||||||
//! Creates an object in the graphics engine from the model
|
//! Creates an object in the graphics engine from the model
|
||||||
bool CreateEngineObject(int objRank, int addState = 0);
|
bool CreateEngineObject(int objRank);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Adds a triangle to the list
|
//! Adds a triangle to the list
|
||||||
|
@ -113,9 +140,6 @@ protected:
|
||||||
CInstanceManager* m_iMan;
|
CInstanceManager* m_iMan;
|
||||||
Gfx::CEngine* m_engine;
|
Gfx::CEngine* m_engine;
|
||||||
|
|
||||||
//! Last error
|
|
||||||
std::string m_error;
|
|
||||||
|
|
||||||
//! Model triangles
|
//! Model triangles
|
||||||
std::vector<Gfx::ModelTriangle> m_triangles;
|
std::vector<Gfx::ModelTriangle> m_triangles;
|
||||||
};
|
};
|
||||||
|
|
|
@ -180,7 +180,7 @@ void Gfx::CTerrain::LevelFlush()
|
||||||
LevelCloseTable();
|
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,
|
int up, int right, int down, int left,
|
||||||
float hardness)
|
float hardness)
|
||||||
{
|
{
|
||||||
|
|
|
@ -157,7 +157,7 @@ public:
|
||||||
//! Empties level
|
//! Empties level
|
||||||
void LevelFlush();
|
void LevelFlush();
|
||||||
//! Initializes the names of textures to use for the land
|
//! 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
|
//! Initializes all the ground with a material
|
||||||
bool LevelInit(int id);
|
bool LevelInit(int id);
|
||||||
//! Generates a level in the terrain
|
//! 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