Contenu connexe Similaire à UnityによるHoloLensアプリケーション入門 (20) Plus de Yuichi Ishii (15) UnityによるHoloLensアプリケーション入門4. 使用しているソフトウェアについて
ソフトウェア名 バージョン
Unity Unity 2017.2.1.p1(MRTK対応バージョン)
PC Windows 10 Fall Creators Update必須
Visual Studio 2017
MixedRealityToolkit‐Unity 2017.2.1.3 Hot Fix
https://github.com/Microsoft/MixedRealityToolkit‐Unity/releases
(C) 2018 石井 勇一 4
61. Gaze関連イベント処理
プログラム例
(C) 2018 石井 勇一 61
using UnityEngine;
using HoloToolkit.Unity.InputModule;
// IFocusableインタフェースを実装することで、注視された時とはずれたときにそれぞれメソッドが呼び出される
public class GreetingUnitychan : MonoBehaviour, IFocusable {
private Animator anim;
void Start()
{
anim = GetComponent<Animator>();
}
// フォーカス(注視)し始めたとき時
public void OnFocusEnter()
{
anim.SetTrigger("Greeting");
}
// フォーカス(注視)が外れた
public void OnFocusExit()
{
// 今回は特に実装無し
}
}
67. IManipulationHandlerインタフェース
インタフェース
(C) 2018 石井 勇一 67
public interface IManipulationHandler : IEventSystemHandler
{
void OnManipulationStarted(ManipulationEventData eventData);
void OnManipulationUpdated(ManipulationEventData eventData);
void OnManipulationCompleted(ManipulationEventData eventData);
void OnManipulationCanceled(ManipulationEventData eventData);
}
68. INavigationHandlerインタフェース
インタフェース
(C) 2018 石井 勇一 68
public interface INavigationHandler : IEventSystemHandler
{
void OnNavigationStarted(NavigationEventData eventData);
void OnNavigationUpdated(NavigationEventData eventData);
void OnNavigationCompleted(NavigationEventData eventData);
void OnNavigationCanceled(NavigationEventData eventData);
}
69. 実装例
AirTapによって自分自身を消す
(C) 2018 石井 勇一 69
using HoloToolkit.Unity.InputModule;
using UnityEngine;
// IInputClickHandlerを実装することで、注視&クリック(AirTap)時に呼び出されるメソッドが呼び出される
public class HideCube : MonoBehaviour, IInputClickHandler {
// 注視&クリック(AirTap)されると呼び出される
public void OnInputClicked(InputClickedEventData eventData)
{
// 自分自身の削除
Destroy(gameObject);
}
}
70. 何も無い所をAirTapした時のイベントを
取得するには
InputManager.Instance.AddGlobalListener()に登録する
(C) 2018 石井 勇一 70
using HoloToolkit.Unity.InputModule;
using UnityEngine;
public class NothingSpaceClickHandler : MonoBehaviour, IInputClickHandler {
void Start () {
// 全てのジェスチャーイベントをキャッチできるようにする
InputManager.Instance.AddGlobalListener(gameObject);
}
/// AirTapイベントのハンドラ
public void OnInputClicked(InputClickedEventData eventData) {
// 何もGazeしていないときだけ動作する
if (!GazeManager.Instance.HitObject) {
// ログを吐くだけ
Debug.Log("Click on nothing point !!!!");
}
}
}
参考: http://blog.d‐yama7.com/archives/699
122. InteractionReceiverでオーバーライド可
能メソッド
(C) 2018 石井 勇一 122
#region Protected Virtual Callback Functions
protected virtual void FocusEnter(GameObject obj, PointerSpecificEventData eventData) { }
protected virtual void FocusExit(GameObject obj, PointerSpecificEventData eventData) { }
protected virtual void InputDown(GameObject obj, InputEventData eventData) { }
protected virtual void InputUp(GameObject obj, InputEventData eventData) { }
protected virtual void InputClicked(GameObject obj, InputClickedEventData eventData) { }
protected virtual void HoldStarted(GameObject obj, HoldEventData eventData) { }
protected virtual void HoldCompleted(GameObject obj, HoldEventData eventData) { }
protected virtual void HoldCanceled(GameObject obj, HoldEventData eventData) { }
protected virtual void ManipulationStarted(GameObject obj, ManipulationEventData eventData) { }
protected virtual void ManipulationUpdated(GameObject obj, ManipulationEventData eventData) { }
protected virtual void ManipulationCompleted(GameObject obj, ManipulationEventData eventData) { }
protected virtual void ManipulationCanceled(GameObject obj, ManipulationEventData eventData) { }
protected virtual void NavigationStarted(GameObject obj, NavigationEventData eventData) { }
protected virtual void NavigationUpdated(GameObject obj, NavigationEventData eventData) { }
protected virtual void NavigationCompleted(GameObject obj, NavigationEventData eventData) { }
protected virtual void NavigationCanceled(GameObject obj, NavigationEventData eventData) { }
#endregion
123. ButtonReceiverExampleのコード
(C) 2018 石井 勇一 123
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
using HoloToolkit.Unity;
using System.Collections.Generic;
using UnityEngine;
using HoloToolkit.Unity.Receivers;
using HoloToolkit.Unity.InputModule;
namespace HoloToolkit.Unity.Examples
{
public class ButtonReceiverExample : InteractionReceiver
{
public GameObject textObjectState;
private TextMesh txt;
void Start()
{
txt = textObjectState.GetComponentInChildren<TextMesh>();
}
124. ButtonReceiverExampleのコード
(C) 2018 石井 勇一 124
protected override void FocusEnter(GameObject obj, PointerSpecificEventData eventData) {
Debug.Log(obj.name + " : FocusEnter");
txt.text = obj.name + " : FocusEnter";
}
protected override void FocusExit(GameObject obj, PointerSpecificEventData eventData) {
Debug.Log(obj.name + " : FocusExit");
txt.text = obj.name + " : FocusExit";
}
protected override void InputDown(GameObject obj, InputEventData eventData) {
Debug.Log(obj.name + " : InputDown");
txt.text = obj.name + " : InputDown";
}
protected override void InputUp(GameObject obj, InputEventData eventData) {
Debug.Log(obj.name + " : InputUp");
txt.text = obj.name + " : InputUp";
}
}
}
141. Spatial Understandingの設定
Spatial Understanding Custom Meshコンポー
ネント
◦ Import Mesh Period
◦ スキャンフェーズ中に、メッシュをインポートする間隔を秒
単位で指定します。 0の値は、DLLからメッシュのインポート
を行いません。
◦ Mesh Material
◦ DLLによって生成されたカスタムメッシュをレンダリングする
ために使用されるマテリアル。
◦ Max Frame Time
◦ メッシュの処理に費やすフレームあたりの最大時間(ミリ
秒)。処理が1フレームに割り当てられている時間を超過し
ないようにするために使用されます。
◦ Create Mesh Colliders
◦ Meshコライダーを生成するかどうか。
(C) 2018 石井 勇一 141
142. サンプルプログラムの流れ
AppState.csのStartメソッド(以下、すべてAppState.cs内のメソッド)
(C) 2018 石井 勇一 142
namespace HoloToolkit.Examples.SpatialUnderstandingFeatureOverview
{
public class AppState : Singleton<AppState>, ISourceStateHandler, IInputClickHandler
{
private void Start()
{
// Default the scene & the HoloToolkit objects to the camera
Vector3 sceneOrigin = CameraCache.Main.transform.position;
Parent_Scene.transform.position = sceneOrigin;
MappingObserver.SetObserverOrigin(sceneOrigin);
InputManager.Instance.AddGlobalListener(gameObject);
var keywordsToActions = new Dictionary<string, Action>
{
{ "Toggle Scanned Mesh", ToggleScannedMesh },
{ "Toggle Processed Mesh", ToggleProcessedMesh },
};
keywordRecognizer = new KeywordRecognizer(keywordsToActions.Keys.ToArray());
keywordRecognizer.OnPhraseRecognized += args => keywordsToActions[args.text].Invoke();
keywordRecognizer.Start();
}
音声入力
どこでも
ハンドジェスチャー
入力
144. ハンドジェスチャー入力
ISourceStateHandler(手の検出), IInputClickHandler(AirTapの検出)
(C) 2018 石井 勇一 144
public void OnSourceDetected(SourceStateEventData eventData) {
// If the source has positional info and there is currently no visible source
if (eventData.InputSource.SupportsInputInfo(eventData.SourceId, SupportedInputInfo.Position))
{
trackedHandsCount++;
}
}
public void OnSourceLost(SourceStateEventData eventData) {
if (eventData.InputSource.SupportsInputInfo(eventData.SourceId, SupportedInputInfo.Position))
{
trackedHandsCount--;
}
}
public void OnInputClicked(InputClickedEventData eventData) {
if ((SpatialUnderstanding.Instance.ScanState == SpatialUnderstanding.ScanStates.Scanning) &&
!SpatialUnderstanding.Instance.ScanStatsReportStillWorking)
{
SpatialUnderstanding.Instance.RequestFinishScan();
}
}
指を検出したタイミングで
メッセージの色を変えるた
めにカウントを記録
十分なデータがえらたタイ
ミングで、AirTapで終了依
頼を発行するために使用
145. 音声入力
Spatial MappingのVisual MeshとSpatial UnderstandingのCustomMeshをそれぞれOn/Offする
実はキーボード入力でも最終的にここが呼ばれるようにプログラムされている(後述)
(C) 2018 石井 勇一 145
private static void ToggleScannedMesh()
{
SpatialMappingManager.Instance.DrawVisualMeshes = !SpatialMappingManager.Instance.DrawVisualMeshes;
Debug.Log("SpatialUnderstanding -> SpatialMappingManager.Instance.DrawVisualMeshes=" +
SpatialMappingManager.Instance.DrawVisualMeshes);
}
private static void ToggleProcessedMesh()
{
SpatialUnderstanding.Instance.UnderstandingCustomMesh.DrawProcessedMesh =
!SpatialUnderstanding.Instance.UnderstandingCustomMesh.DrawProcessedMesh;
Debug.Log("SpatialUnderstanding -> SpatialUnderstanding.Instance.UnderstandingCustomMesh.DrawProcessedMesh=" +
SpatialUnderstanding.Instance.UnderstandingCustomMesh.DrawProcessedMesh);
}
152. PrimaryTextプロパティの処理
ScanStateに合わせてメインメッセージを変更(続き)
(C) 2018 石井 勇一 152
// Scan state
if (SpatialUnderstanding.Instance.AllowSpatialUnderstanding){
switch (SpatialUnderstanding.Instance.ScanState) {
case SpatialUnderstanding.ScanStates.Scanning: //スキャン中
// Get the scan stats
IntPtr statsPtr = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticPlayspaceStatsPtr();
if (SpatialUnderstandingDll.Imports.QueryPlayspaceStats(statsPtr) == 0){
return "playspace stats query failed";
}
// 終了させても良さそうかどうか調べる(これも複雑なコードが付いているプロパティ)
if (DoesScanMeetMinBarForCompletion) {
return "When ready, air tap to finalize your playspace"; // AirTapで終了するというメッセージを表示
}
return "Walk around and scan in your playspace"; // まだ不十分なので歩き回ってスキャンしなさいと表示
:
:
153. PrimaryTextプロパティの処理
ScanStateに合わせてメインメッセージを変更(続き)
(C) 2018 石井 勇一 153
case SpatialUnderstanding.ScanStates.Finishing: // 終了処理中
return "Finalizing scan (please wait)";
case SpatialUnderstanding.ScanStates.Done: // 終了
return "Scan complete - Use the menu to run queries";
default:
return "ScanState = " + SpatialUnderstanding.Instance.ScanState.ToString();
}
}
return "";
}
154. PrimaryColorプロパティの処理
◦ ステータスに合わせてメッセージの色を変更。
(C) 2018 石井 勇一 154
public Color PrimaryColor {
get {
if (SpatialUnderstanding.Instance.ScanState == SpatialUnderstanding.ScanStates.Scanning){
if (trackedHandsCount > 0) {
return DoesScanMeetMinBarForCompletion ? Color.green : Color.red;
}
return DoesScanMeetMinBarForCompletion ? Color.yellow : Color.white;
}
// メニューを見ているときはそれを消す(実際には透明度15%にする)
Vector3 hitPos, hitNormal;
UnityEngine.UI.Button hitButton;
float alpha = AppCursor.RayCastUI(out hitPos, out hitNormal, out hitButton) ? 0.15f : 1.0f;
// 特殊ケース処理 &
return (!string.IsNullOrEmpty(SpaceQueryDescription) || !string.IsNullOrEmpty(ObjectPlacementDescription)) ?
(PrimaryText.Contains("processing") ? new Color(1.0f, 0.0f, 0.0f, 1.0f) : new Color(1.0f, 0.7f, 0.1f, alpha)) :
new Color(1.0f, 1.0f, 1.0f, alpha);
}
}
155. DetailsTextプロパティの処理
◦ 検索結果のサマリー
(C) 2018 石井 勇一 155
public string DetailsText {
get {
if (SpatialUnderstanding.Instance.ScanState == SpatialUnderstanding.ScanStates.None)
{
return "";
}
// スキャン統計は2番目に優先されます
if ((SpatialUnderstanding.Instance.ScanState == SpatialUnderstanding.ScanStates.Scanning) &&
(SpatialUnderstanding.Instance.AllowSpatialUnderstanding))
{
// 統計情報が取得できていない場合は取得に失敗という文字列を返す
IntPtr statsPtr = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticPlayspaceStatsPtr();
if (SpatialUnderstandingDll.Imports.QueryPlayspaceStats(statsPtr) == 0)
{
return "Playspace stats query failed";
}
:
:
156. PrimaryColorプロパティの処理
◦ ステータスに合わせてメッセージの色を変更。
(C) 2018 石井 勇一 156
SpatialUnderstandingDll.Imports.PlayspaceStats stats =
SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticPlayspaceStats();
// 統計情報がゼロでなければ統計情報の表示を開始する
if (stats.TotalSurfaceArea > kMinAreaForStats) {
string subDisplayText = string.Format("totalArea={0:0.0}, horiz={1:0.0}, wall={2:0.0}",
stats.TotalSurfaceArea, stats.HorizSurfaceArea, stats.WallSurfaceArea);
subDisplayText += string.Format("¥nnumFloorCells={0}, numCeilingCells={1}, numPlatformCells={2}",
stats.NumFloor, stats.NumCeiling, stats.NumPlatform);
subDisplayText += string.Format("¥npaintMode={0}, seenCells={1}, notSeen={2}",
stats.CellCount_IsPaintMode,
stats.CellCount_IsSeenQualtiy_Seen + stats.CellCount_IsSeenQualtiy_Good,
stats.CellCount_IsSeenQualtiy_None);
return subDisplayText;
}
return "";
}
return "";
}
PlayspaceStatsクラスの定義は次
のスライドを参照
157. (C) 2018 石井 勇一 157
namespace HoloToolkit.Unity
{
public class SpatialUnderstandingDll {
public class PlayspaceStats {
public int IsWorkingOnStats; // 0 まだ統計を作成している場合
public float HorizSurfaceArea; // In m2 : 床から-0.15~1mの間にある上向きの全ての水平面
public float TotalSurfaceArea; // In m2 : すべて
public float UpSurfaceArea; // In m2 : 床を含むすべての上向きな水平面
public float DownSurfaceArea; // In m2 : 天井を含むすべて下向きの水平面
public float WallSurfaceArea; // In m2 : 壁だけでない、すべての垂直面
public float VirtualCeilingSurfaceArea; // In m2 : 実質的な天井面の推定数
public float VirtualWallSurfaceArea; // In m2 : 実質的な壁の推定数
public int NumFloor; // 各フロアのリスト数(カウントを含む)
public int NumCeiling; // 各天井のリスト数(カウントを含む)
public int NumWall_XNeg; // 各壁においてX軸マイナス方向を向いている数(カウントを含む)
public int NumWall_XPos; // 各壁においてX軸プラス方向を向いている数(カウントを含む)
public int NumWall_ZNeg; // 各壁においてZ軸マイナス方向を向いている数(カウントを含む)
public int NumWall_ZPos; // 各壁においてZ軸プラス方向を向いている数(カウントを含む)
public int NumPlatform; // 床を含まない水平面の数 (例えばテーブルや椅子など)(カウントを含む)
public int CellCount_IsPaintMode; // ペイントセル数(ペイント数で面積が推測できる)=> 1セルにつき8cm×8cm
public int CellCount_IsSeenQualtiy_None; // 見えないセルの数 => 1セルにつき8cm×8cm
public int CellCount_IsSeenQualtiy_Seen; // 見えるセルの数=> 1セルにつき8cm×8cm
public int CellCount_IsSeenQualtiy_Good; // 良質な見えるセルの数 => 1セルにつき8cm×8cm
};
}
}
158. DoesScanMeetMinBarForCompletionプ
ロパティ
スキャン完了とするための必要最小限度を満たしているかどうかを判定して結果を返す
(C) 2018 石井 勇一 158
public bool DoesScanMeetMinBarForCompletion {
get {
// 実際にスキャンしているか?
if ((SpatialUnderstanding.Instance.ScanState != SpatialUnderstanding.ScanStates.Scanning) ||
(!SpatialUnderstanding.Instance.AllowSpatialUnderstanding))
{
return false;
}
// 現在の統計情報を調べる
IntPtr statsPtr = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticPlayspaceStatsPtr();
if (SpatialUnderstandingDll.Imports.QueryPlayspaceStats(statsPtr) == 0)
{
return false;
}
:
:
160. 統計情報の利用
UI.csのSetupMenus()
(C) 2018 石井 勇一 160
private void SetupMenus()
{
// Topology queries
ButtonPanels[(int)Panels.Topology].Button.GetComponentInChildren<Text>().text = "Topology Queries";
ButtonPanels[(int)Panels.Topology].Button.onClick.AddListener(() => { SetActiveTab(Panels.Topology); });
AddButton("Position on wall", Panels.Topology, () => {
SpaceVisualizer.Instance.Query_Topology_FindPositionOnWall();
timeLastQuery = DateTime.MinValue;
});
AddButton("Large positions on wall", Panels.Topology, () => {
SpaceVisualizer.Instance.Query_Topology_FindLargePositionsOnWalls();
timeLastQuery = DateTime.MinValue;
});
AddButton("Largest wall", Panels.Topology, () => {
SpaceVisualizer.Instance.Query_Topology_FindLargeWall();
timeLastQuery = DateTime.MinValue;
});
:
:
161. 統計情報の利用
UI.csのSetupMenus()
(C) 2018 石井 勇一 161
private void SetupMenus()
{
// Topology queries
ButtonPanels[(int)Panels.Topology].Button.GetComponentInChildren<Text>().text = "Topology Queries";
ButtonPanels[(int)Panels.Topology].Button.onClick.AddListener(() => { SetActiveTab(Panels.Topology); });
AddButton("Position on wall", Panels.Topology, () => {
SpaceVisualizer.Instance.Query_Topology_FindPositionOnWall();
timeLastQuery = DateTime.MinValue;
});
AddButton("Large positions on wall", Panels.Topology, () => {
SpaceVisualizer.Instance.Query_Topology_FindLargePositionsOnWalls();
timeLastQuery = DateTime.MinValue;
});
AddButton("Largest wall", Panels.Topology, () => {
SpaceVisualizer.Instance.Query_Topology_FindLargeWall();
timeLastQuery = DateTime.MinValue;
});
:
:
162. 統計情報の利用
UI.csのSetupMenus()
(C) 2018 石井 勇一 162
// Shape queries
ButtonPanels[(int)Panels.Shapes].Button.GetComponentInChildren<Text>().text = "Shape Queries";
ButtonPanels[(int)Panels.Shapes].Button.onClick.AddListener(() => { SetActiveTab(Panels.Shapes); });
ReadOnlyCollection<string> customShapes = ShapeDefinition.Instance.CustomShapeDefinitions;
for (int i = 0; i < customShapes.Count; ++i)
{
string shapeName = customShapes[i];
AddButton(shapeName, Panels.Shapes, () =>
{
SpaceVisualizer.Instance.Query_Shape_FindShapeHalfDims(shapeName);
timeLastQuery = DateTime.MinValue;
});
}
:
:
163. 統計情報の利用
UI.csのSetupMenus()
(C) 2018 石井 勇一 163
// Level solver
ButtonPanels[(int)Panels.LevelSolver].Button.GetComponentInChildren<Text>().text = "Object Placement";
ButtonPanels[(int)Panels.LevelSolver].Button.onClick.AddListener(() => {
SetActiveTab(Panels.LevelSolver);
timeLastQuery = DateTime.MinValue;
});
AddButton("On Floor", Panels.LevelSolver, () => {
LevelSolver.Instance.Query_OnFloor();
timeLastQuery = DateTime.MinValue;
});
AddButton("On Wall", Panels.LevelSolver, () => {
LevelSolver.Instance.Query_OnWall();
timeLastQuery = DateTime.MinValue;
});
:
:
164. 統計情報の利用
UI.csのSetupMenus()
(C) 2018 石井 勇一 164
public void Query_Topology_FindPositionOnWall() {
ClearGeometry(); // 既に表示しているワイヤーフレームを消す(2回目を想定)
// Spatial Undedrstandingが有効でなければ何もしない
if (!SpatialUnderstanding.Instance.AllowSpatialUnderstanding) {
return;
}
// セットアップ
float minHeightOfWallSpace = 0.5f; // 壁とみなす最小の高さ(単位メートル)
float minWidthOfWallSpace = 0.75f; // 壁とみなす最小の幅(単位メートル)
float minHeightAboveFloor = 1.25f; // 壁とみなす床からの高さ(単位メートル)
float minFacingClearance = 1.5f; // 壁の前に求める最小の空き領域(単位メートル)
// 問い合わせ
IntPtr resultsTopologyPtr = SpatialUnderstanding.Instance.UnderstandingDLL.PinObject(resultsTopology);
int locationCount = SpatialUnderstandingDllTopology.QueryTopology_FindPositionsOnWalls(
minHeightOfWallSpace, minWidthOfWallSpace, minHeightAboveFloor, minFacingClearance,
resultsTopology.Length, resultsTopologyPtr);
// 出力
HandleResults_Topology("Find Position On Wall", locationCount, new Vector3(minWidthOfWallSpace, minHeightOfWallSpace, 0.025f), Color.blue);
}
165. 統計情報の利用
SpatialUnderstandingDllTopology.csのQueryTopology_FindPositionsOnWalls ()
(C) 2018 石井 勇一 165
/// <summary>
///パラメータで指定された基準を満たす壁のスペースを検索します。
/// </summary>
/// <param name="minHeightOfWallSpace">クエリによって検出されるスペースの最小高さ。</param>
/// <param name="minWidthOfWallSpace">クエリによって検出されるスペースの最小幅。</param>
/// <param name="minHeightAboveFloor">そのスペースの下端と床の上との最小距離。</param>
/// <param name="minFacingClearance">そのスペースの前方のゆとり空間の最小距離。</param>
/// <param name="locationCount">locationDataでユーザーが指定したロケーション結果の数。</param>
/// <param name="locationData">クエリによって検出されたスペースで満たされるTopologyResultのロケーション結果配列。</param>
/// <returns>クエリによって検出されたスペースの数。 この値は、呼び出し元によって提供された結果の数によって制限されます(locationCount)</returns>
// Queries (topology)
[DllImport("SpatialUnderstanding", CallingConvention = CallingConvention.Cdecl)]
public static extern int QueryTopology_FindPositionsOnWalls(
[In] float minHeightOfWallSpace,
[In] float minWidthOfWallSpace,
[In] float minHeightAboveFloor,
[In] float minFacingClearance,
[In] int locationCount, // locationDataに割り当てられた領域を渡します。
[In, Out] IntPtr locationData); // TopologyResult
166. 統計情報の利用
ShapeDefinition.csのCreateCustomShapeDefinitions()にて、想定される形のデータを登録し、
統計情報から登録された形データを元に検索ができる。
「椅子」の定義例
(C) 2018 石井 勇一 166
// Chair
shapeComponents = new List<SpatialUnderstandingDllShapes.ShapeComponent>()
{
new SpatialUnderstandingDllShapes.ShapeComponent(
new List<SpatialUnderstandingDllShapes.ShapeComponentConstraint>()
{
SpatialUnderstandingDllShapes.ShapeComponentConstraint.Create_SurfaceHeight_Between(0.25f, 0.6f),
SpatialUnderstandingDllShapes.ShapeComponentConstraint.Create_SurfaceCount_Min(1),
SpatialUnderstandingDllShapes.ShapeComponentConstraint.Create_SurfaceArea_Min(0.035f),
SpatialUnderstandingDllShapes.ShapeComponentConstraint.Create_IsRectangle(),
SpatialUnderstandingDllShapes.ShapeComponentConstraint.Create_RectangleLength_Between(0.1f, 0.5f),
SpatialUnderstandingDllShapes.ShapeComponentConstraint.Create_RectangleWidth_Between(0.1f, 0.4f),
SpatialUnderstandingDllShapes.ShapeComponentConstraint.Create_SurfaceNotPartOfShape("Couch"),
}),
};
AddShape("Chair", shapeComponents);
167. 最小限度の設定の例
ZuQ9‐>Nn To 辛周(ズキューンとからまわり)さんのブログ
◦ HoloLens開発 SpatialUnderstanding事始め 空間検知と空間内の情報(天井、床、壁)の判定まで
◦ http://zuq9nn.blogspot.jp/2017/06/hololens‐spatialunderstanding.html
◦ HoloLensの開発 SpatialUnderstandingDllTopologyで壁にオブジェクト配置してみる
◦ http://zuq9nn.blogspot.jp/2017/09/hololensspatialunderstandingdlltopology.html
(C) 2018 石井 勇一 167
195. お問い合わせ
株式会社シーディングソフテック 石井 勇一
◦ E‐mail: yuichi.ishii@seedingsoftech.jp
◦ Home Page: http://seedingsoftech.jp/
個人的なお問い合わせ
◦ Twitter: @z_zabaglione
◦ Home Page: http://zabaglione.info/
本資料をシーディングソフテックの書面による事前許可なく本資料を複製、再製、改変、発表、アッ
プロード、掲示、転送、配布することを禁じます。
著者が作成したオリジナルのプログラムコードは個人・商用利用ともに一切の制限もなくロイヤリ
ティフリーでご利用可能です。
画像、音声、3Dモデルデータなどのリソース類、その他のツールやプログラムなどは原著者の利用
許諾に従ってご利用ください。
(C) 2018 石井 勇一 195