フォトビューワーの改装


うちの母が手作り石けんのオンラインショップをやっていて、
レンタル鯖ロリポップを使っているんですが、
4日前に鯖側のトラブルでデータが吹っ飛んだみたいです。

レンタル鯖でこんな事故初めて聞いたんですが、
お金払ってる鯖でもこんなことがあるんですねぇ。。

で、
今まで作った石けんの画像を見れるFlashを一年前に作ったのですが、
これも吹っ飛んでいました。

自分のPCからバックアップを鯖に上げたのですが、
うまく動かずw

中身を見てみたものの、ASを始めたばっかの頃のものだったので
手続き型でコードを書いていて把握するのに結構時間がかかりそうだった。
その他にも拡大画像が見れないとか検索できないとか色々不便だったので
8割くらい書き直しそれらの機能も付けてみました。

これで今後メンテもいくらかしやくすなったはず。。。
よかったら見てください〜 ついでに買ってくれれば◎w
http://mammasoap.com/albam/

グーローシェーディングを実装


デモデモ


実装に当ってPsyark.jpさんのこのエントリーが大変参考になりました。
(3年も前のエントリーというのが驚き!)
というか「Flash」「グーローシェーディング」でgoogle先生に聞いてみても
国内でこの方のエントリー以外は見当たらなさそうだった。
始めソースを見たときは何がどうなって動いてるのかわからなかったけど
ペイントでいじりながら見てたら何となくわかってきました。
多分↓こういうことだと思います。

それと

即値1638.4(=2^14/10)はbeginGradientFillのマジックナンバーです。

