ObJS.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /********************************************************************
  2. * Parameters used all along the script. Only for *
  3. * customization. *
  4. ********************************************************************/
  5. var backColor = "rgba(200, 200, 200, 1)";
  6. var vertColor = "rgba(10, 10, 10, 1)";
  7. var edgeColor = "rgba(100, 70, 70, 1)";
  8. var faceColor = "rgba(180, 180, 255, .6)";
  9. var textColor = "rgba(0, 0, 0, 1)";
  10. var vertSize = 4; //Make it even: at small scales will look better
  11. var rotationSpeed = 100; //Smaller = faster. 100 is a good speed
  12. /********************************************************************
  13. * Parameters used to scale the measures in the .obj file. Can be *
  14. * integer or float, greater than 0 *
  15. * TODO: Must be automatically calculated according to the canvas *
  16. * dimensions, so the bigest dimension from the object can fit in *
  17. * the smallest dimension of the canvas. *
  18. ********************************************************************/
  19. var scale;// = 50;
  20. /********************************************************************
  21. * Global variable to determine if the mouse button is being holded *
  22. * down. *
  23. ********************************************************************/
  24. var mDown = false;
  25. /********************************************************************
  26. * Global variables containing the canvas and its context. *
  27. ********************************************************************/
  28. var canvas;
  29. var ctx;
  30. /********************************************************************
  31. * Global variables containing the number of elements. *
  32. ********************************************************************/
  33. var totalVert;
  34. var totalEdge;//TODO: I dont know how to calculate
  35. var totalFace
  36. /********************************************************************
  37. * Arrays containing the vertices, edges and faces. *
  38. ********************************************************************/
  39. var obj; //Unused
  40. var vert;
  41. var face;
  42. /********************************************************************
  43. * Array containing the order the veres and faces. *
  44. ********************************************************************/
  45. var order;
  46. /********************************************************************
  47. * Booleans to determine wich elements are to draw. *
  48. ********************************************************************/
  49. var dVerts = true;
  50. var dEdges = true;
  51. var dFaces = true;
  52. /********************************************************************
  53. * Global variables that will contain the position of the mouse in *
  54. * the previous frame to calculate rotation. *
  55. ********************************************************************/
  56. var pX = null;
  57. var pY = null;
  58. /********************************************************************
  59. * Function switching the elements to draw (dVerts, dEdges, dFaces) *
  60. * #parameters: *
  61. * name (string): key to the element to draw. *
  62. * value (boolean): indicating if the element is to be drawn. *
  63. * #return: nothing *
  64. ********************************************************************/
  65. function drawElement(name, value){
  66. switch (name){
  67. case "verts":
  68. dVerts = value;
  69. break;
  70. case "edges":
  71. dEdges = value;
  72. break;
  73. case "faces":
  74. dFaces = value;
  75. break;
  76. }
  77. draw();
  78. }
  79. /********************************************************************
  80. * Main function, called every time a file is to be loaded. *
  81. * #parameters: *
  82. * val (string): name of the file, without path or extension. *
  83. * #return: nothing *
  84. ********************************************************************/
  85. function loadModel(val){
  86. //Get file
  87. xmlhttp = new XMLHttpRequest();
  88. xmlhttp.open("GET","/obj/" + val.value + ".obj", false);
  89. xmlhttp.send();
  90. var fileContent = xmlhttp.responseText;
  91. initArrays();
  92. if (canvas == null)
  93. initCanvas();
  94. readVerts(fileContent);
  95. readFaces(fileContent);
  96. draw();
  97. }
  98. /********************************************************************
  99. * Function initializing the arrays obj, vert and face as empty *
  100. * arrays. *
  101. * #parameters: none *
  102. * #return: nothing *
  103. ********************************************************************/
  104. function initArrays(){
  105. obj = null;
  106. vert = null;
  107. face = null;
  108. obj = new Array();
  109. vert = new Array();
  110. face = new Array();
  111. }
  112. /********************************************************************
  113. * Function tat populates the vert[] array with and array of three *
  114. * elements, containig the coordinates, with the scale applied. *
  115. * #parameters: *
  116. * text (string): the content of the obj file. *
  117. * #return: nothing *
  118. ********************************************************************/
  119. function readVerts(text){
  120. var line;
  121. var i = 0;
  122. var max = 0;
  123. var dist;
  124. while (text.indexOf("v ") != -1){
  125. line = text.substring(text.indexOf("v "), text.indexOf("\n", text.indexOf("v ")));
  126. vert[i] = new Array(3);
  127. line = line.substring(2);
  128. vert[i][0] = line.substring(0, line.indexOf(" "));
  129. line = line.substring(line.indexOf(" ") + 1);
  130. vert[i][1] = line.substring(0, line.indexOf(" "));
  131. line = line.substring(line.indexOf(" ") + 1);
  132. vert[i][2] = line;
  133. text = text.substring(text.indexOf("v ") + 1)
  134. dist = Math.sqrt(vert[i][0] * vert[i][0] + vert[i][1] * vert[i][1] + vert[i][2] * vert[i][2]);
  135. if (dist > max)
  136. max = dist;
  137. i = i + 1;
  138. }
  139. scale = calculateScale(max);
  140. totalVert = vert.length;
  141. }
  142. /********************************************************************
  143. * Function that automatically calculates the best scale for the *
  144. * modelermined number of elements, containing the verices that *
  145. * form a face, so the bigest dimension from the object can fit in *
  146. * the smallest dimension of the canvas. *
  147. * #parameters: *
  148. * text (int): the farthest vertex, from the center. *
  149. * #return: (int) The scale to be aplied. *
  150. ********************************************************************/
  151. function calculateScale(max){
  152. var dim;
  153. if (canvas.width < canvas.height)
  154. dim = canvas.width;
  155. else
  156. dim = canvas.height;
  157. var sc = Math.round((0.95 * dim) / (2 * max));
  158. return sc;
  159. }
  160. /********************************************************************
  161. * Function that populates the face[] array with and array of an *
  162. * undetermined number of elements, containing the verices that *
  163. * form a face. *
  164. * #parameters: *
  165. * text (string): the content of the obj file. *
  166. * #return: nothing *
  167. ********************************************************************/
  168. function readFaces(text){
  169. var finish = false;
  170. var line;
  171. var i = 0;
  172. var j;
  173. while (text.indexOf("f ") != -1){
  174. line = text.substring(text.indexOf("f "), text.indexOf("\n", text.indexOf("f ")));
  175. line = line.substring(2);
  176. face[i] = new Array();
  177. j = 0;
  178. while(line.indexOf(" ") != -1){
  179. face[i][j] = line.substring(0, line.indexOf(" ")) - 1;
  180. line = line.substring(line.indexOf(" ") + 1);
  181. j = j + 1;
  182. }
  183. face[i][j] = line - 1;
  184. i = i + 1;
  185. text = text.substring(text.indexOf("f ") + 1)
  186. }
  187. totalFace = face.length;
  188. }
  189. /********************************************************************
  190. * Function that compares the average Z coordinate of two faces. *
  191. * Must be used when sorting the face array. *
  192. * #parameters: *
  193. * a (Array): One face. *
  194. * b (Array): The other face. *
  195. * #return: (int) -1, 1 or 0. *
  196. ********************************************************************/
  197. function faceComparator(a,b){
  198. var aZ;
  199. var bZ;
  200. var i = 0;
  201. var sum = 0.0;
  202. while (i < a.length){
  203. sum = sum + parseFloat(vert[a[i]][2]);
  204. i = i + 1;
  205. }
  206. aZ = sum / parseFloat(i);
  207. i = 0;
  208. sum = 0;
  209. while (i < b.length){
  210. sum = sum + parseFloat(1 * vert[b[i]][2]);
  211. i = i + 1;
  212. }
  213. bZ = sum / parseFloat(i);
  214. if (aZ < bZ) return -1;
  215. if (aZ > bZ) return 1;
  216. return 0;
  217. }
  218. /********************************************************************
  219. * Function that writes text in the corner of the canvas. Must be *
  220. * called when everithing has been drawn. *
  221. * #parameters: none *
  222. * #return: nothing *
  223. ********************************************************************/
  224. function writeCredits(){
  225. ctx.fillStyle = textColor;
  226. ctx.font = "12px Arial";
  227. var h = canvas.height / 2 - 14;
  228. var w = 10 - (canvas.height / 2);
  229. ctx.fillText("ObJS " + totalVert + " vertizes " + totalFace + " faces", w, h);
  230. }
  231. /********************************************************************
  232. * Function that draws th vertizes, faces and edges in the canvas. *
  233. * #parameters: none *
  234. * #return: nothing *
  235. ********************************************************************/
  236. function draw(){
  237. face = face.sort(faceComparator).reverse();
  238. clearCanvas();
  239. for (var i = 0; i < face.length; i++){
  240. ctx.strokeStyle = edgeColor;
  241. ctx.fillStyle = vertColor;
  242. ctx.beginPath();
  243. ctx.moveTo(scale * vert[face[i][0]][0], scale * vert[face[i][0]][1]);
  244. for (var j = 1; j < face[i].length; j++) {
  245. ctx.lineTo(scale * vert[face[i][j]][0], scale * vert[face[i][j]][1]);
  246. if(dEdges)
  247. ctx.stroke();
  248. if(dVerts){
  249. var x = scale * vert[face[i][j]][0] - (vertSize / 2);
  250. var w = vertSize;
  251. var y = scale * vert[face[i][j]][1] - (vertSize / 2);
  252. var h = vertSize;
  253. ctx.fillRect(x, y, w, h);
  254. }
  255. }
  256. ctx.closePath();
  257. ctx.fillStyle = faceColor;
  258. if(dFaces)
  259. ctx.fill();
  260. }
  261. writeCredits();
  262. }
  263. /********************************************************************
  264. * Function that rotates elements in the canvas along the Y axis, *
  265. * calculating the new position for each vertex in the vert array. *
  266. * #parameters: *
  267. * des (int): mouse displacement from the last frame. *
  268. * #return: nothing *
  269. ********************************************************************/
  270. function rotateY(des) {
  271. for (var i = 0; i < vert.length; i ++) {
  272. var x = vert[i][0];
  273. var z = vert[i][2];
  274. vert[i][0] = x * Math.cos(des / rotationSpeed) - z * Math.sin(des / rotationSpeed);
  275. vert[i][2] = z * Math.cos(des / rotationSpeed) + x * Math.sin(des / rotationSpeed);
  276. }
  277. };
  278. /********************************************************************
  279. * Function that rotates elements in the canvas along the X axis, *
  280. * calculating the new position for each vertex in the vert array. *
  281. * #parameters: *
  282. * des (int): mouse displacement from the last frame. *
  283. * #return: nothing *
  284. ********************************************************************/
  285. function rotateX(des) {
  286. for (var i = 0; i < vert.length; i ++) {
  287. var y = vert[i][1];
  288. var z = vert[i][2];
  289. vert[i][1] = y * Math.cos(des / rotationSpeed) - z * Math.sin(des / rotationSpeed);
  290. vert[i][2] = z * Math.cos(des / rotationSpeed) + y * Math.sin(des / rotationSpeed);
  291. }
  292. };
  293. /********************************************************************
  294. * Function that initializes the canvas, assignin it to the HTML *
  295. * element, and set the required mouse events. *
  296. * #parameters: none *
  297. * #return: nothing *
  298. ********************************************************************/
  299. function initCanvas(){
  300. canvas = document.getElementById("ObJSCanvas");
  301. ctx = canvas.getContext("2d");
  302. ctx.translate(canvas.width / 2, canvas.height / 2);
  303. canvas.onmousedown = function(e){
  304. pX = e.offsetX==undefined?e.layerX:e.offsetX;
  305. pY = e.offsetY==undefined?e.layerY:e.offsetY;
  306. mDown = true;
  307. }
  308. canvas.onmouseup = function(e){
  309. if(mDown)
  310. mouseClick(e);
  311. pX = null;
  312. pY = null;
  313. mDown = false;
  314. }
  315. canvas.onmousemove = function(e){
  316. if(!mDown)
  317. return;
  318. var x = e.offsetX==undefined?e.layerX:e.offsetX;
  319. var y = e.offsetY==undefined?e.layerY:e.offsetY;
  320. rotateY(x - pX);
  321. rotateX(y - pY);
  322. pX = x;
  323. pY = y;
  324. draw();
  325. return false;
  326. }
  327. }
  328. /********************************************************************
  329. * Function that clears the canvas and gets it ready to draw on it. *
  330. * #parameters: none *
  331. * #return: nothing *
  332. ********************************************************************/
  333. function clearCanvas(){
  334. ctx.clearRect(0, 0, canvas.width, canvas.height);
  335. ctx.fillStyle = backColor;
  336. ctx.fillRect(-canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height);
  337. }
  338. /********************************************************************
  339. * TODO: Function used when something in the canvas is clicked. *
  340. * #parameters: none *
  341. * #return: nothing *
  342. ********************************************************************/
  343. function mouseClick(){
  344. }