Simple Runtime Placement
The attached Unity package contains an example of a simple decal placement on a car.
Code
using UnityEngine;
using System.Collections;
using ch.sycoforge.Decal;
public class DecalPlacement : MonoBehaviour
{
//---------------------------------
// Exposed Fields
//---------------------------------
public EasyDecal Decal;
public float PlacementOffset = 4;
public float RotationSpeed = 6;
public float Rotation;
public float ScaleSpeed = 1;
public Vector2 Scale = Vector2.one;
public bool Editable;
//---------------------------------
// Fields
//---------------------------------
private Camera ActiveCamera;
//---------------------------------
// Constants
//---------------------------------
private const string ROT_INPUT_NAME = "Mouse ScrollWheel";
private const string VER_INPUT_NAME = "Vertical";
private const string HOR_INPUT_NAME = "Horizontal";
//---------------------------------
// Mehods
//---------------------------------
private void Start()
{
// Take main camera if no camera specified
if(ActiveCamera == null)
{
ActiveCamera = Camera.main;
}
}
private void Update ()
{
ChangeAtlasIndex();
if(Input.GetKeyDown(KeyCode.E))
{
Editable = !Editable;
Decal.Baked = !Editable;
}
if (!Editable) { return; }
MoveRotateDecal();
ScaleDecal();
}
private void ChangeAtlasIndex()
{
int dir = 0;
if (Input.GetKeyDown(KeyCode.Y)) { dir = 1; }
if (Input.GetKeyDown(KeyCode.X)) { dir = -1; }
if(dir != 0)
{
Decal.Baked = false;
Decal.AtlasRegionIndex += dir;
Decal.LateBake();
}
}
private void MoveRotateDecal()
{
float delta = Input.GetAxis(ROT_INPUT_NAME);
// Scroll event received
if (Mathf.Abs(delta) > 0f)
{
// Sum delta rotation
Rotation += delta * RotationSpeed * Time.deltaTime * 1000.0f;
}
Vector2 screenPoint = Input.mousePosition;
// Ray from camera's origin
Ray ray = ActiveCamera.ScreenPointToRay(screenPoint);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, ActiveCamera.farClipPlane))
{
Vector3 avgNormal = AverageNormal(screenPoint, PlacementOffset);
Quaternion quat = Quaternion.AngleAxis(Rotation, avgNormal) * Quaternion.FromToRotation(Vector3.up, avgNormal);
// Apply decal transformations
Decal.CachedTransform.position = hit.point + avgNormal * 0.2f;
Decal.CachedTransform.rotation = quat;
}
}
private void ScaleDecal()
{
float v = Input.GetAxis(VER_INPUT_NAME) * ScaleSpeed;
float h = Input.GetAxis(HOR_INPUT_NAME) * ScaleSpeed;
// Return if no input changes
if (!(Mathf.Abs(v) > 0f || Mathf.Abs(h) > 0))
{
return;
}
// Sum delta scale
Scale += new Vector2(h, v) * Time.deltaTime;
Decal.CachedTransform.localScale = new Vector3(Scale.x, 1.0f, Scale.y);
}
private Vector3 AverageNormal(Vector2 screenPoint, float offset)
{
Vector3 normal = Vector3.zero;
Camera cam = Camera.current;
int hits = 0;
Vector2[] offsets = new Vector2[]
{
new Vector2(0, offset),
new Vector2(offset, offset),
new Vector2(offset, 0),
new Vector2(offset, -offset),
new Vector2(0, -offset),
new Vector2(-offset, -offset),
new Vector2(-offset, 0),
new Vector2(-offset, offset)
};
for (int i = 0; i < offsets.Length; i++)
{
Ray ray = ActiveCamera.ScreenPointToRay(screenPoint + offsets[i]);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 1000.0f))
{
normal += hit.normal;
hits++;
}
}
return normal / hits;
}
}
Download