2021-03-13 17:35:25 +01:00
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using UnityEditor;
|
|
|
|
using UnityEngine;
|
|
|
|
using ConsoleLSystem;
|
|
|
|
using System;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
abstract public class TurtleLSystem : MonoBehaviour
|
|
|
|
{
|
|
|
|
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 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
private 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());
|
|
|
|
}
|
|
|
|
private GameObject prepeareGameObject(string name, GameObject gameObject,Matrix4x4 transformation) {
|
2021-03-26 21:33:33 +01:00
|
|
|
GameObject instance;
|
|
|
|
if (PrefabUtility.GetPrefabAssetType(gameObject) != PrefabAssetType.NotAPrefab) {
|
|
|
|
instance = Instantiate(gameObject);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
instance = gameObject;
|
|
|
|
}
|
|
|
|
|
2021-03-13 17:35:25 +01:00
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
|
|
|
|
}
|
|
|
|
gameObjects = new List<GameObject>();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void present() {
|
|
|
|
clearObjects();
|
|
|
|
createModelsRecursive(evaluator.lSystemString, Matrix4x4.identity);
|
|
|
|
}
|
|
|
|
abstract protected void initLiteralInterpretation();
|
|
|
|
public void loadFile() {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Start is called before the first frame update
|
|
|
|
void Start()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update is called once per frame
|
|
|
|
void Update()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|