Skip to content

Instantly share code, notes, and snippets.

@toxicFork

toxicFork/ClippableObject.cs Secret

Created Mar 16, 2015
Embed
What would you like to do?
using UnityEngine;
using System.Collections;
using System.Linq;
[ExecuteInEditMode]
public class ClippableObject : MonoBehaviour {
public void OnEnable() {
//let's just create a new material instance.
GetComponent<MeshRenderer>().sharedMaterial = new Material(Shader.Find("Custom/StandardClippable")) {
hideFlags = HideFlags.HideAndDontSave
};
}
public void Start() { }
//only 3 clip planes for now, will need to modify the shader for more.
[Range(0, 3)]
public int clipPlanes = 0;
//preview size for the planes. Shown when the object is selected.
public float planePreviewSize = 5.0f;
//Positions and rotations for the planes. The rotations will be converted into normals to be used by the shaders.
public Vector3 plane1Position = Vector3.zero;
public Vector3 plane1Rotation = new Vector3(0, 0, 0);
public Vector3 plane2Position = Vector3.zero;
public Vector3 plane2Rotation = new Vector3(0, 90, 90);
public Vector3 plane3Position = Vector3.zero;
public Vector3 plane3Rotation = new Vector3(0, 0, 90);
//Only used for previewing a plane. Draws diagonals and edges of a limited flat plane.
private void DrawPlane(Vector3 position, Vector3 euler) {
var forward = Quaternion.Euler(euler) * Vector3.forward;
var left = Quaternion.Euler(euler) * Vector3.left;
var forwardLeft = position + forward * planePreviewSize * 0.5f + left * planePreviewSize * 0.5f;
var forwardRight = forwardLeft - left * planePreviewSize;
var backRight = forwardRight - forward * planePreviewSize;
var backLeft = forwardLeft - forward * planePreviewSize;
Gizmos.DrawLine(position, forwardLeft);
Gizmos.DrawLine(position, forwardRight);
Gizmos.DrawLine(position, backRight);
Gizmos.DrawLine(position, backLeft);
Gizmos.DrawLine(forwardLeft, forwardRight);
Gizmos.DrawLine(forwardRight, backRight);
Gizmos.DrawLine(backRight, backLeft);
Gizmos.DrawLine(backLeft, forwardLeft);
}
private void OnDrawGizmosSelected() {
if (clipPlanes >= 1) {
DrawPlane(plane1Position, plane1Rotation);
}
if (clipPlanes >= 2) {
DrawPlane(plane2Position, plane2Rotation);
}
if (clipPlanes >= 3) {
DrawPlane(plane3Position, plane3Rotation);
}
}
//Ideally the planes do not need to be updated every frame, but we'll just keep the logic here for simplicity purposes.
public void Update()
{
var sharedMaterial = GetComponent<MeshRenderer>().sharedMaterial;
//Only should enable one keyword. If you want to enable any one of them, you actually need to disable the others.
//This may be a bug...
switch (clipPlanes) {
case 0:
sharedMaterial.DisableKeyword("CLIP_ONE");
sharedMaterial.DisableKeyword("CLIP_TWO");
sharedMaterial.DisableKeyword("CLIP_THREE");
break;
case 1:
sharedMaterial.EnableKeyword("CLIP_ONE");
sharedMaterial.DisableKeyword("CLIP_TWO");
sharedMaterial.DisableKeyword("CLIP_THREE");
break;
case 2:
sharedMaterial.DisableKeyword("CLIP_ONE");
sharedMaterial.EnableKeyword("CLIP_TWO");
sharedMaterial.DisableKeyword("CLIP_THREE");
break;
case 3:
sharedMaterial.DisableKeyword("CLIP_ONE");
sharedMaterial.DisableKeyword("CLIP_TWO");
sharedMaterial.EnableKeyword("CLIP_THREE");
break;
}
//pass the planes to the shader if necessary.
if (clipPlanes >= 1)
{
sharedMaterial.SetVector("_planePos", plane1Position);
//plane normal vector is the rotated 'up' vector.
sharedMaterial.SetVector("_planeNorm", Quaternion.Euler(plane1Rotation) * Vector3.up);
}
if (clipPlanes >= 2)
{
sharedMaterial.SetVector("_planePos2", plane2Position);
sharedMaterial.SetVector("_planeNorm2", Quaternion.Euler(plane2Rotation) * Vector3.up);
}
if (clipPlanes >= 3)
{
sharedMaterial.SetVector("_planePos3", plane3Position);
sharedMaterial.SetVector("_planeNorm3", Quaternion.Euler(plane3Rotation) * Vector3.up);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment