Rewritten model loading
- written new implementation of CModelFile (old CModFile) - added stringutils and ioutils in src/common - removed old CModel (model viewer)dev-ui
parent
3204360515
commit
2383a42347
|
@ -38,6 +38,7 @@ common/iman.cpp
|
|||
# common/modfile.cpp
|
||||
# common/profile.cpp
|
||||
# common/restext.cpp
|
||||
common/stringutils.cpp
|
||||
graphics/common/camera.cpp
|
||||
graphics/common/cloud.cpp
|
||||
graphics/common/color.cpp
|
||||
|
@ -45,8 +46,7 @@ graphics/common/device.cpp
|
|||
graphics/common/engine.cpp
|
||||
graphics/common/light.cpp
|
||||
graphics/common/lightning.cpp
|
||||
graphics/common/model.cpp
|
||||
graphics/common/modfile.cpp
|
||||
graphics/common/modelfile.cpp
|
||||
graphics/common/particle.cpp
|
||||
graphics/common/planet.cpp
|
||||
graphics/common/pyro.cpp
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
// * This file is part of the COLOBOT source code
|
||||
// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
// ioutils.h
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
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 */
|
||||
template<int N, typename T>
|
||||
void WriteBinary(T value, std::ostream &ostr)
|
||||
{
|
||||
for (int i = 0; i < N; ++i)
|
||||
{
|
||||
unsigned char byte = (value >> (i*8)) & 0xFF;
|
||||
ostr.write((char*)&byte, 1);
|
||||
}
|
||||
}
|
||||
|
||||
//! 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 */
|
||||
template<int N, typename T>
|
||||
T ReadBinary(std::istream &istr)
|
||||
{
|
||||
T value = 0;
|
||||
for (int i = 0; i < N; ++i)
|
||||
{
|
||||
unsigned char byte = 0;
|
||||
istr.read((char*)&byte, 1);
|
||||
value |= byte << (i*8);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
//! 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. */
|
||||
void WriteBinaryFloat(float value, std::ostream &ostr)
|
||||
{
|
||||
unsigned int iValue = *( (unsigned int*)( (void*)(&value) ) );
|
||||
IOUtils::WriteBinary<4, unsigned int>(iValue, 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. */
|
||||
float ReadBinaryFloat(std::istream &istr)
|
||||
{
|
||||
unsigned int iValue = IOUtils::ReadBinary<4, unsigned int>(istr);
|
||||
float result = *( (float*)( (void*)(&iValue) ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
}; // namespace IOUtils
|
|
@ -0,0 +1,149 @@
|
|||
// * This file is part of the COLOBOT source code
|
||||
// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
// stringutils.cpp
|
||||
|
||||
#include "stringutils.h"
|
||||
|
||||
|
||||
std::string StrUtils::Replace(const std::string &str, const std::string &oldStr, const std::string &newStr)
|
||||
{
|
||||
std::string result = str;
|
||||
size_t pos = 0;
|
||||
while ((pos = str.find(oldStr, pos)) != std::string::npos)
|
||||
{
|
||||
result.replace(pos, oldStr.length(), newStr);
|
||||
pos += newStr.length();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string StrUtils::UnicodeCharToUtf8(unsigned int ch)
|
||||
{
|
||||
std::string result;
|
||||
if (ch < 0x0080)
|
||||
{
|
||||
result += (char)(ch);
|
||||
}
|
||||
else if (ch < 0x0800)
|
||||
{
|
||||
char ch1 = 0xC0 | ((ch & 0x07C0) >> 6);
|
||||
char ch2 = 0x80 | (ch & 0x3F);
|
||||
result += ch1;
|
||||
result += ch2;
|
||||
}
|
||||
else
|
||||
{
|
||||
char ch1 = 0xE0 | ((ch & 0xF000) >> 12);
|
||||
char ch2 = 0x80 | ((ch & 0x07C0) >> 6);
|
||||
char ch3 = 0x80 | (ch & 0x3F);
|
||||
result += ch1;
|
||||
result += ch2;
|
||||
result += ch3;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string StrUtils::UnicodeStringToUtf8(const std::wstring &str)
|
||||
{
|
||||
std::string result;
|
||||
for (unsigned int i = 0; i < str.size(); ++i)
|
||||
result += StrUtils::UnicodeCharToUtf8((unsigned int)str[i]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int StrUtils::Utf8CharToUnicode(const std::string &ch)
|
||||
{
|
||||
if (ch.empty())
|
||||
return 0;
|
||||
|
||||
unsigned int result = 0;
|
||||
if ((ch[0] & 0x80) == 0)
|
||||
{
|
||||
if (ch.size() == 1)
|
||||
result = (unsigned int)ch[0];
|
||||
}
|
||||
else if ((ch[0] & 0xC0) == 0xC0)
|
||||
{
|
||||
if (ch.size() == 2)
|
||||
{
|
||||
unsigned int ch1 = (ch[0] & 0x1F) << 6;
|
||||
unsigned int ch2 = (ch[1] & 0x3F);
|
||||
result = ch1 | ch2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ch.size() == 3)
|
||||
{
|
||||
unsigned int ch1 = (ch[0] & 0xF0) << 12;
|
||||
unsigned int ch2 = (ch[1] & 0xC0) << 6;
|
||||
unsigned int ch3 = (ch[2] & 0xC0);
|
||||
result = ch1 | ch2 | ch3;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::wstring StrUtils::Utf8StringToUnicode(const std::string &str)
|
||||
{
|
||||
std::wstring result;
|
||||
unsigned int pos = 0;
|
||||
while (pos < str.size())
|
||||
{
|
||||
int len = StrUtils::Utf8CharSizeAt(str, pos);
|
||||
if (len == 0)
|
||||
break;
|
||||
|
||||
std::string ch = str.substr(pos, len);
|
||||
result += (wchar_t)(StrUtils::Utf8CharToUnicode(ch));
|
||||
pos += len;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int StrUtils::Utf8CharSizeAt(const std::string &str, unsigned int pos)
|
||||
{
|
||||
if (pos >= str.size())
|
||||
return 0;
|
||||
|
||||
if ((str[pos] & 0x80) == 0)
|
||||
return 1;
|
||||
else if ((str[pos] & 0xC0) == 0xC0)
|
||||
return 2;
|
||||
else
|
||||
return 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t StrUtils::Utf8StringLength(const std::string &str)
|
||||
{
|
||||
size_t result = 0;
|
||||
for (unsigned int i = 0; i < str.size(); ++i)
|
||||
{
|
||||
char ch = str[i];
|
||||
if ((ch & 0x80) == 0)
|
||||
++result;
|
||||
else if ((ch & 0xC0) == 0xC0)
|
||||
result += 2;
|
||||
else
|
||||
result += 3;
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
// * This file is part of the COLOBOT source code
|
||||
// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
// stringutils.h
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
namespace StrUtils {
|
||||
|
||||
//! Converts a value to string
|
||||
/** If given, \a ok is set to true/false on success/failure.
|
||||
Warning: To avoid unnecessary problems, *always* give full template qualifier e.g. ToString\<int\> */
|
||||
template<class T>
|
||||
std::string ToString(T value, bool *ok = NULL)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << value;
|
||||
if (ok != NULL)
|
||||
*ok = !s.fail();
|
||||
return s.str();
|
||||
}
|
||||
|
||||
//! Converts a value to string
|
||||
/** If given, \a ok is set to true/false on success/failure.
|
||||
Warning: To avoid unnecessary problems, *always* give full template qualifier e.g. FromString\<int\> */
|
||||
template<class T>
|
||||
T FromString(const std::string &str, bool *ok = NULL)
|
||||
{
|
||||
std::istringstream s;
|
||||
s.str(str);
|
||||
T value;
|
||||
s >> value;
|
||||
if (ok != NULL)
|
||||
*ok = !s.fail();
|
||||
return value;
|
||||
}
|
||||
|
||||
//! Returns a string with every occurence of \a oldStr in \a str replaced to \a newStr
|
||||
std::string Replace(const std::string &str, const std::string &oldStr, const std::string &newStr);
|
||||
|
||||
|
||||
//! Converts a wide Unicode char to a single UTF-8 encoded char
|
||||
std::string UnicodeCharToUtf8(unsigned int ch);
|
||||
|
||||
//! Converts a wide Unicode string to a UTF-8 encoded string
|
||||
std::string UnicodeStringToUtf8(const std::wstring &str);
|
||||
|
||||
//! Converts a UTF-8 encoded single character to wide Unicode char
|
||||
unsigned int Utf8CharToUnicode(const std::string &ch);
|
||||
|
||||
//! Converts a UTF-8 encoded string to wide Unicode string
|
||||
std::wstring Utf8StringToUnicode(const std::string &str);
|
||||
|
||||
//! Returns the size in bytes of UTF-8 character at given \a pos in a UTF-8 \a str
|
||||
int Utf8CharSizeAt(const std::string &str, unsigned int pos);
|
||||
|
||||
//! Returns the length in characters of UTF-8 string \a str
|
||||
size_t Utf8StringLength(const std::string &str);
|
||||
|
||||
}; // namespace StrUtil
|
|
@ -1,23 +0,0 @@
|
|||
// * This file is part of the COLOBOT source code
|
||||
// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
|
||||
// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
// model.cpp
|
||||
|
||||
#include "graphics/common/model.h"
|
||||
|
||||
|
||||
// TODO implementation
|
|
@ -1,141 +0,0 @@
|
|||
// * This file is part of the COLOBOT source code
|
||||
// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
|
||||
// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
// model.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "engine.h"
|
||||
#include "common/event.h"
|
||||
#include "modfile.h"
|
||||
#include "vertex.h"
|
||||
#include "math/point.h"
|
||||
|
||||
|
||||
class CInstanceManager;
|
||||
class CModFile;
|
||||
class CInterface;
|
||||
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
class CEngine;
|
||||
|
||||
|
||||
class CModel {
|
||||
public:
|
||||
CModel(CInstanceManager* iMan);
|
||||
~CModel();
|
||||
|
||||
void StartUserAction();
|
||||
void StopUserAction();
|
||||
|
||||
bool EventProcess(const Event &event);
|
||||
|
||||
void InitView();
|
||||
void InitViewFromSelect();
|
||||
void UpdateView();
|
||||
void ViewMove(const Event &event, float speed);
|
||||
|
||||
protected:
|
||||
bool EventFrame(const Event &event);
|
||||
bool GetVertex(int rank, Gfx::VertexTex2 &vertex);
|
||||
bool SetVertex(int rank, Gfx::VertexTex2 &vertex);
|
||||
Math::Vector RetSelectCDG();
|
||||
Math::Vector RetSelectNormal();
|
||||
void SmoothSelect();
|
||||
void PlaneSelect();
|
||||
void ColorSelect();
|
||||
void StateSelect();
|
||||
void MoveSelect(Math::Vector move);
|
||||
void OperSelect(Math::Vector move, char oper);
|
||||
void ReadScript(char *filename);
|
||||
void BBoxCompute(Math::Vector &min, Math::Vector &max);
|
||||
bool IsMappingSelectPlausible(Gfx::Mapping D3Dmode);
|
||||
void MappingSelect(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
|
||||
void MappingSelectSpherical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
|
||||
Math::Vector RetMappingCenter(Math::Vector pos, Math::Vector min);
|
||||
void MappingSelectCylindrical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
|
||||
void MappingSelectFace(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
|
||||
void MappingSelect2(int texNum2, int subdiv, int offsetU, int offsetV, bool bMirrorX, bool bMirrorY);
|
||||
void MappingSelectPlane2(int mode, bool bMirrorX, bool bMirrorY);
|
||||
void MappingSelectSpherical2(bool bMirrorX, bool bMirrorY);
|
||||
void MappingSelectMagic2(bool bMirrorX, bool bMirrorY);
|
||||
int SearchNext(int rank, int step);
|
||||
int SearchSamePlane(int first, int step);
|
||||
void CurrentSearchNext(int step, bool bControl);
|
||||
void CurrentInit();
|
||||
void CurrentSelect(bool bSelect);
|
||||
void DeselectAll();
|
||||
void SelectAll();
|
||||
void SelectZone(int first, int last);
|
||||
void SelectTerm();
|
||||
void DefaultSelect();
|
||||
void SelectDelete();
|
||||
void Compress();
|
||||
void MinMaxSelect();
|
||||
void MinMaxChange();
|
||||
void UpdateInfoText();
|
||||
int* RetTextureTable();
|
||||
void TexturePartUpdate();
|
||||
void TextureRankChange(int step);
|
||||
void TexturePartChange(int step);
|
||||
void PutTextureValues();
|
||||
void GetTextureValues();
|
||||
void GetModelName(char *buffer);
|
||||
void GetDXFName(char *buffer);
|
||||
void GetScriptName(char *buffer);
|
||||
bool IsEditFocus();
|
||||
|
||||
protected:
|
||||
CInstanceManager* m_iMan;
|
||||
Gfx::CEngine* m_engine;
|
||||
CModFile* m_modFile;
|
||||
CInterface* m_interface;
|
||||
|
||||
float m_time;
|
||||
ModelTriangle* m_triangleTable;
|
||||
int m_triangleSel1;
|
||||
int m_triangleSel2;
|
||||
int m_mode;
|
||||
int m_textureMode;
|
||||
int m_textureRotate;
|
||||
bool m_bTextureMirrorX;
|
||||
bool m_bTextureMirrorY;
|
||||
Math::Point m_textureInf;
|
||||
Math::Point m_textureSup;
|
||||
int m_texturePart;
|
||||
int m_textureRank;
|
||||
char m_textureName[20];
|
||||
bool m_bDisplayTransparent;
|
||||
bool m_bDisplayOnlySelection;
|
||||
float m_viewHeight;
|
||||
float m_viewDist;
|
||||
float m_viewAngleH;
|
||||
float m_viewAngleV;
|
||||
int m_color;
|
||||
int m_state;
|
||||
int m_secondTexNum;
|
||||
int m_secondSubdiv;
|
||||
int m_secondOffsetU;
|
||||
int m_secondOffsetV;
|
||||
char m_oper;
|
||||
float m_min;
|
||||
float m_max;
|
||||
};
|
||||
|
||||
}; // namespace Gfx
|
|
@ -0,0 +1,815 @@
|
|||
// * This file is part of the COLOBOT source code
|
||||
// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
|
||||
// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
// modelfile.cpp (aka modfile.cpp)
|
||||
|
||||
#include "graphics/common/modelfile.h"
|
||||
|
||||
#include "common/iman.h"
|
||||
#include "common/ioutils.h"
|
||||
#include "common/stringutils.h"
|
||||
#include "math/geometry.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
|
||||
//! How big the triangle vector is by default
|
||||
const int TRIANGLE_PREALLOCATE_COUNT = 2000;
|
||||
|
||||
/**
|
||||
\struct ModelHeader
|
||||
\brief Header info for model file
|
||||
*/
|
||||
struct ModelHeader
|
||||
{
|
||||
//! Revision number
|
||||
int revision;
|
||||
//! Version number
|
||||
int version;
|
||||
//! Total number of vertices
|
||||
int totalVertices;
|
||||
//! Reserved area
|
||||
int reserved[10];
|
||||
|
||||
ModelHeader()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct OldModelTriangle1
|
||||
{
|
||||
char used;
|
||||
char selected;
|
||||
Gfx::Vertex p1;
|
||||
Gfx::Vertex p2;
|
||||
Gfx::Vertex p3;
|
||||
Gfx::Material material;
|
||||
char texName[20];
|
||||
float min;
|
||||
float max;
|
||||
|
||||
OldModelTriangle1()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
};
|
||||
|
||||
struct OldModelTriangle2
|
||||
{
|
||||
char used;
|
||||
char selected;
|
||||
Gfx::Vertex p1;
|
||||
Gfx::Vertex p2;
|
||||
Gfx::Vertex p3;
|
||||
Gfx::Material material;
|
||||
char texName[20];
|
||||
float min;
|
||||
float max;
|
||||
long state;
|
||||
short reserved1;
|
||||
short reserved2;
|
||||
short reserved3;
|
||||
short reserved4;
|
||||
OldModelTriangle2()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct NewModelTriangle
|
||||
{
|
||||
char used;
|
||||
char selected;
|
||||
Gfx::VertexTex2 p1;
|
||||
Gfx::VertexTex2 p2;
|
||||
Gfx::VertexTex2 p3;
|
||||
Gfx::Material material;
|
||||
char texName[20];
|
||||
float min;
|
||||
float max;
|
||||
long state;
|
||||
short texNum2;
|
||||
short reserved2;
|
||||
short reserved3;
|
||||
short reserved4;
|
||||
|
||||
NewModelTriangle()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Gfx::Vertex ReadBinaryVertex(std::istream &stream)
|
||||
{
|
||||
Gfx::Vertex result;
|
||||
|
||||
result.coord.x = IOUtils::ReadBinaryFloat(stream);
|
||||
result.coord.y = IOUtils::ReadBinaryFloat(stream);
|
||||
result.coord.z = IOUtils::ReadBinaryFloat(stream);
|
||||
result.normal.x = IOUtils::ReadBinaryFloat(stream);
|
||||
result.normal.y = IOUtils::ReadBinaryFloat(stream);
|
||||
result.normal.z = IOUtils::ReadBinaryFloat(stream);
|
||||
result.texCoord.x = IOUtils::ReadBinaryFloat(stream);
|
||||
result.texCoord.y = IOUtils::ReadBinaryFloat(stream);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void WriteBinaryVertex(Gfx::Vertex vertex, std::ostream &stream)
|
||||
{
|
||||
IOUtils::WriteBinaryFloat(vertex.coord.x, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.coord.y, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.coord.z, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.normal.x, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.normal.y, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.normal.z, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.texCoord.x, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.texCoord.y, stream);
|
||||
}
|
||||
|
||||
Gfx::VertexTex2 ReadBinaryVertexTex2(std::istream &stream)
|
||||
{
|
||||
Gfx::VertexTex2 result;
|
||||
|
||||
result.coord.x = IOUtils::ReadBinaryFloat(stream);
|
||||
result.coord.y = IOUtils::ReadBinaryFloat(stream);
|
||||
result.coord.z = IOUtils::ReadBinaryFloat(stream);
|
||||
result.normal.x = IOUtils::ReadBinaryFloat(stream);
|
||||
result.normal.y = IOUtils::ReadBinaryFloat(stream);
|
||||
result.normal.z = IOUtils::ReadBinaryFloat(stream);
|
||||
result.texCoord.x = IOUtils::ReadBinaryFloat(stream);
|
||||
result.texCoord.y = IOUtils::ReadBinaryFloat(stream);
|
||||
result.texCoord2.x = IOUtils::ReadBinaryFloat(stream);
|
||||
result.texCoord2.y = IOUtils::ReadBinaryFloat(stream);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void WriteBinaryVertexTex2(Gfx::VertexTex2 vertex, std::ostream &stream)
|
||||
{
|
||||
IOUtils::WriteBinaryFloat(vertex.coord.x, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.coord.y, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.coord.z, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.normal.x, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.normal.y, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.normal.z, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.texCoord.x, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.texCoord.y, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.texCoord2.x, stream);
|
||||
IOUtils::WriteBinaryFloat(vertex.texCoord2.y, stream);
|
||||
}
|
||||
|
||||
Gfx::Material ReadBinaryMaterial(std::istream &stream)
|
||||
{
|
||||
Gfx::Material result;
|
||||
|
||||
result.diffuse.r = IOUtils::ReadBinaryFloat(stream);
|
||||
result.diffuse.g = IOUtils::ReadBinaryFloat(stream);
|
||||
result.diffuse.b = IOUtils::ReadBinaryFloat(stream);
|
||||
result.diffuse.a = IOUtils::ReadBinaryFloat(stream);
|
||||
|
||||
result.ambient.r = IOUtils::ReadBinaryFloat(stream);
|
||||
result.ambient.g = IOUtils::ReadBinaryFloat(stream);
|
||||
result.ambient.b = IOUtils::ReadBinaryFloat(stream);
|
||||
result.ambient.a = IOUtils::ReadBinaryFloat(stream);
|
||||
|
||||
result.specular.r = IOUtils::ReadBinaryFloat(stream);
|
||||
result.specular.g = IOUtils::ReadBinaryFloat(stream);
|
||||
result.specular.b = IOUtils::ReadBinaryFloat(stream);
|
||||
result.specular.a = IOUtils::ReadBinaryFloat(stream);
|
||||
|
||||
/* emissive.r = */ IOUtils::ReadBinaryFloat(stream);
|
||||
/* emissive.g = */ IOUtils::ReadBinaryFloat(stream);
|
||||
/* emissive.b = */ IOUtils::ReadBinaryFloat(stream);
|
||||
/* emissive.a = */ IOUtils::ReadBinaryFloat(stream);
|
||||
|
||||
/* power = */ IOUtils::ReadBinaryFloat(stream);
|
||||
|
||||
/* padding? */ IOUtils::ReadBinary<2, unsigned int>(stream);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void WriteBinaryMaterial(Gfx::Material material, std::ostream &stream)
|
||||
{
|
||||
IOUtils::WriteBinaryFloat(material.diffuse.r, stream);
|
||||
IOUtils::WriteBinaryFloat(material.diffuse.g, stream);
|
||||
IOUtils::WriteBinaryFloat(material.diffuse.b, stream);
|
||||
IOUtils::WriteBinaryFloat(material.diffuse.a, stream);
|
||||
|
||||
IOUtils::WriteBinaryFloat(material.ambient.r, stream);
|
||||
IOUtils::WriteBinaryFloat(material.ambient.g, stream);
|
||||
IOUtils::WriteBinaryFloat(material.ambient.b, stream);
|
||||
IOUtils::WriteBinaryFloat(material.ambient.a, stream);
|
||||
|
||||
IOUtils::WriteBinaryFloat(material.specular.r, stream);
|
||||
IOUtils::WriteBinaryFloat(material.specular.g, stream);
|
||||
IOUtils::WriteBinaryFloat(material.specular.b, stream);
|
||||
IOUtils::WriteBinaryFloat(material.specular.a, stream);
|
||||
|
||||
/* emissive.r */ IOUtils::WriteBinaryFloat(0.0f, stream);
|
||||
/* emissive.g */ IOUtils::WriteBinaryFloat(0.0f, stream);
|
||||
/* emissive.b */ IOUtils::WriteBinaryFloat(0.0f, stream);
|
||||
/* emissive.a */ IOUtils::WriteBinaryFloat(0.0f, stream);
|
||||
|
||||
/* power */ IOUtils::WriteBinaryFloat(0.0f, stream);
|
||||
|
||||
/* padding? */ IOUtils::WriteBinary<2, unsigned int>(0, stream);
|
||||
}
|
||||
|
||||
Gfx::ModelTriangle::ModelTriangle()
|
||||
{
|
||||
min = 0.0f;
|
||||
max = 0.0f;
|
||||
state = 0L;
|
||||
}
|
||||
|
||||
|
||||
Gfx::CModelFile::CModelFile(CInstanceManager* iMan)
|
||||
{
|
||||
m_iMan = iMan;
|
||||
|
||||
m_engine = (CEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
|
||||
|
||||
m_triangles.reserve(TRIANGLE_PREALLOCATE_COUNT);
|
||||
}
|
||||
|
||||
Gfx::CModelFile::~CModelFile()
|
||||
{
|
||||
}
|
||||
|
||||
std::string Gfx::CModelFile::GetError()
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
|
||||
bool Gfx::CModelFile::ReadModel(const std::string &filename, bool edit, bool meta)
|
||||
{
|
||||
m_triangles.clear();
|
||||
m_error = "";
|
||||
|
||||
std::ifstream stream;
|
||||
stream.open(filename.c_str(), std::ios_base::in | std::ios_base::binary);
|
||||
if (! stream.good())
|
||||
{
|
||||
m_error = std::string("Could not open file '") + filename + std::string("'");
|
||||
return false;
|
||||
}
|
||||
|
||||
return ReadModel(stream, edit, meta);
|
||||
}
|
||||
|
||||
bool Gfx::CModelFile::ReadModel(std::istream &stream, bool edit, bool meta)
|
||||
{
|
||||
m_triangles.clear();
|
||||
m_error = "";
|
||||
|
||||
// FIXME: for now, reading models only from files, not metafile
|
||||
|
||||
ModelHeader header;
|
||||
|
||||
header.revision = IOUtils::ReadBinary<4, int>(stream);
|
||||
header.version = IOUtils::ReadBinary<4, int>(stream);
|
||||
header.totalVertices = IOUtils::ReadBinary<4, int>(stream);
|
||||
for (int i = 0; i < 10; ++i)
|
||||
header.reserved[i] = IOUtils::ReadBinary<4, int>(stream);
|
||||
|
||||
|
||||
if (! stream.good())
|
||||
{
|
||||
m_error = "Error reading model file header";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Old model version #1
|
||||
if ( (header.revision == 1) && (header.version == 0) )
|
||||
{
|
||||
for (int i = 0; i < header.totalVertices; ++i)
|
||||
{
|
||||
OldModelTriangle1 t;
|
||||
t.used = IOUtils::ReadBinary<1, char>(stream);
|
||||
t.selected = IOUtils::ReadBinary<1, char>(stream);
|
||||
|
||||
t.p1 = ReadBinaryVertex(stream);
|
||||
t.p2 = ReadBinaryVertex(stream);
|
||||
t.p3 = ReadBinaryVertex(stream);
|
||||
|
||||
t.material = ReadBinaryMaterial(stream);
|
||||
stream.read(t.texName, 20);
|
||||
t.min = IOUtils::ReadBinaryFloat(stream);
|
||||
t.max = IOUtils::ReadBinaryFloat(stream);
|
||||
|
||||
if (! stream.good())
|
||||
{
|
||||
m_error = "Error reading model data";
|
||||
return false;
|
||||
}
|
||||
|
||||
Gfx::ModelTriangle triangle;
|
||||
triangle.p1.FromVertex(t.p1);
|
||||
triangle.p2.FromVertex(t.p2);
|
||||
triangle.p3.FromVertex(t.p3);
|
||||
|
||||
triangle.material = t.material;
|
||||
triangle.tex1Name = std::string(t.texName);
|
||||
triangle.min = t.min;
|
||||
triangle.max = t.max;
|
||||
|
||||
m_triangles.push_back(triangle);
|
||||
}
|
||||
}
|
||||
else if ( header.revision == 1 && header.version == 1 )
|
||||
{
|
||||
for (int i = 0; i < header.totalVertices; ++i)
|
||||
{
|
||||
OldModelTriangle2 t;
|
||||
t.used = IOUtils::ReadBinary<1, char>(stream);
|
||||
t.selected = IOUtils::ReadBinary<1, char>(stream);
|
||||
|
||||
t.p1 = ReadBinaryVertex(stream);
|
||||
t.p2 = ReadBinaryVertex(stream);
|
||||
t.p3 = ReadBinaryVertex(stream);
|
||||
|
||||
t.material = ReadBinaryMaterial(stream);
|
||||
stream.read(t.texName, 20);
|
||||
t.min = IOUtils::ReadBinaryFloat(stream);
|
||||
t.max = IOUtils::ReadBinaryFloat(stream);
|
||||
t.state = IOUtils::ReadBinary<4, long>(stream);
|
||||
|
||||
t.reserved1 = IOUtils::ReadBinary<2, short>(stream);
|
||||
t.reserved2 = IOUtils::ReadBinary<2, short>(stream);
|
||||
t.reserved3 = IOUtils::ReadBinary<2, short>(stream);
|
||||
t.reserved4 = IOUtils::ReadBinary<2, short>(stream);
|
||||
|
||||
if (! stream.good())
|
||||
{
|
||||
m_error = "Error reading model data";
|
||||
return false;
|
||||
}
|
||||
|
||||
Gfx::ModelTriangle triangle;
|
||||
triangle.p1.FromVertex(t.p1);
|
||||
triangle.p2.FromVertex(t.p2);
|
||||
triangle.p3.FromVertex(t.p3);
|
||||
|
||||
triangle.material = t.material;
|
||||
triangle.tex1Name = std::string(t.texName);
|
||||
triangle.min = t.min;
|
||||
triangle.max = t.max;
|
||||
triangle.state = t.state;
|
||||
|
||||
m_triangles.push_back(triangle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < header.totalVertices; ++i)
|
||||
{
|
||||
NewModelTriangle t;
|
||||
t.used = IOUtils::ReadBinary<1, char>(stream);
|
||||
t.selected = IOUtils::ReadBinary<1, char>(stream);
|
||||
|
||||
t.p1 = ReadBinaryVertexTex2(stream);
|
||||
t.p2 = ReadBinaryVertexTex2(stream);
|
||||
t.p3 = ReadBinaryVertexTex2(stream);
|
||||
|
||||
t.material = ReadBinaryMaterial(stream);
|
||||
stream.read(t.texName, 20);
|
||||
t.min = IOUtils::ReadBinaryFloat(stream);
|
||||
t.max = IOUtils::ReadBinaryFloat(stream);
|
||||
t.state = IOUtils::ReadBinary<4, long>(stream);
|
||||
t.texNum2 = IOUtils::ReadBinary<2, short>(stream);
|
||||
|
||||
t.reserved2 = IOUtils::ReadBinary<2, short>(stream);
|
||||
t.reserved3 = IOUtils::ReadBinary<2, short>(stream);
|
||||
t.reserved4 = IOUtils::ReadBinary<2, short>(stream);
|
||||
|
||||
if (! stream.good())
|
||||
{
|
||||
m_error = "Error reading model data";
|
||||
return false;
|
||||
}
|
||||
|
||||
Gfx::ModelTriangle triangle;
|
||||
triangle.p1 = t.p1;
|
||||
triangle.p2 = t.p2;
|
||||
triangle.p3 = t.p3;
|
||||
|
||||
triangle.material = t.material;
|
||||
triangle.tex1Name = std::string(t.texName);
|
||||
char tex2Name[20] = { 0 };
|
||||
triangle.min = t.min;
|
||||
triangle.max = t.max;
|
||||
triangle.state = t.state;
|
||||
sprintf(tex2Name, "dirty%.2d.tga", t.texNum2); // hardcoded as in the original code
|
||||
triangle.tex2Name = std::string(tex2Name);
|
||||
|
||||
m_triangles.push_back(triangle);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int) m_triangles.size(); ++i)
|
||||
m_triangles[i].tex1Name = StrUtils::Replace(m_triangles[i].tex1Name, "bmp", "tga");
|
||||
|
||||
/*
|
||||
if (! edit)
|
||||
{
|
||||
float limit[2];
|
||||
limit[0] = m_engine->RetLimitLOD(0); // frontier AB as config
|
||||
limit[1] = m_engine->RetLimitLOD(1); // frontier BC as config
|
||||
|
||||
// Standard frontiers -> config.
|
||||
for (int i = 0; i < m_triangles.size(); ++i)
|
||||
{
|
||||
if ( m_triangles[i].min == 0.0f &&
|
||||
m_triangles[i].max == 100.0f ) // resolution A ?
|
||||
{
|
||||
m_triangles[i].max = limit[0];
|
||||
}
|
||||
else if ( m_triangles[i].min == 100.0f &&
|
||||
m_triangles[i].max == 200.0f ) // resolution B ?
|
||||
{
|
||||
m_triangles[i].min = limit[0];
|
||||
m_triangles[i].max = limit[1];
|
||||
}
|
||||
else if ( m_triangles[i].min == 200.0f &&
|
||||
m_triangles[i].max == 1000000.0f ) // resolution C ?
|
||||
{
|
||||
m_triangles[i].min = limit[1];
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Gfx::CModelFile::WriteModel(const std::string &filename)
|
||||
{
|
||||
m_error = "";
|
||||
|
||||
std::ofstream stream;
|
||||
stream.open(filename.c_str(), std::ios_base::out | std::ios_base::binary);
|
||||
if (! stream.good())
|
||||
{
|
||||
m_error = std::string("Could not open file '") + filename + std::string("'");
|
||||
return false;
|
||||
}
|
||||
|
||||
return WriteModel(stream);
|
||||
}
|
||||
|
||||
bool Gfx::CModelFile::WriteModel(std::ostream &stream)
|
||||
{
|
||||
m_error = "";
|
||||
|
||||
if (m_triangles.size() == 0)
|
||||
{
|
||||
m_error = "Empty model";
|
||||
return false;
|
||||
}
|
||||
|
||||
ModelHeader header;
|
||||
header.revision = 1;
|
||||
header.version = 2;
|
||||
header.totalVertices = m_triangles.size();
|
||||
|
||||
IOUtils::WriteBinary<4, int>(header.revision, stream);
|
||||
IOUtils::WriteBinary<4, int>(header.version, stream);
|
||||
IOUtils::WriteBinary<4, int>(header.totalVertices, stream);
|
||||
for (int i = 0; i < 10; ++i)
|
||||
IOUtils::WriteBinary<4, int>(header.reserved[i], stream);
|
||||
|
||||
for (int i = 0; i < (int)m_triangles.size(); ++i)
|
||||
{
|
||||
NewModelTriangle t;
|
||||
|
||||
t.used = true;
|
||||
|
||||
t.p1 = m_triangles[i].p1;
|
||||
t.p2 = m_triangles[i].p2;
|
||||
t.p3 = m_triangles[i].p3;
|
||||
|
||||
t.material = m_triangles[i].material;
|
||||
strncpy(t.texName, m_triangles[i].tex1Name.c_str(), 20);
|
||||
t.min = m_triangles[i].min;
|
||||
t.max = m_triangles[i].max;
|
||||
t.state = m_triangles[i].state;
|
||||
int no = 0;
|
||||
sscanf(m_triangles[i].tex2Name.c_str(), "dirty%d.tga", &no); // hardcoded as in the original code
|
||||
t.texNum2 = no;
|
||||
|
||||
|
||||
IOUtils::WriteBinary<1, char>(t.used, stream);
|
||||
IOUtils::WriteBinary<1, char>(t.selected, stream);
|
||||
|
||||
WriteBinaryVertexTex2(t.p1, stream);
|
||||
WriteBinaryVertexTex2(t.p2, stream);
|
||||
WriteBinaryVertexTex2(t.p3, stream);
|
||||
|
||||
WriteBinaryMaterial(t.material, stream);
|
||||
stream.write(t.texName, 20);
|
||||
IOUtils::WriteBinaryFloat(t.min, stream);
|
||||
IOUtils::WriteBinaryFloat(t.max, stream);
|
||||
IOUtils::WriteBinary<4, long>(t.state, stream);
|
||||
IOUtils::WriteBinary<2, short>(t.texNum2, stream);
|
||||
|
||||
IOUtils::WriteBinary<2, short>(t.reserved2, stream);
|
||||
IOUtils::WriteBinary<2, short>(t.reserved3, stream);
|
||||
IOUtils::WriteBinary<2, short>(t.reserved4, stream);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Gfx::CModelFile::ReadDXF(const std::string &filename, float min, float max)
|
||||
{
|
||||
m_triangles.clear();
|
||||
m_error = "";
|
||||
|
||||
std::ifstream stream;
|
||||
stream.open(filename.c_str(), std::ios_base::in);
|
||||
if (! stream.good())
|
||||
{
|
||||
m_error = std::string("Couldn't open file '") + filename + std::string("'");
|
||||
return false;
|
||||
}
|
||||
|
||||
return ReadDXF(stream, min, max);
|
||||
}
|
||||
|
||||
bool Gfx::CModelFile::ReadDXF(std::istream &stream, float min, float max)
|
||||
{
|
||||
m_triangles.clear();
|
||||
m_error = "";
|
||||
|
||||
if (! stream.good())
|
||||
{
|
||||
m_error = "Invalid stream";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Input state
|
||||
bool waitNumVertex = false;
|
||||
bool waitNumFace = false;
|
||||
bool waitVertexX = false;
|
||||
bool waitVertexY = false;
|
||||
bool waitVertexZ = false;
|
||||
bool waitFaceX = false;
|
||||
bool waitFaceY = false;
|
||||
bool waitFaceZ = false;
|
||||
|
||||
// Vertex array
|
||||
std::vector<Math::Vector> vertices;
|
||||
vertices.reserve(TRIANGLE_PREALLOCATE_COUNT);
|
||||
|
||||
// Number of vertices & faces of the primitive to be read
|
||||
int vertexNum = 0, faceNum = 0;
|
||||
// Vertex coords
|
||||
Math::Vector coords;
|
||||
// Indexes of face (triangle) points
|
||||
int p1 = 0, p2 = 0, p3 = 0;
|
||||
|
||||
// Input line
|
||||
std::string line;
|
||||
while (! stream.eof() )
|
||||
{
|
||||
// Read line with command
|
||||
std::getline(stream, line);
|
||||
int command = StrUtils::FromString<int>(line);
|
||||
|
||||
// Read line with param
|
||||
std::getline(stream, line);
|
||||
|
||||
bool ok = true;
|
||||
|
||||
|
||||
if (command == 66)
|
||||
{
|
||||
waitNumVertex = true;
|
||||
}
|
||||
|
||||
if ( command == 71 && waitNumVertex )
|
||||
{
|
||||
waitNumVertex = false;
|
||||
vertexNum = StrUtils::FromString<int>(line, &ok);
|
||||
waitNumFace = true;
|
||||
}
|
||||
|
||||
if ( command == 72 && waitNumFace )
|
||||
{
|
||||
waitNumFace = false;
|
||||
faceNum = StrUtils::FromString<int>(line, &ok);
|
||||
waitVertexX = true;
|
||||
}
|
||||
|
||||
if ( command == 10 && waitVertexX )
|
||||
{
|
||||
waitVertexX = false;
|
||||
coords.x = StrUtils::FromString<float>(line, &ok);
|
||||
waitVertexY = true;
|
||||
}
|
||||
|
||||
if ( command == 20 && waitVertexY )
|
||||
{
|
||||
waitVertexY = false;
|
||||
coords.y = StrUtils::FromString<float>(line, &ok);
|
||||
waitVertexZ = true;
|
||||
}
|
||||
|
||||
if ( command == 30 && waitVertexZ )
|
||||
{
|
||||
waitVertexZ = false;
|
||||
coords.z = StrUtils::FromString<float>(line, &ok);
|
||||
|
||||
vertexNum --;
|
||||
if ( vertexNum >= 0 )
|
||||
{
|
||||
Math::Vector p(coords.x, coords.z, coords.y); // permutation of Y and Z!
|
||||
vertices.push_back(p);
|
||||
waitVertexX = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
waitFaceX = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( command == 71 && waitFaceX )
|
||||
{
|
||||
waitFaceX = false;
|
||||
p1 = StrUtils::FromString<int>(line, &ok);
|
||||
if ( p1 < 0 ) p1 = -p1;
|
||||
waitFaceY = true;
|
||||
}
|
||||
|
||||
if ( command == 72 && waitFaceY )
|
||||
{
|
||||
waitFaceY = false;
|
||||
p2 = StrUtils::FromString<int>(line, &ok);
|
||||
if ( p2 < 0 ) p2 = -p2;
|
||||
waitFaceZ = true;
|
||||
}
|
||||
|
||||
if ( command == 73 && waitFaceZ )
|
||||
{
|
||||
waitFaceZ = false;
|
||||
p3 = StrUtils::FromString<int>(line, &ok);
|
||||
if ( p3 < 0 ) p3 = -p3;
|
||||
|
||||
faceNum --;
|
||||
if ( faceNum >= 0 )
|
||||
{
|
||||
assert( (p1-1 >= 0) && (p1-1 < (int)vertices.size() ) );
|
||||
assert( (p2-1 >= 0) && (p2-1 < (int)vertices.size() ) );
|
||||
assert( (p3-1 >= 0) && (p3-1 < (int)vertices.size() ) );
|
||||
|
||||
CreateTriangle(vertices[p3-1], vertices[p2-1], vertices[p1-1], min, max);
|
||||
waitFaceX = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! ok)
|
||||
{
|
||||
m_error = "Error reading data";
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Gfx::CModelFile::CreateEngineObject(int objRank, int addState)
|
||||
{
|
||||
/*char texName1[20];
|
||||
char texName2[20];
|
||||
int texNum, i, state;
|
||||
|
||||
for (int i = 0; i < m_trianglesUsed; i++)
|
||||
{
|
||||
if (! m_triangles[i].used) continue;
|
||||
|
||||
state = m_triangles[i].state;
|
||||
strcpy(texName1, m_triangles[i].texName);
|
||||
texName2[0] = 0;
|
||||
|
||||
if ( strcmp(texName1, "plant.tga") == 0 ) // ???
|
||||
{
|
||||
state |= D3DSTATEALPHA;
|
||||
}
|
||||
|
||||
if ( m_triangles[i].texNum2 != 0 )
|
||||
{
|
||||
if ( m_triangles[i].texNum2 == 1 )
|
||||
{
|
||||
texNum = m_engine->RetSecondTexture();
|
||||
}
|
||||
else
|
||||
{
|
||||
texNum = m_triangles[i].texNum2;
|
||||
}
|
||||
|
||||
if ( texNum >= 1 && texNum <= 10 )
|
||||
{
|
||||
state |= D3DSTATEDUALb;
|
||||
}
|
||||
if ( texNum >= 11 && texNum <= 20 )
|
||||
{
|
||||
state |= D3DSTATEDUALw;
|
||||
}
|
||||
sprintf(texName2, "dirty%.2d.tga", texNum); // ???
|
||||
}
|
||||
|
||||
m_engine->AddTriangle(objRank, &m_triangles[i].p1, 3,
|
||||
m_triangles[i].material,
|
||||
state + addState,
|
||||
texName1, texName2,
|
||||
m_triangles[i].min,
|
||||
m_triangles[i].max, false);
|
||||
}*/
|
||||
return true;
|
||||
}
|
||||
|
||||
void Gfx::CModelFile::Mirror()
|
||||
{
|
||||
for (int i = 0; i < (int)m_triangles.size(); i++)
|
||||
{
|
||||
Gfx::VertexTex2 t = m_triangles[i].p1;
|
||||
m_triangles[i].p1 = m_triangles[i].p2;
|
||||
m_triangles[i].p2 = t;
|
||||
|
||||
m_triangles[i].p1.coord.z = -m_triangles[i].p1.coord.z;
|
||||
m_triangles[i].p2.coord.z = -m_triangles[i].p2.coord.z;
|
||||
m_triangles[i].p3.coord.z = -m_triangles[i].p3.coord.z;
|
||||
|
||||
m_triangles[i].p1.normal.z = -m_triangles[i].p1.normal.z;
|
||||
m_triangles[i].p2.normal.z = -m_triangles[i].p2.normal.z;
|
||||
m_triangles[i].p3.normal.z = -m_triangles[i].p3.normal.z;
|
||||
}
|
||||
}
|
||||
|
||||
int Gfx::CModelFile::GetTriangleCount()
|
||||
{
|
||||
return m_triangles.size();
|
||||
}
|
||||
|
||||
float Gfx::CModelFile::GetHeight(Math::Vector pos)
|
||||
{
|
||||
float limit = 5.0f;
|
||||
|
||||
for (int i = 0; i < (int)m_triangles.size(); i++)
|
||||
{
|
||||
if ( fabs(pos.x - m_triangles[i].p1.coord.x) < limit &&
|
||||
fabs(pos.z - m_triangles[i].p1.coord.z) < limit )
|
||||
return m_triangles[i].p1.coord.y;
|
||||
|
||||
if ( fabs(pos.x - m_triangles[i].p2.coord.x) < limit &&
|
||||
fabs(pos.z - m_triangles[i].p2.coord.z) < limit )
|
||||
return m_triangles[i].p2.coord.y;
|
||||
|
||||
if ( fabs(pos.x - m_triangles[i].p3.coord.x) < limit &&
|
||||
fabs(pos.z - m_triangles[i].p3.coord.z) < limit )
|
||||
return m_triangles[i].p3.coord.y;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void Gfx::CModelFile::CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max)
|
||||
{
|
||||
Gfx::ModelTriangle triangle;
|
||||
|
||||
Math::Vector n = Math::NormalToPlane(p3, p2, p1);
|
||||
triangle.p1 = Gfx::VertexTex2(p1, n);
|
||||
triangle.p2 = Gfx::VertexTex2(p2, n);
|
||||
triangle.p3 = Gfx::VertexTex2(p3, n);
|
||||
|
||||
triangle.material.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f, 0.0f);
|
||||
triangle.material.ambient = Gfx::Color(0.5f, 0.5f, 0.5f, 0.0f);
|
||||
|
||||
triangle.min = min;
|
||||
triangle.max = max;
|
||||
|
||||
m_triangles.push_back(triangle);
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
// * This file is part of the COLOBOT source code
|
||||
// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
|
||||
// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
// modelfile.h (aka modfile.h)
|
||||
|
||||
#include "graphics/common/engine.h"
|
||||
#include "graphics/common/vertex.h"
|
||||
#include "graphics/common/material.h"
|
||||
#include "math/vector.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
class CInstanceManager;
|
||||
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
/**
|
||||
\struct ModelTriangle
|
||||
\brief Triangle of a 3D model
|
||||
*/
|
||||
struct ModelTriangle
|
||||
{
|
||||
//! 1st vertex
|
||||
Gfx::VertexTex2 p1;
|
||||
//! 2nd vertex
|
||||
Gfx::VertexTex2 p2;
|
||||
//! 3rd vertex
|
||||
Gfx::VertexTex2 p3;
|
||||
//! Material
|
||||
Gfx::Material material;
|
||||
//! Name of 1st texture
|
||||
std::string tex1Name;
|
||||
//! Name of 2nd texture
|
||||
std::string tex2Name;
|
||||
//! Min LOD threshold
|
||||
float min;
|
||||
//! Max LOD threshold
|
||||
float max;
|
||||
//! Rendering state to be set
|
||||
long state;
|
||||
|
||||
ModelTriangle();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
\class CModelFile
|
||||
\brief Model file reader/writer
|
||||
|
||||
Allows reading and writing model objects. Models are collections of ModelTriangle structs. */
|
||||
class CModelFile
|
||||
{
|
||||
public:
|
||||
CModelFile(CInstanceManager* iMan);
|
||||
~CModelFile();
|
||||
|
||||
//! Returns the last error encountered
|
||||
std::string GetError();
|
||||
|
||||
//! Reads a binary Colobot model from file
|
||||
bool ReadModel(const std::string &filename, bool edit = false, bool meta = true);
|
||||
//! Reads a binary Colobot model from stream
|
||||
bool ReadModel(std::istream &stream, bool edit = false, bool meta = true);
|
||||
//! Writes the model to Colobot binary model file
|
||||
bool WriteModel(const std::string &filename);
|
||||
//! Writes the model to Colobot binary model file
|
||||
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 height of model -- closest point to X and Z coords of \a pos
|
||||
float GetHeight(Math::Vector pos);
|
||||
|
||||
//! Mirrors the model along the Z axis
|
||||
void Mirror();
|
||||
|
||||
//! Creates an object in the graphics engine from the model
|
||||
bool CreateEngineObject(int objRank, int addState = 0);
|
||||
|
||||
protected:
|
||||
//! Adds a triangle to the list
|
||||
void CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max);
|
||||
|
||||
protected:
|
||||
CInstanceManager* m_iMan;
|
||||
CEngine* m_engine;
|
||||
|
||||
//! Last error
|
||||
std::string m_error;
|
||||
|
||||
//! Model triangles
|
||||
std::vector<Gfx::ModelTriangle> m_triangles;
|
||||
};
|
||||
|
||||
}; // namespace Gfx
|
|
@ -1,23 +0,0 @@
|
|||
// * This file is part of the COLOBOT source code
|
||||
// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
|
||||
// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
// modfile.cpp
|
||||
|
||||
#include "graphics/common/modfile.h"
|
||||
|
||||
|
||||
// TODO implementation
|
|
@ -1,114 +0,0 @@
|
|||
// * This file is part of the COLOBOT source code
|
||||
// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
|
||||
// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
// modfile.h
|
||||
|
||||
#include "engine.h"
|
||||
#include "vertex.h"
|
||||
#include "material.h"
|
||||
#include "math/vector.h"
|
||||
|
||||
|
||||
class CInstanceManager;
|
||||
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
struct OldModelTriangle1
|
||||
{
|
||||
char bUsed; // TRUE -> using
|
||||
char bSelect; // TRUE -> selected
|
||||
Vertex p1;
|
||||
Vertex p2;
|
||||
Vertex p3;
|
||||
Material material;
|
||||
char texName[20];
|
||||
float min;
|
||||
float max;
|
||||
}; // length = 196 bytes
|
||||
|
||||
struct OldModelTriangle2
|
||||
{
|
||||
char bUsed; // TRUE -> used
|
||||
char bSelect; // TRUE -> selected
|
||||
Vertex p1;
|
||||
Vertex p2;
|
||||
Vertex p3;
|
||||
Material material;
|
||||
char texName[20];
|
||||
float min;
|
||||
float max;
|
||||
long state;
|
||||
short reserve1;
|
||||
short reserve2;
|
||||
short reserve3;
|
||||
short reserve4;
|
||||
};
|
||||
|
||||
struct ModelTriangle
|
||||
{
|
||||
char bUsed; // TRUE -> used
|
||||
char bSelect; // TRUE -> selected
|
||||
VertexTex2 p1;
|
||||
VertexTex2 p2;
|
||||
VertexTex2 p3;
|
||||
Material material;
|
||||
char texName[20];
|
||||
float min;
|
||||
float max;
|
||||
long state;
|
||||
short texNum2;
|
||||
short reserve2;
|
||||
short reserve3;
|
||||
short reserve4;
|
||||
}; // length = 208 bytes
|
||||
|
||||
|
||||
|
||||
|
||||
class CModFile {
|
||||
public:
|
||||
CModFile(CInstanceManager* iMan);
|
||||
~CModFile();
|
||||
|
||||
bool ReadDXF(char *filename, float min, float max);
|
||||
bool AddModel(char *filename, int first, bool bEdit=false, bool bMeta=true);
|
||||
bool ReadModel(char *filename, bool bEdit=false, bool bMeta=true);
|
||||
bool WriteModel(char *filename);
|
||||
|
||||
bool CreateEngineObject(int objRank, int addState=0);
|
||||
void Mirror();
|
||||
|
||||
void SetTriangleUsed(int total);
|
||||
int RetTriangleUsed();
|
||||
int RetTriangleMax();
|
||||
ModelTriangle* RetTriangleList();
|
||||
|
||||
float RetHeight(Math::Vector pos);
|
||||
|
||||
protected:
|
||||
bool CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max);
|
||||
|
||||
protected:
|
||||
CInstanceManager* m_iMan;
|
||||
CEngine* m_engine;
|
||||
|
||||
ModelTriangle* m_triangleTable;
|
||||
int m_triangleUsed;
|
||||
};
|
||||
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(CMAKE_BUILD_TYPE debug)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0")
|
||||
|
||||
include_directories(. ../../..)
|
||||
add_executable(modelfile_test modelfile_test.cpp ../modelfile.cpp ../../../common/stringutils.cpp ../../../common/iman.cpp)
|
|
@ -0,0 +1,48 @@
|
|||
#include "graphics/common/modelfile.h"
|
||||
#include "common/iman.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 4)
|
||||
{
|
||||
std::cerr << "Usage: " << argv[0] << " {mod|dxf} in_file out_file" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
CInstanceManager iMan;
|
||||
Gfx::CModelFile modfile(&iMan);
|
||||
|
||||
std::string mode(argv[1]);
|
||||
if (mode == "mod")
|
||||
{
|
||||
if (! modfile.ReadModel(argv[2], false, false) )
|
||||
{
|
||||
std::cerr << "Read error: " << modfile.GetError() << std::endl;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
else if (mode == "dxf")
|
||||
{
|
||||
if (! modfile.ReadDXF(argv[2], false, false) )
|
||||
{
|
||||
std::cerr << "Read error: " << modfile.GetError() << std::endl;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Usage: " << argv[0] << " {mod|dxf} in_file out_file" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (! modfile.WriteModel(argv[3]) )
|
||||
{
|
||||
std::cerr << "Write error: " << modfile.GetError() << std::endl;
|
||||
return 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -94,6 +94,14 @@ struct VertexTex2
|
|||
Math::Point aTexCoord = Math::Point(),
|
||||
Math::Point aTexCoord2 = Math::Point())
|
||||
: coord(aCoord), normal(aNormal), texCoord(aTexCoord), texCoord2(aTexCoord2) {}
|
||||
|
||||
void FromVertex(const Gfx::Vertex &v)
|
||||
{
|
||||
coord = v.coord;
|
||||
normal = v.normal;
|
||||
texCoord = v.texCoord;
|
||||
texCoord2 = Math::Point();
|
||||
}
|
||||
};
|
||||
|
||||
}; // namespace Gfx
|
||||
|
|
Loading…
Reference in New Issue