I have 2400 small cubes stacked to form a brick base. The total dimension is 40x12x5 with each cube size of 1x1x1. There is a large cone, some parts of that directly go through the brick base as shown in the figure. Is there any very fast way of getting the name of all the objects (cubes) that touches / falls inside the cone?
$\begingroup$
$\endgroup$
2
-
1$\begingroup$ There are numerous Q&A re intersecting meshes eg blender.stackexchange.com/questions/9073/… blender.stackexchange.com/questions/71289/… blender.stackexchange.com/questions/45827/… $\endgroup$– batFINGERCommented Oct 7, 2020 at 18:13
-
1$\begingroup$ blender.stackexchange.com/a/167594/15543 $\endgroup$– batFINGERCommented Oct 8, 2020 at 18:28
Add a comment
|
1 Answer
$\begingroup$
$\endgroup$
I have found a solution with two different approaches. The first is to find the cubes that intersect with the cone and usually on the side of the edge. Second, finds the cubes that sit inside the cone. In the second part, there will be some cubes that actually intersect with the cone. Thus, there will be some cubes present both results. You can just join both lists and get rid of the duplicate cubes for the correct answer.
# import libraries
import bpy, bmesh, time
from mathutils.bvhtree import BVHTree
from mathutils import Vector
obj_list = [e for e in bpy.data.objects if e.type == 'MESH' and e != bpy.data.objects['Cone']] # get all the cubes
cone = bpy.data.objects['Cone']
# part 1: find the cubes intersect with the cone create cone mesh and it's BVH Tree
cone_mesh = bmesh.new()
cone_mesh.from_mesh(cone.data)
cone_mesh.transform(cone.matrix_world)
cone_BVHtree = BVHTree.FromBMesh(cone_mesh)
intersect_obj_list = [] # the cubes intersect the cone create cube mesh for each cube and their BVH Trees
for cube in obj_list:
cube_mesh = bmesh.new()
cube_mesh.from_mesh(cube.data)
cube_mesh.transform(cube.matrix_world)
cube_BVHtree = BVHTree.FromBMesh(cube_mesh)
# get the intersected faces using BVHtree, if result is non-none, the cube is intersecting
inter = cone_BVHtree.overlap(cube_BVHtree)
if inter != []:
intersect_obj_list.append(cube)
print (len(intersect_obj_list))
# part 2: find the cubes sits completely inside the cone
falls_inside = []
for cube in obj_list:
cube_location = cube.location
x,y,z = cube_location
dest_point = Vector((x, y, z+100)) # destination will be point far from the origin
origin = cone.matrix_local.inverted()@cube_location
destination = cone.matrix_local.inverted()@dest_point
direction = (destination - origin).normalized() #normalizing
# shooting ray from origin to the destinantion, if it hits then the object is sitting inside the cone
hit, loc, norm, face = cone.ray_cast(origin, direction)
if hit:
falls_inside.append(cube)
interset_inside_cubes = list(set(intersect_obj_list+falls_inside))