2010年09月

2010年09月30日

clothやってみた その2 3dsmax 2011

なんだか変な熱が出て昨日から寝込んでました・・・orz

ようやく熱もひいて体調も戻ったみたい。遅ればせながら本日の更新です。

前回は服飾メーカーモディファイヤと布地モディファイヤを組み合わせて服を縫い合わせる手順をちょっとやってみた。服を作ってシミュレートするならこの組み合わせが現実の服作りに近い方法なんだけど、通常のモデリングをしたメッシュに対して布地モディファイヤだけ適用してシミュレートすることも当然出来る。

例えば下の画像のように球体と平面を配置して、平面に布地モディファイヤを設定して、

fig01

布地モディファイアのオブジェクトロールアウトの「オブジェクトプロパティ」を押してパネルを出し、平面を布地に設定する。

fig02

さらに「オブジェクトを追加」ボタンを押して球体を追加し、それを衝突オブジェクトに設定する。

fig03

そしてシミュレーションパラメータはこのようにして、重力がON、個体衝突がONになっている状態にして、布地が重力の影響で下に落下し、衝突オブジェクトとして設定した球体に衝突するように設定して、

fig04

ローカルシミュレーション(ダンピング)ボタンを押すと、シミュレーションが開始されて、

fig05

しばらく待っているとこのような状況になった。放っておくといつまでもシミュレーションをし続けるので適当なところで再び「ローカルシミュレーション(ダンピング)」をクリックしてシミュレーションを終了させる。

fig06

このようにメッシュが粗いと布が衝突オブジェクトを貫通してしまったりする。ある程度の精度を得るにはそれなりの解像度が必要だ。

下の画像は「状態をリセット」ボタンを押して形状を元に戻し、モディファイヤパネルでPlaneを選んでセグメントを20×20に変えてから「ローカルシミュレーション(ダンピング)」をやり直したものだ。4×4の時よりはずっと布らしい振る舞いになっている。

fig07

ただ四角ポリゴンで布を構成した場合、変形が素直になり過ぎて規則的な皺ができやすい。その点、前回使った服飾メーカーは編集可能スプラインをドローネメッシュという不規則な三角ポリゴンに分割するから皺の寄り方や凹凸が不規則になってより布らしい振る舞いになるらしい。下の画像は左が通常の平面でセグメントを増やしたもの。右が編集可能スプラインを4角でブレークしたものを服飾メーカーでドローネメッシュ化したもの。

fig08

これを同一条件で球にかぶせてみたのが下の画像だ。ドローネメッシュの方がより強(こわ)い感じで、不規則な皺によって布が完全に下に垂れ下がらないように抵抗している感じだ。

fig09

これがレンダリング結果。

fig10

fig05布のシミュレーション計算をさせるボタンは上記で使用した「ローカルシミュレーション(ダンピング)」と「ローカルシミュレーション」、「シミュレート」の3つあり、ローカルの方は現在のフレームのままシミュレーションだけ進めるもので、シミュレートの方はシミュレーション計算とともに現在時刻も更新されて、他のオブジェクトのアニメーションと連動した布のシミュレーションが行えるようになっている。
この2系統あるのは、ローカルの方が布の初期状態を作り出すのが目的で、シミュレートの方はその初期状態から布のアニメーションを作り出すのが目的だからだ。そうじゃないと服飾メーカーを使って服を生成した場合、アニメーションの冒頭に必ず生地が縫い合わされるアニメーションが入ることになっちゃうからね。
さらにローカルシミュレーションはダンピング付きと無しに分かれている。このダンピングは速度に対する抵抗力みたいなもので、例えば布が凄い力で引っ張られていた場合、シミュレーションを開始するとその力で布の各ポイントが勢いよく引っ張られて加速し、大きな速度が出たりする。布のシミュレータは時間をちょっとずつ進めて前の状態から次の状態を求める方式なんだけど速度が上がるとちょっと時間を進めただけなのにとんでもないところまでポイントがすっ飛んで行ってしまう事があるわけだ。現実にはそんな遠くまでポイントが吹っ飛ぶ前に布内部の抵抗力とかで抑えられるわけだけど、それを計算に入れるためにはその間の地点での計算も必要になり、ポイントの速度が上がるほどシミュレータは時間を細かく分割してちょっとずつ時間を進めて計算しなくちゃ正確な計算が出来なくなってしまうわけだ。これは非常に効率が悪いので(ダンピング)付きの方は、速度に対する抵抗(ダンパ)を計算に組み込んで布の速度が極端に上がらないように抑えて計算させる仕組みのようだ。だからダンピング無しに比べて布の反応は鈍くなるけど、速度超過による計算密度の不足みたいな事は起こらなくて済むわけだ。まあ待てない時間でもないからこっちを使っとけばいいんだろうね。

