diff --git a/data/models/regolith/generate_regolith.py b/data/models/regolith/generate_regolith.py new file mode 100644 index 0000000000..61f606a64e --- /dev/null +++ b/data/models/regolith/generate_regolith.py @@ -0,0 +1,146 @@ +import bpy +import random +import os + +# Directory where the OBJ files will be saved +export_directory = "/tmp/regolith/" # Change this to your desired path + +def create_granular_particle(): + # Create a base shape (e.g., icosphere for a round particle) + bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=2, radius=0.5, location=(0, 0, 0)) # Generate at origin + particle = bpy.context.object + + # First Displace Modifier for Coarse Roughness + bpy.ops.object.modifier_add(type='DISPLACE') + displace_mod = particle.modifiers[-1] + + # Create a texture for coarse displacement + tex_name = "CoarseRoughTexture_" + str(random.randint(0, 10000)) + tex = bpy.data.textures.new(name=tex_name, type='VORONOI') + tex.noise_intensity = random.uniform(0.8, 1.2) + tex.distance_metric = 'MINKOVSKY' + tex.minkovsky_exponent = random.uniform(0.6, 0.9) + + displace_mod.texture = tex + displace_mod.strength = random.uniform(0.1, 0.3) + + bpy.ops.object.modifier_apply(modifier=displace_mod.name) + + # Second Displace Modifier for Fine Surface Detail + bpy.ops.object.modifier_add(type='DISPLACE') + displace_mod2 = particle.modifiers[-1] + tex_name2 = "FineRoughTexture_" + str(random.randint(0, 10000)) + tex2 = bpy.data.textures.new(name=tex_name2, type='CLOUDS') + tex2.noise_scale = random.uniform(0.1, 0.15) + displace_mod2.texture = tex2 + displace_mod2.strength = random.uniform(0.02, 0.08) + + bpy.ops.object.modifier_apply(modifier=displace_mod2.name) + + # Subdivision Surface Modifier for smoothing + bpy.ops.object.modifier_add(type='SUBSURF') + subsurf_mod = particle.modifiers[-1] + subsurf_mod.levels = 1 + bpy.ops.object.modifier_apply(modifier=subsurf_mod.name) + + # Random rotation for variety + particle.rotation_euler = (random.uniform(0, 360), random.uniform(0, 360), random.uniform(0, 360)) + + # Randomize the shape: flat, elongated, or round + shape_variation = random.choice(['round', 'flat', 'elongated']) + + if shape_variation == 'flat': + particle.scale = (random.uniform(0.008, 0.012), + random.uniform(0.008, 0.012), + random.uniform(0.004, 0.006)) + elif shape_variation == 'elongated': + elongation_axis = random.choice(['x', 'y', 'z']) + if elongation_axis == 'x': + particle.scale = (random.uniform(0.015, 0.02), + random.uniform(0.008, 0.012), + random.uniform(0.008, 0.012)) + elif elongation_axis == 'y': + particle.scale = (random.uniform(0.008, 0.012), + random.uniform(0.015, 0.02), + random.uniform(0.008, 0.012)) + elif elongation_axis == 'z': + particle.scale = (random.uniform(0.008, 0.012), + random.uniform(0.008, 0.012), + random.uniform(0.015, 0.02)) + else: + particle.scale = (random.uniform(0.008, 0.012), + random.uniform(0.008, 0.012), + random.uniform(0.008, 0.012)) + + # Create a new material for lunar regolith appearance + mat = bpy.data.materials.new(name="LunarRegolithMaterial") + mat.use_nodes = True + nodes = mat.node_tree.nodes + links = mat.node_tree.links + + # Clear default nodes + for node in nodes: + nodes.remove(node) + + # Add necessary nodes + output_node = nodes.new(type='ShaderNodeOutputMaterial') + principled_bsdf = nodes.new(type='ShaderNodeBsdfPrincipled') + + # Set base color to dark gray (lunar regolith color) + principled_bsdf.inputs['Base Color'].default_value = (0.3, 0.3, 0.3, 1.0) + + # Increase roughness for a dusty look + principled_bsdf.inputs['Roughness'].default_value = 0.9 + + # Add noise texture for bump mapping (surface roughness) + noise_texture = nodes.new(type='ShaderNodeTexNoise') + noise_texture.inputs['Scale'].default_value = 30.0 + noise_texture.inputs['Detail'].default_value = 2.0 + + # Add bump node to connect noise texture for surface detail + bump_node = nodes.new(type='ShaderNodeBump') + bump_node.inputs['Strength'].default_value = 0.3 # Moderate bump effect + + # Connect noise texture to bump node + links.new(noise_texture.outputs['Fac'], bump_node.inputs['Height']) + + # Connect bump node to Principled BSDF normal input + links.new(bump_node.outputs['Normal'], principled_bsdf.inputs['Normal']) + + # Connect BSDF to Material Output + links.new(principled_bsdf.outputs['BSDF'], output_node.inputs['Surface']) + + # Assign the material to the particle + particle.data.materials.append(mat) + + return particle, mat + +def export_particle_as_obj(particle, file_name): + # Select the particle before exporting + bpy.ops.object.select_all(action='DESELECT') # Deselect all + particle.select_set(True) # Select the particle to export + + # Export the particle as an OBJ file with the material + bpy.ops.wm.obj_export(filepath=file_name, export_selected_objects=True, export_materials=True) + +def delete_particle_and_material(particle, material): + # Delete the particle and its material + bpy.data.objects.remove(particle, do_unlink=True) + bpy.data.materials.remove(material, do_unlink=True) + +# Number of granular particles to generate and export +num_particles = 10 + +for i in range(num_particles): + # Step 1: Generate a particle + particle, material = create_granular_particle() + + # Step 2: Export the particle as OBJ with the material + obj_file_name = os.path.join(export_directory, f"particle_{i+1}.obj") + export_particle_as_obj(particle, obj_file_name) + + # Step 3: Delete the particle and material + delete_particle_and_material(particle, material) + + print(f"Particle {i+1} exported and deleted.") + diff --git a/data/models/regolith/particle_1.mtl b/data/models/regolith/particle_1.mtl new file mode 100644 index 0000000000..681ee11066 --- /dev/null +++ b/data/models/regolith/particle_1.mtl @@ -0,0 +1,12 @@ +# Blender 4.2.1 LTS MTL File: 'lunarregolith.blend' +# www.blender.org + +newmtl LunarRegolithMaterial.032 +Ns 10.000005 +Ka 1.000000 1.000000 1.000000 +Kd 0.500000 0.500000 0.500000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 diff --git a/data/models/regolith/particle_1.obj b/data/models/regolith/particle_1.obj new file mode 100644 index 0000000000..35086747eb --- /dev/null +++ b/data/models/regolith/particle_1.obj @@ -0,0 +1,1013 @@ +# Blender 4.2.1 LTS +# www.blender.org +mtllib particle_1.mtl +o Icosphere +v 0.000694 -0.003137 0.003261 +v -0.000780 0.000467 0.002717 +v -0.003505 -0.002282 0.001961 +v -0.000353 -0.002344 -0.000282 +v 0.002113 -0.001492 -0.000068 +v 0.001506 0.000288 0.001493 +v -0.002020 0.001255 0.000136 +v -0.001870 -0.000353 -0.001526 +v 0.000291 -0.000147 -0.001070 +v 0.001827 0.001177 -0.001045 +v 0.000235 0.001312 0.000237 +v -0.000559 0.002203 -0.002336 +v -0.001625 -0.003275 0.003176 +v -0.000190 -0.001152 0.003332 +v -0.002473 -0.000805 0.003197 +v 0.000785 0.000503 0.002584 +v 0.001592 -0.001150 0.002634 +v 0.000050 -0.003543 0.001408 +v -0.001963 -0.003087 0.000652 +v 0.001737 -0.002402 0.001421 +v 0.000859 -0.001886 -0.000157 +v 0.002011 -0.000679 0.000836 +v -0.000106 0.000881 0.001109 +v 0.001078 0.001353 0.001133 +v -0.002939 -0.000008 0.000958 +v -0.001774 0.001030 0.001658 +v -0.001152 -0.001389 -0.000906 +v -0.002943 -0.001294 -0.000321 +v 0.001136 -0.000768 -0.000905 +v 0.000063 -0.000899 -0.000756 +v 0.001354 0.000587 0.000207 +v 0.001926 -0.000136 -0.000571 +v -0.000672 0.001208 0.000158 +v -0.002543 0.000617 -0.000949 +v -0.000585 -0.000260 -0.001545 +v 0.001246 0.000415 -0.001599 +v 0.001042 0.001701 -0.000312 +v -0.001462 0.001846 -0.001151 +v -0.000096 0.002182 -0.000889 +v -0.001397 0.000937 -0.002130 +v 0.000042 0.000848 -0.002292 +v 0.000862 0.001869 -0.001831 +v -0.000351 -0.003398 0.003402 +v -0.000546 -0.000169 0.003132 +v -0.003233 -0.001699 0.002769 +v 0.000027 0.000501 0.002704 +v 0.001640 -0.000320 0.002067 +v 0.000424 -0.003614 0.002562 +v -0.001048 -0.002841 0.000065 +v 0.001323 -0.002957 0.002500 +v 0.001616 -0.001738 -0.000139 +v 0.001754 -0.000178 0.001196 +v -0.000441 0.000763 0.001952 +v 0.000665 0.001373 0.000664 +v -0.003447 -0.001205 0.001548 +v -0.001939 0.001197 0.000878 +v -0.000741 -0.001919 -0.000601 +v -0.002418 -0.000773 -0.001074 +v 0.001716 -0.001197 -0.000561 +v 0.000170 -0.000475 -0.000841 +v 0.001409 0.000435 0.000849 +v 0.001927 0.000576 -0.000856 +v -0.001383 0.001303 0.000181 +v -0.002326 0.000079 -0.001371 +v -0.000113 -0.000183 -0.001254 +v 0.001702 0.000875 -0.001416 +v 0.000618 0.001592 0.000034 +v -0.001781 0.001540 -0.000498 +v -0.000361 0.002403 -0.001736 +v -0.001689 0.000254 -0.001859 +v 0.000195 0.000265 -0.001650 +v 0.001504 0.001572 -0.001455 +v -0.002849 -0.002921 0.002714 +v 0.000307 -0.002337 0.003485 +v -0.001612 -0.000015 0.003103 +v 0.001279 0.000454 0.002123 +v 0.001259 -0.002254 0.003112 +v -0.000199 -0.003039 0.000394 +v -0.002987 -0.002893 0.001391 +v 0.002048 -0.001940 0.000561 +v 0.000225 -0.002147 -0.000231 +v 0.002224 -0.001193 0.000353 +v 0.000107 0.001033 0.000581 +v 0.001318 0.000904 0.001383 +v -0.002488 0.000808 0.000494 +v -0.001354 0.000786 0.002306 +v -0.001555 -0.000873 -0.001279 +v -0.003437 -0.001910 0.000817 +v 0.000667 -0.000421 -0.000955 +v -0.000116 -0.001581 -0.000592 +v 0.001639 0.000907 -0.000473 +v 0.002117 -0.000876 -0.000322 +v -0.000161 0.001188 0.000156 +v -0.002373 0.001056 -0.000389 +v -0.001229 -0.000332 -0.001632 +v 0.000729 0.000080 -0.001358 +v 0.001520 0.001514 -0.000749 +v -0.001051 0.002178 -0.001868 +v 0.000084 0.001708 -0.000250 +v -0.001007 0.001693 -0.002383 +v -0.000278 0.001649 -0.002533 +v 0.000127 0.002167 -0.002218 +v 0.000392 0.002225 -0.001433 +v 0.000512 0.002005 -0.000620 +v 0.001042 0.001917 -0.001102 +v 0.000489 0.001435 -0.002263 +v 0.001151 0.001174 -0.001863 +v 0.000680 0.000652 -0.001986 +v -0.000682 0.000931 -0.002375 +v -0.000308 0.000272 -0.001948 +v -0.000992 0.000288 -0.001979 +v -0.001569 0.001528 -0.001775 +v -0.002041 0.000826 -0.001629 +v -0.002080 0.001331 -0.001103 +v -0.000787 0.002139 -0.001065 +v -0.001054 0.001605 -0.000473 +v -0.000390 0.001691 -0.000367 +v 0.001063 0.001536 0.000446 +v 0.001219 0.001064 0.000700 +v 0.001243 0.001218 -0.000023 +v 0.001677 0.000148 -0.001156 +v 0.001645 -0.000513 -0.000839 +v 0.001200 -0.000212 -0.001237 +v -0.000264 -0.000582 -0.001078 +v -0.000470 -0.001120 -0.000882 +v -0.000814 -0.000786 -0.001264 +v -0.002859 -0.000294 -0.000696 +v -0.003169 -0.000696 0.000281 +v -0.002817 0.000332 -0.000093 +v -0.001187 0.001150 0.000872 +v -0.000925 0.000995 0.001360 +v -0.000416 0.000960 0.000603 +v 0.001701 0.000225 -0.000200 +v 0.001657 -0.000027 0.000484 +v 0.002018 -0.000419 0.000094 +v 0.000577 -0.000818 -0.000790 +v 0.001034 -0.001289 -0.000609 +v 0.000439 -0.001344 -0.000545 +v -0.002098 -0.001469 -0.000716 +v -0.001605 -0.002272 -0.000288 +v -0.002638 -0.002296 0.000133 +v -0.002448 0.000639 0.001460 +v -0.002915 -0.000389 0.002214 +v -0.002245 0.000303 0.002544 +v 0.000570 0.001142 0.001165 +v 0.000369 0.000806 0.001904 +v 0.000999 0.001032 0.001883 +v 0.001917 -0.000929 0.001747 +v 0.001800 -0.001906 0.002169 +v 0.002052 -0.001552 0.001171 +v 0.001367 -0.002303 0.000576 +v 0.000998 -0.003120 0.001481 +v 0.000544 -0.002774 0.000534 +v -0.000993 -0.003525 0.001078 +v -0.000775 -0.003735 0.002417 +v -0.001954 -0.003479 0.001998 +v 0.001219 -0.000262 0.002753 +v 0.000404 -0.000200 0.003056 +v 0.000848 -0.001178 0.003142 +v -0.002248 -0.002144 0.003431 +v -0.000951 -0.002332 0.003513 +v -0.001414 -0.001030 0.003435 +v -0.000331 -0.002767 0.003558 +v -0.000010 0.000091 0.003014 +v -0.000238 -0.003713 0.002898 +v 0.000975 -0.003335 0.002209 +v 0.001535 -0.002430 0.002671 +v 0.000008 0.000701 0.002195 +v -0.003296 -0.001094 0.002237 +v -0.001138 -0.002378 -0.000313 +v 0.001473 -0.001433 -0.000482 +v 0.001595 0.000073 0.000814 +v -0.000918 0.000898 0.001848 +v -0.003442 -0.001288 0.000870 +v -0.000425 -0.001514 -0.000716 +v 0.001870 -0.000884 -0.000595 +v 0.001310 0.000822 0.000966 +v -0.001392 0.001486 -0.000279 +v -0.002048 0.000406 -0.001672 +v -0.000078 0.000109 -0.001615 +v 0.001500 0.001243 -0.001623 +v 0.000391 0.001787 -0.000281 +v 0.000065 0.002344 -0.001844 +v 0.000660 0.002091 -0.001042 +v 0.001415 0.001725 -0.001130 +v 0.000129 0.001804 -0.002416 +v 0.000795 0.001075 -0.002092 +v 0.000536 0.000329 -0.001675 +v -0.000680 0.001449 -0.002520 +v -0.000652 0.000480 -0.002144 +v -0.001310 0.000066 -0.001856 +v -0.001241 0.001854 -0.002066 +v -0.001935 0.001241 -0.001518 +v -0.002119 0.001365 -0.000683 +v -0.000768 0.002332 -0.001580 +v -0.000734 0.001827 -0.000623 +v -0.000151 0.001523 -0.000148 +v 0.000819 0.001528 0.000411 +v 0.001166 0.001305 0.000396 +v 0.001477 0.001221 -0.000417 +v 0.001837 0.000536 -0.001166 +v 0.001505 -0.000198 -0.001115 +v 0.000872 -0.000199 -0.001173 +v -0.000079 -0.000407 -0.001010 +v -0.000498 -0.000814 -0.001084 +v -0.001170 -0.000685 -0.001416 +v -0.002599 -0.000346 -0.001079 +v -0.002981 -0.000193 -0.000208 +v -0.002591 0.000750 -0.000005 +v -0.001500 0.001243 0.000681 +v -0.000838 0.001031 0.000930 +v -0.000147 0.000989 0.000415 +v 0.001781 0.000576 -0.000522 +v 0.001771 -0.000078 0.000131 +v 0.002191 -0.000826 0.000028 +v 0.000463 -0.000566 -0.000827 +v 0.000674 -0.001123 -0.000669 +v 0.000191 -0.001660 -0.000482 +v -0.002046 -0.001044 -0.001059 +v -0.002122 -0.002038 -0.000326 +v -0.003133 -0.002441 0.000751 +v -0.002319 0.000940 0.000949 +v -0.002567 0.000227 0.002115 +v -0.001798 0.000406 0.002743 +v 0.000448 0.001183 0.000791 +v 0.000680 0.001025 0.001668 +v 0.001228 0.000868 0.001844 +v 0.001814 -0.000472 0.001684 +v 0.001960 -0.001451 0.001705 +v 0.002170 -0.001609 0.000694 +v 0.001733 -0.002019 0.000320 +v 0.000974 -0.002756 0.000844 +v 0.000207 -0.002693 0.000207 +v -0.000752 -0.003220 0.000482 +v -0.001250 -0.003666 0.001839 +v -0.002675 -0.003209 0.002088 +v 0.001412 -0.000038 0.002363 +v 0.000854 -0.000514 0.003021 +v 0.000853 -0.001941 0.003314 +v -0.002888 -0.002335 0.003106 +v -0.001565 -0.001844 0.003524 +v -0.001215 -0.000381 0.003276 +vn 0.2045 -0.2013 0.9579 +vn 0.0229 0.1366 0.9904 +vn -0.1993 -0.2117 0.9568 +vn -0.0431 0.5643 0.8245 +vn 0.0856 0.2348 0.9683 +vn 0.1830 0.5181 0.8355 +vn 0.3092 -0.8120 0.4950 +vn -0.2042 -0.8958 0.3947 +vn 0.1104 -0.9896 -0.0917 +vn 0.5771 -0.7604 0.2978 +vn 0.3828 -0.8999 -0.2088 +vn 0.7175 -0.6862 -0.1196 +vn 0.7290 -0.4110 0.5475 +vn 0.9176 -0.3723 0.1394 +vn 0.8711 -0.0242 0.4905 +vn -0.0426 0.9345 0.3535 +vn 0.0473 0.9261 0.3744 +vn -0.0422 0.9848 0.1685 +vn -0.9685 0.1195 0.2183 +vn -0.7512 0.4038 0.5221 +vn -0.8782 0.4566 0.1424 +vn 0.0572 -0.5969 -0.8003 +vn -0.2419 -0.6717 -0.7002 +vn -0.0989 -0.5130 -0.8527 +vn 0.3890 -0.6099 -0.6904 +vn 0.0924 -0.6599 -0.7456 +vn 0.1266 -0.4864 -0.8645 +vn 0.8790 0.4755 -0.0353 +vn 0.8753 0.4833 -0.0169 +vn 0.8903 0.4543 0.0308 +vn 0.1819 0.8922 0.4134 +vn 0.2064 0.9566 0.2057 +vn 0.0924 0.9625 0.2551 +vn -0.9991 0.0233 -0.0364 +vn -0.9279 0.3687 -0.0554 +vn -0.9216 0.0326 -0.3867 +vn 0.2462 -0.4322 -0.8675 +vn 0.1729 -0.3777 -0.9096 +vn 0.3219 -0.3135 -0.8934 +vn 0.6608 -0.3222 -0.6779 +vn 0.3235 -0.3280 -0.8875 +vn 0.7265 -0.0328 -0.6863 +vn 0.9584 0.2745 -0.0782 +vn 0.9588 0.2823 -0.0320 +vn 0.9112 0.4104 -0.0364 +vn -0.0915 0.9225 0.3751 +vn 0.0729 0.8914 0.4473 +vn -0.0951 0.9173 0.3867 +vn -0.5341 -0.2781 -0.7984 +vn -0.8057 0.1062 -0.5827 +vn -0.5658 -0.0182 -0.8243 +vn 0.3367 -0.7438 -0.5774 +vn 0.4280 -0.6967 -0.5757 +vn 0.3771 -0.6582 -0.6516 +vn 0.8598 0.2176 -0.4620 +vn 0.5532 -0.1938 -0.8102 +vn 0.5528 0.3051 -0.7754 +vn -0.1748 0.7510 0.6367 +vn 0.1369 0.8470 0.5137 +vn -0.0647 0.8131 0.5785 +vn 0.1519 0.9699 0.1903 +vn 0.5005 0.8344 -0.2306 +vn 0.0819 0.9258 -0.3689 +vn 0.1624 0.9583 0.2350 +vn 0.3903 0.8812 0.2666 +vn 0.4757 0.8709 -0.1230 +vn 0.5055 0.8245 0.2544 +vn 0.7964 0.6040 0.0316 +vn 0.4806 0.8531 -0.2031 +vn 0.5706 0.3286 -0.7526 +vn 0.2916 -0.1494 -0.9448 +vn 0.1459 0.4293 -0.8913 +vn 0.5648 0.2137 -0.7971 +vn 0.5073 -0.2661 -0.8196 +vn 0.3176 -0.2465 -0.9156 +vn 0.1601 -0.7235 -0.6715 +vn 0.0548 -0.7953 -0.6037 +vn 0.1001 -0.7207 -0.6860 +vn 0.0869 -0.2605 -0.9615 +vn -0.3750 -0.1688 -0.9115 +vn -0.1805 0.2602 -0.9485 +vn 0.0862 -0.5067 -0.8578 +vn 0.0205 -0.6283 -0.7777 +vn -0.2670 -0.4090 -0.8726 +vn 0.1269 -0.5218 -0.8435 +vn -0.1633 -0.4655 -0.8699 +vn -0.1472 -0.3109 -0.9390 +vn -0.7467 0.1719 -0.6426 +vn -0.7815 0.5960 -0.1843 +vn -0.5401 0.5894 -0.6008 +vn -0.6440 0.2869 -0.7091 +vn -0.8105 0.3920 -0.4352 +vn -0.6568 0.6932 -0.2968 +vn -0.8387 0.5256 -0.1422 +vn -0.6028 0.7780 0.1774 +vn -0.5863 0.8100 0.0102 +vn -0.4767 0.8565 0.1982 +vn -0.1030 0.9464 0.3062 +vn -0.2609 0.9371 -0.2320 +vn -0.3629 0.7671 0.5291 +vn -0.1981 0.7605 0.6183 +vn -0.1815 0.7775 0.6022 +vn -0.0225 0.7156 0.6981 +vn -0.3067 0.6714 0.6746 +vn -0.1856 0.7412 0.6451 +vn -0.2145 0.9288 0.3023 +vn -0.0736 0.9748 0.2105 +vn -0.4117 0.8513 0.3254 +vn 0.9309 0.3542 0.0890 +vn 0.9693 0.2317 0.0819 +vn 0.9091 0.4107 0.0697 +vn 0.8100 0.3238 0.4889 +vn 0.8256 0.3591 0.4352 +vn 0.6990 0.5279 0.4824 +vn 0.8851 -0.2368 -0.4007 +vn 0.6030 -0.2875 -0.7442 +vn 0.9386 0.0772 -0.3363 +vn 0.7693 -0.3053 -0.5612 +vn 0.3507 -0.5150 -0.7821 +vn 0.4547 -0.4248 -0.7828 +vn -0.2418 -0.5033 -0.8296 +vn -0.1920 -0.6006 -0.7762 +vn -0.1061 -0.5215 -0.8466 +vn 0.5128 -0.2721 -0.8143 +vn 0.5561 -0.5008 -0.6633 +vn 0.3398 -0.6417 -0.6876 +vn 0.4003 -0.4465 -0.8003 +vn 0.2954 -0.5723 -0.7650 +vn 0.4413 -0.5321 -0.7226 +vn 0.0842 -0.5829 -0.8082 +vn -0.1016 -0.5000 -0.8600 +vn 0.1855 -0.5103 -0.8398 +vn -0.7596 -0.2158 -0.6136 +vn -0.8113 0.1247 -0.5712 +vn -0.5099 -0.2342 -0.8278 +vn -0.9529 -0.0023 -0.3033 +vn -0.9476 0.3191 -0.0160 +vn -0.9284 0.2885 -0.2340 +vn -0.8633 0.4982 0.0798 +vn -0.6747 0.7288 0.1172 +vn -0.8671 0.4854 -0.1121 +vn 0.0628 0.9715 0.2286 +vn 0.1503 0.9734 0.1731 +vn -0.0730 0.9930 0.0924 +vn 0.1668 0.9620 0.2159 +vn 0.1820 0.9803 0.0766 +vn 0.3199 0.9064 0.2757 +vn -0.1302 0.9786 0.1595 +vn -0.3941 0.7544 0.5249 +vn 0.1118 0.8578 0.5017 +vn 0.8329 0.2690 0.4837 +vn 0.9047 0.1575 0.3960 +vn 0.8682 0.2859 0.4056 +vn 0.8353 0.4966 0.2358 +vn 0.8106 0.5523 0.1945 +vn 0.8582 0.4911 0.1495 +vn 0.9409 0.3014 0.1545 +vn 0.9772 -0.0850 -0.1945 +vn 0.9535 0.2880 -0.0893 +vn -0.2073 -0.3341 -0.9195 +vn -0.0268 -0.1768 -0.9839 +vn -0.1328 -0.5378 -0.8325 +vn -0.1085 -0.4480 -0.8874 +vn -0.0356 -0.5633 -0.8255 +vn -0.0243 -0.4170 -0.9086 +vn 0.2812 -0.4140 -0.8658 +vn 0.2171 -0.4288 -0.8769 +vn 0.2065 -0.3006 -0.9311 +vn -0.1100 -0.6273 -0.7710 +vn -0.4278 -0.5608 -0.7089 +vn -0.2546 -0.4960 -0.8301 +vn -0.1433 -0.5321 -0.8345 +vn -0.2641 -0.6789 -0.6851 +vn -0.4440 -0.4844 -0.7538 +vn -0.4543 -0.7494 -0.4817 +vn -0.8442 -0.4996 -0.1940 +vn -0.6983 -0.4234 -0.5772 +vn -0.8294 0.5436 0.1287 +vn -0.5255 0.7951 0.3028 +vn -0.6134 0.7858 0.0789 +vn -0.8452 0.5072 0.1684 +vn -0.7275 0.4640 0.5054 +vn -0.5655 0.7516 0.3396 +vn -0.4101 0.5122 0.7547 +vn -0.0244 0.7092 0.7046 +vn -0.3215 0.8236 0.4672 +vn -0.4035 0.9023 0.1517 +vn -0.4054 0.8566 0.3191 +vn -0.5228 0.7630 0.3801 +vn -0.3729 0.8788 0.2978 +vn -0.2769 0.8209 0.4994 +vn -0.3066 0.8961 0.3208 +vn 0.5816 0.5362 0.6118 +vn 0.9241 0.3030 0.2329 +vn 0.7101 0.6424 0.2882 +vn 0.9040 0.2188 0.3673 +vn 0.9404 0.3086 0.1431 +vn 0.8941 0.4082 0.1843 +vn 0.9334 0.0418 0.3565 +vn 0.9525 -0.2673 0.1458 +vn 0.9868 0.0881 0.1357 +vn 0.9252 -0.3226 0.2000 +vn 0.9601 -0.2566 -0.1109 +vn 0.9585 0.1251 0.2563 +vn 0.4435 -0.8461 -0.2957 +vn 0.1877 -0.8015 -0.5677 +vn 0.4797 -0.7182 -0.5040 +vn 0.6099 -0.6958 -0.3792 +vn 0.3853 -0.7918 -0.4740 +vn 0.4117 -0.6639 -0.6243 +vn 0.3731 -0.7796 -0.5031 +vn 0.2478 -0.6321 -0.7342 +vn 0.3947 -0.6233 -0.6751 +vn 0.1573 -0.8820 -0.4442 +vn -0.1668 -0.8214 -0.5454 +vn 0.1202 -0.6831 -0.7203 +vn 0.0401 -0.9861 -0.1609 +vn -0.2748 -0.9408 0.1986 +vn -0.2997 -0.9158 -0.2673 +vn -0.3406 -0.8991 0.2749 +vn -0.7480 -0.6606 0.0641 +vn -0.3594 -0.8977 -0.2549 +vn 0.6312 0.4817 0.6079 +vn 0.8337 0.2545 0.4900 +vn 0.8857 0.3949 0.2442 +vn 0.3462 0.3902 0.8532 +vn 0.1845 0.1687 0.9682 +vn 0.5462 0.1296 0.8276 +vn 0.1715 0.2053 0.9636 +vn 0.3694 -0.0902 0.9249 +vn 0.5488 0.1876 0.8146 +vn -0.3799 -0.4512 0.8075 +vn -0.5260 0.0924 0.8455 +vn -0.8490 -0.2868 0.4438 +vn -0.0948 -0.2317 0.9682 +vn 0.0925 0.0922 0.9914 +vn -0.1907 0.1390 0.9717 +vn 0.1156 0.2241 0.9677 +vn 0.0536 0.5301 0.8462 +vn -0.1532 0.2799 0.9477 +vt 0.181819 0.000000 +vt 0.204546 0.039365 +vt 0.181819 0.052487 +vt 0.159092 0.039365 +vt 0.227273 0.078731 +vt 0.181819 0.078731 +vt 0.136365 0.078731 +vt 0.272728 0.157461 +vt 0.295455 0.118096 +vt 0.318182 0.131218 +vt 0.318182 0.157461 +vt 0.318182 0.078731 +vt 0.340910 0.118096 +vt 0.363637 0.157461 +vt 0.909091 0.000000 +vt 0.931818 0.039365 +vt 0.909091 0.052487 +vt 0.886364 0.039365 +vt 0.954545 0.078731 +vt 0.909091 0.078731 +vt 0.863636 0.078731 +vt 0.727273 0.000000 +vt 0.750000 0.039365 +vt 0.727273 0.052487 +vt 0.704546 0.039365 +vt 0.772727 0.078731 +vt 0.727273 0.078731 +vt 0.681818 0.078731 +vt 0.545455 0.000000 +vt 0.568182 0.039365 +vt 0.545455 0.052487 +vt 0.522728 0.039365 +vt 0.590909 0.078731 +vt 0.545455 0.078731 +vt 0.500000 0.078731 +vt 0.318182 0.183704 +vt 0.295455 0.196826 +vt 0.340910 0.196826 +vt 0.318183 0.236191 +vt 0.090910 0.157461 +vt 0.136365 0.157461 +vt 0.136365 0.183704 +vt 0.113637 0.196826 +vt 0.181819 0.157461 +vt 0.159092 0.196826 +vt 0.136364 0.236191 +vt 0.818182 0.157461 +vt 0.863636 0.157461 +vt 0.863636 0.183704 +vt 0.840909 0.196826 +vt 0.909091 0.157461 +vt 0.886364 0.196826 +vt 0.863637 0.236191 +vt 0.636364 0.157461 +vt 0.681819 0.157461 +vt 0.681818 0.183704 +vt 0.659091 0.196826 +vt 0.727273 0.157461 +vt 0.704546 0.196826 +vt 0.681819 0.236191 +vt 0.454546 0.157461 +vt 0.500001 0.157461 +vt 0.500001 0.183704 +vt 0.477273 0.196826 +vt 0.545455 0.157461 +vt 0.522728 0.196826 +vt 0.500001 0.236191 +vt 0.272728 0.209948 +vt 0.250001 0.196826 +vt 0.272728 0.236191 +vt 0.227274 0.236191 +vt 0.090910 0.209948 +vt 0.068183 0.196826 +vt 0.090910 0.236191 +vt 0.045455 0.236191 +vt 0.818182 0.209948 +vt 0.795455 0.196826 +vt 0.818182 0.236191 +vt 0.772728 0.236191 +vt 0.636364 0.209948 +vt 0.613637 0.196826 +vt 0.636364 0.236191 +vt 0.590910 0.236191 +vt 0.454546 0.209948 +vt 0.431819 0.196826 +vt 0.454546 0.236191 +vt 0.409092 0.236191 +vt 0.181819 0.314921 +vt 0.227274 0.314921 +vt 0.227274 0.341165 +vt 0.204546 0.354286 +vt 0.272728 0.314921 +vt 0.250001 0.354286 +vt 0.227273 0.393651 +vt 0.000000 0.314921 +vt 0.045455 0.314921 +vt 0.045455 0.341165 +vt 0.022728 0.354286 +vt 0.090910 0.314921 +vt 0.068182 0.354286 +vt 0.045455 0.393651 +vt 0.727273 0.314921 +vt 0.772728 0.314921 +vt 0.772727 0.341165 +vt 0.750000 0.354286 +vt 0.818182 0.314921 +vt 0.795455 0.354286 +vt 0.772727 0.393651 +vt 0.545455 0.314921 +vt 0.590910 0.314921 +vt 0.590909 0.341165 +vt 0.568182 0.354286 +vt 0.636364 0.314921 +vt 0.613637 0.354286 +vt 0.590909 0.393651 +vt 0.363637 0.314921 +vt 0.409092 0.314921 +vt 0.409092 0.341165 +vt 0.386364 0.354286 +vt 0.454546 0.314921 +vt 0.431819 0.354286 +vt 0.409092 0.393651 +vt 0.454546 0.393652 +vt 0.454546 0.419895 +vt 0.431819 0.433017 +vt 0.500000 0.393651 +vt 0.477273 0.433017 +vt 0.454546 0.472382 +vt 0.454546 0.367408 +vt 0.477273 0.354286 +vt 0.500001 0.314921 +vt 0.500000 0.341165 +vt 0.522728 0.354286 +vt 0.636364 0.393652 +vt 0.636364 0.419895 +vt 0.613637 0.433017 +vt 0.681818 0.393651 +vt 0.659091 0.433017 +vt 0.636364 0.472382 +vt 0.636364 0.367408 +vt 0.659091 0.354286 +vt 0.681819 0.314921 +vt 0.681818 0.341165 +vt 0.704546 0.354286 +vt 0.818182 0.393652 +vt 0.818182 0.419895 +vt 0.795455 0.433017 +vt 0.863636 0.393651 +vt 0.840909 0.433017 +vt 0.818182 0.472382 +vt 0.818182 0.367408 +vt 0.840909 0.354286 +vt 0.863637 0.314921 +vt 0.863636 0.341165 +vt 0.909091 0.314921 +vt 0.886364 0.354286 +vt 0.090910 0.393652 +vt 0.090910 0.419895 +vt 0.068183 0.433017 +vt 0.136365 0.393651 +vt 0.113637 0.433017 +vt 0.090910 0.472382 +vt 0.090910 0.367408 +vt 0.113637 0.354286 +vt 0.136364 0.314921 +vt 0.136364 0.341165 +vt 0.159092 0.354286 +vt 0.272728 0.393652 +vt 0.272728 0.419895 +vt 0.250001 0.433017 +vt 0.318182 0.393651 +vt 0.295455 0.433017 +vt 0.272728 0.472382 +vt 0.272728 0.367408 +vt 0.295455 0.354286 +vt 0.318182 0.314921 +vt 0.318182 0.341165 +vt 0.340910 0.354286 +vt 0.431819 0.275556 +vt 0.409092 0.288678 +vt 0.386364 0.275556 +vt 0.454546 0.262434 +vt 0.477273 0.275556 +vt 0.522728 0.275556 +vt 0.500000 0.288678 +vt 0.613637 0.275556 +vt 0.590910 0.288678 +vt 0.568182 0.275556 +vt 0.636364 0.262434 +vt 0.659091 0.275556 +vt 0.704546 0.275556 +vt 0.681819 0.288678 +vt 0.795455 0.275556 +vt 0.772728 0.288678 +vt 0.750000 0.275556 +vt 0.818182 0.262434 +vt 0.840909 0.275556 +vt 0.886364 0.275556 +vt 0.863636 0.288678 +vt 0.068182 0.275556 +vt 0.045455 0.288678 +vt 0.022728 0.275556 +vt 0.090910 0.262434 +vt 0.113637 0.275556 +vt 0.159092 0.275556 +vt 0.136364 0.288678 +vt 0.250001 0.275556 +vt 0.227274 0.288678 +vt 0.204546 0.275556 +vt 0.272728 0.262434 +vt 0.295455 0.275556 +vt 0.340910 0.275556 +vt 0.318183 0.288678 +vt 0.545455 0.236191 +vt 0.545455 0.262434 +vt 0.545455 0.209948 +vt 0.568182 0.196826 +vt 0.590910 0.157461 +vt 0.590909 0.183704 +vt 0.727273 0.236191 +vt 0.727273 0.262434 +vt 0.727273 0.209948 +vt 0.750000 0.196826 +vt 0.772728 0.157461 +vt 0.772727 0.183704 +vt 0.909091 0.236191 +vt 0.909091 0.262434 +vt 0.954545 0.236191 +vt 0.931818 0.275556 +vt 0.909091 0.209948 +vt 0.931818 0.196826 +vt 0.954546 0.157461 +vt 0.954545 0.183704 +vt 1.000000 0.157461 +vt 0.977273 0.196826 +vt 0.181819 0.236191 +vt 0.181819 0.262434 +vt 0.181819 0.209948 +vt 0.204546 0.196826 +vt 0.227274 0.157461 +vt 0.227274 0.183704 +vt 0.363637 0.236191 +vt 0.363637 0.262434 +vt 0.363637 0.209948 +vt 0.386364 0.196826 +vt 0.409092 0.157461 +vt 0.409092 0.183704 +vt 0.522728 0.118096 +vt 0.500001 0.131218 +vt 0.477273 0.118096 +vt 0.545455 0.104974 +vt 0.568182 0.118096 +vt 0.613637 0.118096 +vt 0.590910 0.131218 +vt 0.704546 0.118096 +vt 0.681819 0.131218 +vt 0.659091 0.118096 +vt 0.727273 0.104974 +vt 0.750000 0.118096 +vt 0.795455 0.118096 +vt 0.772727 0.131218 +vt 0.886364 0.118096 +vt 0.863636 0.131218 +vt 0.840909 0.118096 +vt 0.909091 0.104974 +vt 0.931818 0.118096 +vt 0.977273 0.118096 +vt 0.954546 0.131218 +vt 0.386364 0.118096 +vt 0.409092 0.131218 +vt 0.409092 0.078731 +vt 0.431819 0.118096 +vt 0.363637 0.104974 +vt 0.363637 0.078731 +vt 0.340910 0.039365 +vt 0.363637 0.052487 +vt 0.363637 0.000000 +vt 0.386364 0.039365 +vt 0.159092 0.118096 +vt 0.136365 0.131218 +vt 0.113637 0.118096 +vt 0.181819 0.104974 +vt 0.204546 0.118096 +vt 0.250001 0.118096 +vt 0.227274 0.131218 +s 0 +usemtl LunarRegolithMaterial.032 +f 1/1/1 74/2/1 163/3/1 43/4/1 +f 14/5/2 161/6/2 163/3/2 74/2/2 +f 13/7/3 43/4/3 163/3/3 161/6/3 +f 2/8/4 44/9/4 164/10/4 46/11/4 +f 14/12/5 158/13/5 164/10/5 44/9/5 +f 16/14/6 46/11/6 164/10/6 158/13/6 +f 1/15/7 43/16/7 165/17/7 48/18/7 +f 13/19/8 155/20/8 165/17/8 43/16/8 +f 18/21/9 48/18/9 165/17/9 155/20/9 +f 1/22/10 48/23/10 166/24/10 50/25/10 +f 18/26/11 152/27/11 166/24/11 48/23/11 +f 20/28/12 50/25/12 166/24/12 152/27/12 +f 1/29/13 50/30/13 167/31/13 77/32/13 +f 20/33/14 149/34/14 167/31/14 50/30/14 +f 17/35/15 77/32/15 167/31/15 149/34/15 +f 2/8/16 46/11/16 168/36/16 53/37/16 +f 16/14/17 146/38/17 168/36/17 46/11/17 +f 23/39/18 53/37/18 168/36/18 146/38/18 +f 3/40/19 45/41/19 169/42/19 55/43/19 +f 15/44/20 143/45/20 169/42/20 45/41/20 +f 25/46/21 55/43/21 169/42/21 143/45/21 +f 4/47/22 49/48/22 170/49/22 57/50/22 +f 19/51/23 140/52/23 170/49/23 49/48/23 +f 27/53/24 57/50/24 170/49/24 140/52/24 +f 5/54/25 51/55/25 171/56/25 59/57/25 +f 21/58/26 137/59/26 171/56/26 51/55/26 +f 29/60/27 59/57/27 171/56/27 137/59/27 +f 6/61/28 52/62/28 172/63/28 61/64/28 +f 22/65/29 134/66/29 172/63/29 52/62/29 +f 31/67/30 61/64/30 172/63/30 134/66/30 +f 2/8/31 53/37/31 173/68/31 86/69/31 +f 23/39/32 131/70/32 173/68/32 53/37/32 +f 26/71/33 86/69/33 173/68/33 131/70/33 +f 3/40/34 55/43/34 174/72/34 88/73/34 +f 25/46/35 128/74/35 174/72/35 55/43/35 +f 28/75/36 88/73/36 174/72/36 128/74/36 +f 4/47/37 57/50/37 175/76/37 90/77/37 +f 27/53/38 125/78/38 175/76/38 57/50/38 +f 30/79/39 90/77/39 175/76/39 125/78/39 +f 5/54/40 59/57/40 176/80/40 92/81/40 +f 29/60/41 122/82/41 176/80/41 59/57/41 +f 32/83/42 92/81/42 176/80/42 122/82/42 +f 6/61/43 61/64/43 177/84/43 84/85/43 +f 31/67/44 119/86/44 177/84/44 61/64/44 +f 24/87/45 84/85/45 177/84/45 119/86/45 +f 7/88/46 63/89/46 178/90/46 68/91/46 +f 33/92/47 116/93/47 178/90/47 63/89/47 +f 38/94/48 68/91/48 178/90/48 116/93/48 +f 8/95/49 64/96/49 179/97/49 70/98/49 +f 34/99/50 113/100/50 179/97/50 64/96/50 +f 40/101/51 70/98/51 179/97/51 113/100/51 +f 9/102/52 65/103/52 180/104/52 71/105/52 +f 35/106/53 110/107/53 180/104/53 65/103/53 +f 41/108/54 71/105/54 180/104/54 110/107/54 +f 10/109/55 66/110/55 181/111/55 72/112/55 +f 36/113/56 107/114/56 181/111/56 66/110/56 +f 42/115/57 72/112/57 181/111/57 107/114/57 +f 11/116/58 67/117/58 182/118/58 99/119/58 +f 37/120/59 104/121/59 182/118/59 67/117/59 +f 39/122/60 99/119/60 182/118/60 104/121/60 +f 39/122/61 103/123/61 183/124/61 69/125/61 +f 42/126/62 102/127/62 183/124/62 103/123/62 +f 12/128/63 69/125/63 183/124/63 102/127/63 +f 39/122/64 104/121/64 184/129/64 103/123/64 +f 37/120/65 105/130/65 184/129/65 104/121/65 +f 42/126/66 103/123/66 184/129/66 105/130/66 +f 37/120/67 97/131/67 185/132/67 105/130/67 +f 10/109/68 72/133/68 185/132/68 97/131/68 +f 42/126/69 105/130/69 185/132/69 72/133/69 +f 42/115/70 106/134/70 186/135/70 102/136/70 +f 41/137/71 101/138/71 186/135/71 106/134/71 +f 12/139/72 102/136/72 186/135/72 101/138/72 +f 42/115/73 107/114/73 187/140/73 106/134/73 +f 36/113/74 108/141/74 187/140/74 107/114/74 +f 41/137/75 106/134/75 187/140/75 108/141/75 +f 36/113/76 96/142/76 188/143/76 108/141/76 +f 9/102/77 71/144/77 188/143/77 96/142/77 +f 41/137/78 108/141/78 188/143/78 71/144/78 +f 41/108/79 109/145/79 189/146/79 101/147/79 +f 40/148/80 100/149/80 189/146/80 109/145/80 +f 12/150/81 101/147/81 189/146/81 100/149/81 +f 41/108/82 110/107/82 190/151/82 109/145/82 +f 35/106/83 111/152/83 190/151/83 110/107/83 +f 40/148/84 109/145/84 190/151/84 111/152/84 +f 35/106/85 95/153/85 191/154/85 111/152/85 +f 8/155/86 70/156/86 191/154/86 95/153/86 +f 40/148/87 111/152/87 191/154/87 70/156/87 +f 40/101/88 112/157/88 192/158/88 100/159/88 +f 38/160/89 98/161/89 192/158/89 112/157/89 +f 12/162/90 100/159/90 192/158/90 98/161/90 +f 40/101/91 113/100/91 193/163/91 112/157/91 +f 34/99/92 114/164/92 193/163/92 113/100/92 +f 38/160/93 112/157/93 193/163/93 114/164/93 +f 34/99/94 94/165/94 194/166/94 114/164/94 +f 7/88/95 68/167/95 194/166/95 94/165/95 +f 38/160/96 114/164/96 194/166/96 68/167/96 +f 38/94/97 115/168/97 195/169/97 98/170/97 +f 39/171/98 69/172/98 195/169/98 115/168/98 +f 12/173/99 98/170/99 195/169/99 69/172/99 +f 38/94/100 116/93/100 196/174/100 115/168/100 +f 33/92/101 117/175/101 196/174/101 116/93/101 +f 39/171/102 115/168/102 196/174/102 117/175/102 +f 33/92/103 93/176/103 197/177/103 117/175/103 +f 11/116/104 99/178/104 197/177/104 93/176/104 +f 39/171/105 117/175/105 197/177/105 99/178/105 +f 24/87/106 118/179/106 198/180/106 54/181/106 +f 37/120/107 67/117/107 198/180/107 118/179/107 +f 11/116/108 54/181/108 198/180/108 67/117/108 +f 24/87/109 119/86/109 199/182/109 118/179/109 +f 31/67/110 120/183/110 199/182/110 119/86/110 +f 37/120/111 118/179/111 199/182/111 120/183/111 +f 31/67/112 91/184/112 200/185/112 120/183/112 +f 10/109/113 97/131/113 200/185/113 91/184/113 +f 37/120/114 120/183/114 200/185/114 97/131/114 +f 32/83/115 121/186/115 201/187/115 62/188/115 +f 36/113/116 66/110/116 201/187/116 121/186/116 +f 10/109/117 62/188/117 201/187/117 66/110/117 +f 32/83/118 122/82/118 202/189/118 121/186/118 +f 29/60/119 123/190/119 202/189/119 122/82/119 +f 36/113/120 121/186/120 202/189/120 123/190/120 +f 29/60/121 89/191/121 203/192/121 123/190/121 +f 9/102/122 96/142/122 203/192/122 89/191/122 +f 36/113/123 123/190/123 203/192/123 96/142/123 +f 30/79/124 124/193/124 204/194/124 60/195/124 +f 35/106/125 65/103/125 204/194/125 124/193/125 +f 9/102/126 60/195/126 204/194/126 65/103/126 +f 30/79/127 125/78/127 205/196/127 124/193/127 +f 27/53/128 126/197/128 205/196/128 125/78/128 +f 35/106/129 124/193/129 205/196/129 126/197/129 +f 27/53/130 87/198/130 206/199/130 126/197/130 +f 8/155/131 95/153/131 206/199/131 87/198/131 +f 35/106/132 126/197/132 206/199/132 95/153/132 +f 28/75/133 127/200/133 207/201/133 58/202/133 +f 34/99/134 64/96/134 207/201/134 127/200/134 +f 8/95/135 58/202/135 207/201/135 64/96/135 +f 28/75/136 128/74/136 208/203/136 127/200/136 +f 25/46/137 129/204/137 208/203/137 128/74/137 +f 34/99/138 127/200/138 208/203/138 129/204/138 +f 25/46/139 85/205/139 209/206/139 129/204/139 +f 7/88/140 94/165/140 209/206/140 85/205/140 +f 34/99/141 129/204/141 209/206/141 94/165/141 +f 26/71/142 130/207/142 210/208/142 56/209/142 +f 33/92/143 63/89/143 210/208/143 130/207/143 +f 7/88/144 56/209/144 210/208/144 63/89/144 +f 26/71/145 131/70/145 211/210/145 130/207/145 +f 23/39/146 132/211/146 211/210/146 131/70/146 +f 33/92/147 130/207/147 211/210/147 132/211/147 +f 23/39/148 83/212/148 212/213/148 132/211/148 +f 11/116/149 93/176/149 212/213/149 83/212/149 +f 33/92/150 132/211/150 212/213/150 93/176/150 +f 31/67/151 133/214/151 213/215/151 91/184/151 +f 32/83/152 62/188/152 213/215/152 133/214/152 +f 10/109/153 91/184/153 213/215/153 62/188/153 +f 31/67/154 134/66/154 214/216/154 133/214/154 +f 22/65/155 135/217/155 214/216/155 134/66/155 +f 32/83/156 133/214/156 214/216/156 135/217/156 +f 22/65/157 82/218/157 215/219/157 135/217/157 +f 5/54/158 92/81/158 215/219/158 82/218/158 +f 32/83/159 135/217/159 215/219/159 92/81/159 +f 29/60/160 136/220/160 216/221/160 89/191/160 +f 30/79/161 60/195/161 216/221/161 136/220/161 +f 9/102/162 89/191/162 216/221/162 60/195/162 +f 29/60/163 137/59/163 217/222/163 136/220/163 +f 21/58/164 138/223/164 217/222/164 137/59/164 +f 30/79/165 136/220/165 217/222/165 138/223/165 +f 21/58/166 81/224/166 218/225/166 138/223/166 +f 4/47/167 90/77/167 218/225/167 81/224/167 +f 30/79/168 138/223/168 218/225/168 90/77/168 +f 27/53/169 139/226/169 219/227/169 87/198/169 +f 28/228/170 58/229/170 219/227/170 139/226/170 +f 8/155/171 87/198/171 219/227/171 58/229/171 +f 27/53/172 140/52/172 220/230/172 139/226/172 +f 19/51/173 141/231/173 220/230/173 140/52/173 +f 28/228/174 139/226/174 220/230/174 141/231/174 +f 19/51/175 79/232/175 221/233/175 141/231/175 +f 3/234/176 88/235/176 221/233/176 79/232/176 +f 28/228/177 141/231/177 221/233/177 88/235/177 +f 25/46/178 142/236/178 222/237/178 85/205/178 +f 26/71/179 56/209/179 222/237/179 142/236/179 +f 7/88/180 85/205/180 222/237/180 56/209/180 +f 25/46/181 143/45/181 223/238/181 142/236/181 +f 15/44/182 144/239/182 223/238/182 143/45/182 +f 26/71/183 142/236/183 223/238/183 144/239/183 +f 15/44/184 75/240/184 224/241/184 144/239/184 +f 2/8/185 86/69/185 224/241/185 75/240/185 +f 26/71/186 144/239/186 224/241/186 86/69/186 +f 23/39/187 145/242/187 225/243/187 83/212/187 +f 24/87/188 54/181/188 225/243/188 145/242/188 +f 11/116/189 83/212/189 225/243/189 54/181/189 +f 23/39/190 146/38/190 226/244/190 145/242/190 +f 16/14/191 147/245/191 226/244/191 146/38/191 +f 24/87/192 145/242/192 226/244/192 147/245/192 +f 16/14/193 76/246/193 227/247/193 147/245/193 +f 6/61/194 84/85/194 227/247/194 76/246/194 +f 24/87/195 147/245/195 227/247/195 84/85/195 +f 17/35/196 148/248/196 228/249/196 47/250/196 +f 22/65/197 52/62/197 228/249/197 148/248/197 +f 6/61/198 47/250/198 228/249/198 52/62/198 +f 17/35/199 149/34/199 229/251/199 148/248/199 +f 20/33/200 150/252/200 229/251/200 149/34/200 +f 22/65/201 148/248/201 229/251/201 150/252/201 +f 20/33/202 80/253/202 230/254/202 150/252/202 +f 5/54/203 82/218/203 230/254/203 80/253/203 +f 22/65/204 150/252/204 230/254/204 82/218/204 +f 20/28/205 151/255/205 231/256/205 80/257/205 +f 21/58/206 51/55/206 231/256/206 151/255/206 +f 5/54/207 80/257/207 231/256/207 51/55/207 +f 20/28/208 152/27/208 232/258/208 151/255/208 +f 18/26/209 153/259/209 232/258/209 152/27/209 +f 21/58/210 151/255/210 232/258/210 153/259/210 +f 18/26/211 78/260/211 233/261/211 153/259/211 +f 4/47/212 81/224/212 233/261/212 78/260/212 +f 21/58/213 153/259/213 233/261/213 81/224/213 +f 18/21/214 154/262/214 234/263/214 78/264/214 +f 19/51/215 49/48/215 234/263/215 154/262/215 +f 4/47/216 78/264/216 234/263/216 49/48/216 +f 18/21/217 155/20/217 235/265/217 154/262/217 +f 13/19/218 156/266/218 235/265/218 155/20/218 +f 19/51/219 154/262/219 235/265/219 156/266/219 +f 13/19/220 73/267/220 236/268/220 156/266/220 +f 3/234/221 79/232/221 236/268/221 73/267/221 +f 19/51/222 156/266/222 236/268/222 79/232/222 +f 16/14/223 157/269/223 237/270/223 76/246/223 +f 17/271/224 47/272/224 237/270/224 157/269/224 +f 6/61/225 76/246/225 237/270/225 47/272/225 +f 16/14/226 158/13/226 238/273/226 157/269/226 +f 14/12/227 159/274/227 238/273/227 158/13/227 +f 17/271/228 157/269/228 238/273/228 159/274/228 +f 14/12/229 74/275/229 239/276/229 159/274/229 +f 1/277/230 77/278/230 239/276/230 74/275/230 +f 17/271/231 159/274/231 239/276/231 77/278/231 +f 13/7/232 160/279/232 240/280/232 73/281/232 +f 15/44/233 45/41/233 240/280/233 160/279/233 +f 3/40/234 73/281/234 240/280/234 45/41/234 +f 13/7/235 161/6/235 241/282/235 160/279/235 +f 14/5/236 162/283/236 241/282/236 161/6/236 +f 15/44/237 160/279/237 241/282/237 162/283/237 +f 14/5/238 44/284/238 242/285/238 162/283/238 +f 2/8/239 75/240/239 242/285/239 44/284/239 +f 15/44/240 162/283/240 242/285/240 75/240/240 diff --git a/data/models/regolith/particle_2.mtl b/data/models/regolith/particle_2.mtl new file mode 100644 index 0000000000..681ee11066 --- /dev/null +++ b/data/models/regolith/particle_2.mtl @@ -0,0 +1,12 @@ +# Blender 4.2.1 LTS MTL File: 'lunarregolith.blend' +# www.blender.org + +newmtl LunarRegolithMaterial.032 +Ns 10.000005 +Ka 1.000000 1.000000 1.000000 +Kd 0.500000 0.500000 0.500000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 diff --git a/data/models/regolith/particle_2.obj b/data/models/regolith/particle_2.obj new file mode 100644 index 0000000000..d367401b91 --- /dev/null +++ b/data/models/regolith/particle_2.obj @@ -0,0 +1,1013 @@ +# Blender 4.2.1 LTS +# www.blender.org +mtllib particle_2.mtl +o Icosphere +v -0.000272 -0.001162 0.002456 +v 0.000942 -0.001675 0.000321 +v 0.002149 0.000105 0.001812 +v -0.000076 0.001017 0.001408 +v -0.001543 0.000119 0.000784 +v -0.000775 -0.001359 0.000052 +v 0.001555 -0.000121 -0.000691 +v 0.000976 0.001497 -0.000013 +v -0.000449 0.000821 -0.000170 +v -0.001256 -0.000055 -0.001066 +v 0.000045 -0.000722 -0.000913 +v 0.000236 0.000889 -0.001808 +v 0.001096 -0.000640 0.002540 +v 0.000496 -0.001699 0.001405 +v 0.001871 -0.001215 0.001201 +v -0.000065 -0.001899 0.000196 +v -0.000746 -0.001569 0.001154 +v -0.000205 0.000220 0.002363 +v 0.000988 0.000871 0.002002 +v -0.001155 -0.000461 0.001656 +v -0.000828 0.000572 0.001131 +v -0.001289 -0.000710 0.000478 +v 0.000395 -0.001117 -0.000423 +v -0.000413 -0.001386 -0.000697 +v 0.002152 -0.000055 0.000348 +v 0.001520 -0.001048 -0.000237 +v 0.000472 0.001318 0.000750 +v 0.001703 0.001136 0.000840 +v -0.001028 0.000654 0.000232 +v -0.000307 0.000898 0.000447 +v -0.000926 -0.000658 -0.000453 +v -0.001419 0.000039 -0.000157 +v 0.000685 -0.000458 -0.000824 +v 0.001645 0.000906 -0.000470 +v 0.000104 0.001311 -0.000136 +v -0.001046 0.000666 -0.000692 +v -0.000602 -0.000577 -0.001261 +v 0.001019 0.000418 -0.001353 +v 0.000158 -0.000118 -0.001576 +v 0.000723 0.001385 -0.000996 +v -0.000297 0.001206 -0.001028 +v -0.000678 0.000422 -0.001637 +v 0.000359 -0.000974 0.002641 +v 0.000785 -0.001783 0.000804 +v 0.002160 -0.000573 0.001633 +v 0.000444 -0.001834 0.000265 +v -0.000805 -0.001514 0.000539 +v -0.000265 -0.000532 0.002600 +v 0.000370 0.001033 0.001755 +v -0.000771 -0.000868 0.002191 +v -0.001275 0.000350 0.000977 +v -0.001032 -0.001070 0.000260 +v 0.000688 -0.001447 -0.000088 +v -0.000184 -0.001065 -0.000845 +v 0.002288 0.000030 0.001149 +v 0.001582 -0.000587 -0.000499 +v 0.000185 0.001188 0.001113 +v 0.001337 0.001400 0.000365 +v -0.001361 0.000429 0.000530 +v -0.000369 0.000822 0.000123 +v -0.000848 -0.001019 -0.000198 +v -0.001374 -0.000007 -0.000655 +v 0.001154 -0.000323 -0.000796 +v 0.001358 0.001322 -0.000235 +v -0.000194 0.001035 -0.000155 +v -0.001252 0.000311 -0.000951 +v -0.000250 -0.000711 -0.001123 +v 0.001318 0.000146 -0.001022 +v 0.000216 0.000410 -0.001828 +v 0.000883 0.001494 -0.000489 +v -0.000399 0.001023 -0.000546 +v -0.001060 0.000155 -0.001397 +v 0.001775 -0.000260 0.002280 +v 0.000091 -0.001503 0.002075 +v 0.001428 -0.001571 0.000715 +v -0.000485 -0.001714 0.000105 +v -0.000561 -0.001454 0.001906 +v -0.000146 0.000749 0.001914 +v 0.001696 0.000530 0.002038 +v -0.001441 -0.000128 0.001194 +v -0.000442 0.000824 0.001297 +v -0.001524 -0.000271 0.000679 +v 0.000185 -0.000876 -0.000671 +v -0.000603 -0.001442 -0.000349 +v 0.001896 -0.000107 -0.000278 +v 0.001284 -0.001428 0.000045 +v 0.000744 0.001461 0.000365 +v 0.002042 0.000677 0.001405 +v -0.000710 0.000728 0.000016 +v -0.000213 0.000991 0.000906 +v -0.001133 -0.000343 -0.000791 +v -0.001547 0.000084 0.000344 +v 0.000324 -0.000571 -0.000852 +v 0.001685 0.000361 -0.000639 +v 0.000532 0.001479 -0.000078 +v -0.000736 0.000784 -0.000405 +v -0.000992 -0.000312 -0.001230 +v 0.000646 0.000695 -0.001688 +v 0.000100 -0.000462 -0.001218 +v 0.000491 0.001191 -0.001504 +v -0.000036 0.001141 -0.001535 +v -0.000216 0.000702 -0.001822 +v -0.000268 0.000141 -0.001738 +v -0.000248 -0.000361 -0.001472 +v -0.000688 -0.000107 -0.001543 +v -0.000534 0.000897 -0.001420 +v -0.000938 0.000606 -0.001223 +v -0.000703 0.000949 -0.000890 +v 0.000198 0.001388 -0.001066 +v -0.000080 0.001300 -0.000580 +v 0.000392 0.001453 -0.000571 +v 0.000955 0.000971 -0.001275 +v 0.001224 0.001206 -0.000785 +v 0.001386 0.000687 -0.000983 +v 0.000603 0.000137 -0.001544 +v 0.000861 -0.000059 -0.001136 +v 0.000433 -0.000287 -0.001206 +v -0.000515 -0.001016 -0.000988 +v -0.000674 -0.001074 -0.000627 +v -0.000789 -0.000672 -0.000902 +v -0.001299 0.000378 -0.000444 +v -0.001313 0.000401 0.000044 +v -0.001054 0.000663 -0.000211 +v -0.000095 0.001082 0.000175 +v 0.000037 0.001135 0.000580 +v 0.000255 0.001335 0.000286 +v 0.001761 0.001068 0.000165 +v 0.002069 0.000610 0.000624 +v 0.001964 0.000483 -0.000082 +v 0.001090 -0.000766 -0.000570 +v 0.000954 -0.001099 -0.000368 +v 0.000554 -0.000766 -0.000599 +v -0.001224 -0.000313 -0.000312 +v -0.001112 -0.000672 -0.000005 +v -0.001402 -0.000324 0.000154 +v -0.000658 0.000762 0.000346 +v -0.000962 0.000647 0.000653 +v -0.000570 0.000779 0.000756 +v 0.001093 0.001334 0.000853 +v 0.000743 0.001204 0.001378 +v 0.001428 0.001081 0.001483 +v 0.001939 -0.000654 0.000026 +v 0.002158 -0.000684 0.000800 +v 0.001809 -0.001218 0.000419 +v -0.000042 -0.001309 -0.000574 +v 0.000166 -0.001581 -0.000168 +v -0.000261 -0.001704 -0.000308 +v -0.001089 -0.001165 0.000827 +v -0.001027 -0.001085 0.001499 +v -0.001320 -0.000637 0.001079 +v -0.001059 0.000119 0.001475 +v -0.000750 -0.000132 0.002113 +v -0.000590 0.000451 0.001774 +v 0.000403 0.000582 0.002308 +v 0.000433 -0.000191 0.002651 +v 0.001112 0.000174 0.002448 +v -0.000400 -0.001843 0.000677 +v 0.000181 -0.001910 0.000764 +v -0.000185 -0.001753 0.001329 +v 0.001608 -0.001006 0.001980 +v 0.000851 -0.001281 0.002094 +v 0.001244 -0.001527 0.001373 +v 0.000443 -0.001288 0.002333 +v 0.000466 -0.001889 0.000602 +v 0.000180 -0.000583 0.002721 +v -0.000636 -0.000508 0.002366 +v -0.000826 -0.001176 0.001910 +v 0.000423 -0.001634 -0.000005 +v 0.002270 -0.000428 0.001209 +v 0.000431 0.001175 0.001429 +v -0.001220 0.000505 0.000726 +v -0.001001 -0.000907 0.000016 +v 0.000986 -0.001329 -0.000169 +v 0.002189 0.000464 0.001073 +v -0.000007 0.001115 0.000851 +v -0.001440 0.000316 0.000311 +v -0.000710 -0.001183 -0.000406 +v 0.001106 -0.000077 -0.000997 +v 0.001172 0.001375 -0.000525 +v -0.000226 0.001125 -0.000422 +v -0.001114 0.000368 -0.001224 +v -0.000125 -0.000515 -0.001283 +v -0.000099 0.000423 -0.001851 +v -0.000406 -0.000127 -0.001611 +v -0.000947 -0.000096 -0.001435 +v -0.000281 0.000940 -0.001640 +v -0.000747 0.000846 -0.001188 +v -0.000616 0.000926 -0.000616 +v 0.000224 0.001290 -0.001398 +v 0.000159 0.001411 -0.000741 +v 0.000601 0.001503 -0.000387 +v 0.000715 0.000978 -0.001532 +v 0.001214 0.000970 -0.001027 +v 0.001489 0.000402 -0.000916 +v 0.000514 0.000407 -0.001738 +v 0.000632 -0.000083 -0.001305 +v 0.000285 -0.000442 -0.001090 +v -0.000333 -0.000961 -0.000999 +v -0.000655 -0.000943 -0.000856 +v -0.000981 -0.000450 -0.000982 +v -0.001349 0.000231 -0.000690 +v -0.001229 0.000502 -0.000208 +v -0.000841 0.000724 -0.000192 +v -0.000209 0.000961 0.000054 +v 0.000055 0.001188 0.000339 +v 0.000488 0.001446 0.000200 +v 0.001516 0.001297 0.000105 +v 0.001962 0.000741 0.000220 +v 0.001881 0.000252 -0.000341 +v 0.001279 -0.000588 -0.000633 +v 0.000864 -0.000877 -0.000519 +v 0.000344 -0.000713 -0.000684 +v -0.001265 -0.000222 -0.000593 +v -0.001240 -0.000436 -0.000051 +v -0.001534 -0.000174 0.000385 +v -0.000572 0.000756 0.000167 +v -0.000728 0.000737 0.000571 +v -0.000417 0.000872 0.000969 +v 0.001067 0.001429 0.000530 +v 0.001090 0.001236 0.001249 +v 0.001768 0.000815 0.001681 +v 0.001838 -0.000467 -0.000276 +v 0.002005 -0.000881 0.000404 +v 0.001551 -0.001453 0.000387 +v -0.000015 -0.001085 -0.000702 +v -0.000057 -0.001559 -0.000368 +v -0.000453 -0.001670 -0.000212 +v -0.000998 -0.001268 0.000543 +v -0.001166 -0.000977 0.001131 +v -0.001469 -0.000345 0.001008 +v -0.001296 0.000118 0.001229 +v -0.000810 0.000164 0.001801 +v -0.000412 0.000699 0.001683 +v 0.000201 0.000827 0.002036 +v 0.000651 0.000210 0.002518 +v 0.001567 0.000158 0.002326 +v -0.000577 -0.001724 0.000447 +v -0.000143 -0.001874 0.000914 +v -0.000237 -0.001618 0.001796 +v 0.001910 -0.000645 0.002032 +v 0.001259 -0.001302 0.001835 +v 0.001175 -0.001660 0.000970 +vn -0.0103 -0.7278 0.6857 +vn 0.2474 -0.8807 0.4039 +vn 0.3871 -0.6103 0.6912 +vn 0.3426 -0.9307 -0.1282 +vn 0.1866 -0.9574 0.2203 +vn 0.0954 -0.9904 -0.1004 +vn -0.2359 -0.2464 0.9400 +vn 0.1925 -0.0315 0.9808 +vn -0.2187 0.3079 0.9259 +vn -0.5387 -0.1874 0.8214 +vn -0.5292 0.3165 0.7872 +vn -0.8015 0.0860 0.5918 +vn -0.5952 -0.5145 0.6173 +vn -0.8766 -0.2595 0.4052 +vn -0.7273 -0.6373 0.2548 +vn 0.3144 -0.7399 -0.5947 +vn 0.1884 -0.7900 -0.5834 +vn 0.2689 -0.5966 -0.7561 +vn 0.9749 -0.0293 0.2206 +vn 0.8901 -0.4522 0.0573 +vn 0.9802 -0.0936 -0.1746 +vn -0.2944 0.9060 0.3041 +vn 0.0352 0.8965 0.4417 +vn -0.1210 0.9728 0.1974 +vn -0.7239 0.6417 0.2535 +vn -0.4631 0.8287 0.3144 +vn -0.4954 0.8660 0.0686 +vn -0.8168 -0.4375 -0.3761 +vn -0.8437 -0.4044 -0.3531 +vn -0.8286 -0.4291 -0.3596 +vn 0.1516 -0.8135 -0.5614 +vn 0.0831 -0.6608 -0.7459 +vn 0.2500 -0.6492 -0.7184 +vn 0.9404 0.2838 0.1873 +vn 0.9631 0.1937 -0.1869 +vn 0.8139 0.5807 -0.0209 +vn -0.4812 0.8717 0.0926 +vn -0.3876 0.9217 0.0151 +vn -0.5436 0.8381 -0.0459 +vn -0.8817 0.4717 0.0058 +vn -0.6430 0.7584 -0.1066 +vn -0.8794 0.3908 -0.2718 +vn -0.8712 -0.4043 -0.2786 +vn -0.8712 -0.3852 -0.3045 +vn -0.7587 -0.4789 -0.4416 +vn 0.4498 -0.5103 -0.7331 +vn 0.2735 -0.6312 -0.7258 +vn 0.4098 -0.4839 -0.7732 +vn 0.3749 0.9240 -0.0758 +vn 0.6888 0.6576 -0.3051 +vn 0.3965 0.8438 -0.3616 +vn -0.6273 0.7158 0.3067 +vn -0.6420 0.7160 0.2743 +vn -0.6349 0.7525 0.1751 +vn -0.8920 0.1381 -0.4305 +vn -0.7662 0.5970 -0.2378 +vn -0.6510 0.4215 -0.6313 +vn 0.3640 -0.7318 -0.5762 +vn 0.0604 -0.7049 -0.7067 +vn 0.2837 -0.6920 -0.6638 +vn 0.0682 -0.4264 -0.9019 +vn -0.3448 -0.1073 -0.9325 +vn 0.0311 0.0692 -0.9971 +vn 0.0628 -0.4659 -0.8826 +vn -0.1857 -0.5508 -0.8137 +vn -0.3139 -0.1982 -0.9285 +vn -0.3927 -0.5473 -0.7391 +vn -0.7438 -0.3191 -0.5873 +vn -0.4349 -0.1217 -0.8922 +vn -0.5833 0.4447 -0.6797 +vn -0.4752 0.8020 -0.3619 +vn -0.1979 0.5909 -0.7821 +vn -0.6451 0.5038 -0.5745 +vn -0.7160 0.6723 -0.1883 +vn -0.5478 0.7978 -0.2520 +vn -0.5316 0.8122 0.2405 +vn -0.4366 0.8260 0.3566 +vn -0.4629 0.8574 0.2250 +vn -0.3513 0.8893 -0.2927 +vn 0.1038 0.9317 -0.3481 +vn -0.0268 0.7148 -0.6989 +vn -0.3828 0.9224 -0.0518 +vn -0.3085 0.9425 0.1282 +vn -0.0108 0.9919 -0.1268 +vn -0.3389 0.9396 0.0471 +vn -0.0105 0.9996 0.0273 +vn -0.0478 0.9787 -0.1995 +vn 0.5602 0.6566 -0.5051 +vn 0.7259 0.1804 -0.6637 +vn 0.3909 0.4253 -0.8163 +vn 0.5017 0.6395 -0.5825 +vn 0.7383 0.4286 -0.5207 +vn 0.6392 0.2098 -0.7399 +vn 0.8270 0.2066 -0.5228 +vn 0.7584 -0.1748 -0.6279 +vn 0.6797 -0.0328 -0.7328 +vn 0.5912 -0.2445 -0.7686 +vn 0.2941 -0.4583 -0.8387 +vn 0.2928 0.0288 -0.9557 +vn 0.5900 -0.5155 -0.6214 +vn 0.4550 -0.6767 -0.5788 +vn 0.4079 -0.6633 -0.6274 +vn 0.3206 -0.7852 -0.5297 +vn 0.4717 -0.7239 -0.5035 +vn 0.3949 -0.7131 -0.5792 +vn 0.2446 -0.5927 -0.7673 +vn 0.1323 -0.4936 -0.8595 +vn 0.4764 -0.4859 -0.7327 +vn -0.7309 -0.5460 -0.4094 +vn -0.8592 -0.4332 -0.2723 +vn -0.7314 -0.4566 -0.5065 +vn -0.7095 -0.6778 -0.1930 +vn -0.7569 -0.5878 -0.2857 +vn -0.5578 -0.7082 -0.4329 +vn -0.9749 0.2169 -0.0494 +vn -0.8121 0.5640 -0.1494 +vn -0.9499 0.0841 -0.3010 +vn -0.9261 0.3745 -0.0447 +vn -0.6807 0.7302 0.0585 +vn -0.7373 0.6738 -0.0500 +vn -0.2245 0.9726 0.0610 +vn -0.2453 0.9591 0.1414 +vn -0.3386 0.9405 0.0305 +vn -0.6822 0.7294 -0.0520 +vn -0.7087 0.6962 0.1139 +vn -0.6219 0.7594 0.1912 +vn -0.6051 0.7906 0.0939 +vn -0.4821 0.8479 0.2206 +vn -0.6092 0.7806 0.1401 +vn -0.2746 0.9383 0.2103 +vn -0.0710 0.9947 0.0748 +vn -0.3845 0.9204 0.0705 +vn 0.6211 0.7836 0.0143 +vn 0.6993 0.6539 -0.2888 +vn 0.3652 0.9247 -0.1077 +vn 0.8317 0.5551 -0.0062 +vn 0.9628 0.2017 -0.1797 +vn 0.8577 0.4226 -0.2928 +vn 0.9322 0.0118 -0.3618 +vn 0.7853 -0.1157 -0.6082 +vn 0.8536 0.2145 -0.4748 +vn 0.3053 -0.5239 -0.7952 +vn 0.1763 -0.4672 -0.8664 +vn 0.3885 -0.3356 -0.8581 +vn 0.1955 -0.5677 -0.7997 +vn 0.0808 -0.5027 -0.8607 +vn 0.0441 -0.5753 -0.8167 +vn 0.3039 -0.4888 -0.8178 +vn 0.4986 -0.5985 -0.6270 +vn 0.2092 -0.6719 -0.7105 +vn -0.7688 -0.6309 -0.1045 +vn -0.8826 -0.4691 -0.0317 +vn -0.8335 -0.5158 -0.1979 +vn -0.7870 -0.5238 -0.3259 +vn -0.7933 -0.5081 -0.3353 +vn -0.8541 -0.3968 -0.3362 +vn -0.8861 -0.4337 -0.1637 +vn -0.9987 -0.0495 0.0139 +vn -0.9386 -0.2035 -0.2785 +vn -0.2252 0.9722 -0.0638 +vn -0.3232 0.9315 -0.1668 +vn -0.2878 0.9543 0.0802 +vn -0.3127 0.9488 0.0455 +vn -0.3599 0.9101 0.2053 +vn -0.3472 0.9371 0.0357 +vn -0.5715 0.8179 0.0671 +vn -0.4844 0.8705 0.0876 +vn -0.4904 0.8695 -0.0599 +vn -0.0681 0.9528 0.2960 +vn 0.2915 0.9178 0.2696 +vn 0.1014 0.9891 0.1071 +vn -0.0429 0.9760 0.2134 +vn 0.0909 0.8911 0.4445 +vn 0.2960 0.9305 0.2157 +vn 0.2986 0.7453 0.5961 +vn 0.7188 0.4796 0.5033 +vn 0.5541 0.7912 0.2589 +vn 0.9180 -0.1343 -0.3731 +vn 0.7199 -0.4304 -0.5445 +vn 0.7357 -0.1797 -0.6530 +vn 0.9435 -0.1867 -0.2736 +vn 0.8572 -0.5103 -0.0690 +vn 0.7543 -0.4835 -0.4442 +vn 0.6616 -0.7487 -0.0408 +vn 0.3565 -0.8953 -0.2671 +vn 0.5920 -0.6627 -0.4586 +vn 0.4857 -0.4261 -0.7632 +vn 0.4140 -0.5588 -0.7186 +vn 0.5635 -0.4824 -0.6706 +vn 0.4926 -0.5839 -0.6454 +vn 0.3837 -0.7934 -0.4726 +vn 0.3258 -0.6444 -0.6918 +vn -0.3326 -0.9211 -0.2024 +vn -0.7556 -0.6298 -0.1804 +vn -0.5016 -0.7280 -0.4673 +vn -0.7738 -0.6334 0.0061 +vn -0.8667 -0.4706 -0.1656 +vn -0.7877 -0.5617 -0.2532 +vn -0.8102 -0.5688 0.1420 +vn -0.9020 -0.2983 0.3122 +vn -0.9146 -0.4043 0.0061 +vn -0.8799 -0.2931 0.3740 +vn -0.9815 -0.0690 0.1783 +vn -0.8831 -0.4687 0.0222 +vn -0.6862 0.3160 0.6552 +vn -0.5268 0.6607 0.5347 +vn -0.7745 0.4645 0.4294 +vn -0.7966 0.3211 0.5122 +vn -0.6080 0.5166 0.6029 +vn -0.6856 0.6140 0.3912 +vn -0.5717 0.5788 0.5816 +vn -0.4908 0.8052 0.3327 +vn -0.6503 0.6835 0.3317 +vn -0.3308 0.6102 0.7198 +vn -0.0161 0.7751 0.6316 +vn -0.3400 0.8475 0.4075 +vn -0.1583 0.3953 0.9048 +vn 0.2150 0.1378 0.9668 +vn 0.1592 0.5555 0.8161 +vn 0.2950 0.0809 0.9521 +vn 0.6489 0.2806 0.7073 +vn 0.2281 0.5503 0.8032 +vn -0.3844 -0.9111 -0.1491 +vn -0.6350 -0.7723 0.0174 +vn -0.7250 -0.6474 -0.2353 +vn -0.1175 -0.9928 0.0218 +vn 0.0386 -0.9558 0.2915 +vn -0.3587 -0.9011 0.2438 +vn 0.0544 -0.9529 0.2985 +vn -0.2038 -0.8105 0.5492 +vn -0.3704 -0.9011 0.2254 +vn 0.4787 -0.4175 0.7724 +vn 0.7068 -0.5986 0.3771 +vn 0.8311 -0.1049 0.5461 +vn 0.3374 -0.6454 0.6853 +vn 0.2204 -0.8802 0.4204 +vn 0.4984 -0.7828 0.3725 +vn 0.2148 -0.9436 0.2520 +vn 0.3016 -0.9495 -0.0864 +vn 0.4834 -0.8540 0.1923 +vt 0.181819 0.000000 +vt 0.204546 0.039365 +vt 0.181819 0.052487 +vt 0.159092 0.039365 +vt 0.227273 0.078731 +vt 0.181819 0.078731 +vt 0.136365 0.078731 +vt 0.272728 0.157461 +vt 0.295455 0.118096 +vt 0.318182 0.131218 +vt 0.318182 0.157461 +vt 0.318182 0.078731 +vt 0.340910 0.118096 +vt 0.363637 0.157461 +vt 0.909091 0.000000 +vt 0.931818 0.039365 +vt 0.909091 0.052487 +vt 0.886364 0.039365 +vt 0.954545 0.078731 +vt 0.909091 0.078731 +vt 0.863636 0.078731 +vt 0.727273 0.000000 +vt 0.750000 0.039365 +vt 0.727273 0.052487 +vt 0.704546 0.039365 +vt 0.772727 0.078731 +vt 0.727273 0.078731 +vt 0.681818 0.078731 +vt 0.545455 0.000000 +vt 0.568182 0.039365 +vt 0.545455 0.052487 +vt 0.522728 0.039365 +vt 0.590909 0.078731 +vt 0.545455 0.078731 +vt 0.500000 0.078731 +vt 0.318182 0.183704 +vt 0.295455 0.196826 +vt 0.340910 0.196826 +vt 0.318183 0.236191 +vt 0.090910 0.157461 +vt 0.136365 0.157461 +vt 0.136365 0.183704 +vt 0.113637 0.196826 +vt 0.181819 0.157461 +vt 0.159092 0.196826 +vt 0.136364 0.236191 +vt 0.818182 0.157461 +vt 0.863636 0.157461 +vt 0.863636 0.183704 +vt 0.840909 0.196826 +vt 0.909091 0.157461 +vt 0.886364 0.196826 +vt 0.863637 0.236191 +vt 0.636364 0.157461 +vt 0.681819 0.157461 +vt 0.681818 0.183704 +vt 0.659091 0.196826 +vt 0.727273 0.157461 +vt 0.704546 0.196826 +vt 0.681819 0.236191 +vt 0.454546 0.157461 +vt 0.500001 0.157461 +vt 0.500001 0.183704 +vt 0.477273 0.196826 +vt 0.545455 0.157461 +vt 0.522728 0.196826 +vt 0.500001 0.236191 +vt 0.272728 0.209948 +vt 0.250001 0.196826 +vt 0.272728 0.236191 +vt 0.227274 0.236191 +vt 0.090910 0.209948 +vt 0.068183 0.196826 +vt 0.090910 0.236191 +vt 0.045455 0.236191 +vt 0.818182 0.209948 +vt 0.795455 0.196826 +vt 0.818182 0.236191 +vt 0.772728 0.236191 +vt 0.636364 0.209948 +vt 0.613637 0.196826 +vt 0.636364 0.236191 +vt 0.590910 0.236191 +vt 0.454546 0.209948 +vt 0.431819 0.196826 +vt 0.454546 0.236191 +vt 0.409092 0.236191 +vt 0.181819 0.314921 +vt 0.227274 0.314921 +vt 0.227274 0.341165 +vt 0.204546 0.354286 +vt 0.272728 0.314921 +vt 0.250001 0.354286 +vt 0.227273 0.393651 +vt 0.000000 0.314921 +vt 0.045455 0.314921 +vt 0.045455 0.341165 +vt 0.022728 0.354286 +vt 0.090910 0.314921 +vt 0.068182 0.354286 +vt 0.045455 0.393651 +vt 0.727273 0.314921 +vt 0.772728 0.314921 +vt 0.772727 0.341165 +vt 0.750000 0.354286 +vt 0.818182 0.314921 +vt 0.795455 0.354286 +vt 0.772727 0.393651 +vt 0.545455 0.314921 +vt 0.590910 0.314921 +vt 0.590909 0.341165 +vt 0.568182 0.354286 +vt 0.636364 0.314921 +vt 0.613637 0.354286 +vt 0.590909 0.393651 +vt 0.363637 0.314921 +vt 0.409092 0.314921 +vt 0.409092 0.341165 +vt 0.386364 0.354286 +vt 0.454546 0.314921 +vt 0.431819 0.354286 +vt 0.409092 0.393651 +vt 0.454546 0.393652 +vt 0.454546 0.419895 +vt 0.431819 0.433017 +vt 0.500000 0.393651 +vt 0.477273 0.433017 +vt 0.454546 0.472382 +vt 0.454546 0.367408 +vt 0.477273 0.354286 +vt 0.500001 0.314921 +vt 0.500000 0.341165 +vt 0.522728 0.354286 +vt 0.636364 0.393652 +vt 0.636364 0.419895 +vt 0.613637 0.433017 +vt 0.681818 0.393651 +vt 0.659091 0.433017 +vt 0.636364 0.472382 +vt 0.636364 0.367408 +vt 0.659091 0.354286 +vt 0.681819 0.314921 +vt 0.681818 0.341165 +vt 0.704546 0.354286 +vt 0.818182 0.393652 +vt 0.818182 0.419895 +vt 0.795455 0.433017 +vt 0.863636 0.393651 +vt 0.840909 0.433017 +vt 0.818182 0.472382 +vt 0.818182 0.367408 +vt 0.840909 0.354286 +vt 0.863637 0.314921 +vt 0.863636 0.341165 +vt 0.909091 0.314921 +vt 0.886364 0.354286 +vt 0.090910 0.393652 +vt 0.090910 0.419895 +vt 0.068183 0.433017 +vt 0.136365 0.393651 +vt 0.113637 0.433017 +vt 0.090910 0.472382 +vt 0.090910 0.367408 +vt 0.113637 0.354286 +vt 0.136364 0.314921 +vt 0.136364 0.341165 +vt 0.159092 0.354286 +vt 0.272728 0.393652 +vt 0.272728 0.419895 +vt 0.250001 0.433017 +vt 0.318182 0.393651 +vt 0.295455 0.433017 +vt 0.272728 0.472382 +vt 0.272728 0.367408 +vt 0.295455 0.354286 +vt 0.318182 0.314921 +vt 0.318182 0.341165 +vt 0.340910 0.354286 +vt 0.431819 0.275556 +vt 0.409092 0.288678 +vt 0.386364 0.275556 +vt 0.454546 0.262434 +vt 0.477273 0.275556 +vt 0.522728 0.275556 +vt 0.500000 0.288678 +vt 0.613637 0.275556 +vt 0.590910 0.288678 +vt 0.568182 0.275556 +vt 0.636364 0.262434 +vt 0.659091 0.275556 +vt 0.704546 0.275556 +vt 0.681819 0.288678 +vt 0.795455 0.275556 +vt 0.772728 0.288678 +vt 0.750000 0.275556 +vt 0.818182 0.262434 +vt 0.840909 0.275556 +vt 0.886364 0.275556 +vt 0.863636 0.288678 +vt 0.068182 0.275556 +vt 0.045455 0.288678 +vt 0.022728 0.275556 +vt 0.090910 0.262434 +vt 0.113637 0.275556 +vt 0.159092 0.275556 +vt 0.136364 0.288678 +vt 0.250001 0.275556 +vt 0.227274 0.288678 +vt 0.204546 0.275556 +vt 0.272728 0.262434 +vt 0.295455 0.275556 +vt 0.340910 0.275556 +vt 0.318183 0.288678 +vt 0.545455 0.236191 +vt 0.545455 0.262434 +vt 0.545455 0.209948 +vt 0.568182 0.196826 +vt 0.590910 0.157461 +vt 0.590909 0.183704 +vt 0.727273 0.236191 +vt 0.727273 0.262434 +vt 0.727273 0.209948 +vt 0.750000 0.196826 +vt 0.772728 0.157461 +vt 0.772727 0.183704 +vt 0.909091 0.236191 +vt 0.909091 0.262434 +vt 0.954545 0.236191 +vt 0.931818 0.275556 +vt 0.909091 0.209948 +vt 0.931818 0.196826 +vt 0.954546 0.157461 +vt 0.954545 0.183704 +vt 1.000000 0.157461 +vt 0.977273 0.196826 +vt 0.181819 0.236191 +vt 0.181819 0.262434 +vt 0.181819 0.209948 +vt 0.204546 0.196826 +vt 0.227274 0.157461 +vt 0.227274 0.183704 +vt 0.363637 0.236191 +vt 0.363637 0.262434 +vt 0.363637 0.209948 +vt 0.386364 0.196826 +vt 0.409092 0.157461 +vt 0.409092 0.183704 +vt 0.522728 0.118096 +vt 0.500001 0.131218 +vt 0.477273 0.118096 +vt 0.545455 0.104974 +vt 0.568182 0.118096 +vt 0.613637 0.118096 +vt 0.590910 0.131218 +vt 0.704546 0.118096 +vt 0.681819 0.131218 +vt 0.659091 0.118096 +vt 0.727273 0.104974 +vt 0.750000 0.118096 +vt 0.795455 0.118096 +vt 0.772727 0.131218 +vt 0.886364 0.118096 +vt 0.863636 0.131218 +vt 0.840909 0.118096 +vt 0.909091 0.104974 +vt 0.931818 0.118096 +vt 0.977273 0.118096 +vt 0.954546 0.131218 +vt 0.386364 0.118096 +vt 0.409092 0.131218 +vt 0.409092 0.078731 +vt 0.431819 0.118096 +vt 0.363637 0.104974 +vt 0.363637 0.078731 +vt 0.340910 0.039365 +vt 0.363637 0.052487 +vt 0.363637 0.000000 +vt 0.386364 0.039365 +vt 0.159092 0.118096 +vt 0.136365 0.131218 +vt 0.113637 0.118096 +vt 0.181819 0.104974 +vt 0.204546 0.118096 +vt 0.250001 0.118096 +vt 0.227274 0.131218 +s 0 +usemtl LunarRegolithMaterial.032 +f 1/1/1 74/2/1 163/3/1 43/4/1 +f 14/5/2 161/6/2 163/3/2 74/2/2 +f 13/7/3 43/4/3 163/3/3 161/6/3 +f 2/8/4 44/9/4 164/10/4 46/11/4 +f 14/12/5 158/13/5 164/10/5 44/9/5 +f 16/14/6 46/11/6 164/10/6 158/13/6 +f 1/15/7 43/16/7 165/17/7 48/18/7 +f 13/19/8 155/20/8 165/17/8 43/16/8 +f 18/21/9 48/18/9 165/17/9 155/20/9 +f 1/22/10 48/23/10 166/24/10 50/25/10 +f 18/26/11 152/27/11 166/24/11 48/23/11 +f 20/28/12 50/25/12 166/24/12 152/27/12 +f 1/29/13 50/30/13 167/31/13 77/32/13 +f 20/33/14 149/34/14 167/31/14 50/30/14 +f 17/35/15 77/32/15 167/31/15 149/34/15 +f 2/8/16 46/11/16 168/36/16 53/37/16 +f 16/14/17 146/38/17 168/36/17 46/11/17 +f 23/39/18 53/37/18 168/36/18 146/38/18 +f 3/40/19 45/41/19 169/42/19 55/43/19 +f 15/44/20 143/45/20 169/42/20 45/41/20 +f 25/46/21 55/43/21 169/42/21 143/45/21 +f 4/47/22 49/48/22 170/49/22 57/50/22 +f 19/51/23 140/52/23 170/49/23 49/48/23 +f 27/53/24 57/50/24 170/49/24 140/52/24 +f 5/54/25 51/55/25 171/56/25 59/57/25 +f 21/58/26 137/59/26 171/56/26 51/55/26 +f 29/60/27 59/57/27 171/56/27 137/59/27 +f 6/61/28 52/62/28 172/63/28 61/64/28 +f 22/65/29 134/66/29 172/63/29 52/62/29 +f 31/67/30 61/64/30 172/63/30 134/66/30 +f 2/8/31 53/37/31 173/68/31 86/69/31 +f 23/39/32 131/70/32 173/68/32 53/37/32 +f 26/71/33 86/69/33 173/68/33 131/70/33 +f 3/40/34 55/43/34 174/72/34 88/73/34 +f 25/46/35 128/74/35 174/72/35 55/43/35 +f 28/75/36 88/73/36 174/72/36 128/74/36 +f 4/47/37 57/50/37 175/76/37 90/77/37 +f 27/53/38 125/78/38 175/76/38 57/50/38 +f 30/79/39 90/77/39 175/76/39 125/78/39 +f 5/54/40 59/57/40 176/80/40 92/81/40 +f 29/60/41 122/82/41 176/80/41 59/57/41 +f 32/83/42 92/81/42 176/80/42 122/82/42 +f 6/61/43 61/64/43 177/84/43 84/85/43 +f 31/67/44 119/86/44 177/84/44 61/64/44 +f 24/87/45 84/85/45 177/84/45 119/86/45 +f 7/88/46 63/89/46 178/90/46 68/91/46 +f 33/92/47 116/93/47 178/90/47 63/89/47 +f 38/94/48 68/91/48 178/90/48 116/93/48 +f 8/95/49 64/96/49 179/97/49 70/98/49 +f 34/99/50 113/100/50 179/97/50 64/96/50 +f 40/101/51 70/98/51 179/97/51 113/100/51 +f 9/102/52 65/103/52 180/104/52 71/105/52 +f 35/106/53 110/107/53 180/104/53 65/103/53 +f 41/108/54 71/105/54 180/104/54 110/107/54 +f 10/109/55 66/110/55 181/111/55 72/112/55 +f 36/113/56 107/114/56 181/111/56 66/110/56 +f 42/115/57 72/112/57 181/111/57 107/114/57 +f 11/116/58 67/117/58 182/118/58 99/119/58 +f 37/120/59 104/121/59 182/118/59 67/117/59 +f 39/122/60 99/119/60 182/118/60 104/121/60 +f 39/122/61 103/123/61 183/124/61 69/125/61 +f 42/126/62 102/127/62 183/124/62 103/123/62 +f 12/128/63 69/125/63 183/124/63 102/127/63 +f 39/122/64 104/121/64 184/129/64 103/123/64 +f 37/120/65 105/130/65 184/129/65 104/121/65 +f 42/126/66 103/123/66 184/129/66 105/130/66 +f 37/120/67 97/131/67 185/132/67 105/130/67 +f 10/109/68 72/133/68 185/132/68 97/131/68 +f 42/126/69 105/130/69 185/132/69 72/133/69 +f 42/115/70 106/134/70 186/135/70 102/136/70 +f 41/137/71 101/138/71 186/135/71 106/134/71 +f 12/139/72 102/136/72 186/135/72 101/138/72 +f 42/115/73 107/114/73 187/140/73 106/134/73 +f 36/113/74 108/141/74 187/140/74 107/114/74 +f 41/137/75 106/134/75 187/140/75 108/141/75 +f 36/113/76 96/142/76 188/143/76 108/141/76 +f 9/102/77 71/144/77 188/143/77 96/142/77 +f 41/137/78 108/141/78 188/143/78 71/144/78 +f 41/108/79 109/145/79 189/146/79 101/147/79 +f 40/148/80 100/149/80 189/146/80 109/145/80 +f 12/150/81 101/147/81 189/146/81 100/149/81 +f 41/108/82 110/107/82 190/151/82 109/145/82 +f 35/106/83 111/152/83 190/151/83 110/107/83 +f 40/148/84 109/145/84 190/151/84 111/152/84 +f 35/106/85 95/153/85 191/154/85 111/152/85 +f 8/155/86 70/156/86 191/154/86 95/153/86 +f 40/148/87 111/152/87 191/154/87 70/156/87 +f 40/101/88 112/157/88 192/158/88 100/159/88 +f 38/160/89 98/161/89 192/158/89 112/157/89 +f 12/162/90 100/159/90 192/158/90 98/161/90 +f 40/101/91 113/100/91 193/163/91 112/157/91 +f 34/99/92 114/164/92 193/163/92 113/100/92 +f 38/160/93 112/157/93 193/163/93 114/164/93 +f 34/99/94 94/165/94 194/166/94 114/164/94 +f 7/88/95 68/167/95 194/166/95 94/165/95 +f 38/160/96 114/164/96 194/166/96 68/167/96 +f 38/94/97 115/168/97 195/169/97 98/170/97 +f 39/171/98 69/172/98 195/169/98 115/168/98 +f 12/173/99 98/170/99 195/169/99 69/172/99 +f 38/94/100 116/93/100 196/174/100 115/168/100 +f 33/92/101 117/175/101 196/174/101 116/93/101 +f 39/171/102 115/168/102 196/174/102 117/175/102 +f 33/92/103 93/176/103 197/177/103 117/175/103 +f 11/116/104 99/178/104 197/177/104 93/176/104 +f 39/171/105 117/175/105 197/177/105 99/178/105 +f 24/87/106 118/179/106 198/180/106 54/181/106 +f 37/120/107 67/117/107 198/180/107 118/179/107 +f 11/116/108 54/181/108 198/180/108 67/117/108 +f 24/87/109 119/86/109 199/182/109 118/179/109 +f 31/67/110 120/183/110 199/182/110 119/86/110 +f 37/120/111 118/179/111 199/182/111 120/183/111 +f 31/67/112 91/184/112 200/185/112 120/183/112 +f 10/109/113 97/131/113 200/185/113 91/184/113 +f 37/120/114 120/183/114 200/185/114 97/131/114 +f 32/83/115 121/186/115 201/187/115 62/188/115 +f 36/113/116 66/110/116 201/187/116 121/186/116 +f 10/109/117 62/188/117 201/187/117 66/110/117 +f 32/83/118 122/82/118 202/189/118 121/186/118 +f 29/60/119 123/190/119 202/189/119 122/82/119 +f 36/113/120 121/186/120 202/189/120 123/190/120 +f 29/60/121 89/191/121 203/192/121 123/190/121 +f 9/102/122 96/142/122 203/192/122 89/191/122 +f 36/113/123 123/190/123 203/192/123 96/142/123 +f 30/79/124 124/193/124 204/194/124 60/195/124 +f 35/106/125 65/103/125 204/194/125 124/193/125 +f 9/102/126 60/195/126 204/194/126 65/103/126 +f 30/79/127 125/78/127 205/196/127 124/193/127 +f 27/53/128 126/197/128 205/196/128 125/78/128 +f 35/106/129 124/193/129 205/196/129 126/197/129 +f 27/53/130 87/198/130 206/199/130 126/197/130 +f 8/155/131 95/153/131 206/199/131 87/198/131 +f 35/106/132 126/197/132 206/199/132 95/153/132 +f 28/75/133 127/200/133 207/201/133 58/202/133 +f 34/99/134 64/96/134 207/201/134 127/200/134 +f 8/95/135 58/202/135 207/201/135 64/96/135 +f 28/75/136 128/74/136 208/203/136 127/200/136 +f 25/46/137 129/204/137 208/203/137 128/74/137 +f 34/99/138 127/200/138 208/203/138 129/204/138 +f 25/46/139 85/205/139 209/206/139 129/204/139 +f 7/88/140 94/165/140 209/206/140 85/205/140 +f 34/99/141 129/204/141 209/206/141 94/165/141 +f 26/71/142 130/207/142 210/208/142 56/209/142 +f 33/92/143 63/89/143 210/208/143 130/207/143 +f 7/88/144 56/209/144 210/208/144 63/89/144 +f 26/71/145 131/70/145 211/210/145 130/207/145 +f 23/39/146 132/211/146 211/210/146 131/70/146 +f 33/92/147 130/207/147 211/210/147 132/211/147 +f 23/39/148 83/212/148 212/213/148 132/211/148 +f 11/116/149 93/176/149 212/213/149 83/212/149 +f 33/92/150 132/211/150 212/213/150 93/176/150 +f 31/67/151 133/214/151 213/215/151 91/184/151 +f 32/83/152 62/188/152 213/215/152 133/214/152 +f 10/109/153 91/184/153 213/215/153 62/188/153 +f 31/67/154 134/66/154 214/216/154 133/214/154 +f 22/65/155 135/217/155 214/216/155 134/66/155 +f 32/83/156 133/214/156 214/216/156 135/217/156 +f 22/65/157 82/218/157 215/219/157 135/217/157 +f 5/54/158 92/81/158 215/219/158 82/218/158 +f 32/83/159 135/217/159 215/219/159 92/81/159 +f 29/60/160 136/220/160 216/221/160 89/191/160 +f 30/79/161 60/195/161 216/221/161 136/220/161 +f 9/102/162 89/191/162 216/221/162 60/195/162 +f 29/60/163 137/59/163 217/222/163 136/220/163 +f 21/58/164 138/223/164 217/222/164 137/59/164 +f 30/79/165 136/220/165 217/222/165 138/223/165 +f 21/58/166 81/224/166 218/225/166 138/223/166 +f 4/47/167 90/77/167 218/225/167 81/224/167 +f 30/79/168 138/223/168 218/225/168 90/77/168 +f 27/53/169 139/226/169 219/227/169 87/198/169 +f 28/228/170 58/229/170 219/227/170 139/226/170 +f 8/155/171 87/198/171 219/227/171 58/229/171 +f 27/53/172 140/52/172 220/230/172 139/226/172 +f 19/51/173 141/231/173 220/230/173 140/52/173 +f 28/228/174 139/226/174 220/230/174 141/231/174 +f 19/51/175 79/232/175 221/233/175 141/231/175 +f 3/234/176 88/235/176 221/233/176 79/232/176 +f 28/228/177 141/231/177 221/233/177 88/235/177 +f 25/46/178 142/236/178 222/237/178 85/205/178 +f 26/71/179 56/209/179 222/237/179 142/236/179 +f 7/88/180 85/205/180 222/237/180 56/209/180 +f 25/46/181 143/45/181 223/238/181 142/236/181 +f 15/44/182 144/239/182 223/238/182 143/45/182 +f 26/71/183 142/236/183 223/238/183 144/239/183 +f 15/44/184 75/240/184 224/241/184 144/239/184 +f 2/8/185 86/69/185 224/241/185 75/240/185 +f 26/71/186 144/239/186 224/241/186 86/69/186 +f 23/39/187 145/242/187 225/243/187 83/212/187 +f 24/87/188 54/181/188 225/243/188 145/242/188 +f 11/116/189 83/212/189 225/243/189 54/181/189 +f 23/39/190 146/38/190 226/244/190 145/242/190 +f 16/14/191 147/245/191 226/244/191 146/38/191 +f 24/87/192 145/242/192 226/244/192 147/245/192 +f 16/14/193 76/246/193 227/247/193 147/245/193 +f 6/61/194 84/85/194 227/247/194 76/246/194 +f 24/87/195 147/245/195 227/247/195 84/85/195 +f 17/35/196 148/248/196 228/249/196 47/250/196 +f 22/65/197 52/62/197 228/249/197 148/248/197 +f 6/61/198 47/250/198 228/249/198 52/62/198 +f 17/35/199 149/34/199 229/251/199 148/248/199 +f 20/33/200 150/252/200 229/251/200 149/34/200 +f 22/65/201 148/248/201 229/251/201 150/252/201 +f 20/33/202 80/253/202 230/254/202 150/252/202 +f 5/54/203 82/218/203 230/254/203 80/253/203 +f 22/65/204 150/252/204 230/254/204 82/218/204 +f 20/28/205 151/255/205 231/256/205 80/257/205 +f 21/58/206 51/55/206 231/256/206 151/255/206 +f 5/54/207 80/257/207 231/256/207 51/55/207 +f 20/28/208 152/27/208 232/258/208 151/255/208 +f 18/26/209 153/259/209 232/258/209 152/27/209 +f 21/58/210 151/255/210 232/258/210 153/259/210 +f 18/26/211 78/260/211 233/261/211 153/259/211 +f 4/47/212 81/224/212 233/261/212 78/260/212 +f 21/58/213 153/259/213 233/261/213 81/224/213 +f 18/21/214 154/262/214 234/263/214 78/264/214 +f 19/51/215 49/48/215 234/263/215 154/262/215 +f 4/47/216 78/264/216 234/263/216 49/48/216 +f 18/21/217 155/20/217 235/265/217 154/262/217 +f 13/19/218 156/266/218 235/265/218 155/20/218 +f 19/51/219 154/262/219 235/265/219 156/266/219 +f 13/19/220 73/267/220 236/268/220 156/266/220 +f 3/234/221 79/232/221 236/268/221 73/267/221 +f 19/51/222 156/266/222 236/268/222 79/232/222 +f 16/14/223 157/269/223 237/270/223 76/246/223 +f 17/271/224 47/272/224 237/270/224 157/269/224 +f 6/61/225 76/246/225 237/270/225 47/272/225 +f 16/14/226 158/13/226 238/273/226 157/269/226 +f 14/12/227 159/274/227 238/273/227 158/13/227 +f 17/271/228 157/269/228 238/273/228 159/274/228 +f 14/12/229 74/275/229 239/276/229 159/274/229 +f 1/277/230 77/278/230 239/276/230 74/275/230 +f 17/271/231 159/274/231 239/276/231 77/278/231 +f 13/7/232 160/279/232 240/280/232 73/281/232 +f 15/44/233 45/41/233 240/280/233 160/279/233 +f 3/40/234 73/281/234 240/280/234 45/41/234 +f 13/7/235 161/6/235 241/282/235 160/279/235 +f 14/5/236 162/283/236 241/282/236 161/6/236 +f 15/44/237 160/279/237 241/282/237 162/283/237 +f 14/5/238 44/284/238 242/285/238 162/283/238 +f 2/8/239 75/240/239 242/285/239 44/284/239 +f 15/44/240 162/283/240 242/285/240 75/240/240 diff --git a/data/models/regolith/particle_3.mtl b/data/models/regolith/particle_3.mtl new file mode 100644 index 0000000000..681ee11066 --- /dev/null +++ b/data/models/regolith/particle_3.mtl @@ -0,0 +1,12 @@ +# Blender 4.2.1 LTS MTL File: 'lunarregolith.blend' +# www.blender.org + +newmtl LunarRegolithMaterial.032 +Ns 10.000005 +Ka 1.000000 1.000000 1.000000 +Kd 0.500000 0.500000 0.500000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 diff --git a/data/models/regolith/particle_3.obj b/data/models/regolith/particle_3.obj new file mode 100644 index 0000000000..72f2548ad8 --- /dev/null +++ b/data/models/regolith/particle_3.obj @@ -0,0 +1,1013 @@ +# Blender 4.2.1 LTS +# www.blender.org +mtllib particle_3.mtl +o Icosphere +v -0.004685 -0.003146 0.000828 +v -0.000709 -0.001610 0.002115 +v -0.003317 0.000596 0.003220 +v -0.002175 0.000386 -0.000293 +v -0.001347 -0.001187 -0.001720 +v -0.000221 -0.001984 -0.000172 +v 0.001042 0.001119 0.001730 +v 0.000171 0.002363 0.000357 +v 0.000257 0.000482 -0.000619 +v 0.001625 -0.000246 -0.001597 +v 0.001089 -0.000280 0.000184 +v 0.003155 0.002193 -0.000521 +v -0.004791 -0.001571 0.002408 +v -0.002664 -0.002641 0.001902 +v -0.002276 -0.001007 0.003437 +v -0.000536 -0.002403 0.000960 +v -0.002192 -0.003016 0.000166 +v -0.004106 -0.001174 0.000152 +v -0.003452 0.000652 0.001205 +v -0.003005 -0.002234 -0.000920 +v -0.001729 -0.000380 -0.001009 +v -0.000915 -0.001752 -0.000991 +v 0.000319 -0.000731 0.000767 +v 0.000913 -0.001438 0.000111 +v -0.000620 0.001127 0.002842 +v 0.000233 -0.000194 0.002321 +v -0.001047 0.001338 0.000058 +v -0.001331 0.002115 0.001690 +v -0.000326 -0.000013 -0.001274 +v -0.000553 0.000376 -0.000424 +v 0.000520 -0.000860 -0.000651 +v 0.000161 -0.000644 -0.001554 +v 0.001010 0.000266 0.000717 +v 0.000864 0.002324 0.001408 +v 0.000312 0.001432 -0.000453 +v 0.001047 0.000495 -0.001650 +v 0.001781 -0.000298 -0.000588 +v 0.002276 0.001796 0.000740 +v 0.002441 0.000738 -0.000033 +v 0.001819 0.002642 -0.000055 +v 0.001718 0.001730 -0.001152 +v 0.002618 0.000921 -0.001284 +v -0.005026 -0.002593 0.001624 +v -0.001545 -0.002170 0.002148 +v -0.003048 -0.000204 0.003595 +v -0.000638 -0.002064 0.001552 +v -0.001064 -0.002532 -0.000052 +v -0.004790 -0.002385 0.000530 +v -0.002872 0.000544 0.000277 +v -0.004112 -0.002897 -0.000081 +v -0.001574 -0.000841 -0.001495 +v -0.000555 -0.001882 -0.000555 +v -0.000112 -0.001183 0.001460 +v 0.001043 -0.000842 0.000136 +v -0.002075 0.000940 0.003248 +v 0.000689 0.000500 0.002059 +v -0.001654 0.000845 -0.000131 +v -0.000469 0.002365 0.000939 +v -0.000855 -0.000579 -0.001612 +v -0.000130 0.000347 -0.000427 +v 0.000155 -0.001404 -0.000399 +v 0.000962 -0.000439 -0.001625 +v 0.001092 0.000677 0.001260 +v 0.000519 0.002541 0.000866 +v 0.000275 0.000857 -0.000500 +v 0.001463 0.000103 -0.001787 +v 0.001485 -0.000329 -0.000131 +v 0.001638 0.001458 0.001252 +v 0.003066 0.001571 -0.000278 +v 0.000968 0.002566 0.000162 +v 0.000869 0.001044 -0.000902 +v 0.002184 0.000253 -0.001558 +v -0.004262 -0.000429 0.003051 +v -0.003975 -0.003102 0.001418 +v -0.001388 -0.001444 0.002866 +v -0.000334 -0.002335 0.000347 +v -0.003644 -0.003314 0.000487 +v -0.003140 -0.000210 -0.000156 +v -0.003651 0.000708 0.002387 +v -0.002108 -0.001685 -0.001486 +v -0.001968 0.000029 -0.000637 +v -0.001223 -0.001544 -0.001503 +v 0.000670 -0.000460 0.000380 +v 0.000415 -0.001780 0.000003 +v 0.000411 0.001174 0.002307 +v -0.000242 -0.000939 0.002321 +v -0.000426 0.001924 0.000189 +v -0.002455 0.001497 0.002594 +v -0.000013 0.000217 -0.000860 +v -0.001283 0.000424 -0.000419 +v 0.001113 -0.000539 -0.001172 +v -0.000635 -0.000966 -0.001695 +v 0.000979 -0.000014 0.000370 +v 0.001056 0.001755 0.001686 +v 0.000263 0.001985 -0.000129 +v 0.000599 0.000527 -0.001125 +v 0.001815 -0.000266 -0.001178 +v 0.002935 0.002126 0.000101 +v 0.001676 0.000157 0.000101 +v 0.002686 0.002568 -0.000329 +v 0.002660 0.002165 -0.000938 +v 0.003067 0.001663 -0.000939 +v 0.002765 0.000884 -0.000668 +v 0.002169 0.000209 -0.000341 +v 0.002346 0.000278 -0.000990 +v 0.002328 0.001463 -0.001355 +v 0.001924 0.000768 -0.001631 +v 0.001405 0.001107 -0.001448 +v 0.001881 0.002326 -0.000696 +v 0.000999 0.001621 -0.000792 +v 0.001068 0.002167 -0.000364 +v 0.002259 0.002430 0.000398 +v 0.001442 0.002609 0.000674 +v 0.001702 0.002149 0.001111 +v 0.002503 0.001291 0.000357 +v 0.001705 0.000987 0.000749 +v 0.001715 0.000497 0.000350 +v 0.001337 -0.000889 -0.000214 +v 0.000804 -0.001172 -0.000241 +v 0.001211 -0.000622 -0.000623 +v 0.000643 -0.000071 -0.001703 +v -0.000098 -0.000311 -0.001565 +v 0.000314 0.000222 -0.001451 +v -0.000160 0.000808 -0.000372 +v -0.000746 0.000829 -0.000256 +v -0.000311 0.001362 -0.000251 +v -0.000181 0.002350 0.001619 +v -0.001024 0.001805 0.002427 +v 0.000172 0.001851 0.002152 +v 0.000665 0.000037 0.001452 +v 0.000325 -0.000459 0.001501 +v 0.000575 -0.000195 0.000718 +v 0.000347 -0.000766 -0.001142 +v -0.000156 -0.001246 -0.000805 +v -0.000365 -0.001179 -0.001312 +v -0.000436 0.000148 -0.000781 +v -0.000942 -0.000154 -0.001193 +v -0.001044 0.000089 -0.000729 +v -0.001274 0.001850 0.000801 +v -0.002209 0.001162 0.000556 +v -0.002491 0.001519 0.001526 +v -0.000130 0.000404 0.002775 +v -0.001491 0.000091 0.003380 +v -0.000868 -0.000600 0.003072 +v 0.000620 -0.001165 0.000406 +v -0.000012 -0.001609 0.000885 +v 0.000297 -0.001967 0.000505 +v -0.001551 -0.002451 -0.000507 +v -0.002803 -0.002827 -0.000422 +v -0.001977 -0.002132 -0.001068 +v -0.002494 -0.001297 -0.001096 +v -0.003740 -0.001837 -0.000458 +v -0.002918 -0.000747 -0.000577 +v -0.003995 -0.000275 0.000702 +v -0.004837 -0.001483 0.001291 +v -0.004457 -0.000420 0.001912 +v -0.001345 -0.002839 0.000643 +v -0.001500 -0.002662 0.001437 +v -0.002529 -0.003060 0.001026 +v -0.003754 -0.001370 0.003183 +v -0.003987 -0.002313 0.002326 +v -0.002595 -0.001922 0.002812 +v -0.004467 -0.002757 0.001833 +v -0.001200 -0.002359 0.001733 +v -0.005064 -0.002232 0.001190 +v -0.004339 -0.002445 -0.000052 +v -0.003620 -0.003126 -0.000035 +v -0.000245 -0.001627 0.001281 +v -0.002230 0.000290 0.003523 +v -0.002262 0.000883 0.000202 +v -0.001121 -0.000491 -0.001478 +v -0.000176 -0.001476 -0.000595 +v 0.000051 -0.000831 0.001757 +v -0.001872 0.001487 0.002822 +v -0.001186 0.000701 -0.000284 +v -0.000538 -0.000632 -0.001661 +v 0.000486 -0.001442 -0.000212 +v 0.001490 0.001042 0.001067 +v 0.001019 0.002640 0.000557 +v 0.000697 0.001160 -0.000727 +v 0.001916 0.000379 -0.001714 +v 0.001788 0.000024 -0.000110 +v 0.003067 0.001400 -0.000651 +v 0.002463 0.000442 -0.000662 +v 0.002189 0.000075 -0.001290 +v 0.002772 0.001810 -0.001124 +v 0.001893 0.001146 -0.001536 +v 0.000952 0.000897 -0.001165 +v 0.002472 0.002448 -0.000687 +v 0.001317 0.002072 -0.000657 +v 0.000780 0.002276 -0.000128 +v 0.002717 0.002449 0.000057 +v 0.001827 0.002437 0.000753 +v 0.001529 0.001818 0.001371 +v 0.002936 0.001697 0.000091 +v 0.001985 0.000905 0.000489 +v 0.001441 0.000200 0.000272 +v 0.001307 -0.000730 -0.000074 +v 0.001140 -0.000900 -0.000334 +v 0.001384 -0.000478 -0.000998 +v 0.001034 -0.000158 -0.001767 +v 0.000295 -0.000016 -0.001595 +v 0.000280 0.000308 -0.001144 +v -0.000020 0.000623 -0.000383 +v -0.000385 0.000987 -0.000306 +v -0.000173 0.001750 -0.000111 +v -0.000055 0.002481 0.001156 +v -0.000305 0.002059 0.002088 +v 0.000559 0.001619 0.002080 +v 0.000826 0.000367 0.001599 +v 0.000523 -0.000199 0.001205 +v 0.000675 -0.000204 0.000448 +v 0.000820 -0.000588 -0.001330 +v -0.000067 -0.001046 -0.001061 +v -0.000723 -0.001254 -0.001553 +v -0.000200 0.000202 -0.000641 +v -0.000769 0.000051 -0.000898 +v -0.001388 0.000194 -0.000608 +v -0.000714 0.002096 0.000631 +v -0.002001 0.001545 0.000941 +v -0.002931 0.001334 0.002207 +v 0.000377 0.000709 0.002421 +v -0.000804 -0.000044 0.003140 +v -0.000814 -0.001026 0.002841 +v 0.000781 -0.000812 0.000299 +v 0.000328 -0.001610 0.000588 +v 0.000187 -0.002080 0.000302 +v -0.001047 -0.002321 -0.000390 +v -0.002097 -0.002494 -0.000689 +v -0.001816 -0.001827 -0.001409 +v -0.002081 -0.001301 -0.001422 +v -0.003060 -0.001277 -0.000737 +v -0.002693 -0.000289 -0.000493 +v -0.003401 0.000047 0.000246 +v -0.004514 -0.000721 0.001299 +v -0.004267 -0.000046 0.002514 +v -0.000922 -0.002620 0.000309 +v -0.001769 -0.002902 0.001046 +v -0.003434 -0.003254 0.000987 +v -0.003829 -0.000705 0.003405 +v -0.003481 -0.001907 0.002834 +v -0.001840 -0.001878 0.002663 +vn -0.3340 -0.8524 0.4023 +vn 0.0234 -0.7544 0.6560 +vn -0.3957 -0.4857 0.7794 +vn 0.4778 -0.6271 0.6152 +vn 0.2188 -0.7955 0.5650 +vn 0.4696 -0.7616 0.4466 +vn -0.9250 -0.2835 -0.2531 +vn -0.9739 0.1984 0.1106 +vn -0.8370 0.3266 -0.4392 +vn -0.7572 -0.3322 -0.5623 +vn -0.7283 0.2364 -0.6432 +vn -0.5291 -0.1137 -0.8409 +vn -0.3006 -0.8701 -0.3905 +vn -0.1626 -0.6360 -0.7544 +vn 0.1244 -0.9181 -0.3763 +vn 0.7877 -0.4242 0.4467 +vn 0.7813 -0.4655 0.4157 +vn 0.8639 -0.3215 0.3877 +vn -0.1417 0.3952 0.9076 +vn 0.1492 -0.0701 0.9863 +vn 0.2325 0.3038 0.9239 +vn -0.3823 0.6182 -0.6868 +vn -0.5096 0.7431 -0.4337 +vn -0.3408 0.7181 -0.6068 +vn -0.2867 0.3953 -0.8727 +vn -0.3895 0.6462 -0.6563 +vn -0.2133 0.6632 -0.7174 +vn 0.5231 -0.5715 -0.6322 +vn 0.5425 -0.5793 -0.6084 +vn 0.4926 -0.6133 -0.6174 +vn 0.7484 -0.5998 0.2831 +vn 0.8385 -0.5161 0.1749 +vn 0.8251 -0.4878 0.2851 +vn -0.2225 0.6751 0.7034 +vn 0.1525 0.5767 0.8026 +vn -0.1422 0.8926 0.4279 +vn -0.1416 0.4712 -0.8706 +vn -0.1107 0.4887 -0.8654 +vn -0.0083 0.3829 -0.9238 +vn -0.0526 0.1796 -0.9823 +vn -0.1486 0.5615 -0.8140 +vn 0.1519 0.0703 -0.9859 +vn 0.3743 -0.5435 -0.7514 +vn 0.3814 -0.5707 -0.7272 +vn 0.4961 -0.5769 -0.6488 +vn 0.6987 -0.4825 0.5282 +vn 0.6670 -0.6073 0.4316 +vn 0.6879 -0.4813 0.5433 +vn -0.2770 0.9504 -0.1417 +vn 0.0035 0.9374 0.3483 +vn -0.0387 0.9982 -0.0462 +vn -0.5967 0.2662 -0.7571 +vn -0.5023 0.1502 -0.8515 +vn -0.4940 0.2690 -0.8268 +vn 0.3462 -0.3254 -0.8799 +vn -0.0372 0.2526 -0.9669 +vn 0.4577 0.1068 -0.8827 +vn 0.5134 -0.5247 0.6790 +vn 0.6371 -0.6435 0.4242 +vn 0.5740 -0.5862 0.5717 +vn 0.8134 -0.5130 0.2742 +vn 0.8572 -0.4311 -0.2816 +vn 0.9942 -0.1070 -0.0139 +vn 0.7831 -0.5519 0.2865 +vn 0.7359 -0.6643 0.1307 +vn 0.8510 -0.4969 -0.1699 +vn 0.7082 -0.7050 0.0369 +vn 0.6036 -0.7039 -0.3745 +vn 0.8688 -0.4389 -0.2291 +vn 0.4734 0.0758 -0.8776 +vn -0.0164 0.5166 -0.8561 +vn 0.5786 0.4706 -0.6661 +vn 0.3659 0.1515 -0.9182 +vn -0.1207 0.3219 -0.9391 +vn -0.1159 0.5207 -0.8459 +vn -0.6180 0.5416 -0.5699 +vn -0.6920 0.5585 -0.4575 +vn -0.6160 0.5745 -0.5389 +vn -0.1130 0.6205 -0.7760 +vn -0.1003 0.9175 -0.3848 +vn 0.4079 0.7534 -0.5157 +vn -0.3869 0.5819 -0.7153 +vn -0.4974 0.5733 -0.6511 +vn -0.3507 0.8082 -0.4731 +vn -0.3453 0.4977 -0.7957 +vn -0.3606 0.7280 -0.5831 +vn -0.2231 0.7555 -0.6160 +vn 0.1692 0.9453 0.2787 +vn 0.5180 0.4252 0.7422 +vn 0.7163 0.6498 0.2543 +vn 0.2829 0.9301 0.2343 +vn 0.3165 0.7411 0.5921 +vn 0.6248 0.4246 0.6553 +vn 0.4051 0.4751 0.7811 +vn 0.5961 -0.0037 0.8029 +vn 0.6445 0.0950 0.7587 +vn 0.6845 -0.1342 0.7165 +vn 0.7568 -0.4513 0.4728 +vn 0.9425 -0.0041 0.3341 +vn 0.5217 -0.3849 0.7614 +vn 0.5097 -0.5381 0.6713 +vn 0.5395 -0.5413 0.6449 +vn 0.4814 -0.6699 0.5652 +vn 0.4153 -0.4490 0.7911 +vn 0.4992 -0.5475 0.6716 +vn 0.7279 -0.2364 0.6436 +vn 0.8122 -0.2910 0.5057 +vn 0.6242 -0.1394 0.7687 +vn 0.3923 -0.6784 -0.6212 +vn 0.2971 -0.6838 -0.6664 +vn 0.4217 -0.6956 -0.5817 +vn 0.3287 -0.9231 -0.1996 +vn 0.3526 -0.9117 -0.2109 +vn 0.4636 -0.8838 -0.0636 +vn -0.0815 -0.2735 -0.9584 +vn -0.1374 0.1779 -0.9744 +vn 0.1890 -0.4366 -0.8796 +vn -0.1742 -0.0265 -0.9844 +vn -0.4022 0.4792 -0.7801 +vn -0.3230 0.3828 -0.8655 +vn -0.4186 0.8800 -0.2245 +vn -0.5290 0.7979 -0.2891 +vn -0.4447 0.8142 -0.3732 +vn 0.0198 0.1214 -0.9924 +vn -0.2864 0.0358 -0.9574 +vn -0.5233 0.3028 -0.7966 +vn -0.1797 0.2346 -0.9553 +vn -0.3400 0.2870 -0.8956 +vn -0.2833 0.1304 -0.9501 +vn -0.3909 0.5158 -0.7623 +vn -0.3537 0.6854 -0.6365 +vn -0.3027 0.4438 -0.8434 +vn -0.2278 0.9665 0.1182 +vn 0.0768 0.9472 0.3112 +vn -0.1854 0.9630 -0.1953 +vn -0.1297 0.8793 0.4582 +vn 0.1596 0.5878 0.7931 +vn 0.1776 0.7743 0.6073 +vn 0.4076 0.3376 0.8485 +vn 0.6461 0.0928 0.7576 +vn 0.4444 0.5096 0.7368 +vn 0.8272 -0.4618 0.3201 +vn 0.8397 -0.4911 0.2319 +vn 0.8732 -0.3160 0.3711 +vn 0.8156 -0.5375 0.2144 +vn 0.8845 -0.4475 0.1319 +vn 0.7445 -0.6573 0.1171 +vn 0.8390 -0.2883 0.4614 +vn 0.4714 -0.3075 0.8266 +vn 0.6332 -0.6710 0.3857 +vn 0.2656 -0.9297 -0.2552 +vn 0.2004 -0.9106 -0.3616 +vn 0.2886 -0.9102 -0.2972 +vn 0.5030 -0.7837 -0.3645 +vn 0.5854 -0.7371 -0.3376 +vn 0.5307 -0.7603 -0.3744 +vn 0.4302 -0.7437 -0.5117 +vn 0.1801 -0.4694 -0.8644 +vn 0.4301 -0.6247 -0.6518 +vn -0.2041 0.9382 -0.2793 +vn 0.0800 0.8374 -0.5406 +vn -0.4732 0.7999 -0.3690 +vn -0.2081 0.8928 -0.3994 +vn -0.3088 0.8134 -0.4930 +vn -0.1274 0.8443 -0.5205 +vn -0.1177 0.6142 -0.7803 +vn -0.1389 0.6521 -0.7453 +vn 0.0120 0.6837 -0.7296 +vn -0.4800 0.6535 -0.5853 +vn -0.4790 0.8270 -0.2944 +vn -0.3865 0.7853 -0.4837 +vn -0.3791 0.7217 -0.5791 +vn -0.5293 0.7347 -0.4245 +vn -0.4090 0.8644 -0.2923 +vn -0.6461 0.7440 -0.1702 +vn -0.5579 0.7572 0.3396 +vn -0.4299 0.9022 0.0333 +vn 0.4533 0.2092 0.8665 +vn 0.6594 -0.1865 0.7283 +vn 0.7104 0.0344 0.7030 +vn 0.3657 0.1752 0.9141 +vn 0.2927 -0.1565 0.9433 +vn 0.5891 -0.2019 0.7824 +vn 0.3390 -0.4151 0.8442 +vn 0.5428 -0.6143 0.5728 +vn 0.6292 -0.3616 0.6880 +vn 0.7097 -0.0242 0.7040 +vn 0.5956 -0.1132 0.7952 +vn 0.4802 -0.0899 0.8726 +vn 0.6597 -0.1437 0.7377 +vn 0.5900 -0.2897 0.7536 +vn 0.6524 -0.1715 0.7382 +vn 0.4811 -0.8707 0.1019 +vn 0.3692 -0.7961 -0.4794 +vn 0.6366 -0.7596 -0.1336 +vn 0.2884 -0.8413 -0.4573 +vn 0.3789 -0.7121 -0.5910 +vn 0.4364 -0.7389 -0.5135 +vn 0.2200 -0.8437 -0.4896 +vn -0.0066 -0.6761 -0.7368 +vn 0.2909 -0.7193 -0.6309 +vn -0.0589 -0.6920 -0.7195 +vn 0.0580 -0.4700 -0.8807 +vn 0.3107 -0.7901 -0.5284 +vn -0.6034 0.1793 -0.7770 +vn -0.5416 0.5076 -0.6701 +vn -0.3963 0.2414 -0.8858 +vn -0.4973 0.1346 -0.8571 +vn -0.5831 0.3608 -0.7279 +vn -0.4409 0.4132 -0.7968 +vn -0.5622 0.3529 -0.7479 +vn -0.4116 0.5342 -0.7384 +vn -0.3963 0.4221 -0.8153 +vn -0.6567 0.4276 -0.6212 +vn -0.6324 0.6391 -0.4376 +vn -0.4587 0.5593 -0.6905 +vn -0.8238 0.3628 -0.4356 +vn -0.9441 0.3292 0.0157 +vn -0.7780 0.5858 -0.2271 +vn -0.9365 0.3107 0.1625 +vn -0.6965 0.6020 0.3906 +vn -0.7729 0.6159 -0.1526 +vn 0.4526 -0.8913 0.0285 +vn 0.3143 -0.9089 -0.2742 +vn 0.4403 -0.7979 -0.4118 +vn 0.3775 -0.8857 0.2701 +vn 0.1649 -0.8822 0.4411 +vn 0.1943 -0.9804 0.0331 +vn 0.1498 -0.8751 0.4602 +vn -0.1081 -0.9769 0.1842 +vn 0.2077 -0.9777 0.0300 +vn -0.6014 -0.2169 0.7690 +vn -0.0764 -0.2908 0.9537 +vn -0.4353 0.2927 0.8513 +vn -0.3825 -0.5680 0.7288 +vn 0.0031 -0.7840 0.6208 +vn 0.0001 -0.5571 0.8305 +vn 0.1860 -0.7873 0.5879 +vn 0.4449 -0.6764 0.5870 +vn 0.2004 -0.5927 0.7801 +vt 0.181819 0.000000 +vt 0.204546 0.039365 +vt 0.181819 0.052487 +vt 0.159092 0.039365 +vt 0.227273 0.078731 +vt 0.181819 0.078731 +vt 0.136365 0.078731 +vt 0.272728 0.157461 +vt 0.295455 0.118096 +vt 0.318182 0.131218 +vt 0.318182 0.157461 +vt 0.318182 0.078731 +vt 0.340910 0.118096 +vt 0.363637 0.157461 +vt 0.909091 0.000000 +vt 0.931818 0.039365 +vt 0.909091 0.052487 +vt 0.886364 0.039365 +vt 0.954545 0.078731 +vt 0.909091 0.078731 +vt 0.863636 0.078731 +vt 0.727273 0.000000 +vt 0.750000 0.039365 +vt 0.727273 0.052487 +vt 0.704546 0.039365 +vt 0.772727 0.078731 +vt 0.727273 0.078731 +vt 0.681818 0.078731 +vt 0.545455 0.000000 +vt 0.568182 0.039365 +vt 0.545455 0.052487 +vt 0.522728 0.039365 +vt 0.590909 0.078731 +vt 0.545455 0.078731 +vt 0.500000 0.078731 +vt 0.318182 0.183704 +vt 0.295455 0.196826 +vt 0.340910 0.196826 +vt 0.318183 0.236191 +vt 0.090910 0.157461 +vt 0.136365 0.157461 +vt 0.136365 0.183704 +vt 0.113637 0.196826 +vt 0.181819 0.157461 +vt 0.159092 0.196826 +vt 0.136364 0.236191 +vt 0.818182 0.157461 +vt 0.863636 0.157461 +vt 0.863636 0.183704 +vt 0.840909 0.196826 +vt 0.909091 0.157461 +vt 0.886364 0.196826 +vt 0.863637 0.236191 +vt 0.636364 0.157461 +vt 0.681819 0.157461 +vt 0.681818 0.183704 +vt 0.659091 0.196826 +vt 0.727273 0.157461 +vt 0.704546 0.196826 +vt 0.681819 0.236191 +vt 0.454546 0.157461 +vt 0.500001 0.157461 +vt 0.500001 0.183704 +vt 0.477273 0.196826 +vt 0.545455 0.157461 +vt 0.522728 0.196826 +vt 0.500001 0.236191 +vt 0.272728 0.209948 +vt 0.250001 0.196826 +vt 0.272728 0.236191 +vt 0.227274 0.236191 +vt 0.090910 0.209948 +vt 0.068183 0.196826 +vt 0.090910 0.236191 +vt 0.045455 0.236191 +vt 0.818182 0.209948 +vt 0.795455 0.196826 +vt 0.818182 0.236191 +vt 0.772728 0.236191 +vt 0.636364 0.209948 +vt 0.613637 0.196826 +vt 0.636364 0.236191 +vt 0.590910 0.236191 +vt 0.454546 0.209948 +vt 0.431819 0.196826 +vt 0.454546 0.236191 +vt 0.409092 0.236191 +vt 0.181819 0.314921 +vt 0.227274 0.314921 +vt 0.227274 0.341165 +vt 0.204546 0.354286 +vt 0.272728 0.314921 +vt 0.250001 0.354286 +vt 0.227273 0.393651 +vt 0.000000 0.314921 +vt 0.045455 0.314921 +vt 0.045455 0.341165 +vt 0.022728 0.354286 +vt 0.090910 0.314921 +vt 0.068182 0.354286 +vt 0.045455 0.393651 +vt 0.727273 0.314921 +vt 0.772728 0.314921 +vt 0.772727 0.341165 +vt 0.750000 0.354286 +vt 0.818182 0.314921 +vt 0.795455 0.354286 +vt 0.772727 0.393651 +vt 0.545455 0.314921 +vt 0.590910 0.314921 +vt 0.590909 0.341165 +vt 0.568182 0.354286 +vt 0.636364 0.314921 +vt 0.613637 0.354286 +vt 0.590909 0.393651 +vt 0.363637 0.314921 +vt 0.409092 0.314921 +vt 0.409092 0.341165 +vt 0.386364 0.354286 +vt 0.454546 0.314921 +vt 0.431819 0.354286 +vt 0.409092 0.393651 +vt 0.454546 0.393652 +vt 0.454546 0.419895 +vt 0.431819 0.433017 +vt 0.500000 0.393651 +vt 0.477273 0.433017 +vt 0.454546 0.472382 +vt 0.454546 0.367408 +vt 0.477273 0.354286 +vt 0.500001 0.314921 +vt 0.500000 0.341165 +vt 0.522728 0.354286 +vt 0.636364 0.393652 +vt 0.636364 0.419895 +vt 0.613637 0.433017 +vt 0.681818 0.393651 +vt 0.659091 0.433017 +vt 0.636364 0.472382 +vt 0.636364 0.367408 +vt 0.659091 0.354286 +vt 0.681819 0.314921 +vt 0.681818 0.341165 +vt 0.704546 0.354286 +vt 0.818182 0.393652 +vt 0.818182 0.419895 +vt 0.795455 0.433017 +vt 0.863636 0.393651 +vt 0.840909 0.433017 +vt 0.818182 0.472382 +vt 0.818182 0.367408 +vt 0.840909 0.354286 +vt 0.863637 0.314921 +vt 0.863636 0.341165 +vt 0.909091 0.314921 +vt 0.886364 0.354286 +vt 0.090910 0.393652 +vt 0.090910 0.419895 +vt 0.068183 0.433017 +vt 0.136365 0.393651 +vt 0.113637 0.433017 +vt 0.090910 0.472382 +vt 0.090910 0.367408 +vt 0.113637 0.354286 +vt 0.136364 0.314921 +vt 0.136364 0.341165 +vt 0.159092 0.354286 +vt 0.272728 0.393652 +vt 0.272728 0.419895 +vt 0.250001 0.433017 +vt 0.318182 0.393651 +vt 0.295455 0.433017 +vt 0.272728 0.472382 +vt 0.272728 0.367408 +vt 0.295455 0.354286 +vt 0.318182 0.314921 +vt 0.318182 0.341165 +vt 0.340910 0.354286 +vt 0.431819 0.275556 +vt 0.409092 0.288678 +vt 0.386364 0.275556 +vt 0.454546 0.262434 +vt 0.477273 0.275556 +vt 0.522728 0.275556 +vt 0.500000 0.288678 +vt 0.613637 0.275556 +vt 0.590910 0.288678 +vt 0.568182 0.275556 +vt 0.636364 0.262434 +vt 0.659091 0.275556 +vt 0.704546 0.275556 +vt 0.681819 0.288678 +vt 0.795455 0.275556 +vt 0.772728 0.288678 +vt 0.750000 0.275556 +vt 0.818182 0.262434 +vt 0.840909 0.275556 +vt 0.886364 0.275556 +vt 0.863636 0.288678 +vt 0.068182 0.275556 +vt 0.045455 0.288678 +vt 0.022728 0.275556 +vt 0.090910 0.262434 +vt 0.113637 0.275556 +vt 0.159092 0.275556 +vt 0.136364 0.288678 +vt 0.250001 0.275556 +vt 0.227274 0.288678 +vt 0.204546 0.275556 +vt 0.272728 0.262434 +vt 0.295455 0.275556 +vt 0.340910 0.275556 +vt 0.318183 0.288678 +vt 0.545455 0.236191 +vt 0.545455 0.262434 +vt 0.545455 0.209948 +vt 0.568182 0.196826 +vt 0.590910 0.157461 +vt 0.590909 0.183704 +vt 0.727273 0.236191 +vt 0.727273 0.262434 +vt 0.727273 0.209948 +vt 0.750000 0.196826 +vt 0.772728 0.157461 +vt 0.772727 0.183704 +vt 0.909091 0.236191 +vt 0.909091 0.262434 +vt 0.954545 0.236191 +vt 0.931818 0.275556 +vt 0.909091 0.209948 +vt 0.931818 0.196826 +vt 0.954546 0.157461 +vt 0.954545 0.183704 +vt 1.000000 0.157461 +vt 0.977273 0.196826 +vt 0.181819 0.236191 +vt 0.181819 0.262434 +vt 0.181819 0.209948 +vt 0.204546 0.196826 +vt 0.227274 0.157461 +vt 0.227274 0.183704 +vt 0.363637 0.236191 +vt 0.363637 0.262434 +vt 0.363637 0.209948 +vt 0.386364 0.196826 +vt 0.409092 0.157461 +vt 0.409092 0.183704 +vt 0.522728 0.118096 +vt 0.500001 0.131218 +vt 0.477273 0.118096 +vt 0.545455 0.104974 +vt 0.568182 0.118096 +vt 0.613637 0.118096 +vt 0.590910 0.131218 +vt 0.704546 0.118096 +vt 0.681819 0.131218 +vt 0.659091 0.118096 +vt 0.727273 0.104974 +vt 0.750000 0.118096 +vt 0.795455 0.118096 +vt 0.772727 0.131218 +vt 0.886364 0.118096 +vt 0.863636 0.131218 +vt 0.840909 0.118096 +vt 0.909091 0.104974 +vt 0.931818 0.118096 +vt 0.977273 0.118096 +vt 0.954546 0.131218 +vt 0.386364 0.118096 +vt 0.409092 0.131218 +vt 0.409092 0.078731 +vt 0.431819 0.118096 +vt 0.363637 0.104974 +vt 0.363637 0.078731 +vt 0.340910 0.039365 +vt 0.363637 0.052487 +vt 0.363637 0.000000 +vt 0.386364 0.039365 +vt 0.159092 0.118096 +vt 0.136365 0.131218 +vt 0.113637 0.118096 +vt 0.181819 0.104974 +vt 0.204546 0.118096 +vt 0.250001 0.118096 +vt 0.227274 0.131218 +s 0 +usemtl LunarRegolithMaterial.032 +f 1/1/1 74/2/1 163/3/1 43/4/1 +f 14/5/2 161/6/2 163/3/2 74/2/2 +f 13/7/3 43/4/3 163/3/3 161/6/3 +f 2/8/4 44/9/4 164/10/4 46/11/4 +f 14/12/5 158/13/5 164/10/5 44/9/5 +f 16/14/6 46/11/6 164/10/6 158/13/6 +f 1/15/7 43/16/7 165/17/7 48/18/7 +f 13/19/8 155/20/8 165/17/8 43/16/8 +f 18/21/9 48/18/9 165/17/9 155/20/9 +f 1/22/10 48/23/10 166/24/10 50/25/10 +f 18/26/11 152/27/11 166/24/11 48/23/11 +f 20/28/12 50/25/12 166/24/12 152/27/12 +f 1/29/13 50/30/13 167/31/13 77/32/13 +f 20/33/14 149/34/14 167/31/14 50/30/14 +f 17/35/15 77/32/15 167/31/15 149/34/15 +f 2/8/16 46/11/16 168/36/16 53/37/16 +f 16/14/17 146/38/17 168/36/17 46/11/17 +f 23/39/18 53/37/18 168/36/18 146/38/18 +f 3/40/19 45/41/19 169/42/19 55/43/19 +f 15/44/20 143/45/20 169/42/20 45/41/20 +f 25/46/21 55/43/21 169/42/21 143/45/21 +f 4/47/22 49/48/22 170/49/22 57/50/22 +f 19/51/23 140/52/23 170/49/23 49/48/23 +f 27/53/24 57/50/24 170/49/24 140/52/24 +f 5/54/25 51/55/25 171/56/25 59/57/25 +f 21/58/26 137/59/26 171/56/26 51/55/26 +f 29/60/27 59/57/27 171/56/27 137/59/27 +f 6/61/28 52/62/28 172/63/28 61/64/28 +f 22/65/29 134/66/29 172/63/29 52/62/29 +f 31/67/30 61/64/30 172/63/30 134/66/30 +f 2/8/31 53/37/31 173/68/31 86/69/31 +f 23/39/32 131/70/32 173/68/32 53/37/32 +f 26/71/33 86/69/33 173/68/33 131/70/33 +f 3/40/34 55/43/34 174/72/34 88/73/34 +f 25/46/35 128/74/35 174/72/35 55/43/35 +f 28/75/36 88/73/36 174/72/36 128/74/36 +f 4/47/37 57/50/37 175/76/37 90/77/37 +f 27/53/38 125/78/38 175/76/38 57/50/38 +f 30/79/39 90/77/39 175/76/39 125/78/39 +f 5/54/40 59/57/40 176/80/40 92/81/40 +f 29/60/41 122/82/41 176/80/41 59/57/41 +f 32/83/42 92/81/42 176/80/42 122/82/42 +f 6/61/43 61/64/43 177/84/43 84/85/43 +f 31/67/44 119/86/44 177/84/44 61/64/44 +f 24/87/45 84/85/45 177/84/45 119/86/45 +f 7/88/46 63/89/46 178/90/46 68/91/46 +f 33/92/47 116/93/47 178/90/47 63/89/47 +f 38/94/48 68/91/48 178/90/48 116/93/48 +f 8/95/49 64/96/49 179/97/49 70/98/49 +f 34/99/50 113/100/50 179/97/50 64/96/50 +f 40/101/51 70/98/51 179/97/51 113/100/51 +f 9/102/52 65/103/52 180/104/52 71/105/52 +f 35/106/53 110/107/53 180/104/53 65/103/53 +f 41/108/54 71/105/54 180/104/54 110/107/54 +f 10/109/55 66/110/55 181/111/55 72/112/55 +f 36/113/56 107/114/56 181/111/56 66/110/56 +f 42/115/57 72/112/57 181/111/57 107/114/57 +f 11/116/58 67/117/58 182/118/58 99/119/58 +f 37/120/59 104/121/59 182/118/59 67/117/59 +f 39/122/60 99/119/60 182/118/60 104/121/60 +f 39/122/61 103/123/61 183/124/61 69/125/61 +f 42/126/62 102/127/62 183/124/62 103/123/62 +f 12/128/63 69/125/63 183/124/63 102/127/63 +f 39/122/64 104/121/64 184/129/64 103/123/64 +f 37/120/65 105/130/65 184/129/65 104/121/65 +f 42/126/66 103/123/66 184/129/66 105/130/66 +f 37/120/67 97/131/67 185/132/67 105/130/67 +f 10/109/68 72/133/68 185/132/68 97/131/68 +f 42/126/69 105/130/69 185/132/69 72/133/69 +f 42/115/70 106/134/70 186/135/70 102/136/70 +f 41/137/71 101/138/71 186/135/71 106/134/71 +f 12/139/72 102/136/72 186/135/72 101/138/72 +f 42/115/73 107/114/73 187/140/73 106/134/73 +f 36/113/74 108/141/74 187/140/74 107/114/74 +f 41/137/75 106/134/75 187/140/75 108/141/75 +f 36/113/76 96/142/76 188/143/76 108/141/76 +f 9/102/77 71/144/77 188/143/77 96/142/77 +f 41/137/78 108/141/78 188/143/78 71/144/78 +f 41/108/79 109/145/79 189/146/79 101/147/79 +f 40/148/80 100/149/80 189/146/80 109/145/80 +f 12/150/81 101/147/81 189/146/81 100/149/81 +f 41/108/82 110/107/82 190/151/82 109/145/82 +f 35/106/83 111/152/83 190/151/83 110/107/83 +f 40/148/84 109/145/84 190/151/84 111/152/84 +f 35/106/85 95/153/85 191/154/85 111/152/85 +f 8/155/86 70/156/86 191/154/86 95/153/86 +f 40/148/87 111/152/87 191/154/87 70/156/87 +f 40/101/88 112/157/88 192/158/88 100/159/88 +f 38/160/89 98/161/89 192/158/89 112/157/89 +f 12/162/90 100/159/90 192/158/90 98/161/90 +f 40/101/91 113/100/91 193/163/91 112/157/91 +f 34/99/92 114/164/92 193/163/92 113/100/92 +f 38/160/93 112/157/93 193/163/93 114/164/93 +f 34/99/94 94/165/94 194/166/94 114/164/94 +f 7/88/95 68/167/95 194/166/95 94/165/95 +f 38/160/96 114/164/96 194/166/96 68/167/96 +f 38/94/97 115/168/97 195/169/97 98/170/97 +f 39/171/98 69/172/98 195/169/98 115/168/98 +f 12/173/99 98/170/99 195/169/99 69/172/99 +f 38/94/100 116/93/100 196/174/100 115/168/100 +f 33/92/101 117/175/101 196/174/101 116/93/101 +f 39/171/102 115/168/102 196/174/102 117/175/102 +f 33/92/103 93/176/103 197/177/103 117/175/103 +f 11/116/104 99/178/104 197/177/104 93/176/104 +f 39/171/105 117/175/105 197/177/105 99/178/105 +f 24/87/106 118/179/106 198/180/106 54/181/106 +f 37/120/107 67/117/107 198/180/107 118/179/107 +f 11/116/108 54/181/108 198/180/108 67/117/108 +f 24/87/109 119/86/109 199/182/109 118/179/109 +f 31/67/110 120/183/110 199/182/110 119/86/110 +f 37/120/111 118/179/111 199/182/111 120/183/111 +f 31/67/112 91/184/112 200/185/112 120/183/112 +f 10/109/113 97/131/113 200/185/113 91/184/113 +f 37/120/114 120/183/114 200/185/114 97/131/114 +f 32/83/115 121/186/115 201/187/115 62/188/115 +f 36/113/116 66/110/116 201/187/116 121/186/116 +f 10/109/117 62/188/117 201/187/117 66/110/117 +f 32/83/118 122/82/118 202/189/118 121/186/118 +f 29/60/119 123/190/119 202/189/119 122/82/119 +f 36/113/120 121/186/120 202/189/120 123/190/120 +f 29/60/121 89/191/121 203/192/121 123/190/121 +f 9/102/122 96/142/122 203/192/122 89/191/122 +f 36/113/123 123/190/123 203/192/123 96/142/123 +f 30/79/124 124/193/124 204/194/124 60/195/124 +f 35/106/125 65/103/125 204/194/125 124/193/125 +f 9/102/126 60/195/126 204/194/126 65/103/126 +f 30/79/127 125/78/127 205/196/127 124/193/127 +f 27/53/128 126/197/128 205/196/128 125/78/128 +f 35/106/129 124/193/129 205/196/129 126/197/129 +f 27/53/130 87/198/130 206/199/130 126/197/130 +f 8/155/131 95/153/131 206/199/131 87/198/131 +f 35/106/132 126/197/132 206/199/132 95/153/132 +f 28/75/133 127/200/133 207/201/133 58/202/133 +f 34/99/134 64/96/134 207/201/134 127/200/134 +f 8/95/135 58/202/135 207/201/135 64/96/135 +f 28/75/136 128/74/136 208/203/136 127/200/136 +f 25/46/137 129/204/137 208/203/137 128/74/137 +f 34/99/138 127/200/138 208/203/138 129/204/138 +f 25/46/139 85/205/139 209/206/139 129/204/139 +f 7/88/140 94/165/140 209/206/140 85/205/140 +f 34/99/141 129/204/141 209/206/141 94/165/141 +f 26/71/142 130/207/142 210/208/142 56/209/142 +f 33/92/143 63/89/143 210/208/143 130/207/143 +f 7/88/144 56/209/144 210/208/144 63/89/144 +f 26/71/145 131/70/145 211/210/145 130/207/145 +f 23/39/146 132/211/146 211/210/146 131/70/146 +f 33/92/147 130/207/147 211/210/147 132/211/147 +f 23/39/148 83/212/148 212/213/148 132/211/148 +f 11/116/149 93/176/149 212/213/149 83/212/149 +f 33/92/150 132/211/150 212/213/150 93/176/150 +f 31/67/151 133/214/151 213/215/151 91/184/151 +f 32/83/152 62/188/152 213/215/152 133/214/152 +f 10/109/153 91/184/153 213/215/153 62/188/153 +f 31/67/154 134/66/154 214/216/154 133/214/154 +f 22/65/155 135/217/155 214/216/155 134/66/155 +f 32/83/156 133/214/156 214/216/156 135/217/156 +f 22/65/157 82/218/157 215/219/157 135/217/157 +f 5/54/158 92/81/158 215/219/158 82/218/158 +f 32/83/159 135/217/159 215/219/159 92/81/159 +f 29/60/160 136/220/160 216/221/160 89/191/160 +f 30/79/161 60/195/161 216/221/161 136/220/161 +f 9/102/162 89/191/162 216/221/162 60/195/162 +f 29/60/163 137/59/163 217/222/163 136/220/163 +f 21/58/164 138/223/164 217/222/164 137/59/164 +f 30/79/165 136/220/165 217/222/165 138/223/165 +f 21/58/166 81/224/166 218/225/166 138/223/166 +f 4/47/167 90/77/167 218/225/167 81/224/167 +f 30/79/168 138/223/168 218/225/168 90/77/168 +f 27/53/169 139/226/169 219/227/169 87/198/169 +f 28/228/170 58/229/170 219/227/170 139/226/170 +f 8/155/171 87/198/171 219/227/171 58/229/171 +f 27/53/172 140/52/172 220/230/172 139/226/172 +f 19/51/173 141/231/173 220/230/173 140/52/173 +f 28/228/174 139/226/174 220/230/174 141/231/174 +f 19/51/175 79/232/175 221/233/175 141/231/175 +f 3/234/176 88/235/176 221/233/176 79/232/176 +f 28/228/177 141/231/177 221/233/177 88/235/177 +f 25/46/178 142/236/178 222/237/178 85/205/178 +f 26/71/179 56/209/179 222/237/179 142/236/179 +f 7/88/180 85/205/180 222/237/180 56/209/180 +f 25/46/181 143/45/181 223/238/181 142/236/181 +f 15/44/182 144/239/182 223/238/182 143/45/182 +f 26/71/183 142/236/183 223/238/183 144/239/183 +f 15/44/184 75/240/184 224/241/184 144/239/184 +f 2/8/185 86/69/185 224/241/185 75/240/185 +f 26/71/186 144/239/186 224/241/186 86/69/186 +f 23/39/187 145/242/187 225/243/187 83/212/187 +f 24/87/188 54/181/188 225/243/188 145/242/188 +f 11/116/189 83/212/189 225/243/189 54/181/189 +f 23/39/190 146/38/190 226/244/190 145/242/190 +f 16/14/191 147/245/191 226/244/191 146/38/191 +f 24/87/192 145/242/192 226/244/192 147/245/192 +f 16/14/193 76/246/193 227/247/193 147/245/193 +f 6/61/194 84/85/194 227/247/194 76/246/194 +f 24/87/195 147/245/195 227/247/195 84/85/195 +f 17/35/196 148/248/196 228/249/196 47/250/196 +f 22/65/197 52/62/197 228/249/197 148/248/197 +f 6/61/198 47/250/198 228/249/198 52/62/198 +f 17/35/199 149/34/199 229/251/199 148/248/199 +f 20/33/200 150/252/200 229/251/200 149/34/200 +f 22/65/201 148/248/201 229/251/201 150/252/201 +f 20/33/202 80/253/202 230/254/202 150/252/202 +f 5/54/203 82/218/203 230/254/203 80/253/203 +f 22/65/204 150/252/204 230/254/204 82/218/204 +f 20/28/205 151/255/205 231/256/205 80/257/205 +f 21/58/206 51/55/206 231/256/206 151/255/206 +f 5/54/207 80/257/207 231/256/207 51/55/207 +f 20/28/208 152/27/208 232/258/208 151/255/208 +f 18/26/209 153/259/209 232/258/209 152/27/209 +f 21/58/210 151/255/210 232/258/210 153/259/210 +f 18/26/211 78/260/211 233/261/211 153/259/211 +f 4/47/212 81/224/212 233/261/212 78/260/212 +f 21/58/213 153/259/213 233/261/213 81/224/213 +f 18/21/214 154/262/214 234/263/214 78/264/214 +f 19/51/215 49/48/215 234/263/215 154/262/215 +f 4/47/216 78/264/216 234/263/216 49/48/216 +f 18/21/217 155/20/217 235/265/217 154/262/217 +f 13/19/218 156/266/218 235/265/218 155/20/218 +f 19/51/219 154/262/219 235/265/219 156/266/219 +f 13/19/220 73/267/220 236/268/220 156/266/220 +f 3/234/221 79/232/221 236/268/221 73/267/221 +f 19/51/222 156/266/222 236/268/222 79/232/222 +f 16/14/223 157/269/223 237/270/223 76/246/223 +f 17/271/224 47/272/224 237/270/224 157/269/224 +f 6/61/225 76/246/225 237/270/225 47/272/225 +f 16/14/226 158/13/226 238/273/226 157/269/226 +f 14/12/227 159/274/227 238/273/227 158/13/227 +f 17/271/228 157/269/228 238/273/228 159/274/228 +f 14/12/229 74/275/229 239/276/229 159/274/229 +f 1/277/230 77/278/230 239/276/230 74/275/230 +f 17/271/231 159/274/231 239/276/231 77/278/231 +f 13/7/232 160/279/232 240/280/232 73/281/232 +f 15/44/233 45/41/233 240/280/233 160/279/233 +f 3/40/234 73/281/234 240/280/234 45/41/234 +f 13/7/235 161/6/235 241/282/235 160/279/235 +f 14/5/236 162/283/236 241/282/236 161/6/236 +f 15/44/237 160/279/237 241/282/237 162/283/237 +f 14/5/238 44/284/238 242/285/238 162/283/238 +f 2/8/239 75/240/239 242/285/239 44/284/239 +f 15/44/240 162/283/240 242/285/240 75/240/240 diff --git a/src/chrono_fsi/sph/ChFsiFluidSystemSPH.cpp b/src/chrono_fsi/sph/ChFsiFluidSystemSPH.cpp index 3b7c673031..c2571074fc 100644 --- a/src/chrono_fsi/sph/ChFsiFluidSystemSPH.cpp +++ b/src/chrono_fsi/sph/ChFsiFluidSystemSPH.cpp @@ -369,8 +369,7 @@ void ChFsiFluidSystemSPH::CheckSPHParameters() { // Check if user-defined cMin and cMax are much larger than defaults if (m_paramsH->cMin.x < 2 * default_cMin.x || m_paramsH->cMin.y < 2 * default_cMin.y || m_paramsH->cMin.z < 2 * default_cMin.z || m_paramsH->cMax.x > 2 * default_cMax.x || m_paramsH->cMax.y > 2 * default_cMax.y || m_paramsH->cMax.z > 2 * default_cMax.z) { - cerr << "WARNING: User-defined cMin or cMax is much larger than the default values. " - << "This may slow down the simulation." << endl; + cerr << "WARNING: User-defined cMin or cMax is much larger than the default values. " << "This may slow down the simulation." << endl; } // TODO: Add check for whether computational domain is larger than SPH + BCE layers @@ -2871,6 +2870,18 @@ std::vector ChFsiFluidSystemSPH::GetPositions() const { return m_data_mgr->GetPositions(); } +ChFsiSphMarkerDeviceView ChFsiFluidSystemSPH::GetMarkerDeviceView() const { + ChFsiSphMarkerDeviceView view; + + SynchronizeCopyStream(); + + const auto& pos_rad = m_data_mgr->sphMarkers_D->posRadD; + view.pos_rad = pos_rad.empty() ? nullptr : thrust::raw_pointer_cast(pos_rad.data()); + view.num_fluid_markers = m_data_mgr->countersH->numFluidMarkers; + + return view; +} + std::vector ChFsiFluidSystemSPH::GetVelocities() const { SynchronizeCopyStream(); return m_data_mgr->GetVelocities(); diff --git a/src/chrono_fsi/sph/ChFsiFluidSystemSPH.h b/src/chrono_fsi/sph/ChFsiFluidSystemSPH.h index 526a598716..d3763db23a 100644 --- a/src/chrono_fsi/sph/ChFsiFluidSystemSPH.h +++ b/src/chrono_fsi/sph/ChFsiFluidSystemSPH.h @@ -34,6 +34,13 @@ class SphFluidDynamics; class SphBceManager; struct FsiDataManager; +/// Device-resident view of the current FSI-SPH marker positions. +/// The positions are stored as Real4 values, with XYZ as world position and W as marker radius. +struct CH_FSI_API ChFsiSphMarkerDeviceView { + const Real4* pos_rad = nullptr; ///< device pointer to marker position/radius data + size_t num_fluid_markers = 0; ///< number of fluid markers, starting at pos_rad[0] +}; + /// @addtogroup fsisph /// @{ @@ -388,6 +395,11 @@ class CH_FSI_API ChFsiFluidSystemSPH : public ChFsiFluidSystem { /// Extract positions of all markers (SPH and BCE). std::vector GetPositions() const; + /// Return a device-resident view of all marker positions. + /// This accessor does not copy marker data to the host. The returned device pointer remains owned by this SPH system + /// and is valid until marker storage is resized or the SPH system is destroyed. + ChFsiSphMarkerDeviceView GetMarkerDeviceView() const; + /// Extract velocities of all markers (SPH and BCE). std::vector GetVelocities() const; diff --git a/src/chrono_sensor/CMakeLists.txt b/src/chrono_sensor/CMakeLists.txt index 1d91d6d9a3..730b07bbcd 100644 --- a/src/chrono_sensor/CMakeLists.txt +++ b/src/chrono_sensor/CMakeLists.txt @@ -190,6 +190,15 @@ if(CH_USE_SENSOR_OPTIX) cuda/phys_cam_ops.cuh ) + if(CH_ENABLE_MODULE_FSI_SPH) + list(APPEND Chrono_sensor_CUDA_SOURCES + cuda/fsi_sph_render.cu + ) + list(APPEND Chrono_sensor_CUDA_HEADERS + cuda/fsi_sph_render.cuh + ) + endif() + source_group("cuda" FILES ${Chrono_sensor_CUDA_SOURCES} ${Chrono_sensor_CUDA_HEADERS}) else() @@ -212,6 +221,7 @@ set(Chrono_sensor_HEADERS ChApiSensor.h ChSensorManager.h ChDynamicsManager.h + ChFsiSphRender.h ) source_group("source" FILES ${Chrono_sensor_SOURCES} ${Chrono_sensor_HEADERS}) @@ -520,6 +530,10 @@ if(CH_USE_SENSOR_OPTIX) target_link_libraries(Chrono_sensor PRIVATE OpenVDB::nanovdb) endif() + if(CH_ENABLE_MODULE_FSI_SPH) + target_link_libraries(Chrono_sensor PUBLIC Chrono_fsisph) + endif() + endif() # print cxx compiler flags\ diff --git a/src/chrono_sensor/ChFsiSphRender.h b/src/chrono_sensor/ChFsiSphRender.h new file mode 100644 index 0000000000..a1d1ceb317 --- /dev/null +++ b/src/chrono_sensor/ChFsiSphRender.h @@ -0,0 +1,61 @@ +// ============================================================================= +// PROJECT CHRONO - http://projectchrono.org +// +// Copyright (c) 2026 projectchrono.org +// All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file at the top level of the distribution and at +// http://projectchrono.org/license-chrono.txt. +// +// ============================================================================= +// Author: Bocheng Zou +// ============================================================================= +// +// Native Chrono::FSI::SPH rendering options for Chrono::Sensor. +// +// ============================================================================= + +#ifndef CH_FSI_SPH_RENDER_H +#define CH_FSI_SPH_RENDER_H + +#include +#include + +#include "chrono/assets/ChVisualShape.h" +#include "chrono/core/ChVector3.h" +#include "chrono_sensor/ChApiSensor.h" +#include "chrono_sensor/ChConfigSensor.h" + +namespace chrono { + +namespace fsi { +namespace sph { +class ChFsiFluidSystemSPH; +} +} // namespace fsi + +namespace sensor { + +/// Options for rendering Chrono::FSI::SPH fluid markers in Chrono::Sensor. +struct CH_SENSOR_API ChFsiSphRenderOptions { + std::vector> sprite_shapes; ///< Required visual shape templates used for marker sprites. + ChVector3f sprite_position_jitter = ChVector3f(0.005f, 0.005f, 0.f); ///< Deterministic per-marker sprite jitter. + float render_particle_spacing = 0.f; ///< Absolute visual particle spacing. Must be positive to render particles. +}; + +#ifdef CHRONO_FSI_SPH + +/// One FSI-SPH render source attached to a Sensor scene. +struct CH_SENSOR_API ChFsiSphRenderSource { + int id = -1; + std::shared_ptr system; + ChFsiSphRenderOptions options; +}; + +#endif + +} // namespace sensor +} // namespace chrono + +#endif diff --git a/src/chrono_sensor/ChSensorManager.cpp b/src/chrono_sensor/ChSensorManager.cpp index 42b5705594..525dbfb18d 100644 --- a/src/chrono_sensor/ChSensorManager.cpp +++ b/src/chrono_sensor/ChSensorManager.cpp @@ -23,6 +23,9 @@ #ifdef CHRONO_HAS_OPTIX #include "chrono_sensor/sensors/ChOptixSensor.h" #endif +#ifdef CHRONO_FSI_SPH + #include "chrono_fsi/sph/ChFsiFluidSystemSPH.h" +#endif using std::cout; using std::cerr; @@ -31,8 +34,7 @@ using std::endl; namespace chrono { namespace sensor { -CH_SENSOR_API ChSensorManager::ChSensorManager(ChSystem* chrono_system) - : m_verbose(false), m_debug(false), m_optix_reflections(9) { +CH_SENSOR_API ChSensorManager::ChSensorManager(ChSystem* chrono_system) : m_verbose(false), m_debug(false), m_optix_reflections(9) { // Assign the Chrono system handle m_system = chrono_system; m_device_list = {0}; @@ -86,6 +88,31 @@ CH_SENSOR_API void ChSensorManager::ReconstructScenes() { #endif } +#ifdef CHRONO_FSI_SPH +CH_SENSOR_API int ChSensorManager::AttachFsiSphSystem(std::shared_ptr sys, const ChFsiSphRenderOptions& options) { + int handle = -1; + #ifdef CHRONO_HAS_OPTIX + handle = scene->AddFsiSphSystem(sys, options); + ReconstructScenes(); + #endif + return handle; +} + +CH_SENSOR_API void ChSensorManager::DetachFsiSphSystem(int handle) { + #ifdef CHRONO_HAS_OPTIX + scene->RemoveFsiSphSystem(handle); + #endif + ReconstructScenes(); +} + +CH_SENSOR_API void ChSensorManager::ClearFsiSphSystems() { + #ifdef CHRONO_HAS_OPTIX + scene->ClearFsiSphSystems(); + #endif + ReconstructScenes(); +} +#endif + CH_SENSOR_API void ChSensorManager::SetMaxEngines(int num_groups) { if (num_groups > 0 && num_groups < 1000) { m_allowable_groups = num_groups; @@ -117,8 +144,7 @@ CH_SENSOR_API void ChSensorManager::AddSensor(std::shared_ptr sensor) // add the sensor to an engine with sensor of similar update frequencies for (auto engine : m_engines) { - if (!found_group && engine->GetSensor().size() > 0 && - abs(engine->GetSensor()[0]->GetUpdateRate() - sensor->GetUpdateRate()) < 0.001) { + if (!found_group && engine->GetSensor().size() > 0 && abs(engine->GetSensor()[0]->GetUpdateRate() - sensor->GetUpdateRate()) < 0.001) { found_group = true; engine->AssignSensor(pOptixSensor); @@ -134,9 +160,12 @@ CH_SENSOR_API void ChSensorManager::AddSensor(std::shared_ptr sensor) // limits to 2 gpus, TODO: check if device supports CUDA if (m_verbose) cout << "Create new OptiX engine\n"; - - auto engine = chrono_types::make_shared( - m_system, m_device_list[(int)m_engines.size()], m_optix_reflections, m_verbose, m_debug); + + auto engine = chrono_types::make_shared(m_system, m_device_list[(int)m_engines.size()], m_optix_reflections, m_verbose, m_debug); + + #ifdef CHRONO_FSI_SPH + engine->SetFsiSphSources(&scene->GetFsiSphSources()); + #endif // engine->ConstructScene(); diff --git a/src/chrono_sensor/ChSensorManager.h b/src/chrono_sensor/ChSensorManager.h index dce8cd50b6..25b5c6334a 100644 --- a/src/chrono_sensor/ChSensorManager.h +++ b/src/chrono_sensor/ChSensorManager.h @@ -30,6 +30,10 @@ #include "chrono_sensor/optix/scene/ChScene.h" #endif +#ifdef CHRONO_FSI_SPH + #include "chrono_sensor/ChFsiSphRender.h" +#endif + #include #include @@ -83,6 +87,18 @@ class CH_SENSOR_API ChSensorManager { /// This translates all objects from the Chrono system into their appropriate OptiX objects. void ReconstructScenes(); +#ifdef CHRONO_FSI_SPH + /// Attach a Chrono::FSI::SPH system for native Sensor rendering. + /// Returns a handle that can be used to detach the source later. + int AttachFsiSphSystem(std::shared_ptr sys, const ChFsiSphRenderOptions& options = ChFsiSphRenderOptions()); + + /// Detach a previously attached Chrono::FSI::SPH render source. + void DetachFsiSphSystem(int handle); + + /// Remove all Chrono::FSI::SPH render sources from this manager. + void ClearFsiSphSystems(); +#endif + /// Get the maximum number of allowed OptiX Engines for the manager. /// @return An integer specifying the maximum number of engines the manager is allowed to create. int GetMaxEngines() { return m_allowable_groups; } diff --git a/src/chrono_sensor/cuda/fsi_sph_render.cu b/src/chrono_sensor/cuda/fsi_sph_render.cu new file mode 100644 index 0000000000..2ae4d98538 --- /dev/null +++ b/src/chrono_sensor/cuda/fsi_sph_render.cu @@ -0,0 +1,135 @@ +// ============================================================================= +// PROJECT CHRONO - http://projectchrono.org +// +// Copyright (c) 2026 projectchrono.org +// All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file at the top level of the distribution and at +// http://projectchrono.org/license-chrono.txt. +// +// ============================================================================= +// Author: Bocheng Zou +// ============================================================================= +// +// CUDA helpers for native Chrono::FSI::SPH rendering in Chrono::Sensor. +// +// ============================================================================= + +#include "chrono_sensor/cuda/fsi_sph_render.cuh" + +namespace chrono { +namespace sensor { + +namespace { + +__device__ unsigned int hash_u32(unsigned int x) { + x ^= x >> 16; + x *= 0x7feb352dU; + x ^= x >> 15; + x *= 0x846ca68bU; + x ^= x >> 16; + return x; +} + +__device__ float hash_unit(unsigned int seed) { + return static_cast(hash_u32(seed) & 0x00ffffffU) / static_cast(0x01000000U); +} + +__global__ void update_fsi_sph_sprite_instances(const chrono::fsi::sph::Real4* pos_rad, + size_t source_count, + size_t render_count, + OptixInstance* instances, + const OptixTraversableHandle* gas_handles, + const unsigned int* sbt_offsets, + const float3* template_scales, + unsigned int num_templates, + float render_particle_spacing, + float jitter_x, + float jitter_y, + float jitter_z, + float origin_x, + float origin_y, + float origin_z) { + const size_t stride = static_cast(blockDim.x) * static_cast(gridDim.x); + for (size_t idx = static_cast(blockIdx.x) * blockDim.x + threadIdx.x; idx < render_count; idx += stride) { + const unsigned int seed = static_cast(idx); + const unsigned int template_id = hash_u32(seed) % num_templates; + + size_t source_idx = idx; + if (render_count != source_count) { + const double scaled = (static_cast(idx) + 0.5) * static_cast(source_count) / static_cast(render_count); + source_idx = static_cast(scaled); + if (source_idx >= source_count) + source_idx = source_count - 1; + } + + const float sprite_offset_x = (2.f * hash_unit(seed ^ 0x63d83595U) - 1.f) * jitter_x; + const float sprite_offset_y = (2.f * hash_unit(seed ^ 0xb7e15162U) - 1.f) * jitter_y; + const float sprite_offset_z = (2.f * hash_unit(seed ^ 0x8aed2a6bU) - 1.f) * jitter_z; + + float resample_offset_x = 0.f; + float resample_offset_y = 0.f; + float resample_offset_z = 0.f; + if (render_particle_spacing > 0.f && render_count > source_count) { + const float radius = 0.5f * render_particle_spacing; + resample_offset_x = (2.f * hash_unit(seed ^ 0x91e10da5U) - 1.f) * radius; + resample_offset_y = (2.f * hash_unit(seed ^ 0xd1b54a35U) - 1.f) * radius; + resample_offset_z = (2.f * hash_unit(seed ^ 0x94d049bbU) - 1.f) * radius; + } + + const auto p = pos_rad[source_idx]; + const float x = static_cast(p.x) + sprite_offset_x + resample_offset_x - origin_x; + const float y = static_cast(p.y) + sprite_offset_y + resample_offset_y - origin_y; + const float z = static_cast(p.z) + sprite_offset_z + resample_offset_z - origin_z; + const float3 template_scale = template_scales[template_id]; + + OptixInstance instance = {}; + instance.traversableHandle = gas_handles[template_id]; + instance.flags = OPTIX_INSTANCE_FLAG_DISABLE_ANYHIT; + instance.instanceId = static_cast(idx); + instance.sbtOffset = sbt_offsets[template_id]; + instance.visibilityMask = 1; + + instance.transform[0] = template_scale.x; + instance.transform[1] = 0.f; + instance.transform[2] = 0.f; + instance.transform[3] = x; + instance.transform[4] = 0.f; + instance.transform[5] = template_scale.y; + instance.transform[6] = 0.f; + instance.transform[7] = y; + instance.transform[8] = 0.f; + instance.transform[9] = 0.f; + instance.transform[10] = template_scale.z; + instance.transform[11] = z; + + instances[idx] = instance; + } +} + +} // namespace + +void cuda_update_fsi_sph_sprite_instances(const chrono::fsi::sph::Real4* pos_rad, + size_t source_count, + size_t render_count, + OptixInstance* instances, + const OptixTraversableHandle* gas_handles, + const unsigned int* sbt_offsets, + const float3* template_scales, + unsigned int num_templates, + float render_particle_spacing, + const ChVector3f& position_jitter, + const ChVector3f& origin_offset) { + if (!pos_rad || !instances || !gas_handles || !sbt_offsets || !template_scales || source_count == 0 || render_count == 0 || num_templates == 0) + return; + + constexpr int block_size = 256; + size_t grid_size = (render_count + block_size - 1) / block_size; + update_fsi_sph_sprite_instances<<(grid_size), block_size>>>(pos_rad, source_count, render_count, instances, gas_handles, sbt_offsets, template_scales, + num_templates, render_particle_spacing, position_jitter.x(), position_jitter.y(), + position_jitter.z(), origin_offset.x(), origin_offset.y(), origin_offset.z()); +} + +} // namespace sensor +} // namespace chrono diff --git a/src/chrono_sensor/cuda/fsi_sph_render.cuh b/src/chrono_sensor/cuda/fsi_sph_render.cuh new file mode 100644 index 0000000000..cb1eb57a62 --- /dev/null +++ b/src/chrono_sensor/cuda/fsi_sph_render.cuh @@ -0,0 +1,48 @@ +// ============================================================================= +// PROJECT CHRONO - http://projectchrono.org +// +// Copyright (c) 2026 projectchrono.org +// All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file at the top level of the distribution and at +// http://projectchrono.org/license-chrono.txt. +// +// ============================================================================= +// Author: Bocheng Zou +// ============================================================================= +// +// CUDA helpers for native Chrono::FSI::SPH rendering in Chrono::Sensor. +// +// ============================================================================= + +#ifndef CH_SENSOR_FSI_SPH_RENDER_CUH +#define CH_SENSOR_FSI_SPH_RENDER_CUH + +#include + +#include +#include + +#include "chrono/core/ChVector3.h" +#include "chrono_fsi/sph/ChFsiDataTypesSPH.h" + +namespace chrono { +namespace sensor { + +void cuda_update_fsi_sph_sprite_instances(const chrono::fsi::sph::Real4* pos_rad, + size_t source_count, + size_t render_count, + OptixInstance* instances, + const OptixTraversableHandle* gas_handles, + const unsigned int* sbt_offsets, + const float3* template_scales, + unsigned int num_templates, + float render_particle_spacing, + const ChVector3f& position_jitter, + const ChVector3f& origin_offset); + +} // namespace sensor +} // namespace chrono + +#endif diff --git a/src/chrono_sensor/optix/ChOptixEngine.cpp b/src/chrono_sensor/optix/ChOptixEngine.cpp index 8af8bd41da..a75c930c88 100644 --- a/src/chrono_sensor/optix/ChOptixEngine.cpp +++ b/src/chrono_sensor/optix/ChOptixEngine.cpp @@ -46,17 +46,52 @@ #include "chrono/assets/ChTexture.h" #include "chrono/physics/ChSystem.h" #include "chrono_sensor/optix/ChNVDBVolume.h" +#include +#include +#include #include #include "chrono_sensor/cuda/cuda_utils.cuh" +#ifdef CHRONO_FSI_SPH + #include "chrono_fsi/sph/ChFsiFluidSystemSPH.h" +#endif + #ifdef USE_SENSOR_NVDB -#include + #include #endif namespace chrono { namespace sensor { +#ifdef CHRONO_FSI_SPH +namespace { + +size_t EstimateFsiSphRenderCount(size_t num_fluid_markers, double source_spacing, float render_particle_spacing) { + if (num_fluid_markers == 0) + return 0; + + if (render_particle_spacing <= 0.f) + return 0; + + const double source = std::max(source_spacing, 1e-12); + const double target = std::max(static_cast(render_particle_spacing), 1e-12); + const double ratio = source / target; + const double estimate = static_cast(num_fluid_markers) * ratio * ratio * ratio; + + if (!std::isfinite(estimate) || estimate <= 1.0) + return 1; + + const double max_size = static_cast(std::numeric_limits::max()); + if (estimate >= max_size) + return std::numeric_limits::max(); + + return std::max(1, static_cast(estimate + 0.5)); +} + +} // namespace +#endif + ChOptixEngine::ChOptixEngine(ChSystem* sys, int device_id, int max_scene_reflections, bool verbose, bool debug) : m_verbose(verbose), m_debug(debug), m_deviceId(device_id), m_recursions(max_scene_reflections), m_sceneThread() { m_sceneThread.start = false; @@ -106,14 +141,14 @@ void ChOptixEngine::Initialize() { m_params.scene_epsilon = 1.e-3f; // TODO: determine a good value for this m_params.importance_cutoff = .01f; /// TODO: determine a good value for this - #ifdef USE_SENSOR_NVDB - m_params.handle_ptr = nullptr; - m_params.normal_handle_ptr = nullptr; - #else - m_params.handle_ptr = 0; - m_params.normal_handle_ptr = 0; - #endif // USE_SENSOR_NVDB - +#ifdef USE_SENSOR_NVDB + m_params.handle_ptr = nullptr; + m_params.normal_handle_ptr = nullptr; +#else + m_params.handle_ptr = 0; + m_params.normal_handle_ptr = 0; +#endif // USE_SENSOR_NVDB + CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&md_params), sizeof(ContextParameters))); m_params.root = {}; @@ -159,14 +194,13 @@ void ChOptixEngine::AssignSensor(std::shared_ptr sensor) { opx_filter->m_denoiser = chrono_types::make_shared(m_context); // opx_filter->m_denoiser = nullptr; } - - } - else if (auto phys_cam = std::dynamic_pointer_cast(sensor)) { + + } else if (auto phys_cam = std::dynamic_pointer_cast(sensor)) { if (phys_cam->GetUseDenoiser()) { std::cout << "Sensor: " << phys_cam->GetName() << " requested OptiX denoiser\n"; opx_filter->m_denoiser = chrono_types::make_shared(m_context); - //opx_filter->m_denoiser = nullptr; - } + // opx_filter->m_denoiser = nullptr; + } } //// ---- Register Your Customized Sensor Here (if amazing optixDenoiser needed to add) ---- //// @@ -184,8 +218,7 @@ void ChOptixEngine::AssignSensor(std::shared_ptr sensor) { m_renderThreads[id].done = true; m_renderThreads[id].start = false; m_renderThreads[id].terminate = false; - m_renderThreads[id].thread = - std::move(std::thread(&ChOptixEngine::RenderProcess, this, std::ref(m_renderThreads[id]), sensor)); + m_renderThreads[id].thread = std::move(std::thread(&ChOptixEngine::RenderProcess, this, std::ref(m_renderThreads[id]), sensor)); } if (!m_started) { Start(); @@ -202,11 +235,9 @@ void ChOptixEngine::UpdateSensors(std::shared_ptr scene) { // check if any of the sensors would be collecting data right now, if so, pack a tmp start keyframe for (int i = 0; i < m_assignedSensor.size(); i++) { auto sensor = m_assignedSensor[i]; - if (m_system->GetChTime() > sensor->GetNumLaunches() / sensor->GetUpdateRate() - 1e-7 && - !m_cameraStartFrames_set[i]) { + if (m_system->GetChTime() > sensor->GetNumLaunches() / sensor->GetUpdateRate() - 1e-7 && !m_cameraStartFrames_set[i]) { // do this once per sensor because we don't know if they will be updated at the same time - m_geometry->UpdateBodyTransformsStart((float)m_system->GetChTime(), - (float)m_system->GetChTime() + sensor->GetCollectionWindow()); + m_geometry->UpdateBodyTransformsStart((float)m_system->GetChTime(), (float)m_system->GetChTime() + sensor->GetCollectionWindow()); m_cameraStartFrames[i] = sensor->GetParent()->GetVisualModelFrame(); m_cameraStartFrames_set[i] = true; } @@ -215,8 +246,7 @@ void ChOptixEngine::UpdateSensors(std::shared_ptr scene) { // check which sensors need to be updated this step for (int i = 0; i < m_assignedSensor.size(); i++) { auto sensor = m_assignedSensor[i]; - if (m_system->GetChTime() > - sensor->GetNumLaunches() / sensor->GetUpdateRate() + sensor->GetCollectionWindow() - 1e-7) { + if (m_system->GetChTime() > sensor->GetNumLaunches() / sensor->GetUpdateRate() + sensor->GetCollectionWindow() - 1e-7) { to_be_updated.push_back(i); } } @@ -247,8 +277,7 @@ void ChOptixEngine::UpdateSensors(std::shared_ptr scene) { m_renderQueue.push_back(i); m_assignedSensor[i]->IncrementNumLaunches(); m_assignedRenderers[i]->m_time_stamp = t; - m_renderThreads[i].done = - false; // this render thread must not be done now given we have prepped some data for it + m_renderThreads[i].done = false; // this render thread must not be done now given we have prepped some data for it } } // we only notify the worker thread when there is a sensor to launch and filters to process @@ -262,8 +291,7 @@ void ChOptixEngine::UpdateSensors(std::shared_ptr scene) { for (int i = 0; i < m_assignedSensor.size(); i++) { auto sensor = m_assignedSensor[i]; - if (m_system->GetChTime() > (sensor->GetNumLaunches() - 1) / sensor->GetUpdateRate() + - sensor->GetCollectionWindow() + sensor->GetLag() - 1e-7) { + if (m_system->GetChTime() > (sensor->GetNumLaunches() - 1) / sensor->GetUpdateRate() + sensor->GetCollectionWindow() + sensor->GetLag() - 1e-7) { // wait for the sensor thread i which will notify everyone when done // if (!m_mainLock.owns_lock()) @@ -412,8 +440,7 @@ void ChOptixEngine::SceneProcess(RenderThread& tself) { std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); m_geometry->RebuildRootStructure(); std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now(); - std::chrono::duration wall_time = - std::chrono::duration_cast>(t2 - t1); + std::chrono::duration wall_time = std::chrono::duration_cast>(t2 - t1); // launch the render threads for (auto i : m_renderQueue) { m_renderThreads[i].done = false; @@ -441,9 +468,7 @@ void ChOptixEngine::SceneProcess(RenderThread& tself) { } } -void ChOptixEngine::boxVisualization(std::shared_ptr body, - std::shared_ptr box_shape, - ChFrame<> asset_frame) { +void ChOptixEngine::boxVisualization(std::shared_ptr body, std::shared_ptr box_shape, ChFrame<> asset_frame) { ChVector3d size = box_shape->GetLengths(); unsigned int mat_id; @@ -456,9 +481,7 @@ void ChOptixEngine::boxVisualization(std::shared_ptr body, m_pipeline->AddBody(body); } -void ChOptixEngine::sphereVisualization(std::shared_ptr body, - std::shared_ptr sphere_shape, - ChFrame<> asset_frame) { +void ChOptixEngine::sphereVisualization(std::shared_ptr body, std::shared_ptr sphere_shape, ChFrame<> asset_frame) { ChVector3d size(sphere_shape->GetRadius()); unsigned int mat_id; @@ -471,9 +494,7 @@ void ChOptixEngine::sphereVisualization(std::shared_ptr body, m_pipeline->AddBody(body); } -void ChOptixEngine::cylinderVisualization(std::shared_ptr body, - std::shared_ptr cyl_shape, - ChFrame<> asset_frame) { +void ChOptixEngine::cylinderVisualization(std::shared_ptr body, std::shared_ptr cyl_shape, ChFrame<> asset_frame) { double radius = cyl_shape->GetRadius(); double height = cyl_shape->GetHeight(); @@ -489,9 +510,7 @@ void ChOptixEngine::cylinderVisualization(std::shared_ptr body, m_pipeline->AddBody(body); } -void ChOptixEngine::rigidMeshVisualization(std::shared_ptr body, - std::shared_ptr mesh_shape, - ChFrame<> asset_frame) { +void ChOptixEngine::rigidMeshVisualization(std::shared_ptr body, std::shared_ptr mesh_shape, ChFrame<> asset_frame) { if (mesh_shape->IsWireframe()) { std::cerr << "WARNING: Chrono::Sensor does not support wireframe meshes. Defaulting back to solid mesh, please " "check for visual issues.\n"; @@ -507,9 +526,7 @@ void ChOptixEngine::rigidMeshVisualization(std::shared_ptr body, m_pipeline->AddBody(body); } -void ChOptixEngine::deformableMeshVisualization(std::shared_ptr body, - std::shared_ptr mesh_shape, - ChFrame<> asset_frame) { +void ChOptixEngine::deformableMeshVisualization(std::shared_ptr body, std::shared_ptr mesh_shape, ChFrame<> asset_frame) { if (mesh_shape->IsWireframe()) { std::cerr << "WARNING: Chrono::Sensor does not support wireframe meshes. Defaulting back to solid mesh, please " "check for visual issues.\n"; @@ -519,16 +536,79 @@ void ChOptixEngine::deformableMeshVisualization(std::shared_ptr body, unsigned int mat_id; CUdeviceptr d_vertex_buffer; // handle will go to m_geometry CUdeviceptr d_index_buffer; // handle will go to m_geometry - mat_id = - m_pipeline->GetDeformableMeshMaterial(d_vertex_buffer, d_index_buffer, mesh_shape, mesh_shape->GetMaterials()); + mat_id = m_pipeline->GetDeformableMeshMaterial(d_vertex_buffer, d_index_buffer, mesh_shape, mesh_shape->GetMaterials()); m_geometry->AddDeformableMesh(d_vertex_buffer, d_index_buffer, mesh_shape, body, asset_frame, size, mat_id); m_pipeline->AddBody(body); } +#ifdef CHRONO_FSI_SPH +void ChOptixEngine::AddFsiSphVisualization() { + if (!m_fsi_sph_sources) + return; + + for (const auto& source : *m_fsi_sph_sources) { + if (!source.system) + continue; + + const auto view = source.system->GetMarkerDeviceView(); + if (view.num_fluid_markers == 0) + continue; + + if (source.options.sprite_shapes.empty()) + continue; + + const auto& sprite_shapes = source.options.sprite_shapes; + + std::vector d_vertices; + std::vector d_indices; + std::vector> shapes; + std::vector mat_ids; + d_vertices.reserve(sprite_shapes.size()); + d_indices.reserve(sprite_shapes.size()); + shapes.reserve(sprite_shapes.size()); + mat_ids.reserve(sprite_shapes.size()); + + for (const auto& shape : sprite_shapes) { + if (!shape) + continue; + + std::vector> materials = shape->GetMaterials(); + if (auto mesh = std::dynamic_pointer_cast(shape)) { + CUdeviceptr d_vertex_buffer = {}; + CUdeviceptr d_index_buffer = {}; + const unsigned int mat_id = m_pipeline->GetRigidMeshMaterial(d_vertex_buffer, d_index_buffer, mesh, materials); + d_vertices.push_back(d_vertex_buffer); + d_indices.push_back(d_index_buffer); + shapes.push_back(mesh); + mat_ids.push_back(mat_id); + } + } + + const size_t render_count = EstimateFsiSphRenderCount(view.num_fluid_markers, source.system->GetInitialSpacing(), source.options.render_particle_spacing); + m_geometry->AddFsiSphCloud(source.id, render_count, view.num_fluid_markers, d_vertices, d_indices, shapes, mat_ids, source.options.render_particle_spacing, + source.options.sprite_position_jitter); + } +} + +void ChOptixEngine::UpdateFsiSphVisualization() { + if (!m_fsi_sph_sources) + return; + + for (const auto& source : *m_fsi_sph_sources) { + if (!source.system) + continue; + + const auto view = source.system->GetMarkerDeviceView(); + if (!view.pos_rad || view.num_fluid_markers == 0) + continue; + + m_geometry->UpdateFsiSphCloud(source.id, view.pos_rad, 0, view.num_fluid_markers); + } +} +#endif + #ifdef USE_SENSOR_NVDB -void ChOptixEngine::nvdbVisualization(std::shared_ptr body, - std::shared_ptr box_shape, - ChFrame<> asset_frame) { +void ChOptixEngine::nvdbVisualization(std::shared_ptr body, std::shared_ptr box_shape, ChFrame<> asset_frame) { ChVector3d size = box_shape->GetBoxGeometry().GetLengths(); unsigned int mat_id; @@ -575,13 +655,13 @@ void ChOptixEngine::ConstructScene() { // std::cout << "Ignoring an asset that is set to invisible\n"; } else if (auto box_shape = std::dynamic_pointer_cast(shape)) { boxVisualization(body, box_shape, shape_frame); - } - #ifdef USE_SENSOR_NVDB + } +#ifdef USE_SENSOR_NVDB else if (std::shared_ptr nvdb_shape = std::dynamic_pointer_cast(shape)) { nvdbVisualization(body, nvdb_shape, shape_frame); printf("Added NVDB Shape!"); } - #endif +#endif else if (auto sphere_shape = std::dynamic_pointer_cast(shape)) { sphereVisualization(body, sphere_shape, shape_frame); } else if (auto cylinder_shape = std::dynamic_pointer_cast(shape)) { @@ -650,6 +730,10 @@ void ChOptixEngine::ConstructScene() { } } +#ifdef CHRONO_FSI_SPH + AddFsiSphVisualization(); +#endif + m_params.root = m_geometry->CreateRootStructure(); m_pipeline->UpdateAllSBTs(); m_pipeline->UpdateAllPipelines(); @@ -668,7 +752,7 @@ void ChOptixEngine::UpdateSensorParameters(std::vector& to_be_updated, std: if (auto p_phys_cam = std::dynamic_pointer_cast(p_sensor)) { // update filter parameters p_phys_cam->UpdateFilterParameters(); - + // update raygen_record parameters m_assignedRenderers[id]->m_raygen_record->data.specific.phys_camera.hFOV = p_phys_cam->GetHFOV(); } @@ -698,8 +782,7 @@ void ChOptixEngine::UpdateSensorTransforms(std::vector& to_be_updated, std: ChVector3f origin(0, 0, 0); auto r = radar->GetOffsetPose().GetPos() - origin; auto ang_vel = radar->GetAngularVelocity() % r; - auto vel_abs = - radar->GetOffsetPose().TransformDirectionLocalToParent(ang_vel) + radar->GetTranslationalVelocity(); + auto vel_abs = radar->GetOffsetPose().TransformDirectionLocalToParent(ang_vel) + radar->GetTranslationalVelocity(); m_assignedRenderers[id]->m_raygen_record->data.specific.radar.velocity.x = vel_abs.x(); m_assignedRenderers[id]->m_raygen_record->data.specific.radar.velocity.y = vel_abs.y(); m_assignedRenderers[id]->m_raygen_record->data.specific.radar.velocity.z = vel_abs.z(); @@ -720,12 +803,10 @@ void ChOptixEngine::UpdateSensorTransforms(std::vector& to_be_updated, std: m_assignedRenderers[id]->m_raygen_record->data.t1 = (float)(m_system->GetChTime()); m_assignedRenderers[id]->m_raygen_record->data.pos0 = make_float3(pos_0.x(), pos_0.y(), pos_0.z()); m_assignedRenderers[id]->m_raygen_record->data.rot0 = - make_float4((float)global_loc_0.GetRot().e0(), (float)global_loc_0.GetRot().e1(), - (float)global_loc_0.GetRot().e2(), (float)global_loc_0.GetRot().e3()); + make_float4((float)global_loc_0.GetRot().e0(), (float)global_loc_0.GetRot().e1(), (float)global_loc_0.GetRot().e2(), (float)global_loc_0.GetRot().e3()); m_assignedRenderers[id]->m_raygen_record->data.pos1 = make_float3(pos_1.x(), pos_1.y(), pos_1.z()); m_assignedRenderers[id]->m_raygen_record->data.rot1 = - make_float4((float)global_loc_1.GetRot().e0(), (float)global_loc_1.GetRot().e1(), - (float)global_loc_1.GetRot().e2(), (float)global_loc_1.GetRot().e3()); + make_float4((float)global_loc_1.GetRot().e0(), (float)global_loc_1.GetRot().e1(), (float)global_loc_1.GetRot().e2(), (float)global_loc_1.GetRot().e3()); m_assignedRenderers[id]->m_time_stamp = (float)m_system->GetChTime(); } } @@ -752,7 +833,6 @@ void ChOptixEngine::UpdateSceneDescription(std::shared_ptr scene) { std::vector lights = scene->GetLights(); if (scene->GetLightsChanged() || scene->GetOriginChanged()) { - // Handling changes to all lights if (lights.size() != m_params.num_lights) { // need new memory in this case if (m_params.lights) { @@ -767,23 +847,16 @@ void ChOptixEngine::UpdateSceneDescription(std::shared_ptr scene) { lights[i].specific.environment.env_map = m_pipeline->GetBackgroundTexSampler(); } - lights[i].pos = make_float3( - lights[i].pos.x - scene->GetOriginOffset().x(), - lights[i].pos.y - scene->GetOriginOffset().y(), - lights[i].pos.z - scene->GetOriginOffset().z() - ); + lights[i].pos = + make_float3(lights[i].pos.x - scene->GetOriginOffset().x(), lights[i].pos.y - scene->GetOriginOffset().y(), lights[i].pos.z - scene->GetOriginOffset().z()); } - cudaMemcpy( - reinterpret_cast(m_params.lights), lights.data(), lights.size() * sizeof(ChOptixLight), - cudaMemcpyHostToDevice - ); + cudaMemcpy(reinterpret_cast(m_params.lights), lights.data(), lights.size() * sizeof(ChOptixLight), cudaMemcpyHostToDevice); m_params.num_lights = static_cast(lights.size()); - + // Handling changes in origin - m_params.ambient_light_color = {scene->GetAmbientLight().x(), scene->GetAmbientLight().y(), - scene->GetAmbientLight().z()}; + m_params.ambient_light_color = {scene->GetAmbientLight().x(), scene->GetAmbientLight().y(), scene->GetAmbientLight().z()}; cudaMemcpy(reinterpret_cast(md_params), &m_params, sizeof(ContextParameters), cudaMemcpyHostToDevice); @@ -792,55 +865,59 @@ void ChOptixEngine::UpdateSceneDescription(std::shared_ptr scene) { scene->ResetOriginChanged(); } - #ifdef USE_SENSOR_NVDB - if (float* d_pts = scene->GetFSIParticles()) { - int n = scene->GetNumFSIParticles(); - - printf("Creating NanoVDB Handle...\n"); - using buildType = nanovdb::Point; - nanovdb::GridHandle handle = createNanoVDBGridHandle(d_pts, n); - nanovdb::NanoGrid* grid = handle.deviceGrid(); - handle.deviceDownload(); - auto* grid_h = handle.grid(); - auto* tree = grid_h->treePtr(); - - // printf("Grid Size: %d\n", grid_h->gridSize()); - ////printf("Point Count: %d", (int)grid_h->pointCount()); - // printf("Upper Internal Nodes: %d\n", grid_h->tree().nodeCount(2)); - // printf("Lower Internal Nodes: %d\n", grid_h->tree().nodeCount(1)); - // printf("Leaf Nodes: %d\n", grid_h->tree().nodeCount(0)); - - // float wBBoxDimZ = (float)grid_h->worldBBox().dim()[2] * 2; - // nanovdb::Vec3 wBBoxCenter = nanovdb::Vec3(grid_h->worldBBox().min() + grid_h->worldBBox().dim() - // * 0.5f); nanovdb::CoordBBox treeIndexBbox = grid_h->tree().bbox(); std::cout << "Bounds: " - // << "[" << treeIndexBbox.min()[0] << "," << treeIndexBbox.min()[1] << "," << treeIndexBbox.min()[2] - // << "] -> [" << treeIndexBbox.max()[0] << "," << treeIndexBbox.max()[1] << "," << - // treeIndexBbox.max()[2] - // << "]" << std::endl; - - /* printf("size of handle_ptr: %d | size of grid*: %d\n", sizeof(m_params.handle_ptr), sizeof(grid)); - printf("Grid ptr: %p | Grid Size: %d | Grid Type: %d | Grid Empty: %d\n ", grid, handle.gridSize(), - handle.gridType(), handle.empty()); printf("size of ContextParameters: %d\n", sizeof(ContextParameters));*/ - - cudaMalloc((void**)&m_params.handle_ptr, handle.gridSize()); - cudaMemcpy((void*)m_params.handle_ptr, grid, handle.gridSize(), cudaMemcpyDeviceToDevice); - /* cudaError_t status = cudaMalloc((void**)&md_params->handle_ptr, handle.gridSize()); - if (status != cudaSuccess) { - printf("cudaMalloc failed: %s\n",cudaGetErrorString(status)); - } - printf("md grid ptr: %p\n", md_params->handle_ptr); - - cudaMemcpy(md_params->handle_ptr, grid, handle.gridSize(), cudaMemcpyDeviceToDevice);*/ - /*printf("Done!\n"); - size_t sz = handle.gridSize(); - cudaMalloc(reinterpret_cast(&m_params.handle_ptr), sz);he - printf("handle: %p\n", &handle); - cudaMemcpy(reinterpret_cast(m_params.handle_ptr), &handle, sz, cudaMemcpyHostToDevice);*/ +#ifdef CHRONO_FSI_SPH + UpdateFsiSphVisualization(); +#endif - cudaMemcpy(reinterpret_cast(md_params), &m_params, sizeof(ContextParameters), cudaMemcpyHostToDevice); +#ifdef USE_SENSOR_NVDB + if (float* d_pts = scene->GetFSIParticles()) { + int n = scene->GetNumFSIParticles(); + + printf("Creating NanoVDB Handle...\n"); + using buildType = nanovdb::Point; + nanovdb::GridHandle handle = createNanoVDBGridHandle(d_pts, n); + nanovdb::NanoGrid* grid = handle.deviceGrid(); + handle.deviceDownload(); + auto* grid_h = handle.grid(); + auto* tree = grid_h->treePtr(); + + // printf("Grid Size: %d\n", grid_h->gridSize()); + ////printf("Point Count: %d", (int)grid_h->pointCount()); + // printf("Upper Internal Nodes: %d\n", grid_h->tree().nodeCount(2)); + // printf("Lower Internal Nodes: %d\n", grid_h->tree().nodeCount(1)); + // printf("Leaf Nodes: %d\n", grid_h->tree().nodeCount(0)); + + // float wBBoxDimZ = (float)grid_h->worldBBox().dim()[2] * 2; + // nanovdb::Vec3 wBBoxCenter = nanovdb::Vec3(grid_h->worldBBox().min() + grid_h->worldBBox().dim() + // * 0.5f); nanovdb::CoordBBox treeIndexBbox = grid_h->tree().bbox(); std::cout << "Bounds: " + // << "[" << treeIndexBbox.min()[0] << "," << treeIndexBbox.min()[1] << "," << treeIndexBbox.min()[2] + // << "] -> [" << treeIndexBbox.max()[0] << "," << treeIndexBbox.max()[1] << "," << + // treeIndexBbox.max()[2] + // << "]" << std::endl; + + /* printf("size of handle_ptr: %d | size of grid*: %d\n", sizeof(m_params.handle_ptr), sizeof(grid)); + printf("Grid ptr: %p | Grid Size: %d | Grid Type: %d | Grid Empty: %d\n ", grid, handle.gridSize(), + handle.gridType(), handle.empty()); printf("size of ContextParameters: %d\n", sizeof(ContextParameters));*/ + + cudaMalloc((void**)&m_params.handle_ptr, handle.gridSize()); + cudaMemcpy((void*)m_params.handle_ptr, grid, handle.gridSize(), cudaMemcpyDeviceToDevice); + /* cudaError_t status = cudaMalloc((void**)&md_params->handle_ptr, handle.gridSize()); + if (status != cudaSuccess) { + printf("cudaMalloc failed: %s\n",cudaGetErrorString(status)); } - #endif // USE_SENSOR_NVDB + printf("md grid ptr: %p\n", md_params->handle_ptr); + + cudaMemcpy(md_params->handle_ptr, grid, handle.gridSize(), cudaMemcpyDeviceToDevice);*/ + /*printf("Done!\n"); + size_t sz = handle.gridSize(); + cudaMalloc(reinterpret_cast(&m_params.handle_ptr), sz);he + printf("handle: %p\n", &handle); + cudaMemcpy(reinterpret_cast(m_params.handle_ptr), &handle, sz, cudaMemcpyHostToDevice);*/ + + cudaMemcpy(reinterpret_cast(md_params), &m_params, sizeof(ContextParameters), cudaMemcpyHostToDevice); } +#endif // USE_SENSOR_NVDB +} } // namespace sensor } // namespace chrono diff --git a/src/chrono_sensor/optix/ChOptixEngine.h b/src/chrono_sensor/optix/ChOptixEngine.h index 54a307603a..f625b0a2d9 100644 --- a/src/chrono_sensor/optix/ChOptixEngine.h +++ b/src/chrono_sensor/optix/ChOptixEngine.h @@ -89,6 +89,11 @@ class CH_SENSOR_API ChOptixEngine { /// Tells the optix manager to construct the scene from scratch, translating all objects from Chrono to OptiX void ConstructScene(); +#ifdef CHRONO_FSI_SPH + /// Set the native FSI-SPH render sources to include when constructing and updating the OptiX scene. + void SetFsiSphSources(const std::vector* sources) { m_fsi_sph_sources = sources; } +#endif + /// Way to query the device ID on which the engine is running. CANNOT BE MODIFIED since the engine will have been /// already constructed /// @return the GPU ID @@ -124,45 +129,43 @@ class CH_SENSOR_API ChOptixEngine { /// Update all sensor positions and orientations. /// @param to_be_updated the vector of Optix sensor IDs to be updated /// @param scene the scene that these Optix sensors belong to - void UpdateSensorTransforms(std::vector& to_be_updated, std::shared_ptr scene); - - /// Update all raygen_record and filter parameters of the Optix sensors + void UpdateSensorTransforms(std::vector& to_be_updated, std::shared_ptr scene); + + /// Update all raygen_record and filter parameters of the Optix sensors /// @param to_be_updated the vector of Optix sensor IDs to be updated /// @param scene the scene that these Optix sensors belong to void UpdateSensorParameters(std::vector& to_be_updated, std::shared_ptr scene); - void UpdateDeformableMeshes(); ///< updates the dynamic meshes in the scene + void UpdateDeformableMeshes(); ///< updates the dynamic meshes in the scene /// Update the scene characteristics such as lights, background, etc. void UpdateSceneDescription(std::shared_ptr scene); +#ifdef CHRONO_FSI_SPH + /// Add native FSI-SPH render sources to the scene. + void AddFsiSphVisualization(); + + /// Update native FSI-SPH render source instance transforms. + void UpdateFsiSphVisualization(); +#endif + /// Creates an optix box visualization object from a Chrono box shape. - void boxVisualization(std::shared_ptr body, - std::shared_ptr box_shape, - ChFrame<> asset_frame); + void boxVisualization(std::shared_ptr body, std::shared_ptr box_shape, ChFrame<> asset_frame); /// Creates an optix sphere visualization object from a Chrono sphere shape. - void sphereVisualization(std::shared_ptr body, - std::shared_ptr sphere_shape, - ChFrame<> asset_frame); + void sphereVisualization(std::shared_ptr body, std::shared_ptr sphere_shape, ChFrame<> asset_frame); /// Creates an optix cylinder visualization object from a Chrono cylinder shape. - void cylinderVisualization(std::shared_ptr body, - std::shared_ptr sphere_shape, - ChFrame<> asset_frame); + void cylinderVisualization(std::shared_ptr body, std::shared_ptr sphere_shape, ChFrame<> asset_frame); /// Creates an optix rigid mesh visualization object from a Chrono mesh shape - void rigidMeshVisualization(std::shared_ptr body, - std::shared_ptr sphere_shape, - ChFrame<> asset_frame); + void rigidMeshVisualization(std::shared_ptr body, std::shared_ptr sphere_shape, ChFrame<> asset_frame); /// Creates an optix deformable mesh visualization object from a Chrono mesh shape. - void deformableMeshVisualization(std::shared_ptr body, - std::shared_ptr sphere_shape, - ChFrame<> asset_frame); + void deformableMeshVisualization(std::shared_ptr body, std::shared_ptr sphere_shape, ChFrame<> asset_frame); - #ifdef USE_SENSOR_NVDB - void nvdbVisualization(std::shared_ptr body, std::shared_ptr box_shape, ChFrame<> asset_frame); - #endif +#ifdef USE_SENSOR_NVDB + void nvdbVisualization(std::shared_ptr body, std::shared_ptr box_shape, ChFrame<> asset_frame); +#endif std::vector m_renderQueue; ///< list of sensor indices that need to be updated @@ -180,14 +183,17 @@ class CH_SENSOR_API ChOptixEngine { // information that belongs to the rendering concept of this engine OptixDeviceContext m_context; ///< the optix context we use for everything ContextParameters m_params; + +#ifdef CHRONO_FSI_SPH + const std::vector* m_fsi_sph_sources = nullptr; ///< native FSI-SPH render sources +#endif ContextParameters* md_params = nullptr; OptixTraversableHandle m_root; std::shared_ptr m_geometry; // manager of all geometry in the scene std::shared_ptr m_pipeline; // manager of all geometry in the scene - std::vector> m_assignedSensor; ///< list of sensor this engine is responsible for - std::vector> - m_assignedRenderers; ///< list of sensor this engine is responsible for + std::vector> m_assignedSensor; ///< list of sensor this engine is responsible for + std::vector> m_assignedRenderers; ///< list of sensor this engine is responsible for std::vector> m_cameraStartFrames; std::vector m_cameraStartFrames_set; diff --git a/src/chrono_sensor/optix/ChOptixGeometry.cpp b/src/chrono_sensor/optix/ChOptixGeometry.cpp index 73cc77c3a3..10021a0298 100644 --- a/src/chrono_sensor/optix/ChOptixGeometry.cpp +++ b/src/chrono_sensor/optix/ChOptixGeometry.cpp @@ -24,7 +24,11 @@ #include #include "chrono_sensor/optix/ChOptixUtils.h" +#ifdef CHRONO_FSI_SPH + #include "chrono_sensor/cuda/fsi_sph_render.cuh" +#endif +#include #include namespace chrono { @@ -92,15 +96,29 @@ void ChOptixGeometry::Cleanup() { // clear our deformable meshes m_deformable_meshes.clear(); +#ifdef CHRONO_FSI_SPH + for (auto& cloud : m_fsi_sph_clouds) { + if (cloud.d_sprite_gas_handles) { + CUDA_ERROR_CHECK(cudaFree(reinterpret_cast(cloud.d_sprite_gas_handles))); + cloud.d_sprite_gas_handles = {}; + } + if (cloud.d_sprite_mat_ids) { + CUDA_ERROR_CHECK(cudaFree(reinterpret_cast(cloud.d_sprite_mat_ids))); + cloud.d_sprite_mat_ids = {}; + } + if (cloud.d_sprite_scales) { + CUDA_ERROR_CHECK(cudaFree(reinterpret_cast(cloud.d_sprite_scales))); + cloud.d_sprite_scales = {}; + } + } + m_fsi_sph_clouds.clear(); +#endif + // clear out index buffers m_obj_mat_ids.clear(); } -void ChOptixGeometry::AddGenericObject(unsigned int mat_id, - std::shared_ptr body, - ChFrame asset_frame, - ChVector3d scale, - OptixTraversableHandle gas_handle) { +void ChOptixGeometry::AddGenericObject(unsigned int mat_id, std::shared_ptr body, ChFrame asset_frame, ChVector3d scale, OptixTraversableHandle gas_handle) { // add to list of box instances m_obj_mat_ids.push_back(mat_id); m_bodies.push_back(body); @@ -127,10 +145,7 @@ void ChOptixGeometry::AddGenericObject(unsigned int mat_id, memcpy(m_motion_transforms[i].transform[1], t, 12 * sizeof(float)); } -void ChOptixGeometry::AddBox(std::shared_ptr body, - ChFrame asset_frame, - ChVector3d scale, - unsigned int mat_id) { +void ChOptixGeometry::AddBox(std::shared_ptr body, ChFrame asset_frame, ChVector3d scale, unsigned int mat_id) { if (!m_box_inst) { // create first box instance OptixAabb aabb[1]; @@ -158,8 +173,8 @@ void ChOptixGeometry::AddBox(std::shared_ptr body, aabb_input.customPrimitiveArray.primitiveIndexOffset = 0; OptixAccelBuildOptions accel_options = {}; - accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION; // allow compaction to save memory - accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; // build operation + accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION; // allow compaction to save memory + accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; // build operation // building box GAS OptixAccelBufferSizes gas_buffer_sizes; @@ -170,8 +185,7 @@ void ChOptixGeometry::AddBox(std::shared_ptr body, size_t compactedSizeOffset = (size_t)((gas_buffer_sizes.outputSizeInBytes + 8ull - 1 / 8ull) * 8ull); - CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&d_buffer_temp_output_gas_and_compacted_size), - compactedSizeOffset + 8)); + CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&d_buffer_temp_output_gas_and_compacted_size), compactedSizeOffset + 8)); OptixAccelEmitDesc emitProperty = {}; emitProperty.type = OPTIX_PROPERTY_TYPE_COMPACTED_SIZE; emitProperty.result = (CUdeviceptr)((char*)d_buffer_temp_output_gas_and_compacted_size + compactedSizeOffset); @@ -180,22 +194,18 @@ void ChOptixGeometry::AddBox(std::shared_ptr body, m_gas_buffers.emplace_back(); m_box_gas_id = static_cast(m_gas_handles.size() - 1); - OPTIX_ERROR_CHECK(optixAccelBuild(m_context, 0, &accel_options, &aabb_input, 1, d_temp_buffer_gas, - gas_buffer_sizes.tempSizeInBytes, d_buffer_temp_output_gas_and_compacted_size, - gas_buffer_sizes.outputSizeInBytes, &m_gas_handles[m_box_gas_id], - &emitProperty, 1)); + OPTIX_ERROR_CHECK(optixAccelBuild(m_context, 0, &accel_options, &aabb_input, 1, d_temp_buffer_gas, gas_buffer_sizes.tempSizeInBytes, + d_buffer_temp_output_gas_and_compacted_size, gas_buffer_sizes.outputSizeInBytes, &m_gas_handles[m_box_gas_id], &emitProperty, 1)); CUDA_ERROR_CHECK(cudaFree(reinterpret_cast(d_temp_buffer_gas))); size_t compacted_gas_size; - CUDA_ERROR_CHECK(cudaMemcpy(&compacted_gas_size, reinterpret_cast(emitProperty.result), sizeof(size_t), - cudaMemcpyDeviceToHost)); + CUDA_ERROR_CHECK(cudaMemcpy(&compacted_gas_size, reinterpret_cast(emitProperty.result), sizeof(size_t), cudaMemcpyDeviceToHost)); if (compacted_gas_size < gas_buffer_sizes.outputSizeInBytes) { CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&m_gas_buffers[m_box_gas_id]), compacted_gas_size)); // use handle as input and output - OPTIX_ERROR_CHECK(optixAccelCompact(m_context, 0, m_gas_handles[m_box_gas_id], m_gas_buffers[m_box_gas_id], - compacted_gas_size, &m_gas_handles[m_box_gas_id])); + OPTIX_ERROR_CHECK(optixAccelCompact(m_context, 0, m_gas_handles[m_box_gas_id], m_gas_buffers[m_box_gas_id], compacted_gas_size, &m_gas_handles[m_box_gas_id])); CUDA_ERROR_CHECK(cudaFree(reinterpret_cast(d_buffer_temp_output_gas_and_compacted_size))); } else { m_gas_buffers[m_box_gas_id] = d_buffer_temp_output_gas_and_compacted_size; @@ -208,12 +218,8 @@ void ChOptixGeometry::AddBox(std::shared_ptr body, AddGenericObject(mat_id, body, asset_frame, scale, m_gas_handles[m_box_gas_id]); } - #ifdef USE_SENSOR_NVDB -void ChOptixGeometry::AddNVDBVolume(std::shared_ptr body, - ChFrame asset_frame, - ChVector3d scale, - unsigned int mat_id) { +void ChOptixGeometry::AddNVDBVolume(std::shared_ptr body, ChFrame asset_frame, ChVector3d scale, unsigned int mat_id) { if (!m_nvdb_inst) { // create first box instance OptixAabb aabb[1]; @@ -248,8 +254,8 @@ void ChOptixGeometry::AddNVDBVolume(std::shared_ptr body, aabb_input.customPrimitiveArray.primitiveIndexOffset = 0; OptixAccelBuildOptions accel_options = {}; - accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION; // allow compaction to save memory - accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; // build operation + accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION; // allow compaction to save memory + accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; // build operation // building box GAS OptixAccelBufferSizes gas_buffer_sizes; @@ -260,8 +266,7 @@ void ChOptixGeometry::AddNVDBVolume(std::shared_ptr body, size_t compactedSizeOffset = (size_t)((gas_buffer_sizes.outputSizeInBytes + 8ull - 1 / 8ull) * 8ull); - CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&d_buffer_temp_output_gas_and_compacted_size), - compactedSizeOffset + 8)); + CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&d_buffer_temp_output_gas_and_compacted_size), compactedSizeOffset + 8)); OptixAccelEmitDesc emitProperty = {}; emitProperty.type = OPTIX_PROPERTY_TYPE_COMPACTED_SIZE; emitProperty.result = (CUdeviceptr)((char*)d_buffer_temp_output_gas_and_compacted_size + compactedSizeOffset); @@ -270,22 +275,18 @@ void ChOptixGeometry::AddNVDBVolume(std::shared_ptr body, m_gas_buffers.emplace_back(); m_box_gas_id = static_cast(m_gas_handles.size() - 1); - OPTIX_ERROR_CHECK(optixAccelBuild(m_context, 0, &accel_options, &aabb_input, 1, d_temp_buffer_gas, - gas_buffer_sizes.tempSizeInBytes, d_buffer_temp_output_gas_and_compacted_size, - gas_buffer_sizes.outputSizeInBytes, &m_gas_handles[m_box_gas_id], - &emitProperty, 1)); + OPTIX_ERROR_CHECK(optixAccelBuild(m_context, 0, &accel_options, &aabb_input, 1, d_temp_buffer_gas, gas_buffer_sizes.tempSizeInBytes, + d_buffer_temp_output_gas_and_compacted_size, gas_buffer_sizes.outputSizeInBytes, &m_gas_handles[m_box_gas_id], &emitProperty, 1)); CUDA_ERROR_CHECK(cudaFree(reinterpret_cast(d_temp_buffer_gas))); size_t compacted_gas_size; - CUDA_ERROR_CHECK(cudaMemcpy(&compacted_gas_size, reinterpret_cast(emitProperty.result), sizeof(size_t), - cudaMemcpyDeviceToHost)); + CUDA_ERROR_CHECK(cudaMemcpy(&compacted_gas_size, reinterpret_cast(emitProperty.result), sizeof(size_t), cudaMemcpyDeviceToHost)); if (compacted_gas_size < gas_buffer_sizes.outputSizeInBytes) { CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&m_gas_buffers[m_box_gas_id]), compacted_gas_size)); // use handle as input and output - OPTIX_ERROR_CHECK(optixAccelCompact(m_context, 0, m_gas_handles[m_box_gas_id], m_gas_buffers[m_box_gas_id], - compacted_gas_size, &m_gas_handles[m_box_gas_id])); + OPTIX_ERROR_CHECK(optixAccelCompact(m_context, 0, m_gas_handles[m_box_gas_id], m_gas_buffers[m_box_gas_id], compacted_gas_size, &m_gas_handles[m_box_gas_id])); CUDA_ERROR_CHECK(cudaFree(reinterpret_cast(d_buffer_temp_output_gas_and_compacted_size))); } else { m_gas_buffers[m_box_gas_id] = d_buffer_temp_output_gas_and_compacted_size; @@ -297,12 +298,9 @@ void ChOptixGeometry::AddNVDBVolume(std::shared_ptr body, AddGenericObject(mat_id, body, asset_frame, scale, m_gas_handles[m_box_gas_id]); } -#endif // USE_SENSOR_NVDB +#endif // USE_SENSOR_NVDB -void ChOptixGeometry::AddSphere(std::shared_ptr body, - ChFrame asset_frame, - ChVector3d scale, - unsigned int mat_id) { +void ChOptixGeometry::AddSphere(std::shared_ptr body, ChFrame asset_frame, ChVector3d scale, unsigned int mat_id) { if (!m_sphere_inst) { // create first sphere instance OptixAabb aabb[1]; @@ -325,8 +323,8 @@ void ChOptixGeometry::AddSphere(std::shared_ptr body, aabb_input.customPrimitiveArray.primitiveIndexOffset = 0; OptixAccelBuildOptions accel_options = {}; - accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION; // allow compaction to save memory - accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; // build operation + accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION; // allow compaction to save memory + accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; // build operation // building sphere GAS OptixAccelBufferSizes gas_buffer_sizes; @@ -337,8 +335,7 @@ void ChOptixGeometry::AddSphere(std::shared_ptr body, size_t compactedSizeOffset = (size_t)((gas_buffer_sizes.outputSizeInBytes + 8ull - 1 / 8ull) * 8ull); - CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&d_buffer_temp_output_gas_and_compacted_size), - compactedSizeOffset + 8)); + CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&d_buffer_temp_output_gas_and_compacted_size), compactedSizeOffset + 8)); OptixAccelEmitDesc emitProperty = {}; emitProperty.type = OPTIX_PROPERTY_TYPE_COMPACTED_SIZE; emitProperty.result = (CUdeviceptr)((char*)d_buffer_temp_output_gas_and_compacted_size + compactedSizeOffset); @@ -347,23 +344,18 @@ void ChOptixGeometry::AddSphere(std::shared_ptr body, m_gas_buffers.emplace_back(); m_sphere_gas_id = static_cast(m_gas_handles.size() - 1); - OPTIX_ERROR_CHECK(optixAccelBuild(m_context, 0, &accel_options, &aabb_input, 1, d_temp_buffer_gas, - gas_buffer_sizes.tempSizeInBytes, d_buffer_temp_output_gas_and_compacted_size, - gas_buffer_sizes.outputSizeInBytes, &m_gas_handles[m_sphere_gas_id], - &emitProperty, 1)); + OPTIX_ERROR_CHECK(optixAccelBuild(m_context, 0, &accel_options, &aabb_input, 1, d_temp_buffer_gas, gas_buffer_sizes.tempSizeInBytes, + d_buffer_temp_output_gas_and_compacted_size, gas_buffer_sizes.outputSizeInBytes, &m_gas_handles[m_sphere_gas_id], &emitProperty, 1)); CUDA_ERROR_CHECK(cudaFree(reinterpret_cast(d_temp_buffer_gas))); size_t compacted_gas_size; - CUDA_ERROR_CHECK(cudaMemcpy(&compacted_gas_size, reinterpret_cast(emitProperty.result), sizeof(size_t), - cudaMemcpyDeviceToHost)); + CUDA_ERROR_CHECK(cudaMemcpy(&compacted_gas_size, reinterpret_cast(emitProperty.result), sizeof(size_t), cudaMemcpyDeviceToHost)); if (compacted_gas_size < gas_buffer_sizes.outputSizeInBytes) { CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&m_gas_buffers[m_sphere_gas_id]), compacted_gas_size)); // use handle as input and output - OPTIX_ERROR_CHECK(optixAccelCompact(m_context, 0, m_gas_handles[m_sphere_gas_id], - m_gas_buffers[m_sphere_gas_id], compacted_gas_size, - &m_gas_handles[m_sphere_gas_id])); + OPTIX_ERROR_CHECK(optixAccelCompact(m_context, 0, m_gas_handles[m_sphere_gas_id], m_gas_buffers[m_sphere_gas_id], compacted_gas_size, &m_gas_handles[m_sphere_gas_id])); CUDA_ERROR_CHECK(cudaFree(reinterpret_cast(d_buffer_temp_output_gas_and_compacted_size))); } else { m_gas_buffers[m_sphere_gas_id] = d_buffer_temp_output_gas_and_compacted_size; @@ -375,10 +367,101 @@ void ChOptixGeometry::AddSphere(std::shared_ptr body, AddGenericObject(mat_id, body, asset_frame, scale, m_gas_handles[m_sphere_gas_id]); } -void ChOptixGeometry::AddCylinder(std::shared_ptr body, - ChFrame asset_frame, - ChVector3d scale, - unsigned int mat_id) { +#ifdef CHRONO_FSI_SPH +void ChOptixGeometry::AddFsiSphCloud(int source_id, + size_t count, + size_t source_count, + const std::vector& d_vertices, + const std::vector& d_indices, + const std::vector>& shapes, + const std::vector& mat_ids, + float render_particle_spacing, + const ChVector3f& position_jitter) { + if (count == 0 || source_count == 0 || shapes.empty()) + return; + if (d_vertices.size() != shapes.size() || d_indices.size() != shapes.size() || mat_ids.size() != shapes.size()) + return; + + size_t instance_offset = m_obj_mat_ids.size(); + for (const auto& cloud : m_fsi_sph_clouds) + instance_offset += cloud.count; + + FsiSphCloud cloud; + cloud.source_id = source_id; + cloud.instance_offset = instance_offset; + cloud.count = count; + cloud.source_count = source_count; + cloud.render_particle_spacing = render_particle_spacing; + cloud.sprite_position_jitter = position_jitter; + + std::vector gas_handles; + std::vector template_mat_ids; + std::vector template_scales; + gas_handles.reserve(shapes.size()); + template_mat_ids.reserve(shapes.size()); + template_scales.reserve(shapes.size()); + + for (size_t i = 0; i < shapes.size(); ++i) { + if (!shapes[i]) + continue; + + unsigned int gas_id = 0; + ChVector3f shape_scale(1.f, 1.f, 1.f); + + if (auto mesh_shape = std::dynamic_pointer_cast(shapes[i])) { + gas_id = GetOrCreateRigidMeshGAS(d_vertices[i], d_indices[i], mesh_shape); + const ChVector3d mesh_scale = mesh_shape->GetScale(); + shape_scale = ChVector3f(static_cast(mesh_scale.x()), static_cast(mesh_scale.y()), static_cast(mesh_scale.z())); + } else { + continue; + } + + FsiSphSpriteTemplate sprite_template; + sprite_template.gas_id = gas_id; + sprite_template.mat_id = mat_ids[i]; + sprite_template.scale = shape_scale; + cloud.sprite_templates.push_back(sprite_template); + + gas_handles.push_back(m_gas_handles[gas_id]); + template_mat_ids.push_back(mat_ids[i]); + template_scales.push_back(make_float3(sprite_template.scale.x(), sprite_template.scale.y(), sprite_template.scale.z())); + } + + if (cloud.sprite_templates.empty()) + return; + + CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&cloud.d_sprite_gas_handles), gas_handles.size() * sizeof(OptixTraversableHandle))); + CUDA_ERROR_CHECK( + cudaMemcpy(reinterpret_cast(cloud.d_sprite_gas_handles), gas_handles.data(), gas_handles.size() * sizeof(OptixTraversableHandle), cudaMemcpyHostToDevice)); + + CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&cloud.d_sprite_mat_ids), template_mat_ids.size() * sizeof(unsigned int))); + CUDA_ERROR_CHECK(cudaMemcpy(reinterpret_cast(cloud.d_sprite_mat_ids), template_mat_ids.data(), template_mat_ids.size() * sizeof(unsigned int), cudaMemcpyHostToDevice)); + + CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&cloud.d_sprite_scales), template_scales.size() * sizeof(float3))); + CUDA_ERROR_CHECK(cudaMemcpy(reinterpret_cast(cloud.d_sprite_scales), template_scales.data(), template_scales.size() * sizeof(float3), cudaMemcpyHostToDevice)); + + m_fsi_sph_clouds.push_back(cloud); +} + +void ChOptixGeometry::UpdateFsiSphCloud(int source_id, const chrono::fsi::sph::Real4* pos_rad, size_t marker_offset, size_t count) { + if (!pos_rad || !md_instances || count == 0) + return; + + for (const auto& cloud : m_fsi_sph_clouds) { + if (cloud.source_id != source_id) + continue; + + cuda_update_fsi_sph_sprite_instances(pos_rad + marker_offset, count, cloud.count, reinterpret_cast(md_instances) + cloud.instance_offset, + reinterpret_cast(cloud.d_sprite_gas_handles), + reinterpret_cast(cloud.d_sprite_mat_ids), reinterpret_cast(cloud.d_sprite_scales), + static_cast(cloud.sprite_templates.size()), cloud.render_particle_spacing, cloud.sprite_position_jitter, + m_origin_offset); + return; + } +} +#endif + +void ChOptixGeometry::AddCylinder(std::shared_ptr body, ChFrame asset_frame, ChVector3d scale, unsigned int mat_id) { if (!m_cyl_inst) { // create first cylinder instance OptixAabb aabb[1]; @@ -401,8 +484,8 @@ void ChOptixGeometry::AddCylinder(std::shared_ptr body, aabb_input.customPrimitiveArray.primitiveIndexOffset = 0; OptixAccelBuildOptions accel_options = {}; - accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION; // allow compaction to save memory - accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; // build operation + accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION; // allow compaction to save memory + accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; // build operation // building cylinder GAS OptixAccelBufferSizes gas_buffer_sizes; @@ -413,8 +496,7 @@ void ChOptixGeometry::AddCylinder(std::shared_ptr body, size_t compactedSizeOffset = (size_t)((gas_buffer_sizes.outputSizeInBytes + 8ull - 1 / 8ull) * 8ull); - CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&d_buffer_temp_output_gas_and_compacted_size), - compactedSizeOffset + 8)); + CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&d_buffer_temp_output_gas_and_compacted_size), compactedSizeOffset + 8)); OptixAccelEmitDesc emitProperty = {}; emitProperty.type = OPTIX_PROPERTY_TYPE_COMPACTED_SIZE; emitProperty.result = (CUdeviceptr)((char*)d_buffer_temp_output_gas_and_compacted_size + compactedSizeOffset); @@ -423,22 +505,18 @@ void ChOptixGeometry::AddCylinder(std::shared_ptr body, m_gas_buffers.emplace_back(); m_cyl_gas_id = static_cast(m_gas_handles.size() - 1); - OPTIX_ERROR_CHECK(optixAccelBuild(m_context, 0, &accel_options, &aabb_input, 1, d_temp_buffer_gas, - gas_buffer_sizes.tempSizeInBytes, d_buffer_temp_output_gas_and_compacted_size, - gas_buffer_sizes.outputSizeInBytes, &m_gas_handles[m_cyl_gas_id], - &emitProperty, 1)); + OPTIX_ERROR_CHECK(optixAccelBuild(m_context, 0, &accel_options, &aabb_input, 1, d_temp_buffer_gas, gas_buffer_sizes.tempSizeInBytes, + d_buffer_temp_output_gas_and_compacted_size, gas_buffer_sizes.outputSizeInBytes, &m_gas_handles[m_cyl_gas_id], &emitProperty, 1)); CUDA_ERROR_CHECK(cudaFree(reinterpret_cast(d_temp_buffer_gas))); size_t compacted_gas_size; - CUDA_ERROR_CHECK(cudaMemcpy(&compacted_gas_size, reinterpret_cast(emitProperty.result), sizeof(size_t), - cudaMemcpyDeviceToHost)); + CUDA_ERROR_CHECK(cudaMemcpy(&compacted_gas_size, reinterpret_cast(emitProperty.result), sizeof(size_t), cudaMemcpyDeviceToHost)); if (compacted_gas_size < gas_buffer_sizes.outputSizeInBytes) { CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&m_gas_buffers[m_cyl_gas_id]), compacted_gas_size)); // use handle as input and output - OPTIX_ERROR_CHECK(optixAccelCompact(m_context, 0, m_gas_handles[m_cyl_gas_id], m_gas_buffers[m_cyl_gas_id], - compacted_gas_size, &m_gas_handles[m_cyl_gas_id])); + OPTIX_ERROR_CHECK(optixAccelCompact(m_context, 0, m_gas_handles[m_cyl_gas_id], m_gas_buffers[m_cyl_gas_id], compacted_gas_size, &m_gas_handles[m_cyl_gas_id])); CUDA_ERROR_CHECK(cudaFree(reinterpret_cast(d_buffer_temp_output_gas_and_compacted_size))); } else { m_gas_buffers[m_cyl_gas_id] = d_buffer_temp_output_gas_and_compacted_size; @@ -450,14 +528,7 @@ void ChOptixGeometry::AddCylinder(std::shared_ptr body, AddGenericObject(mat_id, body, asset_frame, scale, m_gas_handles[m_cyl_gas_id]); } -unsigned int ChOptixGeometry::AddRigidMesh(CUdeviceptr d_vertices, - CUdeviceptr d_indices, - std::shared_ptr mesh_shape, - std::shared_ptr body, - ChFrame asset_frame, - ChVector3d scale, - unsigned int mat_id) { - // std::cout << "Adding rigid mesh to optix!\n"; +unsigned int ChOptixGeometry::GetOrCreateRigidMeshGAS(CUdeviceptr d_vertices, CUdeviceptr d_indices, std::shared_ptr mesh_shape) { bool mesh_found = false; unsigned int mesh_gas_id = 0; for (int i = 0; i < m_known_meshes.size(); i++) { @@ -479,6 +550,19 @@ unsigned int ChOptixGeometry::AddRigidMesh(CUdeviceptr d_vertices, // std::cout << "Created a mesh from scratch:\n"; } + return mesh_gas_id; +} + +unsigned int ChOptixGeometry::AddRigidMesh(CUdeviceptr d_vertices, + CUdeviceptr d_indices, + std::shared_ptr mesh_shape, + std::shared_ptr body, + ChFrame asset_frame, + ChVector3d scale, + unsigned int mat_id) { + // std::cout << "Adding rigid mesh to optix!\n"; + unsigned int mesh_gas_id = GetOrCreateRigidMeshGAS(d_vertices, d_indices, mesh_shape); + AddGenericObject(mat_id, body, asset_frame, scale, m_gas_handles[mesh_gas_id]); return mesh_gas_id; @@ -517,9 +601,9 @@ unsigned int ChOptixGeometry::BuildTrianglesGAS(std::shared_ptrGetMesh(); OptixAccelBuildOptions accel_options = {}; - accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION; // allow compaction to save memory - accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; // build operation - + accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION; // allow compaction to save memory + accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; // build operation + if (!compact_no_update) { accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_UPDATE; // accel_options.buildFlags = OPTIX_BUILD_FLAG_NONE; @@ -567,20 +651,16 @@ unsigned int ChOptixGeometry::BuildTrianglesGAS(std::shared_ptr(&d_buffer_temp_output_gas_and_compacted_size), - compactedSizeOffset + 8)); + CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&d_buffer_temp_output_gas_and_compacted_size), compactedSizeOffset + 8)); OptixAccelEmitDesc emitProperty = {}; emitProperty.type = OPTIX_PROPERTY_TYPE_COMPACTED_SIZE; emitProperty.result = (CUdeviceptr)((char*)d_buffer_temp_output_gas_and_compacted_size + compactedSizeOffset); - OPTIX_ERROR_CHECK(optixAccelBuild(m_context, 0, &accel_options, &mesh_input, 1, d_temp_buffer_gas, - gas_buffer_sizes.tempSizeInBytes, d_buffer_temp_output_gas_and_compacted_size, - gas_buffer_sizes.outputSizeInBytes, &m_gas_handles[mesh_gas_id], - &emitProperty, 1)); + OPTIX_ERROR_CHECK(optixAccelBuild(m_context, 0, &accel_options, &mesh_input, 1, d_temp_buffer_gas, gas_buffer_sizes.tempSizeInBytes, + d_buffer_temp_output_gas_and_compacted_size, gas_buffer_sizes.outputSizeInBytes, &m_gas_handles[mesh_gas_id], &emitProperty, 1)); CUDA_ERROR_CHECK(cudaFree(reinterpret_cast(d_temp_buffer_gas))); size_t compacted_gas_size; - CUDA_ERROR_CHECK(cudaMemcpy(&compacted_gas_size, reinterpret_cast(emitProperty.result), sizeof(size_t), - cudaMemcpyDeviceToHost)); + CUDA_ERROR_CHECK(cudaMemcpy(&compacted_gas_size, reinterpret_cast(emitProperty.result), sizeof(size_t), cudaMemcpyDeviceToHost)); if (compacted_gas_size < gas_buffer_sizes.outputSizeInBytes) { if (rebuild && m_gas_buffers[mesh_gas_id]) { @@ -589,8 +669,7 @@ unsigned int ChOptixGeometry::BuildTrianglesGAS(std::shared_ptr(&m_gas_buffers[mesh_gas_id]), compacted_gas_size)); // use handle as input and output - OPTIX_ERROR_CHECK(optixAccelCompact(m_context, 0, m_gas_handles[mesh_gas_id], m_gas_buffers[mesh_gas_id], - compacted_gas_size, &m_gas_handles[mesh_gas_id])); + OPTIX_ERROR_CHECK(optixAccelCompact(m_context, 0, m_gas_handles[mesh_gas_id], m_gas_buffers[mesh_gas_id], compacted_gas_size, &m_gas_handles[mesh_gas_id])); CUDA_ERROR_CHECK(cudaFree(reinterpret_cast(d_buffer_temp_output_gas_and_compacted_size))); } else { m_gas_buffers[mesh_gas_id] = d_buffer_temp_output_gas_and_compacted_size; @@ -598,11 +677,9 @@ unsigned int ChOptixGeometry::BuildTrianglesGAS(std::shared_ptr(&m_gas_buffers[mesh_gas_id]), gas_buffer_sizes.outputSizeInBytes)); + CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&m_gas_buffers[mesh_gas_id]), gas_buffer_sizes.outputSizeInBytes)); } - OPTIX_ERROR_CHECK(optixAccelBuild(m_context, 0, &accel_options, &mesh_input, 1, d_temp_buffer_gas, - gas_buffer_sizes.tempSizeInBytes, m_gas_buffers[mesh_gas_id], + OPTIX_ERROR_CHECK(optixAccelBuild(m_context, 0, &accel_options, &mesh_input, 1, d_temp_buffer_gas, gas_buffer_sizes.tempSizeInBytes, m_gas_buffers[mesh_gas_id], gas_buffer_sizes.outputSizeInBytes, &m_gas_handles[mesh_gas_id], nullptr, 0)); CUDA_ERROR_CHECK(cudaFree(reinterpret_cast(d_temp_buffer_gas))); } @@ -614,10 +691,8 @@ OptixTraversableHandle ChOptixGeometry::CreateRootStructure() { // std::cout << "Creating root structure with " << m_obj_mat_ids.size() << " objects\n"; // malloc the gpu memory for motion transform - CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&md_motion_transforms), - m_motion_transforms.size() * sizeof(OptixMatrixMotionTransform))); - CUDA_ERROR_CHECK(cudaMemcpy(reinterpret_cast(md_motion_transforms), m_motion_transforms.data(), - m_motion_transforms.size() * sizeof(OptixMatrixMotionTransform), + CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&md_motion_transforms), m_motion_transforms.size() * sizeof(OptixMatrixMotionTransform))); + CUDA_ERROR_CHECK(cudaMemcpy(reinterpret_cast(md_motion_transforms), m_motion_transforms.data(), m_motion_transforms.size() * sizeof(OptixMatrixMotionTransform), cudaMemcpyHostToDevice)); // loop through and make motion transforms into handles @@ -625,14 +700,20 @@ OptixTraversableHandle ChOptixGeometry::CreateRootStructure() { // << " with size=" << sizeof(OptixMatrixMotionTransform) << std::endl; for (int i = 0; i < m_motion_transforms.size(); i++) { - OPTIX_ERROR_CHECK(optixConvertPointerToTraversableHandle( - m_context, md_motion_transforms + i * sizeof(OptixMatrixMotionTransform), - OPTIX_TRAVERSABLE_TYPE_MATRIX_MOTION_TRANSFORM, &m_motion_handles[i])); + OPTIX_ERROR_CHECK(optixConvertPointerToTraversableHandle(m_context, md_motion_transforms + i * sizeof(OptixMatrixMotionTransform), + OPTIX_TRAVERSABLE_TYPE_MATRIX_MOTION_TRANSFORM, &m_motion_handles[i])); } + size_t num_fsi_sph_instances = 0; +#ifdef CHRONO_FSI_SPH + for (const auto& cloud : m_fsi_sph_clouds) + num_fsi_sph_instances += cloud.count; +#endif + // update and build the instances - size_t instance_size_in_bytes = sizeof(OptixInstance) * m_obj_mat_ids.size(); - m_instances = std::vector(m_obj_mat_ids.size()); + const size_t num_instances = m_obj_mat_ids.size() + num_fsi_sph_instances; + size_t instance_size_in_bytes = sizeof(OptixInstance) * num_instances; + m_instances = std::vector(num_instances); memset(m_instances.data(), 0, instance_size_in_bytes); CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&md_instances), instance_size_in_bytes)); @@ -663,7 +744,7 @@ OptixTraversableHandle ChOptixGeometry::CreateRootStructure() { CUDA_ERROR_CHECK(cudaMalloc(reinterpret_cast(&md_root_output_buffer), ias_buffer_sizes.outputSizeInBytes)); // pack the data for each instance - for (int i = 0; i < m_instances.size(); i++) { + for (int i = 0; i < m_obj_mat_ids.size(); i++) { const float t[12] = {1.f, 0.f, 0.f, 0.f, // 0.f, 1.f, 0.f, 0.f, // 0.f, 0.f, 1.f, 0.f}; @@ -677,14 +758,34 @@ OptixTraversableHandle ChOptixGeometry::CreateRootStructure() { memcpy(m_instances[i].transform, t, sizeof(float) * 12); } - CUDA_ERROR_CHECK(cudaMemcpy(reinterpret_cast(md_instances), m_instances.data(), instance_size_in_bytes, - cudaMemcpyHostToDevice)); +#ifdef CHRONO_FSI_SPH + for (const auto& cloud : m_fsi_sph_clouds) { + for (size_t k = 0; k < cloud.count; ++k) { + const size_t i = cloud.instance_offset + k; + const auto& sprite_template = cloud.sprite_templates[k % cloud.sprite_templates.size()]; + const OptixTraversableHandle gas_handle = m_gas_handles[sprite_template.gas_id]; + const unsigned int mat_id = sprite_template.mat_id; + const ChVector3f scale = sprite_template.scale; + + const float t[12] = {scale.x(), 0.f, 0.f, 0.f, // + 0.f, scale.y(), 0.f, 0.f, // + 0.f, 0.f, scale.z(), 0.f}; + m_instances[i].traversableHandle = gas_handle; + m_instances[i].flags = OPTIX_INSTANCE_FLAG_DISABLE_ANYHIT; + m_instances[i].instanceId = static_cast(i); + m_instances[i].sbtOffset = mat_id; + m_instances[i].visibilityMask = 1; + memcpy(m_instances[i].transform, t, sizeof(float) * 12); + } + } +#endif + + CUDA_ERROR_CHECK(cudaMemcpy(reinterpret_cast(md_instances), m_instances.data(), instance_size_in_bytes, cudaMemcpyHostToDevice)); OPTIX_ERROR_CHECK(optixAccelBuild(m_context, 0, // CUDA stream &accel_options, &instance_input, 1, // num build inputs - md_root_temp_buffer, ias_buffer_sizes.tempSizeInBytes, md_root_output_buffer, - ias_buffer_sizes.outputSizeInBytes, &m_root, + md_root_temp_buffer, ias_buffer_sizes.tempSizeInBytes, md_root_output_buffer, ias_buffer_sizes.outputSizeInBytes, &m_root, nullptr, // emitted property list 0 // num emitted properties )); @@ -694,9 +795,7 @@ OptixTraversableHandle ChOptixGeometry::CreateRootStructure() { // rebuilding the structure without creating anything new void ChOptixGeometry::RebuildRootStructure() { - m_end_time = m_end_time > (m_start_time + 1e-2) - ? m_end_time - : m_end_time + 1e-2; // need to ensure start time is at least slightly after end time + m_end_time = m_end_time > (m_start_time + 1e-2) ? m_end_time : m_end_time + 1e-2; // need to ensure start time is at least slightly after end time for (int i = 0; i < m_motion_transforms.size(); i++) { // update the motion transforms @@ -714,8 +813,7 @@ void ChOptixGeometry::RebuildRootStructure() { GetT3x4FromSRT(m_obj_scales[i], rot_mat_end, pos_end, m_motion_transforms[i].transform[1]); } - CUDA_ERROR_CHECK(cudaMemcpy(reinterpret_cast(md_motion_transforms), m_motion_transforms.data(), - m_motion_transforms.size() * sizeof(OptixMatrixMotionTransform), + CUDA_ERROR_CHECK(cudaMemcpy(reinterpret_cast(md_motion_transforms), m_motion_transforms.data(), m_motion_transforms.size() * sizeof(OptixMatrixMotionTransform), cudaMemcpyHostToDevice)); OptixBuildInput instance_input = {}; @@ -740,8 +838,7 @@ void ChOptixGeometry::RebuildRootStructure() { 0, // CUDA stream &accel_options, &instance_input, 1, // num build inputs - md_root_temp_buffer, ias_buffer_sizes.tempSizeInBytes, md_root_output_buffer, - ias_buffer_sizes.outputSizeInBytes, &m_root, + md_root_temp_buffer, ias_buffer_sizes.tempSizeInBytes, md_root_output_buffer, ias_buffer_sizes.outputSizeInBytes, &m_root, nullptr, // emitted property list 0 // num emitted properties )); @@ -813,10 +910,7 @@ void ChOptixGeometry::GetT3x4FromSRT(const ChVector3d& s, const ChMatrix33& a, - const ChVector3d& b, - float* t) { +void ChOptixGeometry::GetInvT3x4FromSRT(const ChVector3d& s, const ChMatrix33& a, const ChVector3d& b, float* t) { t[0] = (float)(a(0) / s.x()); t[1] = (float)(a(3) / s.x()); t[2] = (float)(a(6) / s.x()); diff --git a/src/chrono_sensor/optix/ChOptixGeometry.h b/src/chrono_sensor/optix/ChOptixGeometry.h index 343001963b..2d417038e4 100644 --- a/src/chrono_sensor/optix/ChOptixGeometry.h +++ b/src/chrono_sensor/optix/ChOptixGeometry.h @@ -24,6 +24,11 @@ #include "chrono/physics/ChBody.h" #include "chrono/assets/ChVisualShapeTriangleMesh.h" +#ifdef CHRONO_FSI_SPH + #include "chrono_fsi/sph/ChFsiFluidSystemSPH.h" + #include "chrono_sensor/ChFsiSphRender.h" +#endif + #include namespace chrono { @@ -55,15 +60,14 @@ class CH_SENSOR_API ChOptixGeometry { /// @param mat_id the material id associated with the box void AddBox(std::shared_ptr body, ChFrame asset_frame, ChVector3d scale, unsigned int mat_id); - #ifdef USE_SENSOR_NVDB +#ifdef USE_SENSOR_NVDB /// Add a NVDB volume to the optix scene /// @param body the Chrono Body that drives the NVDB volume /// @param asset_frame the Chrono frame that specifies how the asset is attached to the body /// @param scale the scale of the NVDB volume /// @param mat_id the material id associated with the NVDB volume - void AddNVDBVolume(std::shared_ptr body, ChFrame asset_frame,ChVector3d scale,unsigned int mat_id); - #endif - + void AddNVDBVolume(std::shared_ptr body, ChFrame asset_frame, ChVector3d scale, unsigned int mat_id); +#endif /// Add a sphere geometry to the optix scene /// @param body the Chrono Body that drives the sphere @@ -111,7 +115,6 @@ class CH_SENSOR_API ChOptixGeometry { ChVector3d scale, unsigned int mat_id); - /// Create the root node and acceleration structure of the scene ///@return A traversable handle to the root node OptixTraversableHandle CreateRootStructure(); @@ -128,6 +131,22 @@ class CH_SENSOR_API ChOptixGeometry { /// Update the deformable meshes based on how the meshes changed in Chrono void UpdateDeformableMeshes(); +#ifdef CHRONO_FSI_SPH + /// Add a native FSI-SPH marker cloud rendered as visual shape sprite instances. + void AddFsiSphCloud(int source_id, + size_t count, + size_t source_count, + const std::vector& d_vertices, + const std::vector& d_indices, + const std::vector>& shapes, + const std::vector& mat_ids, + float render_particle_spacing, + const ChVector3f& position_jitter); + + /// Update a native FSI-SPH marker cloud from device-resident FSI marker positions. + void UpdateFsiSphCloud(int source_id, const chrono::fsi::sph::Real4* pos_rad, size_t marker_offset, size_t count); +#endif + /// Cleanup the entire optix geometry manager, cleans and frees device pointers and root structure void Cleanup(); @@ -141,11 +160,7 @@ class CH_SENSOR_API ChOptixGeometry { /// @param asset_frame the frame associated with the asset relative to the body /// @param scale the scale of the object /// @param gas_handle the handle to the geometry acceleration structure - void AddGenericObject(unsigned int mat_id, - std::shared_ptr body, - ChFrame asset_frame, - ChVector3d scale, - OptixTraversableHandle gas_handle); + void AddGenericObject(unsigned int mat_id, std::shared_ptr body, ChFrame asset_frame, ChVector3d scale, OptixTraversableHandle gas_handle); /// Function to build a geometry acceleration structure for a triangle mesh /// @param mesh_shape the chrono mesh representing this asset @@ -161,6 +176,9 @@ class CH_SENSOR_API ChOptixGeometry { bool rebuild = false, unsigned int gas_id = 0); + /// Reuse or build a GAS for a rigid triangle mesh. + unsigned int GetOrCreateRigidMeshGAS(CUdeviceptr d_vertices, CUdeviceptr d_indices, std::shared_ptr mesh_shape); + /// Function ot convert scale, rotation, translation to top 3 rows of transform matrix /// @param[in] s the scale vector /// @param[in] a the rotation matrix @@ -186,7 +204,7 @@ class CH_SENSOR_API ChOptixGeometry { bool m_cyl_inst = false; ///< whether a cylinder has been created unsigned int m_nvdb_gas_id; - bool m_nvdb_inst = false; + bool m_nvdb_inst = false; // instance and root buffers std::vector m_instances; ///< host vector of geometry instances @@ -223,8 +241,30 @@ class CH_SENSOR_API ChOptixGeometry { std::vector> m_known_meshes; /// deformable mesh list [mesh shape, d_vertices, d_indices, gas id] - std::vector, CUdeviceptr, CUdeviceptr, unsigned int>> - m_deformable_meshes; + std::vector, CUdeviceptr, CUdeviceptr, unsigned int>> m_deformable_meshes; + +#ifdef CHRONO_FSI_SPH + struct FsiSphSpriteTemplate { + unsigned int gas_id = 0; + unsigned int mat_id = 0; + ChVector3f scale = ChVector3f(1.f, 1.f, 1.f); + }; + + struct FsiSphCloud { + int source_id = -1; + size_t instance_offset = 0; + size_t count = 0; + size_t source_count = 0; + std::vector sprite_templates; + CUdeviceptr d_sprite_gas_handles = {}; + CUdeviceptr d_sprite_mat_ids = {}; + CUdeviceptr d_sprite_scales = {}; + float render_particle_spacing = 0.f; + ChVector3f sprite_position_jitter = ChVector3f(0.f, 0.f, 0.f); + }; + + std::vector m_fsi_sph_clouds; ///< native FSI-SPH instance clouds +#endif float m_start_time; ///< time corresponding to start frame float m_end_time; ///< time corresponding to end frame @@ -235,4 +275,4 @@ class CH_SENSOR_API ChOptixGeometry { } // namespace sensor } // namespace chrono -#endif \ No newline at end of file +#endif diff --git a/src/chrono_sensor/optix/ChVisualSystemOptix.cpp b/src/chrono_sensor/optix/ChVisualSystemOptix.cpp index a85f810997..45ae4805ac 100644 --- a/src/chrono_sensor/optix/ChVisualSystemOptix.cpp +++ b/src/chrono_sensor/optix/ChVisualSystemOptix.cpp @@ -17,8 +17,7 @@ namespace chrono { namespace sensor { -ChVisualSystemOptix::ChVisualSystemOptix(ChSystem& sys) - : ChVisualSystem(sys), m_verbose(false), m_optix_reflections(9) { +ChVisualSystemOptix::ChVisualSystemOptix(ChSystem& sys) : ChVisualSystem(sys), m_verbose(false), m_optix_reflections(9) { // save the chrono system handle scene = chrono_types::make_shared(); m_device_list = {0}; @@ -83,8 +82,7 @@ void ChVisualSystemOptix::AddSensor(std::shared_ptr sensor) { // add the sensor to an engine with sensor of similar update frequencies for (auto engine : m_engines) { - if (!found_engine && engine->GetSensor().size() > 0 && - abs(engine->GetSensor()[0]->GetUpdateRate() - sensor->GetUpdateRate()) < 0.001) { + if (!found_engine && engine->GetSensor().size() > 0 && abs(engine->GetSensor()[0]->GetUpdateRate() - sensor->GetUpdateRate()) < 0.001) { found_engine = true; engine->AssignSensor(pOptixSensor); if (m_verbose) @@ -96,9 +94,12 @@ void ChVisualSystemOptix::AddSensor(std::shared_ptr sensor) { // create new engines only when we need them if (!found_engine) { if (m_engines.size() < m_allowable_groups) { - auto engine = chrono_types::make_shared( - m_system, m_device_list[(int)m_engines.size()], m_optix_reflections, - m_verbose); // limits to 2 gpus, TODO: check if device supports cuda + auto engine = chrono_types::make_shared(m_system, m_device_list[(int)m_engines.size()], m_optix_reflections, + m_verbose); // limits to 2 gpus, TODO: check if device supports cuda + +#ifdef CHRONO_FSI_SPH + engine->SetFsiSphSources(&scene->GetFsiSphSources()); +#endif // engine->ConstructScene(); engine->AssignSensor(pOptixSensor); diff --git a/src/chrono_sensor/optix/scene/ChScene.h b/src/chrono_sensor/optix/scene/ChScene.h index 494f08d9e2..28f553aa30 100644 --- a/src/chrono_sensor/optix/scene/ChScene.h +++ b/src/chrono_sensor/optix/scene/ChScene.h @@ -32,19 +32,23 @@ // #include #include +#include + #include "chrono/physics/ChBody.h" #include "chrono/assets/ChColor.h" #include "chrono_sensor/ChApiSensor.h" +#ifdef CHRONO_FSI_SPH + #include "chrono_sensor/ChFsiSphRender.h" +#endif #include "chrono_sensor/optix/ChOptixDefinitions.h" #include "chrono_sensor/optix/ChOptixUtils.h" #include "chrono_sensor/optix/shaders/ChOptixLightStructs.h" #ifdef USE_SENSOR_NVDB - #include + #include #endif - namespace chrono { namespace sensor { @@ -54,10 +58,10 @@ namespace sensor { /// Information about the background of the scene. Determines the color, gradient, or image that is spherically mapped /// to camera ray misses struct Background { - BackgroundMode mode; ///< 0=solid zenith color, 1=gradient, 2=environment map + BackgroundMode mode; ///< 0=solid zenith color, 1=gradient, 2=environment map ChVector3f color_zenith; ///< color at zenith ChVector3f color_horizon; ///< color at horizon (for gradient) - std::string env_tex; ///< full path name of the texture + std::string env_tex; ///< full path name of the texture }; /// Scene class used for camera renderings. Includes environment colors, lights, etc @@ -93,7 +97,6 @@ class CH_SENSOR_API ChScene { /// @param directional_light the new directional light void ModifyDirectionalLight(unsigned int light_ID, const ChOptixLight& directional_light); - /// @brief Add a spot light that emits light in a particular direction. /// @param pos the world position of the spot light /// @param color color radiance of the light @@ -104,15 +107,13 @@ class CH_SENSOR_API ChScene { /// @param angle_range [rad], angle range of the spotlight falling off to zero. /// @param const_color whether to use constant color (no attenuation with distance) /// @return the index of the light that has been added - unsigned int AddSpotLight( - ChVector3f pos, ChColor color, float max_range, ChVector3f light_dir, float angle_falloff_start, float angle_range, bool const_color = true - ); + unsigned int AddSpotLight(ChVector3f pos, ChColor color, float max_range, ChVector3f light_dir, float angle_falloff_start, float angle_range, bool const_color = true); /// @brief Function for modifying an existing spot light in the scene /// @param light_ID the index of the spot light to be modified /// @param spot_light the new spot light void ModifySpotLight(unsigned int light_ID, const ChOptixLight& spot_light); - + /// @brief Add a rectangle light that emits light forward from a rectangle area. /// @param pos [m], the world position of the rectangle light /// @param color [W/m^2] or [lumen/m^2], color radiance of the light @@ -122,9 +123,7 @@ class CH_SENSOR_API ChScene { /// @param width_vec [m], the other edge vector of the rectangle light perpendicular to `length_vec`. Light direction is: length_vec x width_vec. /// @param const_color whether to use constant color (no attenuation with distance) /// @return the index of the added light - unsigned int AddRectangleLight( - ChVector3f pos, ChColor color, float max_range, ChVector3f length_vec, ChVector3f width_vec, bool const_color = true - ); + unsigned int AddRectangleLight(ChVector3f pos, ChColor color, float max_range, ChVector3f length_vec, ChVector3f width_vec, bool const_color = true); /// @brief Function for modifying an existing rectangle light in the scene /// @param light_ID the index of the rectangle light to be modified @@ -140,15 +139,13 @@ class CH_SENSOR_API ChScene { /// @param radius [m], radius of the disk light /// @param const_color whether to use constant color (no attenuation with distance) /// @return the index of the added light - unsigned int AddDiskLight( - ChVector3f pos, ChColor color, float max_range, ChVector3f light_dir, float radius, bool const_color = true - ); + unsigned int AddDiskLight(ChVector3f pos, ChColor color, float max_range, ChVector3f light_dir, float radius, bool const_color = true); /// @brief Function for modifying an existing disk light in the scene /// @param light_ID the index of the disk light to be modified /// @param disk_light the new disk light void ModifyDiskLight(unsigned int light_ID, const ChOptixLight& disk_light); - + /// @brief Add the environment light that emits light from all directions based on an environment map. /// @param env_tex_path the full path of the environment map texture. /// @param intensity_scale a scale factor for the intensity of the environment light. Default value is 1.0 (no scaling). @@ -157,7 +154,7 @@ class CH_SENSOR_API ChScene { /// Function for gaining access to the vector of lights which can be used to modify lighting dynamically. /// @return A vector of lights in the scene currently - std::vector GetLights() {return m_lights;} + std::vector GetLights() { return m_lights; } /// Function for gaining access to the background. Can be used to dynamically change the background color, or /// texture @@ -212,12 +209,36 @@ class CH_SENSOR_API ChScene { float GetSceneEpsilon() { return m_scene_epsilon; } void AddSprite(std::shared_ptr sprite); - void SetSprites(std::vector> sprites) {m_sprites = sprites;} + void SetSprites(std::vector> sprites) { m_sprites = sprites; } std::shared_ptr GetSprite(int i) { return m_sprites[i]; } std::vector> GetSprites() { return m_sprites; } - #ifdef USE_SENSOR_NVDB +#ifdef CHRONO_FSI_SPH + /// Attach a native Chrono::FSI::SPH render source to this scene. + int AddFsiSphSystem(std::shared_ptr sys, const ChFsiSphRenderOptions& options) { + ChFsiSphRenderSource source; + source.id = m_next_fsi_sph_source_id++; + source.system = sys; + source.options = options; + m_fsi_sph_sources.push_back(source); + return source.id; + } + + /// Remove a native Chrono::FSI::SPH render source from this scene. + void RemoveFsiSphSystem(int id) { + m_fsi_sph_sources.erase(std::remove_if(m_fsi_sph_sources.begin(), m_fsi_sph_sources.end(), [id](const ChFsiSphRenderSource& source) { return source.id == id; }), + m_fsi_sph_sources.end()); + } + + /// Remove all native Chrono::FSI::SPH render sources from this scene. + void ClearFsiSphSystems() { m_fsi_sph_sources.clear(); } + + /// Return all native Chrono::FSI::SPH render sources attached to this scene. + const std::vector& GetFsiSphSources() const { return m_fsi_sph_sources; } +#endif + +#ifdef USE_SENSOR_NVDB /// @brief Allows passing in Chrono::FSI SPH markers to the scene, to be used for rendering SPH simulations. Note: Must also add a ChNVDBVolume body to the scene as well. /// @param fsi_points_d pointer to the FSI markers in host memory void SetFSIParticles(float* fsi_points) { m_fsi_points = fsi_points; } @@ -232,8 +253,8 @@ class CH_SENSOR_API ChScene { /// @brief Returns the number of Chrono::FSI, SPH markers in the scene /// @return the number of Chrono::FSI, SPH markers in the scene (int) - int GetNumFSIParticles() { return m_num_fsi_points;} - #endif + int GetNumFSIParticles() { return m_num_fsi_points; } +#endif /// Function to change the origin offset if necessary /// @param sensor_pos the position of the sensor @@ -263,9 +284,9 @@ class CH_SENSOR_API ChScene { // int GetGVDBChan() { return m_gvdb_chan; } private: - std::vector m_lights; //< list of all lights in the scene - Background m_background; ///< The background object - ChVector3f m_ambient_light; ///< ambient light color used in the scene + std::vector m_lights; //< list of all lights in the scene + Background m_background; ///< The background object + ChVector3f m_ambient_light; ///< ambient light color used in the scene bool lights_changed; ///< for detecting if lights changed bool background_changed; ///< for detecting if background changed @@ -274,20 +295,25 @@ class CH_SENSOR_API ChScene { bool m_dynamic_origin_offset; ///< whether to dynamically change the scene origin when sensors are outside of ///< threshold float m_dynamic_origin_threshold; ///< threshold to prompt moving the origin - ChVector3f m_origin_offset; ///< scene origin offset from Chrono + ChVector3f m_origin_offset; ///< scene origin offset from Chrono bool m_origin_changed; ///< whether the origin changed since last reset - float m_fog_scattering; ///< scattering coefficient of fog in the scene + float m_fog_scattering; ///< scattering coefficient of fog in the scene ChVector3f m_fog_color; ///< color of the fog in the scene std::vector> m_sprites; ///< list of sprites in the scene // nvdb::VolumeGVDB* m_gvdb; // GVDB volume of the scene // int m_gvdb_chan; // GVDB render channel - #ifdef USE_SENSOR_NVDB - float* m_fsi_points = nullptr; // Pointer to FSI particle positions in host - int m_num_fsi_points = 0; // Number of FSI particles - #endif +#ifdef CHRONO_FSI_SPH + std::vector m_fsi_sph_sources; ///< native FSI-SPH render sources + int m_next_fsi_sph_source_id = 0; ///< id generator for native FSI-SPH sources +#endif + +#ifdef USE_SENSOR_NVDB + float* m_fsi_points = nullptr; // Pointer to FSI particle positions in host + int m_num_fsi_points = 0; // Number of FSI particles +#endif }; /// @} sensor_scene diff --git a/src/demos/sensor/CMakeLists.txt b/src/demos/sensor/CMakeLists.txt index 374de399a3..8ea427f4bb 100644 --- a/src/demos/sensor/CMakeLists.txt +++ b/src/demos/sensor/CMakeLists.txt @@ -27,6 +27,12 @@ if(CH_USE_SENSOR_OPTIX) demo_SEN_deformableSoil ) endif() + + if(CH_ENABLE_MODULE_FSI_SPH) + set(DEMOS ${DEMOS} + demo_SEN_CRM_Rendering + ) + endif() endif() @@ -34,6 +40,7 @@ endif() # Include directories, compiler flags, libraries list(APPEND LIBRARIES Chrono_core) +list(APPEND LIBRARIES "ChronoModels_robot") list(APPEND LIBRARIES "Chrono_sensor") if(CH_ENABLE_MODULE_IRRLICHT) @@ -50,6 +57,16 @@ if(CH_ENABLE_MODULE_VEHICLE) endif() endif() +if(CH_ENABLE_MODULE_VSG) + list(APPEND LIBRARIES "Chrono_vsg") + if(CH_ENABLE_MODULE_VEHICLE) + list(APPEND LIBRARIES "Chrono_vehicle_vsg") + endif() + if(CH_ENABLE_MODULE_FSI_SPH) + list(APPEND LIBRARIES "Chrono_fsisph_vsg") + endif() +endif() + #-------------------------------------------------------------- # Add executables diff --git a/src/demos/sensor/demo_SEN_CRM_Rendering.cpp b/src/demos/sensor/demo_SEN_CRM_Rendering.cpp new file mode 100644 index 0000000000..ee1b6ce29a --- /dev/null +++ b/src/demos/sensor/demo_SEN_CRM_Rendering.cpp @@ -0,0 +1,332 @@ +// ============================================================================= +// PROJECT CHRONO - http://projectchrono.org +// +// Copyright (c) 2026 projectchrono.org +// All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file at the top level of the distribution and at +// http://projectchrono.org/license-chrono.txt. +// +// ============================================================================= +// Author: Bocheng Zou, Radu Serban +// ============================================================================= +// +// Viper rover on CRM terrain (initialized from heightmap image) with sensor +// +// ============================================================================= + +#include "chrono/physics/ChSystemNSC.h" +#include "chrono/physics/ChSystemSMC.h" +#include "chrono/input_output/ChWriterCSV.h" +#include "chrono/assets/ChVisualSystem.h" + +#include "chrono_fsi/sph/ChFsiSystemSPH.h" + +#include "chrono_vehicle/ChVehicleDataPath.h" +#include "chrono_models/robot/viper/Viper.h" + +#include "chrono_vehicle/terrain/CRMTerrain.h" + +#include "chrono/utils/ChUtilsCreators.h" +#include "chrono/utils/ChUtilsGenerators.h" +#include "chrono/utils/ChUtilsGeometry.h" +#include "chrono/physics/ChBodyEasy.h" +#include "chrono/physics/ChMassProperties.h" +#include "chrono/geometry/ChTriangleMeshConnected.h" + +#include "chrono_fsi/sph/visualization/ChSphVisualizationVSG.h" + +#include "chrono_sensor/ChFsiSphRender.h" +#include "chrono_sensor/ChSensorManager.h" +#include "chrono_sensor/sensors/ChCameraSensor.h" +#include "chrono_sensor/filters/ChFilterAccess.h" +#include "chrono_sensor/filters/ChFilterVisualize.h" + +using namespace chrono; +using namespace chrono::fsi; +using namespace chrono::fsi::sph; +using namespace chrono::viper; +using namespace chrono::vehicle; +using namespace chrono::sensor; + +using std::cout; +using std::cin; +using std::endl; + +// =================================================================================================================== + +// CRM terrain patch type +enum class PatchType { RECTANGULAR, HEIGHT_MAP }; +PatchType patch_type = PatchType::HEIGHT_MAP; + +// Terrain dimensions (for RECTANGULAR or HEIGHT_MAP patch type) +double terrain_length = 12; +double terrain_width = 3; + +int num_meshes = 3; +std::vector> regolith_meshes; // ChVisualShapeTriangleMesh + +int main(int argc, char* argv[]) { + double density = 100; + double cohesion = 5e3; + double friction = 0.7; + double youngs_modulus = 0.5e5; + double poisson_ratio = 0.3; + + double tend = 30; + double step_size = 5e-4; + ChVector3d active_box_dim(5.0, 5.0, 5.0); + + bool render = true; // use run-time visualization + double render_fps = 200; // rendering FPS + + bool visualization_sph = true; // render SPH particles + bool visualization_bndry_bce = false; // render boundary BCE markers + bool visualization_rigid_bce = false; // render wheel BCE markers + + bool verbose = true; + + // Create the Chrono system and associated collision system + ChSystemNSC sys; + sys.SetCollisionSystemType(ChCollisionSystem::Type::BULLET); + + // Create rover + cout << "Create rover..." << endl; + ViperWheelType wheel_type = ViperWheelType::RealWheel; + ChContactMaterialData wheel_mat(0.4f, // mu + 0.2f, // cr + 2e7f, // Y + 0.3f, // nu + 2e5f, // kn + 40.0f, // gn + 2e5f, // kt + 20.0f // gt + ); + ChVector3d init_loc(1.25, 0.0, 0.55); + + auto driver = chrono_types::make_shared(); + auto rover = chrono_types::make_shared(&sys, wheel_type); + rover->SetDriver(driver); + rover->SetWheelContactMaterial(wheel_mat.CreateMaterial(sys.GetContactMethod())); + rover->Initialize(ChFrame<>(init_loc, QUNIT)); + + // Create the CRM terrain system + double initial_spacing = 0.02; + CRMTerrain terrain(sys, initial_spacing); + auto sysFSI = terrain.GetFsiSystemSPH(); + auto sysSPH = terrain.GetFluidSystemSPH(); + sysSPH->EnableCudaErrorCheck(false); + terrain.SetVerbose(verbose); + terrain.SetGravitationalAcceleration(ChVector3d(0, 0, -9.81)); + terrain.SetStepSizeCFD(step_size); + + ChFsiFluidSystemSPH::ElasticMaterialProperties mat_props; + mat_props.Young_modulus = youngs_modulus; + mat_props.Poisson_ratio = poisson_ratio; + mat_props.mu_I0 = 0.04; + mat_props.mu_fric_s = friction; + mat_props.mu_fric_2 = friction; + mat_props.average_diam = 0.005; + mat_props.cohesion_coeff = cohesion; + terrain.SetElasticSPH(mat_props); + + ChFsiFluidSystemSPH::SPHParameters sph_params; + sph_params.integration_scheme = IntegrationScheme::RK2; + sph_params.initial_spacing = initial_spacing; + sph_params.d0_multiplier = 1.3; + sph_params.free_surface_threshold = 2.0; + sph_params.artificial_viscosity = 0.5; + sph_params.use_consistent_gradient_discretization = false; + sph_params.use_consistent_laplacian_discretization = false; + sph_params.viscosity_method = ViscosityMethod::ARTIFICIAL_BILATERAL; + sph_params.boundary_method = BoundaryMethod::ADAMI; + sph_params.use_variable_time_step = true; // This makes the step size irrelevant - now we just make sure we are + // within the max of exchange_info (meta step) + terrain.SetSPHParameters(sph_params); + sysSPH->SetDensity(density); + + // Set output level from SPH simulation + terrain.SetOutputLevel(OutputLevel::STATE); + + // Add rover wheels as FSI bodies + cout << "Create wheel BCE markers..." << endl; + std::string mesh_filename = GetChronoDataFile("robot/viper/obj/viper_cylwheel.obj"); + auto geometry = chrono_types::make_shared(); + geometry->materials.push_back(ChContactMaterialData()); + geometry->coll_meshes.push_back(utils::ChBodyGeometry::TrimeshShape(VNULL, QUNIT, mesh_filename, VNULL)); + + //// TODO: FIX ChFsiProblemSPH to allow rotating geometry on body!! + for (int i = 0; i < 4; i++) { + auto wheel_body = rover->GetWheels()[i]->GetBody(); + auto yaw = (i % 2 == 0) ? QuatFromAngleZ(CH_PI) : QUNIT; + terrain.AddRigidBody(wheel_body, geometry, false); + } + + terrain.SetActiveDomain(active_box_dim); + + // Construct the terrain + cout << "Create terrain..." << endl; + switch (patch_type) { + case PatchType::RECTANGULAR: + // Create a rectangular terrain patch + terrain.Construct({terrain_length, terrain_width, 0.25}, // length X width X height + ChVector3d(terrain_length / 2, 0, 0), // patch center + BoxSide::ALL & ~BoxSide::Z_POS // all boundaries, except top + ); + break; + case PatchType::HEIGHT_MAP: + // Create a patch from a height field map image + terrain.Construct(GetVehicleDataFile("terrain/height_maps/bump64.bmp"), // height map image file + terrain_length, terrain_width, // length (X) and width (Y) + {0.25, 0.55}, // height range + 0.25, // depth + true, // uniform depth + ChVector3d(terrain_length / 2, 0, 0), // patch center + BoxSide::Z_NEG // bottom wall + ); + break; + } + + // Initialize the terrain system + terrain.Initialize(); + + auto aabb = terrain.GetSPHBoundingBox(); + cout << " SPH particles: " << terrain.GetNumSPHParticles() << endl; + cout << " Bndry BCE markers: " << terrain.GetNumBoundaryBCEMarkers() << endl; + cout << " SPH AABB: " << aabb.min << " " << aabb.max << endl; + + // Create run-time visualization + std::shared_ptr vis; + if (render) { + // FSI plugin + auto col_callback = chrono_types::make_shared(aabb.min.z(), aabb.max.z()); + + auto visFSI = chrono_types::make_shared(sysFSI.get()); + visFSI->EnableFluidMarkers(visualization_sph); + visFSI->EnableBoundaryMarkers(visualization_bndry_bce); + visFSI->EnableRigidBodyMarkers(visualization_rigid_bce); + visFSI->SetSPHColorCallback(col_callback, ChColormap::Type::BROWN); + + // VSG visual system (attach visFSI as plugin) + auto visVSG = chrono_types::make_shared(); + visVSG->AttachPlugin(visFSI); + visVSG->AttachSystem(&sys); + visVSG->SetWindowTitle("Viper rover on CRM deformable terrain"); + visVSG->SetWindowSize(1280, 800); + visVSG->SetWindowPosition(100, 100); + visVSG->AddCamera(init_loc + ChVector3d(0, 6, 0.5), init_loc); + visVSG->SetLightIntensity(0.9f); + + visVSG->Initialize(); + vis = visVSG; + } + + // Load regolith meshes + std::string mesh_name_prefix = "models/regolith/particle_"; + for (int i = 1; i <= num_meshes; i++) { + auto mmesh = ChTriangleMeshConnected::CreateFromWavefrontFile(GetChronoDataFile(mesh_name_prefix + std::to_string(i) + ".obj"), false, true); + mmesh->Transform(ChVector3d(0, 0, 0), ChMatrix33<>(1)); // scale to a different size + auto trimesh_shape = std::make_shared(); + trimesh_shape->SetMesh(mmesh); + // std::cout << "OK1" << std::endl; + trimesh_shape->SetName("RegolithMesh" + std::to_string(i)); + trimesh_shape->SetMutable(false); + regolith_meshes.push_back(trimesh_shape); + } + + auto regolith_material = chrono_types::make_shared(); + regolith_material->SetAmbientColor({1, 1, 1}); // 0.65f,0.65f,0.65f + regolith_material->SetDiffuseColor({1, 1, 1}); // 0.29f, 0.29f, 0.235f + regolith_material->SetSpecularColor({1, 1, 1}); + regolith_material->SetUseSpecularWorkflow(true); + regolith_material->SetRoughness(1.0f); + // regolith_material->SetBSDF((unsigned int)BSDFType::HAPKE); + regolith_material->SetHapkeParameters(0.32357f, 0.23955f, 0.30452f, 1.80238f, 0.07145f, 0.3f, 23.4f * (CH_PI / 180)); + regolith_material->SetClassID(30000); + regolith_material->SetInstanceID(20000); + for (auto& mesh : regolith_meshes) { + if (mesh->GetNumMaterials() == 0) { + mesh->AddMaterial(regolith_material); + } else { + mesh->GetMaterials()[0] = regolith_material; + } + } + + float intensity = 1.0; + auto manager = chrono_types::make_shared(&sys); + manager->scene->AddPointLight({0.5, 1, 1}, {intensity, intensity, intensity}, 500); + manager->scene->SetAmbientLight({.1, .1, .1}); + manager->SetVerbose(false); + manager->SetRayRecursions(4); + + ChFsiSphRenderOptions fsi_render_options; + fsi_render_options.sprite_shapes.reserve(regolith_meshes.size()); + for (const auto& mesh : regolith_meshes) + fsi_render_options.sprite_shapes.push_back(mesh); + fsi_render_options.sprite_position_jitter = ChVector3f(0.005f, 0.005f, 0.f); + fsi_render_options.render_particle_spacing = 0.01f; + manager->AttachFsiSphSystem(sysSPH, fsi_render_options); + + auto floor = chrono_types::make_shared(1, 1, 1, 1000, false, false); + floor->SetPos({0, 0, 0}); + floor->SetFixed(true); + sys.Add(floor); + + chrono::ChFrame offset_pose1({0.5, 1, 1}, QuatFromAngleAxis(-CH_PI_2, {0, 0, 1})); // Q_from_AngAxis(CH_PI_4, {0, 1, 0}) //-1200, -252, 100 + chrono::ChFrame rot = chrono::ChFrame(ChVector3d(0, 0, 0), QuatFromAngleAxis(60.0f / 180.0f * CH_PI, {0, 1, 0})); + + auto cam = chrono_types::make_shared(floor, // body camera is attached to + render_fps, // update rate in Hz + offset_pose1 * rot, // offset pose + 1280, // image width + 720, // image height + 1.5707963267948966, // camera's horizontal field of view + 1, // super sampling factor + CameraLensModelType::PINHOLE, // lens model type + false); + cam->PushFilter(chrono_types::make_shared(1280, 720, "Third Person Camera")); + + manager->AddSensor(cam); + + // Start the simulation + double time = 0; + int sim_frame = 0; + int render_frame = 0; + double exchange_info = 5 * step_size; + while (time < tend) { + rover->Update(); + + // Run-time visualization + if (render && time >= render_frame / render_fps) { + if (!vis->Run()) + break; + vis->Render(); + render_frame++; + } + if (!render) { + std::cout << time << " " << terrain.GetRtfCFD() << " " << terrain.GetRtfMBD() << std::endl; + } + + // Advance dynamics of multibody and fluid systems concurrently + terrain.DoStepDynamics(exchange_info); + if (time > 0) { + manager->Update(); + } + + time += exchange_info; + sim_frame++; + } + std::cout << "Saving data..." << std::endl; + sysSPH->SaveParticleData("particle_data"); + + terrain.PrintStats(); + std::string out_dir = GetChronoOutputPath() + "ROBOT_Viper_CRM/"; + if (!std::filesystem::create_directory(std::filesystem::path(out_dir))) { + std::cerr << "Error creating directory " << out_dir << std::endl; + return 1; + } + terrain.PrintTimeSteps(out_dir + "time_steps.txt"); + + return 0; +}