tornavis/source/blender/blenkernel/intern/CCGSubSurf_intern.h

338 lines
9.5 KiB
C

/*
* ***** 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 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 *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,
#ifdef WITH_OPENSUBDIV
eSyncState_OpenSubdiv,
#endif
} 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;
#ifdef WITH_OPENSUBDIV
/* Skip grids means no CCG geometry is created and subsurf is possible
* to be completely done on GPU.
*/
bool skip_grids;
/* ** GPU backend. ** */
/* Compute device used by GL mesh. */
short osd_compute;
/* Coarse (base mesh) vertex coordinates.
*
* Filled in from the modifier stack and passed to OpenSubdiv compute
* on mesh display.
*/
float (*osd_coarse_coords)[3];
int osd_num_coarse_coords;
/* Denotes whether coarse positions in the GL mesh are invalid.
* Used to avoid updating GL mesh coords on every redraw.
*/
bool osd_coarse_coords_invalid;
/* GL mesh descriptor, used for refinment and draw. */
struct OpenSubdiv_GLMesh *osd_mesh;
/* Refiner which is used to create GL mesh.
*
* Refiner is created from the modifier stack and used later from the main
* thread to construct GL mesh to avoid threaded access to GL.
*/
struct OpenSubdiv_TopologyRefinerDescr *osd_topology_refiner; /* Only used at synchronization stage. */
/* Denotes whether osd_mesh is invalid now due to topology changes and needs
* to be reconstructed.
*
* Reconstruction happens from main thread due to OpenGL communication.
*/
bool osd_mesh_invalid;
/* Vertex array used for osd_mesh draw. */
unsigned int osd_vao;
/* ** CPU backend. ** */
/* Limit evaluator, used to evaluate CCG. */
struct OpenSubdiv_EvaluatorDescr *osd_evaluator;
/* Next PTex face index, used while CCG synchronization
* to fill in PTex index of CCGFace.
*/
int osd_next_face_ptex_index;
bool osd_subdiv_uvs;
#endif
};
/* ** 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);
/* Delayed free routines. Will do actual free if called from
* main thread and schedule free for later free otherwise.
*/
#ifdef WITH_OPENSUBDIV
void ccgSubSurf__delete_osdGLMesh(struct OpenSubdiv_GLMesh *osd_mesh);
void ccgSubSurf__delete_vertex_array(unsigned int vao);
void ccgSubSurf__delete_pending(void);
#endif
/* * 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__ */