Flex 4 (Gumbo) Fire Video on the Supper Club

Intro

Our group just finished the first part of the Beverly Hills Supper Club project. I realize that this is a sensitive area and lives were lost. The completed site will be a memorial to those loved ones that were lost in this tragic fire.

Here I demonstrated playing the Supper Club fire video on the Blender building skin. To see the demo just click the image below (drag the building with the mouse to rotate it and click the play video button to get the video to play):

Supper Club Video on a Blender Model

Supper Club Video on a Blender Model

Demo

Code (Only MXML File – Video too large for Google Code)

UTube

Discussion

It’s pretty easy. Just follow the posts below which explain everything in detail:

1. Learn about netStream and netConnection

Adding Video to a Papervision3D Curved Plan

2. Learn about using video in CS4

Putting Video on a CS4 (Flash 10) Primitive

3. Learn how to build a CS4 shaded model using drawTriangles

CS4 Flat Shaded Tie Fighter with drawTriangles

4. Learn about Light in Papervision3D

Adding Brightness to PV3D Light Source

5. Learn how to model in Blender

3D Modeling

6. Learn how to export your Blender models to Papervision3D and CS4

New Blender XML Exporter/PV3D XML Primitive

The big trick to this is to create a simple parameter that allows you to switch between the shaded model and video within the triangle creation loop.

playMyVideo = false or true;

Run Shade Code if false

….

Run Video Code if true

}else{

var vertices2:Vector.<Number>=new Vector.<Number>();
vertices2.push(dispVec[facesVec[curFace][0]].x, dispVec[facesVec[curFace][0]].y);
vertices2.push(dispVec[facesVec[curFace][1]].x, dispVec[facesVec[curFace][1]].y);
vertices2.push(dispVec[facesVec[curFace][2]].x, dispVec[facesVec[curFace][2]].y);

//Draw Video into Bitmap
bitmapData.draw( this.myVideo);
this.myVideo.attachNetStream ( this.myStream );

spObjImage.graphics.beginBitmapFill(bitmapData,null, false, false);
spObjImage.graphics.drawTriangles(vertices2);
spObjImage.graphics.drawTriangles(vertices2)

}

Another trick is handling rotations correctly. To do this you need to use subtraction of your previous position from you present position (since you are appending rotation in this example). So if you are rotating forward the difference is positive and if backwards the difference is negative.

