warp-lang 0.11.0__py3-none-manylinux2014_x86_64.whl → 1.0.0__py3-none-manylinux2014_x86_64.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.

Files changed (170) hide show
  1. warp/__init__.py +8 -0
  2. warp/bin/warp-clang.so +0 -0
  3. warp/bin/warp.so +0 -0
  4. warp/build.py +7 -6
  5. warp/build_dll.py +70 -79
  6. warp/builtins.py +10 -6
  7. warp/codegen.py +51 -19
  8. warp/config.py +7 -8
  9. warp/constants.py +3 -0
  10. warp/context.py +948 -245
  11. warp/dlpack.py +198 -113
  12. warp/examples/assets/bunny.usd +0 -0
  13. warp/examples/assets/cartpole.urdf +110 -0
  14. warp/examples/assets/crazyflie.usd +0 -0
  15. warp/examples/assets/cube.usda +42 -0
  16. warp/examples/assets/nv_ant.xml +92 -0
  17. warp/examples/assets/nv_humanoid.xml +183 -0
  18. warp/examples/assets/quadruped.urdf +268 -0
  19. warp/examples/assets/rocks.nvdb +0 -0
  20. warp/examples/assets/rocks.usd +0 -0
  21. warp/examples/assets/sphere.usda +56 -0
  22. warp/examples/assets/torus.usda +105 -0
  23. warp/examples/benchmarks/benchmark_api.py +383 -0
  24. warp/examples/benchmarks/benchmark_cloth.py +279 -0
  25. warp/examples/benchmarks/benchmark_cloth_cupy.py +88 -0
  26. warp/examples/benchmarks/benchmark_cloth_jax.py +100 -0
  27. warp/examples/benchmarks/benchmark_cloth_numba.py +142 -0
  28. warp/examples/benchmarks/benchmark_cloth_numpy.py +77 -0
  29. warp/examples/benchmarks/benchmark_cloth_pytorch.py +86 -0
  30. warp/examples/benchmarks/benchmark_cloth_taichi.py +112 -0
  31. warp/examples/benchmarks/benchmark_cloth_warp.py +146 -0
  32. warp/examples/benchmarks/benchmark_launches.py +295 -0
  33. warp/examples/core/example_dem.py +221 -0
  34. warp/examples/core/example_fluid.py +267 -0
  35. warp/examples/core/example_graph_capture.py +129 -0
  36. warp/examples/core/example_marching_cubes.py +177 -0
  37. warp/examples/core/example_mesh.py +154 -0
  38. warp/examples/core/example_mesh_intersect.py +193 -0
  39. warp/examples/core/example_nvdb.py +169 -0
  40. warp/examples/core/example_raycast.py +89 -0
  41. warp/examples/core/example_raymarch.py +178 -0
  42. warp/examples/core/example_render_opengl.py +141 -0
  43. warp/examples/core/example_sph.py +389 -0
  44. warp/examples/core/example_torch.py +181 -0
  45. warp/examples/core/example_wave.py +249 -0
  46. warp/examples/fem/bsr_utils.py +380 -0
  47. warp/examples/fem/example_apic_fluid.py +391 -0
  48. warp/examples/fem/example_convection_diffusion.py +168 -0
  49. warp/examples/fem/example_convection_diffusion_dg.py +209 -0
  50. warp/examples/fem/example_convection_diffusion_dg0.py +194 -0
  51. warp/examples/fem/example_deformed_geometry.py +159 -0
  52. warp/examples/fem/example_diffusion.py +173 -0
  53. warp/examples/fem/example_diffusion_3d.py +152 -0
  54. warp/examples/fem/example_diffusion_mgpu.py +214 -0
  55. warp/examples/fem/example_mixed_elasticity.py +222 -0
  56. warp/examples/fem/example_navier_stokes.py +243 -0
  57. warp/examples/fem/example_stokes.py +192 -0
  58. warp/examples/fem/example_stokes_transfer.py +249 -0
  59. warp/examples/fem/mesh_utils.py +109 -0
  60. warp/examples/fem/plot_utils.py +287 -0
  61. warp/examples/optim/example_bounce.py +248 -0
  62. warp/examples/optim/example_cloth_throw.py +210 -0
  63. warp/examples/optim/example_diffray.py +535 -0
  64. warp/examples/optim/example_drone.py +850 -0
  65. warp/examples/optim/example_inverse_kinematics.py +169 -0
  66. warp/examples/optim/example_inverse_kinematics_torch.py +170 -0
  67. warp/examples/optim/example_spring_cage.py +234 -0
  68. warp/examples/optim/example_trajectory.py +201 -0
  69. warp/examples/sim/example_cartpole.py +128 -0
  70. warp/examples/sim/example_cloth.py +184 -0
  71. warp/examples/sim/example_granular.py +113 -0
  72. warp/examples/sim/example_granular_collision_sdf.py +185 -0
  73. warp/examples/sim/example_jacobian_ik.py +213 -0
  74. warp/examples/sim/example_particle_chain.py +106 -0
  75. warp/examples/sim/example_quadruped.py +179 -0
  76. warp/examples/sim/example_rigid_chain.py +191 -0
  77. warp/examples/sim/example_rigid_contact.py +176 -0
  78. warp/examples/sim/example_rigid_force.py +126 -0
  79. warp/examples/sim/example_rigid_gyroscopic.py +97 -0
  80. warp/examples/sim/example_rigid_soft_contact.py +124 -0
  81. warp/examples/sim/example_soft_body.py +178 -0
  82. warp/fabric.py +29 -20
  83. warp/fem/cache.py +0 -1
  84. warp/fem/dirichlet.py +0 -2
  85. warp/fem/integrate.py +0 -1
  86. warp/jax.py +45 -0
  87. warp/jax_experimental.py +339 -0
  88. warp/native/builtin.h +12 -0
  89. warp/native/bvh.cu +18 -18
  90. warp/native/clang/clang.cpp +8 -3
  91. warp/native/cuda_util.cpp +94 -5
  92. warp/native/cuda_util.h +35 -6
  93. warp/native/cutlass_gemm.cpp +1 -1
  94. warp/native/cutlass_gemm.cu +4 -1
  95. warp/native/error.cpp +66 -0
  96. warp/native/error.h +27 -0
  97. warp/native/mesh.cu +2 -2
  98. warp/native/reduce.cu +4 -4
  99. warp/native/runlength_encode.cu +2 -2
  100. warp/native/scan.cu +2 -2
  101. warp/native/sparse.cu +0 -1
  102. warp/native/temp_buffer.h +2 -2
  103. warp/native/warp.cpp +95 -60
  104. warp/native/warp.cu +1053 -218
  105. warp/native/warp.h +49 -32
  106. warp/optim/linear.py +33 -16
  107. warp/render/render_opengl.py +202 -101
  108. warp/render/render_usd.py +82 -40
  109. warp/sim/__init__.py +13 -4
  110. warp/sim/articulation.py +4 -5
  111. warp/sim/collide.py +320 -175
  112. warp/sim/import_mjcf.py +25 -30
  113. warp/sim/import_urdf.py +94 -63
  114. warp/sim/import_usd.py +51 -36
  115. warp/sim/inertia.py +3 -2
  116. warp/sim/integrator.py +233 -0
  117. warp/sim/integrator_euler.py +447 -469
  118. warp/sim/integrator_featherstone.py +1991 -0
  119. warp/sim/integrator_xpbd.py +1420 -640
  120. warp/sim/model.py +765 -487
  121. warp/sim/particles.py +2 -1
  122. warp/sim/render.py +35 -13
  123. warp/sim/utils.py +222 -11
  124. warp/stubs.py +8 -0
  125. warp/tape.py +16 -1
  126. warp/tests/aux_test_grad_customs.py +23 -0
  127. warp/tests/test_array.py +190 -1
  128. warp/tests/test_async.py +656 -0
  129. warp/tests/test_bool.py +50 -0
  130. warp/tests/test_dlpack.py +164 -11
  131. warp/tests/test_examples.py +166 -74
  132. warp/tests/test_fem.py +8 -1
  133. warp/tests/test_generics.py +15 -5
  134. warp/tests/test_grad.py +1 -1
  135. warp/tests/test_grad_customs.py +172 -12
  136. warp/tests/test_jax.py +254 -0
  137. warp/tests/test_large.py +29 -6
  138. warp/tests/test_launch.py +25 -0
  139. warp/tests/test_linear_solvers.py +20 -3
  140. warp/tests/test_matmul.py +61 -16
  141. warp/tests/test_matmul_lite.py +13 -13
  142. warp/tests/test_mempool.py +186 -0
  143. warp/tests/test_multigpu.py +3 -0
  144. warp/tests/test_options.py +16 -2
  145. warp/tests/test_peer.py +137 -0
  146. warp/tests/test_print.py +3 -1
  147. warp/tests/test_quat.py +23 -0
  148. warp/tests/test_sim_kinematics.py +97 -0
  149. warp/tests/test_snippet.py +126 -3
  150. warp/tests/test_streams.py +108 -79
  151. warp/tests/test_torch.py +16 -8
  152. warp/tests/test_utils.py +32 -27
  153. warp/tests/test_verify_fp.py +65 -0
  154. warp/tests/test_volume.py +1 -1
  155. warp/tests/unittest_serial.py +2 -0
  156. warp/tests/unittest_suites.py +12 -0
  157. warp/tests/unittest_utils.py +14 -7
  158. warp/thirdparty/unittest_parallel.py +15 -3
  159. warp/torch.py +10 -8
  160. warp/types.py +363 -246
  161. warp/utils.py +143 -19
  162. warp_lang-1.0.0.dist-info/LICENSE.md +126 -0
  163. warp_lang-1.0.0.dist-info/METADATA +394 -0
  164. {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/RECORD +167 -86
  165. warp/sim/optimizer.py +0 -138
  166. warp_lang-0.11.0.dist-info/LICENSE.md +0 -36
  167. warp_lang-0.11.0.dist-info/METADATA +0 -238
  168. /warp/tests/{walkthough_debug.py → walkthrough_debug.py} +0 -0
  169. {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/WHEEL +0 -0
  170. {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,181 @@
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
+ ###########################################################################
9
+ # Example Torch
10
+ #
11
+ # Optimizes the Rosenbrock function using the PyTorch Adam optimizer
12
+ # The Rosenbrock function is a non-convex function, and is often used
13
+ # to test optimization algorithms. The function is defined as:
14
+ # f(x, y) = (a - x)^2 + b * (y - x^2)^2
15
+ # where a = 1 and b = 100. The minimum value of the function is 0 at (1, 1).
16
+ #
17
+ # The example demonstrates how to set up a torch.autograd.Function to
18
+ # incorporate Warp kernel launches within a PyTorch graph.
19
+ ###########################################################################
20
+
21
+ import warp as wp
22
+ import numpy as np
23
+ import matplotlib.pyplot as plt
24
+ from matplotlib.animation import FuncAnimation
25
+ import torch
26
+
27
+ wp.init()
28
+
29
+
30
+ pvec2 = wp.types.vector(length=2, dtype=wp.float32)
31
+
32
+ # Define the Rosenbrock function
33
+ @wp.func
34
+ def rosenbrock(x: float, y: float):
35
+ return (1.0 - x) ** 2.0 + 100.0 * (y - x**2.0) ** 2.0
36
+
37
+ @wp.kernel
38
+ def eval_rosenbrock(
39
+ xs: wp.array(dtype=pvec2),
40
+ # outputs
41
+ z: wp.array(dtype=float),
42
+ ):
43
+ i = wp.tid()
44
+ x = xs[i]
45
+ z[i] = rosenbrock(x[0], x[1])
46
+
47
+
48
+ class Rosenbrock(torch.autograd.Function):
49
+ @staticmethod
50
+ def forward(ctx, xy, num_particles):
51
+
52
+ ctx.xy = wp.from_torch(xy, dtype=pvec2, requires_grad=True)
53
+ ctx.num_particles = num_particles
54
+
55
+ # allocate output
56
+ ctx.z = wp.zeros(num_particles, requires_grad=True)
57
+
58
+ wp.launch(
59
+ kernel=eval_rosenbrock,
60
+ dim=ctx.num_particles,
61
+ inputs=[ctx.xy],
62
+ outputs=[ctx.z]
63
+ )
64
+
65
+ return wp.to_torch(ctx.z)
66
+
67
+ @staticmethod
68
+ def backward(ctx, adj_z):
69
+
70
+ # map incoming Torch grads to our output variables
71
+ ctx.z.grad = wp.from_torch(adj_z)
72
+
73
+ wp.launch(
74
+ kernel=eval_rosenbrock,
75
+ dim=ctx.num_particles,
76
+ inputs=[ctx.xy],
77
+ outputs=[ctx.z],
78
+ adj_inputs=[ctx.xy.grad],
79
+ adj_outputs=[ctx.z.grad],
80
+ adjoint=True
81
+ )
82
+
83
+ # return adjoint w.r.t. inputs
84
+ return (wp.to_torch(ctx.xy.grad), None)
85
+
86
+
87
+ class Example:
88
+
89
+ def __init__(self):
90
+
91
+ self.num_particles = 1500
92
+
93
+ min_x, max_x = -2.0, 2.0
94
+ min_y, max_y = -2.0, 2.0
95
+
96
+ # Create a grid of points
97
+ x = np.linspace(min_x, max_x, 100)
98
+ y = np.linspace(min_y, max_y, 100)
99
+ X, Y = np.meshgrid(x, y)
100
+ xy = np.column_stack((X.flatten(), Y.flatten()))
101
+ N = len(xy)
102
+
103
+ xy = wp.array(xy, dtype=pvec2)
104
+ Z = wp.empty(N, dtype=wp.float32)
105
+
106
+ wp.launch(eval_rosenbrock, dim=N, inputs=[xy], outputs=[Z])
107
+ Z = Z.numpy().reshape(X.shape)
108
+
109
+ # Plot the function as a heatmap
110
+ self.fig = plt.figure(figsize=(6, 6))
111
+ ax = plt.gca()
112
+ plt.imshow(
113
+ Z,
114
+ extent=[min_x, max_x, min_y, max_y],
115
+ origin="lower",
116
+ interpolation="bicubic",
117
+ cmap="coolwarm",
118
+ )
119
+ plt.contour(
120
+ X,
121
+ Y,
122
+ Z,
123
+ extent=[min_x, max_x, min_y, max_y],
124
+ levels=150,
125
+ colors="k",
126
+ alpha=0.5,
127
+ linewidths=0.5,
128
+ )
129
+
130
+ plt.title("Rosenbrock function")
131
+ plt.xlabel("x")
132
+ plt.ylabel("y")
133
+
134
+ # Create a scatter plot (initially empty)
135
+ self.scat = ax.scatter([], [], c="k", s=2)
136
+
137
+ # Plot optimum
138
+ plt.plot(1, 1, "*", color="r", markersize=10)
139
+
140
+ self.learning_rate = 5e-2
141
+
142
+ self.torch_device = wp.device_to_torch(wp.get_device())
143
+
144
+ rng = np.random.default_rng(42)
145
+ self.xy = torch.tensor(rng.normal(size=(self.num_particles, 2)), dtype=torch.float32, requires_grad=True, device=self.torch_device)
146
+ self.opt = torch.optim.Adam([self.xy], lr=self.learning_rate)
147
+
148
+ def forward(self):
149
+ self.z = Rosenbrock.apply(self.xy, self.num_particles)
150
+
151
+ def step(self):
152
+ self.opt.zero_grad()
153
+ self.forward()
154
+ self.z.backward(torch.ones_like(self.z))
155
+
156
+ self.opt.step()
157
+
158
+ def render(self):
159
+ # Update the scatter plot
160
+ xy_np = self.xy.numpy(force=True)
161
+ self.scat.set_offsets(np.c_[xy_np[:, 0], xy_np[:, 1]])
162
+
163
+ print(f"\rParticle mean: {np.mean(xy_np, axis=0)} ", end="")
164
+
165
+ # Function to update the scatter plot
166
+ def step_and_render(self, frame):
167
+ for _ in range(10):
168
+ self.step()
169
+
170
+ self.render()
171
+
172
+
173
+ if __name__ == "__main__":
174
+
175
+ example = Example()
176
+
177
+ # Create the animation
178
+ ani = FuncAnimation(example.fig, example.step_and_render, frames=10000, interval=200)
179
+
180
+ # Display the animation
181
+ plt.show()
@@ -0,0 +1,249 @@
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
+ ###########################################################################
9
+ # Example Wave
10
+ #
11
+ # Shows how to implement a simple 2D wave-equation solver with collision
12
+ # against a moving sphere.
13
+ #
14
+ ###########################################################################
15
+
16
+ import math
17
+ import os
18
+
19
+ import warp as wp
20
+ import warp.render
21
+
22
+ wp.init()
23
+
24
+
25
+ @wp.func
26
+ def sample(f: wp.array(dtype=float), x: int, y: int, width: int, height: int):
27
+ # clamp texture coords
28
+ x = wp.clamp(x, 0, width - 1)
29
+ y = wp.clamp(y, 0, height - 1)
30
+
31
+ s = f[y * width + x]
32
+ return s
33
+
34
+
35
+ @wp.func
36
+ def laplacian(f: wp.array(dtype=float), x: int, y: int, width: int, height: int):
37
+ ddx = sample(f, x + 1, y, width, height) - 2.0 * sample(f, x, y, width, height) + sample(f, x - 1, y, width, height)
38
+ ddy = sample(f, x, y + 1, width, height) - 2.0 * sample(f, x, y, width, height) + sample(f, x, y - 1, width, height)
39
+
40
+ return ddx + ddy
41
+
42
+
43
+ @wp.kernel
44
+ def wave_displace(
45
+ hcurrent: wp.array(dtype=float),
46
+ hprevious: wp.array(dtype=float),
47
+ width: int,
48
+ height: int,
49
+ center_x: float,
50
+ center_y: float,
51
+ r: float,
52
+ mag: float,
53
+ t: float,
54
+ ):
55
+ tid = wp.tid()
56
+
57
+ x = tid % width
58
+ y = tid // width
59
+
60
+ dx = float(x) - center_x
61
+ dy = float(y) - center_y
62
+
63
+ dist_sq = float(dx * dx + dy * dy)
64
+
65
+ if dist_sq < r * r:
66
+ h = mag * wp.sin(t)
67
+
68
+ hcurrent[tid] = h
69
+ hprevious[tid] = h
70
+
71
+
72
+ @wp.kernel
73
+ def wave_solve(
74
+ hprevious: wp.array(dtype=float),
75
+ hcurrent: wp.array(dtype=float),
76
+ width: int,
77
+ height: int,
78
+ inv_cell: float,
79
+ k_speed: float,
80
+ k_damp: float,
81
+ dt: float,
82
+ ):
83
+ tid = wp.tid()
84
+
85
+ x = tid % width
86
+ y = tid // width
87
+
88
+ l = laplacian(hcurrent, x, y, width, height) * inv_cell * inv_cell
89
+
90
+ # integrate
91
+ h1 = hcurrent[tid]
92
+ h0 = hprevious[tid]
93
+
94
+ h = 2.0 * h1 - h0 + dt * dt * (k_speed * l - k_damp * (h1 - h0))
95
+
96
+ # buffers get swapped each iteration
97
+ hprevious[tid] = h
98
+
99
+
100
+ # simple kernel to apply height deltas to a vertex array
101
+ @wp.kernel
102
+ def grid_update(heights: wp.array(dtype=float), vertices: wp.array(dtype=wp.vec3)):
103
+ tid = wp.tid()
104
+
105
+ h = heights[tid]
106
+ v = vertices[tid]
107
+
108
+ v_new = wp.vec3(v[0], h, v[2])
109
+
110
+ vertices[tid] = v_new
111
+
112
+
113
+ class Example:
114
+ def __init__(self, stage):
115
+ self.sim_width = 128
116
+ self.sim_height = 128
117
+
118
+ self.sim_fps = 60.0
119
+ self.sim_substeps = 16
120
+ self.sim_duration = 5.0
121
+ self.sim_frames = int(self.sim_duration * self.sim_fps)
122
+ self.sim_dt = (1.0 / self.sim_fps) / self.sim_substeps
123
+ self.sim_time = 0.0
124
+
125
+ # wave constants
126
+ self.k_speed = 1.0
127
+ self.k_damp = 0.0
128
+
129
+ # grid constants
130
+ self.grid_size = 0.1
131
+ self.grid_displace = 0.5
132
+
133
+ vertices = []
134
+ self.indices = []
135
+
136
+ def grid_index(x, y, stride):
137
+ return y * stride + x
138
+
139
+ for z in range(self.sim_height):
140
+ for x in range(self.sim_width):
141
+ pos = (
142
+ float(x) * self.grid_size,
143
+ 0.0,
144
+ float(z) * self.grid_size,
145
+ )
146
+
147
+ # directly modifies verts_host memory since this is a numpy alias of the same buffer
148
+ vertices.append(pos)
149
+
150
+ if x > 0 and z > 0:
151
+ self.indices.append(grid_index(x - 1, z - 1, self.sim_width))
152
+ self.indices.append(grid_index(x, z, self.sim_width))
153
+ self.indices.append(grid_index(x, z - 1, self.sim_width))
154
+
155
+ self.indices.append(grid_index(x - 1, z - 1, self.sim_width))
156
+ self.indices.append(grid_index(x - 1, z, self.sim_width))
157
+ self.indices.append(grid_index(x, z, self.sim_width))
158
+
159
+ # simulation grids
160
+ self.sim_grid0 = wp.zeros(self.sim_width * self.sim_height, dtype=float)
161
+ self.sim_grid1 = wp.zeros(self.sim_width * self.sim_height, dtype=float)
162
+ self.sim_verts = wp.array(vertices, dtype=wp.vec3)
163
+
164
+ # create surface displacement around a point
165
+ self.cx = self.sim_width / 2 + math.sin(self.sim_time) * self.sim_width / 3
166
+ self.cy = self.sim_height / 2 + math.cos(self.sim_time) * self.sim_height / 3
167
+
168
+ self.renderer = None
169
+ if stage:
170
+ self.renderer = wp.render.UsdRenderer(stage)
171
+
172
+ def step(self):
173
+ with wp.ScopedTimer("step", active=True):
174
+ for s in range(self.sim_substeps):
175
+ # create surface displacement around a point
176
+ self.cx = self.sim_width / 2 + math.sin(self.sim_time) * self.sim_width / 3
177
+ self.cy = self.sim_height / 2 + math.cos(self.sim_time) * self.sim_height / 3
178
+
179
+ wp.launch(
180
+ kernel=wave_displace,
181
+ dim=self.sim_width * self.sim_height,
182
+ inputs=[
183
+ self.sim_grid0,
184
+ self.sim_grid1,
185
+ self.sim_width,
186
+ self.sim_height,
187
+ self.cx,
188
+ self.cy,
189
+ 10.0,
190
+ self.grid_displace,
191
+ -math.pi * 0.5,
192
+ ],
193
+ )
194
+
195
+ # integrate wave equation
196
+ wp.launch(
197
+ kernel=wave_solve,
198
+ dim=self.sim_width * self.sim_height,
199
+ inputs=[
200
+ self.sim_grid0,
201
+ self.sim_grid1,
202
+ self.sim_width,
203
+ self.sim_height,
204
+ 1.0 / self.grid_size,
205
+ self.k_speed,
206
+ self.k_damp,
207
+ self.sim_dt,
208
+ ],
209
+ )
210
+
211
+ # swap grids
212
+ (self.sim_grid0, self.sim_grid1) = (self.sim_grid1, self.sim_grid0)
213
+
214
+ self.sim_time += self.sim_dt
215
+
216
+ with wp.ScopedTimer("mesh", active=False):
217
+ # update grid vertices from heights
218
+ wp.launch(kernel=grid_update, dim=self.sim_width * self.sim_height, inputs=[self.sim_grid0, self.sim_verts])
219
+
220
+ def render(self):
221
+ if self.renderer is None:
222
+ return
223
+
224
+ with wp.ScopedTimer("render", active=True):
225
+ vertices = self.sim_verts.numpy()
226
+
227
+ self.renderer.begin_frame(self.sim_time)
228
+ self.renderer.render_mesh("surface", vertices, self.indices, colors=((0.35, 0.55, 0.9),) * len(vertices))
229
+ self.renderer.render_sphere(
230
+ "sphere",
231
+ (self.cx * self.grid_size, 0.0, self.cy * self.grid_size),
232
+ (0.0, 0.0, 0.0, 1.0),
233
+ 10.0 * self.grid_size,
234
+ color=(1.0, 1.0, 1.0),
235
+ )
236
+ self.renderer.end_frame()
237
+
238
+
239
+ if __name__ == "__main__":
240
+ stage_path = os.path.join(os.path.dirname(__file__), "example_wave.usd")
241
+
242
+ example = Example(stage_path)
243
+
244
+ for i in range(example.sim_frames):
245
+ example.step()
246
+ example.render()
247
+
248
+ if example.renderer:
249
+ example.renderer.save()