★Flash 3D【 Papervision3D 2.0 】情報交換★

1Now_loading...774KB
垢版 |
2008/11/23(日) 19:00:56ID:C8LYNbVA
Flashの3DクラスライブラリのPapervision3D 2.0 GreateWhiteについて
情報交換しましょう。

いくつかの3Dライブラリがその覇を競い合っていますが、
あえてPapervision3Dを選択しているもの同士、語り合おうじゃ
ありませんか。

5044
垢版 |
2009/03/20(金) 20:37:00ID:lXny2v1Y
>>45 すまん、寝ぼけてた

オレも前からプリミティブの解放はよくわかってなかったんで調べ中。
まずは単純なplaneで
plane = new plane();
myScene.addChild(plane);
って感じで10個登録してから、これを解放してみる。

mySceneに含まれているプリミティブの個数を調べようと
myScene.numChildrenすると、DisplayObjectContainer3DのnumChildrenが呼ばれて
10って値が返ってくる。ここまではいいんだけど、myScene.childrenを使ってプリミティブの
名前を取り出そうとすると、nullが5個表示されてしまって、残りの5個が正しく名前が表示される。
でも、myScene.childrenList()を呼ぶとちゃーんと10個分の名前が表示される。
この2つの処理の違いは、DisplayObjectContainer3D.asをみると、
なんだけど、ちゃんと10個表示される方はこれ↓
name = name || child.name || String( child.id );
this._children[ child ] = name;
でもって、最初の5個がnullになっちゃう方は
this._childrenByName[ name ] = child;
っていう方法で格納してるみたいだ。
_childrenと_childrenByNameは共にDictionaryクラス。_childrenByNameが妙な事になってるから
これを返すmyScene.childrenを使ってremoveChildしようとしても5個はnullだから
解放されないわけだ、ダメじゃん。

続く、かもしれない。
2009/03/20(金) 21:24:05ID:lXny2v1Y
>>50続き

いきなり間違えた。
_childrenByNameに罪はなかった。_childrenByNameはDictionaryなのに配列と
同じようにアクセスしてた。

Scene3D、突き詰めるとDisplayObjectContainer3Dに含まれているプリミティブを
取得するには、DisplayObjectContainer3D.childrenを使うとDictionaryとして取得できる。
keyは
name = name || child.name || String( child.id );
として設定される。valueはプリミティブっぽい。
DisplayObjectContainer3Dに含まれるプリミティブを全消しするには
var childList:Object = myScene.children;
for (var key:String in childList) {
var value = childList[key];
myScene.removeChild(value);
}
ってな感じでいいのかなと。
removeChild()の引数はDisplayObject3D。
removeChildByName()ってのもあって、これはDisplayObject3Dの名前?(toString()したもの?)で
削除できるけど、処理内容をみると重そう。

これらの処理でScene3dからプリミティブは消えるけど、プリミティブ自体が
消えた訳じゃないはず。
SWFProfilerで観察してるとGCが効いて増減しつつも、徐々にメモリ使用量が増えてくし。

続く、かもしれない
2009/03/20(金) 21:57:30ID:lXny2v1Y
>>51続き

厳密には、DisplayObjectContainer3D.asでは、
protected var _childrenByName :Object;
private var _childrenTotal :int;
と宣言されていて、その後、
this._children = new Dictionary( false );
this._childrenByName = new Dictionary( true );
となっている。

あと、
Scene3D → SceneObject3D → DisplayObjectContainer3D
という関係で、Scene3Dに対するremoveChild()はDisplayObjectContainer3Dの
removeChild()ではなく、SceneObject3DのremoveChild()が呼ばれている。
そこでは、自身が管理しているDisplayObject3Dを削除した後に、親クラスの
DisplayObjectContainer3DのremoveChild()を呼んでいると。
なんで、DisplayObject3DでもDisplayObject3Dを管理しているのかはよくわからない。
GCの関係?

なかなかプリミティブ自体の削除までたどり着かないなぁ。
2009/03/20(金) 23:50:40ID:lXny2v1Y
Plane→TriangleMesh3D→Vertices3D→DisplayObject3D→DisplayObjectContainer3Dと順に辿っていく。

[Plane]
引数のmaterialは親クラスに渡してて、生成物は
Vertex3D()とTriangle3D()なんだけど、それは
this.geometryという、親クラスが持ってるらしい変数に突っ込んでるだけ。
一時変数だけのクラス。

[TriangleMesh3D]

親クラスのmaterial変数に入れてる。
あとprivateメンバ変数が3つあって、うち2つがArray、もう一はRenderTriangleクラス。
これらがイマイチ不明。デストラクタに該当するものがないっぽい。

