warp-lang 1.0.2__py3-none-macosx_10_13_universal2.whl → 1.1.0__py3-none-macosx_10_13_universal2.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of warp-lang might be problematic. Click here for more details.
- warp/__init__.py +108 -97
- warp/__init__.pyi +1 -1
- warp/bin/libwarp-clang.dylib +0 -0
- warp/bin/libwarp.dylib +0 -0
- warp/build.py +115 -113
- warp/build_dll.py +383 -375
- warp/builtins.py +3425 -3354
- warp/codegen.py +2878 -2792
- warp/config.py +40 -36
- warp/constants.py +45 -45
- warp/context.py +5194 -5102
- warp/dlpack.py +442 -442
- warp/examples/__init__.py +16 -16
- warp/examples/assets/bear.usd +0 -0
- warp/examples/assets/bunny.usd +0 -0
- warp/examples/assets/cartpole.urdf +110 -110
- warp/examples/assets/crazyflie.usd +0 -0
- warp/examples/assets/cube.usd +0 -0
- warp/examples/assets/nv_ant.xml +92 -92
- warp/examples/assets/nv_humanoid.xml +183 -183
- warp/examples/assets/quadruped.urdf +267 -267
- warp/examples/assets/rocks.nvdb +0 -0
- warp/examples/assets/rocks.usd +0 -0
- warp/examples/assets/sphere.usd +0 -0
- warp/examples/benchmarks/benchmark_api.py +383 -383
- warp/examples/benchmarks/benchmark_cloth.py +278 -277
- warp/examples/benchmarks/benchmark_cloth_cupy.py +88 -88
- warp/examples/benchmarks/benchmark_cloth_jax.py +97 -100
- warp/examples/benchmarks/benchmark_cloth_numba.py +146 -142
- warp/examples/benchmarks/benchmark_cloth_numpy.py +77 -77
- warp/examples/benchmarks/benchmark_cloth_pytorch.py +86 -86
- warp/examples/benchmarks/benchmark_cloth_taichi.py +112 -112
- warp/examples/benchmarks/benchmark_cloth_warp.py +146 -146
- warp/examples/benchmarks/benchmark_launches.py +295 -295
- warp/examples/browse.py +29 -29
- warp/examples/core/example_dem.py +234 -219
- warp/examples/core/example_fluid.py +293 -267
- warp/examples/core/example_graph_capture.py +144 -126
- warp/examples/core/example_marching_cubes.py +188 -174
- warp/examples/core/example_mesh.py +174 -155
- warp/examples/core/example_mesh_intersect.py +205 -193
- warp/examples/core/example_nvdb.py +176 -170
- warp/examples/core/example_raycast.py +105 -90
- warp/examples/core/example_raymarch.py +199 -178
- warp/examples/core/example_render_opengl.py +185 -141
- warp/examples/core/example_sph.py +405 -387
- warp/examples/core/example_torch.py +222 -181
- warp/examples/core/example_wave.py +263 -248
- warp/examples/fem/bsr_utils.py +378 -380
- warp/examples/fem/example_apic_fluid.py +407 -389
- warp/examples/fem/example_convection_diffusion.py +182 -168
- warp/examples/fem/example_convection_diffusion_dg.py +219 -209
- warp/examples/fem/example_convection_diffusion_dg0.py +204 -194
- warp/examples/fem/example_deformed_geometry.py +177 -159
- warp/examples/fem/example_diffusion.py +201 -173
- warp/examples/fem/example_diffusion_3d.py +177 -152
- warp/examples/fem/example_diffusion_mgpu.py +221 -214
- warp/examples/fem/example_mixed_elasticity.py +244 -222
- warp/examples/fem/example_navier_stokes.py +259 -243
- warp/examples/fem/example_stokes.py +220 -192
- warp/examples/fem/example_stokes_transfer.py +265 -249
- warp/examples/fem/mesh_utils.py +133 -109
- warp/examples/fem/plot_utils.py +292 -287
- warp/examples/optim/example_bounce.py +260 -246
- warp/examples/optim/example_cloth_throw.py +222 -209
- warp/examples/optim/example_diffray.py +566 -536
- warp/examples/optim/example_drone.py +864 -835
- warp/examples/optim/example_inverse_kinematics.py +176 -168
- warp/examples/optim/example_inverse_kinematics_torch.py +185 -169
- warp/examples/optim/example_spring_cage.py +239 -231
- warp/examples/optim/example_trajectory.py +223 -199
- warp/examples/optim/example_walker.py +306 -293
- warp/examples/sim/example_cartpole.py +139 -129
- warp/examples/sim/example_cloth.py +196 -186
- warp/examples/sim/example_granular.py +124 -111
- warp/examples/sim/example_granular_collision_sdf.py +197 -186
- warp/examples/sim/example_jacobian_ik.py +236 -214
- warp/examples/sim/example_particle_chain.py +118 -105
- warp/examples/sim/example_quadruped.py +193 -180
- warp/examples/sim/example_rigid_chain.py +197 -187
- warp/examples/sim/example_rigid_contact.py +189 -177
- warp/examples/sim/example_rigid_force.py +127 -125
- warp/examples/sim/example_rigid_gyroscopic.py +109 -95
- warp/examples/sim/example_rigid_soft_contact.py +134 -122
- warp/examples/sim/example_soft_body.py +190 -177
- warp/fabric.py +337 -335
- warp/fem/__init__.py +60 -27
- warp/fem/cache.py +401 -388
- warp/fem/dirichlet.py +178 -179
- warp/fem/domain.py +262 -263
- warp/fem/field/__init__.py +100 -101
- warp/fem/field/field.py +148 -149
- warp/fem/field/nodal_field.py +298 -299
- warp/fem/field/restriction.py +22 -21
- warp/fem/field/test.py +180 -181
- warp/fem/field/trial.py +183 -183
- warp/fem/geometry/__init__.py +15 -19
- warp/fem/geometry/closest_point.py +69 -70
- warp/fem/geometry/deformed_geometry.py +270 -271
- warp/fem/geometry/element.py +744 -744
- warp/fem/geometry/geometry.py +184 -186
- warp/fem/geometry/grid_2d.py +380 -373
- warp/fem/geometry/grid_3d.py +441 -435
- warp/fem/geometry/hexmesh.py +953 -953
- warp/fem/geometry/partition.py +374 -376
- warp/fem/geometry/quadmesh_2d.py +532 -532
- warp/fem/geometry/tetmesh.py +840 -840
- warp/fem/geometry/trimesh_2d.py +577 -577
- warp/fem/integrate.py +1630 -1615
- warp/fem/operator.py +190 -191
- warp/fem/polynomial.py +214 -213
- warp/fem/quadrature/__init__.py +2 -2
- warp/fem/quadrature/pic_quadrature.py +243 -245
- warp/fem/quadrature/quadrature.py +295 -294
- warp/fem/space/__init__.py +294 -292
- warp/fem/space/basis_space.py +488 -489
- warp/fem/space/collocated_function_space.py +100 -105
- warp/fem/space/dof_mapper.py +236 -236
- warp/fem/space/function_space.py +148 -145
- warp/fem/space/grid_2d_function_space.py +267 -267
- warp/fem/space/grid_3d_function_space.py +305 -306
- warp/fem/space/hexmesh_function_space.py +350 -352
- warp/fem/space/partition.py +350 -350
- warp/fem/space/quadmesh_2d_function_space.py +368 -369
- warp/fem/space/restriction.py +158 -160
- warp/fem/space/shape/__init__.py +13 -15
- warp/fem/space/shape/cube_shape_function.py +738 -738
- warp/fem/space/shape/shape_function.py +102 -103
- warp/fem/space/shape/square_shape_function.py +611 -611
- warp/fem/space/shape/tet_shape_function.py +565 -567
- warp/fem/space/shape/triangle_shape_function.py +429 -429
- warp/fem/space/tetmesh_function_space.py +294 -292
- warp/fem/space/topology.py +297 -295
- warp/fem/space/trimesh_2d_function_space.py +223 -221
- warp/fem/types.py +77 -77
- warp/fem/utils.py +495 -495
- warp/jax.py +166 -141
- warp/jax_experimental.py +341 -339
- warp/native/array.h +1072 -1025
- warp/native/builtin.h +1560 -1560
- warp/native/bvh.cpp +398 -398
- warp/native/bvh.cu +525 -525
- warp/native/bvh.h +429 -429
- warp/native/clang/clang.cpp +495 -464
- warp/native/crt.cpp +31 -31
- warp/native/crt.h +334 -334
- warp/native/cuda_crt.h +1049 -1049
- warp/native/cuda_util.cpp +549 -540
- warp/native/cuda_util.h +288 -203
- warp/native/cutlass_gemm.cpp +34 -34
- warp/native/cutlass_gemm.cu +372 -372
- warp/native/error.cpp +66 -66
- warp/native/error.h +27 -27
- warp/native/fabric.h +228 -228
- warp/native/hashgrid.cpp +301 -278
- warp/native/hashgrid.cu +78 -77
- warp/native/hashgrid.h +227 -227
- warp/native/initializer_array.h +32 -32
- warp/native/intersect.h +1204 -1204
- warp/native/intersect_adj.h +365 -365
- warp/native/intersect_tri.h +322 -322
- warp/native/marching.cpp +2 -2
- warp/native/marching.cu +497 -497
- warp/native/marching.h +2 -2
- warp/native/mat.h +1498 -1498
- warp/native/matnn.h +333 -333
- warp/native/mesh.cpp +203 -203
- warp/native/mesh.cu +293 -293
- warp/native/mesh.h +1887 -1887
- warp/native/nanovdb/NanoVDB.h +4782 -4782
- warp/native/nanovdb/PNanoVDB.h +2553 -2553
- warp/native/nanovdb/PNanoVDBWrite.h +294 -294
- warp/native/noise.h +850 -850
- warp/native/quat.h +1084 -1084
- warp/native/rand.h +299 -299
- warp/native/range.h +108 -108
- warp/native/reduce.cpp +156 -156
- warp/native/reduce.cu +348 -348
- warp/native/runlength_encode.cpp +61 -61
- warp/native/runlength_encode.cu +46 -46
- warp/native/scan.cpp +30 -30
- warp/native/scan.cu +36 -36
- warp/native/scan.h +7 -7
- warp/native/solid_angle.h +442 -442
- warp/native/sort.cpp +94 -94
- warp/native/sort.cu +97 -97
- warp/native/sort.h +14 -14
- warp/native/sparse.cpp +337 -337
- warp/native/sparse.cu +544 -544
- warp/native/spatial.h +630 -630
- warp/native/svd.h +562 -562
- warp/native/temp_buffer.h +30 -30
- warp/native/vec.h +1132 -1132
- warp/native/volume.cpp +297 -297
- warp/native/volume.cu +32 -32
- warp/native/volume.h +538 -538
- warp/native/volume_builder.cu +425 -425
- warp/native/volume_builder.h +19 -19
- warp/native/warp.cpp +1057 -1052
- warp/native/warp.cu +2943 -2828
- warp/native/warp.h +313 -305
- warp/optim/__init__.py +9 -9
- warp/optim/adam.py +120 -120
- warp/optim/linear.py +1104 -939
- warp/optim/sgd.py +104 -92
- warp/render/__init__.py +10 -10
- warp/render/render_opengl.py +3217 -3204
- warp/render/render_usd.py +768 -749
- warp/render/utils.py +152 -150
- warp/sim/__init__.py +52 -59
- warp/sim/articulation.py +685 -685
- warp/sim/collide.py +1594 -1590
- warp/sim/import_mjcf.py +489 -481
- warp/sim/import_snu.py +220 -221
- warp/sim/import_urdf.py +536 -516
- warp/sim/import_usd.py +887 -881
- warp/sim/inertia.py +316 -317
- warp/sim/integrator.py +234 -233
- warp/sim/integrator_euler.py +1956 -1956
- warp/sim/integrator_featherstone.py +1910 -1991
- warp/sim/integrator_xpbd.py +3294 -3312
- warp/sim/model.py +4473 -4314
- warp/sim/particles.py +113 -112
- warp/sim/render.py +417 -403
- warp/sim/utils.py +413 -410
- warp/sparse.py +1227 -1227
- warp/stubs.py +2109 -2469
- warp/tape.py +1162 -225
- warp/tests/__init__.py +1 -1
- warp/tests/__main__.py +4 -4
- warp/tests/assets/torus.usda +105 -105
- warp/tests/aux_test_class_kernel.py +26 -26
- warp/tests/aux_test_compile_consts_dummy.py +10 -10
- warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -21
- warp/tests/aux_test_dependent.py +22 -22
- warp/tests/aux_test_grad_customs.py +23 -23
- warp/tests/aux_test_reference.py +11 -11
- warp/tests/aux_test_reference_reference.py +10 -10
- warp/tests/aux_test_square.py +17 -17
- warp/tests/aux_test_unresolved_func.py +14 -14
- warp/tests/aux_test_unresolved_symbol.py +14 -14
- warp/tests/disabled_kinematics.py +239 -239
- warp/tests/run_coverage_serial.py +31 -31
- warp/tests/test_adam.py +157 -157
- warp/tests/test_arithmetic.py +1124 -1124
- warp/tests/test_array.py +2417 -2326
- warp/tests/test_array_reduce.py +150 -150
- warp/tests/test_async.py +668 -656
- warp/tests/test_atomic.py +141 -141
- warp/tests/test_bool.py +204 -149
- warp/tests/test_builtins_resolution.py +1292 -1292
- warp/tests/test_bvh.py +164 -171
- warp/tests/test_closest_point_edge_edge.py +228 -228
- warp/tests/test_codegen.py +566 -553
- warp/tests/test_compile_consts.py +97 -101
- warp/tests/test_conditional.py +246 -246
- warp/tests/test_copy.py +232 -215
- warp/tests/test_ctypes.py +632 -632
- warp/tests/test_dense.py +67 -67
- warp/tests/test_devices.py +91 -98
- warp/tests/test_dlpack.py +530 -529
- warp/tests/test_examples.py +400 -378
- warp/tests/test_fabricarray.py +955 -955
- warp/tests/test_fast_math.py +62 -54
- warp/tests/test_fem.py +1277 -1278
- warp/tests/test_fp16.py +130 -130
- warp/tests/test_func.py +338 -337
- warp/tests/test_generics.py +571 -571
- warp/tests/test_grad.py +746 -640
- warp/tests/test_grad_customs.py +333 -336
- warp/tests/test_hash_grid.py +210 -164
- warp/tests/test_import.py +39 -39
- warp/tests/test_indexedarray.py +1134 -1134
- warp/tests/test_intersect.py +67 -67
- warp/tests/test_jax.py +307 -307
- warp/tests/test_large.py +167 -164
- warp/tests/test_launch.py +354 -354
- warp/tests/test_lerp.py +261 -261
- warp/tests/test_linear_solvers.py +191 -171
- warp/tests/test_lvalue.py +421 -493
- warp/tests/test_marching_cubes.py +65 -65
- warp/tests/test_mat.py +1801 -1827
- warp/tests/test_mat_lite.py +115 -115
- warp/tests/test_mat_scalar_ops.py +2907 -2889
- warp/tests/test_math.py +126 -193
- warp/tests/test_matmul.py +500 -499
- warp/tests/test_matmul_lite.py +410 -410
- warp/tests/test_mempool.py +188 -190
- warp/tests/test_mesh.py +284 -324
- warp/tests/test_mesh_query_aabb.py +228 -241
- warp/tests/test_mesh_query_point.py +692 -702
- warp/tests/test_mesh_query_ray.py +292 -303
- warp/tests/test_mlp.py +276 -276
- warp/tests/test_model.py +110 -110
- warp/tests/test_modules_lite.py +39 -39
- warp/tests/test_multigpu.py +163 -163
- warp/tests/test_noise.py +248 -248
- warp/tests/test_operators.py +250 -250
- warp/tests/test_options.py +123 -125
- warp/tests/test_peer.py +133 -137
- warp/tests/test_pinned.py +78 -78
- warp/tests/test_print.py +54 -54
- warp/tests/test_quat.py +2086 -2086
- warp/tests/test_rand.py +288 -288
- warp/tests/test_reload.py +217 -217
- warp/tests/test_rounding.py +179 -179
- warp/tests/test_runlength_encode.py +190 -190
- warp/tests/test_sim_grad.py +243 -0
- warp/tests/test_sim_kinematics.py +91 -97
- warp/tests/test_smoothstep.py +168 -168
- warp/tests/test_snippet.py +305 -266
- warp/tests/test_sparse.py +468 -460
- warp/tests/test_spatial.py +2148 -2148
- warp/tests/test_streams.py +486 -473
- warp/tests/test_struct.py +710 -675
- warp/tests/test_tape.py +173 -148
- warp/tests/test_torch.py +743 -743
- warp/tests/test_transient_module.py +87 -87
- warp/tests/test_types.py +556 -659
- warp/tests/test_utils.py +490 -499
- warp/tests/test_vec.py +1264 -1268
- warp/tests/test_vec_lite.py +73 -73
- warp/tests/test_vec_scalar_ops.py +2099 -2099
- warp/tests/test_verify_fp.py +94 -94
- warp/tests/test_volume.py +737 -736
- warp/tests/test_volume_write.py +255 -265
- warp/tests/unittest_serial.py +37 -37
- warp/tests/unittest_suites.py +363 -359
- warp/tests/unittest_utils.py +603 -578
- warp/tests/unused_test_misc.py +71 -71
- warp/tests/walkthrough_debug.py +85 -85
- warp/thirdparty/appdirs.py +598 -598
- warp/thirdparty/dlpack.py +143 -143
- warp/thirdparty/unittest_parallel.py +566 -561
- warp/torch.py +321 -295
- warp/types.py +4504 -4450
- warp/utils.py +1008 -821
- {warp_lang-1.0.2.dist-info → warp_lang-1.1.0.dist-info}/LICENSE.md +126 -126
- {warp_lang-1.0.2.dist-info → warp_lang-1.1.0.dist-info}/METADATA +338 -400
- warp_lang-1.1.0.dist-info/RECORD +352 -0
- warp/examples/assets/cube.usda +0 -42
- warp/examples/assets/sphere.usda +0 -56
- warp/examples/assets/torus.usda +0 -105
- warp_lang-1.0.2.dist-info/RECORD +0 -352
- {warp_lang-1.0.2.dist-info → warp_lang-1.1.0.dist-info}/WHEEL +0 -0
- {warp_lang-1.0.2.dist-info → warp_lang-1.1.0.dist-info}/top_level.txt +0 -0
warp/render/render_usd.py
CHANGED
|
@@ -1,749 +1,768 @@
|
|
|
1
|
-
# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved.
|
|
2
|
-
# NVIDIA CORPORATION and its licensors retain all intellectual property
|
|
3
|
-
# and proprietary rights in and to this software, related documentation
|
|
4
|
-
# and any modifications thereto. Any use, reproduction, disclosure or
|
|
5
|
-
# distribution of this software and related documentation without an express
|
|
6
|
-
# license agreement from NVIDIA CORPORATION is strictly prohibited.
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def _usd_add_xform(prim):
|
|
14
|
-
from pxr import UsdGeom
|
|
15
|
-
|
|
16
|
-
prim = UsdGeom.Xform(prim)
|
|
17
|
-
prim.ClearXformOpOrder()
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def _usd_set_xform(xform, pos: tuple, rot: tuple, scale: tuple, time):
|
|
25
|
-
from pxr import
|
|
26
|
-
|
|
27
|
-
xform = UsdGeom.Xform(xform)
|
|
28
|
-
|
|
29
|
-
xform_ops = xform.GetOrderedXformOps()
|
|
30
|
-
|
|
31
|
-
if pos is not None:
|
|
32
|
-
xform_ops[0].Set(Gf.Vec3d(float(pos[0]), float(pos[1]), float(pos[2])), time)
|
|
33
|
-
if rot is not None:
|
|
34
|
-
xform_ops[1].Set(Gf.Quatf(float(rot[3]), float(rot[0]), float(rot[1]), float(rot[2])), time)
|
|
35
|
-
if scale is not None:
|
|
36
|
-
xform_ops[2].Set(Gf.Vec3d(float(scale[0]), float(scale[1]), float(scale[2])), time)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
# transforms a cylinder such that it connects the two points pos0, pos1
|
|
40
|
-
def _compute_segment_xform(pos0, pos1):
|
|
41
|
-
from pxr import Gf
|
|
42
|
-
|
|
43
|
-
mid = (pos0 + pos1) * 0.5
|
|
44
|
-
height = (pos1 - pos0).GetLength()
|
|
45
|
-
|
|
46
|
-
dir = (pos1 - pos0) / height
|
|
47
|
-
|
|
48
|
-
rot = Gf.Rotation()
|
|
49
|
-
rot.SetRotateInto((0.0, 0.0, 1.0), Gf.Vec3d(dir))
|
|
50
|
-
|
|
51
|
-
scale = Gf.Vec3f(1.0, 1.0, height)
|
|
52
|
-
|
|
53
|
-
return (mid, Gf.Quath(rot.GetQuat()), scale)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
class UsdRenderer:
|
|
57
|
-
"""A USD renderer"""
|
|
58
|
-
|
|
59
|
-
def __init__(self, stage, up_axis="Y", fps=60, scaling=1.0):
|
|
60
|
-
"""Construct a UsdRenderer object
|
|
61
|
-
|
|
62
|
-
Args:
|
|
63
|
-
model: A simulation model
|
|
64
|
-
stage (str/Usd.Stage): A USD stage (either in memory or on disk)
|
|
65
|
-
up_axis (str): The upfacing axis of the stage
|
|
66
|
-
fps: The number of frames per second to use in the USD file
|
|
67
|
-
scaling: Scaling factor to use for the entities in the scene
|
|
68
|
-
"""
|
|
69
|
-
try:
|
|
70
|
-
from pxr import
|
|
71
|
-
except ImportError:
|
|
72
|
-
raise ImportError("Failed to import pxr. Please install USD (e.g. via `pip install usd-core`).")
|
|
73
|
-
|
|
74
|
-
if isinstance(stage, str):
|
|
75
|
-
self.stage = stage = Usd.Stage.CreateNew(stage)
|
|
76
|
-
elif isinstance(stage, Usd.Stage):
|
|
77
|
-
self.stage = stage
|
|
78
|
-
else:
|
|
79
|
-
print("Failed to create stage in renderer. Please construct with stage path or stage object.")
|
|
80
|
-
self.up_axis = up_axis.upper()
|
|
81
|
-
self.fps = float(fps)
|
|
82
|
-
self.time = 0.0
|
|
83
|
-
|
|
84
|
-
self.draw_points = True
|
|
85
|
-
self.draw_springs = False
|
|
86
|
-
self.draw_triangles = False
|
|
87
|
-
|
|
88
|
-
self.root = UsdGeom.Xform.Define(stage, "/root")
|
|
89
|
-
|
|
90
|
-
# mapping from shape ID to UsdGeom class
|
|
91
|
-
self._shape_constructors = {}
|
|
92
|
-
# optional scaling applied to shape instances (e.g. cubes)
|
|
93
|
-
self._shape_custom_scale = {}
|
|
94
|
-
|
|
95
|
-
# apply scaling
|
|
96
|
-
self.root.ClearXformOpOrder()
|
|
97
|
-
s = self.root.AddScaleOp()
|
|
98
|
-
s.Set(Gf.Vec3d(float(scaling), float(scaling), float(scaling)), 0.0)
|
|
99
|
-
|
|
100
|
-
self.stage.SetDefaultPrim(self.root.GetPrim())
|
|
101
|
-
self.stage.SetStartTimeCode(0.0)
|
|
102
|
-
self.stage.SetEndTimeCode(0.0)
|
|
103
|
-
self.stage.SetTimeCodesPerSecond(self.fps)
|
|
104
|
-
|
|
105
|
-
if up_axis == "X":
|
|
106
|
-
UsdGeom.SetStageUpAxis(self.stage, UsdGeom.Tokens.x)
|
|
107
|
-
elif up_axis == "Y":
|
|
108
|
-
UsdGeom.SetStageUpAxis(self.stage, UsdGeom.Tokens.y)
|
|
109
|
-
elif up_axis == "Z":
|
|
110
|
-
UsdGeom.SetStageUpAxis(self.stage, UsdGeom.Tokens.z)
|
|
111
|
-
|
|
112
|
-
dome_light = UsdLux.DomeLight.Define(stage, "/dome_light")
|
|
113
|
-
dome_light.AddRotateXYZOp().Set((-90.0, -30.0, 0.0))
|
|
114
|
-
dome_light.GetEnableColorTemperatureAttr().Set(True)
|
|
115
|
-
dome_light.GetColorTemperatureAttr().Set(6150.0)
|
|
116
|
-
dome_light.GetIntensityAttr().Set(1.0)
|
|
117
|
-
dome_light.GetExposureAttr().Set(9.0)
|
|
118
|
-
dome_light.GetPrim().CreateAttribute("visibleInPrimaryRay", Sdf.ValueTypeNames.Bool).Set(False)
|
|
119
|
-
|
|
120
|
-
distant_light = UsdLux.DistantLight.Define(stage, "/distant_light")
|
|
121
|
-
distant_light.AddRotateXYZOp().Set((-35.0, 45.0, 0.0))
|
|
122
|
-
distant_light.GetEnableColorTemperatureAttr().Set(True)
|
|
123
|
-
distant_light.GetColorTemperatureAttr().Set(7250.0)
|
|
124
|
-
distant_light.GetIntensityAttr().Set(1.0)
|
|
125
|
-
distant_light.GetExposureAttr().Set(10.0)
|
|
126
|
-
|
|
127
|
-
def begin_frame(self, time):
|
|
128
|
-
self.time = round(time * self.fps)
|
|
129
|
-
self.stage.SetEndTimeCode(self.time)
|
|
130
|
-
|
|
131
|
-
def end_frame(self):
|
|
132
|
-
pass
|
|
133
|
-
|
|
134
|
-
def register_body(self, body_name):
|
|
135
|
-
from pxr import UsdGeom
|
|
136
|
-
|
|
137
|
-
xform = UsdGeom.Xform.Define(self.stage, self.root.GetPath().AppendChild(body_name))
|
|
138
|
-
|
|
139
|
-
_usd_add_xform(xform)
|
|
140
|
-
|
|
141
|
-
def _resolve_path(self, name, parent_body=None, is_template=False):
|
|
142
|
-
# resolve the path to the prim with the given name and optional parent body
|
|
143
|
-
if is_template:
|
|
144
|
-
return self.root.GetPath().AppendChild("_template_shapes").AppendChild(name)
|
|
145
|
-
if parent_body is None:
|
|
146
|
-
return self.root.GetPath().AppendChild(name)
|
|
147
|
-
else:
|
|
148
|
-
return self.root.GetPath().AppendChild(parent_body).AppendChild(name)
|
|
149
|
-
|
|
150
|
-
def add_shape_instance(
|
|
151
|
-
self,
|
|
152
|
-
name: str,
|
|
153
|
-
shape,
|
|
154
|
-
body,
|
|
155
|
-
pos: tuple,
|
|
156
|
-
rot: tuple,
|
|
157
|
-
scale: tuple = (1.0, 1.0, 1.0),
|
|
158
|
-
color: tuple = (1.0, 1.0, 1.0),
|
|
159
|
-
custom_index: int = -1,
|
|
160
|
-
visible: bool = True,
|
|
161
|
-
):
|
|
162
|
-
if not visible:
|
|
163
|
-
return
|
|
164
|
-
sdf_path = self._resolve_path(name, body)
|
|
165
|
-
instance = self._shape_constructors[shape.name].Define(self.stage, sdf_path)
|
|
166
|
-
instance.GetPrim().GetReferences().AddInternalReference(shape)
|
|
167
|
-
|
|
168
|
-
_usd_add_xform(instance)
|
|
169
|
-
if shape.name in self._shape_custom_scale:
|
|
170
|
-
cs = self._shape_custom_scale[shape.name]
|
|
171
|
-
scale = (scale[0] * cs[0], scale[1] * cs[1], scale[2] * cs[2])
|
|
172
|
-
_usd_set_xform(instance, pos, rot, scale, self.time)
|
|
173
|
-
|
|
174
|
-
def render_plane(
|
|
175
|
-
self,
|
|
176
|
-
name: str,
|
|
177
|
-
pos: tuple,
|
|
178
|
-
rot: tuple,
|
|
179
|
-
width: float,
|
|
180
|
-
length: float,
|
|
181
|
-
color: tuple = None,
|
|
182
|
-
parent_body: str = None,
|
|
183
|
-
is_template: bool = False,
|
|
184
|
-
):
|
|
185
|
-
"""
|
|
186
|
-
Render a plane with the given dimensions.
|
|
187
|
-
|
|
188
|
-
Args:
|
|
189
|
-
name: Name of the plane
|
|
190
|
-
pos: Position of the plane
|
|
191
|
-
rot: Rotation of the plane
|
|
192
|
-
width: Width of the plane
|
|
193
|
-
length: Length of the plane
|
|
194
|
-
color: Color of the plane
|
|
195
|
-
parent_body: Name of the parent body
|
|
196
|
-
is_template: Whether the plane is a template
|
|
197
|
-
"""
|
|
198
|
-
from pxr import
|
|
199
|
-
|
|
200
|
-
if is_template:
|
|
201
|
-
prim_path = self._resolve_path(name, parent_body, is_template)
|
|
202
|
-
blueprint = UsdGeom.Scope.Define(self.stage, prim_path)
|
|
203
|
-
blueprint_prim = blueprint.GetPrim()
|
|
204
|
-
blueprint_prim.SetInstanceable(True)
|
|
205
|
-
blueprint_prim.SetSpecifier(Sdf.SpecifierClass)
|
|
206
|
-
plane_path = prim_path.AppendChild("plane")
|
|
207
|
-
else:
|
|
208
|
-
plane_path = self._resolve_path(name, parent_body)
|
|
209
|
-
prim_path = plane_path
|
|
210
|
-
|
|
211
|
-
plane = UsdGeom.Mesh.Get(self.stage, plane_path)
|
|
212
|
-
if not plane:
|
|
213
|
-
plane = UsdGeom.Mesh.Define(self.stage, plane_path)
|
|
214
|
-
plane.CreateDoubleSidedAttr().Set(True)
|
|
215
|
-
|
|
216
|
-
width = width if width > 0.0 else 100.0
|
|
217
|
-
length = length if length > 0.0 else 100.0
|
|
218
|
-
points = ((-width, 0.0, -length), (width, 0.0, -length), (width, 0.0, length), (-width, 0.0, length))
|
|
219
|
-
normals = ((0.0, 1.0, 0.0), (0.0, 1.0, 0.0), (0.0, 1.0, 0.0), (0.0, 1.0, 0.0))
|
|
220
|
-
counts = (4,)
|
|
221
|
-
indices = [0, 1, 2, 3]
|
|
222
|
-
|
|
223
|
-
plane.GetPointsAttr().Set(points)
|
|
224
|
-
plane.GetNormalsAttr().Set(normals)
|
|
225
|
-
plane.GetFaceVertexCountsAttr().Set(counts)
|
|
226
|
-
plane.GetFaceVertexIndicesAttr().Set(indices)
|
|
227
|
-
_usd_add_xform(plane)
|
|
228
|
-
|
|
229
|
-
self._shape_constructors[name] = UsdGeom.Mesh
|
|
230
|
-
|
|
231
|
-
if not is_template:
|
|
232
|
-
_usd_set_xform(plane, pos, rot, (1.0, 1.0, 1.0), 0.0)
|
|
233
|
-
|
|
234
|
-
return prim_path
|
|
235
|
-
|
|
236
|
-
def render_ground(self, size: float = 100.0, plane=None):
|
|
237
|
-
from pxr import UsdGeom
|
|
238
|
-
|
|
239
|
-
mesh = UsdGeom.Mesh.Define(self.stage, self.root.GetPath().AppendChild("ground"))
|
|
240
|
-
mesh.CreateDoubleSidedAttr().Set(True)
|
|
241
|
-
|
|
242
|
-
if self.up_axis == "X":
|
|
243
|
-
points = ((0.0,
|
|
244
|
-
normals = ((1.0, 0.0, 0.0), (1.0, 0.0, 0.0), (1.0, 0.0, 0.0), (1.0, 0.0, 0.0))
|
|
245
|
-
elif self.up_axis == "Y":
|
|
246
|
-
points = ((-size, 0.0, -size), (size, 0.0, -size), (size, 0.0, size), (
|
|
247
|
-
normals = ((0.0, 1.0, 0.0), (0.0, 1.0, 0.0), (0.0, 1.0, 0.0), (0.0, 1.0, 0.0))
|
|
248
|
-
elif self.up_axis == "Z":
|
|
249
|
-
points = ((-size,
|
|
250
|
-
normals = ((0.0, 0.0, 1.0), (0.0, 0.0, 1.0), (0.0, 0.0, 1.0), (0.0, 0.0, 1.0))
|
|
251
|
-
if plane is not None:
|
|
252
|
-
normal = np.array(plane[:3])
|
|
253
|
-
normal /= np.linalg.norm(normal)
|
|
254
|
-
pos = plane[3] * normal
|
|
255
|
-
axis_up = [0.0, 0.0, 0.0]
|
|
256
|
-
axis_up["XYZ".index(self.up_axis)] = 1.0
|
|
257
|
-
if np.allclose(normal, axis_up):
|
|
258
|
-
# no rotation necessary
|
|
259
|
-
q = (0.0, 0.0, 0.0, 1.0)
|
|
260
|
-
else:
|
|
261
|
-
c = np.cross(normal, axis_up)
|
|
262
|
-
angle = np.arcsin(np.linalg.norm(c))
|
|
263
|
-
axis = np.abs(c) / np.linalg.norm(c)
|
|
264
|
-
q = wp.quat_from_axis_angle(axis, angle)
|
|
265
|
-
tf = wp.transform(pos, q)
|
|
266
|
-
points = [wp.transform_point(tf, p) for p in points]
|
|
267
|
-
normals = [wp.transform_vector(tf, n) for n in normals]
|
|
268
|
-
counts = (4,)
|
|
269
|
-
indices = [0,
|
|
270
|
-
|
|
271
|
-
mesh.GetPointsAttr().Set(points)
|
|
272
|
-
mesh.GetNormalsAttr().Set(normals)
|
|
273
|
-
mesh.GetFaceVertexCountsAttr().Set(counts)
|
|
274
|
-
mesh.GetFaceVertexIndicesAttr().Set(indices)
|
|
275
|
-
|
|
276
|
-
def render_sphere(
|
|
277
|
-
self,
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
"""
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
capsule.
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
capsule
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
cylinder.
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
cylinder
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
cone.
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
cone
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
def
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
if not
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
1
|
+
# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved.
|
|
2
|
+
# NVIDIA CORPORATION and its licensors retain all intellectual property
|
|
3
|
+
# and proprietary rights in and to this software, related documentation
|
|
4
|
+
# and any modifications thereto. Any use, reproduction, disclosure or
|
|
5
|
+
# distribution of this software and related documentation without an express
|
|
6
|
+
# license agreement from NVIDIA CORPORATION is strictly prohibited.
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
import warp as wp
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _usd_add_xform(prim):
|
|
14
|
+
from pxr import UsdGeom
|
|
15
|
+
|
|
16
|
+
prim = UsdGeom.Xform(prim)
|
|
17
|
+
prim.ClearXformOpOrder()
|
|
18
|
+
|
|
19
|
+
prim.AddTranslateOp()
|
|
20
|
+
prim.AddOrientOp()
|
|
21
|
+
prim.AddScaleOp()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _usd_set_xform(xform, pos: tuple, rot: tuple, scale: tuple, time):
|
|
25
|
+
from pxr import Gf, UsdGeom
|
|
26
|
+
|
|
27
|
+
xform = UsdGeom.Xform(xform)
|
|
28
|
+
|
|
29
|
+
xform_ops = xform.GetOrderedXformOps()
|
|
30
|
+
|
|
31
|
+
if pos is not None:
|
|
32
|
+
xform_ops[0].Set(Gf.Vec3d(float(pos[0]), float(pos[1]), float(pos[2])), time)
|
|
33
|
+
if rot is not None:
|
|
34
|
+
xform_ops[1].Set(Gf.Quatf(float(rot[3]), float(rot[0]), float(rot[1]), float(rot[2])), time)
|
|
35
|
+
if scale is not None:
|
|
36
|
+
xform_ops[2].Set(Gf.Vec3d(float(scale[0]), float(scale[1]), float(scale[2])), time)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# transforms a cylinder such that it connects the two points pos0, pos1
|
|
40
|
+
def _compute_segment_xform(pos0, pos1):
|
|
41
|
+
from pxr import Gf
|
|
42
|
+
|
|
43
|
+
mid = (pos0 + pos1) * 0.5
|
|
44
|
+
height = (pos1 - pos0).GetLength()
|
|
45
|
+
|
|
46
|
+
dir = (pos1 - pos0) / height
|
|
47
|
+
|
|
48
|
+
rot = Gf.Rotation()
|
|
49
|
+
rot.SetRotateInto((0.0, 0.0, 1.0), Gf.Vec3d(dir))
|
|
50
|
+
|
|
51
|
+
scale = Gf.Vec3f(1.0, 1.0, height)
|
|
52
|
+
|
|
53
|
+
return (mid, Gf.Quath(rot.GetQuat()), scale)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class UsdRenderer:
|
|
57
|
+
"""A USD renderer"""
|
|
58
|
+
|
|
59
|
+
def __init__(self, stage, up_axis="Y", fps=60, scaling=1.0):
|
|
60
|
+
"""Construct a UsdRenderer object
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
model: A simulation model
|
|
64
|
+
stage (str/Usd.Stage): A USD stage (either in memory or on disk)
|
|
65
|
+
up_axis (str): The upfacing axis of the stage
|
|
66
|
+
fps: The number of frames per second to use in the USD file
|
|
67
|
+
scaling: Scaling factor to use for the entities in the scene
|
|
68
|
+
"""
|
|
69
|
+
try:
|
|
70
|
+
from pxr import Gf, Sdf, Usd, UsdGeom, UsdLux
|
|
71
|
+
except ImportError as e:
|
|
72
|
+
raise ImportError("Failed to import pxr. Please install USD (e.g. via `pip install usd-core`).") from e
|
|
73
|
+
|
|
74
|
+
if isinstance(stage, str):
|
|
75
|
+
self.stage = stage = Usd.Stage.CreateNew(stage)
|
|
76
|
+
elif isinstance(stage, Usd.Stage):
|
|
77
|
+
self.stage = stage
|
|
78
|
+
else:
|
|
79
|
+
print("Failed to create stage in renderer. Please construct with stage path or stage object.")
|
|
80
|
+
self.up_axis = up_axis.upper()
|
|
81
|
+
self.fps = float(fps)
|
|
82
|
+
self.time = 0.0
|
|
83
|
+
|
|
84
|
+
self.draw_points = True
|
|
85
|
+
self.draw_springs = False
|
|
86
|
+
self.draw_triangles = False
|
|
87
|
+
|
|
88
|
+
self.root = UsdGeom.Xform.Define(stage, "/root")
|
|
89
|
+
|
|
90
|
+
# mapping from shape ID to UsdGeom class
|
|
91
|
+
self._shape_constructors = {}
|
|
92
|
+
# optional scaling applied to shape instances (e.g. cubes)
|
|
93
|
+
self._shape_custom_scale = {}
|
|
94
|
+
|
|
95
|
+
# apply scaling
|
|
96
|
+
self.root.ClearXformOpOrder()
|
|
97
|
+
s = self.root.AddScaleOp()
|
|
98
|
+
s.Set(Gf.Vec3d(float(scaling), float(scaling), float(scaling)), 0.0)
|
|
99
|
+
|
|
100
|
+
self.stage.SetDefaultPrim(self.root.GetPrim())
|
|
101
|
+
self.stage.SetStartTimeCode(0.0)
|
|
102
|
+
self.stage.SetEndTimeCode(0.0)
|
|
103
|
+
self.stage.SetTimeCodesPerSecond(self.fps)
|
|
104
|
+
|
|
105
|
+
if up_axis == "X":
|
|
106
|
+
UsdGeom.SetStageUpAxis(self.stage, UsdGeom.Tokens.x)
|
|
107
|
+
elif up_axis == "Y":
|
|
108
|
+
UsdGeom.SetStageUpAxis(self.stage, UsdGeom.Tokens.y)
|
|
109
|
+
elif up_axis == "Z":
|
|
110
|
+
UsdGeom.SetStageUpAxis(self.stage, UsdGeom.Tokens.z)
|
|
111
|
+
|
|
112
|
+
dome_light = UsdLux.DomeLight.Define(stage, "/dome_light")
|
|
113
|
+
dome_light.AddRotateXYZOp().Set((-90.0, -30.0, 0.0))
|
|
114
|
+
dome_light.GetEnableColorTemperatureAttr().Set(True)
|
|
115
|
+
dome_light.GetColorTemperatureAttr().Set(6150.0)
|
|
116
|
+
dome_light.GetIntensityAttr().Set(1.0)
|
|
117
|
+
dome_light.GetExposureAttr().Set(9.0)
|
|
118
|
+
dome_light.GetPrim().CreateAttribute("visibleInPrimaryRay", Sdf.ValueTypeNames.Bool).Set(False)
|
|
119
|
+
|
|
120
|
+
distant_light = UsdLux.DistantLight.Define(stage, "/distant_light")
|
|
121
|
+
distant_light.AddRotateXYZOp().Set((-35.0, 45.0, 0.0))
|
|
122
|
+
distant_light.GetEnableColorTemperatureAttr().Set(True)
|
|
123
|
+
distant_light.GetColorTemperatureAttr().Set(7250.0)
|
|
124
|
+
distant_light.GetIntensityAttr().Set(1.0)
|
|
125
|
+
distant_light.GetExposureAttr().Set(10.0)
|
|
126
|
+
|
|
127
|
+
def begin_frame(self, time):
|
|
128
|
+
self.time = round(time * self.fps)
|
|
129
|
+
self.stage.SetEndTimeCode(self.time)
|
|
130
|
+
|
|
131
|
+
def end_frame(self):
|
|
132
|
+
pass
|
|
133
|
+
|
|
134
|
+
def register_body(self, body_name):
|
|
135
|
+
from pxr import UsdGeom
|
|
136
|
+
|
|
137
|
+
xform = UsdGeom.Xform.Define(self.stage, self.root.GetPath().AppendChild(body_name))
|
|
138
|
+
|
|
139
|
+
_usd_add_xform(xform)
|
|
140
|
+
|
|
141
|
+
def _resolve_path(self, name, parent_body=None, is_template=False):
|
|
142
|
+
# resolve the path to the prim with the given name and optional parent body
|
|
143
|
+
if is_template:
|
|
144
|
+
return self.root.GetPath().AppendChild("_template_shapes").AppendChild(name)
|
|
145
|
+
if parent_body is None:
|
|
146
|
+
return self.root.GetPath().AppendChild(name)
|
|
147
|
+
else:
|
|
148
|
+
return self.root.GetPath().AppendChild(parent_body).AppendChild(name)
|
|
149
|
+
|
|
150
|
+
def add_shape_instance(
|
|
151
|
+
self,
|
|
152
|
+
name: str,
|
|
153
|
+
shape,
|
|
154
|
+
body,
|
|
155
|
+
pos: tuple,
|
|
156
|
+
rot: tuple,
|
|
157
|
+
scale: tuple = (1.0, 1.0, 1.0),
|
|
158
|
+
color: tuple = (1.0, 1.0, 1.0),
|
|
159
|
+
custom_index: int = -1,
|
|
160
|
+
visible: bool = True,
|
|
161
|
+
):
|
|
162
|
+
if not visible:
|
|
163
|
+
return
|
|
164
|
+
sdf_path = self._resolve_path(name, body)
|
|
165
|
+
instance = self._shape_constructors[shape.name].Define(self.stage, sdf_path)
|
|
166
|
+
instance.GetPrim().GetReferences().AddInternalReference(shape)
|
|
167
|
+
|
|
168
|
+
_usd_add_xform(instance)
|
|
169
|
+
if shape.name in self._shape_custom_scale:
|
|
170
|
+
cs = self._shape_custom_scale[shape.name]
|
|
171
|
+
scale = (scale[0] * cs[0], scale[1] * cs[1], scale[2] * cs[2])
|
|
172
|
+
_usd_set_xform(instance, pos, rot, scale, self.time)
|
|
173
|
+
|
|
174
|
+
def render_plane(
|
|
175
|
+
self,
|
|
176
|
+
name: str,
|
|
177
|
+
pos: tuple,
|
|
178
|
+
rot: tuple,
|
|
179
|
+
width: float,
|
|
180
|
+
length: float,
|
|
181
|
+
color: tuple = None,
|
|
182
|
+
parent_body: str = None,
|
|
183
|
+
is_template: bool = False,
|
|
184
|
+
):
|
|
185
|
+
"""
|
|
186
|
+
Render a plane with the given dimensions.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
name: Name of the plane
|
|
190
|
+
pos: Position of the plane
|
|
191
|
+
rot: Rotation of the plane
|
|
192
|
+
width: Width of the plane
|
|
193
|
+
length: Length of the plane
|
|
194
|
+
color: Color of the plane
|
|
195
|
+
parent_body: Name of the parent body
|
|
196
|
+
is_template: Whether the plane is a template
|
|
197
|
+
"""
|
|
198
|
+
from pxr import Sdf, UsdGeom
|
|
199
|
+
|
|
200
|
+
if is_template:
|
|
201
|
+
prim_path = self._resolve_path(name, parent_body, is_template)
|
|
202
|
+
blueprint = UsdGeom.Scope.Define(self.stage, prim_path)
|
|
203
|
+
blueprint_prim = blueprint.GetPrim()
|
|
204
|
+
blueprint_prim.SetInstanceable(True)
|
|
205
|
+
blueprint_prim.SetSpecifier(Sdf.SpecifierClass)
|
|
206
|
+
plane_path = prim_path.AppendChild("plane")
|
|
207
|
+
else:
|
|
208
|
+
plane_path = self._resolve_path(name, parent_body)
|
|
209
|
+
prim_path = plane_path
|
|
210
|
+
|
|
211
|
+
plane = UsdGeom.Mesh.Get(self.stage, plane_path)
|
|
212
|
+
if not plane:
|
|
213
|
+
plane = UsdGeom.Mesh.Define(self.stage, plane_path)
|
|
214
|
+
plane.CreateDoubleSidedAttr().Set(True)
|
|
215
|
+
|
|
216
|
+
width = width if width > 0.0 else 100.0
|
|
217
|
+
length = length if length > 0.0 else 100.0
|
|
218
|
+
points = ((-width, 0.0, -length), (width, 0.0, -length), (width, 0.0, length), (-width, 0.0, length))
|
|
219
|
+
normals = ((0.0, 1.0, 0.0), (0.0, 1.0, 0.0), (0.0, 1.0, 0.0), (0.0, 1.0, 0.0))
|
|
220
|
+
counts = (4,)
|
|
221
|
+
indices = [0, 1, 2, 3]
|
|
222
|
+
|
|
223
|
+
plane.GetPointsAttr().Set(points)
|
|
224
|
+
plane.GetNormalsAttr().Set(normals)
|
|
225
|
+
plane.GetFaceVertexCountsAttr().Set(counts)
|
|
226
|
+
plane.GetFaceVertexIndicesAttr().Set(indices)
|
|
227
|
+
_usd_add_xform(plane)
|
|
228
|
+
|
|
229
|
+
self._shape_constructors[name] = UsdGeom.Mesh
|
|
230
|
+
|
|
231
|
+
if not is_template:
|
|
232
|
+
_usd_set_xform(plane, pos, rot, (1.0, 1.0, 1.0), 0.0)
|
|
233
|
+
|
|
234
|
+
return prim_path
|
|
235
|
+
|
|
236
|
+
def render_ground(self, size: float = 100.0, plane=None):
|
|
237
|
+
from pxr import UsdGeom
|
|
238
|
+
|
|
239
|
+
mesh = UsdGeom.Mesh.Define(self.stage, self.root.GetPath().AppendChild("ground"))
|
|
240
|
+
mesh.CreateDoubleSidedAttr().Set(True)
|
|
241
|
+
|
|
242
|
+
if self.up_axis == "X":
|
|
243
|
+
points = ((0.0, size, -size), (0.0, -size, -size), (0.0, size, size), (0.0, -size, size))
|
|
244
|
+
normals = ((1.0, 0.0, 0.0), (1.0, 0.0, 0.0), (1.0, 0.0, 0.0), (1.0, 0.0, 0.0))
|
|
245
|
+
elif self.up_axis == "Y":
|
|
246
|
+
points = ((-size, 0.0, -size), (size, 0.0, -size), (-size, 0.0, size), (size, 0.0, size))
|
|
247
|
+
normals = ((0.0, 1.0, 0.0), (0.0, 1.0, 0.0), (0.0, 1.0, 0.0), (0.0, 1.0, 0.0))
|
|
248
|
+
elif self.up_axis == "Z":
|
|
249
|
+
points = ((-size, size, 0.0), (size, size, 0.0), (-size, -size, 0.0), (size, -size, 0.0))
|
|
250
|
+
normals = ((0.0, 0.0, 1.0), (0.0, 0.0, 1.0), (0.0, 0.0, 1.0), (0.0, 0.0, 1.0))
|
|
251
|
+
if plane is not None:
|
|
252
|
+
normal = np.array(plane[:3])
|
|
253
|
+
normal /= np.linalg.norm(normal)
|
|
254
|
+
pos = plane[3] * normal
|
|
255
|
+
axis_up = [0.0, 0.0, 0.0]
|
|
256
|
+
axis_up["XYZ".index(self.up_axis)] = 1.0
|
|
257
|
+
if np.allclose(normal, axis_up):
|
|
258
|
+
# no rotation necessary
|
|
259
|
+
q = (0.0, 0.0, 0.0, 1.0)
|
|
260
|
+
else:
|
|
261
|
+
c = np.cross(normal, axis_up)
|
|
262
|
+
angle = np.arcsin(np.linalg.norm(c))
|
|
263
|
+
axis = np.abs(c) / np.linalg.norm(c)
|
|
264
|
+
q = wp.quat_from_axis_angle(axis, angle)
|
|
265
|
+
tf = wp.transform(pos, q)
|
|
266
|
+
points = [wp.transform_point(tf, wp.vec3(p)) for p in points]
|
|
267
|
+
normals = [wp.transform_vector(tf, wp.vec3(n)) for n in normals]
|
|
268
|
+
counts = (4,)
|
|
269
|
+
indices = [0, 2, 3, 1]
|
|
270
|
+
|
|
271
|
+
mesh.GetPointsAttr().Set(points)
|
|
272
|
+
mesh.GetNormalsAttr().Set(normals)
|
|
273
|
+
mesh.GetFaceVertexCountsAttr().Set(counts)
|
|
274
|
+
mesh.GetFaceVertexIndicesAttr().Set(indices)
|
|
275
|
+
|
|
276
|
+
def render_sphere(
|
|
277
|
+
self,
|
|
278
|
+
name: str,
|
|
279
|
+
pos: tuple,
|
|
280
|
+
rot: tuple,
|
|
281
|
+
radius: float,
|
|
282
|
+
parent_body: str = None,
|
|
283
|
+
is_template: bool = False,
|
|
284
|
+
color: tuple = None,
|
|
285
|
+
):
|
|
286
|
+
"""Debug helper to add a sphere for visualization
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
pos: The position of the sphere
|
|
290
|
+
radius: The radius of the sphere
|
|
291
|
+
name: A name for the USD prim on the stage
|
|
292
|
+
color: The color of the sphere
|
|
293
|
+
"""
|
|
294
|
+
|
|
295
|
+
from pxr import Gf, Sdf, UsdGeom
|
|
296
|
+
|
|
297
|
+
if is_template:
|
|
298
|
+
prim_path = self._resolve_path(name, parent_body, is_template)
|
|
299
|
+
blueprint = UsdGeom.Scope.Define(self.stage, prim_path)
|
|
300
|
+
blueprint_prim = blueprint.GetPrim()
|
|
301
|
+
blueprint_prim.SetInstanceable(True)
|
|
302
|
+
blueprint_prim.SetSpecifier(Sdf.SpecifierClass)
|
|
303
|
+
sphere_path = prim_path.AppendChild("sphere")
|
|
304
|
+
else:
|
|
305
|
+
sphere_path = self._resolve_path(name, parent_body)
|
|
306
|
+
prim_path = sphere_path
|
|
307
|
+
|
|
308
|
+
sphere = UsdGeom.Sphere.Get(self.stage, sphere_path)
|
|
309
|
+
if not sphere:
|
|
310
|
+
sphere = UsdGeom.Sphere.Define(self.stage, sphere_path)
|
|
311
|
+
_usd_add_xform(sphere)
|
|
312
|
+
|
|
313
|
+
sphere.GetRadiusAttr().Set(radius, self.time)
|
|
314
|
+
|
|
315
|
+
if color is not None:
|
|
316
|
+
sphere.GetDisplayColorAttr().Set([Gf.Vec3f(color)], self.time)
|
|
317
|
+
|
|
318
|
+
self._shape_constructors[name] = UsdGeom.Sphere
|
|
319
|
+
|
|
320
|
+
if not is_template:
|
|
321
|
+
_usd_set_xform(sphere, pos, rot, (1.0, 1.0, 1.0), self.time)
|
|
322
|
+
|
|
323
|
+
return prim_path
|
|
324
|
+
|
|
325
|
+
def render_capsule(
|
|
326
|
+
self,
|
|
327
|
+
name: str,
|
|
328
|
+
pos: tuple,
|
|
329
|
+
rot: tuple,
|
|
330
|
+
radius: float,
|
|
331
|
+
half_height: float,
|
|
332
|
+
parent_body: str = None,
|
|
333
|
+
is_template: bool = False,
|
|
334
|
+
color: tuple = None,
|
|
335
|
+
):
|
|
336
|
+
"""
|
|
337
|
+
Debug helper to add a capsule for visualization
|
|
338
|
+
|
|
339
|
+
Args:
|
|
340
|
+
pos: The position of the capsule
|
|
341
|
+
radius: The radius of the capsule
|
|
342
|
+
half_height: The half height of the capsule
|
|
343
|
+
name: A name for the USD prim on the stage
|
|
344
|
+
color: The color of the capsule
|
|
345
|
+
"""
|
|
346
|
+
|
|
347
|
+
from pxr import Gf, Sdf, UsdGeom
|
|
348
|
+
|
|
349
|
+
if is_template:
|
|
350
|
+
prim_path = self._resolve_path(name, parent_body, is_template)
|
|
351
|
+
blueprint = UsdGeom.Scope.Define(self.stage, prim_path)
|
|
352
|
+
blueprint_prim = blueprint.GetPrim()
|
|
353
|
+
blueprint_prim.SetInstanceable(True)
|
|
354
|
+
blueprint_prim.SetSpecifier(Sdf.SpecifierClass)
|
|
355
|
+
capsule_path = prim_path.AppendChild("capsule")
|
|
356
|
+
else:
|
|
357
|
+
capsule_path = self._resolve_path(name, parent_body)
|
|
358
|
+
prim_path = capsule_path
|
|
359
|
+
|
|
360
|
+
capsule = UsdGeom.Capsule.Get(self.stage, capsule_path)
|
|
361
|
+
if not capsule:
|
|
362
|
+
capsule = UsdGeom.Capsule.Define(self.stage, capsule_path)
|
|
363
|
+
_usd_add_xform(capsule)
|
|
364
|
+
|
|
365
|
+
capsule.GetRadiusAttr().Set(float(radius))
|
|
366
|
+
capsule.GetHeightAttr().Set(float(half_height * 2.0))
|
|
367
|
+
capsule.GetAxisAttr().Set("Y")
|
|
368
|
+
|
|
369
|
+
if color is not None:
|
|
370
|
+
capsule.GetDisplayColorAttr().Set([Gf.Vec3f(color)], self.time)
|
|
371
|
+
|
|
372
|
+
self._shape_constructors[name] = UsdGeom.Capsule
|
|
373
|
+
|
|
374
|
+
if not is_template:
|
|
375
|
+
_usd_set_xform(capsule, pos, rot, (1.0, 1.0, 1.0), self.time)
|
|
376
|
+
|
|
377
|
+
return prim_path
|
|
378
|
+
|
|
379
|
+
def render_cylinder(
|
|
380
|
+
self,
|
|
381
|
+
name: str,
|
|
382
|
+
pos: tuple,
|
|
383
|
+
rot: tuple,
|
|
384
|
+
radius: float,
|
|
385
|
+
half_height: float,
|
|
386
|
+
parent_body: str = None,
|
|
387
|
+
is_template: bool = False,
|
|
388
|
+
color: tuple = None,
|
|
389
|
+
):
|
|
390
|
+
"""
|
|
391
|
+
Debug helper to add a cylinder for visualization
|
|
392
|
+
|
|
393
|
+
Args:
|
|
394
|
+
pos: The position of the cylinder
|
|
395
|
+
radius: The radius of the cylinder
|
|
396
|
+
half_height: The half height of the cylinder
|
|
397
|
+
name: A name for the USD prim on the stage
|
|
398
|
+
color: The color of the cylinder
|
|
399
|
+
"""
|
|
400
|
+
|
|
401
|
+
from pxr import Gf, Sdf, UsdGeom
|
|
402
|
+
|
|
403
|
+
if is_template:
|
|
404
|
+
prim_path = self._resolve_path(name, parent_body, is_template)
|
|
405
|
+
blueprint = UsdGeom.Scope.Define(self.stage, prim_path)
|
|
406
|
+
blueprint_prim = blueprint.GetPrim()
|
|
407
|
+
blueprint_prim.SetInstanceable(True)
|
|
408
|
+
blueprint_prim.SetSpecifier(Sdf.SpecifierClass)
|
|
409
|
+
cylinder_path = prim_path.AppendChild("cylinder")
|
|
410
|
+
else:
|
|
411
|
+
cylinder_path = self._resolve_path(name, parent_body)
|
|
412
|
+
prim_path = cylinder_path
|
|
413
|
+
|
|
414
|
+
cylinder = UsdGeom.Cylinder.Get(self.stage, cylinder_path)
|
|
415
|
+
if not cylinder:
|
|
416
|
+
cylinder = UsdGeom.Cylinder.Define(self.stage, cylinder_path)
|
|
417
|
+
_usd_add_xform(cylinder)
|
|
418
|
+
|
|
419
|
+
cylinder.GetRadiusAttr().Set(float(radius))
|
|
420
|
+
cylinder.GetHeightAttr().Set(float(half_height * 2.0))
|
|
421
|
+
cylinder.GetAxisAttr().Set("Y")
|
|
422
|
+
|
|
423
|
+
if color is not None:
|
|
424
|
+
cylinder.GetDisplayColorAttr().Set([Gf.Vec3f(color)], self.time)
|
|
425
|
+
|
|
426
|
+
self._shape_constructors[name] = UsdGeom.Cylinder
|
|
427
|
+
|
|
428
|
+
if not is_template:
|
|
429
|
+
_usd_set_xform(cylinder, pos, rot, (1.0, 1.0, 1.0), self.time)
|
|
430
|
+
|
|
431
|
+
return prim_path
|
|
432
|
+
|
|
433
|
+
def render_cone(
|
|
434
|
+
self,
|
|
435
|
+
name: str,
|
|
436
|
+
pos: tuple,
|
|
437
|
+
rot: tuple,
|
|
438
|
+
radius: float,
|
|
439
|
+
half_height: float,
|
|
440
|
+
parent_body: str = None,
|
|
441
|
+
is_template: bool = False,
|
|
442
|
+
color: tuple = None,
|
|
443
|
+
):
|
|
444
|
+
"""
|
|
445
|
+
Debug helper to add a cone for visualization
|
|
446
|
+
|
|
447
|
+
Args:
|
|
448
|
+
pos: The position of the cone
|
|
449
|
+
radius: The radius of the cone
|
|
450
|
+
half_height: The half height of the cone
|
|
451
|
+
name: A name for the USD prim on the stage
|
|
452
|
+
color: The color of the cone
|
|
453
|
+
"""
|
|
454
|
+
|
|
455
|
+
from pxr import Gf, Sdf, UsdGeom
|
|
456
|
+
|
|
457
|
+
if is_template:
|
|
458
|
+
prim_path = self._resolve_path(name, parent_body, is_template)
|
|
459
|
+
blueprint = UsdGeom.Scope.Define(self.stage, prim_path)
|
|
460
|
+
blueprint_prim = blueprint.GetPrim()
|
|
461
|
+
blueprint_prim.SetInstanceable(True)
|
|
462
|
+
blueprint_prim.SetSpecifier(Sdf.SpecifierClass)
|
|
463
|
+
cone_path = prim_path.AppendChild("cone")
|
|
464
|
+
else:
|
|
465
|
+
cone_path = self._resolve_path(name, parent_body)
|
|
466
|
+
prim_path = cone_path
|
|
467
|
+
|
|
468
|
+
cone = UsdGeom.Cone.Get(self.stage, cone_path)
|
|
469
|
+
if not cone:
|
|
470
|
+
cone = UsdGeom.Cone.Define(self.stage, cone_path)
|
|
471
|
+
_usd_add_xform(cone)
|
|
472
|
+
|
|
473
|
+
cone.GetRadiusAttr().Set(float(radius))
|
|
474
|
+
cone.GetHeightAttr().Set(float(half_height * 2.0))
|
|
475
|
+
cone.GetAxisAttr().Set("Y")
|
|
476
|
+
|
|
477
|
+
if color is not None:
|
|
478
|
+
cone.GetDisplayColorAttr().Set([Gf.Vec3f(color)], self.time)
|
|
479
|
+
|
|
480
|
+
self._shape_constructors[name] = UsdGeom.Cone
|
|
481
|
+
|
|
482
|
+
if not is_template:
|
|
483
|
+
_usd_set_xform(cone, pos, rot, (1.0, 1.0, 1.0), self.time)
|
|
484
|
+
|
|
485
|
+
return prim_path
|
|
486
|
+
|
|
487
|
+
def render_box(
|
|
488
|
+
self,
|
|
489
|
+
name: str,
|
|
490
|
+
pos: tuple,
|
|
491
|
+
rot: tuple,
|
|
492
|
+
extents: tuple,
|
|
493
|
+
parent_body: str = None,
|
|
494
|
+
is_template: bool = False,
|
|
495
|
+
color: tuple = None,
|
|
496
|
+
):
|
|
497
|
+
"""Debug helper to add a box for visualization
|
|
498
|
+
|
|
499
|
+
Args:
|
|
500
|
+
pos: The position of the box
|
|
501
|
+
extents: The radius of the box
|
|
502
|
+
name: A name for the USD prim on the stage
|
|
503
|
+
color: The color of the box
|
|
504
|
+
"""
|
|
505
|
+
|
|
506
|
+
from pxr import Gf, Sdf, UsdGeom
|
|
507
|
+
|
|
508
|
+
if is_template:
|
|
509
|
+
prim_path = self._resolve_path(name, parent_body, is_template)
|
|
510
|
+
blueprint = UsdGeom.Scope.Define(self.stage, prim_path)
|
|
511
|
+
blueprint_prim = blueprint.GetPrim()
|
|
512
|
+
blueprint_prim.SetInstanceable(True)
|
|
513
|
+
blueprint_prim.SetSpecifier(Sdf.SpecifierClass)
|
|
514
|
+
cube_path = prim_path.AppendChild("cube")
|
|
515
|
+
else:
|
|
516
|
+
cube_path = self._resolve_path(name, parent_body)
|
|
517
|
+
prim_path = cube_path
|
|
518
|
+
|
|
519
|
+
cube = UsdGeom.Cube.Get(self.stage, cube_path)
|
|
520
|
+
if not cube:
|
|
521
|
+
cube = UsdGeom.Cube.Define(self.stage, cube_path)
|
|
522
|
+
_usd_add_xform(cube)
|
|
523
|
+
|
|
524
|
+
if color is not None:
|
|
525
|
+
cube.GetDisplayColorAttr().Set([Gf.Vec3f(color)], self.time)
|
|
526
|
+
|
|
527
|
+
self._shape_constructors[name] = UsdGeom.Cube
|
|
528
|
+
self._shape_custom_scale[name] = extents
|
|
529
|
+
|
|
530
|
+
if not is_template:
|
|
531
|
+
_usd_set_xform(cube, pos, rot, extents, self.time)
|
|
532
|
+
|
|
533
|
+
return prim_path
|
|
534
|
+
|
|
535
|
+
def render_ref(self, name: str, path: str, pos: tuple, rot: tuple, scale: tuple, color: tuple = None):
|
|
536
|
+
from pxr import Gf, Usd, UsdGeom
|
|
537
|
+
|
|
538
|
+
ref_path = "/root/" + name
|
|
539
|
+
|
|
540
|
+
ref = UsdGeom.Xform.Get(self.stage, ref_path)
|
|
541
|
+
if not ref:
|
|
542
|
+
ref = UsdGeom.Xform.Define(self.stage, ref_path)
|
|
543
|
+
ref.GetPrim().GetReferences().AddReference(path)
|
|
544
|
+
_usd_add_xform(ref)
|
|
545
|
+
|
|
546
|
+
# update transform
|
|
547
|
+
_usd_set_xform(ref, pos, rot, scale, self.time)
|
|
548
|
+
|
|
549
|
+
if color is not None:
|
|
550
|
+
it = iter(Usd.PrimRange(ref.GetPrim()))
|
|
551
|
+
for prim in it:
|
|
552
|
+
if prim.IsA(UsdGeom.Gprim):
|
|
553
|
+
UsdGeom.Gprim(prim).GetDisplayColorAttr().Set([Gf.Vec3f(color)], self.time)
|
|
554
|
+
it.PruneChildren()
|
|
555
|
+
|
|
556
|
+
def render_mesh(
|
|
557
|
+
self,
|
|
558
|
+
name: str,
|
|
559
|
+
points,
|
|
560
|
+
indices,
|
|
561
|
+
colors=None,
|
|
562
|
+
pos=(0.0, 0.0, 0.0),
|
|
563
|
+
rot=(0.0, 0.0, 0.0, 1.0),
|
|
564
|
+
scale=(1.0, 1.0, 1.0),
|
|
565
|
+
update_topology=False,
|
|
566
|
+
parent_body: str = None,
|
|
567
|
+
is_template: bool = False,
|
|
568
|
+
):
|
|
569
|
+
from pxr import Sdf, UsdGeom
|
|
570
|
+
|
|
571
|
+
if is_template:
|
|
572
|
+
prim_path = self._resolve_path(name, parent_body, is_template)
|
|
573
|
+
blueprint = UsdGeom.Scope.Define(self.stage, prim_path)
|
|
574
|
+
blueprint_prim = blueprint.GetPrim()
|
|
575
|
+
blueprint_prim.SetInstanceable(True)
|
|
576
|
+
blueprint_prim.SetSpecifier(Sdf.SpecifierClass)
|
|
577
|
+
mesh_path = prim_path.AppendChild("mesh")
|
|
578
|
+
else:
|
|
579
|
+
mesh_path = self._resolve_path(name, parent_body)
|
|
580
|
+
prim_path = mesh_path
|
|
581
|
+
|
|
582
|
+
mesh = UsdGeom.Mesh.Get(self.stage, mesh_path)
|
|
583
|
+
if not mesh:
|
|
584
|
+
mesh = UsdGeom.Mesh.Define(self.stage, mesh_path)
|
|
585
|
+
UsdGeom.Primvar(mesh.GetDisplayColorAttr()).SetInterpolation("vertex")
|
|
586
|
+
_usd_add_xform(mesh)
|
|
587
|
+
|
|
588
|
+
# force topology update on first frame
|
|
589
|
+
update_topology = True
|
|
590
|
+
|
|
591
|
+
mesh.GetPointsAttr().Set(points, self.time)
|
|
592
|
+
|
|
593
|
+
if update_topology:
|
|
594
|
+
idxs = np.array(indices).reshape(-1, 3)
|
|
595
|
+
mesh.GetFaceVertexIndicesAttr().Set(idxs, self.time)
|
|
596
|
+
mesh.GetFaceVertexCountsAttr().Set([3] * len(idxs), self.time)
|
|
597
|
+
|
|
598
|
+
if colors:
|
|
599
|
+
mesh.GetDisplayColorAttr().Set(colors, self.time)
|
|
600
|
+
|
|
601
|
+
self._shape_constructors[name] = UsdGeom.Mesh
|
|
602
|
+
self._shape_custom_scale[name] = scale
|
|
603
|
+
|
|
604
|
+
if not is_template:
|
|
605
|
+
_usd_set_xform(mesh, pos, rot, scale, self.time)
|
|
606
|
+
|
|
607
|
+
return prim_path
|
|
608
|
+
|
|
609
|
+
def render_line_list(self, name, vertices, indices, color, radius):
|
|
610
|
+
"""Debug helper to add a line list as a set of capsules
|
|
611
|
+
|
|
612
|
+
Args:
|
|
613
|
+
vertices: The vertices of the line-strip
|
|
614
|
+
color: The color of the line
|
|
615
|
+
time: The time to update at
|
|
616
|
+
"""
|
|
617
|
+
|
|
618
|
+
from pxr import Gf, UsdGeom
|
|
619
|
+
|
|
620
|
+
num_lines = int(len(indices) / 2)
|
|
621
|
+
|
|
622
|
+
if num_lines < 1:
|
|
623
|
+
return
|
|
624
|
+
|
|
625
|
+
# look up rope point instancer
|
|
626
|
+
instancer_path = self.root.GetPath().AppendChild(name)
|
|
627
|
+
instancer = UsdGeom.PointInstancer.Get(self.stage, instancer_path)
|
|
628
|
+
|
|
629
|
+
if not instancer:
|
|
630
|
+
instancer = UsdGeom.PointInstancer.Define(self.stage, instancer_path)
|
|
631
|
+
instancer_capsule = UsdGeom.Capsule.Define(self.stage, instancer.GetPath().AppendChild("capsule"))
|
|
632
|
+
instancer_capsule.GetRadiusAttr().Set(radius)
|
|
633
|
+
instancer.CreatePrototypesRel().SetTargets([instancer_capsule.GetPath()])
|
|
634
|
+
# instancer.CreatePrimvar("displayColor", Sdf.ValueTypeNames.Float3Array, "constant", 1)
|
|
635
|
+
|
|
636
|
+
line_positions = []
|
|
637
|
+
line_rotations = []
|
|
638
|
+
line_scales = []
|
|
639
|
+
|
|
640
|
+
for i in range(num_lines):
|
|
641
|
+
pos0 = vertices[indices[i * 2 + 0]]
|
|
642
|
+
pos1 = vertices[indices[i * 2 + 1]]
|
|
643
|
+
|
|
644
|
+
(pos, rot, scale) = _compute_segment_xform(
|
|
645
|
+
Gf.Vec3f(float(pos0[0]), float(pos0[1]), float(pos0[2])),
|
|
646
|
+
Gf.Vec3f(float(pos1[0]), float(pos1[1]), float(pos1[2])),
|
|
647
|
+
)
|
|
648
|
+
|
|
649
|
+
line_positions.append(pos)
|
|
650
|
+
line_rotations.append(rot)
|
|
651
|
+
line_scales.append(scale)
|
|
652
|
+
# line_colors.append(Gf.Vec3f((float(i)/num_lines, 0.5, 0.5)))
|
|
653
|
+
|
|
654
|
+
instancer.GetPositionsAttr().Set(line_positions, self.time)
|
|
655
|
+
instancer.GetOrientationsAttr().Set(line_rotations, self.time)
|
|
656
|
+
instancer.GetScalesAttr().Set(line_scales, self.time)
|
|
657
|
+
instancer.GetProtoIndicesAttr().Set([0] * num_lines, self.time)
|
|
658
|
+
|
|
659
|
+
# instancer.GetPrimvar("displayColor").Set(line_colors, time)
|
|
660
|
+
|
|
661
|
+
def render_line_strip(self, name: str, vertices, color: tuple, radius: float = 0.01):
|
|
662
|
+
from pxr import Gf, UsdGeom
|
|
663
|
+
|
|
664
|
+
num_lines = int(len(vertices) - 1)
|
|
665
|
+
|
|
666
|
+
if num_lines < 1:
|
|
667
|
+
return
|
|
668
|
+
|
|
669
|
+
# look up rope point instancer
|
|
670
|
+
instancer_path = self.root.GetPath().AppendChild(name)
|
|
671
|
+
instancer = UsdGeom.PointInstancer.Get(self.stage, instancer_path)
|
|
672
|
+
|
|
673
|
+
if not instancer:
|
|
674
|
+
instancer = UsdGeom.PointInstancer.Define(self.stage, instancer_path)
|
|
675
|
+
instancer_capsule = UsdGeom.Capsule.Define(self.stage, instancer.GetPath().AppendChild("capsule"))
|
|
676
|
+
instancer_capsule.GetRadiusAttr().Set(radius)
|
|
677
|
+
instancer.CreatePrototypesRel().SetTargets([instancer_capsule.GetPath()])
|
|
678
|
+
|
|
679
|
+
line_positions = []
|
|
680
|
+
line_rotations = []
|
|
681
|
+
line_scales = []
|
|
682
|
+
|
|
683
|
+
for i in range(num_lines):
|
|
684
|
+
pos0 = vertices[i]
|
|
685
|
+
pos1 = vertices[i + 1]
|
|
686
|
+
|
|
687
|
+
(pos, rot, scale) = _compute_segment_xform(
|
|
688
|
+
Gf.Vec3f(float(pos0[0]), float(pos0[1]), float(pos0[2])),
|
|
689
|
+
Gf.Vec3f(float(pos1[0]), float(pos1[1]), float(pos1[2])),
|
|
690
|
+
)
|
|
691
|
+
|
|
692
|
+
line_positions.append(pos)
|
|
693
|
+
line_rotations.append(rot)
|
|
694
|
+
line_scales.append(scale)
|
|
695
|
+
|
|
696
|
+
instancer.GetPositionsAttr().Set(line_positions, self.time)
|
|
697
|
+
instancer.GetOrientationsAttr().Set(line_rotations, self.time)
|
|
698
|
+
instancer.GetScalesAttr().Set(line_scales, self.time)
|
|
699
|
+
instancer.GetProtoIndicesAttr().Set([0] * num_lines, self.time)
|
|
700
|
+
|
|
701
|
+
instancer_capsule = UsdGeom.Capsule.Get(self.stage, instancer.GetPath().AppendChild("capsule"))
|
|
702
|
+
instancer_capsule.GetDisplayColorAttr().Set([Gf.Vec3f(color)], self.time)
|
|
703
|
+
|
|
704
|
+
def render_points(self, name: str, points, radius, colors=None):
|
|
705
|
+
from pxr import Gf, UsdGeom
|
|
706
|
+
|
|
707
|
+
instancer_path = self.root.GetPath().AppendChild(name)
|
|
708
|
+
instancer = UsdGeom.PointInstancer.Get(self.stage, instancer_path)
|
|
709
|
+
radius_is_scalar = np.isscalar(radius)
|
|
710
|
+
if not instancer:
|
|
711
|
+
if colors is None or len(colors) == 3:
|
|
712
|
+
instancer = UsdGeom.PointInstancer.Define(self.stage, instancer_path)
|
|
713
|
+
instancer_sphere = UsdGeom.Sphere.Define(self.stage, instancer.GetPath().AppendChild("sphere"))
|
|
714
|
+
if radius_is_scalar:
|
|
715
|
+
instancer_sphere.GetRadiusAttr().Set(radius)
|
|
716
|
+
else:
|
|
717
|
+
instancer_sphere.GetRadiusAttr().Set(1.0)
|
|
718
|
+
instancer.GetScalesAttr().Set(np.tile(radius, (3, 1)).T)
|
|
719
|
+
|
|
720
|
+
if colors is not None:
|
|
721
|
+
instancer_sphere.GetDisplayColorAttr().Set([Gf.Vec3f(colors)], self.time)
|
|
722
|
+
|
|
723
|
+
instancer.CreatePrototypesRel().SetTargets([instancer_sphere.GetPath()])
|
|
724
|
+
instancer.CreateProtoIndicesAttr().Set([0] * len(points))
|
|
725
|
+
|
|
726
|
+
# set identity rotations
|
|
727
|
+
quats = [Gf.Quath(1.0, 0.0, 0.0, 0.0)] * len(points)
|
|
728
|
+
instancer.GetOrientationsAttr().Set(quats, self.time)
|
|
729
|
+
else:
|
|
730
|
+
instancer = UsdGeom.Points.Define(self.stage, instancer_path)
|
|
731
|
+
|
|
732
|
+
if radius_is_scalar:
|
|
733
|
+
instancer.GetWidthsAttr().Set([radius * 2.0] * len(points))
|
|
734
|
+
else:
|
|
735
|
+
instancer.GetWidthsAttr().Set(radius * 2.0)
|
|
736
|
+
|
|
737
|
+
if colors is None or len(colors) == 3:
|
|
738
|
+
instancer.GetPositionsAttr().Set(points, self.time)
|
|
739
|
+
else:
|
|
740
|
+
instancer.GetPointsAttr().Set(points, self.time)
|
|
741
|
+
instancer.GetDisplayColorAttr().Set(colors, self.time)
|
|
742
|
+
|
|
743
|
+
def update_body_transforms(self, body_q):
|
|
744
|
+
from pxr import Sdf, UsdGeom
|
|
745
|
+
|
|
746
|
+
if isinstance(body_q, wp.array):
|
|
747
|
+
body_q = body_q.numpy()
|
|
748
|
+
|
|
749
|
+
with Sdf.ChangeBlock():
|
|
750
|
+
for b in range(self.model.body_count):
|
|
751
|
+
node_name = self.body_names[b]
|
|
752
|
+
node = UsdGeom.Xform(self.stage.GetPrimAtPath(self.root.GetPath().AppendChild(node_name)))
|
|
753
|
+
|
|
754
|
+
# unpack rigid transform
|
|
755
|
+
X_sb = wp.transform_expand(body_q[b])
|
|
756
|
+
|
|
757
|
+
_usd_set_xform(node, X_sb.p, X_sb.q, (1.0, 1.0, 1.0), self.time)
|
|
758
|
+
|
|
759
|
+
def save(self):
|
|
760
|
+
try:
|
|
761
|
+
self.stage.Save()
|
|
762
|
+
except Exception as e:
|
|
763
|
+
print("Failed to save USD stage:", e)
|
|
764
|
+
return False
|
|
765
|
+
|
|
766
|
+
file_path = self.stage.GetRootLayer().realPath
|
|
767
|
+
print(f"Saved the USD stage file at `{file_path}`")
|
|
768
|
+
return True
|