User Tools

Site Tools


arma:howto_animate_model

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
arma:howto_animate_model [2007-07-04 11:54]
snakeman created howto_animate_model initial page
arma:howto_animate_model [2017-10-06 22:08] (current)
snakeman http to https switch.
Line 1: Line 1:
-====== How to Animate ​Model ======+====== How To Animate Model ======
  
-SLX for their animation tutorials and examples.+**Attention:​**
  
-====== Animations / translations ======+This article is a tutorial on how to animate parts of your model (e.g. wheels, rotors, etc.). Take all information of this article with a pinch of salt: everything is based on experiments and hasn't been confirmed nor documented by BIS, yet.
  
-after my own tests on the animationshave discovered the following things: for the bonesit is possible to link several bones almost like in the article.+To animate a modelyou have to make use of both, the //​cfgModels//​ and //​cfgSkeletons//​ class.
  
-<​code>​+The //​cfgSkeletons//​ class defines the bones of a vehicle. Bones are, more or less, the __animated selections__ of a model. 
 + 
 +The //​cfgModels//​ class is an extended version of the OFP cfgModels class. It defines the selections of a model which you want to animate or use with the setObjectTexture command, but since ArmA, you have to put everything related to animate your model in here. 
 + 
 +**Model preparation:​** 
 + 
 +Besides adding selections (same as in OFP but in ArmA bone selections should never overlap) you also need to add a following named property to your first resolution LOD (press **ALT-P** to open named properties window): 
 + 
 +<​code ​cpp> 
 +   ​property name: autocenter 
 +   ​value:​ 0 
 +</​code>​ 
 + 
 +If your model has Geometry LOD the above needs to be also done for your Geometry LOD. This property stops engine from shifting the animation axes. 
 + 
 +If you encounter a bug when your weapon bones fall apart after you drop it to the ground the reason might be lack of Geometry or View - pilot LODs. 
 + 
 +====== model.cfg ====== 
 + 
 +According to the article about Model Config, the cfgSkeletons and cfgModels class should be part of a model.cfg file which is located in the addon pbo file. However, this does not seems to work (I assume the model.cfg files will be put into the model p3d file during binarization). For now, you can add the cfgSkeletons and cfgModels class to your config.cpp which works like a charm. 
 + 
 +====== CfgSkeletons ====== 
 + 
 +The //​cfgSkeletons//​ class defines, as mentioned before, the bones (animated selections) of a vehicle. 
 + 
 +Each skeleton is a subclass within the cfgSkeletons class, consisting of three parameters:​ 
 + 
 +^ Parameter ^ Description ^ 
 +| isDiscrete | currently unknown, set to 1 | 
 +| skeletonInherit | inherit bones from given class | 
 +| skeletonBones[] | define your own bones here | 
 + 
 +====== Defining a bone ====== 
 + 
 +Bones are defined in the skeletonBones[] array which is made of a list of unsorted bones. Each bone is the name of a selection you want to animate. 
 + 
 +====== A single bone ====== 
 + 
 +A bone is defined by using two strings: 
 + 
 +<code cpp> 
 +:"​bone",""​ 
 +</​code>​ 
 + 
 +You may define multiple bones by stringing them together. 
 + 
 +**Attention:​** Do not leave out the second string as this will lead to errors! (see linked bones for more information on the second string argument) 
 + 
 +**Example** 
 + 
 +<code cpp>
 skeletonBones[]= skeletonBones[]=
 { {
- "​bone1",""​  + "​bone1",""​, //defines bone1 
- "​bone2","​bone1",​ + "​bone2","" ​ //​defines ​bone2
- "​bone3",​"bone2" ​     ​+
 }; };
 </​code>​ </​code>​
  
-here, we have bone3 connected to bone2, which is connected to bone1. if bone1 move, bone2 and bone3 will move with him. if bone2 move, only bone3 will move with it, bone1 will remain unchanged, etc... i haven'​t tested the maximum limit of bones you can link like that, but 3 bones linked like that works perfectly. ​+**Linked ​bones**
  
-the translations. ​for the translations,​ you need offset0 and offset1 in place of angle0 and angle1.+The second argument (empty in the example above) is used for linking two bones:
  
