topical media & game development
graphic-o3d-samples-o3djs-camera.js / js
/*
* 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 various camera utility functions for
o3d. It puts them in the "camera" module on the o3djs object.
Note: This library is only a sample. It is not meant to be some official
library. It is provided only as example code.
o3djs.provide('o3djs.camera');
o3djs.require('o3djs.util');
o3djs.require('o3djs.math');
A Module for camera utilites.
@namespace
o3djs.camera = o3djs.camera || {};
Class to hold Camera information.
@constructor
parameter: {!o3djs.math.Matrix4} view The 4-by-4 view matrix.
parameter: {number} zNear near z plane.
parameter: {number} zFar far z plane.
parameter: {!o3djs.math.Vector3} opt_eye The eye position.
parameter: {!o3djs.math.Vector3} opt_target The target position.
parameter: {!o3djs.math.Vector3} opt_up The up vector.
o3djs.camera.CameraInfo = function(view,
zNear,
zFar,
opt_eye,
opt_target,
opt_up) {
View Matrix.
@type {!o3djs.math.Matrix4}
this.view = view;
Projection Matrix.
@type {!o3djs.math.Matrix4}
this.projection = o3djs.math.matrix4.identity();
Projection is orthographic.
@type {boolean}
this.orthographic = false;
Near z plane.
@type {number}
this.zNear = zNear;
Far z plane.
@type {number}
this.zFar = zFar;
Field of view in radians.
@type {number}
this.fieldOfViewRadians = o3djs.math.degToRad(30);
Eye position.
@type {(!o3djs.math.Vector3|undefined)}
this.eye = opt_eye;
Target position.
@type {(!o3djs.math.Vector3|undefined)}
this.target = opt_target;
Up Vector.
@type {(!o3djs.math.Vector3|undefined)}
this.up = opt_up;
horizontal magnification for an orthographic view.
@type {(number|undefined)}
this.magX = undefined;
vertical magnification for an orthographic view.
@type {(number|undefined)}
this.magY = undefined;
};
Sets the CameraInfo to an orthographic camera.
parameter: {number} magX horizontal magnification.
parameter: {number} magY vertical magnification.
o3djs.camera.CameraInfo.prototype.setAsOrthographic = function(
magX, magY) {
this.orthographic = true
this.magX = magX;
this.magY = magY;
};
Sets the CameraInfo to an orthographic camera.
parameter: {number} fieldOfView Field of view in radians.
o3djs.camera.CameraInfo.prototype.setAsPerspective = function(
fieldOfView) {
this.orthographic = false;
this.fieldOfViewRadians = fieldOfView;
};
Computes a projection matrix for this CameraInfo using the areaWidth
and areaHeight passed in.
parameter: {number} areaWidth width of client area.
parameter: {number} areaHeight heigh of client area.
returns: {!o3djs.math.Matrix4} The computed projection matrix.
o3djs.camera.CameraInfo.prototype.computeProjection = function(
areaWidth,
areaHeight) {
if (this.orthographic) {
// TODO: figure out if there is a way to make this take the areaWidth
// and areaHeight into account. As it is, magX and magY from the
// collada file are relative to the aspect ratio of Maya's render
// settings which are not available here.
// var magX = areaWidth * 0.5 / this.magX;
// var magY = areaHeight * 0.5 / this.magY;
var magX = this.magX;
var magY = this.magY;
this.projection = o3djs.math.matrix4.orthographic(
-magX, magX, -magY, magY, this.zNear, this.zFar);
} else {
this.projection = o3djs.math.matrix4.perspective(
this.fieldOfViewRadians, // field of view.
areaWidth / areaHeight, // Aspect ratio.
this.zNear, // Near plane.
this.zFar); // Far plane.
}
return this.projection;
};
Searches for all nodes with a "o3d.tags" ParamString
that contains the word "camera" assuming comma separated
words.
parameter: {!o3d.Transform} treeRoot Root of tree to search for cameras.
returns: {!Array.Transform>} Array of camera transforms.
o3djs.camera.findCameras = function(treeRoot) {
return o3djs.util.getTransformsInTreeByTags(treeRoot, 'camera');
};
Creates a object with view and projection matrices using paramters found on
the camera 'o3d.projection_near_z', 'o3d.projection_far_z', and
'o3d.perspective_fov_y' as well as the areaWidth and areaHeight passed
in.
parameter: {!o3d.Transform} camera Transform with camera information on it.
parameter: {number} areaWidth width of client area.
parameter: {number} areaHeight height of client area.
returns: {!o3djs.camera.CameraInfo} A CameraInfo object.
o3djs.camera.getViewAndProjectionFromCamera = function(camera,
areaWidth,
areaHeight) {
var fieldOfView = 30;
var zNear = 1;
var zFar = 5000;
var eye = undefined;
var target = undefined;
var up = undefined;
var view;
var math = o3djs.math;
var cameraInfo;
// Check if any LookAt elements were found for the camera and use their
// values to compute a view matrix.
var eyeParam = camera.getParam('collada.eyePosition');
var targetParam = camera.getParam('collada.targetPosition');
var upParam = camera.getParam('collada.upVector');
if (eyeParam != null && targetParam != null && upParam != null) {
eye = eyeParam.value;
target = targetParam.value;
up = upParam.value;
view = math.matrix4.lookAt(eye, target, up);
} else {
// Set it to the orientation of the camera.
view = math.inverse(camera.getUpdatedWorldMatrix());
}
var projectionType = camera.getParam('collada.projectionType');
if (projectionType) {
zNear = camera.getParam('collada.projectionNearZ').value;
zFar = camera.getParam('collada.projectionFarZ').value;
if (projectionType.value == 'orthographic') {
var magX = camera.getParam('collada.projectionMagX').value;
var magY = camera.getParam('collada.projectionMagY').value;
cameraInfo = new o3djs.camera.CameraInfo(view, zNear, zFar);
cameraInfo.setAsOrthographic(magX, magY);
} else if (projectionType.value == 'perspective') {
fieldOfView = camera.getParam('collada.perspectiveFovY').value;
}
}
if (!cameraInfo) {
cameraInfo = new o3djs.camera.CameraInfo(view, zNear, zFar,
eye, target, up);
cameraInfo.setAsPerspective(math.degToRad(fieldOfView));
}
cameraInfo.computeProjection(areaWidth, areaHeight);
return cameraInfo;
};
Get CameraInfo that represents a view of the bounding box that encompasses
a tree of transforms.
parameter: {!o3d.Transform} treeRoot Root of sub tree to get extents from.
parameter: {number} clientWidth width of client area.
parameter: {number} clientHeight height of client area.
returns: {!o3djs.camera.CameraInfo} A CameraInfo object.
o3djs.camera.getCameraFitToScene = function(treeRoot,
clientWidth,
clientHeight) {
var math = o3djs.math;
var box = o3djs.util.getBoundingBoxOfTree(treeRoot);
var target = math.lerp(box.minExtent, box.maxExtent, 0.5);
var boxDimensions = math.sub(box.maxExtent, box.minExtent);
var diag = o3djs.math.distance(box.minExtent, box.maxExtent);
var eye = math.add(target, [boxDimensions[0] * 0.3,
boxDimensions[1] * 0.7,
diag * 1.5]);
var nearPlane = diag / 1000;
var farPlane = diag * 10;
var up = [0, 1, 0];
var cameraInfo = new o3djs.camera.CameraInfo(
math.matrix4.lookAt(eye, target, up),
nearPlane,
farPlane);
cameraInfo.setAsPerspective(math.degToRad(45));
cameraInfo.computeProjection(clientWidth, clientHeight);
return cameraInfo;
};
Calls findCameras and takes the first camera. Then calls
o3djs.camera.getViewAndProjectionFromCamera. If no camera is found it
sets up some defaults.
parameter: {!o3d.Transform} treeRoot Root of tree to search for cameras.
parameter: {number} areaWidth Width of client area.
parameter: {number} areaHeight Height of client area.
returns: {!o3djs.camera.CameraInfo} A CameraInfo object.
o3djs.camera.getViewAndProjectionFromCameras = function(treeRoot,
areaWidth,
areaHeight) {
var cameras = o3djs.camera.findCameras(treeRoot);
if (cameras.length > 0) {
return o3djs.camera.getViewAndProjectionFromCamera(cameras[0],
areaWidth,
areaHeight);
} else {
// There was no camera in the file so make up a hopefully resonable default.
return o3djs.camera.getCameraFitToScene(treeRoot,
areaWidth,
areaHeight);
}
};
Calls findCameras and creates an array of CameraInfos for each camera found.
parameter: {!o3d.Transform} treeRoot Root of tree to search for cameras.
parameter: {number} areaWidth Width of client area.
parameter: {number} areaHeight Height of client area.
returns: {!Array.} A CameraInfo object.
o3djs.camera.getCameraInfos = function(treeRoot, areaWidth, areaHeight) {
var cameras = o3djs.camera.findCameras(treeRoot);
var cameraInfos = [];
for (var cc = 0; cc < cameras.length; ++cc) {
cameraInfos.push(o3djs.camera.getViewAndProjectionFromCamera(
cameras[cc], areaWidth, areaHeight));
}
return cameraInfos;
};
Sets the view and projection of a DrawContext to view the bounding box
that encompasses the tree of transforms passed.
This function is here to help debug a program by providing an easy way to
attempt to get your content in front of the camera.
parameter: {!o3d.Transform} treeRoot Root of sub tree to get extents from.
parameter: {number} clientWidth width of client area.
parameter: {number} clientHeight height of client area.
parameter: {!o3d.DrawContext} drawContext DrawContext to set view and
projection on.
o3djs.camera.fitContextToScene = function(treeRoot,
clientWidth,
clientHeight,
drawContext) {
var cameraInfo = o3djs.camera.getCameraFitToScene(treeRoot,
clientWidth,
clientHeight);
drawContext.view = cameraInfo.view;
drawContext.projection = cameraInfo.projection;
};
(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.