Procházet zdrojové kódy

Windows redesign. Orthogonal views.

Iñigo Valentin před 7 roky
rodič
revize
7f9dc589e5
10 změnil soubory, kde provedl 1327 přidání a 974 odebrání
  1. 58 83
      README.md
  2. binární
      favicon.ico
  3. binární
      img/bg.png
  4. binární
      img/color.png
  5. binární
      img/eye.png
  6. binární
      img/face.png
  7. binární
      img/line.png
  8. binární
      img/vert.png
  9. 1269 56
      index.html
  10. 0 835
      script/ObJS.js

+ 58 - 83
README.md

@@ -8,11 +8,8 @@ ObJS
 
 ### Live demo ###
 
-<<<<<<< HEAD
-<a href="om/jstricks/ObJS/">http://seavenois.com/jstricks/ObJS/</a>
-=======
-<a href="http://inigovalentin.com/3dview/resource/Bookshelf">http://inigovalentin.com/3dview/resource/Bookshelf</a>
->>>>>>> 28ef4e483d70089a4983965f59082af9d74d6a7b
+<a href="https://inigovalentin.com/en/project/objs">https://inigovalentin.com/project/objs</a>
+
 
 
 
@@ -54,6 +51,7 @@ Note that the canvas is automatically cleared when a new object is loaded.
 
 
 
+
 ### Transformations ###
 
 
@@ -62,12 +60,10 @@ Note that the canvas is automatically cleared when a new object is loaded.
 You can rotate the object by dragging it with the mouse or your finger in a touch screen. Also, you can apply rotation programatically:
 
 ```javascript
-myObJS.rotateX(-1); //Rotate along the X edge to the left
-myObJS.rotateX(1);  //Rotate along the X edge to the right
-myObJS.rotateY(-1); //Rotate along the Y edge to the left
-myObJS.rotateY(1);  //Rotate along the Y edge to the right
+setRotationSpeed(int speed)
+rotateX(int direction)
+rotateY(int direction)
 ```
-Note that the rotation speed can be set (see *Set rotation speed*).
 
 
 ##### Move the object #####
@@ -75,12 +71,10 @@ Note that the rotation speed can be set (see *Set rotation speed*).
 You can move the object around by dragging it with the mouse while holding down the *shift* key. Also, you can move it programatically:
 
 ```javascript
-myObJS.moveHorizontal(-1); //Move to the left
-myObJS.moveHorizontal(1);  //Move right
-myObJS.moveVertical(-1);   //Move up
-myObJS.moveVertical(1);    //Move down
+setMovementSpeed(value)
+moveHorizontal(int direction)
+moveVertical(int direction)
 ```
-Note that the movement speed can be set (see *Set movement speed*).
 
 
 ##### Zoom #####
@@ -88,84 +82,65 @@ Note that the movement speed can be set (see *Set movement speed*).
 Zoom in and out can be achieven with the mouse wheel, by pinching the mode if you are using a touch screen, or programatically:
 
 ```javascript
-myObJS.zoom(value);
+setZoomSpeed(int speed)
+zoom(int level)
 ```
-*value* can be any float number, positive to zoom in, and negative to zoom out. *1* and *-1* are a one step zoom in or out. 
-Note that the zoom speed can be set (see *Set zoom speed*).
 
 
 
 ### Customization ###
 
-You can change parameters such as the elements to draw, their color, transparency, rotation speed, zoom speed... in the script, but much of them can be changed on runtime, so you can use controls.
-
-
-##### Select which elements to draw #####
-```javascript
-myObJS.drawVertices(true);    //Draw vertices
-myObJS.drawVertices(false);   //Don't draw vertices
-
-myObJS.drawEdges(true);       //Draw edges
-myObJS.drawEdges(false);      //Don't draw edges
-
-myObJS.drawFaces(true);       //Draw faces
-myObJS.drawFaces(false);      //Don't draw faces
-
-myObJS.drawBackground(true);  //Draw the background
-myObJS.drawBackground(false); //Don't draw the background
-```
-
-
-##### Select color for elements #####
-```javascript
-myObJS.setVerticesColor(code);   //Set the color for the vertices
-
-myObJS.setEdgesColor(code);      //Set the color for the edges
-
-myObJS.setFacesColor(code);      //Set the color for the faces
-
-myObJS.setBackgroundColor(code); //Set the background color
-```
-* *color* is a hexadecimal triplet with the color code, including the number sign ('#'), and three or six hexadecimal characters. Valid examples are:
-	- *'#ff0000'*  for <span style="color:#ff0000">red</span>.
-	- *'#f00'* also for <span style="color:#ff0000">red</span>.
-	- *'#FF8600'*, for <span style="color:#FF8600">orange</span>.
-	- *'#DDFFDD'*, for <span style="color:#AAFFAA">light green</span>.
-
-
-##### Use materials #####
-
-If a .mtl file is present in the same directory as the obj file, you can use the materials there to colorize the model (enabled by default). 
-```javascript
-myObJS.linkMaterial(true); //Use .mtl file
-myObJS.linkMaterial(false); //Don't use .mtl file
-```
-Note that, when using .mtl files, faces with no material assigned will use the color defined by the user.
+You can programatically change parameters such as the elements to draw, their color, transparency, rotation speed, zoom speed...
 
 
-##### Select face transparency #####
 ```javascript
-myObJS.setAlpha(percent);
+drawVertices(boolean draw)
+drawEdges(boolean draw)
+drawFaces(boolean draw)
+drawBackground(boolean draw)
+setVerticesColor(string code)
+setEdgesColor(string code)
+setFacesColor(string code)
+setBackgroundColor(string code)
+setAlpha(int alpha)
+linkMaterial(boolean link)
 ```
-* *percent* is an integer, between 0 and 100, indicating the level of transparency you want to apply to the faces.
 
 
-##### Set rotation speed #####
-```javascript
-myObJS.setRotationSpeed(value);
-```
-* *value* is an integer, between 0 and 10. The greater it is, the greater the rotation speed.
 
-
-##### Set movement speed #####
-```javascript
-myObJS.setMovementSpeed(value);
-```
-* *value* is an integer, between 0 and 10. The greater it is, the greater the movement speed.
-
-
-##### Set zoom speed #####
-```javascript
-myObJS.setZoomSpeed(value);
-```
-* *value* is an integer, between 0 and 10. The greater it is, the greater the zoom speed.
+### Full list of methods ###
+
+
+| Method                                 | Return                                                | Description |
+| -------------------------------------- | ----------------------------------------------------- | ----------- |
+| ```drawBackground(boolean draw)```     | -                                                     | A solid color background is shown in the canvas depending on the value of *draw*. |
+| ```drawEdges(boolean draw)```          | -                                                     | The edges of the model are represented in the canvas depending on the value of *draw*. |
+| ```drawFaces(boolean draw)```          | -                                                     | The faces of the model are represented in the canvas depending on the value of *draw*. |
+| ```drawVertices(boolean draw)```       | -                                                     | The vertizes of the model are represented in the canvas depending on the value of *draw*. |
+| ```clear()```                          | -                                                     | Clears the canvas.
+| ```getBackgroundColor()```             | {'red': int, 'green': int, 'blue': int, 'alpha': int} | Returns the set color of the canvas background, even if it's not being drawn.
+| ```getEdgeColor()```                   | {'red': int, 'green': int, 'blue': int, 'alpha': int} | Returns the set color of the model edges, even if they are not being drawn.
+| ```getFaceColor()```                   | {'red': int, 'green': int, 'blue': int, 'alpha': int} | Returns the set color of the model face, even if they are not being drawn or a material file is being used.
+| ```getVertexColor()```                 | {'red': int, 'green': int, 'blue': int, 'alpha': int} | Returns the set color of the model vertizes, even if they are not being drawn.
+| ```hasMaterial()```                    | boolean                                               | Will return true if a .mtl file exists for the current model. |
+| ```initCanvas(Canvas canv)```          | -                                                     | Initializes the canvas *canv* where the model will be drawn. Must be called before the model can be presented. |
+| ```isBackgroundDrawn()```              | boolean                                               | Will return true if the canvas background is being drawn. |
+| ```isEdgeDrawn()```                    | boolean                                               | Will return true if the the model edges are being drawn. |
+| ```isFaceDrawn()```                    | boolean                                               | Will return true if the the model faces are being drawn. |
+| ```isVertexDrawn()```                  | boolean                                               | Will return true if the the model vertizes are being drawn. |
+| ```isMaterialUsed()```                 | boolean                                               | Will return true if a material is to be used, even if the material file does not exist. |
+| ```linkMaterial(boolean link)```       | -                                                     | If set to true, it will use a .mtl file in the same directory as the .obj one as material reference. Will have no efect if such file does not exist. |
+| ```load(string filename)```            | -                                                     | Loads a obj file. *filename* must be the name of the file, without path or extension. |
+| ```moveHorizontal(int direction)```    | -                                                     | Moves the model horizontally. A positive value for *direction* will move the model to the right, a negative one will do so to the left. It's recomended to use only values of 1 or -1 to achieve smooth transitions. To control the movements, see the setMovementSpeed(int speed) method.|
+| ```moveVertical(int direction)```      | -                                                     | Moves the model vertically. A positive value for *direction* will move the model up, a negative one will do so down. It's recomended to use only values of 1 or -1 to achieve smooth transitions. To control the movements, see the setMovementSpeed(int speed) method.|
+| ```rotateX(int direction)```           | -                                                     | Rotates the model around the X coordinate. A positive value for *direction* will rotate the model clockwise, a negative one will do so counterclockwise. It's recomended to use only values of 1 or -1 to achieve smooth transitions. To control the speed rotation, see the setRotationSpeed(int speed) method.|
+| ```rotateY(int direction)```           | -                                                     | Rotates the model around the Y coordinate. A positive value for *direction* will rotate the model clockwise, a negative one will do so counterclockwise. It's recomended to use only values of 1 or -1 to achieve smooth transitions. To control the speed rotation, see the setRotationSpeed(int speed) method.|
+| ```setAlpha(int alpha)```              | -                                                     | Sets the transparency of the faces of the model, 0 being fully transparent and 100 fully opaque. |
+| ```setBackgroundColor(string color)``` | -                                                     | Sets the color of the background of the canvas. *color* is a hexadecimal triplet with the color code, including the number sign ('#'), and three or six hexadecimal characters, case insensitive. |
+| ```setEdgesColor(string color)```      | -                                                     | Sets the color of the edges of the model. *color* is a hexadecimal triplet with the color code, including the number sign ('#'), and three or six hexadecimal characters, case insensitive. |
+| ```setFacesColor(string color)```      | -                                                     | Sets the color of the faces of the model. *color* is a hexadecimal triplet with the color code, including the number sign ('#'), and three or six hexadecimal characters, case insensitive. This method will have no efect if a matarial file is enabled. |
+| ```setMovementSpeed(int speed)```      | -                                                     | Sets the speed at which the model will move, between 0 and 10. The greater it is, the greater the movement speed. |
+| ```setRotationSpeed(int speed)```      | -                                                     | Sets the speed at which the model will rotate, between 0 and 10. The greater it is, the greater the rotation speed. |
+| ```setVerticesColor(string color)```   | -                                                     | Sets the color of the vertizes of the model. *color* is a hexadecimal triplet with the color code, including the number sign ('#'), and three or six hexadecimal characters, case insensitive. |
+| ```setZoomSpeed(int speed)```          | -                                                     | Sets the speed at which the model will be zommed in or out, between 0 and 10. The greater it is, the greater the zoom speed. |
+| ```zoom(int level)```                  | -                                                     | Zooms in or out of the model. A positive value for *level* will zoom in, a negative one will zoom out. It's recomended to use only values of 1 or -1 to achieve smooth transitions. To control the zoom rotation, see the setZoomSpeed(int speed) method.|

