差分

ナビゲーションに移動 検索に移動

MonoGameの3Dモデルを管理描画するクラスを作る

2,473 バイト追加, 2018年1月30日 (火) 03:26
編集の要約なし
'''MvvmCross'''とは、[[.NET FramewrokMonoGame]]および[[Mono]](各種[[Xamarin]])で利用できる[[MVVM]]の[[フレームワーク]]である。での3Dモデルの「表示」について解説しているサイトは多数あるが、「回転」や「位置」について記述しているサイトはほとんどないようだ。そもそもモデルと位置情報などを切り離して管理すること自体が馬鹿げているので、それらを管理するクラスを作っておくと捗る。
==概要==また、Drawコールの中でBasicEffect周りを毎回設定している記述も多い。[[MVVMPC]]といえば古くからのように[[WPFCPU]]が高速な環境では問題にならないのだろうが、[[Silverlight]]が存在したが、これら実質的に[[WindowsAndroid]]という単一プラットフォームでしか利用できなく、などではそれだけで結構な負担になる。Android端末の多くが「[[デバッグ]]が楽だね、でも[[ソースコード]]の記述量が増えた分で相殺されて無意味ではないか、などと言われてきた。このように初登場のしかたが悪かったために不遇な扱いを受けてきた[[MVVM]]であるが、[[XamarinOpenGL ES 2.iOS0]]」であるため[[Xamarin.AndroidGeometry Instancing]]などの登場でやっとマルチプラットフォームという利点を活かせる土壌が整い、様々なMVVMフレームワークが登場している。その中のひとつがMvvmCrossである。のようなジオメトリシェーダーを使った技術も使えないのでDrawコールを極力軽くする努力が求められる。 
==MVVMおさらい=====モデル===いわゆる[[ビジネスロジック]]と呼ばれるものを記述する層である。[[設計]]が破綻しているプロジェクトでは単なる[[データベース]]の定義となっている事が多いが、本来であれば机上の空論的に本質的な部分はすべてここに記載され、本質的な[[デバッグ]]はここだけで完結する。追記:小手先の最適化より自前Modelクラスを実装してメッシュ結合できるようにした方が速そう。なお純正のModelクラスはsealed指定されているので継承できない。
今では[[スタンドアローン]]などという考え方は死滅した御時世であり、[[クラウド]]や[[オンプレミス]]を問わずモデル層の99%は[[サーバーサイド]]で実装され、[[<source> using System; using System.NET Framework]]であれば[[WCF]]や[[ASPCollections.NET Web API]]などの領域であると言える。[[スマホ]]の[[アプリ]]などの極小規模なものであれば[[SQLite]]などを用いてローカルにモデル層を保持することもある。Generic;
===ビューモデル=== using Microsoft.Xna.Framework;ビューモデルとは仮想化されたビューである。架空のビューを作り各種操作が行われたときの動作を記述する。[[GUI]]などの要素がない架空のものであるため、[[マウスカーソル]]やボタンを座標などを考える必要がなく「ボタンを押した際の動作」などの[[デバッグ]]が簡単に行える。 using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input;
public class Model3D { public static Dictionary<string, Model> ModelsCache ===ビュー===ビューとはビューモデルに装飾して実際の[[UI]]を貼付ける部分をいう。new Dictionary<string, Model>();
===コントローラー===あまり考える必要はない。 public Game Game;
==使い方=====Mac=== public Model Model;
==関連項目== public Matrix[] Bones;
==参考文献== /// <summary>{{reflist}} /// 回転(単位:degree) /// </summary> public Vector3 Rotation;
/// <summary> /// 位置 /// </summary> public Vector3 Position;  public Model3D(Game game, string modelName) { // game this.Game = game;  // model if (!ModelsCache.ContainsKey(modelName)) {stub var model = game.Content.Load<Model>(modelName); ModelsCache.Add(modelName, model); } this.Model = ModelsCache[modelName];  // boneを抽出しておく。 this.Bones = new Matrix[this.Model.Bones.Count]; this.Model.CopyAbsoluteBoneTransformsTo(this.Bones);  // BasicEffectの基本設定をDrawメソッドの中で毎回やるのは非常に無駄なので事前に設定しておく。 // Androidでは実質的にGeometry Instancingの様な技法が使えないのでDrawコールの軽量化は重要になる。 // (ジオメトリシェーダーに対応したOpenGL ES 3.2対応端末が広く普及するのは10年後だろう) // これだけでもショボいAndroid(F-04G)では300モデルでフレームレートが20%くらい違ってくる。 foreach (var mesh in this.Model.Meshes) { foreach (BasicEffect effect in mesh.Effects) { effect.EnableDefaultLighting(); effect.LightingEnabled = true; effect.PreferPerPixelLighting = true; } } } // Camera引数は「MonoGameのカメラを作る」を参照 public void Draw(Camera camera) { var meshes = this.Model.Meshes; var bones = this.Bones;  // 回転をMatrixに変換 var yaw = MathHelper.ToRadians(this.Rotation.Y); var pitch = MathHelper.ToRadians(this.Rotation.X); var roll = MathHelper.ToRadians(this.Rotation.Z); var rotation = Matrix.CreateFromYawPitchRoll(yaw, pitch, roll);  // 位置をMatrixに変換 var postion = Matrix.CreateTranslation(this.Position);  // この手の定番計算はCameraクラスを作っておくと捗る。 var view = camera.View; var projection = camera.Projection; foreach (var mesh in meshes) { // 一般的な四則演算と異なり、行列の乗算除算は順番が重要。 // そのため「rotation」と「position」を入れ替えると残念な結果になる。 var world = bones[mesh.ParentBone.Index] * rotation * postion;  foreach (BasicEffect effect in mesh.Effects) { effect.World = world; effect.View = view; effect.Projection = projection; } mesh.Draw(); } } }</source> == 関連項目 ==* [[MonoGameのカメラを作る]] * [[Geometry Instancing]]* [[MonoGameで使う3DモデルをFusion360で作成する]]* [[MacOS版のMonoGameのPipeline.appで3Dモデルをビルドできない]]* [[MonoGameで外部のXNBファイルを読み込む]] [[category: MonoGame]]
匿名利用者

案内メニュー