note.x

モデルのモーション制御の方法を模索してみる。
以前に試したMD2インポーターは、なかなか使えそうだったけど、肝心のMD2ファイルをOSX環境のみで作る手だてがどうにも見つからないので、とりあえず他の方法を探してみることに。(Win環境ならイイ感じかと)

ASColladaがボーンアニメーション付きColladaに対応してるので、Blenderでモーション付きのColladaファイルを出力してみた。…んだけど、BlenderのCollada Plug-inは、どーにもまともなデータを吐いてないっぽい。Collada 1.4.0 Plug-in for Blenderの公式サイトに上がってるファイルはBlender2.45に収録されているものと同じなので、sourceforgeのリポジトリから最新版を拝借して入れ替えてみたけど、やっぱりウェイト付けとか反映されないし、なんか変だ。

ネタがネタだけに情報源が少ない中、kumaryu日記さんが、0.3.146用のパッチを公開してくださっていたので、これを参考にして、0.3.159のtranslator.pyに手を入れてみた。で、驚いた。kumaryu日記さんによると、このパッチを2007/02/09付けでillusoftに送ったそうなんだけど、全然反映されてなかった。なんか開発が頓挫してそうな空気感が漂っておりますな。

手作業で該当箇所を適時修正して出来上がったツギハギColladaエクスポーターで吐き出したdaeファイルをASColladaで読み込んだ結果が以下。

bone_anim.swf(要:FlashPlayer9)

kumaryu日記さんのパッチのおかげでウェイト付けはちゃんと反映された。
けど、

objDAE = new DAE(hoge.dae);
objDAE.y = 100;

なんて感じで読み込んだオブジェクトを移動するとおかしなことに。なんかボーンが移動してないみたいで、ボーンを組み込んだオブジェクトだけ初期位置から動かない。あと、キーフレーム間の補完もされてない感じ。これじゃ使えないよー。

3dsMAXから書き出した場合は上手くいくみたいなので、恐らくCollada 1.4.0 Plug-in for Blenderがダメダメなんだろうけど…こんなことのためだけに3dsMAXなんか買えないし、他の方法を探そう。


Qreatureさんが指摘してくださった、「原点にカメラがあるとフリーズする」件を、改めて調べてみた。

Papervision3Dメモ #27のデモを対象に、MacOSX(PowerPC)10.4.10、FireFox2.0.0.9の環境で、FlashPlayer9のいくつかのリビジョンについて検証。結果は以下のようになった。

9.0 r16 問題なさそう
9.0 r28 しばらく放置するとフリーズ
9.0 r45 いきなりフリーズ
9.0 r47 問題なさそう

9.0 r28、r45に関して明らかにフリーズすることが確認できた。特にOSX版のr45に関してはswfを読み込んだ瞬間に固まる。なんというブラクラ。Win環境は調べてないけどたぶん同じような感じかと。

暫定的な解決方法としては、Qreatureさんのおっしゃる通り「とにかく原点(x:0,y:0,z:0)にカメラを置かない」ってのが一番簡単かつ確実っぽい。原点にさえカメラを置かなければいいので、(x:0,y:0,z:1)とか、任意の一軸だけでもずらしておくと上記の問題は起こらない。
24時間耐久テストとかやったらどうなるかわかんないけど、とりあえず15〜20分くらい放置してても問題なかった。

07/11/14追記
Qreatureさんにコメント欄で指摘していただいた仮説に基づき、Camera3Dではなく、FreeCamera3Dを使うことで解決するという手もある事が判った。こっちのほうが考え方としてもスッキリするかな。Qreatureさん感謝です!

ということで、Papervision3Dメモ #27のデモとソースを修正した。9.0 r28、r45をお使いのみなさまにはご迷惑をおかけしました。
それにしてもコレ、ほんとにFlashPlayer側の問題として片づけちゃっていいのか超不安。


bake_texture.swf(要:FlashPlayer9)

オレの環境だと△1000あたりが限界ということがわかったので、なるべく少ないポリゴン数で情報量を上げる手段を模索してみる。高品位なレンダリング結果をテクスチャにするっていうMayaか何かのチュートリアルがPV3D向けに公開されてたのを思い出したんで、Blenderでも同じような事ができないかどうかやってみた。使ったBlenderのバージョンは2.45。

