void _findHandFromVerticesUpdate2(int[] triangles, Vector3[] vertices, out Vector3 outNearPoint, out Vector3 outFarPoint, out Quaternion handRot) { //handSize = 0; if (_colliderHandMeshes != null) { _colliderHandMeshes.sharedMesh.Clear(); } Vector3 newNearPoint, newFarPoint; //MyHelpMesh.GetLineFromVertices(null, vertices, out newNearPoint, out newFarPoint); //get 10 point which is nearest with camera plane findHandDataList.Clear(); Vector3 localEyePos = SRWorkControl.Instance.viveSR.transform.InverseTransformPoint(SRWorkControl.Instance.eye.position); Vector3 localEyeDir = SRWorkControl.Instance.viveSR.transform.InverseTransformDirection(SRWorkControl.Instance.eye.forward); Vector3 cameraNormal = localEyeDir; //cameraNormal.y = 0; cameraNormal.Normalize(); Plane cameraPlane = new Plane(cameraNormal, localEyePos); byte[] colorRGB = null; tempVertices.Clear(); if (considerSkinColor) { int vid = 0; colorRGB = _getDummyLeftTex(); foreach (Vector3 v in vertices) { if (IsSkinColorVert(v, colorRGB)) { tempVertices.Add(vertices[vid]); } vid++; } if (renderSkinVert) { Texture2D tex = ViveSR_DualCameraRig.Instance.DualCameraImageRenderer.UndistortedLeft[0].mainTexture as Texture2D; tex.LoadRawTextureData(_dummyLeftTex); tex.Apply(); //byte[] bytes = tex.EncodeToJPG(); //System.IO.File.WriteAllBytes("d:/234.jpg", bytes); //UnityEditor.EditorApplication.isPaused = true; } } else { tempVertices.AddRange(vertices); } //consider nearest from all dynamic vertices //foreach (Vector3 v in vertices) foreach (Vector3 v in tempVertices) { //limit nearest not too high if (Mathf.Abs(v.y - localEyePos.y) > 0.4f) { continue; } FindHandData data = new FindHandData(); data.cameraPlaneDis = cameraPlane.GetDistanceToPoint(v); data.vert = v; findHandDataList.Add(data); } findHandDataList.Sort(); //get the closest points. float nearestDis = 99999; FindHandData nearestData = null; for (int a = 0; a < 10; a++) { if (a == findHandDataList.Count) { break; } float sqrDis = (findHandDataList[a].vert - localEyePos).sqrMagnitude; if (sqrDis < nearestDis) { nearestDis = sqrDis; nearestData = findHandDataList[a]; } } if (nearestData == null) { outNearPoint = oldNearPoint; outFarPoint = oldFarPoint; handRot = Quaternion.identity; return; } newNearPoint = nearestData.vert; //get 10 point which is farest with camera plane findHandDataList.Clear(); foreach (Vector3 v in tempVertices)//get farest point from skin color vertices { //limit farest not too high if (Mathf.Abs(v.y - localEyePos.y) > 0.5f) { continue; } FindHandData data = new FindHandData(); data.cameraPlaneDis = cameraPlane.GetDistanceToPoint(v); data.vert = v; findHandDataList.Add(data); } findHandDataList.Sort(); //get the point which is farest from newNearPoint float maxDis = 0; newFarPoint = newNearPoint; for (int a = 0; a < findHandDataList.Count; a++) { // if (a == 10)//there are too many other point, so cannot limit the amount // break; FindHandData data = findHandDataList[findHandDataList.Count - a - 1]; float sqrDis = (data.vert - newNearPoint).sqrMagnitude; //float dddd = (data.vert - newNearPoint).magnitude; if (sqrDis > maxDis && sqrDis < 0.5f * 0.5f) { maxDis = sqrDis; newFarPoint = data.vert; } } //fix the hand direction by camera forward Vector3 newDirection = newFarPoint - newNearPoint; if (Vector3.Dot(localEyeDir, newDirection.normalized) < 0) { Vector3 rec = newNearPoint; newNearPoint = newFarPoint; newFarPoint = rec; } newNearPoint = Vector3.Lerp(oldNearPoint, newNearPoint, lowPassRatio); newFarPoint = Vector3.Lerp(oldFarPoint, newFarPoint, lowPassRatio); //save old position oldFarPoint = newFarPoint; oldNearPoint = newNearPoint; //get hand size in range //float handSize = 0; List <int> handIB = new List <int>(); List <Vector3> handVB = new List <Vector3>(); int count = 0; for (int a = 0; a < triangles.Length; a += 3) { Vector3 vA = vertices[triangles[a + 0]]; Vector3 vB = vertices[triangles[a + 1]]; Vector3 vC = vertices[triangles[a + 2]]; //if (considerSkinColor) //{ // if (!IsSkinColorVert(vA, colorRGB) && // !IsSkinColorVert(vB, colorRGB) && // !IsSkinColorVert(vC, colorRGB) // ) // continue; //} Vector3 dA = newFarPoint - vA; Vector3 dB = newFarPoint - vB; Vector3 dC = newFarPoint - vC; if ( dA.sqrMagnitude < handSizeRange * handSizeRange || dB.sqrMagnitude < handSizeRange * handSizeRange || dC.sqrMagnitude < handSizeRange * handSizeRange) { //get area //https://answers.unity.com/questions/291923/area-of-a-triangle-this-code-seems-to-work-why.html //Vector3 V = Vector3.Cross(vA - vB, vA - vC); //handSize += V.magnitude * 0.5f; handVB.Add(vA); handVB.Add(vB); handVB.Add(vC); handIB.Add(count + 0); handIB.Add(count + 1); handIB.Add(count + 2); count += 3; } } //recalculate far point if (handVB.Count > 0) { newFarPoint = Vector3.zero; foreach (Vector3 v in handVB) { newFarPoint += v; } newFarPoint /= handVB.Count; } //set point to world coordinate HandFar = outFarPoint = newFarPoint; // + SRWorkControl.Instance.viveSR.transform.position; HandNear = outNearPoint = newNearPoint; // + SRWorkControl.Instance.viveSR.transform.position; handRot = Quaternion.identity; if (showHand) { _colliderHandMeshes.sharedMesh.Clear(); if (handVB.Count > 0) { for (int a = 0; a < handVB.Count; a++) { handVB[a] += SRWorkControl.Instance.viveSR.transform.position; } _colliderHandMeshes.sharedMesh.SetVertices(handVB); _colliderHandMeshes.sharedMesh.SetIndices(handIB.ToArray(), MeshTopology.Triangles, 0); _colliderHandMeshRenderer.material.color = farDebugColor; } _colliderHandObjs.GetComponent <MeshRenderer>().enabled = true; _getDynamicScanObj().GetComponent <MeshRenderer>().enabled = false; } else { _colliderHandObjs.GetComponent <MeshRenderer>().enabled = false; _getDynamicScanObj().GetComponent <MeshRenderer>().enabled = true; } _showDebug.gameObject.SetActive(false); if (Debug.isDebugBuild && DebugShow) { if (nearDebug == null) { nearDebug = GameObject.CreatePrimitive(PrimitiveType.Sphere); } if (farDebug == null) { farDebug = GameObject.CreatePrimitive(PrimitiveType.Cube); } nearDebug.transform.localScale = Vector3.one * 0.05f; farDebug.transform.localScale = Vector3.one * 0.05f; //Vector3.Lerp(Vector3.one * handSize, farDebug.transform.localScale, 0.1f); nearDebug.transform.position = outNearPoint + SRWorkControl.Instance.viveSR.transform.position; farDebug.transform.position = outFarPoint + SRWorkControl.Instance.viveSR.transform.position; nearDebug.GetComponent <Renderer>().material.color = Color.red; farDebug.GetComponent <Renderer>().material.color = Color.red; Destroy(nearDebug.GetComponent <Collider>()); Destroy(farDebug.GetComponent <Collider>()); float farDis = cameraPlane.GetDistanceToPoint(HandFar); _showDebug.gameObject.SetActive(true); _showDebug.text = //"handSize : " + handSize + Environment.NewLine + "farDis : " + farDis; } }
void _findHandFromVerticesUpdate2(int[] triangles, Vector3[] vertices, out Vector3 outNearPoint, out Vector3 outFarPoint, out Quaternion handRot) { Vector3 newNearPoint, newFarPoint; //MyHelpMesh.GetLineFromVertices(null, vertices, out newNearPoint, out newFarPoint); //get 10 point which is nearest with camera plane findHandDataList.Clear(); Vector3 localEyePos = SRWorksHand.Instance.viveSR.transform.InverseTransformPoint(SRWorksHand.Instance.eye.position); Vector3 localEyeDir = SRWorksHand.Instance.viveSR.transform.InverseTransformDirection(SRWorksHand.Instance.eye.forward); Vector3 cameraNormal = localEyeDir; //cameraNormal.y = 0; cameraNormal.Normalize(); Plane cameraPlane = new Plane(cameraNormal, localEyePos); foreach (Vector3 v in vertices) { //limit nearest not too high if (Mathf.Abs(v.y - localEyePos.y) > 0.4f) { continue; } FindHandData data = new FindHandData(); data.cameraPlaneDis = cameraPlane.GetDistanceToPoint(v); data.vert = v; findHandDataList.Add(data); } findHandDataList.Sort(); //get the closest points. float nearestDis = 99999; FindHandData nearestData = null; for (int a = 0; a < 10; a++) { if (a == findHandDataList.Count) { break; } float sqrDis = (findHandDataList[a].vert - localEyePos).sqrMagnitude; if (sqrDis < nearestDis) { nearestDis = sqrDis; nearestData = findHandDataList[a]; } } if (nearestData == null) { outNearPoint = oldNearPoint; outFarPoint = oldFarPoint; handRot = Quaternion.identity; return; } newNearPoint = nearestData.vert; //get 10 point which is farest with camera plane findHandDataList.Clear(); foreach (Vector3 v in vertices) { //limit farest not too high if (Mathf.Abs(v.y - localEyePos.y) > 0.5f) { continue; } FindHandData data = new FindHandData(); data.cameraPlaneDis = cameraPlane.GetDistanceToPoint(v); data.vert = v; findHandDataList.Add(data); } findHandDataList.Sort(); //get the point which is farthest from newNearPoint float maxDis = 0; newFarPoint = newNearPoint; for (int a = 0; a < findHandDataList.Count; a++) { // if (a == 10)//there are too many other point, so cannot limit the head amount // break; FindHandData data = findHandDataList[findHandDataList.Count - a - 1]; float sqrDis = (data.vert - newNearPoint).sqrMagnitude; //float dddd = (data.vert - newNearPoint).magnitude; if (sqrDis > maxDis && sqrDis < 0.5f * 0.5f) { maxDis = sqrDis; newFarPoint = data.vert; } } Vector3 newDirection = newFarPoint - newNearPoint; if (Vector3.Dot(localEyeDir, newDirection.normalized) < 0) { Vector3 rec = newNearPoint; newNearPoint = newFarPoint; newFarPoint = rec; } newNearPoint = Vector3.Lerp(oldNearPoint, newNearPoint, dynamicHandDisDivided); newFarPoint = Vector3.Lerp(oldFarPoint, newFarPoint, dynamicHandDisDivided); //save old position oldFarPoint = newFarPoint; oldNearPoint = newNearPoint; //get hand direction //Vector3 handPoint; //if (MyHelpMesh.GetLongestPointInRange(vertices, newFarPoint, 0.1f, out handPoint)) //{ // Vector3 handDir = handPoint - newFarPoint; // handDir.Normalize(); // handRot = Quaternion.LookRotation(-handDir, Vector3.up); // handRot = Quaternion.Slerp(oldHandRot, handRot, dynamicHandDisDivided); // oldHandRot = handRot; //} //get hand size in range //float handSize = 0; List <int> handIB = new List <int>(); List <Vector3> handVB = new List <Vector3>(); int count = 0; for (int a = 0; a < triangles.Length; a += 3) { Vector3 vA = vertices[triangles[a + 0]]; Vector3 vB = vertices[triangles[a + 1]]; Vector3 vC = vertices[triangles[a + 2]]; Vector3 dA = newFarPoint - vA; Vector3 dB = newFarPoint - vB; Vector3 dC = newFarPoint - vC; if ( dA.sqrMagnitude < handSizeRange * handSizeRange || dB.sqrMagnitude < handSizeRange * handSizeRange || dC.sqrMagnitude < handSizeRange * handSizeRange) { //get area //https://answers.unity.com/questions/291923/area-of-a-triangle-this-code-seems-to-work-why.html //Vector3 V = Vector3.Cross(vA - vB, vA - vC); // handSize += V.magnitude * 0.5f; handVB.Add(vA + SRWorksHand.Instance.viveSR.transform.position); handVB.Add(vB + SRWorksHand.Instance.viveSR.transform.position); handVB.Add(vC + SRWorksHand.Instance.viveSR.transform.position); handIB.Add(count + 0); handIB.Add(count + 1); handIB.Add(count + 2); count += 3; } } //recalculate far point if (handVB.Count > 0) { newFarPoint = Vector3.zero; foreach (Vector3 v in handVB) { newFarPoint += v - SRWorksHand.Instance.viveSR.transform.position; } newFarPoint /= handVB.Count; } //set point to world coordinate _OutFar = outFarPoint = newFarPoint; // + SRWorkHand.Instance.viveSR.transform.position; _OutNear = outNearPoint = newNearPoint; // + SRWorkHand.Instance.viveSR.transform.position; handRot = Quaternion.identity; if (showHandMesh) { ColliderMeshes.sharedMesh.Clear(); if (handVB.Count > 0) { ColliderMeshes.sharedMesh.SetVertices(handVB); ColliderMeshes.sharedMesh.SetIndices(handIB.ToArray(), MeshTopology.Triangles, 0); } ColliderObjs.GetComponent <MeshRenderer>().enabled = true; GetDynamicHand().GetComponent <MeshRenderer>().enabled = true; } else { ColliderObjs.GetComponent <MeshRenderer>().enabled = false; GetDynamicHand().GetComponent <MeshRenderer>().enabled = false; } _showDebug.gameObject.SetActive(false); if (Debug.isDebugBuild && DebugShow) { if (nearDebug == null) { nearDebug = GameObject.CreatePrimitive(PrimitiveType.Sphere); } if (farDebug == null) { farDebug = GameObject.CreatePrimitive(PrimitiveType.Cube); } nearDebug.transform.localScale = Vector3.one * 0.05f; farDebug.transform.localScale = Vector3.one * 0.05f; //Vector3.Lerp(Vector3.one * handSize, farDebug.transform.localScale, 0.1f); nearDebug.transform.position = outNearPoint + SRWorksHand.Instance.viveSR.transform.position; farDebug.transform.position = outFarPoint + SRWorksHand.Instance.viveSR.transform.position; nearDebug.GetComponent <Renderer>().material.color = Color.red; farDebug.GetComponent <Renderer>().material.color = Color.green; Destroy(nearDebug.GetComponent <Collider>()); Destroy(farDebug.GetComponent <Collider>()); float farDis = cameraPlane.GetDistanceToPoint(_OutFar); _showDebug.gameObject.SetActive(true); _showDebug.text = //"handSize : " + handSize + Environment.NewLine + "farDis : " + farDis; } }