Using the particles location vector, and the closest_point_on_mesh
method. The particle location is in global coords. We can see this by moving the emitter in the UI, the particles remain in their world position and need to be re(bake)calculated.
As pointed out in https://blender.stackexchange.com/a/40979/15543 you need to put the location passed to closest_point_on_mesh
into the objects local space, otherwise it will give unexpected results once the object's matrix_world is no longer the identity matrix.
The particle location is multiplied by the inverse matrix world of the emmitter object, to put it into that objects local coordinates.
I'm using a build of 2.76.4 and it appears closest_point_on_mesh
has a new return value,
>>> C.object.closest_point_on_mesh((0,0,0))
(True, Vector((0.9999996423721313, -2.980232238769531e-07, 0.0)), Vector((1.0, 0.0, 3.2782557468635787e-07)), 2)
The first being success of operation, the others: location vector of closest point; normal vector; and face index.
The script below prints how many particles are closest to each face.
import bpy
context = bpy.context
obj = context.object
mwi = obj.matrix_world.inverted()
ps = obj.particle_systems.active
facelist = []
new_version = bpy.app.version == (2, 76, 4)
print("-" * 72)
print("Obj: %s Particle System: %s" % (obj.name, ps.name))
print("-" * 72)
for i, p in enumerate(ps.particles):
v1 = p.location # global particle location
localPos = mwi * v1 # particle in obj local space
if new_version:
(found, loc, norm, face_index) = obj.closest_point_on_mesh(localPos)
if not found:
continue
else:
(loc, norm, face_index) = obj.closest_point_on_mesh(localPos)
facelist.append(face_index)
mesh = obj.data
for fi in set(facelist):
vertstr = str([v for v in mesh.polygons[fi].vertices])
print("face %d, verts: %s particle count:%d" % (fi, vertstr, facelist.count(fi)))
Sample result default cube, default particle system
------------------------------------------------------------------------
Obj: Cube Particle System: ParticleSystem
------------------------------------------------------------------------
face 0, verts: [0, 1, 2, 3] particle count:180
face 1, verts: [4, 7, 6, 5] particle count:168
face 2, verts: [0, 4, 5, 1] particle count:161
face 3, verts: [1, 5, 6, 2] particle count:169
face 4, verts: [2, 6, 7, 3] particle count:150
face 5, verts: [4, 0, 3, 7] particle count:172