ローカルシミュレーションは前述した通り初期状態を生成するためのシミュレーションで、シミュレートは布アニメーションを作成するためのシミュレーションなので、結果としてローカルの方はシミュレーション結果の形状だけが残るけど、シミュレートの方は布が変形していく様子がフレーム単位で記録される。

例えば球体にこのようなアニメーションをつけて、

fig11

フレーム0で「ローカルシミュレーション(ダンピング)」ボタンを押すと、布のシミュレーションは刻々進んで行くけどタイムスライダはフレーム0のままなので球体は静止したまま布がかぶさる。適当なところでローカルシミュレーションを終了する。

fig12

次に「シミュレート」ボタンを押すと、今度はタイムスライダが進み始め、球体の移動アニメーションが再生され、それに伴って布の方も変形されて行く。

fig13

この動きは全て布地モディファイヤ内に記録され、

fig14何フレーム記録したかはシミュレーションフレームとして表示される。シミュレーション結果のデータを消去したい場合はそのすぐ下にある「シミュレーションを消去」ボタンで消す事が出来る。途中まではOKだったけど、それ以降のオブジェクトの動きに変更があったりしてシミュレーションをやり直したいなんて場合は、やり直したい時刻にタイムスライダを移動して「シミュレーションを切断」を押せばそれ以降のシミュレーションデータだけ消去する事も出来る。

fig15選択オブジェクトマニュピレータにはシミュレータで自動計算させるだけではコントロールしにくい部分の修正などをするためのツールが集まっている。
「初期状態にセット」は現在の布の状態をシミュレーション開始時の布の形状にセットする。布は「メッシュ編集」モディファイヤとか使って変形が出来るので、「ローカルシミュレーション」だけでは思った初期形状に出来なかった時にはメッシュ編集とかで変形してからこのボタンを押して初期形状として登録すればいい。ちなみにボタンを押すとメッシュがおかしな変形状態になる。これはメッシュ編集が布地の初期位置に対して相対的にかかるせいで、その相対的な変形を布に適用した場合、メッシュ編集される布の初期位置が変化後の位置に移動して、さらにそこからメッシュ変形で変形されるため、見かけ上メッシュ変形の適用量が2倍になったように見えるせいだ。もちろんメッシュ編集モディファイヤを削除すればちゃんとした変形結果が残ってるよ。

「初期状態にセット」がモディファイヤスタックトップの状態を布形状の初期形状にキャプチャしてくるのに対して、「状態をリセット」は布地モディファイヤより下の形状をキャプチャする。布地モディファイヤを適用した元のオブジェクトを変形しても、そのままでは布地に反映されない。その変形を布地に適用したければこのボタンを押して変形後の形状をキャプチャしてくる必要があるわけだ。そういう意味でこのボタンは布をシミュレーション前の初期状態に戻すことができる。

