Attribute Node: refactor lookup to remove duplication between engines.
Currently lookup of Object and Instancer attributes is completely duplicated between Cycles, Eevee and Eevee Next. This is bad design, so this patch aims to deduplicate it by introducing a common API in blenkernel. In case of Cycles this requires certain hacks, but according to Brecht it is planned to be rewritten later for more direct access to internal Blender data anyway. Differential Revision: https://developer.blender.org/D16117
This commit is contained in:
parent
42eda155df
commit
554afabf75
|
@ -7,6 +7,7 @@ set(INC
|
|||
../../mikktspace
|
||||
../../../source/blender/makesdna
|
||||
../../../source/blender/makesrna
|
||||
../../../source/blender/blenkernel
|
||||
../../../source/blender/blenlib
|
||||
../../../source/blender/gpu
|
||||
../../../source/blender/render
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "util/log.h"
|
||||
#include "util/task.h"
|
||||
|
||||
#include "BKE_duplilist.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Utilities */
|
||||
|
@ -353,79 +355,26 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
|
|||
return object;
|
||||
}
|
||||
|
||||
/* This function mirrors drw_uniform_property_lookup in draw_instance_data.cpp */
|
||||
static bool lookup_property(BL::ID b_id, const string &name, float4 *r_value)
|
||||
{
|
||||
PointerRNA ptr;
|
||||
PropertyRNA *prop;
|
||||
extern "C" DupliObject *rna_hack_DepsgraphObjectInstance_dupli_object_get(PointerRNA *ptr);
|
||||
|
||||
if (!RNA_path_resolve(&b_id.ptr, name.c_str(), &ptr, &prop)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (prop == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PropertyType type = RNA_property_type(prop);
|
||||
int arraylen = RNA_property_array_length(&ptr, prop);
|
||||
|
||||
if (arraylen == 0) {
|
||||
float value;
|
||||
|
||||
if (type == PROP_FLOAT)
|
||||
value = RNA_property_float_get(&ptr, prop);
|
||||
else if (type == PROP_INT)
|
||||
value = static_cast<float>(RNA_property_int_get(&ptr, prop));
|
||||
else
|
||||
return false;
|
||||
|
||||
*r_value = make_float4(value, value, value, 1.0f);
|
||||
return true;
|
||||
}
|
||||
else if (type == PROP_FLOAT && arraylen <= 4) {
|
||||
*r_value = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
RNA_property_float_get_array(&ptr, prop, &r_value->x);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This function mirrors drw_uniform_attribute_lookup in draw_instance_data.cpp */
|
||||
static float4 lookup_instance_property(BL::DepsgraphObjectInstance &b_instance,
|
||||
const string &name,
|
||||
bool use_instancer)
|
||||
{
|
||||
string idprop_name = string_printf("[\"%s\"]", name.c_str());
|
||||
float4 value;
|
||||
::Object *ob = (::Object *)b_instance.object().ptr.data;
|
||||
::DupliObject *dupli = nullptr;
|
||||
::Object *dupli_parent = nullptr;
|
||||
|
||||
/* If requesting instance data, check the parent particle system and object. */
|
||||
if (use_instancer && b_instance.is_instance()) {
|
||||
BL::ParticleSystem b_psys = b_instance.particle_system();
|
||||
|
||||
if (b_psys) {
|
||||
if (lookup_property(b_psys.settings(), idprop_name, &value) ||
|
||||
lookup_property(b_psys.settings(), name, &value)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
if (lookup_property(b_instance.parent(), idprop_name, &value) ||
|
||||
lookup_property(b_instance.parent(), name, &value)) {
|
||||
return value;
|
||||
}
|
||||
dupli = rna_hack_DepsgraphObjectInstance_dupli_object_get(&b_instance.ptr);
|
||||
dupli_parent = (::Object *)b_instance.parent().ptr.data;
|
||||
}
|
||||
|
||||
/* Check the object and mesh. */
|
||||
BL::Object b_ob = b_instance.object();
|
||||
BL::ID b_data = b_ob.data();
|
||||
float4 value;
|
||||
BKE_object_dupli_find_rgba_attribute(ob, dupli, dupli_parent, name.c_str(), &value.x);
|
||||
|
||||
if (lookup_property(b_ob, idprop_name, &value) || lookup_property(b_ob, name, &value) ||
|
||||
lookup_property(b_data, idprop_name, &value) || lookup_property(b_data, name, &value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return zero_float4();
|
||||
return value;
|
||||
}
|
||||
|
||||
bool BlenderSync::sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object)
|
||||
|
|
|
@ -64,6 +64,14 @@ typedef struct DupliObject {
|
|||
unsigned int random_id;
|
||||
} DupliObject;
|
||||
|
||||
/** Look up the RGBA value of a uniform shader attribute.
|
||||
* \return true if the attribute was found; if not, r_value is also set to zero. */
|
||||
bool BKE_object_dupli_find_rgba_attribute(struct Object *ob,
|
||||
struct DupliObject *dupli,
|
||||
struct Object *dupli_parent,
|
||||
const char *name,
|
||||
float r_value[4]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -58,6 +58,9 @@
|
|||
#include "BLI_hash.h"
|
||||
|
||||
#include "NOD_geometry_nodes_log.hh"
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_path.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
using blender::Array;
|
||||
using blender::float3;
|
||||
|
@ -1711,3 +1714,120 @@ void free_object_duplilist(ListBase *lb)
|
|||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Uniform attribute lookup
|
||||
* \{ */
|
||||
|
||||
/** Lookup an arbitrary RNA property and convert it to RGBA if possible. */
|
||||
static bool find_rna_property_rgba(PointerRNA *id_ptr, const char *name, float r_data[4])
|
||||
{
|
||||
if (id_ptr->data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* First, check custom properties. */
|
||||
IDProperty *group = RNA_struct_idprops(id_ptr, false);
|
||||
PropertyRNA *prop = nullptr;
|
||||
|
||||
if (group && group->type == IDP_GROUP) {
|
||||
prop = (PropertyRNA *)IDP_GetPropertyFromGroup(group, name);
|
||||
}
|
||||
|
||||
/* If not found, do full path lookup. */
|
||||
PointerRNA ptr;
|
||||
|
||||
if (prop != nullptr) {
|
||||
ptr = *id_ptr;
|
||||
}
|
||||
else if (!RNA_path_resolve(id_ptr, name, &ptr, &prop)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (prop == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Convert the value to RGBA if possible. */
|
||||
PropertyType type = RNA_property_type(prop);
|
||||
int array_len = RNA_property_array_length(&ptr, prop);
|
||||
|
||||
if (array_len == 0) {
|
||||
float value;
|
||||
|
||||
if (type == PROP_FLOAT) {
|
||||
value = RNA_property_float_get(&ptr, prop);
|
||||
}
|
||||
else if (type == PROP_INT) {
|
||||
value = static_cast<float>(RNA_property_int_get(&ptr, prop));
|
||||
}
|
||||
else if (type == PROP_BOOLEAN) {
|
||||
value = RNA_property_boolean_get(&ptr, prop) ? 1.0f : 0.0f;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
copy_v4_fl4(r_data, value, value, value, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type == PROP_FLOAT && array_len <= 4) {
|
||||
copy_v4_fl4(r_data, 0, 0, 0, 1);
|
||||
RNA_property_float_get_array(&ptr, prop, r_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type == PROP_INT && array_len <= 4) {
|
||||
int tmp[4] = {0, 0, 0, 1};
|
||||
RNA_property_int_get_array(&ptr, prop, tmp);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
r_data[i] = static_cast<float>(tmp[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool find_rna_property_rgba(ID *id, const char *name, float r_data[4])
|
||||
{
|
||||
PointerRNA ptr;
|
||||
RNA_id_pointer_create(id, &ptr);
|
||||
return find_rna_property_rgba(&ptr, name, r_data);
|
||||
}
|
||||
|
||||
bool BKE_object_dupli_find_rgba_attribute(
|
||||
Object *ob, DupliObject *dupli, Object *dupli_parent, const char *name, float r_value[4])
|
||||
{
|
||||
/* Check the dupli particle system. */
|
||||
if (dupli && dupli->particle_system) {
|
||||
ParticleSettings *settings = dupli->particle_system->part;
|
||||
|
||||
if (find_rna_property_rgba(&settings->id, name, r_value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the dupli parent object. */
|
||||
if (dupli_parent && find_rna_property_rgba(&dupli_parent->id, name, r_value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check the main object. */
|
||||
if (ob) {
|
||||
if (find_rna_property_rgba(&ob->id, name, r_value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check the main object data (e.g. mesh). */
|
||||
if (ob->data && find_rna_property_rgba((ID *)ob->data, name, r_value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
copy_v4_fl(r_value, 0.0f);
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -585,87 +585,18 @@ static DRWUniformAttrBuf *drw_uniform_attrs_pool_ensure(GHash *table,
|
|||
return (DRWUniformAttrBuf *)*pval;
|
||||
}
|
||||
|
||||
/* This function mirrors lookup_property in cycles/blender/blender_object.cpp */
|
||||
static bool drw_uniform_property_lookup(ID *id, const char *name, float r_data[4])
|
||||
{
|
||||
PointerRNA ptr, id_ptr;
|
||||
PropertyRNA *prop;
|
||||
|
||||
if (!id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RNA_id_pointer_create(id, &id_ptr);
|
||||
|
||||
if (!RNA_path_resolve(&id_ptr, name, &ptr, &prop)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (prop == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PropertyType type = RNA_property_type(prop);
|
||||
int arraylen = RNA_property_array_length(&ptr, prop);
|
||||
|
||||
if (arraylen == 0) {
|
||||
float value;
|
||||
|
||||
if (type == PROP_FLOAT) {
|
||||
value = RNA_property_float_get(&ptr, prop);
|
||||
}
|
||||
else if (type == PROP_INT) {
|
||||
value = RNA_property_int_get(&ptr, prop);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
copy_v4_fl4(r_data, value, value, value, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type == PROP_FLOAT && arraylen <= 4) {
|
||||
copy_v4_fl4(r_data, 0, 0, 0, 1);
|
||||
RNA_property_float_get_array(&ptr, prop, r_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This function mirrors lookup_instance_property in cycles/blender/blender_object.cpp */
|
||||
static void drw_uniform_attribute_lookup(GPUUniformAttr *attr,
|
||||
Object *ob,
|
||||
Object *dupli_parent,
|
||||
DupliObject *dupli_source,
|
||||
float r_data[4])
|
||||
{
|
||||
copy_v4_fl(r_data, 0);
|
||||
|
||||
/* If requesting instance data, check the parent particle system and object. */
|
||||
if (attr->use_dupli) {
|
||||
if (dupli_source && dupli_source->particle_system) {
|
||||
ParticleSettings *settings = dupli_source->particle_system->part;
|
||||
if (drw_uniform_property_lookup((ID *)settings, attr->name_id_prop, r_data) ||
|
||||
drw_uniform_property_lookup((ID *)settings, attr->name, r_data)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (drw_uniform_property_lookup((ID *)dupli_parent, attr->name_id_prop, r_data) ||
|
||||
drw_uniform_property_lookup((ID *)dupli_parent, attr->name, r_data)) {
|
||||
return;
|
||||
}
|
||||
BKE_object_dupli_find_rgba_attribute(ob, dupli_source, dupli_parent, attr->name, r_data);
|
||||
}
|
||||
|
||||
/* Check the object and mesh. */
|
||||
if (ob) {
|
||||
if (drw_uniform_property_lookup((ID *)ob, attr->name_id_prop, r_data) ||
|
||||
drw_uniform_property_lookup((ID *)ob, attr->name, r_data) ||
|
||||
drw_uniform_property_lookup((ID *)ob->data, attr->name_id_prop, r_data) ||
|
||||
drw_uniform_property_lookup((ID *)ob->data, attr->name, r_data)) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
BKE_object_dupli_find_rgba_attribute(ob, NULL, NULL, attr->name, r_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,58 +18,6 @@
|
|||
/** \name ObjectAttributes
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Extract object attribute from RNA property.
|
||||
* Returns true if the attribute was correctly extracted.
|
||||
* This function mirrors lookup_property in cycles/blender/blender_object.cpp
|
||||
*/
|
||||
bool ObjectAttribute::id_property_lookup(ID *id, const char *name)
|
||||
{
|
||||
PointerRNA ptr, id_ptr;
|
||||
PropertyRNA *prop;
|
||||
|
||||
if (id == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RNA_id_pointer_create(id, &id_ptr);
|
||||
|
||||
if (!RNA_path_resolve(&id_ptr, name, &ptr, &prop)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (prop == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PropertyType type = RNA_property_type(prop);
|
||||
int array_len = RNA_property_array_length(&ptr, prop);
|
||||
|
||||
if (array_len == 0) {
|
||||
float value;
|
||||
|
||||
if (type == PROP_FLOAT) {
|
||||
value = RNA_property_float_get(&ptr, prop);
|
||||
}
|
||||
else if (type == PROP_INT) {
|
||||
value = RNA_property_int_get(&ptr, prop);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
*reinterpret_cast<float4 *>(&data_x) = float4(value, value, value, 1.0f);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type == PROP_FLOAT && array_len <= 4) {
|
||||
*reinterpret_cast<float4 *>(&data_x) = float4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
RNA_property_float_get_array(&ptr, prop, &data_x);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through all possible source of the given object uniform attribute.
|
||||
* Returns true if the attribute was correctly filled.
|
||||
|
@ -81,29 +29,12 @@ bool ObjectAttribute::sync(const blender::draw::ObjectRef &ref, const GPUUniform
|
|||
|
||||
/* If requesting instance data, check the parent particle system and object. */
|
||||
if (attr.use_dupli) {
|
||||
if ((ref.dupli_object != nullptr) && (ref.dupli_object->particle_system != nullptr)) {
|
||||
ParticleSettings *settings = ref.dupli_object->particle_system->part;
|
||||
if (this->id_property_lookup((ID *)settings, attr.name_id_prop) ||
|
||||
this->id_property_lookup((ID *)settings, attr.name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (this->id_property_lookup((ID *)ref.dupli_parent, attr.name_id_prop) ||
|
||||
this->id_property_lookup((ID *)ref.dupli_parent, attr.name)) {
|
||||
return true;
|
||||
}
|
||||
return BKE_object_dupli_find_rgba_attribute(
|
||||
ref.object, ref.dupli_object, ref.dupli_parent, attr.name, &data_x);
|
||||
}
|
||||
|
||||
/* Check the object and mesh. */
|
||||
if (ref.object != nullptr) {
|
||||
if (this->id_property_lookup((ID *)ref.object, attr.name_id_prop) ||
|
||||
this->id_property_lookup((ID *)ref.object, attr.name) ||
|
||||
this->id_property_lookup((ID *)ref.object->data, attr.name_id_prop) ||
|
||||
this->id_property_lookup((ID *)ref.object->data, attr.name)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return BKE_object_dupli_find_rgba_attribute(ref.object, nullptr, nullptr, attr.name, &data_x);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -205,7 +205,6 @@ struct ObjectAttribute {
|
|||
|
||||
#if !defined(GPU_SHADER) && defined(__cplusplus)
|
||||
bool sync(const blender::draw::ObjectRef &ref, const GPUUniformAttr &attr);
|
||||
bool id_property_lookup(ID *id, const char *name);
|
||||
#endif
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
|
@ -335,8 +335,6 @@ typedef struct GPUUniformAttr {
|
|||
|
||||
/* Meaningful part of the attribute set key. */
|
||||
char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
|
||||
/** Escaped name with [""]. */
|
||||
char name_id_prop[64 * 2 + 4];
|
||||
/** Hash of name[64] + use_dupli. */
|
||||
uint32_t hash_code;
|
||||
bool use_dupli;
|
||||
|
|
|
@ -416,11 +416,6 @@ static GPUUniformAttr *gpu_node_graph_add_uniform_attribute(GPUNodeGraph *graph,
|
|||
if (attr == NULL && attrs->count < GPU_MAX_UNIFORM_ATTR) {
|
||||
attr = MEM_callocN(sizeof(*attr), __func__);
|
||||
STRNCPY(attr->name, name);
|
||||
{
|
||||
char attr_name_esc[sizeof(attr->name) * 2];
|
||||
BLI_str_escape(attr_name_esc, attr->name, sizeof(attr_name_esc));
|
||||
SNPRINTF(attr->name_id_prop, "[\"%s\"]", attr_name_esc);
|
||||
}
|
||||
attr->use_dupli = use_dupli;
|
||||
attr->hash_code = BLI_ghashutil_strhash_p(attr->name) << 1 | (attr->use_dupli ? 0 : 1);
|
||||
attr->id = -1;
|
||||
|
|
|
@ -61,6 +61,14 @@ void **rna_DepsgraphIterator_instance(PointerRNA *ptr)
|
|||
}
|
||||
# endif
|
||||
|
||||
/* Temporary hack for Cycles until it is changed to work with the C API directly. */
|
||||
DupliObject *rna_hack_DepsgraphObjectInstance_dupli_object_get(PointerRNA *ptr)
|
||||
{
|
||||
RNA_DepsgraphIterator *di = ptr->data;
|
||||
DEGObjectIterData *deg_iter = (DEGObjectIterData *)di->iter.data;
|
||||
return deg_iter->dupli_object_current;
|
||||
}
|
||||
|
||||
static PointerRNA rna_DepsgraphObjectInstance_object_get(PointerRNA *ptr)
|
||||
{
|
||||
RNA_DepsgraphIterator *di = ptr->data;
|
||||
|
|
Loading…
Reference in New Issue