TDME2  1.9.200
ObjectNodeMesh.cpp
Go to the documentation of this file.
2 
3 #include <map>
4 #include <string>
5 #include <unordered_map>
6 
7 #include <tdme/tdme.h>
13 #include <tdme/engine/model/Node.h>
21 #include <tdme/math/Math.h>
22 #include <tdme/math/Matrix4x4.h>
23 #include <tdme/math/Vector2.h>
24 #include <tdme/math/Vector3.h>
26 #include <tdme/utilities/Console.h>
29 
30 using std::map;
31 using std::string;
32 using std::unordered_map;
33 
46 using tdme::math::Math;
54 
55 ObjectNodeMesh::ObjectNodeMesh(ObjectNodeRenderer* objectNodeRenderer, Engine::AnimationProcessingTarget animationProcessingTarget, Node* node, const vector<unordered_map<string, Matrix4x4*>*>& transformMatrices, const vector<unordered_map<string, Matrix4x4*>*>& skinningMatrices, int instances)
56 {
57  //
58  this->instances = instances;
59  this->objectNodeRenderer = objectNodeRenderer;
60  this->node = node;
61  // node data
62  const auto& nodeVertices = node->getVertices();
63  const auto& nodeNormals = node->getNormals();
64  const auto& nodeTextureCoordinates = node->getTextureCoordinates();
65  const auto& nodeTangents = node->getTangents();
66  const auto& nodeBitangents = node->getBitangents();
67  // determine face count
69  // animation processing target
70  this->animationProcessingTarget = animationProcessingTarget;
71  // transform for skinned meshes
72  auto skinning = node->getSkinning();
73  this->skinning = skinning != nullptr;
75  if (skinning != nullptr) {
76  jointsSkinningMatrices.resize(instances);
77  for (auto i = 0; i < instances; i++) {
78  for (const auto& joint: skinning->getJoints()) {
79  jointsSkinningMatrices[i].push_back(skinningMatrices[i]->find(joint.getNodeId())->second);
80  }
81  }
82  }
83  // set up transformed vertices, normals and friends
84  if (instances > 1 || (skinning != nullptr && animationProcessingTarget == Engine::AnimationProcessingTarget::CPU) ||
85  animationProcessingTarget == Engine::AnimationProcessingTarget::CPU_NORENDERING) {
86  // transformed mesh vertices
87  transformedVertices.resize(nodeVertices.size() * instances);
89  {
90  auto idx = 0;
91  for (auto i = 0; i < instances; i++)
92  for (auto j = 0; j < nodeVertices.size(); j++) {
93  transformedVertices[idx++].set(nodeVertices[j]);
94  }
95  }
96  // transformed mesh normals
97  transformedNormals.resize(nodeNormals.size() * instances);
99  {
100  auto idx = 0;
101  for (auto i = 0; i < instances; i++)
102  for (auto j = 0; j < nodeNormals.size(); j++) {
103  transformedNormals[idx++].set(nodeNormals[j]);
104  }
105  }
106  if (instances > 1) {
107  // transformed mesh texture coordinates
108  transformedTextureCoordinates.resize(nodeTextureCoordinates.size() * instances);
110  {
111  auto idx = 0;
112  for (auto i = 0; i < instances; i++)
113  for (auto j = 0; j < nodeTextureCoordinates.size(); j++) {
114  transformedTextureCoordinates[idx++].set(nodeTextureCoordinates[j]);
115  }
116  }
117  } else {
118  textureCoordinates = &nodeTextureCoordinates;
119  }
120  // transformed mesh tangents
121  if (nodeTangents.size() > 0) {
122  transformedTangents.resize(nodeTangents.size() * instances);
124  {
125  auto idx = 0;
126  for (auto i = 0; i < instances; i++)
127  for (auto j = 0; j < nodeTangents.size(); j++) {
128  transformedTangents[idx++].set(nodeTangents[j]);
129  }
130  }
131  }
132  // transformed mesh bitangents
133  if (nodeBitangents.size() > 0) {
134  transformedBitangents.resize(nodeBitangents.size() * instances);
136  {
137  auto idx = 0;
138  for (auto i = 0; i < instances; i++)
139  for (auto j = 0; j < nodeBitangents.size(); j++) {
140  transformedBitangents[idx++].set(nodeBitangents[j]);
141  }
142  }
143  }
144  } else {
145  // no transform on CPU, we can use model data
146  vertices = &nodeVertices;
147  normals = &nodeNormals;
148  textureCoordinates = &nodeTextureCoordinates;
149  if (nodeTangents.size() > 0) {
150  tangents = &nodeTangents;
151  }
152  if (nodeBitangents.size() > 0) {
153  bitangents = &nodeBitangents;
154  }
155  }
156 
157  // indices
158  auto indicesCount = 0;
159  for (const auto& facesEntity: node->getFacesEntities()) {
160  indicesCount += 3 * facesEntity.getFaces().size();
161  }
162  indices.resize(instances * indicesCount);
163  {
164  auto j = 0;
165  for (const auto& facesEntity: node->getFacesEntities()) {
166  for (auto i = 0; i < instances; i++) {
167  for (const auto& face: facesEntity.getFaces())
168  for (auto vertexIndex: face.getVertexIndices()) {
169  indices[j++] = nodeVertices.size() * i + vertexIndex;
170  }
171  }
172  }
173  }
174 
175  //
176  recreatedBuffers = false;
177  // node transform matrix
178  if (animationProcessingTarget == Engine::AnimationProcessingTarget::CPU ||
179  animationProcessingTarget == Engine::AnimationProcessingTarget::CPU_NORENDERING ||
180  animationProcessingTarget == Engine::AnimationProcessingTarget::GPU) {
181  // node transform matrix
182  nodeTransformMatrix = transformMatrices[0]->find(node->getId())->second;
183  }
184  // skinning
185  if (skinning != nullptr) {
187  skinningJointWeight.resize(nodeVertices.size());
189  for (auto i = 0; i < instances; i++) skinningJointTransformMatrices[i].resize(nodeVertices.size());
190  // compute joint weight caches
191  const auto& joints = skinning->getJoints();
192  const auto& weights = skinning->getWeights();
193  const auto& jointsWeights = skinning->getVerticesJointsWeights();
194  for (auto vertexIndex = 0; vertexIndex < nodeVertices.size(); vertexIndex++) {
195  auto vertexJointWeights = jointsWeights[vertexIndex].size();
196  if (vertexJointWeights > skinningMaxVertexWeights) skinningMaxVertexWeights = vertexJointWeights;
197  skinningJointWeight[vertexIndex].resize(vertexJointWeights);
198  for (auto i = 0; i < instances; i++) skinningJointTransformMatrices[i][vertexIndex].resize(vertexJointWeights);
199  {
200  auto jointWeightIdx = 0;
201  for (const auto& jointWeight : jointsWeights[vertexIndex]) {
202  const auto& joint = joints[jointWeight.getJointIndex()];
203  skinningJointWeight[vertexIndex][jointWeightIdx] = weights[jointWeight.getWeightIndex()];
204  // next
205  jointWeightIdx++;
206  }
207  }
208  for (auto i = 0; i < instances; i++) {
209  auto jointWeightIdx = 0;
210  for (const auto& jointWeight : jointsWeights[vertexIndex]) {
211  auto& joint = joints[jointWeight.getJointIndex()];
212  auto skinningMatrixIt = skinningMatrices[i]->find(joint.getNodeId());
213  skinningJointTransformMatrices[i][vertexIndex][jointWeightIdx] = skinningMatrixIt != skinningMatrices[i]->end()?skinningMatrixIt->second:nullptr;
214  // next
215  jointWeightIdx++;
216  }
217  }
218  }
219  }
220  recreateBuffers();
221 }
222 
223 void ObjectNodeMesh::computeSkinning(int contextIdx, ObjectBase* objectBase)
224 {
225  // transform for skinned meshes
226  auto skinning = node->getSkinning();
227  if (skinning != nullptr) {
228  // compute skinning on CPU if required
229  if (animationProcessingTarget == Engine::AnimationProcessingTarget::GPU) {
230  Engine::getSkinningShader()->computeSkinning(contextIdx, objectBase, this);
231  } else
232  if (animationProcessingTarget == Engine::AnimationProcessingTarget::CPU || animationProcessingTarget == Engine::AnimationProcessingTarget::CPU_NORENDERING) {
233  const auto& nodeVertices = node->getVertices();
234  const auto& nodeNormals = node->getNormals();
235  const auto& nodeTangent = node->getTangents();
236  const auto& nodeBitangent = node->getBitangents();
237  const auto& jointsWeights = skinning->getVerticesJointsWeights();
238  const Vector3* vertex;
239  Vector3* transformedVertex;
240  const Vector3* normal;
241  Vector3* transformedNormal;
242  const Vector3* tangent;
243  Vector3* transformedTangent;
244  const Vector3* bitangent;
245  Vector3* transformedBitangent;
246  float totalWeights;
247  float weightNormalized;
248  auto j = 0;
249  Matrix4x4 transformMatrix;
250  auto currentInstance = objectBase->getCurrentInstance();
251  for (auto i = 0; i < instances; i++) {
252  if (objectBase->instanceEnabled[i] == false) continue;
253  objectBase->setCurrentInstance(i);
254  for (auto vertexIndex = 0; vertexIndex < nodeVertices.size(); vertexIndex++) {
255  // do vertices, normals, tangents and bitangents
256  vertex = &nodeVertices[vertexIndex];
257  transformedVertex = &transformedVertices[nodeVertices.size() * j + vertexIndex].set(0.0f, 0.0f, 0.0f);
258  normal = &nodeNormals[vertexIndex];
259  transformedNormal = &transformedNormals[nodeVertices.size() * j + vertexIndex].set(0.0f, 0.0f, 0.0f);
260  tangent = tangents != nullptr?&nodeTangent[vertexIndex]:nullptr;
261  transformedTangent = tangents != nullptr?&transformedTangents[nodeVertices.size() * j + vertexIndex].set(0.0f, 0.0f, 0.0f):nullptr;
262  bitangent = bitangents != nullptr?&nodeBitangent[vertexIndex]:nullptr;
263  transformedBitangent = bitangents != nullptr?&transformedBitangents[nodeVertices.size() * j + vertexIndex].set(0.0f, 0.0f, 0.0f):nullptr;
264  // compute every influence on vertex and ...
265  totalWeights = 0.0f;
266  for (auto vertexJointWeightIdx = 0; vertexJointWeightIdx < jointsWeights[vertexIndex].size(); vertexJointWeightIdx++) {
267  // skip on missing matrix
268  auto skinningJointTransformMatrix = skinningJointTransformMatrices[i][vertexIndex][vertexJointWeightIdx];
269  if (skinningJointTransformMatrix == nullptr) continue;
270  //
271  auto weight = skinningJointWeight[vertexIndex][vertexJointWeightIdx];
272  //
273  transformMatrix.set(*skinningJointTransformMatrix).multiply(objectBase->getTransformMatrix());
274  // vertex
275  transformedVertex->add(transformMatrix.multiply(*vertex).scale(weight));
276  // normals
277  transformedNormal->add(transformMatrix.multiplyNoTranslation(*normal).scale(weight));
278  // tangent
279  if (tangent != nullptr && transformedTangent != nullptr) {
280  transformedTangent->add(transformMatrix.multiplyNoTranslation(*tangent).scale(weight));
281  }
282  // bitangent
283  if (bitangent != nullptr && transformedBitangent != nullptr) {
284  transformedBitangent->add(transformMatrix.multiplyNoTranslation(*bitangent).scale(weight));
285  }
286  //
287  totalWeights += weight;
288  }
289  // scale to full weight
290  if (Math::abs(totalWeights - 1.0f) > Math::EPSILON) {
291  weightNormalized = 1.0f / totalWeights;
292  // vertex
293  transformedVertex->scale(weightNormalized);
294  // normals
295  transformedNormal->scale(weightNormalized);
296  // tangent
297  if (transformedTangent != nullptr) {
298  transformedTangent->scale(weightNormalized);
299  }
300  // bitangent
301  if (transformedBitangent != nullptr) {
302  transformedBitangent->scale(weightNormalized);
303  }
304  }
305  // normalize normal
306  transformedNormal->normalize();
307  }
308  j++;
309  }
310  objectBase->setCurrentInstance(currentInstance);
311  // recreate buffers
312  recreateBuffers();
313  }
314  } else
315  if (animationProcessingTarget == Engine::AnimationProcessingTarget::CPU_NORENDERING) {
316  const auto& nodeVertices = node->getVertices();
317  const auto& nodeNormals = node->getNormals();
318  // transform for non skinned rendering
319  // vertices
320  for (auto vertexIndex = 0; vertexIndex < nodeVertices.size(); vertexIndex++) {
321  transformedVertices[vertexIndex].set(nodeTransformMatrix->multiply(nodeVertices[vertexIndex]));
322  }
323  // normals
324  for (auto normalIndex = 0; normalIndex < nodeNormals.size(); normalIndex++) {
325  transformedNormals[normalIndex].set(nodeTransformMatrix->multiplyNoTranslation(nodeNormals[normalIndex]).normalize());
326  }
327  // TODO: tangents, bitangents, but actually it is only in use for computing bounding volumes, so I am not in a hurry
328  // recreate buffers
329  recreateBuffers();
330  }
331 }
332 
334 {
335  recreatedBuffers = true;
336 }
337 
339 {
340  if (recreatedBuffers == true) {
341  recreatedBuffers = false;
342  return true;
343  } else {
344  return false;
345  }
346 }
347 
348 void ObjectNodeMesh::setupVertexIndicesBuffer(Renderer *renderer, int contextIdx, int32_t vboId) {
349  // upload
350  if (renderer->isUsingShortIndices() == true) {
351  if (instances * indices.size() > 65535) {
352  Console::println(
353  "ObjectNodeMesh::setupVertexIndicesBuffer(): " +
354  node->getModel()->getName() + ":" +
355  node->getName() + ":" +
356  "more than 2^16-1 indices: " +
357  to_string(indices.size())
358  );
359  }
360  auto sbIndices = ObjectBuffer::getByteBuffer(contextIdx, instances * faceCount * 3 * sizeof(uint16_t))->asShortBuffer();
361  // create face vertex indices, will never be changed in engine
362  for (auto i = 0; i < instances; i++)
363  for (auto index: indices) {
364  sbIndices.put(index);
365  }
366  // done, upload
367  renderer->uploadIndicesBufferObject(contextIdx, vboId, sbIndices.getPosition() * sizeof(uint16_t), &sbIndices);
368  } else {
369  auto ibIndices = ObjectBuffer::getByteBuffer(contextIdx, instances * faceCount * 3 * sizeof(uint32_t))->asIntBuffer();
370  // create face vertex indices, will never be changed in engine
371  for (auto i = 0; i < instances; i++)
372  for (auto index: indices) {
373  ibIndices.put(index);
374  }
375  // done, upload
376  renderer->uploadIndicesBufferObject(contextIdx, vboId, ibIndices.getPosition() * sizeof(uint32_t), &ibIndices);
377  }
378 }
379 
380 
381 void ObjectNodeMesh::setupTextureCoordinatesBuffer(Renderer* renderer, int contextIdx, int32_t vboId)
382 {
383  if (textureCoordinates->size() == 0) return;
384  // create texture coordinates buffer, will never be changed in engine
385  auto fbTextureCoordinates = ObjectBuffer::getByteBuffer(contextIdx, textureCoordinates->size() * 2 * sizeof(float))->asFloatBuffer();
386  // construct texture coordinates byte buffer as this will not change usually
387  for (const auto& textureCoordinate: *textureCoordinates) {
388  fbTextureCoordinates.put(textureCoordinate.getArray());
389  }
390  // done, upload
391  renderer->uploadBufferObject(contextIdx, vboId, fbTextureCoordinates.getPosition() * sizeof(float), &fbTextureCoordinates);
392 }
393 
394 void ObjectNodeMesh::setupVerticesBuffer(Renderer* renderer, int contextIdx, int32_t vboId)
395 {
396  auto fbVertices = ObjectBuffer::getByteBuffer(contextIdx, vertices->size() * 3 * sizeof(float))->asFloatBuffer();
397  // create vertices buffers
398  for (const auto& vertex: *vertices) {
399  fbVertices.put(vertex.getArray());
400  }
401  // done, upload
402  renderer->uploadBufferObject(contextIdx, vboId, fbVertices.getPosition() * sizeof(float), &fbVertices);
403 }
404 
405 void ObjectNodeMesh::setupNormalsBuffer(Renderer* renderer, int contextIdx, int32_t vboId)
406 {
407  auto fbNormals = ObjectBuffer::getByteBuffer(contextIdx, normals->size() * 3 * sizeof(float))->asFloatBuffer();
408  // create normals buffers
409  for (const auto& normal: *normals) {
410  fbNormals.put(normal.getArray());
411  }
412  // done, upload
413  renderer->uploadBufferObject(contextIdx, vboId, fbNormals.getPosition() * sizeof(float), &fbNormals);
414 }
415 
416 void ObjectNodeMesh::setupTangentsBuffer(Renderer* renderer, int contextIdx, int32_t vboId)
417 {
418  // check if we have tangents
419  if (tangents == nullptr) return;
420  auto fbTangents = ObjectBuffer::getByteBuffer(contextIdx, tangents->size() * 3 * sizeof(float))->asFloatBuffer();
421  // create tangents buffers
422  for (const auto& tangent: *tangents) {
423  fbTangents.put(tangent.getArray());
424  }
425  // done, upload
426  renderer->uploadBufferObject(contextIdx, vboId, fbTangents.getPosition() * sizeof(float), &fbTangents);
427 }
428 
429 void ObjectNodeMesh::setupBitangentsBuffer(Renderer* renderer, int contextIdx, int32_t vboId)
430 {
431  // check if we have bitangents
432  if (bitangents == nullptr) return;
433  auto fbBitangents = ObjectBuffer::getByteBuffer(contextIdx, bitangents->size() * 3 * sizeof(float))->asFloatBuffer();
434  // create bitangents buffers
435  for (const auto& bitangent: *bitangents) {
436  fbBitangents.put(bitangent.getArray());
437  }
438  // done, upload
439  renderer->uploadBufferObject(contextIdx, vboId, fbBitangents.getPosition() * sizeof(float), &fbBitangents);
440 }
441 
442 void ObjectNodeMesh::setupOriginsBuffer(Renderer* renderer, int contextIdx, int32_t vboId) {
443  // check if we have origins
444  const auto& origins = node->getOrigins();
445  if (origins.size() == 0) return;
446  // create origins buffer, will never be changed in engine
447  auto fbOrigins = ObjectBuffer::getByteBuffer(contextIdx, origins.size() * 3 * sizeof(float))->asFloatBuffer();
448  // construct origins buffer
449  for (const auto& origin: origins) {
450  fbOrigins.put(origin.getArray());
451  }
452  // done, upload
453  renderer->uploadBufferObject(contextIdx, vboId, fbOrigins.getPosition() * sizeof(float), &fbOrigins);
454 }
455 
456 void ObjectNodeMesh::setupLodBuffer(Renderer* renderer, int contextIdx, int32_t vboId, int lodLevel) {
457  // TODO: we only support faces entities 0 lod indices for terrain now
458  const vector<int32_t>* indices { nullptr };
459  switch (lodLevel) {
460  case 1: indices = &node->getFacesEntities()[0].getLOD1Indices(); break;
461  case 2: indices = &node->getFacesEntities()[0].getLOD2Indices(); break;
462  case 3: indices = &node->getFacesEntities()[0].getLOD3Indices(); break;
463  default:
464  Console::println(
465  "ObjectNodeMesh::setupLodBuffer(): " +
466  node->getModel()->getName() + ":" +
467  node->getName() + ":" +
468  "no valid lod level: " + to_string(lodLevel)
469  );
470  return;
471  }
472  if (indices->empty() == true) {
473  Console::println(
474  "ObjectNodeMesh::setupLodBuffer(): " +
475  node->getModel()->getName() + ":" +
476  node->getName() + ":" +
477  "no indices"
478  );
479  return;
480  }
481  if (renderer->isUsingShortIndices() == true) {
482  if (instances * indices->size() > 65535) {
483  Console::println(
484  "ObjectNodeMesh::setupLodBuffer(): " +
485  node->getModel()->getName() + ":" +
486  node->getName() + ":" +
487  "more than 2^16-1 indices: " +
488  to_string(indices->size())
489  );
490  }
491  // create indices buffer, will never be changed in engine
492  auto sbIndices = ObjectBuffer::getByteBuffer(contextIdx, indices->size() * sizeof(uint16_t))->asShortBuffer();
493  // construct indices buffer
494  for (const auto index: *indices) {
495  sbIndices.put(index);
496  }
497  renderer->uploadIndicesBufferObject(contextIdx, vboId, sbIndices.getPosition() * sizeof(uint16_t), &sbIndices);
498  } else {
499  // create indices buffer, will never be changed in engine
500  auto ibIndices = ObjectBuffer::getByteBuffer(contextIdx, indices->size() * sizeof(uint32_t))->asIntBuffer();
501  // construct indices buffer
502  for (const auto index: *indices) {
503  ibIndices.put(index);
504  }
505  renderer->uploadIndicesBufferObject(contextIdx, vboId, ibIndices.getPosition() * sizeof(uint32_t), &ibIndices);
506  }
507 }
static SkinningShader * getSkinningShader()
Definition: Engine.h:469
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 string & getName()
Definition: Model.h:135
Model node.
Definition: Node.h:32
const vector< Vector3 > & getBitangents() const
Definition: Node.h:216
int32_t getFaceCount() const
Definition: Node.cpp:105
const vector< Vector3 > & getTangents() const
Definition: Node.h:203
Model * getModel()
Definition: Node.h:74
const vector< Vector3 > & getOrigins() const
Definition: Node.h:280
const string & getName()
Definition: Node.h:96
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
Skinning definition for nodes.
Definition: Skinning.h:25
virtual void uploadIndicesBufferObject(int contextIdx, int32_t bufferObjectId, int32_t size, ShortBuffer *data)=0
Uploads buffer data to buffer object.
virtual void uploadBufferObject(int contextIdx, int32_t bufferObjectId, int32_t size, FloatBuffer *data)=0
Uploads buffer data to buffer object.
void setCurrentInstance(int currentInstance)
Set current instance.
Definition: ObjectBase.h:165
const Matrix4x4 & getTransformMatrix() const
Definition: ObjectBase.h:293
Buffers used to transfer data between main memory to graphics board memory.
Definition: ObjectBuffer.h:24
static ByteBuffer * getByteBuffer(int contextIdx, int32_t bytes)
Get byte buffer for given context.
Object node mesh specifically for rendering.
void setupOriginsBuffer(Renderer *renderer, int contextIdx, int32_t vboId)
Set up render node object origins data buffer.
void setupNormalsBuffer(Renderer *renderer, int contextIdx, int32_t vboId)
Set up normals buffer.
void setupVertexIndicesBuffer(Renderer *renderer, int contextIdx, int32_t vboId)
Set up vertex indices buffer.
Engine::AnimationProcessingTarget animationProcessingTarget
void computeSkinning(int contextIdx, ObjectBase *objectBase)
Computes skinning.
void setupLodBuffer(Renderer *renderer, int contextIdx, int32_t vboId, int lodLevel)
Set up render node object lod data buffer.
void setupTextureCoordinatesBuffer(Renderer *renderer, int contextIdx, int32_t vboId)
Set up texture coordinates buffer.
vector< vector< vector< Matrix4x4 * > > > skinningJointTransformMatrices
void recreateBuffers()
Recreates node float buffers.
void setupTangentsBuffer(Renderer *renderer, int contextIdx, int32_t vboId)
Set up tangents buffer.
void setupVerticesBuffer(Renderer *renderer, int contextIdx, int32_t vboId)
Set up vertices buffer.
vector< vector< Matrix4x4 * > > jointsSkinningMatrices
void setupBitangentsBuffer(Renderer *renderer, int contextIdx, int32_t vboId)
Set up bitangents buffer.
vector< unordered_map< string, Matrix4x4 * > * > skinningMatrices
Interface to compute shader skinning shader program.
void computeSkinning(int contextIdx, ObjectBase *objectBase, ObjectNodeMesh *objectNodeMesh)
Compute skinning.
Standard math functions.
Definition: Math.h:19
Matrix4x4 class representing matrix4x4 mathematical structure and operations for 3d space.
Definition: Matrix4x4.h:23
Vector3 multiply(const Vector3 &vector3) const
Multiplies this matrix with vector3.
Definition: Matrix4x4.h:225
Matrix4x4 & set(float r0c0, float r0c1, float r0c2, float r0c3, float r1c0, float r1c1, float r1c2, float r1c3, float r2c0, float r2c1, float r2c2, float r2c3, float r3c0, float r3c1, float r3c2, float r3c3)
Sets this matrix by its components.
Definition: Matrix4x4.h:108
Vector3 multiplyNoTranslation(const Vector3 &vector3) const
Multiplies this matrix with vector3 while ignoring translation.
Definition: Matrix4x4.h:238
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 & scale(float scalar)
Scales by scalar.
Definition: Vector3.h:201
Vector3 & normalize()
Normalizes this vector3.
Definition: Vector3.h:239
Byte buffer class.
Definition: ByteBuffer.h:27
ShortBuffer asShortBuffer()
Definition: ByteBuffer.h:53
FloatBuffer asFloatBuffer()
Definition: ByteBuffer.h:39
Console class.
Definition: Console.h:29
Float buffer class.
Definition: FloatBuffer.h:18
FloatBuffer * put(float value)
Put a float value into float buffer.
Definition: FloatBuffer.h:67
IntBuffer * put(uint32_t value)
Puts a value into buffer at its current position.
Definition: IntBuffer.h:61
Short buffer class.
Definition: ShortBuffer.h:14
ShortBuffer * put(uint16_t value)
Put a value into current position.
Definition: ShortBuffer.h:60