CCGSubSurf: Split file into several smaller ones

This is a preparation commit for having OpenSubdiv integrated into Blender
and new layout is the following:

- CCGSubSurf.c contains implementation of common functions used by both
  legacy subdivisions code and by the new code in the future.

- CCGSubSurf_inline.h contains internal functions which are to be inlined
  due to the performance reasons. Those functions are only ment to be used
  bu CCGSubSurf* files.

- CCGSubSurf_intern.h contains declarations of private functions and data
  structures used by CCGSubSurf module.

- CCGSubSurf_legacy.c contains legacy implementation of subdivision algorithm.

- CCHSubSurf_util.c contains utility functions which are not directly related
  on the subdivision code (i.e. debug functions, hash implementation etc).

There should be no functional changes so far.
This commit is contained in:
Sergey Sharybin 2015-07-20 15:05:16 +02:00
parent 6190d75b5a
commit ccc3c2dbda
6 changed files with 2119 additions and 1744 deletions

@ -61,6 +61,8 @@ set(INC_SYS
set(SRC
intern/CCGSubSurf.c
intern/CCGSubSurf_legacy.c
intern/CCGSubSurf_util.c
intern/DerivedMesh.c
intern/action.c
intern/addon.c
@ -285,6 +287,8 @@ set(SRC
nla_private.h
tracking_private.h
intern/CCGSubSurf.h
intern/CCGSubSurf_inline.h
intern/CCGSubSurf_intern.h
intern/pbvh_intern.h
intern/data_transfer_intern.h
)

File diff suppressed because it is too large Load Diff

@ -0,0 +1,269 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/blenkernel/intern/CCGSubSurf_inline.h
* \ingroup bke
*/
#ifndef __CCGSUBSURF_INLINE_H__
#define __CCGSUBSURF_INLINE_H__
BLI_INLINE int ccg_gridsize(int level)
{
BLI_assert(level > 0);
BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
return (1 << (level - 1)) + 1;
}
BLI_INLINE int ccg_edgesize(int level)
{
BLI_assert(level > 0);
BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
return 1 + (1 << level);
}
BLI_INLINE int ccg_spacing(int high_level, int low_level)
{
BLI_assert(high_level > 0 && low_level > 0);
BLI_assert(high_level >= low_level);
BLI_assert((high_level - low_level) <= CCGSUBSURF_LEVEL_MAX);
return 1 << (high_level - low_level);
}
BLI_INLINE int ccg_edgebase(int level)
{
BLI_assert(level > 0);
BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
return level + (1 << level) - 1;
}
/* **** */
BLI_INLINE byte *VERT_getLevelData(CCGVert *v)
{
return (byte *)(&(v)[1]);
}
BLI_INLINE byte *EDGE_getLevelData(CCGEdge *e)
{
return (byte *)(&(e)[1]);
}
BLI_INLINE CCGVert **FACE_getVerts(CCGFace *f)
{
return (CCGVert **)(&f[1]);
}
BLI_INLINE CCGEdge **FACE_getEdges(CCGFace *f)
{
return (CCGEdge **)(&(FACE_getVerts(f)[f->numVerts]));
}
BLI_INLINE byte *FACE_getCenterData(CCGFace *f)
{
return (byte *)(&(FACE_getEdges(f)[(f)->numVerts]));
}
/* **** */
BLI_INLINE void *ccg_vert_getCo(CCGVert *v, int lvl, int dataSize)
{
return &VERT_getLevelData(v)[lvl * dataSize];
}
BLI_INLINE float *ccg_vert_getNo(CCGVert *v,
int lvl,
int dataSize,
int normalDataOffset)
{
return (float *) &VERT_getLevelData(v)[lvl * dataSize + normalDataOffset];
}
BLI_INLINE void *ccg_edge_getCo(CCGEdge *e, int lvl, int x, int dataSize)
{
int levelBase = ccg_edgebase(lvl);
return &EDGE_getLevelData(e)[dataSize * (levelBase + x)];
}
BLI_INLINE float *ccg_edge_getNo(CCGEdge *e,
int lvl,
int x,
int dataSize,
int normalDataOffset)
{
int levelBase = ccg_edgebase(lvl);
return (float *) &EDGE_getLevelData(e)[dataSize * (levelBase + x) + normalDataOffset];
}
BLI_INLINE void *ccg_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize)
{
int maxGridSize = ccg_gridsize(levels);
int spacing = ccg_spacing(levels, lvl);
byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
return &gridBase[dataSize * x * spacing];
}
BLI_INLINE void *ccg_face_getIENo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize, int normalDataOffset)
{
int maxGridSize = ccg_gridsize(levels);
int spacing = ccg_spacing(levels, lvl);
byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
return &gridBase[dataSize * x * spacing + normalDataOffset];
}
BLI_INLINE void *ccg_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize)
{
int maxGridSize = ccg_gridsize(levels);
int spacing = ccg_spacing(levels, lvl);
byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
return &gridBase[dataSize * (maxGridSize + (y * maxGridSize + x) * spacing)];
}
BLI_INLINE float *ccg_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset)
{
int maxGridSize = ccg_gridsize(levels);
int spacing = ccg_spacing(levels, lvl);
byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
return (float *) &gridBase[dataSize * (maxGridSize + (y * maxGridSize + x) * spacing) + normalDataOffset];
}
BLI_INLINE int ccg_face_getVertIndex(CCGFace *f, CCGVert *v)
{
int i;
for (i = 0; i < f->numVerts; i++)
if (FACE_getVerts(f)[i] == v)
return i;
return -1;
}
BLI_INLINE int ccg_face_getEdgeIndex(CCGFace *f, CCGEdge *e)
{
int i;
for (i = 0; i < f->numVerts; i++)
if (FACE_getEdges(f)[i] == e)
return i;
return -1;
}
BLI_INLINE void *ccg_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int f_ed_idx, int lvl, int eX, int eY, int levels, int dataSize)
{
int maxGridSize = ccg_gridsize(levels);
int spacing = ccg_spacing(levels, lvl);
int x, y, cx, cy;
BLI_assert(f_ed_idx == ccg_face_getEdgeIndex(f, e));
eX = eX * spacing;
eY = eY * spacing;
if (e->v0 != FACE_getVerts(f)[f_ed_idx]) {
eX = (maxGridSize * 2 - 1) - 1 - eX;
}
y = maxGridSize - 1 - eX;
x = maxGridSize - 1 - eY;
if (x < 0) {
f_ed_idx = (f_ed_idx + f->numVerts - 1) % f->numVerts;
cx = y;
cy = -x;
}
else if (y < 0) {
f_ed_idx = (f_ed_idx + 1) % f->numVerts;
cx = -y;
cy = x;
}
else {
cx = x;
cy = y;
}
return ccg_face_getIFCo(f, levels, f_ed_idx, cx, cy, levels, dataSize);
}
BLI_INLINE void Normalize(float no[3])
{
const float length = sqrtf(no[0] * no[0] + no[1] * no[1] + no[2] * no[2]);
if (length > EPSILON) {
const float length_inv = 1.0f / length;
no[0] *= length_inv;
no[1] *= length_inv;
no[2] *= length_inv;
}
else {
NormZero(no);
}
}
/* Data layers mathematics. */
BLI_INLINE int VertDataEqual(const float a[], const float b[], const CCGSubSurf *ss)
{
int i;
for (i = 0; i < ss->meshIFC.numLayers; i++) {
if (a[i] != b[i])
return 0;
}
return 1;
}
BLI_INLINE void VertDataZero(float v[], const CCGSubSurf *ss)
{
memset(v, 0, sizeof(float) * ss->meshIFC.numLayers);
}
BLI_INLINE void VertDataCopy(float dst[], const float src[], const CCGSubSurf *ss)
{
int i;
for (i = 0; i < ss->meshIFC.numLayers; i++)
dst[i] = src[i];
}
BLI_INLINE void VertDataAdd(float a[], const float b[], const CCGSubSurf *ss)
{
int i;
for (i = 0; i < ss->meshIFC.numLayers; i++)
a[i] += b[i];
}
BLI_INLINE void VertDataSub(float a[], const float b[], const CCGSubSurf *ss)
{
int i;
for (i = 0; i < ss->meshIFC.numLayers; i++)
a[i] -= b[i];
}
BLI_INLINE void VertDataMulN(float v[], float f, const CCGSubSurf *ss)
{
int i;
for (i = 0; i < ss->meshIFC.numLayers; i++)
v[i] *= f;
}
BLI_INLINE void VertDataAvg4(float v[],
const float a[], const float b[],
const float c[], const float d[],
const CCGSubSurf *ss)
{
int i;
for (i = 0; i < ss->meshIFC.numLayers; i++)
v[i] = (a[i] + b[i] + c[i] + d[i]) * 0.25f;
}
#endif /* __CCGSUBSURF_INLINE_H__ */

