4 #include <unordered_map>
25 using std::unordered_map;
45 BoundingBox* ModelUtilitiesInternal::createBoundingBox(
Model* model,
const unordered_map<string, Matrix4x4*> overriddenNodeTransformMatrices)
48 objectModel.
instanceAnimations[0]->overriddenTransformMatrices = overriddenNodeTransformMatrices;
56 auto model = objectModelInternal->
getModel();
58 float minX = 0.0f, minY = 0.0f, minZ = 0.0f;
59 float maxX = 0.0f, maxY = 0.0f, maxZ = 0.0f;
60 auto firstVertex =
true;
63 animationState.
setup = defaultAnimation;
66 animationState.
time = 0.0f;
68 for (
auto t = 0.0f; t <= (defaultAnimation != nullptr ? static_cast<float>(defaultAnimation->getFrames()) : 0.0f) / model->getFPS(); t += 1.0f / model->getFPS()) {
75 for (
auto objectNode : objectModelInternal->
objectNodes) {
76 for (
const auto& vertex : *objectNode->mesh->vertices) {
77 if (firstVertex ==
true) {
86 if (vertex[0] < minX) minX = vertex[0];
87 if (vertex[1] < minY) minY = vertex[1];
88 if (vertex[2] < minZ) minZ = vertex[2];
89 if (vertex[0] > maxX) maxX = vertex[0];
90 if (vertex[1] > maxY) maxY = vertex[1];
91 if (vertex[2] > maxZ) maxZ = vertex[2];
95 animationState.
currentAtTime =
static_cast<int64_t
>((t * 1000.0f));
96 animationState.
lastAtTime =
static_cast<int64_t
>((t * 1000.0f));
99 if (firstVertex ==
true)
return nullptr;
106 auto model = objectModelInternal->
getModel();
108 float minX = 0.0f, minY = 0.0f, minZ = 0.0f;
109 float maxX = 0.0f, maxY = 0.0f, maxZ = 0.0f;
110 auto firstVertex =
true;
113 animationState.
setup = defaultAnimation;
116 animationState.
time = 0.0f;
119 for (
auto t = 0.0f; t <= (defaultAnimation != nullptr ? static_cast<float>(defaultAnimation->getFrames()) : 0.0f) / model->getFPS(); t += 1.0f / model->getFPS()) {
124 for (
const auto& [nodeId, node]: model->getNodes()) {
126 vertex = transformedNodeMatrix.multiply(vertex.
set(0.0f, 0.0f, 0.0f));
127 if (firstVertex ==
true) {
136 if (vertex[0] < minX) minX = vertex[0];
137 if (vertex[1] < minY) minY = vertex[1];
138 if (vertex[2] < minZ) minZ = vertex[2];
139 if (vertex[0] > maxX) maxX = vertex[0];
140 if (vertex[1] > maxY) maxY = vertex[1];
141 if (vertex[2] > maxZ) maxZ = vertex[2];
144 animationState.
currentAtTime =
static_cast<int64_t
>((t * 1000.0f));
145 animationState.
lastAtTime =
static_cast<int64_t
>((t * 1000.0f));
148 if (firstVertex ==
true)
return nullptr;
160 for (
const auto& [nodeId, node]: nodes) {
161 auto normals = node->getNormals();
162 for (
auto& normal : normals) {
166 node->setNormals(normals);
180 unordered_map<string, int32_t> materialCountById;
181 auto opaqueFaceCount = 0;
182 auto transparentFaceCount = 0;
183 for (
auto objectNode : objectModelInternal->
objectNodes) {
185 const auto& facesEntities = objectNode->node->getFacesEntities();
186 auto facesEntityIdxCount = facesEntities.size();
187 for (
auto faceEntityIdx = 0; faceEntityIdx < facesEntityIdxCount; faceEntityIdx++) {
188 const auto& facesEntity = facesEntities[faceEntityIdx];
189 auto faces = facesEntity.getFaces().size();
191 auto material = facesEntity.getMaterial();
193 auto transparentFacesEntity =
false;
195 if (material !=
nullptr) {
196 auto specularMaterialProperties = material->getSpecularMaterialProperties();
197 if (specularMaterialProperties !=
nullptr &&
198 (specularMaterialProperties->hasColorTransparency() ==
true || specularMaterialProperties->hasTextureTransparency() ==
true))
199 transparentFacesEntity =
true;
203 auto materialId = material ==
nullptr ?
"tdme.material.none" : material->getId();
204 materialCountById[materialId]++;
206 if (transparentFacesEntity ==
true) {
208 transparentFaceCount += faces;
212 opaqueFaceCount += faces;
216 auto materialCount = materialCountById.size();
235 for (
auto i = 0; i < objectModel1Internal->
objectNodes.size(); i++) {
236 auto objectNodeModel1 = objectModel1Internal->
objectNodes[i];
237 auto objectNodeModel2 = objectModel2Internal->
objectNodes[i];
238 auto node1 = objectModel1Internal->
objectNodes[i]->node;
239 auto node2 = objectModel2Internal->
objectNodes[i]->node;
240 const auto& facesEntitiesModel1 = objectNodeModel1->node->getFacesEntities();
241 const auto& facesEntitiesModel2 = objectNodeModel2->node->getFacesEntities();
243 if (objectNodeModel1->node->getTransformMatrix().equals(objectNodeModel2->node->getTransformMatrix()) ==
false)
246 if (node1->getVertices().size() != node2->getVertices().size())
249 for (
auto j = 0; j < node1->getVertices().size(); j++) {
250 if (node1->getVertices()[j].equals(node2->getVertices()[j]) ==
false)
254 if (node1->getNormals().size() != node2->getNormals().size())
257 for (
auto j = 0; j < node1->getNormals().size(); j++) {
258 if (node1->getNormals()[j].equals(node2->getNormals()[j]) ==
false)
262 if (facesEntitiesModel1.size() != facesEntitiesModel2.size())
265 for (
auto j = 0; j < facesEntitiesModel1.size(); j++) {
266 auto facesEntityModel1 = facesEntitiesModel1[j];
267 auto facesEntityModel2 = facesEntitiesModel2[j];
270 if (facesEntityModel1.getMaterial() ==
nullptr && facesEntityModel2.getMaterial() !=
nullptr)
273 if (facesEntityModel1.getMaterial() !=
nullptr && facesEntityModel2.getMaterial() ==
nullptr)
276 if (facesEntityModel1.getMaterial() !=
nullptr && facesEntityModel2.getMaterial() !=
nullptr &&
277 facesEntityModel1.getMaterial()->getId() != facesEntityModel2.getMaterial()->getId()) {
281 const auto& facesModel1 = facesEntityModel1.getFaces();
282 const auto& facesModel2 = facesEntityModel2.getFaces();
284 if (facesModel1.size() != facesModel2.size())
287 for (
auto k = 0; k < facesModel1.size(); k++) {
289 auto vertexIndicesModel1 = facesModel1[k].getVertexIndices();
290 auto vertexIndicesModel2 = facesModel2[k].getVertexIndices();
291 if (vertexIndicesModel1[0] != vertexIndicesModel2[0] ||
292 vertexIndicesModel1[1] != vertexIndicesModel2[1] ||
293 vertexIndicesModel1[2] != vertexIndicesModel2[2]) {
static constexpr int64_t UNDEFINED
Represents a model face, consisting of vertex, normal, tangent and bitangent vectors,...
Node faces entity A node can have multiple entities containing faces and a applied material.
Representation of a 3D model.
unordered_map< string, Node * > & getSubNodes()
Returns object's sub nodes.
AnimationSetup * getAnimationSetup(const string &id)
const Matrix4x4 & getImportTransformMatrix()
Represents specular material properties.
Axis aligned bounding box used for frustum, this is not directly connectable with physics engine.
static void invertNormals(Model *model)
Invert normals of a model.
static void computeModelStatistics(Model *model, ModelStatistics *modelStatistics)
Compute model statistics.
static bool equals(Model *model1, Model *model2)
Compute if model 1 equals model 2.
static BoundingBox * createBoundingBox(Model *model, const unordered_map< string, Matrix4x4 * > overriddenNodeTransformMatrices=unordered_map< string, Matrix4x4 * >())
Creates a bounding box from given model.
static BoundingBox * createBoundingBoxNoMesh(ObjectModelInternal *objectModelInternal)
Creates a bounding box from given object model without mesh.
const Matrix4x4 getNodeTransformMatrix(const string &id)
Returns transform matrix for given node.
vector< ObjectAnimation * > instanceAnimations
vector< ObjectNode * > objectNodes
const Matrix4x4 & getTransformMatrix() const
Object model To be used in non engine context.
Object node mesh specifically for rendering.
Object node specifically for rendering.
static void computeAnimation(int contextIdx, vector< ObjectNode * > &objectNodes)
Computes animation for given object nodes.
Matrix4x4 class representing matrix4x4 mathematical structure and operations for 3d space.
Vector3 multiply(const Vector3 &vector3) const
Multiplies this matrix with vector3.
Vector3 class representing vector3 mathematical structure and operations with x, y,...
Vector3 & set(float x, float y, float z)
Sets this vector3 by its components.
int32_t transparentFaceCount