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

Last change on this file since 120 was 120, checked in by Maciej Komosinski, 9 years ago

added sources of the f9->f0 genetic converter

  • Property svn:eol-style set to native
File size: 4.2 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
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"
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.