μ ν΄μ§ κ·μΉμ μν΄ νΉμ λ¬Έμμ΄μ λ°λ³΅νμ¬ μ κ°ν ν μ κ°λ λ¬Έμμ΄μ μκ±°νμ¬ κ·Έλ¦Όμ 그리λ κ²μ L-μμ€ν
μ΄λΌ νλ€. 1986λ
λ¦°λ΄λ§μ΄μ΄(Lindenmayer)κ° μνκ³μ μ±μ₯ λͺ¨ν, νΉν λ무μ λΆκΈ° λͺ¨νμ μ°κ΅¬νλ λͺ©μ μΌλ‘ κ³ μνμλ€.
L-SYSTEM κ°μ
F, +, -
L-μμ€ν
μμλ κ±°λΆμ΄ κ·Έλν½κ³Ό λ¬Έμμ΄μ μκ±°νμ¬ νλνμ 그리λλ°, λ¬Έμμ΄μ λ¬Έμ μ€ λ€μμ λ¬Έμλ₯Ό λ§λλ©΄ κ±°λΆμ΄ κ·Έλν½μ μννμ¬ μ μ κ·Έλ¦¬κ³ νμ μ νλ€.
F : μΌμ ν κΈΈμ΄μ μ μ κ·Έλ¦¬κ³ νμ¬μ μ μ μ μ λμ μΌλ‘ μ΄λ
: μΌμͺ½ λ°©ν₯μΌλ‘ angle λ§νΌ νμ
: μ€λ₯Έμͺ½ λ°©ν₯μΌλ‘ angle λ§νΌ νμ
λ³νκ·μΉ
μλμ κ°μ μ½νΈ 곑μ μ 그리λ κ²½μ°λ₯Ό μκ°ν΄ 보μ.
60 λ μ’νμ νλ€ ( + )
60 λ μ°νμ νλ€ ( - )
60 λ μ°νμ νλ€ ( - )
60 λ μ’νμ νλ€ ( + )
μ΄μ ν΄λΉνλ λ¬Έμμ΄μ λ€μκ³Ό κ°λ€.
1μ°¨ λ³ν : F+F--F+F
μλ 1 μ°¨μμ μ½νΈ 곑μ μ κ·Έλ¦° κ²μ΄λ€. κ·Έλ λ€λ©΄ μλμ 2 μ°¨μμ μ½νΈ 곑μ μ μ΄λ»κ² 그릴κΉ? 1 μ°¨ μ½νΈ 곑μ μ 그리λ κ·μΉμ AλΌ νλ€λ©΄ A λ λ€μκ³Ό κ°μ΄ λλ€. A( F+F--F+F)
60 λ μ’νμ νλ€ ( + )
60 λ μ°νμ νλ€ ( - )
60 λ μ°νμ νλ€ ( - )
60 λ μ’νμ νλ€ ( + )
μ΄μ ν΄λΉνλ λ¬Έμμ΄μ λ€μκ³Ό κ°λ€.
μμ κ·μΉμ A -> F + F - - F + F
λ‘ κ³ μ³λ³΄λ©΄ λ€μκ³Ό κ°λ€.
2μ°¨ λ³ν : F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F
μ΄λ₯Ό 3μ°¨ λ³ν ν΄ λ³Έλ€λ©΄ μλμ κ°μ΄ λλ€.
3μ°¨ λ³ν : F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F+F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F+F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F
μ΄μ κ°μ΄ F -> F+F--F+F
λ‘ λ³ννλ κ·μΉμ λ³νκ·μΉμ΄λΌκ³ νλ€. μ΄ λ³ν κ·μΉμ 3λ² λ³ννλ©΄ μμ 3μ°¨ λ³νμ΄ λμ€κ² λλ€.
곡리
μνμμ 곡리λ κ°μ₯ κΈ°λ³Έμ μ΄λ£¬λ€. μλ₯Ό λ€μ΄ 'μΌκ°ν λ΄κ°μ ν©μ 180λμ΄λ€' κ° κ³΅λ¦¬μ μμ΄λ€. μ΄λ¬ν 곡리μμ λ§μ μνμ μ 리λ€μ΄ λ§λ€μ΄μ‘λ€. μ¦ κ³΅λ¦¬λ κ°μ₯ κΈ°λ³Έμ μΈ μμΉμ΄λΌκ³ ν μ μλ€. μ΄ κ³΅λ¦¬λ λ§μΉ μ μ μμλ κ°λ€. κ°λ¨ν μ μ μκ° μ물체μ μ¬λ¬ κ°μ§ 볡μ‘ν μ±μ₯μ μ μ΄νλ€. L-μμ€ν
μμλ 곡리λ μ΄μ λΉμ·ν κ°λ
μ κ°λλ€. λ€μ λ§νμλ©΄ L-μμ€ν
μμ 곡리λ 볡μ‘ν νλνμμ μ¨μ΄ μλ μ μ μλΌκ³ ν μ μλ€.
L-SYSTEM ꡬν
μ§κΈλΆν° ꡬνν΄λ³Ό L-μμ€ν
μ λ€μκ³Ό κ°μ κ·μΉμ κ°λλ€.
@
: μ μ κ·Έλ¦°λ€.(μ΄λ§€λ₯Ό κ·Έλ¦°λ€)
[
: νμ¬ μμΉμ κ°λλ₯Ό μ€νμ μ μ₯νλ€.
]
: νμ¬ μμΉμ κ°λλ₯Ό μ€νμ μ΅μμ μμ΄ν
μ μμΉμ κ°λλ‘ μ€μ νλ€.
{
: νμ¬ μμΉλ§μ μ€νμ μ μ₯νλ€.
}
: νμ¬ μμΉλ₯Ό μ€νμ μ΅μμ μμ΄ν
μ μμΉμ κ°λλ‘ μ€μ νλ€.
|
: μΌμͺ½μΌλ‘ 180 λ νμ νλ€.
μ΄λ₯Ό μν΄μ κ±°λΆμ΄ κ·Έλν½ ν΄λμ€κ° μ½κ° λ³νλμλ€. μ€νμ μ μ₯νλ λ΄μ©κ³Ό Push() ν¨μμ μλ‘μ΄ μΈμκ° μ€μ λ κ²μ΄λ€. μμ€ μ½λλ₯Ό 보면 μ΄ν΄κ° κ° κ²μ΄λ€.
struct StackItem
{
Point3D cp;
float angle;
bool save_angle;
StackItem() { cp.x=cp.y=cp.z=0.0f; angle=0.0f; save_angle=false; }
StackItem(const Point3D& pt, float a, bool s)
{
cp.x = pt.x;
cp.y = pt.y;
cp.z = pt.z;
angle = a;
save_angle = s;
}
StackItem(const StackItem& i)
{
cp = i.cp;
angle = i.angle;
save_angle = i.save_angle;
}
};
typedef stack<StackItem> pstack;
class Turtle
{
...
void Push(bool save_angle=true);
void Pop(void);
...
};
void Turtle::Push(bool save_angle)
{
int index = PointList.size()-1;
Point3D pt(PointList[index].x, PointList[index].y, PointList[index].z);
//ν¬μΈνΈ 리μ€νΈμ μ μ₯λμ΄ μλ λ§μ§λ§ μ μ push νλ€.
// save_angle μ΄ true μ΄λ©΄ pop μνμ μ μ₯λ κ°λκ° νμ¬ κ°λκ° λλ€.
StackItem s(pt, angle, save_angle);
PointStack.push(s);
}
void Turtle::Pop(void)
{
if(PointStack.size())
{
StackItem s(PointStack.top());
PointStack.pop();
PointList.push_back(s.cp);
if(s.save_angle)
{
angle = s.angle;
}
}
}
μ΄μ L μμ€ν
μ ꡬνν΄ λ³΄μ. μλλ μμ€ μ½λλ₯Ό λνλΈ κ²μ΄λ€. λ°λ‘ μ€λͺ
μ νμ§ μκ³ μ£Όμμ λ¬μλ€.
/*******************************************************************************
{ LSystem Class
{ written by Sungcheol Kim
{ 2003.4.27
{
{ F : μ μ§
{ + : μΌμͺ½μΌλ‘ νμ
{ - : μ€λ₯Έμͺ½μΌλ‘ νμ
{ | : μΌμͺ½μΌλ‘ 180 λ νμ
{ [ : νμ¬μ’ν, νμ¬ κ°λλ₯Ό μ€νμμ μ₯
{ ] : νμ¬μ’ν, νμ¬ κ°λλ₯Ό μ μ₯νλ μ’ν,κ°λλ‘ μ€μ
{ { : νμ¬μ’νλ§ μ μ₯
{ } : νμ¬μ’νλ§ μ μ₯νλ μ’νλ‘ μ€μ
{ @ : μ΄λ§€λ₯Ό κ·Έλ¦°λ€.
*******************************************************************************/
#ifndef _LSYSTEM_H_
#define _LSYSTEM_H_
#pragma warning(disable : 4786)
#include <map>
#include <string>
#include "turtle.h"
using namespace std;
typedef map< char, string > trule_list;
typedef map< char, string >::iterator ai;
class LSystem
{
public:
string TotalAxiom; //μ΅μ’
곡리
trule_list TRuleList; //λ³νκ·μΉ 리μ€νΈ
float angle; //νμ κ°λ
float length; //μ§νκΈΈμ΄
float factor; //κΈΈμ΄μ λ°°μ¨
Turtle *turtle; //κ±°λΆμ΄
public:
LSystem();
void SetAngle(float rotate_angle); //νμ κ°λλ₯Ό μ€μ νλ€.
void SetLength(float move_distance); //μ μ§ κ±°λ¦¬λ₯Ό μ€μ νλ€.
void SetFactor(float magnification); //μ μ§ λΉμ¨μ μ€μ νλ€. μ΅μ’
μ μ§ κ±°λ¦¬λ length*factor μ κ°λ€.
void SelectTurtle(Turtle *pturtle); //κ±°λΆμ΄λ₯Ό μ ννλ€.
void AddTransRule(char name, string rule); //λ³ν κ·μΉμ μμ±, μΆκ°νλ€.
void MakeAxiom(string axiom, int n); //곡리λ₯Ό λ§λ λ€. n μ°¨κΉμ§ 곡리 λ³ν
void Draw(void); //곡리μ μν L-μμ€ν
μ κ·Έλ¦°λ€.
};
#endif
#include "LSystem.h"
LSystem::LSystem(void)
{
angle = 0.0f;
length = 1.0f;
factor = 1.0f;
turtle = NULL;
TotalAxiom = "";
TRuleList.clear();
}
void LSystem::SetAngle(float rotate_angle)
{
angle = rotate_angle;
}
void LSystem::SetLength(float move_distance)
{
length = move_distance;
}
void LSystem::SetFactor(float magnification)
{
factor = magnification;
}
void LSystem::SelectTurtle(Turtle *pturtle)
{
turtle = pturtle;
}
void LSystem::AddTransRule(char name, string rule)
{
TRuleList[name] = rule;
}
void LSystem::MakeAxiom(string axiom, int n)
{
ai fi;
string buffer;
TotalAxiom = axiom;
for(int x=0; x<n; ++x) //nμ°¨κΉμ§ λ³ν
{
buffer.erase(buffer.begin(), buffer.end());//곡리λ₯Ό λ΄μ λ²νΌ
for(int i=0; i<TotalAxiom.length(); ++i)
{
switch(TotalAxiom[i])
{
case 'F':
fi = TRuleList.find('F'); // F μ λν΄μ μ μλ λ³ν κ·μΉμ΄ μμΌλ©΄ κ·Έ κ·μΉμ λ²νΌμ λ£κ³ μλλ©΄ κ·Έλ₯ F(μ μ§) μλ₯Ό λ£λλ€.
if(fi!=TRuleList.end())
{
buffer += fi->second;
}
else
{
buffer += "F";
}
break;
case '@':
buffer += "@";
break;
case '+':
buffer += "+";
break;
case '-':
buffer += "-";
break;
case '[':
buffer += "[";
break;
case ']':
buffer += "]";
break;
case '{':
buffer += "{";
break;
case '}':
buffer += "}";
break;
case '|':
buffer += "|";
break;
default: //μμ λ¬Έμ μ΄μΈμ λ¬Έμλ ν΄λΉ λ¬Έμμ ν΄λΉνλ λ³νκ·μΉμ΄ μμΌλ©΄ λ²νΌμ λ£λλ€.
fi = TRuleList.find((char)(TotalAxiom[i]));
if(fi!=TRuleList.end())
{
buffer += fi->second;
}
break;
}
}
TotalAxiom = buffer; //λ²νΌλ₯Ό μ΅μ’
곡리μ λ£λλ€.
}
}
void LSystem::Draw(void)
{
for(string::iterator i = TotalAxiom.begin(); i!=TotalAxiom.end(); ++i)
{
switch((char)(*i))
{
case 'F':
turtle->Forward(length*factor); //μ μ§
break;
case '@':
turtle->MarkCurrentPoint(); //μ΄λ§€κ·Έλ¦¬κΈ°
break;
case '+':
turtle->Left(angle); //μ’νμ
break;
case '-':
turtle->Right(angle); //μ°νμ
break;
case '|':
turtle->Left(180); //μ’λ‘ 180 λ νμ
break;
case '[':
turtle->Push(true); //μμΉ, κ°λ μ μ₯
break;
case ']':
case '}':
turtle->Pop(); //μμΉ λλ κ°λ νμ
break;
case '{':
turtle->Push(false); //μμΉ μ μ₯
break;
}
}
}
μλμ μ½λλ L-μμ€ν
μ μ¬μ©νλ μΌλ ¨μ μ½λλ₯Ό 보μ¬μ€λ€.
#include "lib\egl.h"
#include "LSystem.h"
using namespace egl;
class RenderWindow : public Window
{
private:
LSystem lsystem;
Turtle turtle;
public:
virtual BOOL InitGL(void);
virtual void RenderGLScene(void);
};
BOOL RenderWindow::InitGL(void)
{
Window::InitGL();
lsystem.SelectTurtle(&turtle); //κ±°λΆμ΄ μ ν
lsystem.SetAngle(60.0f); //νμ κ°λλ₯Ό 60 λλ‘ μ€μ
lsystem.SetLength(1.0f); //μ μ§ κ±°λ¦¬λ₯Ό 1.0 μΌλ‘ μ€μ
lsystem.SetFactor(1.0f); //μ μ§ λΉμ¨μ 1.0 μΌλ‘ μ€μ
lsystem.AddTransRule('F', "F+F--F+F"); //μ½ν 곑μ μ 그리λ λ³ν κ·μΉ F μμ± λ° μΆκ°
lsystem.MakeAxiom("F", 3); //곡리 F λ₯Ό 3 μ°¨μ κ±Έμ³ λ³ν
return TRUE;
}
void RenderWindow::RenderGLScene(void)
{
Window::RenderGLScene();
turtle.SetStartPoint(-13.0f, 0.0f, -30.0f); //κ±°λΆμ΄μ μμμμΉλ₯Ό μ νκ³
lsystem.Draw(); //L-μμ€ν
μ μν΄ μμ±λ νλνμ κ·Έλ¦°λ€.
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
RenderWindow app;
if(!app.Create(FALSE, "EDin's OpenGL - Texture2D"))
return EXIT_FAILURE;
return app.Run();
}
μλλ μ€ν κ²°κ³Όμ΄λ€.
λ€μ μ₯μμ L-μμ€ν
μ νμ©ν μ¬λ¬κ°μ§ νλνμ κ·Έλ €λ³΄μ.