You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
3.5 KiB
122 lines
3.5 KiB
// DFVolume - Distance field volume generator for Unity
|
|
// https://github.com/keijiro/DFVolume
|
|
|
|
using UnityEngine;
|
|
|
|
namespace DFVolume
|
|
{
|
|
public class VolumeSampler : MonoBehaviour
|
|
{
|
|
#region Exposed attributes
|
|
|
|
[SerializeField] int _resolution = 50;
|
|
|
|
public int resolution {
|
|
get { return _resolution; }
|
|
}
|
|
|
|
[SerializeField] float _extent = 0.5f;
|
|
|
|
public float extent {
|
|
get { return _extent; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
#region Editor functions
|
|
|
|
void OnDrawGizmos()
|
|
{
|
|
Gizmos.matrix = transform.localToWorldMatrix;
|
|
Gizmos.color = Color.yellow;
|
|
Gizmos.DrawWireCube(Vector3.zero, Vector3.one * _extent * 2);
|
|
}
|
|
|
|
public Color[] GenerateBitmap()
|
|
{
|
|
// Generate a distance field.
|
|
var df = new float[_resolution * _resolution * _resolution];
|
|
|
|
for (var xi = 0; xi < _resolution; xi++)
|
|
{
|
|
var x = 2.0f * xi / (_resolution - 1) - 1;
|
|
for (var yi = 0; yi < _resolution; yi++)
|
|
{
|
|
var y = 2.0f * yi / (_resolution - 1) - 1;
|
|
for (var zi = 0; zi < _resolution; zi++)
|
|
{
|
|
var z = 2.0f * zi / (_resolution - 1) - 1;
|
|
|
|
var pt = new Vector3(x, y, z) * _extent;
|
|
pt = transform.TransformPoint(pt);
|
|
|
|
var dist = SearchDistance(pt) * 0.5f / _extent;
|
|
df[GetIndex(xi, yi, zi)] = dist;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Compute gradients and pack them into a bitmap.
|
|
var bmp = new Color[df.Length];
|
|
var dds2 = (_resolution - 1) / 2.0f;
|
|
|
|
for (var xi = 0; xi < _resolution; xi++)
|
|
{
|
|
for (var yi = 0; yi < _resolution; yi++)
|
|
{
|
|
for (var zi = 0; zi < _resolution; zi++)
|
|
{
|
|
var d = df[GetIndex(xi, yi, zi)];
|
|
var dx0 = df[GetIndex(xi - 1, yi, zi)];
|
|
var dx1 = df[GetIndex(xi + 1, yi, zi)];
|
|
var dy0 = df[GetIndex(xi, yi - 1, zi)];
|
|
var dy1 = df[GetIndex(xi, yi + 1, zi)];
|
|
var dz0 = df[GetIndex(xi, yi, zi - 1)];
|
|
var dz1 = df[GetIndex(xi, yi, zi + 1)];
|
|
|
|
bmp[GetIndex(xi, yi, zi)] = new Color(
|
|
(dx1 - dx0) * dds2,
|
|
(dy1 - dy0) * dds2,
|
|
(dz1 - dz0) * dds2,
|
|
d
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
return bmp;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Private functions
|
|
|
|
int GetIndex(int xi, int yi, int zi)
|
|
{
|
|
xi = Mathf.Clamp(xi, 0, _resolution - 1);
|
|
yi = Mathf.Clamp(yi, 0, _resolution - 1);
|
|
zi = Mathf.Clamp(zi, 0, _resolution - 1);
|
|
return xi + _resolution * (yi + _resolution * zi);
|
|
}
|
|
|
|
float SearchDistance(Vector3 pt)
|
|
{
|
|
var r = _extent;
|
|
var s = _extent * 0.5f;
|
|
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
r += (Physics.CheckSphere(pt, r) ? -1 : 1) * s;
|
|
s *= 0.5f;
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endif
|
|
}
|
|
}
|
|
|