久しぶりにスキニングメッシュ(エンベロープモデル)のネタです。
キャラクターのモデルでバウンディングボックスやスフィアを使って、あたり判定を行っていましたが、
結構無駄な部分が出来てしまい、結果厳密なチェックが出来ないという残念な結果になってしまいます。
かといって、頂点変形をCPUで全ての頂点で行って厳密なバウンディングボックスを作るのもこのご時世に何かあっていないようなそんな気がします。今だとシェーダーでスキニングロジック実装しちゃいますしね。
そんなわけでもう少しまともなバウンディングボックスを作れないかチャレンジしてみました。今回はこの中身に触れたいと思いますが、まずは処理結果の図を以下に示します。
割と各部位に従ってボックスが出来ているのがわかると思います。これが動きに合わせて追従してくれるので、使い勝手はよいかなと思っています。ボックス自体の頂点情報は固定で、単にボーンの行列に合わせて変形されるので処理も結構軽い物となっています。
処理手順
画像を見てもわかるようにDirectXサンプルの定番 tiny.x を使用しています。
そして、SkinnedMeshサンプルの改造です。
- 各ボーンの影響頂点群を取得して、各頂点で一番大きなボーンはどれなのかの情報を保持します。
D3DXにはこの操作に便利な GetBoneInfluence, GetNumBoneInfluence というID3DXSkinInfoのメンバ関数が用意されているので楽に処理できます。 - 各頂点を走査して、自身が一番影響を受けるボーンのボーン行列と頂点位置を乗算します。
- 計算されたボーンローカルの位置で、そのボーンがもつバウンディングボックス情報を更新します。
位置が最小、最大なら現在の値で置き換えるという処理。
これらの処理により、各ボーンが自分の影響する範囲でのバウンディングボックスを構築することが出来ます。
その他
動かしてみていると若干つなぎ目部分で隙間が出来ていたりします。
あたり判定に使うにはちょっとまずい場合があるのかもしれません。
あと、ConvertToIndexedBlendedMesh でメッシュを更新したあとだと、GetBoneInfluenceで返ってくる値と食い違いが出て悩みました。どうやらこれは変換前の頂点データ群についての結果を返してくるようです。
変換前後での頂点のマップを用意して処理してあげることが必要でした。
コメント