「オブジェクトのキャッシュを削除」は「シミュレーションを消去」と同じように布の変形アニメーションデータを消去するんだけど、その消去の対象となるデータの格納場所が異なる。布地のオブジェクトプロパティパネルで選択したオブジェクトを「非アクティブ」「布地」「衝突オブジェクト」に切り替えられるけど、「布地」から「衝突オブジェクト」に切り替える時、一緒に変形アニメーションのデータも移す事ができる。「シミュレーションを消去」はこの衝突オブジェクトに移された変形アニメーションのデータを消去するためのボタンだ。このように布の変形アニメーションのデータを布の変形シミュレーション用と衝突オブジェクトの変形用に分けることで、完成した部分のアニメーションは固定し、それを衝突オブジェクトとして使ってさらに上から布をかぶせてシミュレーション計算が出来るようになっている。例えばズボンをシミュレーション計算してアニメーションデータを作ってから、それを衝突オブジェクトとして上着のみのシミュレーション計算が出来るわけだ。

例えば下の画像のように先にシミュレーションしたシーンにさらに服飾メーカで新しいパネルを加えた。

fig16

この状態でオブジェクトプロパティパネルを開けてオブジェクトを追加で新しく作成したパネルを追加し、布地としてシミュレートしたものを衝突オブジェクトに切り替える。

fig17

そして追加したパネルを布地にする。

fig18

これでOKを押すとシミュレーションフレームが1に戻ってシミュレーションデータが消えている事がわかる(衝突オブジェクトに移された)。

fig19

この状態でシミュレートを開始すると、衝突オブジェクトに変更したオブジェクトは以前のシミュレート結果のデータで変形アニメーションされ、それを衝突オブジェクトとして追加したオブジェクトがシミュレーション計算される。

fig20

ここで「シミュレーションを消去」をしても衝突オブジェクトのアニメーションはそのまま残り、新しくシミュレーションした方のアニメーションだけ削除されるわけだ。そして衝突オブジェクトの方についているアニメーションを消去したい時には「オブジェクトのキャッシュを削除」を使うわけだ。ただし消去しても初期形状は残るよ。

「状態を確保」はフレーム単位でシミュレーションデータを修正するためのボタンだ。「初期状態にセット」が現在のスタックトップの形状をキャプチャしてシミュレーションの初期形状を修正したように、「状態を確保」は現在のスタックトップの形状をキャプチャして現フレームのシミュレーションデータを修正する。だから服がちょっと突き抜けちゃったとか変形がおかしいなんて場合に、そのフレームに移動してメッシュ編集モディファイヤを追加して、形状を修正し、このボタンを押せば、このフレームのシミュレーション結果だけその形状で修正される。ただしメッシュ編集モディファイヤが適用結果にさらにかかるから見た目は変形が倍になったように見えるよ。編集が全部終わったらメッシュ変形モディファイヤは削除してね。

長くなったので続きはまた次回。

今週は大事をとって明日も休みます。

maxまとめページ



take_z_ultima at 16:34|この記事のURLComments(2)TrackBack(0)3ds Max | CG

2010年09月29日

今日は更新を休みます

また明日。



take_z_ultima at 10:14|この記事のURLComments(0)TrackBack(0)その他 

2010年09月28日

Maximaを使ってみた その11

地デジ化前にすでにだんだんTV番組を見なくなって来たなぁ。このぶんなら録画用のデッキ1台だけ買っとけばTVまで買わなくても済ませられそうな感じだなぁ。かつてゴールデンタイムと呼ばれた午後7時台はホントに見たい番組が無くなった。ニュースも耳を塞ぎたくなるようなものばかりだしね・・・。
TUTAYAが4本以上借りると1本あたり250円で借りられるので、シリーズものを借りて見ている。最近見たものではFRINGEが面白かったなぁ。でもファーストシーズンでかなりネタバレしたからセカンドシーズンはちょっと停滞気味かな。

それとMaximaがいいオモチャになってて、線形代数の本を片手にあーでもないこーでもないしてるとあっと言う間に時間が経っていく感じ。

