def test_export_to_x3d_IndexedFaceSet(self):
     """ 3rd test : export a sphere to an X3D IndexedFaceSet triangle mesh """
     a_sphere = BRepPrimAPI_MakeBox(10., 10., 10.).Shape()
     ifs = Tesselator(a_sphere).ExportShapeToX3DIndexedFaceSet()
     self.assert_(ifs.startswith("<IndexedFaceSet"))
     self.assert_("0 10 0" in ifs)  # a vertex
     self.assert_("0 0 1" in ifs)  # a normal
예제 #2
0
 def test_export_to_x3d(self):
     """ 3rd test : export a sphere to X3D file format """
     a_sphere = BRepPrimAPI_MakeSphere(10.).Shape()
     tess = Tesselator(a_sphere)
     tess.Compute()
     tess.ExportShapeToX3D(os.path.join("test_io", "sphere.x3d"))
     self.assert_(os.path.exists(os.path.join("test_io", "sphere.x3d")))
예제 #3
0
 def test_export_to_x3d_IndexedFaceSet(self):
     """ 3rd test : export a sphere to an X3D IndexedFaceSet triangle mesh """
     a_sphere = BRepPrimAPI_MakeBox(10., 10., 10.).Shape()
     ifs = Tesselator(a_sphere).ExportShapeToX3DIndexedFaceSet()
     self.assert_(ifs.startswith("<IndexedFaceSet"))
     self.assert_("0 10 0" in ifs)  # a vertex
     self.assert_("0 0 1" in ifs)  # a normal
예제 #4
0
 def test_tesselate_torus(self):
     """ 2st test : tesselation of a torus """
     a_box = BRepPrimAPI_MakeTorus(10, 4).Shape()
     tess = Tesselator(a_box, atNormal, 1.0, 1, 0.01, 0.1, 0.1, 0.1, 0.1,
                       0.1, 0.1, 0.)
     self.assert_(tess.ObjGetTriangleCount() > 100)
     self.assert_(tess.ObjGetNormalCount() > 100)
예제 #5
0
 def test_tesselate_box(self):
     """ 1st test : tesselation of a box """
     a_box = BRepPrimAPI_MakeBox(10, 20, 30).Shape()
     tess = Tesselator(a_box, atNormal, 1.0, 1, 0.01, 0.1, 0.1, 0.1, 0.1,
                       0.1, 0.1, 0.)
     self.assert_(tess.ObjGetTriangleCount() == 12)
     self.assert_(tess.ObjGetNormalCount() == 24)
예제 #6
0
 def test_tesselate_torus_with_edges(self):
     """ 2st test : tesselation of a torus """
     a_torus = BRepPrimAPI_MakeTorus(10, 4).Shape()
     tess = Tesselator(a_torus, atNormal, 1.0, 1, 0.01, 0.1, 0.1, 0.1, 0.1,
                       0.1, 0.1, 0.)
     tess.Compute(compute_edges=True)
     self.assert_(tess.ObjGetTriangleCount() > 100)
     self.assert_(tess.ObjGetNormalCount() > 100)
예제 #7
0
def import_as_one_shape(file):
    shp = read_step_file(file)
    tess = Tesselator(shp)
    tess.Compute()
    threejsString = tess.ExportShapeToThreejsJSONString('someid')
    # with open("outputs/threejs/shape.json", "w") as f:
    #    f.write(threejsString)
    return threejsString
예제 #8
0
 def test_export_to_3js_JSON(self):
     a_box = BRepPrimAPI_MakeBox(10, 20, 30).Shape()
     tess = Tesselator(a_box)
     tess.Compute()
     # get the JSON string
     JSON_str = tess.ExportShapeToThreejsJSONString("myshapeid")
     # check the python JSON parser can decode the string
     # i.e. the JSON string is well formed
     dico = json.loads(JSON_str)
     # after that, check that the number of vertices is ok
     assert len(dico["data"]["attributes"]["position"]["array"]) == 36 * 3