■ザックリすぎるメモ

  1. とりあえずモデリング。ローポリで十分。
  2. UVマップを作る。UV/Image Editorは後でも使うのでそのまま表示しておく。
  3. ラジオシティの光源用オブジェクトを作る。法線の向きに注意。光源用オブジェクトのマテリアル設定 – Shadersパネルの「Emit」を「0」以外の数値にして、光源として定義する。
  4. 表示モデルと光源用オブジェクトを選択して、Radiosityパネルの「CollectMeshes」をクリック、Caluculationパネルが表示されるので、「GO」をクリックして計算開始。しばし待つ。計算が終わったら「FaceFilter」「ElementFilter」などで微調整。
  5. RadioToolパネルの「Add new Meshes」を押してメッシュ分割・頂点カラー焼き付け済みのオブジェクトを新規追加(この時、元のオブジェクトとは別のレイヤー選んでおく)
  6. 「Free Radio Data」を押して通常モードに戻る。
  7. Radiosityパネル使って出来上がったオブジェクトを選んで「UV Face Select」モードに切り替え。全Faceを選択。最初に作ったUVマップが継承されてるので、UV/Image EditorのImageメニューから「New」を選んで空ビットマップを作成。
  8. SceneのBakeパネルで「Bake」を押すとUV/Image Editor上にレンダリングされる。
  9. でき上がったテクスチャを保存、実際に使うローポリオブジェクトに適用しておしまい。

■参考情報
JBDP – モデリングツールとしてのラジオシティ
Blenderで3DCG制作日記 操作メモ – レンダーベイキング
python, mesh 3d coordinates to uv, texture baker

これイイかも。
ヘタにマシンパワー食う処理とか使わなくても十分見てられるし、フォトリアル系に傾倒してるわけじゃないけど、一手間かけるだけで随分と質感が変わるのがステキ。


前々回前回と続いたこのネタも、ようやくネギ振り実装完了(まだやってた)

ねぎミクPV3D改善版ねぎ振り付き(要:FlashPlayer9)
※クリックで振る

腕とネギだけが動けばいいので、特に難しく考えず腕とネギをペアレントした上で、それぞれ rotationX で動かした。Away3DのCORRECT_Z_ORDERレンダラ版は重すぎて、ねぎ振りは断念。

コレを全力で動かすとしたらMD2フォーマットのスキンメッシュ使うのが現実的なのかなぁ。ボーン制御だとメッシュのメリ込み回避とか面倒くさそう。

(続きを読む…)


e_negimiku2.jpg

前回の続き。
元データのままじゃ重いので、mqoインポーター使ってBlenderに読み込んで再編集した。
元データはエッジ表示用のポリゴンが貼られてたんだけど、多少のディテール低下はやむを得ないのでこれを丸ごと削除、さらに目立たない部分をチマチマ削除したりして何とか△987まで減らした。フォルムを殺さずにローポリ化するってのはそれだけでかなりの職人芸だわ。上手い人はもっと少ないポリゴン数で作れるんだろうな。
ローポリ化した後、PV3Dで簡易的にZ-Sortの弱点をカバーするdisplayObject3Dの「meshSort」プロパティを使う為に「髪の毛と上半身」「顔と下半身」を別のノードに分けてCollada出力した。結果は以下。

ねぎミクPV3D改善版(要:FlashPlayer9)

前回と比べてパフォーマンスもちょっと向上、さらに髪の毛のポリゴン欠けはかなり軽減した。meshSortプロパティは、わりと使いどころが難しいけど丁寧にやればもう少しポリゴン欠けを押さえられそうだ。

ポリゴン数を半分以下に減らしたんで、Away3Dでもなんとか動くようになった。
ねぎミクAway3D改善版(要:FlashPlayer9)

とはいえ重いのは変わりない。CORRECT_Z_ORDERレンダラは強力だけど、相当ポリゴン数が少なくないとダメか。Away3DにはmeshSortが無いので、パフォーマンスと品質を両立させた上でこの手のキャラクタを動かしたい場合、モデリングの時点である程度工夫が必要と。PV3DはmeshSortを上手く使うことを心がけるのがコツっぽいな。


e_negimiku.jpg

はちゅねミクことネギミクをPV3Dで読み込んでみた。
メッシュデータは七葉の保管庫から拝借(作者はズサさん)、ありがたいことでございます。メタセコで作られたデータなので、rch850さんによるMetasequoiaクラスを使ってみた。

あっさりおしまい、かと思ったらMetasequoiaクラスが PV3D1.5用みたいで、PV3D1.7だと使えない。何事も修業ってことで、1.7に対応させてみた。

208行目

var materialName:String;
↓
var materialName:MaterialObject3D;

208行目

var materialName:String;
↓
var materialName:MaterialObject3D;

298行目

materialName = mMaterialNames[parseInt(mstr)];
↓
materialName = materials.getMaterialByName(mMaterialNames[parseInt(mstr)]);

321行目

face = new Face3D([a, b, c], face.materialName, face.uv);
↓
face = new Face3D([a, b, c], face.material, face.uv);

331行目

materialName = mMaterialNames[parseInt(mstr)];
↓
materialName = materials.getMaterialByName(mMaterialNames[parseInt(mstr)]);

