summaryrefslogtreecommitdiffstats
path: root/o3d/samples
diff options
context:
space:
mode:
Diffstat (limited to 'o3d/samples')
-rw-r--r--o3d/samples/manipulators/rotate1.html40
-rw-r--r--o3d/samples/manipulators/translate1.html133
-rw-r--r--o3d/samples/manipulators/translate2.html133
-rw-r--r--o3d/samples/o3djs/cameracontroller.js208
-rw-r--r--o3d/samples/o3djs/lineprimitives.js100
-rw-r--r--o3d/samples/o3djs/manipulators.js219
6 files changed, 675 insertions, 158 deletions
diff --git a/o3d/samples/manipulators/rotate1.html b/o3d/samples/manipulators/rotate1.html
index 49f56f3..0b418db 100644
--- a/o3d/samples/manipulators/rotate1.html
+++ b/o3d/samples/manipulators/rotate1.html
@@ -52,6 +52,7 @@ o3djs.require('o3djs.rendergraph');
o3djs.require('o3djs.primitives');
o3djs.require('o3djs.manipulators');
o3djs.require('o3djs.effect');
+o3djs.require('o3djs.cameracontroller');
// global variables
var g_o3dElement;
@@ -62,10 +63,10 @@ var g_mainPack;
var g_mainViewInfo;
var g_mainRoot;
var g_lightPosition = [5, 5, 7];
-var g_eyePosition = [1, 5, 23];
var g_lastCubeTransform;
var g_primitives = [];
var g_manager;
+var g_cameraController;
/**
* Creates the client area.
@@ -110,14 +111,20 @@ function main(clientElements) {
}
function onMouseDown(e) {
- g_manager.mousedown(e.x, e.y,
- g_mainViewInfo.drawContext.view,
- g_mainViewInfo.drawContext.projection,
- g_client.width,
- g_client.height);
+ if(e.button == 2) {
+ g_cameraController.mousedown(e);
+ } else {
+ g_manager.mousedown(e.x, e.y,
+ g_mainViewInfo.drawContext.view,
+ g_mainViewInfo.drawContext.projection,
+ g_client.width,
+ g_client.height);
+ }
}
function onMouseMove(e) {
+ g_cameraController.mousemove(e);
+ g_mainViewInfo.drawContext.view = g_cameraController.calculateViewMatrix();
g_manager.mousemove(e.x, e.y,
g_mainViewInfo.drawContext.view,
g_mainViewInfo.drawContext.projection,
@@ -127,8 +134,12 @@ function onMouseMove(e) {
}
function onMouseUp(e) {
- g_manager.mouseup();
- g_manager.updateInactiveManipulators();
+ if(e.button == 2) {
+ g_cameraController.mouseup(e);
+ } else {
+ g_manager.mouseup();
+ g_manager.updateInactiveManipulators();
+ }
}
/**
@@ -164,12 +175,13 @@ function initContext() {
1, // Near plane.
5000); // Far plane.
- // Set up our view transformation to look towards the world origin where the
- // primitives are located.
- g_mainViewInfo.drawContext.view = g_math.matrix4.lookAt(
- g_eyePosition, // eye
- [0, 2, 0], // target
- [0, 1, 0]); // up
+ // Set up our view transformation using our CameraController.
+ g_cameraController = o3djs.cameracontroller.createCameraController(
+ [0, 2, 0], // centerPos
+ 23, // backpedal
+ 0, // heightAngle
+ 0); // rotationAngle
+ g_mainViewInfo.drawContext.view = g_cameraController.calculateViewMatrix();
}
/**
diff --git a/o3d/samples/manipulators/translate1.html b/o3d/samples/manipulators/translate1.html
index 7debeae..c8eb98e 100644
--- a/o3d/samples/manipulators/translate1.html
+++ b/o3d/samples/manipulators/translate1.html
@@ -52,20 +52,21 @@ o3djs.require('o3djs.rendergraph');
o3djs.require('o3djs.primitives');
o3djs.require('o3djs.manipulators');
o3djs.require('o3djs.effect');
+o3djs.require('o3djs.cameracontroller');
// global variables
var g_o3dElement;
var g_client;
var g_o3d;
var g_math;
-var g_pack;
-var g_viewInfo;
-
+var g_mainPack;
+var g_mainViewInfo;
+var g_mainRoot;
var g_lightPosition = [5, 5, 7];
-var g_eyePosition = [1, 5, 23];
-
+var g_lastCubeTransform;
var g_primitives = [];
var g_manager;
+var g_cameraController;
/**
* Creates the client area.
@@ -92,15 +93,15 @@ function main(clientElements) {
// Init global variables.
initGlobals(clientElements);
- // Set up the view and projection transformations.
- initContext();
-
// Add the shapes to the transform heirarchy.
createShapes();
// Add the manipulators to the transform hierarchy.
createManipulators();
+ // Set up the view and projection transformations.
+ initContext();
+
// Start picking; it won't do anything until the scene finishes loading.
o3djs.event.addEventListener(o3dElement, 'mousedown', onMouseDown);
o3djs.event.addEventListener(o3dElement, 'mousemove', onMouseMove);
@@ -110,25 +111,35 @@ function main(clientElements) {
}
function onMouseDown(e) {
- g_manager.mousedown(e.x, e.y,
- g_viewInfo.drawContext.view,
- g_viewInfo.drawContext.projection,
- g_client.width,
- g_client.height);
+ if(e.button == 2) {
+ g_cameraController.mousedown(e);
+ } else {
+ g_manager.mousedown(e.x, e.y,
+ g_mainViewInfo.drawContext.view,
+ g_mainViewInfo.drawContext.projection,
+ g_client.width,
+ g_client.height);
+ }
}
function onMouseMove(e) {
+ g_cameraController.mousemove(e);
+ g_mainViewInfo.drawContext.view = g_cameraController.calculateViewMatrix();
g_manager.mousemove(e.x, e.y,
- g_viewInfo.drawContext.view,
- g_viewInfo.drawContext.projection,
+ g_mainViewInfo.drawContext.view,
+ g_mainViewInfo.drawContext.projection,
g_client.width,
g_client.height);
g_manager.updateInactiveManipulators();
}
function onMouseUp(e) {
- g_manager.mouseup();
- g_manager.updateInactiveManipulators();
+ if(e.button == 2) {
+ g_cameraController.mouseup(e);
+ } else {
+ g_manager.mouseup();
+ g_manager.updateInactiveManipulators();
+ }
}
/**
@@ -141,12 +152,15 @@ function initGlobals(clientElements) {
g_math = o3djs.math;
// Create a pack to manage the objects created.
- g_pack = g_client.createPack();
+ g_mainPack = g_client.createPack();
+
+ // Make a root transform for our scene.
+ g_mainRoot = g_mainPack.createObject('Transform');
- // Create the render graph for a view.
- g_viewInfo = o3djs.rendergraph.createBasicView(
- g_pack,
- g_client.root,
+ // Create the render graph for the scene view.
+ g_mainViewInfo = o3djs.rendergraph.createBasicView(
+ g_mainPack,
+ g_mainRoot,
g_client.renderGraphRoot);
}
@@ -155,18 +169,19 @@ function initGlobals(clientElements) {
*/
function initContext() {
// Set up a perspective transformation for the projection.
- g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
- g_math.degToRad(30), // 30 degree frustum.
+ g_mainViewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(30), // 30 degree frustum.
g_o3dElement.clientWidth / g_o3dElement.clientHeight, // Aspect ratio.
- 1, // Near plane.
- 5000); // Far plane.
-
- // Set up our view transformation to look towards the world origin where the
- // primitives are located.
- g_viewInfo.drawContext.view = g_math.matrix4.lookAt(
- g_eyePosition, // eye
- [0, 2, 0], // target
- [0, 1, 0]); // up
+ 1, // Near plane.
+ 5000); // Far plane.
+
+ // Set up our view transformation using our CameraController.
+ g_cameraController = o3djs.cameracontroller.createCameraController(
+ [0, 2, 0], // centerPos
+ 23, // backpedal
+ 0, // heightAngle
+ 0); // rotationAngle
+ g_mainViewInfo.drawContext.view = g_cameraController.calculateViewMatrix();
}
/**
@@ -175,7 +190,8 @@ function initContext() {
*/
function createShapes() {
// Create a little tree-like hierarchy of cubes
- createCubeTree(2, 1.5, [0, 0, 0], g_client.root);
+ createCubeTree(2, 1.5, [0, 0, 0], g_mainRoot);
+ g_lastCubeTransform.scale(3, 1, 1);
}
/**
@@ -210,13 +226,14 @@ function createCubeTree(depth, edgeLength, translation, parent) {
*/
function createCube(edgeLength, opt_translation, opt_parent) {
var cube = o3djs.primitives.createCube(
- g_pack,
+ g_mainPack,
// A green phong-shaded material.
- o3djs.material.createBasicMaterial(g_pack,
- g_viewInfo,
+ o3djs.material.createBasicMaterial(g_mainPack,
+ g_mainViewInfo,
[0, 1, 0, 1]),
edgeLength);
- var transform = g_pack.createObject('Transform');
+ var transform = g_mainPack.createObject('Transform');
+ g_lastCubeTransform = transform;
transform.addShape(cube);
if (opt_translation) {
transform.translate(opt_translation);
@@ -224,7 +241,7 @@ function createCube(edgeLength, opt_translation, opt_parent) {
if (opt_parent) {
transform.parent = opt_parent;
} else {
- transform.parent = g_client.root;
+ transform.parent = g_mainRoot;
}
g_primitives.push(transform);
return transform;
@@ -234,11 +251,39 @@ function createCube(edgeLength, opt_translation, opt_parent) {
* Creates manipulators attached to the objects we've just created.
*/
function createManipulators() {
- g_manager = o3djs.manipulators.createManager(g_pack,
- g_viewInfo.performanceDrawList,
- g_client.root,
- null,
- 0);
+ // Create a separate pack for the manipulators so they don't get mixed in
+ // with the main scene's objects.
+ var pack = g_client.createPack();
+
+ // Create a root transform for the manipulators so they are 100% separate
+ // from the scene's transforms.
+ var manipulatorRoot = pack.createObject('Transform');
+
+ // Create the render graph for the manipulators view that uses the same
+ // DrawContext as the main view.
+ var manipulatorViewInfo = o3djs.rendergraph.createView(
+ pack,
+ manipulatorRoot,
+ g_client.renderGraphRoot,
+ undefined, // clearColor
+ undefined, // priority
+ undefined, // viewport
+ undefined, // performanceDrawList
+ undefined, // zOrderedDrawList
+ g_mainViewInfo.drawContext);
+
+ // Make sure the manipulators gets drawn after the scene.
+ manipulatorViewInfo.root.priority = g_mainViewInfo.root.priority + 1;
+
+ // Turn off clearing the color for the manipulators.
+ manipulatorViewInfo.clearBuffer.clearColorFlag = false;
+
+ g_manager = o3djs.manipulators.createManager(
+ pack,
+ manipulatorViewInfo.performanceDrawList,
+ manipulatorRoot,
+ null,
+ 0);
var jj = 2;
for (var ii = 0; ii < g_primitives.length; ii++) {
var manip = g_manager.createTranslate1();
diff --git a/o3d/samples/manipulators/translate2.html b/o3d/samples/manipulators/translate2.html
index f9cbff7..3946d74 100644
--- a/o3d/samples/manipulators/translate2.html
+++ b/o3d/samples/manipulators/translate2.html
@@ -52,20 +52,21 @@ o3djs.require('o3djs.rendergraph');
o3djs.require('o3djs.primitives');
o3djs.require('o3djs.manipulators');
o3djs.require('o3djs.effect');
+o3djs.require('o3djs.cameracontroller');
// global variables
var g_o3dElement;
var g_client;
var g_o3d;
var g_math;
-var g_pack;
-var g_viewInfo;
-
+var g_mainPack;
+var g_mainViewInfo;
+var g_mainRoot;
var g_lightPosition = [5, 5, 7];
-var g_eyePosition = [1, 5, 23];
-
+var g_lastCubeTransform;
var g_primitives = [];
var g_manager;
+var g_cameraController;
/**
* Creates the client area.
@@ -92,15 +93,15 @@ function main(clientElements) {
// Init global variables.
initGlobals(clientElements);
- // Set up the view and projection transformations.
- initContext();
-
// Add the shapes to the transform heirarchy.
createShapes();
// Add the manipulators to the transform hierarchy.
createManipulators();
+ // Set up the view and projection transformations.
+ initContext();
+
// Start picking; it won't do anything until the scene finishes loading.
o3djs.event.addEventListener(o3dElement, 'mousedown', onMouseDown);
o3djs.event.addEventListener(o3dElement, 'mousemove', onMouseMove);
@@ -110,25 +111,35 @@ function main(clientElements) {
}
function onMouseDown(e) {
- g_manager.mousedown(e.x, e.y,
- g_viewInfo.drawContext.view,
- g_viewInfo.drawContext.projection,
- g_client.width,
- g_client.height);
+ if(e.button == 2) {
+ g_cameraController.mousedown(e);
+ } else {
+ g_manager.mousedown(e.x, e.y,
+ g_mainViewInfo.drawContext.view,
+ g_mainViewInfo.drawContext.projection,
+ g_client.width,
+ g_client.height);
+ }
}
function onMouseMove(e) {
+ g_cameraController.mousemove(e);
+ g_mainViewInfo.drawContext.view = g_cameraController.calculateViewMatrix();
g_manager.mousemove(e.x, e.y,
- g_viewInfo.drawContext.view,
- g_viewInfo.drawContext.projection,
+ g_mainViewInfo.drawContext.view,
+ g_mainViewInfo.drawContext.projection,
g_client.width,
g_client.height);
g_manager.updateInactiveManipulators();
}
function onMouseUp(e) {
- g_manager.mouseup();
- g_manager.updateInactiveManipulators();
+ if(e.button == 2) {
+ g_cameraController.mouseup(e);
+ } else {
+ g_manager.mouseup();
+ g_manager.updateInactiveManipulators();
+ }
}
/**
@@ -141,12 +152,15 @@ function initGlobals(clientElements) {
g_math = o3djs.math;
// Create a pack to manage the objects created.
- g_pack = g_client.createPack();
+ g_mainPack = g_client.createPack();
+
+ // Make a root transform for our scene.
+ g_mainRoot = g_mainPack.createObject('Transform');
- // Create the render graph for a view.
- g_viewInfo = o3djs.rendergraph.createBasicView(
- g_pack,
- g_client.root,
+ // Create the render graph for the scene view.
+ g_mainViewInfo = o3djs.rendergraph.createBasicView(
+ g_mainPack,
+ g_mainRoot,
g_client.renderGraphRoot);
}
@@ -155,18 +169,19 @@ function initGlobals(clientElements) {
*/
function initContext() {
// Set up a perspective transformation for the projection.
- g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
- g_math.degToRad(30), // 30 degree frustum.
+ g_mainViewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(30), // 30 degree frustum.
g_o3dElement.clientWidth / g_o3dElement.clientHeight, // Aspect ratio.
- 1, // Near plane.
- 5000); // Far plane.
-
- // Set up our view transformation to look towards the world origin where the
- // primitives are located.
- g_viewInfo.drawContext.view = g_math.matrix4.lookAt(
- g_eyePosition, // eye
- [0, 2, 0], // target
- [0, 1, 0]); // up
+ 1, // Near plane.
+ 5000); // Far plane.
+
+ // Set up our view transformation using our CameraController.
+ g_cameraController = o3djs.cameracontroller.createCameraController(
+ [0, 2, 0], // centerPos
+ 23, // backpedal
+ 0, // heightAngle
+ 0); // rotationAngle
+ g_mainViewInfo.drawContext.view = g_cameraController.calculateViewMatrix();
}
/**
@@ -175,7 +190,8 @@ function initContext() {
*/
function createShapes() {
// Create a little tree-like hierarchy of cubes
- createCubeTree(2, 1.5, [0, 0, 0], g_client.root);
+ createCubeTree(2, 1.5, [0, 0, 0], g_mainRoot);
+ g_lastCubeTransform.scale(3, 1, 1);
}
/**
@@ -210,13 +226,14 @@ function createCubeTree(depth, edgeLength, translation, parent) {
*/
function createCube(edgeLength, opt_translation, opt_parent) {
var cube = o3djs.primitives.createCube(
- g_pack,
+ g_mainPack,
// A green phong-shaded material.
- o3djs.material.createBasicMaterial(g_pack,
- g_viewInfo,
+ o3djs.material.createBasicMaterial(g_mainPack,
+ g_mainViewInfo,
[0, 1, 0, 1]),
edgeLength);
- var transform = g_pack.createObject('Transform');
+ var transform = g_mainPack.createObject('Transform');
+ g_lastCubeTransform = transform;
transform.addShape(cube);
if (opt_translation) {
transform.translate(opt_translation);
@@ -224,7 +241,7 @@ function createCube(edgeLength, opt_translation, opt_parent) {
if (opt_parent) {
transform.parent = opt_parent;
} else {
- transform.parent = g_client.root;
+ transform.parent = g_mainRoot;
}
g_primitives.push(transform);
return transform;
@@ -234,11 +251,39 @@ function createCube(edgeLength, opt_translation, opt_parent) {
* Creates manipulators attached to the objects we've just created.
*/
function createManipulators() {
- g_manager = o3djs.manipulators.createManager(g_pack,
- g_viewInfo.performanceDrawList,
- g_client.root,
- null,
- 0);
+ // Create a separate pack for the manipulators so they don't get mixed in
+ // with the main scene's objects.
+ var pack = g_client.createPack();
+
+ // Create a root transform for the manipulators so they are 100% separate
+ // from the scene's transforms.
+ var manipulatorRoot = pack.createObject('Transform');
+
+ // Create the render graph for the manipulators view that uses the same
+ // DrawContext as the main view.
+ var manipulatorViewInfo = o3djs.rendergraph.createView(
+ pack,
+ manipulatorRoot,
+ g_client.renderGraphRoot,
+ undefined, // clearColor
+ undefined, // priority
+ undefined, // viewport
+ undefined, // performanceDrawList
+ undefined, // zOrderedDrawList
+ g_mainViewInfo.drawContext);
+
+ // Make sure the manipulators gets drawn after the scene.
+ manipulatorViewInfo.root.priority = g_mainViewInfo.root.priority + 1;
+
+ // Turn off clearing the color for the manipulators.
+ manipulatorViewInfo.clearBuffer.clearColorFlag = false;
+
+ g_manager = o3djs.manipulators.createManager(
+ pack,
+ manipulatorViewInfo.performanceDrawList,
+ manipulatorRoot,
+ null,
+ 0);
var jj = 2;
for (var ii = 0; ii < g_primitives.length; ii++) {
var manip = g_manager.createTranslate2();
diff --git a/o3d/samples/o3djs/cameracontroller.js b/o3d/samples/o3djs/cameracontroller.js
new file mode 100644
index 0000000..9dcb980
--- /dev/null
+++ b/o3d/samples/o3djs/cameracontroller.js
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**
+ * @fileoverview This file contains sample code for controlling the camera
+ * (ie view matrix) using the mouse and keyboard.
+ */
+
+o3djs.provide('o3djs.cameracontroller');
+
+o3djs.require('o3djs.math');
+
+/**
+ * A Module for user control of the camera / view matrix.
+ * @namespace
+ */
+o3djs.cameracontroller = o3djs.cameracontroller || {};
+
+/**
+ * Creates a CameraController.
+ * @param {!o3djs.math.Vector3} centerPos The position that the camera is
+ * looking at and rotating around; or if backpedal is zero, the location
+ * of the camera. In world space.
+ * @param {number} backpedal The distance the camera moves back from the
+ * centerPos.
+ * @param {number} heightAngle The angle the camera rotates up or down
+ * (about the x axis that passes through the centerPos). In radians.
+ * @param {number} rotationAngle The angle the camera rotates left or right
+ * (about the y axis that passes through the centerPos). In radians.
+ * @param {function(!o3djs.cameracontroller.CameraController): void}
+ * opt_onchange Pointer to a callback to call when the camera changes.
+ * @return {!o3djs.cameracontroller.CameraController} The created
+ * CameraController.
+ */
+o3djs.cameracontroller.createCameraController = function(centerPos,
+ backpedal,
+ heightAngle,
+ rotationAngle,
+ opt_onchange) {
+ return new o3djs.cameracontroller.CameraController(centerPos,
+ backpedal,
+ heightAngle,
+ rotationAngle,
+ opt_onchange);
+};
+
+/**
+ * Class to hold user-controlled camera information and handle user events.
+ * @constructor
+ * @param {!o3djs.math.Vector3} centerPos The position that the camera is
+ * looking at and rotating around; or if backpedal is zero, the location
+ * of the camera. In world space.
+ * @param {number} backpedal The distance the camera moves back from the
+ * centerPos.
+ * @param {number} heightAngle The angle the camera rotates up or down
+ * (about the x axis that passes through the centerPos). In radians.
+ * @param {number} rotationAngle The angle the camera rotates left or right
+ * (about the y axis that passes through the centerPos). In radians.
+ * @param {function(!o3djs.cameracontroller.CameraController): void}
+ * opt_onchange Pointer to a callback to call when the camera changes.
+ */
+o3djs.cameracontroller.CameraController = function(centerPos,
+ backpedal,
+ heightAngle,
+ rotationAngle,
+ opt_onchange) {
+ /**
+ * The position that the camera is looking at and rotating around.
+ * Or if backpedal is zero, the location of the camera. In world space.
+ * @type {!o3djs.math.Vector3}
+ */
+ this.centerPos = centerPos;
+
+ /**
+ * The distance the camera moves back from the centerPos.
+ * @type {number}
+ */
+ this.backpedal = backpedal;
+
+ /**
+ * The angle the camera rotates up or down.
+ * @type {number}
+ */
+ this.heightAngle = heightAngle;
+
+ /**
+ * The angle the camera rotates left or right.
+ * @type {number}
+ */
+ this.rotationAngle = rotationAngle;
+
+
+ /**
+ * Points to a callback to call when the camera changes.
+ * @type {function(!o3djs.cameracontroller.CameraController): void}
+ */
+ this.onchange = opt_onchange || null;
+
+ /**
+ * Whether the mouse is currently being dragged to control the camera.
+ * @private
+ * @type {boolean}
+ */
+ this.dragging_ = false;
+
+ /**
+ * The last X coordinate of the mouse.
+ * @private
+ * @type {number}
+ */
+ this.mouseX_ = 0;
+
+ /**
+ * The last Y coordinate of the mouse.
+ * @private
+ * @type {number}
+ */
+ this.mouseY_ = 0;
+
+ /**
+ * Controls how quickly the mouse moves the camera.
+ * @type {number}
+ */
+ this.dragScaleFactor = 300.0;
+};
+
+/**
+ * Calculates the view matrix for this camera.
+ * @return {!o3djs.math.Matrix4} The view matrix.
+ */
+o3djs.cameracontroller.CameraController.prototype.calculateViewMatrix = function() {
+ var matrix4 = o3djs.math.matrix4;
+ var view = matrix4.translation(o3djs.math.negativeVector(this.centerPos));
+ view = matrix4.mul(view, matrix4.rotationY(this.rotationAngle));
+ view = matrix4.mul(view, matrix4.rotationX(this.heightAngle));
+ view = matrix4.mul(view, matrix4.translation([0, 0, -this.backpedal]));
+ return view;
+};
+
+/**
+ * Method which should be called by end user code upon receiving a
+ * mouse-down event.
+ * @param {!o3d.Event} ev The event.
+ */
+o3djs.cameracontroller.CameraController.prototype.mousedown = function(ev) {
+ this.dragging_ = true;
+ this.mouseX_ = ev.x;
+ this.mouseY_ = ev.y;
+};
+
+/**
+ * Method which should be called by end user code upon receiving a
+ * mouse-up event.
+ * @param {!o3d.Event} ev The event.
+ */
+o3djs.cameracontroller.CameraController.prototype.mouseup = function(ev) {
+ this.dragging_ = false;
+};
+
+/**
+ * Method which should be called by end user code upon receiving a
+ * mouse-move event.
+ * @param {!o3d.Event} ev The event.
+ */
+o3djs.cameracontroller.CameraController.prototype.mousemove = function(ev) {
+ if (this.dragging_) {
+ var curX = ev.x;
+ var curY = ev.y;
+ var deltaX = (curX - this.mouseX_) / this.dragScaleFactor;
+ var deltaY = (curY - this.mouseY_) / this.dragScaleFactor;
+ this.mouseX_ = curX;
+ this.mouseY_ = curY;
+ this.rotationAngle += deltaX;
+ this.heightAngle += deltaY;
+ if (this.onchange != null) {
+ this.onchange(this);
+ }
+ }
+};
diff --git a/o3d/samples/o3djs/lineprimitives.js b/o3d/samples/o3djs/lineprimitives.js
index 8a5d1d6..8e4d923 100644
--- a/o3d/samples/o3djs/lineprimitives.js
+++ b/o3d/samples/o3djs/lineprimitives.js
@@ -129,10 +129,10 @@ o3djs.lineprimitives.createLineVertexInfo = function() {
};
/**
- * Creates the vertices and indices for a cube of lines. The
- * cube will be created around the origin. (-size / 2, size / 2)
+ * Creates the vertices and indices for a cube of lines.
+ * The cube will be created around the origin (-size / 2, size / 2).
* The created cube has a position stream only and can therefore only be used
- * with shaders that support those a position stream.
+ * with appropriate shaders.
*
* @param {number} size Width, height and depth of the cube.
* @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply all
@@ -188,8 +188,12 @@ o3djs.lineprimitives.createLineCubeVertices = function(size, opt_matrix) {
/**
* Creates a cube of lines.
- * @param {!o3d.Pack} pack Pack to create sphere elements in.
- * @param {!o3d.Material} material to use.
+ * The cube will be created around the origin (-size / 2, size / 2).
+ * The created cube has a position stream only and can therefore only be used
+ * with appropriate shaders.
+ *
+ * @param {!o3d.Pack} pack Pack to create cube elements in.
+ * @param {!o3d.Material} material Material to use.
* @param {number} size Width, height and depth of the cube.
* @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply all
* the vertices.
@@ -208,11 +212,11 @@ o3djs.lineprimitives.createLineCube = function(
/**
* Creates sphere vertices.
* The created sphere has a position stream only and can therefore only be
- * used with shaders that support those a position stream.
+ * used with appropriate shaders.
*
* @param {number} radius radius of the sphere.
* @param {number} subdivisionsAxis number of steps around the sphere.
- * @param {number} subdivisionsHeight number of vertically on the sphere.
+ * @param {number} subdivisionsHeight number of steps vertically on the sphere.
* @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply all
* the vertices.
* @return {!o3djs.lineprimitives.LineVertexInfo} The created sphere vertices.
@@ -274,15 +278,14 @@ o3djs.lineprimitives.createLineSphereVertices = function(
/**
* Creates a sphere.
- * The created sphere has position, normal, uv and vertex color streams only
- * and can therefore only be used with shaders that support those 4
- * streams.
+ * The created sphere has a position stream only and can therefore only be
+ * used with appropriate shaders.
*
* @param {!o3d.Pack} pack Pack to create sphere elements in.
- * @param {!o3d.Material} material to use.
+ * @param {!o3d.Material} material Material to use.
* @param {number} radius radius of the sphere.
* @param {number} subdivisionsAxis number of steps around the sphere.
- * @param {number} subdivisionsHeight number of vertically on the sphere.
+ * @param {number} subdivisionsHeight number of steps vertically on the sphere.
* @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply all
* the vertices.
* @return {!o3d.Shape} The created sphere.
@@ -306,3 +309,76 @@ o3djs.lineprimitives.createLineSphere = function(
return vertexInfo.createShape(pack, material);
};
+/**
+ * Creates ring vertices.
+ * The ring is a circle in the XZ plane, centered at the origin.
+ * The created ring has a position stream and a normal stream.
+ * The normals point outwards from the center of the ring.
+ *
+ * @param {number} radius Radius of the ring.
+ * @param {number} subdivisions Number of steps around the ring.
+ * @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply all
+ * the vertices.
+ * @return {!o3djs.lineprimitives.LineVertexInfo} The created ring vertices.
+ */
+o3djs.lineprimitives.createLineRingVertices = function(
+ radius,
+ subdivisions,
+ opt_matrix) {
+ if (subdivisions < 3) {
+ throw Error('subdivisions must be >= 3');
+ }
+
+ var vertexInfo = o3djs.lineprimitives.createLineVertexInfo();
+ var positionStream = vertexInfo.addStream(
+ 3, o3djs.base.o3d.Stream.POSITION);
+ var normalStream = vertexInfo.addStream(
+ 3, o3djs.base.o3d.Stream.NORMAL);
+
+ // Generate the individual vertices in our vertex buffer.
+ for (var i = 0; i < subdivisions; i++) {
+ var theta = 2 * Math.PI * i / subdivisions;
+ positionStream.addElement(radius * Math.cos(theta), 0,
+ radius * Math.sin(theta));
+ normalStream.addElement(Math.cos(theta), 0, Math.sin(theta));
+ }
+
+ // Connect the vertices by simple lines.
+ for (var i = 0; i < subdivisions; i++) {
+ vertexInfo.addLine(i, (i+1) % subdivisions);
+ }
+
+ if (opt_matrix) {
+ vertexInfo.reorient(opt_matrix);
+ }
+ return vertexInfo;
+};
+
+/**
+ * Creates a ring.
+ * The ring is a circle in the XZ plane, centered at the origin.
+ * The created ring has a position stream only and can therefore only be
+ * used with appropriate shaders.
+ *
+ * @param {!o3d.Pack} pack Pack to create ring elements in.
+ * @param {!o3d.Material} material Material to use.
+ * @param {number} radius Radius of the ring.
+ * @param {number} subdivisions Number of steps around the ring.
+ * @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply all
+ * the vertices.
+ * @return {!o3d.Shape} The created ring.
+ */
+o3djs.lineprimitives.createLineRing = function(
+ pack,
+ material,
+ radius,
+ subdivisions,
+ opt_matrix) {
+ var vertexInfo = o3djs.lineprimitives.createLineRingVertices(
+ radius,
+ subdivisions,
+ opt_matrix);
+
+ return vertexInfo.createShape(pack, material);
+};
+
diff --git a/o3d/samples/o3djs/manipulators.js b/o3d/samples/o3djs/manipulators.js
index 85fb611..76db16c 100644
--- a/o3d/samples/o3djs/manipulators.js
+++ b/o3d/samples/o3djs/manipulators.js
@@ -37,6 +37,8 @@
o3djs.provide('o3djs.manipulators');
+o3djs.require('o3djs.lineprimitives');
+
o3djs.require('o3djs.material');
o3djs.require('o3djs.math');
@@ -491,18 +493,17 @@ o3djs.manipulators.Manager = function(pack,
this.lightPosition = [10, 10, 10];
/**
- * The default material for manipulators (used when not highlighted).
+ * A constant-shaded material, useful for line geometry in some manipulators.
+ *
+ * TODO(simonrad): This is currently used for Translate1+2 polygon geometry.
+ * We should change polygon geometry back to using phong shader. We should
+ * use this constant shader for Translate1+2 line geometry, if we add it.
+ * Rotate1 line geometry uses a different, special shader.
+ *
* @type {!o3d.Material}
*/
- this.defaultMaterial =
- this.createMaterial_(o3djs.manipulators.DEFAULT_COLOR);
- /**
- * The material used for manipulators when they are highlighted.
- * (TODO(simonrad): This is not currently used; only defaultMaterial is used. Remove this?)
- * @type {!o3d.Material}
- */
- this.highlightedMaterial =
- this.createMaterial_(o3djs.manipulators.HIGHLIGHTED_COLOR);
+ this.constantMaterial =
+ this.createConstantMaterial_(o3djs.manipulators.DEFAULT_COLOR);
/**
* A map from the manip's parent Transform clientId to the manip.
@@ -512,10 +513,9 @@ o3djs.manipulators.Manager = function(pack,
/**
* A PickManager to manage picking for the manipulators.
- * @type {!o3djs.picking.TransformInfo}
+ * @type {!o3djs.picking.PickManager}
*/
- this.pickManager =
- o3djs.picking.createPickManager(this.parentTransform);
+ this.pickManager = o3djs.picking.createPickManager(this.parentTransform);
/**
* The currently-highlighted manipulator.
@@ -532,19 +532,24 @@ o3djs.manipulators.Manager = function(pack,
}
/**
- * Creates a material based on the given single color.
+ * Creates a constant-shaded material based on the given single color.
* @private
* @param {!o3djs.math.Vector4} baseColor A vector with 4 entries, the
* R,G,B, and A components of a color.
- * @return {!o3d.Material} A phong material whose overall pigment is baseColor.
+ * @return {!o3d.Material} A constant material whose overall pigment is baseColor.
*/
-o3djs.manipulators.Manager.prototype.createMaterial_ =
+o3djs.manipulators.Manager.prototype.createConstantMaterial_ =
function(baseColor) {
- // Create a new, empty Material object.
return o3djs.material.createConstantMaterialEx(
this.pack, this.drawList, baseColor);
}
+// TODO(simonrad): Add phong shader back in. We need it for the solid cones
+// of the Translate1+2 manipulators. Note that for highlighting, the phong
+// shader uses diffuse param and the constant shader uses emissive param, so
+// we'll need to either change that or split them onto separate transforms.
+// Probably the former would be better.
+
/**
* Creates a new Translate1 manipulator. A Translate1 moves along the
* X axis in its local coordinate system.
@@ -586,8 +591,6 @@ o3djs.manipulators.Manager.prototype.createRotate1 = function() {
o3djs.manipulators.Manager.prototype.add_ = function(manip) {
// Generate draw elements for the manipulator's transform
manip.getTransform().createDrawElements(this.pack, null);
- // Add the manipulator's transform to the parent transform
- manip.getBaseTransform_().parent = this.parentTransform;
// Add the manipulator into our managed list
this.manipsByClientId[manip.getTransform().clientId] = manip;
}
@@ -628,8 +631,13 @@ o3djs.manipulators.Manager.prototype.handleMouse_ = function(x,
// Find which manipulator we picked.
// NOTE this assumes some things about the transform graph
// structure of the manipulators.
+ // We may need to index by the parent-parent transform instead, since the
+ // shape could be attached to the manip's invisibleTransform_, which is a
+ // child of the localTransform_.
var manip =
- this.manipsByClientId[pickResult.shapeInfo.parent.transform.clientId];
+ this.manipsByClientId[pickResult.shapeInfo.parent.transform.clientId] ||
+ this.manipsByClientId[
+ pickResult.shapeInfo.parent.parent.transform.clientId];
func(this, pickResult, manip);
} else {
func(this, null, null);
@@ -808,9 +816,28 @@ o3djs.manipulators.Manip = function(manager) {
*/
this.baseTransform_ = pack.createObject('Transform');
+ /**
+ * This child transform is used only to hold any invisible shapes
+ * we may want. Invisible shapes can be useful for picking. Visibility is
+ * controlled by the transform, which is why we need this transform.
+ * The local matrix of this transform should only be the identity matrix.
+ * @private
+ * @type {!o3d.Transform}
+ */
+ this.invisibleTransform_ = pack.createObject('Transform');
+ this.invisibleTransform_.visible = false;
+
// Hook up these transforms
+ this.invisibleTransform_.parent = this.localTransform_;
this.localTransform_.parent = this.offsetTransform_;
this.offsetTransform_.parent = this.baseTransform_;
+ this.baseTransform_.parent = manager.parentTransform;
+
+ // Make the invisible transform pickable even though it's invisible
+ manager.pickManager.update();
+ var invisibleTransformInfo = manager.pickManager.getTransformInfo(
+ this.invisibleTransform_);
+ invisibleTransformInfo.pickableEvenIfInvisible = true;
/**
* This is the transform in the scene graph to which this
@@ -833,10 +860,19 @@ o3djs.manipulators.Manip = function(manager) {
* Adds shapes to the internal transform of this manipulator.
* @private
* @param {!Array.<!o3d.Shape>} shapes Array of shapes to add.
+ * @param {boolean} opt_visible Whether the added shapes should be visible.
+ * Default = true. Invisible geometry can be useful for picking.
*/
-o3djs.manipulators.Manip.prototype.addShapes_ = function(shapes) {
+o3djs.manipulators.Manip.prototype.addShapes_ = function(shapes, opt_visible) {
+ if (opt_visible == undefined) {
+ opt_visible = true;
+ }
for (var ii = 0; ii < shapes.length; ii++) {
- this.localTransform_.addShape(shapes[ii]);
+ if(opt_visible) {
+ this.localTransform_.addShape(shapes[ii]);
+ } else {
+ this.invisibleTransform_.addShape(shapes[ii]);
+ }
}
}
@@ -1145,7 +1181,7 @@ o3djs.manipulators.Translate1 = function(manager) {
o3djs.manipulators.Manip.call(this, manager);
var pack = manager.pack;
- var material = manager.defaultMaterial;
+ var material = manager.constantMaterial;
var shape = manager.translate1Shape_;
if (!shape) {
@@ -1159,10 +1195,6 @@ o3djs.manipulators.Translate1 = function(manager) {
this.addShapes_([ shape ]);
- this.transformInfo = manager.pickManager.createTransformInfo(
- this.getTransform(),
- manager.transformInfo);
-
/**
* A parameter added to our transform to be able to change the
* material's color for highlighting.
@@ -1254,7 +1286,7 @@ o3djs.manipulators.Translate2 = function(manager) {
o3djs.manipulators.Manip.call(this, manager);
var pack = manager.pack;
- var material = manager.defaultMaterial;
+ var material = manager.constantMaterial;
var shape = manager.Translate2Shape_;
if (!shape) {
@@ -1271,10 +1303,6 @@ o3djs.manipulators.Translate2 = function(manager) {
this.addShapes_([ shape ]);
- this.transformInfo = manager.pickManager.createTransformInfo(
- this.getTransform(),
- manager.transformInfo);
-
/**
* A parameter added to our transform to be able to change the
* material's color for highlighting.
@@ -1367,27 +1395,40 @@ o3djs.manipulators.Rotate1 = function(manager) {
o3djs.manipulators.Manip.call(this, manager);
var pack = manager.pack;
- var material = manager.defaultMaterial;
- var shape = manager.Rotate1Shape_;
- if (!shape) {
- // Create the geometry for the manipulator, which looks like
+ if (!manager.lineRingMaterial) {
+ manager.lineRingMaterial = o3djs.manipulators.createLineRingMaterial(
+ pack, manager.drawList, [1, 1, 1, 1], [1, 1, 1, 0.4]);
+ }
+
+ var pickShape = manager.Rotate1PickShape_;
+ if (!pickShape) {
+ // Create the polygon geometry for picking the manipulator, which looks like
// a torus centered at the origin, with the X axis as its vertical axis.
var verts = o3djs.primitives.createTorusVertices(
1.0,
0.1,
- 32,
- 8,
+ 16,
+ 6,
o3djs.math.matrix4.rotationZ(Math.PI / 2));
- shape = verts.createShape(pack, material);
- manager.Rotate1Shape_ = shape;
+ pickShape = verts.createShape(pack, manager.constantMaterial);
+ manager.Rotate1PickShape_ = pickShape;
}
- this.addShapes_([ shape ]);
+ var visibleShape = manager.Rotate1VisibleShape_;
+ if (!visibleShape) {
+ // Create the line geometry for displaying the manipulator, which looks like
+ // a ring centered at the origin, with the X axis as its vertical axis.
+ var verts = o3djs.lineprimitives.createLineRingVertices(
+ 1.0,
+ 32,
+ o3djs.math.matrix4.rotationZ(Math.PI / 2));
+ visibleShape = verts.createShape(pack, manager.lineRingMaterial);
+ manager.Rotate1VisibleShape_ = visibleShape;
+ }
- this.transformInfo = manager.pickManager.createTransformInfo(
- this.getTransform(),
- manager.transformInfo);
+ this.addShapes_([ pickShape ], false); // Invisible
+ this.addShapes_([ visibleShape ]);
/**
* A parameter added to our transform to be able to change the
@@ -1508,3 +1549,93 @@ o3djs.manipulators.Rotate1.prototype.drag = function(startPoint,
this.getTransform().localMatrix = o3djs.math.matrix4.rotationX(-angle);
this.updateAttachedTransformFromLocalTransform_();
}
+
+
+// The shader and material for the Rotate1 manipulator's line ring.
+// TODO(simonrad): Find a better place for these?
+
+/**
+ * The name of the Rotate1 manipulator's line ring effect.
+ * @type {string}
+ */
+o3djs.manipulators.LINE_RING_EFFECT_NAME =
+ 'o3djs.manipulators.lineRingEffect';
+
+/**
+ * An effect string for the Rotate1 manipulator's line ring.
+ * @type {string}
+ */
+o3djs.manipulators.LINE_RING_FXSTRING = '' +
+ 'float4x4 worldViewProjection : WORLDVIEWPROJECTION;\n' +
+ 'float4x4 worldViewProjectionInverseTranspose :\n' +
+ ' WORLDVIEWPROJECTIONINVERSETRANSPOSE;\n' +
+ 'float4 color1;\n' +
+ 'float4 color2;\n' +
+ 'float4 emissive; // Used for highlighting.\n' +
+ '\n' +
+ 'struct VertexShaderInput {\n' +
+ ' float4 position : POSITION;\n' +
+ ' float4 normal : NORMAL;\n' +
+ '};\n' +
+ '\n' +
+ 'struct PixelShaderInput {\n' +
+ ' float4 position : POSITION;\n' +
+ ' float3 normal : TEXCOORD0;\n' +
+ '};\n' +
+ '\n' +
+ 'PixelShaderInput vertexShaderFunction(VertexShaderInput input) {\n' +
+ ' PixelShaderInput output;\n' +
+ '\n' +
+ ' output.position = mul(input.position, worldViewProjection);\n' +
+ ' output.normal = mul(input.normal,\n' +
+ ' worldViewProjectionInverseTranspose).xyz;\n' +
+ ' return output;\n' +
+ '}\n' +
+ '\n' +
+ 'float4 pixelShaderFunction(PixelShaderInput input): COLOR {\n' +
+ ' if (input.normal.z < 0) {\n' +
+ ' return color1 * emissive;\n' +
+ ' } else {\n' +
+ ' return color2 * emissive;\n' +
+ ' }\n' +
+ '}\n' +
+ '\n' +
+ '// #o3d VertexShaderEntryPoint vertexShaderFunction\n' +
+ '// #o3d PixelShaderEntryPoint pixelShaderFunction\n' +
+ '// #o3d MatrixLoadOrder RowMajor\n';
+
+/**
+ * Creates the Rotate1 manipulator's line ring material.
+ *
+ * @param {!o3d.Pack} pack The pack to create the effect and material in.
+ * @param {!o3d.DrawList} drawList The draw list against which
+ * the material is created.
+ * @param {!o3djs.math.Vector4} color1 A color in the format [r, g, b, a].
+ * @param {!o3djs.math.Vector4} color2 A color in the format [r, g, b, a].
+ * @return {!o3d.Material} The created material.
+ */
+o3djs.manipulators.createLineRingMaterial = function(pack,
+ drawList,
+ color1,
+ color2) {
+ var material = pack.createObject('Material');
+ material.effect = pack.createObject('Effect');
+ material.effect.loadFromFXString(o3djs.manipulators.LINE_RING_FXSTRING);
+ material.effect.name = o3djs.manipulators.LINE_RING_EFFECT_NAME;
+ material.drawList = drawList;
+ material.createParam('color1', 'ParamFloat4').value = color1;
+ material.createParam('color2', 'ParamFloat4').value = color2;
+
+ // Set up the state to allow alpha blending
+ material.state = pack.createObject('State');
+ material.state.getStateParam('AlphaBlendEnable').value = true;
+ material.state.getStateParam('SourceBlendFunction').value =
+ o3djs.base.o3d.State.BLENDFUNC_SOURCE_ALPHA;
+ material.state.getStateParam('DestinationBlendFunction').value =
+ o3djs.base.o3d.State.BLENDFUNC_INVERSE_SOURCE_ALPHA;
+ material.state.getStateParam('AlphaTestEnable').value = true;
+ material.state.getStateParam('AlphaComparisonFunction').value =
+ o3djs.base.o3d.State.CMP_GREATER;
+
+ return material;
+};