topical media & game development

talk show tell print

graphic-webgl-scenejs-examples-morphing-random-morphing-random.js / js



  /*
   Mesh morphing demo
  
   In this example we're copying the vertex positions of a teapot node, multiplying them
   by a sine wave, then wrapping the teapot in a morphGeometry that uses the new postions as a target.
  
   We're then animating the morphGeometry 'factor' attribute in the render loop to peform the morphing.
  
   lindsay.kay@xeolabs.com
  
   github.com/xeolabs/scenejs/wiki/morphGeometry
  
   */
  SceneJS.createScene({
  
    type: "scene",
    id: "theScene",
    canvasId: "theCanvas",
    loggingElementId: "theLoggingDiv",
  
    nodes: [
      {
        type: "lookAt",
        eye : { x: 0.0, y: 10.0, z: 15 },
        look : { y:1.0 },
        up : { y: 1.0 },
  
        nodes: [
          {
            type: "camera",
            optics: {
              type: "perspective",
              fovy : 25.0,
              aspect : 1.47,
              near : 0.10,
              far : 300.0
            },
  
            nodes: [
              {
                type: "light",
                mode:          "dir",
                color:         { r: 1.0, g: 0.5, b: 0.5 },
                diffuse:        true,
                specular:        true,
                dir:          { x: 1.0, y: -1.0, z: -1.0 }
              },
  
              {
                type: "light",
                mode:          "dir",
                color:         { r: 0.5, g: 1.0, b: 0.5 },
                diffuse:        true,
                specular:        true,
                dir:          { x: 0.0, y: -1.0, z: -1.0 }
              },
  
              {
                type: "light",
                mode:          "dir",
                color:         { r: 0.2, g: 0.2, b: 1.0 },
                diffuse:        true,
                specular:        true,
                dir:          { x: -1.0, y: 0.0, z: -1.0 }
              },
              {
                type: "rotate",
                id: "pitch",
                angle: 0.0,
                x : 1.0,
  
                nodes: [
                  {
                    type: "rotate",
                    id: "yaw",
                    angle: 0.0,
                    y : 1.0,
  
                    nodes: [
                      {
                        type: "material",
                        id: "the-material",
  
                        emit: 0,
                        baseColor:   { r: 0.3, g: 0.3, b: 0.9 },
                        specularColor: { r: 0.9, g: 0.9, b: 0.9 },
                        specular:    0.9,
                        shine:     100.0,
  
                        nodes: [
  
                          {
                            type : "teapot",
                            id: "the-teapot"
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  });
  
  /*----------------------------------------------------------------------
   * When the teapot has been rendered, get its positions, multiply them
   * by a sine wave, then wrap the teapot in a morphGeometry that uses the
   * new postions as a target.
   *
   * The teapot node can only provide its positions after it has been
   * rendered.
   *---------------------------------------------------------------------*/
  
  var morphCreated = false;
  
  var scene = SceneJS.scene("theScene");
  
  var teapot = scene.findNode("the-teapot");
  
  function addMorph() {
  
    if (!morphCreated) {
  
      var positions = teapot.get("positions");
      if (positions.length == 0) {
        return;
      }
  
      var positions1 = [];
      for (var i = 0, j = 0, len = positions.length; i < len; i++,j += 3) {
        positions1.push(positions[i]);
      }
      var positions2 = [];
      for (var i = 0, j = 0, len = positions.length; i < len; i++,j += 3) {
        positions2.push(positions[i] * (1 + (Math.sin(i * 0.003) * 0.1)));
      }
      var positions3 = [];
      for (var i = 0, j = 0, len = positions.length; i < len; i++,j += 3) {
        positions3.push(positions[i] * (1 + (Math.sin(i * 0.015) * 0.1)));
      }
  
      teapot.parent().insert({
        node: {
          type: "morphGeometry",
          id: "my-morph-geometry",
  
          keys: [
            0, // Target 1
            1, // Target 2
            3 // target 3
          ],
  
          targets: [
            {
              positions: positions1 // Target 1
            },
            {
              positions: positions2 // Target 2
            },
            {
              positions: positions3 // Target 3
            }
          ],
  
          factor: 0.0
        }
      });
    }
  
    morphCreated = true;
  }
  
  var yaw = 0;
  var pitch = 0;
  var lastX;
  var lastY;
  var dragging = false;
  
  var factor = 0;
  
  var canvas = document.getElementById("theCanvas");
  
  function mouseDown(event) {
    lastX = event.clientX;
    lastY = event.clientY;
    dragging = true;
  }
  
  function touchStart(event) {
    lastX = event.targetTouches[0].clientX;
    lastY = event.targetTouches[0].clientY;
    dragging = true;
  }
  
  function mouseUp() {
    dragging = false;
  }
  
  function touchEnd() {
    dragging = false;
  }
  
  function mouseMove(event) {
    var posX = event.clientX;
    var posY = event.clientY;
    actionMove(posX,posY);
  }
  
  function touchMove(event) {
    var posX = event.targetTouches[0].clientX;
    var posY = event.targetTouches[0].clientY;
    actionMove(posX,posY);
  }
  
  /* On a mouse/touch drag, we'll re-render the scene, passing in
   * incremented angles in each time.
   */
  function actionMove(posX, posY) {
    if (dragging) {
      yaw += (posX - lastX) * 0.5;
      pitch += (posY - lastY) * -0.5;
  
      scene.findNode("yaw").set("angle", yaw);
      scene.findNode("pitch").set("angle", pitch);
  
      lastX = posX;
      lastY = posY;
    }
  }
  
  canvas.addEventListener('mousedown', mouseDown, true);
  canvas.addEventListener('mousemove', mouseMove, true);
  canvas.addEventListener('mouseup', mouseUp, true);
  canvas.addEventListener('touchstart', touchStart, true);
  canvas.addEventListener('touchmove', touchMove, true);
  canvas.addEventListener('touchend', touchEnd, true);
  
  /*----------------------------------------------------------------------
   * In our rendering loop, as soon as the morphGeometry exists, we'll
   * increment its factor to move the morph between its two targets
   *---------------------------------------------------------------------*/
  
  scene.start({
    idleFunc: function() {
      addMorph();
      var morphGeometry = this.findNode("my-morph-geometry");  // Wont exist until created
      if (morphGeometry) {
        morphGeometry.set("factor", 1.0 + (Math.sin(factor) * 2.0));
        factor += 0.1;
      }
    }
  });
  


(C) Æliens 04/09/2009

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.