forked from bartvdbraak/blender
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.
This commit is contained in:
parent
3eab8156d3
commit
c37ca43720
@ -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"
|
||||
|
||||
|
@ -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_deleteEvaluatorDescr(
|
||||
OpenSubdiv_EvaluatorDescr *evaluator_descr);
|
||||
|
||||
void openSubdiv_setEvaluatorCoarsePositions(OpenSubdiv_EvaluatorDescr *evaluator_descr,
|
||||
float *positions,
|
||||
int start_vert,
|
||||
int num_vert);
|
||||
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_setEvaluatorVaryingData(OpenSubdiv_EvaluatorDescr *evaluator_descr,
|
||||
float *varying_data,
|
||||
int start_vert,
|
||||
int num_vert);
|
||||
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);
|
||||
|
@ -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,
|
||||
float *varying_data,
|
||||
int start_vert,
|
||||
int num_verts)
|
||||
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_vert, num_verts);
|
||||
/* TODO(sergey): Get rid of this ASAP. */
|
||||
evaluator_descr->eval_output->UpdateVaryingData(varying_data,
|
||||
start_vertex_index,
|
||||
num_vertices);
|
||||
}
|
||||
|
||||
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. */
|
||||
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();
|
||||
}
|
||||
|
||||
|
40
intern/opensubdiv/opensubdiv_gl_mesh.h
Normal file
40
intern/opensubdiv/opensubdiv_gl_mesh.h
Normal file
@ -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__ */
|
@ -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;
|
||||
|
@ -198,7 +198,7 @@ void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, DerivedMesh *dm)
|
||||
ss->osd_topology_refiner = NULL;
|
||||
}
|
||||
|
||||
/* Reste CPU side. */
|
||||
/* Reset CPU side. */
|
||||
if (ss->osd_evaluator != NULL) {
|
||||
openSubdiv_deleteEvaluatorDescr(ss->osd_evaluator);
|
||||
ss->osd_evaluator = NULL;
|
||||
@ -523,6 +523,7 @@ static void opensubdiv_updateEvaluatorCoarsePositions(CCGSubSurf *ss)
|
||||
(float *)positions,
|
||||
0,
|
||||
num_basis_verts);
|
||||
openSubdiv_refineEvaluator(ss->osd_evaluator);
|
||||
|
||||
MEM_freeN(positions);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user