1638.4と言う定数があるんですが、
これはどうやらグラデーションボックスを調整するもののようですね。
グラデーション調整は本来matrixクラスのcreateGradientBoxメソッドを呼び出して行いますが、
このメソッドにはボックスサイズ(width,height)と回転(rotate[radian]と座標位置(x,y)があります。
このメソッドを呼び出したしてボックスサイズを指定しなかった場合、
縦横のサイズは-819.2〜+819.2で出力されるようです。

つまりこのメソッドを使わない場合は
このデフォルト正方形のサイズを考慮して指定する必要があるため
「指定したいボックスサイズ / 1638.4」としているんですね。

行列クラスがオリジナルのものを使用していたので、
それにあわせたコードで実装したらそっちの方が負担が大きかった…w
ので、更に調整して何とか参考のソースコードと同様程度の速度に直せました。

が、重いです!
頂点法線求めるロジックとかひどいことになってる…
もっとスマートに組みたいなぁ(;´Д`)

パッケージにしてみたけどクラス分けが下手糞なのか、
500行超えてるクラスが二つある…

苦肉の策でFPS120で回してますwwwww
よし後はテクスチャだけだ!(フォンはスルー!

Zソートを実装


正六面体が飽きたので色々な長さの立方体を並べてビルっぽくしてみました。w

デモデモ


ZバッファZバッファ言っていましたが、Zソートで実装しました・・・。
一度はZバッファで実装を試みたけどFlashでZバッファとかありえない話でした。
画素単位でZ値書き込み&判定とか絶対無理。

なのでZバッファが主流になる前に良く使われていたというZソートを実装。
こっちはモデルのローカル原点をワールドに展開したときのZ値を判定するだけなので、
レンダリングするモデルの数が大量じゃなければそこまで負担はかからない。

でもZソートには弱点があって2つのモデルがあった場合、
片方がもう一方にスタックしてたり貫通してたりすると上手く表示できない。
(モデルを配置するときに分割して配置することで回避する模様。)
まぁそこまで複雑なモデルを表示できるほどポテンシャルなさげなのでZソートで十分ですね。

画素単位つながりでシェーディングの話になりますが、
グーローやフォンの実装も考えていて仕組みを調べてるんですけど、
フォンはFlashじゃ無理くさいですね。
画素単位で法線を求めると場合によっては1ポリゴンでもかなり負担かかりそう。

巷にあるFlashの3DAPIもフォンを仕組みどおりに実装してるものはなさそう。
(円グラデーションを使ったフォンシュミレーション的なモノはあるらしいw

ってか面を画素単位でリアルタイムレンダリングすることが厳しいから
グーローもグラデーションで実装しなきゃかもしれないですね。

後、高速化もしたつもりです・・・。
ロジック自体を色々変えたのとクラス内のメソッドでメンバ変数扱う場合でも
ローカル変数に代入してから扱うように徹底してみました。
(ちょっと度が過ぎてそうだけどw)

効果はと言うと頂点が多くなった場合の負担が軽くなってる。
前は頂点が1000いくと5fps下回る程に負担かかってたのが
今は10前後で踏ん張ってくれてる。
ただ頂点が少ないときの負担が前よりひどいような・・・w
もっと早くならないかなー(;´Д`)

フラットシェーディングを実装




Zバッファ入れてないので相変わらず重なりがおかしい!
デモデモ
コンボボックス3項目あるのですが
直でswf表示してるのでブラウザによっては一番下の項目見えないかも知れません。

昨日の日記に頂点の追加は実装依存と書いたけど、
そんなことないのかも。w

面法線を求めるのに稜線テーブルから頂点引っ張って来て求めるけど
もし頂点の順番が面ごとにバラバラだと
クロスベクトルが逆になったりして上手く計算できなくなることに気づいた。

一応頂点は常に反時計回りで追加していくらしい。
これは右手系なのか左手系なのかわかんない( ゚д゚)

色々と参考書やらHP見てるから右手と左手がごっちゃに頭に入ってる;
いつか整理しよう…

ワイヤーフレームの実装でもちょっと重くなったけど、
フラットシェーディングを実装したら更に重たくなってきたーーー(;´Д`)
すでに200頂点で10FPSあたりになってる。

後2種類くらいシェーディングを追加して、
テクスチャ張れるようにしたら高速化に力入れ始めよう。うん。

ワイヤーフレーム描画処理を実装




デモデモ


特に躓きもせず実装できた!( ´∀`)人(´∀` )
ついでにビュー座標変換も修正完了!写像も消せた。

ワイヤーフレームの描画はデータの持ち方がちょっと悩みますね。

色々と調べてみた所
ポリゴンとしてモデルデータを記憶する場合、
頂点配列とは別に稜線テーブルと言われる配列を持つ事が多いみたい。

この配列の中身は頂点配列のインデックスを格納していて
頂点がどの面を構成しているのかを記録するための配列データなんだけど、
多分法則的なものがない気がする。(=実装依存)

DirextXで直に描画を行う場合DrawPrimitiveメソッドを使うようなのですが
この引数には頂点をどんな方法で描画するかが指定できる形になってて
その中に
三角形ストリップと三角形ファン
というものがあってその描画規則に合うように頂点を追加していく形。
この場合、稜線テーブルがない代わりに規則に従わせることで描画を実現させてますね。

一方、メタセコファイルフォーマットを覗いてみたらこっちは稜線テーブルがあった。
なのでテーブルに従って描画しているのでしょう。

ワイヤーフレーム描画だけの悩みかもしれないけど、
稜線テーブルでも規則性を持たせる方法にしてもどっちもデメリットがあるような…

稜線テーブルはメンテしやすいけど描画時の負担が大きい気がする。
デモのようなオブジェクト(六面体)のワイヤーフレームを描画する場合、
頂点データが8、稜線データが12(三角形をプリミティブな図形とした場合)
となるので処理的には面を構成する辺の数*プリミティブ数(3*12=36)分だけ
描画処理(ASならlineTo)を呼び出すことになりますね。

一方、規則性を持たせた方法を取ると
頂点配列8、稜線なし(メモリ的にも易しい)、
尚且つ描画処理も規則を考慮したものとなるので最低限の呼び出しで描画可能です。
(あってるかわかんないけど線の数のみ=12回

しかしこっちは、自由度が全くない。
単純な図形でもかなり頭使わないと描画できない。
Xファイルとかどうなってるんだろ。中身見たことないや。
モデリングソフトなんかはこういう規則に従って
頂点データ格納してるんですかねぇ。(だとしたら凄すぎ)

謎は多いですが取りあえずワイヤーフレーム完成したので満足。
っつか落ち着いたら高速化を考えなければっ。(;´Д`)

座標変換ほぼ完了したよ

前回から一週間くらい経ちましたがそろそろ座標変換は卒業できそうかも?



3Dの頂点データから2D(ディスプレイ)への変換は、


1.ローカル座標(モデルを構成する生の頂点データ)
2.ワールド座標変換(3D空間上にモデルを置く)
3.ビュー座標変換(カメラの視点でモデルを見る)
4.プロジェクション座標変換(遠近法)
5.スクリーン座標変換(ディスプレイへ表示)


と5段階の行列変換を掛け合わせたものをモデルの各頂点にあてるのですが、
この内、ローカル、ワールド、スクリーンは単純なのですぐ理解できました。


射影変換の行列も感覚的にはわかったけど応用は出来ないレベル。
(まぁ今のところどんな場面で応用出来るのかすら思い浮かばないけど。


問題はビュー座標変換。あんま理解できてない。
今回のデモをいじくるとわかると思いますけど、
カメラの移動がちゃんと実装できてません。


参考書読んでも理解できなかったのでゴリ押しで実装したら見事に撃沈。
今の実装だとカメラが正面を向いてる状態での各平行移動しかできないみたいですw
(カメラの視点を変えてもそれが反映されない)
後、視界に入らない頂点を描画しない処理(これもカリングって言うんですかね?)

今の状態だと写像が後ろにも映って
90度以上カメラ回すと自分がどこ見てるのか分からなくなる。


それ以外は完璧だと思います。
で、ついでに頂点をリアルタイムに追加できる機能も付けてみました。


うちの化石PCで限界を計ってみたら、
Athlon XP2500+ → 頂点3000辺りでFPS5 w
Pen4   3.7  → 頂点10000辺りでFPS5
こんな感じでした。C2Dだとどこまで増やせるのかなー。


因みに48 * 48 * 8 = 最大18432頂点まで増やせます。
是非フリーズしない程度に試してみてください。w
デモデモ


↑の機能とかとりあえず実験的な実装が多くて
段々Main.asがカオスになって来てます…
どっかのタイミングで整理しないとコード汚いのが原因で投げ出しそうw


とまぁ黙々とやってきましたが、
この先の予定は
1.取りあえずビュー座標変換をもっと調べて理解する。ソース修正。
2.ワイヤーフレームの描画方法を考える。(頂点増やさずにどうにかしたい…)
3.ランバート拡散照明やグーローなど割とオーソドックスと思われるシェーディングの実装
4.物理をそろそろ…(曲線とか書けるようになりたい><




何はともあれ、かなり苦戦して「絶対こんなもん理解できねー!」って思ってたものが、
実装できるレベルまで理解できたことに達成感が持てたのでまだまだがんばれそうです。

遂に3Dを描画出来るようになったっ!

途中何度か諦めそうになりながらも
なんとかベクトルや行列を使った座標変換が出来るようになった。長かった><

とりあえずASで組んでみた。
マウス左クリックしながらドラッグするとオブジェクトをクルクル出来ます。
後、マウスホイールでオブジェクトの拡大縮小。
※1つの描画領域で全ての頂点を書き込んでるので重なりはおかしいです。

今のところ頂点データの描画(行列を使った頂点の平行移動・スケーリング・X/Y/Zの回転)しか出来ない。
単純な物体ならその物体の光の反射やテクスチャの張り方はあと一歩といった感じなんじゃないでしょうかね。

面張できるようになったら
メタセコイアのモデルファイルから頂点データを吸い出して表示できるようにさせたいなー。
(あのファイル頂点の座標が生で書かれてるからそのまま使えそうだし!)

それが出来たら今度はワールド内でカメラを自由に移動させたい!
そこまで理解できたらもうAPIで組んでも良いかなと思ってる。

APIときたらDirectXですがこっちもなかなか良い感じの進み具合です。
何をやってるのか何ができるのかだんだん見えてきた。

そんな感じです。引き続きがんばれ俺!