Partial refactor of model I/O

* Mostly removed legacy Gfx::Material usage
* Bake legacy diffuse color to vertex color
* Removed code that writes to old model formats
dev
Tomasz Kapuściński 2022-01-19 19:46:39 +01:00
parent a54a59146d
commit 5dacb82b22
13 changed files with 119 additions and 580 deletions

View File

@ -26,6 +26,7 @@
#include <sstream>
#include <glm/glm.hpp>
// Graphics module namespace
@ -45,6 +46,14 @@ struct Color
explicit Color(float aR = 0.0f, float aG = 0.0f, float aB = 0.0f, float aA = 0.0f)
: r(aR), g(aG), b(aB), a(aA) {}
Color(const glm::vec4& color)
: r(color.r), g(color.g), b(color.b), a(color.a) {}
operator glm::vec4() const
{
return { r, g, b, a };
}
inline Color Inverse() const
{
return Color(1.0f - r, 1.0f - g, 1.0f - b, 1.0f - a);
@ -111,6 +120,14 @@ struct IntColor
//! Constructor; default values are (0,0,0,0) = black
explicit IntColor(unsigned char aR = 0, unsigned char aG = 0, unsigned char aB = 0, unsigned char aA = 0)
: r(aR), g(aG), b(aB), a(aA) {}
IntColor(const glm::u8vec4& color)
: r(color.r), g(color.g), b(color.b), a(color.a) {}
operator glm::u8vec4() const
{
return { r, g, b, a };
}
};
inline Color IntColorToColor(IntColor color)

View File

