Friday 4 July 2008

Mapping flv video to geometry in Actionscript

To avoid having to use SWF encapsulated video files to map video to geometry in Flash 9, use the flash.media.Video class instead. The following extends the Plane class in the open source Away3D flash library to have a plane with a texture mapped video (flv). The constructor takes the location of the flv file (either a path to the file or as a URL).

This version of the class should now work with Away3D 3.0.0

package
{
import away3d.core.math.Number3D;
import away3d.primitives.Plane;
import away3d.materials.BitmapMaterial;
import away3d.materials.VideoMaterial;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.display.*;
import flash.events.*;
import flash.net.*;
import flash.media.Video;


public class videoPlane extends Plane
{
private var video: DisplayObject;
private var videoURL:String;
private var videoBitmapData: BitmapData;
private var videomaterial: BitmapMaterial;

private var alphaMap:BitmapData;

private var vidConnection:NetConnection;
private var vidStream:NetStream;
private var vid:Video;
private var infoClient:Object;
private var alphax:Number;
private var alphay:Number;
private var asset:String;
private var alphaBool:Boolean;


private var aspectRatio:Number;



public function videoPlane(assetLocation:String)
{

asset = assetLocation;
this.ownCanvas = true;
alphaBool = true;

trace("videoPlane()");
this.segmentsH = 8; //increases the number of triangles in the plane, and hence improves the accuracy of
this.segmentsW = 8; //the mean z algorithm used to determine Z-depth when rendering


vidConnection = new NetConnection();
vidConnection.addEventListener(NetStatusEvent.NET_STATUS, NetStatusHandler);
vidConnection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, SecurityErrorHandler);
vidConnection.connect(null);


this.bothsides = true;
aspectRatio = 1024 / 576;

this.height = 50;

this.width = this.height * aspectRatio;




}

private function NetStatusHandler(event:NetStatusEvent):void
{
switch (event.info.code)
{
case "NetConnection.Connect.Success":
vidStream = new NetStream(vidConnection);
infoClient = new Object();
vidStream.client = infoClient;
vid = new Video();
vid.attachNetStream(vidStream);
vidStream.play(asset);
this.videoBitmapData = new BitmapData(vid.width, vid.height, true, 0xFF00ce);
videomaterial = new BitmapMaterial(this.videoBitmapData);
videomaterial.precision = 5;
this.material = videomaterial;
this.bothsides = true;
this.videoBitmapData.draw(vid);
alphaMap = new BitmapData(vid.width, vid.height, true, 0x7F000000);
vidStream.addEventListener(NetStatusEvent.NET_STATUS, vidStreamCompleteHandler);
//connectStream();
break;
case "NetStream.Play.StreamNotFound":
dispatchEvent(new StatusEvent(StatusEvent.STATUS, true, false, event.info.code, "Status"));
break;
}


}

private function SecurityErrorHandler(event:SecurityErrorEvent):void
{
dispatchEvent(new StatusEvent(StatusEvent.STATUS, true, false, event.type, "Status"));
}


private function vidStreamCompleteHandler(ns:NetStatusEvent):void
{

if (ns.info.code == "NetStream.Play.Stop")
{
vidStream.seek(0);
vidStream.resume();
}

}


public function updateVideo():void
{

//trace("updateVideo");

if(vid != null)
{

videomaterial = new BitmapMaterial(this.videoBitmapData);

this.material = videomaterial;

this.videoBitmapData.draw(vid);


}


}

public function pausePlayback():void
{
vidStream.pause();
}
public function resumePlayback():void
{
vidStream.resume();
}

}

}

2 comments:

Anonymous said...

Hi there, thank you for sharing your videoPlane class, I have a problem tho.

var videA:videoPlane;
videA = videoPlane("media/test.flv");
addChild( videA );

Is that the correct use? I'm getting Error 1034: can't convert "media/test.flv" in videoPlane.

Thanks for any pointers.

Best.

LJ said...

Hmm, bit sure about that, it looks like a casting error, possibly due to the string argument rather than the video (I assume that you have copied the code from this blog into a file, inserted that file into your flash project).

Try altering the videoPlane class to use a hardcoded address for the video asset.

ie

change:
vidStream.play(assetLocation);

to

vidStream.play("media/test.flv");


Looking this error up on other websites, it may also be dependent on where you are taking your flv file from, is it from a server? Or a local file?
Sorry I cant be more help, it is not a problem I have seen or can replicate.