bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

unityでL-Systemの最後

3Dの木っぽいものができたのでいったん終了。

L-System

L-System


思っていたよりもコードが少ない。
自然に見せるためにはもう一工夫必要で、恐らく時間がかかりそう。
Parse関数のswitchかかっこ悪い。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class LSystem : MonoBehaviour {

	GameObject m_Root = null;

	const float FORWARD_DISTANCE = 2.0f;

	class Pointer {
		public Vector3 pos = Vector3.zero;
		public Quaternion rot = Quaternion.identity;
	}

	//string m_InitialString = "F";
	//string m_InitialString = "F-F-F-F";
	//string m_InitialString = "B";
	string m_InitialString = "X";
	string m_CurrentString = "";
	Dictionary<string, string> m_RuleTable = null;
	Pointer m_Pointer = null;
	int m_Index = 0;
	float m_Angle = 90;

	Stack<Pointer> m_Stack = null;

	void Awake () {
		m_Pointer = new Pointer();
		m_Stack = new Stack<Pointer>();
		m_Pointer.pos = Vector3.zero;
		m_Pointer.rot = Quaternion.identity;
		m_Root = new GameObject("Tree");
		m_Root.transform.position = Vector3.zero;
		m_Root.transform.rotation = Quaternion.identity;

		m_Angle = 27.5f;
		m_RuleTable = new Dictionary<string, string>();
		//m_RuleTable.Add("F", "FFF-FF-F-F+F+FF-F-FFF");
		//m_RuleTable.Add("F", "F+F-F-F+F");
		m_RuleTable.Add("F", "FF");
		m_RuleTable.Add("-", "-");
		m_RuleTable.Add("+", "+");
		m_RuleTable.Add("A", "B+A+B");
		m_RuleTable.Add("B", "A-B-A");
		m_RuleTable.Add("X", "F[+<*X]F[->*X]+<*X");
		m_RuleTable.Add("Y", "FX-Y");
		m_RuleTable.Add("[", "[");
		m_RuleTable.Add("]", "]");
		m_RuleTable.Add(">", ">");
		m_RuleTable.Add("<", "<");
		m_RuleTable.Add("*", "*");
		m_RuleTable.Add("/", "/");
		string cmd = m_InitialString;
		for(int i = 0; i < 6; ++i) {
			m_CurrentString = "";
			foreach(char s in cmd) {
				m_CurrentString += m_RuleTable[s.ToString()];
			}
			cmd = m_CurrentString;
		}
	}

	void Build (string command) {
		foreach(char s in command) {
			ParseCommand(s);
		}
	}

	void ParseCommand(char s) {
		switch(s) {
		case 'F':
		case 'A':
		case 'B':
			GameObject go = GameObject.Instantiate(Resources.Load("Branch")) as GameObject;
			go.name = "Branch"+m_Index;
			go.transform.position = m_Pointer.pos;
			go.transform.rotation = m_Pointer.rot;
			go.transform.parent = m_Root.transform;
			Vector3 n = m_Pointer.rot*(FORWARD_DISTANCE*Vector3.up) + m_Pointer.pos;
			m_Pointer.pos = n;
			break;
		case 'X':
		case 'Y':
			break;
		case '-':
			m_Pointer.rot = m_Pointer.rot * Quaternion.AngleAxis(m_Angle, Vector3.left);
			break;
		case '+':
			m_Pointer.rot = m_Pointer.rot * Quaternion.AngleAxis(-m_Angle, Vector3.left);
			break;
		case '[':
			Pointer push = new Pointer();
			push.pos = m_Pointer.pos;
			push.rot = m_Pointer.rot;
			m_Stack.Push(push);
			break;
		case ']':
			if(m_Stack.Count > 0) {
				Pointer pop = m_Stack.Pop();
				m_Pointer.pos = pop.pos;
				m_Pointer.rot = pop.rot;
			}
			break;
		case '>':
			m_Pointer.rot = m_Pointer.rot * Quaternion.AngleAxis(m_Angle, Vector3.forward);
			break;
		case '<':
			m_Pointer.rot = m_Pointer.rot * Quaternion.AngleAxis(-m_Angle, Vector3.forward);
			break;
		case '*':
			m_Pointer.rot = m_Pointer.rot * Quaternion.AngleAxis(m_Angle, Vector3.up);
			break;
		case '/':
			m_Pointer.rot = m_Pointer.rot * Quaternion.AngleAxis(-m_Angle, Vector3.up);
			break;
		}
		m_Index++;
	}

	// Use this for initialization
	void Start () {
		Build(m_CurrentString);
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}