diff --git a/src/main.ts b/src/main.ts
index 502c7c2bcd8d26ab77384ab47577007b509a3c2b..50f7b9a00733cba06f8a43a0de339079c967fe73 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,32 +1,13 @@
-import * as CG from "./uitls/rendering";
-import * as THREE from "three";
-import { UI } from "./uitls/ui";
-import * as Interpolation from "./uitls/bezierCurve";
+import * as CG from "./uitls/Rendering";
+import { UI } from "./uitls/UI";
+import { Curve2d } from "./uitls/Curve2d";
 
 const render = new CG.RenderManager('#canvas', { near: 0.1, far: 1000, fov: 45, height: 1 });
 const ui = new UI();
 
-const startPoint = new THREE.Vector2(-1, -1);
-const endPoint = new THREE.Vector2(1, 1);
-const startControlPoint = new THREE.Vector2(-1, 1);
-const endControlPoint = new THREE.Vector2(1, -1);
+const curve = new Curve2d();
+curve.objects().forEach(obj => { render.add(obj); });
 
-// const curve = new Interpolation.BezierCurveTest(
-//   startPoint,
-//   startControlPoint,
-//   endControlPoint,
-//   endPoint
-// )
-const curve = new Interpolation.BezierCurve(
-  startPoint,
-  endPoint,
-  startControlPoint,
-  endControlPoint
-)
-
-const line = curve.createLine();
-
-render.add(line);
 render.render();
 
 ui.addModifiable(render);
