Fix T84326: No ID for geometry nodes instances after scattering
Instances are created with an "index" parameter used for persistence over time through animation. Currently the geometry nodes instancer passes the index in the array for this value, but the arrays created by the "Point Distribution" node aren't necessarily stable in this way when the input mesh is deformed. In D9832 we already mostly solved this problem with an `id` attribute. The solution here is to create instances with this attribute as well. It's important to note that deforming the instanced points *after* distribution will usually be a better solution for this problem. This solution is likely still important though. Differential Revision: https://developer.blender.org/D10024
This commit is contained in:
parent
4c0fc60105
commit
3db975f30d
Notes:
blender-bot
2023-02-14 11:00:17 +01:00
Referenced by issue #84504, Crash on smoke simulation when rendering Referenced by issue #84502, Eevee volume render without shaders render parameters breaks Referenced by issue #84326, Geometry Nodes: Apparently No Frame-to-Frame Linkage Between Instanced Objects and Point Cloud Elements - Shader Node Object Info Becomes Unreliable
|
@ -49,6 +49,7 @@ int BKE_geometry_set_instances(const struct GeometrySet *geometry_set,
|
|||
float (**r_positions)[3],
|
||||
float (**r_rotations)[3],
|
||||
float (**r_scales)[3],
|
||||
int **r_ids,
|
||||
struct InstancedData **r_instanced_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -364,6 +364,7 @@ class InstancesComponent : public GeometryComponent {
|
|||
blender::Vector<blender::float3> positions_;
|
||||
blender::Vector<blender::float3> rotations_;
|
||||
blender::Vector<blender::float3> scales_;
|
||||
blender::Vector<int> ids_;
|
||||
blender::Vector<InstancedData> instanced_data_;
|
||||
|
||||
public:
|
||||
|
@ -375,20 +376,24 @@ class InstancesComponent : public GeometryComponent {
|
|||
void add_instance(Object *object,
|
||||
blender::float3 position,
|
||||
blender::float3 rotation = {0, 0, 0},
|
||||
blender::float3 scale = {1, 1, 1});
|
||||
blender::float3 scale = {1, 1, 1},
|
||||
const int id = -1);
|
||||
void add_instance(Collection *collection,
|
||||
blender::float3 position,
|
||||
blender::float3 rotation = {0, 0, 0},
|
||||
blender::float3 scale = {1, 1, 1});
|
||||
blender::float3 scale = {1, 1, 1},
|
||||
const int id = -1);
|
||||
void add_instance(InstancedData data,
|
||||
blender::float3 position,
|
||||
blender::float3 rotation,
|
||||
blender::float3 scale);
|
||||
blender::float3 scale,
|
||||
const int id = -1);
|
||||
|
||||
blender::Span<InstancedData> instanced_data() const;
|
||||
blender::Span<blender::float3> positions() const;
|
||||
blender::Span<blender::float3> rotations() const;
|
||||
blender::Span<blender::float3> scales() const;
|
||||
blender::Span<int> ids() const;
|
||||
blender::MutableSpan<blender::float3> positions();
|
||||
int instances_amount() const;
|
||||
|
||||
|
|
|
@ -476,34 +476,38 @@ void InstancesComponent::clear()
|
|||
void InstancesComponent::add_instance(Object *object,
|
||||
blender::float3 position,
|
||||
blender::float3 rotation,
|
||||
blender::float3 scale)
|
||||
blender::float3 scale,
|
||||
const int id)
|
||||
{
|
||||
InstancedData data;
|
||||
data.type = INSTANCE_DATA_TYPE_OBJECT;
|
||||
data.data.object = object;
|
||||
this->add_instance(data, position, rotation, scale);
|
||||
this->add_instance(data, position, rotation, scale, id);
|
||||
}
|
||||
|
||||
void InstancesComponent::add_instance(Collection *collection,
|
||||
blender::float3 position,
|
||||
blender::float3 rotation,
|
||||
blender::float3 scale)
|
||||
blender::float3 scale,
|
||||
const int id)
|
||||
{
|
||||
InstancedData data;
|
||||
data.type = INSTANCE_DATA_TYPE_COLLECTION;
|
||||
data.data.collection = collection;
|
||||
this->add_instance(data, position, rotation, scale);
|
||||
this->add_instance(data, position, rotation, scale, id);
|
||||
}
|
||||
|
||||
void InstancesComponent::add_instance(InstancedData data,
|
||||
blender::float3 position,
|
||||
blender::float3 rotation,
|
||||
blender::float3 scale)
|
||||
blender::float3 scale,
|
||||
const int id)
|
||||
{
|
||||
instanced_data_.append(data);
|
||||
positions_.append(position);
|
||||
rotations_.append(rotation);
|
||||
scales_.append(scale);
|
||||
ids_.append(id);
|
||||
}
|
||||
|
||||
Span<InstancedData> InstancesComponent::instanced_data() const
|
||||
|
@ -516,16 +520,21 @@ Span<float3> InstancesComponent::positions() const
|
|||
return positions_;
|
||||
}
|
||||
|
||||
blender::Span<blender::float3> InstancesComponent::rotations() const
|
||||
Span<float3> InstancesComponent::rotations() const
|
||||
{
|
||||
return rotations_;
|
||||
}
|
||||
|
||||
blender::Span<blender::float3> InstancesComponent::scales() const
|
||||
Span<float3> InstancesComponent::scales() const
|
||||
{
|
||||
return scales_;
|
||||
}
|
||||
|
||||
Span<int> InstancesComponent::ids() const
|
||||
{
|
||||
return ids_;
|
||||
}
|
||||
|
||||
MutableSpan<float3> InstancesComponent::positions()
|
||||
{
|
||||
return positions_;
|
||||
|
@ -565,6 +574,7 @@ int BKE_geometry_set_instances(const GeometrySet *geometry_set,
|
|||
float (**r_positions)[3],
|
||||
float (**r_rotations)[3],
|
||||
float (**r_scales)[3],
|
||||
int **r_ids,
|
||||
InstancedData **r_instanced_data)
|
||||
{
|
||||
const InstancesComponent *component = geometry_set->get_component_for_read<InstancesComponent>();
|
||||
|
@ -574,6 +584,8 @@ int BKE_geometry_set_instances(const GeometrySet *geometry_set,
|
|||
*r_positions = (float(*)[3])component->positions().data();
|
||||
*r_rotations = (float(*)[3])component->rotations().data();
|
||||
*r_scales = (float(*)[3])component->scales().data();
|
||||
*r_ids = (int *)component->ids().data();
|
||||
*r_instanced_data = (InstancedData *)component->instanced_data().data();
|
||||
*r_instanced_data = (InstancedData *)component->instanced_data().data();
|
||||
return component->instances_amount();
|
||||
}
|
||||
|
|
|
@ -816,9 +816,14 @@ static void make_duplis_instances_component(const DupliContext *ctx)
|
|||
float(*positions)[3];
|
||||
float(*rotations)[3];
|
||||
float(*scales)[3];
|
||||
int *ids;
|
||||
InstancedData *instanced_data;
|
||||
const int amount = BKE_geometry_set_instances(
|
||||
ctx->object->runtime.geometry_set_eval, &positions, &rotations, &scales, &instanced_data);
|
||||
const int amount = BKE_geometry_set_instances(ctx->object->runtime.geometry_set_eval,
|
||||
&positions,
|
||||
&rotations,
|
||||
&scales,
|
||||
&ids,
|
||||
&instanced_data);
|
||||
|
||||
for (int i = 0; i < amount; i++) {
|
||||
InstancedData *data = &instanced_data[i];
|
||||
|
@ -831,17 +836,19 @@ static void make_duplis_instances_component(const DupliContext *ctx)
|
|||
mul_m4_m4m4(instance_offset_matrix, rotation_matrix, scale_matrix);
|
||||
copy_v3_v3(instance_offset_matrix[3], positions[i]);
|
||||
|
||||
const int id = ids[i] != -1 ? ids[i] : i;
|
||||
|
||||
if (data->type == INSTANCE_DATA_TYPE_OBJECT) {
|
||||
Object *object = data->data.object;
|
||||
if (object != NULL) {
|
||||
float matrix[4][4];
|
||||
mul_m4_m4m4(matrix, ctx->object->obmat, instance_offset_matrix);
|
||||
make_dupli(ctx, object, matrix, i);
|
||||
make_dupli(ctx, object, matrix, id);
|
||||
|
||||
float space_matrix[4][4];
|
||||
mul_m4_m4m4(space_matrix, instance_offset_matrix, object->imat);
|
||||
mul_m4_m4_pre(space_matrix, ctx->object->obmat);
|
||||
make_recursive_duplis(ctx, object, space_matrix, i);
|
||||
make_recursive_duplis(ctx, object, space_matrix, id);
|
||||
}
|
||||
}
|
||||
else if (data->type == INSTANCE_DATA_TYPE_COLLECTION) {
|
||||
|
@ -862,8 +869,8 @@ static void make_duplis_instances_component(const DupliContext *ctx)
|
|||
float instance_matrix[4][4];
|
||||
mul_m4_m4m4(instance_matrix, collection_matrix, object->obmat);
|
||||
|
||||
make_dupli(ctx, object, instance_matrix, i);
|
||||
make_recursive_duplis(ctx, object, collection_matrix, i);
|
||||
make_dupli(ctx, object, instance_matrix, id);
|
||||
make_recursive_duplis(ctx, object, collection_matrix, id);
|
||||
}
|
||||
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
|
||||
}
|
||||
|
|
|
@ -161,10 +161,11 @@ static void add_instances_from_geometry_component(InstancesComponent &instances,
|
|||
"rotation", domain, {0, 0, 0});
|
||||
Float3ReadAttribute scales = src_geometry.attribute_get_for_read<float3>(
|
||||
"scale", domain, {1, 1, 1});
|
||||
Int32ReadAttribute ids = src_geometry.attribute_get_for_read<int>("id", domain, -1);
|
||||
|
||||
for (const int i : IndexRange(domain_size)) {
|
||||
if (instances_data[i].has_value()) {
|
||||
instances.add_instance(*instances_data[i], positions[i], rotations[i], scales[i]);
|
||||
instances.add_instance(*instances_data[i], positions[i], rotations[i], scales[i], ids[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue