Browse Source

Color support by mtl file

Iñigo Valentin 12 years ago
parent
commit
ba91b9042c
9 changed files with 247 additions and 81 deletions
  1. 3 10
      README.md
  2. 2 1
      index.html
  3. 2 2
      obj/cube.mtl
  4. 2 2
      obj/monkey.mtl
  5. 2 2
      obj/multiple.mtl
  6. 74 0
      obj/rainbow.mtl
  7. 45 0
      obj/rainbow.obj
  8. 2 2
      obj/sphere.mtl
  9. 115 62
      script/ObJS.js

+ 3 - 10
README.md

@@ -1,7 +1,7 @@
 ObJS
 ObJS
 ====
 ====
 
 
-## A .obj files viewer for HTML5 written in JavaScript ###
+## A 3D Wavefront obj file viewer for HTML5 written in JavaScript ###
 
 
 <a href="http://imgur.com/kT7mGoK"><img src="http://i.imgur.com/kT7mGoK.png" title="ObJS - Bolt" /></a>
 <a href="http://imgur.com/kT7mGoK"><img src="http://i.imgur.com/kT7mGoK.png" title="ObJS - Bolt" /></a>
 
 
@@ -25,14 +25,12 @@ Just include the *ObJS.js* in your project, create a ObJS object, and initalize
 myObJS = new ObJS();
 myObJS = new ObJS();
 myObJS.initCanvas(canvas);
 myObJS.initCanvas(canvas);
 ```
 ```
-Where 
 * *canvas* is the canvas element in witch the model will be represented. If this parameter is not specified, the script will try to use a canvas called *ObJSCanvas*.
 * *canvas* is the canvas element in witch the model will be represented. If this parameter is not specified, the script will try to use a canvas called *ObJSCanvas*.
 
 
 Then you can load any obj model by calling
 Then you can load any obj model by calling
 ```javascript
 ```javascript
 myObJS.load(file);
 myObJS.load(file);
 ```
 ```
-Where
 * *file* is a character string with the path to the file, relative or absolute.
 * *file* is a character string with the path to the file, relative or absolute.
 
 
 
 
@@ -48,7 +46,7 @@ Note that the canvas is automatically cleared when a new object is loaded.
 
 
 The model can be rotated and zoomed in and out with the mouse, but it can also be done programmatically.
 The model can be rotated and zoomed in and out with the mouse, but it can also be done programmatically.
 
 
-To rotate the object, just call
+##### Rotate the object #####
 ```javascript
 ```javascript
 myObJS.rotateX(-1); //Rotate along the X edge to the left
 myObJS.rotateX(-1); //Rotate along the X edge to the left
 myObJS.rotateX(1);  //Rotate along the X edge to the right
 myObJS.rotateX(1);  //Rotate along the X edge to the right
@@ -57,7 +55,7 @@ myObJS.rotateY(1);  //Rotate along the Y edge to the right
 ```
 ```
 Note that the rotation speed can be set (see *Seting rotation speed*).
 Note that the rotation speed can be set (see *Seting rotation speed*).
 
 
-To zoom in or out the object, call the method
+##### Zoom #####
 ```javascript
 ```javascript
 myObJS.zoom("+"); //Zoom in
 myObJS.zoom("+"); //Zoom in
 myObJS.zoom("-"); //Zoom out
 myObJS.zoom("-"); //Zoom out
@@ -74,7 +72,6 @@ You can change parameters such as the elements to draw, their color, transparenc
 ```javascript
 ```javascript
 myObJS.drawElement(keyword, on);
 myObJS.drawElement(keyword, on);
 ```
 ```
-Where
 * *keyword* is a character string indicating witch element you want or don't want to be drawn. Possible values are
 * *keyword* is a character string indicating witch element you want or don't want to be drawn. Possible values are
 	- *'backg'*, for the background.
 	- *'backg'*, for the background.
 	- *'verts'*, for the vertizes.
 	- *'verts'*, for the vertizes.
@@ -86,7 +83,6 @@ Where
 ```javascript
 ```javascript
 myObJS.colorElement(keyword, color);
 myObJS.colorElement(keyword, color);
 ```
 ```
