Listing the "Blender Foundation" as copyright holder implied the Blender Foundation holds copyright to files which may include work from many developers. While keeping copyright on headers makes sense for isolated libraries, Blender's own code may be refactored or moved between files in a way that makes the per file copyright holders less meaningful. Copyright references to the "Blender Foundation" have been replaced with "Blender Authors", with the exception of `./extern/` since these this contains libraries which are more isolated, any changed to license headers there can be handled on a case-by-case basis. Some directories in `./intern/` have also been excluded: - `./intern/cycles/` it's own `AUTHORS` file is planned. - `./intern/opensubdiv/`. An "AUTHORS" file has been added, using the chromium projects authors file as a template. Design task: #110784 Ref !110783.
272 lines
6.5 KiB
C
272 lines
6.5 KiB
C
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup bke
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* 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) (EHEntry **)((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 *user_data);
|
|
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 implementation.
|
|
*/
|
|
|
|
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 *user_data; */
|
|
};
|
|
|
|
struct CCGEdge {
|
|
CCGEdge *next; /* EHData.next */
|
|
CCGEdgeHDL eHDL; /* EHData.key */
|
|
|
|
short numFaces, flags;
|
|
float crease;
|
|
|
|
CCGVert *v0, *v1;
|
|
CCGFace **faces;
|
|
|
|
/* byte *levelData; */
|
|
/* byte *user_data; */
|
|
};
|
|
|
|
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 *user_data; */
|
|
};
|
|
|
|
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) (float *)ccg_vert_getCo(v, lvl, vertDataSize)
|
|
#define VERT_getNo(v, lvl) ccg_vert_getNo(v, lvl, vertDataSize, normalDataOffset)
|
|
#define EDGE_getCo(e, lvl, x) (float *)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)
|
|
#if 0
|
|
# define FACE_calcIFNo(f, lvl, S, x, y, no) \
|
|
_face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize)
|
|
#endif
|
|
#define FACE_getIENo(f, lvl, S, x) \
|
|
ccg_face_getIENo(f, lvl, S, x, subdivLevels, vertDataSize, normalDataOffset)
|
|
#define FACE_getIECo(f, lvl, S, x) \
|
|
(float *)ccg_face_getIECo(f, lvl, S, x, subdivLevels, vertDataSize)
|
|
#define FACE_getIFCo(f, lvl, S, x, y) \
|
|
(float *)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.cc` */
|
|
|
|
void ccgSubSurf__allFaces(CCGSubSurf *ss, CCGFace ***faces, int *numFaces, int *freeFaces);
|
|
void ccgSubSurf__effectedFaceNeighbors(CCGSubSurf *ss,
|
|
CCGFace **faces,
|
|
int numFaces,
|
|
CCGVert ***verts,
|
|
int *numVerts,
|
|
CCGEdge ***edges,
|
|
int *numEdges);
|
|
|
|
/* `CCGSubSurf_legacy.cc` */
|
|
|
|
void ccgSubSurf__sync_legacy(CCGSubSurf *ss);
|
|
|
|
struct OpenSubdiv_Converter;
|
|
|
|
/* `CCGSubSurf_util.cc` */
|
|
|
|
#ifdef DUMP_RESULT_GRIDS
|
|
void ccgSubSurf__dumpCoords(CCGSubSurf *ss);
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#include "CCGSubSurf_inline.h"
|