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
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
[738]2// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
[286]3// See LICENSE.txt for details.
[109]4
5#ifndef _MODELPARTS_H_
6#define _MODELPARTS_H_
7
8#include <frams/util/3d.h>
[121]9#include <frams/genetics/genoconv.h>
[109]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
[899]26typedef UserTags<Model, void *, 5> ModelUserTags;
[109]27
28/** Common base for model elements. */
29class PartBase
30{
31public:
[714]32        SString vis_style;
[899]33        PartBase(const SString &s) :vis_style(s), mapped(0) {}
[714]34        ~PartBase();
[899]35        static SString getDefaultStyle() { return SString("none"); }
[714]36        MultiRange *mapped;
37        enum PartBaseFlags { Selected = 1 };
38        int flags;
39        Model *owner;   ///< backlink to the model
[109]40
[714]41        SString info;
[109]42
[714]43        Model &getModel() const { return *owner; }
[109]44
[714]45        ModelUserTags userdata;
[109]46
[714]47        void notifyMappingChange();
[109]48
[714]49        void clearMapping();
[899]50        MultiRange *getMapping() { return mapped; }
[714]51        void setMapping(const IRange &mr);
52        void addMapping(const IRange &mr);
53        void setMapping(const MultiRange &mr);
54        void addMapping(const MultiRange &mr);
[109]55
[899]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);
[109]60};
61
[408]62/// Part is the only real physical object in the Framsticks creature.
[109]63/// You can use this class for querying and adjusting constructed
64/// model properties
[714]65class Part : public PartBase
[109]66{
[714]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)
[109]71        {}
[714]72        void defassign();
[109]73public:
[714]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
[109]82
[714]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" ;-)
[109]91
[714]92        Pt3D vcolor;
93        double vsize;
[109]94
[714]95        Part(enum Shape s = SHAPE_BALL_AND_STICK);
[899]96        Part(const Part &src) :PartBase(getDefaultStyle()) { operator=(src); }
97        void operator=(const Part &src);
[109]98
[714]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
[109]102
[899]103        static Param &getStaticParam();
[109]104};
105
106/// Imaginary connection between two parts.
107/// Joint has no mass nor intertia but can transfer forces.
[714]108class Joint : public PartBase
[109]109{
[714]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();
[109]119public:
[714]120        // base properties:
121        paInt p1_refno, p2_refno; ///< parts' reference numbers
[109]122
[714]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
[915]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.
[109]134
[714]135        Joint();
[899]136        Joint(const Joint &src) :PartBase(getDefaultStyle()) { operator=(src); }
137        void operator=(const Joint &src);
[109]138
[714]139        /** connect two parts with this joint.
140                p2 position will be adjusted if delta option is in effect.
141                @see isDelta()
142                */
[899]143        void attachToParts(Part *p1, Part *p2);
[714]144        /// @see attachToParts(Part*,Part*)
145        void attachToParts(int p1, int p2);
[109]146
[714]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();
[109]151
[714]152        /** enable or disable delta option.
153                delta value is not changed.
154                */
155        void useDelta(bool use);
[109]156
[714]157        /** @return true if delta option is in effect.
158                @see useDelta(), resetDelta(), useDelta()
159                */
160        bool isDelta();
[109]161
[714]162        /// ParamInterface object is preferred way to get/set other properties.
163        Param extraProperties();
164        Param properties();
[109]165
[714]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;
[109]175
[899]176        static Param &getStaticParam();
[109]177};
178
179#define JOINT_DELTA_MARKER 99999.0
180
181
[899]182
183////////////////// Neural Network /////////////////
184
[109]185class NeuroClass;
186
[899]187typedef UserTags<NeuroClass, void *, 5> NeuroClassUserTags;
[109]188
189/** Information about neuron class.
190 */
191class NeuroClass
192{
[714]193        bool ownedvectordata;
[899]194        void operator=(const NeuroClass &nosuchthich) {}
[714]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;
[109]203
[714]204        //void *impl;
205        int impl_count;
206        bool active;
207        bool genactive;
208        NeuroClassUserTags userdata;
[109]209
[714]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" */
[899]217        const SString &getName() { return name; }
[714]218        /** human friendly name, eg. "Neuron","Link","Gyroscope"  */
[899]219        const SString &getLongName() { return longname; }
[714]220        /** long description */
[899]221        const SString &getDescription() { return description; }
222        ParamEntry *getParamTab() { return props; }
[109]223
[714]224        /** NeuroClass specific properties, recognized by all neurons of this class */
225        Param getProperties() { return Param(props); }
[109]226
[714]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; }
[109]231
[714]232        /** @return 0 if this object doesn't provide useful output signal. */
233        int getPreferredOutput() { return (int)prefoutput; }
[109]234
[714]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                */
[899]250        int *getSymbolGlyph()
[714]251        {
252                return vectordata;
253        }
254        void setSymbolGlyph(int *data, bool owned = 1)
255        {
[899]256                if (vectordata && ownedvectordata) delete[]vectordata;
[714]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        }
[109]268
[714]269        enum Hint
[738]270        {
[714]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        };
[109]287
[714]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
[899]292        static void setGenActive(const char *classes[]); ///< set genactive for specified classes
[109]293};
294
295
[899]296
297
298
299
300/** Single processing unit in Framsticks neural network.  */
[714]301class Neuro : public PartBase
[109]302{
[714]303        friend class Model;
304        static SString getDefaultStyle();
[109]305
[714]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        };
[109]310
[714]311        SListTempl<NInput> inputs;
[109]312
[714]313        NeuroClass *myclass;
314        bool knownclass;
315        SString myclassname, myclassparams;
316        /** set myclass and make knownclass=true */
317        void checkClass();
[899]318        SString **inputInfo(int i);
[714]319        void defassign();
[109]320
321public:
[714]322        enum NeuroFlags { HoldState = 2 };
323        Param properties();
324        Param extraProperties();
[109]325
[899]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);
[714]329        SString getInputInfo(int i);
[899]330        SString getInputInfo(int i, const SString &name);
[109]331
[899]332        NeuroClass *getClass();
333        void setClass(NeuroClass *);
[109]334
[714]335        SString getClassParams() { return myclassparams; }
[899]336        void setClassParams(const SString &cp) { myclassparams = cp; }
[109]337
[714]338        SString getClassName();
[899]339        void setClassName(const SString &clazz);
[109]340
[714]341        /** return neuro unit details encoded as <CLASS> ":" <PROPERTIES>
[109]342
[714]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
[109]348
[714]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();
[109]360
[714]361        /** details = classname + ":" + classparams
362                @see getDetails()
363                */
[899]364        void setDetails(const SString &);
[714]365
[109]366#define STATRICKCLASS Neuro
[714]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);
[109]374#undef STATRICKCLASS
375
[714]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)
[109]380
[714]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#
[109]383
[714]384        Pt3D pos, rot;  ///< default = zero
[109]385
[714]386        ModelUserTags userdata;
[109]387
[714]388        Neuro();
389        Neuro(double _state, double _inertia, double _force, double _sigmo);
[899]390        Neuro(const Neuro &src) :PartBase(getDefaultStyle()) { operator=(src); }
[109]391
[714]392        ~Neuro();
[109]393
[899]394        void operator=(const Neuro &src);
[109]395
[714]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                */
[899]400        void attachToPart(Part *p) { part = p; joint = 0; }
[109]401
[714]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                */
[899]406        void attachToJoint(Joint *j) { joint = j; part = 0; }
[109]407
[714]408        void attachToPart(int i);
409        void attachToJoint(int i);
[109]410
[714]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; }
[109]415
[714]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; }
[109]420
[714]421        int isOldEffector();
422        int isOldReceptor();
423        int isOldNeuron();
424        int isNNConnection();
[109]425
[714]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(); }
[109]430
[714]431        /// @return the number of output connections (including possible self-connections)
432        int getOutputsCount() const;
[109]433
[714]434        /** @return the Neuro connected as i-th input */
[899]435        Neuro *getInput(int i) const { return (i >= inputs.size()) ? 0 : inputs(i).n; }
[714]436        /** @return the Neuro connected as i-th input.
437                @param weight
438                */
[899]439        Neuro *getInput(int i, double &weight) const;
[714]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 */
[899]445        void setInput(int i, Neuro *n);
[714]446        /** connect i-th input with another neuron */
[899]447        void setInput(int i, Neuro *n, double weight);
[714]448        /** add new input. @return its reference number */
[899]449        int addInput(Neuro *child, double weight = 1.0, const SString *info = 0);
[714]450        /** @return reference number [0..InputCount-1] of the input
451           or -1 if 'child' is not connected with this Neuro.*/
[899]452        int findInput(Neuro *child) const;
[714]453        void removeInput(paInt refno);
454        /**    @return reference number of the child connection, like findInput() */
[899]455        int removeInput(Neuro *child);
[109]456
[899]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;
[109]459
[714]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);
[899]466        static NeuroClass *getClass(int classindex);
467        static NeuroClass *getClass(const SString &classname);
468        static int getClassIndex(const NeuroClass *nc);
[109]469
[714]470        // not really private, but you should not access those directly
471        double state;
[109]472
[714]473        /** may reference parent neuron if parentcount is exacty 1. parent is invalid otherwise. @sa parentcount */
474        Neuro *parent;
475        int parentcount; ///< @sa parent
[109]476
[714]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[];
[899]481        static Param &getStaticParam();
[109]482};
483
[714]484class NeuroExt : public Neuro
[109]485{
[714]486public:
[109]487#define STATRICKCLASS NeuroExt
[714]488        PARAMGETDEF(neuroclass);
489        PARAMSETDEF(neuroclass);
[109]490#undef STATRICKCLASS
[714]491        static ParamEntry *getParamTab();
[109]492};
493
494class NeuroConn
495{
[714]496        void defassign();
497public:
498        int n1_refno, n2_refno;
499        double weight;
500        SString info;
501        NeuroConn();
[109]502};
503
[714]504extern ParamEntry f0_part_paramtab[], f0_joint_paramtab[], f0_nodeltajoint_paramtab[], f0_neuro_paramtab[], f0_neuroconn_paramtab[], f0_neuroitem_paramtab[];
[109]505
506#endif
Note: See TracBrowser for help on using the repository browser.