2021-07-06 22:14:00 +02:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using UnityEditor;
|
|
|
|
using UnityEngine;
|
|
|
|
|
2021-07-09 20:35:34 +02:00
|
|
|
abstract public class TurtleLSystem : MonoBehaviour
|
2021-07-06 22:14:00 +02:00
|
|
|
{
|
|
|
|
public float speed;
|
|
|
|
private float nextStep;
|
|
|
|
|
|
|
|
|
|
|
|
public string LSystemPath;
|
|
|
|
|
|
|
|
public uint steps;
|
|
|
|
|
|
|
|
public Dictionary<string, Func<float[], Tuple<GameObject, Matrix4x4>>> turtleInterpretation = new Dictionary<string, Func<float[], Tuple<GameObject, Matrix4x4>>>();
|
|
|
|
|
|
|
|
private List<GameObject> gameObjects = new List<GameObject>();
|
|
|
|
|
|
|
|
private bool isAnimationRunning = false;
|
|
|
|
|
|
|
|
private Mesh getCylinder(int quality, float width, float length)
|
|
|
|
{
|
|
|
|
Mesh mesh = new Mesh();
|
|
|
|
//mesh.triangles
|
|
|
|
var points = new List<Vector3>();
|
|
|
|
var normals = new List<Vector3>();
|
|
|
|
var indices = new List<int>();
|
|
|
|
for (float i = 0; i < quality; i++)
|
|
|
|
{
|
|
|
|
points.Add(new Vector3(Mathf.Cos((i / quality) * 2 * Mathf.PI) * width, 0, Mathf.Sin((i / quality) * 2 * Mathf.PI) * width));
|
|
|
|
}
|
|
|
|
for (float i = 0; i < quality; i++)
|
|
|
|
{
|
|
|
|
points.Add(new Vector3(Mathf.Cos((i / quality) * 2 * Mathf.PI) * width, length, Mathf.Sin((i / quality) * 2 * Mathf.PI) * width));
|
|
|
|
}
|
|
|
|
//points.Add(new Vector3(0,0,0));
|
|
|
|
//points.Add(new Vector3(0, length, 0));
|
|
|
|
|
|
|
|
for (float i = 0; i < quality; i++)
|
|
|
|
{
|
|
|
|
normals.Add(new Vector3(Mathf.Cos((i / quality) * 2 * Mathf.PI) * width, 0, Mathf.Sin((i / quality) * 2 * Mathf.PI) * width));
|
|
|
|
}
|
|
|
|
for (float i = 0; i < quality; i++)
|
|
|
|
{
|
|
|
|
normals.Add(new Vector3(Mathf.Cos((i / quality) * 2 * Mathf.PI) * width, 0, Mathf.Sin((i / quality) * 2 * Mathf.PI) * width));
|
|
|
|
}
|
|
|
|
|
|
|
|
//for (int i = 0; i < quality; i++) {
|
|
|
|
// indices.Add(i);
|
|
|
|
// indices.Add((i + 1) % quality);
|
|
|
|
// indices.Add(quality * 2);
|
|
|
|
//}
|
|
|
|
//for (int i = 0; i < quality; i++) {
|
|
|
|
// indices.Add((i + 1) % quality + quality);
|
|
|
|
// indices.Add(i + quality);
|
|
|
|
// indices.Add(quality * 2 + 1);
|
|
|
|
//}
|
|
|
|
for (int i = 0; i < quality; i++)
|
|
|
|
{
|
|
|
|
indices.Add((i + 1) % quality);
|
|
|
|
indices.Add(i);
|
|
|
|
indices.Add(i + quality);
|
|
|
|
|
|
|
|
indices.Add(i + quality);
|
|
|
|
indices.Add((i + 1) % quality + quality);
|
|
|
|
indices.Add((i + 1) % quality);
|
|
|
|
}
|
|
|
|
mesh.vertices = points.ToArray();
|
|
|
|
mesh.triangles = indices.ToArray();
|
|
|
|
mesh.normals = normals.ToArray();
|
|
|
|
return mesh;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected LSystemEvaluator evaluator = null;
|
|
|
|
|
|
|
|
private void parseRules(StreamReader sr)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
public void evaluate()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < steps; i++)
|
|
|
|
{
|
|
|
|
evaluator.rewrite();
|
|
|
|
}
|
|
|
|
Debug.Log(evaluator.lSystemString.ToString());
|
|
|
|
}
|
|
|
|
protected GameObject prepeareGameObject(string name, GameObject gameObject, Matrix4x4 transformation)
|
|
|
|
{
|
|
|
|
GameObject instance;
|
|
|
|
if (PrefabUtility.GetPrefabAssetType(gameObject) != PrefabAssetType.NotAPrefab)
|
|
|
|
{
|
|
|
|
instance = Instantiate(gameObject);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
instance = gameObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
instance.name = String.Format("LSystem Literal {0}", name);
|
|
|
|
instance.tag = "LSystemLiteral";
|
|
|
|
instance.transform.parent = this.gameObject.transform;
|
|
|
|
instance.transform.position = transformation.ExtractPosition() + transformation.MultiplyPoint(instance.transform.position);
|
|
|
|
instance.transform.rotation *= transformation.ExtractRotation();
|
|
|
|
instance.transform.localScale = Vector3.Scale(transformation.ExtractScale(), instance.transform.localScale);
|
|
|
|
return instance;
|
|
|
|
|
|
|
|
}
|
|
|
|
public void createModelsRecursive(LSystemNode node, Matrix4x4 transformation)
|
|
|
|
{
|
|
|
|
while (node != null)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
new_transformation = new_transformation * result.Item2;
|
|
|
|
if (result.Item1 != null)
|
|
|
|
{
|
|
|
|
var instance = prepeareGameObject(name, result.Item1, new_transformation);
|
|
|
|
}
|
|
|
|
//gameObjects.Add(gameObject);
|
|
|
|
//remove scale, rather unnecesary
|
|
|
|
new_transformation = new_transformation * Matrix4x4.Scale(result.Item2.ExtractScale()).inverse;
|
|
|
|
}
|
|
|
|
foreach (var child in node.children)
|
|
|
|
{
|
|
|
|
createModelsRecursive(child, new_transformation);
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
|
|
|
|
}
|
|
|
|
Debug.Log("#OldClear");
|
|
|
|
gameObjects = new List<GameObject>();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void present()
|
|
|
|
{
|
|
|
|
clearObjects();
|
|
|
|
createModelsRecursive(evaluator.lSystemString, Matrix4x4.identity);
|
|
|
|
}
|
|
|
|
abstract protected void initLiteralInterpretation();
|
|
|
|
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 evaluateAndPresent()
|
|
|
|
{
|
|
|
|
evaluate();
|
|
|
|
present();
|
|
|
|
Debug.Log(evaluator.lSystemString.ToString().Length);
|
|
|
|
//x.name = "aaa";
|
|
|
|
|
|
|
|
//Instantiate(x,Matrix4x4.identity);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void switchAnimation()
|
|
|
|
{
|
|
|
|
this.isAnimationRunning = !this.isAnimationRunning;
|
|
|
|
nextStep = Time.time;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void runAnimation()
|
|
|
|
{
|
|
|
|
if (nextStep < Time.time)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < (Time.time - nextStep) * speed; i++)
|
|
|
|
{
|
|
|
|
evaluator.rewrite();
|
|
|
|
}
|
|
|
|
present();
|
|
|
|
nextStep = Time.time + 1 / speed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update is called once per frame
|
|
|
|
protected virtual void Update()
|
|
|
|
{
|
|
|
|
if (this.isAnimationRunning)
|
|
|
|
{
|
|
|
|
this.runAnimation();
|
|
|
|
}
|
|
|
|
}
|
2021-07-09 20:35:34 +02:00
|
|
|
}
|