diff --git a/demo.ipynb b/demo.ipynb index a3c6369..5562863 100644 --- a/demo.ipynb +++ b/demo.ipynb @@ -153,6 +153,75 @@ "vis.delete()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "MeshCat supports simple 2d texts rendering. For example, to write 2d texts onto a geometry:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "vis.set_object(g.Box([1, 1, 2]),g.MeshPhongMaterial(map=g.TextTexture('Hello, world!')))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is also possible to simple write 'floating' texts onto a scene without attaching it to an object (e.g., for scene description):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "vis.delete()\n", + "vis.set_object(g.SceneText('Hello, world!',font_size=100))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "and just like the usual geometry/object, the scene texts can be rotated:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Rz = tf.rotation_matrix(np.pi/2, [0, 0, 1])\n", + "Ry = tf.rotation_matrix(np.pi/2, [0, 1, 0])\n", + "vis.set_transform(Ry.dot(Rz))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Under the hood, the `SceneTexts` are written onto a `Plane` geometry, and the plane size can be specified by width and height. These two parameters affect the texts size when the font_size itself is set too large; they would force a font downsizing when rendering so as to fit all the texts within the specified plane." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for i in np.linspace(8,2,10):\n", + " vis.set_object(g.SceneText('Hello, world!',width=2*i,height=2*i,font_size=300))\n", + " time.sleep(0.05)" + ] + }, { "cell_type": "markdown", "metadata": {}, diff --git a/src/meshcat/commands.py b/src/meshcat/commands.py index 037bb5f..ad30ea7 100644 --- a/src/meshcat/commands.py +++ b/src/meshcat/commands.py @@ -4,7 +4,8 @@ if sys.version_info >= (3, 0): unicode = str -from .geometry import Geometry, Object, Mesh, MeshPhongMaterial, PointsMaterial, Points +from .geometry import (Geometry, Plane, Object, Mesh, +MeshPhongMaterial, PointsMaterial, Points, TextTexture) class SetObject: __slots__ = ["object", "path"] diff --git a/src/meshcat/geometry.py b/src/meshcat/geometry.py index 66e30d2..8938658 100644 --- a/src/meshcat/geometry.py +++ b/src/meshcat/geometry.py @@ -86,6 +86,25 @@ def intrinsic_transform(self): return np.diag(np.hstack((self.radii, 1.0))) +class Plane(Geometry): + + def __init__(self, width=1, height=1, widthSegments=1, heightSegments=1): + super(Plane, self).__init__() + self.width = width + self.height = height + self.widthSegments = widthSegments + self.heightSegments = heightSegments + + def lower(self, object_data): + return { + u"uuid": self.uuid, + u"type": u"PlaneGeometry", + u"width": self.width, + u"height": self.height, + u"widthSegments": self.widthSegments, + u"heightSegments": self.heightSegments, + } + """ A cylinder of the given height and radius. By Three.js convention, the axis of rotational symmetry is aligned with the y-axis. @@ -184,6 +203,26 @@ def lower(self, object_data): } +class TextTexture(Texture): + + def __init__(self, text, font_size=100, font_face='sans-serif', + width=200, height=100, position=[10, 10]): + super(TextTexture, self).__init__() + self.text = text + # font_size will be passed to the JS side as is; however if the + # text width exceeds canvas width, font_size will be reduced. + self.font_size = font_size + self.font_face = font_face + + def lower(self, object_data): + return { + u"uuid": self.uuid, + u"type": u"_text", + u"text": unicode(self.text), + u"font_size": self.font_size, + u"font_face": self.font_face, + } + class GenericTexture(Texture): def __init__(self, properties): super(GenericTexture, self).__init__() @@ -390,6 +429,15 @@ def PointCloud(position, color, **kwargs): ) + +def SceneText(text, width=10, height=10, **kwargs): + return Mesh( + Plane(width=width,height=height), + MeshPhongMaterial(map=TextTexture(text,**kwargs),transparent=True, + needsUpdate=True) + ) + + class Line(Object): _type = u"Line"