-Where
 * *keyword* is a character string indicating witch element you want to colorize. Possible values are
 * *keyword* is a character string indicating witch element you want to colorize. Possible values are
 	- *'backg'*, for the background.
 	- *'backg'*, for the background.
 	- *'verts'*, for the vertizes.
 	- *'verts'*, for the vertizes.
@@ -98,19 +94,16 @@ Where
 ```javascript
 ```javascript
 myObJS.setAlpha(percent);
 myObJS.setAlpha(percent);
 ```
 ```
-Where
 * *percent* is an integer, between 0 and 100, indicating the level of transparency you want to apply to the faces.
 * *percent* is an integer, between 0 and 100, indicating the level of transparency you want to apply to the faces.
 
 
 ##### Set rotation speed #####
 ##### Set rotation speed #####
 ```javascript
 ```javascript
 myObJS.setRotationSpeed(value);
 myObJS.setRotationSpeed(value);
 ```
 ```
-Where
 * *value* is an integer, between 0 and 10. The greater it is, the greater the rotation speed.
 * *value* is an integer, between 0 and 10. The greater it is, the greater the rotation speed.
 
 
 ##### Set zoom speed #####
 ##### Set zoom speed #####
 ```javascript
 ```javascript
 myObJS.setZoomSpeed(value);
 myObJS.setZoomSpeed(value);
 ```
 ```
-Where
 * *value* is an integer, between 0 and 10. The greater it is, the greater the zoom speed.
 * *value* is an integer, between 0 and 10. The greater it is, the greater the zoom speed.

+ 2 - 1
index.html

@@ -18,7 +18,8 @@
 				<td>
 				<td>
 					Choose a model:
 					Choose a model:
 					<select id="objSelector" name="objSelector" onChange="objs.load(this.value)">
 					<select id="objSelector" name="objSelector" onChange="objs.load(this.value)">
-						<option value="obj/cube.obj" selected="selected">Cube</option>
+						<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/sphere.obj">Sphere</option>
 						<option value="obj/monkey.obj">Monkey</option>
 						<option value="obj/monkey.obj">Monkey</option>
 						<option value="obj/bolt.obj">Bolt</option>
 						<option value="obj/bolt.obj">Bolt</option>

+ 2 - 2
obj/cube.mtl

@@ -4,7 +4,7 @@
 newmtl None
 newmtl None
 Ns 0
 Ns 0
 Ka 0.000000 0.000000 0.000000
 Ka 0.000000 0.000000 0.000000
-Kd 0.8 0.8 0.8
-Ks 0.8 0.8 0.8
+Kd 0.8 0.5 0.5
+Ks 0.8 0.5 0.5
 d 1
 d 1
 illum 2
 illum 2

+ 2 - 2
obj/monkey.mtl

@@ -4,7 +4,7 @@
 newmtl None
 newmtl None
 Ns 0
 Ns 0
 Ka 0.000000 0.000000 0.000000
 Ka 0.000000 0.000000 0.000000
-Kd 0.8 0.8 0.8
-Ks 0.8 0.8 0.8
+Kd 0.0 0.8 0.8
+Ks 0.0 0.8 0.8
 d 1
 d 1
 illum 2
 illum 2

+ 2 - 2
obj/multiple.mtl

@@ -4,7 +4,7 @@
 newmtl None
 newmtl None
 Ns 0
 Ns 0
 Ka 0.000000 0.000000 0.000000
 Ka 0.000000 0.000000 0.000000
-Kd 0.8 0.8 0.8
-Ks 0.8 0.8 0.8
+Kd 0.2 0.8 0.9
+Ks 0.2 0.8 0.9
 d 1
 d 1
 illum 2
 illum 2

+ 74 - 0
obj/rainbow.mtl

