I was using particle systems in Isaac Sim 2022.2.0, where I spawn liquid inside a beaker. I used OmniSurface_ClearWater material for the liquid, but when the liquid was spawned, each particle within the liquid is visible, even though I have the isosurface api, particle anisotropy api, and particle smooting api. However, when I pause the simulation, the individual particles are no longer visible. This seems to happen with certain materials, but not all materials. Here is the code I used to configure the fluid.
def create_new_pbd_material(target_path: str, color_rgb: Tuple) → Sdf.Path:
stage = stage_utils.get_current_stage()
# create material for extras
create_list = []
omni.kit.commands.execute(
"CreateAndBindMdlMaterialFromLibrary",
mdl_name="OmniSurfacePresets.mdl",
mtl_name="OmniSurface_ClearWater",
mtl_created_list=create_list,
)
# target_path = "/World/Looks/" + mat_name
if create_list[0] != target_path:
omni.kit.commands.execute("MovePrims", paths_to_move={create_list[0]: target_path})
shader = UsdShade.Shader.Get(stage, target_path + "/Shader")
shader.CreateInput("specular_transmission_color", Sdf.ValueTypeNames.Color3f).Set(color_rgb)
shader.CreateInput("diffuse_color_constant", Sdf.ValueTypeNames.Color3f).Set(color_rgb)
shader.CreateInput("diffuse_reflection_color", Sdf.ValueTypeNames.Color3f).Set(color_rgb)
return Sdf.Path(target_path)
class Fluid():
def __init__(self, name, cfg):
self.name = name
self.cfg = cfg
def create(self, stage, scenePath, prim_path):
self.stage = stage
self.scenePath = scenePath
self.prim_path = prim_path
# Create particle system
self.particle_system_path = Sdf.Path(self.prim_path + f"/particleSystem_{self.name}")
particle_system = PhysxSchema.PhysxParticleSystem.Define(stage, self.particle_system_path)
particle_system.CreateSimulationOwnerRel().SetTargets([scenePath])
# Use a smaller particle size for nicer fluid, and let the sim figure out the other offsets
self.particle_contact_offset = 0.004 # in meters
particle_system.CreateParticleContactOffsetAttr().Set(self.particle_contact_offset)
# Limit particle velocity for better collision detection
particle_system.CreateMaxVelocityAttr().Set(1.0)
# Create render material
self.material_prim_path = self.prim_path + "/OmniPBR"
self.material_path1 = create_new_pbd_material(self.prim_path + "/OmniPBR", color_rgb=self.cfg.color_rgb)
# create material and assign it to the system:
# the isosurface uses the render material assigned to the particle system, so add
# particle material to the render material created earlier
particleUtils.add_pbd_particle_material(
stage,
self.material_path1,
cohesion=0.01,
viscosity=0.0091,
surface_tension=0.0074,
friction=0.1,
)
omni.kit.commands.execute(
"BindMaterialCommand",
prim_path=stage.GetPrimAtPath(self.particle_system_path).GetPath(),
material_path=self.material_path1,
strength=None,
)
size = self.cfg.volume
lower = (0.0, 0.0, 0.0)
# use particle fluid restoffset to create a particle grid, using same formula as simulation, see
# https://docs.omniverse.nvidia.com/prod_extensions/prod_extensions/ext_physics.html#offset-autocomputation
particle_fluid_restoffset = 0.99 * 0.6 * self.particle_contact_offset
particleSpacing = 2.0 * particle_fluid_restoffset
num_samples = round(size / particleSpacing) + 1
# assert False
self.positions, self.velocities = particleUtils.create_particles_grid(
lower, particleSpacing, num_samples, num_samples, 11 * num_samples
)
density = 1000.0
mass = density * 1.333 * 3.14159 * particle_fluid_restoffset * particle_fluid_restoffset * particle_fluid_restoffset
self.particle_point_instancer_path = Sdf.Path(self.prim_path + "/particles")
# self.particle_point_instancer_paths.append(self.particle_point_instancer_path)
self.instancer = particleUtils.add_physx_particleset_pointinstancer(
stage,
self.particle_point_instancer_path,
Vt.Vec3fArray(self.positions),
Vt.Vec3fArray(self.velocities),
self.particle_system_path,
self_collision=True,
fluid=True,
particle_group=0,
particle_mass=mass,
density=density,
)
# apply api and use all defaults
smoothingAPI = PhysxSchema.PhysxParticleSmoothingAPI.Apply(particle_system.GetPrim())
smoothingAPI.CreateParticleSmoothingEnabledAttr().Set(True)
smoothingAPI.CreateStrengthAttr().Set(0.5)
# apply api and use all defaults
isosurfaceAPI = PhysxSchema.PhysxParticleIsosurfaceAPI.Apply(particle_system.GetPrim())
isosurfaceAPI.CreateIsosurfaceEnabledAttr().Set(True)
isosurfaceAPI.CreateMaxVerticesAttr().Set(1024 * 1024)
isosurfaceAPI.CreateMaxTrianglesAttr().Set(2 * 1024 * 1024)
isosurfaceAPI.CreateMaxSubgridsAttr().Set(1024 * 4)
isosurfaceAPI.CreateGridSpacingAttr().Set(particle_fluid_restoffset * 1.5)
isosurfaceAPI.CreateSurfaceDistanceAttr().Set(particle_fluid_restoffset * 1.6)
isosurfaceAPI.CreateGridFilteringPassesAttr().Set("")
isosurfaceAPI.CreateGridSmoothingRadiusAttr().Set(particle_fluid_restoffset * 2)
isosurfaceAPI.CreateNumMeshSmoothingPassesAttr().Set(1)
# tweak anisotropy min, max, and scale to work better with isosurface:
ani_api = PhysxSchema.PhysxParticleAnisotropyAPI.Apply(particle_system.GetPrim())
ani_api.CreateScaleAttr().Set(5.0)
ani_api.CreateMinAttr().Set(1.0) # avoids gaps in surface
ani_api.CreateMaxAttr().Set(2.0)
# get and config sphere prototype:
particle_prototype_sphere = UsdGeom.Sphere.Get(
stage, self.particle_point_instancer_path.AppendChild("particlePrototype0")
)
particle_prototype_sphere.CreateRadiusAttr().Set(particle_fluid_restoffset)
# material_path = create_pbd_material(template_env_ns + "/OmniPBR1", color_rgb=Gf.Vec3f(0.8, 0.2, 0.2))
particleUtils.add_pbd_particle_material(stage, self.material_path1)
omni.kit.commands.execute(
"BindMaterialCommand",
prim_path=particle_prototype_sphere.GetPath(),
material_path=self.material_path1,
strength=None,
)
self.particle_system_view = ParticleSystemView(self.prim_path + f"/particleSystem_{self.name}")
point_instancer = UsdGeom.PointInstancer.Get(self.stage, self.particle_point_instancer_path)
physicsUtils.set_or_add_translate_op(point_instancer, translate=self.cfg.pos)
def change_material(self):
# prims_utils.delete_prim(self.prim_path + "/OmniPBR")
# Create render material
self.material_prim_path = self.prim_path + "/OmniPBR1"
omni.kit.commands.execute(
"BindMaterialCommand",
prim_path=self.stage.GetPrimAtPath(self.particle_system_path).GetPath(),
material_path=self.material_path2,
strength=None,
)