diff --git a/src/uitls/CubicBezierCurve2d.ts b/src/uitls/CubicBezierCurve2d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..498ef7cf8915497bca95577747656453fc22b769
--- /dev/null
+++ b/src/uitls/CubicBezierCurve2d.ts
@@ -0,0 +1,163 @@
+import { Vector2 } from "three";
+
+function lerp(a: Vector2, b: Vector2, t: number): Vector2 {
+    return new Vector2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t);
+}
+
+export class CubicBezierCurve2d {
+    private _startPoint: Vector2;
+    private _endPoint: Vector2;
+    private _startControlPoint: Vector2;
+    private _endControlPoint: Vector2;
+
+    private _dirty: boolean = true;
+    private _resolution: number = 5;
+    private _points: Vector2[] = [];
+    private _coefficients: number[][] = [];
+
+    constructor(
+        startPoint: Vector2,
+        endPoint: Vector2,
+        startControlPoint: Vector2,
+        endControlPoint: Vector2
+    ) {
+        this._startPoint = startPoint;
+        this._endPoint = endPoint;
+        this._startControlPoint = startControlPoint;
+        this._endControlPoint = endControlPoint;
+    }
+
+    get startPoint(): Vector2 {
+        return this._startPoint;
+    }
+
+    get endPoint(): Vector2 {
+        return this._endPoint;
+    }
+
+    get startControlPoint(): Vector2 {
+        return this._startControlPoint;
+    }
+
+    get endControlPoint(): Vector2 {
+        return this._endControlPoint;
+    }
+
+    get points(): Vector2[] {
+        return this._points;
+    }
+
+    get coefficients(): number[][] {
+        return this._coefficients;
+    }
+
+    set startPoint(value: Vector2) {
+        this._startPoint = value;
+        this._dirty = true;
+        this.generatePoints(this._resolution);
+    }
+
+    set endPoint(value: Vector2) {
+        this._endPoint = value;
+        this._dirty = true;
+        this.generatePoints(this._resolution);
+    }
+
+    set startControlPoint(value: Vector2) {
+        this._startControlPoint = value;
+        this._dirty = true;
+        this.generatePoints(this._resolution);
+    }
+
+    set endControlPoint(value: Vector2) {
+        this._endControlPoint = value;
+        this._dirty = true;
+        this.generatePoints(this._resolution);
+    }
+
+    bernstain(s: number): [Vector2, number[]] {
+
+        // p(t) = (1-t)³ * p0 + 3 * (1-t)² * t * p1 + 
+        //        3 * (1-t) * t² * p2 + t³ * p3
+        // => subtitute: 1 - t = s
+        // p(t) = k³ * p0 + 3 * k² * t * p1 + 
+        //        3 * k * t² * p2 + t³ * p3
+
+        const p0 = this.startPoint;
+        const p1 = this.startControlPoint;
+        const p2 = this.endControlPoint;
+        const p3 = this.endPoint;
+
+        // set k = 1 - s => substitution
+        const t = s;
+        const k = 1 - s;
+
+        // calculate the coefficients
+        const u0 = 1 * Math.pow(k, 3) * Math.pow(t, 0);
+        const u1 = 3 * Math.pow(k, 2) * Math.pow(t, 1);
+        const u2 = 3 * Math.pow(k, 1) * Math.pow(t, 2);
+        const u3 = 1 * Math.pow(k, 0) * Math.pow(t, 3);
+
+        // calculate the point
+        const p = new Vector2(
+            u0 * p0.x + u1 * p1.x + u2 * p2.x + u3 * p3.x,
+            u0 * p0.y + u1 * p1.y + u2 * p2.y + u3 * p3.y
+        );
+
+        return [p, [u0, u1, u2, u3]];
+    }
+
+    deCasteljau(t: number): Vector2[][] {
+
+        const p0 = this.startPoint;
+        const p1 = this.startControlPoint;
+        const p2 = this.endControlPoint;
+        const p3 = this.endPoint;
+
+        // iterative implementation of deCasteljau
+        let points: Vector2[] = [p0, p1, p2, p3];
+        let temporary: Vector2[] = [];
+
+        const results: Vector2[][] = [];
+        results.push(points);
+        while (points.length > 1) {
+            temporary = [];
+            for (let i = 0; i < points.length - 1; i++)
+                temporary.push(lerp(points[i], points[i + 1], t));
+            points = temporary;
+            results.push(points); // save every iteration
+        }
+
+        return results;
+    }
+
+    generatePoints(resolution: number): Vector2[] {
+
+        if (!this._dirty && this._points.length === resolution)
+            return this._points;
+        
+        this._coefficients = [];
+        this._points = [];        
+
+        this._resolution = resolution;
+        const sampleSize = 1 / resolution;
+
+        for (let t = 0; t <= 1; t += sampleSize) {
+            t = Math.round(t * 10000) / 10000;
+            const [point, coefficients] = this.bernstain(t);
+            this._points.push(point);
+            this._coefficients.push(coefficients);
+        }
+
+        this._dirty = false;
+
+        return this._points;
+    }
+
+    generatePointAt(t: number): [Vector2[][], number[], Vector2] {
+        const points = this.deCasteljau(t);
+        const coefficients = this._coefficients[Math.floor(t * this._resolution)];
+        const point = points[points.length - 1];
+        return [points, coefficients, point[0]];
+    }
+}
diff --git a/src/uitls/Curve2d.ts b/src/uitls/Curve2d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2badea50376f42c667290f35c94edb677cce5f78
--- /dev/null
+++ b/src/uitls/Curve2d.ts
@@ -0,0 +1,216 @@
+import { GUI } from "dat.gui";
+import { BufferGeometry, CircleGeometry, Color, Group, Line, LineBasicMaterial, Mesh, MeshBasicMaterial, Object3D, Vector2 } from "three";
+import { CubicBezierCurve2d } from "./CubicBezierCurve2d";
+import { Animatable, Updatable, Modifiable } from "./Interfaces";
+import { UI } from "./UI";
+
+
+export class Curve2d implements Animatable, Updatable, Modifiable {
+    private _curve: CubicBezierCurve2d = new CubicBezierCurve2d(
+        new Vector2(0, 0),
+        new Vector2(1, 1),
+        new Vector2(0.5, 0),
+        new Vector2(0.5, 1)
+    );
+
+    private _reference: Group = new Group();
+    private _bernstain: Group = new Group();
+    private _points: Group = new Group();
+    private _line: Line = new Line();
+
+    public t: number = .5;
+    public resolution: number = 100;
+    public positionBernstain: Vector2 = new Vector2(1.5,0);
+
+    constructor() {
+        this._curve.generatePoints(this.resolution);
+        this._line.material = new LineBasicMaterial({ color: 0xffffff });
+
+        this._bernstain.position.set(this.positionBernstain.x, this.positionBernstain.y, 0);
+        this._points.position.set(this.positionBernstain.x, this.positionBernstain.y, 0);
+
+        this.createReference();
+        this.createLine();
+        this.createBernstain();
+    }
+
+    /**
+     * @returns {Object3D[]} Contains all the object which are used to draw the curve 
+     */
+    objects(): Object3D[] {
+        return [this._bernstain, this._line, this._reference, this._points];
+    }
+
+    /**
+     * Updates static objects
+     */
+    update(): void {
+        this._curve.generatePoints(this.resolution);
+        this._line.geometry.dispose();
+        this._line.geometry = new BufferGeometry().setFromPoints(this._curve.points);
+        this._line.geometry.attributes.position.needsUpdate = true;
+    
+        this._bernstain.position.set(this.positionBernstain.x, this.positionBernstain.y, 0);
+        this._points.position.set(this.positionBernstain.x, this.positionBernstain.y, 0);
+        
+        this.animate(this.t);
+    }
+
+    /**
+     * Takes care of updating dynamic objects
+     * @param delta t value between 0 and 1 to find the position of the bernstein
+     */
+    animate(delta: number): void {
+        const [cpoints, coefficients] = this._curve.generatePointAt(delta);
+
+        // update the reference
+        for (let i = 0; i < cpoints.length; i++) {
+
+            // update lines
+            for (let j = 0; j < cpoints[i].length - 1; j++) {
+                // update lines
+                const line = this._reference.getObjectByName(`line_${i}_${j}_${j + 1}`) as Line;
+                line.geometry.setFromPoints([cpoints[i][j], cpoints[i][j + 1]]);
+                line.geometry.attributes.position.needsUpdate = true;
+            }
+
+            // update circle
+            for (let j = 0; j < cpoints[i].length; j++) {
+                const circle = this._reference.getObjectByName(`point_${i}_${j}_${j + 1}`) as Mesh;
+                circle.position.set(cpoints[i][j].x, cpoints[i][j].y, 0);
+            }
+        }
+
+        // update the bernstain
+        for (let i = 0; i < coefficients.length; i++) {
+            const bernstain = this._points.getObjectByName(`bernstain_point_${i}`) as Mesh;
+            bernstain.position.set(delta, coefficients[i], 0);
+        }
+
+
+    }
+
+    /**
+     * Build the UI elements
+     */
+    createElement(gui: GUI): void {
+        const curve = gui.addFolder('Curve');
+        curve.add(this, 'resolution', 100, 500).step(1).onChange(() => this.update());
+        curve.add(this, 't', 0, 1).step(0.01).onChange(() => this.animate(this.t));
+        UI.addVector<Vector2>(curve, this, this.positionBernstain, 'Bernstain position')
+        UI.addVector<Vector2>(curve, this, this._curve.startPoint, 'Start Point');
+        UI.addVector<Vector2>(curve, this, this._curve.endPoint, 'End Point');
+        UI.addVector<Vector2>(curve, this, this._curve.startControlPoint, 'Start Control Point');
+        UI.addVector<Vector2>(curve, this, this._curve.endControlPoint, 'End Control Point');
+    }
+
+
+    private createLine(): void {
+        this._line.geometry = new BufferGeometry().setFromPoints(this._curve.points);
+        this._line.position.set(0, 0, 0);
+    }
+
+
+    private createReference(): void {
+        const cpoints = this._curve.generatePointAt(0.74)[0];
+
+        for (let i = 0; i < cpoints.length; i++) {
+
+            const color = new Color(0xffffff);
+            color.setHSL(i / cpoints.length, 1, 0.5);
+
+            const mat_point = new MeshBasicMaterial({ color: color.getHex() });
+            const mat_line = new LineBasicMaterial({ color: color.getHex() });
+
+            // create lines
+            for (let j = 0; j < cpoints[i].length - 1; j++) {
+                const p1 = cpoints[i][j];
+                const p2 = cpoints[i][j + 1];
+
+                const lineGeometry = new BufferGeometry().setFromPoints([p1, p2]);
+                const line = new Line(lineGeometry, mat_line);
+                line.name = `line_${i}_${j}_${j + 1}`;
+                line.geometry.setFromPoints([p1, p2]);
+                this._reference.add(line);
+            }
+
+            // create circle on every point with the color of the line
+            for (let j = 0; j < cpoints[i].length; j++) {
+                const circle = new Mesh(new CircleGeometry(0.01, 32), mat_point);
+                circle.position.set(cpoints[i][j].x, cpoints[i][j].y, 0);
+                circle.name = `point_${i}_${j}_${j + 1}`;
+                this._reference.add(circle);
+            }
+
+        }
+
+    }
+
+    private createBernstain(): void {
+
+        // prepare vector for lines
+        const points: Vector2[][] = [];
+        for (let i = 0; i < this._curve.coefficients[0].length; i++)
+            points.push([]);
+
+        // create points
+        let max = this._curve.coefficients.length;
+        for (let i = 0; i < max; i++) {
+            let bernstainY = this._curve.coefficients[i];
+            let X = i / max;
+
+            for (let i = 0; i < bernstainY.length; i++) {
+                const Y = bernstainY[i];
+                const point = new Vector2(X, Y);
+                points[i].push(point);
+            }
+        }
+
+        // create the lines
+        for (let i = 0; i < points.length; i++) {
+            const lineGeometry = new BufferGeometry().setFromPoints(points[i]);
+
+            const color = new Color(0xffffff);
+            let s = i / points.length;
+            color.setHSL(s, 1 - s, 0.5);
+            const line = new Line(lineGeometry, new LineBasicMaterial({ color: color.getHex() }));
+            line.name = `bernstain_${i}`;
+            this._bernstain.add(line);
+        }
+
+
+        const lineGeometry = new BufferGeometry().setFromPoints([
+            new Vector2(0, 0),
+            new Vector2(0, 1)
+        ]);
+        this._bernstain.add(
+            new Line(lineGeometry, new LineBasicMaterial({ color: 0xffffff }))
+        );
+
+        const lineGeometry2 = new BufferGeometry().setFromPoints([
+            new Vector2(0, 0),
+            new Vector2(1, 0)
+        ]);
+        this._bernstain.add(
+            new Line(lineGeometry2, new LineBasicMaterial({ color: 0xffffff }))
+        );
+
+        // get coefficients at 0.5
+        const coefficients = this._curve.generatePointAt(0.5)[1];
+        
+        // create the points
+        for (let i = 0; i < coefficients.length; i++) {
+            const point = new Vector2(0.5, coefficients[i]);
+            const pointGeometry = new CircleGeometry(0.01, 32);
+            const pointMaterial = new MeshBasicMaterial({ color: 0xffffff });
+            const pointMesh = new Mesh(pointGeometry, pointMaterial);
+            pointMesh.name = `bernstain_point_${i}`;
+            pointMesh.position.set(point.x, point.y, 0);
+            this._points.add(pointMesh);
+            
+        }
+
+    }
+
+
+}
\ No newline at end of file
diff --git a/src/uitls/Interfaces.ts b/src/uitls/Interfaces.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c41b1dc2c6a99bd3a3fae4da252244bd16bb586a
--- /dev/null
+++ b/src/uitls/Interfaces.ts
@@ -0,0 +1,25 @@
+import { GUI } from "dat.gui";
+
+
+
+export interface Animatable {
+    animate(delta: number): void;
+}
+
+/**
+ * Class which implement this interface can be updated. It is important for
+ * the GUI element to be updated when the object is changed.
+ * @interface Updatable
+ */
+export interface Updatable {
+    update(): void;
+}
+
+/**
+ * Class which implement this interface do create a GUI element for the object.
+ * The element will be added to the GUI which is passed to the constructor.
+ * @interface Modifiable
+ */
+export interface Modifiable {
+    createElement(gui: GUI): void;
+}
\ No newline at end of file
diff --git a/src/uitls/bezierCurve.ts b/src/uitls/bezierCurve.ts
deleted file mode 100644
index 40465d9a8f4529e9deb26a865fce99253cc326c2..0000000000000000000000000000000000000000
--- a/src/uitls/bezierCurve.ts
+++ /dev/null
@@ -1,183 +0,0 @@
-import { Modifiable, UI, Updatable } from "./ui";
-import {
-    Line,
-    Vector2,
-    Vector3,
-    BufferGeometry,
-    LineBasicMaterial,
-    CubicBezierCurve3
-} from "three";
-import { GUI } from "dat.gui";
-
-function lerp(a: Vector2, b: Vector2, t: number): Vector2 {
-    return new Vector2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t);
-}
-
-
-export abstract class AbstractBezierCurve implements Modifiable, Updatable {
-    constructor(startPoint: Vector2, endPoint: Vector2, startControlPoint: Vector2, endControlPoint: Vector2) {
-        this.startPoint = startPoint;
-        this.endPoint = endPoint;
-        this.startControlPoint = startControlPoint;
-        this.endControlPoint = endControlPoint;
-
-        this._geomBuffer = new BufferGeometry();
-    }
-
-    abstract generateCurvePoints(): Vector2[];
-
-    updateGeomBuffer() {
-        this._geomBuffer.dispose();
-        this._geomBuffer = new BufferGeometry();
-        this._geomBuffer.setFromPoints(this._curvePoints);
-    }
-
-    createLine() {
-        this.update();
-        this._line = new Line(this._geomBuffer, new LineBasicMaterial({ color: 0xffffff }));
-        this._line.name = 'bezierCurve';
-        return this._line;
-    }
-
-    update() {
-        this._curvePoints = this.generateCurvePoints();
-        this.updateGeomBuffer();
-        if (this._line)
-            this._line.geometry = this._geomBuffer;
-    }
-
-    createElement(gui: GUI): void {
-        const folder = gui.addFolder('Bezier Curve');
-        UI.addVector(folder, this, this.startPoint, 'Start Point');
-        UI.addVector(folder, this, this.endPoint, 'End Point');
-        UI.addVector(folder, this, this.startControlPoint, 'Start Control Point');
-        UI.addVector(folder, this, this.endControlPoint, 'End Control Point');
-        folder.add(this, "_numPoints", 10, 100).step(1).name("Points").onChange(() => { this.update(); });
-
-    }
-
-    public startPoint: Vector2;
-    public endPoint: Vector2;
-    public startControlPoint: Vector2;
-    public endControlPoint: Vector2;
-
-    protected _numPoints: number = 100;
-
-    private _line?: Line;
-    private _curvePoints: Vector2[] = [];
-    private _geomBuffer: BufferGeometry;
-}
-
-// TODO: Handles for the control points
-export class Debug implements Updatable, Modifiable {
-    constructor(private _curve: AbstractBezierCurve) { }
-
-    update() {
-        this._curve.update();
-    }
-
-    createElement(gui: GUI): void {
-        const folder = gui.addFolder('Debug');
-        folder.add(this, "update").name("Update");
-    }
-}
-
-
-export class BezierCurveTest extends AbstractBezierCurve {
-
-    generateCurvePoints(): Vector2[] {
-        const curve = new CubicBezierCurve3(
-            new Vector3(this.startPoint.x, this.startPoint.y, 0),
-            new Vector3(this.startControlPoint.x, this.startControlPoint.y, 0),
-            new Vector3(this.endPoint.x, this.endPoint.y, 0),
-            new Vector3(this.endControlPoint.x, this.endControlPoint.y, 0)
-        );
-
-        let curvePoints: Vector2[] = [];
-
-        curve.getPoints(this._numPoints).forEach(point => {
-            curvePoints.push(new Vector2(point.x, point.y));
-        });
-
-        return curvePoints;
-    }
-}
-
-
-export class BezierCurve extends AbstractBezierCurve {
-
-
-    bernstain(s: number): [Vector2, number[]] {
-
-        // p(t) = (1-t)³ * p0 + 3 * (1-t)² * t * p1 + 
-        //        3 * (1-t) * t² * p2 + t³ * p3
-        // => subtitute: 1 - t = s
-        // p(t) = k³ * p0 + 3 * k² * t * p1 + 
-        //        3 * k * t² * p2 + t³ * p3
-
-        const p0 = this.startPoint;
-        const p1 = this.startControlPoint;
-        const p2 = this.endControlPoint;
-        const p3 = this.endPoint;
-
-        // set k = 1 - s => substitution
-        const t = s;
-        const k = 1 - s;
-
-        // calculate the coefficients
-        const u0 = 1 * Math.pow(k, 3) * Math.pow(t, 0);
-        const u1 = 3 * Math.pow(k, 2) * Math.pow(t, 1);
-        const u2 = 3 * Math.pow(k, 1) * Math.pow(t, 2);
-        const u3 = 1 * Math.pow(k, 0) * Math.pow(t, 3);
-
-        // calculate the point
-        const p = new Vector2(
-            u0 * p0.x + u1 * p1.x + u2 * p2.x + u3 * p3.x,
-            u0 * p0.y + u1 * p1.y + u2 * p2.y + u3 * p3.y
-        );
-
-        return [p, [u0, u1, u2, u3]];
-    }
-
-
-    deCasteljau(t: number): Vector2 {
-
-        const p0 = this.startPoint;
-        const p1 = this.startControlPoint;
-        const p2 = this.endControlPoint;
-        const p3 = this.endPoint;
-
-        // iterative implementation of deCasteljau
-        let points: Vector2[] = [p0, p1, p2, p3];
-        let temporary: Vector2[] = [];
-        while (points.length > 1) {
-            temporary = [];
-            for (let i = 0; i < points.length - 1; i++)
-                temporary.push(lerp(points[i], points[i + 1], t));
-            points = temporary;
-        }
-
-        return points[0];
-    }
-
-
-    generateCurvePoints(): Vector2[] {
-        const curvePoints: Vector2[] = [];
-        const sampleSize = 1 / this._numPoints;
-
-        if (true)
-            for (let t = 0; t < 1; t += sampleSize) {
-                t = Math.round(t * 10000) / 10000;
-                curvePoints.push(this.deCasteljau(t));
-            }
-        else
-            for (let s = 0; s < 1; s += sampleSize) {
-                s = Math.round(s * 10000) / 10000;
-                const [point, coefficient] = this.bernstain(s);
-                curvePoints.push(point);
-            }
-
-
-        return curvePoints;
-    }
-}
\ No newline at end of file
diff --git a/src/uitls/rendering.ts b/src/uitls/rendering.ts
index 347d57203890f943029078e39f1ddf465fd97587..f9b784762c1bdf58d60f521def05b6a73f2756cf 100644
--- a/src/uitls/rendering.ts
+++ b/src/uitls/rendering.ts
@@ -7,7 +7,7 @@ import {
     Scene
 } from 'three';
 