あと、これまでPV3D触ってきた経験上
162行目の

material.doubleSided = true;

はコメントアウトした。doubleSidedプロパティは基本的にfalseで、どーしても必要な場合のみtrueが無難、ってのがオレの考え。

以上でめでたくPV3D1.7で使えるようになった。メタセコ派のPapervisionalistはお試しあれ。
Face3Dの仕様変更が原因なので1.5と1.7両対応ってのは面倒そう。
以下が結果。

ネギミクPV3D版(要:FlashPlayer9)

うーん。重いのはまぁしょーがないとして、左右が反転してるのは何で?Metasequoiaクラスの改造がマズかったかな。

07/11/12追記
↑の疑問を太郎日記’79Jさんが見事に解決してくださいました。つーか、自分で調べた座標系の事をスッポリ忘れて何というイノセントな感想を語っているのかオレ…orz。

それよかやっぱり複雑なメッシュだとポリゴン欠けが目立つなぁー。Z-Sortなんとかなんねーのか。
とかなんとか、ひとしきりグチったとこでポリゴン欠けが円形脱毛症に見えてしょーがねーのでついカッとなって、MetasequoiaクラスをAway3D用に移植、CORRECT_Z_ORDERレンダラ使ってやってみた。

ネギミクAway3D版(要:FlashPlayer9)※デンジャラス重いです

おげぇー!重いーっつーか動いてねぇ(笑)ポリゴン欠けはウソみたいに無くなったけど…ねぇ。CORRECT_Z_ORDERレンダラって重いんだなぁ。これじゃネギ振るなんてムリだ。

mqoから一旦Blenderにコンバートして、もっとローポリ化しないとダメか。
Metasequoiaクラス移植した意味無ぇなぁ(笑)とりあえず面白かったけど。

追記:
太郎日記’79Jさんとネタかぶった…orz。
しかもつい2時間前のエントリ。でもむしろ同志がいてくれてウレシイ。


PV3Dにも参加してるTim Knip氏が開発中のASCOLLADAで、GoogleSketchUpからエクスポートしたkmzファイルに含まれるdaeファイルを、比較的まともにPV3Dで読めるようになってたので忘れないようにメモ。
使ったPV3Dのリビジョンはrev.243。

ASCOLLADA自体は、svnから落とす。

http://ascollada.googlecode.com/svn/as3/

(前述のTim氏によるエントリに記載されてるURLは古いので注意)
PV3DでASCOLLADAを使う場合は、上記svnからpapervision3d拡張用のクラスファイルも全て落とした上で、それぞれ所定のディレクトリに置く。

Googleの3DWareHouseから適当なデータの「Google Earth形式(.kmz)」を落とす。オレの場合は、Corn Exchange National Bankを落とした。

.kmzファイルの実態はzip形式のアーカイブなので、拡張子を.zipに書き換えるとかして展開。中には

  • doc.kml
  • textures.txt
  • imagesフォルダ(テクスチャ)
  • modelsフォルダ(daeファイル)

が入ってるので、modelsフォルダ内のdaeファイルをPV3Dで読み込めばよし。
Tim氏のエントリにあるように

var dae:DAE = new DAE( “somedae.dae” );
scene.addChild( dae );

とかやればいい。
注意点として、GoogleSketchUpでテクスチャをタイリング処理してあることが多いので、それに対処するためには、MaterialObjectのtiledプロパティを「true」にする必要がある。面倒な場合は、org/papervision3d/core/proto/
MaterialObject3D.asの79行目を

public var tiled :Boolean = true;

に書き換えておく。デフォルトは「false」なので必要ない時は戻したほうがいいかも。

結果は以下の通り。

e_ascollada.jpg

obj_Collada.swf(要:FlashPlayer9)

手ぇ抜いてマテリアルをデフォルトのままにしたもんだから、テクスチャ歪みまくり。
PreciseBitmapMaterialで設定し直したほうが美しいだろうな…かなりめんどくさいけど。
今回は出来あいのkmzからdaeを拝借したけど、GoogleSketchUpで作った形状をkmzでエクスポートしても多分読めると思う。ただ、GoogleWareHouseで公開されてるデータが全部まともに読めるわけではないので、何かの機能を使うことでASCOLLADAで読めないものになるみたいだ。この辺は要調査。
とはいえ、そこそこ使えそう。これで貧乏人のためのモデリングツールがまたひとつ増えたかな?


GeodesicSphere

PV3DMLで以前紹介された、GeodesicSphere.asを使ってみた。
通常のSphereオブジェクトは、四角ポリゴンを三角メッシュに分割して作られるのに対して、GeodesicSphereは正多面体で構成される。なので『極』が無い球体が作れる。

e_geodesic.jpg

