TDME2  1.9.200
ModelTools.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <array>
4 #include <string>
5 #include <unordered_map>
6 #include <vector>
7 
8 #include <tdme/tdme.h>
12 #include <tdme/engine/model/Face.h>
14 #include <tdme/engine/model/Node.h>
15 #include <tdme/engine/Transform.h>
16 #include <tdme/math/fwd-tdme.h>
17 #include <tdme/math/Vector2.h>
18 #include <tdme/math/Vector3.h>
19 #include <tdme/math/Matrix4x4.h>
21 
22 using std::array;
23 using std::string;
24 using std::unordered_map;
25 using std::vector;
26 
36 
37 /**
38  * Model tools functions class
39  * @author Andreas Drewke
40  */
42 {
43 private:
44  /**
45  * Simple class to determine if a transform matrix is right handed
46  * @author Andreas Drewke
47  */
49  {
50  private:
54 
55  public:
56  /**
57  * Public constructor
58  */
60  }
61 
62  /**
63  * Check if matrix is negative
64  * @param matrix matrix
65  * @return negative
66  */
67  inline bool isRightHanded(Matrix4x4& matrix) {
68  // copy into x,y,z axes
69  xAxis.set(matrix[0], matrix[1], matrix[2]);
70  yAxis.set(matrix[4], matrix[5], matrix[6]);
71  zAxis.set(matrix[8], matrix[9], matrix[10]);
72  // check if right handed
73  return Vector3::computeDotProduct(Vector3::computeCrossProduct(xAxis, yAxis), zAxis) < 0.0f;
74  }
75  };
76 
77 public:
79 
80  /**
81  * Determines vertex order of face
82  * @param vertices vertices
83  * @return vertex order
84  */
85  static VertexOrder determineVertexOrder(const vector<Vector3>& vertices);
86 
87  /**
88  * Computes face normal for given face vertices
89  * @param vertices face vertices
90  * @return computed face normal
91  */
92  inline static Vector3 computeNormal(const array<Vector3,3>& vertices) {
93  // face normal
94  auto normal = Vector3::computeCrossProduct(
95  (vertices)[1].clone().sub((vertices)[0]),
96  (vertices)[2].clone().sub((vertices)[0])
97  );
98  // check if zero?
99  if (normal.computeLengthSquared() < Math::EPSILON * Math::EPSILON) {
100  // take up vector
101  normal.set(0.0f, 1.0f, 0.0f);
102  } else {
103  // otherwise normalize
104  normal.normalize();
105  }
106  return normal;
107  }
108 
109  /**
110  * Computes face normals for given face vertices
111  * these normals will not be smooth
112  * @param vertices face vertices
113  * @return normals computed face normals
114  */
115  static array<Vector3,3> computeNormals(const array<Vector3,3>& vertices) {
116  // face normal
117  auto normal = computeNormal(vertices);
118 
119  // compute vertex normal
120  array<Vector3,3> normals;
121  for (auto i = 0; i < vertices.size(); i++) {
122  normals[i].set(normal);
123  }
124 
125  //
126  return normals;
127  }
128 
129  /**
130  * Prepare for indexed rendering
131  * @param model model
132  */
133  static void prepareForIndexedRendering(Model* model);
134 
135 private:
136 
137  /**
138  * Prepares this node for indexed rendering
139  * @param nodes nodes
140  */
141  static void prepareForIndexedRendering(const unordered_map<string, Node*>& nodes);
142 
143  /**
144  * Maps original vertices to new vertice mapping
145  * @param skinning skinning
146  * @param vertexMapping vertice mapping / new vertex index to old vertex index
147  * @param vertices vertice count
148  */
149  static void prepareForIndexedRendering(Skinning* skinning, const vector<int32_t>& vertexMapping, int32_t vertices);
150 
151 public:
152 
153  /**
154  * Set up joints for skinning nodes
155  * @param model model
156  */
157  static void setupJoints(Model* model);
158 
159 private:
160 
161  /**
162  * Sets up a node as joint taking all subnodes into account
163  * @param root node
164  */
165  static void setJoint(Node* root);
166 
167 public:
168 
169  /**
170  * Fix animation length
171  * @param model model
172  */
173  static void fixAnimationLength(Model* model);
174 
175 private:
176 
177  /**
178  * Fixes animation length as sometimes they are only given partially, which is not supported by engine
179  * @param root node
180  * @param frames frames
181  */
182  static void fixAnimationLength(Node* root, int32_t frames);
183 
184 public:
185 
186  /**
187  * Check default animation
188  * @param model model
189  * @return if animation exists
190  */
191  static bool hasDefaultAnimation(Model* model);
192 
193  /**
194  * Create default animation
195  * @param model model
196  * @param frames frames
197  */
198  static void createDefaultAnimation(Model* model, int32_t frames);
199 
200  /**
201  * Clone material
202  * @param material material
203  * @param id new id to use
204  * @return material
205  */
206  static Material* cloneMaterial(const Material* material, const string& id = string());
207 
208  /**
209  * Create model from source sub nodes into target sub nodes
210  * @param sourceNode source node
211  * @param targetModel target model
212  * @param targetParentNode target parent node
213  * @param cloneMesh clone mesh
214  */
215  static void cloneNode(Node* sourceNode, Model* targetModel, Node* targetParentNode = nullptr, bool cloneMesh = true);
216 
217 private:
218 
219  /**
220  * Partition sub nodes
221  * @param sourceNode source node to partition
222  * @param modelsByPartition models by partition
223  * @param modelsPosition models position
224  * @param parentTransformMatrix parent transform matrix
225  */
226  static void partitionNode(Node* sourceNode, unordered_map<string, Model*>& modelsByPartition, unordered_map<string, Vector3>& modelsPosition, const Matrix4x4& parentTransformMatrix);
227 
228  /**
229  * Shrink to fit node
230  * @param node node
231  */
232  static void shrinkToFit(Node* node);
233 
234  /**
235  * Find all faces that include vertex and compute the avarage normal
236  * @param node node
237  * @param vertex vertex
238  * @param normals normals
239  * @param normal normal
240  */
241  inline static bool interpolateNormal(Node* node, const Vector3& vertex, const vector<Vector3>& normals, Vector3& normal) {
242  array<Vector3, 3> vertices;
243  auto normalCount = 0;
244  normal.set(0.0f, 0.0f, 0.0f);
245  for (const auto& facesEntity: node->getFacesEntities()) {
246  for (const auto& face: facesEntity.getFaces()) {
247  for (auto i = 0; i < vertices.size(); i++) {
248  if (vertex.equals(node->getVertices()[face.getVertexIndices()[i]]) == true) {
249  normal.add(normals[face.getNormalIndices()[0]]);
250  normalCount++;
251  break;
252  }
253  }
254  if (normalCount == 6) break;
255  }
256  if (normalCount == 6) break;
257  }
258  if (normalCount > 1) {
259  normal.normalize();
260  return true;
261  } else {
262  return false;
263  }
264  }
265 
266  /**
267  * Compute normals
268  * @param node node
269  */
270  static float computeNormals(Node* node, ProgressCallback* progressCallback = nullptr, float incrementPerFace = 0.0f, float progress = 0.0f);
271 
272  /**
273  * Compute face count
274  * @param node node
275  */
276  static int determineFaceCount(Node* node);
277 
278 public:
279  /**
280  * Partition model
281  * @param model model
282  * @param transform transform
283  * @param modelsByPartition models by partition
284  * @param modelsPosition models position
285  */
286  static void partition(Model* model, const Transform& transform, unordered_map<string, Model*>& modelsByPartition, unordered_map<string, Vector3>& modelsPosition);
287 
288  /**
289  * Shrink to fit
290  * @param model model
291  */
292  static void shrinkToFit(Model* model);
293 
294  /**
295  * Compute normals
296  * @param node node
297  */
298  static void computeNormals(Model* model, ProgressCallback* progressCallback = nullptr);
299 
300  /**
301  * Prepare model for specific shader
302  * @param model model
303  * @param shader optional shader
304  */
305  static void prepareForShader(Model* model, const string& shader = string());
306 
307  /**
308  * @returns if model has been optimized
309  */
310  static bool isOptimizedModel(Model* model);
311 
312  /**
313  * Optimizes model in terms of material / node reduction
314  * @param model model
315  * @param texturePathName texturePathName
316  * @param excludeDiffuseTextureFileNamePatterns exclude diffuse texture file name patterns
317  */
318  static Model* optimizeModel(Model* model, const string& texturePathName = string(), const vector<string>& excludeDiffuseTextureFileNamePatterns = vector<string>());
319 
320  /**
321  * Compute tangents and bitangents for given node
322  * @param node node
323  */
324  static void computeTangentsAndBitangents(Node* node);
325 
326  /**
327  * Change front face from counter clock wise to clock wise or clock wise to counter clock wise
328  * @param node node
329  * @param applyToSubNodes apply to sub nodes
330  */
331  static void changeFrontFace(Node* node, bool applyToSubNodes);
332 
333  /**
334  * Change front face from counter clock wise to clock wise or clock wise to counter clock wise
335  * @param model model
336  */
337  static void changeFrontFace(Model* model);
338 
339 private:
340 
341  /**
342  * Prepare node for default shader
343  * @param node node
344  * @param parentTransformMatrix parent transform matrix
345  */
346  static void prepareForDefaultShader(Node* node, const Matrix4x4& parentTransformMatrix);
347 
348  /**
349  * Prepare node for foliage shader
350  * @param node node
351  * @param parentTransformMatrix parent transform matrix
352  * @param shader shader
353  */
354  static void prepareForFoliageTreeShader(Node* node, const Matrix4x4& parentTransformMatrix, const string& shader);
355 
356  /**
357  * Prepare node for water shader
358  * @param node node
359  * @param parentTransformMatrix parent transform matrix
360  */
361  static void prepareForWaterShader(Node* node, const Matrix4x4& parentTransformMatrix);
362 
363  /**
364  * Check for optimization
365  * @param node node
366  * @param materialUseCount material use count
367  * @param excludeDiffuseTextureFileNamePatterns exclude diffuse texture file name patterns
368  */
369  static void checkForOptimization(Node* node, unordered_map<string, int>& materialUseCount, const vector<string>& excludeDiffuseTextureFileNamePatterns);
370 
371  /**
372  * Prepare for optimization
373  * @param node node
374  * @param parentTransformMatrix parent transform matrix
375  * @param materialUseCount material use count
376  */
377  static void prepareForOptimization(Node* node, const Matrix4x4& parentTransformMatrix);
378 
379  /**
380  * Prepare for optimization
381  * @param sourceNode source node
382  * @param targetModel target model
383  * @param diffuseTextureAtlasSize diffuse texture atlas size
384  * @param diffuseTextureAtlasIndices diffuse texture atlas indices
385  * @param excludeDiffuseTextureFileNamePatterns exclude diffuse texture file name patterns
386  */
387  static void optimizeNode(Node* sourceNode, Model* targetModel, int diffuseTextureAtlasSize, const unordered_map<string, int>& diffuseTextureAtlasIndices, const vector<string>& excludeDiffuseTextureFileNamePatterns);
388 
389 };
Texture entity.
Definition: Texture.h:24
Transform which contain scale, rotations and translation.
Definition: Transform.h:29
Represents a material.
Definition: Material.h:23
Representation of a 3D model.
Definition: Model.h:35
Model node.
Definition: Node.h:32
const vector< Vector3 > & getVertices() const
Definition: Node.h:155
const vector< FacesEntity > & getFacesEntities() const
Definition: Node.h:260
Skinning definition for nodes.
Definition: Skinning.h:25
Matrix4x4 class representing matrix4x4 mathematical structure and operations for 3d space.
Definition: Matrix4x4.h:23
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
Vector3 & add(float scalar)
Adds a scalar.
Definition: Vector3.h:153
Vector3 & set(float x, float y, float z)
Sets this vector3 by its components.
Definition: Vector3.h:70
bool equals(const Vector3 &vector3, float tolerance=Math::EPSILON) const
Compares this vector3 with given vector3.
Definition: Vector3.h:226
Vector3 & normalize()
Normalizes this vector3.
Definition: Vector3.h:239
Simple class to determine if a transform matrix is right handed.
Definition: ModelTools.h:49
bool isRightHanded(Matrix4x4 &matrix)
Check if matrix is negative.
Definition: ModelTools.h:67
Model tools functions class.
Definition: ModelTools.h:42
static bool interpolateNormal(Node *node, const Vector3 &vertex, const vector< Vector3 > &normals, Vector3 &normal)
Find all faces that include vertex and compute the avarage normal.
Definition: ModelTools.h:241
static void prepareForWaterShader(Node *node, const Matrix4x4 &parentTransformMatrix)
Prepare node for water shader.
static void shrinkToFit(Node *node)
Shrink to fit node.
Definition: ModelTools.cpp:613
static void computeTangentsAndBitangents(Node *node)
Compute tangents and bitangents for given node.
static void checkForOptimization(Node *node, unordered_map< string, int > &materialUseCount, const vector< string > &excludeDiffuseTextureFileNamePatterns)
Check for optimization.
Definition: ModelTools.cpp:841
static void createDefaultAnimation(Model *model, int32_t frames)
Create default animation.
Definition: ModelTools.cpp:259
static bool hasDefaultAnimation(Model *model)
Check default animation.
Definition: ModelTools.cpp:255
static array< Vector3, 3 > computeNormals(const array< Vector3, 3 > &vertices)
Computes face normals for given face vertices these normals will not be smooth.
Definition: ModelTools.h:115
static void prepareForFoliageTreeShader(Node *node, const Matrix4x4 &parentTransformMatrix, const string &shader)
Prepare node for foliage shader.
Definition: ModelTools.cpp:778
static void prepareForIndexedRendering(Model *model)
Prepare for indexed rendering.
Definition: ModelTools.cpp:86
static void partition(Model *model, const Transform &transform, unordered_map< string, Model * > &modelsByPartition, unordered_map< string, Vector3 > &modelsPosition)
Partition model.
Definition: ModelTools.cpp:597
static void prepareForOptimization(Node *node, const Matrix4x4 &parentTransformMatrix)
Prepare for optimization.
Definition: ModelTools.cpp:870
static void setupJoints(Model *model)
Set up joints for skinning nodes.
Definition: ModelTools.cpp:194
static void prepareForShader(Model *model, const string &shader=string())
Prepare model for specific shader.
Definition: ModelTools.cpp:713
static void changeFrontFace(Node *node, bool applyToSubNodes)
Change front face from counter clock wise to clock wise or clock wise to counter clock wise.
static Model * optimizeModel(Model *model, const string &texturePathName=string(), const vector< string > &excludeDiffuseTextureFileNamePatterns=vector< string >())
Optimizes model in terms of material / node reduction.
static void partitionNode(Node *sourceNode, unordered_map< string, Model * > &modelsByPartition, unordered_map< string, Vector3 > &modelsPosition, const Matrix4x4 &parentTransformMatrix)
Partition sub nodes.
Definition: ModelTools.cpp:364
static int determineFaceCount(Node *node)
Compute face count.
Definition: ModelTools.cpp:704
static void optimizeNode(Node *sourceNode, Model *targetModel, int diffuseTextureAtlasSize, const unordered_map< string, int > &diffuseTextureAtlasIndices, const vector< string > &excludeDiffuseTextureFileNamePatterns)
Prepare for optimization.
Definition: ModelTools.cpp:920
static Material * cloneMaterial(const Material *material, const string &id=string())
Clone material.
Definition: ModelTools.cpp:277
static bool isOptimizedModel(Model *model)
static void fixAnimationLength(Model *model)
Fix animation length.
Definition: ModelTools.cpp:221
static VertexOrder determineVertexOrder(const vector< Vector3 > &vertices)
Determines vertex order of face.
Definition: ModelTools.cpp:71
static void setJoint(Node *root)
Sets up a node as joint taking all subnodes into account.
Definition: ModelTools.cpp:213
static void prepareForDefaultShader(Node *node, const Matrix4x4 &parentTransformMatrix)
Prepare node for default shader.
Definition: ModelTools.cpp:723
static void cloneNode(Node *sourceNode, Model *targetModel, Node *targetParentNode=nullptr, bool cloneMesh=true)
Create model from source sub nodes into target sub nodes.
Definition: ModelTools.cpp:317
static Vector3 computeNormal(const array< Vector3, 3 > &vertices)
Computes face normal for given face vertices.
Definition: ModelTools.h:92