예제 #9
0
    def _exportThreeJS(filePath, _shape):
        _tess = Tesselator(_shape)
        _tess.Compute(uv_coords=False, compute_edges=False, mesh_quality=50)

        json_shape = _tess.ExportShapeToThreejsJSONString(filePath)

        json_shape = json_shape.replace("data\\", "data/")
        json_shape = json_shape.replace("\\step_postprocessed\\",
                                        "/step_postprocessed/")

        return json_shape
예제 #10
0
 def test_tesselate_torus_with_bad_quality(self):
     """ 2st test : tesselation of a torus """
     a_torus = BRepPrimAPI_MakeTorus(10, 4).Shape()
     tess = Tesselator(a_torus, atNormal, 1.0, 1, 0.01, 0.1, 0.1, 0.1, 0.1,
                       0.1, 0.1, 0.)
     tess.Compute(mesh_quality=40.)
     # since mesh quality is much lower, we should count less vertices and
     # triangles
     self.assert_(tess.ObjGetTriangleCount() > 10)
     self.assert_(tess.ObjGetTriangleCount() < 100)
     self.assert_(tess.ObjGetNormalCount() > 10)
     self.assert_(tess.ObjGetNormalCount() < 100)
예제 #11
0
 def DisplayShape(self,
                  shape,
                  vertex_shader=None,
                  fragment_shader=None,
                  map_faces_to_mesh=False,
                  export_edges=False,
                  color=(0.65, 0.65, 0.65),
                  specular_color=(1, 1, 1),
                  shininess=0.9,
                  transparency=0.,
                  line_color=(0, 0., 0.),
                  line_width=2.,
                  mesh_quality=1.):
     # create the shape hash
     shape_uuid = uuid.uuid4().hex
     shape_hash = "shp%s" % shape_uuid
     # tesselate
     tess = Tesselator(shape)
     tess.Compute(compute_edges=export_edges, mesh_quality=mesh_quality)
     #
     sys.stdout.write(
         "\r%s mesh shape, %i triangles" %
         (next(self.spinning_cursor), tess.ObjGetTriangleCount()))
     sys.stdout.flush()
     # export to 3JS
     shape_full_path = os.path.join(self._path, shape_hash + '.json')
     # add this shape to the shape dict, sotres everything related to it
     self._3js_shapes[shape_hash] = [
         export_edges, color, specular_color, shininess, transparency,
         line_color, line_width
     ]
     # generate the mesh
     #tess.ExportShapeToThreejs(shape_hash, shape_full_path)
     # and also to JSON
     with open(shape_full_path, 'w') as json_file:
         json_file.write(tess.ExportShapeToThreejsJSONString(shape_uuid))
     # draw edges if necessary
     edges = []
     if export_edges:
         # export each edge to a single json
         # get number of edges
         nbr_edges = tess.ObjGetEdgeCount()
         for i_edge in range(nbr_edges):
             # after that, the file can be appended
             str_to_write = ''
             edge_point_set = []
             nbr_vertices = tess.ObjEdgeGetVertexCount(i_edge)
             for i_vert in range(nbr_vertices):
                 edge_point_set.append(tess.GetEdgeVertex(i_edge, i_vert))
             # write to file
             edge_hash = "edg%s" % uuid.uuid4().hex
             str_to_write += ExportEdgeToJSON(edge_hash, edge_point_set)
             # create the file
             edge_full_path = os.path.join(self._path, edge_hash + '.json')
             with open(edge_full_path, "w") as edge_file:
                 edge_file.write(str_to_write)
             # store this edge hash
             self._edges_hash.append(edge_hash)
 def create_files(self, shape):
     ''' generate .js and .html files '''
     self._shape = shape
     print("Tesselate shape ...")
     t0 = time()
     tess = Tesselator(self._shape)
     t1 = time()
     print("done in %f s." % (t1-t0))
     print("Exporting tesselation to JSON ...")
     t2 = time()
     tess.ExportShapeToThreejs(self._js_filename)
     t3 = time()
     print("done in %f s." % (t3-t2))
     print("Generating HTML stream ...")
     self.GenerateHTMLFile()
     print("done.")
     return self._js_filename, self._html_filename