obj_GeodesicSphere.swf(要:FlashPlayer9)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package
{
    import flash.display.*;
    import flash.events.*;
 
    import org.papervision3d.core.*;
    import org.papervision3d.scenes.*;
    import org.papervision3d.objects.*;
    import org.papervision3d.cameras.*;
    import org.papervision3d.materials.*;
    import org.papervision3d.events.*;
 
    [SWF(backgroundColor=0x000000)]
 
    public class obj_GeodesicSphere extends Sprite
    {
 
        private var container : Sprite;
        private var scene     : MovieScene3D;
        private var camera    : Camera3D;
        private var rootNode  : DisplayObject3D;
        private var valx      : Number = 0;
        private var valy      : Number = 0;
 
        public function obj_GeodesicSphere():void
        {
            stage.frameRate = 60;
            stage.quality   = StageQuality.MEDIUM;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            this.addEventListener(Event.ENTER_FRAME, loop3D);
            init3D();
        }
 
        private function init3D():void
        {
            container = new Sprite();
            addChild(this.container);
            container.x = stage.stageWidth / 2;
            container.y = stage.stageHeight / 2;
            stage.addEventListener(Event.RESIZE, onStageResize);
 
            scene = new MovieScene3D( container );
 
            camera = new Camera3D();
            camera.z = 500;
            camera.focus = 500;
            camera.zoom = 1;
 
            rootNode = scene.addChild( new DisplayObject3D( "rootNode" ) );
 
            var shadeMaterial:ShadedColorMaterial = new ShadedColorMaterial( 0x00ccff );
 
            var icosa:GeodesicSphere = new GeodesicSphere(shadeMaterial, 300, 2);
            rootNode.addChild(icosa);
            icosa.x = 0;
            icosa.y = 0;
            icosa.z = 0;
        }
 
        private function loop3D( event:Event ):void
        {
            valx += this.container.mouseX / 50;
            valy += this.container.mouseY / 50;
            rootNode.rotationY = valx;
            rootNode.rotationX = valy;
 
            scene.renderCamera( camera );
        }
 
        private function onStageResize(event:Event):void
        {
            container.x = this.stage.stageWidth  / 2;
            container.y = this.stage.stageHeight / 2;
        }
 
    }
}

残念だったのが、正二十面体が作れることを期待してたのにできなかったことと、BitmapMaterialが貼れないこと。Sphereと違って『極』が無いから、

テクスチャが極に向かって収束しないで貼れそう。

Google Earth的なものが作れる?

とか妄想してたんだけど、いきなりずっこけてしまった。考えが浅すぎた。にしてもBitmapMaterialが貼れない理由がわからん。メッシュをアジの開きにした際に矩形にならないものはダメってことかなぁ。


CurlingPlane.as を試す

lee felarca氏のblogで随分前に公開された、CurlingPlane.asの使い方が全然解んなくてずっと放置してたんだけど、やっとこさ理解できたので氏のサンプルと同じようなものを作ってみた。

e_curling.jpg

curling_Plane.swf(要:FlashPlayer9)
画像をドラッグするとページをめくれる。

このクラスの使い方は、

var planeObj:CurlingPlane = new CurlingPlane ( BitmapData,  CurlingPlaneの分割数);
planeObj.rotate(0);
scene.addChild( planeObj );

のような感じ。

rotate()メソッドで、ページのめくれ角度を0〜180で指定する。
長いことハマってたのは、rotate()メソッドで、角度を指定しないと画面に表示されないことに気が付かなくて、関係ないことばっかりやってたから。

また、lee felarca氏の別のエントリのコメント欄で紹介されているパッチをCurlingPlane.asに追記すると、

var planeObj:CurlingPlane = new CurlingPlane ( BitmapData,  CurlingPlaneの分割数, 裏返すかどうかのフラグ:Boolean);

のように、CurlingPlaneを定義できる。ページめくりには表と裏の2枚のPlaneが必要なんだけど、lee felarca氏のオリジナルクラスには、裏返しにするための処理が含まれてないので、このパッチを当てたほうが扱いやすい。


Maps.swf(要:FlashPlayer9)
※負荷が心配なのでスグ消すかも。

PV3Dとスクロールマップサービスを連動させて、バードビューな表示をするための習作。
せめてドラッグスクロールできるようにはしてみたい。
サクっと出来ると思ってたのに、MovieMaterialにMapオブジェクト突っ込んだ途端「Sandbox違反」。そういうことなのか〜。悩みに悩んだ挙げ句、Perlスクリプトを間に挟んで回避するというヤンチャな手段に打って出た。YahooMaps AS-Flash API使ったほうがぜんぜん楽チンだったかもしれない。GoogleMapsは確実にライセンス違反だろうから断腸の思いで見送る方向で。