Mercurial > hg > Members > e085711
comparison webGL/dandy/resources/#utils3d.js# @ 7:4343c1feedb5
upload boss.js xmlAlpha file
author | NOBUYASU Oshiro |
---|---|
date | Mon, 05 Jul 2010 17:19:51 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
6:881478004f18 | 7:4343c1feedb5 |
---|---|
1 /* | |
2 * Copyright (C) 2009 Apple Inc. All Rights Reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions | |
6 * are met: | |
7 * 1. Redistributions of source code must retain the above copyright | |
8 * notice, this list of conditions and the following disclaimer. | |
9 * 2. Redistributions in binary form must reproduce the above copyright | |
10 * notice, this list of conditions and the following disclaimer in the | |
11 * documentation and/or other materials provided with the distribution. | |
12 * | |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | |
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 */ | |
25 | |
26 // | |
27 // initWebGL | |
28 // | |
29 // Initialize the Canvas element with the passed name as a WebGL object and return the | |
30 // WebGLRenderingContext. | |
31 // | |
32 // Load shaders with the passed names and create a program with them. Return this program | |
33 // in the 'program' property of the returned context. | |
34 // | |
35 // For each string in the passed attribs array, bind an attrib with that name at that index. | |
36 // Once the attribs are bound, link the program and then use it. | |
37 // | |
38 // Set the clear color to the passed array (4 values) and set the clear depth to the passed value. | |
39 // Enable depth testing and blending with a blend func of (SRC_ALPHA, ONE_MINUS_SRC_ALPHA) | |
40 // | |
41 // A console function is added to the context: console(string). This can be replaced | |
42 // by the caller. By default, it maps to the window.console() function on WebKit and to | |
43 // an empty function on other browsers. | |
44 // | |
45 function initWebGL(canvasName, vshader, fshader, attribs, clearColor, clearDepth) | |
46 { | |
47 var canvas = document.getElementById(canvasName); | |
48 var gl = canvas.getContext("experimental-webgl"); | |
49 if (!gl) { | |
50 alert("No WebGL context found"); | |
51 return null; | |
52 } | |
53 | |
54 // Add a console | |
55 gl.console = ("console" in window) ? window.console : { log: function() { } }; | |
56 | |
57 // create our shaders | |
58 var vertexShader = loadShader(gl, vshader); | |
59 var fragmentShader = loadShader(gl, fshader); | |
60 | |
61 if (!vertexShader || !fragmentShader) | |
62 return null; | |
63 | |
64 // Create the program object | |
65 gl.program = gl.createProgram(); | |
66 | |
67 if (!gl.program) | |
68 return null; | |
69 | |
70 // Attach our two shaders to the program | |
71 gl.attachShader (gl.program, vertexShader); | |
72 gl.attachShader (gl.program, fragmentShader); | |
73 | |
74 // Bind attributes | |
75 for (var i in attribs) | |
76 gl.bindAttribLocation (gl.program, i, attribs[i]); | |
77 | |
78 // Link the program | |
79 gl.linkProgram(gl.program); | |
80 | |
81 // Check the link status | |
82 var linked = gl.getProgramParameter(gl.program, gl.LINK_STATUS); | |
83 if (!linked) { | |
84 // something went wrong with the link | |
85 var error = gl.getProgramInfoLog (gl.program); | |
86 gl.console.log("Error in program linking:"+error); | |
87 | |
88 gl.deleteProgram(gl.program); | |
89 gl.deleteProgram(fragmentShader); | |
90 gl.deleteProgram(vertexShader); | |
91 | |
92 return null; | |
93 } | |
94 | |
95 gl.useProgram(gl.program); | |
96 | |
97 gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); | |
98 gl.clearDepth(clearDepth); | |
99 | |
100 // gl.enable(gl.DEPTH_TEST); | |
101 gl.enable(gl.BLEND); | |
102 gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); | |
103 | |
104 return gl; | |
105 } | |
106 | |
107 // | |
108 // loadShader | |
109 // | |
110 // 'shaderId' is the id of a <script> element containing the shader source string. | |
111 // Load this shader and return the WebGLShader object corresponding to it. | |
112 // | |
113 function loadShader(ctx, shaderId) | |
114 { | |
115 var shaderScript = document.getElementById(shaderId); | |
116 if (!shaderScript) { | |
117 ctx.console.log("*** Error: shader script '"+shaderId+"' not found"); | |
118 return null; | |
119 } | |
120 | |
121 if (shaderScript.type == "x-shader/x-vertex") | |
122 var shaderType = ctx.VERTEX_SHADER; | |
123 else if (shaderScript.type == "x-shader/x-fragment") | |
124 var shaderType = ctx.FRAGMENT_SHADER; | |
125 else { | |
126 ctx.console.log("*** Error: shader script '"+shaderId+"' of undefined type '"+shaderScript.type+"'"); | |
127 return null; | |
128 } | |
129 | |
130 // Create the shader object | |
131 var shader = ctx.createShader(shaderType); | |
132 if (shader == null) { | |
133 ctx.console.log("*** Error: unable to create shader '"+shaderId+"'"); | |
134 return null; | |
135 } | |
136 | |
137 // Load the shader source | |
138 ctx.shaderSource(shader, shaderScript.text); | |
139 | |
140 // Compile the shader | |
141 ctx.compileShader(shader); | |
142 | |
143 // Check the compile status | |
144 var compiled = ctx.getShaderParameter(shader, ctx.COMPILE_STATUS); | |
145 if (!compiled) { | |
146 // Something went wrong during compilation; get the error | |
147 var error = ctx.getShaderInfoLog(shader); | |
148 ctx.console.log("*** Error compiling shader '"+shaderId+"':"+error); | |
149 ctx.deleteShader(shader); | |
150 return null; | |
151 } | |
152 | |
153 return shader; | |
154 } | |
155 | |
156 // | |
157 // makeBox | |
158 // | |
159 // Create a box with vertices, normals and texCoords. Create VBOs for each as well as the index array. | |
160 // Return an object with the following properties: | |
161 // | |
162 // normalObject WebGLBuffer object for normals | |
163 // texCoordObject WebGLBuffer object for texCoords | |
164 // vertexObject WebGLBuffer object for vertices | |
165 // indexObject WebGLBuffer object for indices | |
166 // numIndices The number of indices in the indexObject | |
167 // | |
168 function makeBox(ctx) | |
169 { | |
170 // box | |
171 // v6----- v5 | |
172 // /| /| | |
173 // v1------v0| | |
174 // | | | | | |
175 // | |v7---|-|v4 | |
176 // |/ |/ | |
177 // v2------v3 | |
178 // | |
179 // vertex coords array | |
180 var vertices = new WebGLFloatArray( | |
181 [ 1, 1, 1, -1, 1, 1, -1,-1, 1, 1,-1, 1, // v0-v1-v2-v3 front | |
182 1, 1, 1, 1,-1, 1, 1,-1,-1, 1, 1,-1, // v0-v3-v4-v5 right | |
183 1, 1, 1, 1, 1,-1, -1, 1,-1, -1, 1, 1, // v0-v5-v6-v1 top | |
184 -1, 1, 1, -1, 1,-1, -1,-1,-1, -1,-1, 1, // v1-v6-v7-v2 left | |
185 -1,-1,-1, 1,-1,-1, 1,-1, 1, -1,-1, 1, // v7-v4-v3-v2 bottom | |
186 1,-1,-1, -1,-1,-1, -1, 1,-1, 1, 1,-1 ] // v4-v7-v6-v5 back | |
187 ); | |
188 | |
189 // normal array | |
190 var normals = new WebGLFloatArray( | |
191 [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // v0-v1-v2-v3 front | |
192 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0-v3-v4-v5 right | |
193 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // v0-v5-v6-v1 top | |
194 -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // v1-v6-v7-v2 left | |
195 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, // v7-v4-v3-v2 bottom | |
196 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1 ] // v4-v7-v6-v5 back | |
197 ); | |
198 | |
199 | |
200 // texCoord array | |
201 var texCoords = new WebGLFloatArray( | |
202 [ 1, 1, 0, 1, 0, 0, 1, 0, // v0-v1-v2-v3 front | |
203 0, 1, 0, 0, 1, 0, 1, 1, // v0-v3-v4-v5 right | |
204 1, 0, 1, 1, 0, 1, 0, 0, // v0-v5-v6-v1 top | |
205 1, 1, 0, 1, 0, 0, 1, 0, // v1-v6-v7-v2 left | |
206 0, 0, 1, 0, 1, 1, 0, 1, // v7-v4-v3-v2 bottom | |
207 0, 0, 1, 0, 1, 1, 0, 1 ] // v4-v7-v6-v5 back | |
208 ); | |
209 | |
210 // index array | |
211 var indices = new WebGLUnsignedByteArray( | |
212 [ 0, 1, 2, 0, 2, 3, // front | |
213 4, 5, 6, 4, 6, 7, // right | |
214 8, 9,10, 8,10,11, // top | |
215 12,13,14, 12,14,15, // left | |
216 16,17,18, 16,18,19, // bottom | |
217 20,21,22, 20,22,23 ] // back | |
218 ); | |
219 | |
220 var retval = { }; | |
221 | |
222 retval.normalObject = ctx.createBuffer(); | |
223 ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.normalObject); | |
224 ctx.bufferData(ctx.ARRAY_BUFFER, normals, ctx.STATIC_DRAW); | |
225 | |
226 retval.texCoordObject = ctx.createBuffer(); | |
227 ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.texCoordObject); | |
228 ctx.bufferData(ctx.ARRAY_BUFFER, texCoords, ctx.STATIC_DRAW); | |
229 | |
230 retval.vertexObject = ctx.createBuffer(); | |
231 ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.vertexObject); | |
232 ctx.bufferData(ctx.ARRAY_BUFFER, vertices, ctx.STATIC_DRAW); | |
233 | |
234 ctx.bindBuffer(ctx.ARRAY_BUFFER, null); | |
235 | |
236 retval.indexObject = ctx.createBuffer(); | |
237 ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, retval.indexObject); | |
238 ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, indices, ctx.STATIC_DRAW); | |
239 ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, null); | |
240 | |
241 retval.numIndices = indices.length; | |
242 | |
243 return retval; | |
244 } | |
245 | |
246 // | |
247 // makeSphere | |
248 // | |
249 // Create a sphere with the passed number of latitude and longitude bands and the passed radius. | |
250 // Sphere has vertices, normals and texCoords. Create VBOs for each as well as the index array. | |
251 // Return an object with the following properties: | |
252 // | |
253 // normalObject WebGLBuffer object for normals | |
254 // texCoordObject WebGLBuffer object for texCoords | |
255 // vertexObject WebGLBuffer object for vertices | |
256 // indexObject WebGLBuffer object for indices | |
257 // numIndices The number of indices in the indexObject | |
258 // | |
259 function makeSphere(ctx, radius, lats, longs) | |
260 { | |
261 var geometryData = [ ]; | |
262 var normalData = [ ]; | |
263 var texCoordData = [ ]; | |
264 var indexData = [ ]; | |
265 | |
266 for (var latNumber = 0; latNumber <= lats; ++latNumber) { | |
267 for (var longNumber = 0; longNumber <= longs; ++longNumber) { | |
268 var theta = latNumber * Math.PI / lats; | |
269 var phi = longNumber * 2 * Math.PI / longs; | |
270 var sinTheta = Math.sin(theta); | |
271 var sinPhi = Math.sin(phi); | |
272 var cosTheta = Math.cos(theta); | |
273 var cosPhi = Math.cos(phi); | |
274 | |
275 var x = cosPhi * sinTheta; | |
276 var y = cosTheta; | |
277 var z = sinPhi * sinTheta; | |
278 var u = 1-(longNumber/longs); | |
279 var v = latNumber/lats; | |
280 | |
281 normalData.push(x); | |
282 normalData.push(y); | |
283 normalData.push(z); | |
284 texCoordData.push(u); | |
285 texCoordData.push(v); | |
286 geometryData.push(radius * x); | |
287 geometryData.push(radius * y); | |
288 geometryData.push(radius * z); | |
289 } | |
290 } | |
291 | |
292 for (var latNumber = 0; latNumber < lats; ++latNumber) { | |
293 for (var longNumber = 0; longNumber < longs; ++longNumber) { | |
294 var first = (latNumber * (longs+1)) + longNumber; | |
295 var second = first + longs + 1; | |
296 indexData.push(first); | |
297 indexData.push(second); | |
298 indexData.push(first+1); | |
299 | |
300 indexData.push(second); | |
301 indexData.push(second+1); | |
302 indexData.push(first+1); | |
303 } | |
304 } | |
305 | |
306 var retval = { }; | |
307 | |
308 retval.normalObject = ctx.createBuffer(); | |
309 ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.normalObject); | |
310 ctx.bufferData(ctx.ARRAY_BUFFER, new WebGLFloatArray(normalData), ctx.STATIC_DRAW); | |
311 | |
312 retval.texCoordObject = ctx.createBuffer(); | |
313 ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.texCoordObject); | |
314 ctx.bufferData(ctx.ARRAY_BUFFER, new WebGLFloatArray(texCoordData), ctx.STATIC_DRAW); | |
315 | |
316 retval.vertexObject = ctx.createBuffer(); | |
317 ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.vertexObject); | |
318 ctx.bufferData(ctx.ARRAY_BUFFER, new WebGLFloatArray(geometryData), ctx.STATIC_DRAW); | |
319 | |
320 retval.numIndices = indexData.length; | |
321 retval.indexObject = ctx.createBuffer(); | |
322 ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, retval.indexObject); | |
323 ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, new WebGLUnsignedShortArray(indexData), ctx.STREAM_DRAW); | |
324 | |
325 return retval; | |
326 } | |
327 | |
328 // | |
329 // loadObj | |
330 // | |
331 // Load a .obj file from the passed URL. Return an object with a 'loaded' property set to false. | |
332 // When the object load is complete, the 'loaded' property becomes true and the following | |
333 // properties are set: | |
334 // | |
335 // normalObject WebGLBuffer object for normals | |
336 // texCoordObject WebGLBuffer object for texCoords | |
337 // vertexObject WebGLBuffer object for vertices | |
338 // indexObject WebGLBuffer object for indices | |
339 // numIndices The number of indices in the indexObject | |
340 // | |
341 function loadObj(ctx, url) | |
342 { | |
343 var obj = { loaded : false }; | |
344 obj.ctx = ctx; | |
345 var req = new XMLHttpRequest(); | |
346 req.obj = obj; | |
347 req.onreadystatechange = function () { processLoadObj(req) }; | |
348 req.open("GET", url, true); | |
349 req.send(null); | |
350 return obj; | |
351 } | |
352 | |
353 function processLoadObj(req) | |
354 { | |
355 req.obj.ctx.console.log("req="+req) | |
356 // only if req shows "complete" | |
357 if (req.readyState == 4) { | |
358 doLoadObj(req.obj, req.responseText); | |
359 } | |
360 } | |
361 | |
362 function doLoadObj(obj, text) | |
363 { | |
364 vertexArray = [ ]; | |
365 normalArray = [ ]; | |
366 textureArray = [ ]; | |
367 indexArray = [ ]; | |
368 | |
369 var vertex = [ ]; | |
370 var normal = [ ]; | |
371 var texture = [ ]; | |
372 var facemap = { }; | |
373 var index = 0; | |
374 | |
375 var lines = text.split("\n"); | |
376 for (var lineIndex in lines) { | |
377 var line = lines[lineIndex].replace(/[ \t]+/g, " ").replace(/\s\s*$/, ""); | |
378 | |
379 // ignore comments | |
380 if (line[0] == "#") | |
381 continue; | |
382 | |
383 var array = line.split(" "); | |
384 if (array[0] == "v") { | |
385 // vertex | |
386 vertex.push(parseFloat(array[1])); | |
387 vertex.push(parseFloat(array[2])); | |
388 vertex.push(parseFloat(array[3])); | |
389 } | |
390 else if (array[0] == "vt") { | |
391 // normal | |
392 texture.push(parseFloat(array[1])); | |
393 texture.push(parseFloat(array[2])); | |
394 } | |
395 else if (array[0] == "vn") { | |
396 // normal | |
397 normal.push(parseFloat(array[1])); | |
398 normal.push(parseFloat(array[2])); | |
399 normal.push(parseFloat(array[3])); | |
400 } | |
401 else if (array[0] == "f") { | |
402 // face | |
403 if (array.length != 4) { | |
404 obj.ctx.console.log("*** Error: face '"+line+"' not handled"); | |
405 continue; | |
406 } | |
407 | |
408 for (var i = 1; i < 4; ++i) { | |
409 if (!(array[i] in facemap)) { | |
410 // add a new entry to the map and arrays | |
411 var f = array[i].split("/"); | |
412 var vtx, nor, tex; | |
413 | |
414 if (f.length == 1) { | |
415 vtx = parseInt(f[0]) - 1; | |
416 nor = vtx; | |
417 tex = vtx; | |
418 } | |
419 else if (f.length = 3) { | |
420 vtx = parseInt(f[0]) - 1; | |
421 tex = parseInt(f[1]) - 1; | |
422 nor = parseInt(f[2]) - 1; | |
423 } | |
424 else { | |
425 obj.ctx.console.log("*** Error: did not understand face '"+array[i]+"'"); | |
426 return null; | |
427 } | |
428 | |
429 // do the vertices | |
430 var x = 0; | |
431 var y = 0; | |
432 var z = 0; | |
433 if (vtx * 3 + 2 < vertex.length) { | |
434 x = vertex[vtx*3]; | |
435 y = vertex[vtx*3+1]; | |
436 z = vertex[vtx*3+2]; | |
437 } | |
438 vertexArray.push(x); | |
439 vertexArray.push(y); | |
440 vertexArray.push(z); | |
441 | |
442 // do the textures | |
443 x = 0; | |
444 y = 0; | |
445 if (tex * 2 + 1 < texture.length) { | |
446 x = texture[tex*2]; | |
447 y = texture[tex*2+1]; | |
448 } | |
449 textureArray.push(x); | |
450 textureArray.push(y); | |
451 | |
452 // do the normals | |
453 x = 0; | |
454 y = 0; | |
455 z = 1; | |
456 if (nor * 3 + 2 < normal.length) { | |
457 x = normal[nor*3]; | |
458 y = normal[nor*3+1]; | |
459 z = normal[nor*3+2]; | |
460 } | |
461 normalArray.push(x); | |
462 normalArray.push(y); | |
463 normalArray.push(z); | |
464 | |
465 facemap[array[i]] = index++; | |
466 } | |
467 | |
468 indexArray.push(facemap[array[i]]); | |
469 } | |
470 } | |
471 } | |
472 | |
473 // set the VBOs | |
474 obj.normalObject = obj.ctx.createBuffer(); | |
475 obj.ctx.bindBuffer(obj.ctx.ARRAY_BUFFER, obj.normalObject); | |
476 obj.ctx.bufferData(obj.ctx.ARRAY_BUFFER, new WebGLFloatArray(normalArray), obj.ctx.STATIC_DRAW); | |
477 | |
478 obj.texCoordObject = obj.ctx.createBuffer(); | |
479 obj.ctx.bindBuffer(obj.ctx.ARRAY_BUFFER, obj.texCoordObject); | |
480 obj.ctx.bufferData(obj.ctx.ARRAY_BUFFER, new WebGLFloatArray(textureArray), obj.ctx.STATIC_DRAW); | |
481 | |
482 obj.vertexObject = obj.ctx.createBuffer(); | |
483 obj.ctx.bindBuffer(obj.ctx.ARRAY_BUFFER, obj.vertexObject); | |
484 obj.ctx.bufferData(obj.ctx.ARRAY_BUFFER, new WebGLFloatArray(vertexArray), obj.ctx.STATIC_DRAW); | |
485 | |
486 obj.numIndices = indexArray.length; | |
487 obj.indexObject = obj.ctx.createBuffer(); | |
488 obj.ctx.bindBuffer(obj.ctx.ELEMENT_ARRAY_BUFFER, obj.indexObject); | |
489 obj.ctx.bufferData(obj.ctx.ELEMENT_ARRAY_BUFFER, new WebGLUnsignedShortArray(indexArray), obj.ctx.STREAM_DRAW); | |
490 | |
491 obj.loaded = true; | |
492 } | |
493 | |
494 // | |
495 // loadImageTexture | |
496 // | |
497 // Load the image at the passed url, place it in a new WebGLTexture object and return the WebGLTexture. | |
498 // | |
499 function loadImageTexture(ctx, url) | |
500 { | |
501 var texture = ctx.createTexture(); | |
502 texture.image = new Image(); | |
503 texture.image.onload = function() { doLoadImageTexture(ctx, texture.image, texture) } | |
504 texture.image.src = url; | |
505 // alert("texture.image.src:"+texture.image.src); | |
506 return texture; | |
507 } | |
508 | |
509 function doLoadImageTexture(ctx, image, texture) | |
510 { | |
511 ctx.bindTexture(ctx.TEXTURE_2D, texture); | |
512 ctx.texImage2D(ctx.TEXTURE_2D, 0, image); | |
513 ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MAG_FILTER, ctx.LINEAR); | |
514 ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.LINEAR); | |
515 ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_S, ctx.CLAMP_TO_EDGE); | |
516 ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_T, ctx.CLAMP_TO_EDGE); | |
517 //ctx.generateMipmap(ctx.TEXTURE_2D) | |
518 ctx.bindTexture(ctx.TEXTURE_2D, null); | |
519 } | |
520 | |
521 // | |
522 // Framerate object | |
523 // | |
524 // This object keeps track of framerate and displays it as the innerHTML text of the | |
525 // HTML element with the passed id. Once created you call snapshot at the end | |
526 // of every rendering cycle. Every 500ms the framerate is updated in the HTML element. | |
527 // | |
528 Framerate = function(id) | |
529 { | |
530 this.numFramerates = 10; | |
531 this.framerateUpdateInterval = 500; | |
532 this.id = id; | |
533 | |
534 this.renderTime = -1; | |
535 this.framerates = [ ]; | |
536 self = this; | |
537 var fr = function() { self.updateFramerate() } | |
538 setInterval(fr, this.framerateUpdateInterval); | |
539 } | |
540 | |
541 Framerate.prototype.updateFramerate = function() | |
542 { | |
543 var tot = 0; | |
544 for (var i = 0; i < this.framerates.length; ++i) | |
545 tot += this.framerates[i]; | |
546 | |
547 var framerate = tot / this.framerates.length; | |
548 framerate = Math.round(framerate); | |
549 document.getElementById(this.id).innerHTML = "Framerate:"+framerate+"fps"; | |
550 } | |
551 | |
552 Framerate.prototype.snapshot = function() | |
553 { | |
554 if (this.renderTime < 0) | |
555 this.renderTime = new Date().getTime(); | |
556 else { | |
557 var newTime = new Date().getTime(); | |
558 var t = newTime - this.renderTime; | |
559 var framerate = 1000/t; | |
560 this.framerates.push(framerate); | |
561 while (this.framerates.length > this.numFramerates) | |
562 this.framerates.shift(); | |
563 this.renderTime = newTime; | |
564 } | |
565 } |