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> 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 transformList = new List(); transformListJ = new List>(); 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().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(); } } } } if (transformList.Count > 0) { transformListJ.Add(transformList); transformList = new List(); } } // 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().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().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().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().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; } } }