From c2a8c2f058766465fbd591c6c97dae1e7ea74f4a Mon Sep 17 00:00:00 2001 From: Gregory Izatt Date: Wed, 20 Apr 2022 19:56:30 -0400 Subject: [PATCH 1/2] Add UUID-based caching of geometry and materials --- src/meshcat/geometry.py | 14 +++++++++-- src/meshcat/tests/test_drawing.py | 41 +++++++++++++++++++++++++++++-- src/meshcat/viewer | 2 +- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/meshcat/geometry.py b/src/meshcat/geometry.py index 2d1ebdb..8412410 100644 --- a/src/meshcat/geometry.py +++ b/src/meshcat/geometry.py @@ -268,6 +268,9 @@ def lower(self, object_data): class Object(SceneElement): + sent_geom_uuids = set() + sent_material_uuids = set() + def __init__(self, geometry, material=MeshPhongMaterial()): super(Object, self).__init__() self.geometry = geometry @@ -289,8 +292,15 @@ def lower(self): u"matrix": list(self.geometry.intrinsic_transform().flatten()) } } - self.geometry.lower_in_object(data) - self.material.lower_in_object(data) + # If this geometry or material has been previously sent, + # then we don't need to populate these fields; the server + # will load the matching geometry or material from its cache. + if self.geometry.uuid not in self.sent_geom_uuids: + self.sent_geom_uuids.add(self.geometry.uuid) + self.geometry.lower_in_object(data) + if self.material.uuid not in self.sent_material_uuids: + self.sent_material_uuids.add(self.material.uuid) + self.material.lower_in_object(data) return data diff --git a/src/meshcat/tests/test_drawing.py b/src/meshcat/tests/test_drawing.py index f2101a7..317d562 100644 --- a/src/meshcat/tests/test_drawing.py +++ b/src/meshcat/tests/test_drawing.py @@ -23,10 +23,10 @@ def setUp(self): port = self.vis.url().split(":")[-1].split("/")[0] self.dummy_proc = subprocess.Popen([sys.executable, "-m", "meshcat.tests.dummy_websocket_client", str(port)]) else: - self.vis.open() + #self.vis.open() self.dummy_proc = None - self.vis.wait() + #self.vis.wait() def tearDown(self): if self.dummy_proc is not None: @@ -271,6 +271,43 @@ def runTest(self): v.set_object(g.TriangularMeshGeometry(vertices, faces, colors), g.MeshLambertMaterial(vertexColors=True, wireframe=True)) +class TestUUIDCloning(VisualizerTest): + def runTest(self): + """ + Test that geometry with identical UUIDs are handled correctly. + """ + v = self.vis["triangular_mesh"] + v.set_transform(tf.rotation_matrix(np.pi/2, [0., 0, 1])) + vertices = np.array([ + [0, 0, 0], + [1, 0, 0], + [1, 0, 1], + [0, 0, 1] + ]) + faces = np.array([ + [0, 1, 2], + [3, 0, 2] + ]) + geom = g.TriangularMeshGeometry(vertices, faces) + mat = g.MeshLambertMaterial(color=0xeedd22, wireframe=True) + geom.uuid = 1234 + mat.uuid = 5678 + v.set_object(geom, mat) + + # This should be drawn as a duplicate of the first geometry + # at and offset; if nothing appears, or the material is different, + # the UUID lookup did not succeed. + geom_2 = g.TriangularMeshGeometry(np.empty((0, 3)), np.empty((0, 3))) + mat_2 = g.MeshLambertMaterial(color=0x000000, wireframe=False) + geom_2.uuid = 1234 + mat_2.uuid = 5678 + v2 = v["duplicate"] + v2.set_transform(tf.translation_matrix([2., 0., 0.])) + v2.set_object(geom_2, mat_2) + + import time + time.sleep(1000) + class TestOrthographicCamera(VisualizerTest): def runTest(self): """ diff --git a/src/meshcat/viewer b/src/meshcat/viewer index 978cb8f..d75b33b 160000 --- a/src/meshcat/viewer +++ b/src/meshcat/viewer @@ -1 +1 @@ -Subproject commit 978cb8f519f9bb540e94b7f97a39ada4d7916b7c +Subproject commit d75b33b84a32f10ba1c526fa3cd60f617a69a2c4 From 3f7fc1add884ccada71f9f645ed9b537b0b3ffa6 Mon Sep 17 00:00:00 2001 From: Gregory Izatt Date: Wed, 20 Apr 2022 20:19:10 -0400 Subject: [PATCH 2/2] Return test to a reasonable state --- src/meshcat/tests/test_drawing.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/meshcat/tests/test_drawing.py b/src/meshcat/tests/test_drawing.py index 317d562..3cb3539 100644 --- a/src/meshcat/tests/test_drawing.py +++ b/src/meshcat/tests/test_drawing.py @@ -23,10 +23,10 @@ def setUp(self): port = self.vis.url().split(":")[-1].split("/")[0] self.dummy_proc = subprocess.Popen([sys.executable, "-m", "meshcat.tests.dummy_websocket_client", str(port)]) else: - #self.vis.open() + self.vis.open() self.dummy_proc = None - #self.vis.wait() + self.vis.wait() def tearDown(self): if self.dummy_proc is not None: @@ -304,9 +304,6 @@ def runTest(self): v2 = v["duplicate"] v2.set_transform(tf.translation_matrix([2., 0., 0.])) v2.set_object(geom_2, mat_2) - - import time - time.sleep(1000) class TestOrthographicCamera(VisualizerTest): def runTest(self):