最近読んでるのが共立出版の「計算による線形代数 (工系数学講座) 」と「現代線形代数 ―分解定理を中心として― 」だ。前者は計算手順が実例入りで載っていたり、固有値解析や一般逆行列まで扱っていたりして、わかり易い上に実用的で有用な範囲をちゃんと網羅しているという意味で、かなりお買い得感があった。後者の方はなかなか自分には歯ごたえがあるけど、線形代数のあの手この手がたくさん紹介されていて、興味が尽きない。これだけの情報をたった4〜5千円で手に入れられるんだから、いい時代に生きてるよね。

Maximaで行列をいろいろいじってると、行列の一部を切り取ったり繋いだりなんてことがしょっちゅう出てくる。そんな時に最近良く使うのが

genmatrix(lambda([i,j],行列要素の算出記述),m,n)

の書式だ。genmatrix(関数,範囲)は指定した範囲で2つのパラメータを変化させて関数を呼び出し、それを該当する行、列の示す要素に格納して行列を生成する関数で、lambda( )はそこで使う関数をいちいち他で定義しないでgenmatrix()の中で名前を付けずに定義してしまうための仕組みだ。

例えば行列の固有値を対角に並べた行列が欲しいときはこんな感じだ。

fig01

行列Mの固有値がvalに配列で格納されていて、lambda( )関数は与えられた2つのパラメータ変数 i と j の値が同じだった時にval[i]の値を、それ以外は0を返す。これをgenmatrix(関数,3,3)の中で使うと、(i,j)を(1,1)、(1,2)、(1,3)、(2,1)、・・・、(3,3)と変化させながら関数を呼び出し、その結果を行列の[i][j]の要素に設定する形で行列が生成される。だから行番号と列番号が等しい対角の位置にvalの値が並んだ行列が出来るわけだ。

genmatrix()はパラメータを3つ4つ5つとる3つのパターンが存在していて、

  • genmatrix(関数,右下の行番号m,右下の列番号n)
  • genmatrix(関数,右下の行番号m,右下の列番号n,
          左上の行列番号p)
  • genmatrix(関数,右下の行番号m,右下の列番号n,
          左上の行番号p,左上の列番号q)

となっている。2番目のパターンの「左上の行列番号p」は行番号も列番号も同じpになる場合ね。

例えば行列Mの右上の4つの要素で構成される2行2列の行列を取り出したいなら、

genmatrix(lambda([i,j],M[i][j]),2,3,1,2);

などと書けばいい。そうすれば左上1行2列の要素から右下2行3列の要素を対角とする要素が切り出されて行列が生成される。

fig02

これを5X5の単位行列の左下に入れようと思ったら、

fig03

なんて書き方も出来る。使い方によってはかなり強力だね。たぶんこれを使わない方法もあるんだろうとは思うんだけど、覚えるものは少ないに越したことはないし・・・。

それからちょっと面白い関数も見つけた。それは連立方程式を行列の掛け算の形に変換する

augcoefmatrix ([eqn_1, ..., eqn_m], [x_1, ..., x_n])
coefmatrix ([eqn_1, ..., eqn_m], [x_1, ..., x_n])

などだ。
連立方程式をAx+c=0とした時に、上の関数は[Ac]の形で行列を返し、下の関数はAだけ返す。このように2式の連立方程式とそこから整理して抜き出すベクトル(x、y)を指定してやれば、Ax+c=0のAの部分の行列が取得出来る。

fig04

さらに、[Ac]の形で欲しければaugcoefmatrixを使えばいい。さらにAx+c=0のcだけ抽出したければcol()を使って切り出せる。今回はついでにAx=−cの形になるようにCを右辺に移項したと想定して符号を反転させておいた。

fig05

係数拡大行列である行列Mにはこんなベクトルを作ってかけてやれば、もとの方程式を=0でまとめた形の式が現れる。

fig06

この係数拡大行列は掃き出し法で解を求める時に出てくる奴だね。

掃き出し法は行列Mの右側の部分が単位行列になるように行どうしを定数倍して足したり引いたりすれば、右側の部分が解になるって奴だね。

