public void OnDrop(object sender, DragEventArgs e) { if (!e.Data.GetDataPresent(DataFormats.FileDrop)) { return; } string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); if (files != null) { foreach (string file in files) { string extension = Path.GetExtension(file)?.ToLower(); //判斷當前的檔案副檔名是否為stl,不是的話則跳過 if (extension != null && !extension.Equals(".stl")) { continue; } BoneModel model = new BoneModel { FilePath = file, MarkerId = "", BoneDiffuseColor = System.Windows.Media.Color.FromArgb(255, 40, 181, 187), Transform = new MatrixTransform3D() }; model.LoadModel(); MultiAngleViewModel.NormalModelCollection.Add(model); } } MultiAngleViewModel.ResetCameraPosition(); }
void StartListening(BoneModel bone) { PuppetReprModel slave = bone.reprs[PuppetModel.key] as PuppetReprModel; // Listen to trigger and collision notifiers for each bone.pheasy (when possible) if (slave.pheasy) { if (slave.pheasy.collisionNotifier) { slave.pheasy.collisionNotifier.invokeStayEvents = true; slave.pheasy.collisionNotifier.onRbEnter.AddListener(col => OnRbTouchStart(col, bone)); slave.pheasy.collisionNotifier.onRbStay.AddListener(col => OnRbTouchStay(col, bone)); slave.pheasy.collisionNotifier.onRbExit.AddListener(col => OnRbTouchEnd(col, bone)); } if (model.hoverDetectionSystem == HoverDetectionSystem.Triggers) { for (int tn = 0; tn < slave.pheasy.triggerNotifiers.Length; tn++) { slave.pheasy.triggerNotifiers[tn].onRbEnter.AddListener(col => OnRbEnter(col, bone)); slave.pheasy.triggerNotifiers[tn].onRbExit.AddListener(col => OnRbExit(col, bone)); } } } }
public void AddAvatar(AvatarController avatar) { this._avatars.Add(avatar); avatar.ControllerStart(); if (applyThisLayerToAvatars != "") { int layer = LayerMask.NameToLayer(applyThisLayerToAvatars); if (layer >= 0) { foreach (BodyModel body in avatar.model.bodies) { BoneModel rootBone = body.root.root; foreach (KeyValuePair <string, ReprModel> entry in rootBone.point.reprs) { BasicHelpers.ApplyLayerRecursively(entry.Value.transformRef, layer); } } } } onAvatarEntered.Invoke(avatar.model.view); }
/// <summary> /// DeleteBoneCommad 的實作內容,刪除Bone模型項目 /// </summary> private void DeleteBoneItem(object o) { ListView boneListView = _mainWindow.BoneListView; if (boneListView.SelectedItem != null) { //選擇的BoneModel BoneModel selectedModelItem = (BoneModel)boneListView.SelectedItem; int temp = boneListView.SelectedIndex; var ballCollection = MainViewModel.ProjData.BoneCollection; ballCollection.Remove(selectedModelItem); //刪減之後數量若跟舊的索引值一樣,代表選項在最後一個 if (ballCollection.Count == temp) { boneListView.SelectedIndex = ballCollection.Count - 1; } else//不是的話則維持原索引值 { boneListView.SelectedIndex = temp; } ListViewItem item = boneListView.ItemContainerGenerator.ContainerFromIndex(boneListView.SelectedIndex) as ListViewItem; item?.Focus(); } }
void OnRbTouchStay(Collision collision, BoneModel bone) { stayedContact = model.contacts.Find(c => c.contactable.pheasy.rb == collision.rigidbody); if (stayedContact == null || stayedContact.contactable == null) { return; } stayedContactable = stayedContact.contactable; if (stayedContactable) { Contact contact = model.contacts.Find(c => c.contactable == stayedContactable); if (contact != null) { BoneCollisionModel boneCollision = contact.bonesTouching.Find(bc => bc.bone == bone); if (boneCollision != null) { collision.GetContacts(boneCollision.points); } } } }
void OnRbEnter(Rigidbody enteredRb, BoneModel bone) { ContactableView contactable = enteredRb.GetComponent <ContactableView>(); if (contactable) { Contact contact = model.contacts.Find(c => c.contactable == contactable); if (contact != null) { // Existing contact if (!contact.bonesEntered.Contains(bone)) { contact.bonesEntered.Add(bone); } } else { // New valid contact contact = AddContact(contactable); contact.type = ContactType.None; contact.bonesEntered.Add(bone); } } }
public static BoneBody AddBone(this ConnectionSlotBody slotBody, BoneModel boneModel) { var slot = slotBody.Model; slot.IsOccupied = true; var slotPos = slotBody.State.Position; var slotSize = slotBody.Model.Size; var centerLoc = Vector2D.FromLengthAndAngle((boneModel.Length + slotSize) * 0.5, slotPos.Angular); var bonePos = new ALVector2D(slotPos.Angular, slotPos.Linear + centerLoc); var rectBody = CreateRectangle(boneModel.Thickness, boneModel.Length, 0.00001, bonePos); var newBone = rectBody.CopyAsBone(slotBody.ModelId); newBone.Model = boneModel; newBone.Parent = slotBody; var joints = slotBody.ConnectWith(newBone, (2 * bonePos.Linear + 8 * slotBody.State.Position.Linear) * 0.1f); Will.Instance.AddBody(newBone); Will.Instance.AddJoint(joints.Item1); Will.Instance.AddJoint(joints.Item2); return(newBone); }
void OnRbTouchStart(Collision collision, BoneModel bone) { ContactableView contactable = collision.rigidbody.GetComponent <ContactableView>(); if (contactable) { Contact contact = model.contacts.Find(c => c.contactable == contactable); BoneCollisionModel boneCollision; if (contact != null) { // Existing contact boneCollision = contact.bonesTouching.Find(bc => bc.bone == bone); if (boneCollision == null) { boneCollision = new BoneCollisionModel(bone); collision.GetContacts(boneCollision.points); contact.bonesTouching.Add(boneCollision); } } else { // New valid contact contact = AddContact(contactable); contact.type = ContactType.None; boneCollision = new BoneCollisionModel(bone); collision.GetContacts(boneCollision.points); contact.bonesTouching.Add(boneCollision); } } }
public void DeleteItem(object sender, RoutedEventArgs e) { if (BoneListView.SelectedItem != null) { //選擇的BoneModel BoneModel selectedModelItem = (BoneModel)BoneListView.SelectedItem; int temp = BoneListView.SelectedIndex; var ballCollection = MainViewModel.ProjData.BoneCollection; ballCollection.Remove(selectedModelItem); //刪減之後數量若跟舊的索引值一樣,代表選項在最後一個 if (ballCollection.Count == temp) { BoneListView.SelectedIndex = ballCollection.Count - 1; } else//不是的話則維持原索引值 { BoneListView.SelectedIndex = temp; } ListViewItem item = BoneListView.ItemContainerGenerator.ContainerFromIndex(BoneListView.SelectedIndex) as ListViewItem; if (item != null) { item.Focus(); } } }
void LateBoneStart(BoneModel bone) { if (!bone.reprs.ContainsKey(PuppetModel.key)) { Debug.Log("Bone " + bone + " does not have a " + PuppetModel.key + " representation"); return; } PuppetReprModel slave = bone.reprs[PuppetModel.key] as PuppetReprModel; if (!slave.usePhysics) { return; } if (bone.parent != null) { // Ignore part-parent collisions for (int b = 0; b < bone.part.parent.bones.Count; b++) { BoneModel parentBone = bone.part.parent.bones[b]; if (parentBone.reprs.ContainsKey(PuppetModel.key)) { PuppetReprModel parentSlave = parentBone.reprs[PuppetModel.key] as PuppetReprModel; slave.pheasy.IgnoreCollisions(parentSlave.pheasy, true, true); } } } slave.specificView.onPhysicsReady.Invoke(); slave.ready = true; }
public void ApplyToArmature() { if (!hand) { return; } if (!hand.proxyHand) { Debug.LogError("Hand.ProxyHand is NULL!"); return; } if (hand.fingers.Length != hand.proxyHand.master.fingers.Length) { Debug.LogError("Hand.fingers and Hand.proxyHand.master.fingers have to have the same length!"); return; } MasterBoneModel masterWristBone = hand.proxyHand.master.wrist as MasterBoneModel; if (masterWristBone.armatureBone) { if (space == Space.World) { masterWristBone.armatureBone.rotation = hand.wrist.transformRef.rotation * masterWristBone.relativeToOriginalArmatureWorld; } else { /* unsupported */ Debug.LogError("Local space is not supported!"); return; } } for (int f = 0; f < hand.fingers.Length; f++) { for (int b = 0; b < hand.fingers[f].bones.Length; b++) { BoneModel bone = hand.fingers[f].bones[b]; MasterBoneModel masterBone = hand.proxyHand.master.fingers[f].bones[b] as MasterBoneModel; if (masterBone.armatureBone) { if (space == Space.World) { masterBone.armatureBone.rotation = bone.transformRef.rotation * masterBone.relativeToOriginalArmatureWorld; } else { /* unreachable */ } } } } }
public MasterBoneModel CastBone(BoneModel bone) { MasterBoneModel masterBone = bone.gameObject.AddComponent <MasterBoneModel>(); masterBone.transformRef = bone.transformRef; Destroy(bone); return(masterBone); }
public Bone GetSettedBone() { DiceParameter diceParameter = Mediator.Instance.GameConfig.DiceParameters.Find(dice => dice.DiceID == PlayerPrefs.GetString("SelectedDiceID", "WB")); BoneModel boneModel = diceParameter.BonePrefab.GetComponentInChildren <BoneModel>(); boneModel.BodyMaterial.color = diceParameter.BodyColor; boneModel.PointsMaterial.color = diceParameter.PointsColor; return(diceParameter.BonePrefab); }
void BoneUpdate(BoneModel bone) { if (bone.point.master == null || !bone.point.reprs.ContainsKey(PuppetModel.key)) { return; } ReprModel master; PuppetReprModel slave = bone.point.reprs[PuppetModel.key] as PuppetReprModel; if (!slave.usePhysics) { return; } if (!bone.reprs.ContainsKey(model.mimicRepr)) { Debug.LogWarning("Bone " + bone.name + " does not have a " + model.mimicRepr + " representation. Puppet goal cannot be updated for this bone"); return; } if (slave.constraint.connectedBody) { master = bone.point.reprs[model.mimicRepr]; if (master.localRotZ < slave.maxLocalRotZ && master.localRotZ > slave.minLocalRotZ) { slave.goal.rotation = slave.goal.parent.rotation * master.localRotation; } else { slave.goal.localRotation = slave.fixedLocalRot; } } else { master = bone.point.reprs[model.mimicRepr]; slave.goal.rotation = master.transformRef.rotation; slave.goal.position = master.transformRef.position; if (model.forceUnconnected) { slave.pheasy.rb.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative; } else { slave.pheasy.rb.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; } slave.pheasy.rb.isKinematic = model.forceUnconnected; slave.constraint.force = model.forceUnconnected; } }
public ProjectData(SerializationInfo info, StreamingContext context) { Name = (string)info.GetValue("Name", typeof(string)); ID = (string)info.GetValue("ID", typeof(string)); Institution = (string)info.GetValue("Institution", typeof(string)); RegFilePath = (string)info.GetValue("RegFilePath", typeof(string)); IsRegInitialized = (bool)info.GetValue("IsRegInitialized", typeof(bool)); IsNavSet = (bool)info.GetValue("IsNavSet", typeof(bool)); Stage1Red = (float)info.GetValue("Stage1Red", typeof(float)); Stage1Green = (float)info.GetValue("Stage1Green", typeof(float)); Stage1Blue = (float)info.GetValue("Stage1Blue", typeof(float)); Stage2Red = (float)info.GetValue("Stage2Red", typeof(float)); Stage2Green = (float)info.GetValue("Stage2Green", typeof(float)); Stage2Blue = (float)info.GetValue("Stage2Blue", typeof(float)); DA = (float)info.GetValue("DA", typeof(float)); FDA = (float)info.GetValue("FDA", typeof(float)); HDA = (float)info.GetValue("HDA", typeof(float)); DD = (float)info.GetValue("DD", typeof(float)); PDD = (float)info.GetValue("PDD", typeof(float)); FirstNavigation = (string)info.GetValue("FirstNavigation", typeof(string)); IsNavDone = (bool)info.GetValue("IsNavDone", typeof(bool)); int count = (int)info.GetValue("BallCollection_Count", typeof(int)); ObservableCollection <BallModel> ballCollection = new ObservableCollection <BallModel>(); for (int i = 0; i < count; i++) { BallModel ballModel = (BallModel)info.GetValue("BallCollection_" + i, typeof(BallModel)); ballModel.CreateBall(); ballCollection.Add(ballModel); } BallCollection = ballCollection; count = (int)info.GetValue("BoneCollection_Count", typeof(int)); ObservableCollection <BoneModel> boneCollection = new ObservableCollection <BoneModel>(); for (int i = 0; i < count; i++) { BoneModel boneModel = (BoneModel)info.GetValue("BoneCollection_" + i, typeof(BoneModel)); boneCollection.Add(boneModel); } BoneCollection = boneCollection; count = (int)info.GetValue("TargetCollection_Count", typeof(int)); ObservableCollection <BoneModel> targetCollection = new ObservableCollection <BoneModel>(); for (int i = 0; i < count; i++) { BoneModel targetModel = (BoneModel)info.GetValue("TargetCollection_" + i, typeof(BoneModel)); targetCollection.Add(targetModel); } TargetCollection = targetCollection; }
public static BoneBody AddBoneBody(BoneModel boneModel) { var slotBody = Will.Instance.Bodies.RandomOrDefault <ConnectionSlotBody>(b => !b.Model.IsOccupied); if (slotBody == null) { return(null); // TODO: replace with unconnected bone } var newBone = slotBody.AddBone(boneModel); return(newBone); }
public override sealed void InitFingerGesture() { base.InitFingerGesture(); if (_model.finger.tip.bone.parent) { strengthDirector = _model.finger.tip.bone.parent; } else { strengthDirector = _model.finger.tip.bone; } }
// If bone1 -> Finger rotation. If bone 2 -> Finger strength public static float GetBoneRotLerp(BoneModel bone, float maxLocalRotZ, float minLocalRotZ) { float localRotZ = bone.transformRef.localRotation.eulerAngles.z; if (localRotZ <= maxLocalRotZ && localRotZ >= minLocalRotZ) { return(Mathf.InverseLerp(maxLocalRotZ, minLocalRotZ, localRotZ)); } else if (localRotZ < 0.0f || localRotZ > maxLocalRotZ || (localRotZ >= 0.0f && localRotZ < 180.0f)) { return(0.0f); } else { return(1.0f); } }
public void UpdateData(ProjectData projectData) { this.Name = projectData.Name; this.ID = projectData.ID; this.Institution = projectData.Institution; this.RegFilePath = projectData.RegFilePath; this.IsRegInitialized = projectData.IsRegInitialized; this.IsNavSet = projectData._isNavSet; this.Stage1Red = projectData.Stage1Red; this.Stage1Green = projectData.Stage1Green; this.Stage1Blue = projectData.Stage1Blue; this.Stage2Red = projectData.Stage2Red; this.Stage2Green = projectData.Stage2Green; this.Stage2Blue = projectData.Stage2Blue; this.DA = projectData.DA; this.FDA = projectData.FDA; this.HDA = projectData.HDA; this.DD = projectData.DD; this.PDD = projectData.PDD; this.FirstNavigation = projectData.FirstNavigation; this.IsNavDone = projectData.IsNavDone; this.BallCollection.Clear(); for (int i = 0; i < projectData.BallCollection.Count; i++) { BallModel ballModel = projectData.BallCollection[i]; this.BallCollection.Add(ballModel); } this.BoneCollection.Clear(); for (int i = 0; i < projectData.BoneCollection.Count; i++) { BoneModel boneModel = projectData.BoneCollection[i]; this.BoneCollection.Add(boneModel); } this.TargetCollection.Clear(); for (int i = 0; i < projectData.TargetCollection.Count; i++) { BoneModel targetModel = projectData.TargetCollection[i]; this.TargetCollection.Add(targetModel); } }
void OnRbTouchEnd(Collision collision, BoneModel bone) { ContactableView contactable = collision.rigidbody.GetComponent <ContactableView>(); if (contactable) { Contact contact = model.contacts.Find(c => c.contactable == contactable); if (contact != null) { BoneCollisionModel boneCollision = contact.bonesTouching.Find(bc => bc.bone == bone); if (boneCollision != null) { contact.bonesTouching.Remove(boneCollision); } } } }
void OnRbExit(Rigidbody exitedRb, BoneModel bone) { ContactableView contactable = exitedRb.GetComponent <ContactableView>(); if (contactable) { Contact contact = model.contacts.Find(c => c.contactable == contactable); if (contact != null) { // Existing contact if (contact.bonesEntered.Contains(bone)) { bool stillEntered = false; /* * PuppetReprModel slave = bone.reprs.FirstOrDefault(r => r.Value is PuppetReprModel).Value as PuppetReprModel; * PuppetReprModel slave = BasicHelpers.Get<ReprModel, PuppetReprModel>(bone.reprs); */ PuppetReprModel slave = bone.reprs[PuppetModel.key] as PuppetReprModel; // Remove bone only if exitedRb is not in any bone.pheasy.triggerNotifiers for (int tn = 0; tn < slave.pheasy.triggerNotifiers.Length; tn++) { if (slave.pheasy.triggerNotifiers[tn].enteredRbs.Contains(exitedRb)) { stillEntered = true; break; } } if (!stillEntered) { contact.bonesEntered.Remove(bone); } } } } }
public static void GetBonesFromRootToTip(FingerModel finger, List <BoneModel> _orderedBones) { _orderedBones.Clear(); BoneModel bone = finger.tip.bone; for (int i = 0; i < 50; i++) { _orderedBones.Add(bone); if (!bone.parent || bone == finger.root) { break; } else { bone = bone.parent; } } _orderedBones.Reverse(); }
void OverlapSphere(BoneModel bone, float radius, List <Rigidbody> foundRbs) { foundRbs.Clear(); if (!bone.reprs.ContainsKey(PuppetModel.key)) { return; } PuppetReprModel slave = bone.reprs[PuppetModel.key] as PuppetReprModel; Collider[] colliders = UnityEngine.Physics.OverlapSphere(slave.transformRef.position, radius); for (int c = 0; c < colliders.Length; c++) { if (!colliders[c].attachedRigidbody) { continue; } foundRbs.Add(colliders[c].attachedRigidbody); } }
public BoneViewModel(BoneModel model) { this.model = model; }
/// <summary> ///將設置清單的每個Item Load進檔案,並轉成模型清單 /// </summary> public void LoadSettingModel(object o) { //確保所有模型資訊都有set進去ModelInfo的資料 for (int i = 0; i < ModelSettingCollection.Count; i++) { //Load模型檔,內部有防呆防止重複Load ModelSettingCollection[i].Load(); OspModel ospModel = ModelSettingCollection[i].Osp; BoneModel boneModel = ModelSettingCollection[i].Bone; //確認有Load過且有沒有被加進去modelDataCollection if (ospModel.IsLoaded && !ospModel.IsAdded) { MultiAngleViewModel.OspModelCollection.Add(ModelSettingCollection[i].Osp); ModelSettingCollection[i].Osp.IsAdded = true; } //確認有Load過且有沒有被加進去modelDataCollection if (boneModel.IsLoaded && !boneModel.IsAdded) { MainViewModel.ProjData.BoneCollection.Add(ModelSettingCollection[i].Bone); ModelSettingCollection[i].Bone.IsAdded = true; //除了頭部以外需要guide if (!boneModel.MarkerId.Equals("Head") && !boneModel.MarkerId.Equals("C")) { ModelSettingCollection[i].Guide = new DraggableTriangle(boneModel.ModelCenter); MultiAngleViewModel.TriangleModelCollection.Add(ModelSettingCollection[i].Guide); } } //做bone 跟 osp transform的binding if (boneModel.IsLoaded && ospModel.IsAdded) { var binding = new Binding("Transform"); binding.Source = boneModel; binding.Mode = BindingMode.OneWay; BindingOperations.SetBinding(ospModel, Model3D.TransformProperty, binding); } //做bone 的轉移矩陣綁到 DraggableTriangle的ModelTransform上面 if (boneModel.IsLoaded && ModelSettingCollection[i].Guide != null) { var binding = new Binding("Transform"); binding.Source = boneModel; binding.Mode = BindingMode.OneWay; BindingOperations.SetBinding(ModelSettingCollection[i].Guide, HelixToolkit.Wpf.SharpDX.GroupModel3D.TransformProperty, binding); } } //刪除modelDataCollection中已經從ModelInfoCollection移除的模型, for (int i = 0; i < MainViewModel.ProjData.BoneCollection.Count; i++) { BoneModel boneModel = MainViewModel.ProjData.BoneCollection[i] as BoneModel; //模型如果透過 - 移除 或是 因為換錯誤檔名造成IsLoaded 為false則直接移除 if (boneModel.IsRemoved || !boneModel.IsLoaded) { MainViewModel.ProjData.BoneCollection.RemoveAt(i); boneModel.IsAdded = false; i--; } } //刪除modelDataCollection中已經從ModelInfoCollection移除的模型, for (int i = 0; i < MultiAngleViewModel.OspModelCollection.Count; i++) { OspModel ospModel = MultiAngleViewModel.OspModelCollection[i] as OspModel; //模型如果透過 - 移除 或是 因為換錯誤檔名造成IsLoaded 為false則直接移除 if (ospModel.IsRemoved || !ospModel.IsLoaded) { MultiAngleViewModel.OspModelCollection.RemoveAt(i); ospModel.IsAdded = false; i--; } } Console.WriteLine("OSP 數量:" + MultiAngleViewModel.OspModelCollection.Count); Console.WriteLine("Bone 數量:" + MainViewModel.ProjData.BoneCollection.Count); MultiAngleViewModel.ResetCameraPosition(); _modelSettingView.Hide(); }
public void LoadSettingModel(object o) { MainViewModel.ProjData.TargetCollection.Clear(); MainViewModel.ProjData.BoneCollection.Clear(); MultiAngleViewModel.OspModelCollection.Clear(); MultiAngleViewModel.TriangleModelCollection.Clear(); //讀取原始上下顎 加上 規劃後的轉移矩陣 Matrix plannedMatrix = ReadMatrixFile(_plannedMaxillaMatrix); BoneModel targetMaxilla = new BoneModel { FilePath = MaxillaModel, IsRendering = false, MarkerId = "", ModelType = ModelType.TargetMaxilla, BoneDiffuseColor = Color.FromArgb(255, 100, 100, 100), Transform = new MatrixTransform3D(plannedMatrix.ToMatrix3D()) }; targetMaxilla.LoadModel(); Matrix plannedMandible = ReadMatrixFile(_plannedMandibleMatrix); BoneModel targetMandible = new BoneModel { FilePath = MandibleModel, IsRendering = false, MarkerId = "", ModelType = ModelType.TargetMandible, BoneDiffuseColor = Color.FromArgb(255, 100, 100, 100), Transform = new MatrixTransform3D(plannedMandible.ToMatrix3D()) }; targetMandible.LoadModel(); //MainViewModel.Data.TargetCollection.Add(head); MainViewModel.ProjData.TargetCollection.Add(targetMaxilla); MainViewModel.ProjData.TargetCollection.Add(targetMandible); BoneModel head = new BoneModel { FilePath = HeadModel, MarkerId = "Head", ModelType = ModelType.Head, BoneDiffuseColor = HeadDiffuseColor }; head.LoadModel(); BoneModel oriMaxilla = new BoneModel { FilePath = MaxillaModel, ModelType = ModelType.MovedMaxilla, MarkerId = "Splint", BoneDiffuseColor = MaxillaDiffuseColor }; oriMaxilla.LoadModel(); BoneModel oriMandible = new BoneModel { FilePath = MandibleModel, ModelType = ModelType.MovedMandible, MarkerId = "Splint", BoneDiffuseColor = MandibleDiffuseColor }; oriMandible.LoadModel(); MainViewModel.ProjData.BoneCollection.Add(head); MainViewModel.ProjData.BoneCollection.Add(oriMaxilla); MainViewModel.ProjData.BoneCollection.Add(oriMandible); //載入OSP模型 OspModel headOsp = new OspModel { MarkerId = "Head", FilePath = HeadOsp, DiffuseColor = Color.FromArgb(50, 11, 243, 243) }; headOsp.LoadOsp(); OspModel mandibleOsp = new OspModel { MarkerId = "C", FilePath = MandibleOsp, DiffuseColor = Color.FromArgb(50, 2, 231, 2) }; mandibleOsp.LoadOsp(); //綁定下顎對稱面到下顎模型 SetBinding(oriMandible, mandibleOsp, "Transform", HelixToolkit.Wpf.SharpDX.Model3D.TransformProperty, BindingMode.OneWay); MultiAngleViewModel.OspModelCollection.Add(headOsp); MultiAngleViewModel.OspModelCollection.Add(mandibleOsp); //標記屬於上顎的ID,綁定到目標上顎 DraggableTriangle maxillaTargetTriangle = new DraggableTriangle(targetMaxilla.ModelCenter) { MarkerId = "Maxilla", IsRendering = false, Transform = targetMaxilla.Transform, ModelType = ModelType.TargetMaxillaTriangle, }; //標記屬於下顎的ID,綁定到目標下顎 DraggableTriangle mandibleTargetTriangle = new DraggableTriangle(targetMandible.ModelCenter) { MarkerId = "Mandible", IsRendering = false, Transform = targetMandible.Transform, ModelType = ModelType.TargetMandibleTriangle, }; //將導航三角形綁定到導航的上顎 DraggableTriangle maxillaTriangle = new DraggableTriangle(oriMaxilla.ModelCenter) { MarkerId = "Maxilla", Transparency = 0.5f, IsRendering = false, ModelType = ModelType.MovedMaxillaTriangle, }; SetBinding(oriMaxilla, maxillaTriangle, "Transform", HelixToolkit.Wpf.SharpDX.GroupModel3D.TransformProperty, BindingMode.OneWay); //將導航三角形綁定到導航的下顎 DraggableTriangle mandibleTriangle = new DraggableTriangle(oriMandible.ModelCenter) { MarkerId = "Mandible", Transparency = 0.5f, IsRendering = false, ModelType = ModelType.MovedMandibleTriangle, }; SetBinding(oriMandible, mandibleTriangle, "Transform", HelixToolkit.Wpf.SharpDX.GroupModel3D.TransformProperty, BindingMode.OneWay); MultiAngleViewModel.TriangleModelCollection.Add(maxillaTargetTriangle); MultiAngleViewModel.TriangleModelCollection.Add(mandibleTargetTriangle); MultiAngleViewModel.TriangleModelCollection.Add(maxillaTriangle); MultiAngleViewModel.TriangleModelCollection.Add(mandibleTriangle); MultiAngleViewModel.ResetCameraPosition(); MainViewModel.ProjData.IsNavSet = true; _navigateView.Hide(); }
public BoneCollisionModel(BoneModel bone) { this.bone = bone; this.points = new List <ContactPoint>(); }
public override void ControllerUpdate() { base.ControllerUpdate(); if (!model.inputDataProvider) { return; } if (!gameObject.activeSelf) { return; } masterReprKey = AvatarModel.key; model.inputDataProvider.UpdateData(); // On hand tracked if (conf.ignoreTrackingLoss || model.inputDataProvider.confidence > conf.handTrackingLostUnderConfidence) { if (!model.handIsTracked) { model.handIsTracked = true; model.view.onHandTrackingRecovered.Invoke(); } if (model.isPredicting) { model.isPredicting = false; model.view.onPredictionInterrupted.Invoke(); } // If recovered from tracking loss if (timeSinceLastValidRecord != 0.0f) { timeSinceLastValidRecord = 0.0f; if (conf.hideMasterWhenLost) { model.hand.specificView.SetHandVisuals(true, masterReprKey); } if (conf.hideSlaveWhenLost) { model.hand.specificView.SetHandVisuals(true, PuppetModel.key); model.hand.specificView.SetHandPhysics(true); } } // Calculate clamping if (conf.useHandClamping) { if (conf.gradualHandClamping) { handClampLerp = Mathf.Lerp(0.0f, conf.startDecreasingHandClampUnderConfidence, model.inputDataProvider.confidence); } else if (model.inputDataProvider.confidence > conf.startDecreasingHandClampUnderConfidence) { handClampLerp = 1.0f; // High confidece. Clamp set to highest } else { handClampLerp = 0.0f; // Low confidence. Clamp set to lowest } maxHandLinearSpeed = Mathf.Lerp(conf.lowestHandLinearSpeed, model.highestLinearSpeed, handClampLerp); maxHandAngularSpeed = Mathf.Lerp(conf.lowestHandAngularSpeed, model.highestAngularSpeed, handClampLerp); } else { maxHandLinearSpeed = -1.0f; maxHandAngularSpeed = -1.0f; } // Update record if (model.configuration.recordTracking) { InputHelpers.RecordBone(model.boneRecords, model.inputDataProvider.bones[0], 0); // RecordBone(model.inputDataProvider.bones[1], 1); } // Noise reduction if (model.configuration.movingAverage != MovingAverage.None) { model.inputDataProvider.bones[0] = ReduceNoise(model.boneRecords[0], 0); // model.inputDataProvider.bones[1] = ReduceNoise(model.boneRecords[1], 1); } // Use or get what to move as wrist if (!model.moveThisAsWrist) { model.moveThisAsWrist = model.rigMap.wrist.master.transformRef; } // Find a point of reference (if neede) if (model.replicatedTsf && !model.referenceTsf) { model.referenceTsf = HPTK.core.trackingSpace; } // Update pos and rot for wrist and forearm if (conf.updateWrist && model.bonesToUpdate[0] != null) { // Update wrist position and rotation UpdateBoneTsfPos(model.rigMap.wrist.master, model.moveThisAsWrist, model.inputDataProvider.bones[0], maxHandLinearSpeed, model.referenceTsf, model.replicatedTsf); UpdateBoneTsfRot(model.rigMap.wrist.master, model.moveThisAsWrist, model.inputDataProvider.bones[0], maxHandAngularSpeed, model.referenceTsf, model.replicatedTsf); } if (conf.updateForearm && model.bonesToUpdate[1] != null) { // Optional if (model.configuration.recordTracking) { InputHelpers.RecordBone(model.boneRecords, model.inputDataProvider.bones[1], 1); } // Update wrist position and rotation UpdateBoneTsfPos(model.rigMap.forearm.master, model.rigMap.forearm.master.transformRef, model.inputDataProvider.bones[1], maxHandLinearSpeed, model.referenceTsf, model.replicatedTsf); UpdateBoneTsfRot(model.rigMap.forearm.master, model.rigMap.forearm.master.transformRef, model.inputDataProvider.bones[1], maxHandAngularSpeed, model.referenceTsf, model.replicatedTsf); // Optional } } // On hand tracking loss else { if (model.handIsTracked) { model.handIsTracked = false; model.view.onHandTrackingLost.Invoke(); } if (timeSinceLastValidRecord == 0.0f) { if (conf.usePredictiveTrackingWhenLost) { acceleration = (0.0f - wristSpeed) / conf.maxPredictionTime; predictedDirection = wristVelocityDirection; lastWristPosition = model.rigMap.wrist.transformRef.position; if (!model.isPredicting) { model.isPredicting = true; model.view.onPredictionStart.Invoke(); } } if (conf.hideMasterWhenLost) { model.hand.specificView.SetHandVisuals(false, masterReprKey); } if (conf.hideSlaveWhenLost) { model.hand.specificView.SetHandVisuals(false, PuppetModel.key); model.hand.specificView.SetHandPhysics(false); } } timeSinceLastValidRecord = Time.timeSinceLevelLoad - timeOfLastRecord; if (conf.usePredictiveTrackingWhenLost) { if (timeSinceLastValidRecord < conf.maxPredictionTime) { // Predict new position // currentTime - lastRecordTime = 0 -> velocity = initial // currentTime - lastRecordTime = maxPeedictionTime -> velocity = 0 newDisplacement = wristSpeed * timeSinceLastValidRecord + 0.5f * acceleration * timeSinceLastValidRecord * timeSinceLastValidRecord; predictedDirection = Quaternion.Slerp(wristDirectionChange, Quaternion.identity, timeSinceLastValidRecord / conf.maxPredictionTime) * wristVelocityDirection; model.rigMap.wrist.transformRef.position = lastWristPosition + predictedDirection * newDisplacement; } else { if (model.isPredicting) { model.isPredicting = false; model.view.onPredictionTimeLimitReached.Invoke(); } } } } // On fingers tracked if (conf.ignoreTrackingLoss || model.inputDataProvider.confidence > conf.fingersTrackingLostUnderConfidence) { if (!model.fingersAreTracked) { model.fingersAreTracked = true; model.view.onFingersTrackingRecovered.Invoke(); } // Calculate clamping if (conf.useFingerClamping) { if (conf.gradualFingerClamping) { fingerClampLerp = Mathf.Lerp(0.0f, conf.startDecreasingFingerClampUnderConfidence, model.inputDataProvider.confidence); } else if (model.inputDataProvider.confidence > conf.startDecreasingFingerClampUnderConfidence) { fingerClampLerp = 1.0f; // High confidece. Clamp set to highest } else { fingerClampLerp = 0.0f; // Low confidence. Clamp set to lowest } // maxFingerLinearSpeed = Mathf.Lerp(model.lowestMasterBoneLinearSpeed, model.highestLinearSpeed, fingerClampLerp); maxFingerAngularSpeed = Mathf.Lerp(conf.lowestFingerAngularSpeed, model.highestAngularSpeed, fingerClampLerp); } else { // maxFingerLinearSpeed = -1.0f; maxFingerAngularSpeed = -1.0f; } // Finger bones start at i=2 (i=0 -> wrist, i=1 -> forearm) for (int i = 2; i < model.bonesToUpdate.Length; i++) { // Update record if (model.configuration.recordTracking) { InputHelpers.RecordBone(model.boneRecords, model.inputDataProvider.bones[i], i); } // Noise reduction if (model.configuration.movingAverage != MovingAverage.None) { model.inputDataProvider.bones[i] = ReduceNoise(model.boneRecords[i], i); } // Update only fingers rotation (assuming hierachy) if (model.bonesToUpdate[i] != null) { BoneModel bone = model.bonesToUpdate[i]; AbstractTsf inputData = model.inputDataProvider.bones[i]; // Estimate rotation. Assuming sorted array of bones (i-1 => thumb0, i => thumb1, i+1 => thumb2) if (!model.rigMap.thumb0 && bone == model.rigMap.thumb1) { inputData.rotation = EstimateLocalRotation(model.inputDataProvider.bones[i - 1], model.inputDataProvider.bones[i]); } else if (!model.rigMap.pinky0 && bone == model.rigMap.pinky1) { inputData.rotation = EstimateLocalRotation(model.inputDataProvider.bones[i - 1], model.inputDataProvider.bones[i]); } UpdateBoneTsfRot(bone.master, bone.master.transformRef, inputData, maxFingerAngularSpeed, null, null); } } } // On fingers tracking loss else { if (model.fingersAreTracked) { model.fingersAreTracked = false; model.view.onFingersTrackingLost.Invoke(); } } // If we need to record and confidence is good enough to record if (conf.usePredictiveTrackingWhenLost && model.inputDataProvider.confidence > conf.saveHandHistoricOverConfidence) { // Before updating wristVelocityDirection and wristPosition wristDirectionChange = Quaternion.FromToRotation(wristVelocityDirection, (model.rigMap.wrist.transformRef.position - wristPosition).normalized); // Before updating wristPosition and timeOfLastRecord deltaTime = Time.timeSinceLevelLoad - timeOfLastRecord; displacement = Vector3.Distance(wristPosition, model.rigMap.wrist.transformRef.position); displacement = Mathf.Clamp(displacement, 0.0f, conf.maxPredictionDisplacement * deltaTime); wristSpeed = displacement / deltaTime; wristVelocityDirection = (model.rigMap.wrist.transformRef.position - wristPosition).normalized; // Update wristPosition wristPosition = model.rigMap.wrist.transformRef.position; // Update timeOfLastRecord timeOfLastRecord = Time.timeSinceLevelLoad; } // Hand scaling if (model.updateRealScale && model.inputDataProvider.scale != model.hand.realScale) { model.hand.realScale = model.inputDataProvider.scale; } }
private void CalcBtn_Click(object sender, RoutedEventArgs e) { BoneModel model1 = MainViewModel.ProjData.BoneCollection[1]; BoneModel model2 = MainViewModel.ProjData.BoneCollection[2]; HelixToolkit.Wpf.SharpDX.Core.Vector3Collection model1Position = model1.Geometry.Positions; HelixToolkit.Wpf.SharpDX.Core.Vector3Collection model2Position = model2.Geometry.Positions; double total = 0; double Xtotal = 0; double Ytotal = 0; double Ztotal = 0; double totalfordev = 0; double Xtotalfordev = 0; double Ytotalfordev = 0; double Ztotalfordev = 0; double RMStotal = 0; double max = 0; double XMax = 0; double YMax = 0; double ZMax = 0; if (model1Position.Count != model2Position.Count) { System.Windows.MessageBox.Show("模型不同 有錯"); return; } for (int i = 0; i < model1Position.Count; i++) { double distance = Math.Sqrt(Math.Pow(model1Position[i].X - model2Position[i].X, 2) + Math.Pow(model1Position[i].Y - model2Position[i].Y, 2) + Math.Pow(model1Position[i].Z - model2Position[i].Z, 2)); double Xdistance = Math.Abs(model1Position[i].X - model2Position[i].X); double Ydistance = Math.Abs(model1Position[i].Y - model2Position[i].Y); double Zdistance = Math.Abs(model1Position[i].Z - model2Position[i].Z); //目前距離大於最大的 if (distance > max) { max = distance; } if (Xdistance > XMax) { XMax = Xdistance; } if (Ydistance > YMax) { YMax = Ydistance; } if (Zdistance > ZMax) { ZMax = Zdistance; } total += distance; Xtotal += Xdistance; Ytotal += Ydistance; Ztotal += Zdistance; RMStotal += distance * distance; } double avg = Math.Round(total / model1Position.Count, 3); double xavg = Math.Round(Xtotal / model1Position.Count, 3); double yavg = Math.Round(Ytotal / model1Position.Count, 3); double zavg = Math.Round(Ztotal / model1Position.Count, 3); for (int i = 0; i < model1Position.Count; i++) { double distance = Math.Sqrt(Math.Pow(model1Position[i].X - model2Position[i].X, 2) + Math.Pow(model1Position[i].Y - model2Position[i].Y, 2) + Math.Pow(model1Position[i].Z - model2Position[i].Z, 2)); double Xdistance = Math.Abs(model1Position[i].X - model2Position[i].X); double Ydistance = Math.Abs(model1Position[i].Y - model2Position[i].Y); double Zdistance = Math.Abs(model1Position[i].Z - model2Position[i].Z); totalfordev += (distance - avg) * (distance - avg); Xtotalfordev += (Xdistance - xavg) * (Xdistance - xavg); Ytotalfordev += (Ydistance - yavg) * (Ydistance - yavg); Ztotalfordev += (Zdistance - zavg) * (Zdistance - zavg); } double Dev = Math.Sqrt(totalfordev / model1Position.Count); double XDev = Math.Sqrt(Xtotalfordev / model1Position.Count); double YDev = Math.Sqrt(Ytotalfordev / model1Position.Count); double ZDev = Math.Sqrt(Ztotalfordev / model1Position.Count); double RMS = Math.Sqrt(RMStotal / model1Position.Count); Console.WriteLine("模型一:" + model1.FilePath); Console.WriteLine("模型二:" + model2.FilePath); Console.WriteLine("整體:" + avg + "±" + Math.Round(Dev, 3) + " " + Math.Round(max, 3)); Console.WriteLine("RMS Error:" + Math.Round(RMS, 3)); Console.WriteLine("XYZ Mean:" + xavg + "±" + Math.Round(XDev, 3) + " " + yavg + "±" + Math.Round(YDev, 3) + " " + zavg + "±" + Math.Round(ZDev, 3)); Console.WriteLine("XYZ Max:" + Math.Round(XMax, 3) + " " + Math.Round(YMax, 3) + " " + Math.Round(ZMax, 3) + " "); Console.WriteLine("\n"); }
void BoneStart(BoneModel bone, BoneModel mainRoot) { if (!bone.reprs.ContainsKey(PuppetModel.key)) { Debug.LogWarning("Bone " + bone.name + " does not have any " + PuppetModel.key + " representation. PuppetController cannot start this bone"); return; } PuppetReprModel slave = bone.reprs[PuppetModel.key] as PuppetReprModel; // Set puppet model for each puppet representation slave.puppet = model; // Set thumb bones as special if (bone.part is FingerModel) { FingerModel finger = bone.part as FingerModel; if (finger == finger.hand.thumb) { slave.isSpecial = true; } } if (!slave.usePhysics) { Debug.LogWarning("Bone " + bone.name + " has slave representation but it won't use physics"); return; } // Set pheasy if needed if (slave.pheasy == null) { Pheasy pheasy = slave.transformRef.GetComponent <Pheasy>(); if (pheasy == null) { pheasy = slave.transformRef.gameObject.AddComponent <Pheasy>(); } pheasy.rb.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative; pheasy.rb.isKinematic = true; pheasy.axis = model.axisPrefab; slave.pheasy = pheasy; } // Get connected body Rigidbody connectedBody = null; if (bone.parent != null) { if (bone.parent.reprs.ContainsKey(PuppetModel.key)) { PuppetReprModel parentSlave = bone.parent.reprs[PuppetModel.key] as PuppetReprModel; if (parentSlave.usePhysics && !parentSlave.pheasy) { // Debug.LogWarning("Bone " + bone.parent.name + " has a " + PuppetModel.key + " representation and it use physics but it has no Pheasy component. Forcing initialization"); BoneStart(bone.parent, mainRoot); } if (parentSlave.pheasy) { connectedBody = parentSlave.pheasy.rb; } } else { Debug.LogWarning("Parent of bone " + bone.name + ", " + bone.parent.name + ", does not have a " + PuppetModel.key + " representation"); } } // Add and save pheasy.constraint if (slave.constraint == null || slave.constraint.pheasy == null) { slave.constraint = slave.pheasy.AddTargetConstraint("PuppetBone", connectedBody, false, null); } // Replace or instantiate goal if (slave.goal == null) { slave.goal = slave.constraint.connectedAnchor; } else { slave.constraint.connectedAnchor = slave.goal; } // Set freedom slave.constraint.settings.angularMotion = ConfigurableJointMotion.Free; if (connectedBody != null) { slave.constraint.settings.linearMotion = ConfigurableJointMotion.Locked; } else { slave.constraint.settings.linearMotion = ConfigurableJointMotion.Free; } // Replace connected body by parent if (bone.parent == null || slave.point.bone == mainRoot || slave.constraint.connectedBody == null) // Wrist { UpdatePhysicsSettings(slave, model.configuration.root); } else if (slave.isSpecial) // Special bones { UpdatePhysicsSettings(slave, model.configuration.special); } else // Common bones { UpdatePhysicsSettings(slave, model.configuration.standard); } if (slave.constraint != null) { // Stability slave.constraint.settings.collideWithConnectedRb = false; slave.pheasy.safeMode = true; slave.pheasy.gradualMode = false; // Forced values slave.constraint.enabled = true; slave.constraint.keepAxisRelativeToObject = true; slave.pheasy.rb.isKinematic = false; slave.pheasy.rb.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; // Performance slave.pheasy.editMode = true; AsyncHelpers.DoAfterFrames(this, 1, () => slave.pheasy.editMode = false); } // Find colliders and triggers. Children colliders are updated before their parents slave.pheasy.UpdateCollidersAndTriggerNotifiers(); }