Skip to content

Commit

Permalink
Merge pull request #188 from imadhammani/main
Browse files Browse the repository at this point in the history
XCore intersectMesh: BVH
  • Loading branch information
benoit128 authored Sep 19, 2024
2 parents 22213d3 + a413f36 commit a73df77
Show file tree
Hide file tree
Showing 9 changed files with 295 additions and 8 deletions.
74 changes: 74 additions & 0 deletions Cassiopee/XCore/XCore/common/mem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,77 @@ void *xresize(void *ptr, E_Int nbytes, const char *file, E_Int line)
}
return ptr;
}

Mem_arena::Mem_arena()
{
arena = NULL;
size = 0;
capacity = 0;
nresize = 0;
nalloc = 0;
}

Mem_arena::Mem_arena(size_t nbytes)
{
arena = XMALLOC(nbytes);
size = 0;
capacity = nbytes;
nresize = 0;
nalloc = 0;
}

void Mem_arena::reserve(size_t nbytes)
{
assert(arena == NULL);
arena = XMALLOC(nbytes);
capacity = nbytes;
}

void *Mem_arena::alloc(size_t nbytes, const char *file, int line)
{
void *ptr = NULL;

nalloc++;

if (size + nbytes > capacity) {
/*
nresize++;
size_t new_size = size + nbytes;
size_t new_capacity = (size_t)((E_Float)new_size * 1.5);
arena = XRESIZE(arena, new_capacity);
assert(size + nbytes < new_capacity);
ptr = (void *)((char *)arena + size);
size = new_size;
capacity = new_capacity;
*/
fprintf(stderr, "Mem_arena: out of memory at %s:%d\n", file, line);
print_stats();
exit(1);
} else {
ptr = (void *)((char *)arena + size);
size += nbytes;
}

return ptr;
}

void Mem_arena::drop()
{
XFREE(arena);
size = capacity = nalloc = nresize = 0;
}

void Mem_arena::print_stats()
{
printf("\n");
printf(" /**** Mem_arena stats ****/\n");
printf(" size: %lu B\n", size);
printf(" capacity: %lu B\n", capacity);
printf(" usage: %.2f %%\n", size * 100.0f / capacity);
printf(" number of allocations: %zu\n", nalloc);
printf(" number of reallocations: %zu\n", nresize);
printf(" /*************************/\n");
printf("\n");
}
24 changes: 24 additions & 0 deletions Cassiopee/XCore/XCore/common/mem.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,28 @@ void *xcalloc(E_Int, E_Int, const char *, E_Int);
void xfree(void *, const char *, E_Int);
void *xresize(void *, E_Int, const char *, E_Int);

struct Mem_arena {
void *arena;

size_t size;
size_t capacity;

size_t nresize;
size_t nalloc;

Mem_arena();

Mem_arena(size_t nbytes);

void reserve(size_t nbytes);

void *alloc(size_t nbytes, const char *file, int line);

void drop();

void print_stats();
};

#define ARENA_ALLOC(nbytes) arena.alloc((nbytes), __FILE__, __LINE__)

#endif
31 changes: 31 additions & 0 deletions Cassiopee/XCore/XCore/intersectMesh/AABB.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "AABB.h"
#include "mesh.h"

AABB::AABB()
: xmin(EFLOATMAX), ymin(EFLOATMAX), zmin(EFLOATMAX),
xmax(EFLOATMIN), ymax(EFLOATMIN), zmax(EFLOATMIN)
{}

AABB::AABB(const IMesh &M, E_Int *ids, E_Int count)
{
xmin = ymin = zmin = EFLOATMAX;
xmax = ymax = zmax = EFLOATMIN;

for (E_Int i = 0; i < count; i++) {
E_Int fid = ids[i];

const auto &pn = M.F[fid];

for (E_Int p : pn) {
E_Float x = M.X[p];
E_Float y = M.Y[p];
E_Float z = M.Z[p];
if (x < xmin) xmin = x;
if (y < ymin) ymin = y;
if (z < zmin) zmin = z;
if (x > xmax) xmax = x;
if (y > ymax) ymax = y;
if (z > zmax) zmax = z;
}
}
}
20 changes: 14 additions & 6 deletions Cassiopee/XCore/XCore/intersectMesh/AABB.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
#pragma once

#include "xcore.h"

struct IMesh;

struct AABB {
E_Float xmin = EFLOATMAX;
E_Float xmax = EFLOATMIN;
E_Float ymin = EFLOATMAX;
E_Float ymax = EFLOATMIN;
E_Float zmin = EFLOATMAX;
E_Float zmax = EFLOATMIN;
E_Float xmin;
E_Float ymin;
E_Float zmin;
E_Float xmax;
E_Float ymax;
E_Float zmax;

AABB();

AABB(const IMesh &M, E_Int *ids, E_Int count);
};
107 changes: 107 additions & 0 deletions Cassiopee/XCore/XCore/intersectMesh/BVH.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#include "BVH.h"
#include "mesh.h"

// Creates the tree

static size_t leaf_count = 0;

BVH_node *BVH_create_node(AABB aabb, BVH_node *left_child, BVH_node *right_child,
E_Int *ids, E_Int count, Mem_arena &arena)
{
BVH_node *node = (BVH_node *)ARENA_ALLOC(sizeof(BVH_node));

node->bbox = aabb;
node->left = left_child;
node->right = right_child;
node->elements = (E_Int *)ARENA_ALLOC(count * sizeof(E_Int));
assert(count > 0);
memcpy(node->elements, ids, count * sizeof(E_Int));

leaf_count++;

return node;
}