예제 #13
0
 def DisplayShape(self, shape):
     self._shape = shape
     print("Tesselate shape ...")
     t0 = time()
     tess = Tesselator(self._shape)
     t1 = time()
     print("done in %f s." % (t1 - t0))
     print("Exporting tesselation to X3D ...")
     t2 = time()
     tess.ExportShapeToX3D(self._x3d_filename)
     t3 = time()
     print("done in %f s." % (t3 - t2))
     print("Generating HTML stream ...")
     self.GenerateHTMLFile()
     print("done.")
     print("Opening html output in the default webbrowser ...")
     # open the file in the browser
     _path = "file:///{0}".format(
         os.path.join(os.getcwd(), self._html_filename))
     webbrowser.open_new_tab(_path)
예제 #14
0
 def DisplayShape(self, shape):
     self._shape = shape
     print("Tesselate shape ...")
     t0 = time()
     tess = Tesselator(self._shape)
     t1 = time()
     print("done in %f s." % (t1 - t0))
     print("Exporting tesselation to JSON ...")
     t2 = time()
     tess.ExportShapeToJSON(self._js_filename)
     t3 = time()
     print("done in %f s." % (t3 - t2))
     print("Generating HTML stream ...")
     self.GenerateHTMLFile()
     print("done.")
     print("Opening html output in the default webbrowser ...")
     # previous version us a os.system call to the "open" command
     # but this is a platform (osx) specific solution
     _path = "file:///{0}".format(
         os.path.join(os.getcwd(), self._html_filename))
     webbrowser.open_new_tab(_path)
예제 #15
0
def draw_shape_mpl(shape):
    """
    Draw a TopoDS_Shape with matplotlib
    """

    tess = Tesselator(shape)

    triangles = []
    edges = []

    # get the triangles
    triangle_count = tess.ObjGetTriangleCount()
    for i_triangle in range(0, triangle_count):
        i1, i2, i3 = tess.GetTriangleIndex(i_triangle)
        triangles.append(
            [tess.GetVertex(i1),
             tess.GetVertex(i2),
             tess.GetVertex(i3)])

    # get the edges
    edge_count = tess.ObjGetEdgeCount()
    for i_edge in range(0, edge_count):
        vertex_count = tess.ObjEdgeGetVertexCount(i_edge)
        edge = []
        for i_vertex in range(0, vertex_count):
            vertex = tess.GetEdgeVertex(i_edge, i_vertex)
            edge.append(vertex)
        edges.append(edge)

    # plot it
    fig = plt.figure()
    ax = Axes3D(fig)

    ax.add_collection3d(Poly3DCollection(triangles, linewidths=0.2, alpha=0.5))
    ax.add_collection3d(Line3DCollection(edges, colors='w', linewidths=1.0))

    ax.get_xaxis().set_visible(True)
    ax.get_yaxis().set_visible(True)
    ax.set_autoscale_on(True)
    plt.show()
예제 #16
0
 def compute(self):
     shape_tesselator = Tesselator(self._shape)
     shape_tesselator.Compute(compute_edges=self._export_edges,
                              mesh_quality=self._mesh_quality)
     self._triangle_sets.append(shape_tesselator.ExportShapeToX3DIndexedFaceSet())
     # then process edges
     if self._export_edges:
         # get number of edges
         nbr_edges = shape_tesselator.ObjGetEdgeCount()
         for i_edge in range(nbr_edges):
             edge_point_set = []
             nbr_vertices = shape_tesselator.ObjEdgeGetVertexCount(i_edge)
             for i_vert in range(nbr_vertices):
                 edge_point_set.append(shape_tesselator.GetEdgeVertex(i_edge, i_vert))
             ils = ExportEdgeToILS(edge_point_set)
             self._line_sets.append(ils)
