TDME2  1.9.200
TMWriter.cpp
Go to the documentation of this file.
2 
3 #include <array>
4 #include <memory>
5 #include <string>
6 #include <unordered_map>
7 #include <vector>
8 
9 #include <tdme/tdme.h>
13 #include <tdme/engine/Texture.h>
16 #include <tdme/engine/Color4.h>
17 #include <tdme/engine/model/Face.h>
23 #include <tdme/engine/model/Node.h>
33 #include <tdme/math/Matrix4x4.h>
34 #include <tdme/math/Vector2.h>
35 #include <tdme/math/Vector3.h>
39 #include <tdme/utilities/Console.h>
41 
42 using std::array;
43 using std::make_unique;
44 using std::string;
45 using std::to_string;
46 using std::unique_ptr;
47 using std::unordered_map;
48 using std::vector;
49 
83 
84 void TMWriter::write(Model* model, const string& pathName, const string& fileName, bool useBC7TextureCompression)
85 {
86  vector<uint8_t> data;
87  write(model, data, useBC7TextureCompression);
88  FileSystem::getInstance()->setContent(pathName, fileName, data);
89 }
90 
91 void TMWriter::write(Model* model, vector<uint8_t>& data, bool useBC7TextureCompression) {
92  TMWriterOutputStream os(&data);
93  os.writeString("TDME Model");
94  os.writeByte(static_cast<uint8_t>(1));
95  os.writeByte(static_cast<uint8_t>(9));
96  os.writeByte(static_cast<uint8_t>(20));
97  os.writeString(model->getName());
98  os.writeString(model->getUpVector()->getName());
99  os.writeString(model->getRotationOrder()->getName());
100  os.writeString(model->getShaderModel()->getName());
103  os.writeFloatArray(model->getBoundingBox()->getMin().getArray());
104  os.writeFloatArray(model->getBoundingBox()->getMax().getArray());
105  os.writeFloat(model->getFPS());
107  writeEmbeddedTextures(&os, model, useBC7TextureCompression);
108  os.writeInt(model->getMaterials().size());
109  for (const auto& [materialId, material]: model->getMaterials()) {
110  writeMaterial(&os, material);
111  }
112  writeSubNodes(&os, model->getSubNodes());
113  os.writeInt(model->getAnimationSetups().size());
114  for (const auto& [animationSetupId, animationSetup]: model->getAnimationSetups()) {
115  writeAnimationSetup(&os, animationSetup);
116  }
117  if (Application::hasApplication() == true && os.getData()->size() < 10 * 1024 * 1024) writeThumbnail(&os, model);
118 }
119 
120 void TMWriter::writeEmbeddedTextures(TMWriterOutputStream* os, Model* m, bool useBC7TextureCompression) {
121  unordered_map<string, Texture*> embeddedTextures;
122  for (const auto& [materialId, material]: m->getMaterials()) {
123  auto smp = material->getSpecularMaterialProperties();
124  if (smp != nullptr && m->hasEmbeddedSpecularTextures() == true) {
125  if (smp->getDiffuseTexture() != nullptr) embeddedTextures[smp->getDiffuseTexture()->getId()] = smp->getDiffuseTexture();
126  if (smp->getSpecularTexture() != nullptr) embeddedTextures[smp->getSpecularTexture()->getId()] = smp->getSpecularTexture();
127  if (smp->getNormalTexture() != nullptr) embeddedTextures[smp->getNormalTexture()->getId()] = smp->getNormalTexture();
128  }
129  auto pmp = material->getPBRMaterialProperties();
130  if (pmp != nullptr && m->hasEmbeddedPBRTextures() == true) {
131  if (pmp->getBaseColorTexture() != nullptr) embeddedTextures[pmp->getBaseColorTexture()->getId()] = pmp->getBaseColorTexture();
132  if (pmp->getMetallicRoughnessTexture() != nullptr) embeddedTextures[pmp->getMetallicRoughnessTexture()->getId()] = pmp->getMetallicRoughnessTexture();
133  if (pmp->getNormalTexture() != nullptr) embeddedTextures[pmp->getNormalTexture()->getId()] = pmp->getNormalTexture();
134  if (pmp->getEmissiveTexture() != nullptr) embeddedTextures[pmp->getEmissiveTexture()->getId()] = pmp->getEmissiveTexture();
135  }
136  }
137  os->writeInt(embeddedTextures.size());
138  for (const auto& [embeddedTextureId, embeddedTexture]: embeddedTextures) {
139  os->writeString(embeddedTexture->getId());
140  // optional PNG
141  if (useBC7TextureCompression == true) {
142  os->writeByte(3); // BC7 with mip maps
143  vector<uint8_t> bc7Data;
144  os->writeInt(embeddedTexture->getWidth());
145  os->writeInt(embeddedTexture->getHeight());
146  os->writeInt(embeddedTexture->getTextureWidth());
147  os->writeInt(embeddedTexture->getTextureHeight());
148  os->writeByte(embeddedTexture->getRGBDepthBitsPerPixel());
149  os->writeByte(embeddedTexture->getMinFilter());
150  os->writeByte(embeddedTexture->getMagFilter());
151  BC7TextureWriter::write(embeddedTexture->getTextureWidth(), embeddedTexture->getTextureHeight(), embeddedTexture->getRGBDepthBitsPerPixel() / 8, embeddedTexture->getRGBTextureData(), bc7Data);
152  os->writeInt(bc7Data.size());
153  os->writeUInt8tArray(bc7Data);
154  if (embeddedTexture->isUseMipMap() == false) {
155  os->writeByte(0);
156  } else {
157  auto mipMapTextures = embeddedTexture->getMipMapTextures(true);
158  os->writeByte(mipMapTextures.size());
159  for (const auto& mipMapTexture: mipMapTextures) {
160  os->writeByte(mipMapTexture.format);
161  os->writeInt(mipMapTexture.width);
162  os->writeInt(mipMapTexture.height);
163  os->writeInt(mipMapTexture.textureData.getBufferVector()->size());
164  os->writeUInt8tArray(*mipMapTexture.textureData.getBufferVector());
165  }
166  }
167  } else {
168  vector<uint8_t> pngData;
169  PNGTextureWriter::write(embeddedTexture, pngData, false, false);
170  os->writeByte(1); // PNG
171  os->writeByte(embeddedTexture->getMinFilter());
172  os->writeByte(embeddedTexture->getMagFilter());
173  os->writeInt(pngData.size());
174  os->writeUInt8tArray(pngData);
175  }
176  }
177 }
178 
180 {
181  // TODO: minFilter, magFilter for non embedded textures
182  auto smp = m->getSpecularMaterialProperties();
183  auto pmp = m->getPBRMaterialProperties();
184  os->writeString(m->getId());
185  os->writeFloatArray(smp->getAmbientColor().getArray());
186  os->writeFloatArray(smp->getDiffuseColor().getArray());
187  os->writeFloatArray(smp->getSpecularColor().getArray());
188  os->writeFloatArray(smp->getEmissionColor().getArray());
189  os->writeFloat(smp->getShininess());
190  os->writeInt(smp->getTextureAtlasSize());
191  os->writeString(smp->getDiffuseTexturePathName());
192  os->writeString(smp->getDiffuseTextureFileName());
193  os->writeString(smp->getDiffuseTransparencyTexturePathName());
194  os->writeString(smp->getDiffuseTransparencyTextureFileName());
195  os->writeString(smp->getSpecularTexturePathName());
196  os->writeString(smp->getSpecularTextureFileName());
197  os->writeString(smp->getNormalTexturePathName());
198  os->writeString(smp->getNormalTextureFileName());
199  os->writeBoolean(smp->hasDiffuseTextureTransparency());
200  os->writeBoolean(smp->hasDiffuseTextureMaskedTransparency());
201  os->writeFloat(smp->getDiffuseTextureMaskedTransparencyThreshold());
202  os->writeBoolean(m->isDoubleSided());
204  if (pmp == nullptr) {
205  os->writeBoolean(false);
206  } else {
207  os->writeBoolean(true);
208  os->writeFloatArray(pmp->getBaseColorFactor().getArray());
209  os->writeString(pmp->getBaseColorTexturePathName());
210  os->writeString(pmp->getBaseColorTextureFileName());
211  os->writeBoolean(pmp->hasBaseColorTextureMaskedTransparency());
212  os->writeFloat(pmp->getBaseColorTextureMaskedTransparencyThreshold());
213  os->writeFloat(pmp->getMetallicFactor());
214  os->writeFloat(pmp->getRoughnessFactor());
215  os->writeString(pmp->getMetallicRoughnessTexturePathName());
216  os->writeString(pmp->getMetallicRoughnessTextureFileName());
217  os->writeFloat(pmp->getNormalScale());
218  os->writeString(pmp->getNormalTexturePathName());
219  os->writeString(pmp->getNormalTextureFileName());
220  os->writeFloatArray(pmp->getEmissiveFactor().getArray());
221  os->writeString(pmp->getEmissiveTexturePathName());
222  os->writeString(pmp->getEmissiveTextureFileName());
223  os->writeFloat(pmp->getExposure());
224  }
225 }
226 
228  os->writeString(animationSetup->getId());
229  os->writeString(animationSetup->getOverlayFromNodeId());
230  os->writeInt(animationSetup->getStartFrame());
231  os->writeInt(animationSetup->getEndFrame());
232  os->writeBoolean(animationSetup->isLoop());
233  os->writeFloat(animationSetup->getSpeed());
234 }
235 
236 void TMWriter::writeVertices(TMWriterOutputStream* os, const vector<Vector3>& v)
237 {
238  if (v.size() == 0) {
239  os->writeBoolean(false);
240  } else {
241  os->writeBoolean(true);
242  os->writeInt(v.size());
243  for (auto i = 0; i < v.size(); i++) {
244  os->writeFloatArray(v[i].getArray());
245  }
246  }
247 }
248 
249 void TMWriter::writeTextureCoordinates(TMWriterOutputStream* os, const vector<Vector2>& tc)
250 {
251  if (tc.size() == 0) {
252  os->writeBoolean(false);
253  } else {
254  os->writeBoolean(true);
255  os->writeInt(tc.size());
256  for (auto i = 0; i < tc.size(); i++) {
257  os->writeFloatArray(tc[i].getArray());
258  }
259  }
260 }
261 
262 void TMWriter::writeIndices(TMWriterOutputStream* os, const array<int32_t, 3>& indices)
263 {
264  os->writeBoolean(true);
265  os->writeInt(indices.size());
266  for (auto i = 0; i < indices.size(); i++) {
267  os->writeInt(indices[i]);
268  }
269 }
270 
272 {
273  if (a == nullptr) {
274  os->writeBoolean(false);
275  } else {
276  os->writeBoolean(true);
277  os->writeInt(a->getTransformMatrices().size());
278  for (auto i = 0; i < a->getTransformMatrices().size(); i++) {
279  os->writeFloatArray(a->getTransformMatrices()[i].getArray());
280  }
281  }
282 }
283 
284 void TMWriter::writeFacesEntities(TMWriterOutputStream* os, const vector<FacesEntity>& facesEntities)
285 {
286  os->writeInt(facesEntities.size());
287  for (auto i = 0; i < facesEntities.size(); i++) {
288  const auto& fe = facesEntities[i];
289  os->writeString(fe.getId());
290  if (fe.getMaterial() == nullptr) {
291  os->writeBoolean(false);
292  } else {
293  os->writeBoolean(true);
294  os->writeString(fe.getMaterial()->getId());
295  }
296  os->writeInt(fe.getFaces().size());
297  for (auto j = 0; j < fe.getFaces().size(); j++) {
298  const auto& f = fe.getFaces()[j];
299  writeIndices(os, f.getVertexIndices());
300  writeIndices(os, f.getNormalIndices());
301  writeIndices(os, f.getTextureCoordinateIndices());
302  writeIndices(os, f.getTangentIndices());
303  writeIndices(os, f.getBitangentIndices());
304  }
305  }
306 }
307 
309 {
310  os->writeString(joint.getNodeId());
311  os->writeFloatArray(joint.getBindMatrix().getArray());
312 }
313 
315 {
316  os->writeInt(jointWeight.getJointIndex());
317  os->writeInt(jointWeight.getWeightIndex());
318 }
319 
321 {
322  if (skinning == nullptr) {
323  os->writeBoolean(false);
324  } else {
325  os->writeBoolean(true);
326  os->writeFloatArray(skinning->getWeights());
327  os->writeInt(skinning->getJoints().size());
328  for (auto i = 0; i < skinning->getJoints().size(); i++) {
329  writeSkinningJoint(os, skinning->getJoints()[i]);
330  }
331  os->writeInt(skinning->getVerticesJointsWeights().size());
332  for (auto i = 0; i < skinning->getVerticesJointsWeights().size(); i++) {
333  os->writeInt(skinning->getVerticesJointsWeights()[i].size());
334  for (auto j = 0; j < skinning->getVerticesJointsWeights()[i].size(); j++) {
335  writeSkinningJointWeight(os, skinning->getVerticesJointsWeights()[i][j]);
336  }
337  }
338  }
339 }
340 
341 void TMWriter::writeSubNodes(TMWriterOutputStream* os, const unordered_map<string, Node*>& subNodes)
342 {
343  os->writeInt(subNodes.size());
344  for (const auto& [subNodeId, subNode]: subNodes) {
345  writeNode(os, subNode);
346  }
347 }
348 
350 {
351  os->writeString(g->getId());
352  os->writeString(g->getName());
353  os->writeBoolean(g->isJoint());
355  writeVertices(os, g->getVertices());
356  writeVertices(os, g->getNormals());
358  writeVertices(os, g->getTangents());
359  writeVertices(os, g->getBitangents());
360  writeAnimation(os, g->getAnimation());
361  writeSkinning(os, g->getSkinning());
363  writeSubNodes(os, g->getSubNodes());
364 }
365 
367  // generate thumbnail
368  auto prototype = make_unique<Prototype>(
369  Prototype::ID_NONE,
370  Prototype_Type::MODEL,
371  model->getId(),
372  model->getId(),
373  "",
374  model->getId(),
375  string(),
376  model
377  );
378  vector<uint8_t> pngData;
379  string base64PNGData;
380  Tools::oseThumbnail(prototype.get(), pngData);
381  prototype->unsetModel();
382 
383  // write as attachment
384  os->writeUInt8tArray(pngData);
385  os->writeInt(pngData.size()); // png size
386  os->writeUInt8tArray({'T', 'M', 'B', 'N'}); // attachment type id
387  os->writeUInt8tArray({'A', 'T', 'M', 'T'}); // attachment id
388 }
Application base class, please make sure to allocate application on heap to have correct application ...
Definition: Application.h:41
Color 4 definition class.
Definition: Color4.h:18
Texture entity.
Definition: Texture.h:24
vector< uint8_t > * getData()
Get data.
Definition: TMWriter.h:66
void writeString(const string &s)
Writes a string to output stream.
Definition: TMWriter.h:115
void writeUInt8tArray(const vector< uint8_t > &d)
Writes a uint8_t array to output stream, note that no size information is given in this case.
Definition: TMWriter.h:204
void writeByte(uint8_t b)
Writes a byte to output stream.
Definition: TMWriter.h:84
void writeInt(int32_t i)
Writes a integer to output stream.
Definition: TMWriter.h:93
void writeFloat(float f)
Writes a float to output stream.
Definition: TMWriter.h:105
void writeFloatArray(const array< float, 2 > &f)
Writes a float array to output stream.
Definition: TMWriter.h:132
void writeBoolean(bool b)
Writes a boolean to output stream.
Definition: TMWriter.h:75
static void writeAnimationSetup(TMWriterOutputStream *os, AnimationSetup *animationSetup)
Write animation setup.
Definition: TMWriter.cpp:227
static void writeAnimation(TMWriterOutputStream *os, Animation *a)
Write animation to output stream.
Definition: TMWriter.cpp:271
static void writeTextureCoordinates(TMWriterOutputStream *os, const vector< Vector2 > &tc)
Write texture coordinates to output stream.
Definition: TMWriter.cpp:249
static void write(Model *model, const string &pathName, const string &fileName, bool useBC7TextureCompression=true)
TDME model format writer.
Definition: TMWriter.cpp:84
static void writeFacesEntities(TMWriterOutputStream *os, const vector< FacesEntity > &facesEntities)
Write faces entities to output stream.
Definition: TMWriter.cpp:284
static void writeSkinning(TMWriterOutputStream *os, Skinning *skinning)
Write skinning to output stream.
Definition: TMWriter.cpp:320
static void writeThumbnail(TMWriterOutputStream *os, Model *model)
Write thumbnail to output stream.
Definition: TMWriter.cpp:366
static void writeVertices(TMWriterOutputStream *os, const vector< Vector3 > &v)
Write vertices to output stream.
Definition: TMWriter.cpp:236
static void writeMaterial(TMWriterOutputStream *os, Material *m)
Write material.
Definition: TMWriter.cpp:179
static void writeEmbeddedTextures(TMWriterOutputStream *os, Model *m, bool useBC7TextureCompression)
Write embedded textures.
Definition: TMWriter.cpp:120
static void writeSkinningJoint(TMWriterOutputStream *os, const Joint &joint)
Write skinning joint.
Definition: TMWriter.cpp:308
static void writeNode(TMWriterOutputStream *os, Node *g)
Write node to output stream.
Definition: TMWriter.cpp:349
static void writeSubNodes(TMWriterOutputStream *os, const unordered_map< string, Node * > &subNodes)
Write sub nodes.
Definition: TMWriter.cpp:341
static void writeIndices(TMWriterOutputStream *os, const array< int32_t, 3 > &indices)
Write indices to output stream.
Definition: TMWriter.cpp:262
static void writeSkinningJointWeight(TMWriterOutputStream *os, const JointWeight &jointWeight)
Write skinning joint weight.
Definition: TMWriter.cpp:314
const string & getOverlayFromNodeId()
If this is a overlay animation this returns a node id from which node the animation will start in the...
const vector< Matrix4x4 > & getTransformMatrices() const
Returns transform matrices.
Definition: Animation.h:43
Represents a model face, consisting of vertex, normal, tangent and bitangent vectors,...
Definition: Face.h:18
Node faces entity A node can have multiple entities containing faces and a applied material.
Definition: FacesEntity.h:23
Joint / Bone.
Definition: Joint.h:19
const Matrix4x4 & getBindMatrix() const
Bind matrix.
Definition: Joint.h:48
const string & getNodeId() const
Associated node or bone id.
Definition: Joint.h:40
Represents a material.
Definition: Material.h:23
const PBRMaterialProperties * getPBRMaterialProperties() const
Definition: Material.h:78
const SpecularMaterialProperties * getSpecularMaterialProperties() const
Definition: Material.h:64
const string & getId() const
Definition: Material.h:57
const Matrix3x3 & getTextureMatrix() const
Definition: Material.h:119
Representation of a 3D model.
Definition: Model.h:35
unordered_map< string, Node * > & getSubNodes()
Returns object's sub nodes.
Definition: Model.h:220
unordered_map< string, Material * > & getMaterials()
Returns all object materials.
Definition: Model.h:185
RotationOrder * getRotationOrder()
Definition: Model.h:157
bool hasEmbeddedPBRTextures() const
Definition: Model.h:410
const Matrix4x4 & getImportTransformMatrix()
Definition: Model.h:340
ShaderModel * getShaderModel()
Definition: Model.h:164
const string & getName()
Definition: Model.h:135
bool hasEmbeddedSpecularTextures() const
Definition: Model.h:395
const string & getId()
Definition: Model.h:128
UpVector * getUpVector()
Definition: Model.h:142
const unordered_map< string, AnimationSetup * > & getAnimationSetups()
Definition: Model.h:262
BoundingBox * getBoundingBox()
Definition: Model.cpp:150
Model node.
Definition: Node.h:32
const vector< Vector3 > & getBitangents() const
Definition: Node.h:216
unordered_map< string, Node * > & getSubNodes()
Definition: Node.h:293
const vector< Vector3 > & getTangents() const
Definition: Node.h:203
bool isJoint() const
Definition: Node.h:110
const string & getName()
Definition: Node.h:96
Animation * getAnimation()
Definition: Node.h:229
const vector< Vector3 > & getVertices() const
Definition: Node.h:155
const vector< Vector3 > & getNormals() const
Definition: Node.h:177
const vector< Vector2 > & getTextureCoordinates() const
Definition: Node.h:190
Skinning * getSkinning()
Definition: Node.h:242
const string & getId()
Returns id.
Definition: Node.h:89
const vector< FacesEntity > & getFacesEntities() const
Definition: Node.h:260
const Matrix4x4 & getTransformMatrix() const
Definition: Node.h:125
Represents specular material properties.
Represents rotation orders of a model.
Definition: RotationOrder.h:23
Skinning definition for nodes.
Definition: Skinning.h:25
const vector< float > & getWeights()
Definition: Skinning.h:44
const vector< vector< JointWeight > > & getVerticesJointsWeights()
Definition: Skinning.h:70
const vector< Joint > & getJoints()
Definition: Skinning.h:57
Represents specular material properties.
Model up vector.
Definition: UpVector.h:20
Axis aligned bounding box used for frustum, this is not directly connectable with physics engine.
Definition: BoundingBox.h:26
Prototype definition.
Definition: Prototype.h:55
const array< float, 9 > & getArray() const
Definition: Matrix3x3.h:369
Matrix4x4 class representing matrix4x4 mathematical structure and operations for 3d space.
Definition: Matrix4x4.h:23
const array< float, 16 > & getArray() const
Definition: Matrix4x4.h:611
Vector2 class representing vector2 mathematical structure and operations with x, y components.
Definition: Vector2.h:20
Vector3 class representing vector3 mathematical structure and operations with x, y,...
Definition: Vector3.h:20
const array< float, 3 > & getArray() const
Definition: Vector3.h:366
File system singleton class.
Definition: FileSystem.h:17
Console class.
Definition: Console.h:29
const string & getName() const
Definition: Enum.h:37
std::exception Exception
Exception base class.
Definition: Exception.h:18