#include "../../GLM.h"
+#include <list>
+#include <array>
+
#include "../Shader.h"
#include "../Texture.h"
#include "../../Message.h"
#include "../Graphix.h"
using std::string;
-
-IMesh::IMesh(const string& _modelpath, uint _mindex) : modelpath(_modelpath)
+using std::list;
+using std::array;
+typedef Model::Triangle Triangle;
+typedef IMesh::Node Node;
+
+// Vergleiche Unterbaum
+//#define COMPARE_MTREE
+// Vergleiche auch Triangles
+#define COMPARE_FACE
+// Fordere mindestens prozentuelles gleichgewicht .1 = 10%
+#define HEAP_SCALE_BOUND .1f
+
+IMesh::IMesh(const string& _modelpath, uint _mindex) : modelpath(_modelpath), root(nullptr)
{
import(_modelpath, numvertices, numfaces, vertex, uvs, normals, index, _mindex);
- updateBB(numvertices,vertex);
+#ifdef COMPARE_MTREE
+ root = buildMeshTree(modelMat, numvertices, numfaces, vertex, normals, index);
+
+ vec3 min, max;
+ root->getBBmm(min, max);
+ updateBB(min, max);
+#else
+ updateBB(numvertices, vertex);
+#endif
genBuffer(vertexBuffer, numvertices * 3 * sizeof(float), (void*)vertex);
genBuffer(normalBuffer, numvertices * 3 * sizeof(float), (void*)normals);
}
-IMesh::IMesh(const aiMesh* _mesh, const mat4& _transformation) : modelMat(_transformation), modelpath("IMesh")
+IMesh::IMesh(const aiMesh* _mesh, const mat4& _transformation) : modelMat(_transformation), modelpath("IMesh"), root(nullptr)
{
import(_mesh, numvertices, numfaces, vertex, uvs, normals, index);
- updateBB(numvertices,vertex,modelMat);
+#ifdef COMPARE_MTREE
+ root = buildMeshTree(modelMat, numvertices, numfaces, vertex, normals, index);
+
+ vec3 min, max;
+ root->getBBmm(min, max);
+ updateBB(min, max);
+#else
+ updateBB(numvertices, vertex);
+#endif
genBuffer(vertexBuffer, numvertices * 3 * sizeof(float), (void*)vertex);
genBuffer(normalBuffer, numvertices * 3 * sizeof(float), (void*)normals);
}
-
IMesh::~IMesh()
{
delete vertex, normals, uvs, index;
glDeleteBuffers(1, &uvBuffer);
}
-
void IMesh::useModelMat(const mat4& _model, Shader* _shader) const
{
-// Model::useModelMat(_model, _shader);
-// Model::useModelMat(_model * modelMat, _shader);
+ // Model::useModelMat(_model, _shader);
+ // Model::useModelMat(_model * modelMat, _shader);
int tmp = _shader->getUniformLocation("uModel");
if (tmp >= 0)
glUniformMatrix4fv(tmp, 1, GL_FALSE, value_ptr(_model* modelMat));
//Outer BBox
Overlap firstBB = Model::checkColS2O(_mMat, _model, _modelMat);
//if (!firstBB)
- return firstBB;
+ return firstBB;
//Inner Mesh
//call _model->checkColO2STriangle
// tmp = _model->checkColO2STriangle(_modelMat, pos, direction);
// if (tmp)
// secondT.update(tmp);
- // }
+ // }
//return secondT;
}
//Outer Mesh
Overlap firstBB = Model::checkColO2SBox(_mMat, _pos, _size, _modelMat);
//if (!firstBB)
- return firstBB;
+ return firstBB;
//Inner Mesh
//call checkColO2STriangle
{
Overlap firstBB = Model::checkColO2STriangle(_mMat, _posB, _directionsB);
//if (!firstBB)
- return firstBB;
+ return firstBB;
//Inner Mesh
-
+
}
IMesh::operator string() const
return "IMesh";
}
+void getPSfromNodeList(vec3& center, vec3& size, const list<Node*>& TriList)
+{
+ vec3 BBmin, BBmax;
+ TriList.front()->getBBmm(BBmin, BBmax);
+ for (auto k = TriList.cbegin(); k != TriList.cend(); ++k)
+ {
+ (*k)->getUBBmm(BBmin, BBmax);
+ }
+
+ size = (BBmax - BBmin) / 2.f;
+ center = (BBmin + BBmax) / 2.f;
+}
+
+Node* IMesh::buildMeshTree(const list<Node*>& _triList, vec3 center, vec3 size)
+{
+ //catch if list is empty
+ if (_triList.size() == 0)
+ return nullptr;
+ //catch if list has only one element => LEAF
+ if (_triList.size() == 1)
+ return _triList.front();
+ //catch if list has only two elements => 2 LEAFS
+ if (_triList.size() == 2)
+ return new Node(center, size, _triList.front(), _triList.back());
+
+ //find longest dist
+ vec3 sort = sortVec3(size);
+
+ //SPLIT and call self
+ array<list<Node*>, 3> lower, upper;
+ vec3 tmpMin, tmpMax;
+ mat3 lMin, lMax, uMin, uMax;
+ int dim(0), bestDim;
+ float bestPerc(1), splitPerc(1);
+
+ //try different DIM
+
+ for (auto k = _triList.cbegin(); k != _triList.cend(); ++k)
+ {
+ (*k)->getBBmm(tmpMin, tmpMax);
+ vec3 mean = (*k)->getMean();
+ for (dim = 0; dim < 3; ++dim)
+ {
+ if (mean[(int)sort[dim]] < center[(int)sort[dim]])
+ {
+ if (lower[dim].size() < 1)
+ {
+ lMin[dim] = tmpMin;
+ lMax[dim] = tmpMax;
+ }
+ else
+ updateVec3MinMax(lMin[dim], lMax[dim], tmpMin, tmpMax);
+ lower[dim].push_back(*k);
+ }
+ else
+ {
+ if (upper[dim].size() < 1)
+ {
+ uMin[dim] = tmpMin;
+ uMax[dim] = tmpMax;
+ }
+ else
+ updateVec3MinMax(uMin[dim], uMax[dim], tmpMin, tmpMax);
+ upper[dim].push_back(*k);
+ }
+ }
+ }
+ for (dim = 0; dim < 3; ++dim)
+ {
+ splitPerc = abs(upper[dim].size() / (float)_triList.size() - .5f);
+ if (splitPerc < .4f)
+ break;
+ if (splitPerc < bestPerc)
+ {
+ bestDim = dim;
+ bestPerc = splitPerc;
+ }
+
+ }
+ if (dim == 3)
+ dim = bestDim;
+
+
+ return new Node(center, size, buildMeshTree(lower[dim], (lMin[dim] + lMax[dim]) / 2.f, (lMax[dim] - lMin[dim]) / 2.f),
+ buildMeshTree(upper[dim], (uMin[dim] + uMax[dim]) / 2.f, (uMax[dim] - uMin[dim]) / 2.f));
+}
+
+Node* IMesh::buildMeshTree(const mat4& modelMat, const uint& numvertices, const uint& numfaces, const float* vertex, const float* normals, const uint* index)
+{
+ list<Node*> node_list;
+ mat3 tmp_vert;
+ vec3 tmp_normal;
+ for (uint i = 0; i < numfaces; ++i)
+ {
+ tmp_vert[0] = (vec3)(modelMat*vec4(vertex[3 * index[3 * i]], vertex[3 * index[3 * i] + 1], vertex[3 * index[3 * i] + 2], 1.f));
+ tmp_vert[1] = (vec3)(modelMat*vec4(vertex[3 * index[3 * i + 1]], vertex[3 * index[3 * i + 1] + 1], vertex[3 * index[3 * i + 1] + 2], 1.f));
+ tmp_vert[2] = (vec3)(modelMat*vec4(vertex[3 * index[3 * i + 2]], vertex[3 * index[3 * i + 2] + 1], vertex[3 * index[3 * i + 2] + 2], 1.f));
+
+ tmp_normal = cross(tmp_vert[1] - tmp_vert[0], tmp_vert[2] - tmp_vert[0]);
+ if (0>dot(tmp_normal, vec3(normals[3 * index[3 * i]], normals[3 * index[3 * i] + 1], normals[3 * index[3 * i] + 2])))
+ tmp_normal *= -1;
+ node_list.push_back(new Node(new Triangle(tmp_vert, tmp_normal)));
+ }
+ vec3 center, size;
+ getPSfromNodeList(center, size, node_list);
+
+
+ return buildMeshTree(node_list, center, size);
+}
+
+
+Node::Node(Triangle* tri) : element(tri), lNode(nullptr), uNode(nullptr), splitDim(-1)
+{
+ mean = element->getMean();
+ element->getBBmm(min, max);
+ size = (max - min) / 2.f;
+ center = (min + max) / 2.f;
+}
+
+//Node::Node(Triangle* tri, const vec3& cen, const vec3& siz, const vec3& mi, const vec3& ma)
+// : element(tri), center(cen), size(siz), min(mi), max(ma), lNode(nullptr), uNode(nullptr), splitDim(-1)
+//{
+//}
+
+Node::Node(const vec3& _center, const vec3& _size, Node* _lower, Node* _upper)
+ : element(nullptr), lNode(_lower), uNode(_upper), splitDim(-1), center(_center), size(_size)
+{
+}
+
+Node::~Node()
+{
+ if (element != nullptr)
+ delete element;
+ else
+ delete lNode, uNode;
+}
+
+
+void Node::getBBcs(vec3& cen, vec3& siz) const
+{
+ cen = center;
+ siz = size;
+}
+
+void Node::getBBmm(vec3& mi, vec3& ma) const
+{
+ mi = min;
+ ma = max;
+}
-IMesh::Node::Node()
+void Node::getUBBmm(vec3& mi, vec3& ma) const
{
+ updateVec3MinMax(mi, ma, min, max);
}
-IMesh::Node::~Node()
+vec3 Node::getMean() const
{
+ return mean;
}
#pragma once
#include <string>
+#include <list>
#include "../../GLM.h"
#include "../../Overlap.h"
class IMesh : public Model
{
public:
+ class Node;
+
IMesh(const std::string& modelpath, uint index=0);
IMesh(const aiMesh* mesh, const mat4& transformation);
operator std::string() const override;
+ static Node* buildMeshTree(const mat4& modelMat, const uint& numvertices, const uint& numfaces, const float* vertex, const float* normals, const uint* index);
+ static Node* buildMeshTree(const std::list<IMesh::Node*>& triList, vec3 center, vec3 size);
+
+ class Node
+ {
+ public:
+ Node(Triangle* tri);
+ //Node(Triangle* tri, const vec3& center, const vec3& size, const vec3& min, const vec3& max);
+ Node::Node(const vec3& center, const vec3& size, Node* lower, Node* upper);
+ ~Node();
+
+ /* sets center & size */
+ void getBBcs(vec3& center, vec3& size) const;
+ /* sets min & max */
+ void getBBmm(vec3& min, vec3& max) const;
+ /* updates min & max */
+ void getUBBmm(vec3& min, vec3& max) const;
+ /* get mean*/
+ vec3 getMean() const;
+
+ private:
+ vec3 center;
+ vec3 size;
+ vec3 min;
+ vec3 max;
+ vec3 mean;
+
+ Node *lNode, *uNode;
+ Model::Triangle *element;
+
+ int splitDim;
+ };
+
protected:
std::string modelpath;
bool import(const std::string& modelpath, uint& numvertices, uint& numfaces, float*& vertex, float*& uvs, float*& normals, uint*& index , uint mindex = 0) const;
bool import(const aiMesh* mesh, uint& numvertices, uint& numfaces, float*& vertex, float*& uvs, float*& normals, uint*& index) const;
- class Node;
Node* root;
- class Node
- {
- public:
- Node();
- ~Node();
- private:
- vec3 center;
- vec3 size_2;
-
- Node *lNode, *hNode;
- Model::Triangle *element;
-
- int splitDim;
- int splitCenter;
-
- };
};
\ No newline at end of file