Răsfoiți Sursa

Color support by mtl file

Iñigo Valentin 12 ani în urmă
părinte
comite
ba91b9042c
9 a modificat fișierele cu 247 adăugiri și 81 ștergeri
  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
 ====
 
-## 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>
 
@@ -25,14 +25,12 @@ Just include the *ObJS.js* in your project, create a ObJS object, and initalize
 myObJS = new ObJS();
 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*.
 
 Then you can load any obj model by calling
 ```javascript
 myObJS.load(file);
 ```
-Where
 * *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.
 
-To rotate the object, just call
+##### Rotate the object #####
 ```javascript
 myObJS.rotateX(-1); //Rotate along the X edge to the left
 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*).
 
-To zoom in or out the object, call the method
+##### Zoom #####
 ```javascript
 myObJS.zoom("+"); //Zoom in
 myObJS.zoom("-"); //Zoom out
@@ -74,7 +72,6 @@ You can change parameters such as the elements to draw, their color, transparenc
 ```javascript
 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
 	- *'backg'*, for the background.
 	- *'verts'*, for the vertizes.
@@ -86,7 +83,6 @@ Where
 ```javascript
 myObJS.colorElement(keyword, color);
 ```
-Where
 * *keyword* is a character string indicating witch element you want to colorize. Possible values are
 	- *'backg'*, for the background.
 	- *'verts'*, for the vertizes.
@@ -98,19 +94,16 @@ Where
 ```javascript
 myObJS.setAlpha(percent);
 ```
-Where
 * *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);
 ```
-Where
 * *value* is an integer, between 0 and 10. The greater it is, the greater the rotation speed.
 
 ##### Set zoom speed #####
 ```javascript
 myObJS.setZoomSpeed(value);
 ```
-Where
 * *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>
 					Choose a model:
 					<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/monkey.obj">Monkey</option>
 						<option value="obj/bolt.obj">Bolt</option>

+ 2 - 2
obj/cube.mtl

@@ -4,7 +4,7 @@
 newmtl None
 Ns 0
 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
 illum 2

+ 2 - 2
obj/monkey.mtl

@@ -4,7 +4,7 @@
 newmtl None
 Ns 0
 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
 illum 2

+ 2 - 2
obj/multiple.mtl

@@ -4,7 +4,7 @@
 newmtl None
 Ns 0
 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
 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
 Ns 0
 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
 illum 2

+ 115 - 62
script/ObJS.js

@@ -51,13 +51,13 @@ function ObJS(file, canv){
 	 * Variables containing the number of elements.                     *
 	 ********************************************************************/ 
 	var totalVert;
-	var totalEdge;//TODO: I dont know how to calculate. And I dont need it
+	var totalMaterial;
 	var totalFace
 	
 	/********************************************************************
-	 * Arrays containing the vertices, edges and faces.                 *
+	 * Arrays containing the vertices, faces and materials.             *
 	 ********************************************************************/ 
-	var obj; //Unused
+	var material;
 	var vert;
 	var face;
 	
@@ -69,6 +69,11 @@ function ObJS(file, canv){
 	var dFaces = 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  *
 	 * the previous frame to calculate rotation.                        *
@@ -140,14 +145,20 @@ function ObJS(file, canv){
 	 * #scope: public                                                   *
 	 ********************************************************************/
 	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();
 		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();
-		readVerts(fileContent);
-		readFaces(fileContent);
+		readFile(fileContent);
+		readMtlFile(mtlContent);
 		draw();
 	};
 	
@@ -347,44 +358,106 @@ function ObJS(file, canv){
 	 * #scope: private                                                  *
 	 ********************************************************************/ 
 	var initArrays = function(){
-		obj =  null;
+		material = null;
 		vert = null;
 		face = null;
-		obj =  new Array();
+		material = new Array();
 		vert = new Array();
 		face = new Array();
 	};
 	
 	/********************************************************************
 	 * 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:                                                     *
 	 *   text (string): the content of the obj file.                    *
 	 * #return: nothing                                                 *
 	 * #scope: private                                                  *
 	 ********************************************************************/ 
-	var readVerts = function(text){
+	var readFile = function(text){
 		var line;
-		var i = 0;
+		var v = 0;
+		var f = 0;
+		var m = 0;
 		var max = 0;
+		var j;
 		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);
 		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;
 	};
 	
-	/********************************************************************
-	 * 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.    *
 	 * Must be used when sorting the face array.                        *
@@ -452,14 +494,14 @@ function ObJS(file, canv){
 		var bZ;
 		var i = 0;
 		var sum = 0.0;
-		while (i < a.length){
+		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){
+		while (i < b.length - 1){
 			sum = sum + parseFloat(1 * vert[b[i]][2]);
 			i = i + 1;
 		}
@@ -498,7 +540,7 @@ function ObJS(file, canv){
 			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; 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]);
 				if(dEdges)
 					ctx.stroke();
@@ -511,7 +553,18 @@ function ObJS(file, canv){
 				}
 			}
 			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)
 				ctx.fill();
 		}