This commit contains all the remained parts needed for initial integration of OpenSubdiv into Blender's subdivision surface code. Includes both GPU and CPU backends which works in the following way: - When SubSurf modifier is the last in the modifiers stack then GPU pipeline of OpenSubdiv is used, making viewport performance as fast as possible. This also requires graphscard with GLSL 1.5 support. If this requirement is not met, then no GPU pipeline is used at all. - If SubSurf is not a last modifier or if DerivesMesh is being evaluated for rendering then CPU limit evaluation API from OpenSubdiv is used. This only replaces the legacy evaluation code from CCGSubSurf_legacy, but keeps CCG structures exactly the same as they used to be for ages now. This integration is fully covered with ifdef and not enabled by default because there are several TODOs to be solved first: - Face varying data interpolation is not really cleanly implemented for GPU in OpenSubdiv 3.0. It is also not implemented for limit evaluation API. This basically means we'll have really hard time supporting UVs. - Limit evaluation only works with adaptivly subdivided meshes so far, which basically means all the points of CCG are pushed to the limit. This gives different result from old code. - There are some serious optimizations possible on the topology refiner creation, which would speed up initial OpenSubdiv mesh creation. - There are some hardcoded asumptions in the GPU and DerivedMesh areas which could be generalized. That's something where Antony and Campbell can help, making it so the code is structured in a way which is reusable by all planned viewport projects. - There are also some workarounds in the dependency graph to make sure OpenGL buffers are only freed from the main thread. Those who'll be wanting to make experiments with this code should grab dev branch (NOT master) from https://github.com/Nazg-Gul/OpenSubdiv/tree/dev There are some patches applied in there which we're working on on getting into upstream.
240 lines
9.4 KiB
C
240 lines
9.4 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 *****
|
|
*/
|
|
|
|
#ifndef __CCGSUBSURF_H__
|
|
#define __CCGSUBSURF_H__
|
|
|
|
/** \file blender/blenkernel/intern/CCGSubSurf.h
|
|
* \ingroup bke
|
|
*/
|
|
|
|
typedef void* CCGMeshHDL;
|
|
typedef void* CCGVertHDL;
|
|
typedef void* CCGEdgeHDL;
|
|
typedef void* CCGFaceHDL;
|
|
|
|
typedef struct CCGSubSurf CCGSubSurf;
|
|
typedef struct CCGVert CCGVert;
|
|
typedef struct CCGEdge CCGEdge;
|
|
typedef struct CCGFace CCGFace;
|
|
|
|
typedef struct CCGMeshIFC {
|
|
int vertUserSize, edgeUserSize, faceUserSize;
|
|
int numLayers;
|
|
int vertDataSize;
|
|
int simpleSubdiv;
|
|
} CCGMeshIFC;
|
|
|
|
/***/
|
|
|
|
typedef void* CCGAllocatorHDL;
|
|
|
|
typedef struct CCGAllocatorIFC {
|
|
void* (*alloc) (CCGAllocatorHDL a, int numBytes);
|
|
void* (*realloc) (CCGAllocatorHDL a, void *ptr, int newSize, int oldSize);
|
|
void (*free) (CCGAllocatorHDL a, void *ptr);
|
|
void (*release) (CCGAllocatorHDL a);
|
|
} CCGAllocatorIFC;
|
|
|
|
/* private, so we can allocate on the stack */
|
|
typedef struct _EHashIterator {
|
|
struct _EHash *eh;
|
|
int curBucket;
|
|
struct _EHEntry *curEntry;
|
|
} EHashIterator;
|
|
|
|
/***/
|
|
|
|
typedef enum {
|
|
eCCGError_None = 0,
|
|
|
|
eCCGError_InvalidSyncState,
|
|
eCCGError_InvalidValue,
|
|
} CCGError;
|
|
|
|
/***/
|
|
|
|
#define CCG_OMP_LIMIT 1000000
|
|
|
|
/***/
|
|
|
|
CCGSubSurf* ccgSubSurf_new (CCGMeshIFC *ifc, int subdivisionLevels, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator);
|
|
void ccgSubSurf_free (CCGSubSurf *ss);
|
|
|
|
CCGError ccgSubSurf_initFullSync (CCGSubSurf *ss);
|
|
CCGError ccgSubSurf_initPartialSync (CCGSubSurf *ss);
|
|
#ifdef WITH_OPENSUBDIV
|
|
CCGError ccgSubSurf_initOpenSubdivSync (CCGSubSurf *ss);
|
|
#endif
|
|
|
|
CCGError ccgSubSurf_syncVert (CCGSubSurf *ss, CCGVertHDL vHDL, const void *vertData, int seam, CCGVert **v_r);
|
|
CCGError ccgSubSurf_syncEdge (CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease, CCGEdge **e_r);
|
|
CCGError ccgSubSurf_syncFace (CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r);
|
|
|
|
CCGError ccgSubSurf_syncVertDel (CCGSubSurf *ss, CCGVertHDL vHDL);
|
|
CCGError ccgSubSurf_syncEdgeDel (CCGSubSurf *ss, CCGEdgeHDL eHDL);
|
|
CCGError ccgSubSurf_syncFaceDel (CCGSubSurf *ss, CCGFaceHDL fHDL);
|
|
|
|
CCGError ccgSubSurf_processSync (CCGSubSurf *ss);
|
|
|
|
CCGError ccgSubSurf_updateFromFaces(CCGSubSurf *ss, int lvl, CCGFace **faces, int numFaces);
|
|
CCGError ccgSubSurf_updateToFaces(CCGSubSurf *ss, int lvl, CCGFace **faces, int numFaces);
|
|
CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **faces, int numFaces);
|
|
CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **faces, int numFaces);
|
|
CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **faces, int numFaces);
|
|
|
|
CCGError ccgSubSurf_setSubdivisionLevels (CCGSubSurf *ss, int subdivisionLevels);
|
|
|
|
CCGError ccgSubSurf_setAllowEdgeCreation (CCGSubSurf *ss, int allowEdgeCreation, float defaultCreaseValue, void *defaultUserData);
|
|
void ccgSubSurf_getAllowEdgeCreation (CCGSubSurf *ss, int *allowEdgeCreation_r, float *defaultCreaseValue_r, void *defaultUserData_r);
|
|
|
|
void ccgSubSurf_getUseAgeCounts (CCGSubSurf *ss, int *useAgeCounts_r, int *vertUserOffset_r, int *edgeUserOffset_r, int *faceUserOffset_r);
|
|
CCGError ccgSubSurf_setUseAgeCounts (CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset);
|
|
|
|
CCGError ccgSubSurf_setCalcVertexNormals (CCGSubSurf *ss, int useVertNormals, int normalDataOffset);
|
|
void ccgSubSurf_setAllocMask (CCGSubSurf *ss, int allocMask, int maskOffset);
|
|
|
|
void ccgSubSurf_setNumLayers (CCGSubSurf *ss, int numLayers);
|
|
|
|
/***/
|
|
|
|
int ccgSubSurf_getNumVerts (const CCGSubSurf *ss);
|
|
int ccgSubSurf_getNumEdges (const CCGSubSurf *ss);
|
|
int ccgSubSurf_getNumFaces (const CCGSubSurf *ss);
|
|
|
|
int ccgSubSurf_getSubdivisionLevels (const CCGSubSurf *ss);
|
|
int ccgSubSurf_getEdgeSize (const CCGSubSurf *ss);
|
|
int ccgSubSurf_getEdgeLevelSize (const CCGSubSurf *ss, int level);
|
|
int ccgSubSurf_getGridSize (const CCGSubSurf *ss);
|
|
int ccgSubSurf_getGridLevelSize (const CCGSubSurf *ss, int level);
|
|
int ccgSubSurf_getSimpleSubdiv (const CCGSubSurf *ss);
|
|
|
|
CCGVert* ccgSubSurf_getVert (CCGSubSurf *ss, CCGVertHDL v);
|
|
CCGVertHDL ccgSubSurf_getVertVertHandle (CCGVert *v);
|
|
int ccgSubSurf_getVertNumFaces (CCGVert *v);
|
|
CCGFace* ccgSubSurf_getVertFace (CCGVert *v, int index);
|
|
int ccgSubSurf_getVertNumEdges (CCGVert *v);
|
|
CCGEdge* ccgSubSurf_getVertEdge (CCGVert *v, int index);
|
|
|
|
int ccgSubSurf_getVertAge (CCGSubSurf *ss, CCGVert *v);
|
|
void* ccgSubSurf_getVertUserData (CCGSubSurf *ss, CCGVert *v);
|
|
void* ccgSubSurf_getVertData (CCGSubSurf *ss, CCGVert *v);
|
|
void* ccgSubSurf_getVertLevelData (CCGSubSurf *ss, CCGVert *v, int level);
|
|
|
|
CCGEdge* ccgSubSurf_getEdge (CCGSubSurf *ss, CCGEdgeHDL e);
|
|
CCGEdgeHDL ccgSubSurf_getEdgeEdgeHandle (CCGEdge *e);
|
|
int ccgSubSurf_getEdgeNumFaces (CCGEdge *e);
|
|
CCGFace* ccgSubSurf_getEdgeFace (CCGEdge *e, int index);
|
|
CCGVert* ccgSubSurf_getEdgeVert0 (CCGEdge *e);
|
|
CCGVert* ccgSubSurf_getEdgeVert1 (CCGEdge *e);
|
|
float ccgSubSurf_getEdgeCrease (CCGEdge *e);
|
|
|
|
int ccgSubSurf_getEdgeAge (CCGSubSurf *ss, CCGEdge *e);
|
|
void* ccgSubSurf_getEdgeUserData (CCGSubSurf *ss, CCGEdge *e);
|
|
void* ccgSubSurf_getEdgeDataArray (CCGSubSurf *ss, CCGEdge *e);
|
|
void* ccgSubSurf_getEdgeData (CCGSubSurf *ss, CCGEdge *e, int x);
|
|
void* ccgSubSurf_getEdgeLevelData (CCGSubSurf *ss, CCGEdge *e, int x, int level);
|
|
|
|
CCGFace* ccgSubSurf_getFace (CCGSubSurf *ss, CCGFaceHDL f);
|
|
CCGFaceHDL ccgSubSurf_getFaceFaceHandle (CCGFace *f);
|
|
int ccgSubSurf_getFaceNumVerts (CCGFace *f);
|
|
CCGVert* ccgSubSurf_getFaceVert (CCGFace *f, int index);
|
|
CCGEdge* ccgSubSurf_getFaceEdge (CCGFace *f, int index);
|
|
int ccgSubSurf_getFaceEdgeIndex (CCGFace *f, CCGEdge *e);
|
|
|
|
int ccgSubSurf_getFaceAge (CCGSubSurf *ss, CCGFace *f);
|
|
void* ccgSubSurf_getFaceUserData (CCGSubSurf *ss, CCGFace *f);
|
|
void* ccgSubSurf_getFaceCenterData (CCGFace *f);
|
|
void* ccgSubSurf_getFaceGridEdgeDataArray (CCGSubSurf *ss, CCGFace *f, int gridIndex);
|
|
void* ccgSubSurf_getFaceGridEdgeData (CCGSubSurf *ss, CCGFace *f, int gridIndex, int x);
|
|
void* ccgSubSurf_getFaceGridDataArray (CCGSubSurf *ss, CCGFace *f, int gridIndex);
|
|
void* ccgSubSurf_getFaceGridData (CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y);
|
|
|
|
int ccgSubSurf_getNumFinalVerts (const CCGSubSurf *ss);
|
|
int ccgSubSurf_getNumFinalEdges (const CCGSubSurf *ss);
|
|
int ccgSubSurf_getNumFinalFaces (const CCGSubSurf *ss);
|
|
|
|
/***/
|
|
|
|
typedef struct _EHashIterator CCGVertIterator;
|
|
typedef struct _EHashIterator CCGEdgeIterator;
|
|
typedef struct _EHashIterator CCGFaceIterator;
|
|
|
|
void ccgSubSurf_initVertIterator(CCGSubSurf *ss, CCGVertIterator *viter);
|
|
void ccgSubSurf_initEdgeIterator(CCGSubSurf *ss, CCGEdgeIterator *eiter);
|
|
void ccgSubSurf_initFaceIterator(CCGSubSurf *ss, CCGFaceIterator *fiter);
|
|
|
|
CCGVert* ccgVertIterator_getCurrent (CCGVertIterator *vi);
|
|
int ccgVertIterator_isStopped (CCGVertIterator *vi);
|
|
void ccgVertIterator_next (CCGVertIterator *vi);
|
|
|
|
CCGEdge* ccgEdgeIterator_getCurrent (CCGEdgeIterator *ei);
|
|
int ccgEdgeIterator_isStopped (CCGEdgeIterator *ei);
|
|
void ccgEdgeIterator_next (CCGEdgeIterator *ei);
|
|
|
|
CCGFace* ccgFaceIterator_getCurrent (CCGFaceIterator *fi);
|
|
int ccgFaceIterator_isStopped (CCGFaceIterator *fi);
|
|
void ccgFaceIterator_next (CCGFaceIterator *fi);
|
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
struct DerivedMesh;
|
|
|
|
/* Check if topology changed and evaluators are to be re-created. */
|
|
void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, struct DerivedMesh *dm);
|
|
|
|
/* Create topology refiner from give derived mesh which then later will be
|
|
* used for GL mesh creation.
|
|
*/
|
|
void ccgSubSurf_prepareTopologyRefiner(CCGSubSurf *ss, struct DerivedMesh *dm);
|
|
|
|
/* Make sure GL mesh exists, up to date and ready to draw. */
|
|
bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl);
|
|
|
|
/* Draw given partitions of the GL mesh.
|
|
*
|
|
* TODO(sergey): fill_quads is actually an invariant and should be part
|
|
* of the prepare routine.
|
|
*/
|
|
void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, bool fill_quads,
|
|
int start_partition, int num_partitions);
|
|
|
|
/* Controls whether CCG are needed (Cmeaning CPU evaluation) or fully GPU compute
|
|
* and draw is allowed.
|
|
*/
|
|
void ccgSubSurf_setSkipGrids(CCGSubSurf *ss, bool skip_grids);
|
|
bool ccgSubSurf_needGrids(CCGSubSurf *ss);
|
|
|
|
/* Set evaluator's face varying data from UV coordinates.
|
|
* Used for CPU evaluation.
|
|
*/
|
|
void ccgSubSurf_evaluatorSetFVarUV(CCGSubSurf *ss,
|
|
struct DerivedMesh *dm,
|
|
int layer_index);
|
|
|
|
/* TODO(sergey): Temporary call to test things. */
|
|
void ccgSubSurf_evaluatorFVarUV(CCGSubSurf *ss,
|
|
int face_index, int S,
|
|
float grid_u, float grid_v,
|
|
float uv[2]);
|
|
|
|
#endif
|
|
|
|
#endif /* __CCGSUBSURF_H__ */
|