[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