[Vertices3D]
一時変数だけのクラス。ただ、boundingBoxとかを生成してreturnで返してるから、
それを受け取った側で解放してなきゃアウト。

[DisplayObject3D]
なかなか読み応えあるね。yawとかpitchとかlookAtはここで定義してあるんだ。
いろいろなprivate, publicな変数がある。
親クラスのDisplayObjectContainerにaddChildしている箇所はここなんだけど、
removeChildに該当する処理はないと。DisplayObject3DにDisplayObject3Dを
入れた場合は、当然、自分でremoveChildしなさいと。それから、
[TODO: If you add a child object that already has a different display object container as a parent,
the object is removed from the child list of the other display object container.]
って書いてある。
デストラクタに該当するものがないっぽいけど、new Plane()とかで生成された頂点や面の情報は
Plane自体を切り離せばDisplayObject3Dも分離されるみたいだから、あとはGCにがんばってもらえば
なんとかなるのかもしれない。(ホントか?)

マテリアルを貼り付けていないPlaneは、newしたらそれを参照しているトコを全て切り離せばGCまかせっぽい。
2009/03/21(土) 00:27:54ID:fKmdslcf
次は、planeにmaterialを貼り付けて、それを解放する場合。
(planeに貼ったMaterialObject3Dをどこで持ってるのかイマイチわからんのだけれど)

単純そうなColorMaterialから辿ってみる。
ColorMaterial→TriangleMaterial→MaterialObject3D

[ColorMaterial]
カラーコードすら保持していないけど、指定色で三角形を書いてるのはここ。
beginFill()、moveTo()、lineTo()、endFill()とか。

[TriangleMaterial]
こいつはつなぎなので無視。

[MaterialObject3D]
色コードとかBitmapはここで持ってる。
複数個のマテリアルを管理できるっぽい?
マテリアルの管理は、MaterialManagerクラスがしてるみたい。MaterialManagerクラスは
シングルトンみたいなもんでSWF全体で1つしかない。
MaterialObject3Dには、destroy()がある。といっても
objects = null;
bitmap = null;
MaterialManager.unRegisterMaterial(this);
これだけ。大雑把すぐる。
ColorMaterialクラス自身はdestroy()メソッドを持ってないけど、ちゃんと呼ばないとダメかな。

ついでにBitmapMaterialも読んでみたけど、こいつはdestroy()を持っていて、
一通りnull代入してるし、bitmapに対してはdispose()してるし、親のMaterialObject3Dの
destroy()も呼んでる。

BitmapFileMaterialクラスははBitmapMaterialクラスの派生クラスなので同上。
2009/03/21(土) 01:19:02ID:fKmdslcf
Planeはわかったので、次はCube。
頂点やら面情報を持ってるところはPlaneと同じ。頂点情報は共有してるかもしれないけど
今回のテーマ(ちゃんと解放したい)とは関係ないので読んでない。
>>41氏が>>49で書いてるとおり、Cubeはdestoryを持っていて、
MaterialObject3Dを解放する処理が記述されていると。ただこれは後述するけど
unregisterObject()っていうメソッドを呼んでるのであって、マテリアルの削除ではない。
CubeはMaterialObject3Dを複数個管理できるMaterialsListクラスでマテリアルを管理している。
Cubeのdestory()では、頂点やら面はほったらかし。

あ、そうだ、Planeでマテリアルにnullを指定した場合は自動的に
MaterialObject3D.DEFAULTが使われて、そこではWireframeMaterialクラスっていうマテリアルが
生成される。色はランダム。余談ね。

MaterialsListクラスは、マテリアル情報をDictionaryで管理してる。
マテリアルのインスタンスと、そこから生成した名前(文字列)の両方。
removeMaterial()でMaterialsListから指定したマテリアルを削除できるようだ。

でだ、cubeのdestory()は、マテリアルリストに含まれるマテリアルに対して
removeMaterial()は呼んでいなくて、unregisterObject()しているだけ。
これは、Cubeの生成時にマテリアルにCubeを登録( registerObject() )しているので
そこから消してる。つまり、描画はCubeではなくてマテリアルがやってるってことだろうかね。
Cubeのdestory()は、なんでremoveMaterial()しないのかは、ここら辺が関わっていて、
例えば、2個のCubeがある時に、それぞれのCubeが同じマテリアルを使っていると、
1つめのCubeの削除と同時にマテリアルの削除はしちゃダメってことになる。もう片方のCubeで
そのマテリアルが使えなくなるから。マテリアルとプリミティブは対等な関係じゃないので
それぞれ管理しないさいと。

ここまで来たら、あとはサンプルコードを書いて実践したいけど、もう眠いわ。
レスを投稿する

5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況