(2010/11/10 記事を修正しました。)
Flashの3D表現ライブラリの1つである、Alternativa3Dに手を出してみました。
使ってるバージョンは7.5です。
今回は、前回述べた「viewをリサイズすると、全体の大きさも変わる。」っていうのの対処法。
viewのサイズを変更しても大きさを変更したくない場合は、時前でfov計算をしないといけないらしいです。
narutohyperさんがWonderflにアップしたプログラムのなかに、その計算をしているものがあったので、参考にさせてもらいました。
以下のプログラムを参考にしました。
前回のと比べると、今回のサンプルはviewをリサイズしても拡大/縮小していません。
以下ソースです。
package
{
import alternativa.engine3d.core.Camera3D;
import alternativa.engine3d.core.Object3DContainer;
import alternativa.engine3d.core.View;
import alternativa.engine3d.materials.FillMaterial;
import alternativa.engine3d.materials.TextureMaterial;
import alternativa.engine3d.primitives.Box;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
[SWF(backgroundColor=0x000000)]
public class Main extends Sprite
{
[Embed(source='image.jpg')]
private var img:Class;
private static const RADIAN:Number = Math.PI/180;
private static const FOCUS:Number = 800;
private var rootContainer:Object3DContainer;
private var camera:Camera3D;
private var view:View;
private var box1:Box;
private var box2:Box;
public function Main()
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.HIGH;
stage.frameRate = 40;
// ベースとなるコンテナ。
rootContainer = new Object3DContainer();
// カメラの初期化 (PV3Dでいうフリーカメラみたいなの)。
camera = rootContainer.addChild(new Camera3D) as Camera3D;
camera.z = -800;
camera.x = camera.y = 0;
// ビューポート (View is DisplayObject)
view = new View(stage.stageWidth, stage.stageHeight);
view.logoAlign = StageAlign.TOP_LEFT;
view.logoHorizontalMargin = 80;
camera.view = addChild(view) as View;
// デバッグ情報を表示する場合は記述
camera.diagramAlign = StageAlign.TOP_LEFT;
addChild(camera.diagram);
// 箱1を作成
box1 = new Box(130, 130, 130);
box1.x = 200;
box1.setMaterialToAllFaces(new FillMaterial(0x770000, 1, 7, 0x220000));
rootContainer.addChild(box1);
// 箱2を作成
var texture:BitmapData = (new img as Bitmap).bitmapData;
box2 = new Box(130, 130, 130);
box2.x = -200;
box2.setMaterialToAllFaces(new TextureMaterial(texture, false, true));
rootContainer.addChild(box2);
addEventListener(Event.ENTER_FRAME, onFrame);
stage.addEventListener(Event.RESIZE, onResize);
}
// viewのリサイズに合わせてカメラを調整
// 参考:http://wonderfl.net/c/i3op/ (thanks to @narutohyper)
private function onResize(e:Event):void
{
// Viewportの幅を調整
view.width = stage.stageWidth;
view.height = stage.stageHeight;
//fovの計算
camera.fov = 2 * Math.atan2(Math.sqrt(view.width * view.width +view.height * view.height) / 2, 800);
}
private function onFrame(e:Event):void
{
// Box1をローテーション
box1.rotationX += RADIAN;
box1.rotationY += RADIAN;
// Box2をローテーション
box2.rotationX -= RADIAN;
box2.rotationY -= RADIAN;
// レンダリング
camera.render();
}
}
}
