source: cpp/frams/model/modelparts.h @ 199

Last change on this file since 199 was 197, checked in by Maciej Komosinski, 11 years ago

GDK used by developers since 1999, distributed on the web since 2002

  • Property svn:eol-style set to native
File size: 16.7 KB
Line 
1// This file is a part of the Framsticks GDK.
2// Copyright (C) 1999-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#ifndef _MODELPARTS_H_
6#define _MODELPARTS_H_
7
8#include <frams/util/3d.h>
9#include <frams/genetics/genoconv.h>
10
11#include <frams/util/extvalue.h>
12#include <frams/util/list.h>
13#include <frams/util/sstring.h>
14#include <frams/util/sstringutils.h>
15#include <frams/param/param.h>
16#include <frams/param/syntparam.h>
17#include <frams/util/usertags.h>
18#include <frams/param/paramtabobj.h>
19
20#include <stdio.h>
21
22//#define MODEL_V1_COMPATIBLE
23
24class Model;
25class IRange;
26class MultiRange;
27
28typedef UserTags<Model,void*,5> ModelUserTags;
29
30/** Common base for model elements. */
31class PartBase
32{
33public:
34SString vis_style;
35PartBase(const SString& s):vis_style(s),mapped(0) {}
36~PartBase();
37static SString getDefaultStyle(){return SString("none");}
38MultiRange *mapped;
39enum PartBaseFlags { Selected=1 };
40long flags;
41Model *owner;   ///< backlink to the model
42
43SString info;
44
45Model &getModel() const {return *owner;}
46
47ModelUserTags userdata;
48
49void notifyMappingChange();
50
51void clearMapping();
52MultiRange* getMapping() {return mapped;}
53void setMapping(const IRange &mr);
54void addMapping(const IRange &mr);
55void setMapping(const MultiRange &mr);
56void addMapping(const MultiRange &mr);
57
58void setInfo(const SString& name,const SString& value);
59void setInfo(const SString& name,int value);
60void setInfo(const SString& name,double value);
61SString getInfo(const SString& name);
62};
63
64/// Part is the only real physical object in the framsticks creature.
65/// You can use this class for querying and adjusting constructed
66/// model properties
67class Part: public PartBase
68{
69friend class Model;
70static SString getDefaultStyle();
71Part(double _mass,double _size,double _density,double _friction,double _ingest,double _assim)
72        :PartBase(getDefaultStyle()),mass(_mass),size(_size),density(_density),friction(_friction),ingest(_ingest),assim(_assim)
73        {}
74void defassign();
75public:
76// base properties - have special meaning and therefore are often accessed directly for convenience
77Pt3D p;    ///< 3d coordinates of the part
78Orient o;  ///< orientation in 3d space (rotation matrix)
79/// ParamInterface object is preferred way to get/set other properties.
80Param extraProperties();
81Param properties();
82long refno;
83Pt3D rot;///< rotation angles
84
85///
86long shape;///default=old framsticks compatible, do not mix with shapes>0
87enum Shape {SHAPE_DEFAULT=0, SHAPE_ELLIPSOID=1, SHAPE_CUBOID=2, SHAPE_CYLINDER=3};
88double mass,size,density,friction,ingest,assim;
89Pt3D scale;
90Pt3D food;
91//SList points; // collistion points
92//Slist neurons; // "select * from owner->neurons where part=this" ;-)
93
94Pt3D vcolor;
95double vsize;
96
97Part(enum Shape s=SHAPE_DEFAULT);
98Part(const Part& src):PartBase(getDefaultStyle()) {operator=(src);}
99void operator=(const Part& src);
100
101void setPositionAndRotationFromAxis(const Pt3D &p1,const Pt3D &p2);
102void setOrient(const Orient &o);///< set part.o and calculates part.rot (rotation angles)
103void setRot(const Pt3D &r);///< set part.rot (rotation angles) and calculate part.o
104
105static Param& getStaticParam();
106};
107
108/// Imaginary connection between two parts.
109/// Joint has no mass nor intertia but can transfer forces.
110class Joint: public PartBase
111{
112friend class Model;
113SString getDefaultStyle();
114Joint(double _stamina,double _stif,double _rotstif,double _d)
115        :PartBase(getDefaultStyle()),stamina(_stamina),stif(_stif),rotstif(_rotstif)
116        {d=Pt3D(_d,0,0);}
117void defassign();
118void resetDeltaMarkers();
119public:
120// base properties:
121long p1_refno,p2_refno; ///< parts' reference numbers
122
123Part *part1,*part2;     ///< references to parts
124class Pt3D d;           ///< position delta between parts
125class Pt3D rot; ///< orientation delta between parts expressed as 3 angles
126enum Shape {SHAPE_DEFAULT=0, SHAPE_SOLID=1};
127long shape;///< default=old framsticks compatible, creates a physical rod between parts (cylinder or cuboid), do not mix with shape>0,  solid=merge parts into one physical entity
128
129Joint();
130Joint(const Joint& src):PartBase(getDefaultStyle()) {operator=(src);}
131void operator=(const Joint& src);
132
133/** connect two parts with this joint.
134    p2 position will be adjusted if delta option is in effect.
135    @see isDelta()
136  */
137void attachToParts(Part* p1,Part* p2);
138/// @see attachToParts(Part*,Part*)
139void attachToParts(int p1,int p2);
140
141/** discard delta information but don't disable delta flag.
142    delta will be calculated from parts positions during final consistency check.
143 */
144void resetDelta();
145
146/** enable or disable delta option.
147    delta value is not changed.
148 */
149void useDelta(bool use);
150
151/** @return true if delta option is in effect.
152    @see useDelta(), resetDelta(), useDelta()
153*/
154bool isDelta();
155
156/// ParamInterface object is preferred way to get/set other properties.
157Param extraProperties();
158Param properties();
159
160// do not touch these:
161long refno; ///< this joint's reference number
162double stamina;
163double stif,rotstif;    ///< stiffness for moving and bending forces
164class Orient o; ///< orientation delta between parts as rotation matrix
165/** flag: generated f0 should include delta data.
166    set by 'singlestep' if j: attributes use delta option */
167bool usedelta;
168Pt3D vcolor;
169
170static Param& getStaticParam();
171};
172
173#define JOINT_DELTA_MARKER 99999.0
174
175////////////////// NN /////////////////
176
177class NeuroClass;
178
179typedef UserTags<NeuroClass,void*,5> NeuroClassUserTags;
180
181/** Information about neuron class.
182 */
183class NeuroClass
184{
185bool ownedvectordata;
186void operator=(const NeuroClass& nosuchthich){}
187  public:
188SString name,longname,description;
189ParamEntry *props;
190bool ownedprops;//< destructor will free props using ParamObject::freeParamTab
191long prefinputs,prefoutput;
192long preflocation;
193int *vectordata;
194long visualhints;
195
196//void *impl;
197int impl_count;
198bool active;
199int genactive;
200NeuroClassUserTags userdata;
201
202//////////////////////
203~NeuroClass();
204NeuroClass();
205NeuroClass(ParamEntry *_props,SString _description,
206           int _prefinputs,int _prefoutput,int _preflocation,int *_vectordata,bool own_vd=1,int vhints=0);
207/** class name for use in Neuro::setClassName(), Neuro::setDetails() (former 'moredata' field),
208    eg. "N","-",G" */
209const SString& getName() {return name;}
210/** human friendly name, eg. "Neuron","Link","Gyroscope"  */
211const SString& getLongName() {return longname;}
212/** long description */
213const SString& getDescription() {return description;}
214ParamEntry* getParamTab() {return props;}
215
216/** NeuroClass specific properties, recognized by all neurons of this class */
217Param getProperties() {return Param(props);}
218
219/** preferred number of inputs, -1 = no preference (any number will go).
220    extra inputs may be ignored by the object (depends on the class).
221 */
222int getPreferredInputs() {return prefinputs;}
223
224/** @return 0 if this object doesn't provide useful output signal. */
225int getPreferredOutput() {return prefoutput;}
226
227/** @return 0 if the object doesn't need any assignment to the body element.
228    @return 1 = it likes to be attached to the Part ( @see Neuro::attachToPart() )
229    @return 2 = the object prefers to have the Joint ( @see Neuro::attachToJoint() )
230 */
231int getPreferredLocation() {return preflocation;}
232/** vector drawing to be used in neuro net diagram.
233    interpretation:
234       {   
235           LEN = datalength (excluding this number)
236           NL = number_of_lines
237line#1 ->  NS = number_of_segments, x1,y1, x2,y2, ... xNS-1,yNS-1,
238         ...
239line#NL -> NS = number_of_segments, x1,y1, x2,y2, ... xNS-1,yNS-1,
240       }
241 */
242int* getSymbolGlyph()
243 {return vectordata;}
244void setSymbolGlyph(int *data,bool owned=1)
245 {if (vectordata&&ownedvectordata) delete []vectordata;
246 vectordata=data; ownedvectordata=owned;}
247/** additional information about how the neuron should be drawn
248    used by structure view (and maybe some other components).
249    return value is defined by the enum Hint
250    @see enum Hint
251 */
252int getVisualHints()
253 {return visualhints;}
254
255enum Hint
256        /** don't draw neurons of this class */
257 { Invisible=1,
258        /** don't draw classname label below the neuron */
259   DontShowClass=2,
260        /** draw the neuron at the first part when attached to joint (default is in the middle) */
261   AtFirstPart=4,
262        /** draw the neuron at the second part when attached to joint (default is in the middle) */
263   AtSecondPart=8,
264        /** use effector colour for this neuro unit */
265   EffectorClass=16,
266        /** use receptor colour for this neuro unit */
267   ReceptorClass=32,
268   V1BendMuscle=64,
269   V1RotMuscle=128,
270   LinearMuscle=256
271 };
272
273/** textual summary, automatically generated from other properties (like the neuro class tooltip) */
274SString getSummary();
275};
276
277class Neuro;
278
279#ifdef MODEL_V1_COMPATIBLE
280class NeuroItem;
281
282/** for compatibility with old Neuro/NeuroItem  */
283class OldItems
284{
285Neuro &neuro;
286SList syntitems; ///< to be deleted
287SList items;
288int listok;
289  public:
290OldItems(Neuro &n):neuro(n),listok(0) {}
291~OldItems() {freelist();}
292void buildlist();
293void freelist();
294
295int getItemCount();
296NeuroItem *getNeuroItem(int i);
297NeuroItem *addNewNeuroItem();
298int findNeuroItem(NeuroItem *n);
299};
300#endif
301
302/** Single processing unit in framsticks NN.  */
303class Neuro: public PartBase
304{
305friend class Model;
306static SString getDefaultStyle();
307
308struct NInput { Neuro *n; double weight; SString *info;
309        NInput(Neuro *_n,double w,SString *i=0):n(_n),weight(w),info(i) {} };
310
311SListTempl<NInput> inputs;
312
313NeuroClass *myclass;
314bool knownclass;
315SString myclassname, myclassparams;
316/** set myclass and make knownclass=true */
317void checkClass();
318SString** inputInfo(int i);
319void defassign();
320
321public:
322enum NeuroFlags { HoldState=2 };
323Param properties();
324Param extraProperties();
325
326void setInputInfo(int i,const SString& name,const SString &value);
327void setInputInfo(int i,const SString& name,int value);
328void setInputInfo(int i,const SString& name,double value);
329SString getInputInfo(int i);
330SString getInputInfo(int i,const SString& name);
331
332NeuroClass* getClass();
333void setClass(NeuroClass*);
334
335SString getClassParams() {return myclassparams;}
336void setClassParams(const SString& cp) {myclassparams=cp;}
337
338SString getClassName();
339void setClassName(const SString& clazz);
340
341/** return neuro unit details encoded as <CLASS> ":" <PROPERTIES>
342   
343    new Neuro can be created as root object (without parent) or can be
344    the child of existing Neuro. Children of the Neuro are its inputs.
345    Standard framsticks neuron calculates the sum of all input units - other processing
346    units don't have to treat them equally and can even ignore some of them.
347    There are hints about expected inputs in the class database, @see getClass
348
349    Application should not assume anything about classes and its properties
350    except for two standard classes: (information about all current classes
351    can be retrieved with getClass/getClassProperties methods)
352    - getClassName()="N" is the standard framsticks neuron, accepts any number of inputs,
353      compatible with old Neuro object
354    - getClassName()="-" is the neuron link, compatible with old Neuro-Neuro link
355      (NeuroItem with empty details)
356    Empty details defaults to "-" if the parent unit is specified,
357    and "N" if the unit has no parent.
358 */
359SString getDetails();
360
361/** details = classname + ":" + classparams
362    @see getDetails()
363 */
364void setDetails(const SString&);
365
366#define STATRICKCLASS Neuro
367PARAMGETDEF(details) {arg1->setString(getDetails());}
368PARAMSETDEF(details) {setDetails(arg1->getString());return PSET_CHANGED;}
369PARAMGETDEF(inputCount);
370PARAMPROCDEF(p_getInputNeuroDef);
371PARAMPROCDEF(p_getInputNeuroIndex);
372PARAMPROCDEF(p_getInputWeight);
373PARAMGETDEF(classObject);
374#undef STATRICKCLASS
375
376///@param handle_defaults_when_saving see SyntParam
377SyntParam classProperties(bool handle_defaults_when_saving=true);
378// base properties:
379long refno; ///< unique reference number (former 'neuro' refno)
380
381long part_refno; ///< can be used by some items as the part ref#
382long joint_refno; ///< can be used by some items as the joint ref#
383
384Pt3D pos,rot;   ///< default = zero
385
386ModelUserTags userdata;
387
388Neuro();
389Neuro(double _state,double _inertia,double _force,double _sigmo);
390Neuro(const Neuro& src):PartBase(getDefaultStyle()) {operator=(src);}
391
392~Neuro();
393
394void operator=(const Neuro& src);
395
396/** Attach this Neuro to the specified Part or detach it from the body if p==NULL.
397    Neuro can be attached to either Part or Joint, but not both.
398    @see getPart()
399 */
400void attachToPart(Part* p) {part=p; joint=0;}
401
402/** Attach this Neuro to the specified Joint or detach it from the body if p==NULL.
403    Neuro can be attached to either Part or Joint, but not both.
404    @see getJoint()
405 */
406void attachToJoint(Joint* j) {joint=j; part=0;}
407
408void attachToPart(int i);
409void attachToJoint(int i);
410
411/** @return Part the Neuro is attached to, or NULL if it has no defined location on the body.
412    @see attachToPart()
413 */
414Part *getPart() {return part;}
415
416/** @return Joint the Neuro is attached to, or NULL if it has no defined location on the body.
417    @see attachToJoint()
418 */
419Joint *getJoint() {return joint;}
420
421int isOldEffector();
422int isOldReceptor();
423int isOldNeuron();
424int isNNConnection();
425
426/** @return the number of inputs connected to this Neuro.
427    Functions like getInput(), getInputWeight() will accept connection number [0..InputCount-1]
428 */
429int getInputCount() const {return inputs.size();}
430
431/// @return the number of output connections (including possible self-connections)
432int getOutputsCount() const;
433
434/** @return the Neuro connected as i-th input */
435Neuro* getInput(int i) const {return (i>=inputs.size())?0:inputs(i).n;}
436/** @return the Neuro connected as i-th input.
437    @param weight
438 */
439Neuro* getInput(int i,double &weight) const;
440/** @return connectin weight for i-th input */
441double getInputWeight(int i) const;
442/** change connection weight for i-th input */
443void setInputWeight(int i,double weight);
444/** connect i-th input with another neuron */
445void setInput(int i,Neuro*n);
446/** connect i-th input with another neuron */
447void setInput(int i,Neuro*n,double weight);
448/** add new input. @return its reference number */
449int addInput(Neuro* child,double weight=1.0,const SString* info=0);
450/** @return reference number [0..InputCount-1] of the input
451   or -1 if 'child' is not connected with this Neuro.*/
452int findInput(Neuro* child) const;
453void removeInput(int refno);
454/**    @return reference number of the child connection, like findInput() */
455int removeInput(Neuro* child);
456
457int findInputs(SList& result,const char* classname=0,const Part* part=0,const Joint* joint=0) const;
458int findOutputs(SList& result,const char* classname=0,const Part* part=0,const Joint* joint=0) const;
459
460/* class database retrieval */
461static int getClassCount();
462/** @return Neuro class name.
463    @param classindex 0 .. getClassCount()
464 */
465static SString getClassName(int classindex);
466static NeuroClass* getClass(int classindex);
467static NeuroClass* getClass(const SString& classname);
468static int getClassIndex(const NeuroClass*nc);
469
470#ifdef MODEL_V1_COMPATIBLE
471friend class OldItems;
472long neuro_refno; ///< parent ref# (called neuro_refno for compatibility with old Neuro class), @see moredata
473long conn_refno; ///< the other neuron ref# in N-N connections, can be used by some other items
474double weight; ///< weight of the N-N connection and (all?) receptors
475double inertia,force,sigmo; //!!!
476
477/** @deprecated provided only for compatibility with old Neuro/NeuroItem classes.
478    use getInputCount() instead. @sa getInputCount() */
479int getItemCount() {return oldItems().getItemCount();}
480
481/** @deprecated provided only for compatibility with old Neuro/NeuroItem classes.
482    use getInput() instead. @sa getInput() */
483NeuroItem* getNeuroItem(int i) {return oldItems().getNeuroItem(i);}
484#endif
485
486  protected:
487#ifdef MODEL_V1_COMPATIBLE
488/** old Neuro compatibility */
489OldItems* olditems;
490OldItems& oldItems() {if (!olditems) olditems=new OldItems(*this); return *olditems;}
491void invalidateOldItems() {if (olditems) olditems->freelist();}
492#endif
493
494  public:
495
496// not really private, but you should not access those directly
497double state;
498
499/** may reference parent neuron if parentcount is exacty 1. parent is invalid otherwise. @sa parentcount */
500Neuro *parent;
501int parentcount; ///< @sa parent
502
503Part *part;     ///< link to the Part
504Joint *joint;   ///< link to the Joint - required by some objects (eg.muscles)
505Orient o;       ///< rotation matrix calculated from "rot"
506static ParamEntry emptyParamTab[];
507static Param& getStaticParam();
508};
509
510#ifdef MODEL_V1_COMPATIBLE
511class NeuroItem;
512
513/// for compatibility with old NeuroItem class.
514class NeuroItem: public Neuro
515{
516public:
517NeuroItem() {}
518};
519#endif
520
521class NeuroExt: public Neuro
522{
523  public:
524#define STATRICKCLASS NeuroExt
525PARAMGETDEF(neuroclass);
526PARAMSETDEF(neuroclass);
527#undef STATRICKCLASS
528static ParamEntry *getParamTab();
529};
530
531class NeuroConn
532{
533void defassign();
534  public:
535int n1_refno,n2_refno;
536double weight;
537SString info;
538NeuroConn();
539};
540
541extern ParamEntry f0_part_paramtab[],f0_joint_paramtab[],f0_nodeltajoint_paramtab[],f0_neuro_paramtab[],f0_neuroconn_paramtab[],f0_neuroitem_paramtab[];
542
543#endif
Note: See TracBrowser for help on using the repository browser.