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

Last change on this file since 906 was 899, checked in by Maciej Komosinski, 5 years ago

Code formatting

  • 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
176
177////////////////// Neural Network /////////////////
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        {
265                /** don't draw neurons of this class */
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
289
290
291
292
293
294/** Single processing unit in Framsticks neural network.  */
295class Neuro : public PartBase
296{
297        friend class Model;
298        static SString getDefaultStyle();
299
300        struct NInput {
301                Neuro *n; double weight; SString *info;
302                NInput(Neuro *_n, double w, SString *i = 0) :n(_n), weight(w), info(i) {}
303        };
304
305        SListTempl<NInput> inputs;
306
307        NeuroClass *myclass;
308        bool knownclass;
309        SString myclassname, myclassparams;
310        /** set myclass and make knownclass=true */
311        void checkClass();
312        SString **inputInfo(int i);
313        void defassign();
314
315public:
316        enum NeuroFlags { HoldState = 2 };
317        Param properties();
318        Param extraProperties();
319
320        void setInputInfo(int i, const SString &name, const SString &value);
321        void setInputInfo(int i, const SString &name, int value);
322        void setInputInfo(int i, const SString &name, double value);
323        SString getInputInfo(int i);
324        SString getInputInfo(int i, const SString &name);
325
326        NeuroClass *getClass();
327        void setClass(NeuroClass *);
328
329        SString getClassParams() { return myclassparams; }
330        void setClassParams(const SString &cp) { myclassparams = cp; }
331
332        SString getClassName();
333        void setClassName(const SString &clazz);
334
335        /** return neuro unit details encoded as <CLASS> ":" <PROPERTIES>
336
337                new Neuro can be created as root object (without parent) or can be
338                the child of existing Neuro. Children of the Neuro are its inputs.
339                Standard Framsticks neuron calculates the sum of all input units - other processing
340                units don't have to treat them equally and can even ignore some of them.
341                There are hints about expected inputs in the class database, @see getClass
342
343                Application should not assume anything about classes and its properties
344                except for two standard classes: (information about all current classes
345                can be retrieved with getClass/getClassProperties methods)
346                - getClassName()="N" is the standard Framsticks neuron, accepts any number of inputs,
347                compatible with old Neuro object
348                - getClassName()="-" is the neuron link, compatible with old Neuro-Neuro link
349                (NeuroItem with empty details)
350                Empty details defaults to "-" if the parent unit is specified,
351                and "N" if the unit has no parent.
352                */
353        SString getDetails();
354
355        /** details = classname + ":" + classparams
356                @see getDetails()
357                */
358        void setDetails(const SString &);
359
360#define STATRICKCLASS Neuro
361        PARAMGETDEF(details) { arg1->setString(getDetails()); }
362        PARAMSETDEF(details) { setDetails(arg1->getString()); return PSET_CHANGED; }
363        PARAMGETDEF(inputCount);
364        PARAMPROCDEF(p_getInputNeuroDef);
365        PARAMPROCDEF(p_getInputNeuroIndex);
366        PARAMPROCDEF(p_getInputWeight);
367        PARAMGETDEF(classObject);
368#undef STATRICKCLASS
369
370        ///@param handle_defaults_when_saving see SyntParam
371        SyntParam classProperties(bool handle_defaults_when_saving = true);
372        // base properties:
373        paInt refno; ///< unique reference number (former 'neuro' refno)
374
375        paInt part_refno; ///< can be used by some items as the part ref#
376        paInt joint_refno; ///< can be used by some items as the joint ref#
377
378        Pt3D pos, rot;  ///< default = zero
379
380        ModelUserTags userdata;
381
382        Neuro();
383        Neuro(double _state, double _inertia, double _force, double _sigmo);
384        Neuro(const Neuro &src) :PartBase(getDefaultStyle()) { operator=(src); }
385
386        ~Neuro();
387
388        void operator=(const Neuro &src);
389
390        /** Attach this Neuro to the specified Part or detach it from the body if p==NULL.
391                Neuro can be attached to either Part or Joint, but not both.
392                @see getPart()
393                */
394        void attachToPart(Part *p) { part = p; joint = 0; }
395
396        /** Attach this Neuro to the specified Joint or detach it from the body if p==NULL.
397                Neuro can be attached to either Part or Joint, but not both.
398                @see getJoint()
399                */
400        void attachToJoint(Joint *j) { joint = j; part = 0; }
401
402        void attachToPart(int i);
403        void attachToJoint(int i);
404
405        /** @return Part the Neuro is attached to, or NULL if it has no defined location on the body.
406                @see attachToPart()
407                */
408        Part *getPart() { return part; }
409
410        /** @return Joint the Neuro is attached to, or NULL if it has no defined location on the body.
411                @see attachToJoint()
412                */
413        Joint *getJoint() { return joint; }
414
415        int isOldEffector();
416        int isOldReceptor();
417        int isOldNeuron();
418        int isNNConnection();
419
420        /** @return the number of inputs connected to this Neuro.
421                Functions like getInput(), getInputWeight() will accept connection number [0..InputCount-1]
422                */
423        int getInputCount() const { return inputs.size(); }
424
425        /// @return the number of output connections (including possible self-connections)
426        int getOutputsCount() const;
427
428        /** @return the Neuro connected as i-th input */
429        Neuro *getInput(int i) const { return (i >= inputs.size()) ? 0 : inputs(i).n; }
430        /** @return the Neuro connected as i-th input.
431                @param weight
432                */
433        Neuro *getInput(int i, double &weight) const;
434        /** @return connectin weight for i-th input */
435        double getInputWeight(int i) const;
436        /** change connection weight for i-th input */
437        void setInputWeight(int i, double weight);
438        /** connect i-th input with another neuron */
439        void setInput(int i, Neuro *n);
440        /** connect i-th input with another neuron */
441        void setInput(int i, Neuro *n, double weight);
442        /** add new input. @return its reference number */
443        int addInput(Neuro *child, double weight = 1.0, const SString *info = 0);
444        /** @return reference number [0..InputCount-1] of the input
445           or -1 if 'child' is not connected with this Neuro.*/
446        int findInput(Neuro *child) const;
447        void removeInput(paInt refno);
448        /**    @return reference number of the child connection, like findInput() */
449        int removeInput(Neuro *child);
450
451        int findInputs(SList &result, const char *classname = 0, const Part *part = 0, const Joint *joint = 0) const;
452        int findOutputs(SList &result, const char *classname = 0, const Part *part = 0, const Joint *joint = 0) const;
453
454        /* class database retrieval */
455        static int getClassCount();
456        /** @return Neuro class name.
457                @param classindex 0 .. getClassCount()
458                */
459        static SString getClassName(int classindex);
460        static NeuroClass *getClass(int classindex);
461        static NeuroClass *getClass(const SString &classname);
462        static int getClassIndex(const NeuroClass *nc);
463
464        // not really private, but you should not access those directly
465        double state;
466
467        /** may reference parent neuron if parentcount is exacty 1. parent is invalid otherwise. @sa parentcount */
468        Neuro *parent;
469        int parentcount; ///< @sa parent
470
471        Part *part;     ///< link to the Part
472        Joint *joint;   ///< link to the Joint - required by some objects (eg.muscles)
473        Orient o;       ///< rotation matrix calculated from "rot"
474        static ParamEntry emptyParamTab[];
475        static Param &getStaticParam();
476};
477
478class NeuroExt : public Neuro
479{
480public:
481#define STATRICKCLASS NeuroExt
482        PARAMGETDEF(neuroclass);
483        PARAMSETDEF(neuroclass);
484#undef STATRICKCLASS
485        static ParamEntry *getParamTab();
486};
487
488class NeuroConn
489{
490        void defassign();
491public:
492        int n1_refno, n2_refno;
493        double weight;
494        SString info;
495        NeuroConn();
496};
497
498extern ParamEntry f0_part_paramtab[], f0_joint_paramtab[], f0_nodeltajoint_paramtab[], f0_neuro_paramtab[], f0_neuroconn_paramtab[], f0_neuroitem_paramtab[];
499
500#endif
Note: See TracBrowser for help on using the repository browser.