303 lines
12 KiB
C#
303 lines
12 KiB
C#
|
using System.Collections.Generic;
|
||
|
using UnityEngine;
|
||
|
|
||
|
public class Environment : MonoBehaviour
|
||
|
{
|
||
|
public int sizeX = 100;
|
||
|
public int sizeY = 100;
|
||
|
public int sizeZ = 100;
|
||
|
public float voxelSize = 0.1f;
|
||
|
|
||
|
public bool visualizeLigth = true;
|
||
|
public int visualizeEveryNVoxel = 100;
|
||
|
|
||
|
// Voxel[,,] voxelSpace;
|
||
|
byte[,,] voxelSpace;
|
||
|
|
||
|
public bool rotateTowardsLight = false;
|
||
|
public bool sendShadowToLSystem = true;
|
||
|
public bool cutBranchesWithMaxShadow = false;
|
||
|
|
||
|
List<List<Matrix4x4>> transformListJ;
|
||
|
|
||
|
// Start is called before the first frame update
|
||
|
public void Reset()
|
||
|
{
|
||
|
Start();
|
||
|
}
|
||
|
void Start()
|
||
|
{
|
||
|
voxelSpace = new byte[sizeX, sizeY, sizeZ];
|
||
|
for (int i = 0; i < sizeX; i++)
|
||
|
{
|
||
|
for (int k = 0; k < sizeZ; k++)
|
||
|
{
|
||
|
for (int j = sizeY - 1; j >= 0; j--)
|
||
|
{
|
||
|
voxelSpace[i, j, k] = (byte)1;
|
||
|
if (i == 0 || i == sizeX - 1 || k == 0 || k == sizeZ - 1)
|
||
|
{
|
||
|
voxelSpace[i, j, k] = (byte)255;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
List<Matrix4x4> transformList = new List<Matrix4x4>();
|
||
|
transformListJ = new List<List<Matrix4x4>>();
|
||
|
for (int i = 0; i < sizeX; i++)
|
||
|
{
|
||
|
for (int k = 0; k < sizeZ; k++)
|
||
|
{
|
||
|
for (int j = sizeY - 1; j >= 0; j--)
|
||
|
{
|
||
|
if (visualizeLigth &&
|
||
|
(i % visualizeEveryNVoxel == 0 && j % visualizeEveryNVoxel == 0 && k % visualizeEveryNVoxel == 0))
|
||
|
{
|
||
|
Vector3 position = gameObject.GetComponent<Transform>().position;
|
||
|
Matrix4x4 matrixLigth = new Matrix4x4();
|
||
|
|
||
|
//Take the origin position, and apply the offsets
|
||
|
position.x += i * voxelSize;
|
||
|
position.y += j * voxelSize;
|
||
|
position.z += k * voxelSize;
|
||
|
|
||
|
//Create a matrix for the position created from this iteration of the loop
|
||
|
|
||
|
//Set the position/rotation/scale for this matrix
|
||
|
if (voxelSpace[i, j, k] != null)
|
||
|
{
|
||
|
matrixLigth.SetTRS(position, Quaternion.Euler(Vector3.zero), new Vector3(voxelSpace[i, j, k] * voxelSize * visualizeEveryNVoxel / 255.0f, voxelSpace[i, j, k] * voxelSize * visualizeEveryNVoxel / 255.0f, voxelSpace[i, j, k] * voxelSize * visualizeEveryNVoxel / 255.0f));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
matrixLigth.SetTRS(position, Quaternion.Euler(Vector3.zero), new Vector3(0, 0, 0));
|
||
|
}
|
||
|
transformList.Add(matrixLigth);
|
||
|
}
|
||
|
if (transformList.Count > 1020)
|
||
|
{
|
||
|
transformListJ.Add(transformList);
|
||
|
transformList = new List<Matrix4x4>();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (transformList.Count > 0)
|
||
|
{
|
||
|
transformListJ.Add(transformList);
|
||
|
transformList = new List<Matrix4x4>();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update is called once per frame
|
||
|
int frame = 0;
|
||
|
void Update()
|
||
|
{
|
||
|
if (frame % 300 == 0)
|
||
|
{
|
||
|
int mxx = 0;
|
||
|
Vector3 pos = new Vector3(0, 0, 0);
|
||
|
for (int j = sizeY - 1; j >= 0; j--)
|
||
|
{
|
||
|
for (int i = 0; i < sizeX; i++)
|
||
|
{
|
||
|
for (int k = 0; k < sizeZ; k++)
|
||
|
{
|
||
|
if (voxelSpace[i, j, k] > mxx)
|
||
|
{
|
||
|
mxx = voxelSpace[i, j, k];
|
||
|
pos = new Vector3(i, j, k);
|
||
|
// Debug.Log("mxPos = "+mxx+" "+pos);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
frame += 1;
|
||
|
// Debug.Log("frame"+frame);
|
||
|
}
|
||
|
public void addShadowPoint(Vector3 position, sbyte strength) // negative value to remove
|
||
|
{
|
||
|
Vector3 voxelPosition = positionInVoxel(position);
|
||
|
Debug.Log(voxelPosition + " adding " + strength);
|
||
|
if (inVoxelSpace((int)voxelPosition.x, (int)voxelPosition.y, (int)voxelPosition.z))
|
||
|
{
|
||
|
voxelSpace[(int)voxelPosition.x, (int)voxelPosition.y, (int)voxelPosition.z] += (byte)strength;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Debug.Log("not in vexel space: " + voxelPosition + " - error adding");
|
||
|
}
|
||
|
|
||
|
}
|
||
|
public void removeShadow(Vector3 position, sbyte strength) // negative value to remove
|
||
|
{
|
||
|
addShadow(position, (sbyte)-strength);
|
||
|
}
|
||
|
public void addShadow(Vector3 position, sbyte strength) // negative value to remove
|
||
|
{
|
||
|
// 6.2 / 0.1 = 62.0
|
||
|
Vector3 voxelPosition = positionInVoxel(position);
|
||
|
for (int j = (int)voxelPosition.y; j >= 0; j--)
|
||
|
{
|
||
|
if (voxelPosition.y - j > 250)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
int rotj = (int)(voxelPosition.y - j) * 1;
|
||
|
for (int i = (int)voxelPosition.x - rotj; i <= (int)voxelPosition.x + rotj; i++)
|
||
|
{
|
||
|
for (int k = (int)voxelPosition.z - rotj; k <= (int)voxelPosition.z + rotj; k++)
|
||
|
{
|
||
|
|
||
|
if (inVoxelSpace(i, j, k) &&
|
||
|
(i % visualizeEveryNVoxel == 0 && j % visualizeEveryNVoxel == 0 && k % visualizeEveryNVoxel == 0))
|
||
|
{
|
||
|
float secondaryStrength = 1.0f * strength;
|
||
|
secondaryStrength = secondaryStrength / ((Mathf.Abs(k - (int)voxelPosition.z) + 1 + Mathf.Abs(i - (int)voxelPosition.x)) / 8.0f);
|
||
|
if (voxelSpace[i, j, k] == null)
|
||
|
{
|
||
|
voxelSpace[i, j, k] = 0;
|
||
|
}
|
||
|
if (secondaryStrength > 0)
|
||
|
{
|
||
|
if (voxelSpace[i, j, k] >= 255 - (byte)secondaryStrength)
|
||
|
{
|
||
|
voxelSpace[i, j, k] = 255;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
voxelSpace[i, j, k] += (byte)secondaryStrength;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (voxelSpace[i, j, k] > (byte)secondaryStrength)
|
||
|
{
|
||
|
voxelSpace[i, j, k] -= (byte)(-1 * secondaryStrength);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
voxelSpace[i, j, k] = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((i % visualizeEveryNVoxel == 0 && j % visualizeEveryNVoxel == 0 && k % visualizeEveryNVoxel == 0) && visualizeLigth)
|
||
|
{
|
||
|
Vector3 positionBox = gameObject.GetComponent<Transform>().position;
|
||
|
Matrix4x4 matrixLigth = new Matrix4x4();
|
||
|
|
||
|
//Take the origin position, and apply the offsets
|
||
|
positionBox.x += i * voxelSize;
|
||
|
positionBox.y += j * voxelSize;
|
||
|
positionBox.z += k * voxelSize;
|
||
|
|
||
|
//Create a matrix for the position created from this iteration of the loop
|
||
|
|
||
|
//Set the position/rotation/scale for this matrix
|
||
|
matrixLigth.SetTRS(positionBox, Quaternion.Euler(Vector3.zero), new Vector3(voxelSpace[i, j, k] * voxelSize * visualizeEveryNVoxel / 255.0f, voxelSpace[i, j, k] * voxelSize * visualizeEveryNVoxel / 255.0f, voxelSpace[i, j, k] * voxelSize * visualizeEveryNVoxel / 255.0f));
|
||
|
int l = (i * sizeZ * sizeY / (visualizeEveryNVoxel * visualizeEveryNVoxel * visualizeEveryNVoxel) + k * sizeY / (visualizeEveryNVoxel * visualizeEveryNVoxel) + j / visualizeEveryNVoxel);
|
||
|
transformListJ[l / 1021][l % 1021] = matrixLigth;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
public void addShadowLine(Vector3 positionStart, Vector3 positionEnd, sbyte strength) // negative value to remove
|
||
|
{
|
||
|
int linePoints = (int)((Mathf.Abs(positionEnd.x - positionStart.x) + Mathf.Abs(positionEnd.z - positionStart.z)) / (voxelSize));
|
||
|
if (linePoints < 3)
|
||
|
{
|
||
|
linePoints = 3;
|
||
|
}
|
||
|
Vector3 stepChange = new Vector3(
|
||
|
(positionEnd.x - positionStart.x) / linePoints,
|
||
|
(positionEnd.y - positionStart.y) / linePoints,
|
||
|
(positionEnd.z - positionStart.z) / linePoints);
|
||
|
Vector3 positionNow = positionStart;
|
||
|
sbyte newStrength = (sbyte)(2 * (strength / linePoints));
|
||
|
if (newStrength == 0)
|
||
|
{
|
||
|
if (strength > 0)
|
||
|
{
|
||
|
if (strength > 0.4f)
|
||
|
newStrength = (sbyte)1;
|
||
|
}
|
||
|
if (strength < 0)
|
||
|
{
|
||
|
newStrength = (sbyte)-1;
|
||
|
}
|
||
|
}
|
||
|
for (int i = 0; i < linePoints; i++)
|
||
|
{
|
||
|
addShadow(positionNow, newStrength);
|
||
|
positionNow += stepChange;
|
||
|
}
|
||
|
}
|
||
|
bool inVoxelSpace(int a, int b, int c)
|
||
|
{
|
||
|
return (a < sizeX && a >= 0 && b < sizeY && b >= 0 && c < sizeZ && c >= 0);
|
||
|
}
|
||
|
public Vector3 positionInVoxel(Vector3 positionInWorld)
|
||
|
{
|
||
|
Vector3 voxelPosition = new Vector3(0.0f, 0.0f, 0.0f);
|
||
|
positionInWorld -= gameObject.GetComponent<Transform>().position;
|
||
|
voxelPosition.x = (int)(0.5f + (positionInWorld.x / voxelSize));
|
||
|
voxelPosition.y = (int)(0.5f + (positionInWorld.y / voxelSize));
|
||
|
voxelPosition.z = (int)(0.5f + (positionInWorld.z / voxelSize));
|
||
|
return voxelPosition;
|
||
|
}
|
||
|
|
||
|
public Vector3 positionInWorld(Vector3 positionInVoxel)
|
||
|
{
|
||
|
return positionInVoxel * voxelSize + gameObject.GetComponent<Transform>().position;
|
||
|
}
|
||
|
public void groundShape()
|
||
|
{
|
||
|
|
||
|
for (int i = 0; i < sizeX; i++)
|
||
|
{
|
||
|
for (int k = 0; k < sizeZ; k++)
|
||
|
{
|
||
|
for (int j = sizeY - 1; j >= 0; j--)
|
||
|
{
|
||
|
|
||
|
Collider[] hitColliders = Physics.OverlapSphere(new Vector3(i * voxelSize, j * voxelSize, k * voxelSize), voxelSize / 2.0f);
|
||
|
foreach (var hitCollider in hitColliders)
|
||
|
{
|
||
|
addShadow(new Vector3(i * voxelSize, j * voxelSize, k * voxelSize), 100);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
public byte shadowStrength(Vector3 pos)
|
||
|
{
|
||
|
Vector3 shadowPosition = positionInVoxel(pos);//pos - gameObject.GetComponent<Transform>().position;
|
||
|
if (inVoxelSpace((int)((shadowPosition.x)), (int)((shadowPosition.y)), (int)((shadowPosition.z))))
|
||
|
{
|
||
|
byte mx = voxelSpace[0 + (int)((shadowPosition.x)), (int)((shadowPosition.y)), 0 + (int)((shadowPosition.z))];
|
||
|
return mx;
|
||
|
}
|
||
|
return 255;
|
||
|
}
|
||
|
public bool isShadow(Vector3 pos)
|
||
|
{
|
||
|
if (shadowStrength(pos) > 10)
|
||
|
{
|
||
|
// Debug.Log("#shadow");
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|