268 lines
11 KiB
C#
268 lines
11 KiB
C#
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.IO;
|
||
|
using UnityEngine;
|
||
|
|
||
|
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;
|
||
|
|
||
|
if (environment.sendShadowToLSystem)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
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<LSystemNode> children_tmp = new List<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>();
|
||
|
}
|
||
|
}
|