SimpleFlyController test
Extended SimpleObjectController with clipping support.
/**
* Copyright Glidias ( http://wonderfl.net/user/Glidias )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/znNY
*/
package {
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.EllipsoidCollider;
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.core.Sorting;
import alternativ7.engine3d.core.Vertex;
import alternativ7.engine3d.core.View;
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.objects.Mesh;
import flash.geom.Vector3D;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import alternativ7.engine3d.alternativa3d;
/**
* SimpleFlyControllerTest with colliding on map surfaces.
* Scroll to bottom for class.
*/
public class SimpleFlyControllerTest extends Sprite {
private var rootContainer:Object3DContainer = new Object3DContainer();
private var camera:Camera3D;
private var controller:SimpleFlyController;
public function SimpleFlyControllerTest() {
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
// Camera and view
// Создание камеры и вьюпорта
camera = new Camera3D();
camera.view = new View(stage.stageWidth, stage.stageHeight);
addChild(camera.view);
addChild(camera.diagram);
// Initial position
// Установка начального положения камеры
camera.rotationX = -120*Math.PI/180;
camera.y = -400;
camera.z = 200;
controller = new SimpleFlyController(new EllipsoidCollider(30,30,30), rootContainer, stage, camera, 500);
rootContainer.addChild(camera);
// Adding of geometry
// Создание геометрии
var mesh:Mesh = new Mesh();
var v1:Vertex = mesh.addVertex(-100, 100, 0, 0, 0, "v1");
var v2:Vertex = mesh.addVertex(-100, -100, 0, 0, 1, "v2");
var v3:Vertex = mesh.addVertex(100, -100, 0, 1, 1, "v3");
var v4:Vertex = mesh.addVertex(100, 100, 0, 1, 0, "v4");
mesh.addFace(Vector.<Vertex>([v1, v2, v3, v4]), new FillMaterial(0x22AA11, 1, 1));
var material:FillMaterial = new FillMaterial(0xBB3300, 1, 1);
mesh.addVertex(-200, 0, 50, 0, 0, "left");
mesh.addFaceByIds(["v1", "left", "v2"], material);
mesh.addVertex(0, -200, 50, 0, 0, "back");
mesh.addFaceByIds(["v2", "back", "v3"], material);
mesh.addVertex(200, 0, 50, 0, 0, "right");
mesh.addFaceByIds(["v3", "right", "v4"], material);
mesh.addVertex(0, 200, 50, 0, 0, "front");
mesh.addFaceByIds(["v4", "front", "v1"], material);
MeshUtils.makeDoubleSided(mesh);
// Calculating of normals
// Расчёт нормалей
mesh.calculateNormals(true);
var dynamicMesh:Mesh = mesh.clone() as Mesh;
dynamicMesh.sorting = Sorting.DYNAMIC_BSP;
dynamicMesh.optimizeForDynamicBSP(10);
// Calculating of bounds
// Расчёт границ
mesh.calculateBounds();
mesh.rotationZ = -0.3;
rootContainer.addChild(mesh);
// Listeners
// Подписка на события
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(Event.RESIZE, onResize);
}
private function onEnterFrame(e:Event):void {
controller.update();
camera.render();
}
private function onResize(e:Event = null):void {
// Width and height of view
// Установка ширины и высоты вьюпорта
camera.view.width = stage.stageWidth;
camera.view.height = stage.stageHeight;
}
}
}
import alternativ7.engine3d.core.Face;
import alternativ7.engine3d.core.Wrapper;
import alternativ7.engine3d.objects.Mesh;
import alternativ7.engine3d.alternativa3d;
use namespace alternativa3d;
internal class MeshUtils {
public static function makeDoubleSided(mesh:Mesh):void {
// Create new list of faces and combine them together
var tailNewFace:Face;
var newFace:Face;
var headNewFace:Face;
var lastFace:Face;
for (var face:Face = mesh.faceList; face!=null; face= face.next) {
newFace = cloneFace(face);
flipFaces(newFace);
if (tailNewFace != null) tailNewFace.next = newFace
else headNewFace = newFace
tailNewFace = newFace;
lastFace = face;
}
// combine lists with new
lastFace.next = headNewFace;
}
public static function cloneFace(face:Face):Face
{
// Prepare cloned face
var clipFace:Face = face.create();
clipFace.material = face.material;
clipFace.offset = face.offset;
clipFace.normalX = face.normalX;
clipFace.normalY = face.normalY;
clipFace.normalZ = face.normalZ;
// deepCloneWrapper() inline
var wrapper:Wrapper = face.wrapper;
var wrapperClone:Wrapper = wrapper.create();
wrapperClone.vertex = wrapper.vertex;
var w:Wrapper = wrapper.next;
var tailWrapper:Wrapper = wrapperClone;
var wClone:Wrapper;
while (w != null) {
wClone = w.create();
wClone.vertex = w.vertex;
tailWrapper.next = wClone;
tailWrapper = wClone;
w = w.next;
}
clipFace.wrapper = wrapperClone;
return clipFace;
}
public static function flipFaces(list:Face):void {
for (var f:Face = list; f != null; f = f.next) {
// Flip normal/offset values
f.normalX = -f.normalX;
f.normalY = -f.normalY;
f.normalZ = -f.normalZ;
f.offset = -f.offset;
// Reverse vertex order
var nextWrapper:Wrapper;
var headerWrapper:Wrapper = null;
for (var w:Wrapper = f.wrapper; w != null; w = nextWrapper) {
nextWrapper = w.next;
w.next = headerWrapper;
headerWrapper = w;
}
f.wrapper = headerWrapper;
}
}
}
//package
//{
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.EllipsoidCollider;
import alternativ7.engine3d.core.Object3D;
import flash.display.InteractiveObject;
import flash.geom.Vector3D;
import flash.utils.Dictionary;
/**
* ...
* @author Glenn Ko
*/
//public
class SimpleFlyController extends SimpleObjectController
{
public var collider:EllipsoidCollider;
public var collidable:Object3D;
public var displacement:Vector3D = new Vector3D();
public var collisionPoint:Vector3D = new Vector3D();
public var lastPosition:Vector3D = new Vector3D();
public var excludedObjects:Dictionary = null;
public function SimpleFlyController(collider:EllipsoidCollider, collidable:Object3D, eventSource:InteractiveObject, object:Object3D, speed:Number, speedMultiplier:Number = 3, mouseSensitivity:Number = 1)
{
super(eventSource, object, speed, speedMultiplier, mouseSensitivity);
this.collider = collider;
this.collidable = collidable;
}
override public function update():void {
var object:Object3D = this.object;
if (object == null) return;
if (collider && collidable) {
lastPosition.x = object.x;
lastPosition.y = object.y;
lastPosition.z = object.z;
super.update();
displacement.x = object.x - lastPosition.x;
displacement.y = object.y - lastPosition.y;
displacement.z = object.z - lastPosition.z;
var dest:Vector3D = collider.calculateDestination(lastPosition, displacement, collidable, excludedObjects);
// set back frame coherant transform values
setObjectPosXYZ(dest.x, dest.y, dest.z);
// refresh values immediately
object.x = dest.x;
object.y = dest.y;
object.z = dest.z;
}
else {
super.update();
}
}
}
//}