private function boardMove(e:MouseEvent):void {

var locX:Number=prevX;
var locY:Number=prevY;
if(doRotate){
prevX=spBoard.mouseX;
prevY=spBoard.mouseY;
rotateObj(prevY-locY,-(prevX-locX),0);
e.updateAfterEvent();

}

Once you “get this in your head” you’ll undertstand “append” rotation in CS4 – otherwise it’s uncontrollably wild.

Now there’s on more “Super trick”. This application was originally created for an Adobe Air and was run on the desktop. So when you put it on the web the video will not work since it uses

spObjImage.graphics.drawTriangles(vertices2)

looks like a terrible sandbox issue, but wait a second didn’t we get video on a prim in the previous post on Putting Video on a CS4 (Flash 10) Primitive…

Yes we did???

But this time we don’t have indices and uv data … shouldn’t we just give up or get some expert to tell us what to do…nah, just replace indices and uv data with null and it works…please don’t ask me why. Remember, I said this was a trick.

spObjImage.graphics.drawTriangles(vertices2, null, null,TriangleCulling.NEGATIVE);

And Tada, video on the Supper Club.

Remarks

The full project will allow site visitors to leave messages in supper club rooms…building a flexpress flat-file data base to handle these messages is part of the TEI project… The advantage of the flat-file data base is that you can drop the program onto any server – hassle free and it works – no fancy install!

To see the entire code click the more button below:

Full Code

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml&#8221; layout=”absolute” creationComplete=”init()”>

<mx:Script>
<![CDATA[

import mx.collections.ArrayCollection;

import flash.net.URLRequest;
import mx.controls.Alert;
import flash.media.SoundChannel;

import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.net.*;

import org.lively3d.lights.SimpleLight;
import org.lively3d.materials.utils.LightMaps;

import mx.core.BitmapAsset;

private var soundChannel:SoundChannel;

private var numVertices:int;
private var numFaces:int;
private var imageStringNum:String;
private var imageNum:int;
private var vertsVec:Vector.<Vector3D>=new Vector.<Vector3D>();
private var facesVec:Vector.<Array>=new Vector.<Array>();
private var facesColors:Vector.<Number>= new Vector.<Number>();
private var fLen:Number=500;
private var spBoard:Sprite=new Sprite();
private var shBack:Shape=new Shape();
private var spObject:Sprite=new Sprite();
private var spObjImage:Sprite=new Sprite();
private var doRotate:Boolean=false;
private var prevX:Number;
private var prevY:Number;

private var bitmapData:BitmapData;
private var playMyVideo:Boolean=false;

//Video
//net stream assets
private var myConnection : NetConnection;
private var myStream : NetStream;
private var myVideo : Video;
private var myCam:Camera;
private var matrix:Matrix;

private var myCount:int=0;

private var doIterate:Boolean=false;

private var AVect:Vector.<Vector3D>=new Vector.<Vector3D>();

//Photo Sphere

private var posX:Number=250;
private var posY:Number=250;

private var rad:Number=250;
private var thumbWidth:Number=70;
private var thumbHeight:Number=53;
private var thumbsArray:Array=[];
private var picsArray:Array=[];
private var holdersArray:Array=[];
private var midsArray:Array=[];
private var splitArray:Array=[];

private var stringNumIs:Number;

private var jLen:Vector.<Number>=new Vector.<Number>();
private var thetaStep:Vector.<Number>=new Vector.<Number>();
private var phiStep:Number=30;
private var phiTilt:Vector.<Number>=new Vector.<Number>();
private var autoOn:Boolean=true;
private var manualOn:Boolean=false;
private var prevX2:Number;
private var prevY2:Number;

private var board:Sprite=new Sprite();
private var spSphere:Sprite=new Sprite();

private var photoHolder:Sprite=new Sprite();

private var loader:Loader=new Loader();

//set a light in the scene
private var light:SimpleLight=new SimpleLight(100, 100, -1000, 1,0xffffff,0x3322ee,5);

//The ‘velocity’ variables are related to auto rotation.

private var velX:Number=0;
private var velY:Number=0;
private var velMag:Number=5;
//for shading
private var _colors:Array;

public var myFileGet:String;
public var xmlReq:URLRequest;
public var xmlLoader:URLLoader;
public var myData_xml:XML;
public var iFacNum:Number;

private var i:int;
private var j:int;
private var distArray:Array= new Array();
private var dispVec:Vector.<Vector3D>=new Vector.<Vector3D>();
private var newVertsVec:Vector.<Vector3D>=new Vector.<Vector3D>();
private var zAverage:Number;
private var dist:Number;
private var curFace:int;
private var curFaceLen:int;
private var curObjMat:Matrix3D;

private var myXRotIs:Number=0;
private var myYRotIs:Number=0;
private var myZRotIs:Number=0;

private function init():void{

bitmapData = new BitmapData(320, 240, false);

initboard();

//Test 3D
var externalXML:XML;
var loader:URLLoader = new URLLoader();
var request:URLRequest = new URLRequest(“data/buildwtop.xml”);

loader.load(request);
loader.addEventListener(Event.COMPLETE, onComplete);

function onComplete(event:Event):void
{
var loader:URLLoader = event.target as URLLoader;
if (loader != null)
{
externalXML = new XML(loader.data);
setVertices(externalXML);
}
else
{
trace(“loader is not a URLLoader!”);
}

}
rotateObj(0,0,0);

}

private function loadMyVideo(event:MouseEvent):void
{

if(myPlayBtn.label==”Play Video”){

myPlayBtn.label=”Stop Video”;

playMyVideo=true;

//Set up Net Connection
myConnection = new NetConnection();
//Not on the media server
myConnection.connect(null);
myStream = new NetStream(myConnection);
//Set buffer time – at lease 2 seconds are required for some machines.
myStream.bufferTime = 2;
//Set up My Stream for client
myStream.client = new Object();
//Instantiate the video
myVideo = new Video(320, 240);
myStream.play(“video/Supper_Club_Fire.flv”);
//Attach to local client side video
myVideo.attachNetStream(myStream);

}else{

myPlayBtn.label=”Play Video”;
playMyVideo=false;
myStream.pause();
myConnection.close();

}}

private function initboard():void{

mapHolder.rawChildren.addChild(spBoard);

spBoard.x=350;
spBoard.y=285;
spBoard.filters=[ new DropShadowFilter() ];
spBoard.addChild(shBack);
spBoard.addChild(spObjImage);
spObject.rotationX=170;
spObject.rotationY=190;
spObject.rotationZ=0;
spObject.scaleX=3.0;
spObject.scaleZ=3.0;
spObject.scaleY=1.5;

addList();
drawBoard2();

}

private function myXRot():void{

rotateObj(-(xSlider.value-myXRotIs),0,0)

myXRotIs=xSlider.value;
}

/* private function myYRot():void{

rotateObj(0,-(ySlider.value-myYRotIs),0)

myYRotIs=ySlider.value;

}

private function myZRot():void{

rotateObj(0,0,-(zSlider.value-myZRotIs))
myZRotIs=zSlider.value;

} */

//Model Parsing Functions
private function setVertices(myData_xml:XML):void {

var mySlitVert:Array=myData_xml.myPrimSet[0].myVertices.split(“,”);
var mySlitFace:Array=myData_xml.myPrimSet[0].myFaces.split(“,”);
numVertices=(mySlitVert.length-1)/3;
var myScale:Number=20;

for(i=0;i<=numVertices;i++){

vertsVec[i]= new Vector3D(mySlitVert[i*3]*myScale,mySlitVert[i*3+1]*myScale,mySlitVert[i*3+2]*myScale);
}

numFaces = (mySlitFace.length-1)/3;

for(j=0;j<=numFaces;j++){

facesVec[j]=[mySlitFace[j*3],mySlitFace[j*3+1],mySlitFace[j*3+2]];
facesColors[j]=Math.random()*0xffffff;
}}

//There are no changes in rotateObj function.

private function rotateObj(rotx:Number,roty:Number,rotz:Number):void {

spObject.transform.matrix3D.appendRotation(rotx,Vector3D.X_AXIS);
spObject.transform.matrix3D.appendRotation(roty,Vector3D.Y_AXIS);
spObject.transform.matrix3D.appendRotation(rotz,Vector3D.Z_AXIS);
curObjMat=spObject.transform.matrix3D.clone();
spObjImage.graphics.clear();

for(i=0;i<numVertices;i++){

newVertsVec[i]=curObjMat.deltaTransformVector(vertsVec[i]);

}

for(i=0;i<numVertices;i++){

newVertsVec[i].w=(fLen+newVertsVec[i].z)/fLen;
newVertsVec[i].project();
}

//Depth Sorting

for(i=0;i<numFaces;i++){

zAverage=0;
for(j=0;j<3;j++){
zAverage+=newVertsVec[facesVec[i][j]].z;
}

zAverage/=3;
dist=zAverage;
distArray[i]=[dist,i];
}

//distArray.sortOn(“byDist”, Array.DESCENDING | Array.NUMERIC);

distArray.sort(byDist);

for(i=0;i<numVertices;i++){

dispVec[i]=new Vector3D();
dispVec[i].x=newVertsVec[i].x;
dispVec[i].y=newVertsVec[i].y;
dispVec[i].z=newVertsVec[i].z;

}

for(i=0;i<numFaces;i++){

curFace=distArray[i][1];
var Shader:String=”flat”;

if(playMyVideo==false){

switch(Shader){

case “flat”:

AVect[0]=new Vector3D(dispVec[facesVec[curFace][0]].x,dispVec[facesVec[curFace][0]].y,dispVec[facesVec[curFace][0]].z);
AVect[1]=new Vector3D(dispVec[facesVec[curFace][1]].x,dispVec[facesVec[curFace][1]].y,dispVec[facesVec[curFace][1]].z);
AVect[2]=new Vector3D(dispVec[facesVec[curFace][2]].x,dispVec[facesVec[curFace][2]].y,dispVec[facesVec[curFace][2]].z);

AVect[3]= AVect[0].subtract(AVect[1]);
AVect[4]= AVect[1].subtract(AVect[2]);

AVect[5]=AVect[4].crossProduct(AVect[3]);
AVect[6]=new Vector3D(light.x, light.y, light.z);

var mag1:Number=AVect[5].length;
var mag2:Number=AVect[6].length;

var zd:Number = AVect[6].dotProduct(AVect[5])/(mag1*mag2);

if(zd < 0){
zd = 0;
}else{
zd = Math.abs(zd);
};

_colors = LightMaps.getFlatMapArray(light.lightColor, light.ambientColor, light.specular);
var zAngle:int = zd*0xff*light.brightness;
var currentColor:Number = _colors[zAngle];

break;
case “cell”:
//See the book website
break;
case “gouraud”:
//See the book website
break;
case “phong”:
//See the book website
break;
case “envmap”:
//See the book website
break;

default:
//Not in my arsenal
break;}

if(zd>0){
var vertices:Vector.<Number>=new Vector.<Number>();
vertices.push(dispVec[facesVec[curFace][0]].x, dispVec[facesVec[curFace][0]].y);
vertices.push(dispVec[facesVec[curFace][1]].x, dispVec[facesVec[curFace][1]].y);
vertices.push(dispVec[facesVec[curFace][2]].x, dispVec[facesVec[curFace][2]].y);
//spObjImage.graphics.lineStyle(0);
spObjImage.graphics.beginFill(currentColor, .8);
spObjImage.graphics.drawTriangles(vertices);
}}else{

var vertices2:Vector.<Number>=new Vector.<Number>();
vertices2.push(dispVec[facesVec[curFace][0]].x, dispVec[facesVec[curFace][0]].y);
vertices2.push(dispVec[facesVec[curFace][1]].x, dispVec[facesVec[curFace][1]].y);
vertices2.push(dispVec[facesVec[curFace][2]].x, dispVec[facesVec[curFace][2]].y);

//Draw Video into Bitmap
bitmapData.draw( this.myVideo);
this.myVideo.attachNetStream ( this.myStream );

spObjImage.graphics.beginBitmapFill(bitmapData,null, false, false);
//spObjImage.graphics.drawTriangles(vertices2);
//Super Trick
spObjImage.graphics.drawTriangles(vertices2, null, null,TriangleCulling.NEGATIVE);
}

}
}

private function byDist(v:Array,w:Array):Number {

if (v[0]>w[0]){

return -1;

} else if (v[0]<w[0]){

return 1;

} else {

return 0;
}

}

private function addList():void{

spBoard.addEventListener(MouseEvent.ROLL_OUT,boardOut);
spBoard.addEventListener(MouseEvent.MOUSE_MOVE,boardMove);
spBoard.addEventListener(MouseEvent.MOUSE_DOWN,boardDown);
spBoard.addEventListener(MouseEvent.MOUSE_UP,boardUp);
this.addEventListener(Event.ENTER_FRAME,whenEnterFrame);

}

private function boardOut(e:MouseEvent):void {
doRotate=false;
}

private function boardDown(e:MouseEvent):void {

prevX=spBoard.mouseX;
prevY=spBoard.mouseY;
velX=0;
velY=0;
velMag=0;
doRotate=true;
}

private function boardUp(e:MouseEvent):void {

doRotate=false;

}

private function boardMove(e:MouseEvent):void {

var locX:Number=prevX;
var locY:Number=prevY;
if(doRotate){
prevX=spBoard.mouseX;
prevY=spBoard.mouseY;
//velX=-2*(prevX-locX);
//velY=2*(prevY-locY);
//velMag=Math.abs(velX)+Math.abs(velY);
rotateObj(prevY-locY,-(prevX-locX),0);
e.updateAfterEvent();

}
}

private function whenEnterFrame(e:Event):void {

//if(!doRotate >0 ||playMyVideo==true){

rotateObj(0,0,0);

myCount++;

//}
}

private function drawBoard2():void {

spBoard.graphics.clear();

spBoard.graphics.beginFill(0x000000, .01);

spBoard.graphics.drawRect(-240,-240,400,400);

spBoard.graphics.endFill();

}

private function zSortPics():void {

var distArray:Array=[];

var dist:Number;

var i:int;

var j:int;

var k:int;

var curMatrix:Matrix3D;

var curMid:Vector3D;

curMatrix=spSphere.transform.matrix3D.clone();

while(spSphere.numChildren>0){

spSphere.removeChildAt(0);

}

for(i=0;i<7;i++){

for(j=0;j<jLen[i];j++){

curMid=curMatrix.deltaTransformVector(midsArray[i][j]);

dist=curMid.z;

distArray.push([dist,i,j]);

}

}

distArray.sort(byDist);

for(k=0;k<distArray.length;k++){

spSphere.addChild(holdersArray[distArray[k][1]][distArray[k][2]]);

holdersArray[distArray[k][1]][distArray[k][2]].alpha=Math.max(k/(distArray.length-1),0.5);

}

}

private function rotateSphere(rotx:Number,roty:Number,rotz:Number):void {

spSphere.z=0;

spSphere.transform.matrix3D.appendRotation(rotx,Vector3D.X_AXIS);

spSphere.transform.matrix3D.appendRotation(roty,Vector3D.Y_AXIS);

spSphere.transform.matrix3D.appendRotation(rotz,Vector3D.Z_AXIS);

spSphere.z=rad;

zSortPics();

}

]]>
</mx:Script>

<mx:Canvas id=”pv3dContainer” clipContent=”true” left=”0″ right=”0″ top=”0″ bottom=”0″ horizontalScrollPolicy=”off” verticalScrollPolicy=”off” color=”#000202″ backgroundColor=”#010000″>

<mx:VRule x=”169.1″ y=”48″ width=”8.6″ height=”673″/>

<mx:HSlider x=”6.1″ y=”195.05″ width=”160″ height=”12″ id=”xSlider” change=”myXRot()” minimum=”-90″ maximum=”90″ value=”0″ liveDragging=”true” />
<mx:Label x=”10″ y=”166.05″ text=”Rotation” color=”#FEFEFE”/>
<mx:Button id=”myPlayBtn” x=”10″ y=”130″ label=”Play Video” click=”loadMyVideo(event)” />
<mx:Canvas id=”mapHolder” x=”209.1″ y=”90.05″ width=”125″ height=”117″>
</mx:Canvas>

</mx:Canvas>

<mx:Canvas id=”mapNavigationPanel0″ horizontalScrollPolicy=”off” verticalScrollPolicy=”off” backgroundColor=”#1C1C1C” backgroundAlpha=”0.7″ cornerRadius=”6″ borderStyle=”solid” top=”10″ left=”27″ right=”148″ height=”36″>
<mx:filters>
<mx:DropShadowFilter alpha=”0.5″ blurX=”6″ blurY=”4″ angle=”90″ distance=”1″ quality=”2″ />
</mx:filters>
<mx:Label text=”Beverly Hills Supper Club” fontSize=”20″ fontWeight=”normal” id=”demoTitle” top=”1″ left=”53″ height=”33″ color=”#FFFFFF” width=”316″>
</mx:Label>
</mx:Canvas>
</mx:Application>


About these ads

One Response to Flex 4 (Gumbo) Fire Video on the Supper Club

  1. [...] > Flex 4 (Gumbo) Fire Video on the Supper Club « Professional Papervision3D Book [...]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: