forked from: Alternativa3D / Zoom to object's face
Alternativa3D 7.5
Camera3D, Matrix3D, pointAt
@author liquid.cow
/**
* Copyright bradsedito ( http://wonderfl.net/user/bradsedito )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/dga7
*/
// 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.Sine;
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;
/**
*
* Alternativa3D 7.5
*
* Camera3D, Matrix3D, pointAt
*
* @author liquid.cow
*/
[SWF(backgroundColor="#FFFFFF", frameRate="100", width="800", height="600")]
public class Test extends Sprite
{
private static const V_CAMERA_INIT : Vector3D = new Vector3D(0, 3000, -4000);
private static const CAM_DISTANCE : Number = 1100;
private static const RAD2DEG : Number = 180 / Math.PI;
private static const DEG2RAD : Number = Math.PI / 180;
private var _container : KDContainer;
private var _camera : Camera3D;
private var _vCam : Vector3D;
private var _vCamTarget : Vector3D;
private var _cameraMatrix : Matrix3D;
private var _camRotationY : Number;
private var _vMouse3D : Vector3D;
private var _clickedFace : Face;
public function Test() : 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);
_camera.view.interactive = true;
addChild(_camera.view);
_container = new KDContainer();
_container.resolveByAABB = true;
_container.resolveByOOBB = true;
_container.addChild(_camera);
_vCamTarget = new Vector3D();
_vCam = V_CAMERA_INIT.clone();
_camRotationY = 0;
var positions:Vector.<Vector3D> = new Vector.<Vector3D>();
positions.push(new Vector3D(-500, 0, -500), new Vector3D(500, 0, -500), new Vector3D(0, 0, 500));
var rotations:Vector.<Number> = new Vector.<Number>();
rotations.push(45 * DEG2RAD, -45 * DEG2RAD, 0);
var material:FillMaterial = new FillMaterial(0x333333, 1, 0, 0x0);
for (var i:int = 0; i<3; i++) {
var box:Box = new Box(500, 300, 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);
stage.addEventListener(MouseEvent.CLICK, onStageClick);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
addEventListener(Event.ENTER_FRAME, render);
onResize();
}
private function onClick(e:MouseEvent3D):void
{
var vTarget:Vector3D;
var vCam:Vector3D;
var camRotationY:Number = 0;
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;
// Difference vector of clicked face to object's pos
var vDiff:Vector3D = new Vector3D();
var m3d : Matrix3D = tempObject.matrix.clone();
m3d.appendTranslation(_clickedFace.normal.x * tempObject.boundMaxX, _clickedFace.normal.y * tempObject.boundMaxY, _clickedFace.normal.z * tempObject.boundMaxZ);
vDiff = m3d.transformVector(vDiff);
// Direction vector
var vDirection : Vector3D = vPos.clone();
vDirection = vDirection.subtract(vDiff.clone());
vDirection.normalize();
// Check face vector's alignment to y-axis
var angleDirectionToUpVector:Number = Vector3D.angleBetween(new Vector3D(0,1,0), vDirection) * RAD2DEG;
camRotationY = (angleDirectionToUpVector == 0 || angleDirectionToUpVector == 180) ? tempObject.rotationY : 0;
// Calculate new camera target pos
var vO : Vector3D = new Vector3D();
m3d = new Matrix3D();
m3d.identity();
m3d.appendTranslation(-vDirection.x * tempObject.boundMaxX, -vDirection.y * tempObject.boundMaxY, -vDirection.z * tempObject.boundMaxZ);
m3d.appendRotation(tempObject.rotationY * RAD2DEG, Vector3D.Y_AXIS, vO);
m3d.appendTranslation(vPos.x, vPos.y, vPos.z);
vTarget = new Vector3D();
vTarget = m3d.transformVector(vTarget);
// Calculate new camera pos
m3d = new Matrix3D();
m3d.identity();
m3d.appendTranslation(-vDirection.x * CAM_DISTANCE, -vDirection.y * CAM_DISTANCE, -vDirection.z * CAM_DISTANCE);
m3d.appendRotation(tempObject.rotationY * RAD2DEG, Vector3D.Y_AXIS, vO);
m3d.appendTranslation(vTarget.x, vTarget.y, vTarget.z);
vCam = new Vector3D();
vCam = m3d.transformVector(vCam);
vCam.z -= .001; // up-vector hack
// Start camera tween
moveCamera(vTarget, vCam, camRotationY);
}
private function moveCamera(vTarget : Vector3D, vCam : Vector3D, camRotationY_:Number) : void
{
TweenLite.killTweensOf(_vCamTarget);
TweenLite.to(_vCamTarget, 1, {x:vTarget.x, y:vTarget.y, z:vTarget.z, ease:Sine.easeInOut});
TweenLite.killTweensOf(this);
TweenLite.to(this, 1, {camRotationY:camRotationY_, ease:Sine.easeInOut});
TweenLite.killTweensOf(_vCam);
TweenLite.to(_vCam, 1, {x:vCam.x, y:vCam.y, z:vCam.z, ease:Sine.easeInOut});
}
private function render( event:Event ) : void
{
_cameraMatrix = new Matrix3D();
_cameraMatrix.identity();
_cameraMatrix.appendTranslation(_vCam.x, _vCam.y, _vCam.z);
_cameraMatrix.appendRotation(_camRotationY * RAD2DEG, Vector3D.Y_AXIS, _vCamTarget);
_cameraMatrix.pointAt(new Vector3D(_vCamTarget.x, _vCamTarget.y, _vCamTarget.z), Vector3D.Z_AXIS, Vector3D.Y_AXIS);
_camera.matrix = _cameraMatrix;
_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
{
if (event.target is Stage) {
if (!_clickedFace)
{
var vTarget:Vector3D = _vMouse3D.clone();
var vCam:Vector3D;
var camRotationY:Number = 0;
// Calculate direction vector of clicked pos (x,0,z) in relation to zero point (0,0,0)
var vDirection : Vector3D = new Vector3D();
vDirection = vDirection.subtract(vTarget.clone());
vDirection.normalize();
vDirection.scaleBy(4000);
vCam = vTarget.clone();
vCam = vCam.subtract(vDirection);
vCam.y = 4000;
moveCamera(vTarget, vCam, camRotationY);
}
else
{
_clickedFace = null;
moveCamera(new Vector3D(), V_CAMERA_INIT.clone(), 0);
}
}
}
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 camRotationY() : Number {
return _camRotationY;
}
public function set camRotationY(camRotationY : Number) : void {
_camRotationY = camRotationY;
}
public function get vCamTarget() : Vector3D {
return _vCamTarget;
}
public function set vCamTarget(vCamTarget : Vector3D) : void {
_vCamTarget = vCamTarget;
}
public function get vCam() : Vector3D {
return _vCam;
}
public function set vCam(vCam : Vector3D) : void {
_vCam = vCam;
}
}
}