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>>(); 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().position, shadowStrength); // } // else // { // if(isParentThisGameObject(gameObject, 2)) // { // environment.addShadowPoint(gameObject.GetComponent().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> 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 children_tmp = new List(); 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().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().position, (sbyte)-shadowStrength); if (child.gameObject.tag == "LSystemLiteral") { DestroyImmediate(child.gameObject); } removed++; // GameObject.Destroy(child.gameObject); } } refreshShadows(); // gameObjects = new List(); } }