annotate js/bt/other_libs/excanvas_0002/examples/example2.html @ 47:cbfe386cb51b

Add a function to refresh opened libraries. The source URL of each libraries is now tracked, which allows for auto refreshing the libraries based on various events. The obvious use case is to refresh the library when an atom has been added to Scald, for example via a Popups dialog.
author Franck Deroche <defr@ows.fr>
date Mon, 15 Feb 2010 14:08:04 +0000
parents 0d557e6e73f7
children
rev   line source
eads@18 1 <!--
eads@18 2 Copyright 2006 Google Inc.
eads@18 3
eads@18 4 Licensed under the Apache License, Version 2.0 (the "License");
eads@18 5 you may not use this file except in compliance with the License.
eads@18 6 You may obtain a copy of the License at
eads@18 7
eads@18 8 http://www.apache.org/licenses/LICENSE-2.0
eads@18 9
eads@18 10 Unless required by applicable law or agreed to in writing, software
eads@18 11 distributed under the License is distributed on an "AS IS" BASIS,
eads@18 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
eads@18 13 See the License for the specific language governing permissions and
eads@18 14 limitations under the License.
eads@18 15 -->
eads@18 16 <html>
eads@18 17 <head>
eads@18 18 <title>ExplorerCanvas Example 1</title>
eads@18 19 <!--[if IE]><script type="text/javascript" src="../excanvas.js"></script><![endif]-->
eads@18 20 <script type="text/javascript">
eads@18 21 /* -------------------------------------------------------------------- */
eads@18 22
eads@18 23 var canvas, ctx;
eads@18 24 var canvasWidth, halfCanvasWidth;
eads@18 25 var canvasHeight, halfCanvasHeight;
eads@18 26
eads@18 27 var space; // 3D Engine
eads@18 28 var scene; // 3D Scene
eads@18 29
eads@18 30 /* -------------------------------------------------------------------- */
eads@18 31
eads@18 32 /**
eads@18 33 * Space is a simple 3D system.
eads@18 34 *
eads@18 35 * Y+ = up
eads@18 36 * Z+ = into screen
eads@18 37 * X+ = right
eads@18 38 */
eads@18 39 function Space() {
eads@18 40 this.m = this.createMatrixIdentity();
eads@18 41 this.mStack = [];
eads@18 42 }
eads@18 43
eads@18 44 Space.prototype.createMatrixIdentity = function() {
eads@18 45 return [
eads@18 46 [1, 0, 0, 0],
eads@18 47 [0, 1, 0, 0],
eads@18 48 [0, 0, 1, 0],
eads@18 49 [0, 0, 0, 1]
eads@18 50 ];
eads@18 51 }
eads@18 52
eads@18 53 /**
eads@18 54 * Multiplies two 4x4 matricies together.
eads@18 55 */
eads@18 56 Space.prototype.matrixMultiply = function(m1, m2) {
eads@18 57 var result = this.createMatrixIdentity();
eads@18 58
eads@18 59 var width = m1[0].length;
eads@18 60 var height = m1.length;
eads@18 61
eads@18 62 if (width != m2.length) {
eads@18 63 // error
eads@18 64 }
eads@18 65
eads@18 66 for (var x = 0; x < width; x++) {
eads@18 67 for (var y = 0; y < height; y++) {
eads@18 68 var sum = 0;
eads@18 69
eads@18 70 for (var z = 0; z < width; z++) {
eads@18 71 sum += m1[y][z] * m2[z][x];
eads@18 72 }
eads@18 73
eads@18 74 result[y][x] = sum;
eads@18 75 }
eads@18 76 }
eads@18 77
eads@18 78 return result;
eads@18 79 }
eads@18 80
eads@18 81 /**
eads@18 82 * Transforms a coordinate using the current transformation
eads@18 83 * matrix, then flattens it using the projection matrix.
eads@18 84 */
eads@18 85 Space.prototype.flatten = function(point) {
eads@18 86 var p = [[point.x, point.y, point.z, 1]];
eads@18 87 var pm = this.matrixMultiply(p, this.m);
eads@18 88
eads@18 89 point.tx = pm[0][0];
eads@18 90 point.ty = pm[0][1];
eads@18 91 point.tz = pm[0][2];
eads@18 92
eads@18 93 // lazy projection
eads@18 94 point.fx = halfCanvasWidth + (canvasWidth * point.tx / point.tz);
eads@18 95 point.fy = halfCanvasHeight -(canvasWidth * point.ty / point.tz);
eads@18 96 }
eads@18 97
eads@18 98 /**
eads@18 99 * Translate (move) the current transformation matrix
eads@18 100 */
eads@18 101 Space.prototype.translate = function(x, y, z) {
eads@18 102 var m = [
eads@18 103 [1, 0, 0, 0],
eads@18 104 [0, 1, 0, 0],
eads@18 105 [0, 0, 1, 0],
eads@18 106 [x, y, z, 1]
eads@18 107 ];
eads@18 108
eads@18 109 this.m = this.matrixMultiply(m, this.m);
eads@18 110 }
eads@18 111
eads@18 112 /**
eads@18 113 * Rotate the current transformation matrix. Rotations are
eads@18 114 * world-oriented, and occur in y,x,z order.
eads@18 115 */
eads@18 116 Space.prototype.rotate = function(x, y, z) {
eads@18 117 if (y) {
eads@18 118 var cosY = Math.cos(y);
eads@18 119 var sinY = Math.sin(y);
eads@18 120 var rotY = [
eads@18 121 [cosY, 0, sinY, 0],
eads@18 122 [0, 1, 0, 0],
eads@18 123 [-sinY, 0, cosY, 0],
eads@18 124 [0, 0, 0, 1]
eads@18 125 ];
eads@18 126
eads@18 127 this.m = this.matrixMultiply(this.m, rotY);
eads@18 128 }
eads@18 129
eads@18 130 if (x) {
eads@18 131 var cosX = Math.cos(x);
eads@18 132 var sinX = Math.sin(x);
eads@18 133 var rotX = [
eads@18 134 [1, 0, 0, 0],
eads@18 135 [0, cosX, -sinX, 0],
eads@18 136 [0, sinX, cosX,0],
eads@18 137 [0, 0, 0, 1]
eads@18 138 ];
eads@18 139 this.m = this.matrixMultiply(this.m, rotX);
eads@18 140 }
eads@18 141
eads@18 142 if (z) {
eads@18 143 var cosZ = Math.cos(z);
eads@18 144 var sinZ = Math.sin(z);
eads@18 145 var rotZ = [
eads@18 146 [cosZ, -sinZ, 0, 0],
eads@18 147 [sinZ, cosZ, 0, 0],
eads@18 148 [0, 0, 1, 0],
eads@18 149 [0, 0, 0, 1]
eads@18 150 ];
eads@18 151
eads@18 152 this.m = this.matrixMultiply(this.m, rotZ);
eads@18 153 }
eads@18 154 }
eads@18 155
eads@18 156 /**
eads@18 157 * Pushes the current transformation onto the stack
eads@18 158 */
eads@18 159 Space.prototype.push = function() {
eads@18 160 this.mStack.push(this.m);
eads@18 161 this.m = [
eads@18 162 [this.m[0][0], this.m[0][1], this.m[0][2], this.m[0][3]],
eads@18 163 [this.m[1][0], this.m[1][1], this.m[1][2], this.m[1][3]],
eads@18 164 [this.m[2][0], this.m[2][1], this.m[2][2], this.m[2][3]],
eads@18 165 [this.m[3][0], this.m[3][1], this.m[3][2], this.m[3][3]]
eads@18 166 ];
eads@18 167 }
eads@18 168
eads@18 169 /**
eads@18 170 * Pops the end off the transformation stack
eads@18 171 */
eads@18 172 Space.prototype.pop = function() {
eads@18 173 this.m = this.mStack.pop();
eads@18 174 }
eads@18 175
eads@18 176 /* -------------------------------------------------------------------- */
eads@18 177
eads@18 178 /**
eads@18 179 * A 3d coordinate
eads@18 180 */
eads@18 181 function Point(x, y, z) {
eads@18 182 this.x = x;
eads@18 183 this.y = y;
eads@18 184 this.z = z;
eads@18 185
eads@18 186 // Relative to camera coordinates
eads@18 187 this.tx;
eads@18 188 this.ty;
eads@18 189 this.tz;
eads@18 190
eads@18 191 // Flattened coordinates
eads@18 192 this.fx;
eads@18 193 this.fy;
eads@18 194 }
eads@18 195
eads@18 196 /**
eads@18 197 * A Shape is made up of polygons
eads@18 198 */
eads@18 199 function Shape() {
eads@18 200 this.points = [];
eads@18 201 this.polygons = [];
eads@18 202 }
eads@18 203
eads@18 204 /**
eads@18 205 * Draws the shape
eads@18 206 */
eads@18 207 Shape.prototype.draw = function(drawlist) {
eads@18 208 for (var i = 0; i< this.points.length; i++) {
eads@18 209 space.flatten(this.points[i]);
eads@18 210 }
eads@18 211
eads@18 212 for (var i = 0; i< this.polygons.length; i++) {
eads@18 213 var poly = this.polygons[i]; // convenience
eads@18 214
eads@18 215 space.flatten(poly.origin);
eads@18 216
eads@18 217 // lazy backface culling
eads@18 218 if (poly.normal && this.backface) {
eads@18 219 space.flatten(poly.normal);
eads@18 220
eads@18 221 var originDist = Math.pow(poly.origin.tx, 2)
eads@18 222 + Math.pow(poly.origin.ty, 2)
eads@18 223 + Math.pow(poly.origin.tz, 2);
eads@18 224
eads@18 225 var normalDist = Math.pow(poly.normal.tx, 2)
eads@18 226 + Math.pow(poly.normal.ty, 2)
eads@18 227 + Math.pow(poly.normal.tz, 2);
eads@18 228
eads@18 229 if(originDist > normalDist) {
eads@18 230 drawlist.push(poly);
eads@18 231 }
eads@18 232 } else {
eads@18 233 drawlist.push(poly);
eads@18 234 }
eads@18 235 }
eads@18 236 }
eads@18 237
eads@18 238 /**
eads@18 239 * A polygon is a connection of points in the shape object. You
eads@18 240 * should probably try to make them coplanar.
eads@18 241 */
eads@18 242 function Polygon(points, normal, backface, type, color) {
eads@18 243 this.points = points;
eads@18 244
eads@18 245 this.origin = new Point(0, 0, 0);
eads@18 246 for(var i = 0; i < this.points.length; i++) {
eads@18 247 this.origin.x += this.points[i].x;
eads@18 248 this.origin.y += this.points[i].y;
eads@18 249 this.origin.z += this.points[i].z;
eads@18 250 }
eads@18 251
eads@18 252 this.origin.x /= this.points.length;
eads@18 253 this.origin.y /= this.points.length;
eads@18 254 this.origin.z /= this.points.length;
eads@18 255
eads@18 256 if (normal) {
eads@18 257 this.normal = new Point(this.origin.x + normal.x,
eads@18 258 this.origin.y + normal.y,
eads@18 259 this.origin.z + normal.z);
eads@18 260 } else {
eads@18 261 this.normal = null;
eads@18 262 }
eads@18 263
eads@18 264 this.backface = backface;
eads@18 265 this.type = type;
eads@18 266 this.color = color;
eads@18 267 }
eads@18 268
eads@18 269 Polygon.SOLID = 0;
eads@18 270 Polygon.WIRE = 1;
eads@18 271
eads@18 272 /**
eads@18 273 * Draws the polygon. Assumes that the points have already been
eads@18 274 * flattened.
eads@18 275 */
eads@18 276 Polygon.prototype.draw = function() {
eads@18 277 ctx.beginPath();
eads@18 278 ctx.moveTo(this.points[0].fx, this.points[0].fy);
eads@18 279
eads@18 280 for(var i = 0; i < this.points.length; i++) {
eads@18 281 ctx.lineTo(this.points[i].fx, this.points[i].fy);
eads@18 282 }
eads@18 283
eads@18 284 ctx.closePath();
eads@18 285
eads@18 286 var color = this.color;
eads@18 287
eads@18 288 /*
eads@18 289 // Do lighting here
eads@18 290 lightvector = Math.abs(this.normal.x + this.normal.y);
eads@18 291 if(lightvector > 1) {
eads@18 292 lightvector = 1;
eads@18 293 }
eads@18 294
eads@18 295 color[0] = (color[0] * lightvector).toString();
eads@18 296 color[1] = (color[1] * lightvector).toString();
eads@18 297 color[2] = (color[2] * lightvector).toString();
eads@18 298 */
eads@18 299
eads@18 300 if (color.length > 3) {
eads@18 301 var style = ["rgba(",
eads@18 302 color[0], ",",
eads@18 303 color[1], ",",
eads@18 304 color[2], ",",
eads@18 305 color[3], ")"].join("");
eads@18 306 } else {
eads@18 307 var style = ["rgb(",
eads@18 308 color[0], ",",
eads@18 309 color[1], ",",
eads@18 310 color[2], ")"].join("");
eads@18 311 }
eads@18 312
eads@18 313 if (this.type == Polygon.SOLID) {
eads@18 314 ctx.fillStyle = style;
eads@18 315 ctx.fill();
eads@18 316 } else if (this.type == Polygon.WIRE) {
eads@18 317 ctx.strokeStyle = style;
eads@18 318 ctx.stroke();
eads@18 319 }
eads@18 320 }
eads@18 321
eads@18 322 /* -------------------------------------------------------------------- */
eads@18 323
eads@18 324 /**
eads@18 325 * Scene describes the 3D environment
eads@18 326 */
eads@18 327 function Scene() {
eads@18 328 this.shapes = {};
eads@18 329 this.camera = new Point(0, 0, 0);
eads@18 330 this.cameraTarget = new Point(0, 0, 0);
eads@18 331 this.cameraRotation = 0;
eads@18 332
eads@18 333 this.drawlist = [];
eads@18 334 }
eads@18 335
eads@18 336 /**
eads@18 337 * Draw the world
eads@18 338 */
eads@18 339 Scene.prototype.draw = function() {
eads@18 340 space.push();
eads@18 341
eads@18 342 // Camera transformation
eads@18 343 space.translate(
eads@18 344 -this.camera.x,
eads@18 345 -this.camera.y,
eads@18 346 -this.camera.z
eads@18 347 );
eads@18 348
eads@18 349 // Camera rotation
eads@18 350 var xdiff = this.cameraTarget.x - this.camera.x;
eads@18 351 var ydiff = this.cameraTarget.y - this.camera.y;
eads@18 352 var zdiff = this.cameraTarget.z - this.camera.z;
eads@18 353
eads@18 354 var xzdist = Math.sqrt(Math.pow(xdiff, 2) + Math.pow(zdiff, 2));
eads@18 355
eads@18 356 var xrot = -Math.atan2(ydiff, xzdist); // up/down rotation
eads@18 357 var yrot = Math.atan2(xdiff, zdiff); // left/right rotation
eads@18 358
eads@18 359 space.rotate(xrot, yrot, this.cameraRotation);
eads@18 360
eads@18 361 // Drawing
eads@18 362 this.drawlist = [];
eads@18 363
eads@18 364 for(var i in this.shapes) {
eads@18 365 this.shapes[i].draw(this.drawlist);
eads@18 366 }
eads@18 367
eads@18 368 // Depth sorting (warning: this is only enough to drive this demo - feel
eads@18 369 // free to contribute a better system).
eads@18 370 this.drawlist.sort(function (poly1, poly2) {
eads@18 371 return poly2.origin.tz - poly1.origin.tz;
eads@18 372 });
eads@18 373
eads@18 374 for (var i = 0; i < this.drawlist.length; i++) {
eads@18 375 this.drawlist[i].draw();
eads@18 376 }
eads@18 377
eads@18 378 space.pop();
eads@18 379 }
eads@18 380
eads@18 381 /* -------------------------------------------------------------------- */
eads@18 382
eads@18 383 var count = 0;
eads@18 384
eads@18 385 function loop() {
eads@18 386 ctx.clearRect(0, 0, canvasWidth, canvasHeight);
eads@18 387
eads@18 388 scene.camera.x = 70*Math.sin(count);
eads@18 389 scene.camera.y = 70;
eads@18 390 scene.camera.z = 70*Math.cos(count);
eads@18 391 scene.cameraRotation = count / 10;
eads@18 392
eads@18 393 count += 0.01;
eads@18 394 scene.draw();
eads@18 395 }
eads@18 396
eads@18 397 function load() {
eads@18 398 // Init drawing system
eads@18 399 canvas = document.getElementById("cv");
eads@18 400 ctx = canvas.getContext("2d");
eads@18 401
eads@18 402 canvasWidth = canvas.width;
eads@18 403 canvasHeight = canvas.height;
eads@18 404 halfCanvasWidth = canvasWidth * 0.5;
eads@18 405 halfCanvasHeight = canvasHeight * 0.5;
eads@18 406
eads@18 407 // Init 3D components
eads@18 408 space = new Space();
eads@18 409 scene = new Scene();
eads@18 410
eads@18 411 // Create a box shape and add it to the scene
eads@18 412 scene.shapes['box'] = new Shape();
eads@18 413 var p = scene.shapes['box'].points; // for convenience
eads@18 414
eads@18 415 p[0] = new Point(-10, -10, -10); // left bottom front
eads@18 416 p[1] = new Point(10, -10, -10); // right bottom front
eads@18 417 p[2] = new Point(10, 10, -10); // right top front
eads@18 418 p[3] = new Point(-10, 10, -10); // left top front
eads@18 419
eads@18 420 p[4] = new Point(-10, -10, 10); // left bottom back
eads@18 421 p[5] = new Point(10, -10, 10); // right bottom back
eads@18 422 p[6] = new Point(10, 10, 10); // right top back
eads@18 423 p[7] = new Point(-10, 10, 10); // left top back
eads@18 424
eads@18 425 // Back
eads@18 426 scene.shapes['box'].polygons.push(new Polygon(
eads@18 427 [ p[0], p[1], p[2], p[3] ],
eads@18 428 new Point(0, 0, -1),
eads@18 429 true /* double-sided */,
eads@18 430 Polygon.SOLID,
eads@18 431 [255, 0, 0]
eads@18 432 ));
eads@18 433
eads@18 434 // Front
eads@18 435 scene.shapes['box'].polygons.push(new Polygon(
eads@18 436 [ p[4], p[5], p[6], p[7] ],
eads@18 437 new Point(0, 0, 1),
eads@18 438 true /* double-sided */,
eads@18 439 Polygon.SOLID,
eads@18 440 [0, 0, 255]
eads@18 441 ));
eads@18 442
eads@18 443 // Top
eads@18 444 scene.shapes['box'].polygons.push(new Polygon(
eads@18 445 [ p[2], p[3], p[7], p[6] ],
eads@18 446 new Point(0, 1, 0),
eads@18 447 false /* single-sided */,
eads@18 448 Polygon.WIRE,
eads@18 449 [0, 255, 0]
eads@18 450 ));
eads@18 451
eads@18 452 // Transparent Top
eads@18 453 scene.shapes['box'].polygons.push(new Polygon(
eads@18 454 [ p[2], p[3], p[7], p[6] ],
eads@18 455 new Point(0, 1, 0),
eads@18 456 false /* single-sided */,
eads@18 457 Polygon.SOLID,
eads@18 458 [0, 255, 0, 0.4]
eads@18 459 ));
eads@18 460
eads@18 461 // Left
eads@18 462 scene.shapes['box'].polygons.push(new Polygon(
eads@18 463 [ p[0], p[4], p[7], p[3] ],
eads@18 464 new Point(-1, 0, 0),
eads@18 465 true /* double-sided */,
eads@18 466 Polygon.SOLID,
eads@18 467 [255, 255, 0]
eads@18 468 ));
eads@18 469
eads@18 470 // Right
eads@18 471 scene.shapes['box'].polygons.push(new Polygon(
eads@18 472 [ p[1], p[5], p[6], p[2] ],
eads@18 473 new Point(1, 0, 0),
eads@18 474 true /* double-sided */,
eads@18 475 Polygon.SOLID,
eads@18 476 [0, 255, 255]
eads@18 477 ));
eads@18 478
eads@18 479 // Create a floor shape and add it to the scene
eads@18 480 scene.shapes['floor'] = new Shape();
eads@18 481 var p = scene.shapes['floor'].points; // for convenience
eads@18 482
eads@18 483 p[0] = new Point(-40, -10, -40);
eads@18 484 p[1] = new Point(-40, -10, 40);
eads@18 485 p[2] = new Point( 40, -10, 40);
eads@18 486 p[3] = new Point( 40, -10, -40);
eads@18 487
eads@18 488 // Floor
eads@18 489 scene.shapes['floor'].polygons.push(new Polygon(
eads@18 490 [ p[0], p[1], p[2], p[3] ],
eads@18 491 new Point(0, 1, 0),
eads@18 492 false /* single-sided */,
eads@18 493 Polygon.SOLID,
eads@18 494 [45, 45, 45]
eads@18 495 ));
eads@18 496
eads@18 497 setInterval('loop()', 20);
eads@18 498 }
eads@18 499
eads@18 500 /* -------------------------------------------------------------------- */
eads@18 501 </script>
eads@18 502 <style>
eads@18 503 body {
eads@18 504 background-color:black;
eads@18 505 margin:50px;
eads@18 506 text-align:center;
eads@18 507 }
eads@18 508 </style>
eads@18 509 </head>
eads@18 510 <body onload="load();">
eads@18 511 <canvas id="cv" width="400" height="300"></canvas>
eads@18 512 </body>
eads@18 513 </html>