こんにちは、読者の皆様。
今日は、Swarp SDKを使用してアプリケーションを作成する方法の話を続けます。 この投稿では、Swarp SDKのレビューを続けています 。 最初の部分では、標準のSwarpパッケージの例と、それを使用するための一般的な原則を見ました。 次に、カメラの前のマーカーの存在に応じて3Dモデルのアニメーションを変更するARアプリケーションを作成します。 誰が気にする-私は猫をお願いします。
アプリについて
したがって、ここに私たちのプロジェクトの基本的な要件があります。
アプリケーションは、忍者の標準的なMogreの3Dモデルを使用します(すべてのモデルとソースコードは、投稿の付録にあります)。 カメラの視野に特定のマーカーがある場合、適切な向きでモデルを表示する必要があります。 そして今、楽しい部分はアニメーションです。 忍者モデルには16のアニメーションがあります(私の記憶が私に役立っている場合)。 そのうち3つを選択しました: Crouch 、 Attack1 、 Backflip 。 これらの各アニメーションにマーカーが添付されます。 アニメーションマーカーがシーン上にない場合、対応するアニメーションを実行する必要があります。 すべてのマーカーが存在する場合、 Idle1アニメーションが実行されます。 実装を取得します。
実装
Visual Studio 2010を使用してプロジェクトを作成し、まずWin32コンソールアプリケーションを作成してHabrDemo2と呼びます。 ところで、アプリケーションのデバッグ中にスタジオが停止しないようにするには、[デバッグ]タブと[ビルド]タブでアンマネージコードのデバッグを有効にし、安全でないコードを有効にする必要があります。
プロジェクトには、アプリケーションへのエントリポイントを含むProgram.csファイルがあります。
実際、彼と一緒に仕事をします。
次に、リンクを使用済みアセンブリに接続する必要があります。 次のものが必要です。
小さな機能: Swarp SDKは、アセンブリを追加する.NETタブにアセンブリを追加して、開発者の時間を節約します。
本当に便利-インストールされたSDKを探してフォルダーを登る必要はありません。
これで準備が終わりました-プログラムを書き始めます。
コードを書く
フィールド
いくつかのプライベートフィールドが必要です。
/// <summary> /// . /// </summary> private static AugmentedRealityManager _arManager; /// <summary> /// . /// </summary> private static ITrackable _ninjaTrackable; /// <summary> /// . /// </summary> private static List<ITrackable> _animationTrackables=new List<ITrackable>(); /// <summary> /// C . /// </summary> private static AnimationState _animationState; /// <summary> /// C . /// </summary> private static float _animTime = 0.1f;
_arManagerフィールドは、拡張現実プロセスを実装するSwarpコアクラスのインスタンスです。 Start()およびStop()メソッドを呼び出すことにより、プロセスを開始または停止します。 ITrackableインターフェイスは、 Swarpで使用されるトークンを記述します。 _ninjaTrackableインスタンスを使用して、3Dモデルの表示を担当するマーカーと、アニメーションマーカーに関する情報を格納する_animationTrackablesリストを記述します。 _animationStateフィールドも使用します。 モデルのアニメーションを記述するために必要です。 AnimationStateクラスは、Mogreアセンブリで説明されています。 さて、最後のフィールドは_animTimeです。 これは、アニメーションが各フレームで「シフト」する量を決定する時間の量です。
フィールドが完成しました。 次のステップは初期化です。
アプリケーションの初期化
拡張現実の初期化については、最初の部分で詳しく説明します。ここでは、初期化アルゴリズムとコードの特徴的な場所について簡単に説明します。
初期化アルゴリズム自体は非常に単純で、次の手順で構成されています。
- カメラ
- トラッカー
- レンダラー。
アプリケーションでのカメラの初期化は非常に簡単で、標準のSwarp SDK OgreSimpleSceneExampleの例から取得されます。
// var camera = CameraManager.Instance.GetFirstWorkedCamera(); if (camera == null) { MessageBox.Show(Resources.CameraNotFoundString, Resources.WarningString, MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } // 64048030FPS , var displayParameters = new DisplayParameters(30, new Size(640, 480)); camera.DisplayParameters = camera.IsSupportedDisplayParameters(displayParameters) ? displayParameters : camera.GetSupportedDisplayParameters()[0];
トラッカーには特別な注意が必要です。
ここで、トラッカーを初期化し、使用済みマーカーをロードします。
// , // - 4 var tracker = new SquareMarkerTracker(4); // _ninjaTrackable = new SquareMarker("Ninja Marker", "Trackable\\1.trackable"); var animationAttackTrackable = new SquareMarker("Attack3", "Trackable\\5.trackable"); var animationCrouchTrackable = new SquareMarker("Crouch", "Trackable\\6.trackable"); var animationBackflipTrackable = new SquareMarker("Backflip", "Trackable\\7.trackable"); _animationTrackables.Add(animationCrouchTrackable); _animationTrackables.Add(animationBackflipTrackable); _animationTrackables.Add(animationAttackTrackable); // tracker.TrackableObjects.Add(_ninjaTrackable); tracker.TrackableObjects.AddRange(_animationTrackables);
SquareMarkerコンストラクターは、入力として2つのパラメーター(マーカー名とファイルパス)を受け入れることに注意してください。 実際には、さらに2つのオーバーロードがありますが、今は必要ありません。 各アニメーションマーカーには、関連するアニメーションの名前で名前を付けます。 将来的には、今後、行方不明のマーカーの名前でアニメーションをロードするためにこれを行うと言います。
そして今、レンダラーの初期化:
// , var ogreSimpleSceneForm = new Form { Size = new Size(640, 480), Text = Resources.SwarpSDKExampleString, }; // var renderer = new Ogre3DRenderSystem(ogreSimpleSceneForm.Handle, "OgreConfig\\plugins.cfg", "OgreConfig\\ogre.cfg", "OgreConfig\\ogre.log") { SizeMode = SizeMode.Autosize }; // renderer.LoadResources("OgreConfig\\resources.cfg"); // . . var ninjaScene = new Ogre3DScene(renderer.Root, "Ninja Scene"); renderer.Scenes.Add(ninjaScene); LoadScene(ninjaScene.SceneManager);
すべてがはっきりしているように見えますが、最後にはLoadScene()メソッドが潜んでいます。 彼のタスクは、モデルをロードし、シーンに追加し、テクスチャをプルし、 アイドルアニメーションを開始することです。
private static void LoadScene(SceneManager sceneManager) { // , . var ninjaNode = sceneManager.RootSceneNode.CreateChildSceneNode("NinjaNode"); // ( ). var ninjaEntity = sceneManager.CreateEntity("Ninja", "ninja.mesh"); _animationState = ninjaEntity.GetAnimationState("Idle1"); _animationState.Loop = true; _animationState.Enabled = true; // MaterialPtr material = MaterialManager.Singleton.Create("NinjaMaterial", ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME); material.GetTechnique(0).GetPass(0).CreateTextureUnitState("nskingr.jpg"); material.GetTechnique(0).GetPass(0).SetSceneBlending(SceneBlendType.SBT_TRANSPARENT_ALPHA); material.GetTechnique(0).GetPass(0).DepthCheckEnabled = true; material.GetTechnique(0).GetPass(0).DepthWriteEnabled = true; material.GetTechnique(0).GetPass(0).LightingEnabled = false; ninjaEntity.SetMaterial(material); // 3 , ninjaNode.Scale(3f,3f,3f); ninjaNode.AttachObject(ninjaEntity); ninjaNode.SetVisible(true); }
これですべてが初期化されました。
プログラムのメインサイクル
カメラを起動し、拡張現実マネージャーを起動して、プロセスを楽しんでください。 疑問が生じます-「どのように?」 最初の記事を注意深く読んだ人はおそらく答えをすでに知っているでしょう: _arManagerフィールドとカメラ変数があるのは理由がないわけではありません。
// . _arManager = new AugmentedRealityManager(camera, tracker, renderer); // . camera.Start(); // . _arManager.Start(); ogreSimpleSceneForm.Show(); while (ogreSimpleSceneForm.Created) { // , UpdateScenes(ninjaScene.SceneManager); // . // , , // . _arManager.Renderer.RenderFrame(); // . Application.DoEvents(); } // . _arManager.Dispose(); renderer.Dispose(); camera.Dispose();
コードのこのセクションでは、マーカーが検出され、対応するアニメーションがアクティブになり、レンダリングフォームが存在する間にフレームが描画されます。 問題もないようです。 プログラムの「中心」であるUpdateScenesメソッドに渡します。
ここでも複雑なことはありません。 主なアイデアは、各呼び出しでトラッカーから見つかったマーカーのリストを受け取り、このリストに基づいて対応するアニメーションを開始することです。 実際、これは以下のコードで実装されています。
private static void UpdateScenes(SceneManager ninjaSceneManager) { foreach (var tracker in _arManager.Trackers) { // , // , . var foundTrackableObjects = new List<ITrackable>(tracker.LastDetectedObjects); // . foreach (var scene in _arManager.Renderer.Scenes) { // , . if (foundTrackableObjects.Contains(_ninjaTrackable)) { // , . scene.Visible = true; // . var trackablePose = tracker.GetPose(_ninjaTrackable); // . scene.OrientScene(trackablePose); // ( =)) var ninjaEntity = ninjaSceneManager.GetEntity("Ninja"); // var newAnimationState = ninjaEntity.GetAnimationState(SelectAnimation(foundTrackableObjects, _animationTrackables)); // , if (newAnimationState.AnimationName != _animationState.AnimationName) { _animationState.Enabled = false; _animationState = newAnimationState; _animationState.Loop = true; _animationState.Enabled = true; } // , _animationState.AddTime(_animTime); } else { scene.Visible = false; } } } } private static string SelectAnimation(ICollection<ITrackable> found, IEnumerable<ITrackable> target) { foreach (var trackable in target.Where(trackable => !found.Contains(trackable))) { return trackable.Name; } return "Idle1"; }
SelectAnimationメソッドに注意してください 。 見つかったマーカーのリストと登録済みのアニメーションマーカーのリストの2つのパラメーターがあります。 このメソッドは、見つからない最初のアニメーションマーカーの名前を返します。 すべてのアニメーションマーカーが存在する場合、fromは文字列「Idle1」を返します。 このため、マーカーをそれに関連付けられたアニメーションの名前で呼び出しました。
落とし穴:このコードに注意してください:
// var newAnimationState = ninjaEntity.GetAnimationState(SelectAnimation(foundTrackableObjects, _animationTrackables)); // , if (newAnimationState.AnimationName != _animationState.AnimationName) { _animationState.Enabled = false; _animationState = newAnimationState; _animationState.Loop = true; _animationState.Enabled = true; }
アニメーションを変更するときは、前のアニメーションを無効にする必要があります。無効にしないと、正しく機能しません。 私はカントが何であるかを理解しようとして多くの時間を費やしました。
さて、私たちが得たものを見る時が来ましたか?
結果
以下は私が録画したビデオです。 どんなテキストでも私たちがやったことを示すよりも雄弁であるように思えます。
かなり面白い。 ところで、Swarpは、マーカーが部分的に重なっている場合でもマーカーを検出します。
参照資料
ソース: HabrDemo2.rar
開発者サイト: www.sectar.com
SDKダウンロードリンク: Swarp SDK
マネージオーガ : Mogre wiki
UPD :ところで、昨日、Sectarは競争を発表しました。 参加するには、8月31日まで無料のキーを取得できます。受賞者には、6か月と1年間無料の開発ライセンスが与えられます。 詳細: 競争 。