예제 #17
0
    def tessellate(self, tolerance):
        tess = Tesselator(self.wrapped)
        tess.Compute(compute_edges=True, mesh_quality=tolerance)

        vertices = []
        indexes = []

        # add vertices
        for i_vert in range(tess.ObjGetVertexCount()):
            xyz = tess.GetVertex(i_vert)
            vertices.append(Vector(*xyz))

        # add triangles
        for i_tr in range(tess.ObjGetTriangleCount()):
            indexes.append(tess.GetTriangleIndex(i_tr))

        return vertices, indexes
예제 #18
0
 def compute(self):
     # get faces
     explorer = TopExp_Explorer()
     explorer.Init(self._shape, TopAbs_FACE)
     if self._map_faces_to_mesh:  # one mesh per face
         faces = []
         while explorer.More():
             current_face = explorer.Current()
             faces.append(current_face)
             explorer.Next()
         # loop over faces
         for face in faces:
             face_tesselator = Tesselator(face)
             self._indexed_face_sets.append(face_tesselator.ExportShapeToX3DIndexedFaceSet())
     else:  # only one mesh for the whole shape
         shape_tesselator = Tesselator(self._shape)
         self._indexed_face_sets.append(shape_tesselator.ExportShapeToX3DIndexedFaceSet())
예제 #19
0
def _write_threejs_json(html_dir, shape):
    tess = Tesselator(shape)
    tess.Compute(compute_edges=False, mesh_quality=1.)
    with open(os.path.join(html_dir, "table.json"), 'w') as f:
        f.write(tess.ExportShapeToThreejsJSONString('table'))
예제 #20
0
 def test_export_to_x3d(self):
     """ 3rd test : export a sphere to X3D file format """
     a_sphere = BRepPrimAPI_MakeSphere(10.).Shape()
     Tesselator(a_sphere).ExportShapeToX3D("sphere.x3d")
     self.assert_(os.path.exists("sphere.x3d"))
예제 #21
0
def stpTox3d(filename):
    shape = read_step_file('stp_uploads/%s.stp' % filename)
    tess = Tesselator(shape)
    tess.Compute()
    tess.ExportShapeToX3D('x3d_output/%s.x3d' % filename)
# TEST 1 : one big STEP file into one single compound
# loads the step file
# load twice, not a copy/paste typo. It's because meshes are stored
# the second time, meshing time is much faster
print("TEST 1 ===")
shp = read_step_file(
    os.path.join('..', 'examples', 'models',
                 'RC_Buggy_2_front_suspension.stp'))
shp2 = read_step_file(
    os.path.join('..', 'examples', 'models',
                 'RC_Buggy_2_front_suspension.stp'))

# tesselate in single thread mode
print("Tesselate in single thread mode")
t_single = Tesselator(shp)
t0 = time.monotonic()
t_single.Compute(parallel=False, mesh_quality=0.5)
t1 = time.monotonic()
delta_single = t1 - t0

# tesselate in parallel thread mode
print("Tesselate in parallelized mode")
t_multi = Tesselator(shp2)
t2 = time.monotonic()
t_multi.Compute(parallel=True, mesh_quality=0.5)
t3 = time.monotonic()
delta_multi = t3 - t2

print("Test 1 Results:")
print("  * single thread runtime: %.2fs" % delta_single)
예제 #23
0
##along with pythonOCC.  If not, see <http://www.gnu.org/licenses/>.

from OCC.Visualization import Tesselator
from OCC.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakeTorus

try:
    import numpy as np
    HAVE_NUMPY = True
except:
    HAVE_NUMPY = False

