1 /*{# Copyright (c) 2010-2012 Turbulenz Limited #}*/ 2 var __extends = this.__extends || function (d, b) { 3 for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 4 function __() { this.constructor = d; } 5 __.prototype = b.prototype; 6 d.prototype = new __(); 7 }; 8 /* 9 * @title: Animation 10 * @description: 11 * This sample shows how to load multiple animations and build an animation controller hierarchy. 12 * An animation transition controller is used to blend between two animations. 13 * You can enable drawing of debug information to see the animation bounding box, the skeleton, 14 * and the mesh wireframe. 15 * You can also click on the rendering windows to move and rotate the camera around. 16 */ 17 /*{{ javascript("jslib/aabbtree.js") }}*/ 18 /*{{ javascript("jslib/camera.js") }}*/ 19 /*{{ javascript("jslib/geometry.js") }}*/ 20 /*{{ javascript("jslib/material.js") }}*/ 21 /*{{ javascript("jslib/light.js") }}*/ 22 /*{{ javascript("jslib/scenenode.js") }}*/ 23 /*{{ javascript("jslib/scene.js") }}*/ 24 /*{{ javascript("jslib/vmath.js") }}*/ 25 /*{{ javascript("jslib/effectmanager.js") }}*/ 26 /*{{ javascript("jslib/shadermanager.js") }}*/ 27 /*{{ javascript("jslib/texturemanager.js") }}*/ 28 /*{{ javascript("jslib/animationmanager.js") }}*/ 29 /*{{ javascript("jslib/renderingcommon.js") }}*/ 30 /*{{ javascript("jslib/defaultrendering.js") }}*/ 31 /*{{ javascript("jslib/observer.js") }}*/ 32 /*{{ javascript("jslib/requesthandler.js") }}*/ 33 /*{{ javascript("jslib/resourceloader.js") }}*/ 34 /*{{ javascript("jslib/animation.js") }}*/ 35 /*{{ javascript("jslib/scenedebugging.js") }}*/ 36 /*{{ javascript("jslib/utilities.js") }}*/ 37 /*{{ javascript("jslib/vertexbuffermanager.js") }}*/ 38 /*{{ javascript("jslib/indexbuffermanager.js") }}*/ 39 /*{{ javascript("jslib/services/turbulenzservices.js") }}*/ 40 /*{{ javascript("jslib/services/turbulenzbridge.js") }}*/ 41 /*{{ javascript("jslib/services/gamesession.js") }}*/ 42 /*{{ javascript("jslib/services/mappingtable.js") }}*/ 43 /*{{ javascript("scripts/sceneloader.js") }}*/ 44 /*{{ javascript("scripts/motion.js") }}*/ 45 /*{{ javascript("scripts/htmlcontrols.js") }}*/ 46 /*global TurbulenzEngine: true */ 47 /*global TurbulenzServices: false */ 48 /*global RequestHandler: false */ 49 /*global TextureManager: false */ 50 /*global ShaderManager: false */ 51 /*global EffectManager: false */ 52 /*global Scene: false */ 53 /*global SceneLoader: false */ 54 /*global ResourceLoader: false */ 55 /*global Camera: false */ 56 /*global HTMLControls: false */ 57 /*global AnimationManager: false */ 58 /*global CameraController: false */ 59 /*global DefaultRendering: false */ 60 /*global SkinnedNode: false */ 61 /*global VMath: false */ 62 /*global GPUSkinController: false */ 63 /*global InterpolatorController: false */ 64 /*global ReferenceController: false */ 65 /*global NodeTransformController: false */ 66 /*global TransitionController: false */ 67 // We put some custom data onto Scene 68 var CustomScene = (function (_super) { 69 __extends(CustomScene, _super); 70 function CustomScene() { 71 _super.apply(this, arguments); 72 } 73 return CustomScene; 74 })(Scene); 75 ; 76 77 TurbulenzEngine.onload = function onloadFn() { 78 var errorCallback = function errorCallback(msg) { 79 window.alert(msg); 80 }; 81 TurbulenzEngine.onerror = errorCallback; 82 83 var graphicsDeviceParameters = {}; 84 var graphicsDevice = TurbulenzEngine.createGraphicsDevice(graphicsDeviceParameters); 85 86 if (!graphicsDevice.shadingLanguageVersion) { 87 errorCallback("No shading language support detected.\nPlease check your graphics drivers are up to date."); 88 graphicsDevice = null; 89 return; 90 } 91 92 // Clear the background color of the engine window 93 var clearColor = [0.5, 0.5, 0.5, 1.0]; 94 if (graphicsDevice.beginFrame()) { 95 graphicsDevice.clear(clearColor); 96 graphicsDevice.endFrame(); 97 } 98 99 var mathDeviceParameters = {}; 100 var mathDevice = TurbulenzEngine.createMathDevice(mathDeviceParameters); 101 102 var inputDeviceParameters = {}; 103 var inputDevice = TurbulenzEngine.createInputDevice(inputDeviceParameters); 104 105 var requestHandlerParameters = {}; 106 var requestHandler = RequestHandler.create(requestHandlerParameters); 107 108 var textureManager = TextureManager.create(graphicsDevice, requestHandler, null, errorCallback); 109 var shaderManager = ShaderManager.create(graphicsDevice, requestHandler, null, errorCallback); 110 var effectManager = EffectManager.create(); 111 var animationManager = AnimationManager.create(errorCallback); 112 var mappingTable; 113 114 var resourceLoader = ResourceLoader.create(); 115 116 // Setup world space 117 var worldUp = mathDevice.v3Build(0.0, 1.0, 0.0); 118 119 // Bounds are red, interpolatorColor is updated per animation 120 var boundsColor = [1, 0, 0]; 121 var interpolatorColor = [0, 0, 0]; 122 123 // Setup a camera to view a close-up object 124 var camera = Camera.create(mathDevice); 125 camera.nearPlane = 0.05; 126 camera.updateViewMatrix(); 127 128 var animMinExtent, animMaxExtent; 129 130 var cameraController = CameraController.create(graphicsDevice, inputDevice, camera); 131 var maxSpeed = cameraController.maxSpeed; 132 var cameraDistanceFactor = 1.0; 133 var cameraDir = [1, 1, 1]; 134 135 // Settings for the animation 136 var settings = { 137 animScale: 1, 138 defaultRate: 1, 139 drawDebug: false, 140 drawInterpolators: false, 141 drawWireframe: false, 142 loopAnimation: true, 143 blendAnimation: false, 144 transitionLength: 1 145 }; 146 147 // The default animation to start with 148 var defaultAnimIndex = 0; 149 150 // The current playing animation 151 var curAnimIndex = 0; 152 153 // The controller references by index 154 var controllerMap = []; 155 156 // This is our base asset that includes a character and animations 157 var assetToLoad = "models/Seymour.dae"; 158 159 // The list of animations to load pre-scene load (by reference) 160 // This is only for animations that are not included in the default scene 161 // e.g. "animations/default_walking.anim" 162 var addAnimations = ["models/Seymour_anim2_rot90_anim_only.dae"]; 163 164 // The list of animations to be remove from the scene data pre-load 165 // This is for undesired animations that are packed in the scene 166 // All these animations are not required for this sample 167 var removeAnimations = [ 168 "default_astroboy_w_skel02_gog_polySurface5", 169 "default_astroboy_w_skel02_polySurface5", 170 "default_astroboy_w_skel02c_gog_polySurface5", 171 "default_astroboy_w_skel02c_polySurface5", 172 "default_gog_polySurface5", 173 "default_polySurface5" 174 ]; 175 176 // The controller to blend the transisitions between animations, that don't have a matching key frame 177 var transitionController = null; 178 var transitionStartColor = [0, 0, 0]; 179 var transitionEndColor = [0, 0, 0]; 180 181 // Reference controller for the whole animation 182 var currentReferenceController = null; 183 var currentNodeController = null; 184 185 var animationsLoaded; 186 187 // When the JSON is loaded, add a prefix to uniquely identify that set of animation data 188 var animationsLoadedCallback = function animationsLoadedCallbackFn(jsonData) { 189 var addAnimNum = (addAnimations.length - animationsLoaded); 190 animationManager.loadData(jsonData, "AnimExtra" + addAnimNum + "-"); 191 animationsLoaded -= 1; 192 }; 193 194 var addAnimationsToScene = function addAnimationsToSceneFn() { 195 // Attach additional animations to the scene (specify by path) 196 // The animations are added by reference and the resourceLoader will attempt to load them using request 197 animationsLoaded = addAnimations.length; 198 for (var i = 0; i < addAnimations.length; i += 1) { 199 var path = addAnimations[i]; 200 resourceLoader.load(mappingTable.getURL(path), { 201 append: true, 202 onload: animationsLoadedCallback, 203 requestHandler: requestHandler 204 }); 205 } 206 }; 207 208 var removeAnimationsFromScene = function removeAnimationsFromSceneFn(sceneData) { 209 // Remove unrequired animations from scene, if they exist before load 210 var anims = sceneData.animations; 211 var animationRef; 212 213 if (anims) { 214 for (var i = 0; i < removeAnimations.length; i += 1) { 215 animationRef = removeAnimations[i]; 216 if (anims[animationRef]) { 217 delete anims[animationRef]; 218 } 219 } 220 } 221 }; 222 223 // Sets the next animation to play 224 var nextAnimation = function nextAnimationFn(nextAnimIndex) { 225 var controllers, interpStart, interpEnd, startColor, endColor, startSkinnedNode, endSkinnedNode, startNodes, endNodes; 226 227 controllers = controllerMap[curAnimIndex]; 228 if (controllers) { 229 interpStart = controllers.interpController; 230 startColor = controllers.color; 231 startSkinnedNode = controllers.skinnedNode; 232 startNodes = controllers.nodeCount; 233 } 234 235 controllers = controllerMap[nextAnimIndex]; 236 if (controllers) { 237 interpEnd = controllers.interpController; 238 endColor = controllers.color; 239 endSkinnedNode = controllers.skinnedNode; 240 endNodes = controllers.nodeCount; 241 } 242 243 if (interpEnd) { 244 interpEnd.setTime(0); 245 246 if (startSkinnedNode && (startSkinnedNode !== endSkinnedNode)) { 247 startSkinnedNode.active = false; 248 startSkinnedNode.setInputController(interpStart); 249 } 250 251 if ((settings.blendAnimation || !interpStart) && (interpStart !== interpEnd) && (startNodes === endNodes)) { 252 if (!transitionController) { 253 transitionController = TransitionController.create(interpStart, interpEnd, settings.transitionLength); 254 transitionController.onFinishedTransitionCallback = function onFinishedTransitionCallbackFn(/* transition */ ) { 255 var controllers = controllerMap[curAnimIndex]; 256 if (controllers) { 257 var skinnedNode = controllers.skinnedNode; 258 currentReferenceController.setReferenceController(controllers.interpController); 259 currentReferenceController.setTime(0); 260 interpolatorColor = controllers.color; 261 if (skinnedNode) { 262 skinnedNode.setInputController(currentReferenceController); 263 skinnedNode.active = true; 264 } 265 } 266 267 // Callback return value of 'false' tells the controller not to continue operating 268 // This is because we have decided to set a different controller to be used instead 269 return false; 270 }; 271 transitionController.onUpdateCallback = function onUpdateCallbackFn(transition) { 272 var delta = (transition.transitionTime / transition.transitionLength); 273 interpolatorColor = VMath.v3Add(VMath.v3ScalarMul(transitionStartColor, 1 - delta), VMath.v3ScalarMul(transitionEndColor, delta)); 274 }; 275 } else { 276 transitionController.setEndController(interpEnd); 277 transitionController.setStartController(interpStart); 278 transitionController.setTransitionLength(settings.transitionLength); 279 } 280 281 currentReferenceController.setReferenceController(transitionController); 282 transitionStartColor = startColor; 283 transitionEndColor = endColor; 284 } else { 285 // Set the node controller to be the reference controller 286 currentReferenceController.setReferenceController(interpEnd); 287 interpolatorColor = endColor; 288 } 289 290 // Reset the animation about to play 291 currentReferenceController.setTime(0); 292 293 if (endSkinnedNode) { 294 endSkinnedNode.setInputController(currentReferenceController); 295 endSkinnedNode.active = true; 296 } 297 curAnimIndex = nextAnimIndex; 298 } 299 }; 300 301 // Update the settings for an existing animation controller 302 var updateAnimations = function updateAnimationsFn(/* scene */ ) { 303 var i, controllers, interp; 304 var length = controllerMap.length; 305 306 for (i = 0; i < length; i += 1) { 307 controllers = controllerMap[i]; 308 if (controllers) { 309 interp = controllers.interpController; 310 if (interp) { 311 interp.setAnimation(interp.currentAnim, settings.loopAnimation); 312 interp.setRate(settings.defaultRate); 313 } 314 } 315 } 316 }; 317 318 function calcAnimationExtents(scene, animationIndex) { 319 // Calculate the extents from the animation 320 var controllers = controllerMap[animationIndex]; 321 if (controllers) { 322 var maxValue = Number.MAX_VALUE; 323 var animExtentMin0 = maxValue; 324 var animExtentMin1 = maxValue; 325 var animExtentMin2 = maxValue; 326 var animExtentMax0 = -maxValue; 327 var animExtentMax1 = -maxValue; 328 var animExtentMax2 = -maxValue; 329 330 var bounds = controllers.animation.bounds; 331 var numFrames = bounds.length; 332 for (var i = 0; i < numFrames; i = i + 1) { 333 var bound = bounds[i]; 334 var center = bound.center; 335 var halfExtent = bound.halfExtent; 336 var c0 = center[0]; 337 var c1 = center[1]; 338 var c2 = center[2]; 339 var h0 = halfExtent[0]; 340 var h1 = halfExtent[1]; 341 var h2 = halfExtent[2]; 342 var min0 = (c0 - h0); 343 var min1 = (c1 - h1); 344 var min2 = (c2 - h2); 345 var max0 = (c0 + h0); 346 var max1 = (c1 + h1); 347 var max2 = (c2 + h2); 348 animExtentMin0 = (animExtentMin0 < min0 ? animExtentMin0 : min0); 349 animExtentMin1 = (animExtentMin1 < min1 ? animExtentMin1 : min1); 350 animExtentMin2 = (animExtentMin2 < min2 ? animExtentMin2 : min2); 351 animExtentMax0 = (animExtentMax0 > max0 ? animExtentMax0 : max0); 352 animExtentMax1 = (animExtentMax1 > max1 ? animExtentMax1 : max1); 353 animExtentMax2 = (animExtentMax2 > max2 ? animExtentMax2 : max2); 354 } 355 356 animMinExtent = mathDevice.v3Build(animExtentMin0, animExtentMin1, animExtentMin2); 357 animMaxExtent = mathDevice.v3Build(animExtentMax0, animExtentMax1, animExtentMax2); 358 } else { 359 // Use the scene extents 360 var sceneExtents = scene.getExtents(); 361 animMinExtent = mathDevice.v3Build(sceneExtents[0], sceneExtents[1], sceneExtents[2]); 362 animMaxExtent = mathDevice.v3Build(sceneExtents[3], sceneExtents[4], sceneExtents[5]); 363 } 364 } 365 366 // Calculates a position for the camera to lookAt 367 var resetCamera = function resetCameraFn(camera, scene) { 368 calcAnimationExtents(scene, curAnimIndex); 369 370 // Update the camera to scale to the size of the scene 371 var center = mathDevice.v3ScalarMul(mathDevice.v3Add(animMaxExtent, animMinExtent), 0.5); 372 var extent = mathDevice.v3Sub(center, animMinExtent); 373 374 camera.lookAt(center, worldUp, mathDevice.v3Build(center[0] + extent[0] * cameraDistanceFactor * cameraDir[0] * 2, center[1] + extent[1] * cameraDistanceFactor * cameraDir[1], center[2] + extent[2] * cameraDistanceFactor * cameraDir[2] * 2)); 375 camera.updateViewMatrix(); 376 377 // Calculates the appropriate nearPlane for the animation extents 378 var len = VMath.v3Length(extent); 379 if (len < 4.0) { 380 camera.nearPlane = len * 0.1; 381 } else { 382 camera.nearPlane = 1.0; 383 } 384 camera.farPlane = Math.ceil(len) * 100.0; 385 camera.updateProjectionMatrix(); 386 387 // Calculates the speed to move around the animation 388 maxSpeed = (len < 100 ? (len * 2) : (len * 0.5)); 389 }; 390 391 // Create object using scene loader 392 var scene = (Scene.create(mathDevice)); 393 var sceneLoader = SceneLoader.create(); 394 395 var renderer; 396 var loadAssets = function loadAssets() { 397 // Renderer for the scene (requires shader assets). 398 renderer = DefaultRendering.create(graphicsDevice, mathDevice, shaderManager, effectManager); 399 400 renderer.setGlobalLightPosition(mathDevice.v3Build(0.5, 100.0, 0.5)); 401 renderer.setAmbientColor(mathDevice.v3Build(0.3, 0.3, 0.4)); 402 renderer.setDefaultTexture(textureManager.get("default")); 403 404 sceneLoader.setPathRemapping(mappingTable.urlMapping, mappingTable.assetPrefix); 405 sceneLoader.load({ 406 scene: scene, 407 assetPath: assetToLoad, 408 graphicsDevice: graphicsDevice, 409 mathDevice: mathDevice, 410 textureManager: textureManager, 411 effectManager: effectManager, 412 shaderManager: shaderManager, 413 animationManager: animationManager, 414 requestHandler: requestHandler, 415 keepVertexData: true, 416 preSceneLoadFn: function (sceneData) { 417 // Apply the modifications to the data from assetPath 418 addAnimationsToScene(); 419 removeAnimationsFromScene(sceneData); 420 }, 421 keepLights: true, 422 append: true 423 }); 424 }; 425 426 var mappingTableReceived = function mappingTableReceivedFn(mappingTable) { 427 textureManager.setPathRemapping(mappingTable.urlMapping, mappingTable.assetPrefix); 428 shaderManager.setPathRemapping(mappingTable.urlMapping, mappingTable.assetPrefix); 429 sceneLoader.setPathRemapping(mappingTable.urlMapping, mappingTable.assetPrefix); 430 431 loadAssets(); 432 }; 433 434 var gameSessionCreated = function gameSessionCreatedFn(gameSession) { 435 var defaultMappingSettings = { 436 mappingTablePrefix: "staticmax/", 437 assetPrefix: "missing/", 438 mappingTableURL: "mapping_table.json" 439 }; 440 mappingTable = TurbulenzServices.createMappingTable(requestHandler, gameSession, mappingTableReceived, defaultMappingSettings); 441 }; 442 var gameSession = TurbulenzServices.createGameSession(requestHandler, gameSessionCreated); 443 444 // Controls 445 var htmlControls = HTMLControls.create(); 446 447 htmlControls.addButtonControl({ 448 id: "button01", 449 value: "Next", 450 fn: function () { 451 nextAnimation((curAnimIndex + 1) % controllerMap.length); 452 } 453 }); 454 455 htmlControls.addButtonControl({ 456 id: "button02", 457 value: "Previous", 458 fn: function () { 459 var index = (curAnimIndex - 1); 460 index = (index === -1) ? (controllerMap.length - 1) : index; 461 nextAnimation(index); 462 } 463 }); 464 465 htmlControls.addButtonControl({ 466 id: "button03", 467 value: "Reset Camera", 468 fn: function () { 469 resetCamera(camera, scene); 470 } 471 }); 472 473 htmlControls.addCheckboxControl({ 474 id: "checkbox01", 475 value: "loopAnimation", 476 isSelected: settings.loopAnimation, 477 fn: function () { 478 settings.loopAnimation = !settings.loopAnimation; 479 updateAnimations(); 480 return settings.loopAnimation; 481 } 482 }); 483 484 htmlControls.addCheckboxControl({ 485 id: "checkbox02", 486 value: "blendAnimation", 487 isSelected: settings.blendAnimation, 488 fn: function () { 489 settings.blendAnimation = !settings.blendAnimation; 490 return settings.blendAnimation; 491 } 492 }); 493 494 htmlControls.addCheckboxControl({ 495 id: "checkbox03", 496 value: "drawDebug", 497 isSelected: settings.drawDebug, 498 fn: function () { 499 settings.drawDebug = !settings.drawDebug; 500 settings.drawWireframe = settings.drawDebug; 501 settings.drawInterpolators = settings.drawDebug; 502 return settings.drawDebug; 503 } 504 }); 505 506 htmlControls.register(); 507 508 // Provides a distinct array of colors to use for each controller 509 // Does not use red, black or white as they are reserved 510 var colorArray = [ 511 [0.5, 1, 0.5], 512 [0.5, 1, 1], 513 [1, 1, 0.5], 514 [1, 0.5, 1], 515 [0.5, 0.5, 1] 516 ]; 517 var lastColor = (colorArray.length - 1); 518 var getControllerColor = function getControllerColorFn() { 519 lastColor = (lastColor + 1) % colorArray.length; 520 return colorArray[lastColor]; 521 }; 522 523 // Initialise all animations with InterpolatorControllers set to start time 524 var initAnimations = function initAnimationsFn(scene) { 525 var a, n, anim, interp, tempNode, skinnedNode, node, hierarchy; 526 var nodeHasSkeleton = animationManager.nodeHasSkeleton; 527 var sceneNodes = scene.rootNodes; 528 var numNodes = sceneNodes.length; 529 scene.skinnedNodes = []; 530 531 for (n = 0; n < numNodes; n += 1) { 532 node = sceneNodes[n]; 533 var skeleton = nodeHasSkeleton(node); 534 if (skeleton && skeleton.numNodes) { 535 skinnedNode = SkinnedNode.create(graphicsDevice, mathDevice, node, skeleton); 536 scene.skinnedNodes.push(skinnedNode); 537 } 538 } 539 540 numNodes = scene.skinnedNodes.length; 541 542 // For each animation, create an interpolation controller 543 var animations = animationManager.getAll(); 544 for (a in animations) { 545 if (animations.hasOwnProperty(a)) { 546 anim = animations[a]; 547 hierarchy = anim.hierarchy; 548 549 // Create an interpolator controller for each animation 550 interp = InterpolatorController.create(hierarchy); 551 interp.setAnimation(anim, settings.loopAnimation); 552 interp.setTime(0); 553 interp.setRate(settings.defaultRate); 554 555 skinnedNode = null; 556 if (numNodes !== 0) { 557 for (n = 0; n < numNodes; n += 1) { 558 tempNode = scene.skinnedNodes[n]; 559 if (tempNode && (anim.numNodes === tempNode.skinController.skeleton.numNodes)) { 560 skinnedNode = tempNode; 561 } 562 } 563 } 564 565 // Controller map used for every interp controller 566 controllerMap.push({ 567 interpController: interp, 568 animation: anim, 569 nodeCount: hierarchy.numNodes, 570 skinnedNode: skinnedNode, 571 color: getControllerColor() 572 }); 573 } 574 } 575 576 var index = (controllerMap.length - 1); 577 if (index === -1) { 578 // Couldn't find any animations on the scene 579 return false; 580 } 581 582 var controllers = controllerMap[defaultAnimIndex]; 583 if (!controllers) { 584 // Pick the last added as a default 585 controllers = controllerMap[index]; 586 } else { 587 index = defaultAnimIndex; 588 } 589 590 var defaultInterp = controllers.interpController; 591 currentReferenceController = ReferenceController.create(defaultInterp); 592 hierarchy = currentReferenceController.getHierarchy(); 593 594 // Assumes hierarchy is the same for all anims 595 // If different hierarchies are used, create a new controller 596 currentNodeController = NodeTransformController.create(hierarchy, scene); 597 currentNodeController.setInputController(currentReferenceController); 598 currentNodeController.active = true; 599 600 // Set the initial animation 601 nextAnimation(index); 602 603 return true; 604 }; 605 606 // Callback to draw extra debug information 607 function drawDebugCB() { 608 if (currentNodeController.active) { 609 if (settings.drawInterpolators) { 610 var interp = currentNodeController.inputController; 611 var hierarchy = interp.getHierarchy(); 612 scene.drawAnimationHierarchy(graphicsDevice, shaderManager, camera, hierarchy, hierarchy.numNodes, interp, null, interpolatorColor, boundsColor); 613 } 614 } 615 } 616 617 // Initialize the previous frame time 618 var previousFrameTime = TurbulenzEngine.time; 619 620 var renderFrame = function renderFrameFn() { 621 var skinnedNodes, numSkins, skinnedNode, skin; 622 623 var currentTime = TurbulenzEngine.time; 624 var deltaTime = (currentTime - previousFrameTime); 625 if (deltaTime > 0.1) { 626 deltaTime = 0.1; 627 } 628 cameraController.maxSpeed = (maxSpeed * deltaTime); 629 630 // Update input 631 inputDevice.update(); 632 633 cameraController.update(); 634 635 var deviceWidth = graphicsDevice.width; 636 var deviceHeight = graphicsDevice.height; 637 var aspectRatio = (deviceWidth / deviceHeight); 638 if (aspectRatio !== camera.aspectRatio) { 639 camera.aspectRatio = aspectRatio; 640 camera.updateProjectionMatrix(); 641 } 642 camera.updateViewProjectionMatrix(); 643 644 // Update the current animation by using the node controller 645 // The node controller input is the referenceNodeController 646 currentNodeController.addTime(deltaTime * settings.animScale); 647 648 skinnedNodes = scene.skinnedNodes; 649 numSkins = skinnedNodes.length; 650 651 for (skin = 0; skin < numSkins; skin += 1) { 652 skinnedNode = skinnedNodes[skin]; 653 if (skinnedNode.active) { 654 // The skinned node will peform the update 655 skinnedNode.update(); 656 } 657 } 658 659 scene.update(); 660 661 renderer.update(graphicsDevice, camera, scene, currentTime); 662 663 if (graphicsDevice.beginFrame()) { 664 if (skinnedNode.active) { 665 renderer.setWireframe(settings.drawWireframe); 666 667 if (renderer.updateBuffers(graphicsDevice, deviceWidth, deviceHeight)) { 668 renderer.draw(graphicsDevice, clearColor, null, null, drawDebugCB); 669 } 670 } 671 672 graphicsDevice.endFrame(); 673 } 674 675 previousFrameTime = currentTime; 676 }; 677 678 var intervalID; 679 var loadingLoop = function loadingLoopFn() { 680 if (sceneLoader.complete() && animationsLoaded === 0) { 681 TurbulenzEngine.clearInterval(intervalID); 682 683 // Init the animations from the scene 684 initAnimations(scene); 685 686 // Intial reset of the camera 687 resetCamera(camera, scene); 688 689 // Scene loading is complete, now update the loaded shaders 690 renderer.updateShader(shaderManager); 691 692 intervalID = TurbulenzEngine.setInterval(renderFrame, 1000 / 60); 693 } 694 }; 695 intervalID = TurbulenzEngine.setInterval(loadingLoop, 1000 / 10); 696 697 // Create a scene destroy callback to run when the window is closed 698 TurbulenzEngine.onunload = function destroyScene() { 699 TurbulenzEngine.clearInterval(intervalID); 700 701 if (gameSession) { 702 gameSession.destroy(); 703 gameSession = null; 704 } 705 706 if (scene) { 707 scene.destroy(); 708 scene = null; 709 } 710 711 requestHandler = null; 712 sceneLoader = null; 713 714 htmlControls = null; 715 716 transitionController = null; 717 transitionStartColor = []; 718 transitionEndColor = []; 719 720 currentReferenceController = null; 721 currentNodeController = null; 722 723 if (renderer) { 724 renderer.destroy(); 725 renderer = null; 726 } 727 728 addAnimations = []; 729 removeAnimations = []; 730 731 settings = null; 732 733 cameraController = null; 734 camera = null; 735 cameraDir = []; 736 737 mappingTable = null; 738 739 animMinExtent = []; 740 animMaxExtent = []; 741 742 boundsColor = []; 743 interpolatorColor = []; 744 745 clearColor = []; 746 worldUp = null; 747 748 if (textureManager) { 749 textureManager.destroy(); 750 textureManager = null; 751 } 752 753 if (shaderManager) { 754 shaderManager.destroy(); 755 shaderManager = null; 756 } 757 758 effectManager = null; 759 760 TurbulenzEngine.flush(); 761 graphicsDevice = null; 762 mathDevice = null; 763 inputDevice = null; 764 }; 765 };