BVH_node *BVH_create_node(AABB aabb, BVH_node *left_child,
BVH_node *right_child, Mem_arena &arena)
{
BVH_node *node = (BVH_node *)ARENA_ALLOC(sizeof(BVH_node));

node->bbox = aabb;
node->left = left_child;
node->right = right_child;
node->elements = NULL;

return node;
}

BVH_node *BVH_create_node(E_Int *ids, E_Int count, const IMesh &M,
Mem_arena &arena)
{
AABB aabb(M, ids, count);

if (count <= MAX_FACES_PER_LEAF) {
return BVH_create_node(aabb, NULL, NULL, ids, count, arena);
}

E_Float dx = aabb.xmax - aabb.xmin;
E_Float dy = aabb.ymax - aabb.ymin;
E_Float dz = aabb.zmax - aabb.zmin;

E_Float *pCoor;

if (dx >= dy && dx >= dz) {
pCoor = (E_Float *)M.X.data();
} else if (dy >= dz) {
assert(dy >= dx);
pCoor = (E_Float *)M.Y.data();
} else {
assert(dz >= dx && dz >= dy);
pCoor = (E_Float *)M.Z.data();
}

std::sort(ids, ids + count, [&] (E_Int i, E_Int j)
{
E_Float cci = 0.0, ccj = 0.0;

const auto &pni = M.F[i];
for (const E_Int p : pni) cci += pCoor[p];
cci /= pni.size();

const auto &pnj = M.F[j];
for (const E_Int p : pnj) ccj += pCoor[p];
ccj /= pnj.size();

return cci < ccj;
});

BVH_node *left = BVH_create_node(ids, count/2, M, arena);
BVH_node *right = BVH_create_node(ids + count/2, count - count/2, M, arena);

return BVH_create_node(aabb, left, right, arena);
}

BVH::BVH(const IMesh &M)
{
if (M.skin.empty()) {
puts("empty skin!");
exit(1);
}

size_t NF = M.skin.size();

printf("Number of faces: %zu\n", NF);

arena.reserve(10 * NF * sizeof(E_Int));

E_Int *ids = (E_Int *)ARENA_ALLOC(NF * sizeof(E_Int));

for (size_t i = 0; i < NF; i++) ids[i] = M.skin[i];

root = BVH_create_node(ids, NF, M, arena);

printf("Leaves: %zu\n", leaf_count);

arena.print_stats();
}
32 changes: 32 additions & 0 deletions Cassiopee/XCore/XCore/intersectMesh/BVH.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once

#include "AABB.h"
#include "common/mem.h"

#define MAX_FACES_PER_LEAF 10

struct IMesh;

struct BVH_node {
AABB bbox;
BVH_node *left;
BVH_node *right;
E_Int *elements;
};

BVH_node *BVH_create_node(AABB aabb, BVH_node *left_child,
BVH_node *right_child, Mem_arena &arena);

BVH_node *BVH_create_node(AABB aabb, BVH_node *left_child, BVH_node *right_child,
E_Int *ids, E_Int count, Mem_arena &arena);

BVH_node *BVH_create_node(E_Int *ids, E_Int count, const IMesh &M,
Mem_arena &arena);

struct BVH {
BVH_node *root;

Mem_arena arena;

BVH(const IMesh &M);
};
10 changes: 9 additions & 1 deletion Cassiopee/XCore/XCore/intersectMesh/IntersectMesh_Init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
#include "mesh.h"
#include "karray.h"
//#include "BVH.h"

PyObject *K_XCORE::IntersectMesh_Init(PyObject *self, PyObject *args)
{
Expand All @@ -39,6 +40,13 @@ PyObject *K_XCORE::IntersectMesh_Init(PyObject *self, PyObject *args)
// Init mesh

IMesh *M = new IMesh(*karray.cn, karray.X, karray.Y, karray.Z, karray.npts);
/*
M->make_skin();
puts("Making BVH");
BVH bvh(*M);
puts("Done");
bvh.arena.drop();
*/

if (TAGS != Py_None) {
E_Int size, nfld;
Expand Down Expand Up @@ -67,4 +75,4 @@ PyObject *K_XCORE::IntersectMesh_Init(PyObject *self, PyObject *args)
PyObject *hook = PyCapsule_New((void *)M, "IntersectMesh", NULL);

return hook;
}
}
2 changes: 1 addition & 1 deletion Cassiopee/XCore/XCore/intersectMesh/dcel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1040,7 +1040,7 @@ void Dcel::trace_hedge(Hedge *sh, const Smesh &M, const Smesh &S, E_Int hid)

} else {

// E_Intersection, move
// Intersection, move

current_face = h->twin->left;

Expand Down
3 changes: 3 additions & 0 deletions Cassiopee/XCore/srcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
'XCore/common/mem.cpp',
'XCore/common/common.cpp',

'XCore/intersectMesh/BVH.cpp',
'XCore/intersectMesh/AABB.cpp',

'XCore/intersectMesh/extract.cpp',

'XCore/intersectMesh/IntersectMesh_Init.cpp',
Expand Down

0 comments on commit a73df77

Please sign in to comment.