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

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