binární
favicon.ico


binární
img/bg.png


binární
img/color.png


binární
img/eye.png


binární
img/face.png


binární
img/line.png


binární
img/vert.png


+ 1269 - 56
index.html

@@ -1,58 +1,1271 @@
 <!DOCTYPE html>
 <html>
-	<head>
-		<meta content="text/html; charset=windows-1252" http-equiv="content-type"/>
-		<title>ObJS</title>
-		<!-- Script file -->
-		<script type="text/javascript" src="script/ObJS.js"></script>
-	</head>
-	<body onload="objs = new ObJS(); objs.initCanvas();objs.load(document.getElementById('objSelector').value);">
-		<table>
-			<tr>
-				<td>
-					<canvas id="ObJSCanvas" width="500" height="500">
-						Your browser does not support the HTML5 canvas tag.
-					</canvas>
-				</td>
-				<td id="ObJSControl">
-					Choose a model:
-					<select id="objSelector" onChange="objs.load(this.value)">
-						<option value="obj/rainbow.obj" selected="selected">Rainbow</option>
-						<option value="obj/cube.obj">Cube</option>
-						<option value="obj/sphere.obj">Sphere</option>
-						<option value="obj/star.obj">Star</option>
-						<option value="obj/monkey.obj">Monkey</option>
-						<option value="obj/bolt.obj">Bolt</option>
-						<option value="obj/multiple.obj">Multiple Objects</option>
-						<option value="obj/seaplane.obj">Seaplane (Can freeze browser)</option>
-					</select>
-					<br/><br/><br/>
-					<input type="checkbox" value="backg" checked onChange="objs.drawBackground(this.checked);"/>Background
-					<input type="color" value="#C8C8C8" onChange="objs.setBackgroundColor(this.value)"/>
-					<br/>
-					<input type="checkbox"  value="verts" checked onChange="objs.drawVertizes(this.checked);"/>Vertices
-					<input type="color"  value="#0A0A0A" onChange="objs.setVertizesColor(this.value);"/>
-					<br/>
-					<input type="checkbox" value="edges" checked onChange="objs.drawEdges(this.checked);"/>Edges
-					<input type="color" value="#644646" onChange="objs.setEdgesColor(this.value);"/>
-					<br/>
-					<input type="checkbox" value="faces" checked onChange="objs.drawFaces(this.checked);"/>Faces
-					<input type="color" value="#B4B4FF" onChange="objs.setFacesColor(this.value);"/>
-					<input type="checkbox" checked onChange="objs.linkMaterial(this.checked);"/>Use materials
-					<br/><br/>
-					Alpha:<br/>
-					0% <input type="range" min="0" max="100" step="1" value="60" onInput="objs.setAlpha(this.value);" onChange="objs.setAlpha(this.value);"/>100%
-					<br/><br/>
-					Rotation speed:<br/>
-					0% <input type="range" min="0" max="10" step="1" value="3" onInput="objs.setRotationSpeed(this.value);" onChange="objs.setRotationSpeed(this.value);"/>100%
-					<br/><br/>
-					Zoom speed:<br/>
-					0% <input type="range" min="0" max="10" step="1" value="2" onInput="objs.setZoomSpeed(this.value);" onChange="objs.setZoomSpeed(this.value);"/>100%
-					<br/><br/>
-					Movement speed:<br/>
-					0% <input type="range" min="0" max="10" step="1" value="5" onInput="objs.setMovementSpeed(this.value);" onChange="objs.setMovementSpeed(this.value);"/>100%
-				</td>
-			</tr>
-		</table>
-	</body>
-</html>
+    <head>
+        <title>ObJS</title>
+        <link rel='shortcut icon' href='favicon.ico'/>
+        <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
+        <meta charset='utf-8'/>
+        <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
+        <link rel='author' href='I&ntilde;igo Valentin'/>
+        <link rel='publisher' href='I&ntilde;igo Valentin'/>
+        <meta name='description' content='Demo of ObJS - 3D viewer in pure Javascript'/>
+        <!-- Script file -->
+        <script type="text/javascript">
+            /********************************************************************
+             * The ObJS object initializes the canvas, assigning it to the HTML *
+             * element, and set the required mouse events.                      *
+             * #parameters: none                                                *
+             * #return: the ObJS object.                                        *
+             ********************************************************************/
+            function ObJS(){
+
+                /********************************************************************
+                 * Parameters for costumization.                                    *
+                 ********************************************************************/
+                var backColor = "rgba(200, 200, 200, 1)";
+                var vertColor = "rgba(10, 10, 10, 1)";
+                var edgeColor = "rgba(100, 70, 70, 1)";
+                var faceColor = "rgba(180, 180, 255, .6)";
+                var faceAlpha = .6;
+                var textColor = "rgba(0, 0, 0, 1)";
+                var vertSize = 4; //Make it even: at small scales will look better
+                var rotationSpeed = 90; //Smaller = faster. 100 is a good speed
+                var zoomSpeed = 0.161; //0-1. 0.2 or 0.3 are good speeds
+                var moveSpeed = .5;
+
+                /********************************************************************
+                 * Variable containing this object, to be refered from nested       *
+                 * functions.                                                       *
+                 ********************************************************************/
+                var thisObJS;
+
+                /********************************************************************
+                 * Parameter used to scale the measures in the .obj file. Can be    *
+                 * integer or float, greater than 0. 50 is a good default.          *
+                 ********************************************************************/
+                var scale;
+
+                /********************************************************************
+                 * Variable to determine if the canvas has been initialized.        *
+                 ********************************************************************/
+                var canvasInitialized = false;
+
+                /********************************************************************
+                 * Variable to determine if the mouse button is being holded down.  *
+                 ********************************************************************/
+                var mDown = false;
+                var pinch = false;
+                var pinchScale = 0;
+
+                /********************************************************************
+                 * Variables containing the canvas and its context.                 *
+                 ********************************************************************/
+                var canvas;
+                var topCanvas;
+                var frontCanvas;
+                var sideCanvas;
+                var ctx;
+                var topCtx;
+                var frontCtx;
+                var sideCtx;
+
+                /********************************************************************
+                 * Variables containing the number of elements.                     *
+                 ********************************************************************/
+                var totalVert;
+                var totalMaterial = 0;
+                var totalFace
+
+                /********************************************************************
+                 * Arrays containing the vertices, faces and materials.             *
+                 ********************************************************************/
+                var material;
+                var vert;
+                var face;
+
+                /********************************************************************
+                 * Booleans to determine wich elements are to draw.                 *
+                 ********************************************************************/
+                var dVerts = true;
+                var dEdges = true;
+                var dFaces = true;
+                var dBackg = true;
+
+                /********************************************************************
+                 * Booleans to indicate if mtl file should be used.                 *
+                 ********************************************************************/
+                var hasMtl = true;
+                var useMtl = true;
+
+                /********************************************************************
+                 * Global variables that will contain the position of the mouse in  *
+                 * the previous frame to calculate rotation.                        *
+                 ********************************************************************/
+                var pX = null;
+                var pY = null;
+
+                /********************************************************************
+                 * Function that initializes the canvas, assignin it to the HTML    *
+                 * element, and set the required mouse events.                      *
+                 * #parameters:                                                     *
+                 *   canv (canvas): canvas to use. If omited, the one named         *
+                 *                  named "ObJSView" will be used.                *
+                 * #return: nothing                                                 *
+                 * #scope: public                                                   *
+                 ********************************************************************/
+                this.initCanvas = function(canv){
+                    if (!canvasInitialized){
+                        if (canv != null){
+                            canvas = canv;
+                        }
+                        else{
+                            canvas = document.getElementById("ObJSView");
+                        }
+                        topCanvas = document.getElementById("ObJSTop");
+                        frontCanvas = document.getElementById("ObJSFront");
+                        sideCanvas = document.getElementById("ObJSSide");
+                        ctx = canvas.getContext("2d");
+                        topCtx = topCanvas.getContext("2d");
+                        frontCtx = frontCanvas.getContext("2d");
+                        sideCtx = sideCanvas.getContext("2d");
+                        ctx.translate(canvas.width / 2, canvas.height / 2);
+
+                        canvas.onmousedown = function(e){
+                            pX = e.offsetX == undefined?e.layerX:e.offsetX;
+                            pY = e.offsetY == undefined?e.layerY:e.offsetY;
+                            mDown = true;
+                        };
+
+                        canvas.onmouseup = function(e){
+                            if(mDown){
+                                mouseClick(e);
+                            }
+                            pX = null;
+                            pY = null;
+                            mDown = false;
+                        };
+
+                        canvas.onmousemove = function(e){
+                            if(!mDown){
+                                return;
+                            }
+                            var x = e.offsetX == undefined?e.layerX:e.offsetX;
+                            var y = e.offsetY == undefined?e.layerY:e.offsetY;
+                            if (e.shiftKey){
+                                thisObJS.moveHorizontal(x - pX);
+                                thisObJS.moveVertical(y - pY);
+                            }
+                            else{
+                                thisObJS.rotateY(x - pX);
+                                thisObJS.rotateX(y - pY);
+                            }
+                            pX = x;
+                            pY = y;
+                            return false;
+                        };
+
+                        canvas.onmouseout = function(e){
+                            if(mDown){
+                                mDown = false;
+                            }
+                        }
+
+                        canvas.addEventListener('mousewheel',function(e){
+                            e.preventDefault();
+                            if (event.wheelDelta > 0){
+                                thisObJS.zoom(1);
+                            }
+                            else{
+                                thisObJS.zoom(-1);
+                            }
+                            return false;
+                        }, false);
+
+                        canvas.addEventListener('touchstart',function(e){
+                            if(e.touches.length == 2) {
+                                pinch = true;
+                                pinchScale = Math.sqrt((e.touches[0].clientX-e.touches[1].clientX) * (e.touches[0].clientX-e.touches[1].clientX) + (e.touches[0].clientY-e.touches[1].clientY) * (e.touches[0].clientY-e.touches[1].clientY));
+                            }
+                            return false;
+                        }, false);
+
+                        canvas.addEventListener('touchend',function(e){
+                            if(pinch){
+                                pinch = false;
+                            }
+                            return false;
+                        }, false);
+
+                        canvas.addEventListener('touchcancel',function(e){
+                            if(pinch){
+                                pinch = false;
+                            }
+                            return false;
+                        }, false);
+
+                        canvas.addEventListener('touchleave',function(e){
+                            if(pinch){
+                                pinch = false;
+                            }
+                            return false;
+                        }, false);
+
+                        canvas.addEventListener('touchmove', function(e){
+                            e.preventDefault();
+                            if(pinch){
+                                var dist = Math.sqrt((e.touches[0].clientX-e.touches[1].clientX) * (e.touches[0].clientX-e.touches[1].clientX) + (e.touches[0].clientY-e.touches[1].clientY) * (e.touches[0].clientY-e.touches[1].clientY));
+                                if (dist > pinchScale){
+                                    thisObJS.zoom(1);
+                                }
+                                else if (dist < pinchScale){
+                                    thisObJS.zoom(-1);
+                                }
+                                pinchScale = dist;
+                            }
+                            else{
+                                var x = e.touches[0].clientX
+                                var y = e.touches[0].clientY;
+                                thisObJS.rotateY(x - pX);
+                                thisObJS.rotateX(y - pY);
+                                pX = x;
+                                pY = y;
+                            }
+                            return false;
+                        }, false);
+
+                        canvasInitialized = true;
+                    }
+                };
+
+                /********************************************************************
+                 * Main function, called every time a file is to be loaded.         *
+                 * #parameters:                                                     *
+                 *   file (string): name of the file, without path or extension.    *
+                 * #return: nothing                                                 *
+                 * #scope: public                                                   *
+                 ********************************************************************/
+                this.load = function(file){
+                    if(!canvasInitialized){
+                        initCanvas();
+                    }
+                    //Get obj file
+                    var xmlhttp = new XMLHttpRequest();
+                    xmlhttp.open("GET", file, false);
+                    xmlhttp.send();
+                    var fileContent = xmlhttp.responseText;
+                    //Get mtl file
+                    xmlhttp = new XMLHttpRequest();
+                    xmlhttp.open("GET",file.substring(0, file.lastIndexOf(".")) + ".mtl", false);
+                    xmlhttp.send();
+                    var mtlContent = xmlhttp.responseText;
+                    initArrays();
+                    readFile(fileContent);
+                    readMtlFile(mtlContent);
+                    draw();
+                    drawSides();
+                };
+
+                /********************************************************************
+                 * Getters that determine if an element is being drawn.             *
+                 ********************************************************************/
+                this.isBackgroundDrawn = function(){
+                    return dBackg;
+                };
+
+                this.ivertexDrawn = function(){
+                    return dVerts;
+                };
+
+                this.isEdgeDrawn = function(){
+                    return dEdges;
+                };
+
+                this.ifaceDrawn = function(){
+                    return dFaces;
+                };
+
+                this.isMaterialUsed = function(){
+                    return useMtl;
+                };
+
+                /********************************************************************
+                 * Getters that determine if the model has associated materials.    *
+                 ********************************************************************/
+                this.hasMaterial = function(){
+                    return hasMtl;
+                };
+
+                /********************************************************************
+                 * Getters for the color of the elements.                           *
+                 ********************************************************************/
+                this.getBackgroundColor = function (){
+                    var str = backColor;
+                    var r = str.substring(5, str.indexOf(', '));
+                    str = str.substring(str.indexOf(', ') + 2);
+                    var g = str.substring(0, str.indexOf(', '));
+                    str = str.substring(str.indexOf(', ') + 2);
+                    var b = str.substring(0, str.indexOf(', '));
+                    var a = 1;
+                    return {red: r, green: g, blue: b, alpha: a};
+                };
+
+                this.gevertexColor = function (){
+                    var str = vertColor;
+                    var r = str.substring(5, str.indexOf(', '));
+                    str = str.substring(str.indexOf(', ') + 2);
+                    var g = str.substring(0, str.indexOf(', '));
+                    str = str.substring(str.indexOf(', ') + 2);
+                    var b = str.substring(0, str.indexOf(', '));
+                    var a = 1;
+                    return {red: r, green: g, blue: b, alpha: a};
+                };
+
+                this.getEdgeColor = function (){
+                    var str = edgeColor;
+                    var r = str.substring(5, str.indexOf(', '));
+                    str = str.substring(str.indexOf(', ') + 2);
+                    var g = str.substring(0, str.indexOf(', '));
+                    str = str.substring(str.indexOf(', ') + 2);
+                    var b = str.substring(0, str.indexOf(', '));
+                    var a = 1;
+                    return {red: r, green: g, blue: b, alpha: a};
+                };
+
+                this.gefaceColor = function (){
+                    var str = faceColor;
+                    var r = str.substring(5, str.indexOf(', '));
+                    str = str.substring(str.indexOf(', ') + 2);
+                    var g = str.substring(0, str.indexOf(', '));
+                    str = str.substring(str.indexOf(', ') + 2);
+                    var b = str.substring(0, str.indexOf(', '));
+                    str = str.substring(str.indexOf(', ') + 2);
+                    var a = str.substring(0, str.indexOf(')'));
+                    return {red: r, green: g, blue: b, alpha: a};
+                };
+
+                /********************************************************************
+                 * Functions switching the elements drawn (dVerts, dEdges, dFaces). *
+                 * #parameters:                                                     *
+                 *   on (boolean): indicating if the element is to be drawn.        *
+                 * #return: nothing                                                 *
+                 * #scope: public                                                   *
+                 ********************************************************************/
+                this.drawVertizes = function(on){
+                    if (on == true || on == false){
+                        dVerts = on;
+                        draw();
+                    }
+                };
+
+                this.drawEdges = function(on){
+                    if (on == true || on == false){
+                        dEdges = on;
+                        draw();
+                    }
+                };
+
+                this.drawFaces = function(on){
+                    if (on == true || on == false){
+                        dFaces = on;
+                        draw();
+                    }
+                };
+
+                this.drawBackground = function(on){
+                    if (on == true || on == false){
+                        dBackg = on;
+                        draw();
+                    }
+                };
+
+                /********************************************************************
+                 * Functions switching the color of the elements.                   *
+                 * #parameters:                                                     *
+                 *   code (string): hex color value, in #fff or #ffffff form. If    *
+                 *                  wrong, a message will be printed to console,    *
+                 *                  and nothing will be changed.                    *
+                 * #return: nothing                                                 *
+                 * #scope: public                                                   *
+                 ********************************************************************/
+                this.severtizesColor = function(code){
+                    if (isColor(code)){
+                        var color = hexToRgb(code);
+                        vertColor = "rgba(" + color.r + ", " + color.g + ", "  + color.b + ", 1)";
+                        draw();
+                    }
+                    else{
+                        console.log("severtizesColor(" + code + ") ERROR: " + code + " not a valid hex color");
+                    }
+                };
+
+                this.setEdgesColor = function(code){
+                    if (isColor(code)){
+                        var color = hexToRgb(code);
+                        edgeColor = "rgba(" + color.r + ", " + color.g + ", "  + color.b + ", 1)";
+                        draw();
+                    }
+                    else{
+                        console.log("setEdgesColor(" + code + ") ERROR: " + code + " not a valid hex color");
+                    }
+                };
+
+                this.sefacesColor = function(code){
+                    if (isColor(code)){
+                        var color = hexToRgb(code);
+                        faceColor = "rgba(" + color.r + ", " + color.g + ", "  + color.b + ", 1)";
+                        draw();
+                    }
+                    else{
+                        console.log("sefacesColor(" + code + ") ERROR: " + code + " not a valid hex color");
+                    }
+                };
+
+                this.setBackgroundColor = function(code){
+                    if (isColor(code)){
+                        var color = hexToRgb(code);
+                        backColor = "rgba(" + color.r + ", " + color.g + ", "  + color.b + ", 1)";
+                        draw();
+                    }
+                    else{
+                        console.log("setBackgroundColor(" + code + ") ERROR: " + code + " not a valid hex color");
+                    }
+                };
+
+                /********************************************************************
+                 * Function switching the use of mtl file for color.                *
+                 * #parameters:                                                     *
+                 *   value (boolean): indicating if the element is to be drawn.     *
+                 * #return: nothing                                                 *
+                 * #scope: public                                                   *
+                 ********************************************************************/
+                this.linkMaterial = function(value){
+                    useMtl = value;
+                    draw();
+                }
+
+                /********************************************************************
+                 * Function switching the alpha value of the faces.                 *
+                 * #parameters:                                                     *
+                 *   percent (int): Value (0-100) of alpha. Must be processed (0-1) *
+                 * #return: nothing                                                 *
+                 * #scope: public                                                   *
+                 ********************************************************************/
+                this.setAlpha = function(percent){
+                    if (percent >= 0 && percent <= 100){
+                        faceAlpha = percent / 100;
+                        faceColor = faceColor.substring(0, faceColor.lastIndexOf(",") + 2) + faceAlpha + ")";
+                        draw();
+                    }
+                    else{
+                        console.log("setAlpha(" + percent + "); ERROR: Only values between 0 and 100 are allowed");
+                    }
+                };
+
+                /********************************************************************
+                 * Function switching the rotation speed.                           *
+                 * #parameters:                                                     *
+                 *   percent (int): Value (0-10) of speed.                          *
+                 * #return: nothing                                                 *
+                 * #scope: public                                                   *
+                 ********************************************************************/
+                this.setRotationSpeed = function(percent){
+                    if (percent >= 0 && percent <= 10){
+                        rotationSpeed = Math.round((10 - percent) * 30);
+                        if (rotationSpeed == 0){
+                            rotationSpeed = 1;
+                        }
+                    }
+                    else{
+                        console.log("setRotationSpeed(" + percent + "); ERROR: Only values between 0 and 10 are allowed");
+                    }
+                }
+
+                /********************************************************************
+                 * Functions that rotate elements in the canvas along the           *
+                 * correspondent axys, calculating the new position for each vertex *
+                 * in the vert array.                                               *
+                 * #parameters:                                                     *
+                 *   des (int): distance to rotate.                                 *
+                 * #return: nothing                                                 *
+                 * #scope: public                                                   *
+                 ********************************************************************/
+                this.rotateY = function(des){
+                    for (var i = 0; i < vert.length; i ++) {
+                        var x = vert[i][0];
+                        var z = vert[i][2];
+                        vert[i][0] = x * Math.cos(des / rotationSpeed) - z * Math.sin(des / rotationSpeed);
+                        vert[i][2] = z * Math.cos(des / rotationSpeed) + x * Math.sin(des / rotationSpeed);
+                    }
+                    draw();
+                };
+
+                this.rotateX = function(des){
+                    for (var i = 0; i < vert.length; i ++) {
+                        var y = vert[i][1];
+                        var z = vert[i][2];
+                        vert[i][1] = y * Math.cos(des / rotationSpeed) - z * Math.sin(des / rotationSpeed);
+                        vert[i][2] = z * Math.cos(des / rotationSpeed) + y * Math.sin(des / rotationSpeed);
+                    }
+                    draw();
+                };
+
+                /********************************************************************
+                 * Function switching the movement speed of the model.              *
+                 * #parameters:                                                     *
+                 *   percent (int): Value (0-10) of speed.                          *
+                 * #return: nothing                                                 *
+                 * #scope: public                                                   *
+                 ********************************************************************/
+                this.setMovementSpeed = function(percent){
+                    if (percent >= 0 && percent <= 10){
+                        moveSpeed = ((percent * 0.8) / 10) + 0.01;
+                    }
+                    else{
+                        console.log("setMoveSpeed(" + percent + "); ERROR: Only values between 0 and 10 are allowed");
+                    }
+                }
+
+                /********************************************************************
+                 * Functions that move elements in the canvas along the selected    *
+                 * direction, calculating the new position for each vertex in the   *
+                 * vert array.                                                      *
+                 * #parameters:                                                     *
+                 *   des (int): distance to move.                                   *
+                 * #return: nothing                                                 *
+                 * #scope: public                                                   *
+                 ********************************************************************/
+                this.moveVertical = function(des){
+                    for (var i = 0; i < vert.length; i ++){
+                        vert[i][1] = (vert[i][1] * 1) + des * (moveSpeed / 50);
+                    }
+                    draw();
+                };
+
+                this.moveHorizontal = function(des){
+                    for (var i = 0; i < vert.length; i ++){
+                        vert[i][0] = (vert[i][0] * 1) + des * (moveSpeed / 50);
+                    }
+                    draw();
+                };
+
+                /********************************************************************
+                 * Function switching the zoom speede of the faces.                 *
+                 * #parameters:                                                     *
+                 *   percent (int): Value (0-100) of speed.                         *
+                 * #return: nothing                                                 *
+                 * #scope: public                                                   *
+                 ********************************************************************/
+                this.setZoomSpeed = function(percent){
+                    if (percent >= 0 && percent <= 10){
+                        zoomSpeed = ((percent * 0.8) / 10) + 0.01;
+                    }
+                    else{
+                        console.log("setZoomSpeed(" + percent + "); ERROR: Only values between 0 and 10 are allowed");
+                    }
+                }
+
+                /********************************************************************
+                 * Function that changes the scale variable, witch results in a     *
+                 * zoom in or zoom out effect.                                      *
+                 * #parameters: none                                                *
+                 * #return: nothing                                                 *
+                 * #scope: public                                                   *
+                 ********************************************************************/
+                this.zoom = function(val){
+                    scale = scale + val * scale * zoomSpeed;
+                    draw();
+                };
+
+                /********************************************************************
+                 * Function that clears the arrays and the canvas. Use to unload a  *
+                 * model.                                                           *
+                 * #parameters: none                                                *
+                 * #return: nothing                                                 *
+                 * #scope: public                                                  *
+                 ********************************************************************/
+                this.clear = function(){
+                    initArrays();
+                    clearCanvas();
+                };
+
+                /********************************************************************
+                 * Function that turns a hex color code in RGB.                     *
+                 * stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb    *
+                 * #parameters:                                                     *
+                 *   hex (string): color code, for example "#33ff99"                *
+                 * #return: (Array) r, g, b, with their correspondent color.        *
+                 * #scope: private                                                  *
+                 ********************************************************************/
+                var hexToRgb = function(hex) {
+                    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+                    return result ? {
+                        r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16)
+                    } : null;
+                };
+
+                /********************************************************************
+                 * Function that checks if a string is a valid hexadecimal color    *
+                 * code, in the format '#ffffff' or '#fff'                          *
+                 * #parameters:                                                     *
+                 *   code (string): Code to check.                                  *
+                 * #return: (Boolean) True if valid color code, false otherwise.    *
+                 * #scope: private                                                  *
+                 ********************************************************************/
+                var isColor = function(code){
+                    if (code[0] != '#'){
+                        return false;
+                    }
+                    if (code.length != 4 && code.length != 7){
+                        return false
+                    }
+                    for (var i = 1; i < code.length; i ++){
+                        if (code[i] < '0' || (code[i] > 9 && code[i] < 'A') || (code[i] > 'Z' && code[i] < 'a') || code[i] > 'z'){
+                            return false;
+                        }
+                    }
+                    return true;
+                };
+
+                /********************************************************************
+                 * Function that clears the canvas and gets it ready to draw on it. *
+                 * #parameters: none                                                *
+                 * #return: nothing                                                 *
+                 * #scope: private                                                  *
+                 ********************************************************************/
+                var clearCanvas = function(){
+                    ctx.clearRect(0, 0, canvas.width, canvas.height);
+                    if (dBackg){
+                        ctx.fillStyle = backColor;
+                    }
+                    else{
+                        ctx.fillStyle = "#ffffff";
+                    }
+                    ctx.fillRect(-canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height);
+                };
+
+                /********************************************************************
+                 * Function initializing the arrays obj, vert and face as empty     *
+                 * arrays.                                                          *
+                 * #parameters: none                                                *
+                 * #return: nothing                                                 *
+                 * #scope: private                                                  *
+                 ********************************************************************/
+                var initArrays = function(){
+                    material = null;
+                    vert = null;
+                    face = null;
+                    material = new Array();
+                    vert = new Array();
+                    face = new Array();
+                };
+
+                /********************************************************************
+                 * Function tat populates the vert[] array with and array of three  *
+                 * elements, containig the coordinates, and the face[] array with   *
+                 * the vertices forming the face, plus one element indicating the   *
+                 * codename of the material.                                        *
+                 * #parameters:                                                     *
+                 *   text (string): the content of the obj file.                    *
+                 * #return: nothing                                                 *
+                 * #scope: private                                                  *
+                 ********************************************************************/
+                var readFile = function(text){
+                    var line;
+                    var v = 0;
+                    var f = 0;
+                    var m = 0;
+                    var max = 0;
+                    var j;
+                    var dist;
+                    var fac;
+                    var mat = "null";
+                    text = text + "\n";
+                    while (text.indexOf("\n") != -1){
+                        line = text.substring(0, text.indexOf("\n"));
+                        if (line.substring(0, 2) == "v "){
+                            vert[v] = new Array(3);
+                            line = line.substring(2);
+                            vert[v][0] = line.substring(0, line.indexOf(" "));
+                            line = line.substring(line.indexOf(" ") + 1);
+                            vert[v][1] = line.substring(0, line.indexOf(" "));
+                            line = line.substring(line.indexOf(" ") + 1);
+                            vert[v][2] = line;
+
+                            dist = Math.sqrt(vert[v][0] * vert[v][0] + vert[v][1] * vert[v][1] + vert[v][2] * vert[v][2]);
+                            if (dist > max){
+                                max = dist;
+                            }
+                            v = v + 1;
+                        }
+                        else if (line.substring(0,2) == "f "){
+                            line = line.substring(2);
+                            face[f] = new Array();
+                            j = 0;
+                            while(line.indexOf(" ") != -1){
+                                face[f][j] = line.substring(0, line.indexOf(" "));
+                                if (face[f][j].indexOf('/') != -1){
+                                    face[f][j] = face[f][j].substring(0, face[f][j].indexOf('/'));
+                                }
+                                face[f][j] = face[f][j] - 1;
+                                line = line.substring(line.indexOf(" ") + 1);
+                                j = j + 1;
+                            }
+                            face[f][j] = line;
+                            if (face[f][j].indexOf('/') != -1){
+                                face[f][j] = face[f][j].substring(0, face[f][j].indexOf('/'));
+                            }
+                            face[f][j] = face[f][j] - 1;
+                            face[f][j + 1] = mat;
+                            f = f + 1;
+                        }
+                        else if (line.substring(0, 6) == "usemtl"){
+                            mat = line.substring(7);
+                        }
+                        text = text.substring(text.indexOf("\n") + 1);
+                    }
+                    scale = calculateScale(max);
+                    totalVert = vert.length;
+                    totalFace = face.length;
+                };
+
+                /********************************************************************
+                 * Function tat populates the material[] array with an array        *
+                 * containig, four values: the material name, and the three RGB     *
+                 * values.                                                          *
+                 * #parameters:                                                     *
+                 *   text (string): the content of the mtl file.                    *
+                 * #return: nothing                                                 *
+                 * #scope: private                                                  *
+                 ********************************************************************/
+                var readMtlFile = function(text){
+                    text = text + "\n";
+                    i = -1;
+                    while (text.indexOf("\n") != -1){
+                        line = text.substring(0, text.indexOf("\n"));
+                        if (line.substring(0, 6) == "newmtl"){
+                            i = i + 1;
+                            material[i] = new Array(4);
+                            material[i][0] = line.substring(line.indexOf(" ") + 1);
+                        }
+                        //Kd, ddifuse color, usefull
+                        //Ka, ambient color, not implemented
+                        //Ks, specular color, not implemented
+                        //d or TR, transparency, not now
+                        else if (line.substring(0, 3) == "Kd "){
+                            line = line.substring(3);
+                            material[i][1] = line.substring(0, line.indexOf(" "));
+                            line = line.substring(line.indexOf(" ") + 1);
+                            material[i][2] = line.substring(0, line.indexOf(" "));
+                            line = line.substring(line.indexOf(" ") + 1);
+                            material[i][3] = line;
+                        }
+                        text = text.substring(text.indexOf("\n") + 1);
+                    }
+                    totalMaterial = material.length;
+                    if (totalMaterial == 0){
+                        hasMtl = false;
+                    }
+                };
+
+                /********************************************************************
+                 * Function that automatically calculates the best scale for the    *
+                 * modelermined number of elements, containing the verices that     *
+                 * form a face, so the bigest dimension from the object can fit in  *
+                 * the smallest dimension of the canvas.                            *
+                 * #parameters:                                                     *
+                 *   text (int): the farthest vertex, from the center.              *
+                 * #return: (int) The scale to be aplied.                           *
+                 * #scope: private                                                  *
+                 ********************************************************************/
+                var calculateScale = function(max){
+                    var dim;
+                    if (canvas.width < canvas.height){
+                        dim = canvas.width;
+                    }
+                    else{
+                        dim = canvas.height;
+                    }
+                    var sc = Math.round((0.95 * dim) / (2 * max));
+                    return sc;
+                };
+
+                /********************************************************************
+                 * Function that compares the average Z coordinate of two faces.    *
+                 * Must be used when sorting the face array.                        *
+                 * #parameters:                                                     *
+                 *   a (Array): One face.                                           *
+                 *   b (Array): The other face.                                     *
+                 * #return: (int) -1, 1 or 0.                                       *
+                 * #scope: private                                                  *
+                 ********************************************************************/
+                var faceComparator = function(a,b){
+                    var aZ;
+                    var bZ;
+                    var i = 0;
+                    var sum = 0.0;
+                    while (i < a.length - 1){
+                        sum = sum + parseFloat(vert[a[i]][2]);
+                        i = i + 1;
+                    }
+                    aZ = sum / parseFloat(i);
+                    i = 0;
+                    sum = 0;
+                    while (i < b.length - 1){
+                        sum = sum + parseFloat(1 * vert[b[i]][2]);
+                        i = i + 1;
+                    }
+                    bZ = sum / parseFloat(i);
+                    if (aZ < bZ) return -1;
+                    if (aZ > bZ) return 1;
+                    return 0;
+                };
+
+                /********************************************************************
+                 * Function that writes text in the corner of the canvas. Must be   *
+                 * called when everithing has been drawn.                           *
+                 * #parameters: none                                                *
+                 * #return: nothing                                                 *
+                 * #scope: private                                                  *
+                 ********************************************************************/
+                var writeCredits = function(){
+                    /*ctx.fillStyle = textColor;
+                    ctx.font = "12px Arial";
+                    var h = canvas.height / 2 - 14;
+                    var w = 10 - (canvas.width / 2);
+                    ctx.fillText("ObJS:   " + totalVert + " vertices   " + totalFace + " faces   " + totalMaterial + " materials", w, h);*/
+                    document.getElementById('details_verts').innerHTML = totalVert + ' vertices';
+                    document.getElementById('details_faces').innerHTML = totalFace + ' faces';
+                    document.getElementById('details_materials').innerHTML = totalMaterial + ' materials';
+                };
+
+                var drawSides = function(){
+                    var sScale = scale * 0.2;
+
+                    // TOP
+                    topCtx.clearRect(0, 0, canvas.width, canvas.height);
+                    topCtx.fillStyle = "#ffffff";
+                    topCtx.fillRect(-topCanvas.width / 2, -topCanvas.height / 2, topCanvas.width, canvas.height);
+                    var des = Math.PI / 2;
+                    for (var i = 0; i < vert.length; i ++) {
+                        var y = vert[i][1];
+                        var z = vert[i][2];
+                        vert[i][1] = y * Math.cos(des) - z * Math.sin(des);
+                        vert[i][2] = z * Math.cos(des) + y * Math.sin(des);
+                    }
+                    for (var i = 0; i < face.length; i++){
+                        topCtx.strokeStyle = '#00000099';
+                        topCtx.beginPath();
+                        topCtx.moveTo(50 + (sScale * vert[face[i][0]][0]), 50 + (sScale * vert[face[i][0]][1]));
+                        for (var j = 1; j < face[i].length - 1; j++) {
+                            topCtx.lineTo(50 + (sScale * vert[face[i][j]][0]), 50 + (sScale * vert[face[i][j]][1]));
+                            //topCtx.stroke();
+                        }
+                        topCtx.closePath();
+                        if (useMtl){
+                            //Get material with the same name as the one in the last element of the face
+                            j = 0;
+                            while (material[j][0] != face[i][face[i].length - 1] && j < material.length){
+                                j = j + 1;
+                            }
+                            if (material[j][0] == face[i][face[i].length - 1]){
+                                topCtx.fillStyle = "rgba(" + Math.round(255 * material[j][1]) + ", " + Math.round(255 * material[j][2]) + ", " + Math.round(255 * material[j][3]) + ", " + 1 + ")";
+                            }
+                            else{
+                                topCtx.fillStyle = faceColor;
+                            }
+                        }
+                        else{
+                            topCtx.fillStyle = faceColor;
+                        }
+                        topCtx.stroke();
+                        if(dFaces){
+                            topCtx.fill();
+                        }
+                    }
+                    //restore
+                    des = Math.PI / -2;
+                    for (var i = 0; i < vert.length; i ++) {
+                        var y = vert[i][1];
+                        var z = vert[i][2];
+                        vert[i][1] = y * Math.cos(des) - z * Math.sin(des);
+                        vert[i][2] = z * Math.cos(des) + y * Math.sin(des);
+                    }
+
+                    // FRONT
+                    frontCtx.clearRect(0, 0, canvas.width, canvas.height);
+                    frontCtx.fillStyle = "#ffffff";
+                    frontCtx.fillRect(-frontCanvas.width / 2, -frontCanvas.height / 2, frontCanvas.width, canvas.height);
+                    des = Math.PI / 2;
+                    for (var i = 0; i < face.length; i++){
+                        frontCtx.strokeStyle = '#00000099';
+                        frontCtx.beginPath();
+                        frontCtx.moveTo(50 + (sScale * vert[face[i][0]][0]), 50 + (sScale * vert[face[i][0]][1]));
+                        for (var j = 1; j < face[i].length - 1; j++) {
+                            frontCtx.lineTo(50 + (sScale * vert[face[i][j]][0]), 50 + (sScale * vert[face[i][j]][1]));
+                            //frontCtx.stroke();
+                        }
+                        frontCtx.closePath();
+                        if (useMtl){
+                            //Get material with the same name as the one in the last element of the face
+                            j = 0;
+                            while (material[j][0] != face[i][face[i].length - 1] && j < material.length){
+                                j = j + 1;
+                            }
+                            if (material[j][0] == face[i][face[i].length - 1]){
+                                frontCtx.fillStyle = "rgba(" + Math.round(255 * material[j][1]) + ", " + Math.round(255 * material[j][2]) + ", " + Math.round(255 * material[j][3]) + ", " + 1 + ")";
+                            }
+                            else{
+                                frontCtx.fillStyle = faceColor;
+                            }
+                        }
+                        else{
+                            frontCtx.fillStyle = faceColor;
+                        }
+                        frontCtx.stroke();
+                        if(dFaces){
+                            frontCtx.fill();
+                        }
+                    }
+
+                    // SIDE
+                    sideCtx.clearRect(0, 0, canvas.width, canvas.height);
+                    sideCtx.fillStyle = "#ffffff";
+                    sideCtx.fillRect(-sideCanvas.width / 2, -sideCanvas.height / 2, sideCanvas.width, canvas.height);
+                    des = Math.PI / 2;
+                    for (var i = 0; i < vert.length; i ++) {
+                        var x = vert[i][0];
+                        var z = vert[i][2];
+                        vert[i][0] = x * Math.cos(des) - z * Math.sin(des);
+                        vert[i][2] = z * Math.cos(des) + x * Math.sin(des);
+                    }
+                    for (var i = 0; i < face.length; i++){
+                        sideCtx.strokeStyle = '#00000099';
+                        sideCtx.beginPath();
+                        sideCtx.moveTo(50 + (sScale * vert[face[i][0]][0]), 50 + (sScale * vert[face[i][0]][1]));
+                        for (var j = 1; j < face[i].length - 1; j++) {
+                            sideCtx.lineTo(50 + (sScale * vert[face[i][j]][0]), 50 + (sScale * vert[face[i][j]][1]));
+                            //sideCtx.stroke();
+                        }
+                        sideCtx.closePath();
+                        if (useMtl){
+                            //Get material with the same name as the one in the last element of the face
+                            j = 0;
+                            while (material[j][0] != face[i][face[i].length - 1] && j < material.length){
+                                j = j + 1;
+                            }
+                            if (material[j][0] == face[i][face[i].length - 1]){
+                                sideCtx.fillStyle = "rgba(" + Math.round(255 * material[j][1]) + ", " + Math.round(255 * material[j][2]) + ", " + Math.round(255 * material[j][3]) + ", " + 1 + ")";
+                            }
+                            else{
+                                sideCtx.fillStyle = faceColor;
+                            }
+                        }
+                        else{
+                            sideCtx.fillStyle = faceColor;
+                        }
+                        sideCtx.stroke();
+                        if(dFaces){
+                            sideCtx.fill();
+                        }
+                    }
+                    //Restore
+                    des = Math.PI / -2;
+                    for (var i = 0; i < vert.length; i ++) {
+                        var x = vert[i][0];
+                        var z = vert[i][2];
+                        vert[i][0] = x * Math.cos(des) - z * Math.sin(des);
+                        vert[i][2] = z * Math.cos(des) + x * Math.sin(des);
+                    }
+                };
+
+                /********************************************************************
+                 * Function that draws th vertices, faces and edges in the canvas.  *
+                 * #parameters: none                                                *
+                 * #return: nothing                                                 *
+                 * #scope: private                                                  *
+                 ********************************************************************/
+                var draw = function(){
+                    face = face.sort(faceComparator).reverse();
+                    clearCanvas();
+                    for (var i = 0; i < face.length; i++){
+                        ctx.strokeStyle = edgeColor;
+                        ctx.fillStyle = vertColor;
+                        ctx.beginPath();
+                        ctx.moveTo(scale * vert[face[i][0]][0], scale * vert[face[i][0]][1]);
+                        for (var j = 1; j < face[i].length - 1; j++) {
+                            ctx.lineTo(scale * vert[face[i][j]][0], scale * vert[face[i][j]][1]);
+                            if(dEdges){
+                                ctx.stroke();
+                            }
+                            if(dVerts){
+                                var x = scale * vert[face[i][j]][0] - (vertSize / 2);
+                                var w = vertSize;
+                                var y = scale * vert[face[i][j]][1] - (vertSize / 2);
+                                var h = vertSize;
+                                ctx.fillRect(x, y, w, h);
+                            }
+                        }
+                        ctx.closePath();
+                        if (useMtl){
+                            //Get material with the same name as the one in the last element of the face
+                            j = 0;
+                            while (material[j][0] != face[i][face[i].length - 1] && j < material.length){
+                                j = j + 1;
+                            }
+                            if (material[j][0] == face[i][face[i].length - 1]){
+                                ctx.fillStyle = "rgba(" + Math.round(255 * material[j][1]) + ", " + Math.round(255 * material[j][2]) + ", " + Math.round(255 * material[j][3]) + ", " + faceAlpha + ")";
+                            }
+                            else{
+                                ctx.fillStyle = faceColor;
+                            }
+                        }
+                        else{
+                            ctx.fillStyle = faceColor;
+                        }
+                        if(dFaces){
+                            ctx.fill();
+                        }
+                    }
+                    writeCredits();
+                };
+
+                /********************************************************************
+                 * TODO: Function used when something in the canvas is clicked.     *
+                 * #parameters: none                                                *
+                 * #return: nothing                                                 *
+                 * #scope: private                                                  *
+                 ********************************************************************/
+                var mouseClick = function(){
+                };
+
+                thisObJS = this;
+                return this;
+            }
+        </script>
+        <style>
+            body{
+                text-align: center;
+                background-color: #002200;
+            }
+            h1{
+                margin-bottom: 0;
+                color: #ffffff;
+            }
+            h2{
+                font-size: 110%;
+                font-style: italic;
+                margin-top: 0;
+                color: #ffffff;
+            }
+            section{
+                display: inline-block;
+                vertical-align: top;
+                height: 526px;
+                margin: 0;
+                border: 2px solid #000000;
+            }
+            section h3{
+                height: 24px;
+                margin: 0;
+                border-bottom: 2px solid #000000;
+                background-color: #cceeff;
+            }
+            section#sideViews{
+                width: 120px;
+                background-color: #e0f5ff;
+                border-top-left-radius: 20px;
+                border-bottom-left-radius: 20px;
+            }
+            section#sideViews h3{
+                border-top-left-radius: 20px;
+            }
+            section#sideViews h4{
+                margin: 10px auto 0 auto;
+            }
+            section#sideViews canvas{
+                border: 0.1em solid #000000;
+                margin: 0 10px 10px 10px;
+                background-color: #ffffff;
+            }
+            section#sideViews div#details{
+                margin-top: 20px;
+            }
+            section#sideViews div#details span{
+                font-size: 70%;
+                display: block;
+                color: #444444;
+                font-weight: bold;
+            }
+            section#controls{
+                text-align: center;
+                width: 260px;
+                background-color: #e0f5ff;
+                border-top-right-radius: 20px;
+                border-bottom-right-radius: 20px;
+            }
+            section#controls h3{
+                border-top-right-radius: 20px;
+                margin-bottom: 20px;
+            }
+            section#controls table#colors{
+                margin: 20px auto;
+                border-collapse: collapse;
+            }
+            section#controls table#colors td{
+                border: 1px solid #000000;
+            }
+            section#controls table#colors td img{
+                width: 30px;
+                height: 30px;
+            }
+            section#controls table#colors td input[type="color"]{
+                width: 30px;
+                height: 30px;
+                padding: 1px;
+            }
+            section#controls input[type="range"]{
+                display: block;
+                width: 80%;
+                margin: auto auto 15px auto;
+            }
+            canvas#ObJSView{
+                width: 500px;
+                height: 500px;
+            }
+            td#ObJSControl input[type="color"]{
+                width: 1.3em;
+                height: 1.3em;
+                padding: 0;
+                vertical-align: middle;
+            }
+            td#ObJSControl input[type="range"]{
+                vertical-align: middle;
+            }
+        </style>
+    </head>
+    <body onload="objs = new ObJS(); objs.initCanvas();objs.load(document.getElementById('objSelector').value);">
+        <h1>
+            ObJS
+        </h1>
+        <h2>
+            by I&ntilde;igo Valentin
+        </h2>
+        <section id='sideViews'>
+            <h3>
+                Details
+            </h3>
+            <h4>
+                Top
+            </h4>
+            <canvas id="ObJSTop" width="100" height="100">
+                Your browser does not support the HTML5 canvas tag.
+            </canvas>
+            <h4>
+                Front
+            </h4>
+            <canvas id="ObJSFront" width="100" height="100">
+                Your browser does not support the HTML5 canvas tag.
+            </canvas>
+            <h4>
+                Side
+            </h4>
+            <canvas id="ObJSSide" width="100" height="100">
+                Your browser does not support the HTML5 canvas tag.
+            </canvas>
+            <div id='details'>
+                <span id='details_verts'></span>
+                <span id='details_faces'></span>
+                <span id='details_materials'></span>
+            </div>
+        </section>
+        <section id='view'>
+            <h3>
+                View
+            </h3>
+            <canvas id="ObJSView" width="500" height="500">
+                Your browser does not support the HTML5 canvas tag.
+            </canvas>
+        </section>
+        <section id='controls'>
+            <h3>
+                Controls
+            </h3>
+            Choose a model:
+            <select id="objSelector" onChange="objs.load(this.value)">
+                <option value="obj/rainbow.obj" selected="selected">Rainbow</option>
+                <option value="obj/cube.obj">Cube</option>
+                <option value="obj/sphere.obj">Sphere</option>
+                <option value="obj/star.obj">Star</option>
+                <option value="obj/monkey.obj">Monkey</option>
+                <option value="obj/bolt.obj">Bolt</option>
+                <option value="obj/multiple.obj">Multiple Objects</option>
+                <option value="obj/seaplane.obj">Seaplane (Can freeze browser)</option>
+            </select>
+            <table id='colors'>
+                <tr>
+                    <td>
+                    </td>
+                    <td>
+                        <img src='img/eye.png'/>
+                    </td>
+                    <td>
+                        <img src='img/color.png'/>
+                    </td>
+                </tr>
+                <tr>
+                    <td>
+                        <img src='img/vert.png'/>
+                    </td>
+                    <td>
+                        <input type="checkbox"  value="verts" checked onChange="objs.drawVertizes(this.checked);"/>
+                    </td>
+                    <td>
+                        <input type="color"  value="#0A0A0A" onChange="objs.severtizesColor(this.value);"/>
+                    </td>
+                </tr>
+                <tr>
+                    <td>
+                        <img src='img/line.png'/>
+                    </td>
+                    <td>
+                        <input type="checkbox" value="edges" checked onChange="objs.drawEdges(this.checked);"/>
+                    </td>
+                    <td>
+                        <input type="color" value="#644646" onChange="objs.setEdgesColor(this.value);"/>
+                    </td>
+                </tr>
+                <tr>
+                    <td>
+                        <img src='img/face.png'/>
+                    </td>
+                    <td>
+                        <input type="checkbox" value="faces" checked onChange="objs.drawFaces(this.checked);"/>
+                    </td>
+                    <td>
+                        <input type="color" value="#B4B4FF" onChange="objs.sefacesColor(this.value);"/>
+                        <!-- <input type="checkbox" checked onChange="objs.linkMaterial(this.checked);"/>Use materials -->
+                    </td>
+                </tr>
+                <tr>
+                    <td>
+                        <img src='img/bg.png'/>
+                    </td>
+                    <td>
+                        <input type="checkbox" value="backg" checked onChange="objs.drawBackground(this.checked);"/>
+                    </td>
+                    <td>
+                        <input type="color" value="#C8C8C8" onChange="objs.setBackgroundColor(this.value)"/>
+                    </td>
+                </tr>
+            </table>
+            Alpha:
+            <input type="range" min="0" max="100" step="1" value="60" onInput="objs.setAlpha(this.value);" onChange="objs.setAlpha(this.value);"/>
+            Rotation speed:
+            <input type="range" min="0" max="10" step="1" value="3" onInput="objs.setRotationSpeed(this.value);" onChange="objs.setRotationSpeed(this.value);"/>
+            Zoom speed:
+            <input type="range" min="0" max="10" step="1" value="2" onInput="objs.setZoomSpeed(this.value);" onChange="objs.setZoomSpeed(this.value);"/>
+            Movement speed:
+            <input type="range" min="0" max="10" step="1" value="5" onInput="objs.setMovementSpeed(this.value);" onChange="objs.setMovementSpeed(this.value);"/>
+        </section>
+    </body>
+</html>

