Created
April 16, 2010 04:21
-
-
Save lamberta/368000 to your computer and use it in GitHub Desktop.
See-Invisible pv3d demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* To see the demo and a writeup, visit: | |
* http://lamberta.posterous.com/3d-flash-demo-see-through | |
* | |
* This software is release under the MIT License. | |
* Copyright (c) Billy Lamberta, 2008 | |
* www.lamberta.org | |
* | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a copy | |
* of this software and associated documentation files (the "Software"), to deal | |
* in the Software without restriction, including without limitation the rights | |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
* copies of the Software, and to permit persons to whom the Software is | |
* furnished to do so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in | |
* all copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
* | |
**/ | |
package { | |
import flash.display.Bitmap; | |
import flash.display.Sprite; | |
import flash.display.StageAlign; | |
import flash.display.StageQuality; | |
import flash.display.StageScaleMode; | |
import flash.events.Event; | |
import flash.text.TextField; | |
import flash.text.TextFieldAutoSize; | |
import org.papervision3d.cameras.Camera3D; | |
import org.papervision3d.events.FileLoadEvent; | |
import org.papervision3d.materials.BitmapMaterial; | |
import org.papervision3d.materials.utils.MaterialsList; | |
import org.papervision3d.objects.DisplayObject3D; | |
import org.papervision3d.objects.parsers.DAE; | |
import org.papervision3d.render.BasicRenderEngine; | |
import org.papervision3d.scenes.Scene3D; | |
import org.papervision3d.view.Viewport3D; | |
import org.papervision3d.view.layer.ViewportLayer; | |
import org.papervision3d.view.stats.StatsView; | |
[SWF(backgroundColor="0x000000")] | |
public class SeeInvisible extends Sprite { | |
//papervison vars | |
private var viewport:Viewport3D; | |
private var scene:Scene3D; | |
private var renderer:BasicRenderEngine; | |
private var camera:Camera3D; | |
/**Embed all the textures. You could reference this within the collada xml | |
* but because of all the rendering I prefer to do them separate. | |
*/ | |
[Embed(source="./assets/models/textures/seeInvis/words-512.jpg")] | |
public var wordsTexture:Class; | |
[Embed(source="./assets/models/textures/seeInvis/floor-1024.jpg")] | |
public var floorTexture:Class; | |
[Embed(source="./assets/models/textures/seeInvis/wallFront-512.jpg")] | |
public var wallFrontTexture:Class; | |
[Embed(source="./assets/models/textures/seeInvis/wallBack-512.jpg")] | |
public var wallBackTexture:Class; | |
[Embed(source="./assets/models/textures/seeInvis/wallLeft-512.jpg")] | |
public var wallLeftTexture:Class; | |
[Embed(source="./assets/models/textures/seeInvis/wallRight-512.jpg")] | |
public var wallRightTexture:Class; | |
private var model:DAE; | |
private var camTarget:DisplayObject3D; | |
//private var stats:StatsView; | |
private var loadingText:TextField; | |
private var angle:Number = 0; | |
public function SeeInvisible() { | |
//setup stage | |
stage.align = StageAlign.TOP_LEFT; | |
stage.scaleMode = StageScaleMode.NO_SCALE; | |
stage.quality = StageQuality.MEDIUM; | |
//setup stats | |
//stats = new StatsView(renderer); | |
//addChild(stats); | |
//display loading text | |
initLoadingText("Hello. Now loading 468kb. Thank you."); | |
//setup papervision | |
init3d(); | |
//setup materials and start loading the model | |
initModels(); | |
} | |
private function init3d():void { | |
viewport = new Viewport3D(stage.stageWidth, stage.stageHeight); | |
addChild(viewport); | |
renderer = new BasicRenderEngine(); | |
scene = new Scene3D(); | |
camera = new Camera3D(); | |
camTarget = new DisplayObject3D(); | |
addEventListener(Event.ENTER_FRAME, onEnterFrame); | |
//setup camera | |
//further back and zoomed in to avoid culling the bottom plane | |
camera.y -= 25; | |
camera.z = -400; | |
camera.zoom = 200; | |
} | |
private function initModels():void { | |
//setup materials list | |
var matList:MaterialsList = new MaterialsList(); | |
//textures to bitmaps | |
var wordsBitmap:Bitmap = new wordsTexture() as Bitmap; | |
var floorBitmap:Bitmap = new floorTexture() as Bitmap; | |
var wallFrontBitmap:Bitmap = new wallFrontTexture() as Bitmap; | |
var wallBackBitmap:Bitmap = new wallBackTexture() as Bitmap; | |
var wallRightBitmap:Bitmap = new wallLeftTexture() as Bitmap; | |
var wallLeftBitmap:Bitmap = new wallRightTexture() as Bitmap; | |
//in the dae file, locate the 'instance_material :: symbol' names, | |
//these are the shader names I created in the modeling app. | |
matList.addMaterial(new BitmapMaterial(wordsBitmap.bitmapData), "lambert7SG"); | |
matList.addMaterial(new BitmapMaterial(floorBitmap.bitmapData), "lambert8SG"); | |
matList.addMaterial(new BitmapMaterial(wallFrontBitmap.bitmapData), "lambert9SG"); | |
matList.addMaterial(new BitmapMaterial(wallBackBitmap.bitmapData), "lambert12SG"); | |
matList.addMaterial(new BitmapMaterial(wallRightBitmap.bitmapData), "lambert11SG"); | |
matList.addMaterial(new BitmapMaterial(wallLeftBitmap.bitmapData), "lambert10SG"); | |
//collada setup | |
model = new DAE(false); | |
model.load("assets/models/seeInvisible.dae"); | |
model.materials = matList; | |
scene.addChild(model); | |
model.addEventListener(FileLoadEvent.LOAD_COMPLETE, modelLoaded); | |
} | |
private function modelLoaded(event:FileLoadEvent) : void { | |
//remove loading text | |
stage.removeChild(loadingText); | |
//setup model | |
model.scale = 4; | |
model.z = 0; | |
model.y = -150; | |
model.rotationY = 45; | |
//keep camera on the model | |
//camera.target = model; | |
camTarget.x = model.x; | |
camTarget.y = model.y + 25; | |
camTarget.z = model.z; | |
camera.target = camTarget; | |
//add model to separate viewport layer to avoid z-sort conflicts | |
viewport.getChildLayer(model.getChildByName("floor", true)); | |
//adjusting alpha of this layer since I'm using a BitmapMaterial | |
var wordLayer:ViewportLayer = viewport.getChildLayer(model.getChildByName("words", true)); | |
wordLayer.alpha = 0.8; | |
} | |
private function onEnterFrame(event:Event):void { | |
//map mouse position to angle of rotation | |
angle -= map(mouseX, 0, stage.stageWidth, -0.15, 0.15); | |
//move camera one way or the other | |
camera.x = (model.x + Math.sin(angle) * 150); | |
camera.z = (model.z + Math.cos(angle) * 400); | |
//render scene | |
renderer.renderScene(scene, camera, viewport); | |
} | |
private function moveCamera():void { | |
camera.x = -(((this.mouseX - (stage.stageWidth / 2)) / stage.stageWidth) * 600); | |
camera.y = -(((this.mouseY - (stage.stageHeight / 2)) / stage.stageHeight) * 200); | |
} | |
private function initLoadingText(text:String, xpos:Number=10, ypos:Number=20):void { | |
/** | |
* Setup a little loading notification for the model. | |
* Will need to manually remove from the stage. | |
*/ | |
loadingText = new TextField(); | |
loadingText.textColor = 0xFFFFFF; | |
loadingText.autoSize= TextFieldAutoSize.LEFT; | |
loadingText.x = xpos; | |
loadingText.y = ypos; | |
loadingText.text = text; | |
stage.addChild(loadingText); | |
} | |
/** | |
* I got these math functions from Keith Peter's blog, quite helpful! | |
* http://www.bit-101.com/blog/?p=1242 | |
*/ | |
public static function normalize(value:Number,minimum:Number,maximum:Number):Number { | |
return(value - minimum) / (maximum - minimum); | |
} | |
public static function lerp(normValue:Number,minimum:Number,maximum:Number):Number { | |
return minimum + (maximum - minimum) * normValue; | |
} | |
public static function map(value:Number,min1:Number,max1:Number,min2:Number,max2:Number):Number { | |
return lerp( normalize(value, min1, max1), min2, max2); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment