[Bf-blender-cvs] [7f802fb7504] functions: initial texture color access after collision
Jacques Lucke
noreply at git.blender.org
Fri Aug 2 19:14:47 CEST 2019
Commit: 7f802fb7504411c7e7c3ae9505402365d3819514
Author: Jacques Lucke
Date: Fri Aug 2 12:56:10 2019 +0200
Branches: functions
https://developer.blender.org/rB7f802fb7504411c7e7c3ae9505402365d3819514
initial texture color access after collision
===================================================================
M release/scripts/startup/nodes/bparticle_nodes/particle_inputs.py
M source/blender/simulations/CMakeLists.txt
M source/blender/simulations/bparticles/events.cpp
M source/blender/simulations/bparticles/events.hpp
M source/blender/simulations/bparticles/particle_function_builder.cpp
===================================================================
diff --git a/release/scripts/startup/nodes/bparticle_nodes/particle_inputs.py b/release/scripts/startup/nodes/bparticle_nodes/particle_inputs.py
index c77e2da251d..64b6b9624d3 100644
--- a/release/scripts/startup/nodes/bparticle_nodes/particle_inputs.py
+++ b/release/scripts/startup/nodes/bparticle_nodes/particle_inputs.py
@@ -22,3 +22,16 @@ class CollisionInfoNode(bpy.types.Node, BParticlesNode):
def declaration(self, builder: NodeBuilder):
builder.fixed_output("normal", "Normal", "Vector")
+
+
+class SurfaceImageNode(bpy.types.Node, BParticlesNode):
+ bl_idname = "bp_SurfaceImageNode"
+ bl_label = "Surface Image"
+
+ image: PointerProperty(type=bpy.types.Image)
+
+ def declaration(self, builder: NodeBuilder):
+ builder.fixed_output("color", "Color", "Color")
+
+ def draw(self, layout):
+ layout.prop(self, "image", text="")
diff --git a/source/blender/simulations/CMakeLists.txt b/source/blender/simulations/CMakeLists.txt
index 17fcc25a15e..0226deedb6f 100644
--- a/source/blender/simulations/CMakeLists.txt
+++ b/source/blender/simulations/CMakeLists.txt
@@ -6,6 +6,7 @@ set(INC
../blenkernel
../depsgraph
../functions
+ ../imbuf
../../../intern/guardedalloc
)
diff --git a/source/blender/simulations/bparticles/events.cpp b/source/blender/simulations/bparticles/events.cpp
index 159dca84768..f759b830b40 100644
--- a/source/blender/simulations/bparticles/events.cpp
+++ b/source/blender/simulations/bparticles/events.cpp
@@ -95,6 +95,7 @@ void MeshCollisionEvent::filter(EventFilterInterface &interface)
result.normal = -result.normal;
}
storage.normal = m_local_to_world.transform_direction(result.normal).normalized();
+ storage.looptri_index = result.index;
}
}
}
@@ -120,16 +121,18 @@ MeshCollisionEvent::RayCastResult MeshCollisionEvent::ray_cast(float3 start,
void MeshCollisionEvent::execute(EventExecuteInterface &interface)
{
ParticleSet particles = interface.particles();
- Vector<float3> normals(particles.block().active_amount());
+ ArrayAllocator::Array<float3> normals(interface.array_allocator());
+ ArrayAllocator::Array<uint> looptri_indices(interface.array_allocator());
auto last_collision_times = particles.attributes().get<float>(m_identifier);
for (uint pindex : particles.pindices()) {
auto storage = interface.get_storage<EventStorage>(pindex);
+ looptri_indices[pindex] = storage.looptri_index;
normals[pindex] = storage.normal;
last_collision_times[pindex] = interface.current_times()[pindex];
}
- CollisionEventInfo action_context(normals);
+ CollisionEventInfo action_context(m_object, looptri_indices, normals);
m_action->execute_from_event(interface, &action_context);
}
diff --git a/source/blender/simulations/bparticles/events.hpp b/source/blender/simulations/bparticles/events.hpp
index 58793741f59..62ad35d43d9 100644
--- a/source/blender/simulations/bparticles/events.hpp
+++ b/source/blender/simulations/bparticles/events.hpp
@@ -39,11 +39,24 @@ class AgeReachedEvent : public Event {
class CollisionEventInfo : public ActionContext {
private:
+ Object *m_object;
+ ArrayRef<uint> m_loop_tri_indices;
ArrayRef<float3> m_normals;
public:
- CollisionEventInfo(ArrayRef<float3> normals) : m_normals(normals)
+ CollisionEventInfo(Object *object, ArrayRef<uint> loop_tri_indices, ArrayRef<float3> normals)
+ : m_object(object), m_loop_tri_indices(loop_tri_indices), m_normals(normals)
+ {
+ }
+
+ Object *object()
+ {
+ return m_object;
+ }
+
+ ArrayRef<uint> loop_tri_indices()
{
+ return m_loop_tri_indices;
}
ArrayRef<float3> normals()
@@ -69,6 +82,7 @@ class MeshCollisionEvent : public Event {
};
struct EventStorage {
+ uint looptri_index;
float3 normal;
};
diff --git a/source/blender/simulations/bparticles/particle_function_builder.cpp b/source/blender/simulations/bparticles/particle_function_builder.cpp
index 53bb2df965a..2078f533193 100644
--- a/source/blender/simulations/bparticles/particle_function_builder.cpp
+++ b/source/blender/simulations/bparticles/particle_function_builder.cpp
@@ -1,4 +1,11 @@
#include "FN_llvm.hpp"
+#include "BKE_image.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "IMB_imbuf_types.h"
+#include "DNA_customdata_types.h"
+#include "BKE_customdata.h"
+#include "BKE_mesh_runtime.h"
#include "particle_function_builder.hpp"
@@ -7,6 +14,8 @@
namespace BParticles {
using BKE::VirtualSocket;
+using BLI::float2;
+using BLI::rgba_b;
using FN::DataSocket;
using FN::FunctionBuilder;
using FN::FunctionGraph;
@@ -102,6 +111,81 @@ class AgeInputProvider : public ParticleFunctionInputProvider {
}
};
+class SurfaceImageInputProvider : public ParticleFunctionInputProvider {
+ private:
+ Image *m_image;
+ ImageUser m_image_user = {0};
+ ImBuf *m_ibuf;
+
+ public:
+ SurfaceImageInputProvider(Image *image) : m_image(image)
+ {
+ m_image_user.ok = true;
+ m_ibuf = BKE_image_acquire_ibuf(image, &m_image_user, NULL);
+ BLI_assert(m_ibuf);
+ }
+
+ ~SurfaceImageInputProvider()
+ {
+ BKE_image_release_ibuf(m_image, m_ibuf, NULL);
+ }
+
+ ParticleFunctionInputArray get(InputProviderInterface &interface) override
+ {
+ ActionContext *action_context = interface.action_context();
+ BLI_assert(action_context != nullptr);
+ CollisionEventInfo *collision_info = dynamic_cast<CollisionEventInfo *>(action_context);
+ BLI_assert(collision_info != nullptr);
+
+ Object *object = collision_info->object();
+ float4x4 ob_inverse = (float4x4)object->imat;
+ Mesh *mesh = (Mesh *)object->data;
+
+ const MLoopTri *triangles = BKE_mesh_runtime_looptri_ensure(mesh);
+
+ int uv_layer_index = CustomData_get_active_layer(&mesh->ldata, CD_MLOOPUV);
+ BLI_assert(uv_layer_index >= 0);
+ MLoopUV *uv_layer = (MLoopUV *)CustomData_get(&mesh->ldata, uv_layer_index, CD_MLOOPUV);
+ BLI_assert(uv_layer != nullptr);
+
+ ArrayRef<float3> positions = interface.particles().attributes().get<float3>("Position");
+
+ rgba_b *pixel_buffer = (rgba_b *)m_ibuf->rect;
+
+ rgba_f *colors = interface.array_allocator().allocate<rgba_f>();
+ for (uint pindex : interface.particles().pindices()) {
+ float3 position_world = positions[pindex];
+ float3 position_local = ob_inverse.transform_position(position_world);
+
+ uint triangle_index = collision_info->loop_tri_indices()[pindex];
+ const MLoopTri &triangle = triangles[triangle_index];
+
+ uint loop1 = triangle.tri[0];
+ uint loop2 = triangle.tri[1];
+ uint loop3 = triangle.tri[2];
+
+ float3 v1 = mesh->mvert[mesh->mloop[loop1].v].co;
+ float3 v2 = mesh->mvert[mesh->mloop[loop2].v].co;
+ float3 v3 = mesh->mvert[mesh->mloop[loop3].v].co;
+
+ float2 uv1 = uv_layer[loop1].uv;
+ float2 uv2 = uv_layer[loop2].uv;
+ float2 uv3 = uv_layer[loop3].uv;
+
+ float3 vertex_weights;
+ interp_weights_tri_v3(vertex_weights, v1, v2, v3, position_local);
+
+ float2 uv;
+ interp_v2_v2v2v2(uv, uv1, uv2, uv3, vertex_weights);
+ uv = uv.clamped_01();
+ uint x = uv.x * (m_ibuf->x - 1);
+ uint y = uv.y * (m_ibuf->y - 1);
+ colors[pindex] = pixel_buffer[y * m_ibuf->x + x];
+ }
+ return {ArrayRef<rgba_f>(colors, interface.array_allocator().array_size()), true};
+ }
+};
+
static ParticleFunctionInputProvider *create_input_provider(VirtualSocket *vsocket)
{
VirtualNode *vnode = vsocket->vnode();
@@ -116,6 +200,12 @@ static ParticleFunctionInputProvider *create_input_provider(VirtualSocket *vsock
else if (STREQ(vnode->idname(), "bp_CollisionInfoNode")) {
return new CollisionNormalInputProvider();
}
+ else if (STREQ(vnode->idname(), "bp_SurfaceImageNode")) {
+ PointerRNA rna = vnode->rna();
+ Image *image = (Image *)RNA_pointer_get(&rna, "image").id.data;
+ BLI_assert(image != nullptr);
+ return new SurfaceImageInputProvider(image);
+ }
else {
BLI_assert(false);
return nullptr;
More information about the Bf-blender-cvs
mailing list