Alternativa3D Matrix3D interpolation / Zoom to object's face
Alternativa3D 7.6
@author liquid.cow
- testing matrix interpolation for animation
- change the camera position and -target by clicking on an object's face or the stage.
- a bug has been removed, but the transition, well ... sucks
- forked from http://wonderfl.net/c/pNAF
/**
* Copyright liquid.cow ( http://wonderfl.net/user/liquid.cow )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/wERV
*/
// forked from liquid.cow's Alternativa3D / Zoom to object's face
package {
import alternativ7.engine3d.containers.KDContainer;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.Face;
import alternativ7.engine3d.core.MouseEvent3D;
import alternativ7.engine3d.core.Object3D;
import alternativ7.engine3d.core.RayIntersectionData;
import alternativ7.engine3d.core.View;
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.primitives.Box;
import gs.*;
import gs.easing.Cubic;
import flash.display.Sprite;
import flash.display.Stage;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
import flash.geom.Point;
/**
*
* Alternativa3D 7.6
*
* Camera3D, Matrix3D, pointAt
* @author liquid.cow
*/
[SWF(backgroundColor="#000000", frameRate="100", width="800", height="600")]
public class Test6 extends Sprite
{
private static const V_CAMERA_INIT : Vector3D = new Vector3D(0, 3000, -4000);
private static const DEG2RAD : Number = Math.PI / 180;
private var _container : KDContainer;
private var _camera : Camera3D;
private var _cameraMatrix : Matrix3D;
private var _vMouse3D : Vector3D;
private var _clickedFace : Face;
private var _targetMatrix : Matrix3D;
private var _value : Number;
private var _initialMatrix : Matrix3D;
public function Test6() : void {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event=null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
_camera = new Camera3D();
_camera.view = new View(stage.stageWidth, stage.stageHeight);
addChild(_camera.view);
_camera.x = V_CAMERA_INIT.x;
_camera.y = V_CAMERA_INIT.y;
_camera.z = V_CAMERA_INIT.z;
_targetMatrix = _camera.matrix.clone();
_targetMatrix.pointAt(new Vector3D(), Vector3D.Z_AXIS, Vector3D.Y_AXIS);
_camera.matrix = _targetMatrix;
_cameraMatrix = _targetMatrix.clone();
_initialMatrix = _targetMatrix.clone();
_container = new KDContainer();
_container.resolveByAABB = true;
_container.resolveByOOBB = true;
_container.addChild(_camera);
_value = 0;
var positions:Vector.<Vector3D> = new Vector.<Vector3D>();
positions.push(new Vector3D(-500, 0, -500), new Vector3D(-500, -100, 500), new Vector3D(100, -200, -500), new Vector3D(500, -300, 500));
var rotations:Vector.<Number> = new Vector.<Number>();
rotations.push(45 * DEG2RAD, -45 * DEG2RAD, 0, 25 * DEG2RAD);
var colors:Vector.<uint> = new Vector.<uint>();
colors.push(0xbf0000, 0xc28a73, 0xeb1e01, 0xba7e47);
for (var i:int = 0; i<4; i++) {
var material:FillMaterial = new FillMaterial(colors[i], .5, 0, 0x0);
var box:Box = new Box(200, 100, 300, 1, 1, 1);
box.x = positions[i].x;
box.y = positions[i].y;
box.z = positions[i].z;
box.rotationY = rotations[i];
box.setMaterialToAllFaces(material);
box.addEventListener(MouseEvent3D.CLICK, onClick);
_container.addChild(box);
}
_camera.render();
stage.addEventListener(Event.RESIZE, onResize);
_camera.view.addEventListener(MouseEvent.CLICK, onStageClick);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
addEventListener(Event.ENTER_FRAME, render);
onResize();
}
private function onClick(e:MouseEvent3D):void
{
var distance:Number = 1100;
var tempObject:Object3D = e.target as Object3D;
var vPos:Vector3D = new Vector3D(tempObject.x, tempObject.y, tempObject.z);
var data:RayIntersectionData = tempObject.intersectRay(e.localOrigin, e.localDirection);
_clickedFace = data.face;
var v : Vector3D = _clickedFace.normal.clone();
v.scaleBy(distance);
v = v.add(new Vector3D(_clickedFace.normal.x * tempObject.boundMaxX, _clickedFace.normal.y * tempObject.boundMaxY, _clickedFace.normal.z * tempObject.boundMaxZ));
var objectTransform:Matrix3D = tempObject.matrix.clone();
v = objectTransform.transformVector(v);
var m : Matrix3D = new Matrix3D();
m.appendTranslation(v.x, v.y, v.z);
if (_clickedFace.normal.y != 0) {
// camera-target-pos is exactly above the object
var components : Vector.<Vector3D> = m.decompose();
components[1].x = Math.PI / 2;
components[1].y = tempObject.rotationY + Math.PI;
components[1].z = 0;
m.recompose(components);
} else {
m.pointAt(vPos, Vector3D.Z_AXIS, Vector3D.Y_AXIS);
}
moveCamera(m);
}
private function moveCamera(targetMatrix_:Matrix3D) : void
{
_cameraMatrix = _camera.matrix.clone();
_targetMatrix = targetMatrix_;
TweenLite.killTweensOf(this);
_value = 0;
TweenLite.to(this, 1, {value:1, ease:Cubic.easeInOut});
}
private function render( event:Event ) : void
{
_camera.matrix = Matrix3D.interpolate(_cameraMatrix, _targetMatrix, _value);
_camera.render();
}
public function onResize(event:Event = null) :void
{
_camera.view.width = stage.stageWidth;
_camera.view.height = stage.stageHeight;
_camera.fov = 2 * Math.atan2(Math.sqrt(_camera.view.width * _camera.view.width + _camera.view.height * _camera.view.height) / 2, 1100);
}
private function onStageClick(event : MouseEvent) : void
{
var a:Array = _camera.view.getObjectsUnderPoint(new Point(_camera.view.mouseX, _camera.view.mouseY));
if (a.length==0) {
_clickedFace = null;
moveCamera(_initialMatrix);
}
}
private function onMouseMove(event : MouseEvent) : void {
if (event.target is Stage) {
var origin:Vector3D = new Vector3D();
var directionA:Vector3D = new Vector3D();
var directionB:Vector3D = new Vector3D();
_camera.calculateRay(origin, directionA, _camera.view.width / 2, _camera.view.height / 2);
_camera.calculateRay(origin, directionB, stage.mouseX, stage.mouseY);
var pos : Vector3D = intersectionPoint(origin, directionB, new Vector3D(0, 0, 0), new Vector3D(0, 1, 0));
_vMouse3D = new Vector3D(pos.x, pos.y, pos.z);
}
}
public static function intersectionPoint(lineStart:Vector3D, lineDirection:Vector3D, planePosition:Vector3D, planeNormal:Vector3D):Vector3D {
var result:Vector3D = new Vector3D();
var w:Vector3D = lineStart.subtract(planePosition);
var d:Number = planeNormal.dotProduct(lineDirection);
var n:Number = -planeNormal.dotProduct(w);
var sI:Number = n / d;
result.x = lineStart.x + (lineDirection.x * sI);
result.y = lineStart.y + (lineDirection.y * sI);
result.z = lineStart.z + (lineDirection.z * sI);
return result;
}
public function get value() : Number {
return _value;
}
public function set value(value : Number) : void {
_value = value;
}
}
}