PV3D StereoScene + Rainbow + clockmaker's Ribon Road
Forked by forresto from clockmaker's "[PV3D] Ribon Road"
* for cross-eye Stereo 3D viewing. Cross your eyes and ride!
=====================================================
Papervison3Dを利用したリボン表現
*
* Tweenerを使って作成したベジェ曲線に
* Planeを位置と角度を調整して並べています。
* 強引なやり方なので、いい方法があったら教えてください!
*
* @author Yasu (clockmaker.jp)
======================================================
/**
* Copyright forresto ( http://wonderfl.net/user/forresto )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/zCbd
*/
/*
* Forked by forresto from clockmaker's "[PV3D] Ribon Road"
* for cross-eye Stereo 3D viewing. Cross your eyes and ride!
*/
/*=====================================================*//**
* Papervison3Dを利用したリボン表現
*
* Tweenerを使って作成したベジェ曲線に
* Planeを位置と角度を調整して並べています。
* 強引なやり方なので、いい方法があったら教えてください!
*
* @author Yasu (clockmaker.jp)
*//*======================================================*/
package
{
import caurina.transitions.Tweener;
import caurina.transitions.properties.CurveModifiers;
import flash.display.*;
import flash.events.*;
import org.papervision3d.cameras.*;
import org.papervision3d.core.geom.*;
import org.papervision3d.core.geom.renderables.*;
import org.papervision3d.core.proto.*;
import org.papervision3d.lights.*;
import org.papervision3d.materials.*;
import org.papervision3d.materials.shadematerials.*;
import org.papervision3d.materials.special.*;
import org.papervision3d.materials.utils.*;
import org.papervision3d.objects.*;
import org.papervision3d.objects.primitives.*;
import org.papervision3d.view.*;
[SWF(width="800", height="400", frameRate="60", backgroundColor="0xFFFFFF")]
public class RibbonRoad3DCross extends Sprite
{
private var stereoScene:StereoScene;
private var lineMaterial :LineMaterial;
private var _arrLines :Array = [];
private var _objArray :Array = [];
private var LINES_NUM :int = 1
private var MAX_RADIUS :int = 3000;
private var POINT_NUM :uint = 5
private var VERTICES_NUM :uint = 400
private var CAMERA_POSITION :uint = 3000;
private var color:Rainbow = new Rainbow(Math.round(Math.random()*360), .75, .75);
public function RibbonRoad3DCross()
{
super();
stereoScene = new StereoScene(800, 400, 2, 250, true, false);
addChild(stereoScene);
CurveModifiers.init();
init()
addEventListener(Event.ENTER_FRAME, render);
}
private function init():void
{
// 3d
for (var i:int = 0; i < LINES_NUM; i++)
{
_arrPlanes[i] = [];
}
// 2d
for (i = 0; i < LINES_NUM; i++)
{
var newPos:Object = getRandomPos()
var o:Object =
{
x : newPos.x,
prevX : newPos.x,
y : newPos.y,
prevY : newPos.y,
z : newPos.z,
prevZ : newPos.z
}
_objArray.push(o)
randomTween(getRandomData(o))
}
}
private function randomTween(o:Object):void
{
Tweener.addTween(o,
{
x : o.x1,
y : o.y1,
z : o.z1,
_bezier : o.bezier,
time : o.time,
transition : "linear",
onComplete : function():void
{
randomTween(getRandomData(o));
}
});
}
private function getRandomData(o:Object):Object
{
o.time = (POINT_NUM * 0.5) + (POINT_NUM * .75);
var newPos:Object = getRandomPos();
o.x1 = newPos.x;
o.y1 = newPos.y;
o.z1 = newPos.z;
o.bezier = [];
for (var i:int = 0; i < POINT_NUM; i++)
{
var newBezierPos:Object = getRandomPos();
o.bezier.push(
{
x : newBezierPos.x,
y : newBezierPos.y,
z : newBezierPos.z
});
}
return o;
}
private function getRandomPos():Object
{
var angleY:Number = Math.random() * 2 * Math.PI;
var angleXZ:Number = Math.random() * 2 * Math.PI;
return {
x : Math.cos(angleY) * Math.sin(angleXZ) * MAX_RADIUS,
y : Math.sin(angleY) * Math.sin(angleXZ) * MAX_RADIUS,
z : Math.cos(angleXZ) * MAX_RADIUS
};
}
private var _arrPlanes:Array = []
private function render(event:Event = null):void
{
for (var i:int = 0; i < LINES_NUM; i++)
{
var d1:DisplayObject3D = new DisplayObject3D()
d1.x = _objArray[i].x
d1.y = _objArray[i].y
d1.z = _objArray[i].z
var d2:DisplayObject3D = new DisplayObject3D()
d2.x = _objArray[i].prevX
d2.y = _objArray[i].prevY
d2.z = _objArray[i].prevZ
d1.lookAt(d2);
// Planes
var len:Number = Math.sqrt(
(_objArray[i].x - _objArray[i].prevX) * (_objArray[i].x - _objArray[i].prevX)
+ (_objArray[i].y - _objArray[i].prevY) * (_objArray[i].y - _objArray[i].prevY)
+ (_objArray[i].z - _objArray[i].prevZ) * (_objArray[i].z - _objArray[i].prevZ)
)
var mat:MaterialObject3D = new WireframeMaterial(color.getNext())
mat.doubleSided = true
var o:DisplayObject3D = stereoScene.scene.addChild(new Plane(mat, 100, 100))
o.copyTransform(d1.transform)
o.pitch(90)
_arrPlanes[i].push(o);
if (_arrPlanes[i].length > 10)
{
var tmp:DisplayObject3D = _arrPlanes[i][0]
var cameraTarget :DisplayObject3D = new DisplayObject3D();
cameraTarget.copyTransform( tmp );
cameraTarget.moveBackward(100);
cameraTarget.moveUp(100);
stereoScene.camera.copyTransform(cameraTarget)
stereoScene.camera.lookAt(_arrPlanes[i][10])
cameraTarget = null
}
if (_arrPlanes[i].length > VERTICES_NUM)
{
stereoScene.scene.removeChild(_arrPlanes[i].shift())
}
_objArray[i].prevX = _objArray[i].x;
_objArray[i].prevY = _objArray[i].y;
_objArray[i].prevZ = _objArray[i].z;
}
stereoScene.onRenderTick();
}
}
}
class Rainbow
{
private var _hue:Number;
private var _saturation:Number;
private var _brightness:Number;
public function Rainbow(hue:Number=0, saturation:Number=1, brightness:Number=1)
{
_hue = hue % 360;
_saturation = saturation;
_brightness = brightness;
}
public function getNext(hueshift:Number=1):uint
{
_hue = (_hue + hueshift) % 360;
return HSBtoRGB(_hue, _saturation, _brightness);
}
public static function HSBtoRGB(hue:Number, saturation:Number, brightness:Number):uint
{
// Conversion taken from Foley, van Dam, et al
var r:Number, g:Number, b:Number;
if (saturation == 0)
{
r = g = b = brightness;
}
else
{
var h:Number = (hue % 360) / 60;
var i:int = int(h);
var f:Number = h - i;
var p:Number = brightness * (1 - saturation);
var q:Number = brightness * (1 - (saturation * f));
var t:Number = brightness * (1 - (saturation * (1 - f)));
switch (i) {
case 0:
r = brightness;
g = t;
b = p;
break;
case 1:
r = q;
g = brightness;
b = p;
break;
case 2:
r = p;
g = brightness;
b = t;
break;
case 3:
r = p;
g = q;
b = brightness;
break;
case 4:
r = t;
g = p;
b = brightness;
break;
case 5:
r = brightness;
g = p;
b = q;
break;
}
}
r *= 255;
g *= 255;
b *= 255;
return (r << 16 | g << 8 | b);
}
}
/*
* These following two classes are adopted from:
* http://codejockeyscorner.blogspot.com/2009/04/papervision3d-anaglyph-scene.html
*
* It will be easy to make the anaglyph again once I find some red/blue glasses.
*/
//package com.codejockey.anaglyph {
//import flash.display.BlendMode;
import flash.display.Sprite;
//import flash.geom.ColorTransform;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.view.stats.StatsView;
class StereoScene extends Sprite
{
private var _width:Number;
private var _height:Number;
private var _debug:Boolean = false;
private var _crosseye:Boolean = true;
private var leftViewport:Viewport3D;
private var rightViewport:Viewport3D;
public var scene:Scene3D;
public var camera:StereoCamera;
private var renderer:BasicRenderEngine;
public const SPACING:int = 30;
public function StereoScene(width:Number=800, height:Number=600, zoom:Number=1, focus:Number=250, crosseye:Boolean=true, debug:Boolean=false) {
_width = width;
_height = height;
_crosseye = crosseye;
_debug = debug;
camera = new StereoCamera(zoom, focus);
init3D();
if (debug) {
this.addChild(new StatsView(renderer));
}
}
private function init3D():void {
leftViewport = new Viewport3D(_width/2 - SPACING*1.5, _height - SPACING*2);
//leftViewport.transform.colorTransform = new ColorTransform(1, 1, 1, 1, 0x00, 0xFF, 0xFF);
this.addChild(leftViewport);
rightViewport = new Viewport3D(_width/2 - SPACING*1.5, _height - SPACING*2);
//rightViewport.transform.colorTransform = new ColorTransform(1, 1, 1, 1, 0xFF, 0x00, 0x00);
//rightViewport.blendMode = BlendMode.MULTIPLY;
this.addChild(rightViewport);
leftViewport.y = SPACING;
rightViewport.y = SPACING;
if (_crosseye) {
// crosseye viewing (focus between eyes and screen)
rightViewport.x = _width/2 + SPACING/2;
leftViewport.x = SPACING;
} else {
// parallel viewing (focus beyond screen)
leftViewport.x = _width/2 + SPACING/2;
rightViewport.x = SPACING;
}
leftViewport.containerSprite.cacheAsBitmap = false;
rightViewport.containerSprite.cacheAsBitmap = false;
scene = new Scene3D();
camera.rotationX = 15;
renderer = new BasicRenderEngine();
}
public function onRenderTick(event:Event = null):void {
renderer.renderScene(scene, camera.leftCamera, leftViewport);
renderer.renderScene(scene, camera.rightCamera, rightViewport);
}
}
//}
//package com.codejockey.anaglyph {
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.objects.DisplayObject3D;
import flash.events.Event;
import org.papervision3d.core.math.Number3D;
class StereoCamera extends DisplayObject3D
{
public const EYE_DISTANCE:int = 24;
public var leftCamera:Camera3D;
public var rightCamera:Camera3D;
public function StereoCamera(zoom:Number=1, focus:Number=250)
{
super();
leftCamera = new Camera3D();
leftCamera.moveLeft(this.EYE_DISTANCE);
rightCamera = new Camera3D();
rightCamera.moveRight(this.EYE_DISTANCE);
leftCamera.zoom = rightCamera.zoom = zoom;
leftCamera.focus = rightCamera.focus = focus;
}
public override function moveLeft(distance:Number):void {
leftCamera.moveLeft(distance);
rightCamera.moveLeft(distance);
super.moveLeft(distance);
}
public override function moveRight(distance:Number):void {
leftCamera.moveRight(distance);
rightCamera.moveRight(distance);
super.moveRight(distance);
}
public override function moveUp(distance:Number):void {
leftCamera.moveUp(distance);
rightCamera.moveUp(distance);
super.moveUp(distance);
}
public override function moveDown(distance:Number):void {
leftCamera.moveDown(distance);
rightCamera.moveDown(distance);
super.moveDown(distance);
}
public override function copyTransform(reference:*):void {
leftCamera.copyTransform(reference);
rightCamera.copyTransform(reference);
leftCamera.moveLeft(this.EYE_DISTANCE);
rightCamera.moveRight(this.EYE_DISTANCE);
super.copyTransform(reference);
}
public override function lookAt(targetObject:DisplayObject3D, upAxis:Number3D=null):void {
leftCamera.lookAt(targetObject, upAxis);
rightCamera.lookAt(targetObject, upAxis);
super.lookAt(targetObject, upAxis);
}
}
//}