diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2018-07-11 11:36:13 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2018-07-11 13:55:22 +0300 |
commit | c37ca437209f00ffe1b56cef2a5e8bbf390e669a (patch) | |
tree | 75f09f48e0c07cc18d5f87573344fcc65c80b9a8 /intern/opensubdiv | |
parent | 3eab8156d369f40de9d8c23672b1de28491ea920 (diff) |
OpenSubdiv: Changes in C-API
- Made OpenSubdiv_GLMesh private
Previously, it was still accessible via C-API from C++ code.
- Don't implicitly refine evaluator when updating coarse positions,
now there is an explicit call to do this.
Allows to first apply all changes to the coarse mesh and then
refine once.
- Added coarse positions update from a continuous buffer with given
starts offset and stride.
Allows to update coarse positions directly from MVert array.
- Refiner is no longer freed when CPU evaluator is created.
Allows to re-use refiner for multiple purposes.
Diffstat (limited to 'intern/opensubdiv')
-rw-r--r-- | intern/opensubdiv/opensubdiv_capi.cc | 1 | ||||
-rw-r--r-- | intern/opensubdiv/opensubdiv_capi.h | 72 | ||||
-rw-r--r-- | intern/opensubdiv/opensubdiv_evaluator_capi.cc | 140 | ||||
-rw-r--r-- | intern/opensubdiv/opensubdiv_gl_mesh.h | 40 | ||||
-rw-r--r-- | intern/opensubdiv/opensubdiv_gpu_capi.cc | 1 |
5 files changed, 160 insertions, 94 deletions
diff --git a/intern/opensubdiv/opensubdiv_capi.cc b/intern/opensubdiv/opensubdiv_capi.cc index bb865bc0e0f..638039f4f3e 100644 --- a/intern/opensubdiv/opensubdiv_capi.cc +++ b/intern/opensubdiv/opensubdiv_capi.cc @@ -70,6 +70,7 @@ #include <opensubdiv/far/stencilTable.h> #include <opensubdiv/far/primvarRefiner.h> +#include "opensubdiv_gl_mesh.h" #include "opensubdiv_intern.h" #include "opensubdiv_topology_refiner.h" diff --git a/intern/opensubdiv/opensubdiv_capi.h b/intern/opensubdiv/opensubdiv_capi.h index 2c3fcee7dbb..c29d08a77e1 100644 --- a/intern/opensubdiv/opensubdiv_capi.h +++ b/intern/opensubdiv/opensubdiv_capi.h @@ -32,22 +32,12 @@ extern "C" { // Types declaration. struct OpenSubdiv_GLMesh; +struct OpenSubdiv_GLMeshDescr; struct OpenSubdiv_GLMeshFVarData; struct OpenSubdiv_TopologyRefinerDescr; typedef struct OpenSubdiv_GLMesh OpenSubdiv_GLMesh; -#ifdef __cplusplus -struct OpenSubdiv_GLMeshDescr; - -typedef struct OpenSubdiv_GLMesh { - int evaluator_type; - OpenSubdiv_GLMeshDescr *descriptor; - OpenSubdiv_TopologyRefinerDescr *topology_refiner; - OpenSubdiv_GLMeshFVarData *fvar_data; -} OpenSubdiv_GLMesh; -#endif - // Keep this a bitmask os it's possible to pass available // evaluators to Blender. enum { @@ -86,11 +76,7 @@ void openSubdiv_osdGLMeshBindVertexBuffer(OpenSubdiv_GLMesh *gl_mesh); const struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_getGLMeshTopologyRefiner( OpenSubdiv_GLMesh *gl_mesh); -/* ** Initialize/Deinitialize global OpenGL drawing buffers/GLSL programs ** */ -bool openSubdiv_osdGLDisplayInit(void); -void openSubdiv_osdGLDisplayDeinit(void); - -/* ** Evaluator API ** */ +/* ============================= Evaluator API ============================== */ struct OpenSubdiv_EvaluatorDescr; typedef struct OpenSubdiv_EvaluatorDescr OpenSubdiv_EvaluatorDescr; @@ -100,17 +86,29 @@ OpenSubdiv_EvaluatorDescr *openSubdiv_createEvaluatorDescr( struct OpenSubdiv_TopologyRefinerDescr *topology_refiner, int subsurf_level); -void openSubdiv_deleteEvaluatorDescr(OpenSubdiv_EvaluatorDescr *evaluator_descr); - -void openSubdiv_setEvaluatorCoarsePositions(OpenSubdiv_EvaluatorDescr *evaluator_descr, - float *positions, - int start_vert, - int num_vert); - -void openSubdiv_setEvaluatorVaryingData(OpenSubdiv_EvaluatorDescr *evaluator_descr, - float *varying_data, - int start_vert, - int num_vert); +void openSubdiv_deleteEvaluatorDescr( + OpenSubdiv_EvaluatorDescr *evaluator_descr); + +void openSubdiv_setEvaluatorCoarsePositions( + OpenSubdiv_EvaluatorDescr *evaluator_descr, + const float *positions, + int start_vertex_index, + int num_vertices); +void openSubdiv_setEvaluatorVaryingData( + OpenSubdiv_EvaluatorDescr *evaluator_descr, + const float *varying_data, + int start_vertex_index, + int num_vertices); + +void openSubdiv_setEvaluatorCoarsePositionsFromBuffer( + OpenSubdiv_EvaluatorDescr *evaluator_descr, + const void *buffer, + int start_offset, + int stride, + int start_vertex_index, + int num_vertices); + +void openSubdiv_refineEvaluator(OpenSubdiv_EvaluatorDescr *evaluator_descr); void openSubdiv_evaluateLimit(OpenSubdiv_EvaluatorDescr *evaluator_descr, int osd_face_index, @@ -124,15 +122,18 @@ void openSubdiv_evaluateVarying(OpenSubdiv_EvaluatorDescr *evaluator_descr, float face_u, float face_v, float varying[3]); -/* ** Actual drawing ** */ +/* ============================== Mesh drawing =============================== */ + +/* Initialize/Deinitialize global OpenGL drawing buffers/GLSL programs. */ +bool openSubdiv_osdGLDisplayInit(void); +void openSubdiv_osdGLDisplayDeinit(void); /* Initialize all the invariants which stays the same for every single path, * for example lighting model stays untouched for the whole mesh. * * TODO(sergey): Some of the stuff could be initialized once for all meshes. */ -void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl, - int active_uv_index); +void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl, int active_uv_index); /* Draw specified patches. */ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh, @@ -140,12 +141,15 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh, int start_patch, int num_patches); -void openSubdiv_osdGLAllocFVar(struct OpenSubdiv_TopologyRefinerDescr *topology_refiner, - OpenSubdiv_GLMesh *gl_mesh, - const float *fvar_data); +void openSubdiv_osdGLAllocFVar( + struct OpenSubdiv_TopologyRefinerDescr *topology_refiner, + OpenSubdiv_GLMesh *gl_mesh, + const float *fvar_data); + void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh); -/* ** Utility functions ** */ +/* =========================== Utility functions ============================ */ + int openSubdiv_getAvailableEvaluators(void); void openSubdiv_init(void); void openSubdiv_cleanup(void); diff --git a/intern/opensubdiv/opensubdiv_evaluator_capi.cc b/intern/opensubdiv/opensubdiv_evaluator_capi.cc index 049c0aad3bf..fb5313b8501 100644 --- a/intern/opensubdiv/opensubdiv_evaluator_capi.cc +++ b/intern/opensubdiv/opensubdiv_evaluator_capi.cc @@ -118,7 +118,7 @@ protected: * is small enough and better to be allocated in stack rather * than in heap. * - * TODO(sergey): Check if bare arrays could be used by CPU evalautor. + * TODO(sergey): Check if bare arrays could be used by CPU evaluator. */ template <int element_size, int num_verts> class StackAllocatedBuffer { @@ -142,7 +142,7 @@ protected: /* Volatile evaluator which can be used from threads. * - * TODO(sergey): Make it possible to evaluate coordinates in chuncks. + * TODO(sergey): Make it possible to evaluate coordinates in chunks. */ template<typename SRC_VERTEX_BUFFER, typename EVAL_VERTEX_BUFFER, @@ -347,85 +347,80 @@ OpenSubdiv_EvaluatorDescr *openSubdiv_createEvaluatorDescr( /* Happens on bad topology. */ return NULL; } - - const StencilTable *vertex_stencils = NULL; - const StencilTable *varying_stencils = NULL; - int num_total_verts = 0; - /* Apply uniform refinement to the mesh so that we can use the * limit evaluation API features. */ TopologyRefiner::UniformOptions options(subsurf_level); refiner->RefineUniform(options); - /* Generate stencil table to update the bi-cubic patches control * vertices after they have been re-posed (both for vertex & varying * interpolation). */ - StencilTableFactory::Options soptions; - soptions.generateOffsets = true; - soptions.generateIntermediateLevels = false; - - vertex_stencils = StencilTableFactory::Create(*refiner, soptions); - - soptions.interpolationMode = StencilTableFactory::INTERPOLATE_VARYING; - varying_stencils = StencilTableFactory::Create(*refiner, soptions); - + StencilTableFactory::Options vertex_stencil_options; + vertex_stencil_options.generateOffsets = true; + vertex_stencil_options.generateIntermediateLevels = false; + const StencilTable *vertex_stencils = + StencilTableFactory::Create(*refiner, vertex_stencil_options); + StencilTableFactory::Options varying_stencil_options; + varying_stencil_options.generateOffsets = true; + varying_stencil_options.generateIntermediateLevels = false; + varying_stencil_options.interpolationMode = + StencilTableFactory::INTERPOLATE_VARYING; + const StencilTable *varying_stencils = + StencilTableFactory::Create(*refiner, varying_stencil_options); /* Generate bi-cubic patch table for the limit surface. */ PatchTableFactory::Options poptions; poptions.SetEndCapType(PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS); - - const PatchTable *patch_table = PatchTableFactory::Create(*refiner, poptions); - + const PatchTable *patch_table = + PatchTableFactory::Create(*refiner, poptions); /* Append local points stencils. */ - /* TODO(sergey): Do we really need to worry about local points stencils? */ - if (const StencilTable *local_point_stencil_table = - patch_table->GetLocalPointStencilTable()) - { + const StencilTable *local_point_stencil_table = + patch_table->GetLocalPointStencilTable(); + if (local_point_stencil_table != NULL) { const StencilTable *table = - StencilTableFactory::AppendLocalPointStencilTable(*refiner, - vertex_stencils, - local_point_stencil_table); + StencilTableFactory::AppendLocalPointStencilTable( + *refiner, + vertex_stencils, + local_point_stencil_table); delete vertex_stencils; vertex_stencils = table; } - if (const StencilTable *local_point_varying_stencil_table = - patch_table->GetLocalPointVaryingStencilTable()) - { + const StencilTable *local_point_varying_stencil_table = + patch_table->GetLocalPointVaryingStencilTable(); + if (local_point_varying_stencil_table != NULL) { const StencilTable *table = - StencilTableFactory::AppendLocalPointStencilTable(*refiner, - varying_stencils, - local_point_varying_stencil_table); + StencilTableFactory::AppendLocalPointStencilTable( + *refiner, + varying_stencils, + local_point_varying_stencil_table); delete varying_stencils; varying_stencils = table; } - /* Total number of vertices = coarse verts + refined verts + gregory basis verts. */ - num_total_verts = vertex_stencils->GetNumControlVertices() + - vertex_stencils->GetNumStencils(); - + /* Total number of vertices = coarse verts + refined verts + gregory + * basis verts. + */ + const int num_total_verts = vertex_stencils->GetNumControlVertices() + + vertex_stencils->GetNumStencils(); const int num_coarse_verts = refiner->GetLevel(0).GetNumVertices(); - + /* Create OpenSubdiv's CPU side evaluator. */ CpuEvalOutput *eval_output = new CpuEvalOutput(vertex_stencils, varying_stencils, num_coarse_verts, num_total_verts, patch_table); - OpenSubdiv::Far::PatchMap *patch_map = new PatchMap(*patch_table); - + /* Wrap everything we need into an object which we control from our + * side. + */ OpenSubdiv_EvaluatorDescr *evaluator_descr; evaluator_descr = OBJECT_GUARDED_NEW(OpenSubdiv_EvaluatorDescr); evaluator_descr->eval_output = eval_output; evaluator_descr->patch_map = patch_map; evaluator_descr->patch_table = patch_table; - - /* TOOD(sergey): Look into whether w've got duplicated stencils arrays. */ + /* TOOD(sergey): Look into whether we've got duplicated stencils arrays. */ delete varying_stencils; delete vertex_stencils; - - delete refiner; - return evaluator_descr; } @@ -437,27 +432,52 @@ void openSubdiv_deleteEvaluatorDescr(OpenSubdiv_EvaluatorDescr *evaluator_descr) OBJECT_GUARDED_DELETE(evaluator_descr, OpenSubdiv_EvaluatorDescr); } -void openSubdiv_setEvaluatorCoarsePositions(OpenSubdiv_EvaluatorDescr *evaluator_descr, - float *positions, - int start_vert, - int num_verts) +void openSubdiv_setEvaluatorCoarsePositions( + OpenSubdiv_EvaluatorDescr *evaluator_descr, + const float *positions, + int start_vertex_index, + int num_vertices) { /* TODO(sergey): Add sanity check on indices. */ - evaluator_descr->eval_output->UpdateData(positions, start_vert, num_verts); - /* TODO(sergey): Consider moving this to a separate call, - * so we can updatwe coordinates in chunks. - */ - evaluator_descr->eval_output->Refine(); + evaluator_descr->eval_output->UpdateData(positions, + start_vertex_index, + num_vertices); +} + +void openSubdiv_setEvaluatorVaryingData( + OpenSubdiv_EvaluatorDescr *evaluator_descr, + const float *varying_data, + int start_vertex_index, + int num_vertices) +{ + /* TODO(sergey): Add sanity check on indices. */ + evaluator_descr->eval_output->UpdateVaryingData(varying_data, + start_vertex_index, + num_vertices); } -void openSubdiv_setEvaluatorVaryingData(OpenSubdiv_EvaluatorDescr *evaluator_descr, - float *varying_data, - int start_vert, - int num_verts) +void openSubdiv_setEvaluatorCoarsePositionsFromBuffer( + OpenSubdiv_EvaluatorDescr *evaluator_descr, + const void *buffer, + int start_offset, + int stride, + int start_vertex_index, + int num_vertices) { + const unsigned char *current_buffer = (unsigned char *)buffer; + current_buffer += start_offset; /* TODO(sergey): Add sanity check on indices. */ - evaluator_descr->eval_output->UpdateVaryingData(varying_data, start_vert, num_verts); - /* TODO(sergey): Get rid of this ASAP. */ + for (int i = 0; i < num_vertices; ++i) { + const int current_vertex_index = start_vertex_index + i; + evaluator_descr->eval_output->UpdateData((float *)current_buffer, + current_vertex_index, + 1); + current_buffer += stride; + } +} + +void openSubdiv_refineEvaluator(OpenSubdiv_EvaluatorDescr *evaluator_descr) +{ evaluator_descr->eval_output->Refine(); } diff --git a/intern/opensubdiv/opensubdiv_gl_mesh.h b/intern/opensubdiv/opensubdiv_gl_mesh.h new file mode 100644 index 00000000000..1e99fc5bce4 --- /dev/null +++ b/intern/opensubdiv/opensubdiv_gl_mesh.h @@ -0,0 +1,40 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2018 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Sergey Sharybin. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __OPENSUBDIV_GL_MESH_H__ +#define __OPENSUBDIV_GL_MESH_H__ + +struct OpenSubdiv_GLMeshDescr; +struct OpenSubdiv_TopologyRefinerDescr; +struct OpenSubdiv_GLMeshFVarData; + +typedef struct OpenSubdiv_GLMesh { + int evaluator_type; + OpenSubdiv_GLMeshDescr *descriptor; + OpenSubdiv_TopologyRefinerDescr *topology_refiner; + OpenSubdiv_GLMeshFVarData *fvar_data; +} OpenSubdiv_GLMesh; + +#endif /* __OPENSUBDIV_GL_MESH_H__ */ diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc index 7d8085c1ff5..d28b48ddd18 100644 --- a/intern/opensubdiv/opensubdiv_gpu_capi.cc +++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc @@ -45,6 +45,7 @@ #include "MEM_guardedalloc.h" #include "opensubdiv_capi.h" +#include "opensubdiv_gl_mesh.h" #include "opensubdiv_topology_refiner.h" using OpenSubdiv::Osd::GLMeshInterface; |