実際やってみると、1行目の左端の値が2だからこの行全体を2で割って左上の数値を1にする。for文使えば一括して出来るね。

fig07

この1行目をa倍して2行目から引けば左下のaは0になる。

fig08

次に2行・2列目の値を1にするために2行目をb-(1-a)*a/2で割る。

fig10

そして2行目を(1-a)/2倍して1行目から引けば、1行2列目の値が0になり、左側が単位行列の形になった。ちょっとややこしい形になったのでrat()関数で整理した。この右側の2つの値が連立方程式の解だ。

fig11

比較のためcoefmatrix( )で生成した行列Aと、augcoefmatrix( )とcol( )で生成した行列cから解を求めてみると、このようになって、上の結果と一致する。

fig12

今は一般逆行列を使った直線近似とかをいろいろ試してみてるところ。CGのプログラムで活かせそうな事がいっぱいあるね。

それではまた次回。



take_z_ultima at 11:30|この記事のURLComments(0)TrackBack(0)Maxima 

2010年09月27日

modoからFLASHへ書き出してみた その26 modo 401 SP4 ActionScript 3.0

さっそくAnimationController.asをほんのちょっとだけいじって、クリップを組み込んでみた。下のFLASHムービーがその成果。この顔のオブジェクトには2つのアニメーションクリップが仕込まれていて、画面の左右をクリックすることで別のムービーが再生されるようにしてある。

Adobe Flash Player を取得

package org.papervision3d.core.controller.AnimationController.asで手を加えちゃったのは以下の部分。