# create the shape
box_s = BRepPrimAPI_MakeBox(10, 20, 30).Shape()

# compute the tesselation
tess = Tesselator(box_s)
tess.Compute()

# get vertices
vertices_position = tess.GetVerticesPositionAsTuple()

number_of_triangles = tess.ObjGetTriangleCount()
number_of_vertices = len(vertices_position)

# number of vertices should be a multiple of 3
assert number_of_vertices % 3 == 0
assert number_of_triangles * 9 == number_of_vertices

# get normals
normals = tess.GetNormalsAsTuple()
number_of_normals = len(normals)
예제 #24
0
    def DisplayShape(self,
                     shp,  # the TopoDS_Shape to be displayed
                     shape_color=default_shape_color,  # the default
                     render_edges=False,
                     edge_color=default_edge_color,
                     compute_uv_coords=False,
                     quality=1.0,
                     update=False):
        """ Displays a topods_shape in the renderer instance.
        shp: the TopoDS_Shape to render
        shape_color: the shape color, in html corm, eg '#abe000'
        render_edges: optional, False by default. If True, compute and dislay all
                      edges as a linear interpolation of segments.
        edge_color: optional, black by default. The color used for edge rendering,
                    in html form eg '#ff00ee'
        compute_uv_coords: optional, false by default. If True, compute texture
                           coordinates (required if the shape has to be textured)
        quality: optional, 1.0 by default. If set to something lower than 1.0,
                      mesh will be more precise. If set to something higher than 1.0,
                      mesh will be less precise, i.e. lower numer of triangles.
        update: optional, False by default. If True, render all the shapes.
        """
        # first, compute the tesselation
        tess = Tesselator(shp)
        tess.Compute(uv_coords=compute_uv_coords,
                     compute_edges=render_edges,
                     mesh_quality=quality,
                     parallel=self._parallel)
        # get vertices and normals
        vertices_position = tess.GetVerticesPositionAsTuple()

        number_of_triangles = tess.ObjGetTriangleCount()
        number_of_vertices = len(vertices_position)

        # number of vertices should be a multiple of 3
        assert number_of_vertices % 3 == 0
        assert number_of_triangles * 9 == number_of_vertices

        # then we build the vertex and faces collections as numpy ndarrays
        np_vertices = np.array(vertices_position, dtype='float32').reshape(int(number_of_vertices / 3), 3)
        # Note: np_faces is just [0, 1, 2, 3, 4, 5, ...], thus arange is used
        np_faces = np.arange(np_vertices.shape[0], dtype='uint32')

        # set geometry properties
        buffer_geometry_properties = {'position': BufferAttribute(np_vertices),
                                      'index'   : BufferAttribute(np_faces)}
        if self._compute_normals_mode == NORMAL.SERVER_SIDE:
            # get the normal list, converts to a numpy ndarray. This should not raise
            # any issue, since normals have been computed by the server, and are available
            # as a list of floats
            np_normals = np.array(tess.GetNormalsAsTuple(), dtype='float32').reshape(-1, 3)
            # quick check
            assert np_normals.shape == np_vertices.shape
            buffer_geometry_properties['normal'] = BufferAttribute(np_normals)

        # build a BufferGeometry instance
        shape_geometry = BufferGeometry(attributes=buffer_geometry_properties)

        # if the client has to render normals, add the related js instructions
        if self._compute_normals_mode == NORMAL.CLIENT_SIDE:
            shape_geometry.exec_three_obj_method('computeVertexNormals')

        # then a default material
        shp_material = MeshPhongMaterial(color=shape_color,
                                         polygonOffset=True,
                                         polygonOffsetFactor=1,
                                         polygonOffsetUnits=1,
                                         shininess=0.9)

        # create a mesh unique id
        mesh_id = uuid.uuid4().hex

        # finally create the mash
        shape_mesh = Mesh(geometry=shape_geometry,
                          material=shp_material,
                          name=mesh_id)

        # adds this mesh to the list of meshes
        self._displayed_pickable_objects.add(shape_mesh)

        # and to the dict of shapes, to have a mapping between meshes and shapes
        self._shapes[mesh_id] = shp

        # edge rendering, if set to True
        edge_lines = None
        if render_edges:
            edges = list(map(lambda i_edge: [tess.GetEdgeVertex(i_edge, i_vert) for i_vert in range(tess.ObjEdgeGetVertexCount(i_edge))], range(tess.ObjGetEdgeCount())))
            edges = list(filter(lambda edge: len(edge) == 2, edges))
            np_edge_vertices = np.array(edges, dtype=np.float32).reshape(-1, 3)
            np_edge_indices = np.arange(np_edge_vertices.shape[0], dtype=np.uint32)
            edge_geometry = BufferGeometry(attributes={
                'position': BufferAttribute(np_edge_vertices),
                'index'   : BufferAttribute(np_edge_indices)
            })
            edge_material = LineBasicMaterial(color=edge_color, linewidth=1)
            edge_lines = LineSegments(geometry=edge_geometry, material=edge_material)
            self._displayed_pickable_objects.add(edge_lines)

        if update:
            self.Display()
