Fix T85049: Geometry Nodes: How to handle instances with shear?

Use transform matrices instead of loc, rot, scale variables to store instance transforms.

Reviewed By: JacquesLucke

Differential Revision: http://developer.blender.org/D10211
This commit is contained in:
Sebastian Parborg 2021-01-26 18:21:12 +01:00
parent 6d40d72189
commit abd6b1d7b2
Notes: blender-bot 2023-02-14 02:27:51 +01:00
Referenced by issue #85049, Geometry Nodes: How to handle instances with shear?
8 changed files with 52 additions and 124 deletions

View File

@ -46,9 +46,7 @@ typedef struct InstancedData {
} InstancedData;
int BKE_geometry_set_instances(const struct GeometrySet *geometry_set,
float (**r_positions)[3],
float (**r_rotations)[3],
float (**r_scales)[3],
float (**r_transforms)[4][4],
int **r_ids,
struct InstancedData **r_instanced_data);

View File

@ -24,6 +24,7 @@
#include <iostream>
#include "BLI_float3.hh"
#include "BLI_float4x4.hh"
#include "BLI_hash.hh"
#include "BLI_map.hh"
#include "BLI_set.hh"
@ -422,9 +423,7 @@ class PointCloudComponent : public GeometryComponent {
/** A geometry component that stores instances. */
class InstancesComponent : public GeometryComponent {
private:
blender::Vector<blender::float3> positions_;
blender::Vector<blender::float3> rotations_;
blender::Vector<blender::float3> scales_;
blender::Vector<blender::float4x4> transforms_;
blender::Vector<int> ids_;
blender::Vector<InstancedData> instanced_data_;
@ -434,30 +433,14 @@ class InstancesComponent : public GeometryComponent {
GeometryComponent *copy() const override;
void clear();
void add_instance(Object *object,
blender::float3 position,
blender::float3 rotation = {0, 0, 0},
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},
const int id = -1);
void add_instance(InstancedData data,
blender::float3 position,
blender::float3 rotation,
blender::float3 scale,
const int id = -1);
void add_instance(Object *object, blender::float4x4 transform, const int id = -1);
void add_instance(Collection *collection, blender::float4x4 transform, const int id = -1);
void add_instance(InstancedData data, blender::float4x4 transform, 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<blender::float4x4> transforms() const;
blender::Span<int> ids() const;
blender::MutableSpan<blender::float3> positions();
blender::MutableSpan<blender::float3> rotations();
blender::MutableSpan<blender::float3> scales();
blender::MutableSpan<blender::float4x4> transforms();
int instances_amount() const;
bool is_empty() const final;

View File

@ -25,6 +25,7 @@
#include "MEM_guardedalloc.h"
using blender::float3;
using blender::float4x4;
using blender::MutableSpan;
using blender::Span;
using blender::StringRef;
@ -458,9 +459,7 @@ InstancesComponent::InstancesComponent() : GeometryComponent(GeometryComponentTy
GeometryComponent *InstancesComponent::copy() const
{
InstancesComponent *new_component = new InstancesComponent();
new_component->positions_ = positions_;
new_component->rotations_ = rotations_;
new_component->scales_ = scales_;
new_component->transforms_ = transforms_;
new_component->instanced_data_ = instanced_data_;
return new_component;
}
@ -468,45 +467,29 @@ GeometryComponent *InstancesComponent::copy() const
void InstancesComponent::clear()
{
instanced_data_.clear();
positions_.clear();
rotations_.clear();
scales_.clear();
transforms_.clear();
}
void InstancesComponent::add_instance(Object *object,
blender::float3 position,
blender::float3 rotation,
blender::float3 scale,
const int id)
void InstancesComponent::add_instance(Object *object, float4x4 transform, const int id)
{
InstancedData data;
data.type = INSTANCE_DATA_TYPE_OBJECT;
data.data.object = object;
this->add_instance(data, position, rotation, scale, id);
this->add_instance(data, transform, id);
}
void InstancesComponent::add_instance(Collection *collection,
blender::float3 position,
blender::float3 rotation,
blender::float3 scale,
const int id)
void InstancesComponent::add_instance(Collection *collection, float4x4 transform, const int id)
{
InstancedData data;
data.type = INSTANCE_DATA_TYPE_COLLECTION;
data.data.collection = collection;
this->add_instance(data, position, rotation, scale, id);
this->add_instance(data, transform, id);
}
void InstancesComponent::add_instance(InstancedData data,
blender::float3 position,
blender::float3 rotation,
blender::float3 scale,
const int id)
void InstancesComponent::add_instance(InstancedData data, float4x4 transform, const int id)
{
instanced_data_.append(data);
positions_.append(position);
rotations_.append(rotation);
scales_.append(scale);
transforms_.append(transform);
ids_.append(id);
}
@ -515,19 +498,9 @@ Span<InstancedData> InstancesComponent::instanced_data() const
return instanced_data_;
}
Span<float3> InstancesComponent::positions() const
Span<float4x4> InstancesComponent::transforms() const
{
return positions_;
}
Span<float3> InstancesComponent::rotations() const
{
return rotations_;
}
Span<float3> InstancesComponent::scales() const
{
return scales_;
return transforms_;
}
Span<int> InstancesComponent::ids() const
@ -535,33 +508,21 @@ Span<int> InstancesComponent::ids() const
return ids_;
}
MutableSpan<float3> InstancesComponent::positions()
MutableSpan<float4x4> InstancesComponent::transforms()
{
return positions_;
}
MutableSpan<float3> InstancesComponent::rotations()
{
return rotations_;
}
MutableSpan<float3> InstancesComponent::scales()
{
return scales_;
return transforms_;
}
int InstancesComponent::instances_amount() const
{
const int size = instanced_data_.size();
BLI_assert(positions_.size() == size);
BLI_assert(rotations_.size() == size);
BLI_assert(scales_.size() == size);
BLI_assert(transforms_.size() == size);
return size;
}
bool InstancesComponent::is_empty() const
{
return positions_.size() == 0;
return transforms_.size() == 0;
}
/** \} */
@ -581,9 +542,7 @@ bool BKE_geometry_set_has_instances(const GeometrySet *geometry_set)
}
int BKE_geometry_set_instances(const GeometrySet *geometry_set,
float (**r_positions)[3],
float (**r_rotations)[3],
float (**r_scales)[3],
float (**r_transforms)[4][4],
int **r_ids,
InstancedData **r_instanced_data)
{
@ -591,9 +550,7 @@ int BKE_geometry_set_instances(const GeometrySet *geometry_set,
if (component == nullptr) {
return 0;
}
*r_positions = (float(*)[3])component->positions().data();
*r_rotations = (float(*)[3])component->rotations().data();
*r_scales = (float(*)[3])component->scales().data();
*r_transforms = (float(*)[4][4])component->transforms().data();
*r_ids = (int *)component->ids().data();
*r_instanced_data = (InstancedData *)component->instanced_data().data();
*r_instanced_data = (InstancedData *)component->instanced_data().data();

View File

@ -813,40 +813,26 @@ static const DupliGenerator gen_dupli_verts_pointcloud = {
static void make_duplis_instances_component(const DupliContext *ctx)
{
float(*positions)[3];
float(*rotations)[3];
float(*scales)[3];
float(*instance_offset_matrices)[4][4];
int *ids;
InstancedData *instanced_data;
const int amount = BKE_geometry_set_instances(ctx->object->runtime.geometry_set_eval,
&positions,
&rotations,
&scales,
&ids,
&instanced_data);
const int amount = BKE_geometry_set_instances(
ctx->object->runtime.geometry_set_eval, &instance_offset_matrices, &ids, &instanced_data);
for (int i = 0; i < amount; i++) {
InstancedData *data = &instanced_data[i];
float scale_matrix[4][4];
size_to_mat4(scale_matrix, scales[i]);
float rotation_matrix[4][4];
eul_to_mat4(rotation_matrix, rotations[i]);
float instance_offset_matrix[4][4];
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);
mul_m4_m4m4(matrix, ctx->object->obmat, instance_offset_matrices[i]);
make_dupli(ctx, object, matrix, id);
float space_matrix[4][4];
mul_m4_m4m4(space_matrix, instance_offset_matrix, object->imat);
mul_m4_m4m4(space_matrix, instance_offset_matrices[i], object->imat);
mul_m4_m4_pre(space_matrix, ctx->object->obmat);
make_recursive_duplis(ctx, object, space_matrix, id);
}
@ -857,7 +843,7 @@ static void make_duplis_instances_component(const DupliContext *ctx)
float collection_matrix[4][4];
unit_m4(collection_matrix);
sub_v3_v3(collection_matrix[3], collection->instance_offset);
mul_m4_m4_pre(collection_matrix, instance_offset_matrix);
mul_m4_m4_pre(collection_matrix, instance_offset_matrices[i]);
mul_m4_m4_pre(collection_matrix, ctx->object->obmat);
eEvaluationMode mode = DEG_get_mode(ctx->depsgraph);

View File

@ -45,6 +45,17 @@ struct float4x4 {
return &values[0][0];
}
using c_style_float4x4 = float[4][4];
c_style_float4x4 &ptr()
{
return values;
}
const c_style_float4x4 &ptr() const
{
return values;
}
friend float4x4 operator*(const float4x4 &a, const float4x4 &b)
{
float4x4 result;

View File

@ -233,11 +233,9 @@ static void join_components(Span<const InstancesComponent *> src_components, Geo
for (const InstancesComponent *component : src_components) {
const int size = component->instances_amount();
Span<InstancedData> instanced_data = component->instanced_data();
Span<float3> positions = component->positions();
Span<float3> rotations = component->rotations();
Span<float3> scales = component->scales();
Span<float4x4> transforms = component->transforms();
for (const int i : IndexRange(size)) {
dst_component.add_instance(instanced_data[i], positions[i], rotations[i], scales[i]);
dst_component.add_instance(instanced_data[i], transforms[i]);
}
}
}

View File

@ -165,7 +165,9 @@ static void add_instances_from_geometry_component(InstancesComponent &instances,
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], ids[i]);
float transform[4][4];
loc_eul_size_to_mat4(transform, positions[i], rotations[i], scales[i]);
instances.add_instance(*instances_data[i], transform, ids[i]);
}
}
}

View File

@ -91,27 +91,20 @@ static void transform_instances(InstancesComponent &instances,
const float3 rotation,
const float3 scale)
{
MutableSpan<float3> positions = instances.positions();
MutableSpan<float3> rotations = instances.rotations();
MutableSpan<float3> scales = instances.scales();
MutableSpan<float4x4> transforms = instances.transforms();
/* Use only translation if rotation and scale don't apply. */
if (use_translate(rotation, scale)) {
for (float3 &position : positions) {
add_v3_v3(position, translation);
for (float4x4 &transform : transforms) {
add_v3_v3(transform.ptr()[3], translation);
}
}
else {
float mat[4][4];
float instance_mat[4][4];
float quaternion[4];
loc_eul_size_to_mat4(mat, translation, rotation, scale);
for (int i = 0; i < positions.size(); i++) {
loc_eul_size_to_mat4(instance_mat, positions[i], rotations[i], scales[i]);
mul_m4_m4_pre(instance_mat, mat);
mat4_decompose(positions[i], quaternion, scales[i], instance_mat);
quat_to_eul(rotations[i], quaternion);
for (float4x4 &transform : transforms) {
mul_m4_m4_pre(transform.ptr(), mat);
}
}
}