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

Last change on this file since 854 was 844, checked in by Maciej Komosinski, 6 years ago

Initialization of static fields in a template conforming to the C++17 standard

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