Merge branch 'blender-v3.2-release'
This commit is contained in:
commit
b712dbe5de
@ -46,6 +46,8 @@ class EvalOutputAPI::EvalOutput {
|
|||||||
|
|
||||||
virtual void updateVaryingData(const float *src, int start_vertex, int num_vertices) = 0;
|
virtual void updateVaryingData(const float *src, int start_vertex, int num_vertices) = 0;
|
||||||
|
|
||||||
|
virtual void updateVertexData(const float *src, int start_vertex, int num_vertices) = 0;
|
||||||
|
|
||||||
virtual void updateFaceVaryingData(const int face_varying_channel,
|
virtual void updateFaceVaryingData(const int face_varying_channel,
|
||||||
const float *src,
|
const float *src,
|
||||||
int start_vertex,
|
int start_vertex,
|
||||||
@ -70,6 +72,11 @@ class EvalOutputAPI::EvalOutput {
|
|||||||
const int num_patch_coords,
|
const int num_patch_coords,
|
||||||
float *varying) = 0;
|
float *varying) = 0;
|
||||||
|
|
||||||
|
// NOTE: vertex_data must point to a memory of at least float*num_vertex_data.
|
||||||
|
virtual void evalPatchesVertexData(const PatchCoord *patch_coord,
|
||||||
|
const int num_patch_coords,
|
||||||
|
float *vertex_data) = 0;
|
||||||
|
|
||||||
virtual void evalPatchesFaceVarying(const int face_varying_channel,
|
virtual void evalPatchesFaceVarying(const int face_varying_channel,
|
||||||
const PatchCoord *patch_coord,
|
const PatchCoord *patch_coord,
|
||||||
const int num_patch_coords,
|
const int num_patch_coords,
|
||||||
@ -331,11 +338,13 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
|
|||||||
const StencilTable *varying_stencils,
|
const StencilTable *varying_stencils,
|
||||||
const vector<const StencilTable *> &all_face_varying_stencils,
|
const vector<const StencilTable *> &all_face_varying_stencils,
|
||||||
const int face_varying_width,
|
const int face_varying_width,
|
||||||
|
const int vertex_data_width,
|
||||||
const PatchTable *patch_table,
|
const PatchTable *patch_table,
|
||||||
EvaluatorCache *evaluator_cache = NULL,
|
EvaluatorCache *evaluator_cache = NULL,
|
||||||
DEVICE_CONTEXT *device_context = NULL)
|
DEVICE_CONTEXT *device_context = NULL)
|
||||||
: src_desc_(0, 3, 3),
|
: src_desc_(0, 3, 3),
|
||||||
src_varying_desc_(0, 3, 3),
|
src_varying_desc_(0, 3, 3),
|
||||||
|
src_vertex_data_desc_(0, vertex_data_width, vertex_data_width),
|
||||||
face_varying_width_(face_varying_width),
|
face_varying_width_(face_varying_width),
|
||||||
evaluator_cache_(evaluator_cache),
|
evaluator_cache_(evaluator_cache),
|
||||||
device_context_(device_context)
|
device_context_(device_context)
|
||||||
@ -352,6 +361,16 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
|
|||||||
device_context_);
|
device_context_);
|
||||||
varying_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(varying_stencils,
|
varying_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(varying_stencils,
|
||||||
device_context_);
|
device_context_);
|
||||||
|
|
||||||
|
// Optionally allocate additional data to be subdivided like vertex coordinates.
|
||||||
|
if (vertex_data_width > 0) {
|
||||||
|
src_vertex_data_ = SRC_VERTEX_BUFFER::Create(
|
||||||
|
vertex_data_width, num_total_vertices, device_context_);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
src_vertex_data_ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Create evaluators for every face varying channel.
|
// Create evaluators for every face varying channel.
|
||||||
face_varying_evaluators_.reserve(all_face_varying_stencils.size());
|
face_varying_evaluators_.reserve(all_face_varying_stencils.size());
|
||||||
int face_varying_channel = 0;
|
int face_varying_channel = 0;
|
||||||
@ -370,6 +389,7 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
|
|||||||
{
|
{
|
||||||
delete src_data_;
|
delete src_data_;
|
||||||
delete src_varying_data_;
|
delete src_varying_data_;
|
||||||
|
delete src_vertex_data_;
|
||||||
delete patch_table_;
|
delete patch_table_;
|
||||||
delete vertex_stencils_;
|
delete vertex_stencils_;
|
||||||
delete varying_stencils_;
|
delete varying_stencils_;
|
||||||
@ -390,6 +410,11 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
|
|||||||
src_varying_data_->UpdateData(src, start_vertex, num_vertices, device_context_);
|
src_varying_data_->UpdateData(src, start_vertex, num_vertices, device_context_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateVertexData(const float *src, int start_vertex, int num_vertices) override
|
||||||
|
{
|
||||||
|
src_vertex_data_->UpdateData(src, start_vertex, num_vertices, device_context_);
|
||||||
|
}
|
||||||
|
|
||||||
void updateFaceVaryingData(const int face_varying_channel,
|
void updateFaceVaryingData(const int face_varying_channel,
|
||||||
const float *src,
|
const float *src,
|
||||||
int start_vertex,
|
int start_vertex,
|
||||||
@ -426,6 +451,22 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
|
|||||||
vertex_stencils_,
|
vertex_stencils_,
|
||||||
eval_instance,
|
eval_instance,
|
||||||
device_context_);
|
device_context_);
|
||||||
|
|
||||||
|
// Evaluate smoothly interpolated vertex data.
|
||||||
|
if (src_vertex_data_) {
|
||||||
|
BufferDescriptor dst_vertex_data_desc = src_vertex_data_desc_;
|
||||||
|
dst_vertex_data_desc.offset += num_coarse_vertices_ * src_vertex_data_desc_.stride;
|
||||||
|
const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
|
||||||
|
evaluator_cache_, src_vertex_data_desc_, dst_vertex_data_desc, device_context_);
|
||||||
|
EVALUATOR::EvalStencils(src_vertex_data_,
|
||||||
|
src_vertex_data_desc_,
|
||||||
|
src_vertex_data_,
|
||||||
|
dst_vertex_data_desc,
|
||||||
|
vertex_stencils_,
|
||||||
|
eval_instance,
|
||||||
|
device_context_);
|
||||||
|
}
|
||||||
|
|
||||||
// Evaluate varying data.
|
// Evaluate varying data.
|
||||||
if (hasVaryingData()) {
|
if (hasVaryingData()) {
|
||||||
BufferDescriptor dst_varying_desc = src_varying_desc_;
|
BufferDescriptor dst_varying_desc = src_varying_desc_;
|
||||||
@ -521,6 +562,27 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
|
|||||||
device_context_);
|
device_context_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: data must point to a memory of at least float*num_vertex_data.
|
||||||
|
void evalPatchesVertexData(const PatchCoord *patch_coord,
|
||||||
|
const int num_patch_coords,
|
||||||
|
float *data) override
|
||||||
|
{
|
||||||
|
RawDataWrapperBuffer<float> vertex_data(data);
|
||||||
|
BufferDescriptor vertex_desc(0, src_vertex_data_desc_.length, src_vertex_data_desc_.length);
|
||||||
|
ConstPatchCoordWrapperBuffer patch_coord_buffer(patch_coord, num_patch_coords);
|
||||||
|
const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
|
||||||
|
evaluator_cache_, src_vertex_data_desc_, vertex_desc, device_context_);
|
||||||
|
EVALUATOR::EvalPatches(src_vertex_data_,
|
||||||
|
src_vertex_data_desc_,
|
||||||
|
&vertex_data,
|
||||||
|
vertex_desc,
|
||||||
|
patch_coord_buffer.GetNumVertices(),
|
||||||
|
&patch_coord_buffer,
|
||||||
|
patch_table_,
|
||||||
|
eval_instance,
|
||||||
|
device_context_);
|
||||||
|
}
|
||||||
|
|
||||||
void evalPatchesFaceVarying(const int face_varying_channel,
|
void evalPatchesFaceVarying(const int face_varying_channel,
|
||||||
const PatchCoord *patch_coord,
|
const PatchCoord *patch_coord,
|
||||||
const int num_patch_coords,
|
const int num_patch_coords,
|
||||||
@ -560,9 +622,11 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
|
|||||||
private:
|
private:
|
||||||
SRC_VERTEX_BUFFER *src_data_;
|
SRC_VERTEX_BUFFER *src_data_;
|
||||||
SRC_VERTEX_BUFFER *src_varying_data_;
|
SRC_VERTEX_BUFFER *src_varying_data_;
|
||||||
|
SRC_VERTEX_BUFFER *src_vertex_data_;
|
||||||
PATCH_TABLE *patch_table_;
|
PATCH_TABLE *patch_table_;
|
||||||
BufferDescriptor src_desc_;
|
BufferDescriptor src_desc_;
|
||||||
BufferDescriptor src_varying_desc_;
|
BufferDescriptor src_varying_desc_;
|
||||||
|
BufferDescriptor src_vertex_data_desc_;
|
||||||
|
|
||||||
int num_coarse_vertices_;
|
int num_coarse_vertices_;
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ class CpuEvalOutput : public VolatileEvalOutput<CpuVertexBuffer,
|
|||||||
const StencilTable *varying_stencils,
|
const StencilTable *varying_stencils,
|
||||||
const vector<const StencilTable *> &all_face_varying_stencils,
|
const vector<const StencilTable *> &all_face_varying_stencils,
|
||||||
const int face_varying_width,
|
const int face_varying_width,
|
||||||
|
const int vertex_data_width,
|
||||||
const PatchTable *patch_table,
|
const PatchTable *patch_table,
|
||||||
EvaluatorCache *evaluator_cache = NULL)
|
EvaluatorCache *evaluator_cache = NULL)
|
||||||
: VolatileEvalOutput<CpuVertexBuffer,
|
: VolatileEvalOutput<CpuVertexBuffer,
|
||||||
@ -54,6 +55,7 @@ class CpuEvalOutput : public VolatileEvalOutput<CpuVertexBuffer,
|
|||||||
varying_stencils,
|
varying_stencils,
|
||||||
all_face_varying_stencils,
|
all_face_varying_stencils,
|
||||||
face_varying_width,
|
face_varying_width,
|
||||||
|
vertex_data_width,
|
||||||
patch_table,
|
patch_table,
|
||||||
evaluator_cache)
|
evaluator_cache)
|
||||||
{
|
{
|
||||||
|
@ -45,6 +45,7 @@ GpuEvalOutput::GpuEvalOutput(const StencilTable *vertex_stencils,
|
|||||||
const StencilTable *varying_stencils,
|
const StencilTable *varying_stencils,
|
||||||
const vector<const StencilTable *> &all_face_varying_stencils,
|
const vector<const StencilTable *> &all_face_varying_stencils,
|
||||||
const int face_varying_width,
|
const int face_varying_width,
|
||||||
|
const int vertex_data_width,
|
||||||
const PatchTable *patch_table,
|
const PatchTable *patch_table,
|
||||||
VolatileEvalOutput::EvaluatorCache *evaluator_cache)
|
VolatileEvalOutput::EvaluatorCache *evaluator_cache)
|
||||||
: VolatileEvalOutput<GLVertexBuffer,
|
: VolatileEvalOutput<GLVertexBuffer,
|
||||||
@ -55,6 +56,7 @@ GpuEvalOutput::GpuEvalOutput(const StencilTable *vertex_stencils,
|
|||||||
varying_stencils,
|
varying_stencils,
|
||||||
all_face_varying_stencils,
|
all_face_varying_stencils,
|
||||||
face_varying_width,
|
face_varying_width,
|
||||||
|
vertex_data_width,
|
||||||
patch_table,
|
patch_table,
|
||||||
evaluator_cache)
|
evaluator_cache)
|
||||||
{
|
{
|
||||||
|
@ -40,6 +40,7 @@ class GpuEvalOutput : public VolatileEvalOutput<GLVertexBuffer,
|
|||||||
const StencilTable *varying_stencils,
|
const StencilTable *varying_stencils,
|
||||||
const vector<const StencilTable *> &all_face_varying_stencils,
|
const vector<const StencilTable *> &all_face_varying_stencils,
|
||||||
const int face_varying_width,
|
const int face_varying_width,
|
||||||
|
const int vertex_data_width,
|
||||||
const PatchTable *patch_table,
|
const PatchTable *patch_table,
|
||||||
EvaluatorCache *evaluator_cache = NULL);
|
EvaluatorCache *evaluator_cache = NULL);
|
||||||
|
|
||||||
|
@ -36,6 +36,14 @@ void setCoarsePositions(OpenSubdiv_Evaluator *evaluator,
|
|||||||
evaluator->impl->eval_output->setCoarsePositions(positions, start_vertex_index, num_vertices);
|
evaluator->impl->eval_output->setCoarsePositions(positions, start_vertex_index, num_vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setVertexData(OpenSubdiv_Evaluator *evaluator,
|
||||||
|
const float *vertex_data,
|
||||||
|
const int start_vertex_index,
|
||||||
|
const int num_vertices)
|
||||||
|
{
|
||||||
|
evaluator->impl->eval_output->setVertexData(vertex_data, start_vertex_index, num_vertices);
|
||||||
|
}
|
||||||
|
|
||||||
void setVaryingData(OpenSubdiv_Evaluator *evaluator,
|
void setVaryingData(OpenSubdiv_Evaluator *evaluator,
|
||||||
const float *varying_data,
|
const float *varying_data,
|
||||||
const int start_vertex_index,
|
const int start_vertex_index,
|
||||||
@ -115,6 +123,15 @@ void evaluatePatchesLimit(OpenSubdiv_Evaluator *evaluator,
|
|||||||
patch_coords, num_patch_coords, P, dPdu, dPdv);
|
patch_coords, num_patch_coords, P, dPdu, dPdv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void evaluateVertexData(OpenSubdiv_Evaluator *evaluator,
|
||||||
|
const int ptex_face_index,
|
||||||
|
float face_u,
|
||||||
|
float face_v,
|
||||||
|
float vertex_data[3])
|
||||||
|
{
|
||||||
|
evaluator->impl->eval_output->evaluateVertexData(ptex_face_index, face_u, face_v, vertex_data);
|
||||||
|
}
|
||||||
|
|
||||||
void evaluateVarying(OpenSubdiv_Evaluator *evaluator,
|
void evaluateVarying(OpenSubdiv_Evaluator *evaluator,
|
||||||
const int ptex_face_index,
|
const int ptex_face_index,
|
||||||
float face_u,
|
float face_u,
|
||||||
@ -206,6 +223,7 @@ void wrapFVarSrcBuffer(struct OpenSubdiv_Evaluator *evaluator,
|
|||||||
void assignFunctionPointers(OpenSubdiv_Evaluator *evaluator)
|
void assignFunctionPointers(OpenSubdiv_Evaluator *evaluator)
|
||||||
{
|
{
|
||||||
evaluator->setCoarsePositions = setCoarsePositions;
|
evaluator->setCoarsePositions = setCoarsePositions;
|
||||||
|
evaluator->setVertexData = setVertexData;
|
||||||
evaluator->setVaryingData = setVaryingData;
|
evaluator->setVaryingData = setVaryingData;
|
||||||
evaluator->setFaceVaryingData = setFaceVaryingData;
|
evaluator->setFaceVaryingData = setFaceVaryingData;
|
||||||
|
|
||||||
@ -217,6 +235,7 @@ void assignFunctionPointers(OpenSubdiv_Evaluator *evaluator)
|
|||||||
|
|
||||||
evaluator->evaluateLimit = evaluateLimit;
|
evaluator->evaluateLimit = evaluateLimit;
|
||||||
evaluator->evaluateVarying = evaluateVarying;
|
evaluator->evaluateVarying = evaluateVarying;
|
||||||
|
evaluator->evaluateVertexData = evaluateVertexData;
|
||||||
evaluator->evaluateFaceVarying = evaluateFaceVarying;
|
evaluator->evaluateFaceVarying = evaluateFaceVarying;
|
||||||
|
|
||||||
evaluator->evaluatePatchesLimit = evaluatePatchesLimit;
|
evaluator->evaluatePatchesLimit = evaluatePatchesLimit;
|
||||||
@ -239,12 +258,16 @@ void assignFunctionPointers(OpenSubdiv_Evaluator *evaluator)
|
|||||||
OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
|
OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
|
||||||
OpenSubdiv_TopologyRefiner *topology_refiner,
|
OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||||
eOpenSubdivEvaluator evaluator_type,
|
eOpenSubdivEvaluator evaluator_type,
|
||||||
OpenSubdiv_EvaluatorCache *evaluator_cache)
|
OpenSubdiv_EvaluatorCache *evaluator_cache,
|
||||||
|
const OpenSubdiv_EvaluatorSettings *settings)
|
||||||
{
|
{
|
||||||
OpenSubdiv_Evaluator *evaluator = MEM_new<OpenSubdiv_Evaluator>(__func__);
|
OpenSubdiv_Evaluator *evaluator = MEM_new<OpenSubdiv_Evaluator>(__func__);
|
||||||
assignFunctionPointers(evaluator);
|
assignFunctionPointers(evaluator);
|
||||||
evaluator->impl = openSubdiv_createEvaluatorInternal(
|
evaluator->impl = openSubdiv_createEvaluatorInternal(topology_refiner,
|
||||||
topology_refiner, evaluator_type, evaluator_cache ? evaluator_cache->impl : nullptr);
|
evaluator_type,
|
||||||
|
evaluator_cache ? evaluator_cache->impl :
|
||||||
|
nullptr,
|
||||||
|
settings);
|
||||||
evaluator->type = evaluator->impl ? evaluator_type : static_cast<eOpenSubdivEvaluator>(0);
|
evaluator->type = evaluator->impl ? evaluator_type : static_cast<eOpenSubdivEvaluator>(0);
|
||||||
return evaluator;
|
return evaluator;
|
||||||
}
|
}
|
||||||
|
@ -182,6 +182,14 @@ void EvalOutputAPI::setVaryingData(const float *varying_data,
|
|||||||
implementation_->updateVaryingData(varying_data, start_vertex_index, num_vertices);
|
implementation_->updateVaryingData(varying_data, start_vertex_index, num_vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EvalOutputAPI::setVertexData(const float *vertex_data,
|
||||||
|
const int start_vertex_index,
|
||||||
|
const int num_vertices)
|
||||||
|
{
|
||||||
|
// TODO(sergey): Add sanity check on indices.
|
||||||
|
implementation_->updateVertexData(vertex_data, start_vertex_index, num_vertices);
|
||||||
|
}
|
||||||
|
|
||||||
void EvalOutputAPI::setFaceVaryingData(const int face_varying_channel,
|
void EvalOutputAPI::setFaceVaryingData(const int face_varying_channel,
|
||||||
const float *face_varying_data,
|
const float *face_varying_data,
|
||||||
const int start_vertex_index,
|
const int start_vertex_index,
|
||||||
@ -286,6 +294,20 @@ void EvalOutputAPI::evaluateVarying(const int ptex_face_index,
|
|||||||
implementation_->evalPatchesVarying(&patch_coord, 1, varying);
|
implementation_->evalPatchesVarying(&patch_coord, 1, varying);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EvalOutputAPI::evaluateVertexData(const int ptex_face_index,
|
||||||
|
float face_u,
|
||||||
|
float face_v,
|
||||||
|
float vertex_data[])
|
||||||
|
{
|
||||||
|
assert(face_u >= 0.0f);
|
||||||
|
assert(face_u <= 1.0f);
|
||||||
|
assert(face_v >= 0.0f);
|
||||||
|
assert(face_v <= 1.0f);
|
||||||
|
const PatchTable::PatchHandle *handle = patch_map_->FindPatch(ptex_face_index, face_u, face_v);
|
||||||
|
PatchCoord patch_coord(*handle, face_u, face_v);
|
||||||
|
implementation_->evalPatchesVertexData(&patch_coord, 1, vertex_data);
|
||||||
|
}
|
||||||
|
|
||||||
void EvalOutputAPI::evaluateFaceVarying(const int face_varying_channel,
|
void EvalOutputAPI::evaluateFaceVarying(const int face_varying_channel,
|
||||||
const int ptex_face_index,
|
const int ptex_face_index,
|
||||||
float face_u,
|
float face_u,
|
||||||
@ -403,7 +425,8 @@ OpenSubdiv_EvaluatorImpl::~OpenSubdiv_EvaluatorImpl()
|
|||||||
OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
|
OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
|
||||||
OpenSubdiv_TopologyRefiner *topology_refiner,
|
OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||||
eOpenSubdivEvaluator evaluator_type,
|
eOpenSubdivEvaluator evaluator_type,
|
||||||
OpenSubdiv_EvaluatorCacheImpl *evaluator_cache_descr)
|
OpenSubdiv_EvaluatorCacheImpl *evaluator_cache_descr,
|
||||||
|
const OpenSubdiv_EvaluatorSettings *settings)
|
||||||
{
|
{
|
||||||
// Only CPU and GLCompute are implemented at the moment.
|
// Only CPU and GLCompute are implemented at the moment.
|
||||||
if (evaluator_type != OPENSUBDIV_EVALUATOR_CPU &&
|
if (evaluator_type != OPENSUBDIV_EVALUATOR_CPU &&
|
||||||
@ -422,6 +445,7 @@ OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
|
|||||||
const bool has_face_varying_data = (num_face_varying_channels != 0);
|
const bool has_face_varying_data = (num_face_varying_channels != 0);
|
||||||
const int level = topology_refiner->getSubdivisionLevel(topology_refiner);
|
const int level = topology_refiner->getSubdivisionLevel(topology_refiner);
|
||||||
const bool is_adaptive = topology_refiner->getIsAdaptive(topology_refiner);
|
const bool is_adaptive = topology_refiner->getIsAdaptive(topology_refiner);
|
||||||
|
const int vertex_data_width = settings->num_vertex_data;
|
||||||
// Common settings for stencils and patches.
|
// Common settings for stencils and patches.
|
||||||
const bool stencil_generate_intermediate_levels = is_adaptive;
|
const bool stencil_generate_intermediate_levels = is_adaptive;
|
||||||
const bool stencil_generate_offsets = true;
|
const bool stencil_generate_offsets = true;
|
||||||
@ -526,12 +550,17 @@ OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
|
|||||||
varying_stencils,
|
varying_stencils,
|
||||||
all_face_varying_stencils,
|
all_face_varying_stencils,
|
||||||
2,
|
2,
|
||||||
|
vertex_data_width,
|
||||||
patch_table,
|
patch_table,
|
||||||
evaluator_cache);
|
evaluator_cache);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
eval_output = new blender::opensubdiv::CpuEvalOutput(
|
eval_output = new blender::opensubdiv::CpuEvalOutput(vertex_stencils,
|
||||||
vertex_stencils, varying_stencils, all_face_varying_stencils, 2, patch_table);
|
varying_stencils,
|
||||||
|
all_face_varying_stencils,
|
||||||
|
2,
|
||||||
|
vertex_data_width,
|
||||||
|
patch_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
blender::opensubdiv::PatchMap *patch_map = new blender::opensubdiv::PatchMap(*patch_table);
|
blender::opensubdiv::PatchMap *patch_map = new blender::opensubdiv::PatchMap(*patch_table);
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
struct OpenSubdiv_Buffer;
|
struct OpenSubdiv_Buffer;
|
||||||
struct OpenSubdiv_EvaluatorCacheImpl;
|
struct OpenSubdiv_EvaluatorCacheImpl;
|
||||||
|
struct OpenSubdiv_EvaluatorSettings;
|
||||||
struct OpenSubdiv_PatchCoord;
|
struct OpenSubdiv_PatchCoord;
|
||||||
struct OpenSubdiv_TopologyRefiner;
|
struct OpenSubdiv_TopologyRefiner;
|
||||||
|
|
||||||
@ -60,6 +61,8 @@ class EvalOutputAPI {
|
|||||||
void setCoarsePositions(const float *positions,
|
void setCoarsePositions(const float *positions,
|
||||||
const int start_vertex_index,
|
const int start_vertex_index,
|
||||||
const int num_vertices);
|
const int num_vertices);
|
||||||
|
// Set vertex data from a continuous array of data.
|
||||||
|
void setVertexData(const float *data, const int start_vertex_index, const int num_vertices);
|
||||||
// Set varying data from a continuous array of data.
|
// Set varying data from a continuous array of data.
|
||||||
void setVaryingData(const float *varying_data,
|
void setVaryingData(const float *varying_data,
|
||||||
const int start_vertex_index,
|
const int start_vertex_index,
|
||||||
@ -114,6 +117,9 @@ class EvalOutputAPI {
|
|||||||
float dPdu[3],
|
float dPdu[3],
|
||||||
float dPdv[3]);
|
float dPdv[3]);
|
||||||
|
|
||||||
|
// Evaluate varying data at a given bilinear coordinate of given ptex face.
|
||||||
|
void evaluateVertexData(const int ptes_face_index, float face_u, float face_v, float data[]);
|
||||||
|
|
||||||
// Evaluate varying data at a given bilinear coordinate of given ptex face.
|
// Evaluate varying data at a given bilinear coordinate of given ptex face.
|
||||||
void evaluateVarying(const int ptes_face_index, float face_u, float face_v, float varying[3]);
|
void evaluateVarying(const int ptes_face_index, float face_u, float face_v, float varying[3]);
|
||||||
|
|
||||||
@ -198,7 +204,8 @@ struct OpenSubdiv_EvaluatorImpl {
|
|||||||
OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
|
OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
|
||||||
struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||||
eOpenSubdivEvaluator evaluator_type,
|
eOpenSubdivEvaluator evaluator_type,
|
||||||
OpenSubdiv_EvaluatorCacheImpl *evaluator_cache_descr);
|
OpenSubdiv_EvaluatorCacheImpl *evaluator_cache_descr,
|
||||||
|
const OpenSubdiv_EvaluatorSettings *settings);
|
||||||
|
|
||||||
void openSubdiv_deleteEvaluatorInternal(OpenSubdiv_EvaluatorImpl *evaluator);
|
void openSubdiv_deleteEvaluatorInternal(OpenSubdiv_EvaluatorImpl *evaluator);
|
||||||
|
|
||||||
|
@ -69,6 +69,11 @@ typedef struct OpenSubdiv_Evaluator {
|
|||||||
const float *positions,
|
const float *positions,
|
||||||
const int start_vertex_index,
|
const int start_vertex_index,
|
||||||
const int num_vertices);
|
const int num_vertices);
|
||||||
|
// Set vertex data from a continuous array of coordinates.
|
||||||
|
void (*setVertexData)(struct OpenSubdiv_Evaluator *evaluator,
|
||||||
|
const float *data,
|
||||||
|
const int start_vertex_index,
|
||||||
|
const int num_vertices);
|
||||||
// Set varying data from a continuous array of data.
|
// Set varying data from a continuous array of data.
|
||||||
void (*setVaryingData)(struct OpenSubdiv_Evaluator *evaluator,
|
void (*setVaryingData)(struct OpenSubdiv_Evaluator *evaluator,
|
||||||
const float *varying_data,
|
const float *varying_data,
|
||||||
@ -129,6 +134,13 @@ typedef struct OpenSubdiv_Evaluator {
|
|||||||
float dPdu[3],
|
float dPdu[3],
|
||||||
float dPdv[3]);
|
float dPdv[3]);
|
||||||
|
|
||||||
|
// Evaluate vertex data at a given bilinear coordinate of given ptex face.
|
||||||
|
void (*evaluateVertexData)(struct OpenSubdiv_Evaluator *evaluator,
|
||||||
|
const int ptex_face_index,
|
||||||
|
float face_u,
|
||||||
|
float face_v,
|
||||||
|
float data[]);
|
||||||
|
|
||||||
// Evaluate varying data at a given bilinear coordinate of given ptex face.
|
// Evaluate varying data at a given bilinear coordinate of given ptex face.
|
||||||
void (*evaluateVarying)(struct OpenSubdiv_Evaluator *evaluator,
|
void (*evaluateVarying)(struct OpenSubdiv_Evaluator *evaluator,
|
||||||
const int ptex_face_index,
|
const int ptex_face_index,
|
||||||
@ -215,10 +227,16 @@ typedef struct OpenSubdiv_EvaluatorCache {
|
|||||||
struct OpenSubdiv_EvaluatorCacheImpl *impl;
|
struct OpenSubdiv_EvaluatorCacheImpl *impl;
|
||||||
} OpenSubdiv_EvaluatorCache;
|
} OpenSubdiv_EvaluatorCache;
|
||||||
|
|
||||||
|
typedef struct OpenSubdiv_EvaluatorSettings {
|
||||||
|
// Number of smoothly interpolated vertex data channels.
|
||||||
|
int num_vertex_data;
|
||||||
|
} OpenSubdiv_EvaluatorSettings;
|
||||||
|
|
||||||
OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
|
OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
|
||||||
struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||||
eOpenSubdivEvaluator evaluator_type,
|
eOpenSubdivEvaluator evaluator_type,
|
||||||
OpenSubdiv_EvaluatorCache *evaluator_cache);
|
OpenSubdiv_EvaluatorCache *evaluator_cache,
|
||||||
|
const OpenSubdiv_EvaluatorSettings *settings);
|
||||||
|
|
||||||
void openSubdiv_deleteEvaluator(OpenSubdiv_Evaluator *evaluator);
|
void openSubdiv_deleteEvaluator(OpenSubdiv_Evaluator *evaluator);
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
|
OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
|
||||||
struct OpenSubdiv_TopologyRefiner * /*topology_refiner*/,
|
struct OpenSubdiv_TopologyRefiner * /*topology_refiner*/,
|
||||||
eOpenSubdivEvaluator /*evaluator_type*/,
|
eOpenSubdivEvaluator /*evaluator_type*/,
|
||||||
OpenSubdiv_EvaluatorCache * /*evaluator_cache*/)
|
OpenSubdiv_EvaluatorCache * /*evaluator_cache*/,
|
||||||
|
const OpenSubdiv_EvaluatorSettings * /*settings*/)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ template<typename T> T mix3(const float3 &weights, const T &v0, const T &v1, con
|
|||||||
template<>
|
template<>
|
||||||
inline int8_t mix3(const float3 &weights, const int8_t &v0, const int8_t &v1, const int8_t &v2)
|
inline int8_t mix3(const float3 &weights, const int8_t &v0, const int8_t &v1, const int8_t &v2)
|
||||||
{
|
{
|
||||||
return static_cast<int8_t>(weights.x * v0 + weights.y * v1 + weights.z * v2);
|
return static_cast<int8_t>(std::round(weights.x * v0 + weights.y * v1 + weights.z * v2));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v1, const bool &v2)
|
template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v1, const bool &v2)
|
||||||
@ -66,7 +66,7 @@ template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v
|
|||||||
|
|
||||||
template<> inline int mix3(const float3 &weights, const int &v0, const int &v1, const int &v2)
|
template<> inline int mix3(const float3 &weights, const int &v0, const int &v1, const int &v2)
|
||||||
{
|
{
|
||||||
return static_cast<int>(weights.x * v0 + weights.y * v1 + weights.z * v2);
|
return static_cast<int>(std::round(weights.x * v0 + weights.y * v1 + weights.z * v2));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
@ -131,12 +131,12 @@ template<> inline bool mix2(const float factor, const bool &a, const bool &b)
|
|||||||
|
|
||||||
template<> inline int8_t mix2(const float factor, const int8_t &a, const int8_t &b)
|
template<> inline int8_t mix2(const float factor, const int8_t &a, const int8_t &b)
|
||||||
{
|
{
|
||||||
return static_cast<int8_t>((1.0f - factor) * a + factor * b);
|
return static_cast<int8_t>(std::round((1.0f - factor) * a + factor * b));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline int mix2(const float factor, const int &a, const int &b)
|
template<> inline int mix2(const float factor, const int &a, const int &b)
|
||||||
{
|
{
|
||||||
return static_cast<int>((1.0f - factor) * a + factor * b);
|
return static_cast<int>(std::round((1.0f - factor) * a + factor * b));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline float mix2(const float factor, const float &a, const float &b)
|
template<> inline float mix2(const float factor, const float &a, const float &b)
|
||||||
@ -356,7 +356,7 @@ template<> struct DefaultMixerStruct<ColorGeometry4b> {
|
|||||||
template<> struct DefaultMixerStruct<int> {
|
template<> struct DefaultMixerStruct<int> {
|
||||||
static int double_to_int(const double &value)
|
static int double_to_int(const double &value)
|
||||||
{
|
{
|
||||||
return static_cast<int>(value);
|
return static_cast<int>(std::round(value));
|
||||||
}
|
}
|
||||||
/* Store interpolated ints in a double temporarily, so that weights are handled correctly. It
|
/* Store interpolated ints in a double temporarily, so that weights are handled correctly. It
|
||||||
* uses double instead of float so that it is accurate for all 32 bit integers. */
|
* uses double instead of float so that it is accurate for all 32 bit integers. */
|
||||||
@ -375,7 +375,7 @@ template<> struct DefaultMixerStruct<bool> {
|
|||||||
template<> struct DefaultMixerStruct<int8_t> {
|
template<> struct DefaultMixerStruct<int8_t> {
|
||||||
static int8_t float_to_int8_t(const float &value)
|
static int8_t float_to_int8_t(const float &value)
|
||||||
{
|
{
|
||||||
return static_cast<int8_t>(value);
|
return static_cast<int8_t>(std::round(value));
|
||||||
}
|
}
|
||||||
/* Store interpolated 8 bit integers in a float temporarily to increase accuracy. */
|
/* Store interpolated 8 bit integers in a float temporarily to increase accuracy. */
|
||||||
using type = SimpleMixerWithAccumulationType<int8_t, float, float_to_int8_t>;
|
using type = SimpleMixerWithAccumulationType<int8_t, float, float_to_int8_t>;
|
||||||
|
@ -15,6 +15,7 @@ extern "C" {
|
|||||||
|
|
||||||
struct Mesh;
|
struct Mesh;
|
||||||
struct OpenSubdiv_EvaluatorCache;
|
struct OpenSubdiv_EvaluatorCache;
|
||||||
|
struct OpenSubdiv_EvaluatorSettings;
|
||||||
struct Subdiv;
|
struct Subdiv;
|
||||||
|
|
||||||
typedef enum eSubdivEvaluatorType {
|
typedef enum eSubdivEvaluatorType {
|
||||||
@ -25,7 +26,8 @@ typedef enum eSubdivEvaluatorType {
|
|||||||
/* Returns true if evaluator is ready for use. */
|
/* Returns true if evaluator is ready for use. */
|
||||||
bool BKE_subdiv_eval_begin(struct Subdiv *subdiv,
|
bool BKE_subdiv_eval_begin(struct Subdiv *subdiv,
|
||||||
eSubdivEvaluatorType evaluator_type,
|
eSubdivEvaluatorType evaluator_type,
|
||||||
struct OpenSubdiv_EvaluatorCache *evaluator_cache);
|
struct OpenSubdiv_EvaluatorCache *evaluator_cache,
|
||||||
|
const struct OpenSubdiv_EvaluatorSettings *settings);
|
||||||
|
|
||||||
/* coarse_vertex_cos is an optional argument which allows to override coordinates of the coarse
|
/* coarse_vertex_cos is an optional argument which allows to override coordinates of the coarse
|
||||||
* mesh. */
|
* mesh. */
|
||||||
@ -60,6 +62,13 @@ void BKE_subdiv_eval_limit_point_and_derivatives(struct Subdiv *subdiv,
|
|||||||
void BKE_subdiv_eval_limit_point_and_normal(
|
void BKE_subdiv_eval_limit_point_and_normal(
|
||||||
struct Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3], float r_N[3]);
|
struct Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3], float r_N[3]);
|
||||||
|
|
||||||
|
/* Evaluate smoothly interpolated vertex data (such as orco). */
|
||||||
|
void BKE_subdiv_eval_vertex_data(struct Subdiv *subdiv,
|
||||||
|
const int ptex_face_index,
|
||||||
|
const float u,
|
||||||
|
const float v,
|
||||||
|
float r_vertex_data[]);
|
||||||
|
|
||||||
/* Evaluate face-varying layer (such as UV). */
|
/* Evaluate face-varying layer (such as UV). */
|
||||||
void BKE_subdiv_eval_face_varying(struct Subdiv *subdiv,
|
void BKE_subdiv_eval_face_varying(struct Subdiv *subdiv,
|
||||||
int face_varying_channel,
|
int face_varying_channel,
|
||||||
|
@ -1165,6 +1165,10 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||||||
BKE_id_free(nullptr, mesh_orco_cloth);
|
BKE_id_free(nullptr, mesh_orco_cloth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove temporary data layer only needed for modifier evaluation.
|
||||||
|
* Save some memory, and ensure GPU subdivision does not need to deal with this. */
|
||||||
|
CustomData_free_layers(&mesh_final->vdata, CD_CLOTH_ORCO, mesh_final->totvert);
|
||||||
|
|
||||||
/* Compute normals. */
|
/* Compute normals. */
|
||||||
if (is_own_mesh) {
|
if (is_own_mesh) {
|
||||||
mesh_calc_modifier_final_normals(mesh_input, &final_datamask, sculpt_dyntopo, mesh_final);
|
mesh_calc_modifier_final_normals(mesh_input, &final_datamask, sculpt_dyntopo, mesh_final);
|
||||||
|
@ -1073,7 +1073,9 @@ static void reshape_subdiv_create(MultiresReshapeSmoothContext *reshape_smooth_c
|
|||||||
converter_init(reshape_smooth_context, &converter);
|
converter_init(reshape_smooth_context, &converter);
|
||||||
|
|
||||||
Subdiv *reshape_subdiv = BKE_subdiv_new_from_converter(settings, &converter);
|
Subdiv *reshape_subdiv = BKE_subdiv_new_from_converter(settings, &converter);
|
||||||
BKE_subdiv_eval_begin(reshape_subdiv, SUBDIV_EVALUATOR_TYPE_CPU, NULL);
|
|
||||||
|
OpenSubdiv_EvaluatorSettings evaluator_settings = {0};
|
||||||
|
BKE_subdiv_eval_begin(reshape_subdiv, SUBDIV_EVALUATOR_TYPE_CPU, NULL, &evaluator_settings);
|
||||||
|
|
||||||
reshape_smooth_context->reshape_subdiv = reshape_subdiv;
|
reshape_smooth_context->reshape_subdiv = reshape_subdiv;
|
||||||
|
|
||||||
|
@ -670,6 +670,7 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
|
|||||||
|
|
||||||
ntree->progress = nullptr;
|
ntree->progress = nullptr;
|
||||||
ntree->execdata = nullptr;
|
ntree->execdata = nullptr;
|
||||||
|
ntree->runtime_flag = 0;
|
||||||
|
|
||||||
ntree->field_inferencing_interface = nullptr;
|
ntree->field_inferencing_interface = nullptr;
|
||||||
BKE_ntree_update_tag_missing_runtime_data(ntree);
|
BKE_ntree_update_tag_missing_runtime_data(ntree);
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "DNA_node_types.h"
|
#include "DNA_node_types.h"
|
||||||
|
|
||||||
#include "BKE_anim_data.h"
|
#include "BKE_anim_data.h"
|
||||||
|
#include "BKE_image.h"
|
||||||
#include "BKE_main.h"
|
#include "BKE_main.h"
|
||||||
#include "BKE_node.h"
|
#include "BKE_node.h"
|
||||||
#include "BKE_node_tree_update.h"
|
#include "BKE_node_tree_update.h"
|
||||||
@ -984,6 +985,7 @@ class NodeTreeMainUpdater {
|
|||||||
this->remove_unused_previews_when_necessary(ntree);
|
this->remove_unused_previews_when_necessary(ntree);
|
||||||
|
|
||||||
this->ensure_tree_ref(ntree, tree_ref);
|
this->ensure_tree_ref(ntree, tree_ref);
|
||||||
|
this->update_has_image_animation(*tree_ref);
|
||||||
if (ntree.type == NTREE_GEOMETRY) {
|
if (ntree.type == NTREE_GEOMETRY) {
|
||||||
if (node_field_inferencing::update_field_inferencing(*tree_ref)) {
|
if (node_field_inferencing::update_field_inferencing(*tree_ref)) {
|
||||||
result.interface_changed = true;
|
result.interface_changed = true;
|
||||||
@ -1254,6 +1256,35 @@ class NodeTreeMainUpdater {
|
|||||||
BKE_node_preview_remove_unused(&ntree);
|
BKE_node_preview_remove_unused(&ntree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void update_has_image_animation(const NodeTreeRef &tree_ref)
|
||||||
|
{
|
||||||
|
bNodeTree &ntree = *tree_ref.btree();
|
||||||
|
ntree.runtime_flag &= ~NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION;
|
||||||
|
if (ntree.type != NTREE_SHADER) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if a used node group has an animated image. */
|
||||||
|
for (const NodeRef *group_node : tree_ref.nodes_by_type("NodeGroup")) {
|
||||||
|
const bNodeTree *group = reinterpret_cast<bNodeTree *>(group_node->bnode()->id);
|
||||||
|
if (group != nullptr) {
|
||||||
|
if (group->runtime_flag & NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION) {
|
||||||
|
ntree.runtime_flag |= NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Check if the tree itself has an animated image. */
|
||||||
|
for (const StringRefNull idname : {"ShaderNodeTexImage", "ShaderNodeTexEnvironment"})
|
||||||
|
for (const NodeRef *node : tree_ref.nodes_by_type(idname)) {
|
||||||
|
Image *image = reinterpret_cast<Image *>(node->bnode()->id);
|
||||||
|
if (image != nullptr && BKE_image_is_animated(image)) {
|
||||||
|
ntree.runtime_flag |= NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void update_node_levels(bNodeTree &ntree)
|
void update_node_levels(bNodeTree &ntree)
|
||||||
{
|
{
|
||||||
ntreeUpdateNodeLevels(&ntree);
|
ntreeUpdateNodeLevels(&ntree);
|
||||||
|
@ -48,7 +48,8 @@ static eOpenSubdivEvaluator opensubdiv_evalutor_from_subdiv_evaluator_type(
|
|||||||
|
|
||||||
bool BKE_subdiv_eval_begin(Subdiv *subdiv,
|
bool BKE_subdiv_eval_begin(Subdiv *subdiv,
|
||||||
eSubdivEvaluatorType evaluator_type,
|
eSubdivEvaluatorType evaluator_type,
|
||||||
OpenSubdiv_EvaluatorCache *evaluator_cache)
|
OpenSubdiv_EvaluatorCache *evaluator_cache,
|
||||||
|
const OpenSubdiv_EvaluatorSettings *settings)
|
||||||
{
|
{
|
||||||
BKE_subdiv_stats_reset(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
|
BKE_subdiv_stats_reset(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
|
||||||
if (subdiv->topology_refiner == NULL) {
|
if (subdiv->topology_refiner == NULL) {
|
||||||
@ -61,7 +62,7 @@ bool BKE_subdiv_eval_begin(Subdiv *subdiv,
|
|||||||
opensubdiv_evalutor_from_subdiv_evaluator_type(evaluator_type);
|
opensubdiv_evalutor_from_subdiv_evaluator_type(evaluator_type);
|
||||||
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
|
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
|
||||||
subdiv->evaluator = openSubdiv_createEvaluatorFromTopologyRefiner(
|
subdiv->evaluator = openSubdiv_createEvaluatorFromTopologyRefiner(
|
||||||
subdiv->topology_refiner, opensubdiv_evaluator_type, evaluator_cache);
|
subdiv->topology_refiner, opensubdiv_evaluator_type, evaluator_cache, settings);
|
||||||
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
|
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
|
||||||
if (subdiv->evaluator == NULL) {
|
if (subdiv->evaluator == NULL) {
|
||||||
return false;
|
return false;
|
||||||
@ -183,13 +184,52 @@ static void set_face_varying_data_from_uv(Subdiv *subdiv,
|
|||||||
MEM_freeN(buffer);
|
MEM_freeN(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_vertex_data_from_orco(Subdiv *subdiv, const Mesh *mesh)
|
||||||
|
{
|
||||||
|
const float(*orco)[3] = CustomData_get_layer(&mesh->vdata, CD_ORCO);
|
||||||
|
const float(*cloth_orco)[3] = CustomData_get_layer(&mesh->vdata, CD_CLOTH_ORCO);
|
||||||
|
|
||||||
|
if (orco || cloth_orco) {
|
||||||
|
OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
|
||||||
|
OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
|
||||||
|
const int num_verts = topology_refiner->getNumVertices(topology_refiner);
|
||||||
|
|
||||||
|
if (orco && cloth_orco) {
|
||||||
|
/* Set one by one if have both. */
|
||||||
|
for (int i = 0; i < num_verts; i++) {
|
||||||
|
float data[6];
|
||||||
|
copy_v3_v3(data, orco[i]);
|
||||||
|
copy_v3_v3(data + 3, cloth_orco[i]);
|
||||||
|
evaluator->setVertexData(evaluator, data, i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Faster single call if we have either. */
|
||||||
|
if (orco) {
|
||||||
|
evaluator->setVertexData(evaluator, orco[0], 0, num_verts);
|
||||||
|
}
|
||||||
|
else if (cloth_orco) {
|
||||||
|
evaluator->setVertexData(evaluator, cloth_orco[0], 0, num_verts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_mesh_evaluator_settings(OpenSubdiv_EvaluatorSettings *settings, const Mesh *mesh)
|
||||||
|
{
|
||||||
|
settings->num_vertex_data = (CustomData_has_layer(&mesh->vdata, CD_ORCO) ? 3 : 0) +
|
||||||
|
(CustomData_has_layer(&mesh->vdata, CD_CLOTH_ORCO) ? 3 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
bool BKE_subdiv_eval_begin_from_mesh(Subdiv *subdiv,
|
bool BKE_subdiv_eval_begin_from_mesh(Subdiv *subdiv,
|
||||||
const Mesh *mesh,
|
const Mesh *mesh,
|
||||||
const float (*coarse_vertex_cos)[3],
|
const float (*coarse_vertex_cos)[3],
|
||||||
eSubdivEvaluatorType evaluator_type,
|
eSubdivEvaluatorType evaluator_type,
|
||||||
OpenSubdiv_EvaluatorCache *evaluator_cache)
|
OpenSubdiv_EvaluatorCache *evaluator_cache)
|
||||||
{
|
{
|
||||||
if (!BKE_subdiv_eval_begin(subdiv, evaluator_type, evaluator_cache)) {
|
OpenSubdiv_EvaluatorSettings settings = {0};
|
||||||
|
get_mesh_evaluator_settings(&settings, mesh);
|
||||||
|
if (!BKE_subdiv_eval_begin(subdiv, evaluator_type, evaluator_cache, &settings)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return BKE_subdiv_eval_refine_from_mesh(subdiv, mesh, coarse_vertex_cos);
|
return BKE_subdiv_eval_refine_from_mesh(subdiv, mesh, coarse_vertex_cos);
|
||||||
@ -212,6 +252,8 @@ bool BKE_subdiv_eval_refine_from_mesh(Subdiv *subdiv,
|
|||||||
const MLoopUV *mloopuv = CustomData_get_layer_n(&mesh->ldata, CD_MLOOPUV, layer_index);
|
const MLoopUV *mloopuv = CustomData_get_layer_n(&mesh->ldata, CD_MLOOPUV, layer_index);
|
||||||
set_face_varying_data_from_uv(subdiv, mesh, mloopuv, layer_index);
|
set_face_varying_data_from_uv(subdiv, mesh, mloopuv, layer_index);
|
||||||
}
|
}
|
||||||
|
/* Set vertex data to orco. */
|
||||||
|
set_vertex_data_from_orco(subdiv, mesh);
|
||||||
/* Update evaluator to the new coarse geometry. */
|
/* Update evaluator to the new coarse geometry. */
|
||||||
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_EVALUATOR_REFINE);
|
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_EVALUATOR_REFINE);
|
||||||
subdiv->evaluator->refine(subdiv->evaluator);
|
subdiv->evaluator->refine(subdiv->evaluator);
|
||||||
@ -287,6 +329,12 @@ void BKE_subdiv_eval_limit_point_and_normal(Subdiv *subdiv,
|
|||||||
normalize_v3(r_N);
|
normalize_v3(r_N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BKE_subdiv_eval_vertex_data(
|
||||||
|
Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_vertex_data[])
|
||||||
|
{
|
||||||
|
subdiv->evaluator->evaluateVertexData(subdiv->evaluator, ptex_face_index, u, v, r_vertex_data);
|
||||||
|
}
|
||||||
|
|
||||||
void BKE_subdiv_eval_face_varying(Subdiv *subdiv,
|
void BKE_subdiv_eval_face_varying(Subdiv *subdiv,
|
||||||
const int face_varying_channel,
|
const int face_varying_channel,
|
||||||
const int ptex_face_index,
|
const int ptex_face_index,
|
||||||
|
@ -44,6 +44,9 @@ typedef struct SubdivMeshContext {
|
|||||||
/* UV layers interpolation. */
|
/* UV layers interpolation. */
|
||||||
int num_uv_layers;
|
int num_uv_layers;
|
||||||
MLoopUV *uv_layers[MAX_MTFACE];
|
MLoopUV *uv_layers[MAX_MTFACE];
|
||||||
|
/* Orco interpolation. */
|
||||||
|
float (*orco)[3];
|
||||||
|
float (*cloth_orco)[3];
|
||||||
/* Per-subdivided vertex counter of averaged values. */
|
/* Per-subdivided vertex counter of averaged values. */
|
||||||
int *accumulated_counters;
|
int *accumulated_counters;
|
||||||
bool have_displacement;
|
bool have_displacement;
|
||||||
@ -69,6 +72,9 @@ static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx)
|
|||||||
ctx->poly_origindex = CustomData_get_layer(&subdiv_mesh->pdata, CD_ORIGINDEX);
|
ctx->poly_origindex = CustomData_get_layer(&subdiv_mesh->pdata, CD_ORIGINDEX);
|
||||||
/* UV layers interpolation. */
|
/* UV layers interpolation. */
|
||||||
subdiv_mesh_ctx_cache_uv_layers(ctx);
|
subdiv_mesh_ctx_cache_uv_layers(ctx);
|
||||||
|
/* Orco interpolation. */
|
||||||
|
ctx->orco = CustomData_get_layer(&subdiv_mesh->vdata, CD_ORCO);
|
||||||
|
ctx->cloth_orco = CustomData_get_layer(&subdiv_mesh->vdata, CD_CLOTH_ORCO);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void subdiv_mesh_prepare_accumulator(SubdivMeshContext *ctx, int num_vertices)
|
static void subdiv_mesh_prepare_accumulator(SubdivMeshContext *ctx, int num_vertices)
|
||||||
@ -416,6 +422,34 @@ static void subdiv_mesh_tls_free(void *tls_v)
|
|||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Evaluation helper functions
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
static void subdiv_vertex_orco_evaluate(const SubdivMeshContext *ctx,
|
||||||
|
const int ptex_face_index,
|
||||||
|
const float u,
|
||||||
|
const float v,
|
||||||
|
const int subdiv_vertex_index)
|
||||||
|
{
|
||||||
|
if (ctx->orco || ctx->cloth_orco) {
|
||||||
|
float vertex_data[6];
|
||||||
|
BKE_subdiv_eval_vertex_data(ctx->subdiv, ptex_face_index, u, v, vertex_data);
|
||||||
|
|
||||||
|
if (ctx->orco) {
|
||||||
|
copy_v3_v3(ctx->orco[subdiv_vertex_index], vertex_data);
|
||||||
|
if (ctx->cloth_orco) {
|
||||||
|
copy_v3_v3(ctx->orco[subdiv_vertex_index], vertex_data + 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ctx->cloth_orco) {
|
||||||
|
copy_v3_v3(ctx->orco[subdiv_vertex_index], vertex_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/** \name Accumulation helpers
|
/** \name Accumulation helpers
|
||||||
* \{ */
|
* \{ */
|
||||||
@ -530,6 +564,8 @@ static void evaluate_vertex_and_apply_displacement_copy(const SubdivMeshContext
|
|||||||
BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
|
BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
|
||||||
/* Apply displacement. */
|
/* Apply displacement. */
|
||||||
add_v3_v3(subdiv_vert->co, D);
|
add_v3_v3(subdiv_vert->co, D);
|
||||||
|
/* Evaluate undeformed texture coordinate. */
|
||||||
|
subdiv_vertex_orco_evaluate(ctx, ptex_face_index, u, v, subdiv_vertex_index);
|
||||||
/* Remove facedot flag. This can happen if there is more than one subsurf modifier. */
|
/* Remove facedot flag. This can happen if there is more than one subsurf modifier. */
|
||||||
BLI_BITMAP_DISABLE(ctx->subdiv_mesh->runtime.subsurf_face_dot_tags, subdiv_vertex_index);
|
BLI_BITMAP_DISABLE(ctx->subdiv_mesh->runtime.subsurf_face_dot_tags, subdiv_vertex_index);
|
||||||
}
|
}
|
||||||
@ -556,6 +592,8 @@ static void evaluate_vertex_and_apply_displacement_interpolate(
|
|||||||
BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
|
BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
|
||||||
/* Apply displacement. */
|
/* Apply displacement. */
|
||||||
add_v3_v3(subdiv_vert->co, D);
|
add_v3_v3(subdiv_vert->co, D);
|
||||||
|
/* Evaluate undeformed texture coordinate. */
|
||||||
|
subdiv_vertex_orco_evaluate(ctx, ptex_face_index, u, v, subdiv_vertex_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void subdiv_mesh_vertex_displacement_every_corner_or_edge(
|
static void subdiv_mesh_vertex_displacement_every_corner_or_edge(
|
||||||
@ -723,6 +761,7 @@ static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context
|
|||||||
subdiv_vertex_data_interpolate(ctx, subdiv_vert, &tls->vertex_interpolation, u, v);
|
subdiv_vertex_data_interpolate(ctx, subdiv_vert, &tls->vertex_interpolation, u, v);
|
||||||
BKE_subdiv_eval_final_point(subdiv, ptex_face_index, u, v, subdiv_vert->co);
|
BKE_subdiv_eval_final_point(subdiv, ptex_face_index, u, v, subdiv_vert->co);
|
||||||
subdiv_mesh_tag_center_vertex(coarse_poly, subdiv_vertex_index, u, v, subdiv_mesh);
|
subdiv_mesh_tag_center_vertex(coarse_poly, subdiv_vertex_index, u, v, subdiv_mesh);
|
||||||
|
subdiv_vertex_orco_evaluate(ctx, ptex_face_index, u, v, subdiv_vertex_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
@ -108,12 +108,20 @@ template<typename T,
|
|||||||
BLI_ENABLE_IF((is_math_float_type<FactorT>))>
|
BLI_ENABLE_IF((is_math_float_type<FactorT>))>
|
||||||
inline T interpolate(const T &a, const T &b, const FactorT &t)
|
inline T interpolate(const T &a, const T &b, const FactorT &t)
|
||||||
{
|
{
|
||||||
return a * (1 - t) + b * t;
|
auto result = a * (1 - t) + b * t;
|
||||||
|
if constexpr (std::is_integral_v<T> && std::is_floating_point_v<FactorT>) {
|
||||||
|
result = std::round(result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> inline T midpoint(const T &a, const T &b)
|
template<typename T> inline T midpoint(const T &a, const T &b)
|
||||||
{
|
{
|
||||||
return (a + b) * T(0.5);
|
auto result = (a + b) * T(0.5);
|
||||||
|
if constexpr (std::is_integral_v<T>) {
|
||||||
|
result = std::round(result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::math
|
} // namespace blender::math
|
||||||
|
@ -1078,14 +1078,17 @@ void DepsgraphNodeBuilder::build_animdata_nlastrip_targets(ListBase *strips)
|
|||||||
|
|
||||||
void DepsgraphNodeBuilder::build_animation_images(ID *id)
|
void DepsgraphNodeBuilder::build_animation_images(ID *id)
|
||||||
{
|
{
|
||||||
/* GPU materials might use an animated image. However, these materials have no been built yet. We
|
/* GPU materials might use an animated image. However, these materials have no been built yet so
|
||||||
* could scan the entire node tree recursively to check if any texture node has a video. That is
|
* we have to check if they might be created during evaluation. */
|
||||||
* quite expensive. For now just always add this operation node, because it is very fast. */
|
bool has_image_animation = false;
|
||||||
/* TODO: Add a more precise check when it is cheaper to iterate over all image nodes in a node
|
if (ELEM(GS(id->name), ID_MA, ID_WO)) {
|
||||||
* tree. */
|
bNodeTree *ntree = *BKE_ntree_ptr_from_id(id);
|
||||||
const bool can_have_gpu_material = ELEM(GS(id->name), ID_MA, ID_WO);
|
if (ntree != nullptr && ntree->runtime_flag & NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION) {
|
||||||
|
has_image_animation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (can_have_gpu_material || BKE_image_user_id_has_animation(id)) {
|
if (has_image_animation || BKE_image_user_id_has_animation(id)) {
|
||||||
ID *id_cow = get_cow_id(id);
|
ID *id_cow = get_cow_id(id);
|
||||||
add_operation_node(
|
add_operation_node(
|
||||||
id,
|
id,
|
||||||
|
@ -1446,10 +1446,15 @@ void DepsgraphRelationBuilder::build_animdata_drivers(ID *id)
|
|||||||
void DepsgraphRelationBuilder::build_animation_images(ID *id)
|
void DepsgraphRelationBuilder::build_animation_images(ID *id)
|
||||||
{
|
{
|
||||||
/* See #DepsgraphNodeBuilder::build_animation_images. */
|
/* See #DepsgraphNodeBuilder::build_animation_images. */
|
||||||
const bool can_have_gpu_material = ELEM(GS(id->name), ID_MA, ID_WO);
|
bool has_image_animation = false;
|
||||||
|
if (ELEM(GS(id->name), ID_MA, ID_WO)) {
|
||||||
|
bNodeTree *ntree = *BKE_ntree_ptr_from_id(id);
|
||||||
|
if (ntree != nullptr && ntree->runtime_flag & NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION) {
|
||||||
|
has_image_animation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: can we check for existence of node for performance? */
|
if (has_image_animation || BKE_image_user_id_has_animation(id)) {
|
||||||
if (can_have_gpu_material || BKE_image_user_id_has_animation(id)) {
|
|
||||||
OperationKey image_animation_key(
|
OperationKey image_animation_key(
|
||||||
id, NodeType::IMAGE_ANIMATION, OperationCode::IMAGE_ANIMATION);
|
id, NodeType::IMAGE_ANIMATION, OperationCode::IMAGE_ANIMATION);
|
||||||
TimeSourceKey time_src_key;
|
TimeSourceKey time_src_key;
|
||||||
|
@ -676,6 +676,40 @@ static void track_colors(MovieTrackingTrack *track, int act, float col[3], float
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_draw_marker_area_color(const MovieTrackingTrack *track,
|
||||||
|
const MovieTrackingMarker *marker,
|
||||||
|
const bool is_track_active,
|
||||||
|
const bool is_area_selected,
|
||||||
|
const float color[3],
|
||||||
|
const float selected_color[3])
|
||||||
|
{
|
||||||
|
if (track->flag & TRACK_LOCKED) {
|
||||||
|
if (is_track_active) {
|
||||||
|
immUniformThemeColor(TH_ACT_MARKER);
|
||||||
|
}
|
||||||
|
else if (is_area_selected) {
|
||||||
|
immUniformThemeColorShade(TH_LOCK_MARKER, 64);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
immUniformThemeColor(TH_LOCK_MARKER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (marker->flag & MARKER_DISABLED) {
|
||||||
|
if (is_track_active) {
|
||||||
|
immUniformThemeColor(TH_ACT_MARKER);
|
||||||
|
}
|
||||||
|
else if (is_area_selected) {
|
||||||
|
immUniformThemeColorShade(TH_DIS_MARKER, 128);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
immUniformThemeColor(TH_DIS_MARKER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
immUniformColor3fv(is_area_selected ? selected_color : color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void draw_marker_areas(SpaceClip *sc,
|
static void draw_marker_areas(SpaceClip *sc,
|
||||||
MovieTrackingTrack *track,
|
MovieTrackingTrack *track,
|
||||||
MovieTrackingMarker *marker,
|
MovieTrackingMarker *marker,
|
||||||
@ -785,31 +819,7 @@ static void draw_marker_areas(SpaceClip *sc,
|
|||||||
GPU_matrix_push();
|
GPU_matrix_push();
|
||||||
GPU_matrix_translate_2fv(marker_pos);
|
GPU_matrix_translate_2fv(marker_pos);
|
||||||
|
|
||||||
if (track->flag & TRACK_LOCKED) {
|
set_draw_marker_area_color(track, marker, act, track->pat_flag & SELECT, col, scol);
|
||||||
if (act) {
|
|
||||||
immUniformThemeColor(TH_ACT_MARKER);
|
|
||||||
}
|
|
||||||
else if (track->pat_flag & SELECT) {
|
|
||||||
immUniformThemeColorShade(TH_LOCK_MARKER, 64);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
immUniformThemeColor(TH_LOCK_MARKER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (marker->flag & MARKER_DISABLED) {
|
|
||||||
if (act) {
|
|
||||||
immUniformThemeColor(TH_ACT_MARKER);
|
|
||||||
}
|
|
||||||
else if (track->pat_flag & SELECT) {
|
|
||||||
immUniformThemeColorShade(TH_DIS_MARKER, 128);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
immUniformThemeColor(TH_DIS_MARKER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
immUniformColor3fv((track->pat_flag & SELECT) ? scol : col);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tiny) {
|
if (tiny) {
|
||||||
immUniform1f("dash_width", 6.0f);
|
immUniform1f("dash_width", 6.0f);
|
||||||
@ -834,6 +844,8 @@ static void draw_marker_areas(SpaceClip *sc,
|
|||||||
0;
|
0;
|
||||||
|
|
||||||
if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) {
|
if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) {
|
||||||
|
set_draw_marker_area_color(track, marker, act, track->search_flag & SELECT, col, scol);
|
||||||
|
|
||||||
imm_draw_box_wire_2d(shdr_pos,
|
imm_draw_box_wire_2d(shdr_pos,
|
||||||
marker->search_min[0],
|
marker->search_min[0],
|
||||||
marker->search_min[1],
|
marker->search_min[1],
|
||||||
|
@ -499,7 +499,13 @@ typedef struct bNodeTree {
|
|||||||
|
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
char _pad1[4];
|
/**
|
||||||
|
* Used to cache run-time information of the node tree.
|
||||||
|
* #eNodeTreeRuntimeFlag.
|
||||||
|
*/
|
||||||
|
uint8_t runtime_flag;
|
||||||
|
|
||||||
|
char _pad1[3];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sockets in groups have unique identifiers, adding new sockets always
|
* Sockets in groups have unique identifiers, adding new sockets always
|
||||||
@ -601,6 +607,11 @@ typedef enum eNodeTreeExecutionMode {
|
|||||||
NTREE_EXECUTION_MODE_FULL_FRAME = 1,
|
NTREE_EXECUTION_MODE_FULL_FRAME = 1,
|
||||||
} eNodeTreeExecutionMode;
|
} eNodeTreeExecutionMode;
|
||||||
|
|
||||||
|
typedef enum eNodeTreeRuntimeFlag {
|
||||||
|
/** There is a node that references an image with animation. */
|
||||||
|
NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION = 1 << 0,
|
||||||
|
} eNodeTreeRuntimeFlag;
|
||||||
|
|
||||||
/* socket value structs for input buttons
|
/* socket value structs for input buttons
|
||||||
* DEPRECATED now using ID properties
|
* DEPRECATED now using ID properties
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user