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

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

source reorganization (see README)
new feature added: part/joint shapes (see frams/_demos/part_shapes.cpp)

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