using System.Collections; 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 visualizeWater = true; public bool visualizeLigth = true; public int visualizeEveryNVoxel = 100; public GameObject shape; public GameObject ball; // Voxel[,,] voxelSpace; byte[,,] voxelSpace; private Bounds bounds; public Material material; public bool rotateTowardsLight = false; public bool sendShadowToLSystem = true; public bool cutBranchesWithMaxShadow = false; private ComputeBuffer meshPropertiesBuffer; private ComputeBuffer argsBuffer; 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(); } // Debug.Log("G_first_frame_end"); } // Update is called once per frame int frame = 0; void Update() { if(frame > 60) { for(int i = 0;i().mesh, 0, shape.GetComponent().material, transformListJ[i], null, UnityEngine.Rendering.ShadowCastingMode.Off, false); } } 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); } } } } ball.GetComponent().position = pos*voxelSize+gameObject.GetComponent().position; ball.name = "shadow max = "+mxx; // Debug.Log("mxShadow = "+mxx); } 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); // Debug.Log("j "+j+" i "+(i-voxelPosition.x)+" s "+(sbyte)secondaryStrength); // voxelSpace[i,j,k].addShadow((sbyte)secondaryStrength); // if(secondaryStrength<3) // { // return; // } 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=0&&b=0&&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))]; // if(mx >10) // { // Debug.Log("#shadowPosA " + (int)((shadowPosition.x))+" "+(int)((shadowPosition.y))+" "+(int)((shadowPosition.z))+" = "+voxelSpace[(int)((shadowPosition.x)),(int)((shadowPosition.y)),(int)((shadowPosition.z))]+" ("+mx+") "); //// Instantiate(ball, positionInWorld(shadowPosition), Quaternion.Euler(0,0,0)); // } return mx; } return 255; } public bool isShadow(Vector3 pos) { if(shadowStrength(pos) > 10) { // Debug.Log("#shadow"); return true; } else { return false; } } } public class Voxel { public byte shadow = 0; // 0 - 1 // public int x = 0; // public int y = 0; // public int z = 0; // public float voxelSize = 0.1f; // public Matrix4x4 matrixWater = new Matrix4x4(); // public Matrix4x4 matrixLigth = new Matrix4x4(); // public void updateWater() // { // if(y > 0) // { // if(water > waterAbsortion) // { // if(waterTransmission < (water - waterAbsortion)) // { // waterChange = -1.0f * waterTransmission; // } // else // { // waterChange = -1.0f * (water - waterAbsortion); // } // } // } // } // public void applyChanges(float change) // { // water += waterChange+change; // waterChange = 0.0f; //// shape.GetComponent().localScale = new Vector3(water*0.5f*voxelSize, water*0.5f*voxelSize, water*0.5f*voxelSize); // // // } public void addShadow(sbyte strength) { if(strength > 0) { if(shadow >= 255-strength) { shadow = 255; } else { shadow += (byte)strength; } } else { if(shadow > strength) { shadow -= (byte)(-1*strength); } else { shadow = 0; } } // } } }