ZMWSLI0-SL2021-GR11/cw5/zadanie3.cs
2021-05-20 21:16:43 +02:00

283 lines
12 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using ConsoleLSystem;
using System;
using System.Linq;
abstract public class TurtleLSystemEnvironment : TurtleLSystem {
public Environment environment;
// private LSystemEvaluator evaluator = null;
// private float nextStep;
public sbyte shadowStrength;
public int lookForLightAngle = 35;
public float lookForLightLength = 2.0f;
public Matrix4x4 lightDirection(Matrix4x4 transformation, Matrix4x4 resultTransformation, GameObject shape, LSystemNode node)
{
int minShadow = 10000;
Matrix4x4 bestTransformation = transformation;
int maxShadowTries = 20;
int shadowRotate = 360/20;
int shadowStrength_ = 0;
bool clearShape = false;
if(shape == null)
{
clearShape = true;
shape = new GameObject("ShadowConeShape");
}
GameObject instance;
Matrix4x4 new_transformation = transformation;
foreach (GameObject gameObject in GameObject.FindGameObjectsWithTag("ShadowCone")) {
DestroyImmediate(gameObject);
}
Matrix4x4 objectTransformation = (transformation*resultTransformation);
int nr_shadow_str = 1;
//---------------------miejsce-na-zadanie-3.4--------------------------------------//
var strengths = new List<int>();
for(var x = -lookForLightLength; x < lookForLightLength; x =+ 0.5f)
{
for (var y = 0.0f; y < lookForLightLength; y = +0.5f)
{
for (var z = -lookForLightLength; z < lookForLightLength; z = +0.5f)
{
var actualPosition = objectTransformation;
actualPosition *= Matrix4x4.Translate(new Vector3(x, y, z));
var shadowStrenght = (int)environment.shadowStrength(actualPosition.ExtractPosition());
strengths.Add(shadowStrenght);
}
}
}
//---------------------miejsce-na-zadanie-3.4-koniec-------------------------------//
if (environment.sendShadowToLSystem)
{
//---------------------miejsce-na-zadanie-3.5--------------------------------------//
var avg = strengths.Average();
node.literal.values[1] = (float)avg;
//---------------------miejsce-na-zadanie-3.5-koniec------------------------------//
}
bestTransformation = transformation*resultTransformation;
if(environment.rotateTowardsLight)
{
minShadow = shadowStrength_;
if(shadowStrength_/nr_shadow_str > 5.0f)
{
shadowConeLimiter ++;
// transformation = Matrix4x4.Translate(gameObject.transform.position)*transformation;
for(int angle = 0;angle <= lookForLightAngle;angle+=10)
{
for(int i = 0; i < 360; i += shadowRotate)
{
shadowStrength_ = 0;
for(float length = 0.5f; length<lookForLightLength; length+=environment.voxelSize*0.5f)
{
new_transformation = (transformation*(resultTransformation*Matrix4x4.Rotate(Quaternion.Euler(0, i, 0))*Matrix4x4.Rotate(Quaternion.Euler(0, 0, angle))*Matrix4x4.Translate(new Vector3(0,length,0))));
shadowStrength_ += (int)environment.shadowStrength(new_transformation.ExtractPosition()+transformation.MultiplyPoint(shape.transform.position));
// if(shadowConeLimiter % 10 == 0)
// {
// instance = Instantiate(environment.shape);
// instance.name = "ShadowCone";
// instance.tag = "ShadowCone";
// instance.transform.position = new_transformation.ExtractPosition()+transformation.MultiplyPoint(shape.transform.position);
// instance.transform.rotation *= transformation.ExtractRotation();
// }
}
if(shadowStrength_ < minShadow)
{
minShadow = shadowStrength_;
bestTransformation = (transformation*(resultTransformation*Matrix4x4.Rotate(Quaternion.Euler(0, i, 0))*Matrix4x4.Rotate(Quaternion.Euler(0, 0, angle))));
}
}
}
}
if(minShadow > 220*lookForLightLength*2.0f)
{
bestTransformation = Matrix4x4.Translate(new Vector3(0,0,0));
}
}
if(clearShape)
{
DestroyImmediate(shape);
}
return bestTransformation;
}
public void evaluate() {
base.evaluate();
}
public void evaluateAndPresent() {
evaluate();
present();
// Debug.Log(evaluator.lSystemString.ToString().Length);
//x.name = "aaa";
//Instantiate(x,Matrix4x4.identity);
}
public void loadFile() {
// nextStep = Time.time;
// clearObjects();
var sr = new StreamReader(LSystemPath);
evaluator = LSystemFileParser.parseLSystem(sr);
sr.Close();
turtleInterpretation = new Dictionary<string, Func<float[], Tuple<GameObject, Matrix4x4>>>();
initLiteralInterpretation();
}
public void present() {
clearObjects();
createModelsRecursiveInEnviroment(evaluator.lSystemString, Matrix4x4.Translate(gameObject.transform.position/2.0f));//Matrix4x4.identity);
}
void refreshShadows()
{
environment.Reset();
foreach (GameObject gameObject in GameObject.FindGameObjectsWithTag("LSystemLiteral")) {
// if(!isParentThisGameObject(gameObject))
// {
environment.addShadow(gameObject.GetComponent<Transform>().position, shadowStrength);
// }
// else
// {
// if(isParentThisGameObject(gameObject, 2))
// {
// environment.addShadowPoint(gameObject.GetComponent<Transform>().position, 6);
// }
// }
}
}
bool isParentThisGameObject(GameObject gameObject, int depth = 3)
{
if(gameObject.transform.parent != null)
{
if(gameObject.transform.parent.gameObject == this.gameObject)
{
return true;
}
else
{
if(depth >= 0)
{
return isParentThisGameObject(gameObject.transform.parent.gameObject, depth-1);
}
}
}
return false;
}
int objectCounter = 0;
int shadowConeLimiter = 0;
public int childrenCount(LSystemNode node, int depth = 3)
{
int c = 0;
if(node.children.Count > 0)
{
c += node.children.Count;
if(depth > 0)
{
foreach(LSystemNode child in node.children)
{
c+= childrenCount(child, depth - 1);
}
}
}
return c;
}
public void createModelsRecursiveInEnviroment(LSystemNode node, Matrix4x4 transformation, int depth = 0)
{
// transformation *= Matrix4x4.Translate(gameObject.transform.position);
while (node != null && objectCounter < 25000) {
Matrix4x4 new_transformation=transformation;
Func<float[], Tuple<GameObject, Matrix4x4>> interpretation;
var name = node.literal.name;
if (turtleInterpretation.TryGetValue(name, out interpretation) || turtleInterpretation.TryGetValue("*.*", out interpretation)) {
var result = interpretation(node.literal.values);
Debug.Log("D: "+node.literal);
new_transformation = new_transformation*Matrix4x4.Rotate(Quaternion.Euler(UnityEngine.Random.Range(-0.5f, 0.5f), UnityEngine.Random.Range(-0.5f, 0.5f), UnityEngine.Random.Range(-0.5f, 0.5f)));
new_transformation = lightDirection(new_transformation, result.Item2, result.Item1, node);
if(new_transformation == Matrix4x4.Translate(new Vector3(0,0,0)) && environment.cutBranchesWithMaxShadow)
{
Debug.Log(" children "+node.children.Count);
// node.literal.
if(childrenCount(node) < 5)
{
LSystemNode destroyNode = node;
if(destroyNode.parent != null)
{
destroyNode.parent.children.Remove(node);
if(destroyNode.parent.mainChild == null)
{
destroyNode.parent.mainChild = destroyNode.parent.children[0];
}
node = node.mainChild;
destroyNode = null;
// DestroyImmediate(instance);
objectCounter--;
}
continue;
}
}
if (result.Item1 != null && new_transformation != Matrix4x4.Translate(new Vector3(0,0,0))) {
var instance = this.prepeareGameObject(name, result.Item1, new_transformation);
environment.addShadow(new_transformation.ExtractPosition()+transformation.MultiplyPoint(result.Item1.transform.position), (sbyte)(shadowStrength/8.0f));
}
environment.addShadow(new_transformation.ExtractPosition()+transformation.ExtractPosition(), (sbyte)(shadowStrength/8.0f));
environment.addShadow((new_transformation*Matrix4x4.Translate(new Vector3(0,1,0))).ExtractPosition()+transformation.ExtractPosition(), (sbyte)(shadowStrength/8.0f));
//remove scale, rather unnecesary
new_transformation = new_transformation * Matrix4x4.Scale(result.Item2.ExtractScale()).inverse;
}
if(node != null)
{
List<ConsoleLSystem.LSystemNode> children_tmp = new List<ConsoleLSystem.LSystemNode>();
foreach (var child in node.children)
{
children_tmp.Add(child);
}
foreach (var child in children_tmp)
{
if(child != null)
{
createModelsRecursiveInEnviroment(child, new_transformation, depth+1);
}
}
node = node.mainChild;
}
transformation = new_transformation;
}
}
private void clearObjects() {
//var objects = Resources.FindObjectsOfTypeAll<GameObject>().Where(obj => obj.name == "Name");
// foreach (GameObject gameObject in GameObject.FindGameObjectsWithTag("LSystemLiteral")) {
// DestroyImmediate(gameObject);
//
// }
objectCounter = 0;
int removed = 1;
while (removed > 0)
{
removed = 0;
foreach (Transform child in this.gameObject.transform) {
// environment.addShadow(gameObject.GetComponent<Transform>().position, (sbyte)-shadowStrength);
if(child.gameObject.tag == "LSystemLiteral")
{
DestroyImmediate(child.gameObject);
}
removed ++;
// GameObject.Destroy(child.gameObject);
}
}
refreshShadows();
// gameObjects = new List<GameObject>();
}
}