Away 3D 4 and AwayPhysics ASFEAT - AR
So, the only way I found to both use in2ar and awayPhysics, it's to use 2 differents swf. Both in2ar and awayPhysic use 'alchemy's swc'. It appears when you use both in the same swf some memory conflic occurs. So here is my solution. I have on one side a swf contains AWAY3D 4.0 & IN2AR and on a other side a swf dealing physics. The second one is loaded by the first one via a Loader. Each swfs have their own ApplicationDomain. Here is the two class. It uses FP11.2 Beta, in2ar SDK, away3d 4 & awayPhysics. The first one build physic, the second integrate away3d & in2ar.
package
{
import away3d.containers.View3D;
import away3d.debug.AwayStats;
import away3d.entities.Mesh;
import away3d.lights.DirectionalLight;
import away3d.lights.PointLight;
import away3d.materials.BitmapMaterial;
import away3d.materials.ColorMaterial;
import away3d.materials.methods.FilteredShadowMapMethod;
import away3d.primitives.Cube;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.StageVideoAvailabilityEvent;
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.geom.Rectangle;
import flash.geom.Vector3D;
import flash.media.Camera;
import flash.media.StageVideo;
import flash.net.URLRequest;
import flash.system.ApplicationDomain;
import flash.utils.ByteArray;
import flash.utils.Endian;
import ru.inspirit.asfeat.ASFEAT;
import ru.inspirit.asfeat.IASFEAT;
import ru.inspirit.asfeat.calibration.IntrinsicParameters;
import ru.inspirit.asfeat.detect.ASFEATReference;
import ru.inspirit.asfeat.event.ASFEATCalibrationEvent;
import ru.inspirit.asfeat.event.ASFEATDetectionEvent;
[SWF(width='1024',height='512',frameRate='60',backgroundColor='0xFFFFFF')]
public class In2ARShadow extends Sprite
{
//3D
[Embed(source="../assets/trans.png")]
private var Skin : Class;
private var view:View3D ;
private var light :* ;
private var isDir:Boolean = true ;
private var arrayAwSphere:Vector. = new Vector.() ;
private var container:Mesh = new Mesh() ;
// Physics
private var objectPhysic:Object = new Object()
private var loader:Loader = new Loader() ;
//ASFEAT & CAM
// embed your data file here
[Embed(source = '../assets/def_data.ass', mimeType='application/octet-stream')]
private static const data_ass:Class;
private var _cambuff:BitmapData ;
protected var _cam:Camera;
protected var stageVideo:StageVideo ;
public var asfeat:ASFEAT;
public var asfeatLib:IASFEAT;
public var intrinsic:IntrinsicParameters;
public var camWidth:int = 1024;
public var camHeight:int = 512;
public var downScaleRatio:Number = 1;
public var srcWidth:int = 1024; // should be the same as camera size untill downscale is used
public var srcHeight:int = 512;
public var maxPointsToDetect:int = 250; // max point to allow on the screen
public var maxReferenceObjects:int = 1; // max reference objects to be used
protected var _cambuff_rect:Rectangle;
protected var _cam_mtx:Matrix;
protected var _buff_rect:Rectangle;
protected var _buff_mtx:Matrix;
protected var _buffer:BitmapData;
public var ram:ByteArray;
public var applicationDomain:ApplicationDomain = ApplicationDomain.currentDomain;
public var maxTransformError:Number = 10 * 10;
public function In2ARShadow()
{
if(stage) onAddedToStage();
else addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
protected function onAddedToStage(e:Event = null):void
{
removeEventListener( Event.ADDED_TO_STAGE, onAddedToStage );
ini3D() ;
iniSpheres() ;
loadSwfPhysic() ;
}
////////////////////////////////////////////StageVideo - Cam - ASFEAT /////////////////////////////////////////////////////////
private function preInitASFEAT():void {
asfeat = new ASFEAT(null);
asfeat.addEventListener( Event.INIT, init );
}
protected function initStage():void
{
stage.scaleMode = StageScaleMode.NO_SCALE;
}
protected function init(e:Event = null):void
{
initStage();
//
srcWidth = camWidth * downScaleRatio;
srcHeight = camHeight * downScaleRatio;
// DIFFERENT OBJECTS USED TO WORK WITH WEB CAMERA
_cambuff_rect = _cambuff.rect;
_cam_mtx = new Matrix(-1.0, 0, 0, 1.0, camWidth);
_buffer = new BitmapData( srcWidth, srcHeight, false, 0x00 );
_buff_rect = _buffer.rect;
_buff_mtx = new Matrix(downScaleRatio, 0, 0, downScaleRatio);
//
// INITIATE ASFEAT/IN2AR LIB
initASFEAT();
}
protected function initASFEAT():void
{
trace("Ini ASFEAT") ;
asfeat.removeEventListener( Event.INIT, init );
asfeatLib = asfeat.lib;
// just believe me
ram = new ByteArray();
ram.endian = Endian.LITTLE_ENDIAN;
ram.length = asfeatLib.calcRequiredChunkSize(srcWidth, srcHeight, maxPointsToDetect, maxReferenceObjects);
ram.position = 0;
applicationDomain.domainMemory = ram;
// init our engine
asfeatLib.init( ram, 0, srcWidth, srcHeight, maxPointsToDetect, maxReferenceObjects, maxTransformError, stage );
// add reference object
asfeatLib.addReferenceObject( ByteArray( new data_ass ) );
// add event listeners
asfeatLib.addListener( ASFEATCalibrationEvent.COMPLETE, onCalibDone );
asfeatLib.addListener( ASFEATDetectionEvent.DETECTED, onModelDetected );
asfeatLib.setSingleReferenceMode(true);
// indexing reference data will result in huge
// speed up during matching (see docs for more info)
asfeatLib.indexReferenceData(16, 12);
// u can repform geometric calibration
// during detection/tracking (see onCalibDone method)
asfeatLib.startGeometricCalibration();
intrinsic = asfeatLib.getIntrinsicParams();
}
protected function onModelDetected(e:ASFEATDetectionEvent):void
{
trace("MODEL DETECT") ;
var refList:Vector. = e.detectedReferences;
var ref:ASFEATReference;
ref = refList[0];
var m:Matrix3D = new Matrix3D() ;
m = get3DMatrixLH(ref.rotationMatrix , ref.translationVector) ;
m.prependRotation(180,Vector3D.Y_AXIS) ;
m.prependRotation(180,Vector3D.Z_AXIS) ;
m.prependRotation(-90,Vector3D.X_AXIS) ;
try{
container.transform = m ;
} catch (e:Error) {}
}
public function get3DMatrixLH(R:Vector., t:Vector.):Matrix3D
{
var data:Vector. = new Vector. ;
data[0] = R[0];
data[1] = -R[3];
data[2] = R[6];
data[3] = 0.0;
data[4] = R[1];
data[5] = -R[4];
data[6] = R[7];
data[7] = 0.0;
data[8] = -R[2];
data[9] = R[5];
data[10] = -R[8];
data[11] = 0.0;
data[12] = t[0];
data[13] = -t[1];
data[14] = t[2]-00; // tZ
data[15] = 1.0;
return new Matrix3D(data) ;
}
protected function onCalibDone(e:ASFEATCalibrationEvent):void
{
trace("ASFEAT Calibration") ;
var fx:Number = (e.fx + e.fy) * 0.5;
var fy:Number = fx;
intrinsic.update(fx, fy, intrinsic.cx, intrinsic.cy);
asfeatLib.updateIntrinsicParams();
}
private function onStageVideoAvailability(e:StageVideoAvailabilityEvent):void {
if ( stageVideo == null )
{
stageVideo = stage.stageVideos [ 0 ] ;
//stageVideo.viewPort = new Rectangle ( 0 , 0 , 1024 , 512 ) ;
}
stageVideo.attachCamera(_cam) ;
trace("StageVideo ok") ;
addListernerAway3D_ObjectPhysic() ;
preInitASFEAT() ;
_cam.addEventListener(Event.VIDEO_FRAME , newFrame) ;
}
private function getCam(w:int = 1024, h:int = 512, fps:int = 25):void {
_cambuff = new BitmapData( w, h, true, 0x0 );
_cam = Camera.getCamera();
_cam.setMode( 1024, 512,25, true );
trace("Cam ok") ;
}
private function newFrame(e:Event):void {
_cam.drawToBitmapData(_cambuff) ;
asfeatLib.detect( _cambuff );
view.backgroundImage = _cambuff ;
}
///////////////////////////////////////////Away3D & AwayPhysics ////////////////////////////////////////////////////
private function loadSwfPhysic():void {
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, swfPhysicIsLoaded);
loader.load(new URLRequest("TestASFeadPhysic.swf")) ;
}
private function swfPhysicIsLoaded(e:Event):void {
trace("Physic is Loaded") ;
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,swfPhysicIsLoaded) ;
objectPhysic = e.target.content ;
// ini cam & stageVideo
getCam() ;
stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, onStageVideoAvailability);
}
private function addListernerAway3D_ObjectPhysic():void {
stage.addEventListener(Event.ENTER_FRAME,render) ;
stage.addEventListener( KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener( KeyboardEvent.KEY_UP, keyUpHandler);
}
private function ini3D():void {
trace("INI3D") ;
view = new View3D();
if(!isDir) {
trace("Point Light") ;
light = new PointLight();
light.y = 0;
light.z = -1000;
view.scene.addChild(light);
view.camera.lens.far = 10000;
view.camera.y = light.y;
view.camera.z = light.z;
} else {
trace("Directional light") ;
light = new DirectionalLight(-1, -1, 1);
light.color = 0xffffee;
light.position=new Vector3D(1000,1000,1000);
view.scene.addChild(light);
view.camera.lens.far = 10000;
view.camera.z=-2000;
view.camera.y=1000;
view.camera.x=0;
view.camera.lookAt(new Vector3D(0,0,0));
}
//stats
var ds:DisplayObject ;
ds = new AwayStats(view) ;
ds.x = 95 ;
this.addChild(ds) ;
addChild(view);
}
private function iniSpheres():void {
var material : ColorMaterial = new ColorMaterial(0xff0000);
material.shadowMethod = new FilteredShadowMapMethod(light);
material.lights = [light];
var n:int = 0
for (var i:int = 0 ;i<4 ; i++) {
for (var j:int = 0 ;j<4 ; j++) {
for (var k:int = 0 ;k<4 ; k++) {
var sphere : AwSphere = new AwSphere(material) ;
arrayAwSphere[n] = sphere ;
container.addChild(arrayAwSphere[n].getAwSphere()) ;
n++
}
}
}
trace("3D spheres created") ;
// add a box
var materialBox : ColorMaterial = new ColorMaterial(0xffffff);
materialBox.shadowMethod = new FilteredShadowMapMethod(light);
materialBox.lights = [light];
materialBox.ambientColor = 0x000000;
materialBox.ambient = 1;
materialBox.alpha = 0.05 ;
var box:Mesh = new Cube(materialBox,20000,10,20000) ;
container.addChild(box) ;
view.scene.addChild(container) ;
}
private function keyDownHandler(event:KeyboardEvent):void
{
objectPhysic.keyDownHandler(event) ;
}
private function keyUpHandler(event:KeyboardEvent):void
{
objectPhysic.keyUpHandler(event) ;
}
private function retrievePhysics():void {
for(var j:int = 0 ; j = new Vector.() ;
public var v:Vector. = new Vector.
public function TestASFeadPhysic()
{
physicsWorld = AWPDynamicsWorld.getInstance();
physicsWorld.initWithDbvtBroadphase();
// create box
var awpB:AWPBoxShape = new AWPBoxShape(20000,10,20000) ;
var box:AWPRigidBody = new AWPRigidBody(awpB,null,0) ;
physicsWorld.addRigidBody(box) ;
// create sphere
var n:int = 0
for (var i:int = 0 ;i<4 ; i++) {
for (var j:int = 0 ;j<4 ; j++) {
for (var k:int = 0 ;k<4 ; k++) {
var sphereShape1:AWPSphereShape = new AWPSphereShape(100);
var s:AWPRigidBody=new AWPRigidBody(sphereShape1,null,2) ;
s.position = new Vector3D(-300 + i * 200, 100+ k * 200, j * 200) ;
s.restitution = 0.7 ;
s.friction = 1 ;
vRb.push(s) ;
physicsWorld.addRigidBody(vRb[n]) ;
//trace("crea =" +n) ;
n++ ;
}
}
}
trace("physic's sphere created") ;
this.addEventListener(Event.ENTER_FRAME, go) ;
}
public function keyDownHandler(event:KeyboardEvent):void
{
trace("down : "+event.keyCode) ;
switch(event.keyCode)
{
case Keyboard.UP:
keyForward = true;
keyReverse = false;
break;
case Keyboard.DOWN:
keyReverse = true;
keyForward = false;
break;
case Keyboard.LEFT:
keyLeft = true;
keyRight = false;
break;
case Keyboard.RIGHT:
keyRight = true;
keyLeft = false;
break;
}
}
public function keyUpHandler(event:KeyboardEvent):void
{
trace("up : "+event.keyCode) ;
switch(event.keyCode)
{
case Keyboard.UP:
keyForward = false;
break;
case Keyboard.DOWN:
keyReverse = false;
break;
case Keyboard.LEFT:
keyLeft = false;
break;
case Keyboard.RIGHT:
keyRight = false;
break;
}
}
private function go(e:Event):void {
if(keyLeft)
{
vRb[5].applyCentralForce(new Vector3D( -50, 0, 0));
}
if(keyRight)
{
vRb[5].applyCentralForce(new Vector3D( 50, 0, 0));
}
if(keyForward)
{
vRb[5].applyCentralForce(new Vector3D( 0, 0, 50));
}
if(keyReverse)
{
vRb[5].applyCentralForce(new Vector3D( 0, 0, -50));
}
getVecs3D() ;
physicsWorld.step(0.04,1,0.04) ;
}
public function getVecs3D():void{
for(var i :int = 0 ; i