@@ -0,0 +1,74 @@
+# Blender MTL File: 'None'
+# Material Count: 8
+
+newmtl Blue
+Ns 96.078431
+Ka 0.000000 0.000000 0.000000
+Kd 0.000000 0.632165 0.640000
+Ks 0.500000 0.500000 0.500000
+Ni 1.000000
+d 1.000000
+illum 2
+
+newmtl DBlue
+Ns 96.078431
+Ka 0.000000 0.000000 0.000000
+Kd 0.000000 0.022210 0.640000
+Ks 0.500000 0.500000 0.500000
+Ni 1.000000
+d 1.000000
+illum 2
+
+newmtl Green
+Ns 96.078431
+Ka 0.000000 0.000000 0.000000
+Kd 0.000000 0.640000 0.029176
+Ks 0.500000 0.500000 0.500000
+Ni 1.000000
+d 1.000000
+illum 2
+
+newmtl Orange
+Ns 96.078431
+Ka 0.000000 0.000000 0.000000
+Kd 0.640000 0.177481 0.000000
+Ks 0.500000 0.500000 0.500000
+Ni 1.000000
+d 1.000000
+illum 2
+
+newmtl Red
+Ns 96.078431
+Ka 0.000000 0.000000 0.000000
+Kd 0.640000 0.000000 0.000000
+Ks 0.500000 0.500000 0.500000
+Ni 1.000000
+d 1.000000
+illum 2
+
+newmtl Violet
+Ns 96.078431
+Ka 0.000000 0.000000 0.000000
+Kd 0.341311 0.000000 0.640000
+Ks 0.500000 0.500000 0.500000
+Ni 1.000000
+d 1.000000
+illum 2
+
+newmtl White
+Ns 96.078431
+Ka 0.000000 0.000000 0.000000
+Kd 0.800000 0.800000 0.800000
+Ks 0.500000 0.500000 0.500000
+Ni 1.000000
+d 1.000000
+illum 2
+
+newmtl Yellow
+Ns 96.078431
+Ka 0.000000 0.000000 0.000000
+Kd 0.640000 0.579129 0.000000
+Ks 0.500000 0.500000 0.500000
+Ni 1.000000
+d 1.000000
+illum 2

+ 45 - 0
obj/rainbow.obj

@@ -0,0 +1,45 @@
+# Blender v2.70 (sub 0) OBJ File: ''
+# www.blender.org
+mtllib rainbow.mtl
+o Cone_Cone.001
+v 0.000002 -1.005551 -1.000000
+v -0.000002 -3.005551 0.000000
+v -0.781830 -1.005550 -0.623490
+v -0.974926 -1.005550 0.222521
+v -0.433882 -1.005551 0.900969
+v 0.433885 -1.005552 0.900969
+v 0.974929 -1.005553 0.222521
+v 0.781833 -1.005553 -0.623490
+v 0.781833 1.025846 0.623489
+v 0.974929 1.025848 -0.222521
+v 0.433885 1.025848 -0.900969
+v -0.433882 1.025846 -0.900969
+v -0.974926 1.025845 -0.222521
+v -0.781830 1.025844 0.623489
+v -0.000002 3.025846 0.000002
+v 0.000002 1.025844 1.000000
+usemtl White
+s off
+f 1 3 4 5 6 7 8
+f 16 14 13 12 11 10 9
+usemtl Blue
+f 5 2 6
+f 12 15 11
+usemtl DBlue
+f 6 2 7
+f 11 15 10
+usemtl Violet
+f 7 2 8
+f 10 15 9
+usemtl Red
+f 8 2 1
+f 9 15 16
+usemtl Orange
+f 1 2 3
+f 16 15 14
+usemtl Yellow
+f 3 2 4
+f 14 15 13
+usemtl Green
+f 4 2 5
+f 13 15 12

+ 2 - 2
obj/sphere.mtl

@@ -4,7 +4,7 @@
 newmtl None
 newmtl None
 Ns 0
 Ns 0
 Ka 0.000000 0.000000 0.000000
 Ka 0.000000 0.000000 0.000000
-Kd 0.8 0.8 0.8
-Ks 0.8 0.8 0.8
+Kd 0.5 0.6 0.8
+Ks 0.5 0.6 0.8
 d 1
 d 1
 illum 2
 illum 2

+ 115 - 62
script/ObJS.js

