source: cpp/frams/genetics/f9/conv_f9.cpp @ 125

Last change on this file since 125 was 125, checked in by sz, 10 years ago

f9: APPLY_DETERMINISTIC_BODY_NOISE enabled by default

  • Property svn:eol-style set to native
File size: 4.4 KB
Line 
1// This file is a part of the Framsticks GDK.
2// Copyright (C) 2002-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#include "conv_f9.h"
6#include <frams/model/model.h>
7#include <string.h>
8#include <common/nonstd_stl.h> //ARRAY_LENGTH
9
10#define APPLY_DETERMINISTIC_BODY_NOISE //this representation easily produces perfectly vertical sticks that would stay upright forever. In most cases such infinite perfection is not desired, so we make the construct less perfect by perturbing its coordinates.
11
12GenoConv_F90::GenoConv_F90()
13{
14        name = "Turtle3D-ortho encoding";
15        in_format  = '9';
16        out_format = '0';
17        mapsupport = 0; //would be easy and nice to add!
18}
19
20
21const char* turtle_commands_f9 ="LRDUBF";
22
23//const char* turtle_commandsX_f9="-+0000";
24//const char* turtle_commandsY_f9="00-+00";
25//const char* turtle_commandsZ_f9="0000-+";
26
27SString GenoConv_F90::convert(SString &in, MultiMap *map)
28{
29        vector<XYZ_LOC> vertices;
30        XYZ_LOC current;
31        Model m;
32        m.open();
33        int recently_added=addSegment(m,vertices,current,0xDead);
34        for(int i=0;i<in.len();i++)
35        {
36                char command=in[i];
37                char *ptr=strchr((char*)turtle_commands_f9,command);
38                if (ptr)
39                {
40                        int delta[]={0,0,0};
41                        int pos=ptr-turtle_commands_f9;
42                        int axis=pos/2;
43                        int dir=pos%2;
44                        (*(delta+axis))+=dir*2-1; //+1 or -1 in the given axis
45                        current.add(delta);
46                        recently_added=addSegment(m,vertices,current,recently_added);
47                }
48        }
49#ifdef APPLY_DETERMINISTIC_BODY_NOISE
50        perturbPartLocations(m);
51#endif
52        setColors(m);
53        m.close();
54        return m.getF0Geno().getGene();
55}
56
57int GenoConv_F90::addSegment(Model &m,vector<XYZ_LOC> &vertices,const XYZ_LOC &new_vertex,int recently_added)
58{
59        if (vertices.size()<1)
60        {
61                return addNewVertex(m,vertices,new_vertex);
62        } else
63        {
64                int vertex_here=findVertexAt(vertices,new_vertex);
65                if (vertex_here<0) //need to create a new Part
66                {
67                        vertex_here=addNewVertex(m,vertices,new_vertex);
68                } //else there already exists a Part in new_vertex; new Joint may or may not be needed
69                Part *p1=m.getPart(recently_added);
70                Part *p2=m.getPart(vertex_here);
71                if (m.findJoint(p1,p2)<0 && m.findJoint(p2,p1)<0) //new Joint needed? should always be true if we just created a new Part (vertex_here was <0)
72                {
73                        m.addNewJoint(p1,p2);
74                }
75                return vertex_here;
76        }
77}
78
79int GenoConv_F90::findVertexAt(vector<XYZ_LOC> &vertices,const XYZ_LOC &vertex)
80{
81        for(int i=0;i<vertices.size();i++)
82                if (vertices[i].same_coordinates(vertex)) return i;
83        return -1;
84}
85
86
87int GenoConv_F90::addNewVertex(Model &m,vector<XYZ_LOC> &vertices,const XYZ_LOC &new_vertex)
88{
89        Part *p=new Part;
90        p->p.x=new_vertex.x;
91        p->p.y=new_vertex.y;
92        p->p.z=new_vertex.z;
93        m.addPart(p);
94
95        vertices.push_back(new_vertex);
96        return vertices.size()-1;
97}
98
99double mix(int *colortab,int maxind,double ind)
100{
101        int indpre=(int)ind;
102        int indpost=indpre+1;
103        if (indpost>maxind) indpost=maxind;
104        int v1=colortab[indpre];
105        int v2=colortab[indpost];
106        double d1=ind-indpre;
107        double d2=indpost-ind;
108        double v=indpre==indpost?v1:d2*v1+d1*v2; //d1+d2==1
109        return v;
110}
111
112void GenoConv_F90::setColors(Model &m) //sets fixed (independent from genes) colors and widths on a model, purely for aesthetic purposes
113{
114        //a rainbow on Joints: from the first one red, through middle green, to blue or violet - last
115        static int r[]={1,1,0,0,0,1};
116        static int g[]={0,1,1,1,0,0};
117        static int b[]={0,0,0,1,1,1};
118        int maxind=ARRAY_LENGTH(r)-1;
119
120        int joints_count=m.getJointCount();
121        for(int i=0;i<joints_count;i++)
122        {
123                Joint *j=m.getJoint(i);
124                double x=joints_count<2?0:(double)i/(joints_count-1); //0..1, postion in the rainbow
125                double ind=x*maxind;
126                j->vcolor.x=mix(r,maxind,ind);
127                j->vcolor.y=mix(g,maxind,ind);
128                j->vcolor.z=mix(b,maxind,ind);
129        }
130
131        int parts_count=m.getPartCount();
132        SList jlist;
133        for(int i=0;i<parts_count;i++)
134        {
135                Part *p=m.getPart(i);
136                jlist.clear();
137                int count=m.findJoints(jlist,p);
138                Pt3D averagecolor(0,0,0); //Parts will get averaged colors from all attached Joints
139                FOREACH(Joint*,j,jlist)
140                        averagecolor+=j->vcolor;
141                if (count>5) count=5; //avoid too fat...
142                p->vsize=0.3+count/15.0; //the more Joints is attached to a Part, the fatter it is
143                p->vcolor=averagecolor/count;
144        }
145}
146
147void GenoConv_F90::perturbPartLocations(Model &m) //deterministic "body noise", see APPLY_DETERMINISTIC_BODY_NOISE
148{
149        for(int i=0;i<m.getPartCount();i++)
150        {
151                Part *p=m.getPart(i);
152                Pt3D noise(
153                        ((i+1)  %10)-4.5  ,
154                        ((3*i+5)%10)-4.5  ,
155                        ((7*i+2)%10)-4.5
156                        ); //-4.5 .. 4.5 in each axis
157                p->p+=noise/1000;
158        }
159}
Note: See TracBrowser for help on using the repository browser.