Modelowanie_Wirtualnych_Swi.../Assets/Scripts/env/Environment.cs
2021-05-24 23:27:23 +02:00

400 lines
14 KiB
C#

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<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>();
}
// 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<transformListJ.Count;i++)
{
Graphics.DrawMeshInstanced(shape.GetComponent<MeshFilter>().mesh, 0, shape.GetComponent<MeshRenderer>().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<Transform>().position = pos*voxelSize+gameObject.GetComponent<Transform>().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<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))];
// 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<Transform>().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;
}
}
// }
}
}