今回はMolehill API対応3Dエンジンのひとつ"Alternaiva3D 8.5.0"をさわってみた。
今までPapervision3Dを使っていたけど、今回のMolehill対応の波には乗り遅れたそうで今後のMolehill対応は望めない...らしい。
今まで他のAS3の3Dエンジンはおろか3Dエンジン自体、PV3Dの他にはさわったことがないのでちょっと不安。
Alternativa3Dからダウンロード
ロシアの人の開発らしい。
ロシア語なんて基本文字すらよめん。
ダウンロードしたファイルの中には本体とexample、ASdocが入ってた。
ASdocはありがたい。
早速asdoc_enを見てみる。クラスあんまし多くないのね。
あー本体がswcだ。
swcって引数と戻り値、軽い説明は読めるけどコードの中身見れないからなあ。
とりあえずexampleのhelloalternativa3dをやってみよう
package helloalternativa3d { import alternativa.engine3d.core.Camera3D; import alternativa.engine3d.core.Object3D; import alternativa.engine3d.core.Resource; import alternativa.engine3d.core.View; import alternativa.engine3d.materials.FillMaterial; import alternativa.engine3d.primitives.Box; import flash.display.Sprite; import flash.display.Stage3D; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; /** * Alternativa3D "Hello world!" application. * Создание простейшего трёхмерного приложения. */ public class HelloAlternativa3D extends Sprite { private var rootContainer:Object3D = new Object3D(); private var camera:Camera3D; private var stage3D:Stage3D; private var box:Box; public function HelloAlternativa3D() { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; // Camera and view // Создание камеры и вьюпорта camera = new Camera3D(0.1, 10000); camera.view = new View(stage.stageWidth, stage.stageHeight); addChild(camera.view); addChild(camera.diagram); // Initial position // Установка положения камеры camera.rotationX = -120*Math.PI/180; camera.y = -800; camera.z = 400; rootContainer.addChild(camera); // Primitive box // Создание примитива box = new Box(500, 500, 500, 5, 5, 5); var material:FillMaterial = new FillMaterial(0xFF7700); box.setMaterialToAllSurfaces(material); rootContainer.addChild(box); stage3D = stage.stage3Ds[0]; stage3D.addEventListener(Event.CONTEXT3D_CREATE, onContextCreate); stage3D.requestContext3D(); } private function onContextCreate(e:Event):void { for each (var resource:Resource in rootContainer.getResources(true)) { resource.upload(stage3D.context3D); } // Listeners // Подписка на события stage.addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function onEnterFrame(e:Event):void { // Width and height of view // Установка ширины и высоты вьюпорта camera.view.width = stage.stageWidth; camera.view.height = stage.stageHeight; // Rotation // Вращение примитива box.rotationZ -= 0.01; // Render // Отрисовка camera.render(stage3D); } } }
まずはコンストラクタから。
// Camera and view
camera = new Camera3D(0.1, 10000);
camera.view = new View(stage.stageWidth, stage.stageHeight);
addChild(camera.view);
addChild(camera.diagram);
まずはカメラとビューの設定ぽいな
カメラをnewする。
public function Camera3D(nearClipping:Number, farClipping:Number)
ニアクリッピングとファークリッピングの距離を指定。
これらはプロパティを持ってるので後から代入で変更できそう。
で、cameraのviewプロパティにViewをnewして設定。
public function View(width:int, height:int, renderToBitmap:Boolean = false, backgroundColor:uint = 0, backgroundAlpha:Number = 0, antiAlias:int = 0, ratio:Number = 1)
PV3Dで言うViewport3Dかな。サイズともろもろ設定を指定。
addChild(camera.view);
で2D表示リストに追加させると。Spriteの継承クラスだし。
addChild(camera.diagram);
デバッグ用のFPSとか表示させるプロファイラを2D表示リストさせるみたい。
これってカメラが持ってるインスタンスなのね。
// Initial position
camera.rotationX = -120*Math.PI/180;
camera.y = -800;
camera.z = 400;
rootContainer.addChild(camera);
前半はカメラの初期設定ね。後で触れると思うけど座標系がPV3Dと違うので注意。
rotationXとかがラジアン指定なとこも違うかな。
そして
private var rootContainer:Object3D = new Object3D();
で作ったrootContainerにカメラをaddChild。
rootContainerはおそらくPV3Dで言うsceneだね。
Object3Dクラスだけど
Object3D class is a base class for all 3D objects. Object3D can contains children
Altanativaにおける3Dオブジェクトの基本クラスだね。
子を持てるってことは
flashのDisplayObjectContainer→DisplayObject
PV3DのDisplayObject3D→DisplayObjectContainer3D
とは違ってコンテナの機能も最初から含んでるのか。
抽象クラスのDisplayObjectとは違って実際にインスタンス化もできると。
Camera3DもObject3Dを継承してる。
そしてPV3DのScene3Dのように3D表示リストの最上位が特別にクラスになっているわけではないのね。
ていうかいまさらだけどPV3DのDisplayObject3D→DisplayObjectContainer3Dもおかしい気がする...
ファイルがフォルダを継承してるってことだよね。
// Primitive box
box = new Box(500, 500, 500, 5, 5, 5);
var material:FillMaterial = new FillMaterial(0xFF7700);
box.setMaterialToAllSurfaces(material);
rootContainer.addChild(box);
いよいよプリミティブの作成。 直方体がBoxね(PV3Dで言うCube)。
public function Box(width:Number = 100, length:Number = 100, height:Number = 100, widthSegments:uint = 1, lengthSegments:uint = 1, heightSegments:uint = 1, reverse:Boolean = false, material:Material = null)
でべた塗りのテクスチャがFillMaterial(PV3Dで言うColorMaterial)。
public function FillMaterial(color:uint = 0xFFFFFF, alpha:Number = 1)
テクスチャの設定の仕方はコンストラクタに入れるか
Mesh.setMaterialToAllSurfaces()だね。
このへんはPV3Dと同じだからすいすい読めた。
ていうかASdocみたらalternativa.engine3d.primitivesパッケージに球と直方体しかないんだけどどういこと...?
あとは全部頂点から作れってこと?
それともまだ全然開発途中なの?
せめて平面は欲しかった。見落としてるだけかもしれんが。
stage3D = stage.stage3Ds[0];
stage3D.addEventListener(Event.CONTEXT3D_CREATE, onContextCreate);
stage3D.requestContext3D();
stage3Dをstage.stage3Dsから取得。
stage.stage3Ds:Vector. [read-only]
なんでVectorで与えられてんだろ。何枚もあんのかな。
で、Event.CONTEXT3D_CREATEイベントを登録して
Stage3D.requestContext3D();
Request creation of a new Context3D object bound to this renderstage. This function requests creation of a new Context3D object. An event listen for the CONTEXT3D_CREATE event must be registered before requesting a new Context3D. If there is no listener an exception is thrown.
ここがよくわからん。
ていうかContext3Dが具体的になんなのかわからん。なに?
とりあえずリクエストする前にイベント登録しとかないとエラー投げるよと。
private function onContextCreate(e:Event):void {
for each (var resource:Resource in rootContainer.getResources(true)) {
resource.upload(stage3D.context3D);
}
// Listeners
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
ますますわからん。Resource?
Base class for GPU data. GPU data can be divided in 2 groups: geometry data and texture data. For uploading geometry data in GPU are used VertexBufferResource and IndexBufferResource. BitmapTextureResource and CompressedTextureResource allow to upload textures, FileTextureResource must be used with TexturesLoader, which loads textures from files and automaticaly uploads in GPU.
ResourceってGPUに送るデータのフォーマットなのかな。
Stage3DにrequestContext3D()してCONTEXT3D_CREATEされたらsceneのリソースを全部Stage3DのContext3Dにアップロードする。
でENTER_FRAMEイベントを登録して
private function onEnterFrame(e:Event):void
{
// Width and height of view
camera.view.width = stage.stageWidth;
camera.view.height = stage.stageHeight;
// Rotation box.rotationZ -= 0.01;
// Render
camera.render(stage3D);
}
camera.render(stage3D);が毎フレームするレンダリングだとして
camera.view.width = stage.stageWidth;
camera.view.height = stage.stageHeight;
を毎フレームやる意味が分からん。
一通り読んだがわからんこと結構あったな
Context3Dがなんなのかが一番わからん。
GPUの場所かなんかなのかな。
GPUに領域確保してーって言って(stage3D.requestContext3D())
GPUがここ使っていいよーって非同期的に返してきたら(Event.CONTEXT3D_CREATE)
作られたContext3DにGPU用データ(Resource)を全部転送(resource.upload(stage3D.context3D))
こんな流れと勝手に推理。
でもそれならuploadも非同期のはずかな。
やっぱりクラスの中身が見たい
誰か教えて!
Author:9ballsyn
ActionScriptについて
最近はMolehill