tornavis/source/blender/blenkernel/intern/CCGSubSurf_util.cc

317 lines
8.0 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bke
*/
#include <cmath>
#include <cstdlib>
#include <cstring>
#include "BLI_sys_types.h" /* for intptr_t support */
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h" /* for BLI_assert */
#include "CCGSubSurf.h"
#include "CCGSubSurf_intern.h"
/**
* Hash implementation.
*/
static int kHashSizes[] = {
1, 3, 5, 11, 17, 37, 67, 131, 257, 521,
1031, 2053, 4099, 8209, 16411, 32771, 65537, 131101, 262147, 524309,
1048583, 2097169, 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459,
};
/* -------------------------------------------------------------------- */
/** \name Generic Hash Functions
* \{ */
EHash *ccg_ehash_new(int estimatedNumEntries,
CCGAllocatorIFC *allocatorIFC,
CCGAllocatorHDL allocator)
{
EHash *eh = static_cast<EHash *>(allocatorIFC->alloc(allocator, sizeof(*eh)));
eh->allocatorIFC = *allocatorIFC;
eh->allocator = allocator;
eh->numEntries = 0;
eh->curSizeIdx = 0;
while (kHashSizes[eh->curSizeIdx] < estimatedNumEntries) {
eh->curSizeIdx++;
}
eh->curSize = kHashSizes[eh->curSizeIdx];
eh->buckets = EHASH_alloc(eh, eh->curSize * sizeof(*eh->buckets));
memset(eh->buckets, 0, eh->curSize * sizeof(*eh->buckets));
return eh;
}
void ccg_ehash_free(EHash *eh, EHEntryFreeFP freeEntry, void *user_data)
{
int numBuckets = eh->curSize;
while (numBuckets--) {
EHEntry *entry = eh->buckets[numBuckets];
while (entry) {
EHEntry *next = entry->next;
freeEntry(entry, user_data);
entry = next;
}
}
EHASH_free(eh, eh->buckets);
EHASH_free(eh, eh);
}
void ccg_ehash_insert(EHash *eh, EHEntry *entry)
{
int numBuckets = eh->curSize;
int hash = EHASH_hash(eh, entry->key);
entry->next = eh->buckets[hash];
eh->buckets[hash] = entry;
eh->numEntries++;
if (UNLIKELY(eh->numEntries > (numBuckets * 3))) {
EHEntry **oldBuckets = eh->buckets;
eh->curSize = kHashSizes[++eh->curSizeIdx];
eh->buckets = EHASH_alloc(eh, eh->curSize * sizeof(*eh->buckets));
memset(eh->buckets, 0, eh->curSize * sizeof(*eh->buckets));
while (numBuckets--) {
for (entry = oldBuckets[numBuckets]; entry;) {
EHEntry *next = entry->next;
hash = EHASH_hash(eh, entry->key);
entry->next = eh->buckets[hash];
eh->buckets[hash] = entry;
entry = next;
}
}
EHASH_free(eh, oldBuckets);
}
}
void *ccg_ehash_lookupWithPrev(EHash *eh, void *key, void ***prevp_r)
{
int hash = EHASH_hash(eh, key);
void **prevp = (void **)&eh->buckets[hash];
EHEntry *entry;
for (; (entry = static_cast<EHEntry *>(*prevp)); prevp = (void **)&entry->next) {
if (entry->key == key) {
*prevp_r = (void **)prevp;
return entry;
}
}
return nullptr;
}
void *ccg_ehash_lookup(EHash *eh, void *key)
{
int hash = EHASH_hash(eh, key);
EHEntry *entry;
for (entry = eh->buckets[hash]; entry; entry = entry->next) {
if (entry->key == key) {
break;
}
}
return entry;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Hash Elements Iteration
* \{ */
void ccg_ehashIterator_init(EHash *eh, EHashIterator *ehi)
{
/* fill all members */
ehi->eh = eh;
ehi->curBucket = -1;
ehi->curEntry = nullptr;
while (!ehi->curEntry) {
ehi->curBucket++;
if (ehi->curBucket == ehi->eh->curSize) {
break;
}
ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
}
}
void *ccg_ehashIterator_getCurrent(EHashIterator *ehi)
{
return ehi->curEntry;
}
void ccg_ehashIterator_next(EHashIterator *ehi)
{
if (ehi->curEntry) {
ehi->curEntry = ehi->curEntry->next;
while (!ehi->curEntry) {
ehi->curBucket++;
if (ehi->curBucket == ehi->eh->curSize) {
break;
}
ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
}
}
}
int ccg_ehashIterator_isStopped(EHashIterator *ehi)
{
return !ehi->curEntry;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Standard allocator implementation
* \{ */
static void *_stdAllocator_alloc(CCGAllocatorHDL /*a*/, int numBytes)
{
return MEM_mallocN(numBytes, "CCG standard alloc");
}
static void *_stdAllocator_realloc(CCGAllocatorHDL /*a*/, void *ptr, int newSize, int /*oldSize*/)
{
return MEM_reallocN(ptr, newSize);
}
static void _stdAllocator_free(CCGAllocatorHDL /*a*/, void *ptr)
{
MEM_freeN(ptr);
}
CCGAllocatorIFC *ccg_getStandardAllocatorIFC()
{
static CCGAllocatorIFC ifc;
ifc.alloc = _stdAllocator_alloc;
ifc.realloc = _stdAllocator_realloc;
ifc.free = _stdAllocator_free;
ifc.release = nullptr;
return &ifc;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name * Catmull-Clark Gridding Subdivision Surface
* \{ */
#ifdef DUMP_RESULT_GRIDS
void ccgSubSurf__dumpCoords(CCGSubSurf *ss)
{
int vertDataSize = ss->meshIFC.vertDataSize;
int subdivLevels = ss->subdivLevels;
int gridSize = ccg_gridsize(subdivLevels);
int edgeSize = ccg_edgesize(subdivLevels);
int i, index, S;
for (i = 0, index = 0; i < ss->vMap->curSize; i++) {
CCGVert *v = (CCGVert *)ss->vMap->buckets[i];
for (; v; v = v->next, index++) {
float *co = VERT_getCo(v, subdivLevels);
printf("vertex index=%d, co=(%f, %f, %f)\n", index, co[0], co[1], co[2]);
}
}
for (i = 0, index = 0; i < ss->eMap->curSize; i++) {
CCGEdge *e = (CCGEdge *)ss->eMap->buckets[i];
for (; e; e = e->next, index++) {
int x;
float *co = VERT_getCo(e->v0, subdivLevels);
printf("edge index=%d, start_co=(%f, %f, %f)\n", index, co[0], co[1], co[2]);
for (x = 0; x < edgeSize; x++) {
float *co = EDGE_getCo(e, subdivLevels, x);
printf("edge index=%d, seg=%d, co=(%f, %f, %f)\n", index, x, co[0], co[1], co[2]);
}
co = VERT_getCo(e->v1, subdivLevels);
printf("edge index=%d, end_co=(%f, %f, %f)\n", index, co[0], co[1], co[2]);
}
}
for (i = 0, index = 0; i < ss->fMap->curSize; i++) {
CCGFace *f = (CCGFace *)ss->fMap->buckets[i];
for (; f; f = f->next, index++) {
for (S = 0; S < f->numVerts; S++) {
CCGVert *v = FACE_getVerts(f)[S];
float *co = VERT_getCo(v, subdivLevels);
printf("face index=%d, vertex=%d, coord=(%f, %f, %f)\n", index, S, co[0], co[1], co[2]);
}
}
}
for (i = 0, index = 0; i < ss->fMap->curSize; i++) {
CCGFace *f = (CCGFace *)ss->fMap->buckets[i];
for (; f; f = f->next, index++) {
for (S = 0; S < f->numVerts; S++) {
CCGEdge *e = FACE_getEdges(f)[S];
float *co1 = VERT_getCo(e->v0, subdivLevels);
float *co2 = VERT_getCo(e->v1, subdivLevels);
printf("face index=%d, edge=%d, coord1=(%f, %f, %f), coord2=(%f, %f, %f)\n",
index,
S,
co1[0],
co1[1],
co1[2],
co2[0],
co2[1],
co2[2]);
}
}
}
for (i = 0, index = 0; i < ss->fMap->curSize; i++) {
CCGFace *f = (CCGFace *)ss->fMap->buckets[i];
for (; f; f = f->next, index++) {
for (S = 0; S < f->numVerts; S++) {
int x, y;
for (x = 0; x < gridSize; x++) {
for (y = 0; y < gridSize; y++) {
float *co = FACE_getIFCo(f, subdivLevels, S, x, y);
printf("face index=%d. corner=%d, x=%d, y=%d, coord=(%f, %f, %f)\n",
index,
S,
x,
y,
co[0],
co[1],
co[2]);
}
}
for (x = 0; x < gridSize; x++) {
float *co = FACE_getIECo(f, subdivLevels, S, x);
printf("face index=%d. corner=%d, ie_index=%d, coord=(%f, %f, %f)\n",
index,
S,
x,
co[0],
co[1],
co[2]);
}
}
}
}
}
#endif /* DUMP_RESULT_GRIDS */
/** \} */