Skip to content

Commit cb72352

Browse files
authored
Implement rendering capability for FSI-SPH in Chrono::Sensor (#738)
* Add CRM rendering capability * Add CRM rendering capability * Add assets for sprite rendering * Use a separate demo for CRM Rendering * Render FSI-SPH system natively on GPU * Removed unused functions * Implement the visual_spacing, remove unused assets * Rename demo_ROBOT_Viper_CRM_Wheelsinkage to demo_SEN_CRM_Rendering * Relocate particles for CRM Rendering demo * clang-format * Update mesh name prefix for regolith models
1 parent 6b4cc1d commit cb72352

23 files changed

Lines changed: 4464 additions & 324 deletions
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import bpy
2+
import random
3+
import os
4+
5+
# Directory where the OBJ files will be saved
6+
export_directory = "/tmp/regolith/" # Change this to your desired path
7+
8+
def create_granular_particle():
9+
# Create a base shape (e.g., icosphere for a round particle)
10+
bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=2, radius=0.5, location=(0, 0, 0)) # Generate at origin
11+
particle = bpy.context.object
12+
13+
# First Displace Modifier for Coarse Roughness
14+
bpy.ops.object.modifier_add(type='DISPLACE')
15+
displace_mod = particle.modifiers[-1]
16+
17+
# Create a texture for coarse displacement
18+
tex_name = "CoarseRoughTexture_" + str(random.randint(0, 10000))
19+
tex = bpy.data.textures.new(name=tex_name, type='VORONOI')
20+
tex.noise_intensity = random.uniform(0.8, 1.2)
21+
tex.distance_metric = 'MINKOVSKY'
22+
tex.minkovsky_exponent = random.uniform(0.6, 0.9)
23+
24+
displace_mod.texture = tex
25+
displace_mod.strength = random.uniform(0.1, 0.3)
26+
27+
bpy.ops.object.modifier_apply(modifier=displace_mod.name)
28+
29+
# Second Displace Modifier for Fine Surface Detail
30+
bpy.ops.object.modifier_add(type='DISPLACE')
31+
displace_mod2 = particle.modifiers[-1]
32+
tex_name2 = "FineRoughTexture_" + str(random.randint(0, 10000))
33+
tex2 = bpy.data.textures.new(name=tex_name2, type='CLOUDS')
34+
tex2.noise_scale = random.uniform(0.1, 0.15)
35+
displace_mod2.texture = tex2
36+
displace_mod2.strength = random.uniform(0.02, 0.08)
37+
38+
bpy.ops.object.modifier_apply(modifier=displace_mod2.name)
39+
40+
# Subdivision Surface Modifier for smoothing
41+
bpy.ops.object.modifier_add(type='SUBSURF')
42+
subsurf_mod = particle.modifiers[-1]
43+
subsurf_mod.levels = 1
44+
bpy.ops.object.modifier_apply(modifier=subsurf_mod.name)
45+
46+
# Random rotation for variety
47+
particle.rotation_euler = (random.uniform(0, 360), random.uniform(0, 360), random.uniform(0, 360))
48+
49+
# Randomize the shape: flat, elongated, or round
50+
shape_variation = random.choice(['round', 'flat', 'elongated'])
51+
52+
if shape_variation == 'flat':
53+
particle.scale = (random.uniform(0.008, 0.012),
54+
random.uniform(0.008, 0.012),
55+
random.uniform(0.004, 0.006))
56+
elif shape_variation == 'elongated':
57+
elongation_axis = random.choice(['x', 'y', 'z'])
58+
if elongation_axis == 'x':
59+
particle.scale = (random.uniform(0.015, 0.02),
60+
random.uniform(0.008, 0.012),
61+
random.uniform(0.008, 0.012))
62+
elif elongation_axis == 'y':
63+
particle.scale = (random.uniform(0.008, 0.012),
64+
random.uniform(0.015, 0.02),
65+
random.uniform(0.008, 0.012))
66+
elif elongation_axis == 'z':
67+
particle.scale = (random.uniform(0.008, 0.012),
68+
random.uniform(0.008, 0.012),
69+
random.uniform(0.015, 0.02))
70+
else:
71+
particle.scale = (random.uniform(0.008, 0.012),
72+
random.uniform(0.008, 0.012),
73+
random.uniform(0.008, 0.012))
74+
75+
# Create a new material for lunar regolith appearance
76+
mat = bpy.data.materials.new(name="LunarRegolithMaterial")
77+
mat.use_nodes = True
78+
nodes = mat.node_tree.nodes
79+
links = mat.node_tree.links
80+
81+
# Clear default nodes
82+
for node in nodes:
83+
nodes.remove(node)
84+
85+
# Add necessary nodes
86+
output_node = nodes.new(type='ShaderNodeOutputMaterial')
87+
principled_bsdf = nodes.new(type='ShaderNodeBsdfPrincipled')
88+
89+
# Set base color to dark gray (lunar regolith color)
90+
principled_bsdf.inputs['Base Color'].default_value = (0.3, 0.3, 0.3, 1.0)
91+
92+
# Increase roughness for a dusty look
93+
principled_bsdf.inputs['Roughness'].default_value = 0.9
94+
95+
# Add noise texture for bump mapping (surface roughness)
96+
noise_texture = nodes.new(type='ShaderNodeTexNoise')
97+
noise_texture.inputs['Scale'].default_value = 30.0
98+
noise_texture.inputs['Detail'].default_value = 2.0
99+
100+
# Add bump node to connect noise texture for surface detail
101+
bump_node = nodes.new(type='ShaderNodeBump')
102+
bump_node.inputs['Strength'].default_value = 0.3 # Moderate bump effect
103+
104+
# Connect noise texture to bump node
105+
links.new(noise_texture.outputs['Fac'], bump_node.inputs['Height'])
106+
107+
# Connect bump node to Principled BSDF normal input
108+
links.new(bump_node.outputs['Normal'], principled_bsdf.inputs['Normal'])
109+
110+
# Connect BSDF to Material Output
111+
links.new(principled_bsdf.outputs['BSDF'], output_node.inputs['Surface'])
112+
113+
# Assign the material to the particle
114+
particle.data.materials.append(mat)
115+
116+
return particle, mat
117+
118+
def export_particle_as_obj(particle, file_name):
119+
# Select the particle before exporting
120+
bpy.ops.object.select_all(action='DESELECT') # Deselect all
121+
particle.select_set(True) # Select the particle to export
122+
123+
# Export the particle as an OBJ file with the material
124+
bpy.ops.wm.obj_export(filepath=file_name, export_selected_objects=True, export_materials=True)
125+
126+
def delete_particle_and_material(particle, material):
127+
# Delete the particle and its material
128+
bpy.data.objects.remove(particle, do_unlink=True)
129+
bpy.data.materials.remove(material, do_unlink=True)
130+
131+
# Number of granular particles to generate and export
132+
num_particles = 10
133+
134+
for i in range(num_particles):
135+
# Step 1: Generate a particle
136+
particle, material = create_granular_particle()
137+
138+
# Step 2: Export the particle as OBJ with the material
139+
obj_file_name = os.path.join(export_directory, f"particle_{i+1}.obj")
140+
export_particle_as_obj(particle, obj_file_name)
141+
142+
# Step 3: Delete the particle and material
143+
delete_particle_and_material(particle, material)
144+
145+
print(f"Particle {i+1} exported and deleted.")
146+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Blender 4.2.1 LTS MTL File: 'lunarregolith.blend'
2+
# www.blender.org
3+
4+
newmtl LunarRegolithMaterial.032
5+
Ns 10.000005
6+
Ka 1.000000 1.000000 1.000000
7+
Kd 0.500000 0.500000 0.500000
8+
Ks 0.500000 0.500000 0.500000
9+
Ke 0.000000 0.000000 0.000000
10+
Ni 1.500000
11+
d 1.000000
12+
illum 2

0 commit comments

Comments
 (0)