Skip to content

Instantly share code, notes, and snippets.

@lamberta
Created April 16, 2010 04:21
Show Gist options
  • Save lamberta/368000 to your computer and use it in GitHub Desktop.
Save lamberta/368000 to your computer and use it in GitHub Desktop.
See-Invisible pv3d demo
/**
* 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