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

Last change on this file since 839 was 839, checked in by Maciej Komosinski, 7 days ago

Added extern template declarations for UserTags? reg[N] static members

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