forever (1st Papervision Wii Movie)

Intro

A long term goal of ours has been to produce movies with Papervision. Our first attempt is “forever”. We created this movie by screen capturing a Wii controlled silly string application we had written. What we learned from our first creation was how powerful the Wii was as an animation tool in making 3D movies.

We are now working on our next movie called Harry.

The YouTube movie is below. My son Josh (the incredible guitar player) put together all the music.

YouTube Video

Scaled Down Non-Wii version

Click on the image or link below to view a scaled down non-Wii version of this application. Placing your mouse cursor on the right side of the screen causes the string to grow fat, on the left side skinny.

Scaled Down Non-Wii Version

Scaled Down Non-Wii Version

Or click on the link below;

http://www.professionalpapervision.com/demos/web/sillystring/

Downloads

You can download the Wii controlled Silly String program from

http://code.google.com/p/flex3cookbook2/downloads/list

there is also a scaled down web version you can download.

Wiimote Comands

For this particular demonstration we programmed the Wiimote keys as follows. Of course this will change depending on the application.

Press A = Increase Orbit Radius
Release A = Return
Orbit Radius
Press B = Get Fat
Release B = Return Skinny
Press UP = Zoom Out
Release Down = Zoom In

Press + = Increase Velocity
Release
Press – = Decrease Velocity
Press Home = Blow Up (Repeating Destroys More)

Creating the Disk

To create the Wii Disk shown below slow your velocity to zero by holding the “-” key. The silly string will wrap around itself creating the disk. Then play around by pressing the B key, the A key, and then blow it up using the home key.

Disk Trick

Disk Trick

Discussion

The heart of the Wii controlled silly string program is the line3D class and the Wii starter code provided in a previous post. Drawing a 3D line is really simple in Papervision. Just create a new line as shown below

new Line3D(lines, lineMaterial, lineSize, prevVertex3d, myVertexHere);

and give it a starting point and ending point as shown above. The string is then pushed forward by continually incrementing rotation (pitch, yaw, and roll) of the guiding sphere and using the moveForward command as shown below;

sphere.rotationX+=-(int(MyWiiIs.pitch*400)/100);
sphere.rotationY+=(int(MyWiiIs.yaw*400)/100);
sphere.rotationZ+=(int(MyWiiIs.roll*400)/100);

sphere.moveForward(forwardSpeed);

Finally, the string is constrained to a sphere by setting its last coordinates to the guiding sphere’s coordinates. The radius of the sphere constraint can be changed by changing the velocity of your string.

sphere.x=lines.x;
sphere.y=lines.y;
sphere.z=lines.z;

Click the more button below to see the entire code.

Complete Code