public function play( )の定義の部分で、_channelsの配列の要素数を条件にしていたif文を_clipが設定されているかどうかも条件に加えた。

  public function play(clip:String="all", loop:Boolean=true) : void
  {
   if(clip && clip.length && _clipByName[clip] is AnimationClip3D)
   { 
    _clip = _clipByName[clip];
   }
   else
   {
    _clip = null;
   }
   
   if(_channels.length || _clip)
   {
    _loop = loop;
      :

public function update() のところの冒頭もchannels.lengthだけの条件にしないで、_clipsも条件に加えた。

  public function update() : void
  {
//   if(!_isPlaying || _isPaused || !_channels.length)
   if(!_isPlaying || _isPaused || (!_channels.length && !_clip))
   {
    return;
   }
     :

そして現在再生中のクリップを示す変数_clipにアクセスするゲッタメソッドを追加した。

  public function get clip() : AnimationClip3D
  {
   return _clip;
  }

このくらい書き換えないと、クリップの再生が難しかった。

これでなんとかクリップが組み込めるようになったので、org.papervision3d.core.animation.clip.AnimationClip3Dを継承したMyClipクラスを作って、そこに頭のアニメーションを保存できるようにした。

package  {
 import org.papervision3d.Papervision3D;
 import org.papervision3d.core.geom.*;
 import org.papervision3d.core.geom.renderables.Triangle3D;
 import org.papervision3d.core.geom.renderables.Vertex3D;
 import org.papervision3d.core.math.NumberUV;
 import org.papervision3d.core.proto.*;
 import org.papervision3d.core.controller.MorphController;
 import org.papervision3d.core.controller.AnimationController;
 import org.papervision3d.core.animation.channel.controller.MorphWeightChannel3D;
 import org.papervision3d.core.animation.curve.Curve3D;
 import org.papervision3d.core.animation.channel.Channel3D;
 import org.papervision3d.core.animation.key.BezierCurveKey3D;
 import org.papervision3d.events.AnimationEvent;
 
 import org.papervision3d.core.animation.clip.AnimationClip3D;
 
 public class MyClip extends AnimationClip3D{
  private var _channels:Array;
  public var trsX : Channel3D = null;
  public var trsY : Channel3D = null;
  public var trsZ : Channel3D = null;
  public var rotX : Channel3D = null;
  public var rotY : Channel3D = null;
  public var rotZ : Channel3D = null;

  public function MyClip(name : String, startTime : Number = 0.0, endTime : Number = 0.0) {
   super(name, startTime, endTime);
   _channels=new Array();
  }

  public function addChannel(channel : Channel3D)// : Channel3D
  {
   if(_channels.indexOf(channel) == -1)
   {
    _channels.push(channel);
    updateStartAndEndTime();
    return channel;
   }
   return null;
  }

  public function update(currentTime){
   var channel:Channel3D;
   for each(channel in _channels)
   {
    channel.update(currentTime);
   }
   
  }
  
    /**
   * Updates the startTime and endTime of this animation controller.
   */
  protected function updateStartAndEndTime() : void
  {
   var channel : Channel3D;
   
   if(_channels.length == 0)
   {
    startTime = endTime = 0;
    return;
   }
   
   startTime = Number.MAX_VALUE;
   endTime = -startTime;
  
   for each(channel in _channels)
   {
    startTime = Math.min(startTime, channel.startTime);
    endTime = Math.max(endTime, channel.endTime);
   }
  }

 }
 
}

このクリップクラスにはモーフチャンネルとか移動・回転などのアニメーションさせる様々なプロパティに対するチャンネルをaddChannel( )メソッドで登録できるようにしてある。そしてそれらのチャンネルはupdate( )メソッドによって現在時刻のデータに更新されて読み出せるようになる。モーフマップについてはモーフターゲットとチャンネルがバインドされているので、チャンネルをupdate( )した後で、モーフコントローラの方をupdate( )してやれば、各モーフが現在時刻のチャンネルの値でブレンドされてオブジェクトの形状が変化するけど、オブジェクトの移動や回転については変位に関するチャンネルクラスの使い方がいまひとつわからなかったので、独自にMyClipクラスに位置と回転のチャンネルを登録する変数を用意して、addChannel( )メソッドでチャンネルを登録する以外にその変数にもチャンネルを設定するようにしてみた。チャンネルの値を現在時刻で更新するのはaddChannel( )で登録しておけばクリップに対するupdate()の時に勝手にやってくれて、移動や回転チャンネルを登録しておく変数がnullじゃなければそれらにチャンネルが割り当てられているものとして、オブジェクトの位置や回転のパラメータを割り当てられたチャンネルの値で更新するようにした。

それをHead.asのAnimationEvent.NEXT_FRAMEのイベントハンドラにこのような形でコード化してみた。modoの回転角度がラジアンだったので、度に変換したりしている(こんなことしなくてもラジアンで扱えそうなスイッチがあるみたいなんだけど、時間の都合でとりあえずこうしておいた)。クリップクラスに設定したtrsX、trsY、trsZが位置のチャンネルで、rotX、rotY、rotZが回転のチャンネルだ。

  private function loop(e:AnimationEvent){
   if(_animationcontroller.clip){
    MyClip(_animationcontroller.clip).update(e.time);
    if (MyClip(_animationcontroller.clip).trsX) this.x= MyClip(_animationcontroller.clip).trsX.output[0];
    if (MyClip(_animationcontroller.clip).trsY) this.y= MyClip(_animationcontroller.clip).trsY.output[0];
    if (MyClip(_animationcontroller.clip).trsZ) this.z= -MyClip(_animationcontroller.clip).trsZ.output[0];
    if (MyClip(_animationcontroller.clip).rotX) this.rotationX=-MyClip(_animationcontroller.clip).rotX.output[0]*57.295779513082320876798154814105;
    if (MyClip(_animationcontroller.clip).rotY) this.rotationY=MyClip(_animationcontroller.clip).rotY.output[0]*57.295779513082320876798154814105;
    if (MyClip(_animationcontroller.clip).rotZ) this.rotationZ=MyClip(_animationcontroller.clip).rotZ.output[0]*57.295779513082320876798154814105;
   }
   _morphcontroller.update();
  }

だから例えばクリップにオブジェクトのX軸回転のアニメーションチャンネルを登録しようと思ったら以下のようになる。

   channel = new Channel3D();
   curve=new Curve3D();
   curve.addKey(new BezierCurveKey3D(0.0,0.0, 0.0,0.0, 0.0,0.0667));
   curve.addKey(new BezierCurveKey3D(0.2,0.233874, -0.29,-0.29,0.0667,0.0778));
   curve.addKey(new BezierCurveKey3D(0.4333,-0.125664, -0.3898,-0.3898,0.0778,0.1222));
   curve.addKey(new BezierCurveKey3D(0.8,0.0,0.0,0.0,0.1222,0.0));
   channel.addCurve(curve);
   clip.addChannel(channel);
   clip.rotX=channel;

チャンネルとカーブを作って、カーブにキーを追加して、そのカーブをチャンネルに追加して、そのチャンネルをクリップに追加するところまではモーフの時と同じ。それに加えて変数rotXにも同じチャンネルを代入するのがミソ。こうしておけば

  if (MyClip(_animationcontroller.clip).rotX)

の判定がtrueになって、

this.rotationX=-MyClip(_animationcontroller.clip).rotX.output[0]*57.295779513082320876798154814105;

が実行されて、オブジェクトがX軸回転するわけだ。ちなみにoutput[0]はチャンネルの現在時刻での値を表わしていてチャンネルのupdateの時に更新されるプロパティね。配列になってるのは1つのチャンネルにカーブが複数登録できるから、そのカーブ1つにoutput1つが対応しなくちゃならないためね。

あとはMain.asのところでマウスイベントに対応出来るように

stage.addEventListener(MouseEvent.MOUSE_DOWN,mdHandler);

でマウスボタンを押したときに発生するイベントに対するハンドラmdHandlerを登録し、その定義でマウスカーソルのX座標がマイナスだったらクリップ名「surprise」でクリップを再生し、ループなしで終了させ、プラスだったら「wow」を再生させてループなしで終了させるようにしてある。

 public class Main extends BasicView{
  var head:Head;
  public function Main() {

   var material:BitmapAssetMaterial=new BitmapAssetMaterial("imgHead");
   head=new Head(material);
   scene.addChild(head);
   camera.x=0.1;
   camera.y=0.2;
   camera.z=-1.4;
   startRendering();
   stage.addEventListener(MouseEvent.MOUSE_DOWN,mdHandler);
   addEventListener(Event.ENTER_FRAME,loop);
  }
  
  private function mdHandler(e:MouseEvent){
   if(e.localX<0)
    head._animationcontroller.play("surprise",false);
   else
    head._animationcontroller.play("wow",false);
   head._animationcontroller.update();
  }

  private function loop(e:Event){
   head._animationcontroller.update();
  }
 }

プログラムを書いてデータを作ってみたら、モーフ変形が破綻する場面が出てきた。ベジェ曲線の処理部分がまだ完全じゃないのかも。

それではまた次回。

modoカテゴリー別ページ



take_z_ultima at 12:47|この記事のURLComments(0)TrackBack(0)modo | FLASH

2010年09月25日

巨大綾瀬はるか見てきた

新宿東口の新宿ステーションスクエアに巨大バルーンが展示してあると聞いてちょっと見に行ってみた。

東口から出たらいきなりこんな光景がwww。でかっ。

fig01

パナソニックのデジカメ「LUMIX FX700」の発売イベントで作ったバルーンだそうで、全長10mもあるらしい。

fig02

しかし一番いい位置で撮ったショットがレンズの上にストラップがかかっていると言う大失態・・・orz ダメすぎる。

fig03


fig04

いやぁでもよく出来てるわぁ。

fig05

注目度はイマイチかな。

fig06

いつものようにパノラマ合成も作ってみた。

fig07

どうやってこの大きさでキチンと輪郭を保っていられるのかはわからないけど、凄い技術だねぇ。それと台風逸れてよかったねw



take_z_ultima at 18:41|この記事のURLComments(1)TrackBack(1)物見遊山 
Archives