@@ -51,13 +51,13 @@ function ObJS(file, canv){
 	 * Variables containing the number of elements.                     *
 	 * Variables containing the number of elements.                     *
 	 ********************************************************************/ 
 	 ********************************************************************/ 
 	var totalVert;
 	var totalVert;
-	var totalEdge;//TODO: I dont know how to calculate. And I dont need it
+	var totalMaterial;
 	var totalFace
 	var totalFace
 	
 	
 	/********************************************************************
 	/********************************************************************
-	 * Arrays containing the vertices, edges and faces.                 *
+	 * Arrays containing the vertices, faces and materials.             *
 	 ********************************************************************/ 
 	 ********************************************************************/ 
-	var obj; //Unused
+	var material;
 	var vert;
 	var vert;
 	var face;
 	var face;
 	
 	
@@ -69,6 +69,11 @@ function ObJS(file, canv){
 	var dFaces = true;
 	var dFaces = true;
 	var dBackg = true;
 	var dBackg = true;
 	
 	
+	/********************************************************************
+	 * Booleans to indicate if mtl file should be used.                 *
+	 ********************************************************************/
+	var useMtl = true;
+	
 	/********************************************************************
 	/********************************************************************
 	 * Global variables that will contain the position of the mouse in  *
 	 * Global variables that will contain the position of the mouse in  *
 	 * the previous frame to calculate rotation.                        *
 	 * the previous frame to calculate rotation.                        *
@@ -140,14 +145,20 @@ function ObJS(file, canv){
 	 * #scope: public                                                   *
 	 * #scope: public                                                   *
 	 ********************************************************************/
 	 ********************************************************************/
 	this.load = function(file){
 	this.load = function(file){
-		//Get file
-		xmlhttp = new XMLHttpRequest();
-		xmlhttp.open("GET",file, false);
+		//Get obj file
+		var xmlhttp = new XMLHttpRequest();
+		xmlhttp.open("GET", file, false);
 		xmlhttp.send();
 		xmlhttp.send();
 		var fileContent = xmlhttp.responseText;
 		var fileContent = xmlhttp.responseText;
+		//Get mtl file
+		xmlhttp = new XMLHttpRequest();
+		xmlhttp.open("GET",file.substring(0, file.lastIndexOf(".")) + ".mtl", false);
+		console.log("GET" + file.substring(0, file.lastIndexOf(".")) + ".mtl");
+		xmlhttp.send();
+		var mtlContent = xmlhttp.responseText;
 		initArrays();
 		initArrays();
-		readVerts(fileContent);
-		readFaces(fileContent);
+		readFile(fileContent);
+		readMtlFile(mtlContent);
 		draw();
 		draw();
 	};
 	};
 	
 	
@@ -347,44 +358,106 @@ function ObJS(file, canv){
 	 * #scope: private                                                  *
 	 * #scope: private                                                  *
 	 ********************************************************************/ 
 	 ********************************************************************/ 
 	var initArrays = function(){
 	var initArrays = function(){
-		obj =  null;
+		material = null;
 		vert = null;
 		vert = null;
 		face = null;
 		face = null;
-		obj =  new Array();
+		material = new Array();
 		vert = new Array();
 		vert = new Array();
 		face = new Array();
 		face = new Array();
 	};
 	};
 	
 	
 	/********************************************************************
 	/********************************************************************
 	 * Function tat populates the vert[] array with and array of three  *
 	 * Function tat populates the vert[] array with and array of three  *
-	 * elements, containig the coordinates, with the scale applied.     *
+	 * elements, containig the coordinates, and the face[] array with   *
+	 * the vertizes forming the face, plus one element indicating the   *
+	 * codename of the material.                                        *
 	 * #parameters:                                                     *
 	 * #parameters:                                                     *
 	 *   text (string): the content of the obj file.                    *
 	 *   text (string): the content of the obj file.                    *
 	 * #return: nothing                                                 *
 	 * #return: nothing                                                 *
 	 * #scope: private                                                  *
 	 * #scope: private                                                  *
 	 ********************************************************************/ 
 	 ********************************************************************/ 
-	var readVerts = function(text){
+	var readFile = function(text){
 		var line;
 		var line;
-		var i = 0;
+		var v = 0;
+		var f = 0;
+		var m = 0;
 		var max = 0;
 		var max = 0;
+		var j;
 		var dist;
 		var dist;
-		while (text.indexOf("v ") != -1){
-			line = text.substring(text.indexOf("v "), text.indexOf("\n", text.indexOf("v ")));
-			vert[i] = new Array(3);
-			line = line.substring(2);
-			vert[i][0] = line.substring(0, line.indexOf(" "));
-			line = line.substring(line.indexOf(" ") + 1);
-			vert[i][1] = line.substring(0, line.indexOf(" "));
-			line = line.substring(line.indexOf(" ") + 1);
-			vert[i][2] = line;
-			text = text.substring(text.indexOf("v ") + 1)
-			dist = Math.sqrt(vert[i][0] * vert[i][0] + vert[i][1] * vert[i][1] + vert[i][2] * vert[i][2]);
-			if (dist > max)
-				max = dist;
-			i = i + 1;
+		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(" ")) - 1;
+					line = line.substring(line.indexOf(" ") + 1);
+					j = j + 1;
+				}
+				face[f][j] = line - 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);
 		scale = calculateScale(max);
 		totalVert = vert.length;
 		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);
+		}
 	};
 	};
 	
 	
 	/********************************************************************
 	/********************************************************************
@@ -407,37 +480,6 @@ function ObJS(file, canv){
 		return sc;
 		return sc;
 	};
 	};
 	
 	
-	/********************************************************************
-	 * Function that populates the face[] array with and array of an    *
-	 * undetermined number of elements, containing the verices that     *
-	 * form a face.                                                     *
-	 * #parameters:                                                     *
-	 *   text (string): the content of the obj file.                    *
-	 * #return: nothing                                                 *
-	 * #scope: private                                                  *
-	 ********************************************************************/ 
-	var readFaces = function(text){
-		var finish = false;
-		var line;
-		var i = 0;
-		var j;
-		while (text.indexOf("f ") != -1){
-			line = text.substring(text.indexOf("f "), text.indexOf("\n", text.indexOf("f ")));
-			line = line.substring(2);
-			face[i] = new Array();
-			j = 0;
-			while(line.indexOf(" ") != -1){
-				face[i][j] = line.substring(0, line.indexOf(" ")) - 1;
-				line = line.substring(line.indexOf(" ") + 1);
-				j = j + 1;
-			}
-			face[i][j] = line - 1;
-			i = i + 1;
-			text = text.substring(text.indexOf("f ") + 1)	
-		}
-		totalFace = face.length;
-	};
-	
 	/********************************************************************
 	/********************************************************************
 	 * Function that compares the average Z coordinate of two faces.    *
 	 * Function that compares the average Z coordinate of two faces.    *
 	 * Must be used when sorting the face array.                        *
 	 * Must be used when sorting the face array.                        *
@@ -452,14 +494,14 @@ function ObJS(file, canv){
 		var bZ;
 		var bZ;
 		var i = 0;
 		var i = 0;
 		var sum = 0.0;
 		var sum = 0.0;
-		while (i < a.length){
+		while (i < a.length - 1){
 			sum = sum + parseFloat(vert[a[i]][2]);
 			sum = sum + parseFloat(vert[a[i]][2]);
 			i = i + 1;
 			i = i + 1;
 		}
 		}
 		aZ = sum / parseFloat(i);
 		aZ = sum / parseFloat(i);
 		i = 0;
 		i = 0;
 		sum = 0;
 		sum = 0;
-		while (i < b.length){
+		while (i < b.length - 1){
 			sum = sum + parseFloat(1 * vert[b[i]][2]);
 			sum = sum + parseFloat(1 * vert[b[i]][2]);
 			i = i + 1;
 			i = i + 1;
 		}
 		}
@@ -498,7 +540,7 @@ function ObJS(file, canv){
 			ctx.fillStyle = vertColor;
 			ctx.fillStyle = vertColor;
 			ctx.beginPath();
 			ctx.beginPath();
 			ctx.moveTo(scale * vert[face[i][0]][0], scale * vert[face[i][0]][1]);
 			ctx.moveTo(scale * vert[face[i][0]][0], scale * vert[face[i][0]][1]);
-			for (var j = 1; j < face[i].length; j++) {
+			for (var j = 1; j < face[i].length - 1; j++) {
 				ctx.lineTo(scale * vert[face[i][j]][0], scale * vert[face[i][j]][1]);
 				ctx.lineTo(scale * vert[face[i][j]][0], scale * vert[face[i][j]][1]);
 				if(dEdges)
 				if(dEdges)
 					ctx.stroke();
 					ctx.stroke();
@@ -511,7 +553,18 @@ function ObJS(file, canv){
 				}
 				}
 			}
 			}
 			ctx.closePath();
 			ctx.closePath();
-			ctx.fillStyle = faceColor;
+			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)
 			if(dFaces)
 				ctx.fill();
 				ctx.fill();
 		}
 		}