@ -632,16 +632,15 @@ EngineBaseObjTexTier& CEngine::AddLevel2(EngineBaseObject& p1, const std::string
return p1.next.back();
}
EngineBaseObjDataTier& CEngine::AddLevel3(EngineBaseObjTexTier& p3, EngineTriangleType type,
const Material& material, int state)
EngineBaseObjDataTier& CEngine::AddLevel3(EngineBaseObjTexTier& p3, EngineTriangleType type, int state)
{
for (int i = 0; i < static_cast<int>( p3.next.size() ); i++)
{
if ( (p3.next[i].type == type) && (p3.next[i].material == material) && (p3.next[i].state == state) )
if ( (p3.next[i].type == type) && (p3.next[i].state == state) )
return p3.next[i];
}
p3.next.push_back(EngineBaseObjDataTier(type, material, state));
p3.next.push_back(EngineBaseObjDataTier(type, state));
return p3.next.back();
}
@ -742,15 +741,14 @@ void CEngine::CopyBaseObject(int sourceBaseObjRank, int destBaseObjRank)
}
}
void CEngine::AddBaseObjTriangles(int baseObjRank, const std::vector<VertexTex2>& vertices,
const Material& material, int state,
std::string tex1Name, std::string tex2Name)
void CEngine::AddBaseObjTriangles(int baseObjRank, const std::vector<Vertex3D>& vertices,
int state, std::string tex1Name, std::string tex2Name)
{
assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
EngineBaseObject& p1 = m_baseObjects[baseObjRank];
EngineBaseObjTexTier& p2 = AddLevel2(p1, tex1Name, tex2Name);
EngineBaseObjDataTier& p3 = AddLevel3(p2, EngineTriangleType::TRIANGLES, material, state);
EngineBaseObjDataTier& p3 = AddLevel3(p2, EngineTriangleType::TRIANGLES, state);
p3.vertices.insert(p3.vertices.end(), vertices.begin(), vertices.end());
@ -759,12 +757,12 @@ void CEngine::AddBaseObjTriangles(int baseObjRank, const std::vector<VertexTex2>
for (int i = 0; i < static_cast<int>( vertices.size() ); i++)
{
p1.bboxMin.x = Math::Min(vertices[i].coord.x, p1.bboxMin.x);
p1.bboxMin.y = Math::Min(vertices[i].coord.y, p1.bboxMin.y);
p1.bboxMin.z = Math::Min(vertices[i].coord.z, p1.bboxMin.z);
p1.bboxMax.x = Math::Max(vertices[i].coord.x, p1.bboxMax.x);
p1.bboxMax.y = Math::Max(vertices[i].coord.y, p1.bboxMax.y);
p1.bboxMax.z = Math::Max(vertices[i].coord.z, p1.bboxMax.z);
p1.bboxMin.x = Math::Min(vertices[i].position.x, p1.bboxMin.x);
p1.bboxMin.y = Math::Min(vertices[i].position.y, p1.bboxMin.y);
p1.bboxMin.z = Math::Min(vertices[i].position.z, p1.bboxMin.z);
p1.bboxMax.x = Math::Max(vertices[i].position.x, p1.bboxMax.x);
p1.bboxMax.y = Math::Max(vertices[i].position.y, p1.bboxMax.y);
p1.bboxMax.z = Math::Max(vertices[i].position.z, p1.bboxMax.z);
}
p1.boundingSphere = Math::BoundingSphereForBox(p1.bboxMin, p1.bboxMax);
@ -1021,8 +1019,7 @@ int CEngine::GetObjectTotalTriangles(int objRank)
return m_baseObjects[baseObjRank].totalTriangles;
}
EngineBaseObjDataTier* CEngine::FindTriangles(int objRank, const Material& material,
int state, std::string tex1Name,
EngineBaseObjDataTier* CEngine::FindTriangles(int objRank, int state, std::string tex1Name,
std::string tex2Name)
{
assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
@ -1046,8 +1043,7 @@ EngineBaseObjDataTier* CEngine::FindTriangles(int objRank, const Material& mater
{
EngineBaseObjDataTier& p3 = p2.next[l3];
if ( (p3.state & (~(ENG_RSTATE_DUAL_BLACK|ENG_RSTATE_DUAL_WHITE))) != state ||
p3.material != material )
if ( (p3.state & (~(ENG_RSTATE_DUAL_BLACK|ENG_RSTATE_DUAL_WHITE))) != state)
continue;
return &p3;
@ -1098,7 +1094,6 @@ int CEngine::GetPartialTriangles(int objRank, float percent, int maxCount,
t.triangle[0] = p3.vertices[i];
t.triangle[1] = p3.vertices[i+1];
t.triangle[2] = p3.vertices[i+2];
t.material = p3.material;
t.state = p3.state;
t.tex1Name = p2.tex1Name;
t.tex2Name = p2.tex2Name;
@ -1122,7 +1117,6 @@ int CEngine::GetPartialTriangles(int objRank, float percent, int maxCount,
t.triangle[0] = p3.vertices[i];
t.triangle[1] = p3.vertices[i+1];
t.triangle[2] = p3.vertices[i+2];
t.material = p3.material;
t.state = p3.state;
t.tex1Name = p2.tex1Name;
t.tex2Name = p2.tex2Name;
@ -1168,14 +1162,14 @@ void CEngine::ChangeSecondTexture(int objRank, const std::string& tex2Name)
}
}
void CEngine::ChangeTextureMapping(int objRank, const Material& mat, int state,
void CEngine::ChangeTextureMapping(int objRank, int state,
const std::string& tex1Name, const std::string& tex2Name,
EngineTextureMapping mode,
float au, float bu, float av, float bv)
{
assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
EngineBaseObjDataTier* p4 = FindTriangles(objRank, mat, state, tex1Name, tex2Name);
EngineBaseObjDataTier* p4 = FindTriangles(objRank, state, tex1Name, tex2Name);
if (p4 == nullptr)
return;
@ -1230,14 +1224,14 @@ void CEngine::ChangeTextureMapping(int objRank, const Material& mat, int state,
UpdateStaticBuffer(*p4);
}
void CEngine::TrackTextureMapping(int objRank, const Material& mat, int state,
void CEngine::TrackTextureMapping(int objRank, int state,
const std::string& tex1Name, const std::string& tex2Name,
EngineTextureMapping mode,
float pos, float factor, float tl, float ts, float tt)
{
assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
EngineBaseObjDataTier* p4 = FindTriangles(objRank, mat, state, tex1Name, tex2Name);
EngineBaseObjDataTier* p4 = FindTriangles(objRank, state, tex1Name, tex2Name);
if (p4 == nullptr)
return;
@ -3567,8 +3561,7 @@ void CEngine::Draw3DScene()
float dirty = ((p3.state & ENG_RSTATE_DUAL_BLACK) && m_dirty) ? 1.0 : 0.0;
objectRenderer->SetDirty(dirty);
auto color = p3.material.diffuse;
objectRenderer->SetColor({ color.r, color.g, color.b, 1.0 });
objectRenderer->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f });
objectRenderer->SetCullMode((p3.state& ENG_RSTATE_2FACE) == 0);
objectRenderer->DrawObject(p3.buffer);
}
@ -3589,7 +3582,7 @@ void CEngine::Draw3DScene()
if (transparent)
{
Color tColor = Color(68.0f / 255.0f, 68.0f / 255.0f, 68.0f / 255.0f, 68.0f / 255.0f);
Color tColor = Color(68.0f / 255.0f, 68.0f / 255.0f, 68.0f / 255.0f, 255.0f);
for (int objRank = 0; objRank < static_cast<int>(m_objects.size()); objRank++)
{
@ -3635,8 +3628,7 @@ void CEngine::Draw3DScene()
float dirty = (p3.state & ENG_RSTATE_DUAL_BLACK) && m_dirty ? 1.0 : 0.0;
objectRenderer->SetDirty(dirty);
auto color = p3.material.diffuse * tColor;
objectRenderer->SetColor({ color.r, color.g, color.b, 1.0f });
objectRenderer->SetColor(tColor);
objectRenderer->DrawObject(p3.buffer);
}
}
@ -4369,7 +4361,7 @@ void CEngine::DrawInterface()
{
EngineBaseObjDataTier& p3 = p2.next[l3];
SetMaterial(p3.material);
//SetMaterial(p3.material);
SetState(p3.state);
DrawObject(p3);
@ -5412,7 +5404,7 @@ void CEngine::DrawTimer()
void CEngine::AddBaseObjTriangles(int baseObjRank, const std::vector<Gfx::ModelTriangle>& triangles)
{
std::vector<VertexTex2> vs(3, VertexTex2());
std::vector<Vertex3D> vs(3, Vertex3D{});
for (const auto& triangle : triangles)
{
@ -5420,11 +5412,6 @@ void CEngine::AddBaseObjTriangles(int baseObjRank, const std::vector<Gfx::ModelT
vs[1] = triangle.p2;
vs[2] = triangle.p3;
Material material;
material.ambient = triangle.ambient;
material.diffuse = triangle.diffuse;
material.specular = triangle.specular;
int state = GetEngineState(triangle);
std::string tex1Name;
@ -5437,7 +5424,7 @@ void CEngine::AddBaseObjTriangles(int baseObjRank, const std::vector<Gfx::ModelT
else
tex2Name = triangle.tex2Name;
AddBaseObjTriangles(baseObjRank, vs, material, state, tex1Name, tex2Name);
AddBaseObjTriangles(baseObjRank, vs, state, tex1Name, tex2Name);
}
}

View File

@ -153,8 +153,6 @@ struct EngineTriangle
{
//! Triangle vertices
Vertex3D triangle[3];
//! Material
Material material;
//! Render state
int state = ENG_RSTATE_NORMAL;
//! 1st texture
@ -192,17 +190,14 @@ enum EngineObjectType
struct EngineBaseObjDataTier
{
EngineTriangleType type;
Material material;
int state;
std::vector<Vertex3D> vertices;
CVertexBuffer* buffer;
bool updateStaticBuffer;
inline EngineBaseObjDataTier(EngineTriangleType type = EngineTriangleType::TRIANGLES,
const Material& material = Material(),
int state = ENG_RSTATE_NORMAL)
: type(type)
, material(material)
, state(state)
, buffer(nullptr)
, updateStaticBuffer(false)
@ -781,8 +776,7 @@ public:
int GetObjectTotalTriangles(int objRank);
//! Returns the first found tier 4 engine object for the given params or nullptr if not found
EngineBaseObjDataTier* FindTriangles(int objRank, const Material& material,
int state, std::string tex1Name, std::string tex2Name);
EngineBaseObjDataTier* FindTriangles(int objRank, int state, std::string tex1Name, std::string tex2Name);
//! Returns a partial list of triangles for given object
int GetPartialTriangles(int objRank, float percent, int maxCount,
@ -792,13 +786,13 @@ public:
void ChangeSecondTexture(int objRank, const std::string& tex2Name);
//! Changes (recalculates) texture mapping for given object
void ChangeTextureMapping(int objRank, const Material& mat, int state,
void ChangeTextureMapping(int objRank, int state,
const std::string& tex1Name, const std::string& tex2Name,
EngineTextureMapping mode,
float au, float bu, float av, float bv);
//! Changes texture mapping for robot tracks
void TrackTextureMapping(int objRank, const Material& mat, int state,
void TrackTextureMapping(int objRank, int state,
const std::string& tex1Name, const std::string& tex2Name,
EngineTextureMapping mode,
float pos, float factor, float tl, float ts, float tt);
@ -1252,8 +1246,7 @@ protected:
//! Creates a new tier 2 object (texture)
EngineBaseObjTexTier& AddLevel2(EngineBaseObject& p1, const std::string& tex1Name, const std::string& tex2Name);
//! Creates a new tier 3 object (data)
EngineBaseObjDataTier& AddLevel3(EngineBaseObjTexTier &p3, EngineTriangleType type,
const Material& material, int state);
EngineBaseObjDataTier& AddLevel3(EngineBaseObjTexTier &p3, EngineTriangleType type, int state);
//! Create texture and add it to cache
Texture CreateTexture(const std::string &texName, const TextureCreateParams &params, CImage* image = nullptr);
@ -1290,9 +1283,8 @@ protected:
//! Updates static buffers of changed objects
void UpdateStaticBuffers();
void AddBaseObjTriangles(int baseObjRank, const std::vector<VertexTex2>& vertices,
const Material& material, int state,
std::string tex1Name, std::string tex2Name);
void AddBaseObjTriangles(int baseObjRank, const std::vector<Vertex3D>& vertices,
int state, std::string tex1Name, std::string tex2Name);
int GetEngineState(const ModelTriangle& triangle);

View File

@ -3368,6 +3368,15 @@ void CParticle::DrawParticleWheel(int i)
void CParticle::DrawParticle(int sheet)
{
Material mat;
mat.diffuse.r = 1.0f;
mat.diffuse.g = 1.0f;
mat.diffuse.b = 1.0f; // white
mat.ambient.r = 0.5f;
mat.ambient.g = 0.5f;
mat.ambient.b = 0.5f;
m_engine->SetMaterial(mat);
// Draw the basic particles of triangles.
if (m_totalInterface[0][sheet] > 0)
{
@ -3378,21 +3387,11 @@ void CParticle::DrawParticle(int sheet)
if (m_particle[i].type == PARTIPART) continue;
m_engine->SetTexture(!m_triangle[i].tex1Name.empty() ? "textures/"+m_triangle[i].tex1Name : "");
m_engine->SetMaterial(m_triangle[i].material);
m_engine->SetState(m_triangle[i].state);
DrawParticleTriangle(i);
}
}
Material mat;
mat.diffuse.r = 1.0f;
mat.diffuse.g = 1.0f;
mat.diffuse.b = 1.0f; // white
mat.ambient.r = 0.5f;
mat.ambient.g = 0.5f;
mat.ambient.b = 0.5f;
m_engine->SetMaterial(mat);
// Draw tire marks.
if (m_wheelTraceTotal > 0 && sheet == SH_WORLD)
{

View File

@ -572,8 +572,7 @@ VertexTex2 CTerrain::GetVertex(int x, int y, int step)
|
+-------------------> x
\endverbatim */
bool CTerrain::CreateMosaic(int ox, int oy, int step, int objRank,
const Material &mat)
bool CTerrain::CreateMosaic(int ox, int oy, int step, int objRank)
{
int baseObjRank = m_engine->GetObjectBaseRank(objRank);
if (baseObjRank == -1)
@ -635,7 +634,6 @@ bool CTerrain::CreateMosaic(int ox, int oy, int step, int objRank,
buffer.vertices.reserve(total);
buffer.type = EngineTriangleType::SURFACE;
buffer.material = mat;
buffer.state = ENG_RSTATE_WRAP;
@ -1249,10 +1247,6 @@ void CTerrain::FlushMaterialPoints()
bool CTerrain::CreateSquare(int x, int y)
{
Material mat;
mat.diffuse = Color(1.0f, 1.0f, 1.0f);
mat.ambient = Color(0.0f, 0.0f, 0.0f);
int objRank = m_engine->CreateObject();
m_engine->SetObjectType(objRank, ENG_OBJTYPE_TERRAIN);
@ -1260,7 +1254,7 @@ bool CTerrain::CreateSquare(int x, int y)
for (int step = 0; step < m_depth; step++)
{
CreateMosaic(x, y, 1 << step, objRank, mat);
CreateMosaic(x, y, 1 << step, objRank);
}
return true;

View File

@ -256,7 +256,7 @@ protected:
//! Calculates a vertex of the terrain
VertexTex2 GetVertex(int x, int y, int step);
//! Creates all objects of a mosaic
bool CreateMosaic(int ox, int oy, int step, int objRank, const Material& mat);
bool CreateMosaic(int ox, int oy, int step, int objRank);
//! Creates all objects in a mesh square ground
bool CreateSquare(int x, int y);

View File

@ -18,6 +18,7 @@
*/
#include "graphics/model/model_input.h"
#include "graphics/core/material.h"
#include "common/ioutils.h"
#include "common/logger.h"
@ -157,11 +158,18 @@ void ModelInput::ReadBinaryModelV1AndV2(CModel &model, std::istream &stream)
t.p1 = ReadBinaryVertexTex2(stream);
t.p2 = ReadBinaryVertexTex2(stream);
t.p3 = ReadBinaryVertexTex2(stream);
t.material = ReadBinaryMaterial(stream);
auto material = ReadBinaryMaterial(stream);
t.tex1Name = ReadBinaryString<1>(stream);
t.tex2Name = ReadBinaryString<1>(stream);
t.variableTex2 = ReadBinaryBool(stream);
auto diffuse = Gfx::ColorToIntColor(material.diffuse);
glm::u8vec4 color = { diffuse.r, diffuse.g, diffuse.b, 255 };
t.p1.color = color;
t.p2.color = color;
t.p3.color = color;
if (header.version == 1)
t.lodLevel = static_cast<ModelLODLevel>( ReadBinary<4, int>(stream) );
@ -175,9 +183,6 @@ void ModelInput::ReadBinaryModelV1AndV2(CModel &model, std::istream &stream)
triangle.p1 = t.p1;
triangle.p2 = t.p2;
triangle.p3 = t.p3;
triangle.diffuse = t.material.diffuse;
triangle.specular = t.material.specular;
triangle.ambient = t.material.ambient;
triangle.tex1Name = t.tex1Name;
triangle.tex2Name = t.tex2Name;
triangle.variableTex2 = t.variableTex2;
@ -248,7 +253,14 @@ void ModelInput::ReadTextModelV1AndV2(CModel &model, std::istream &stream)
t.p3 = ParseVertexTex2(p3Text);
std::string matText = ReadLineString(stream, "mat");
t.material = ParseMaterial(matText);
auto material = ParseMaterial(matText);
auto diffuse = Gfx::ColorToIntColor(material.diffuse);
glm::u8vec4 color = { diffuse.r, diffuse.g, diffuse.b, 255 };
t.p1.color = color;
t.p2.color = color;
t.p3.color = color;
t.tex1Name = ReadLineString(stream, "tex1");
t.tex2Name = ReadLineString(stream, "tex2");
@ -268,9 +280,6 @@ void ModelInput::ReadTextModelV1AndV2(CModel &model, std::istream &stream)
triangle.p1 = t.p1;
triangle.p2 = t.p2;
triangle.p3 = t.p3;
triangle.ambient = t.material.ambient;
triangle.diffuse = t.material.diffuse;
triangle.specular = t.material.specular;
triangle.tex1Name = t.tex1Name;
triangle.tex2Name = t.tex2Name;
triangle.variableTex2 = t.variableTex2;
@ -356,9 +365,13 @@ CModelMesh ModelInput::ReadTextMesh(std::istream& stream)
std::string matText = ReadLineString(stream, "mat");
Material mat = ParseMaterial(matText);
t.ambient = mat.ambient;
t.diffuse = mat.diffuse;
t.specular = mat.specular;
auto diffuse = Gfx::ColorToIntColor(mat.diffuse);
glm::u8vec4 color = { diffuse.r, diffuse.g, diffuse.b, 255 };
t.p1.color = color;
t.p2.color = color;
t.p3.color = color;
t.tex1Name = ReadLineString(stream, "tex1");
t.tex2Name = ReadLineString(stream, "tex2");
@ -435,7 +448,7 @@ std::vector<ModelTriangle> ModelInput::ReadOldModelV1(std::istream &stream, int
t.p2 = ReadBinaryVertex(stream);
t.p3 = ReadBinaryVertex(stream);
t.material = ReadBinaryMaterial(stream);
auto material = ReadBinaryMaterial(stream);
stream.read(t.texName, 20);
t.min = ReadBinaryFloat(stream);
t.max = ReadBinaryFloat(stream);
@ -450,9 +463,13 @@ std::vector<ModelTriangle> ModelInput::ReadOldModelV1(std::istream &stream, int
triangle.p2 = t.p2;
triangle.p3 = t.p3;
triangle.ambient = t.material.ambient;
triangle.diffuse = t.material.diffuse;
triangle.specular = t.material.specular;
auto diffuse = Gfx::ColorToIntColor(material.diffuse);
glm::u8vec4 color = { diffuse.r, diffuse.g, diffuse.b, 255 };
triangle.p1.color = color;
triangle.p2.color = color;
triangle.p3.color = color;
ConvertOldTex1Name(triangle, t.texName);
triangles.push_back(triangle);
@ -477,7 +494,7 @@ std::vector<ModelTriangle> ModelInput::ReadOldModelV2(std::istream &stream, int
t.p2 = ReadBinaryVertex(stream);
t.p3 = ReadBinaryVertex(stream);
t.material = ReadBinaryMaterial(stream);
auto material = ReadBinaryMaterial(stream);
stream.read(t.texName, 20);
t.min = ReadBinaryFloat(stream);
t.max = ReadBinaryFloat(stream);
@ -498,9 +515,13 @@ std::vector<ModelTriangle> ModelInput::ReadOldModelV2(std::istream &stream, int
triangle.p2 = t.p2;
triangle.p3 = t.p3;
triangle.ambient = t.material.ambient;
triangle.diffuse = t.material.diffuse;
triangle.specular = t.material.specular;
auto diffuse = Gfx::ColorToIntColor(material.diffuse);
glm::u8vec4 color = { diffuse.r, diffuse.g, diffuse.b, 255 };
triangle.p1.color = color;
triangle.p2.color = color;
triangle.p3.color = color;
ConvertOldTex1Name(triangle, t.texName);
ConvertFromOldRenderState(triangle, t.state);
@ -527,7 +548,7 @@ std::vector<ModelTriangle> ModelInput::ReadOldModelV3(std::istream &stream, int
t.p2 = ReadBinaryVertexTex2(stream);
t.p3 = ReadBinaryVertexTex2(stream);
t.material = ReadBinaryMaterial(stream);
auto material = ReadBinaryMaterial(stream);
stream.read(t.texName, 20);
t.min = ReadBinaryFloat(stream);
t.max = ReadBinaryFloat(stream);
@ -548,9 +569,13 @@ std::vector<ModelTriangle> ModelInput::ReadOldModelV3(std::istream &stream, int
triangle.p2 = t.p2;
triangle.p3 = t.p3;
triangle.ambient = t.material.ambient;
triangle.diffuse = t.material.diffuse;
triangle.specular = t.material.specular;
auto diffuse = Gfx::ColorToIntColor(material.diffuse);
glm::u8vec4 color = { diffuse.r, diffuse.g, diffuse.b, 255 };
triangle.p1.color = color;
triangle.p2.color = color;
triangle.p3.color = color;
ConvertOldTex1Name(triangle, t.texName);
ConvertFromOldRenderState(triangle, t.state);

View File

@ -19,8 +19,6 @@
#pragma once
#include "graphics/core/material.h"
#include "graphics/model/model_triangle.h"
namespace Gfx
@ -84,13 +82,11 @@ struct ModelHeaderV1AndV2
struct ModelTriangleV1AndV2
{
//! 1st vertex
VertexTex2 p1;
Vertex3D p1;
//! 2nd vertex
VertexTex2 p2;
Vertex3D p2;
//! 3rd vertex
VertexTex2 p3;
//! Material
Material material;
Vertex3D p3;
//! Name of 1st texture
std::string tex1Name;
//! Name of 2nd texture
@ -187,7 +183,6 @@ struct OldModelTriangleV1
Vertex p1;
Vertex p2;
Vertex p3;
Material material;
char texName[21] = {'\0'};
float min = 0;
float max = 0;
@ -206,7 +201,6 @@ struct OldModelTriangleV2
Vertex p1;
Vertex p2;
Vertex p3;
Material material;
char texName[21] = {'\0'};
float min = 0.0f;
float max = 0.0f;
@ -230,7 +224,6 @@ struct OldModelTriangleV3
Vertex3D p1;
Vertex3D p2;
Vertex3D p3;
Material material;
char texName[21] = {'\0'};
float min = 0.0f;
float max = 0.0f;

View File

@ -25,461 +25,15 @@
#include "graphics/model/model_io_exception.h"
#include "graphics/model/model_io_structs.h"
#include <stdexcept>
#include <fstream>
namespace Gfx
{
// Private functions
namespace ModelOutput
{
void WriteTextModel(const CModel& model, std::ostream &stream);
void WriteTextHeader(const ModelHeaderV3& header, std::ostream &stream);
void WriteCrashSphere(const ModelCrashSphere& crashSphere, std::ostream &stream);
void WriteShadowSpot(const ModelShadowSpot& shadowSpot, std::ostream &stream);
void WriteCameraCollisionSphere(const Math::Sphere& sphere, std::ostream &stream);
void WriteTextMesh(const CModelMesh* mesh, const std::string& meshName, std::ostream &stream);
std::string VectorToString(const glm::vec3& vector);
std::string TransparentModeToString(ModelTransparentMode mode);
std::string SpecialMarkToString(ModelSpecialMark specialMark);
void WriteBinaryModel(const CModel& model, std::ostream &stream);
void WriteOldModel(const CModel& model, std::ostream &stream);
int ConvertToOldState(const ModelTriangle& triangle);
void WriteBinaryVertex3D(const Vertex3D& vertex, std::ostream &stream);
void WriteBinaryMaterial(const Material& material, std::ostream &stream);
void WriteTextVertex3D(const Vertex3D& vertex, std::ostream &stream);
void WriteTextMaterial(const Material& material, std::ostream &stream);
}
using namespace IOUtils;
void ModelOutput::Write(const CModel& model, std::ostream &stream, ModelFormat format)
{
stream.exceptions(std::ios_base::failbit | std::ios_base::badbit);
try
{
switch (format)
{
case ModelFormat::Text:
WriteTextModel(model, stream);
break;
case ModelFormat::Binary:
WriteBinaryModel(model, stream);
break;
case ModelFormat::Old:
WriteOldModel(model, stream);
break;
}
}
catch (const CModelIOException& e)
{
throw;
}
catch (const std::exception& e)
{
throw CModelIOException(std::string("Error saving model data: ") + e.what());
}
throw std::logic_error("Not implemented");
}
void ModelOutput::WriteTextModel(const CModel& model, std::ostream &stream)
{
ModelHeaderV3 header;
header.version = 3;
header.totalCrashSpheres = model.GetCrashSphereCount();
header.hasShadowSpot = model.HasShadowSpot();
header.hasCameraCollisionSphere = model.HasCameraCollisionSphere();
header.totalMeshes = model.GetMeshCount();
WriteTextHeader(header, stream);
stream << "# MODEL PROPERTIES" << std::endl;
for (const auto& crashSphere : model.GetCrashSpheres())
WriteCrashSphere(crashSphere, stream);
if (model.HasShadowSpot())
WriteShadowSpot(model.GetShadowSpot(), stream);
if (model.HasCameraCollisionSphere())
WriteCameraCollisionSphere(model.GetCameraCollisionSphere(), stream);
stream << std::endl;
for (const std::string& meshName : model.GetMeshNames())
{
const CModelMesh* mesh = model.GetMesh(meshName);
assert(mesh != nullptr);
WriteTextMesh(mesh, meshName, stream);
}
}
void ModelOutput::WriteTextHeader(const ModelHeaderV3& header, std::ostream &stream)
{
stream << "# Colobot text model" << std::endl;
stream << std::endl;
stream << "### HEAD" << std::endl;
stream << "version " << header.version << std::endl;
stream << "total_crash_spheres " << header.totalCrashSpheres << std::endl;
stream << "has_shadow_spot " << (header.hasShadowSpot ? "Y" : "N") << std::endl;
stream << "has_camera_collision_sphere " << (header.hasCameraCollisionSphere ? "Y" : "N") << std::endl;
stream << "total_meshes " << header.totalMeshes << std::endl;
stream << std::endl;
}
void ModelOutput::WriteCrashSphere(const ModelCrashSphere& crashSphere, std::ostream &stream)
{
stream << "crash_sphere";
stream << " pos"
<< " " << crashSphere.position.x
<< " " << crashSphere.position.y
<< " " << crashSphere.position.z;
stream << " rad " << crashSphere.radius;
stream << " sound " << crashSphere.sound;
stream << " hard " << crashSphere.hardness;
stream << std::endl;
}
void ModelOutput::WriteShadowSpot(const ModelShadowSpot& shadowSpot, std::ostream &stream)
{
stream << "shadow_spot";
stream << " rad " << shadowSpot.radius;
stream << " int " << shadowSpot.intensity;
stream << std::endl;
}
void ModelOutput::WriteCameraCollisionSphere(const Math::Sphere& sphere, std::ostream &stream)
{
stream << "camera_collision_sphere ";
stream << " pos "
<< sphere.pos.x
<< sphere.pos.y
<< sphere.pos.z;
stream << " rad " << sphere.radius;
stream << std::endl;
}
void ModelOutput::WriteTextMesh(const CModelMesh* mesh, const std::string& meshName, std::ostream &stream)
{
stream << "### MESH" << std::endl;
stream << "mesh " << meshName << std::endl;
stream << "position " << VectorToString(mesh->GetPosition()) << std::endl;
stream << "rotation " << VectorToString(mesh->GetRotation()) << std::endl;
stream << "scale " << VectorToString(mesh->GetScale()) << std::endl;
stream << "parent " << mesh->GetParent() << std::endl;
stream << "total_triangles " << mesh->GetTriangleCount() << std::endl;
stream << std::endl;
stream << "### MESH TRIANGLES" << std::endl;
for (const ModelTriangle& t : mesh->GetTriangles())
{
stream << "p1 ";
WriteTextVertex3D(t.p1, stream);
stream << "p2 ";
WriteTextVertex3D(t.p2, stream);
stream << "p3 ";
WriteTextVertex3D(t.p3, stream);
stream << "mat ";
Material material;
material.ambient = t.ambient;
material.diffuse = t.diffuse;
material.specular = t.specular;
WriteTextMaterial(material, stream);
stream << "tex1 " << t.tex1Name << std::endl;
stream << "tex2 " << t.tex2Name << std::endl;
stream << "var_tex2 " << (t.variableTex2 ? 'Y' : 'N') << std::endl;
stream << "trans_mode " << TransparentModeToString(t.transparentMode) << std::endl;
stream << "mark " << SpecialMarkToString(t.specialMark) << std::endl;
stream << "dbl_side " << (t.doubleSided ? 'Y' : 'N') << std::endl;
stream << std::endl;
}
}
std::string ModelOutput::VectorToString(const glm::vec3& vector)
{
std::ostringstream str;
str << vector.x << " " << vector.y << " " << vector.z;
return str.str();
}
std::string ModelOutput::TransparentModeToString(ModelTransparentMode mode)
{
std::string str;
switch (mode)
{
case ModelTransparentMode::None:
str = "none";
break;
case ModelTransparentMode::AlphaChannel:
str = "alpha";
break;
case ModelTransparentMode::MapBlackToAlpha:
str = "map_black";
break;
case ModelTransparentMode::MapWhiteToAlpha:
str = "map_white";
break;
}
return str;
}
std::string ModelOutput::SpecialMarkToString(ModelSpecialMark specialMark)
{
std::string str;
switch (specialMark)
{
case ModelSpecialMark::None:
str = "none";
break;
case ModelSpecialMark::Part1:
str = "part1";
break;
case ModelSpecialMark::Part2:
str = "part2";
break;
case ModelSpecialMark::Part3:
str = "part3";
break;
}
return str;
}
void ModelOutput::WriteBinaryModel(const CModel& model, std::ostream &stream)
{
const CModelMesh* mesh = model.GetMesh("main");
if (mesh == nullptr)
throw CModelIOException("No main mesh found in model");
ModelHeaderV1AndV2 header;
header.version = 2;
header.totalTriangles = mesh->GetTriangleCount();
WriteBinary<4, int>(header.version, stream);
WriteBinary<4, int>(header.totalTriangles, stream);
for (const ModelTriangle& triangle : mesh->GetTriangles())
{
ModelTriangleV1AndV2 t;
t.p1 = triangle.p1;
t.p2 = triangle.p2;
t.p3 = triangle.p3;
t.material.ambient = triangle.ambient;
t.material.diffuse = triangle.diffuse;
t.material.specular = triangle.specular;
t.tex1Name = triangle.tex1Name;
t.tex2Name = triangle.tex2Name;
t.variableTex2 = triangle.variableTex2;
t.state = ConvertToOldState(triangle);
WriteBinaryVertex3D(t.p1, stream);
WriteBinaryVertex3D(t.p2, stream);
WriteBinaryVertex3D(t.p3, stream);
WriteBinaryMaterial(t.material, stream);
WriteBinaryString<1>(t.tex1Name, stream);
WriteBinaryString<1>(t.tex2Name, stream);
WriteBinaryBool(t.variableTex2, stream);
WriteBinary<4, int>(t.state, stream);
}
}
void ModelOutput::WriteOldModel(const CModel& model, std::ostream &stream)
{
const CModelMesh* mesh = model.GetMesh("main");
if (mesh == nullptr)
throw CModelIOException("No main mesh found in model");
OldModelHeader header;
header.revision = 1;
header.version = 2;
header.totalTriangles = mesh->GetTriangleCount();
WriteBinary<4, int>(header.revision, stream);
WriteBinary<4, int>(header.version, stream);
WriteBinary<4, int>(header.totalTriangles, stream);
for (int i = 0; i < 10; ++i)
WriteBinary<4, int>(header.reserved[i], stream);
for (const ModelTriangle& triangle : mesh->GetTriangles())
{
OldModelTriangleV3 t;
t.used = true;
t.p1 = triangle.p1;
t.p2 = triangle.p2;
t.p3 = triangle.p3;
t.material.ambient = triangle.ambient;
t.material.diffuse = triangle.diffuse;
t.material.specular = triangle.specular;
strncpy(t.texName, triangle.tex1Name.c_str(), sizeof(t.texName)-1);
t.texName[sizeof(t.texName)-1] = '\0';
t.min = 0.0f;
t.max = 1000000.0f;
t.state = ConvertToOldState(triangle);
int no = 0;
if (triangle.variableTex2)
no = 1;
else
std::sscanf(triangle.tex2Name.c_str(), "dirty%d.png", &no);
t.texNum2 = no;
WriteBinary<1, char>(t.used, stream);
WriteBinary<1, char>(t.selected, stream);
/* padding */ WriteBinary<2, unsigned int>(0, stream);
WriteBinaryVertex3D(t.p1, stream);
WriteBinaryVertex3D(t.p2, stream);
WriteBinaryVertex3D(t.p3, stream);
WriteBinaryMaterial(t.material, stream);
stream.write(t.texName, 20);
WriteBinaryFloat(t.min, stream);
WriteBinaryFloat(t.max, stream);
WriteBinary<4, long>(t.state, stream);
WriteBinary<2, short>(t.texNum2, stream);
WriteBinary<2, short>(t.reserved2, stream);
WriteBinary<2, short>(t.reserved3, stream);
WriteBinary<2, short>(t.reserved4, stream);
}
}
int ModelOutput::ConvertToOldState(const ModelTriangle& triangle)
{
int state = 0;
switch (triangle.transparentMode)
{
case ModelTransparentMode::None:
break;
case ModelTransparentMode::AlphaChannel:
state |= static_cast<int>(ModelRenderState::Alpha);
break;
case ModelTransparentMode::MapBlackToAlpha:
state |= static_cast<int>(ModelRenderState::TTextureBlack);
break;
case ModelTransparentMode::MapWhiteToAlpha:
state |= static_cast<int>(ModelRenderState::TTextureWhite);
break;
}
switch (triangle.specialMark)
{
case ModelSpecialMark::None:
break;
case ModelSpecialMark::Part1:
state |= static_cast<int>(ModelRenderState::Part1);
break;
case ModelSpecialMark::Part2:
state |= static_cast<int>(ModelRenderState::Part2);
break;
case ModelSpecialMark::Part3:
state |= static_cast<int>(ModelRenderState::Part3);
break;
}
if (triangle.doubleSided)
state |= static_cast<int>(ModelRenderState::TwoFace);
return state;
}
void ModelOutput::WriteBinaryVertex3D(const Vertex3D& vertex, std::ostream &stream)
{
WriteBinaryFloat(vertex.position.x, stream);
WriteBinaryFloat(vertex.position.y, stream);
WriteBinaryFloat(vertex.position.z, stream);
WriteBinaryFloat(vertex.normal.x, stream);
WriteBinaryFloat(vertex.normal.y, stream);
WriteBinaryFloat(vertex.normal.z, stream);
WriteBinaryFloat(vertex.uv.x, stream);
WriteBinaryFloat(vertex.uv.y, stream);
WriteBinaryFloat(vertex.uv2.x, stream);
WriteBinaryFloat(vertex.uv2.y, stream);
}
void ModelOutput::WriteBinaryMaterial(const Material& material, std::ostream &stream)
{
WriteBinaryFloat(material.diffuse.r, stream);
WriteBinaryFloat(material.diffuse.g, stream);
WriteBinaryFloat(material.diffuse.b, stream);
WriteBinaryFloat(material.diffuse.a, stream);
WriteBinaryFloat(material.ambient.r, stream);
WriteBinaryFloat(material.ambient.g, stream);
WriteBinaryFloat(material.ambient.b, stream);
WriteBinaryFloat(material.ambient.a, stream);
WriteBinaryFloat(material.specular.r, stream);
WriteBinaryFloat(material.specular.g, stream);
WriteBinaryFloat(material.specular.b, stream);
WriteBinaryFloat(material.specular.a, stream);
/* emissive.r */ WriteBinaryFloat(0.0f, stream);
/* emissive.g */ WriteBinaryFloat(0.0f, stream);
/* emissive.b */ WriteBinaryFloat(0.0f, stream);
/* emissive.a */ WriteBinaryFloat(0.0f, stream);
/* power */ WriteBinaryFloat(0.0f, stream);
}
void ModelOutput::WriteTextVertex3D(const Vertex3D& vertex, std::ostream &stream)
{
stream << "c " << vertex.position.x << " " << vertex.position.y << " " << vertex.position.z;
stream << " n " << vertex.normal.x << " " << vertex.normal.y << " " << vertex.normal.z;
stream << " t1 " << vertex.uv.x << " " << vertex.uv.y;
stream << " t2 " << vertex.uv2.x << " " << vertex.uv2.y;
stream << std::endl;
}
void ModelOutput::WriteTextMaterial(const Material& material, std::ostream &stream)
{
stream << "dif " << material.diffuse.r
<< " " << material.diffuse.g
<< " " << material.diffuse.b
<< " " << material.diffuse.a;
stream << " amb " << material.ambient.r
<< " " << material.ambient.g
<< " " << material.ambient.b
<< " " << material.ambient.a;
stream << " spc " << material.specular.r
<< " " << material.specular.g << " "
<< material.specular.b << " "
<< material.specular.a;
stream << std::endl;
}
} // namespace Gfx

View File

@ -65,12 +65,6 @@ struct ModelTriangle
Vertex3D p2;
//! 3rd vertex
Vertex3D p3;
//! Diffuse color
Color diffuse;
//! Ambient color
Color ambient;
//! Specular color
Color specular;
//! Name of 1st texture
std::string tex1Name;
//! Name of 2nd texture

View File

@ -393,24 +393,16 @@ Error CAutoPortico::GetError()
void CAutoPortico::UpdateTrackMapping(float left, float right)
{
Gfx::Material mat;
mat.diffuse.r = 1.0f;
mat.diffuse.g = 1.0f;
mat.diffuse.b = 1.0f; // blank
mat.ambient.r = 0.5f;
mat.ambient.g = 0.5f;
mat.ambient.b = 0.5f;
int rank = m_object->GetObjectRank(0);
std::string teamStr = StrUtils::ToString<int>(m_object->GetTeam());
if(m_object->GetTeam() == 0) teamStr = "";
m_engine->TrackTextureMapping(rank, mat, Gfx::ENG_RSTATE_PART1, "objects/lemt.png"+teamStr, "",
m_engine->TrackTextureMapping(rank, Gfx::ENG_RSTATE_PART1, "objects/lemt.png"+teamStr, "",
Gfx::EngineTextureMapping::X,
right, 8.0f, 8.0f, 192.0f, 256.0f);
m_engine->TrackTextureMapping(rank, mat, Gfx::ENG_RSTATE_PART2, "objects/lemt.png"+teamStr, "",
m_engine->TrackTextureMapping(rank, Gfx::ENG_RSTATE_PART2, "objects/lemt.png"+teamStr, "",
Gfx::EngineTextureMapping::X,
left, 8.0f, 8.0f, 192.0f, 256.0f);
}

View File

@ -1978,10 +1978,6 @@ bool CMotionVehicle::EventFrameCanoni(const Event &event)
void CMotionVehicle::UpdateTrackMapping(float left, float right, ObjectType type)
{
Gfx::Material mat;
mat.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f); // white
mat.ambient = Gfx::Color(0.5f, 0.5f, 0.5f);
int rRank = m_object->GetObjectRank(6);
int lRank = m_object->GetObjectRank(7);
@ -1990,21 +1986,21 @@ void CMotionVehicle::UpdateTrackMapping(float left, float right, ObjectType type
if (type == OBJECT_MOBILEdr)
{
m_engine->TrackTextureMapping(rRank, mat, Gfx::ENG_RSTATE_PART1, "objects/drawer.png"+teamStr, "",
m_engine->TrackTextureMapping(rRank, Gfx::ENG_RSTATE_PART1, "objects/drawer.png"+teamStr, "",
Gfx::EngineTextureMapping::X,
right, 1.0f, 8.0f, 192.0f, 256.0f);
m_engine->TrackTextureMapping(lRank, mat, Gfx::ENG_RSTATE_PART2, "objects/drawer.png"+teamStr, "",
m_engine->TrackTextureMapping(lRank, Gfx::ENG_RSTATE_PART2, "objects/drawer.png"+teamStr, "",
Gfx::EngineTextureMapping::X,
left, 1.0f, 8.0f, 192.0f, 256.0f);
}
else
{
m_engine->TrackTextureMapping(rRank, mat, Gfx::ENG_RSTATE_PART1, "objects/lemt.png"+teamStr, "",
m_engine->TrackTextureMapping(rRank, Gfx::ENG_RSTATE_PART1, "objects/lemt.png"+teamStr, "",
Gfx::EngineTextureMapping::X,
right, 1.0f, 8.0f, 192.0f, 256.0f);
m_engine->TrackTextureMapping(lRank, mat, Gfx::ENG_RSTATE_PART2, "objects/lemt.png"+teamStr, "",
m_engine->TrackTextureMapping(lRank, Gfx::ENG_RSTATE_PART2, "objects/lemt.png"+teamStr, "",
Gfx::EngineTextureMapping::X,
left, 1.0f, 8.0f, 192.0f, 256.0f);
}

View File

@ -2011,10 +2011,6 @@ void COldObject::UpdateEnergyMapping()
m_lastEnergy = GetEnergyLevel();
Gfx::Material mat;
mat.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f); // white
mat.ambient = Gfx::Color(0.5f, 0.5f, 0.5f);
float a = 0.0f, b = 0.0f;
if ( m_type == OBJECT_POWER ||
@ -2043,7 +2039,7 @@ void COldObject::UpdateEnergyMapping()
std::string teamStr = StrUtils::ToString<int>(GetTeam());
if(GetTeam() == 0) teamStr = "";
m_engine->ChangeTextureMapping(m_objectPart[0].object,
mat, Gfx::ENG_RSTATE_PART3, "objects/lemt.png"+teamStr, "",
Gfx::ENG_RSTATE_PART3, "objects/lemt.png"+teamStr, "",
Gfx::EngineTextureMapping::ONE_Y,
au, bu, 1.0f, 0.0f);
}