lsystem.cpp
A scenery demonstrating a quite complicated `
retransformation'. In truth, there is only one object, namely a golden cylinder, but a retransformation function, which is built by a L-System algorithm, is applied to this cylinder, such that it appears multiple times in changing positions. The result is nearly botanical...
#include <3D/main.hpp>
#include <3D/objects/Cylinder.hpp>
#include <3D/objects/planeobjs.hpp>
#include <wb/stack.hpp>
#include <ctype.h>
#include <stdio.h>
#include <fstream.h>
using namespace wb;
using namespace Lux;
char lsystem1[2048];
char lsystem2[16984];
char lsystem3[128*1024];
const char*lsystem = lsystem3;
const double angle = M_PI/29.;
char lsystem0[1024] =
"L40Z(11X5yL)(10Y-5Z9X5y5xL)(-14Y-5Z-7xL)(-12X-3Y-4Z-2x-6yL)S2X1yL";
int maxLsystemlen = 0;
const char*lsys;
Stack<Transformation, 16> LSystemstack;
int retransform(int t,Transformation&T,const ObjectBase&)
{
if (t>maxLsystemlen) return 0;
if (t==0)
{
LSystemstack.popall();
lsys = lsystem;
}
while(*lsys)
{
int sign = 1;
int mCount = 0;
if (*lsys=='+' || *lsys=='-')
{
for(;*lsys=='+';lsys++) sign=+1;
for(;*lsys=='-';lsys++) sign=-1;
}
while(isdigit(*lsys))
{
mCount *= 10;
mCount += *lsys - '0';
lsys++;
}
mCount *= sign;
switch(*lsys++)
{
case 'X': T.Translation+=T.Obj_to_World*vector3(.05*mCount,0,0); break;
case 'Y': T.Translation+=T.Obj_to_World*vector3(0,.05*mCount,0); break;
case 'Z': T.Translation+=T.Obj_to_World*vector3(0,0,.05*mCount); break;
case 'x': T.Obj_to_World*=rotx(angle*mCount);
T.invertflag=1;
break;
case 'y': T.Obj_to_World*=roty(angle*mCount);
T.invertflag=1;
break;
case 'z': T.Obj_to_World*=rotz(angle*mCount);
T.invertflag=1;
break;
case 'S': T.scale(vector3(.9,.9,.9));
break;
case '(': LSystemstack.push(T); break;
case ')': LSystemstack.pop(T); break;
case 'L': return 1;
}
}
return 0;
}
void buildLsystem(char*to,const char*from,const char*const insert)
{
char *o = to;
while(*from) switch(*from)
{
case 'L':
for(const char*cp=insert;*cp; *to++=*cp++)
;
from++;
break;
default:
*to++ = *from++;
}
*to = '\0';
printf("Lsystem: %d Bytes\n",to-o);
}
int Lcount(const char*from)
{
int L;
for(L=0;*from;from++)
if (*from=='L') L++;
return L;
}
main(int argc,const char*argv[])
{
{
ifstream lif("lsystem.str");
lif.getline(lsystem0,sizeof(lsystem0));
}
Camera Kamera(voption(argc,argv,"Standpunkt",vector3(-6,30,.3)),
voption(argc,argv,"Blickpunkt",vector3( 6, 0, 7)) );
Standardobjektiv Lens(ioption(argc,argv,"angle",50));
Kamera.use(Lens);
Scene Welt;
Material s = Material::gold;
Cylinder Kvirtual(s,.05, vector3(0,0,0), vector3(0,0,1.0) );
Kvirtual.name="Virtueller Zylinder";
Material bg(rgb_real(.4,0,.4));
bg.transparency = rgb_real(0,0,0);
bg.refract_indices = rgb_real(1,1,1);
Welt.defBackground(bg);
Welt.add(Kvirtual);
Kvirtual.trans();
Kvirtual.retransform = retransform;
lsystem = lsystem0;
int l = ioption(argc,argv,"level",1);
if (l>1) { buildLsystem(lsystem1,lsystem0,lsystem0); lsystem = lsystem1; }
if (l>2) { buildLsystem(lsystem2,lsystem1,lsystem0); lsystem = lsystem2; }
if (l>3) { buildLsystem(lsystem3,lsystem2,lsystem0); lsystem = lsystem3; }
maxLsystemlen = Lcount(lsystem);
Material Matt = Material::matt;
Plane E1(Matt,vector3(0,0,-1),vector3(0,0,1));
E1.name="Schiefe Ebene";
Welt.add(E1);
InfiniteLight Ls(rgb_real(1,1,1),vector3(-2,3,4));
Ls.On(Welt);
Kamera.autoexpose(Welt,argc,argv);
return 0;
}