// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. using HoloToolkit.Unity.InputModule; using UnityEngine; namespace HoloToolkit.Unity { /// <summary> /// Controls slicing planes for use in volumetric rendering /// Planes represent manipulatable viewable regions of the volume /// </summary> public class SlicingPlaneController : MonoBehaviour, IManipulationHandler { public float KeyboardMovementSpeed = 1.5f; public float GestureMovementSpeed = 1.0f; public GameObject PlaneX; public GameObject PlaneY; public GameObject PlaneZ; private bool wasThickSliceEnabled; public bool ThickSliceEnabled = true; public Material SliceMaterial; public Material ThickSliceMaterial; public void SetMaterial(Material mat) { PlaneX.GetComponent<Renderer>().sharedMaterial = mat; PlaneY.GetComponent<Renderer>().sharedMaterial = mat; PlaneZ.GetComponent<Renderer>().sharedMaterial = mat; } private void OnEnable() { //force initial material setting in case user has made strange editor changes wasThickSliceEnabled = !ThickSliceEnabled; InputManager.Instance.AddGlobalListener(this.gameObject); } private void OnDisable() { InputManager.Instance.RemoveGlobalListener(this.gameObject); } public void SetThickSliceEnabled(bool on) { this.ThickSliceEnabled = on; } private void Update() { HandleDebugKeys(); Vector4 planeEquation; var forward = this.transform.forward; var pos = this.transform.position; planeEquation.x = forward.x; planeEquation.y = forward.y; planeEquation.z = forward.z; //dot product planeEquation.w = (planeEquation.x * pos.x + planeEquation.y * pos.y + planeEquation.z * pos.z); Shader.SetGlobalVector("CutPlane", planeEquation); var cornerPos = this.transform.localPosition; var slabMin = new Vector4(cornerPos.x - 0.5f, cornerPos.y - 0.5f, cornerPos.z - 0.5f, 0.0f); var slabMax = new Vector4(cornerPos.x + 0.5f, cornerPos.y + 0.5f, cornerPos.z + 0.5f, 0.0f); Shader.SetGlobalVector("SlabMin", slabMin); Shader.SetGlobalVector("SlabMax", slabMax); if (ThickSliceEnabled != wasThickSliceEnabled) { SetMaterial(ThickSliceEnabled ? ThickSliceMaterial : SliceMaterial); wasThickSliceEnabled = ThickSliceEnabled; } Shader.SetGlobalMatrix("_SlicingWorldToLocal", this.transform.worldToLocalMatrix); } void HandleDebugKeys() { float movementDelta = KeyboardMovementSpeed * Time.deltaTime; var positionDeltaX = this.transform.localRotation * new Vector3(movementDelta, 0.0f, 0.0f); var positionDeltaY = this.transform.localRotation * new Vector3(0.0f, movementDelta, 0.0f); var positionDeltaZ = this.transform.localRotation * new Vector3(0.0f, 0.0f, movementDelta); if (Input.GetKey(KeyCode.L)) { this.transform.localPosition += positionDeltaX; } if (Input.GetKey(KeyCode.J)) { this.transform.localPosition -= positionDeltaX; } if (Input.GetKey(KeyCode.I)) { this.transform.localPosition += positionDeltaY; } if (Input.GetKey(KeyCode.K)) { this.transform.localPosition -= positionDeltaY; } if (Input.GetKey(KeyCode.RightBracket)) { this.transform.localPosition += positionDeltaZ; } if (Input.GetKey(KeyCode.LeftBracket)) { this.transform.localPosition -= positionDeltaZ; } } public void OnManipulationStarted(ManipulationEventData eventData) { } public void OnManipulationUpdated(ManipulationEventData eventData) { float movementDelta = GestureMovementSpeed * Time.deltaTime; //TODO: consider tether filter this.transform.localPosition += this.transform.localRotation * eventData.CumulativeDelta * movementDelta; } public void OnManipulationCompleted(ManipulationEventData eventData) { } public void OnManipulationCanceled(ManipulationEventData eventData) { } } }