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

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

Added fields to characterize hinges in "solid shape"-type Models

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