I am using the rock generator add-on and dropping rocks into a container (consisting of 4 reshaped cubes) - see attached picture.
The rocks are dropped from a random height into the container and I want to look at the stacking of the rocks.
When the rocks fall into the container, the initial rocks settle, but as more rocks are added the rocks begin to move more erratically upon collision with other rocks, If I leave the simulation long enough most of the rocks are flung out of the container, leaving just the base layer of rocks.
I had previously set my rocks to 'convex hull' for the rigid body simulation and this prevented this effect, but introduced inaccuracies, I have now changed this to 'mesh' which gives the current problem.
I have found various bits of information online but nothing has resolved my issue.
I am using split impulse and the steps per second and solver iterations should be satisfactory.
The container consists of 4 cubes each 10cm thick which make up the walls of the container and the base. Each cube is passive in the rigid body simulation .
The rocks are on the mm range in diameter (which is small but wasnt an issue when using convex hull), I am using a collision margin of zero (rocks must be able to touch), I am applying 0.9 linear and angular damping and have tried using deactivation below a given linear and angular velocity, but with no success.
I have tried changing multiple aspects of my scene and objects, and currently have the following parameters for my active objects (rocks):
Collison Shape = Mesh
Mesh Source=Deform
Use Deform=On
Scaling is applied
Origin set to Center of Mass
Deactivation =On (but having no effect)
Collision Margin = 0.001
Linear Damping Factor = Rotation Damping Factor =0.5
Scene Parameters:
Split Impulse=On
Steps per Second=1000 (changed since I replied to a comment below (no effect on issue))
Solver Iterations=1000 (changed since I replied to a comment below (no effect on issue))
Here is the python code used to generate the attached blend file.
import bpy
import random
import time
import cProfile, pstats,io
from datetime import datetime
from pathlib import Path
import math
Xmax=0.5
Ymax=0.2
Zmax=0.4
V=Xmax*Ymax*Zmax
maxframe=800
def container_genration(Xmax,Ymax,Zmax):
bpy.ops.mesh.primitive_cube_add(size=1, enter_editmode=False, align='WORLD', location=(Xmax/2, Ymax/2, -(Zmax/10)), scale=(1, 1, 1))
bpy.data.objects["Cube"].scale[0]=Xmax*1.2
bpy.data.objects["Cube"].scale[1]=Ymax*1.2
bpy.data.objects["Cube"].scale[2]=(1/10)
bpy.ops.rigidbody.object_add()
bpy.context.object.rigid_body.type = 'PASSIVE'
bpy.data.scenes["Scene"].rigidbody_world.steps_per_second=800
bpy.data.scenes["Scene"].rigidbody_world.solver_iterations=800
bpy.data.scenes["Scene"].rigidbody_world.use_split_impulse
bpy.data.scenes["Scene"].rigidbody_world.point_cache.frame_start = 1
bpy.data.scenes["Scene"].rigidbody_world.point_cache.frame_end = maxframe+100
bpy.ops.mesh.primitive_cube_add(size=0.6, enter_editmode=False, align='WORLD', location=(0-0.03, Ymax/2, Zmax*(1/2)), scale=(1, 1, 1))
bpy.data.objects["Cube.001"].scale[0]=(Zmax*5/3)
bpy.data.objects["Cube.001"].scale[1]=(Ymax*(20/6))
bpy.data.objects["Cube.001"].scale[2]=(0.6/6)
bpy.context.object.rotation_euler[0] = 0
bpy.context.object.rotation_euler[1] = 1.570796
bpy.context.object.rotation_euler[2] = 0
bpy.ops.rigidbody.object_add()
bpy.context.object.rigid_body.type = 'PASSIVE'
bpy.ops.mesh.primitive_cube_add(size=0.6, enter_editmode=False, align='WORLD', location=(Xmax+0.03, Ymax/2, Zmax*(1/2)), scale=(1, 1, 1))
bpy.data.objects["Cube.002"].scale[0]=(Zmax*5/3)
bpy.data.objects["Cube.002"].scale[1]=(Ymax*(20/6))
bpy.data.objects["Cube.002"].scale[2]=(0.6/6)
bpy.context.object.rotation_euler[0] = 0
bpy.context.object.rotation_euler[1] = 1.570796
bpy.context.object.rotation_euler[2] = 0
bpy.ops.rigidbody.object_add()
bpy.context.object.rigid_body.type = 'PASSIVE'
bpy.ops.mesh.primitive_cube_add(size=1.2, enter_editmode=False, align='WORLD', location=(Xmax/2, 0-0.03, Zmax*(1/2)), scale=(1, 1, 1))
bpy.data.objects["Cube.003"].scale[0]=(Zmax*5/6)
bpy.data.objects["Cube.003"].scale[1]=(Xmax)
bpy.data.objects["Cube.003"].scale[2]=(0.3/6)
bpy.context.object.rotation_euler[0] = 1.570796
bpy.context.object.rotation_euler[1] = 1.570796
bpy.context.object.rotation_euler[2] = 0
bpy.ops.rigidbody.object_add()
bpy.context.object.rigid_body.type = 'PASSIVE'
bpy.ops.mesh.primitive_cube_add(size=1.2, enter_editmode=False, align='WORLD', location=(Xmax/2, Ymax+0.03, Zmax/2), scale=(1, 1, 1))
bpy.data.objects["Cube.004"].scale[0]=Zmax*5/6
bpy.data.objects["Cube.004"].scale[1]=(Xmax)
bpy.data.objects["Cube.004"].scale[2]=(0.3/6)
bpy.context.object.rotation_euler[0] = 1.570796
bpy.context.object.rotation_euler[1] = 1.570796
bpy.context.object.rotation_euler[2] = 0
bpy.ops.rigidbody.object_add()
bpy.context.object.rigid_body.type = 'PASSIVE'
container_genration(Xmax,Ymax,Zmax)
### rock generation ###
def zlocations(noparticles):
zcords=[]
for i in range(int(noparticles)):
zcords.append(0.2+(0.065*i))
return zcords
def rockgenerator(particles,minsize,maxsize,zcords,Xmax,Ymax,dampingfactor=0.8,angular_damping=0.8):
for i in range(particles):
bpy.ops.mesh.add_mesh_rock(scale_X=(minsize, maxsize), skew_X=0, scale_Y=(minsize, maxsize), skew_Y=0, scale_Z=(minsize, maxsize), skew_Z=0, use_scale_dis=True, scale_fac=(1.2, 1.2, 1.2))
bpy.ops.rigidbody.object_add()
bpy.context.object.rigid_body.collision_shape = 'MESH'
bpy.context.object.rigid_body.collision_margin=0
bpy.context.object.rigid_body.linear_damping=dampingfactor
# bpy.context.object.rigid_body.angular_damping = angular_damping
bpy.context.object.rotation_euler[0] = random.uniform(0,6.265732)
bpy.context.object.rotation_euler[1] = random.uniform(0,6.265732)
bpy.context.object.rotation_euler[2] = random.uniform(0,6.265732)
bpy.context.object.location[0] = random.uniform(0.05,(Xmax-0.05))
bpy.context.object.location[1] = random.uniform(0.05,(Ymax-0.05))
zloc=random.choice(zcords)
bpy.context.object.location[2] = float(zloc)
zcords.remove(zloc)
return zcords
nop60=int(round(810*V))
noparticles=nop60
zcords=zlocations(noparticles)
zcords=rockgenerator(nop60,0.05,0.06,zcords,Xmax,Ymax,0.98,0.98)
print("Baking Physics")
override = {'scene': bpy.context.scene,
'point_cache': bpy.context.scene.rigidbody_world.point_cache}
bpy.context.scene.frame_current = maxframe
bpy.ops.ptcache.bake(override, bake=False)
UPDATE: Ive added the blend file in case this is more helpful, Ive also updated the python script to the script used for the last blend. Any help is greatly appreciated. The blend and python example contain less rocks than the original image.