예제 #25
0
def generate_png(shape):
	"""
	Draw a TopoDS_Shape with matplotlib
	"""
	from OCC.Visualization import Tesselator
	from mpl_toolkits.mplot3d import Axes3D
	from matplotlib import pyplot as plt
	from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection
	
	tess = Tesselator(shape)
	triangles = []
	edges = []

	# get the triangles
	triangle_count = tess.ObjGetTriangleCount()
	for i_triangle in range(0, triangle_count):
		i1, i2, i3 = tess.GetTriangleIndex(i_triangle)
		triangles.append([tess.GetVertex(i1), tess.GetVertex(i2), tess.GetVertex(i3)])

	# get the edges
	edge_count = tess.ObjGetEdgeCount()
	for i_edge in range(0, edge_count):
		vertex_count = tess.ObjEdgeGetVertexCount(i_edge)
		edge = []
		for i_vertex in range(0, vertex_count):
			vertex = tess.GetEdgeVertex(i_edge, i_vertex)
			edge.append(vertex)
		edges.append(edge)

	# plot it
	fig_side = plt.figure(figsize=(10, 4))
	ax = Axes3D(fig_side)

	ax.add_collection3d(Poly3DCollection(triangles, linewidths=0.15, alpha=0.5))
	ax.add_collection3d(Line3DCollection(edges, colors='w', linewidths=1.0))

	ax.set_axis_off()

	ax.set_xlim(-1800, 1800)
	ax.set_ylim(-800, 800)
	ax.set_zlim(-800, 800)
	ax.view_init(elev=-1., azim=90)
	fig_side.savefig("views/side.png")

	
	fig_top = plt.figure(figsize=(5, 4))
	ax_top = Axes3D(fig_top)

	ax_top.add_collection3d(Poly3DCollection(triangles, linewidths=0.15, alpha=0.5))
	ax_top.add_collection3d(Line3DCollection(edges, colors='w', linewidths=1.0))

	ax_top.set_axis_off()

	ax_top.set_xlim(-2500, 2500)
	ax_top.set_ylim(-50, 450)
	ax_top.set_zlim(-250, 250)
	ax_top.view_init(elev=-1., azim=-2)
	fig_top.savefig("views/back.png")

	ax_top.set_xlim(-2500, 2500)
	ax_top.set_ylim(-50, 450)
	ax_top.set_zlim(-200, 300)
	ax_top.view_init(elev=-1., azim=182)
	fig_top.savefig("views/front.png")
예제 #26
0
    def tessellate(shape):
        tess = Tesselator(shape.wrapped)
        tess.Compute(compute_edges=True, mesh_quality=tolerance)

        return tess
