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

Last change on this file since 932 was 932, checked in by Maciej Komosinski, 4 years ago

Neuron classes now have a property (a bit field) that says whether each neuron class supports model shape BALL_AND_STICK, SOLIDS, or both

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