topical media & game development

talk show tell print

graphic-o3d-samples-box2d-3d-demos-demos.js / js



  This file comes from Box2D-JS, Copyright (c) 2008 ANDO Yasushi.
  The original version is available at http://box2d-js.sourceforge.net/ under the
  zlib/libpng license (see License.txt).
  This version has been modified to make it work with O3D.
  
  o3djs.require('o3djs.util');
  o3djs.require('o3djs.math');
  o3djs.require('o3djs.rendergraph');
  o3djs.require('o3djs.primitives');
  o3djs.require('o3djs.picking');
  
  var initId = 0;
  var world;
  var canvasWidth;
  var canvasHeight;
  var canvasTop;
  var canvasLeft;
  
  function setupWorld(did) {
      var transforms = g.client.getObjectsByClassName('o3d.Transform');
      for (var tt = 0; tt < transforms.length; ++tt) {
        var transform = transforms[tt];
        if (transform.clientId != g.root.clientId &&
            transform.clientId != g.client.root.clientId) {
          transform.parent = null;
          g.pack.removeObject(transform);
        }
      }
    if (!did) did = 0;
    world = createWorld();
    initId += did;
    initId %= demos.InitWorlds.length;
    if (initId < 0) initId = demos.InitWorlds.length + initId;
    demos.InitWorlds[initId](world);
  }
  function setupNextWorld() { setupWorld(1); }
  function setupPrevWorld() { setupWorld(-1); }
  function step(elapsedTime) {
    // NOTE: changed to use the renderEvent's elapsed time instead of
    // javascript timers. The check below makes the physics never do a time step
    // slower that 1/30th of a second because collision bugs will happen.
    if (elapsedTime > 1 / 30) {
      elapsedTime = 1 / 30;
    }
    var stepping = false;
    var timeStep = elapsedTime;
    var iteration = 1;
    if (world) {
      world.Step(timeStep, iteration);
      drawWorld(world);
    }
  }
  
  // When the sample is running in V8, window.g is the browser's global object and
  // g is v8's. When the sample is running only in the browser, they are the same
  // object.
  window.g = {};
  
  // A global object to track stuff with.
  var g = {
    o3dWidth: -1,  // width of our client area
    o3dHeight: -1,  // height of our client area
    materials: [],  // all our materials
    shapes: []  // all our shapes
  };
  
  
Sets up the o3d stuff.
parameter: {HTML element} o3dElement The o3d object element.

  
  function setupO3D(o3dElement) {
    // Initializes global variables and libraries.
    g.o3dElement = o3dElement;
    g.o3d = o3dElement.o3d;
    g.math = o3djs.math;
    g.client = o3dElement.client;
    g.mgr = new O3DManager();
  
    // The browser needs to be able to see these globals so that it can
    // call unload later.
    window.g.client = g.client;
  
    // Get the width and height of our client area.
    g.o3dWidth = g.client.width;
    g.o3dHeight = g.client.height;
  
    // Creates a pack to manage our resources/assets
    g.pack = g.client.createPack();
  
    // Create the render graph for a view.
    g.viewInfo = o3djs.rendergraph.createBasicView(
        g.pack,
        g.client.root,
        g.client.renderGraphRoot);
  
    // Create an object to hold global params.
    g.globalParamObject = g.pack.createObject('ParamObject');
    g.lightWorldPosParam = g.globalParamObject.createParam('lightWorldPos',
                                                           'ParamFloat3');
    g.lightColorParam = g.globalParamObject.createParam('lightColor',
                                                        'ParamFloat4');
    g.lightWorldPosParam.value = [200, -1500, -1000];
    g.lightColorParam.value = [1, 1, 1.0, 1.0];
  
    // Create Materials.
    g.materials = [];
    var material = g.pack.createObject('Material');
    var effect = g.pack.createObject('Effect');
    effect.loadFromFXString(document.getElementById('shader').value);
    material.effect = effect;
    effect.createUniformParameters(material);
    material.getParam('lightWorldPos').bind(g.lightWorldPosParam);
    material.getParam('lightColor').bind(g.lightColorParam);
    material.getParam('emissive').set(0, 0, 0, 1);
    material.getParam('ambient').set(0, 0, 0, 1);
    material.getParam('specular').set(1, 1, 1, 1);
    material.getParam('shininess').value = 20;
    material.drawList = g.viewInfo.performanceDrawList;
    g.materials[0] = material;
  
    // Create a kind of checkboardish texture.
    var pixels = [];
    for (var y = 0; y < 32; ++y) {
      for (var x = 0; x < 32; ++x) {
        var offset = (y * 32 + x) * 3;  // rgb
        var u = x / 32 * Math.PI * 0.5;
        var v = y / 32 * Math.PI * 0.5;
        pixels[offset + 0] = 1;//Math.sin(Math.PI * 32 / x) * 0.2 + 0.8;  // red
        pixels[offset + 1] = Math.floor(x / 8) % 2 * 0.2 + 0.8;  // green
        pixels[offset + 2] = Math.floor(y / 8) % 2 * 0.5 + 0.5;  // blue
      }
    }
    var texture = g.pack.createTexture2D(32, 32, g.o3d.Texture.XRGB8, 1, false);
    texture.set(0, pixels);
    var samplerParam = material.getParam('diffuseSampler');
    var sampler = g.pack.createObject('Sampler');
    samplerParam.value = sampler;
    sampler.texture = texture;
  
    // Creates a transform to put our data on.
    g.root = g.pack.createObject('Transform');
    g.root.parent = g.client.root;
  
    // make a cube for drawing lines
    g.lineShape = o3djs.primitives.createRainbowCube(
        g.pack,
        g.materials[0],
        1,
        g.math.matrix4.translation([0, 0.5, 0]));
  
    // Set the projection matrix
    g.viewInfo.drawContext.projection = g.math.matrix4.perspective(
        g.math.degToRad(45),
        g.o3dWidth / g.o3dHeight,
        0.1,
        10000);
  
    // Set the view matrix.
    g.viewInfo.drawContext.view = g.math.matrix4.lookAt(
        [100, -50, -600],
        [250, 80, 0],
        [0, -1, 0]);
  
    // Make copies of the view and projection matrix to get fast access to them.
    g.projectionMatrix = g.math.copy(g.viewInfo.drawContext.projection);
    g.viewMatrix = g.math.copy(g.viewInfo.drawContext.view);
  
    // Make a bounding box to use for picking.
    g.worldBox = g.o3d.BoundingBox([0, -100, 0],
                                   [500, 250, 5]);
  
    // Steps the physics with a time of zero. This is left over from the orignial
    // code.
    step(0);
  
    g.client.setRenderCallback(o3dOnRender);
  }
  
  
