Author: Makc
Date: July 22nd 2008
version: 3.0.2
We had a lot of demand for code to render 3D stuff in its “actual” size, hence this tutorial. And we thought our camera page would provide some help in this… apparently it did not.
You should at least complete our simplest tutorial.
In Sandy, camera has fov property, which stands for vertical field of view angle. The realtionship between vertical field of view angle and viewport height is illustrated below:
From here, it is fairly easy to calculate focal length:
var fl:Numer = (viewport.height / 2) / Math.tan (camera.fov / 2 * (Math.PI / 180));
Everything behind the plane with wz = fl (a.k.a. focal plane) will appear smaller than it “actually” is, and everything in front of it will appear larger, in pixels.
Given the above, how does one maintain 1:1 scale for some plane when the screen is resized? The trick is to catch Event.RESIZE and reset camera.fov to maintain necessary focal length. Here goes example code and FLA to do this:
import flash.display.*; import flash.events.*; import sandy.core.Scene3D; import sandy.core.scenegraph.*; import sandy.primitive.*; import sandy.materials.*; // make texture, assuming class Texture extends BitmapData var tex:BitmapData = new Texture (0, 0); // set stage to no-scale mode stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; // some standard Sandy stuff var scene:Scene3D = new Scene3D ("myScene", this, new Camera3D (100, 100), new Group ("myRoot")); var plane:Plane3D = new Plane3D ("myPlane", tex.height, tex.width); plane.appearance = new Appearance (new BitmapMaterial (tex)); // add plane to scene and render it to fill its view matrix scene.root.addChild (plane); scene.render (); // finally, make resize handler function onResize (e:Event):void { // get new stage dimensions var w:Number = stage.stageWidth; var h:Number = stage.stageHeight; // update the viewport scene.camera.viewport.width = w; scene.camera.viewport.height = h; // get plane distance to camera var d:Number = plane.getPosition ("camera").getNorm (); // focus camera on wz = d for 1:1 scale scene.camera.fov = 2 * Math.atan2 (h / 2, d) * (180 / Math.PI); // re-render the scene scene.render(); } stage.addEventListener (Event.RESIZE, onResize); onResize (null);
Hope it helps.