diff --git a/integration_tests/data_test.py b/integration_tests/data_test.py
index 0e3db873d53cf9943a8d3b4b1aae5eb4759d7f7b..72211b7bc5506a982bd51391ecd1f990547d1715 100644
--- a/integration_tests/data_test.py
+++ b/integration_tests/data_test.py
@@ -6,7 +6,7 @@ import time
 import numpy as np
 from main import get_discrete_data, get_raw_data
 from utils.files import output
-from utils.files.input import ScannedObject
+from utils.files.input import ScannedObject, parse_result_file
 
 def check_discrete_data(expected_file: str, actual_file: str, ndigits=7, eps=0.00001, silent: bool = False) -> dict:
     """
diff --git a/utils/3d/mpl_render.py b/utils/graph3D/mpl_render.py
similarity index 72%
rename from utils/3d/mpl_render.py
rename to utils/graph3D/mpl_render.py
index 316474e385fe15609e760f0d57500b044b2d740c..c4757fe36e03a2d20fa218cff61b668960bfcdda 100644
--- a/utils/3d/mpl_render.py
+++ b/utils/graph3D/mpl_render.py
@@ -1,16 +1,17 @@
 from mpl_toolkits.mplot3d.art3d import Poly3DCollection
 import matplotlib.pyplot as plt
 import numpy as np
+from utils.files.input import ScannedObject
 
-def render3D(data:dict):
+def render3D(obj:ScannedObject):
     """
     Render a 3D model using matplotlib poly3dcollection
     :param data: A dict with the vertices and faces
     """
     fig = plt.figure()
     ax = fig.add_subplot(projection='3d')
-    faces = np.array(data['faces'])
-    verts = np.array(list(zip(data['x'], data['y'], data['z'])))
+    faces = np.array(obj.get_faces())
+    verts = np.array(obj.get_vertices())
     mesh = Poly3DCollection(verts[faces], alpha=0.25, edgecolor='none')
     ax.add_collection3d(mesh)
     plt.show()
\ No newline at end of file
diff --git a/utils/graph3D/visplot_render.py b/utils/graph3D/visplot_render.py
new file mode 100644
index 0000000000000000000000000000000000000000..d2cd0f24021018cb49a43ee2424a12b8c7382ec8
--- /dev/null
+++ b/utils/graph3D/visplot_render.py
@@ -0,0 +1,33 @@
+import numpy as np
+from vispy import app, scene
+from vispy.scene.visuals import Mesh
+from vispy.scene import transforms
+from vispy.visuals.filters import ShadingFilter, WireframeFilter
+from utils.files.input import ScannedObject
+
+
+def render3D(obj:ScannedObject):
+    vertices = np.asarray(obj.get_vertices())
+    faces = np.asarray(obj.get_faces())
+    canvas = scene.SceneCanvas(keys='interactive', bgcolor='white')
+    view = canvas.central_widget.add_view()
+    view.camera = 'arcball'
+    view.camera.depth_value = 1e3
+    mesh = Mesh(vertices, faces, color=(.5, .7, .5, 1))
+    view.add(mesh)
+    wireframe_filter = WireframeFilter(width=0)
+    shading_filter = ShadingFilter(shininess=0)
+    mesh.attach(wireframe_filter)
+    mesh.attach(shading_filter)
+
+    def attach_headlight(view):
+        light_dir = (0, 1, 0, 0)
+        shading_filter.light_dir = light_dir[:3]
+        initial_light_dir = view.camera.transform.imap(light_dir)
+        @view.scene.transform.changed.connect
+        def on_transform_change(event):
+            transform = view.camera.transform
+            shading_filter.light_dir = transform.map(initial_light_dir)[:3]
+    attach_headlight(view)
+    canvas.show()
+    app.run()
\ No newline at end of file