Called just before rendering each frame.
parameter: {o3d.RenderEvent} renderEvent The render event passed by o3d.

  
  function o3dOnRender(renderEvent) {
    var newWidth = g.client.width;
    var newHeight = g.client.height;
    if (newWidth != g.o3dWidth || newHeight != g.o3dHeight) {
      g.o3dWidth = newWidth;
      g.o3dHeight = newHeight;
  
      // Adjust the projection matrix.
      var projectionMatrix = g.math.matrix4.perspective(g.math.degToRad(45),
                                                        g.o3dWidth / g.o3dHeight,
                                                        0.1,
                                                        10000);
      g.viewInfo.drawContext.projection = projectionMatrix;
      g.projectionMatrix = projectionMatrix;
    }
    step(renderEvent.elapsedTime);
  }
  
  
This is the original setup code modified to work with o3d.
parameter: {Array} clientElements Array of o3d objects.

  
  function setupStep2(clientElements) {
    var canvasElm = clientElements[0];
    canvasElm.id = 'canvas';
    setupO3D(canvasElm);
    setupWorld();
    canvasWidth = g.client.width;
    canvasHeight = g.client.height;
    canvasTop = parseInt(canvasElm.style.top);
    canvasLeft = parseInt(canvasElm.style.left);
    o3djs.event.addEventListener(canvasElm, 'mousedown', function(e) {
      if (e.shiftKey || e.button == g.o3d.Event.BUTTON_RIGHT) {
        setupPrevWorld();
      } else {
        createNewRandomObject(world, e);
      }
    });
  
    window.g_finished = true;  // for selenium
  }
  
  
Creates a new random object using 3d picking to figure out where to start it.
parameter: {Object} world A B2World object.
parameter: {Object} offset Mouse position relative to o3d area.

  
  function createNewRandomObject(world, offset) {
    var worldRay = o3djs.picking.clientPositionToWorldRayEx(
        offset.x,
        offset.y,
        g.viewMatrix,
        g.projectionMatrix,
        g.o3dWidth,
        g.o3dHeight);
    var rayIntersectionInfo = g.worldBox.intersectRay(worldRay.near,
                                                      worldRay.far);
    if (rayIntersectionInfo.intersected) {
      var position = rayIntersectionInfo.position;
      if (Math.random() < 0.5) {
        demos.top.createBall(world, position[0], position[1]);
      } else {
        createBox(world, position[0], position[1], 10, 10, false);
      }
    }
  }
  
  function init() {
    window.g_finished = false;  // for selenium.
  
    // Runs the sample in V8. Comment out this line to run it in the browser
    // JavaScript engine, for example if you want to debug it. This sample cannot
    // currently run in V8 on IE because it access the DOM.
    if (!o3djs.base.IsMSIE()) {
      o3djs.util.setMainEngine(o3djs.util.Engine.V8);
      o3djs.util.addScriptUri('third_party');
      o3djs.util.addScriptUri('demos');
      o3djs.util.addScriptUri('style');
    }
  
    o3djs.util.makeClients(setupStep2);
  }
  
  function uninit() {
    if (g.client) {
      g.client.cleanup();
    }
  }
  


(C) Æliens 20/2/2008

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.