예제 #27
0
    def AddShapeToScene(self,
                        shp,  # the TopoDS_Shape to be displayed
                        shape_color=default_shape_color,  # the default
                        render_edges=False,
                        edge_color=default_edge_color,
                        compute_uv_coords=False,
                        quality=1.0,
                        transparency=False,
                        opacity=1.):
        # first, compute the tesselation
        tess = Tesselator(shp)
        tess.Compute(uv_coords=compute_uv_coords,
                     compute_edges=render_edges,
                     mesh_quality=quality,
                     parallel=self._parallel)
        # get vertices and normals
        vertices_position = tess.GetVerticesPositionAsTuple()

        number_of_triangles = tess.ObjGetTriangleCount()
        number_of_vertices = len(vertices_position)

        # number of vertices should be a multiple of 3
        assert number_of_vertices % 3 == 0
        assert number_of_triangles * 9 == number_of_vertices

        # then we build the vertex and faces collections as numpy ndarrays
        np_vertices = np.array(vertices_position, dtype='float32').reshape(int(number_of_vertices / 3), 3)
        # Note: np_faces is just [0, 1, 2, 3, 4, 5, ...], thus arange is used
        np_faces = np.arange(np_vertices.shape[0], dtype='uint32')

        # set geometry properties
        buffer_geometry_properties = {'position': BufferAttribute(np_vertices),
                                      'index'   : BufferAttribute(np_faces)}
        if self._compute_normals_mode == NORMAL.SERVER_SIDE:
            # get the normal list, converts to a numpy ndarray. This should not raise
            # any issue, since normals have been computed by the server, and are available
            # as a list of floats
            np_normals = np.array(tess.GetNormalsAsTuple(), dtype='float32').reshape(-1, 3)
            # quick check
            assert np_normals.shape == np_vertices.shape
            buffer_geometry_properties['normal'] = BufferAttribute(np_normals)

        # build a BufferGeometry instance
        shape_geometry = BufferGeometry(attributes=buffer_geometry_properties)

        # if the client has to render normals, add the related js instructions
        if self._compute_normals_mode == NORMAL.CLIENT_SIDE:
            shape_geometry.exec_three_obj_method('computeVertexNormals')

        # then a default material
        shp_material = MeshPhongMaterial(color=shape_color,
                                         polygonOffset=True,
                                         polygonOffsetFactor=1,
                                         polygonOffsetUnits=1,
                                         shininess=0.9,
                                         transparent=transparency)

        # create a mesh unique id
        mesh_id = uuid.uuid4().hex

        # finally create the mash
        shape_mesh = Mesh(geometry=shape_geometry,
                          material=shp_material,
                          name=mesh_id)


        # and to the dict of shapes, to have a mapping between meshes and shapes
        self._shapes[mesh_id] = shp

        # edge rendering, if set to True
        edge_lines = None
        if render_edges:
            edges = list(map(lambda i_edge: [tess.GetEdgeVertex(i_edge, i_vert) for i_vert in range(tess.ObjEdgeGetVertexCount(i_edge))], range(tess.ObjGetEdgeCount())))
            edges = list(filter(lambda edge: len(edge) == 2, edges))
            np_edge_vertices = np.array(edges, dtype=np.float32).reshape(-1, 3)
            np_edge_indices = np.arange(np_edge_vertices.shape[0], dtype=np.uint32)
            edge_geometry = BufferGeometry(attributes={
                'position': BufferAttribute(np_edge_vertices),
                'index'   : BufferAttribute(np_edge_indices)
            })
            edge_material = LineBasicMaterial(color=edge_color, linewidth=1)
            edge_lines = LineSegments(geometry=edge_geometry, material=edge_material)

        # Add geometries to pickable or non pickable objects
        self._displayed_pickable_objects.add(shape_mesh)
        if render_edges:
            self._displayed_non_pickable_objects.add(edge_lines)