I'm implementing an Augmented Reality application for android using Flash. In order to get the application working on my Android Phone (nexus One) the Phone Camera must be activated as well. So I need 2 layers one for the background which is the feed of my phone camera and an other one on top of it which is the view from away3d in this case.
So setting up a BitmapData object to hold the information of the most recent webcam still-frame I can make this work.
If I use papervision3D library and FLARToolkit we setting up the BitmapData using the following part of the code found from this video tutorial:
//import libraries
import org.libspark.flartoolkit.core.raster.rgb.FLARRgbRaster_BitmapData;
import org.libspark.flartoolkit.detector.FLARSingleMarkerDetector;
private function setupCamera():void
{
vid = new Video(640, 480);
cam = Camera.getCamera();
cam.setMode(320, 240, 10);
vid.attachCamera(cam);
addChild(vid);
}
private function setupBitmap():void
{
bmd = new BitmapData(640, 480);
bmd.draw(vid);
raster = new FLARRgbRaster_BitmapData(bmd);
detector = new FLARSingleMarkerDetector(fparams, mpattern, 80);
}
private function loop(e:Event):void
{
if(detector.detectMarkerLite(raster, 80) && detector.getConfidence() > 0.5)
{
vp.visible = true;
detector.getTransformMatrix(trans);
container.setTransformMatrix(trans);
bre.renderScene(scene, camera, vp);
}
else{
vp.visible = false}
}
catch(e:Error){}}}}
However, to implement my application Im using Away3D engine and FLARManager and the way of doing that is very different as I can understand. I have implement the following code but the only think it does is just show the Flash Camera in the front of the 3D view and I can't check if my application is work or not since it doesn't show me any 3D Object when I place the marker in front of the screen.
My code is:
//Setting Up Away3DLite Camera3D
import com.transmote.flar.camera.FLARCamera_Away3DLite;
private var camera3D:FLARCamera_Away3DLite;
this.camera3D = new FLARCamera_Away3DLite(this.flarManager, new Rectangle(0, 0, this.stage.stageWidth, this.stage.stageHeight));
//Setting Up the bitmapData
private function bitmap():void
{
c = Camera.getCamera();
c.setMode(320,240,10)
this.v.attachCamera(c);
addChild(this.v);
bmd = new BitmapData(640,480);
bmd.draw(this.v);
}
Can you please help me to find out how can I combine those two?
I will really appreciate any advice i can get from you.
Thank you
To isolate your problem, I'd try to break these two things up and make sure each part works first. It's sounds like you've got the camera part working, try doing just some 3D (no AR) draw a cube or something. Then try implementing the AR but have it do something simple like trace something out or making an object visible or invisible. Then start combining them.
Related
I start creating my flash game using Flashpunk, for collisions i didn't want to use hitboxes because i had images (PNG) with transparent parts in them so i decided to use Collision Detection Kit, i have a problem when creating the collision list, it takes a display object as a parameter and doesn't accept flash punk spritemaps, i tried to cast the spritemap to a flash display object but it's not working, is there a way to use the CDK with flashpunk ?
override public function begin():void
{
_player = new Player(100, 100);// Entity
initCollision(_player.sprPlayer);// The Entity Spritemap
}
private function initCollision(player:Spritemap):void {
collisionChecker = new CollisionList(player); // Problem here
}
Well, you could create an empty BitmapData with the same width & height of your Spritemap and then "render" it to that BitmapData, like so:
var bmd:BitmapData = new BitmapData(64, 64, true, 0);
var sprite:Spritemap = _player.sprPlayer;
sprite.render(bmd, new Point(0,0), new Point(0,0));
collisionChecker = new CollisionList(bmd);
That should draw the spritemap's current frame to a BitmapData which you could then use for the CollisionList. The code above is an example that only demonstrates how to do this. For your actual code, it would be better to avoid constantly initializing new variables during your collision detection.
My testbed is able to composite a thousand elements into clips on screen, but I can't extract a bitmap on the fly from an external swf for Starling or for export to png.
(I'm a bit of a code butcher, but have tried lot of variations and have looked through spritesheet generating examples))
I have seen the advice "You can't get bitmapData from a Class only displayObjects (MClip, Sprite)", My line: s = new AssetClass() below seems to address that.
Correct usage of addtoStage when loading external swf
I am able to generate a bitmap of an internal vector movieclip, and save it to a .png using as3corelib.PNGEncoder.as, but I end up with a blank png using clips from the external swf, running this in Flash Pro CC..
paraphrased code:
// swf load done handler:
testBitmap = new Bitmap(new BitmapData(w, h , true, 0x0));
var AssetClass:Class = getDefinitionByName("assetNameFromDatabase") as Class;
var s:MovieClip = new AssetClass(); // AddChild(s) functions properly
var m:Matrix = new Matrix(1, 0, 0, 1, 400, 300);
testBitmap.bitmapData.draw(s, m);
// addChild(testBitmap); or send to PNGEncoder rsult is blank
// internal clip test that does convert to bitmap
var b:MovieClip = new testdMovieClip();
var m:Matrix = new Matrix(1, 0, 0, 1, 200, 300);
testBitmap.bitmapData.draw(b, m);
//----------------------------
Thanks Vesper, Couldn't gfix things with your suggestion, I was actually already adding to a movieClip, just left it out of the simplified code sample, I did try some variates of adding an instance ahead of drawing to bitmap, still getting no results.
//--
*** Amendment: Looks like the libs have embedded "display but don't copy" protect code? can someone verify this.
I am using merged movieclip libraries provided in swf format, (I have individual fla source for the hundreds of resources in the library swfs that I hoped to avoid dealing with, their removing swf import from Flash Pro cc is a further agrrevation) This is public domain material from a retired game.
Using a Trillix trial, I examined the embedded Class files, along with the usual individual asset Class they had this code:
public override function get movieClipData():flash.utils.ByteArray
{
if (bytes == null)
{
bytes = flash.utils.ByteArray(new dataClass());
}
return bytes;
}
{
bytes = null;
}
internal static var bytes:flash.utils.ByteArray=null;
// the classes also have
import flash.utils.*;
import mx.core.*; // as well as embedded package mx files, is that for Flex?
I was looking at creating some code-less external library files for Air/iOS down the road, I may have to learn to ways to auto merge FLAs sooner than later.
I have seen weird behavior of width and height properties of shape/sprite objects while they are not added to display list, they return -100 million or something. So you should add, then draw, then remove. This trick helped me when I wrote a dynamically generated sprite.
testBitmap = new Bitmap(new BitmapData(w, h , true, 0x0));
var AssetClass:Class = getDefinitionByName("assetNameFromDatabase") as Class;
var s:MovieClip = new AssetClass(); // AddChild(s) functions properly
addChild(s); // !
var m:Matrix = new Matrix(1, 0, 0, 1, 400, 300);
testBitmap.bitmapData.draw(s, m);
removeChild(s);
addChild(testBitmap); // now should display properly
If I publish Windows Projector (.exe) with no hardware acceleration, everything works fine, but if I select direct or gpu harware acceleration I will not get the security panel to show up at all. Anyone else have this same issue, or is it just me?
Basically I would like to publish a stand-alone webcam game, but if I try to use getCamera(), the user will not see the security question at all, and I will not get the camera initialized.Does anyone know a workaround for this? I would love to get HW acceleration to my game.
import flash.system.Security;
import flash.system.SecurityPanel;
//import flash.media.Camera;
Security.showSettings(SecurityPanel.CAMERA);
//var camera:Camera=Camera.getCamera();
I got this to work, but I created a projector through the stand alone and the "Create Projector" menu, not through the Flash IDE. I was able to get the panel to show up using the latest flash.
compiler settings: -swf-version=16 -use-gpu=true
// test showing stage3D + panel
final public class Test extends Sprite {
private var cam:Camera;
private var video:Video = new Video();
public function Test():void {
var stage3D:Stage3D = stage.stage3Ds[0];
stage3D.addEventListener(Event.CONTEXT3D_CREATE, handleContext);
stage3D.requestContext3D();
trace(cam.name);
}
/**
* #private
*/
private function handleContext(e:Event):void {
var stage3D:Stage3D = stage.stage3Ds[0];
var context:Context3D = stage3D.context3D;
context.configureBackBuffer(stage.stageWidth, stage.stageHeight, 0, true);
context.clear(0,0,0,1);
context.present();
Security.showSettings(SecurityPanel.CAMERA);
cam = Camera.getCamera();
cam.setMode(640,360,30);
video.attachCamera(cam);
// change to upload via texture instead
addChild(video);
}
In my experience, hardware acceleration gains are only very minimal without using specific gpu apis. Camera in my experience instead accelerated, only specific types of video decompression. If you're not using Stage3D, you probably won't get any visible gains.
Does anyone know of any libraries or tools for importing an SVG file into actionscript on the fly? I need to be able to import an SVG file into flash and convert it to a movieclip or preferably a flat 3d object. The end goal here is to implement a vector file with Augmented reality.
A great library for this can be downloaded here: http://code.google.com/p/as3svgrendererlib/
It is easy to implement and reliable. Note that there are two ways to implement the code. I prefer the following because it gives you more control:
private function loadSVG(url:String):void {
ProcessExecutor.instance.initialize(stage);
ProcessExecutor.instance.percentFrameProcessingTime = 0.9;
loader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.addEventListener(Event.COMPLETE, svgLoaded, false, 0, true);
try {
loader.load(new URLRequest(url));
} catch (error:Error) {
trace(error);
}
}
private function svgLoaded(e:Event):void {
var svgString:String = loader.data as String;
var svgDocument:SVGDocument = new SVGDocument();
svgDocument.parse(svgString);
this.addChild(svgDocument);
}
The other way is shorter and might be the way to go when you only have to load a small SVG or just a few.
public function loadSVG(url:String) {
ProcessExecutor.instance.initialize(stage);
ProcessExecutor.instance.percentFrameProcessingTime = 0.9;
var svgDocument:SVGDocument = new SVGDocument();
svgDocument.load(url);
addChild(svgDocument);
}
Two important notes:
1. I could not seem to be able to capture the width or height of the SVGs and the parent Sprite had a width and height of 0 after loading the SVG. I solved this by making all the SVGs the same size before loading them into AS3. After that I knew the dimensions I used the ScaleX and scaleY to resize the loaded SVGs.
2. The stage has to exist before you can use this code. adding the following code will make sure you won't run into problems:yourDisplayClass.addEventListener(Event.ADDED_TO_STAGE, loadYourSVGs);
Now how you convert this to a flat 3D object depends on your 3D Library. I have worked with Away3D where you can use bitmapmaterial on your Sprite3D. The Sprite3D class would be the object to use. I hope your 3D Library supports the use of MovieClips so that you can add them to your 3D Object. Else you will have to use to extract the bitmapMaterial from the movie clip as i have done in the following example:
public function movieClipToBitmapMaterial(mc:MovieClip):BitmapMaterial {
var bmData:BitmapData = new BitmapData(mc.width, mc.height, true, 0xFFFFFF);
bmData.draw(displayObject);
return new BitmapMaterial(bmData);
}
Your input in the above function will be the movieclip onto wich you have loaded your SVG.
I am not sure of this but I think that by using this function you will loose the ability to scale as much as you like without loosing quality.
I hope my input was of some help!
Good luck
PS: don't forget to add the SWC from the link to your project and to check out the provided examples. Please note as well the excellent comment of shaunhusain on your original question. You might not have to use 3D Library.
Salam,
It is very easy:
Open the "name.svg" file in illustartror.
Save it as "name.ai"
Import it into the stage in flash, that is all.
I am trying to build a portfolio application similar to the used by Whitevoid. I am using Flex 4 and Papervision3D 2. I have everything working except for one issue. When I try to load an external SWF as a material on one of the planes, I can see any native Flex or Flash components in their correct positions, but the papervision objects are not being rendered properly. It looks like the viewport is not being set in the nested swf. I have posted my code for loading the swf below.
private function loadMovie(path:String=""):void
{
loader = new Loader();
request = new URLRequest(path);
loader.contentLoaderInfo.addEventListener(Event.INIT, addMaterial);
loader.load(request);
}
private function addMaterial(e:Event):void
{
movie = new MovieClip();
movie.addChild(e.target.content);
var width:Number = 0;
var height:Number = 0;
width = loader.contentLoaderInfo.width;
height = loader.contentLoaderInfo.height;
//calculate the aspect ratio of the swf
var matAR:Number = width/height;
if (matAR > aspectRatio)
{
plane.scaleY = aspectRatio / matAR;
}
else if (matAR < aspectRatio)
{
plane.scaleX = matAR / aspectRatio;
}
var mat:MovieMaterial = new MovieMaterial(movie, false, true, false, new Rectangle(0, 0, width, height));
mat.interactive = true;
mat.smooth = true;
plane.material = mat;
}
Below I have posted two pictures. The first is a shot of the application running by itself. The second is the application as a MovieMaterial on a Plane. You can see how the button created as a spark object in the mxml stays in the correct position, but papervision sphere (which is rotating) is in the wrong location. Is there something I am missing here?
Man. I haven't seen that site in a while. Still one of the cooler PV projects...
What do you mean by:
I cannot properly see the scene rendered in Papervision
You say you can see the components in their appropriate positions, as in: you have a plane with what looks like the intended file loading up? But I'm guessing that you can't interact with it.
As far as I know, and I've spent a reasonable amount of time trying to make something similar work, the MovieMaterial (which I assume you're using) draws a Bitmap of whatever contents exist in your MovieClip, and if you set it to animated=true, then it will render out a series of bitmaps - equating animation. What it's not doing, is displaying an actual MovieClip (or SWF) on the plane. So you may see your components, but this is how:
MovieMaterial.as line 137
// ______________________________________________________________________ CREATE BITMAP
/**
*
* #param asset
* #return
*/
protected function createBitmapFromSprite( asset:DisplayObject ):BitmapData
{
// Set the new movie reference
movie = asset;
// initialize the bitmap since it's new
initBitmap( movie );
// Draw
drawBitmap();
// Call super.createBitmap to centralize the bitmap specific code.
// Here only MovieClip specific code, all bitmap code (maxUVs, AUTO_MIP_MAP, correctBitmap) in BitmapMaterial.
bitmap = super.createBitmap( bitmap );
return bitmap;
}
Note in the WhiteVoid you never actually interact with a movie until it "lands" = he's very likely swapping in a Movie on top of the bitmap textured plane.
The part that you are interacting with is probably another plane that holds the "button" that simply becomes visible on mouseover.
I think PV1.0 had access to real swfs as a material but this changed in 2.0. Sadly. Hopefully Molehill will.
cheers