diff --git a/main.py b/main.py
new file mode 100644
index 0000000000000000000000000000000000000000..da3873f72bcb28ec11af3d4b81dc895d01b1d05c
--- /dev/null
+++ b/main.py
@@ -0,0 +1,5 @@
+def main():
+    pass
+
+if __name__ == '__main__':
+    main()
\ No newline at end of file
diff --git a/requirement.txt b/requirement.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/utils/3d/mpl_render.py b/utils/3d/mpl_render.py
new file mode 100644
index 0000000000000000000000000000000000000000..316474e385fe15609e760f0d57500b044b2d740c
--- /dev/null
+++ b/utils/3d/mpl_render.py
@@ -0,0 +1,16 @@
+from mpl_toolkits.mplot3d.art3d import Poly3DCollection
+import matplotlib.pyplot as plt
+import numpy as np
+
+def render3D(data:dict):
+    """
+    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'])))
+    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/norm.py b/utils/norm.py
new file mode 100644
index 0000000000000000000000000000000000000000..e4531d1834a9398e35de9b23972c324a8d4c1c23
--- /dev/null
+++ b/utils/norm.py
@@ -0,0 +1,14 @@
+def denormalizeXYZ(filePath:str, output:str):
+    """
+    Denormalize an XYZ file
+    :param filePath: Path to the XYZ file
+    :param output: Path to the output file
+    """
+    with open(filePath, 'r') as f:
+        data = f.readlines()
+        x = [float(line.split()[0]) for line in data]
+        y = [float(line.split()[1]) for line in data]
+        z = [float(line.split()[2]) for line in data]
+        with open(output, 'w') as f:
+            for i in range(len(x)):
+                f.write(f'{x[i]} {y[i]} {z[i]}\n')
\ No newline at end of file
diff --git a/utils/parsers.py b/utils/parsers.py
new file mode 100644
index 0000000000000000000000000000000000000000..7b3f90aa7d05fb31e2e1e90e0f259cb5603f4e46
--- /dev/null
+++ b/utils/parsers.py
@@ -0,0 +1,48 @@
+def parseOBJfiles(filePath:str,ratio:float = 1,cornered:bool = False)->dict:
+    """
+    Parse an OBJ file and return a dict with the vertices and faces
+    
+    :param filePath: Path to the OBJ file
+    :param ratio: Ratio to apply to the vertices
+    :param cornered: If True, the vertices will be cornered
+    :return: A dict with the vertices and faces
+    """
+    with open(filePath, 'r') as f:
+        x, y, z = [], [], []
+        triangles = []
+        data = f.readlines()
+        for line in data :
+            if line.startswith('f'):
+                # Face indices start at 1, not 0
+                triangles.append([int(line.split()[1])-1, int(line.split()[2])-1, int(line.split()[3])-1])
+            elif line.startswith('v'):
+                x.append(float(line.split()[1]) * ratio)
+                y.append(float(line.split()[2]) * ratio)
+                z.append(float(line.split()[3]) * ratio)
+        if cornered:
+            xmin = min(x)
+            for i in range(len(x)):
+                x[i] -= xmin
+            ymin = min(y)
+            for i in range(len(y)):
+                y[i] -= ymin
+            zmin = min(z)
+            for i in range(len(z)):
+                z[i] -= zmin
+        return {'x':x, 'y':y, 'z':z, 'faces':triangles, "verticies": zip(x,y,z)}
+    
+def parseXYZfiles(filePath: str, delimiter: str = ' ') -> dict:
+    """
+    Parses an xyz file and returns a dict containing the coordinates.
+
+    :param file: The xyz file to be parsed.
+    :param delimiter: The delimiter used in the xyz file.
+    :return: A dictionary containing the  coordinates.
+    """
+    x , y , z = [], [], []
+    with open(filePath, 'r') as f:
+        data = f.readlines()
+        x = [float(line.split(delimiter)[0]) for line in data]
+        y = [float(line.split(delimiter)[1]) for line in data]
+        z = [float(line.split(delimiter)[2]) for line in data]
+    return {'x':x, 'y':y, 'z':z, "verticies": zip(x,y,z)}
\ No newline at end of file