-one thing important to know about translation axis(done several tests about it)+<code cpp> 
 +:"​bone1","​bone2"​ 
 +</​code>​
  
-the distance between ​the two points ​of your axis will become the "unit" ​of the offsetin the following examplehave an offset1="​5"​which means the bone will translate by 5 units. if the distance between the two points of my axis is 1 meter (assuming meters are the base unit in oxygen), the bone will move by 5 meters. if the distance between my two points is different, the bone movement ​will scale accordingly - if distance between the two points ​of the axis is 0.5m, the bone will only translate by 2.5 meters. ​+Linking is used to make the animation of "​bone1"​ depending on the movement ​of "bone2"​. ​If you e.g. have a turretyou have to make use of linking herebecause ​the up and down movement of the turrets weapon ​is typically influenced ​by left and right movement of the turret:
  
-this particular point might be useful if you have to scale up or scale down your whole model, if it is already animated, because the offset value may not need to change.+**Example**
  
-<​code>​ +<​code ​cpp> 
-class translatedobject+skeletonBones[]= 
 +
 + "​turret_x","", ​        //​defines bone turret_x 
 + "​turret_y","​turret_x" ​ //defines bone turret_y and makes it linked to bone turret_x 
 +}; 
 +</​code>​ 
 + 
 +**Attention:​** 
 + 
 +You can not link more than two bones in a row! If you do something like 
 + 
 +<code cpp> 
 +"​bone1","​bone2","​bone3"​ 
 +</​code>​ 
 + 
 +This will result in an error, as Armed Assault interprets this as: 
 +  * defining "​bone1"​ which is linked to "​bone2"​ 
 +  * defining "​bone3",​ //which misses the second argument.//​ 
 + 
 +However, it should be possible to use a syntax like this (not tested yet): 
 + 
 +<code cpp> 
 +skeletonBones[]= 
 +
 + "​bone1","​bone2",​ //defines bone "​bone1"​ and makes it linked to "​bone2"​ 
 + "​bone2","​bone3",​ //defines bone "​bone2"​ and makes it linked to "​bone3"​ 
 + "​bone3","" ​      //​defines bone "​bone3"​. 
 +}; 
 +</​code>​ 
 + 
 +In conclusion, "​bone1"​ is linked to "​bone2",​ which is linked to "​bone3"​. So "​bone1"​ should be depending on the movement of both, "​bone2"​ and "​bone3"​. 
 + 
 +**cfgSkeletons Example** 
 + 
 +<code cpp> 
 +class cfgSkeletons 
 +
 + class BWMod_Tiger_Skeleton 
 +
 + isDiscrete=1;​ 
 + 
 + skeletonInherit="";​ 
 + skeletonBones[]= 
 +
 + "​wheelL","",​ 
 + "​wheelR","",​ 
 + 
 + "​turret_RMK_x","",​ 
 + "​turret_RMK_y","​turret_RMK_x",​ 
 + 
 + "​turret_OSIRIS_y","",​ 
 + "​turret_OSIRIS_x","​turret_OSIRIS_y"​ 
 + }; 
 + }; 
 +}; 
 +</​code>​ 
 + 
 +====== cfgModels ====== 
 + 
 +The cfgModels class is used to declare the selections of a model you want to animate or access via the setObjectTexture command. Since ArmA, the cfgModels class has been extended an is now used to define all animations of a model. 
 + 
 +Each of your model is a subclass inside of the cfgModels class and the models filename is used as the name of your class (without .p3d). E.g. your model p3d is named "​myVehicle.p3d"​ your class is "class myvehicle {}". We will call them "​modelclasses"​ in this article for the sake of simplicity. 
 + 
 +Each modelclass consists of three parameters and an additional subclass which defines the animations of your models: 
 + 
 +^ Parameter ^ Description ^ 
 +| sectionsInherits | inherit sections (= selections) from given glass | 
 +| sections[] | define your sections here | 
 +| skeletonName | class name of skeleton used by this model | 
 +| class Animations {} | subclass which defines the animations of your model | 
 + 
 +**Sections** 
 + 
 +A section is the same as a selection: a part of the model which may be animated or changed via the setObjectTexture command. To define selections in your modelclass make use of the section[]-array. This array is an unordered list of all selections you want to use in the ways described above. 
 + 
 +**Example** 
 + 
 +<code cpp> 
 +sections[]= 
 +
 + "​mainRotor","​mainRotor_static","​mainRotor_blur","​mainRotor_dive",​ 
 + "​tailRotor","​tailRotor_static","​tailRotor_blur","​tailRotor_dive",​ 
 + 
 + "​turret_RMK_x","​turret_RMK_y"​ 
 +}; 
 +</​code>​ 
 + 
 +**Animations** 
 + 
 +To define animations for your model, you have to make use of the class animations in your modelclass. Each animation is a subclass in the class animations with a user definable name and consists of the following parameters:​ 
 + 
 +^ Parameter ^ Description ^ 
 +| type | the type of the animation, e.g. rotating or translation. Refer to Model Config for a list of all animation types | 
 +| source | The source used to animate the selection. Refer to Model Config for a list of all sources | 
 +| selection | The name of the bone (= selection) you want to animate. Has to be defined in the cfgSkeletons class | 
 +| axis | The name of the axis you want to use (only necessary for types //​rotation//​ and //​translation//​) | 
 +| memory | If using an own axis (by the axis-parameter) use value 1 if axis is located in the memory lod of your model or 0 if the axis is located in the lod (or better: every lod) where your animated selection is used | 
 +| sourceAdress | Use "​loop"​ if you want your animation to "​loop"​ (e.g. on wheels) or "​clamp"​ if you want your animation to stop at a specific angle (e.g. on the steering wheel of a car) | 
 +| minValue | If source returns a value <= minValue, the animation is animated with angle0 (see below) | 
 +| maxValue | If source returns a value >= maxValue, the animation is animated with angle1 (see below) | 
 +| angle0 | The angle the selection is animated when minValue is reached | 
 +| angle1 | The angle the selection is animated when maxValue is reached | 
 +| offset0 | The distance the bone is moved when using type="​rotation"​ and minValue is returned. Distance is calculated by the distance of axis' vertices. If the have a distance of 1m and you are using offset0 = 1, the bone will be moved by 1m. If using offset0=0.5,​ the bone will be moved by 0.5m, etc | 
 +| offset1 | Same as offset0, but when maxValue is returned | 
 + 
 +**Attention** 
 + 
 +I am assuming that each source is returning a value between 0 and 1 (the //​animationPhase//​) which is used to animate your selection. Some may even return a value from -1 to 1: 
 +  * If using source="​speed",​ the source is returning 0 when the vehicle is not moving and 1 when the vehicle is moving at maximum speed 
 +  * If using source="​drivingWheel",​ the source is returning -1 when the vehicle is turning left, 0 when the vehicle is not turning and 1 when the vehicle is turning right 
 + 
 +//On turrets, it is necessary that the classnames of the animations match the according turret selection names.// 
 + 
 +So if you're mainTurret selection is named "​turret_RMK_x"​ you have to name your class "​turret_RMK_y",​ too. The same goes for the mainGun selection. 
 + 
 +**Example** 
 + 
 +<code cpp
 +class mainRotor
 { {
- type="​translation"; + type="​rotationY"; ​//rotation around the Y axis 
- source="​animtranslate"; + source="​rotorH"; 
- selection="​translatedbone"; + selection="​mainRotor"; 
- axis="​translateaxis";+ axis=""; ​//no own axis, use centre of selection
  memory=1;  memory=1;
- sourceAddress="​clamp"; + sourceAddress="​loop"; 
- minValue="0"+ minValue=0;​ 
- maxValue="1"+ maxValue=1;​ 
- offset0="0"+ angle0=0; 
- offset1="5";+ angle1="rad -360";
 }; };
 </​code>​ </​code>​
  
-another important point to know, is that the types TranslationXTranslationYand TranslationZif used without ​axis, do not have a meter based unitso it may be better to use your own axis for doing accurate translationsAlsowithout an axis, the translation ​will correctly translate along the XZ or Y axis, but the game engine seems to act weird for the direction to follow along this axis (several times, the object moved only in one direction, whatever ​the offset1 value was negative or not.)+**Axes** 
 + 
 +Since the axes seem a bit messed up when using //​rotationX//​//​rotationY//,​ //​rotationZ//,​ //​translationX//,​ //​translationY//,​ //​translationZ//,​ here is a small image of how the axes are arranged. 
 + 
 +Keep in mind that this image shows only the direction of these axes and //not// their position. The position is always defined by the center of your animated selection. 
 + 
 +As a short examplethe wheels would need "​rotationX"​ as animation type. 
 + 
 +{{https://​pmc.editing.wiki/​images/​howtoanimmodel_axes.jpg}} 
 + 
 +**cfgModels example** 
 + 
 +<code cpp> 
 +class cfgModels 
 +
 + class bwmod_tiger 
 +
 + sectionsInherit="";​ 
 + sections[]= 
 +
 + "​mainRotor"​,"​mainRotor_static"​,"​mainRotor_blur","​mainRotor_dive",​ 
 + "​tailRotor","​tailRotor_static","​tailRotor_blur","​tailRotor_dive",​ 
 + 
 + "​turret_RMK_x","​turret_RMK_y"​ 
 + }; 
 + 
 + skeletonName="​BWMod_Tiger_Skeleton";​ 
 + 
 + class Animations 
 +
 + class mainRotor 
 +
 + type="​rotationY";​ 
 + source="​rotorH";​ 
 + selection="​mainRotor";​ 
 + axis="";​ 
 + memory=1;​ 
 + sourceAddress="​loop";​ 
 + minValue=0;​ 
 + maxValue=1;​ 
 + angle0=0;​ 
 + angle1="​rad -360";​ 
 + }; 
 + 
 + class tailRotor 
 +
 + type="​rotationX";​ 
 + source="​rotorV";​ 
 + selection="​tailRotor";​ 
 + axis="";​ 
 + memory=1;​ 
 + sourceAddress="​loop";​ 
 + minValue=0;​ 
 + maxValue=1;​ 
 + angle0=0;​ 
 + angle1="​rad -360";​ 
 + }; 
 + 
 + class wheelL 
 +
 + type="​translation";​ 
 + source="​altRadar"; ​ //using altRadarsince damper doesn'​t seem to work on  
 +                     //​helicopters,​ even though [[Model_Config]] states something 
 +                     //else. 
 + selection="​wheelL";​ 
 + axis="​axis_damper";​ //vertical axis, vertex distance 1 m 
 + memory=0;​ 
 + animPeriod=0;​ 
 + minValue=0;​ 
 + maxValue=0.05; ​     //max value 0.05m above ground 
 + offset0=0;​ 
 + offset1=-0.05; ​     //animate wheels downwards ​for 0.05m when maxValue is reached. 
 + }; 
 + 
 + class wheelR 
 +
 + type="​translation";​ 
 + source="​altRadar";​ 
 + selection="​wheelR";​ 
 + axis="​axis_damper";​ 
 + memory=0;​ 
 + animPeriod=0;​ 
 + minValue=0;​ 
 + maxValue=0.05;​ 
 + offset0=0;​ 
 + offset1=-0.05;​ 
 + }; 
 + 
 + class turret_RMK_x //the horizontal moving part of the turret 
 +
 + type="​rotationY";​ 
 + source="​mainTurret";​ 
 + selection="​turret_RMK_x";​ 
 + axis="​axis_turret_RMK_x";​ 
 + animPeriod=0;​ 
 + memory=1;​ 
 + minValue="​rad -360";​ 
 + maxValue="​rad +360";​ 
 + angle0="​rad -360";​ 
 + angle1="​rad +360";​ 
 + }; 
 + 
 + class turret_RMK_y //the vertical moving part of the turret 
 +
 + type="​rotationX";​ 
 + source="​mainGun";​ 
 + selection="​turret_RMK_y";​ 
 + axis="​axis_turret_RMK_y";​ 
 + animPeriod=0;​ 
 + memory=1;​ 
 + minValue="​rad -360";​ 
 + maxValue="​rad +360";​ 
 + angle0="​rad -360";​ 
 + angle1="​rad +360";​ 
 + }; 
 + }; 
 + }; 
 +}; 
 +</​code>​ 
 + 
 +====== Machine Gun Belt Rotation ====== 
 + 
 +Open your model in O2 and make a selection called "​belt_rotation"​redefine the entire belt of bullets you want move on your MG and save it. 
 + 
 +Inside your model.cfg file open this class: 
 +<code cpp> 
 +class CfgSkeletons 
 +
 + class NameOfYourWeapon 
 +
 + isDiscrete = 0; 
 + skeletonInherit = "";​ 
 + skeletonBones[] = 
 +
 + "​belt_rotation",​ ""​ 
 + }; 
 + }; 
 +}; 
 +</​code>​ 
 +Again in the model.cfg file, inside your CfgModels describe the new selection and animation as you see below. 
 +<code cpp> 
 +class CfgModels 
 +
 + class Default 
 +
 + sections[] = {}; 
 + sectionsInherit = "";​ 
 + }; 
 + 
 + class Weapon: default{};​ 
 + 
 + class NameOfYourWeapon 
 +
 + skeletonName = "​NameOfYourWeapon";​ 
 + 
 + class Animations 
 +
 + 
 + class belt_rotation 
 +
 + type = "​rotationx";​ 
 + source = "​reload";​ 
 + selection = "​belt_rotation";​ 
 + axis = "​belt_rotation_axis";​ 
 + minValue = 0; 
 + maxValue = "​5";​ 
 + angle0 = "​0";​ 
 + angle1 = "​1";​ 
 + }; 
 + }; 
 + 
 + sections[] = { "​zasleh"​ }; 
 + sectionsInherit = "";​ 
 + }; 
 +}; 
 +</​code>​ 
 +To play around with the sliding belt you just need to take two values in consideration. 
 + 
 +The first is the type = ""​"​rotationx"​ will move you belt from the left to the right or right to the left, the second is the definition of the starting side the angle1 = ""​. 
 + 
 +"​0"​ is a static value which means it won't move at all, negative values like "​-1",​ "​-2"​ ... will make the belt move from the right to the leftpositive values like the "​1"​"​2"​ ... will make it move from the left to the right. 
 + 
 +One thing to take into consideration is the "​rotationz"​ not presented here. Let's say you have the belt not attached to a box but instead falling from the ground. If that is the case you want the belt to move from below to above, ​for that you will use the "​rotationz"​ and again you play with the angle called angle1 = ""​ to set direction ​of the belt's movement. 
 + 
 +Now something worth noticing, let's say that you want the belt to move not straight but unbalancedfor that you will play with the angle0 = ""​. I think most of us won't be using this angle but now you know what it does. 
 + 
 + 
 +====== Animate Cargo Door ====== 
 + 
 +In your model.cfg file in cfgModels put this for example: 
 +<code cpp> 
 +class Animations 
 +
 + class cargodoor 
 +
 + type = "​rotation";​ 
 + source = "​MoveX1";​ 
 + animPeriod = 2.5; 
 + sourceAddress = "​clamp";​ 
 + selection = "​cargodoor";​ 
 + axis = "​osa_cargodoor";​ 
 + memory = true; 
 + minValue = 0; 
 + maxValue = 1; 
 + angle0 = 0; 
 + angle1 = -0.488690;​ 
 + }; 
 +</​code>​ 
 + 
 +In config.cpp file in cfgVehicles put this: 
 +<code cpp> 
 + class AnimationSources:​ AnimationSources 
 +
 + class MoveX1 // Should be the same as your selection name. 
 +
 + source = "​user";​ //The controller is defined as a user animation. 
 + animPeriod = 10;  //The animation period used for this controller. 
 + initPhase = 0;     //​Initial phase when object is created. 0 = CLOSED 
 + }; 
 + }; 
 +</​code>​ 
 +And 
 +<code cpp> 
 + class UserActions 
 +
 + class CargoDoor_OpenP 
 +
 + displayName = "Open cargodoor";​ 
 + position = "​pilotcontrol";​ 
 + onlyforplayer = false; 
 + radius = 0.5; 
 + condition = "this animationPhase ""​cargodoor_down""​ < 0.5";​ 
 + statement = "this animate [""​cargodoor_down"",​1];​ this animate [""​cargodoor_up"",​1]";​ 
 + }; 
 +</​code>​
arma/howto_animate_model.1183550047.txt.gz · Last modified: 2007-07-10 09:52 (external edit)