13#include <opensubdiv/far/patchMap.h>
14#include <opensubdiv/far/patchTable.h>
15#include <opensubdiv/far/patchTableFactory.h>
16#include <opensubdiv/osd/mesh.h>
17#include <opensubdiv/osd/types.h>
18#include <opensubdiv/version.h>
28using OpenSubdiv::Far::PatchTable;
29using OpenSubdiv::Far::PatchTableFactory;
30using OpenSubdiv::Far::StencilTable;
31using OpenSubdiv::Far::StencilTableFactory;
32using OpenSubdiv::Far::StencilTableReal;
33using OpenSubdiv::Far::TopologyRefiner;
34using OpenSubdiv::Osd::PatchArray;
35using OpenSubdiv::Osd::PatchCoord;
76 if (old_num_elements >= num_elements) {
99 if (num_elements < kNumMaxElementsOnStack) {
126 const int num_patch_coords,
131 for (
int i = 0; i < num_patch_coords; ++i) {
132 const PatchTable::PatchHandle *handle = patch_map->
FindPatch(
133 patch_coords[i].ptex_face, patch_coords[i].u, patch_coords[i].
v);
142 : patch_map_(patch_map), implementation_(implementation)
157 const int start_vertex_index,
158 const int num_vertices)
165 const int start_vertex_index,
166 const int num_vertices)
173 const int start_vertex_index,
174 const int num_vertices)
181 const float *face_varying_data,
182 const int start_vertex_index,
183 const int num_vertices)
187 face_varying_channel, face_varying_data, start_vertex_index, num_vertices);
193 const int start_vertex_index,
194 const int num_vertices)
197 const unsigned char *current_buffer = (
unsigned char *)buffer;
199 for (
int i = 0; i < num_vertices; ++i) {
200 const int current_vertex_index = start_vertex_index + i;
202 reinterpret_cast<const float *
>(current_buffer), current_vertex_index, 1);
203 current_buffer += stride;
210 const int start_vertex_index,
211 const int num_vertices)
214 const unsigned char *current_buffer = (
unsigned char *)buffer;
216 for (
int i = 0; i < num_vertices; ++i) {
217 const int current_vertex_index = start_vertex_index + i;
219 reinterpret_cast<const float *
>(current_buffer), current_vertex_index, 1);
220 current_buffer += stride;
228 const int start_vertex_index,
229 const int num_vertices)
232 const unsigned char *current_buffer = (
unsigned char *)buffer;
234 for (
int i = 0; i < num_vertices; ++i) {
235 const int current_vertex_index = start_vertex_index + i;
237 reinterpret_cast<const float *
>(current_buffer),
238 current_vertex_index,
240 current_buffer += stride;
260 const PatchTable::PatchHandle *handle =
patch_map_->
FindPatch(ptex_face_index, face_u, face_v);
261 PatchCoord patch_coord(*handle, face_u, face_v);
262 if (dPdu !=
nullptr || dPdv !=
nullptr) {
279 const PatchTable::PatchHandle *handle =
patch_map_->
FindPatch(ptex_face_index, face_u, face_v);
280 PatchCoord patch_coord(*handle, face_u, face_v);
293 const PatchTable::PatchHandle *handle =
patch_map_->
FindPatch(ptex_face_index, face_u, face_v);
294 PatchCoord patch_coord(*handle, face_u, face_v);
299 const int ptex_face_index,
302 float face_varying[2])
308 const PatchTable::PatchHandle *handle =
patch_map_->
FindPatch(ptex_face_index, face_u, face_v);
309 PatchCoord patch_coord(*handle, face_u, face_v);
314 const int num_patch_coords,
321 if (dPdu !=
nullptr || dPdv !=
nullptr) {
323 patch_coords_array.
data(), num_patch_coords,
P, dPdu, dPdv);
335 int *patches_are_triangular)
346 patch_map_handles->
data<PatchTable::PatchHandle>();
347 memcpy(buffer_handles.
data(),
handles.data(),
sizeof(PatchTable::PatchHandle) *
handles.size());
430 if (refiner ==
nullptr) {
435 const bool has_varying_data =
false;
436 const int num_face_varying_channels = refiner->GetNumFVarChannels();
437 const bool has_face_varying_data = (num_face_varying_channels != 0);
441 const bool stencil_generate_intermediate_levels = is_adaptive;
442 const bool stencil_generate_offsets =
true;
443 const bool use_inf_sharp_patch =
true;
447 TopologyRefiner::AdaptiveOptions
options(level);
448 options.considerFVarChannels = has_face_varying_data;
449 options.useInfSharpPatch = use_inf_sharp_patch;
450 refiner->RefineAdaptive(
options);
453 TopologyRefiner::UniformOptions
options(level);
454 refiner->RefineUniform(
options);
459 auto delete_stencil_table = [](
const StencilTable *table) {
460 static_assert(std::is_base_of_v<StencilTableReal<float>, StencilTable>);
461 delete reinterpret_cast<const StencilTableReal<float> *
>(table);
468 StencilTableFactory::Options vertex_stencil_options;
469 vertex_stencil_options.generateOffsets = stencil_generate_offsets;
470 vertex_stencil_options.generateIntermediateLevels = stencil_generate_intermediate_levels;
471 const StencilTable *vertex_stencils = StencilTableFactory::Create(*refiner,
472 vertex_stencil_options);
477 const StencilTable *varying_stencils =
nullptr;
478 if (has_varying_data) {
479 StencilTableFactory::Options varying_stencil_options;
480 varying_stencil_options.generateOffsets = stencil_generate_offsets;
481 varying_stencil_options.generateIntermediateLevels = stencil_generate_intermediate_levels;
482 varying_stencil_options.interpolationMode = StencilTableFactory::INTERPOLATE_VARYING;
483 varying_stencils = StencilTableFactory::Create(*refiner, varying_stencil_options);
486 std::vector<const StencilTable *> all_face_varying_stencils;
487 all_face_varying_stencils.reserve(num_face_varying_channels);
488 for (
int face_varying_channel = 0; face_varying_channel < num_face_varying_channels;
489 ++face_varying_channel)
491 StencilTableFactory::Options face_varying_stencil_options;
492 face_varying_stencil_options.generateOffsets = stencil_generate_offsets;
493 face_varying_stencil_options.generateIntermediateLevels = stencil_generate_intermediate_levels;
494 face_varying_stencil_options.interpolationMode = StencilTableFactory::INTERPOLATE_FACE_VARYING;
495 face_varying_stencil_options.fvarChannel = face_varying_channel;
496 all_face_varying_stencils.push_back(
497 StencilTableFactory::Create(*refiner, face_varying_stencil_options));
500 PatchTableFactory::Options patch_options(level);
501 patch_options.SetEndCapType(PatchTableFactory::Options::ENDCAP_GREGORY_BASIS);
502 patch_options.useInfSharpPatch = use_inf_sharp_patch;
503 patch_options.generateFVarTables = has_face_varying_data;
504 patch_options.generateFVarLegacyLinearPatches =
false;
505 const PatchTable *patch_table = PatchTableFactory::Create(*refiner, patch_options);
508 const StencilTable *local_point_stencil_table = patch_table->GetLocalPointStencilTable();
509 if (local_point_stencil_table !=
nullptr) {
510 const StencilTable *table = StencilTableFactory::AppendLocalPointStencilTable(
511 *refiner, vertex_stencils, local_point_stencil_table);
512 delete_stencil_table(vertex_stencils);
513 vertex_stencils = table;
516 if (has_varying_data) {
517 const StencilTable *local_point_varying_stencil_table =
518 patch_table->GetLocalPointVaryingStencilTable();
519 if (local_point_varying_stencil_table !=
nullptr) {
520 const StencilTable *table = StencilTableFactory::AppendLocalPointStencilTable(
521 *refiner, varying_stencils, local_point_varying_stencil_table);
522 delete_stencil_table(varying_stencils);
523 varying_stencils = table;
526 for (
int face_varying_channel = 0; face_varying_channel < num_face_varying_channels;
527 ++face_varying_channel)
529 const StencilTable *table = StencilTableFactory::AppendLocalPointStencilTableFaceVarying(
531 all_face_varying_stencils[face_varying_channel],
532 patch_table->GetLocalPointFaceVaryingStencilTable(face_varying_channel),
533 face_varying_channel);
534 if (table !=
nullptr) {
535 delete_stencil_table(all_face_varying_stencils[face_varying_channel]);
536 all_face_varying_stencils[face_varying_channel] = table;
543 if (use_gpu_evaluator) {
545 if (evaluator_cache_descr) {
552 all_face_varying_stencils,
559 vertex_stencils, varying_stencils, all_face_varying_stencils, 2, patch_table);
565 evaluator->
type = evaluator_type;
571 delete_stencil_table(vertex_stencils);
572 delete_stencil_table(varying_stencils);
573 for (
const StencilTable *table : all_face_varying_stencils) {
574 delete_stencil_table(table);
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
ATTR_WARN_UNUSED_RESULT const BMVert * v
T * resize(const size_t newsize)
constexpr T * data() const
virtual GPUStorageBuf * create_face_varying_patch_array_buf(const int)
virtual void evalPatches(const PatchCoord *patch_coord, const int num_patch_coords, float *P)=0
virtual gpu::VertBuf * get_face_varying_source_buf(const int)
virtual GPUStorageBuf * create_patch_arrays_buf()
virtual int get_face_varying_source_offset(const int) const
virtual void evalPatchesVertexData(const PatchCoord *patch_coord, const int num_patch_coords, float *vertex_data)=0
virtual void evalPatchesWithDerivatives(const PatchCoord *patch_coord, const int num_patch_coords, float *P, float *dPdu, float *dPdv)=0
virtual GPUStorageBuf * get_face_varying_patch_param_buf(const int)
virtual bool hasVertexData() const
virtual void updateVertexData(const float *src, int start_vertex, int num_vertices)=0
virtual void updateData(const float *src, int start_vertex, int num_vertices)=0
virtual void evalPatchesVarying(const PatchCoord *patch_coord, const int num_patch_coords, float *varying)=0
virtual void updateSettings(const OpenSubdiv_EvaluatorSettings *settings)=0
virtual void updateFaceVaryingData(const int face_varying_channel, const float *src, int start_vertex, int num_vertices)=0
virtual gpu::VertBuf * get_source_buf()
virtual GPUStorageBuf * get_face_varying_patch_index_buf(const int)
virtual gpu::VertBuf * get_source_data_buf()
virtual GPUStorageBuf * get_patch_param_buf()
virtual void evalPatchesFaceVarying(const int face_varying_channel, const PatchCoord *patch_coord, const int num_patch_coords, float face_varying[2])=0
virtual GPUStorageBuf * get_patch_index_buf()
virtual void updateVaryingData(const float *src, int start_vertex, int num_vertices)=0
gpu::VertBuf * get_face_varying_source_buf(const int face_varying_channel)
void setVaryingData(const float *varying_data, const int start_vertex_index, const int num_vertices)
void evaluatePatchesLimit(const OpenSubdiv_PatchCoord *patch_coords, const int num_patch_coords, float *P, float *dPdu, float *dPdv)
void setSettings(const OpenSubdiv_EvaluatorSettings *settings)
GPUStorageBuf * get_patch_index_buf()
void evaluateVarying(const int ptex_face_index, float face_u, float face_v, float varying[3])
void evaluateLimit(const int ptex_face_index, float face_u, float face_v, float P[3], float dPdu[3], float dPdv[3])
void setFaceVaryingData(const int face_varying_channel, const float *varying_data, const int start_vertex_index, const int num_vertices)
GPUStorageBuf * create_face_varying_patch_array_buf(const int face_varying_channel)
GPUStorageBuf * create_patch_arrays_buf()
EvalOutput * implementation_
void evaluateVertexData(const int ptex_face_index, float face_u, float face_v, float data[])
GPUStorageBuf * get_face_varying_patch_param_buf(const int face_varying_channel)
GPUStorageBuf * get_face_varying_patch_index_buf(const int face_varying_channel)
GPUStorageBuf * get_patch_param_buf()
void evaluateFaceVarying(const int face_varying_channel, const int ptex_face_index, float face_u, float face_v, float face_varying[2])
int get_face_varying_source_offset(const int face_varying_channel) const
void setCoarsePositionsFromBuffer(const void *buffer, const int start_offset, const int stride, const int start_vertex_index, const int num_vertices)
gpu::VertBuf * get_source_data_buf()
gpu::VertBuf * get_source_buf()
void setVaryingDataFromBuffer(const void *buffer, const int start_offset, const int stride, const int start_vertex_index, const int num_vertices)
bool hasVertexData() const
EvalOutputAPI(EvalOutput *implementation, PatchMap *patch_map)
void setFaceVaryingDataFromBuffer(const int face_varying_channel, const void *buffer, const int start_offset, const int stride, const int start_vertex_index, const int num_vertices)
void setVertexData(const float *data, const int start_vertex_index, const int num_vertices)
void getPatchMap(blender::gpu::VertBuf *patch_map_handles, blender::gpu::VertBuf *patch_map_quadtree, int *min_patch_face, int *max_patch_face, int *max_depth, int *patches_are_triangular)
void setCoarsePositions(const float *positions, const int start_vertex_index, const int num_vertices)
An quadtree-based map connecting coarse faces to their sub-patches.
int getMinPatchFace() const
const std::vector< QuadNode > & nodes()
bool getPatchesAreTriangular() const
const std::vector< Handle > & getHandles()
Handle const * FindPatch(int patchFaceId, double u, double v) const
Returns a handle to the sub-patch of the face at the given (u,v). Note that the patch face ID corresp...
int getMaxPatchFace() const
T * allocate(int num_elements)
T stack_elements_[kNumMaxElementsOnStack]
void resize(int num_elements)
StackOrHeapArray(int size)
OpenSubdiv::Far::TopologyRefiner * topology_refiner
OpenSubdiv_TopologyRefinerSettings settings
OpenSubdiv::Osd::EvaluatorCacheT< GPUComputeEvaluator > EvaluatorCache
CCL_NAMESPACE_BEGIN struct Options options
OpenSubdiv_Evaluator * openSubdiv_createEvaluatorFromTopologyRefiner(blender::opensubdiv::TopologyRefinerImpl *topology_refiner, eOpenSubdivEvaluator evaluator_type, OpenSubdiv_EvaluatorCache *evaluator_cache_descr)
#define assert(assertion)
static void convertPatchCoordsToArray(const OpenSubdiv_PatchCoord *patch_coords, const int num_patch_coords, const PatchMap *patch_map, StackOrHeapPatchCoordArray *array)
@ OPENSUBDIV_EVALUATOR_GPU
OpenSubdiv_EvaluatorCacheImpl * impl
const OpenSubdiv::Far::PatchTable * patch_table
blender::opensubdiv::EvalOutputAPI * eval_output
const blender::opensubdiv::PatchMap * patch_map
eOpenSubdivEvaluator type