@ -0,0 +1,277 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/blenkernel/intern/CCGSubSurf_intern.h
* \ingroup bke
*/
#ifndef __CCGSUBSURF_INTERN_H__
#define __CCGSUBSURF_INTERN_H__
/**
* Definitions which defines internal behavior of CCGSubSurf.
*/
/* Define this to see dump of the grids after the subsurf applied. */
#undef DUMP_RESULT_GRIDS
/* used for normalize_v3 in BLI_math_vector
* float.h's FLT_EPSILON causes trouble with subsurf normals - campbell */
#define EPSILON (1.0e-35f)
/* With this limit a single triangle becomes over 3 million faces */
#define CCGSUBSURF_LEVEL_MAX 11
/**
* Common type definitions.
*/
typedef unsigned char byte;
/**
* Hash implementation.
*/
typedef struct _EHEntry {
struct _EHEntry *next;
void *key;
} EHEntry;
typedef struct _EHash {
EHEntry **buckets;
int numEntries, curSize, curSizeIdx;
CCGAllocatorIFC allocatorIFC;
CCGAllocatorHDL allocator;
} EHash;
typedef void (*EHEntryFreeFP)(EHEntry *, void *);
#define EHASH_alloc(eh, nb) ((eh)->allocatorIFC.alloc((eh)->allocator, nb))
#define EHASH_free(eh, ptr) ((eh)->allocatorIFC.free((eh)->allocator, ptr))
#define EHASH_hash(eh, item) (((uintptr_t) (item)) % ((unsigned int) (eh)->curSize))
/* Generic hash functions. */
EHash *ccg_ehash_new(int estimatedNumEntries,
CCGAllocatorIFC *allocatorIFC,
CCGAllocatorHDL allocator);
void ccg_ehash_free(EHash *eh, EHEntryFreeFP freeEntry, void *userData);
void ccg_ehash_insert(EHash *eh, EHEntry *entry);
void *ccg_ehash_lookupWithPrev(EHash *eh, void *key, void ***prevp_r);
void *ccg_ehash_lookup(EHash *eh, void *key);
/* Hash elements iteration. */
void ccg_ehashIterator_init(EHash *eh, EHashIterator *ehi);
void *ccg_ehashIterator_getCurrent(EHashIterator *ehi);
void ccg_ehashIterator_next(EHashIterator *ehi);
int ccg_ehashIterator_isStopped(EHashIterator *ehi);
/**
* Standard allocator implementarion.
*/
CCGAllocatorIFC *ccg_getStandardAllocatorIFC(void);
/**
* Catmull-Clark Gridding Subdivision Surface.
*/
/* TODO(sergey): Get rid of this, it's more or less a bad level call. */
struct DerivedMesh;
/* ** Data structures, constants. enums ** */
enum {
Vert_eEffected = (1 << 0),
Vert_eChanged = (1 << 1),
Vert_eSeam = (1 << 2)
} /*VertFlags*/;
enum {
Edge_eEffected = (1 << 0)
} /*CCGEdgeFlags*/;
enum {
Face_eEffected = (1 << 0)
} /*FaceFlags*/;
struct CCGVert {
CCGVert *next; /* EHData.next */
CCGVertHDL vHDL; /* EHData.key */
short numEdges, numFaces, flags;
int osd_index; /* Index of the vertex in the map, used by OSD. */
CCGEdge **edges;
CCGFace **faces;
/* byte *levelData; */
/* byte *userData; */
};
struct CCGEdge {
CCGEdge *next; /* EHData.next */
CCGEdgeHDL eHDL; /* EHData.key */
short numFaces, flags;
float crease;
CCGVert *v0, *v1;
CCGFace **faces;
/* byte *levelData; */
/* byte *userData; */
};
struct CCGFace {
CCGFace *next; /* EHData.next */
CCGFaceHDL fHDL; /* EHData.key */
short numVerts, flags;
int osd_index;
/* CCGVert **verts; */
/* CCGEdge **edges; */
/* byte *centerData; */
/* byte **gridData; */
/* byte *userData; */
};
typedef enum {
eSyncState_None = 0,
eSyncState_Vert,
eSyncState_Edge,
eSyncState_Face,
eSyncState_Partial,
} SyncState;
struct CCGSubSurf {
EHash *vMap; /* map of CCGVertHDL -> Vert */
EHash *eMap; /* map of CCGEdgeHDL -> Edge */
EHash *fMap; /* map of CCGFaceHDL -> Face */
CCGMeshIFC meshIFC;
CCGAllocatorIFC allocatorIFC;
CCGAllocatorHDL allocator;
int subdivLevels;
int numGrids;
int allowEdgeCreation;
float defaultCreaseValue;
void *defaultEdgeUserData;
void *q, *r;
/* Data for calc vert normals. */
int calcVertNormals;
int normalDataOffset;
/* Data for paint masks. */
int allocMask;
int maskDataOffset;
/* Data for age'ing (to debug sync). */
int currentAge;
int useAgeCounts;
int vertUserAgeOffset;
int edgeUserAgeOffset;
int faceUserAgeOffset;
/* Data used during syncing. */
SyncState syncState;
EHash *oldVMap, *oldEMap, *oldFMap;
int lenTempArrays;
CCGVert **tempVerts;
CCGEdge **tempEdges;
};
/* ** Utility macros ** */
#define CCGSUBSURF_alloc(ss, nb) ((ss)->allocatorIFC.alloc((ss)->allocator, nb))
#define CCGSUBSURF_realloc(ss, ptr, nb, ob) ((ss)->allocatorIFC.realloc((ss)->allocator, ptr, nb, ob))
#define CCGSUBSURF_free(ss, ptr) ((ss)->allocatorIFC.free((ss)->allocator, ptr))
#define VERT_getCo(v, lvl) ccg_vert_getCo(v, lvl, vertDataSize)
#define VERT_getNo(v, lvl) ccg_vert_getNo(v, lvl, vertDataSize, normalDataOffset)
#define EDGE_getCo(e, lvl, x) ccg_edge_getCo(e, lvl, x, vertDataSize)
#define EDGE_getNo(e, lvl, x) ccg_edge_getNo(e, lvl, x, vertDataSize, normalDataOffset)
#define FACE_getIFNo(f, lvl, S, x, y) ccg_face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset)
//#define FACE_calcIFNo(f, lvl, S, x, y, no) _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize)
#define FACE_getIENo(f, lvl, S, x) ccg_face_getIENo(f, lvl, S, x, subdivLevels, vertDataSize, normalDataOffset)
#define FACE_getIECo(f, lvl, S, x) ccg_face_getIECo(f, lvl, S, x, subdivLevels, vertDataSize)
#define FACE_getIFCo(f, lvl, S, x, y) ccg_face_getIFCo(f, lvl, S, x, y, subdivLevels, vertDataSize)
#define NormZero(av) { float *_a = (float *) av; _a[0] = _a[1] = _a[2] = 0.0f; } (void)0
#define NormCopy(av, bv) { float *_a = (float *) av, *_b = (float *) bv; _a[0] = _b[0]; _a[1] = _b[1]; _a[2] = _b[2]; } (void)0
#define NormAdd(av, bv) { float *_a = (float *) av, *_b = (float *) bv; _a[0] += _b[0]; _a[1] += _b[1]; _a[2] += _b[2]; } (void)0
/* ** General purpose functions ** */
/* * CCGSubSurf.c * */
void ccgSubSurf__allFaces(CCGSubSurf *ss, CCGFace ***faces, int *numFaces, int *freeFaces);
void ccgSubSurf__effectedFaceNeighbours(CCGSubSurf *ss,
CCGFace **faces,
int numFaces,
CCGVert ***verts,
int *numVerts,
CCGEdge ***edges,
int *numEdges);
/* * CCGSubSurf_legacy.c * */
void ccgSubSurf__sync_legacy(CCGSubSurf *ss);
/* * CCGSubSurf_opensubdiv.c * */
void ccgSubSurf__sync_opensubdiv(CCGSubSurf *ss);
int ccgSubSurf__getNumOsdBaseVerts(const CCGSubSurf *ss);
int ccgSubSurf__getNumOsdBaseEdges(const CCGSubSurf *ss);
int ccgSubSurf__getNumOsdBaseFaces(const CCGSubSurf *ss);
/* * CCGSubSurf_opensubdiv_converter.c * */
struct OpenSubdiv_Converter;
void ccgSubSurf_converter_setup_from_derivedmesh(
CCGSubSurf *ss,
struct DerivedMesh *dm,
struct OpenSubdiv_Converter *converter);
void ccgSubSurf_converter_setup_from_ccg(
CCGSubSurf *ss,
struct OpenSubdiv_Converter *converter);
void ccgSubSurf_converter_free(
struct OpenSubdiv_Converter *converter);
/* * CCGSubSurf_util.c * */
#ifdef DUMP_RESULT_GRIDS
void ccgSubSurf__dumpCoords(CCGSubSurf *ss);
#endif
#include "CCGSubSurf_inline.h"
#endif /* __CCGSUBSURF_INTERN_H__ */

