From e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 17 Apr 2019 06:17:24 +0200 Subject: ClangFormat: apply to source, most of intern Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat --- .../blenkernel/intern/CCGSubSurf_opensubdiv.c | 1649 ++++++++++---------- 1 file changed, 807 insertions(+), 842 deletions(-) (limited to 'source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c') diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c index 7556af4cb9f..973d5415567 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c +++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c @@ -20,986 +20,951 @@ #ifdef WITH_OPENSUBDIV -#include "MEM_guardedalloc.h" -#include "BLI_sys_types.h" // for intptr_t support +# include "MEM_guardedalloc.h" +# include "BLI_sys_types.h" // for intptr_t support -#include "BLI_utildefines.h" /* for BLI_assert */ -#include "BLI_listbase.h" -#include "BLI_math.h" -#include "BLI_threads.h" +# include "BLI_utildefines.h" /* for BLI_assert */ +# include "BLI_listbase.h" +# include "BLI_math.h" +# include "BLI_threads.h" -#include "CCGSubSurf.h" -#include "CCGSubSurf_intern.h" +# include "CCGSubSurf.h" +# include "CCGSubSurf_intern.h" -#include "BKE_DerivedMesh.h" -#include "BKE_subsurf.h" +# include "BKE_DerivedMesh.h" +# include "BKE_subsurf.h" -#include "DNA_userdef_types.h" +# include "DNA_userdef_types.h" -#include "opensubdiv_capi.h" -#include "opensubdiv_converter_capi.h" -#include "opensubdiv_evaluator_capi.h" -#include "opensubdiv_gl_mesh_capi.h" -#include "opensubdiv_topology_refiner_capi.h" +# include "opensubdiv_capi.h" +# include "opensubdiv_converter_capi.h" +# include "opensubdiv_evaluator_capi.h" +# include "opensubdiv_gl_mesh_capi.h" +# include "opensubdiv_topology_refiner_capi.h" -#include "GPU_glew.h" -#include "GPU_extensions.h" +# include "GPU_glew.h" +# include "GPU_extensions.h" -#define OSD_LOG if (false) printf +# define OSD_LOG \ + if (false) \ + printf static bool compare_ccg_derivedmesh_topology(CCGSubSurf *ss, DerivedMesh *dm) { - const int num_verts = dm->getNumVerts(dm); - const int num_edges = dm->getNumEdges(dm); - const int num_polys = dm->getNumPolys(dm); - const MEdge *medge = dm->getEdgeArray(dm); - const MLoop *mloop = dm->getLoopArray(dm); - const MPoly *mpoly = dm->getPolyArray(dm); - - /* Quick preliminary tests based on the number of verts and facces. */ - { - if (num_verts != ss->vMap->numEntries || - num_edges != ss->eMap->numEntries || - num_polys != ss->fMap->numEntries) - { - return false; - } - } - - /* Rather slow check for faces topology change. */ - { - CCGFaceIterator ccg_face_iter; - for (ccgSubSurf_initFaceIterator(ss, &ccg_face_iter); - !ccgFaceIterator_isStopped(&ccg_face_iter); - ccgFaceIterator_next(&ccg_face_iter)) - { - /*const*/ CCGFace *ccg_face = ccgFaceIterator_getCurrent(&ccg_face_iter); - const int poly_index = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(ccg_face)); - const MPoly *mp = &mpoly[poly_index]; - int corner; - if (ccg_face->numVerts != mp->totloop) { - return false; - } - for (corner = 0; corner < ccg_face->numVerts; corner++) { - /*const*/ CCGVert *ccg_vert = FACE_getVerts(ccg_face)[corner]; - const int vert_index = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(ccg_vert)); - if (vert_index != mloop[mp->loopstart + corner].v) { - return false; - } - } - } - } - - /* Check for edge topology change. */ - { - CCGEdgeIterator ccg_edge_iter; - for (ccgSubSurf_initEdgeIterator(ss, &ccg_edge_iter); - !ccgEdgeIterator_isStopped(&ccg_edge_iter); - ccgEdgeIterator_next(&ccg_edge_iter)) - { - /* const */ CCGEdge *ccg_edge = ccgEdgeIterator_getCurrent(&ccg_edge_iter); - /* const */ CCGVert *ccg_vert1 = ccg_edge->v0; - /* const */ CCGVert *ccg_vert2 = ccg_edge->v1; - const int ccg_vert1_index = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(ccg_vert1)); - const int ccg_vert2_index = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(ccg_vert2)); - const int edge_index = POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(ccg_edge)); - const MEdge *me = &medge[edge_index]; - if (me->v1 != ccg_vert1_index || me->v2 != ccg_vert2_index) { - return false; - } - } - } - - /* TODO(sergey): Crease topology changes detection. */ - { - CCGEdgeIterator ccg_edge_iter; - for (ccgSubSurf_initEdgeIterator(ss, &ccg_edge_iter); - !ccgEdgeIterator_isStopped(&ccg_edge_iter); - ccgEdgeIterator_next(&ccg_edge_iter)) - { - /* const */ CCGEdge *ccg_edge = ccgEdgeIterator_getCurrent(&ccg_edge_iter); - const int edge_index = POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(ccg_edge)); - if (ccg_edge->crease != medge[edge_index].crease) { - return false; - } - } - } - - return true; + const int num_verts = dm->getNumVerts(dm); + const int num_edges = dm->getNumEdges(dm); + const int num_polys = dm->getNumPolys(dm); + const MEdge *medge = dm->getEdgeArray(dm); + const MLoop *mloop = dm->getLoopArray(dm); + const MPoly *mpoly = dm->getPolyArray(dm); + + /* Quick preliminary tests based on the number of verts and facces. */ + { + if (num_verts != ss->vMap->numEntries || num_edges != ss->eMap->numEntries || + num_polys != ss->fMap->numEntries) { + return false; + } + } + + /* Rather slow check for faces topology change. */ + { + CCGFaceIterator ccg_face_iter; + for (ccgSubSurf_initFaceIterator(ss, &ccg_face_iter); + !ccgFaceIterator_isStopped(&ccg_face_iter); + ccgFaceIterator_next(&ccg_face_iter)) { + /*const*/ CCGFace *ccg_face = ccgFaceIterator_getCurrent(&ccg_face_iter); + const int poly_index = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(ccg_face)); + const MPoly *mp = &mpoly[poly_index]; + int corner; + if (ccg_face->numVerts != mp->totloop) { + return false; + } + for (corner = 0; corner < ccg_face->numVerts; corner++) { + /*const*/ CCGVert *ccg_vert = FACE_getVerts(ccg_face)[corner]; + const int vert_index = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(ccg_vert)); + if (vert_index != mloop[mp->loopstart + corner].v) { + return false; + } + } + } + } + + /* Check for edge topology change. */ + { + CCGEdgeIterator ccg_edge_iter; + for (ccgSubSurf_initEdgeIterator(ss, &ccg_edge_iter); + !ccgEdgeIterator_isStopped(&ccg_edge_iter); + ccgEdgeIterator_next(&ccg_edge_iter)) { + /* const */ CCGEdge *ccg_edge = ccgEdgeIterator_getCurrent(&ccg_edge_iter); + /* const */ CCGVert *ccg_vert1 = ccg_edge->v0; + /* const */ CCGVert *ccg_vert2 = ccg_edge->v1; + const int ccg_vert1_index = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(ccg_vert1)); + const int ccg_vert2_index = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(ccg_vert2)); + const int edge_index = POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(ccg_edge)); + const MEdge *me = &medge[edge_index]; + if (me->v1 != ccg_vert1_index || me->v2 != ccg_vert2_index) { + return false; + } + } + } + + /* TODO(sergey): Crease topology changes detection. */ + { + CCGEdgeIterator ccg_edge_iter; + for (ccgSubSurf_initEdgeIterator(ss, &ccg_edge_iter); + !ccgEdgeIterator_isStopped(&ccg_edge_iter); + ccgEdgeIterator_next(&ccg_edge_iter)) { + /* const */ CCGEdge *ccg_edge = ccgEdgeIterator_getCurrent(&ccg_edge_iter); + const int edge_index = POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(ccg_edge)); + if (ccg_edge->crease != medge[edge_index].crease) { + return false; + } + } + } + + return true; } static bool compare_osd_derivedmesh_topology(CCGSubSurf *ss, DerivedMesh *dm) { - OpenSubdiv_Converter converter; - bool result; - if (ss->osd_mesh == NULL && ss->osd_topology_refiner == NULL) { - return true; - } - /* TODO(sergey): De-duplicate with topology counter at the bottom of - * the file. - */ - ccgSubSurf_converter_setup_from_derivedmesh(ss, dm, &converter); - result = openSubdiv_topologyRefinerCompareWithConverter( - ss->osd_topology_refiner, - &converter); - ccgSubSurf_converter_free(&converter); - return result; + OpenSubdiv_Converter converter; + bool result; + if (ss->osd_mesh == NULL && ss->osd_topology_refiner == NULL) { + return true; + } + /* TODO(sergey): De-duplicate with topology counter at the bottom of + * the file. + */ + ccgSubSurf_converter_setup_from_derivedmesh(ss, dm, &converter); + result = openSubdiv_topologyRefinerCompareWithConverter(ss->osd_topology_refiner, &converter); + ccgSubSurf_converter_free(&converter); + return result; } static bool opensubdiv_is_topology_changed(CCGSubSurf *ss, DerivedMesh *dm) { - if (ss->osd_compute != U.opensubdiv_compute_type) { - return true; - } - if (ss->osd_topology_refiner != NULL) { - const int levels = ss->osd_topology_refiner->getSubdivisionLevel( - ss->osd_topology_refiner); - BLI_assert(ss->osd_mesh_invalid == true); - if (levels != ss->subdivLevels) { - return true; - } - } - if (ss->skip_grids == false) { - return compare_ccg_derivedmesh_topology(ss, dm) == false; - } - else { - return compare_osd_derivedmesh_topology(ss, dm) == false; - } - return false; + if (ss->osd_compute != U.opensubdiv_compute_type) { + return true; + } + if (ss->osd_topology_refiner != NULL) { + const int levels = ss->osd_topology_refiner->getSubdivisionLevel(ss->osd_topology_refiner); + BLI_assert(ss->osd_mesh_invalid == true); + if (levels != ss->subdivLevels) { + return true; + } + } + if (ss->skip_grids == false) { + return compare_ccg_derivedmesh_topology(ss, dm) == false; + } + else { + return compare_osd_derivedmesh_topology(ss, dm) == false; + } + return false; } void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, DerivedMesh *dm) { - if (opensubdiv_is_topology_changed(ss, dm)) { - /* ** Make sure both GPU and CPU backends are properly reset. ** */ + if (opensubdiv_is_topology_changed(ss, dm)) { + /* ** Make sure both GPU and CPU backends are properly reset. ** */ - ss->osd_coarse_coords_invalid = true; + ss->osd_coarse_coords_invalid = true; - /* Reset GPU part. */ - ss->osd_mesh_invalid = true; - if (ss->osd_topology_refiner != NULL) { - openSubdiv_deleteTopologyRefiner(ss->osd_topology_refiner); - ss->osd_topology_refiner = NULL; - } + /* Reset GPU part. */ + ss->osd_mesh_invalid = true; + if (ss->osd_topology_refiner != NULL) { + openSubdiv_deleteTopologyRefiner(ss->osd_topology_refiner); + ss->osd_topology_refiner = NULL; + } - /* Reset CPU side. */ - if (ss->osd_evaluator != NULL) { - openSubdiv_deleteEvaluator(ss->osd_evaluator); - ss->osd_evaluator = NULL; - } - } + /* Reset CPU side. */ + if (ss->osd_evaluator != NULL) { + openSubdiv_deleteEvaluator(ss->osd_evaluator); + ss->osd_evaluator = NULL; + } + } } static void ccgSubSurf__updateGLMeshCoords(CCGSubSurf *ss) { - BLI_assert(ss->meshIFC.numLayers == 3); - ss->osd_mesh->setCoarsePositions(ss->osd_mesh, - (float *) ss->osd_coarse_coords, - 0, - ss->osd_num_coarse_coords); -} - -bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, - bool use_osd_glsl, - int active_uv_index) -{ - int compute_type; - - switch (U.opensubdiv_compute_type) { -#define CHECK_COMPUTE_TYPE(type) \ - case USER_OPENSUBDIV_COMPUTE_ ## type: \ - compute_type = OPENSUBDIV_EVALUATOR_ ## type; \ - break; - CHECK_COMPUTE_TYPE(CPU) - CHECK_COMPUTE_TYPE(OPENMP) - CHECK_COMPUTE_TYPE(OPENCL) - CHECK_COMPUTE_TYPE(CUDA) - CHECK_COMPUTE_TYPE(GLSL_TRANSFORM_FEEDBACK) - CHECK_COMPUTE_TYPE(GLSL_COMPUTE) - default: - compute_type = OPENSUBDIV_EVALUATOR_CPU; - break; -#undef CHECK_COMPUTE_TYPE - } - - if (ss->osd_vao == 0) { - glGenVertexArrays(1, &ss->osd_vao); - } - - if (ss->osd_mesh_invalid) { - if (ss->osd_mesh != NULL) { - ccgSubSurf__delete_osdGLMesh(ss->osd_mesh); - ss->osd_mesh = NULL; - } - ss->osd_mesh_invalid = false; - } - - if (ss->osd_mesh == NULL) { - if (ss->osd_topology_refiner == NULL) { - /* Happens with empty meshes. */ - /* TODO(sergey): Add assert that mesh is indeed empty. */ - return false; - } - - ss->osd_mesh = openSubdiv_createOsdGLMeshFromTopologyRefiner( - ss->osd_topology_refiner, - compute_type); - - if (UNLIKELY(ss->osd_mesh == NULL)) { - /* Most likely compute device is not available. */ - return false; - } - - ccgSubSurf__updateGLMeshCoords(ss); - ss->osd_mesh->refine(ss->osd_mesh); - ss->osd_mesh->synchronize(ss->osd_mesh); - ss->osd_coarse_coords_invalid = false; - - glBindVertexArray(ss->osd_vao); - ss->osd_mesh->bindVertexBuffer(ss->osd_mesh); - - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, - sizeof(GLfloat) * 6, 0); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, - sizeof(GLfloat) * 6, (float *)12); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - } - else if (ss->osd_coarse_coords_invalid) { - ccgSubSurf__updateGLMeshCoords(ss); - ss->osd_mesh->refine(ss->osd_mesh); - ss->osd_mesh->synchronize(ss->osd_mesh); - ss->osd_coarse_coords_invalid = false; - } - - ss->osd_mesh->prepareDraw(ss->osd_mesh, use_osd_glsl, active_uv_index); - - return true; -} - -void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, bool fill_quads, - int start_partition, int num_partitions) -{ - if (LIKELY(ss->osd_mesh != NULL)) { - glBindVertexArray(ss->osd_vao); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, - ss->osd_mesh->getPatchIndexBuffer(ss->osd_mesh)); - - ss->osd_mesh->bindVertexBuffer(ss->osd_mesh); - glBindVertexArray(ss->osd_vao); - ss->osd_mesh->drawPatches(ss->osd_mesh, fill_quads, - start_partition, num_partitions); - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } + BLI_assert(ss->meshIFC.numLayers == 3); + ss->osd_mesh->setCoarsePositions( + ss->osd_mesh, (float *)ss->osd_coarse_coords, 0, ss->osd_num_coarse_coords); +} + +bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl, int active_uv_index) +{ + int compute_type; + + switch (U.opensubdiv_compute_type) { +# define CHECK_COMPUTE_TYPE(type) \ + case USER_OPENSUBDIV_COMPUTE_##type: \ + compute_type = OPENSUBDIV_EVALUATOR_##type; \ + break; + CHECK_COMPUTE_TYPE(CPU) + CHECK_COMPUTE_TYPE(OPENMP) + CHECK_COMPUTE_TYPE(OPENCL) + CHECK_COMPUTE_TYPE(CUDA) + CHECK_COMPUTE_TYPE(GLSL_TRANSFORM_FEEDBACK) + CHECK_COMPUTE_TYPE(GLSL_COMPUTE) + default: + compute_type = OPENSUBDIV_EVALUATOR_CPU; + break; +# undef CHECK_COMPUTE_TYPE + } + + if (ss->osd_vao == 0) { + glGenVertexArrays(1, &ss->osd_vao); + } + + if (ss->osd_mesh_invalid) { + if (ss->osd_mesh != NULL) { + ccgSubSurf__delete_osdGLMesh(ss->osd_mesh); + ss->osd_mesh = NULL; + } + ss->osd_mesh_invalid = false; + } + + if (ss->osd_mesh == NULL) { + if (ss->osd_topology_refiner == NULL) { + /* Happens with empty meshes. */ + /* TODO(sergey): Add assert that mesh is indeed empty. */ + return false; + } + + ss->osd_mesh = openSubdiv_createOsdGLMeshFromTopologyRefiner(ss->osd_topology_refiner, + compute_type); + + if (UNLIKELY(ss->osd_mesh == NULL)) { + /* Most likely compute device is not available. */ + return false; + } + + ccgSubSurf__updateGLMeshCoords(ss); + ss->osd_mesh->refine(ss->osd_mesh); + ss->osd_mesh->synchronize(ss->osd_mesh); + ss->osd_coarse_coords_invalid = false; + + glBindVertexArray(ss->osd_vao); + ss->osd_mesh->bindVertexBuffer(ss->osd_mesh); + + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, 0); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (float *)12); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + else if (ss->osd_coarse_coords_invalid) { + ccgSubSurf__updateGLMeshCoords(ss); + ss->osd_mesh->refine(ss->osd_mesh); + ss->osd_mesh->synchronize(ss->osd_mesh); + ss->osd_coarse_coords_invalid = false; + } + + ss->osd_mesh->prepareDraw(ss->osd_mesh, use_osd_glsl, active_uv_index); + + return true; +} + +void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, + bool fill_quads, + int start_partition, + int num_partitions) +{ + if (LIKELY(ss->osd_mesh != NULL)) { + glBindVertexArray(ss->osd_vao); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ss->osd_mesh->getPatchIndexBuffer(ss->osd_mesh)); + + ss->osd_mesh->bindVertexBuffer(ss->osd_mesh); + glBindVertexArray(ss->osd_vao); + ss->osd_mesh->drawPatches(ss->osd_mesh, fill_quads, start_partition, num_partitions); + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } } int ccgSubSurf_getNumGLMeshBaseFaces(CCGSubSurf *ss) { - if (ss->osd_topology_refiner != NULL) { - return ss->osd_topology_refiner->getNumFaces( - ss->osd_topology_refiner); - } - return 0; + if (ss->osd_topology_refiner != NULL) { + return ss->osd_topology_refiner->getNumFaces(ss->osd_topology_refiner); + } + return 0; } /* Get number of vertices in base faces in a particular GL mesh. */ int ccgSubSurf_getNumGLMeshBaseFaceVerts(CCGSubSurf *ss, int face) { - if (ss->osd_topology_refiner != NULL) { - return ss->osd_topology_refiner->getNumFaceVertices( - ss->osd_topology_refiner, face); - } - return 0; + if (ss->osd_topology_refiner != NULL) { + return ss->osd_topology_refiner->getNumFaceVertices(ss->osd_topology_refiner, face); + } + return 0; } void ccgSubSurf_setSkipGrids(CCGSubSurf *ss, bool skip_grids) { - ss->skip_grids = skip_grids; + ss->skip_grids = skip_grids; } bool ccgSubSurf_needGrids(CCGSubSurf *ss) { - return ss->skip_grids == false; -} - -BLI_INLINE void ccgSubSurf__mapGridToFace(int S, float grid_u, float grid_v, - float *face_u, float *face_v) -{ - float u, v; - - /* - Each grid covers half of the face along the edges. - * - Grid's (0, 0) starts from the middle of the face. - */ - u = 0.5f - 0.5f * grid_u; - v = 0.5f - 0.5f * grid_v; - - if (S == 0) { - *face_u = v; - *face_v = u; - } - else if (S == 1) { - *face_u = 1.0f - u; - *face_v = v; - } - else if (S == 2) { - *face_u = 1.0f - v; - *face_v = 1.0f - u; - } - else { - *face_u = u; - *face_v = 1.0f - v; - } -} - -BLI_INLINE void ccgSubSurf__mapEdgeToFace(int S, - int edge_segment, - bool inverse_edge, - int edgeSize, - float *face_u, float *face_v) -{ - int t = inverse_edge ? edgeSize - edge_segment - 1 : edge_segment; - if (S == 0) { - *face_u = (float) t / (edgeSize - 1); - *face_v = 0.0f; - } - else if (S == 1) { - *face_u = 1.0f; - *face_v = (float) t / (edgeSize - 1); - } - else if (S == 2) { - *face_u = 1.0f - (float) t / (edgeSize - 1); - *face_v = 1.0f; - } - else { - *face_u = 0.0f; - *face_v = 1.0f - (float) t / (edgeSize - 1); - } -} - -void ccgSubSurf_evaluatorSetFVarUV(CCGSubSurf *ss, - DerivedMesh *dm, - int layer_index) -{ - MPoly *mpoly = dm->getPolyArray(dm); - MLoopUV *mloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, layer_index); - int num_polys = dm->getNumPolys(dm); - int index, poly; - BLI_assert(ss->osd_evaluator != NULL); - for (poly = 0, index = 0; poly < num_polys; poly++) { - int loop; - MPoly *mp = &mpoly[poly]; - for (loop = 0; loop < mp->totloop; loop++, index++) { - MLoopUV *mluv = &mloopuv[loop + mp->loopstart]; - (void)mluv; - /* TODO(sergey): Send mluv->uv to the evaluator's face varying - * buffer. - */ - } - } - (void)ss; -} - -void ccgSubSurf_evaluatorFVarUV(CCGSubSurf *ss, - int face_index, int S, - float grid_u, float grid_v, - float uv[2]) -{ - float face_u, face_v; - ccgSubSurf__mapGridToFace(S, - grid_u, grid_v, - &face_u, &face_v); - (void)ss; - (void)face_index; - /* TODO(sergey): Evaluate face varying coordinate. */ - zero_v2(uv); + return ss->skip_grids == false; +} + +BLI_INLINE void ccgSubSurf__mapGridToFace( + int S, float grid_u, float grid_v, float *face_u, float *face_v) +{ + float u, v; + + /* - Each grid covers half of the face along the edges. + * - Grid's (0, 0) starts from the middle of the face. + */ + u = 0.5f - 0.5f * grid_u; + v = 0.5f - 0.5f * grid_v; + + if (S == 0) { + *face_u = v; + *face_v = u; + } + else if (S == 1) { + *face_u = 1.0f - u; + *face_v = v; + } + else if (S == 2) { + *face_u = 1.0f - v; + *face_v = 1.0f - u; + } + else { + *face_u = u; + *face_v = 1.0f - v; + } +} + +BLI_INLINE void ccgSubSurf__mapEdgeToFace( + int S, int edge_segment, bool inverse_edge, int edgeSize, float *face_u, float *face_v) +{ + int t = inverse_edge ? edgeSize - edge_segment - 1 : edge_segment; + if (S == 0) { + *face_u = (float)t / (edgeSize - 1); + *face_v = 0.0f; + } + else if (S == 1) { + *face_u = 1.0f; + *face_v = (float)t / (edgeSize - 1); + } + else if (S == 2) { + *face_u = 1.0f - (float)t / (edgeSize - 1); + *face_v = 1.0f; + } + else { + *face_u = 0.0f; + *face_v = 1.0f - (float)t / (edgeSize - 1); + } +} + +void ccgSubSurf_evaluatorSetFVarUV(CCGSubSurf *ss, DerivedMesh *dm, int layer_index) +{ + MPoly *mpoly = dm->getPolyArray(dm); + MLoopUV *mloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, layer_index); + int num_polys = dm->getNumPolys(dm); + int index, poly; + BLI_assert(ss->osd_evaluator != NULL); + for (poly = 0, index = 0; poly < num_polys; poly++) { + int loop; + MPoly *mp = &mpoly[poly]; + for (loop = 0; loop < mp->totloop; loop++, index++) { + MLoopUV *mluv = &mloopuv[loop + mp->loopstart]; + (void)mluv; + /* TODO(sergey): Send mluv->uv to the evaluator's face varying + * buffer. + */ + } + } + (void)ss; +} + +void ccgSubSurf_evaluatorFVarUV( + CCGSubSurf *ss, int face_index, int S, float grid_u, float grid_v, float uv[2]) +{ + float face_u, face_v; + ccgSubSurf__mapGridToFace(S, grid_u, grid_v, &face_u, &face_v); + (void)ss; + (void)face_index; + /* TODO(sergey): Evaluate face varying coordinate. */ + zero_v2(uv); } static bool opensubdiv_createEvaluator(CCGSubSurf *ss) { - OpenSubdiv_Converter converter; - OpenSubdiv_TopologyRefiner *topology_refiner; - if (ss->fMap->numEntries == 0) { - /* OpenSubdiv doesn't support meshes without faces. */ - return false; - } - ccgSubSurf_converter_setup_from_ccg(ss, &converter); - OpenSubdiv_TopologyRefinerSettings settings; - settings.level = ss->subdivLevels; - settings.is_adaptive = false; - topology_refiner = - openSubdiv_createTopologyRefinerFromConverter( - &converter, &settings); - ccgSubSurf_converter_free(&converter); - ss->osd_evaluator = - openSubdiv_createEvaluatorFromTopologyRefiner(topology_refiner); - if (ss->osd_evaluator == NULL) { - BLI_assert(!"OpenSubdiv initialization failed, should not happen."); - return false; - } - return true; + OpenSubdiv_Converter converter; + OpenSubdiv_TopologyRefiner *topology_refiner; + if (ss->fMap->numEntries == 0) { + /* OpenSubdiv doesn't support meshes without faces. */ + return false; + } + ccgSubSurf_converter_setup_from_ccg(ss, &converter); + OpenSubdiv_TopologyRefinerSettings settings; + settings.level = ss->subdivLevels; + settings.is_adaptive = false; + topology_refiner = openSubdiv_createTopologyRefinerFromConverter(&converter, &settings); + ccgSubSurf_converter_free(&converter); + ss->osd_evaluator = openSubdiv_createEvaluatorFromTopologyRefiner(topology_refiner); + if (ss->osd_evaluator == NULL) { + BLI_assert(!"OpenSubdiv initialization failed, should not happen."); + return false; + } + return true; } static bool opensubdiv_ensureEvaluator(CCGSubSurf *ss) { - if (ss->osd_evaluator == NULL) { - OSD_LOG("Allocating new evaluator, %d verts\n", ss->vMap->numEntries); - opensubdiv_createEvaluator(ss); - } - return ss->osd_evaluator != NULL; + if (ss->osd_evaluator == NULL) { + OSD_LOG("Allocating new evaluator, %d verts\n", ss->vMap->numEntries); + opensubdiv_createEvaluator(ss); + } + return ss->osd_evaluator != NULL; } static void opensubdiv_updateEvaluatorCoarsePositions(CCGSubSurf *ss) { - float (*positions)[3]; - int vertDataSize = ss->meshIFC.vertDataSize; - int num_basis_verts = ss->vMap->numEntries; - int i; - - /* TODO(sergey): Avoid allocation on every update. We could either update - * coordinates in chunks of 1K vertices (which will only use stack memory) - * or do some callback magic for OSD evaluator can invoke it and fill in - * buffer directly. - */ - if (ss->meshIFC.numLayers == 3) { - /* If all the components are to be initialized, no need to memset the - * new memory block. - */ - positions = MEM_mallocN(3 * sizeof(float) * num_basis_verts, - "OpenSubdiv coarse points"); - } - else { - /* Calloc in order to have z component initialized to 0 for Uvs */ - positions = MEM_callocN(3 * sizeof(float) * num_basis_verts, - "OpenSubdiv coarse points"); - } -#pragma omp parallel for - for (i = 0; i < ss->vMap->curSize; i++) { - CCGVert *v = (CCGVert *) ss->vMap->buckets[i]; - for (; v; v = v->next) { - float *co = VERT_getCo(v, 0); - BLI_assert(v->osd_index < ss->vMap->numEntries); - VertDataCopy(positions[v->osd_index], co, ss); - OSD_LOG("Point %d has value %f %f %f\n", - v->osd_index, - positions[v->osd_index][0], - positions[v->osd_index][1], - positions[v->osd_index][2]); - } - } - - ss->osd_evaluator->setCoarsePositions(ss->osd_evaluator, - (float *)positions, - 0, - num_basis_verts); - ss->osd_evaluator->refine(ss->osd_evaluator); - - MEM_freeN(positions); + float(*positions)[3]; + int vertDataSize = ss->meshIFC.vertDataSize; + int num_basis_verts = ss->vMap->numEntries; + int i; + + /* TODO(sergey): Avoid allocation on every update. We could either update + * coordinates in chunks of 1K vertices (which will only use stack memory) + * or do some callback magic for OSD evaluator can invoke it and fill in + * buffer directly. + */ + if (ss->meshIFC.numLayers == 3) { + /* If all the components are to be initialized, no need to memset the + * new memory block. + */ + positions = MEM_mallocN(3 * sizeof(float) * num_basis_verts, "OpenSubdiv coarse points"); + } + else { + /* Calloc in order to have z component initialized to 0 for Uvs */ + positions = MEM_callocN(3 * sizeof(float) * num_basis_verts, "OpenSubdiv coarse points"); + } +# pragma omp parallel for + for (i = 0; i < ss->vMap->curSize; i++) { + CCGVert *v = (CCGVert *)ss->vMap->buckets[i]; + for (; v; v = v->next) { + float *co = VERT_getCo(v, 0); + BLI_assert(v->osd_index < ss->vMap->numEntries); + VertDataCopy(positions[v->osd_index], co, ss); + OSD_LOG("Point %d has value %f %f %f\n", + v->osd_index, + positions[v->osd_index][0], + positions[v->osd_index][1], + positions[v->osd_index][2]); + } + } + + ss->osd_evaluator->setCoarsePositions(ss->osd_evaluator, (float *)positions, 0, num_basis_verts); + ss->osd_evaluator->refine(ss->osd_evaluator); + + MEM_freeN(positions); } static void opensubdiv_evaluateQuadFaceGrids(CCGSubSurf *ss, CCGFace *face, const int osd_face_index) { - int normalDataOffset = ss->normalDataOffset; - int subdivLevels = ss->subdivLevels; - int gridSize = ccg_gridsize(subdivLevels); - int edgeSize = ccg_edgesize(subdivLevels); - int vertDataSize = ss->meshIFC.vertDataSize; - int S; - bool do_normals = ss->meshIFC.numLayers == 3; - -#pragma omp parallel for - for (S = 0; S < face->numVerts; S++) { - int x, y, k; - CCGEdge *edge = NULL; - bool inverse_edge = false; - - for (x = 0; x < gridSize; x++) { - for (y = 0; y < gridSize; y++) { - float *co = FACE_getIFCo(face, subdivLevels, S, x, y); - float *no = FACE_getIFNo(face, subdivLevels, S, x, y); - float grid_u = (float) x / (gridSize - 1), - grid_v = (float) y / (gridSize - 1); - float face_u, face_v; - float P[3], dPdu[3], dPdv[3]; - - ccgSubSurf__mapGridToFace(S, grid_u, grid_v, &face_u, &face_v); - - /* TODO(sergey): Need proper port. */ - ss->osd_evaluator->evaluateLimit( - ss->osd_evaluator, osd_face_index, - face_u, face_v, - P, - do_normals ? dPdu : NULL, - do_normals ? dPdv : NULL); - - OSD_LOG("face=%d, corner=%d, grid_u=%f, grid_v=%f, face_u=%f, face_v=%f, P=(%f, %f, %f)\n", - osd_face_index, S, grid_u, grid_v, face_u, face_v, P[0], P[1], P[2]); - - VertDataCopy(co, P, ss); - if (do_normals) { - cross_v3_v3v3(no, dPdu, dPdv); - normalize_v3(no); - } - - if (x == gridSize - 1 && y == gridSize - 1) { - float *vert_co = VERT_getCo(FACE_getVerts(face)[S], subdivLevels); - VertDataCopy(vert_co, co, ss); - if (do_normals) { - float *vert_no = VERT_getNo(FACE_getVerts(face)[S], subdivLevels); - VertDataCopy(vert_no, no, ss); - } - } - if (S == 0 && x == 0 && y == 0) { - float *center_co = (float *)FACE_getCenterData(face); - VertDataCopy(center_co, co, ss); - if (do_normals) { - float *center_no = (float *)((byte *)FACE_getCenterData(face) + normalDataOffset); - VertDataCopy(center_no, no, ss); - } - } - } - } - - for (x = 0; x < gridSize; x++) { - VertDataCopy(FACE_getIECo(face, subdivLevels, S, x), - FACE_getIFCo(face, subdivLevels, S, x, 0), ss); - if (do_normals) { - VertDataCopy(FACE_getIENo(face, subdivLevels, S, x), - FACE_getIFNo(face, subdivLevels, S, x, 0), ss); - } - } - - for (k = 0; k < face->numVerts; k++) { - CCGEdge *current_edge = FACE_getEdges(face)[k]; - CCGVert **face_verts = FACE_getVerts(face); - if (current_edge->v0 == face_verts[S] && - current_edge->v1 == face_verts[(S + 1) % face->numVerts]) - { - edge = current_edge; - inverse_edge = false; - break; - } - if (current_edge->v1 == face_verts[S] && - current_edge->v0 == face_verts[(S + 1) % face->numVerts]) - { - edge = current_edge; - inverse_edge = true; - break; - } - } - - BLI_assert(edge != NULL); - - for (x = 0; x < edgeSize; x++) { - float u = 0, v = 0; - float *co = EDGE_getCo(edge, subdivLevels, x); - float *no = EDGE_getNo(edge, subdivLevels, x); - float P[3], dPdu[3], dPdv[3]; - ccgSubSurf__mapEdgeToFace(S, x, - inverse_edge, - edgeSize, - &u, &v); - - /* TODO(sergey): Ideally we will re-use grid here, but for now - * let's just re-evaluate for simplicity. - */ - /* TODO(sergey): Need proper port. */ - ss->osd_evaluator->evaluateLimit( - ss->osd_evaluator, - osd_face_index, - u, v, - P, dPdu, dPdv); - VertDataCopy(co, P, ss); - if (do_normals) { - cross_v3_v3v3(no, dPdu, dPdv); - normalize_v3(no); - } - } - } + int normalDataOffset = ss->normalDataOffset; + int subdivLevels = ss->subdivLevels; + int gridSize = ccg_gridsize(subdivLevels); + int edgeSize = ccg_edgesize(subdivLevels); + int vertDataSize = ss->meshIFC.vertDataSize; + int S; + bool do_normals = ss->meshIFC.numLayers == 3; + +# pragma omp parallel for + for (S = 0; S < face->numVerts; S++) { + int x, y, k; + CCGEdge *edge = NULL; + bool inverse_edge = false; + + for (x = 0; x < gridSize; x++) { + for (y = 0; y < gridSize; y++) { + float *co = FACE_getIFCo(face, subdivLevels, S, x, y); + float *no = FACE_getIFNo(face, subdivLevels, S, x, y); + float grid_u = (float)x / (gridSize - 1), grid_v = (float)y / (gridSize - 1); + float face_u, face_v; + float P[3], dPdu[3], dPdv[3]; + + ccgSubSurf__mapGridToFace(S, grid_u, grid_v, &face_u, &face_v); + + /* TODO(sergey): Need proper port. */ + ss->osd_evaluator->evaluateLimit(ss->osd_evaluator, + osd_face_index, + face_u, + face_v, + P, + do_normals ? dPdu : NULL, + do_normals ? dPdv : NULL); + + OSD_LOG("face=%d, corner=%d, grid_u=%f, grid_v=%f, face_u=%f, face_v=%f, P=(%f, %f, %f)\n", + osd_face_index, + S, + grid_u, + grid_v, + face_u, + face_v, + P[0], + P[1], + P[2]); + + VertDataCopy(co, P, ss); + if (do_normals) { + cross_v3_v3v3(no, dPdu, dPdv); + normalize_v3(no); + } + + if (x == gridSize - 1 && y == gridSize - 1) { + float *vert_co = VERT_getCo(FACE_getVerts(face)[S], subdivLevels); + VertDataCopy(vert_co, co, ss); + if (do_normals) { + float *vert_no = VERT_getNo(FACE_getVerts(face)[S], subdivLevels); + VertDataCopy(vert_no, no, ss); + } + } + if (S == 0 && x == 0 && y == 0) { + float *center_co = (float *)FACE_getCenterData(face); + VertDataCopy(center_co, co, ss); + if (do_normals) { + float *center_no = (float *)((byte *)FACE_getCenterData(face) + normalDataOffset); + VertDataCopy(center_no, no, ss); + } + } + } + } + + for (x = 0; x < gridSize; x++) { + VertDataCopy( + FACE_getIECo(face, subdivLevels, S, x), FACE_getIFCo(face, subdivLevels, S, x, 0), ss); + if (do_normals) { + VertDataCopy( + FACE_getIENo(face, subdivLevels, S, x), FACE_getIFNo(face, subdivLevels, S, x, 0), ss); + } + } + + for (k = 0; k < face->numVerts; k++) { + CCGEdge *current_edge = FACE_getEdges(face)[k]; + CCGVert **face_verts = FACE_getVerts(face); + if (current_edge->v0 == face_verts[S] && + current_edge->v1 == face_verts[(S + 1) % face->numVerts]) { + edge = current_edge; + inverse_edge = false; + break; + } + if (current_edge->v1 == face_verts[S] && + current_edge->v0 == face_verts[(S + 1) % face->numVerts]) { + edge = current_edge; + inverse_edge = true; + break; + } + } + + BLI_assert(edge != NULL); + + for (x = 0; x < edgeSize; x++) { + float u = 0, v = 0; + float *co = EDGE_getCo(edge, subdivLevels, x); + float *no = EDGE_getNo(edge, subdivLevels, x); + float P[3], dPdu[3], dPdv[3]; + ccgSubSurf__mapEdgeToFace(S, x, inverse_edge, edgeSize, &u, &v); + + /* TODO(sergey): Ideally we will re-use grid here, but for now + * let's just re-evaluate for simplicity. + */ + /* TODO(sergey): Need proper port. */ + ss->osd_evaluator->evaluateLimit(ss->osd_evaluator, osd_face_index, u, v, P, dPdu, dPdv); + VertDataCopy(co, P, ss); + if (do_normals) { + cross_v3_v3v3(no, dPdu, dPdv); + normalize_v3(no); + } + } + } } static void opensubdiv_evaluateNGonFaceGrids(CCGSubSurf *ss, CCGFace *face, const int osd_face_index) { - CCGVert **all_verts = FACE_getVerts(face); - int normalDataOffset = ss->normalDataOffset; - int subdivLevels = ss->subdivLevels; - int gridSize = ccg_gridsize(subdivLevels); - int edgeSize = ccg_edgesize(subdivLevels); - int vertDataSize = ss->meshIFC.vertDataSize; - int S; - bool do_normals = ss->meshIFC.numLayers == 3; - - /* Note about handling non-quad faces. - * - * In order to deal with non-quad faces we need to split them - * into a quads in the following way: - * - * | - * (vert_next) - * | - * | - * | - * (face_center) ------------------- (v2) - * | (o)--------------------> | - * | | v | - * | | | - * | | | - * | | | - * | | y ^ | - * | | | | - * | v u x | | - * | <---(o) | - * ---- (vert_prev) ---- (v1) -------------------- (vert) - * - * This is how grids are expected to be stored and it's how - * OpenSubdiv deals with non-quad faces using ptex face indices. - * We only need to convert ptex (x, y) to grid (u, v) by some - * simple flips and evaluate the ptex face. - */ - - /* Evaluate face grids. */ -#pragma omp parallel for - for (S = 0; S < face->numVerts; S++) { - int x, y; - for (x = 0; x < gridSize; x++) { - for (y = 0; y < gridSize; y++) { - float *co = FACE_getIFCo(face, subdivLevels, S, x, y); - float *no = FACE_getIFNo(face, subdivLevels, S, x, y); - float u = 1.0f - (float) y / (gridSize - 1), - v = 1.0f - (float) x / (gridSize - 1); - float P[3], dPdu[3], dPdv[3]; - - /* TODO(sergey): Need proper port. */ - ss->osd_evaluator->evaluateLimit( - ss->osd_evaluator, - osd_face_index + S, - u, v, - P, dPdu, dPdv); - - OSD_LOG("face=%d, corner=%d, u=%f, v=%f, P=(%f, %f, %f)\n", - osd_face_index + S, S, u, v, P[0], P[1], P[2]); - - VertDataCopy(co, P, ss); - if (do_normals) { - cross_v3_v3v3(no, dPdu, dPdv); - normalize_v3(no); - } - - /* TODO(sergey): De-dpuplicate with the quad case. */ - if (x == gridSize - 1 && y == gridSize - 1) { - float *vert_co = VERT_getCo(FACE_getVerts(face)[S], subdivLevels); - VertDataCopy(vert_co, co, ss); - if (do_normals) { - float *vert_no = VERT_getNo(FACE_getVerts(face)[S], subdivLevels); - VertDataCopy(vert_no, no, ss); - } - } - if (S == 0 && x == 0 && y == 0) { - float *center_co = (float *)FACE_getCenterData(face); - VertDataCopy(center_co, co, ss); - if (do_normals) { - float *center_no = (float *)((byte *)FACE_getCenterData(face) + normalDataOffset); - VertDataCopy(center_no, no, ss); - } - } - } - } - for (x = 0; x < gridSize; x++) { - VertDataCopy(FACE_getIECo(face, subdivLevels, S, x), - FACE_getIFCo(face, subdivLevels, S, x, 0), ss); - if (do_normals) { - VertDataCopy(FACE_getIENo(face, subdivLevels, S, x), - FACE_getIFNo(face, subdivLevels, S, x, 0), ss); - } - } - } - - /* Evaluate edges. */ - for (S = 0; S < face->numVerts; S++) { - CCGEdge *edge = FACE_getEdges(face)[S]; - int x, S0 = 0, S1 = 0; - bool flip; - - for (x = 0; x < face->numVerts; ++x) { - if (all_verts[x] == edge->v0) { - S0 = x; - } - else if (all_verts[x] == edge->v1) { - S1 = x; - } - } - if (S == face->numVerts - 1) { - flip = S0 > S1; - } - else { - flip = S0 < S1; - } - - for (x = 0; x <= edgeSize / 2; x++) { - float *edge_co = EDGE_getCo(edge, subdivLevels, x); - float *edge_no = EDGE_getNo(edge, subdivLevels, x); - float *face_edge_co; - float *face_edge_no; - if (flip) { - face_edge_co = FACE_getIFCo(face, subdivLevels, S0, gridSize - 1, gridSize - 1 - x); - face_edge_no = FACE_getIFNo(face, subdivLevels, S0, gridSize - 1, gridSize - 1 - x); - } - else { - face_edge_co = FACE_getIFCo(face, subdivLevels, S0, gridSize - 1 - x, gridSize - 1); - face_edge_no = FACE_getIFNo(face, subdivLevels, S0, gridSize - 1 - x, gridSize - 1); - } - VertDataCopy(edge_co, face_edge_co, ss); - if (do_normals) { - VertDataCopy(edge_no, face_edge_no, ss); - } - } - for (x = edgeSize / 2 + 1; x < edgeSize; x++) { - float *edge_co = EDGE_getCo(edge, subdivLevels, x); - float *edge_no = EDGE_getNo(edge, subdivLevels, x); - float *face_edge_co; - float *face_edge_no; - if (flip) { - face_edge_co = FACE_getIFCo(face, subdivLevels, S1, x - edgeSize / 2, gridSize - 1); - face_edge_no = FACE_getIFNo(face, subdivLevels, S1, x - edgeSize / 2, gridSize - 1); - } - else { - face_edge_co = FACE_getIFCo(face, subdivLevels, S1, gridSize - 1, x - edgeSize / 2); - face_edge_no = FACE_getIFNo(face, subdivLevels, S1, gridSize - 1, x - edgeSize / 2); - } - VertDataCopy(edge_co, face_edge_co, ss); - if (do_normals) { - VertDataCopy(edge_no, face_edge_no, ss); - } - } - } + CCGVert **all_verts = FACE_getVerts(face); + int normalDataOffset = ss->normalDataOffset; + int subdivLevels = ss->subdivLevels; + int gridSize = ccg_gridsize(subdivLevels); + int edgeSize = ccg_edgesize(subdivLevels); + int vertDataSize = ss->meshIFC.vertDataSize; + int S; + bool do_normals = ss->meshIFC.numLayers == 3; + + /* Note about handling non-quad faces. + * + * In order to deal with non-quad faces we need to split them + * into a quads in the following way: + * + * | + * (vert_next) + * | + * | + * | + * (face_center) ------------------- (v2) + * | (o)--------------------> | + * | | v | + * | | | + * | | | + * | | | + * | | y ^ | + * | | | | + * | v u x | | + * | <---(o) | + * ---- (vert_prev) ---- (v1) -------------------- (vert) + * + * This is how grids are expected to be stored and it's how + * OpenSubdiv deals with non-quad faces using ptex face indices. + * We only need to convert ptex (x, y) to grid (u, v) by some + * simple flips and evaluate the ptex face. + */ + + /* Evaluate face grids. */ +# pragma omp parallel for + for (S = 0; S < face->numVerts; S++) { + int x, y; + for (x = 0; x < gridSize; x++) { + for (y = 0; y < gridSize; y++) { + float *co = FACE_getIFCo(face, subdivLevels, S, x, y); + float *no = FACE_getIFNo(face, subdivLevels, S, x, y); + float u = 1.0f - (float)y / (gridSize - 1), v = 1.0f - (float)x / (gridSize - 1); + float P[3], dPdu[3], dPdv[3]; + + /* TODO(sergey): Need proper port. */ + ss->osd_evaluator->evaluateLimit( + ss->osd_evaluator, osd_face_index + S, u, v, P, dPdu, dPdv); + + OSD_LOG("face=%d, corner=%d, u=%f, v=%f, P=(%f, %f, %f)\n", + osd_face_index + S, + S, + u, + v, + P[0], + P[1], + P[2]); + + VertDataCopy(co, P, ss); + if (do_normals) { + cross_v3_v3v3(no, dPdu, dPdv); + normalize_v3(no); + } + + /* TODO(sergey): De-dpuplicate with the quad case. */ + if (x == gridSize - 1 && y == gridSize - 1) { + float *vert_co = VERT_getCo(FACE_getVerts(face)[S], subdivLevels); + VertDataCopy(vert_co, co, ss); + if (do_normals) { + float *vert_no = VERT_getNo(FACE_getVerts(face)[S], subdivLevels); + VertDataCopy(vert_no, no, ss); + } + } + if (S == 0 && x == 0 && y == 0) { + float *center_co = (float *)FACE_getCenterData(face); + VertDataCopy(center_co, co, ss); + if (do_normals) { + float *center_no = (float *)((byte *)FACE_getCenterData(face) + normalDataOffset); + VertDataCopy(center_no, no, ss); + } + } + } + } + for (x = 0; x < gridSize; x++) { + VertDataCopy( + FACE_getIECo(face, subdivLevels, S, x), FACE_getIFCo(face, subdivLevels, S, x, 0), ss); + if (do_normals) { + VertDataCopy( + FACE_getIENo(face, subdivLevels, S, x), FACE_getIFNo(face, subdivLevels, S, x, 0), ss); + } + } + } + + /* Evaluate edges. */ + for (S = 0; S < face->numVerts; S++) { + CCGEdge *edge = FACE_getEdges(face)[S]; + int x, S0 = 0, S1 = 0; + bool flip; + + for (x = 0; x < face->numVerts; ++x) { + if (all_verts[x] == edge->v0) { + S0 = x; + } + else if (all_verts[x] == edge->v1) { + S1 = x; + } + } + if (S == face->numVerts - 1) { + flip = S0 > S1; + } + else { + flip = S0 < S1; + } + + for (x = 0; x <= edgeSize / 2; x++) { + float *edge_co = EDGE_getCo(edge, subdivLevels, x); + float *edge_no = EDGE_getNo(edge, subdivLevels, x); + float *face_edge_co; + float *face_edge_no; + if (flip) { + face_edge_co = FACE_getIFCo(face, subdivLevels, S0, gridSize - 1, gridSize - 1 - x); + face_edge_no = FACE_getIFNo(face, subdivLevels, S0, gridSize - 1, gridSize - 1 - x); + } + else { + face_edge_co = FACE_getIFCo(face, subdivLevels, S0, gridSize - 1 - x, gridSize - 1); + face_edge_no = FACE_getIFNo(face, subdivLevels, S0, gridSize - 1 - x, gridSize - 1); + } + VertDataCopy(edge_co, face_edge_co, ss); + if (do_normals) { + VertDataCopy(edge_no, face_edge_no, ss); + } + } + for (x = edgeSize / 2 + 1; x < edgeSize; x++) { + float *edge_co = EDGE_getCo(edge, subdivLevels, x); + float *edge_no = EDGE_getNo(edge, subdivLevels, x); + float *face_edge_co; + float *face_edge_no; + if (flip) { + face_edge_co = FACE_getIFCo(face, subdivLevels, S1, x - edgeSize / 2, gridSize - 1); + face_edge_no = FACE_getIFNo(face, subdivLevels, S1, x - edgeSize / 2, gridSize - 1); + } + else { + face_edge_co = FACE_getIFCo(face, subdivLevels, S1, gridSize - 1, x - edgeSize / 2); + face_edge_no = FACE_getIFNo(face, subdivLevels, S1, gridSize - 1, x - edgeSize / 2); + } + VertDataCopy(edge_co, face_edge_co, ss); + if (do_normals) { + VertDataCopy(edge_no, face_edge_no, ss); + } + } + } } static void opensubdiv_evaluateGrids(CCGSubSurf *ss) { - int i; - for (i = 0; i < ss->fMap->curSize; i++) { - CCGFace *face = (CCGFace *) ss->fMap->buckets[i]; - for (; face; face = face->next) { - if (face->numVerts == 4) { - /* For quads we do special magic with converting face coords - * into corner coords and interpolating grids from it. - */ - opensubdiv_evaluateQuadFaceGrids(ss, face, face->osd_index); - } - else { - /* NGons and tris are split into separate osd faces which - * evaluates onto grids directly. - */ - opensubdiv_evaluateNGonFaceGrids(ss, face, face->osd_index); - } - } - } + int i; + for (i = 0; i < ss->fMap->curSize; i++) { + CCGFace *face = (CCGFace *)ss->fMap->buckets[i]; + for (; face; face = face->next) { + if (face->numVerts == 4) { + /* For quads we do special magic with converting face coords + * into corner coords and interpolating grids from it. + */ + opensubdiv_evaluateQuadFaceGrids(ss, face, face->osd_index); + } + else { + /* NGons and tris are split into separate osd faces which + * evaluates onto grids directly. + */ + opensubdiv_evaluateNGonFaceGrids(ss, face, face->osd_index); + } + } + } } CCGError ccgSubSurf_initOpenSubdivSync(CCGSubSurf *ss) { - if (ss->syncState != eSyncState_None) { - return eCCGError_InvalidSyncState; - } - ss->syncState = eSyncState_OpenSubdiv; - return eCCGError_None; + if (ss->syncState != eSyncState_None) { + return eCCGError_InvalidSyncState; + } + ss->syncState = eSyncState_OpenSubdiv; + return eCCGError_None; } void ccgSubSurf_prepareTopologyRefiner(CCGSubSurf *ss, DerivedMesh *dm) { - if (ss->osd_mesh == NULL || ss->osd_mesh_invalid) { - if (dm->getNumPolys(dm) != 0) { - OpenSubdiv_Converter converter; - ccgSubSurf_converter_setup_from_derivedmesh(ss, dm, &converter); - /* TODO(sergey): Remove possibly previously allocated refiner. */ - OpenSubdiv_TopologyRefinerSettings settings; - settings.level = ss->subdivLevels; - settings.is_adaptive = false; - ss->osd_topology_refiner = - openSubdiv_createTopologyRefinerFromConverter( - &converter, &settings); - ccgSubSurf_converter_free(&converter); - } - } - - /* Update number of grids, needed for things like final faces - * counter, used by display drawing. - */ - { - const int num_polys = dm->getNumPolys(dm); - const MPoly *mpoly = dm->getPolyArray(dm); - int poly; - ss->numGrids = 0; - for (poly = 0; poly < num_polys; ++poly) { - ss->numGrids += mpoly[poly].totloop; - } - } - - { - const int num_verts = dm->getNumVerts(dm); - const MVert *mvert = dm->getVertArray(dm); - int vert; - if (ss->osd_coarse_coords != NULL && - num_verts != ss->osd_num_coarse_coords) - { - MEM_freeN(ss->osd_coarse_coords); - ss->osd_coarse_coords = NULL; - } - if (ss->osd_coarse_coords == NULL) { - ss->osd_coarse_coords = MEM_mallocN(sizeof(float) * 6 * num_verts, "osd coarse positions"); - } - for (vert = 0; vert < num_verts; vert++) { - copy_v3_v3(ss->osd_coarse_coords[vert * 2 + 0], mvert[vert].co); - normal_short_to_float_v3(ss->osd_coarse_coords[vert * 2 + 1], mvert[vert].no); - } - ss->osd_num_coarse_coords = num_verts; - ss->osd_coarse_coords_invalid = true; - } + if (ss->osd_mesh == NULL || ss->osd_mesh_invalid) { + if (dm->getNumPolys(dm) != 0) { + OpenSubdiv_Converter converter; + ccgSubSurf_converter_setup_from_derivedmesh(ss, dm, &converter); + /* TODO(sergey): Remove possibly previously allocated refiner. */ + OpenSubdiv_TopologyRefinerSettings settings; + settings.level = ss->subdivLevels; + settings.is_adaptive = false; + ss->osd_topology_refiner = openSubdiv_createTopologyRefinerFromConverter(&converter, + &settings); + ccgSubSurf_converter_free(&converter); + } + } + + /* Update number of grids, needed for things like final faces + * counter, used by display drawing. + */ + { + const int num_polys = dm->getNumPolys(dm); + const MPoly *mpoly = dm->getPolyArray(dm); + int poly; + ss->numGrids = 0; + for (poly = 0; poly < num_polys; ++poly) { + ss->numGrids += mpoly[poly].totloop; + } + } + + { + const int num_verts = dm->getNumVerts(dm); + const MVert *mvert = dm->getVertArray(dm); + int vert; + if (ss->osd_coarse_coords != NULL && num_verts != ss->osd_num_coarse_coords) { + MEM_freeN(ss->osd_coarse_coords); + ss->osd_coarse_coords = NULL; + } + if (ss->osd_coarse_coords == NULL) { + ss->osd_coarse_coords = MEM_mallocN(sizeof(float) * 6 * num_verts, "osd coarse positions"); + } + for (vert = 0; vert < num_verts; vert++) { + copy_v3_v3(ss->osd_coarse_coords[vert * 2 + 0], mvert[vert].co); + normal_short_to_float_v3(ss->osd_coarse_coords[vert * 2 + 1], mvert[vert].no); + } + ss->osd_num_coarse_coords = num_verts; + ss->osd_coarse_coords_invalid = true; + } } void ccgSubSurf__sync_opensubdiv(CCGSubSurf *ss) { - BLI_assert(ss->meshIFC.numLayers == 2 || ss->meshIFC.numLayers == 3); + BLI_assert(ss->meshIFC.numLayers == 2 || ss->meshIFC.numLayers == 3); - /* Common synchronization steps */ - ss->osd_compute = U.opensubdiv_compute_type; + /* Common synchronization steps */ + ss->osd_compute = U.opensubdiv_compute_type; - if (ss->skip_grids == false) { - /* Make sure OSD evaluator is up-to-date. */ - if (opensubdiv_ensureEvaluator(ss)) { - /* Update coarse points in the OpenSubdiv evaluator. */ - opensubdiv_updateEvaluatorCoarsePositions(ss); + if (ss->skip_grids == false) { + /* Make sure OSD evaluator is up-to-date. */ + if (opensubdiv_ensureEvaluator(ss)) { + /* Update coarse points in the OpenSubdiv evaluator. */ + opensubdiv_updateEvaluatorCoarsePositions(ss); - /* Evaluate opensubdiv mesh into the CCG grids. */ - opensubdiv_evaluateGrids(ss); - } - } - else { - BLI_assert(ss->meshIFC.numLayers == 3); - } + /* Evaluate opensubdiv mesh into the CCG grids. */ + opensubdiv_evaluateGrids(ss); + } + } + else { + BLI_assert(ss->meshIFC.numLayers == 3); + } -#ifdef DUMP_RESULT_GRIDS - ccgSubSurf__dumpCoords(ss); -#endif +# ifdef DUMP_RESULT_GRIDS + ccgSubSurf__dumpCoords(ss); +# endif } void ccgSubSurf_free_osd_mesh(CCGSubSurf *ss) { - if (ss->osd_mesh != NULL) { - ccgSubSurf__delete_osdGLMesh(ss->osd_mesh); - ss->osd_mesh = NULL; - } - if (ss->osd_vao != 0) { - glDeleteVertexArrays(1, &ss->osd_vao); - ss->osd_vao = 0; - } + if (ss->osd_mesh != NULL) { + ccgSubSurf__delete_osdGLMesh(ss->osd_mesh); + ss->osd_mesh = NULL; + } + if (ss->osd_vao != 0) { + glDeleteVertexArrays(1, &ss->osd_vao); + ss->osd_vao = 0; + } } void ccgSubSurf_getMinMax(CCGSubSurf *ss, float r_min[3], float r_max[3]) { - int i; - BLI_assert(ss->skip_grids == true); - if (ss->osd_num_coarse_coords == 0) { - zero_v3(r_min); - zero_v3(r_max); - } - for (i = 0; i < ss->osd_num_coarse_coords; i++) { - /* Coarse coordinates has normals interleaved into the array. */ - DO_MINMAX(ss->osd_coarse_coords[2 * i], r_min, r_max); - } + int i; + BLI_assert(ss->skip_grids == true); + if (ss->osd_num_coarse_coords == 0) { + zero_v3(r_min); + zero_v3(r_max); + } + for (i = 0; i < ss->osd_num_coarse_coords; i++) { + /* Coarse coordinates has normals interleaved into the array. */ + DO_MINMAX(ss->osd_coarse_coords[2 * i], r_min, r_max); + } } /* ** Delayed delete routines ** */ typedef struct OsdDeletePendingItem { - struct OsdDeletePendingItem *next, *prev; - OpenSubdiv_GLMesh *osd_mesh; - unsigned int vao; + struct OsdDeletePendingItem *next, *prev; + OpenSubdiv_GLMesh *osd_mesh; + unsigned int vao; } OsdDeletePendingItem; static SpinLock delete_spin; static ListBase delete_pool = {NULL, NULL}; -static void delete_pending_push(OpenSubdiv_GLMesh *osd_mesh, - unsigned int vao) +static void delete_pending_push(OpenSubdiv_GLMesh *osd_mesh, unsigned int vao) { - OsdDeletePendingItem *new_entry = MEM_mallocN(sizeof(OsdDeletePendingItem), - "opensubdiv delete entry"); - new_entry->osd_mesh = osd_mesh; - new_entry->vao = vao; - BLI_spin_lock(&delete_spin); - BLI_addtail(&delete_pool, new_entry); - BLI_spin_unlock(&delete_spin); + OsdDeletePendingItem *new_entry = MEM_mallocN(sizeof(OsdDeletePendingItem), + "opensubdiv delete entry"); + new_entry->osd_mesh = osd_mesh; + new_entry->vao = vao; + BLI_spin_lock(&delete_spin); + BLI_addtail(&delete_pool, new_entry); + BLI_spin_unlock(&delete_spin); } void ccgSubSurf__delete_osdGLMesh(OpenSubdiv_GLMesh *osd_mesh) { - if (BLI_thread_is_main()) { - openSubdiv_deleteOsdGLMesh(osd_mesh); - } - else { - delete_pending_push(osd_mesh, 0); - } + if (BLI_thread_is_main()) { + openSubdiv_deleteOsdGLMesh(osd_mesh); + } + else { + delete_pending_push(osd_mesh, 0); + } } void ccgSubSurf__delete_vertex_array(unsigned int vao) { - if (BLI_thread_is_main()) { - glDeleteVertexArrays(1, &vao); - } - else { - delete_pending_push(NULL, vao); - } + if (BLI_thread_is_main()) { + glDeleteVertexArrays(1, &vao); + } + else { + delete_pending_push(NULL, vao); + } } void ccgSubSurf__delete_pending(void) { - OsdDeletePendingItem *entry; - BLI_assert(BLI_thread_is_main()); - BLI_spin_lock(&delete_spin); - for (entry = delete_pool.first; entry != NULL; entry = entry->next) { - if (entry->osd_mesh != NULL) { - openSubdiv_deleteOsdGLMesh(entry->osd_mesh); - } - if (entry->vao != 0) { - glDeleteVertexArrays(1, &entry->vao); - } - } - BLI_freelistN(&delete_pool); - BLI_spin_unlock(&delete_spin); + OsdDeletePendingItem *entry; + BLI_assert(BLI_thread_is_main()); + BLI_spin_lock(&delete_spin); + for (entry = delete_pool.first; entry != NULL; entry = entry->next) { + if (entry->osd_mesh != NULL) { + openSubdiv_deleteOsdGLMesh(entry->osd_mesh); + } + if (entry->vao != 0) { + glDeleteVertexArrays(1, &entry->vao); + } + } + BLI_freelistN(&delete_pool); + BLI_spin_unlock(&delete_spin); } void ccgSubSurf__sync_subdivUvs(CCGSubSurf *ss, bool subdiv_uvs) { - ss->osd_subdiv_uvs = subdiv_uvs; + ss->osd_subdiv_uvs = subdiv_uvs; } /* ** Public API ** */ void BKE_subsurf_osd_init(void) { - openSubdiv_init(); - BLI_spin_init(&delete_spin); + openSubdiv_init(); + BLI_spin_init(&delete_spin); } void BKE_subsurf_free_unused_buffers(void) { - ccgSubSurf__delete_pending(); + ccgSubSurf__delete_pending(); } void BKE_subsurf_osd_cleanup(void) { - openSubdiv_cleanup(); - ccgSubSurf__delete_pending(); - BLI_spin_end(&delete_spin); + openSubdiv_cleanup(); + ccgSubSurf__delete_pending(); + BLI_spin_end(&delete_spin); } -#endif /* WITH_OPENSUBDIV */ +#endif /* WITH_OPENSUBDIV */ -- cgit v1.2.3