private void OnCollisionEnter(Collision collision) { if (collision.gameObject.layer == 8) // collider layer { Debug.Log("Hit Raycast Layer!"); var contacts = collision.contacts; Vector3 pos = contacts[0].point; Vector3 nrm = contacts[0].normal; // we need to fire a ray from contact point into mesh to allow // for material reaction Ray r = new Ray(pos + (nrm * 0.01f), -nrm); APARaycastHit hit; MaterialStruct mat; if (MaterialRayCastSystem.RayVsSceneMaterial(r, out hit, out mat)) { // Depending on material it should maybe shatter? if (mat.m_breakOnImpact == 1) { // Spawn sounds yey { GameObject soundSpawn = new GameObject(); soundSpawn.transform.position = transform.position; var ac = soundSpawn.AddComponent <AudioSource>(); int randIndex = Random.Range(0, m_brokenSoundFX.Count); ac.clip = m_brokenSoundFX[randIndex]; ac.Play(); } // Trigger Game Reaction Vector3 hitWsPosition = hit.point; Vector3 hitWsNormal = hit.transform.TransformVector(hit.normal); // Shatter var particle = Instantiate(m_explosionParticle) as GameObject; particle.transform.SetPositionAndRotation(hitWsPosition, Quaternion.LookRotation(hitWsNormal, Vector3.up)); m_gameController.GameReaction(hitWsPosition, hitWsNormal, mat); Destroy(gameObject); } } } }
private void MeshPreProcessInteractionRoutine() { Ray r = m_meshRenderCamera.ScreenPointToRay(Input.mousePosition); APARaycastHit hit; MaterialStruct mat; if (MaterialRayCastSystem.RayVsSceneMaterial(r, out hit, out mat)) { Vector3 hitWsPosition = hit.point; Vector3 hitWsNormal = hit.transform.TransformVector(hit.normal); GameReaction(hitWsPosition, hitWsNormal, mat); } else { m_uiMaterialColourOutput.color = m_errorColour; m_uiMaterialTextOutput.text = "No Data / Ray Missed "; } }
// Has to be OnPostRender so we can grab render targets safely private void OnPostRender() { if (m_lastWidth != Screen.width || m_lastHeight != Screen.height) { OnResize(); } if (m_rayCastTriggered) { m_rayCastTriggered = false; var zDepth = m_textureOverlay.depthXYZZed; // Store current RT RenderTexture currentRT = RenderTexture.active; // Create new render target to copy { RenderTexture.active = m_zedRT; Graphics.Blit(zDepth, m_zedRT); Texture2D zedReadable = new Texture2D(zDepth.width, zDepth.height, zDepth.format, false); zedReadable.ReadPixels(new Rect(0, 0, m_zedRT.width, m_zedRT.height), 0, 0); zedReadable.Apply(); Vector2 relMousePos = new Vector2(); relMousePos.x = m_mousePositionWhenTriggered.x / Screen.width; relMousePos.y = m_mousePositionWhenTriggered.y / Screen.height; Vector2 dPixUv = relMousePos; dPixUv.y = 1.0f - dPixUv.y; dPixUv.x *= zedReadable.width; dPixUv.y *= zedReadable.height; // this only works for starting camera position and rotation var depthPixelData = zedReadable.GetPixel((int)dPixUv.x, (int)dPixUv.y); var matPixelData = new Color(0, 0, 0, 0); MaterialStruct matFound = null; if (m_materialColourTexture != null) { Vector2 mPixUv = relMousePos; mPixUv.y = 1.0f - mPixUv.y; mPixUv.x *= m_materialColourTexture.width; mPixUv.y *= m_materialColourTexture.height; matPixelData = m_materialColourTexture.GetPixel((int)mPixUv.x, (int)mPixUv.y); matFound = MaterialRayCastSystem.FindMaterialStructFromColour(matPixelData); } // Need to guard against uninit areas of pixels // This can happen if camera hasn't been able to do depth properly in area if ( float.IsNaN(depthPixelData.r) || float.IsInfinity(depthPixelData.r) || float.IsNaN(depthPixelData.g) || float.IsInfinity(depthPixelData.g) || float.IsNaN(depthPixelData.b) || float.IsInfinity(depthPixelData.b) ) { return; } // If changed process of getting this position, then remember to udpate for loop at bottom Vector3 cVsPos = new Vector3(depthPixelData.r, depthPixelData.g, -depthPixelData.b); // get back into object space Matrix4x4 inverseView = m_zedCamera.worldToCameraMatrix.inverse; Vector3 cWsPos = inverseView * new Vector4(cVsPos.x, cVsPos.y, cVsPos.z, 1.0f); // Now we need to find the normal.... { // https://stackoverflow.com/questions/37627254/how-to-reconstruct-normal-from-depth-without-artifacts-on-edge // [ ] // [ ] [x] [ ] // [ ] // 4 samples around edge // find the closest sample top and bottom, left and right relative to center sample // then normalise cross product on it? (x dir, y dir) Vector2[] offsets = new Vector2[4] { new Vector2(0, 15), new Vector2(0, -15), new Vector2(15, 0), new Vector2(-15, 0) }; Vector3[] wsPositions = new Vector3[4]; float[] distToCenter = new float[4]; for (int i = 0; i < 4; i++) { Vector2 uvOffset = dPixUv + offsets[i]; Color sample = zedReadable.GetPixel((int)uvOffset.x, (int)uvOffset.y); Vector4 vsPos = new Vector4(sample.r, sample.g, -sample.b, 1.0f); // Calculate WS POS Vector3 sampleWsPos = inverseView * vsPos; distToCenter[i] = Vector3.Distance(cWsPos, sampleWsPos); wsPositions[i] = sampleWsPos; } int verticalSampleIndex = 0; int horizontalSampleIndex = 2; // Find closest vertical sample if (distToCenter[0] > distToCenter[1]) { verticalSampleIndex = 1; } // Find closest horizontal sample if (distToCenter[2] > distToCenter[3]) { horizontalSampleIndex = 3; } Vector3 normalGen = Vector3.Cross(wsPositions[verticalSampleIndex] - cWsPos, wsPositions[horizontalSampleIndex] - cWsPos); normalGen.Normalize(); // Update Game Reaction m_gameController.GameReaction(cWsPos, normalGen, matFound); } } // Restore original active render texture RenderTexture.active = currentRT; } }