diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9d8c7e8b160819fdf336fe331b83957e3a8bf21f..43ef656eeac22617ca63c077839cdf64da499713 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,7 @@ set(CMAKE_CXX_STANDARD 11)
 
 find_package(TTKVTK REQUIRED)
 
-add_executable(projet-stage main.cpp triangulate.cpp)
+add_executable(projet-stage main.cpp triangulate.cpp vtkOFFReader.cxx)
 
 target_link_libraries(projet-stage
   PUBLIC
diff --git a/vtkOFFReader.cxx b/vtkOFFReader.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..573793f734f6f4523f19cf7b8742cb60cfa59e90
--- /dev/null
+++ b/vtkOFFReader.cxx
@@ -0,0 +1,188 @@
+/*=========================================================================
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkOFFReader.cxx,v $
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+=========================================================================*/
+#include "vtkOFFReader.h"
+
+#include "vtkCellArray.h"
+#include "vtkFloatArray.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkTriangle.h"
+
+#include <sstream>
+#include <fstream>
+
+vtkStandardNewMacro(vtkOFFReader);
+
+// Description:
+// Instantiate object with NULL filename.
+vtkOFFReader::vtkOFFReader()
+{
+    this->FileName = NULL;
+
+    this->SetNumberOfInputPorts(0);
+}
+
+vtkOFFReader::~vtkOFFReader()
+{
+    if (this->FileName)
+    {
+        delete[] this->FileName;
+        this->FileName = NULL;
+    }
+}
+
+/*--------------------------------------------------------
+This is only partial support for the OFF format, which is
+quite complicated. To find a full specification,
+search the net for "OFF format", eg.:
+http://people.sc.fsu.edu/~burkardt/data/off/off.html
+We support only vertices and faces composed of 3 vertices.
+---------------------------------------------------------*/
+
+// a replacement for isspace()
+int is_whitespace(char c)
+{
+    if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\v' || c == '\f')
+        return 1;
+    else
+        return 0;
+}
+
+int vtkOFFReader::RequestData(
+    vtkInformation *vtkNotUsed(request),
+    vtkInformationVector **vtkNotUsed(inputVector),
+    vtkInformationVector *outputVector)
+{
+    // get the info object
+    vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+    // get the ouptut
+    vtkPolyData *output = vtkPolyData::SafeDownCast(
+        outInfo->Get(vtkDataObject::DATA_OBJECT()));
+
+    if (!this->FileName)
+    {
+        vtkErrorMacro(<< "A FileName must be specified.");
+        return 0;
+    }
+
+    std::ifstream in(this->FileName);
+
+    if (!in)
+    {
+        vtkErrorMacro(<< "File " << this->FileName << " not found");
+        return 0;
+    }
+
+    vtkDebugMacro(<< "Reading file");
+
+    // intialise some structures to store the file contents in
+    vtkPoints *points = vtkPoints::New();
+    vtkCellArray *polys = vtkCellArray::New();
+
+    // -- work through the file line by line, assigning into the above structures as appropriate --
+
+    float xyz[3];
+
+    std::string line;
+
+    getline(in, line); // throw the 1st line away, it always says "OFF"
+
+    // Read until we get to the first line that is not a comment or a blank line.
+    // This line second states the number of vertices, faces, and edges.
+    while (getline(in, line))
+    {
+        // std::cout << line << std::endl;
+        if (line.size() == 0)
+            continue;
+        if (line[0] == '#')
+            continue;
+
+        // if we get to here, this is the info line
+        break;
+    }
+    // std::cout << "Found info line." << std::endl;
+    // At this point, the line were are interested in is stored in 'line'
+    // We are only interested in vertices and faces.
+    std::stringstream ss;
+    ss << line;
+    unsigned int NumberOfVertices, NumberOfFaces;
+    ss >> NumberOfVertices >> NumberOfFaces;
+    // std::cout << "Vertices: " << NumberOfVertices << " Faces: " << NumberOfFaces << std::endl;
+    // Now we can start to read the vertices
+    unsigned int VertexCounter = 0;
+
+    while (getline(in, line) && VertexCounter < NumberOfVertices)
+    {
+        if (line.size() == 0) // skip blank lines (they should only occur before the vertices start)
+            continue;
+
+        std::stringstream ssVertex;
+        ssVertex << line;
+        float x, y, z;
+        ssVertex >> x >> y >> z;
+        points->InsertNextPoint(x, y, z);
+        // std::cout << "adding vertex: " << x << " " << y << " " << z << std::endl;
+        VertexCounter++;
+    } // (end of vertex while loop)
+
+    unsigned int FaceCounter = 0;
+
+    // read faces
+    do
+    {
+        std::stringstream ssFace;
+        ssFace << line;
+        unsigned int NumFaceVerts, Vert0, Vert1, Vert2;
+        ssFace >> NumFaceVerts >> Vert0 >> Vert1 >> Vert2;
+        if (NumFaceVerts != 3)
+        {
+            vtkErrorMacro(<< "File " << this->FileName << " contains a face with >3 (" << NumFaceVerts << ") vertices.");
+            return 0;
+        }
+
+        // std::cout << "adding triangle: " << Vert0 << " " << Vert1 << " " << Vert2 << std::endl;
+        vtkTriangle *triangle = vtkTriangle::New();
+
+        triangle->GetPointIds()->SetId(0, Vert0);
+        triangle->GetPointIds()->SetId(1, Vert1);
+        triangle->GetPointIds()->SetId(2, Vert2);
+
+        polys->InsertNextCell(triangle);
+
+        triangle->Delete();
+
+        FaceCounter++;
+
+    } while (getline(in, line) && FaceCounter < NumberOfFaces);
+
+    // we have finished with the file
+    in.close();
+
+    output->SetPoints(points);
+    output->SetPolys(polys);
+
+    points->Delete();
+    polys->Delete();
+
+    return 1;
+}
+
+void vtkOFFReader::PrintSelf(ostream &os, vtkIndent indent)
+{
+    this->Superclass::PrintSelf(os, indent);
+
+    os << indent << "File Name: "
+       << (this->FileName ? this->FileName : "(none)") << "\n";
+}
\ No newline at end of file
diff --git a/vtkOFFReader.h b/vtkOFFReader.h
new file mode 100644
index 0000000000000000000000000000000000000000..28d311cf8329aea2f487b671becc4e44b3052d20
--- /dev/null
+++ b/vtkOFFReader.h
@@ -0,0 +1,47 @@
+/*=========================================================================
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkOFFReader.h,v $
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+=========================================================================*/
+// .NAME vtkOFFReader - read .off files
+// .SECTION Description
+// vtkOFFReader is a source object that reads .off
+// files. The output of this source object is polygonal data.
+// .SECTION See Also
+
+#ifndef __vtkOFFReader_h
+#define __vtkOFFReader_h
+
+#include "vtkPolyDataAlgorithm.h"
+
+class vtkOFFReader : public vtkPolyDataAlgorithm
+{
+public:
+    static vtkOFFReader *New();
+    vtkTypeMacro(vtkOFFReader, vtkPolyDataAlgorithm);
+    void PrintSelf(ostream &os, vtkIndent indent);
+
+    // Description:
+    // Specify file name of .off file.
+    vtkSetStringMacro(FileName);
+    vtkGetStringMacro(FileName);
+
+protected:
+    vtkOFFReader();
+    ~vtkOFFReader();
+
+    int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
+
+    char *FileName;
+
+private:
+    vtkOFFReader(const vtkOFFReader &);   // Not implemented.
+    void operator=(const vtkOFFReader &); // Not implemented.
+};
+
+#endif
\ No newline at end of file