2015-07-20 15:05:16 +02:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
* \ingroup bke
|
2015-07-20 15:05:16 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#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);
|
|
|
|
|
|
|
|
/**
|
2016-07-19 08:39:38 +10:00
|
|
|
* Standard allocator implementation.
|
2015-07-20 15:05:16 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
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,
|
2015-07-20 16:08:06 +02:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
eSyncState_OpenSubdiv,
|
|
|
|
#endif
|
2015-07-20 15:05:16 +02:00
|
|
|
} 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;
|
2015-07-20 16:08:06 +02:00
|
|
|
|
|
|
|
#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;
|
|
|
|
|
2018-09-24 17:27:41 +02:00
|
|
|
/* GL mesh descriptor, used for refinement and draw. */
|
2015-07-20 16:08:06 +02:00
|
|
|
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.
|
|
|
|
*/
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
struct OpenSubdiv_TopologyRefiner *osd_topology_refiner; /* Only used at synchronization stage. */
|
2015-07-20 16:08:06 +02:00
|
|
|
/* 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. */
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
struct OpenSubdiv_Evaluator *osd_evaluator;
|
2015-08-23 21:12:48 +10:00
|
|
|
/* Next PTex face index, used while CCG synchronization
|
2015-07-20 16:08:06 +02:00
|
|
|
* to fill in PTex index of CCGFace.
|
|
|
|
*/
|
|
|
|
int osd_next_face_ptex_index;
|
2016-07-22 17:52:30 +02:00
|
|
|
|
|
|
|
bool osd_subdiv_uvs;
|
2015-07-20 16:08:06 +02:00
|
|
|
#endif
|
2015-07-20 15:05:16 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/* ** 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);
|
|
|
|
|
2015-11-04 21:30:25 +05:00
|
|
|
/* Delayed free routines. Will do actual free if called from
|
|
|
|
* main thread and schedule free for later free otherwise.
|
|
|
|
*/
|
|
|
|
|
2015-11-04 22:31:06 +05:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
2015-11-04 21:30:25 +05:00
|
|
|
void ccgSubSurf__delete_osdGLMesh(struct OpenSubdiv_GLMesh *osd_mesh);
|
|
|
|
void ccgSubSurf__delete_vertex_array(unsigned int vao);
|
|
|
|
void ccgSubSurf__delete_pending(void);
|
2015-11-04 22:31:06 +05:00
|
|
|
#endif
|
2015-11-04 21:30:25 +05:00
|
|
|
|
2015-07-20 15:05:16 +02:00
|
|
|
/* * 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__ */
|