+ 0 - 835
script/ObJS.js

@@ -1,835 +0,0 @@
-/********************************************************************
- * The ObJS objectnitializes the canvas, assignin it to the HTML    *
- * element, and set the required mouse events.                      *
- * #parameters: none                                                *
- * #return: nothing                                                 *
- ********************************************************************/
-function ObJS(){
-	
-	/********************************************************************
-	 * Parameters for costumization.                                    *
-	 ********************************************************************/ 
-	var backColor = "rgba(200, 200, 200, 1)";
-	var vertColor = "rgba(10, 10, 10, 1)";
-	var edgeColor = "rgba(100, 70, 70, 1)";
-	var faceColor = "rgba(180, 180, 255, .6)";
-	var faceAlpha = .6;
-	var textColor = "rgba(0, 0, 0, 1)";
-	var vertSize = 4; //Make it even: at small scales will look better
-	var rotationSpeed = 90; //Smaller = faster. 100 is a good speed
-	var zoomSpeed = 0.161; //0-1. 0.2 or 0.3 are good speeds
-	var moveSpeed = .5;
-	
-	/********************************************************************
-	 * Variable containing this object, to be refered from nested       *
-	 * functions.                                                       *
-	 ********************************************************************/ 
-	var thisObJS;
-	
-	/********************************************************************
-	 * Parameter used to scale the measures in the .obj file. Can be    *
-	 * integer or float, greater than 0. 50 is a good default.          *
-	 ********************************************************************/
-	var scale;
-	
-	/********************************************************************
-	 * Variable to determine if the canvas has been initialized.        *
-	 ********************************************************************/ 
-	var canvasInitialized = false;
-	
-	/********************************************************************
-	 * Variable to determine if the mouse button is being holded down.  *
-	 ********************************************************************/ 
-	var mDown = false;
-	var pinch = false;
-	var pinchScale = 0;
-	
-	/********************************************************************
-	 * Variables containing the canvas and its context.                 *
-	 ********************************************************************/ 
-	var canvas;
-	var ctx;
-	
-	/********************************************************************
-	 * Variables containing the number of elements.                     *
-	 ********************************************************************/ 
-	var totalVert;
-	var totalMaterial = 0;
-	var totalFace
-	
-	/********************************************************************
-	 * Arrays containing the vertices, faces and materials.             *
-	 ********************************************************************/ 
-	var material;
-	var vert;
-	var face;
-	
-	/********************************************************************
-	 * Booleans to determine wich elements are to draw.                 *
-	 ********************************************************************/ 
-	var dVerts = true;
-	var dEdges = true;
-	var dFaces = true;
-	var dBackg = true;
-	
-	/********************************************************************
-	 * Booleans to indicate if mtl file should be used.                 *
-	 ********************************************************************/
-	var hasMtl = true;
-	var useMtl = true;
-	
-	/********************************************************************
-	 * Global variables that will contain the position of the mouse in  *
-	 * the previous frame to calculate rotation.                        *
-	 ********************************************************************/ 
-	var pX = null;
-	var pY = null;
-	
-	/********************************************************************
-	 * Function that initializes the canvas, assignin it to the HTML    *
-	 * element, and set the required mouse events.                      *
-	 * #parameters:                                                     *
-	 *   canv (canvas): canvas to use. If omited, the one named         *
-	 *                  named "ObJSCanvas" will be used.                *
-	 * #return: nothing                                                 *
-	 * #scope: public                                                   *
-	 ********************************************************************/	
-	this.initCanvas = function(canv){
-		if (!canvasInitialized){
-			if (canv!= null)
-				canvas = canv;
-			else
-				canvas = document.getElementById("ObJSCanvas");
-			ctx = canvas.getContext("2d");
-			ctx.translate(canvas.width / 2, canvas.height / 2);
-			
-			canvas.onmousedown = function(e){
-				pX = e.offsetX==undefined?e.layerX:e.offsetX;
-				pY = e.offsetY==undefined?e.layerY:e.offsetY;
-				mDown = true;
-			};
-			
-			canvas.onmouseup = function(e){
-				if(mDown) 
-					mouseClick(e);
-				pX = null;
-				pY = null;
-				mDown = false;
-			};
-			
-			canvas.onmousemove = function(e){
-				if(!mDown) 
-					return;
-				var x = e.offsetX==undefined?e.layerX:e.offsetX;
-				var y = e.offsetY==undefined?e.layerY:e.offsetY;
-				if (e.shiftKey){
-					thisObJS.moveHorizontal(x - pX);
-					thisObJS.moveVertical(y - pY);
-				}
-				else{
-					thisObJS.rotateY(x - pX);
-					thisObJS.rotateX(y - pY);
-				}
-				pX = x;
-				pY = y;
-				return false;
-			};
-			
-			canvas.onmouseout = function(e){
-				if(mDown)
-					mDown = false;
-			}
-			
-			canvas.addEventListener('mousewheel',function(e){
-				e.preventDefault();
-				if (event.wheelDelta > 0)
-					thisObJS.zoom(1);
-				else 
-					thisObJS.zoom(-1);
-				return false;
-			}, false);
-			
-			canvas.addEventListener('touchstart',function(e){
-				if(e.touches.length == 2) {
-					pinch = true;
-					pinchScale = Math.sqrt((e.touches[0].clientX-e.touches[1].clientX) * (e.touches[0].clientX-e.touches[1].clientX) + (e.touches[0].clientY-e.touches[1].clientY) * (e.touches[0].clientY-e.touches[1].clientY));
-				}
-				return false;
-			}, false);
-			
-			canvas.addEventListener('touchend',function(e){
-				if(pinch)
-					pinch = false;
-				return false;
-			}, false);
-			
-			canvas.addEventListener('touchcancel',function(e){
-				if(pinch)
-					pinch = false;
-				return false;
-			}, false);
-			
-			canvas.addEventListener('touchleave',function(e){
-				if(pinch)
-					pinch = false;
-				return false;
-			}, false);
-			
-			canvas.addEventListener('touchmove',function(e){
-				e.preventDefault();
-				if(pinch){
-					var dist = Math.sqrt((e.touches[0].clientX-e.touches[1].clientX) * (e.touches[0].clientX-e.touches[1].clientX) + (e.touches[0].clientY-e.touches[1].clientY) * (e.touches[0].clientY-e.touches[1].clientY));
-					if (dist > pinchScale)
-						thisObJS.zoom(1);
-					else if (dist < pinchScale)
-						thisObJS.zoom(-1);
-					pinchScale = dist;
-				}
-				else{
-					var x = e.touches[0].clientX
-					var y = e.touches[0].clientY;
-					thisObJS.rotateY(x - pX);
-					thisObJS.rotateX(y - pY);
-					pX = x;
-					pY = y;
-				}
-				return false;
-			}, false);
-			
-			canvasInitialized = true;
-		}
-	};
-	
-	/********************************************************************
-	 * Main function, called every time a file is to be loaded.         *
-	 * #parameters:                                                     *
-	 *   file (string): name of the file, without path or extension.    *
-	 * #return: nothing                                                 *
-	 * #scope: public                                                   *
-	 ********************************************************************/
-	this.load = function(file){
-		if(!canvasInitialized)
-			initCanvas();
-		//Get obj file
-		var xmlhttp = new XMLHttpRequest();
-		xmlhttp.open("GET", file, false);
-		xmlhttp.send();
-		var fileContent = xmlhttp.responseText;
-		//Get mtl file
-		xmlhttp = new XMLHttpRequest();
-		xmlhttp.open("GET",file.substring(0, file.lastIndexOf(".")) + ".mtl", false);
-		xmlhttp.send();
-		var mtlContent = xmlhttp.responseText;
-		initArrays();
-		readFile(fileContent);
-		readMtlFile(mtlContent);
-		draw();
-	};
-	/********************************************************************
-	 * Getters that determine if an element is being drawn.             *
-	 ********************************************************************/
-	this.isBackgroundDrawn = function(){
-		return dBackg;
-	};
-	
-	this.isVertexDrawn = function(){
-		return dVerts;
-	};
-	
-	this.isEdgeDrawn = function(){
-		return dEdges;
-	};
-	
-	this.isFaceDrawn = function(){
-		return dFaces;
-	};
-	
-	this.isMaterialUsed = function(){
-		return useMtl;
-	};
-	/********************************************************************
-	 * Getters that determine if the model has associated materials.    *
-	 ********************************************************************/
-	this.hasMaterial = function(){
-		return hasMtl;
-	};
-	
-	/********************************************************************
-	 * Getters for the color of the elements.                           *
-	 ********************************************************************/
-	this.getBackgroundColor = function (){
-		var str = backColor;
-		var r = str.substring(5, str.indexOf(', '));
-		str = str.substring(str.indexOf(', ') + 2);
-		var g = str.substring(0, str.indexOf(', '));
-		str = str.substring(str.indexOf(', ') + 2);
-		var b = str.substring(0, str.indexOf(', '));
-		var a = 1;
-		return {red: r, green: g, blue: b, alpha: a};
-	};
-	
-	this.getVertexColor = function (){
-		var str = vertColor;
-		var r = str.substring(5, str.indexOf(', '));
-		str = str.substring(str.indexOf(', ') + 2);
-		var g = str.substring(0, str.indexOf(', '));
-		str = str.substring(str.indexOf(', ') + 2);
-		var b = str.substring(0, str.indexOf(', '));
-		var a = 1;
-		return {red: r, green: g, blue: b, alpha: a};
-	};
-	
-	this.getEdgeColor = function (){
-		var str = edgeColor;
-		var r = str.substring(5, str.indexOf(', '));
-		str = str.substring(str.indexOf(', ') + 2);
-		var g = str.substring(0, str.indexOf(', '));
-		str = str.substring(str.indexOf(', ') + 2);
-		var b = str.substring(0, str.indexOf(', '));
-		var a = 1;
-		return {red: r, green: g, blue: b, alpha: a};
-	};
-	
-	this.getFaceColor = function (){
-		var str = faceColor;
-		var r = str.substring(5, str.indexOf(', '));
-		str = str.substring(str.indexOf(', ') + 2);
-		var g = str.substring(0, str.indexOf(', '));
-		str = str.substring(str.indexOf(', ') + 2);
-		var b = str.substring(0, str.indexOf(', '));
-		str = str.substring(str.indexOf(', ') + 2);
-		var a = str.substring(0, str.indexOf(')'));
-		return {red: r, green: g, blue: b, alpha: a};
-	};
-	
-	/********************************************************************
-	 * Functions switching the elements drawn (dVerts, dEdges, dFaces). *
-	 * #parameters:                                                     *
-	 *   on (boolean): indicating if the element is to be drawn.        *
-	 * #return: nothing                                                 *
-	 * #scope: public                                                   *
-	 ********************************************************************/ 
-	this.drawVertices = function(on){
-		if (on == true || on == false){
-			dVerts = on;
-			draw();
-		}
-	};
-	
-	this.drawEdges = function(on){
-		if (on == true || on == false){
-			dEdges = on;
-			draw();
-		}
-	};
-	
-	this.drawFaces = function(on){
-		if (on == true || on == false){
-			dFaces = on;
-			draw();
-		}
-	};
-	
-	this.drawBackground = function(on){
-		if (on == true || on == false){
-			dBackg = on;
-			draw();
-		}
-	};
-	
-	/********************************************************************
-	 * Functions switching the color of the elements.                   *
-	 * #parameters:                                                     *
-	 *   code (string): hex color value, in #fff or #ffffff form. If    *
-	 *                  wrong, a message will be printed to console,    *
-	 *                  and nothing will be changed.                    *
-	 * #return: nothing                                                 *
-	 * #scope: public                                                   *
-	 ********************************************************************/
-	this.setVerticesColor = function(code){
-		if (isColor(code)){
-			var color = hexToRgb(code);
-			vertColor = "rgba(" + color.r + ", " + color.g + ", "  + color.b + ", 1)";
-			draw();
-		}
-		else
-			console.log("setVerticesColor(" + code + ") ERROR: " + code + " not a valid hex color");
-	};
-	
-	this.setEdgesColor = function(code){
-		if (isColor(code)){
-			var color = hexToRgb(code);
-			edgeColor = "rgba(" + color.r + ", " + color.g + ", "  + color.b + ", 1)";
-			draw();
-		}
-		else
-			console.log("setEdgesColor(" + code + ") ERROR: " + code + " not a valid hex color");
-	};
-	
-	this.setFacesColor = function(code){
-		if (isColor(code)){
-			var color = hexToRgb(code);
-			faceColor = "rgba(" + color.r + ", " + color.g + ", "  + color.b + ", 1)";
-			draw();
-		}
-		else
-			console.log("setFacesColor(" + code + ") ERROR: " + code + " not a valid hex color");
-	};
-	
-	this.setBackgroundColor = function(code){
-		if (isColor(code)){
-			var color = hexToRgb(code);
-			backColor = "rgba(" + color.r + ", " + color.g + ", "  + color.b + ", 1)";
-			draw();
-		}
-		else
-			console.log("setBackgroundColor(" + code + ") ERROR: " + code + " not a valid hex color");
-	};
-	
-	/********************************************************************
-	 * Function switching the use of mtl file for color.                *
-	 * #parameters:                                                     *
-	 *   value (boolean): indicating if the element is to be drawn.     *
-	 * #return: nothing                                                 *
-	 * #scope: public                                                   *
-	 ********************************************************************/ 
-	this.linkMaterial = function(value){
-		useMtl = value;
-		draw();
-	}
-	
-	/********************************************************************
-	 * Function switching the alpha value of the faces.                 *
-	 * #parameters:                                                     *
-	 *   percent (int): Value (0-100) of alpha. Must be processed (0-1) *
-	 * #return: nothing                                                 *
-	 * #scope: public                                                   *
-	 ********************************************************************/ 
-	this.setAlpha = function(percent){
-		if (percent >= 0 && percent <= 100){
-			faceAlpha = percent / 100;
-			faceColor = faceColor.substring(0, faceColor.lastIndexOf(",") + 2) + faceAlpha + ")";
-			draw();
-		}
-		else
-			console.log("setAlpha(" + percent + "); ERROR: Only values between 0 and 100 are allowed");
-	};
-	
-	/********************************************************************
-	 * Function switching the rotation speed.                           *
-	 * #parameters:                                                     *
-	 *   percent (int): Value (0-10) of speed.                          *
-	 * #return: nothing                                                 *
-	 * #scope: public                                                   *
-	 ********************************************************************/ 
-	this.setRotationSpeed = function(percent){
-		if (percent >= 0 && percent <= 10){
-			rotationSpeed = Math.round((10 - percent) * 30);
-			if (rotationSpeed == 0)
-				rotationSpeed = 1;
-		}
-		else
-			console.log("setRotationSpeed(" + percent + "); ERROR: Only values between 0 and 10 are allowed");
-	}
-	
-	/********************************************************************
-	 * Functions that rotate elements in the canvas along the           *
-	 * correspondent axys, calculating the new position for each vertex *
-	 * in the vert array.                                               *
-	 * #parameters:                                                     *
-	 *   des (int): distance to rotate.                                 *
-	 * #return: nothing                                                 *
-	 * #scope: public                                                   *
-	 ********************************************************************/
-	this.rotateY = function(des){
-		for (var i = 0; i < vert.length; i ++) {
-			var x = vert[i][0];
-			var z = vert[i][2];
-			vert[i][0] = x * Math.cos(des / rotationSpeed) - z * Math.sin(des / rotationSpeed);
-			vert[i][2] = z * Math.cos(des / rotationSpeed) + x * Math.sin(des / rotationSpeed);
-		}
-		draw();
-	};
-	
-	this.rotateX = function(des){
-		for (var i = 0; i < vert.length; i ++) {
-			var y = vert[i][1];
-			var z = vert[i][2];
-			vert[i][1] = y * Math.cos(des / rotationSpeed) - z * Math.sin(des / rotationSpeed);
-			vert[i][2] = z * Math.cos(des / rotationSpeed) + y * Math.sin(des / rotationSpeed);
-		}
-		draw();
-	};
-	
-	/********************************************************************
-	 * Function switching the movement speed of the model.              *
-	 * #parameters:                                                     *
-	 *   percent (int): Value (0-10) of speed.                          *
-	 * #return: nothing                                                 *
-	 * #scope: public                                                   *
-	 ********************************************************************/ 
-	this.setMovementSpeed = function(percent){
-		if (percent >= 0 && percent <= 10)
-			moveSpeed = ((percent * 0.8) / 10) + 0.01;
-		else
-			console.log("setMoveSpeed(" + percent + "); ERROR: Only values between 0 and 10 are allowed");
-	}
-	
-	/********************************************************************
-	 * Functions that move elements in the canvas along the selected    *
-	 * direction, calculating the new position for each vertex in the   *
-	 * vert array.                                                      *
-	 * #parameters:                                                     *
-	 *   des (int): distance to move.                                   *
-	 * #return: nothing                                                 *
-	 * #scope: public                                                   *
-	 ********************************************************************/
-	this.moveVertical = function(des){
-		for (var i = 0; i < vert.length; i ++)
-			vert[i][1] = (vert[i][1] * 1) + des * (moveSpeed / 50);
-		draw();
-	};
-	
-	this.moveHorizontal = function(des){
-		for (var i = 0; i < vert.length; i ++)
-			vert[i][0] = (vert[i][0] * 1) + des * (moveSpeed / 50);
-		draw();
-	};
-	
-	/********************************************************************
-	 * Function switching the zoom speede of the faces.                 *
-	 * #parameters:                                                     *
-	 *   percent (int): Value (0-100) of speed.                         *
-	 * #return: nothing                                                 *
-	 * #scope: public                                                   *
-	 ********************************************************************/ 
-	this.setZoomSpeed = function(percent){
-		if (percent >= 0 && percent <= 10)
-			zoomSpeed = ((percent * 0.8) / 10) + 0.01;
-		else
-			console.log("setZoomSpeed(" + percent + "); ERROR: Only values between 0 and 10 are allowed");
-	}
-	
-	/********************************************************************
-	 * Function that changes the scale variable, witch results in a     *
-	 * zoom in or zoom out effect.                                      *
-	 * #parameters: none                                                *
-	 * #return: nothing                                                 *
-	 * #scope: public                                                   *
-	 ********************************************************************/
-	this.zoom = function(val){
-		scale = scale + val * scale * zoomSpeed;
-		draw();
-	};
-	
-	/********************************************************************
-	 * Function that clears the arrays and the canvas. Use to unload a  *
-	 * model.                                                           *
-	 * #parameters: none                                                *
-	 * #return: nothing                                                 *
-	 * #scope: public                                                  *
-	 ********************************************************************/
-	this.clear = function(){
-		initArrays();
-		clearCanvas();
-	};
-	
-	/********************************************************************
-	 * Function that turns a hex color code in RGB.                     *
-	 * stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb    *
-	 * #parameters:                                                     *
-	 *   hex (string): color code, for example "#33ff99"                *
-	 * #return: (Array) r, g, b, with their correspondent color.        *
-	 * #scope: private                                                  *
-	 ********************************************************************/ 
-	var hexToRgb = function(hex) {
-		var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
-		return result ? {
-			r: parseInt(result[1], 16),
-						g: parseInt(result[2], 16),
-									b: parseInt(result[3], 16)
-		} : null;
-	};
-	
-	/********************************************************************
-	 * Function that checks if a string is a valid hexadecimal color    *
-	 * code, in the format '#ffffff' or '#fff'                          *
-	 * #parameters:                                                     *
-	 *   code (string): Code to check.                                  *
-	 * #return: (Boolean) True if valid color code, false otherwise.    *
-	 * #scope: private                                                  *
-	 ********************************************************************/ 
-	var isColor = function(code){
-		if (code[0] != '#')
-			return false;
-		if (code.length != 4 && code.length != 7)
-			return false
-		for (var i = 1; i < code.length; i ++)
-			if (code[i] < '0' || (code[i] > 9 && code[i] < 'A') || (code[i] > 'Z' && code[i] < 'a') || code[i] > 'z')
-				return false;
-			return true;	
-	};
-	
-	/********************************************************************
-	 * Function that clears the canvas and gets it ready to draw on it. *
-	 * #parameters: none                                                *
-	 * #return: nothing                                                 *
-	 * #scope: private                                                  *
-	 ********************************************************************/
-	var clearCanvas = function(){
-		ctx.clearRect(0, 0, canvas.width, canvas.height);
-		if (dBackg)
-			ctx.fillStyle = backColor;
-		else
-			ctx.fillStyle = "#ffffff";
-		ctx.fillRect(-canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height);
-	};
-	
-	/********************************************************************
-	 * Function initializing the arrays obj, vert and face as empty     *
-	 * arrays.                                                          *
-	 * #parameters: none                                                *
-	 * #return: nothing                                                 *
-	 * #scope: private                                                  *
-	 ********************************************************************/ 
-	var initArrays = function(){
-		material = null;
-		vert = null;
-		face = null;
-		material = new Array();
-		vert = new Array();
-		face = new Array();
-	};
-	
-	/********************************************************************
-	 * Function tat populates the vert[] array with and array of three  *
-	 * elements, containig the coordinates, and the face[] array with   *
-	 * the vertices forming the face, plus one element indicating the   *
-	 * codename of the material.                                        *
-	 * #parameters:                                                     *
-	 *   text (string): the content of the obj file.                    *
-	 * #return: nothing                                                 *
-	 * #scope: private                                                  *
-	 ********************************************************************/ 
-	var readFile = function(text){
-		var line;
-		var v = 0;
-		var f = 0;
-		var m = 0;
-		var max = 0;
-		var j;
-		var dist;
-		var fac;
-		var mat = "null";
-		text = text + "\n";
-		while (text.indexOf("\n") != -1){
-			line = text.substring(0, text.indexOf("\n"));
-			if (line.substring(0, 2) == "v "){
-				vert[v] = new Array(3);
-				line = line.substring(2);
-				vert[v][0] = line.substring(0, line.indexOf(" "));
-				line = line.substring(line.indexOf(" ") + 1);
-				vert[v][1] = line.substring(0, line.indexOf(" "));
-				line = line.substring(line.indexOf(" ") + 1);
-				vert[v][2] = line;
-				
-				dist = Math.sqrt(vert[v][0] * vert[v][0] + vert[v][1] * vert[v][1] + vert[v][2] * vert[v][2]);
-				if (dist > max)
-					max = dist;
-				v = v + 1;
-			}
-			else if (line.substring(0,2) == "f "){
-				line = line.substring(2);
-				face[f] = new Array();
-				j = 0;
-				while(line.indexOf(" ") != -1){
-					face[f][j] = line.substring(0, line.indexOf(" "));
-					if (face[f][j].indexOf('/') != -1)
-						face[f][j] = face[f][j].substring(0, face[f][j].indexOf('/'));
-					face[f][j] = face[f][j] - 1;
-					line = line.substring(line.indexOf(" ") + 1);
-					j = j + 1;
-				}
-				face[f][j] = line;
-				if (face[f][j].indexOf('/') != -1)
-					face[f][j] = face[f][j].substring(0, face[f][j].indexOf('/'));
-				face[f][j] = face[f][j] - 1;
-				face[f][j + 1] = mat;
-				f = f + 1;
-			}
-			else if (line.substring(0, 6) == "usemtl"){
-				mat = line.substring(7);
-			}
-			text = text.substring(text.indexOf("\n") + 1);
-		}
-		scale = calculateScale(max);
-		totalVert = vert.length;
-		totalFace = face.length;
-	};
-	
-	/********************************************************************
-	 * Function tat populates the material[] array with an array        *
-	 * containig, four values: the material name, and the three RGB     *
-	 * values.                                                          *
-	 * #parameters:                                                     *
-	 *   text (string): the content of the mtl file.                    *
-	 * #return: nothing                                                 *
-	 * #scope: private                                                  *
-	 ********************************************************************/ 
-	var readMtlFile = function(text){
-		text = text + "\n";
-		i = -1;
-		while (text.indexOf("\n") != -1){
-			line = text.substring(0, text.indexOf("\n"));
-			if (line.substring(0, 6) == "newmtl"){
-				i = i + 1;
-				material[i] = new Array(4);
-				material[i][0] = line.substring(line.indexOf(" ") + 1);
-			}
-			//Kd, ddifuse color, usefull
-			//Ka, ambient color, not now
-			//Ks, specular color, not now
-			//d or TR, transparency, not now
-			else if (line.substring(0, 3) == "Kd "){
-				line = line.substring(3);
-				material[i][1] = line.substring(0, line.indexOf(" "));
-				line = line.substring(line.indexOf(" ") + 1);
-				material[i][2] = line.substring(0, line.indexOf(" "));
-				line = line.substring(line.indexOf(" ") + 1);
-				material[i][3] = line;
-			}
-			text = text.substring(text.indexOf("\n") + 1);
-		}
-		totalMaterial = material.length;
-		if (totalMaterial == 0)
-			hasMtl = false;
-	};
-	
-	/********************************************************************
-	 * Function that automatically calculates the best scale for the    *
-	 * modelermined number of elements, containing the verices that     *
-	 * form a face, so the bigest dimension from the object can fit in  *
-	 * the smallest dimension of the canvas.                            *
-	 * #parameters:                                                     *
-	 *   text (int): the farthest vertex, from the center.              *
-	 * #return: (int) The scale to be aplied.                           *
-	 * #scope: private                                                  *
-	 ********************************************************************/ 
-	var calculateScale = function(max){
-		var dim;
-		if (canvas.width < canvas.height)
-			dim = canvas.width;
-		else
-			dim = canvas.height;
-		var sc = Math.round((0.95 * dim) / (2 * max));
-		return sc;
-	};
-	
-	/********************************************************************
-	 * Function that compares the average Z coordinate of two faces.    *
-	 * Must be used when sorting the face array.                        *
-	 * #parameters:                                                     *
-	 *   a (Array): One face.                                           *
-	 *   b (Array): The other face.                                     *
-	 * #return: (int) -1, 1 or 0.                                       *
-	 * #scope: private                                                  *
-	 ********************************************************************/ 
-	var faceComparator = function(a,b){
-		var aZ;
-		var bZ;
-		var i = 0;
-		var sum = 0.0;
-		while (i < a.length - 1){
-			sum = sum + parseFloat(vert[a[i]][2]);
-			i = i + 1;
-		}
-		aZ = sum / parseFloat(i);
-		i = 0;
-		sum = 0;
-		while (i < b.length - 1){
-			sum = sum + parseFloat(1 * vert[b[i]][2]);
-			i = i + 1;
-		}
-		bZ = sum / parseFloat(i);
-		if (aZ < bZ) return -1;
-		if (aZ > bZ) return 1;
-		return 0;
-	};
-	
-	/********************************************************************
-	 * Function that writes text in the corner of the canvas. Must be   *
-	 * called when everithing has been drawn.                           *
-	 * #parameters: none                                                *
-	 * #return: nothing                                                 *
-	 * #scope: private                                                  *
-	 ********************************************************************/
-	var writeCredits = function(){
-		ctx.fillStyle = textColor;
-		ctx.font = "12px Arial";
-		var h = canvas.height / 2 - 14;
-		var w = 10 - (canvas.width / 2);
-		ctx.fillText("ObJS:   " + totalVert + " vertices   " + totalFace + " faces   " + totalMaterial + " materials", w, h);
-	};
-	
-	/********************************************************************
-	 * Function that draws th vertices, faces and edges in the canvas.  *
-	 * #parameters: none                                                *
-	 * #return: nothing                                                 *
-	 * #scope: private                                                  *
-	 ********************************************************************/
-	var draw = function(){
-		face = face.sort(faceComparator).reverse();
-		clearCanvas();
-		for (var i = 0; i < face.length; i++){
-			ctx.strokeStyle = edgeColor;
-			ctx.fillStyle = vertColor;
-			ctx.beginPath();
-			ctx.moveTo(scale * vert[face[i][0]][0], scale * vert[face[i][0]][1]);
-			for (var j = 1; j < face[i].length - 1; j++) {
-				ctx.lineTo(scale * vert[face[i][j]][0], scale * vert[face[i][j]][1]);
-				if(dEdges)
-					ctx.stroke();
-				if(dVerts){
-					var x = scale * vert[face[i][j]][0] - (vertSize / 2);
-					var w = vertSize;
-					var y = scale * vert[face[i][j]][1] - (vertSize / 2);
-					var h = vertSize;
-					ctx.fillRect(x, y, w, h);
-				}
-			}
-			ctx.closePath();
-			if (useMtl){
-				//Get material with the same name as the one in the last element of the face
-				j = 0;
-				while (material[j][0] != face[i][face[i].length - 1] && j < material.length)
-					j = j + 1;
-				if (material[j][0] == face[i][face[i].length - 1])
-					ctx.fillStyle = "rgba(" + Math.round(255 * material[j][1]) + ", " + Math.round(255 * material[j][2]) + ", " + Math.round(255 * material[j][3]) + ", " + faceAlpha + ")";
-				else
-					ctx.fillStyle = faceColor;
-			}
-			else
-				ctx.fillStyle = faceColor;
-			if(dFaces)
-				ctx.fill();
-		}
-		writeCredits();
-	};
-	
-	/********************************************************************
-	 * TODO: Function used when something in the canvas is clicked.     *
-	 * #parameters: none                                                *
-	 * #return: nothing                                                 *
-	 * #scope: private                                                  *
-	 ********************************************************************/
-	var mouseClick = function(){
-	};
-	
-	thisObJS = this;
-	return this;
-}
-
-
-
-
-