-import { Modifiable } from './ui';
+import { Modifiable } from './Interfaces';
 import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
 import { GUI } from 'dat.gui';
 
@@ -32,7 +32,7 @@ class CameraManager {
             new OrthographicCamera(-aspect, aspect, 1, -1, settings.near, settings.far)
         ];
 
-        this.active = this.cameras[0];
+        this.active = this.cameras[1];
         this.active.position.set(0, 0, 5);
     }
 
diff --git a/src/uitls/ui.ts b/src/uitls/ui.ts
index 3bf15e3b07dfca272be7cd00ba7cdd67526a90e7..fba0ab99203a07b04321b657955c509b9e6ba3e0 100644
--- a/src/uitls/ui.ts
+++ b/src/uitls/ui.ts
@@ -1,22 +1,5 @@
 import { GUI } from 'dat.gui';
-
-/**
- * Class which implement this interface do create a GUI element for the object.
- * The element will be added to the GUI which is passed to the constructor.
- * @interface Modifiable
- */
-export interface Modifiable {
-    createElement(gui: GUI): void;
-}
-
-/**
- * Class which implement this interface can be updated. It is important for
- * the GUI element to be updated when the object is changed.
- * @interface Updatable
- */
-export interface Updatable {
-    update(): void;
-}
+import { Modifiable, Updatable } from './Interfaces';
 
 export class UI {
     private _gui: GUI;