def shape_to_mesh(self, shape: Shape): """ Convert pyphysx shape into the pyrender Mesh """ clr_string = shape.get_user_data().get( 'color', None) if shape.get_user_data() is not None else None clr = gl_color_from_matplotlib(color=clr_string, return_rgba=True) basic_trimesh = self._trimesh_from_basic_shape(shape, clr) if basic_trimesh is not None: return Mesh.from_trimesh(basic_trimesh) elif shape.get_geometry_type() == GeometryType.CONVEXMESH: data = shape.get_shape_data() # N x 9 - i.e. 3 triangles primitive = Primitive(data.reshape(-1, 3), normals=None, color_0=clr, mode=GLTF.TRIANGLES, poses=None) return Mesh(primitives=[primitive]) elif shape.get_geometry_type() == GeometryType.PLANE: clr = [0.8] * 3 + [ 0.1 ] if clr_string is None else gl_color_from_matplotlib( clr_string, return_rgba=True) primitive = Primitive(positions=self._grid_lines(), normals=None, color_0=clr, mode=GLTF.LINES, poses=None) return Mesh(primitives=[primitive]) else: raise NotImplementedError('Not supported type of the geometry.')
def create_2d_point_mesh(width, height, pts_2d, point_size_px): # create a triangle mesh def _rot_mat(angle_rad): return np.array( [[np.cos(angle_rad), -np.sin(angle_rad)], [np.sin(angle_rad), np.cos(angle_rad)]], dtype=np.float32) if isinstance(pts_2d, list): pts_2d = np.array(pts_2d, dtype=np.float32) vertices = np.zeros((3, 3), dtype=np.float32) point_size_ndc = point_size_px / height vec = np.array([0, point_size_ndc]) vertices[0, 0:2] = vec vertices[1, 0:2] = _rot_mat(np.radians(120)) @ vec vertices[2, 0:2] = _rot_mat(np.radians(-120)) @ vec mat = MetallicRoughnessMaterial(doubleSided=True, baseColorFactor=[1.0, 0, 0, 1]) instances = [np.eye(4) for i in range(pts_2d.shape[0])] for i in range(pts_2d.shape[0]): instances[i][0, 3] = (2 * pts_2d[i][0] - width) / height instances[i][1, 3] = pts_2d[i][1] / height * 2 - 1 instances[i][2, 3] = -1 prim = Primitive(positions=vertices, mode=GLTF.TRIANGLES, material=mat, poses=instances) return Mesh(primitives=[prim])
def test_meshes(): with pytest.raises(TypeError): x = Mesh() with pytest.raises(TypeError): x = Primitive() with pytest.raises(ValueError): x = Primitive([], mode=10) # Basics x = Mesh([]) assert x.name is None assert x.is_visible assert x.weights is None x.name = 'str' # From Trimesh x = Mesh.from_trimesh(trimesh.creation.box()) assert isinstance(x, Mesh) assert len(x.primitives) == 1 assert x.is_visible assert np.allclose(x.bounds, np.array([ [-0.5, -0.5, -0.5], [0.5, 0.5, 0.5] ])) assert np.allclose(x.centroid, np.zeros(3)) assert np.allclose(x.extents, np.ones(3)) assert np.allclose(x.scale, np.sqrt(3)) assert not x.is_transparent # Test some primitive functions x = x.primitives[0] with pytest.raises(ValueError): x.normals = np.zeros(10) with pytest.raises(ValueError): x.tangents = np.zeros(10) with pytest.raises(ValueError): x.texcoord_0 = np.zeros(10) with pytest.raises(ValueError): x.texcoord_1 = np.zeros(10) with pytest.raises(TypeError): x.material = np.zeros(10) assert x.targets is None assert np.allclose(x.bounds, np.array([ [-0.5, -0.5, -0.5], [0.5, 0.5, 0.5] ])) assert np.allclose(x.centroid, np.zeros(3)) assert np.allclose(x.extents, np.ones(3)) assert np.allclose(x.scale, np.sqrt(3)) x.material.baseColorFactor = np.array([0.0, 0.0, 0.0, 0.0]) assert x.is_transparent # From two trimeshes x = Mesh.from_trimesh([trimesh.creation.box(), trimesh.creation.cylinder(radius=0.1, height=2.0)], smooth=False) assert isinstance(x, Mesh) assert len(x.primitives) == 2 assert x.is_visible assert np.allclose(x.bounds, np.array([ [-0.5, -0.5, -1.0], [0.5, 0.5, 1.0] ])) assert np.allclose(x.centroid, np.zeros(3)) assert np.allclose(x.extents, [1.0, 1.0, 2.0]) assert np.allclose(x.scale, np.sqrt(6)) assert not x.is_transparent # From bad data with pytest.raises(TypeError): x = Mesh.from_trimesh(None) # With instancing poses = np.tile(np.eye(4), (5,1,1)) poses[:,0,3] = np.array([0,1,2,3,4]) x = Mesh.from_trimesh(trimesh.creation.box(), poses=poses) assert np.allclose(x.bounds, np.array([ [-0.5, -0.5, -0.5], [4.5, 0.5, 0.5] ])) poses = np.eye(4) x = Mesh.from_trimesh(trimesh.creation.box(), poses=poses) poses = np.eye(3) with pytest.raises(ValueError): x = Mesh.from_trimesh(trimesh.creation.box(), poses=poses) # From textured meshes fm = trimesh.load('tests/data/fuze.obj') x = Mesh.from_trimesh(fm) assert isinstance(x, Mesh) assert len(x.primitives) == 1 assert x.is_visible assert not x.is_transparent assert x.primitives[0].material.baseColorTexture is not None x = Mesh.from_trimesh(fm, smooth=False) fm.visual = fm.visual.to_color() fm.visual.face_colors = np.array([1.0, 0.0, 0.0, 1.0]) x = Mesh.from_trimesh(fm, smooth=False) with pytest.raises(ValueError): x = Mesh.from_trimesh(fm, smooth=True) fm.visual.vertex_colors = np.array([1.0, 0.0, 0.0, 0.5]) x = Mesh.from_trimesh(fm, smooth=False) x = Mesh.from_trimesh(fm, smooth=True) assert x.primitives[0].color_0 is not None assert x.is_transparent bm = trimesh.load('tests/data/WaterBottle.glb').dump()[0] x = Mesh.from_trimesh(bm) assert x.primitives[0].material.baseColorTexture is not None assert x.primitives[0].material.emissiveTexture is not None assert x.primitives[0].material.metallicRoughnessTexture is not None # From point cloud x = Mesh.from_points(fm.vertices)
def test_scenes(): # Basics s = Scene() assert np.allclose(s.bg_color, np.ones(4)) assert np.allclose(s.ambient_light, np.zeros(3)) assert len(s.nodes) == 0 assert s.name is None s.name = 'asdf' s.bg_color = None s.ambient_light = None assert np.allclose(s.bg_color, np.ones(4)) assert np.allclose(s.ambient_light, np.zeros(3)) assert s.nodes == set() assert s.cameras == set() assert s.lights == set() assert s.point_lights == set() assert s.spot_lights == set() assert s.directional_lights == set() assert s.meshes == set() assert s.camera_nodes == set() assert s.light_nodes == set() assert s.point_light_nodes == set() assert s.spot_light_nodes == set() assert s.directional_light_nodes == set() assert s.mesh_nodes == set() assert s.main_camera_node is None assert np.all(s.bounds == 0) assert np.all(s.centroid == 0) assert np.all(s.extents == 0) assert np.all(s.scale == 0) # From trimesh scene tms = trimesh.load('tests/data/WaterBottle.glb') s = Scene.from_trimesh_scene(tms) assert len(s.meshes) == 1 assert len(s.mesh_nodes) == 1 # Test bg color formatting s = Scene(bg_color=[0, 1.0, 0]) assert np.allclose(s.bg_color, np.array([0.0, 1.0, 0.0, 1.0])) # Test constructor for nodes n1 = Node() n2 = Node() n3 = Node() nodes = [n1, n2, n3] s = Scene(nodes=nodes) n1.children.append(n2) s = Scene(nodes=nodes) n3.children.append(n2) with pytest.raises(ValueError): s = Scene(nodes=nodes) n3.children = [] n2.children.append(n3) n3.children.append(n2) with pytest.raises(ValueError): s = Scene(nodes=nodes) # Test node accessors n1 = Node() n2 = Node() n3 = Node() nodes = [n1, n2] s = Scene(nodes=nodes) assert s.has_node(n1) assert s.has_node(n2) assert not s.has_node(n3) # Test node poses for n in nodes: assert np.allclose(s.get_pose(n), np.eye(4)) with pytest.raises(ValueError): s.get_pose(n3) with pytest.raises(ValueError): s.set_pose(n3, np.eye(4)) tf = np.eye(4) tf[:3, 3] = np.ones(3) s.set_pose(n1, tf) assert np.allclose(s.get_pose(n1), tf) assert np.allclose(s.get_pose(n2), np.eye(4)) nodes = [n1, n2, n3] tf2 = np.eye(4) tf2[:3, :3] = np.diag([-1, -1, 1]) n1.children.append(n2) n1.matrix = tf n2.matrix = tf2 s = Scene(nodes=nodes) assert np.allclose(s.get_pose(n1), tf) assert np.allclose(s.get_pose(n2), tf.dot(tf2)) assert np.allclose(s.get_pose(n3), np.eye(4)) n1 = Node() n2 = Node() n3 = Node() n1.children.append(n2) s = Scene() s.add_node(n1) with pytest.raises(ValueError): s.add_node(n2) s.set_pose(n1, tf) assert np.allclose(s.get_pose(n1), tf) assert np.allclose(s.get_pose(n2), tf) s.set_pose(n2, tf2) assert np.allclose(s.get_pose(n2), tf.dot(tf2)) # Test node removal n1 = Node() n2 = Node() n3 = Node() n1.children.append(n2) n2.children.append(n3) s = Scene(nodes=[n1, n2, n3]) s.remove_node(n2) assert len(s.nodes) == 1 assert n1 in s.nodes assert len(n1.children) == 0 assert len(n2.children) == 1 s.add_node(n2, parent_node=n1) assert len(n1.children) == 1 n1.matrix = tf n3.matrix = tf2 assert np.allclose(s.get_pose(n3), tf.dot(tf2)) # Now test ADD function s = Scene() m = Mesh([], name='m') cp = PerspectiveCamera(yfov=2.0) co = OrthographicCamera(xmag=1.0, ymag=1.0) dl = DirectionalLight() pl = PointLight() sl = SpotLight() n1 = s.add(m, name='mn') assert n1.mesh == m assert len(s.nodes) == 1 assert len(s.mesh_nodes) == 1 assert n1 in s.mesh_nodes assert len(s.meshes) == 1 assert m in s.meshes assert len(s.get_nodes(node=n2)) == 0 n2 = s.add(m, pose=tf) assert len(s.nodes) == len(s.mesh_nodes) == 2 assert len(s.meshes) == 1 assert len(s.get_nodes(node=n1)) == 1 assert len(s.get_nodes(node=n1, name='mn')) == 1 assert len(s.get_nodes(name='mn')) == 1 assert len(s.get_nodes(obj=m)) == 2 assert len(s.get_nodes(obj=m, obj_name='m')) == 2 assert len(s.get_nodes(obj=co)) == 0 nsl = s.add(sl, name='sln') npl = s.add(pl, parent_name='sln') assert nsl.children[0] == npl ndl = s.add(dl, parent_node=npl) assert npl.children[0] == ndl nco = s.add(co) ncp = s.add(cp) assert len(s.light_nodes) == len(s.lights) == 3 assert len(s.point_light_nodes) == len(s.point_lights) == 1 assert npl in s.point_light_nodes assert len(s.spot_light_nodes) == len(s.spot_lights) == 1 assert nsl in s.spot_light_nodes assert len(s.directional_light_nodes) == len(s.directional_lights) == 1 assert ndl in s.directional_light_nodes assert len(s.cameras) == len(s.camera_nodes) == 2 assert s.main_camera_node == nco s.main_camera_node = ncp s.remove_node(ncp) assert len(s.cameras) == len(s.camera_nodes) == 1 assert s.main_camera_node == nco s.remove_node(n2) assert len(s.meshes) == 1 s.remove_node(n1) assert len(s.meshes) == 0 s.remove_node(nsl) assert len(s.lights) == 0 s.remove_node(nco) assert s.main_camera_node is None s.add_node(n1) s.clear() assert len(s.nodes) == 0 # Trigger final errors with pytest.raises(ValueError): s.main_camera_node = None with pytest.raises(ValueError): s.main_camera_node = ncp with pytest.raises(ValueError): s.add(m, parent_node=n1) with pytest.raises(ValueError): s.add(m, name='asdf') s.add(m, name='asdf') s.add(m, parent_name='asdf') with pytest.raises(ValueError): s.add(m, parent_name='asfd') with pytest.raises(TypeError): s.add(None) s.clear() # Test bounds m1 = Mesh.from_trimesh(trimesh.creation.box()) m2 = Mesh.from_trimesh(trimesh.creation.box()) m3 = Mesh.from_trimesh(trimesh.creation.box()) n1 = Node(mesh=m1) n2 = Node(mesh=m2, translation=[1.0, 0.0, 0.0]) n3 = Node(mesh=m3, translation=[0.5, 0.0, 1.0]) s.add_node(n1) s.add_node(n2) s.add_node(n3) assert np.allclose(s.bounds, [[-0.5, -0.5, -0.5], [1.5, 0.5, 1.5]]) s.clear() s.add_node(n1) s.add_node(n2, parent_node=n1) s.add_node(n3, parent_node=n2) assert np.allclose(s.bounds, [[-0.5, -0.5, -0.5], [2.0, 0.5, 1.5]]) tf = np.eye(4) tf[:3, 3] = np.ones(3) s.set_pose(n3, tf) assert np.allclose(s.bounds, [[-0.5, -0.5, -0.5], [2.5, 1.5, 1.5]]) s.remove_node(n2) assert np.allclose(s.bounds, [[-0.5, -0.5, -0.5], [0.5, 0.5, 0.5]]) s.clear() assert np.allclose(s.bounds, 0.0)
def test_nodes(): x = Node() assert x.name is None assert x.camera is None assert x.children == [] assert x.skin is None assert np.allclose(x.matrix, np.eye(4)) assert x.mesh is None assert np.allclose(x.rotation, [0, 0, 0, 1]) assert np.allclose(x.scale, np.ones(3)) assert np.allclose(x.translation, np.zeros(3)) assert x.weights is None assert x.light is None x.name = 'node' # Test node light/camera/mesh tests c = PerspectiveCamera(yfov=2.0) m = Mesh([]) d = DirectionalLight() x.camera = c assert x.camera == c with pytest.raises(TypeError): x.camera = m x.camera = d x.camera = None x.mesh = m assert x.mesh == m with pytest.raises(TypeError): x.mesh = c x.mesh = d x.light = d assert x.light == d with pytest.raises(TypeError): x.light = m x.light = c # Test transformations getters/setters/etc... # Set up test values x = np.array([1.0, 0.0, 0.0]) y = np.array([0.0, 1.0, 0.0]) t = np.array([1.0, 2.0, 3.0]) s = np.array([0.5, 2.0, 1.0]) Mx = transformations.rotation_matrix(np.pi / 2.0, x) qx = np.roll(transformations.quaternion_about_axis(np.pi / 2.0, x), -1) Mxt = Mx.copy() Mxt[:3, 3] = t S = np.eye(4) S[:3, :3] = np.diag(s) Mxts = Mxt.dot(S) My = transformations.rotation_matrix(np.pi / 2.0, y) qy = np.roll(transformations.quaternion_about_axis(np.pi / 2.0, y), -1) Myt = My.copy() Myt[:3, 3] = t x = Node(matrix=Mx) assert np.allclose(x.matrix, Mx) assert np.allclose(x.rotation, qx) assert np.allclose(x.translation, np.zeros(3)) assert np.allclose(x.scale, np.ones(3)) x.matrix = My assert np.allclose(x.matrix, My) assert np.allclose(x.rotation, qy) assert np.allclose(x.translation, np.zeros(3)) assert np.allclose(x.scale, np.ones(3)) x.translation = t assert np.allclose(x.matrix, Myt) assert np.allclose(x.rotation, qy) x.rotation = qx assert np.allclose(x.matrix, Mxt) x.scale = s assert np.allclose(x.matrix, Mxts) x = Node(matrix=Mxt) assert np.allclose(x.matrix, Mxt) assert np.allclose(x.rotation, qx) assert np.allclose(x.translation, t) assert np.allclose(x.scale, np.ones(3)) x = Node(matrix=Mxts) assert np.allclose(x.matrix, Mxts) assert np.allclose(x.rotation, qx) assert np.allclose(x.translation, t) assert np.allclose(x.scale, s) # Individual element getters x.scale[0] = 0 assert np.allclose(x.scale[0], 0) x.translation[0] = 0 assert np.allclose(x.translation[0], 0) x.matrix = np.eye(4) x.matrix[0, 0] = 500 assert x.matrix[0, 0] == 1.0 # Failures with pytest.raises(ValueError): x.matrix = 5 * np.eye(4) with pytest.raises(ValueError): x.matrix = np.eye(5) with pytest.raises(ValueError): x.matrix = np.eye(4).dot([5, 1, 1, 1]) with pytest.raises(ValueError): x.rotation = np.array([1, 2]) with pytest.raises(ValueError): x.rotation = np.array([1, 2, 3]) with pytest.raises(ValueError): x.rotation = np.array([1, 2, 3, 4]) with pytest.raises(ValueError): x.translation = np.array([1, 2, 3, 4]) with pytest.raises(ValueError): x.scale = np.array([1, 2, 3, 4])