private Vector2 GetClosestMouseHit() { foreach (Camera camera in m_Cameras) { Ray ray = camera.ScreenPointToRay(Input.mousePosition); VRRaycastHit hit = RaycastMesh(ray.origin, ray.direction); if (hit != null) { return(hit.textureCoord); } } return(new Vector2(-1, -1)); }
public VRRaycastHit RaycastMesh(Vector3 rayOrigin, Vector3 rayDirection) { for (int i = 0; i < m_RaycastMeshTriangles.Length; i += 3) { int i0 = m_RaycastMeshTriangles[i]; int i1 = m_RaycastMeshTriangles[i + 1]; int i2 = m_RaycastMeshTriangles[i + 2]; VRRaycastHit raycastHit = _RaycastTriangle(i0, i1, i2, rayOrigin, rayDirection); if (raycastHit != null) { return(raycastHit); } } return(null); }
private VRRaycastHit _RaycastTriangle(int i0, int i1, int i2, Vector3 rayOrigin, Vector3 rayDirection) { Vector3 p0 = transform.TransformPoint(m_RaycastMeshVertices[i0]); Vector3 p1 = transform.TransformPoint(m_RaycastMeshVertices[i1]); Vector3 p2 = transform.TransformPoint(m_RaycastMeshVertices[i2]); // Möller–Trumbore intersection algorithm // http://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm // edge 1 Vector3 E1 = p1 - p0; // edge 2 Vector3 E2 = p2 - p0; // edge 3 - only for testing degenerate triangles Vector3 E3 = p2 - p0; if (E1.sqrMagnitude < 0.00001f || E2.sqrMagnitude < 0.00001f || E3.sqrMagnitude < 0.00001f) { // Skip degenerate triangle return(null); } //Begin calculating determinant - also used to calculate u parameter Vector3 P = Vector3.Cross(rayDirection, E2); float det = Vector3.Dot(E1, P); if (det > -0.00001f && det < 0.00001f) { //if determinant is near zero, ray lies in plane of triangle return(null); } float inv_det = 1.0f / det; //Calculate distance from V1 to ray origin Vector3 T = rayOrigin - p0; //Calculate u parameter and test bound float u = Vector3.Dot(T, P) * inv_det; if (u < 0.0f || u > 1.0f) { //The intersection lies outside of the triangle return(null); } //Prepare to test v parameter Vector3 Q = Vector3.Cross(T, E1); //Calculate V parameter and test bound float v = Vector3.Dot(rayDirection, Q) * inv_det; if (v < 0.0f || u + v > 1.0f) { //The intersection lies outside of the triangle return(null); } float t = Vector3.Dot(E2, Q) * inv_det; if (t <= 0.00001f) { // Intersection is before origin return(null); } // We have an intersection, now compute uv Vector3 hitPoint = rayOrigin + (rayDirection * t); Vector3 w = hitPoint - p0; Vector3 vCrossW = Vector3.Cross(E2, w); Vector3 vCrossU = Vector3.Cross(E2, E1); if (Vector3.Dot(vCrossW, vCrossU) < 0.0f) { return(null); } Vector3 uCrossW = Vector3.Cross(E1, w); Vector3 uCrossV = Vector3.Cross(E1, E2); if (Vector3.Dot(uCrossW, uCrossV) < 0.0f) { return(null); } float denom = uCrossV.magnitude; float b1 = vCrossW.magnitude / denom; float b2 = uCrossW.magnitude / denom; if ((b1 <= 1.0f) && (b2 <= 1.0f) && (b1 + b2 <= 1.0f)) { float b0 = 1.0f - b1 - b2; Vector2 uv0 = m_RaycastMeshUV[i0]; Vector2 uv1 = m_RaycastMeshUV[i1]; Vector2 uv2 = m_RaycastMeshUV[i2]; Vector2 uv = new Vector2(b0 * uv0.x + b1 * uv1.x + b2 * uv2.x, b0 * uv0.y + b1 * uv1.y + b2 * uv2.y); VRRaycastHit raycastHit = new VRRaycastHit(); raycastHit.collider = GetComponent <Collider>(); raycastHit.distance = t; raycastHit.normal = vCrossU.normalized; raycastHit.point = hitPoint; raycastHit.textureCoord = uv; return(raycastHit); } else { return(null); } }
protected void _RaySelection() { // Ray picking Vector3 rayOrigin = transform.position; Vector3 rayDirection = transform.TransformDirection(Vector3.forward); VRSelection newSelection = null; foreach (RaycastHit raycastHit in Physics.RaycastAll(rayOrigin, rayDirection, m_Wand.GetDefaultRayLength())) { if (newSelection != null && raycastHit.distance >= newSelection.SelectionDistance) { continue; } GameObject objectHit = raycastHit.collider.gameObject; if (objectHit.name != "VRWand") { // Ignore GameObject without the VRActor component if (objectHit.GetComponent<VRActor>() == null) { continue; } VRWebView webView = objectHit.GetComponent<VRWebView>(); VRRaycastHit completeHit = null; if (webView != null) { completeHit = webView.RaycastMesh(rayOrigin, rayDirection); } else { completeHit = new VRRaycastHit(raycastHit); } if (completeHit != null) { // Special case : pass through transparent pixels of web views. if (webView != null) { if (!webView.GetComponent<Renderer>().enabled || webView.IsPixelEmpty(completeHit.textureCoord)) { continue; } } // Create selection if it does not exist if (newSelection == null) { newSelection = new VRSelection(); } newSelection.SourceWand = m_Wand; newSelection.SelectedObject = objectHit; newSelection.TextureCoordinate = completeHit.textureCoord; newSelection.SelectionDistance = completeHit.distance; newSelection.SelectionContact = completeHit.point; newSelection.SelectionNormal = completeHit.normal; } } } m_LastSelection = m_SelectionMgr.GetSelection(); m_SelectionMgr.SetSelection(newSelection); }
private VRRaycastHit _RaycastTriangle(int i0, int i1, int i2, Vector3 rayOrigin, Vector3 rayDirection) { Vector3 p0 = transform.TransformPoint(m_RaycastMeshVertices[i0]); Vector3 p1 = transform.TransformPoint(m_RaycastMeshVertices[i1]); Vector3 p2 = transform.TransformPoint(m_RaycastMeshVertices[i2]); // Möller–Trumbore intersection algorithm // http://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm // edge 1 Vector3 E1 = p1 - p0; // edge 2 Vector3 E2 = p2 - p0; // edge 3 - only for testing degenerate triangles Vector3 E3 = p2 - p0; if( E1.sqrMagnitude < 0.00001f || E2.sqrMagnitude < 0.00001f || E3.sqrMagnitude < 0.00001f ) { // Skip degenerate triangle return null; } //Begin calculating determinant - also used to calculate u parameter Vector3 P = Vector3.Cross(rayDirection, E2); float det = Vector3.Dot(E1, P); if (det > -0.00001f && det < 0.00001f) { //if determinant is near zero, ray lies in plane of triangle return null; } float inv_det = 1.0f / det; //Calculate distance from V1 to ray origin Vector3 T = rayOrigin - p0; //Calculate u parameter and test bound float u = Vector3.Dot(T, P) * inv_det; if (u < 0.0f || u > 1.0f) { //The intersection lies outside of the triangle return null; } //Prepare to test v parameter Vector3 Q = Vector3.Cross(T, E1); //Calculate V parameter and test bound float v = Vector3.Dot(rayDirection, Q) * inv_det; if (v < 0.0f || u + v > 1.0f) { //The intersection lies outside of the triangle return null; } float t = Vector3.Dot(E2, Q) * inv_det; if (t <= 0.00001f) { // Intersection is before origin return null; } // We have an intersection, now compute uv Vector3 hitPoint = rayOrigin + (rayDirection * t); Vector3 w = hitPoint - p0; Vector3 vCrossW = Vector3.Cross(E2, w); Vector3 vCrossU = Vector3.Cross(E2, E1); if (Vector3.Dot(vCrossW, vCrossU) < 0.0f) { return null; } Vector3 uCrossW = Vector3.Cross(E1, w); Vector3 uCrossV = Vector3.Cross(E1, E2); if (Vector3.Dot(uCrossW, uCrossV) < 0.0f) { return null; } float denom = uCrossV.magnitude; float b1 = vCrossW.magnitude / denom; float b2 = uCrossW.magnitude / denom; if ((b1 <= 1.0f) && (b2 <= 1.0f) && (b1 + b2 <= 1.0f)) { float b0 = 1.0f - b1 - b2; Vector2 uv0 = m_RaycastMeshUV[i0]; Vector2 uv1 = m_RaycastMeshUV[i1]; Vector2 uv2 = m_RaycastMeshUV[i2]; Vector2 uv = new Vector2(b0 * uv0.x + b1 * uv1.x + b2 * uv2.x, b0 * uv0.y + b1 * uv1.y + b2 * uv2.y); VRRaycastHit raycastHit = new VRRaycastHit(); raycastHit.collider = GetComponent<Collider>(); raycastHit.distance = t; raycastHit.normal = vCrossU.normalized; raycastHit.point = hitPoint; raycastHit.textureCoord = uv; return raycastHit; } else { return null; } }
protected void _RaySelection() { // Ray picking Vector3 rayOrigin = transform.position; Vector3 rayDirection = transform.TransformDirection(Vector3.forward); VRSelection newSelection = null; foreach (RaycastHit raycastHit in Physics.RaycastAll(rayOrigin, rayDirection, m_Wand.GetDefaultRayLength())) { if (newSelection != null && raycastHit.distance >= newSelection.SelectionDistance) { continue; } GameObject objectHit = raycastHit.collider.gameObject; if (objectHit.name != "VRWand") { // Ignore GameObject without the VRActor component if (objectHit.GetComponent <VRActor>() == null) { continue; } VRWebView webView = objectHit.GetComponent <VRWebView>(); VRRaycastHit completeHit = null; if (webView != null) { completeHit = webView.RaycastMesh(rayOrigin, rayDirection); } else { completeHit = new VRRaycastHit(raycastHit); } if (completeHit != null) { // Special case : pass through transparent pixels of web views. if (webView != null) { if (!webView.GetComponent <Renderer>().enabled || webView.IsPixelEmpty(completeHit.textureCoord)) { continue; } } // Create selection if it does not exist if (newSelection == null) { newSelection = new VRSelection(); } newSelection.SourceWand = m_Wand; newSelection.SelectedObject = objectHit; newSelection.TextureCoordinate = completeHit.textureCoord; newSelection.SelectionDistance = completeHit.distance; newSelection.SelectionContact = completeHit.point; newSelection.SelectionNormal = completeHit.normal; } } } m_LastSelection = m_SelectionMgr.GetSelection(); m_SelectionMgr.SetSelection(newSelection); }