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

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

Hinges and a muscle for solid shapes in f0

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