finished material and mesh serialisation, added model class
This commit is contained in:
parent
116a5e3d1a
commit
66784724d8
198
src/mesh.cpp
198
src/mesh.cpp
@ -78,7 +78,7 @@ void Mesh::initGL()
|
||||
{
|
||||
auto posBuffer = new TBuffer<glm::vec3>(positions3D, Buffer::VBO);
|
||||
posBuffer->setVertexAttrib(0, 3);
|
||||
addBuffer(posBuffer, POSITION_BUFFER);
|
||||
addBuffer(posBuffer, POSITION3D_BUFFER);
|
||||
|
||||
// init normals vbo
|
||||
if(!normals.empty())
|
||||
@ -100,7 +100,7 @@ void Mesh::initGL()
|
||||
{
|
||||
auto posBuffer = new TBuffer<glm::vec2>(positions2D, Buffer::VBO);
|
||||
posBuffer->setVertexAttrib(0, 2);
|
||||
addBuffer(posBuffer, POSITION_BUFFER);
|
||||
addBuffer(posBuffer, POSITION2D_BUFFER);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -184,22 +184,33 @@ void Mesh::destroyGL()
|
||||
clearBuffers();
|
||||
}
|
||||
|
||||
void Mesh::clearData()
|
||||
{
|
||||
positions3D.clear();
|
||||
normals.clear();
|
||||
tangents.clear();
|
||||
positions2D.clear();
|
||||
texCoords.clear();
|
||||
instances_offsets.clear();
|
||||
indices.clear();
|
||||
}
|
||||
|
||||
unsigned int Mesh::getFlags()
|
||||
{
|
||||
unsigned int flags = material->getFlags();
|
||||
|
||||
if(!indices.empty())
|
||||
if(!(indices.empty() || buffersId[INDICES_BUFFER] == -1))
|
||||
flags |= 1 << MESH_INDEXED;
|
||||
if(!texCoords.empty())
|
||||
if(!(texCoords.empty() || buffersId[TEXCOORD_BUFFER] == -1))
|
||||
flags |= 1 << MESH_TEXTURABLE;
|
||||
if(!instances_offsets.empty())
|
||||
if(!(instances_offsets.empty() || buffersId[INSTANCE_BUFFER] == -1))
|
||||
flags |= 1 << MESH_INSTANCED;
|
||||
|
||||
if(!positions3D.empty())
|
||||
if(!(positions3D.empty() || buffersId[POSITION3D_BUFFER] == -1))
|
||||
{
|
||||
flags |= 1 << MESH_3D;
|
||||
|
||||
if(!tangents.empty())
|
||||
if((!tangents.empty() || buffersId[TANGENT_BUFFER] == -1))
|
||||
flags |= 1 << MESH_TANGENT_SPACE;
|
||||
if(isDoubleSided)
|
||||
flags |= 1 << MESH_DOUBLE_SIDED;
|
||||
@ -399,3 +410,176 @@ void Mesh::computeBoundingBox(glm::vec3 &min, glm::vec3 &max)
|
||||
max.z = pos.z;
|
||||
}
|
||||
}
|
||||
|
||||
// serialisation methods
|
||||
|
||||
struct MeshHeader
|
||||
{
|
||||
unsigned int flags;
|
||||
int nbPositions;
|
||||
int depth;
|
||||
int nbInstances_offsets;
|
||||
int nbIndices;
|
||||
int nameLength;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool writeBuffer(const std::vector<T> &vec, std::FILE *file)
|
||||
{
|
||||
size_t nbWritten = std::fwrite(vec.data(), sizeof(T), vec.size(), file);
|
||||
return (nbWritten == vec.size());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool readBuffer(std::vector<T> &vec, std::FILE *file)
|
||||
{
|
||||
size_t nbRead = std::fread(vec.data(), sizeof(T), vec.size(), file);
|
||||
return (nbRead == vec.size());
|
||||
}
|
||||
|
||||
bool Mesh::serialize(Mesh* mesh, FILE *file)
|
||||
{
|
||||
// creating header
|
||||
MeshHeader header;
|
||||
header.flags = mesh->getFlags();
|
||||
if(header.flags & (1 << Mesh::MESH_3D))
|
||||
header.nbPositions = mesh->positions3D.size();
|
||||
else
|
||||
{
|
||||
header.nbPositions = mesh->positions2D.size();
|
||||
header.depth = mesh->getDepth();
|
||||
}
|
||||
header.nbIndices = mesh->indices.size();
|
||||
header.nbInstances_offsets = mesh->instances_offsets.size();
|
||||
header.nameLength = mesh->getName().size();
|
||||
|
||||
if(header.nbPositions == 0)
|
||||
return false;
|
||||
|
||||
// writing header
|
||||
size_t nbWritten;
|
||||
|
||||
nbWritten = std::fwrite(&header, sizeof(MeshHeader), 1, file);
|
||||
if(nbWritten != 1)
|
||||
return false;
|
||||
|
||||
if(header.nameLength != 0)
|
||||
{
|
||||
nbWritten = std::fwrite(mesh->getName().data(), header.nameLength, 1, file);
|
||||
if(nbWritten != 1)
|
||||
return false;
|
||||
}
|
||||
|
||||
// writing buffers
|
||||
if(header.flags & (1 << Mesh::MESH_3D))
|
||||
{
|
||||
if(!writeBuffer(mesh->positions3D, file))
|
||||
return false;
|
||||
if(mesh->normals.size() == 0)
|
||||
mesh->computeNormals();
|
||||
if(!writeBuffer(mesh->normals, file))
|
||||
return false;
|
||||
if(header.flags & (1 << Mesh::MESH_TANGENT_SPACE))
|
||||
{
|
||||
if(!writeBuffer(mesh->tangents, file))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!writeBuffer(mesh->positions2D, file))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(header.nbInstances_offsets)
|
||||
{
|
||||
if(!writeBuffer(mesh->instances_offsets, file))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(header.nbIndices)
|
||||
{
|
||||
if(!writeBuffer(mesh->indices, file))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(header.flags & (1 << Mesh::MESH_TEXTURABLE))
|
||||
{
|
||||
if(!writeBuffer(mesh->texCoords, file))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Mesh* Mesh::deserialize(FILE *file)
|
||||
{
|
||||
MeshHeader header;
|
||||
size_t nbRead = std::fread(&header, sizeof(MeshHeader), 1, file);
|
||||
|
||||
// deserializing mesh
|
||||
Mesh *mesh = NULL;
|
||||
if(nbRead == 1 && header.nbPositions != 0)
|
||||
mesh = new Mesh();
|
||||
else
|
||||
return NULL;
|
||||
|
||||
std::string name = "mesh";
|
||||
if(header.nameLength != 0)
|
||||
{
|
||||
name.resize(header.nameLength);
|
||||
if(!fread(&(name[0]), header.nameLength, 1, file))
|
||||
{ delete(mesh); return NULL; }
|
||||
}
|
||||
mesh->setName(name);
|
||||
|
||||
if(header.flags & (1 << Mesh::MESH_3D))
|
||||
{
|
||||
mesh->positions3D.reserve(header.nbPositions);
|
||||
if(!readBuffer(mesh->positions3D, file))
|
||||
{ delete(mesh); return NULL; }
|
||||
mesh->normals.reserve(header.nbPositions);
|
||||
if(!readBuffer(mesh->normals, file))
|
||||
{ delete(mesh); return NULL; }
|
||||
if(header.flags & (1 << Mesh::MESH_TANGENT_SPACE))
|
||||
{
|
||||
mesh->tangents.reserve(header.nbPositions);
|
||||
if(!readBuffer(mesh->tangents, file))
|
||||
{ delete(mesh); return NULL; }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh->positions2D.reserve(header.nbPositions);
|
||||
if(!readBuffer(mesh->positions2D, file))
|
||||
{ delete(mesh); return NULL; }
|
||||
mesh->setDepth(header.depth);
|
||||
}
|
||||
|
||||
if(header.nbInstances_offsets)
|
||||
{
|
||||
mesh->instances_offsets.reserve(header.nbInstances_offsets);
|
||||
if(!readBuffer(mesh->instances_offsets, file))
|
||||
{ delete(mesh); return NULL; }
|
||||
}
|
||||
|
||||
if(header.nbIndices)
|
||||
{
|
||||
mesh->indices.reserve(header.nbIndices);
|
||||
if(!readBuffer(mesh->indices, file))
|
||||
{ delete(mesh); return NULL; }
|
||||
}
|
||||
|
||||
if(header.flags & (1 << Mesh::MESH_TEXTURABLE))
|
||||
{
|
||||
mesh->texCoords.reserve(header.nbPositions);
|
||||
if(!readBuffer(mesh->texCoords, file))
|
||||
{ delete(mesh); return NULL; }
|
||||
}
|
||||
|
||||
mesh->setIsBillboard(header.flags & (1 << Mesh::MESH_BILLBOARD));
|
||||
mesh->setIsDoubleSided(header.flags & (1 << Mesh::MESH_DOUBLE_SIDED));
|
||||
mesh->setIsShadowCaster(header.flags & (1 << Mesh::MESH_SHADOWED));
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
26
src/mesh.h
26
src/mesh.h
@ -103,6 +103,11 @@ public:
|
||||
void draw(Shader* shader, bool drawNormals = true, bool drawTexCoord = true, bool drawTangents = true);
|
||||
void destroyGL();
|
||||
|
||||
/**
|
||||
* @brief clearData clears all data vectors, but keeps GPU data allocated.
|
||||
*/
|
||||
void clearData();
|
||||
|
||||
/**
|
||||
* @brief getFlags returns the flags that defines the specificities of the mesh and his material
|
||||
*/
|
||||
@ -197,6 +202,24 @@ public:
|
||||
*/
|
||||
void computeBoundingBox(glm::vec3 &min, glm::vec3 &max);
|
||||
|
||||
/*************************************************************/
|
||||
/* SERIALISATION */
|
||||
/*************************************************************/
|
||||
|
||||
/**
|
||||
* @brief serializeMesh can be used to save a mesh
|
||||
* @return true if the mesh has succesfully been saved
|
||||
*/
|
||||
static bool serialize(Mesh* mesh, FILE *file);
|
||||
|
||||
bool serialize(FILE *file) { return serialize(this, file); }
|
||||
|
||||
/**
|
||||
* @brief deserializeMesh can be used to load a mesh
|
||||
* @return the loaded mesh of NULL if a reading error has occured
|
||||
*/
|
||||
static Mesh* deserialize(FILE *file);
|
||||
|
||||
/*************************************************************/
|
||||
/* ADVANCED CUSTOMISATION */
|
||||
/*************************************************************/
|
||||
@ -224,7 +247,8 @@ protected:
|
||||
|
||||
enum {
|
||||
// required buffer
|
||||
POSITION_BUFFER,
|
||||
POSITION2D_BUFFER,
|
||||
POSITION3D_BUFFER,
|
||||
|
||||
// indices buffers
|
||||
INDICES_BUFFER,
|
||||
|
116
src/model.cpp
Normal file
116
src/model.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
#include "model.h"
|
||||
#include "mesh.h"
|
||||
#include "image.h"
|
||||
#include "texture.h"
|
||||
#include "phongmaterial.h"
|
||||
|
||||
Model::~Model()
|
||||
{
|
||||
destroy();
|
||||
destroyGL();
|
||||
for(Mesh *m : m_meshes)
|
||||
delete m;
|
||||
}
|
||||
|
||||
Image* Model::getImage(const std::string &name)
|
||||
{
|
||||
for(TextureImg &tex : m_textures)
|
||||
{
|
||||
if(name.compare(tex.name) == 0)
|
||||
return tex.img;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Texture* Model::getTexture(const std::string &name)
|
||||
{
|
||||
for(TextureImg &tex : m_textures)
|
||||
{
|
||||
if(name.compare(tex.name) == 0)
|
||||
return tex.tex;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Model::destroy()
|
||||
{
|
||||
for(Mesh* m : m_meshes)
|
||||
m->clearData();
|
||||
for(TextureImg &tex : m_textures)
|
||||
{
|
||||
delete tex.img;
|
||||
tex.img = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Model::initGL()
|
||||
{
|
||||
for(Mesh* m : m_meshes)
|
||||
m->initGL();
|
||||
for(TextureImg &tex : m_textures)
|
||||
{
|
||||
if(tex.tex == NULL)
|
||||
tex.tex = new Texture(tex.img);
|
||||
}
|
||||
}
|
||||
|
||||
void Model::destroyGL()
|
||||
{
|
||||
for(Mesh* m : m_meshes)
|
||||
m->destroyGL();
|
||||
for(TextureImg &tex : m_textures)
|
||||
{
|
||||
if(tex.tex != NULL)
|
||||
{
|
||||
delete tex.tex;
|
||||
tex.tex = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Model::save(const std::string &filename, const std::string &texturesPath)
|
||||
{
|
||||
// open file
|
||||
std::FILE *file = std::fopen(filename.c_str(), "w");
|
||||
if(file == NULL)
|
||||
return false;
|
||||
|
||||
bool ok = false;
|
||||
int size = m_meshes.size();
|
||||
if(std::fwrite(&size, sizeof(int), 1, file))
|
||||
{
|
||||
ok = true;
|
||||
for(Mesh* m : m_meshes)
|
||||
{
|
||||
ok = ok && m->serialize(file);
|
||||
PhongMaterial* mat = (PhongMaterial*)m->getMaterial();
|
||||
ok = ok && mat->serialize(file);
|
||||
}
|
||||
for(Model::TextureImg &texImg : m_textures)
|
||||
{
|
||||
std::string texFilename = texturesPath + texImg.name + ".png";
|
||||
if(texImg.img == NULL && texImg.tex != NULL)
|
||||
texImg.img = texImg.tex->getData();
|
||||
if(texImg.img != NULL)
|
||||
ok = ok && texImg.img->save(texFilename);
|
||||
}
|
||||
std::fclose(file);
|
||||
}
|
||||
|
||||
// finishing
|
||||
return ok;
|
||||
}
|
||||
|
||||
Model* Model::load(const std::string &filename, const std::string &texturesPath)
|
||||
{
|
||||
// open file
|
||||
std::FILE *file = std::fopen(filename.c_str(), "r");
|
||||
if(file == NULL)
|
||||
return NULL;
|
||||
|
||||
bool ok = false;
|
||||
|
||||
|
||||
// finishing
|
||||
return NULL;
|
||||
}
|
90
src/model.h
Normal file
90
src/model.h
Normal file
@ -0,0 +1,90 @@
|
||||
#ifndef MODEL_H
|
||||
#define MODEL_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class Mesh;
|
||||
class Image;
|
||||
class Texture;
|
||||
|
||||
class Model
|
||||
{
|
||||
protected:
|
||||
struct TextureImg
|
||||
{
|
||||
std::string name;
|
||||
Texture* tex;
|
||||
Image* img;
|
||||
|
||||
TextureImg(const std::string n, Image* i) :
|
||||
name(n), tex(NULL), img(i) {}
|
||||
};
|
||||
|
||||
std::vector<Mesh*> m_meshes;
|
||||
std::vector<TextureImg> m_textures;
|
||||
|
||||
public:
|
||||
~Model();
|
||||
|
||||
/**
|
||||
* @brief addMesh adds a mesh to the mesh list
|
||||
*/
|
||||
void addMesh(Mesh *mesh) { m_meshes.push_back(mesh); }
|
||||
|
||||
/**
|
||||
* @brief addImage adds an image to the texture pack
|
||||
*/
|
||||
void addImage(const std::string &name, Image* img)
|
||||
{
|
||||
m_textures.push_back(TextureImg(name, img));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getMeshes returns the mesh array
|
||||
*/
|
||||
const std::vector<Mesh*>& getMeshes() { return m_meshes; }
|
||||
|
||||
/**
|
||||
* @brief getImage returns the image which has the specified name, or NULL if there are no images of this name.
|
||||
*/
|
||||
Image* getImage(const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief getTexture returns the texture which has the specified name, or NULL if there are no images of this name.
|
||||
*/
|
||||
Texture* getTexture(const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief destroy frees Mesh and Image memory in the RAM, but it stays allocated in GPU memory.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* @brief initGL uploads image and mesh data to GPU memory
|
||||
*/
|
||||
void initGL();
|
||||
|
||||
/**
|
||||
* @brief destroyGL frees the meshes and the textures from GPU memory
|
||||
*/
|
||||
void destroyGL();
|
||||
|
||||
/**
|
||||
* @brief save saves the model on a file
|
||||
* @param filename is the name of the resulting file
|
||||
* @param texturesPath is the existing folder where the textures will be saved
|
||||
* @return true if the save succeeded
|
||||
*/
|
||||
bool save(const std::string &filename, const std::string &texturesPath);
|
||||
|
||||
/**
|
||||
* @brief load loads the model from a file
|
||||
* @param filename is the name of the target file
|
||||
* @param texturesPath is the existing folder where the textures will be gathered
|
||||
* @return the model if the loading succeeded, or NULL if it failed
|
||||
*/
|
||||
static Model* load(const std::string &filename, const std::string &texturesPath);
|
||||
};
|
||||
|
||||
#endif // MODEL_H
|
@ -64,3 +64,76 @@ unsigned int PhongMaterial::getFlags()
|
||||
return flags;
|
||||
}
|
||||
|
||||
// serialisation methods :
|
||||
|
||||
struct MaterialHeader
|
||||
{
|
||||
glm::vec3 emission;
|
||||
glm::vec3 diffuse;
|
||||
glm::vec3 specular;
|
||||
float shininess;
|
||||
int textureLengths[PhongMaterial::NB_PHONG_SLOTS];
|
||||
};
|
||||
|
||||
bool PhongMaterial::serialize(PhongMaterial* mat, FILE *file)
|
||||
{
|
||||
unsigned int flags = mat->getFlags();
|
||||
|
||||
if(!fwrite(&flags, sizeof(unsigned int), 1, file))
|
||||
return false;
|
||||
|
||||
if(flags & (1 << Mesh::MATERIAL_PHONG))
|
||||
{
|
||||
MaterialHeader header;
|
||||
header.emission = mat->emission;
|
||||
header.diffuse = mat->diffuse;
|
||||
header.specular = mat->specular;
|
||||
header.shininess = mat->shininess;
|
||||
|
||||
for(int i=0; i<PhongMaterial::NB_PHONG_SLOTS; ++i)
|
||||
{
|
||||
if(mat->textures[i] != NULL)
|
||||
header.textureLengths[i] = mat->textureNames[i].length()+1;
|
||||
}
|
||||
|
||||
if(!std::fwrite(&header, sizeof(MaterialHeader), 1, file))
|
||||
return false;
|
||||
for(int i=0; i<PhongMaterial::NB_PHONG_SLOTS; ++i)
|
||||
{
|
||||
if(header.textureLengths[i] > 0)
|
||||
{
|
||||
if(!std::fwrite(mat->textureNames[i].c_str(), header.textureLengths[i], 1, file))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PhongMaterial* PhongMaterial::deserialize(FILE *file)
|
||||
{
|
||||
int flags;
|
||||
if(!std::fread(&flags, sizeof(int), 1, file))
|
||||
return NULL;
|
||||
|
||||
MaterialHeader header;
|
||||
if(!std::fread(&header, sizeof(MaterialHeader), 1, file))
|
||||
return NULL;
|
||||
|
||||
PhongMaterial *mat = new PhongMaterial();
|
||||
|
||||
mat->diffuse = header.diffuse;
|
||||
mat->emission = header.emission;
|
||||
mat->specular = header.specular;
|
||||
mat->shininess = header.shininess;
|
||||
for(int i=0; i<PhongMaterial::NB_PHONG_SLOTS; ++i)
|
||||
{
|
||||
char str[256];
|
||||
if(!std::fread(str, header.textureLengths[i], 1, file))
|
||||
{ delete mat; return NULL; }
|
||||
mat->textureNames[i] = std::string(str);
|
||||
}
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
@ -44,6 +44,21 @@ struct PhongMaterial : public Material
|
||||
virtual void bindAttributes(Shader* myShader);
|
||||
|
||||
virtual unsigned int getFlags();
|
||||
|
||||
/**
|
||||
* @brief serializeMaterial saves a material to a file
|
||||
* @return true if the save succeeded
|
||||
*/
|
||||
static bool serialize(PhongMaterial* mat, FILE *file);
|
||||
bool serialize(FILE *file) { return serialize(this, file); }
|
||||
|
||||
/**
|
||||
* @brief deserializeMaterial creates a material from reading a file,
|
||||
* be careful, this method has no way to load the attached textures, so you must do it manually,
|
||||
* however, you can use the texture names stored in the textureNames array to find which textures are requested.
|
||||
* @return the material or NULL if the loading failed
|
||||
*/
|
||||
static PhongMaterial* deserialize(FILE *file);
|
||||
};
|
||||
|
||||
#endif // PHONGMATERIAL_H
|
||||
|
@ -1,291 +0,0 @@
|
||||
#include "serializers.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "mesh.h"
|
||||
#include "light.h"
|
||||
#include "texture.h"
|
||||
#include "phongmaterial.h"
|
||||
|
||||
namespace serializers
|
||||
{
|
||||
|
||||
// STRUCTS
|
||||
|
||||
struct MeshHeader
|
||||
{
|
||||
unsigned int flags;
|
||||
int nbPositions;
|
||||
int depth;
|
||||
int nbInstances_offsets;
|
||||
int nbIndices;
|
||||
int nameLength;
|
||||
};
|
||||
|
||||
struct MaterialHeader
|
||||
{
|
||||
glm::vec3 emission;
|
||||
glm::vec3 diffuse;
|
||||
glm::vec3 specular;
|
||||
float shininess;
|
||||
};
|
||||
|
||||
struct LightHeader
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// PRIVATE FUNCTIONS
|
||||
|
||||
bool serializeMesh(Mesh* mesh, const MeshHeader &header, FILE *file);
|
||||
|
||||
bool deserializeMesh(Mesh* mesh, const MeshHeader &header, FILE *file);
|
||||
|
||||
bool serializeMaterial(Material* material, FILE *file);
|
||||
|
||||
Material* deserializeMaterial(FILE *file);
|
||||
|
||||
template<typename T>
|
||||
bool writeBuffer(const std::vector<T> &vec, std::FILE *file);
|
||||
|
||||
template<typename T>
|
||||
bool readBuffer(std::vector<T> &vec, std::FILE *file);
|
||||
|
||||
// IMPLEMENTATIONS
|
||||
|
||||
template<typename T>
|
||||
bool writeBuffer(const std::vector<T> &vec, std::FILE *file)
|
||||
{
|
||||
size_t nbWritten = std::fwrite(vec.data(), sizeof(T), vec.size(), file);
|
||||
return (nbWritten == vec.size());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool readBuffer(std::vector<T> &vec, std::FILE *file)
|
||||
{
|
||||
size_t nbRead = std::fread(vec.data(), sizeof(T), vec.size(), file);
|
||||
return (nbRead == vec.size());
|
||||
}
|
||||
|
||||
bool saveMesh(const std::string &filename, Mesh *mesh)
|
||||
{
|
||||
// open file
|
||||
std::FILE *file = std::fopen(filename.c_str(), "w");
|
||||
if(file == NULL)
|
||||
return false;
|
||||
|
||||
// creating header
|
||||
MeshHeader header;
|
||||
header.flags = mesh->getFlags();
|
||||
if(header.flags & (1 << Mesh::MESH_3D))
|
||||
header.nbPositions = mesh->positions3D.size();
|
||||
else
|
||||
{
|
||||
mesh->positions2D.size();
|
||||
header.depth = mesh->getDepth();
|
||||
}
|
||||
header.nbIndices = mesh->indices.size();
|
||||
header.nbInstances_offsets = mesh->instances_offsets.size();
|
||||
header.nameLength = mesh->getName().size();
|
||||
|
||||
// serializing
|
||||
bool ok = false;
|
||||
if(header.nbPositions != 0)
|
||||
ok = serializeMesh(mesh, header, file);
|
||||
|
||||
// finishing
|
||||
std::fclose(file);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool serializeMesh(Mesh* mesh, const MeshHeader &header, FILE *file)
|
||||
{
|
||||
// writing header
|
||||
size_t nbWritten;
|
||||
|
||||
nbWritten = std::fwrite(&header, sizeof(MeshHeader), 1, file);
|
||||
if(nbWritten != 1)
|
||||
return false;
|
||||
|
||||
if(header.nameLength != 0)
|
||||
{
|
||||
nbWritten = std::fwrite(mesh->getName().data(), header.nameLength, 1, file);
|
||||
if(nbWritten != 1)
|
||||
return false;
|
||||
}
|
||||
|
||||
// writing buffers
|
||||
if(header.flags & (1 << Mesh::MESH_3D))
|
||||
{
|
||||
if(!writeBuffer(mesh->positions3D, file))
|
||||
return false;
|
||||
if(mesh->normals.size() == 0)
|
||||
mesh->computeNormals();
|
||||
if(!writeBuffer(mesh->normals, file))
|
||||
return false;
|
||||
if(header.flags & (1 << Mesh::MESH_TANGENT_SPACE))
|
||||
{
|
||||
if(!writeBuffer(mesh->tangents, file))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!writeBuffer(mesh->positions2D, file))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(header.nbInstances_offsets)
|
||||
{
|
||||
if(!writeBuffer(mesh->instances_offsets, file))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(header.nbIndices)
|
||||
{
|
||||
if(!writeBuffer(mesh->indices, file))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(header.flags & (1 << Mesh::MESH_TEXTURABLE))
|
||||
{
|
||||
if(!writeBuffer(mesh->texCoords, file))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool serializeMaterial(Material* material, FILE *file)
|
||||
{
|
||||
unsigned int flags = material->getFlags();
|
||||
|
||||
if(!fwrite(&flags, sizeof(unsigned int), 1, file))
|
||||
return false;
|
||||
|
||||
if(flags & (1 << Mesh::MATERIAL_PHONG))
|
||||
{
|
||||
MaterialHeader header;
|
||||
PhongMaterial *mat = (PhongMaterial*)material;
|
||||
header.emission = mat->emission;
|
||||
header.diffuse = mat->diffuse;
|
||||
header.specular = mat->specular;
|
||||
header.shininess = mat->shininess;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool saveLight(const std::string &filename, Light *light)
|
||||
{
|
||||
std::FILE *file = std::fopen(filename.c_str(), "w");
|
||||
if(file == NULL)
|
||||
return false;
|
||||
|
||||
std::fclose(file);
|
||||
}
|
||||
|
||||
Mesh* loadMesh(const std::string &filename)
|
||||
{
|
||||
// open file
|
||||
std::FILE *file = std::fopen(filename.c_str(), "r");
|
||||
if(file == NULL)
|
||||
return NULL;
|
||||
|
||||
// reading header
|
||||
MeshHeader header;
|
||||
size_t nbRead = std::fread(&header, sizeof(MeshHeader), 1, file);
|
||||
|
||||
// deserializing mesh
|
||||
bool ok = false;
|
||||
Mesh *mesh = NULL;
|
||||
if(nbRead == 1 && header.nbPositions != 0)
|
||||
{
|
||||
mesh = new Mesh();
|
||||
ok = deserializeMesh(mesh, header, file);
|
||||
}
|
||||
|
||||
// finishing
|
||||
std::fclose(file);
|
||||
|
||||
if(!ok && mesh != NULL)
|
||||
{
|
||||
delete mesh;
|
||||
mesh = NULL;
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
bool deserializeMesh(Mesh* mesh, const MeshHeader &header, FILE *file)
|
||||
{
|
||||
std::string name = "mesh";
|
||||
if(header.nameLength != 0)
|
||||
{
|
||||
name.resize(header.nameLength);
|
||||
if(!fread(&(name[0]), header.nameLength, 1, file))
|
||||
return false;
|
||||
}
|
||||
mesh->setName(name);
|
||||
|
||||
if(header.flags & (1 << Mesh::MESH_3D))
|
||||
{
|
||||
mesh->positions3D.reserve(header.nbPositions);
|
||||
if(!readBuffer(mesh->positions3D, file))
|
||||
return false;
|
||||
mesh->normals.reserve(header.nbPositions);
|
||||
if(!readBuffer(mesh->normals, file))
|
||||
return false;
|
||||
if(header.flags & (1 << Mesh::MESH_TANGENT_SPACE))
|
||||
{
|
||||
mesh->tangents.reserve(header.nbPositions);
|
||||
if(!readBuffer(mesh->tangents, file))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh->positions2D.reserve(header.nbPositions);
|
||||
if(!readBuffer(mesh->positions2D, file))
|
||||
return false;
|
||||
mesh->setDepth(header.depth);
|
||||
}
|
||||
|
||||
if(header.nbInstances_offsets)
|
||||
{
|
||||
mesh->instances_offsets.reserve(header.nbInstances_offsets);
|
||||
if(!readBuffer(mesh->instances_offsets, file))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(header.nbIndices)
|
||||
{
|
||||
mesh->indices.reserve(header.nbIndices);
|
||||
if(!readBuffer(mesh->indices, file))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(header.flags & (1 << Mesh::MESH_TEXTURABLE))
|
||||
{
|
||||
mesh->texCoords.reserve(header.nbPositions);
|
||||
if(!readBuffer(mesh->texCoords, file))
|
||||
return false;
|
||||
}
|
||||
|
||||
mesh->setIsBillboard(header.flags & (1 << Mesh::MESH_BILLBOARD));
|
||||
mesh->setIsDoubleSided(header.flags & (1 << Mesh::MESH_DOUBLE_SIDED));
|
||||
mesh->setIsShadowCaster(header.flags & (1 << Mesh::MESH_SHADOWED));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Material* deserializeMaterial(FILE *file)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Light* loadLight(const std::string &filename)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
#ifndef SERIALIZERS_H
|
||||
#define SERIALIZERS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class Mesh;
|
||||
class Light;
|
||||
class Texture;
|
||||
|
||||
namespace Serializers
|
||||
{
|
||||
bool saveMesh(const std::string &filename, Mesh *mesh);
|
||||
bool saveLight(const std::string &filename, Light *light);
|
||||
|
||||
Mesh* loadMesh(const std::string &filename);
|
||||
Light* loadLight(const std::string &filename);
|
||||
}
|
||||
|
||||
#endif // SERIALIZERS_H
|
Loading…
x
Reference in New Issue
Block a user