package
{
//Flash imports

import flash.display.*;
import flash.events.*;

import org.papervision3d.core.geom.*;
import org.papervision3d.core.geom.renderables.*;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.materials.special.LineMaterial;
import org.papervision3d.objects.*;
import org.papervision3d.objects.primitives.*;
import org.papervision3d.view.BasicView;
import org.wiiflash.Wiimote;
import org.wiiflash.events.ButtonEvent;
import org.wiiflash.events.WiimoteEvent;

public class MyStringThree2 extends BasicView
{

protected var planeBitmapData:BitmapData;
protected var planeMaterial:BitmapMaterial;

public var lineSize:Number = 2;
public var lineSize2:Number = 2;
public var lineSize3:Number = 2;

public var myMoveBack:int=2000;
public var cameraUp:int=0;

private var sideSpeed:Number = 0;
private var forwardSpeed:Number = 500;
private var lineMaterial:LineMaterial;
private var lineMaterial2:LineMaterial;
private var lineMaterial3:LineMaterial;
public var prevVertex3d:Vertex3D;
public var prevVertex3d2:Vertex3D;
public var prevVertex3d3:Vertex3D;
public var stringRadii:Number=10;
private var upRotationSpeed:Number = 0;
private var lines:Lines3D;
private var lines2:Lines3D;
private var lines3:Lines3D;

private var sphere:Sphere;
private var sphereMaterial:WireframeMaterial;

public var wasHere:uint=0;

public var myOsc:int=0;
public var myOscNum:Number;

private var dummy:DisplayObject3D;

private var MyWiiIs:Wiimote;

//Call to the BaseView constructor
public function MyStringThree2()
{
//Width and Height are set to 1, since scaleToStage is set to true, these will be overriden.

super(1, 1, true, true);
lineSize = 2;
sideSpeed = 0;
upRotationSpeed = 0;
forwardSpeed = 500;

MyWiiIs = new Wiimote();
MyWiiIs.connect();

// myWiimote.addEventListener( ButtonEvent.A_PRESS, onAPressed );

initPV3D();
WiiListeners();

}

private function WiiListeners():void{

//Pitch, Yaw, Roll
MyWiiIs.addEventListener( WiimoteEvent.UPDATE, onUpdated );
//Bottons
MyWiiIs.addEventListener( ButtonEvent.A_PRESS, onAPressed );
MyWiiIs.addEventListener( ButtonEvent.A_RELEASE, onAReleased);
MyWiiIs.addEventListener( ButtonEvent.LEFT_PRESS, onLeftPressed );
MyWiiIs.addEventListener( ButtonEvent.LEFT_RELEASE, onLeftReleased);
MyWiiIs.addEventListener( ButtonEvent.RIGHT_PRESS, onRightPressed );
MyWiiIs.addEventListener( ButtonEvent.RIGHT_RELEASE, onRightReleased);
MyWiiIs.addEventListener( ButtonEvent.UP_PRESS, onUpPressed );
MyWiiIs.addEventListener( ButtonEvent.UP_RELEASE, onUpReleased);
MyWiiIs.addEventListener( ButtonEvent.DOWN_PRESS, onDownPressed );
MyWiiIs.addEventListener( ButtonEvent.DOWN_RELEASE, onDownReleased);
MyWiiIs.addEventListener( ButtonEvent.B_PRESS, onBPressed );
MyWiiIs.addEventListener( ButtonEvent.B_RELEASE, onBReleased);
MyWiiIs.addEventListener( ButtonEvent.MINUS_PRESS, onMinusPressed);
MyWiiIs.addEventListener( ButtonEvent.MINUS_RELEASE, onMinusReleased);
MyWiiIs.addEventListener( ButtonEvent.PLUS_PRESS, onPlusPressed);
MyWiiIs.addEventListener( ButtonEvent.PLUS_RELEASE, onPlusReleased);
MyWiiIs.addEventListener( ButtonEvent.HOME_PRESS, onHomePressed);
MyWiiIs.addEventListener( ButtonEvent.HOME_RELEASE, onHomeReleased);
MyWiiIs.addEventListener( ButtonEvent.ONE_PRESS, onOnePressed);
MyWiiIs.addEventListener( ButtonEvent.ONE_RELEASE, onOneReleased);
MyWiiIs.addEventListener( ButtonEvent.TWO_PRESS, onTwoPressed);
MyWiiIs.addEventListener( ButtonEvent.TWO_RELEASE, onTwoReleased);

}

private function onUpdated ( pEvt:WiimoteEvent ):void

{

//modelLocator.myPitchNow=pEvt.target.pitch;
//modelLocator.myRollNow=pEvt.target.roll;
//modelLocator.myYawNow=pEvt.target.yaw;

//trace(pEvt.target.sensorX +” x”);
//trace(pEvt.target.sensorY +” y”);
//trace(pEvt.target.batteryLevel +” battery level”);

}

public var increaseMe:Boolean=false;
public var decreaseMe:Boolean=false;

public var mylinesize:Boolean=false;
public var myradiusis:Boolean=false;

public var myzoomplus:Boolean=false;
public var myzoomminus:Boolean=false;

private function onAPressed ( pEvt:ButtonEvent ):void

{

myradiusis=true;

}

private function onAReleased ( pEvt:ButtonEvent ):void
{

myradiusis=false;

}

private function onMinusPressed ( pEvt:ButtonEvent ):void
{

decreaseMe=true;
}

private function onMinusReleased ( pEvt:ButtonEvent ):void
{

decreaseMe=false;

}

private function onPlusPressed ( pEvt:ButtonEvent ):void
{
increaseMe=true;

}

private function onPlusReleased ( pEvt:ButtonEvent ):void
{

increaseMe=false;

}

private function onHomePressed ( pEvt:ButtonEvent ):void
{
forwardSpeed = 500;

var ii:int;
for (ii = 0; ii < lines.lines.length; ii++)
{

lines.removeLine(lines.lines[ii]);
lines2.removeLine(lines2.lines[ii]);
lines3.removeLine(lines3.lines[ii]);
}

}

private function onHomeReleased ( pEvt:ButtonEvent ):void
{
trace(“Home Released”);

}

private function onOnePressed ( pEvt:ButtonEvent ):void
{

trace(“onOnePressed”);

}

private function onOneReleased ( pEvt:ButtonEvent ):void
{
trace(“onOneReleased”);

}

private function onTwoPressed ( pEvt:ButtonEvent ):void
{

trace(“onTwoPressed”);

}

private function onTwoReleased ( pEvt:ButtonEvent ):void
{
trace(“onTwoReleased”);

}

private function onBPressed ( pEvt:ButtonEvent ):void
{

mylinesize=true;

}

private function onBReleased ( pEvt:ButtonEvent ):void

{

mylinesize=false;

}

private function onUpPressed ( pEvt:ButtonEvent ):void
{

myzoomplus=true;

}

private function onUpReleased ( pEvt:ButtonEvent ):void
{

myzoomplus=false;

}

private function onLeftPressed ( pEvt:ButtonEvent ):void

{

trace(“onLeftPressed”);

}

private function onLeftReleased ( pEvt:ButtonEvent ):void
{

trace(“onLeftReleased”);

}

private function onRightPressed ( pEvt:ButtonEvent ):void
{

trace(“onRightPressed”);
}

private function onRightReleased ( pEvt:ButtonEvent ):void

{

trace(“onRightReleased”);

}

private function onDownPressed ( pEvt:ButtonEvent ):void
{

myzoomminus=true;

}

private function onDownReleased ( pEvt:ButtonEvent ):void
{

myzoomminus=false;

}

private function initPV3D():void
{
//Set the Stage Scale

setStage();

//Color the background of this basicview / helloworld instance black.
opaqueBackground = 0;

//Create the materials and primitives.
createObjects();

//Call the native startRendering function, to render every frame.
startRendering();

}

protected function setStage():void{

stage.quality=”low”;
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;

}

//createObjects creates the needed primitives, and materials.

protected function createObjects():void
{

// Create a material for the sphere
sphereMaterial = new WireframeMaterial(0x44FF44);

// Create use wireframe material, radius 100, default 0,0,0
sphere = new Sphere(sphereMaterial, stringRadii/2, 6, 6);

/* sphere.x=-300;
sphere.y=100;

// Add Your Sphere to the Scene
scene.addChild(sphere);

var light:PointLight3D = new PointLight3D();
light.x = -1000;
light.y = 1000;
light.z=1000;

sphereMaterial = new FlatShadeMaterial(light, 0xcccc00);

sphere = new Sphere(sphereMaterial, 1, 10, 10); */

lineMaterial = new LineMaterial(0xFF4444, 1);
lineMaterial2 = new LineMaterial(0x44FF44, 1);
lineMaterial3 = new LineMaterial(0x4444FF, 1);

lines = new Lines3D(lineMaterial);
lines.addNewLine(lineSize, 0, 0, 0, 0, 0, 500);

lines2 = new Lines3D(lineMaterial2);
lines2.addNewLine(lineSize, 0, 0, 0, 0, 0, 500);

lines3 = new Lines3D(lineMaterial2);
lines3.addNewLine(lineSize, 0, 0, 0, 0, 0, 500);

prevVertex3d = lines.geometry.vertices[1];
prevVertex3d2= lines2.geometry.vertices[1];
prevVertex3d3= lines3.geometry.vertices[1];

scene.addChild(sphere);
scene.addChild(lines);
scene.addChild(lines2);
scene.addChild(lines3);

}

// onRenderTick can be overriden so you can execute code on a per render basis, using basicview.

override protected function onRenderTick(event:Event=null):void
{myOsc++;

//shootString();

//Render Scene

//Call the super.onRenderTick function, which renders the scene to the viewport using the renderer and camera classes.
super.onRenderTick(event);

var myVertexHere:Vertex3D;
var my3DLine:Line3D;

var myVertexHere2:Vertex3D;
var my3DLine2:Line3D;

var myVertexHere3:Vertex3D;
var my3DLine3:Line3D;

sphere.rotationX+=-(int(MyWiiIs.pitch*400)/100);
sphere.rotationY+=(int(MyWiiIs.yaw*400)/100);
sphere.rotationZ+=(int(MyWiiIs.roll*400)/100);

if(increaseMe){forwardSpeed=forwardSpeed+10;
trace(forwardSpeed);
}
if(decreaseMe){forwardSpeed=forwardSpeed-10;
trace(forwardSpeed);
if(forwardSpeed<=0){forwardSpeed=0;}
}

sphere.moveForward(forwardSpeed);

if(mylinesize){lineSize++;
}else{lineSize–;
if(lineSize<=2){lineSize=2;
}

trace(lineSize);

}

if(myradiusis){stringRadii++;
sphere.scale=stringRadii/20;
}else{stringRadii–;
sphere.scale=stringRadii/20;
if(stringRadii<=10){stringRadii=10;

}

}

//myzoomminus
if(myzoomplus){myMoveBack=myMoveBack-50;
}

//myzoomminus
if(myzoomminus){myMoveBack=myMoveBack+50;

}

myVertexHere = new Vertex3D(stringRadii*Math.sin(myOsc+2*Math.PI/3)+sphere.x, stringRadii*Math.cos(myOsc+2*Math.PI/3)+sphere.y, sphere.z);
my3DLine = new Line3D(lines, lineMaterial, lineSize, prevVertex3d, myVertexHere);
lines.addLine(my3DLine);
prevVertex3d = myVertexHere;

myVertexHere2 = new Vertex3D(stringRadii*Math.sin(myOsc)+sphere.x, stringRadii*Math.cos(myOsc)+sphere.y, sphere.z);
my3DLine2 = new Line3D(lines2, lineMaterial2, lineSize, prevVertex3d2, myVertexHere2 );
lines2.addLine(my3DLine2);
prevVertex3d2 = myVertexHere2;

myVertexHere3 = new Vertex3D(stringRadii*Math.sin(myOsc+4*Math.PI/3)+sphere.x, stringRadii*Math.cos(myOsc+4*Math.PI/3)+sphere.y, sphere.z);
my3DLine3 = new Line3D(lines3, lineMaterial3, lineSize, prevVertex3d3, myVertexHere3 );
lines3.addLine(my3DLine3);
prevVertex3d3 = myVertexHere3;

camera.copyPosition(sphere);
camera.copyTransform(sphere);

sphere.x=lines.x;
sphere.y=lines.y;
sphere.z=lines.z;

camera.moveUp(cameraUp);
camera.moveBackward(myMoveBack);
camera.tilt(20);

renderer.renderScene(scene, camera, viewport);
if(wasHere<2){
lines.removeLine(lines.lines[0]);
lines2.removeLine(lines2.lines[0]);
lines3.removeLine(lines3.lines[0]);
wasHere++;
}

if (lines.lines.length > 1000)
{
lines.removeLine(lines.lines[0]);
lines2.removeLine(lines2.lines[0]);
lines3.removeLine(lines3.lines[0]);
}

}

}
}

About these ads

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: