warp-lang 0.15.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.
- warp/__init__.py +1 -0
- warp/codegen.py +7 -3
- warp/config.py +2 -1
- warp/constants.py +3 -0
- warp/context.py +44 -21
- warp/examples/assets/bunny.usd +0 -0
- warp/examples/assets/cartpole.urdf +110 -0
- warp/examples/assets/crazyflie.usd +0 -0
- warp/examples/assets/cube.usda +42 -0
- warp/examples/assets/nv_ant.xml +92 -0
- warp/examples/assets/nv_humanoid.xml +183 -0
- warp/examples/assets/quadruped.urdf +268 -0
- warp/examples/assets/rocks.nvdb +0 -0
- warp/examples/assets/rocks.usd +0 -0
- warp/examples/assets/sphere.usda +56 -0
- warp/examples/assets/torus.usda +105 -0
- warp/examples/core/example_dem.py +6 -6
- warp/examples/core/example_fluid.py +3 -3
- warp/examples/core/example_graph_capture.py +3 -6
- warp/examples/optim/example_bounce.py +9 -8
- warp/examples/optim/example_cloth_throw.py +12 -8
- warp/examples/optim/example_diffray.py +10 -12
- warp/examples/optim/example_drone.py +31 -14
- warp/examples/optim/example_spring_cage.py +10 -15
- warp/examples/optim/example_trajectory.py +7 -24
- warp/examples/sim/example_cartpole.py +3 -9
- warp/examples/sim/example_cloth.py +10 -10
- warp/examples/sim/example_granular.py +3 -3
- warp/examples/sim/example_granular_collision_sdf.py +9 -4
- warp/examples/sim/example_jacobian_ik.py +0 -10
- warp/examples/sim/example_particle_chain.py +4 -4
- warp/examples/sim/example_quadruped.py +15 -11
- warp/examples/sim/example_rigid_chain.py +13 -8
- warp/examples/sim/example_rigid_contact.py +4 -4
- warp/examples/sim/example_rigid_force.py +7 -7
- warp/examples/sim/example_rigid_soft_contact.py +4 -4
- warp/examples/sim/example_soft_body.py +3 -3
- warp/jax.py +45 -0
- warp/jax_experimental.py +339 -0
- warp/render/render_opengl.py +188 -95
- warp/render/render_usd.py +34 -10
- warp/sim/__init__.py +13 -4
- warp/sim/articulation.py +4 -5
- warp/sim/collide.py +320 -175
- warp/sim/import_mjcf.py +25 -30
- warp/sim/import_urdf.py +94 -63
- warp/sim/import_usd.py +51 -36
- warp/sim/inertia.py +3 -2
- warp/sim/integrator.py +233 -0
- warp/sim/integrator_euler.py +447 -469
- warp/sim/integrator_featherstone.py +1991 -0
- warp/sim/integrator_xpbd.py +1420 -640
- warp/sim/model.py +741 -487
- warp/sim/particles.py +2 -1
- warp/sim/render.py +18 -2
- warp/sim/utils.py +222 -11
- warp/stubs.py +1 -0
- warp/tape.py +6 -9
- warp/tests/test_examples.py +87 -20
- warp/tests/test_grad_customs.py +122 -0
- warp/tests/test_jax.py +254 -0
- warp/tests/test_options.py +13 -53
- warp/tests/test_quat.py +23 -0
- warp/tests/test_snippet.py +2 -0
- warp/tests/test_utils.py +31 -26
- warp/tests/test_verify_fp.py +65 -0
- warp/tests/unittest_suites.py +4 -0
- warp/utils.py +50 -1
- {warp_lang-0.15.0.dist-info → warp_lang-1.0.0.dist-info}/METADATA +1 -1
- {warp_lang-0.15.0.dist-info → warp_lang-1.0.0.dist-info}/RECORD +73 -64
- warp/examples/env/__init__.py +0 -0
- warp/examples/env/env_ant.py +0 -61
- warp/examples/env/env_cartpole.py +0 -63
- warp/examples/env/env_humanoid.py +0 -65
- warp/examples/env/env_usd.py +0 -97
- warp/examples/env/environment.py +0 -526
- warp/sim/optimizer.py +0 -138
- {warp_lang-0.15.0.dist-info → warp_lang-1.0.0.dist-info}/LICENSE.md +0 -0
- {warp_lang-0.15.0.dist-info → warp_lang-1.0.0.dist-info}/WHEEL +0 -0
- {warp_lang-0.15.0.dist-info → warp_lang-1.0.0.dist-info}/top_level.txt +0 -0
warp/render/render_opengl.py
CHANGED
|
@@ -667,6 +667,45 @@ class ShapeInstancer:
|
|
|
667
667
|
|
|
668
668
|
self.face_count = len(indices)
|
|
669
669
|
|
|
670
|
+
def update_colors(self, colors1, colors2):
|
|
671
|
+
from pyglet import gl
|
|
672
|
+
|
|
673
|
+
if colors1 is None:
|
|
674
|
+
colors1 = np.tile(self.color1, (self.num_instances, 1))
|
|
675
|
+
if colors2 is None:
|
|
676
|
+
colors2 = np.tile(self.color2, (self.num_instances, 1))
|
|
677
|
+
if np.shape(colors1) != (self.num_instances, 3):
|
|
678
|
+
colors1 = np.tile(colors1, (self.num_instances, 1))
|
|
679
|
+
if np.shape(colors2) != (self.num_instances, 3):
|
|
680
|
+
colors2 = np.tile(colors2, (self.num_instances, 1))
|
|
681
|
+
colors1 = np.array(colors1, dtype=np.float32)
|
|
682
|
+
colors2 = np.array(colors2, dtype=np.float32)
|
|
683
|
+
|
|
684
|
+
gl.glBindVertexArray(self.vao)
|
|
685
|
+
|
|
686
|
+
# create buffer for checkerboard colors
|
|
687
|
+
if self.instance_color1_buffer is None:
|
|
688
|
+
self.instance_color1_buffer = gl.GLuint()
|
|
689
|
+
gl.glGenBuffers(1, self.instance_color1_buffer)
|
|
690
|
+
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.instance_color1_buffer)
|
|
691
|
+
gl.glBufferData(gl.GL_ARRAY_BUFFER, colors1.nbytes, colors1.ctypes.data, gl.GL_STATIC_DRAW)
|
|
692
|
+
|
|
693
|
+
if self.instance_color2_buffer is None:
|
|
694
|
+
self.instance_color2_buffer = gl.GLuint()
|
|
695
|
+
gl.glGenBuffers(1, self.instance_color2_buffer)
|
|
696
|
+
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.instance_color2_buffer)
|
|
697
|
+
gl.glBufferData(gl.GL_ARRAY_BUFFER, colors2.nbytes, colors2.ctypes.data, gl.GL_STATIC_DRAW)
|
|
698
|
+
|
|
699
|
+
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.instance_color1_buffer)
|
|
700
|
+
gl.glVertexAttribPointer(7, 3, gl.GL_FLOAT, gl.GL_FALSE, colors1[0].nbytes, ctypes.c_void_p(0))
|
|
701
|
+
gl.glEnableVertexAttribArray(7)
|
|
702
|
+
gl.glVertexAttribDivisor(7, 1)
|
|
703
|
+
|
|
704
|
+
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.instance_color2_buffer)
|
|
705
|
+
gl.glVertexAttribPointer(8, 3, gl.GL_FLOAT, gl.GL_FALSE, colors2[0].nbytes, ctypes.c_void_p(0))
|
|
706
|
+
gl.glEnableVertexAttribArray(8)
|
|
707
|
+
gl.glVertexAttribDivisor(8, 1)
|
|
708
|
+
|
|
670
709
|
def allocate_instances(self, positions, rotations=None, colors1=None, colors2=None, scalings=None):
|
|
671
710
|
from pyglet import gl
|
|
672
711
|
|
|
@@ -723,31 +762,11 @@ class ShapeInstancer:
|
|
|
723
762
|
int(self.instance_transform_gl_buffer.value), self.device
|
|
724
763
|
)
|
|
725
764
|
|
|
726
|
-
|
|
727
|
-
colors1 = np.tile(self.color1, (self.num_instances, 1))
|
|
728
|
-
if colors2 is None:
|
|
729
|
-
colors2 = np.tile(self.color2, (self.num_instances, 1))
|
|
730
|
-
colors1 = np.array(colors1, dtype=np.float32)
|
|
731
|
-
colors2 = np.array(colors2, dtype=np.float32)
|
|
732
|
-
|
|
733
|
-
# create buffer for checkerboard colors
|
|
734
|
-
if self.instance_color1_buffer is None:
|
|
735
|
-
self.instance_color1_buffer = gl.GLuint()
|
|
736
|
-
gl.glGenBuffers(1, self.instance_color1_buffer)
|
|
737
|
-
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.instance_color1_buffer)
|
|
738
|
-
gl.glBufferData(gl.GL_ARRAY_BUFFER, colors1.nbytes, colors1.ctypes.data, gl.GL_STATIC_DRAW)
|
|
739
|
-
|
|
740
|
-
if self.instance_color2_buffer is None:
|
|
741
|
-
self.instance_color2_buffer = gl.GLuint()
|
|
742
|
-
gl.glGenBuffers(1, self.instance_color2_buffer)
|
|
743
|
-
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.instance_color2_buffer)
|
|
744
|
-
gl.glBufferData(gl.GL_ARRAY_BUFFER, colors2.nbytes, colors2.ctypes.data, gl.GL_STATIC_DRAW)
|
|
765
|
+
self.update_colors(colors1, colors2)
|
|
745
766
|
|
|
746
767
|
# Set up instance attribute pointers
|
|
747
768
|
matrix_size = vbo_transforms[0].nbytes
|
|
748
769
|
|
|
749
|
-
gl.glBindVertexArray(self.vao)
|
|
750
|
-
|
|
751
770
|
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.instance_transform_gl_buffer)
|
|
752
771
|
|
|
753
772
|
# we can only send vec4s to the shader, so we need to split the instance transforms matrix into its column vectors
|
|
@@ -758,16 +777,6 @@ class ShapeInstancer:
|
|
|
758
777
|
gl.glEnableVertexAttribArray(3 + i)
|
|
759
778
|
gl.glVertexAttribDivisor(3 + i, 1)
|
|
760
779
|
|
|
761
|
-
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.instance_color1_buffer)
|
|
762
|
-
gl.glVertexAttribPointer(7, 3, gl.GL_FLOAT, gl.GL_FALSE, colors1[0].nbytes, ctypes.c_void_p(0))
|
|
763
|
-
gl.glEnableVertexAttribArray(7)
|
|
764
|
-
gl.glVertexAttribDivisor(7, 1)
|
|
765
|
-
|
|
766
|
-
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.instance_color2_buffer)
|
|
767
|
-
gl.glVertexAttribPointer(8, 3, gl.GL_FLOAT, gl.GL_FALSE, colors2[0].nbytes, ctypes.c_void_p(0))
|
|
768
|
-
gl.glEnableVertexAttribArray(8)
|
|
769
|
-
gl.glVertexAttribDivisor(8, 1)
|
|
770
|
-
|
|
771
780
|
gl.glBindVertexArray(0)
|
|
772
781
|
|
|
773
782
|
def update_instances(self, transforms: wp.array = None, scalings: wp.array = None, colors1=None, colors2=None):
|
|
@@ -808,6 +817,9 @@ class ShapeInstancer:
|
|
|
808
817
|
|
|
809
818
|
self._instance_transform_cuda_buffer.unmap()
|
|
810
819
|
|
|
820
|
+
if colors1 is not None or colors2 is not None:
|
|
821
|
+
self.update_colors(colors1, colors2)
|
|
822
|
+
|
|
811
823
|
def render(self):
|
|
812
824
|
from pyglet import gl
|
|
813
825
|
|
|
@@ -914,9 +926,6 @@ class OpenGLRenderer:
|
|
|
914
926
|
self.enable_mouse_interaction = enable_mouse_interaction
|
|
915
927
|
self.enable_keyboard_interaction = enable_keyboard_interaction
|
|
916
928
|
|
|
917
|
-
self._camera_pos = PyVec3(*camera_pos)
|
|
918
|
-
self._camera_front = PyVec3(*camera_front)
|
|
919
|
-
self._camera_up = PyVec3(*camera_up)
|
|
920
929
|
self._camera_speed = 0.04
|
|
921
930
|
if isinstance(up_axis, int):
|
|
922
931
|
self._camera_axis = up_axis
|
|
@@ -927,12 +936,19 @@ class OpenGLRenderer:
|
|
|
927
936
|
self._first_mouse = True
|
|
928
937
|
self._left_mouse_pressed = False
|
|
929
938
|
self._keys_pressed = defaultdict(bool)
|
|
939
|
+
self._input_processors = []
|
|
930
940
|
self._key_callbacks = []
|
|
931
941
|
|
|
932
942
|
self.render_2d_callbacks = []
|
|
933
943
|
self.render_3d_callbacks = []
|
|
934
944
|
|
|
935
|
-
self.
|
|
945
|
+
self._camera_pos = PyVec3(0.0, 0.0, 0.0)
|
|
946
|
+
self._camera_front = PyVec3(0.0, 0.0, -1.0)
|
|
947
|
+
self._camera_up = PyVec3(0.0, 1.0, 0.0)
|
|
948
|
+
self._scaling = scaling
|
|
949
|
+
|
|
950
|
+
self._model_matrix = self.compute_model_matrix(self._camera_axis, scaling)
|
|
951
|
+
self.update_view_matrix(cam_pos=camera_pos, cam_front=camera_front, cam_up=camera_up)
|
|
936
952
|
self.update_projection_matrix()
|
|
937
953
|
|
|
938
954
|
self._frame_dt = 1.0 / fps
|
|
@@ -1549,37 +1565,65 @@ class OpenGLRenderer:
|
|
|
1549
1565
|
self.camera_fov, aspect_ratio, self.camera_near_plane, self.camera_far_plane
|
|
1550
1566
|
)
|
|
1551
1567
|
|
|
1552
|
-
|
|
1553
|
-
|
|
1568
|
+
@property
|
|
1569
|
+
def camera_pos(self):
|
|
1570
|
+
return self._camera_pos
|
|
1571
|
+
|
|
1572
|
+
@camera_pos.setter
|
|
1573
|
+
def camera_pos(self, value):
|
|
1574
|
+
self.update_view_matrix(cam_pos=value)
|
|
1575
|
+
|
|
1576
|
+
@property
|
|
1577
|
+
def camera_front(self):
|
|
1578
|
+
return self._camera_front
|
|
1554
1579
|
|
|
1555
|
-
|
|
1556
|
-
|
|
1580
|
+
@camera_front.setter
|
|
1581
|
+
def camera_front(self, value):
|
|
1582
|
+
self.update_view_matrix(cam_front=value)
|
|
1557
1583
|
|
|
1558
|
-
|
|
1584
|
+
@property
|
|
1585
|
+
def camera_up(self):
|
|
1586
|
+
return self._camera_up
|
|
1587
|
+
|
|
1588
|
+
@camera_up.setter
|
|
1589
|
+
def camera_up(self, value):
|
|
1590
|
+
self.update_view_matrix(cam_up=value)
|
|
1591
|
+
|
|
1592
|
+
def update_view_matrix(self, cam_pos=None, cam_front=None, cam_up=None, stiffness=1.0):
|
|
1593
|
+
from pyglet.math import Vec3, Mat4
|
|
1594
|
+
|
|
1595
|
+
if cam_pos is not None:
|
|
1596
|
+
self._camera_pos = self._camera_pos * (1.0 - stiffness) + Vec3(*cam_pos) * stiffness
|
|
1597
|
+
if cam_front is not None:
|
|
1598
|
+
self._camera_front = self._camera_front * (1.0 - stiffness) + Vec3(*cam_front) * stiffness
|
|
1599
|
+
if cam_up is not None:
|
|
1600
|
+
self._camera_up = self._camera_up * (1.0 - stiffness) + Vec3(*cam_up) * stiffness
|
|
1601
|
+
|
|
1602
|
+
model = np.array(self._model_matrix).reshape((4, 4))
|
|
1603
|
+
cp = model @ np.array([*self._camera_pos / self._scaling, 1.0])
|
|
1604
|
+
cf = model @ np.array([*self._camera_front / self._scaling, 1.0])
|
|
1605
|
+
up = model @ np.array([*self._camera_up / self._scaling, 0.0])
|
|
1606
|
+
cp = Vec3(*cp[:3])
|
|
1607
|
+
cf = Vec3(*cf[:3])
|
|
1608
|
+
up = Vec3(*up[:3])
|
|
1609
|
+
self._view_matrix = np.array(Mat4.look_at(cp, cp + cf, up))
|
|
1610
|
+
|
|
1611
|
+
def compute_model_matrix(self, camera_axis: int, scaling: float):
|
|
1612
|
+
if camera_axis == 0:
|
|
1613
|
+
return np.array((0, 0, scaling, 0, scaling, 0, 0, 0, 0, scaling, 0, 0, 0, 0, 0, 1))
|
|
1614
|
+
elif camera_axis == 2:
|
|
1615
|
+
return np.array((-scaling, 0, 0, 0, 0, 0, scaling, 0, 0, scaling, 0, 0, 0, 0, 0, 1))
|
|
1616
|
+
|
|
1617
|
+
return np.array((scaling, 0, 0, 0, 0, scaling, 0, 0, 0, 0, scaling, 0, 0, 0, 0, 1))
|
|
1618
|
+
|
|
1619
|
+
def update_model_matrix(self, model_matrix: Optional[Mat44] = None):
|
|
1559
1620
|
from pyglet import gl
|
|
1560
1621
|
|
|
1561
1622
|
# fmt: off
|
|
1562
|
-
if
|
|
1563
|
-
self._model_matrix =
|
|
1564
|
-
0, 0, self._scaling, 0,
|
|
1565
|
-
self._scaling, 0, 0, 0,
|
|
1566
|
-
0, self._scaling, 0, 0,
|
|
1567
|
-
0, 0, 0, 1
|
|
1568
|
-
))
|
|
1569
|
-
elif self._camera_axis == 2:
|
|
1570
|
-
self._model_matrix = np.array((
|
|
1571
|
-
-self._scaling, 0, 0, 0,
|
|
1572
|
-
0, 0, self._scaling, 0,
|
|
1573
|
-
0, self._scaling, 0, 0,
|
|
1574
|
-
0, 0, 0, 1
|
|
1575
|
-
))
|
|
1623
|
+
if model_matrix is None:
|
|
1624
|
+
self._model_matrix = self.compute_model_matrix(self._camera_axis, self._scaling)
|
|
1576
1625
|
else:
|
|
1577
|
-
self._model_matrix = np.array((
|
|
1578
|
-
self._scaling, 0, 0, 0,
|
|
1579
|
-
0, self._scaling, 0, 0,
|
|
1580
|
-
0, 0, self._scaling, 0,
|
|
1581
|
-
0, 0, 0, 1
|
|
1582
|
-
))
|
|
1626
|
+
self._model_matrix = np.array(model_matrix).flatten()
|
|
1583
1627
|
# fmt: on
|
|
1584
1628
|
ptr = arr_pointer(self._model_matrix)
|
|
1585
1629
|
gl.glUseProgram(self._shape_shader.id)
|
|
@@ -1890,6 +1934,10 @@ Instances: {len(self._instances)}"""
|
|
|
1890
1934
|
import pyglet
|
|
1891
1935
|
from pyglet.math import Vec3 as PyVec3
|
|
1892
1936
|
|
|
1937
|
+
for cb in self._input_processors:
|
|
1938
|
+
if cb(self._key_handler) == pyglet.event.EVENT_HANDLED:
|
|
1939
|
+
return
|
|
1940
|
+
|
|
1893
1941
|
if self._key_handler[pyglet.window.key.W] or self._key_handler[pyglet.window.key.UP]:
|
|
1894
1942
|
self._camera_pos += self._camera_front * (self._camera_speed * self._frame_speed)
|
|
1895
1943
|
self.update_view_matrix()
|
|
@@ -1905,12 +1953,19 @@ Instances: {len(self._instances)}"""
|
|
|
1905
1953
|
self._camera_pos += camera_side * (self._camera_speed * self._frame_speed)
|
|
1906
1954
|
self.update_view_matrix()
|
|
1907
1955
|
|
|
1956
|
+
def register_input_processor(self, callback):
|
|
1957
|
+
self._input_processors.append(callback)
|
|
1958
|
+
|
|
1908
1959
|
def _key_press_callback(self, symbol, modifiers):
|
|
1909
1960
|
import pyglet
|
|
1910
1961
|
|
|
1911
1962
|
if not self.enable_keyboard_interaction:
|
|
1912
1963
|
return
|
|
1913
1964
|
|
|
1965
|
+
for cb in self._key_callbacks:
|
|
1966
|
+
if cb(symbol, modifiers) == pyglet.event.EVENT_HANDLED:
|
|
1967
|
+
return pyglet.event.EVENT_HANDLED
|
|
1968
|
+
|
|
1914
1969
|
if symbol == pyglet.window.key.ESCAPE:
|
|
1915
1970
|
self.close()
|
|
1916
1971
|
if symbol == pyglet.window.key.SPACE:
|
|
@@ -1930,9 +1985,6 @@ Instances: {len(self._instances)}"""
|
|
|
1930
1985
|
if symbol == pyglet.window.key.B:
|
|
1931
1986
|
self.enable_backface_culling = not self.enable_backface_culling
|
|
1932
1987
|
|
|
1933
|
-
for cb in self._key_callbacks:
|
|
1934
|
-
cb(symbol, modifiers)
|
|
1935
|
-
|
|
1936
1988
|
def register_key_press_callback(self, callback):
|
|
1937
1989
|
self._key_callbacks.append(callback)
|
|
1938
1990
|
|
|
@@ -2018,6 +2070,34 @@ Instances: {len(self._instances)}"""
|
|
|
2018
2070
|
self._instance_count = len(self._instances)
|
|
2019
2071
|
return instance
|
|
2020
2072
|
|
|
2073
|
+
def update_instance_colors(self):
|
|
2074
|
+
from pyglet import gl
|
|
2075
|
+
|
|
2076
|
+
colors1, colors2 = [], []
|
|
2077
|
+
all_instances = list(self._instances.values())
|
|
2078
|
+
for shape, instances in self._shape_instances.items():
|
|
2079
|
+
for i in instances:
|
|
2080
|
+
if i >= len(all_instances):
|
|
2081
|
+
continue
|
|
2082
|
+
instance = all_instances[i]
|
|
2083
|
+
colors1.append(instance[5])
|
|
2084
|
+
colors2.append(instance[6])
|
|
2085
|
+
colors1 = np.array(colors1, dtype=np.float32)
|
|
2086
|
+
colors2 = np.array(colors2, dtype=np.float32)
|
|
2087
|
+
|
|
2088
|
+
# create buffer for checkerboard colors
|
|
2089
|
+
if self._instance_color1_buffer is None:
|
|
2090
|
+
self._instance_color1_buffer = gl.GLuint()
|
|
2091
|
+
gl.glGenBuffers(1, self._instance_color1_buffer)
|
|
2092
|
+
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._instance_color1_buffer)
|
|
2093
|
+
gl.glBufferData(gl.GL_ARRAY_BUFFER, colors1.nbytes, colors1.ctypes.data, gl.GL_STATIC_DRAW)
|
|
2094
|
+
|
|
2095
|
+
if self._instance_color2_buffer is None:
|
|
2096
|
+
self._instance_color2_buffer = gl.GLuint()
|
|
2097
|
+
gl.glGenBuffers(1, self._instance_color2_buffer)
|
|
2098
|
+
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._instance_color2_buffer)
|
|
2099
|
+
gl.glBufferData(gl.GL_ARRAY_BUFFER, colors2.nbytes, colors2.ctypes.data, gl.GL_STATIC_DRAW)
|
|
2100
|
+
|
|
2021
2101
|
def allocate_shape_instances(self):
|
|
2022
2102
|
from pyglet import gl
|
|
2023
2103
|
|
|
@@ -2051,28 +2131,7 @@ Instances: {len(self._instances)}"""
|
|
|
2051
2131
|
int(self._instance_transform_gl_buffer.value), self._device
|
|
2052
2132
|
)
|
|
2053
2133
|
|
|
2054
|
-
|
|
2055
|
-
all_instances = list(self._instances.values())
|
|
2056
|
-
for shape, instances in self._shape_instances.items():
|
|
2057
|
-
for i in instances:
|
|
2058
|
-
if i >= len(all_instances):
|
|
2059
|
-
continue
|
|
2060
|
-
instance = all_instances[i]
|
|
2061
|
-
colors1.append(instance[5])
|
|
2062
|
-
colors2.append(instance[6])
|
|
2063
|
-
colors1 = np.array(colors1, dtype=np.float32)
|
|
2064
|
-
colors2 = np.array(colors2, dtype=np.float32)
|
|
2065
|
-
|
|
2066
|
-
# create buffer for checkerboard colors
|
|
2067
|
-
self._instance_color1_buffer = gl.GLuint()
|
|
2068
|
-
gl.glGenBuffers(1, self._instance_color1_buffer)
|
|
2069
|
-
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._instance_color1_buffer)
|
|
2070
|
-
gl.glBufferData(gl.GL_ARRAY_BUFFER, colors1.nbytes, colors1.ctypes.data, gl.GL_STATIC_DRAW)
|
|
2071
|
-
|
|
2072
|
-
self._instance_color2_buffer = gl.GLuint()
|
|
2073
|
-
gl.glGenBuffers(1, self._instance_color2_buffer)
|
|
2074
|
-
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._instance_color2_buffer)
|
|
2075
|
-
gl.glBufferData(gl.GL_ARRAY_BUFFER, colors2.nbytes, colors2.ctypes.data, gl.GL_STATIC_DRAW)
|
|
2134
|
+
self.update_instance_colors()
|
|
2076
2135
|
|
|
2077
2136
|
# set up instance attribute pointers
|
|
2078
2137
|
matrix_size = transforms[0].nbytes
|
|
@@ -2083,6 +2142,7 @@ Instances: {len(self._instances)}"""
|
|
|
2083
2142
|
instances = list(self._instances.values())
|
|
2084
2143
|
inverse_instance_ids = {}
|
|
2085
2144
|
instance_count = 0
|
|
2145
|
+
colors_size = np.zeros(3, dtype=np.float32).nbytes
|
|
2086
2146
|
for shape, (vao, vbo, ebo, tri_count, vertex_cuda_buffer) in self._shape_gl_buffers.items():
|
|
2087
2147
|
gl.glBindVertexArray(vao)
|
|
2088
2148
|
|
|
@@ -2097,12 +2157,12 @@ Instances: {len(self._instances)}"""
|
|
|
2097
2157
|
gl.glVertexAttribDivisor(3 + i, 1)
|
|
2098
2158
|
|
|
2099
2159
|
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._instance_color1_buffer)
|
|
2100
|
-
gl.glVertexAttribPointer(7, 3, gl.GL_FLOAT, gl.GL_FALSE,
|
|
2160
|
+
gl.glVertexAttribPointer(7, 3, gl.GL_FLOAT, gl.GL_FALSE, colors_size, ctypes.c_void_p(0))
|
|
2101
2161
|
gl.glEnableVertexAttribArray(7)
|
|
2102
2162
|
gl.glVertexAttribDivisor(7, 1)
|
|
2103
2163
|
|
|
2104
2164
|
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._instance_color2_buffer)
|
|
2105
|
-
gl.glVertexAttribPointer(8, 3, gl.GL_FLOAT, gl.GL_FALSE,
|
|
2165
|
+
gl.glVertexAttribPointer(8, 3, gl.GL_FLOAT, gl.GL_FALSE, colors_size, ctypes.c_void_p(0))
|
|
2106
2166
|
gl.glEnableVertexAttribArray(8)
|
|
2107
2167
|
gl.glVertexAttribDivisor(8, 1)
|
|
2108
2168
|
|
|
@@ -2124,7 +2184,7 @@ Instances: {len(self._instances)}"""
|
|
|
2124
2184
|
|
|
2125
2185
|
gl.glBindVertexArray(0)
|
|
2126
2186
|
|
|
2127
|
-
def update_shape_instance(self, name, pos, rot, color1=None, color2=None, visible=None):
|
|
2187
|
+
def update_shape_instance(self, name, pos=None, rot=None, color1=None, color2=None, visible=None):
|
|
2128
2188
|
"""Update the instance transform of the shape
|
|
2129
2189
|
|
|
2130
2190
|
Args:
|
|
@@ -2135,21 +2195,33 @@ Instances: {len(self._instances)}"""
|
|
|
2135
2195
|
color2: The second color of the checker pattern
|
|
2136
2196
|
visible: Whether the shape is visible
|
|
2137
2197
|
"""
|
|
2198
|
+
from pyglet import gl
|
|
2199
|
+
|
|
2138
2200
|
if name in self._instances:
|
|
2139
|
-
i, body, shape,
|
|
2201
|
+
i, body, shape, tf, scale, old_color1, old_color2, v = self._instances[name]
|
|
2140
2202
|
if visible is None:
|
|
2141
2203
|
visible = v
|
|
2204
|
+
new_tf = np.copy(tf)
|
|
2205
|
+
if pos is not None:
|
|
2206
|
+
new_tf[:3] = pos
|
|
2207
|
+
if rot is not None:
|
|
2208
|
+
new_tf[3:] = rot
|
|
2142
2209
|
self._instances[name] = (
|
|
2143
2210
|
i,
|
|
2144
2211
|
body,
|
|
2145
2212
|
shape,
|
|
2146
|
-
|
|
2213
|
+
new_tf,
|
|
2147
2214
|
scale,
|
|
2148
2215
|
color1 or old_color1,
|
|
2149
2216
|
color2 or old_color2,
|
|
2150
2217
|
visible,
|
|
2151
2218
|
)
|
|
2152
2219
|
self._update_shape_instances = True
|
|
2220
|
+
if color1 is not None or color2 is not None:
|
|
2221
|
+
vao, vbo, ebo, tri_count, vertex_cuda_buffer = self._shape_gl_buffers[shape]
|
|
2222
|
+
gl.glBindVertexArray(vao)
|
|
2223
|
+
self.update_instance_colors()
|
|
2224
|
+
gl.glBindVertexArray(0)
|
|
2153
2225
|
return True
|
|
2154
2226
|
return False
|
|
2155
2227
|
|
|
@@ -2425,7 +2497,7 @@ Instances: {len(self._instances)}"""
|
|
|
2425
2497
|
self.add_shape_instance(name, shape, body, pos, rot)
|
|
2426
2498
|
return shape
|
|
2427
2499
|
|
|
2428
|
-
def render_ground(self, size: float =
|
|
2500
|
+
def render_ground(self, size: float = 1000.0, plane=None):
|
|
2429
2501
|
"""Add a ground plane for visualization
|
|
2430
2502
|
|
|
2431
2503
|
Args:
|
|
@@ -2440,9 +2512,22 @@ Instances: {len(self._instances)}"""
|
|
|
2440
2512
|
q = (0.0, 0.0, 0.0, 1.0)
|
|
2441
2513
|
elif self._camera_axis == 2:
|
|
2442
2514
|
q = (sqh, 0.0, 0.0, sqh)
|
|
2515
|
+
pos = (0.0, 0.0, 0.0)
|
|
2516
|
+
if plane is not None:
|
|
2517
|
+
normal = np.array(plane[:3])
|
|
2518
|
+
normal /= np.linalg.norm(normal)
|
|
2519
|
+
pos = plane[3] * normal
|
|
2520
|
+
if np.allclose(normal, (0.0, 1.0, 0.0)):
|
|
2521
|
+
# no rotation necessary
|
|
2522
|
+
q = (0.0, 0.0, 0.0, 1.0)
|
|
2523
|
+
else:
|
|
2524
|
+
c = np.cross(normal, (0.0, 1.0, 0.0))
|
|
2525
|
+
angle = np.arcsin(np.linalg.norm(c))
|
|
2526
|
+
axis = np.abs(c) / np.linalg.norm(c)
|
|
2527
|
+
q = wp.quat_from_axis_angle(axis, angle)
|
|
2443
2528
|
return self.render_plane(
|
|
2444
2529
|
"ground",
|
|
2445
|
-
|
|
2530
|
+
pos,
|
|
2446
2531
|
q,
|
|
2447
2532
|
size,
|
|
2448
2533
|
size,
|
|
@@ -2453,7 +2538,14 @@ Instances: {len(self._instances)}"""
|
|
|
2453
2538
|
)
|
|
2454
2539
|
|
|
2455
2540
|
def render_sphere(
|
|
2456
|
-
self,
|
|
2541
|
+
self,
|
|
2542
|
+
name: str,
|
|
2543
|
+
pos: tuple,
|
|
2544
|
+
rot: tuple,
|
|
2545
|
+
radius: float,
|
|
2546
|
+
parent_body: str = None,
|
|
2547
|
+
is_template: bool = False,
|
|
2548
|
+
color=None,
|
|
2457
2549
|
):
|
|
2458
2550
|
"""Add a sphere for visualization
|
|
2459
2551
|
|
|
@@ -2466,14 +2558,14 @@ Instances: {len(self._instances)}"""
|
|
|
2466
2558
|
geo_hash = hash(("sphere", radius))
|
|
2467
2559
|
if geo_hash in self._shape_geo_hash:
|
|
2468
2560
|
shape = self._shape_geo_hash[geo_hash]
|
|
2469
|
-
if self.update_shape_instance(name, pos, rot):
|
|
2561
|
+
if self.update_shape_instance(name, pos, rot, color1=color, color2=color):
|
|
2470
2562
|
return shape
|
|
2471
2563
|
else:
|
|
2472
2564
|
vertices, indices = self._create_sphere_mesh(radius)
|
|
2473
2565
|
shape = self.register_shape(geo_hash, vertices, indices, color1=color, color2=color)
|
|
2474
2566
|
if not is_template:
|
|
2475
2567
|
body = self._resolve_body_id(parent_body)
|
|
2476
|
-
self.add_shape_instance(name, shape, body, pos, rot)
|
|
2568
|
+
self.add_shape_instance(name, shape, body, pos, rot, color1=color, color2=color)
|
|
2477
2569
|
return shape
|
|
2478
2570
|
|
|
2479
2571
|
def render_capsule(
|
|
@@ -2800,6 +2892,7 @@ Instances: {len(self._instances)}"""
|
|
|
2800
2892
|
instancer = self._shape_instancers[name]
|
|
2801
2893
|
if len(lines) != instancer.num_instances:
|
|
2802
2894
|
instancer.allocate_instances(np.zeros((len(lines), 3)))
|
|
2895
|
+
instancer.update_colors(color, color)
|
|
2803
2896
|
|
|
2804
2897
|
lines_wp = wp.array(lines, dtype=wp.vec3, ndim=2, device=self._device)
|
|
2805
2898
|
with instancer:
|
warp/render/render_usd.py
CHANGED
|
@@ -28,9 +28,12 @@ def _usd_set_xform(xform, pos: tuple, rot: tuple, scale: tuple, time):
|
|
|
28
28
|
|
|
29
29
|
xform_ops = xform.GetOrderedXformOps()
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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)
|
|
34
37
|
|
|
35
38
|
|
|
36
39
|
# transforms a cylinder such that it connects the two points pos0, pos1
|
|
@@ -151,7 +154,11 @@ class UsdRenderer:
|
|
|
151
154
|
rot: tuple,
|
|
152
155
|
scale: tuple = (1.0, 1.0, 1.0),
|
|
153
156
|
color: tuple = (1.0, 1.0, 1.0),
|
|
157
|
+
custom_index: int = -1,
|
|
158
|
+
visible: bool = True,
|
|
154
159
|
):
|
|
160
|
+
if not visible:
|
|
161
|
+
return
|
|
155
162
|
sdf_path = self._resolve_path(name, body)
|
|
156
163
|
instance = self._shape_constructors[shape.name].Define(self.stage, sdf_path)
|
|
157
164
|
instance.GetPrim().GetReferences().AddInternalReference(shape)
|
|
@@ -224,7 +231,7 @@ class UsdRenderer:
|
|
|
224
231
|
|
|
225
232
|
return prim_path
|
|
226
233
|
|
|
227
|
-
def render_ground(self, size: float = 100.0):
|
|
234
|
+
def render_ground(self, size: float = 100.0, plane=None):
|
|
228
235
|
from pxr import UsdGeom
|
|
229
236
|
|
|
230
237
|
mesh = UsdGeom.Mesh.Define(self.stage, self.root.GetPath().AppendChild("ground"))
|
|
@@ -239,6 +246,23 @@ class UsdRenderer:
|
|
|
239
246
|
elif self.up_axis == "Z":
|
|
240
247
|
points = ((-size, -size, 0.0), (size, -size, 0.0), (size, size, 0.0), (-size, size, 0.0))
|
|
241
248
|
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))
|
|
249
|
+
if plane is not None:
|
|
250
|
+
normal = np.array(plane[:3])
|
|
251
|
+
normal /= np.linalg.norm(normal)
|
|
252
|
+
pos = plane[3] * normal
|
|
253
|
+
axis_up = [0.0, 0.0, 0.0]
|
|
254
|
+
axis_up["XYZ".index(self.up_axis)] = 1.0
|
|
255
|
+
if np.allclose(normal, axis_up):
|
|
256
|
+
# no rotation necessary
|
|
257
|
+
q = (0.0, 0.0, 0.0, 1.0)
|
|
258
|
+
else:
|
|
259
|
+
c = np.cross(normal, axis_up)
|
|
260
|
+
angle = np.arcsin(np.linalg.norm(c))
|
|
261
|
+
axis = np.abs(c) / np.linalg.norm(c)
|
|
262
|
+
q = wp.quat_from_axis_angle(axis, angle)
|
|
263
|
+
tf = wp.transform(pos, q)
|
|
264
|
+
points = [wp.transform_point(tf, p) for p in points]
|
|
265
|
+
normals = [wp.transform_vector(tf, n) for n in normals]
|
|
242
266
|
counts = (4,)
|
|
243
267
|
indices = [0, 1, 2, 3]
|
|
244
268
|
|
|
@@ -339,7 +363,7 @@ class UsdRenderer:
|
|
|
339
363
|
self._shape_constructors[name] = UsdGeom.Capsule
|
|
340
364
|
|
|
341
365
|
if not is_template:
|
|
342
|
-
_usd_set_xform(capsule, pos, rot, (1.0, 1.0, 1.0),
|
|
366
|
+
_usd_set_xform(capsule, pos, rot, (1.0, 1.0, 1.0), self.time)
|
|
343
367
|
|
|
344
368
|
return prim_path
|
|
345
369
|
|
|
@@ -393,7 +417,7 @@ class UsdRenderer:
|
|
|
393
417
|
self._shape_constructors[name] = UsdGeom.Cylinder
|
|
394
418
|
|
|
395
419
|
if not is_template:
|
|
396
|
-
_usd_set_xform(cylinder, pos, rot, (1.0, 1.0, 1.0),
|
|
420
|
+
_usd_set_xform(cylinder, pos, rot, (1.0, 1.0, 1.0), self.time)
|
|
397
421
|
|
|
398
422
|
return prim_path
|
|
399
423
|
|
|
@@ -447,7 +471,7 @@ class UsdRenderer:
|
|
|
447
471
|
self._shape_constructors[name] = UsdGeom.Cone
|
|
448
472
|
|
|
449
473
|
if not is_template:
|
|
450
|
-
_usd_set_xform(cone, pos, rot, (1.0, 1.0, 1.0),
|
|
474
|
+
_usd_set_xform(cone, pos, rot, (1.0, 1.0, 1.0), self.time)
|
|
451
475
|
|
|
452
476
|
return prim_path
|
|
453
477
|
|
|
@@ -488,7 +512,7 @@ class UsdRenderer:
|
|
|
488
512
|
self._shape_custom_scale[name] = extents
|
|
489
513
|
|
|
490
514
|
if not is_template:
|
|
491
|
-
_usd_set_xform(cube, pos, rot, extents,
|
|
515
|
+
_usd_set_xform(cube, pos, rot, extents, self.time)
|
|
492
516
|
|
|
493
517
|
return prim_path
|
|
494
518
|
|
|
@@ -712,6 +736,6 @@ class UsdRenderer:
|
|
|
712
736
|
try:
|
|
713
737
|
self.stage.Save()
|
|
714
738
|
return True
|
|
715
|
-
except:
|
|
716
|
-
print("Failed to save USD stage")
|
|
739
|
+
except Exception as e:
|
|
740
|
+
print("Failed to save USD stage:", e)
|
|
717
741
|
return False
|
warp/sim/__init__.py
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# license agreement from NVIDIA CORPORATION is strictly prohibited.
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
from .model import State, Model, ModelBuilder, Mesh, SDF
|
|
9
|
+
from .model import State, Control, Model, ModelBuilder, Mesh, SDF
|
|
10
10
|
|
|
11
11
|
from .model import GEO_SPHERE
|
|
12
12
|
from .model import GEO_BOX
|
|
@@ -17,13 +17,13 @@ from .model import GEO_MESH
|
|
|
17
17
|
from .model import GEO_SDF
|
|
18
18
|
from .model import GEO_PLANE
|
|
19
19
|
from .model import GEO_NONE
|
|
20
|
-
from .model import ModelShapeGeometry
|
|
21
20
|
|
|
22
|
-
from .model import
|
|
21
|
+
from .model import JOINT_MODE_FORCE
|
|
23
22
|
from .model import JOINT_MODE_TARGET_POSITION
|
|
24
23
|
from .model import JOINT_MODE_TARGET_VELOCITY
|
|
25
24
|
|
|
26
25
|
from .model import JointAxis
|
|
26
|
+
from .model import ModelShapeGeometry
|
|
27
27
|
from .model import ModelShapeMaterials
|
|
28
28
|
|
|
29
29
|
from .model import JOINT_PRISMATIC
|
|
@@ -36,8 +36,10 @@ from .model import JOINT_UNIVERSAL
|
|
|
36
36
|
from .model import JOINT_DISTANCE
|
|
37
37
|
from .model import JOINT_D6
|
|
38
38
|
|
|
39
|
+
from .integrator import Integrator, integrate_particles, integrate_bodies
|
|
39
40
|
from .integrator_euler import SemiImplicitIntegrator
|
|
40
|
-
|
|
41
|
+
|
|
42
|
+
from .integrator_featherstone import FeatherstoneIntegrator
|
|
41
43
|
|
|
42
44
|
from .integrator_xpbd import XPBDIntegrator
|
|
43
45
|
|
|
@@ -48,3 +50,10 @@ from .import_mjcf import parse_mjcf
|
|
|
48
50
|
from .import_urdf import parse_urdf
|
|
49
51
|
from .import_snu import parse_snu
|
|
50
52
|
from .import_usd import parse_usd, resolve_usd_from_url
|
|
53
|
+
|
|
54
|
+
from .utils import velocity_at_point
|
|
55
|
+
from .utils import quat_from_euler
|
|
56
|
+
from .utils import quat_to_euler
|
|
57
|
+
from .utils import load_mesh
|
|
58
|
+
|
|
59
|
+
from .inertia import transform_inertia
|
warp/sim/articulation.py
CHANGED
|
@@ -105,7 +105,7 @@ def compute_3d_rotational_dofs(
|
|
|
105
105
|
local_1 = wp.quat_rotate(q_off, wp.vec3(0.0, 1.0, 0.0))
|
|
106
106
|
local_2 = wp.quat_rotate(q_off, wp.vec3(0.0, 0.0, 1.0))
|
|
107
107
|
|
|
108
|
-
# reconstruct rotation axes
|
|
108
|
+
# reconstruct rotation axes
|
|
109
109
|
axis_0 = local_0
|
|
110
110
|
q_0 = wp.quat_from_axis_angle(axis_0, q0)
|
|
111
111
|
|
|
@@ -331,10 +331,9 @@ def eval_articulation_fk(
|
|
|
331
331
|
iq = q_start + lin_axis_count
|
|
332
332
|
iqd = qd_start + lin_axis_count
|
|
333
333
|
if ang_axis_count == 1:
|
|
334
|
-
axis = joint_axis[
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
vel_w = joint_qd[qd_start + lin_axis_count + 0] * axis
|
|
334
|
+
axis = joint_axis[ia]
|
|
335
|
+
rot = wp.quat_from_axis_angle(axis, joint_q[iq])
|
|
336
|
+
vel_w = joint_qd[iqd] * axis
|
|
338
337
|
if ang_axis_count == 2:
|
|
339
338
|
rot, vel_w = compute_2d_rotational_dofs(
|
|
340
339
|
joint_axis[ia + 0],
|