Gödel, Escher, Bach
/**
* Copyright yuuganisakase ( http://wonderfl.net/user/yuuganisakase )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/b0QQ
*/
package
{
import fl.motion.easing.Cubic;
import flash.display.*
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.GlowFilter;
import flash.geom.ColorTransform;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import org.papervision3d.core.proto.DisplayObjectContainer3D;
import org.papervision3d.core.proto.LightObject3D;
import org.papervision3d.materials.BitmapFileMaterial;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
import org.papervision3d.materials.shaders.FlatShader;
import org.papervision3d.materials.shaders.ShadedMaterial;
import org.papervision3d.materials.special.CompositeMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.parsers.DAE;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.view.BasicView;
import flash.filters.BlurFilter;
import org.papervision3d.materials.MovieMaterial;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.objects.primitives.Plane;
import org.papervision3d.view.layer.util.ViewportLayerSortMode;
import com.flashdynamix.motion.Tweensy;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.events.FileLoadEvent;
import flash.system.Security;
[SWF(width=465, height=465, frameRate=12, backgroundColor=0x000000)]
public class ShadowLetters extends BasicView
{
private const ShadowBlend:String = BlendMode.MULTIPLY;
private const ShadowAlpha:Number = 0.8;
private const ShadowBlur:BlurFilter = new BlurFilter(4, 4, 2);
public var shadowCaster1:ShadowCaster = new ShadowCaster("shadow", 0, ShadowBlend, ShadowAlpha, [ShadowBlur]);
public var shadowCaster2:ShadowCaster = new ShadowCaster("shadow2", 0, ShadowBlend, ShadowAlpha, [ShadowBlur]);
public var shadowCaster3:ShadowCaster = new ShadowCaster("shadow3", 0, ShadowBlend, ShadowAlpha, [ShadowBlur]);
private var casterArray:Array = [shadowCaster1, shadowCaster2, shadowCaster3];
private var movieMaterial:MovieMaterial;
private var plane1:Plane;
private var plane2:Plane;
private var plane3:Plane;
private var cameraTarget:DisplayObject3D;
private var light1:PointLight3D;
private var sun:Sphere = new Sphere(new ColorMaterial(0xccbbaa,0.6),16, 4, 4);
private var clickCount:int = 2;
private var text1:DAE = new DAE();// = new DAE("untitled.dae");
private var loader:Loader;
private var loader2:Loader
private var shadowTarget:DisplayObject3D;
private var mouseOn:Boolean = true;
public function ShadowLetters(viewportWidth:Number = 465, viewportHeight:Number = 465, scaleToStage:Boolean = true, interactive:Boolean = false, cameraType:String = "Target")
{
Wonderfl.capture_delay( 9);
super(viewportWidth, viewportHeight, scaleToStage, interactive, cameraType);
addEventListener(Event.ADDED_TO_STAGE, onInit);
}
private function onInit(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, onInit);
viewport.containerSprite.sortMode = ViewportLayerSortMode.INDEX_SORT;
viewport.containerSprite.filters = [new BlurFilter(2, 2, 1)];
camera.x = -1042;
camera.y = 1200;
camera.z = -762;
cameraTarget = new DisplayObject3D();
cameraTarget.x = 300;
cameraTarget.y = 620;
cameraTarget.z = 300;
for each( var c:ShadowCaster in casterArray) {
c.setType(ShadowCaster.DIRECTIONAL);
}
Security.loadPolicyFile("http://lucasclaus.sakura.ne.jp/crossdomain.xml");
var context:LoaderContext = new LoaderContext(true);
loader = new Loader();
loader.load(new URLRequest("http://lucasclaus.sakura.ne.jp/swf/shadowLetters/back.png"),context);
//loader.load(new URLRequest("back.png"),context);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onBackLoad);
loader2 = new Loader();
loader2.load(new URLRequest("http://lucasclaus.sakura.ne.jp/swf/shadowLetters/back3.png"),context);
loader2.contentLoaderInfo.addEventListener(Event.COMPLETE, onTexLoad);
light1 = new PointLight3D(true);
camera.target = cameraTarget;
}
private function onTexLoad(e:Event):void
{
var bd:BitmapData = new BitmapData(1024, 1024);
bd.draw(loader2,null, new ColorTransform());
var sh:ShadedMaterial = new ShadedMaterial(new BitmapMaterial(bd), new FlatShader(light1, 0xccbbaa, 0x221100),0);
var mats:MaterialsList = new MaterialsList();
mats.addMaterial(sh, "back3_png");
//mats.addMaterial(shadow,"mat22");
text1.load("http://lucasclaus.sakura.ne.jp/swf/shadowLetters/gebTest1.dae",mats);
text1.addEventListener(FileLoadEvent.LOAD_COMPLETE, onLoad);
}
private function onBackLoad(e:Event):void
{
var bp:BitmapData = new BitmapData(300, 300);
bp.draw(loader,null, new ColorTransform(1,1,1,1,-90,-110,-130));
var sp1:Sprite = new Sprite();
sp1.graphics.beginBitmapFill(bp);
sp1.graphics.drawRect(0, 0, 300, 300);
var sp2:Sprite = new Sprite();
sp2.graphics.beginBitmapFill(bp);
sp2.graphics.drawRect(0, 0, 300, 300);
var sp3:Sprite = new Sprite();
sp3.graphics.beginBitmapFill(bp);
sp3.graphics.drawRect(0, 0, 300, 300);
var mm:MovieMaterial = new MovieMaterial(sp1 , false, true, true);
var mm2:MovieMaterial = new MovieMaterial(sp2,false, true, true);
var mm3:MovieMaterial = new MovieMaterial(sp3 ,false, true, true);
var pSize:int = 2000;
plane1 = new Plane(mm, pSize, pSize, 10, 10);
plane2 = new Plane(mm2, pSize, pSize, 1, 1);
plane3 = new Plane(mm3, pSize, pSize, 1, 1);
scene.addChild(plane1);
scene.addChild(plane2);
scene.addChild(plane3);
plane1.pitch(90);
plane2.yaw(90);
plane3.roll(90);
plane3.y = pSize/2;
plane3.z = pSize/2;
plane2.x = pSize/2;
plane2.y = pSize / 2;
viewport.getChildLayer(plane1).layerIndex = -100;
viewport.getChildLayer(plane2).layerIndex = -100;
viewport.getChildLayer(plane3).layerIndex = -100;
}
private function onLoad(e:FileLoadEvent):void
{
text1.removeEventListener(FileLoadEvent.LOAD_COMPLETE, onLoad);
stage.addEventListener(MouseEvent.CLICK, onClick);
stage.addEventListener(Event.ENTER_FRAME, tick);
stage.addEventListener( Event.MOUSE_LEAVE, function():void { mouseOn = false;} );
stage.addEventListener(MouseEvent.MOUSE_MOVE, function():void { mouseOn = true; } );
scene.addChild(text1);
text1.rotationX = -90;
text1.rotationY = 90;
text1.y = 700;
text1.z = 100;
text1.x = -100;
text1.scale = 263;
shadowTarget = text1;//.rootNode;
viewport.getChildLayer(text1).layerIndex = 11;
viewport.getChildLayer(sun).filters = [new GlowFilter(0xE8F471, 0.7, 16,16,8,2)];
viewport.getChildLayer(sun).blendMode = BlendMode.ADD;
scene.addChild(sun);
viewport.getChildLayer(sun).layerIndex = 200;
light1.x = 1400;
light1.y = 900;
light1.z = 1500;
scene.addChild(light1);
Tweensy.fromTo(light1, { x:1500, y:1000, z:1500 }, { x: -800, y:1120, z: -600 }, 4, null);
}
private function onClick(e:MouseEvent):void
{
var dur:Number = 2.5;
clickCount += 1;
if (clickCount % 3 == 0) {
Tweensy.to(light1, { x:-188, y:990, z:-700 }, dur);
}else if(clickCount % 3 == 1) {
Tweensy.to(light1, { x:-700, y:960, z:-100 }, dur);
}else {
Tweensy.to(light1, { x:-205, y:1470, z:-105 }, dur);
}
}
public function tick(e:Event):void
{
singleRender();
var cull:Boolean = true;
shadowCaster1.castModel(shadowTarget, light1, plane1, true,cull);
shadowCaster2.castModel(shadowTarget, light1, plane2, true,cull);
shadowCaster3.castModel(shadowTarget, light1, plane3, true,cull);
sun.copyPosition(light1);
if(mouseOn) mouseMove();
}
public function mouseMove():void
{
var mouseMargin:int = 50;
if (mouseX < mouseMargin && camera.position.x > -1200) {
camera.moveLeft(40);
}else if (mouseX > 465 - mouseMargin && camera.position.x < -500) {
camera.moveRight(40);
}
}
}
}
//
// ShadowCaster class
// http://blog.zupko.info/?p=146
//
import flash.display.Sprite;
import flash.filters.BlurFilter;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.Dictionary;
import org.papervision3d.core.geom.TriangleMesh3D;
import org.papervision3d.core.geom.renderables.Triangle3D;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.core.math.BoundingSphere;
import org.papervision3d.core.math.Matrix3D;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.core.math.Plane3D;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.MovieMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Plane;
class ShadowCaster
{
private var vertexRefs:Dictionary;
private var numberRefs:Dictionary;
private var lightRay:Number3D = new Number3D()
private var p3d:Plane3D = new Plane3D();
public var color:uint = 0;
public var alpha:Number = 0;
public var blend:String = "";
public var filters:Array;
public var uid:String;
private var _type:String = "point";
private var dir:Number3D;
private var planeBounds:Dictionary;
private var targetBounds:Dictionary;
private var models:Dictionary;
public static var DIRECTIONAL:String = "dir";
public static var SPOTLIGHT:String = "spot";
public function ShadowCaster(uid:String, color:uint = 0, blend:String = "multiply", alpha:Number = 1, filters:Array=null)
{
this.uid = uid;
this.color = color;
this.alpha = alpha;
this.blend = blend;
this.filters = filters ? filters : [new BlurFilter()];
numberRefs = new Dictionary(true);
targetBounds = new Dictionary(true);
planeBounds = new Dictionary(true);
models = new Dictionary(true);
}
public function castModel(model:DisplayObject3D, light:PointLight3D, plane:Plane, faces:Boolean = true, cull:Boolean = false):void{
var ar:Array;
if(models[model])
{
ar = models[model];
}else{
ar = new Array();
getChildMesh(model, ar);
models[model] = ar;
}
var reset:Boolean = true;
for each(var t:TriangleMesh3D in ar) {
if(faces)
castFaces(light, t, plane, cull, reset);
else
castBoundingSphere(light, t, plane, 0.75, reset);
reset = false;
}
}
private function getChildMesh(do3d:DisplayObject3D, ar:Array):void
{
if(do3d)
{
if(do3d is TriangleMesh3D)
{
ar.push(do3d);
}
for each(var d:DisplayObject3D in do3d.children)
{
getChildMesh(d, ar);
}
}
}
public function setType(type:String="point"):void{
_type = type;
}
public function getType():String{
return _type;
}
public function castBoundingSphere(light:PointLight3D, target:TriangleMesh3D, plane:Plane, scaleRadius:Number=0.8, clear:Boolean = true):void{
var planeVertices:Array = plane.geometry.vertices;
//convert to target space?
var world:Matrix3D = plane.world;
var inv:Matrix3D = Matrix3D.inverse(plane.transform);
var lp:Number3D = new Number3D(light.x, light.y, light.z);
Matrix3D.multiplyVector(inv, lp);
p3d.setNormalAndPoint(plane.geometry.faces[0].faceNormal, new Number3D());
var b:BoundingSphere = target.geometry.boundingSphere;
var bounds:Object = planeBounds[plane];
if(!bounds){
bounds = plane.boundingBox();
planeBounds[plane] = bounds;
}
var tbounds:Object = targetBounds[target];
if(!tbounds){
tbounds = target.boundingBox();
targetBounds[target] = tbounds;
}
var planeMovie:Sprite = Sprite(MovieMaterial(plane.material).movie);
var movieSize:Point = new Point(planeMovie.width, planeMovie.height);
var castClip:Sprite = getCastClip(plane);
castClip.blendMode = this.blend;
castClip.filters = this.filters;
castClip.alpha = this.alpha;
if(clear)
castClip.graphics.clear();
vertexRefs = new Dictionary(true);
var tlp:Number3D = new Number3D(light.x, light.y, light.z);
Matrix3D.multiplyVector(Matrix3D.inverse(target.world), tlp);
var center:Number3D = new Number3D(tbounds.min.x+tbounds.size.x*0.5, tbounds.min.y+tbounds.size.y*0.5, tbounds.min.z+tbounds.size.z*0.5);
var dif:Number3D = Number3D.sub(lp, center);
dif.normalize();
var other:Number3D = new Number3D();
other.x = -dif.y;
other.y = dif.x;
other.z = 0;
other.normalize();
var cross:Number3D = Number3D.cross(new Number3D(plane.transform.n12, plane.transform.n22, plane.transform.n32), p3d.normal);
cross.normalize();
//cross = new Number3D(-dif.y, dif.x, 0);
//cross.normalize();
cross.multiplyEq(b.radius*scaleRadius);
if(_type == DIRECTIONAL){
var oPos:Number3D = new Number3D(target.x, target.y, target.z);
Matrix3D.multiplyVector(target.world, oPos);
Matrix3D.multiplyVector(inv, oPos);
dir = new Number3D(oPos.x-lp.x, oPos.y-lp.y, oPos.z-lp.z);
}
//numberRefs = new Dictionary(true);
var pos:Number3D;
var c2d:Point;
var r2d:Point;
//_type = SPOTLIGHT;
pos = projectVertex(new Vertex3D(center.x, center.y, center.z), lp, inv, target.world);
c2d = get2dPoint(pos, bounds.min, bounds.size, movieSize);
pos = projectVertex(new Vertex3D(center.x+cross.x, center.y+cross.y, center.z+cross.z), lp, inv, target.world);
r2d = get2dPoint(pos, bounds.min, bounds.size, movieSize);
var dx:Number = r2d.x-c2d.x;
var dy:Number = r2d.y-c2d.y;
var rad:Number = Math.sqrt(dx*dx+dy*dy);
castClip.graphics.beginFill(color);
castClip.graphics.moveTo(c2d.x, c2d.y);
castClip.graphics.drawCircle(c2d.x, c2d.y, rad);
castClip.graphics.endFill();
}
public function getCastClip(plane:Plane):Sprite{
var planeMovie:Sprite = Sprite(MovieMaterial(plane.material).movie);
var movieSize:Point = new Point(planeMovie.width, planeMovie.height);
var castClip:Sprite;// = new Sprite();
if(planeMovie.getChildByName("castClip"+uid))
return Sprite(planeMovie.getChildByName("castClip"+uid));
else{
castClip = new Sprite();
castClip.name = "castClip"+uid;
castClip.scrollRect = new Rectangle(0, 0, movieSize.x, movieSize.y);
//castClip.alpha = 0.4;
planeMovie.addChild(castClip);
return castClip;
}
}
public function castFaces(light:PointLight3D, target:TriangleMesh3D, plane:Plane, cull:Boolean=false, clear:Boolean = true):void{
var planeVertices:Array = plane.geometry.vertices;
//convert to target space?
var world:Matrix3D = plane.world;
var inv:Matrix3D = Matrix3D.inverse(plane.transform);
var lp:Number3D = new Number3D(light.x, light.y, light.z);
Matrix3D.multiplyVector(inv, lp);
var tlp:Number3D;
if(cull){
tlp = new Number3D(light.x, light.y, light.z);
Matrix3D.multiplyVector(Matrix3D.inverse(target.world), tlp);
}
//Matrix3D.multiplyVector(Matrix3D.inverse(target.transform), tlp);
//p3d.setThreePoints(planeVertices[0].getPosition(), planeVertices[1].getPosition(), planeVertices[2].getPosition());
p3d.setNormalAndPoint(plane.geometry.faces[0].faceNormal, new Number3D());
if(_type == DIRECTIONAL){
var oPos:Number3D = new Number3D(target.x, target.y, target.z);
Matrix3D.multiplyVector(target.world, oPos);
Matrix3D.multiplyVector(inv, oPos);
dir = new Number3D(oPos.x-lp.x, oPos.y-lp.y, oPos.z-lp.z);
}
var bounds:Object = planeBounds[plane];
if(!bounds){
bounds = plane.boundingBox();
planeBounds[plane] = bounds;
}
var castClip:Sprite = getCastClip(plane);
castClip.blendMode = this.blend;
castClip.filters = this.filters;
castClip.alpha = this.alpha;
var planeMovie:Sprite = Sprite(MovieMaterial(plane.material).movie);
var movieSize:Point = new Point(planeMovie.width, planeMovie.height);
if(clear)
castClip.graphics.clear();
vertexRefs = new Dictionary(true);
//numberRefs = new Dictionary(true);
var pos:Number3D;
var p2d:Point;
var s2d:Point;
var hitVert:Number3D = new Number3D();
for each(var t:Triangle3D in target.geometry.faces){
if( cull){
hitVert.x = t.v0.x;
hitVert.y = t.v0.y;
hitVert.z = t.v0.z;
if(Number3D.dot(t.faceNormal, Number3D.sub(tlp, hitVert)) <= 0)
continue;
}
castClip.graphics.beginFill(color);
pos = projectVertex(t.v0, lp, inv, target.world);
s2d = get2dPoint(pos, bounds.min, bounds.size, movieSize);
castClip.graphics.moveTo(s2d.x, s2d.y);
pos = projectVertex(t.v1, lp, inv, target.world);
p2d = get2dPoint(pos, bounds.min, bounds.size, movieSize);
castClip.graphics.lineTo(p2d.x, p2d.y);
pos = projectVertex(t.v2, lp, inv, target.world);
p2d = get2dPoint(pos, bounds.min, bounds.size, movieSize);
castClip.graphics.lineTo(p2d.x, p2d.y);
castClip.graphics.lineTo(s2d.x, s2d.y);
castClip.graphics.endFill();
}
}
public function invalidate():void{
invalidateModels();
invalidatePlanes();
}
public function invalidatePlanes():void{
planeBounds = new Dictionary(true);
}
public function invalidateTargets():void{
numberRefs = new Dictionary(true);
targetBounds = new Dictionary(true);
}
public function invalidateModels():void{
models = new Dictionary(true);
invalidateTargets();
}
private function get2dPoint(pos3D:Number3D, min3D:Number3D, size3D:Number3D, movieSize:Point):Point{
return new Point((pos3D.x-min3D.x)/size3D.x*movieSize.x, ((-pos3D.y-min3D.y)/size3D.y*movieSize.y));
}
private function projectVertex(v:Vertex3D, light:Number3D, invMat:Matrix3D, world:Matrix3D):Number3D{
var pos:Number3D = vertexRefs[v];
if(pos)
return pos;
var n:Number3D = numberRefs[v];
if(!n){
n = new Number3D(v.x, v.y, v.z);
Matrix3D.multiplyVector(world, n);
Matrix3D.multiplyVector(invMat, n);
numberRefs[v] = n;
}
if(_type == SPOTLIGHT){
lightRay.x = light.x;
lightRay.y = light.y;
lightRay.z = light.z;
}else{
lightRay.x = n.x-dir.x;
lightRay.y = n.y-dir.y;
lightRay.z = n.z-dir.z;
}
pos = p3d.getIntersectionLineNumbers(lightRay, n);
vertexRefs[v] = pos;
return pos;
}
}