Skip to content

Commit 59d33db

Browse files
authored
UPBGE: Implement BVH generation from KX_Mesh. (#736)
The python function KX_Mesh.constructBvh now returns a new BVH Tree based on the mesh geometry where every indices elements of the tree correspond to the polygons indices.
1 parent f72f4c0 commit 59d33db

File tree

5 files changed

+93
-1
lines changed

5 files changed

+93
-1
lines changed

doc/python_api/rst/bge_types/bge.types.KX_Mesh.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,10 @@ base class --- :class:`EXP_Value`
154154

155155
:return: a duplicated mesh of the current used.
156156
:rtype: :class:`KX_Mesh`.
157+
158+
.. method:: constructBvh()
159+
160+
Return a BVH tree based on mesh geometry. Indices of tree elements match polygons indices.
161+
162+
:return: A BVH tree based on mesh geometry.
163+
:rtype: :class:`mathutils.bvhtree.BVHTree`

source/blender/python/mathutils/mathutils_bvhtree.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ typedef struct {
117117
/** \name Utility helper functions
118118
* \{ */
119119

120-
static PyObject *bvhtree_CreatePyObject(
120+
PyObject *bvhtree_CreatePyObject(
121121
BVHTree *tree, float epsilon,
122122

123123
float (*coords)[3], unsigned int coords_len,

source/blender/python/mathutils/mathutils_bvhtree.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,22 @@
2626
#ifndef __MATHUTILS_BVHTREE_H__
2727
#define __MATHUTILS_BVHTREE_H__
2828

29+
typedef struct BVHTree BVHTree;
30+
2931
PyMODINIT_FUNC PyInit_mathutils_bvhtree(void);
3032

3133
extern PyTypeObject PyBVHTree_Type;
3234

3335
#define PyBVHTree_Check(v) PyObject_TypeCheck((v), &PyBVHTree_Type)
3436
#define PyBVHTree_CheckExact(v) (Py_TYPE(v) == &PyBVHTree_Type)
3537

38+
PyObject *bvhtree_CreatePyObject(
39+
BVHTree *tree, float epsilon,
40+
41+
float (*coords)[3], unsigned int coords_len,
42+
unsigned int (*tris)[3], unsigned int tris_len,
43+
44+
/* optional arrays */
45+
int *orig_index, float (*orig_normal)[3]);
46+
3647
#endif /* __MATHUTILS_BVHTREE_H__ */

source/gameengine/Ketsji/KX_Mesh.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@
5353
#include "EXP_PyObjectPlus.h"
5454
#include "EXP_ListWrapper.h"
5555

56+
#include "BLI_kdopbvh.h"
57+
58+
#include "MEM_guardedalloc.h"
59+
60+
extern "C" {
61+
# include "mathutils_bvhtree.h"
62+
}
63+
5664
KX_Mesh::KX_Mesh(KX_Scene *scene, Mesh *mesh, const RAS_Mesh::LayersInfo& layersInfo)
5765
:RAS_Mesh(mesh, layersInfo),
5866
m_scene(scene)
@@ -108,6 +116,7 @@ PyMethodDef KX_Mesh::Methods[] = {
108116
{"transformUV", (PyCFunction)KX_Mesh::sPyTransformUV, METH_VARARGS},
109117
{"replaceMaterial", (PyCFunction)KX_Mesh::sPyReplaceMaterial, METH_VARARGS},
110118
{"copy", (PyCFunction)KX_Mesh::sPyCopy, METH_NOARGS},
119+
{"constructBvh", (PyCFunction)KX_Mesh::sPyConstructBvh, METH_VARARGS},
111120
{nullptr, nullptr} //Sentinel
112121
};
113122

@@ -392,6 +401,70 @@ PyObject *KX_Mesh::PyCopy()
392401
return dupli->GetProxy();
393402
}
394403

404+
PyObject *KX_Mesh::PyConstructBvh(PyObject *args, PyObject *kwds)
405+
{
406+
float epsilon = 0.0f;
407+
408+
if (!PyArg_ParseTuple(args, "|f:constructBvh", &epsilon)) {
409+
return nullptr;
410+
}
411+
412+
BVHTree *tree = BLI_bvhtree_new(m_numPolygons, epsilon, 4, 6);
413+
414+
unsigned int numVert = 0;
415+
// Compute the totale number of vertices.
416+
for (const PolygonRangeInfo& range : m_polygonRanges) {
417+
numVert += range.array->GetVertexCount();
418+
}
419+
420+
float (*coords)[3] = (float (*)[3])MEM_mallocN(sizeof(float[3]) * numVert, __func__);
421+
// Convert the vertices.
422+
{
423+
unsigned vertBase = 0;
424+
for (const PolygonRangeInfo& range : m_polygonRanges) {
425+
RAS_DisplayArray *array = range.array;
426+
for (unsigned int i = 0, size = array->GetVertexCount(); i < size; ++i) {
427+
copy_v3_v3(coords[vertBase + i], array->GetPosition(i).data);
428+
}
429+
vertBase += array->GetVertexCount();
430+
}
431+
}
432+
433+
unsigned int *tris = (unsigned int *)MEM_mallocN(sizeof(unsigned int) * 3 * m_numPolygons, __func__);
434+
// Convert the indices.
435+
{
436+
unsigned int index = 0;
437+
unsigned int vertBase = 0;
438+
for (const PolygonRangeInfo& range : m_polygonRanges) {
439+
// Iterate by triangle (3 indices).
440+
for (; index < range.endIndex; index += 3) {
441+
// Get the relative triangle base index.
442+
const unsigned int triBase = index - range.startIndex;
443+
float co[3][3];
444+
445+
for (unsigned short i = 0; i < 3; ++i) {
446+
// Get the absolute the vertex index.
447+
const unsigned int vertIndex = vertBase + range.array->GetTriangleIndex(triBase + i);
448+
449+
tris[index + i] = vertIndex;
450+
copy_v3_v3(co[i], coords[vertIndex]);
451+
}
452+
453+
BLI_bvhtree_insert(tree, index / 3, co[0], 3);
454+
}
455+
vertBase += range.array->GetVertexCount();
456+
}
457+
}
458+
459+
BLI_bvhtree_balance(tree);
460+
461+
return bvhtree_CreatePyObject(
462+
tree, epsilon,
463+
coords, numVert,
464+
(unsigned int (*)[3])tris, m_numPolygons * 3,
465+
nullptr, nullptr);
466+
}
467+
395468
PyObject *KX_Mesh::pyattr_get_materials(EXP_PyObjectPlus *self_v, const EXP_PYATTRIBUTE_DEF *attrdef)
396469
{
397470
KX_Mesh *self = static_cast<KX_Mesh *>(self_v);

source/gameengine/Ketsji/KX_Mesh.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class KX_Mesh : public EXP_Value, public RAS_Mesh
7676
EXP_PYMETHOD(KX_Mesh, TransformUV);
7777
EXP_PYMETHOD(KX_Mesh, ReplaceMaterial);
7878
EXP_PYMETHOD_NOARGS(KX_Mesh, Copy);
79+
EXP_PYMETHOD(KX_Mesh, ConstructBvh);
7980

8081
static PyObject *pyattr_get_materials(EXP_PyObjectPlus *self_v, const EXP_PYATTRIBUTE_DEF *attrdef);
8182
static PyObject *pyattr_get_numMaterials(EXP_PyObjectPlus *self_v, const EXP_PYATTRIBUTE_DEF *attrdef);

0 commit comments

Comments
 (0)