File diff suppressed because it is too large Load Diff

@ -0,0 +1,306 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/blenkernel/intern/CCGSubSurf_util.c
* \ingroup bke
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "MEM_guardedalloc.h"
#include "BLI_sys_types.h" // for intptr_t support
#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
};
/* Generic hash functions. */
EHash *ccg_ehash_new(int estimatedNumEntries,
CCGAllocatorIFC *allocatorIFC,
CCGAllocatorHDL allocator)
{
EHash *eh = 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 *userData)
{
int numBuckets = eh->curSize;
while (numBuckets--) {
EHEntry *entry = eh->buckets[numBuckets];
while (entry) {
EHEntry *next = entry->next;
freeEntry(entry, userData);
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 = *prevp); prevp = (void **) &entry->next) {
if (entry->key == key) {
*prevp_r = (void **) prevp;
return entry;
}
}
return NULL;
}
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;
}
/* Hash elements iteration. */
void ccg_ehashIterator_init(EHash *eh, EHashIterator *ehi)
{
/* fill all members */
ehi->eh = eh;
ehi->curBucket = -1;
ehi->curEntry = NULL;
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;
}
/**
* Standard allocator implementarion.
*/
static void *_stdAllocator_alloc(CCGAllocatorHDL UNUSED(a), int numBytes)
{
return MEM_mallocN(numBytes, "CCG standard alloc");
}
static void *_stdAllocator_realloc(CCGAllocatorHDL UNUSED(a),
void *ptr,
int newSize,
int UNUSED(oldSize))
{
return MEM_reallocN(ptr, newSize);
}
static void _stdAllocator_free(CCGAllocatorHDL UNUSED(a), void *ptr)
{
MEM_freeN(ptr);
}
CCGAllocatorIFC *ccg_getStandardAllocatorIFC(void)
{
static CCGAllocatorIFC ifc;
ifc.alloc = _stdAllocator_alloc;
ifc.realloc = _stdAllocator_realloc;
ifc.free = _stdAllocator_free;
ifc.release = NULL;
return &ifc;
}
/**
* 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. cornder=%d, ie_index=%d, coord=(%f, %f, %f)\n",
index, S, x, co[0], co[1], co[2]);
}
}
}
}
}
#endif /* DUMP_RESULT_GRIDS */