Ticket #1988: anchor_hybrid.diff

File anchor_hybrid.diff, 37.8 KB (added by sanderd17, 11 years ago)
  • binaries/data/mods/public/simulation/templates/gaia/fauna_bear.xml

     
    1818    <SpecificName>Bear</SpecificName>
    1919    <Icon>gaia/fauna_bear.png</Icon>
    2020  </Identity>
     21  <Position>
     22    <Anchor>pitch</Anchor>
     23  </Position>
    2124  <Sound>
    2225    <SoundGroups>
    2326      <select>actor/fauna/animal/lion_select.xml</select>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_boar.xml

     
    1818    <SpecificName>Boar</SpecificName>
    1919    <Icon>gaia/fauna_boar.png</Icon>
    2020  </Identity>
     21  <Position>
     22    <Anchor>pitch</Anchor>
     23  </Position>
    2124  <ResourceSupply>
    2225    <Amount>150</Amount>
    2326    <Type>food.meat</Type>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_camel.xml

     
    1212  <Obstruction>
    1313    <Unit radius="1.5"/>
    1414  </Obstruction>
     15  <Position>
     16    <Anchor>pitch</Anchor>
     17  </Position>
    1518  <Sound>
    1619    <SoundGroups>
    1720      <select>actor/fauna/animal/camel.xml</select>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_deer.xml

     
    55    <SpecificName>Deer</SpecificName>
    66    <Icon>gaia/fauna_deer.png</Icon>
    77  </Identity>
     8  <Position>
     9    <Anchor>pitch</Anchor>
     10  </Position>
    811  <UnitMotion>
    912    <WalkSpeed>2.0</WalkSpeed>
    1013    <Run>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_elephant.xml

     
    1414    <SpecificName>Elephant</SpecificName>
    1515    <Icon>gaia/fauna_elephant.png</Icon>
    1616  </Identity>
     17  <Position>
     18    <Anchor>pitch</Anchor>
     19  </Position>
    1720  <Sound>
    1821    <SoundGroups>
    1922      <select>actor/fauna/animal/elephant_select.xml</select>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_elephant_african_bush.xml

     
    5353  <Obstruction>
    5454    <Unit radius="3.5"/>
    5555  </Obstruction>
     56  <Position>
     57    <Anchor>pitch</Anchor>
     58  </Position>
    5659  <ResourceSupply>
    5760    <Amount>800</Amount>
    5861    <Type>food.meat</Type>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_elephant_african_infant.xml

     
    1818  <Obstruction>
    1919    <Unit radius="1.5"/>
    2020  </Obstruction>
     21  <Position>
     22    <Anchor>pitch</Anchor>
     23  </Position>
    2124  <ResourceSupply>
    2225    <Amount>100</Amount>
    2326    <Type>food.meat</Type>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_elephant_asian.xml

     
    5353  <Obstruction>
    5454    <Unit radius="2.7"/>
    5555  </Obstruction>
     56  <Position>
     57    <Anchor>pitch</Anchor>
     58  </Position>
    5659  <ResourceSupply>
    5760    <Amount>650</Amount>
    5861    <Type>food.meat</Type>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_gazelle.xml

     
    55    <SpecificName>Gazelle</SpecificName>
    66    <Icon>gaia/fauna_gazelle.png</Icon>
    77  </Identity>
     8  <Position>
     9    <Anchor>pitch</Anchor>
     10  </Position>
    811  <UnitMotion>
    912    <Run>
    1013      <Range>600.0</Range>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_giraffe.xml

     
    1616  <Obstruction>
    1717    <Unit radius="2.0"/>
    1818  </Obstruction>
     19  <Position>
     20    <Anchor>pitch</Anchor>
     21  </Position>
    1922  <ResourceSupply>
    2023    <Amount>350</Amount>
    2124    <Type>food.meat</Type>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_giraffe_infant.xml

     
    1212  <Obstruction>
    1313    <Unit radius="1.5"/>
    1414  </Obstruction>
     15  <Position>
     16    <Anchor>pitch</Anchor>
     17  </Position>
    1518  <ResourceSupply>
    1619    <Amount>150</Amount>
    1720    <Type>food.meat</Type>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_goat.xml

     
    1111    <SpecificName>Goat</SpecificName>
    1212    <Icon>gaia/fauna_goat.png</Icon>
    1313  </Identity>
     14  <Position>
     15    <Anchor>pitch</Anchor>
     16  </Position>
    1417  <ResourceSupply>
    1518    <Amount>120</Amount>
    1619    <Type>food.meat</Type>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_horse.xml

     
    1212  <Obstruction>
    1313    <Unit radius="1.5"/>
    1414  </Obstruction>
     15  <Position>
     16    <Anchor>pitch</Anchor>
     17  </Position>
    1518  <ResourceSupply>
    1619    <Amount>200</Amount>
    1720  </ResourceSupply>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_lion.xml

     
    1818    <SpecificName>Lion</SpecificName>
    1919    <Icon>gaia/fauna_lion.png</Icon>
    2020  </Identity>
     21  <Position>
     22    <Anchor>pitch</Anchor>
     23  </Position>
    2124  <Sound>
    2225    <SoundGroups>
    2326      <select>actor/fauna/animal/lion_select.xml</select>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_lioness.xml

     
    1818    <SpecificName>Lion</SpecificName>
    1919    <Icon>gaia/fauna_lion.png</Icon>
    2020  </Identity>
     21  <Position>
     22    <Anchor>pitch</Anchor>
     23  </Position>
    2124  <Sound>
    2225    <SoundGroups>
    2326      <select>actor/fauna/animal/lion_select.xml</select>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_muskox.xml

     
    99    <SpecificName>Muskox</SpecificName>
    1010    <Icon>gaia/fauna_muskox.png</Icon>
    1111  </Identity>
     12  <Position>
     13    <Anchor>pitch</Anchor>
     14  </Position>
    1215  <ResourceSupply>
    1316    <Amount>200</Amount>
    1417    <Type>food.meat</Type>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_pig.xml

     
    55    <SpecificName>Pig</SpecificName>
    66    <Icon>gaia/fauna_pig.png</Icon>
    77  </Identity>
     8  <Position>
     9    <Anchor>pitch</Anchor>
     10  </Position>
    811  <StatusBars>
    912    <HeightOffset>5.0</HeightOffset>
    1013  </StatusBars>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_rabbit.xml

     
    99    <SpecificName>Rabbit</SpecificName>
    1010    <Icon>gaia/fauna_rabbit.png</Icon>
    1111  </Identity>
     12  <Position>
     13    <Anchor>pitch</Anchor>
     14  </Position>
    1215  <ResourceSupply>
    1316    <Amount>50</Amount>
    1417    <Type>food.meat</Type>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_sheep.xml

     
    1212    <Classes datatype="tokens">Domestic</Classes>
    1313    <Icon>gaia/fauna_sheep.png</Icon>
    1414  </Identity>
     15  <Position>
     16    <Anchor>pitch</Anchor>
     17  </Position>
    1518  <Sound>
    1619    <SoundGroups>
    1720      <select>actor/fauna/animal/sheep.xml</select>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_tiger.xml

     
    1818    <SpecificName>Tiger</SpecificName>
    1919    <Icon>gaia/fauna_tiger.png</Icon>
    2020  </Identity>
     21  <Position>
     22    <Anchor>pitch</Anchor>
     23  </Position>
    2124  <Sound>
    2225    <SoundGroups>
    2326      <select>actor/fauna/animal/lion_select.xml</select>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_walrus.xml

     
    2323    <SpecificName>Walrus</SpecificName>
    2424    <Icon>gaia/fauna_walrus.png</Icon>
    2525  </Identity>
     26  <Position>
     27    <Anchor>pitch</Anchor>
     28  </Position>
    2629  <ResourceSupply>
    2730    <Amount>300</Amount>
    2831    <Type>food.meat</Type>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_wildebeest.xml

     
    1010    <History>The wildebeest (plural wildebeest, wildebeests or wildebai), also called the gnu, is an antelope of the genus Connochaetes. It is a hooved (ungulate) mammal. Wildebeest are well known for their annual migration to new pastures in which vast numbers of wildebeest can be seen crossing rivers, such as the Mara River and dying in large numbers as they attempt to reach the other side. Many of them are eaten by crocodiles while others simply drown. Herds of wildebeest possesses what is known as "swarm intelligence", whereby the animals systematically explore and overcome obstacles as one when, for instance, crossing a river or defending against predator attacks.</History>
    1111    <Icon>gaia/fauna_wildebeest.png</Icon>
    1212  </Identity>
     13  <Position>
     14    <Anchor>pitch</Anchor>
     15  </Position>
    1316  <ResourceSupply>
    1417    <Amount>150</Amount>
    1518    <Type>food.meat</Type>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_wolf.xml

     
    1818    <SpecificName>Wolf</SpecificName>
    1919    <Icon>gaia/fauna_wolf.png</Icon>
    2020  </Identity>
     21  <Position>
     22    <Anchor>pitch</Anchor>
     23  </Position>
    2124  <VisualActor>
    2225    <Actor>fauna/wolf.xml</Actor>
    2326  </VisualActor>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_wolf_snow.xml

     
    1818    <SpecificName>Snow Wolf</SpecificName>
    1919    <Icon>gaia/fauna_wolf_snow.png</Icon>
    2020  </Identity>
     21  <Position>
     22    <Anchor>pitch</Anchor>
     23  </Position>
    2124  <VisualActor>
    2225    <Actor>fauna/wolf_snow.xml</Actor>
    2326  </VisualActor>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_zebra.xml

     
    99    <SpecificName>Zebra</SpecificName>
    1010    <Icon>gaia/fauna_zebra.png</Icon>
    1111  </Identity>
     12  <Position>
     13    <Anchor>pitch</Anchor>
     14  </Position>
    1215  <ResourceSupply>
    1316    <Amount>150</Amount>
    1417    <Type>food.meat</Type>
  • binaries/data/mods/public/simulation/templates/gaia/geology_metal_alpine.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22<Entity parent="template_gaia_geo_mineral">
    3   <Position>
    4     <Anchor>pitch-roll</Anchor>
    5   </Position>
    63  <VisualActor>
    74    <Actor>geology/metalmine_alpine.xml</Actor>
    85  </VisualActor>
  • binaries/data/mods/public/simulation/templates/gaia/geology_metal_desert_small.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22<Entity parent="template_gaia_geo_mineral">
    3   <Position>
    4     <Anchor>pitch-roll</Anchor>
    5   </Position>
    63  <VisualActor>
    74    <Actor>geology/metalmine_desert_small.xml</Actor>
    85  </VisualActor>
  • binaries/data/mods/public/simulation/templates/gaia/geology_metal_greek.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22<Entity parent="template_gaia_geo_mineral">
    3   <Position>
    4     <Anchor>pitch-roll</Anchor>
    5   </Position>
    63  <VisualActor>
    74    <Actor>geology/metalmine_granite_greek.xml</Actor>
    85  </VisualActor>
  • binaries/data/mods/public/simulation/templates/gaia/geology_metal_mediterranean.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22<Entity parent="template_gaia_geo_mineral">
    3   <Position>
    4     <Anchor>pitch-roll</Anchor>
    5   </Position>
    63  <VisualActor>
    74    <Actor>geology/metalmine_mediterranean.xml</Actor>
    85  </VisualActor>
  • binaries/data/mods/public/simulation/templates/gaia/geology_metal_temperate.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22<Entity parent="template_gaia_geo_mineral">
    3   <Position>
    4     <Anchor>pitch-roll</Anchor>
    5   </Position>
    63  <VisualActor>
    74    <Actor>geology/metalmine_granite_temperate.xml</Actor>
    85  </VisualActor>
  • binaries/data/mods/public/simulation/templates/gaia/geology_metal_tropic.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22<Entity parent="template_gaia_geo_mineral">
    3   <Position>
    4     <Anchor>pitch-roll</Anchor>
    5   </Position>
    63  <VisualActor>
    74    <Actor>geology/metalmine_tropic.xml</Actor>
    85  </VisualActor>
  • binaries/data/mods/public/simulation/templates/gaia/geology_stone_alpine_a.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22<Entity parent="template_gaia_geo_rock">
    3   <Position>
    4     <Anchor>pitch-roll</Anchor>
    5   </Position>
    63  <VisualActor>
    74    <Actor>geology/stonemine_alpine_a.xml</Actor>
    85  </VisualActor>
  • binaries/data/mods/public/simulation/templates/gaia/geology_stone_desert_small.xml

     
    77  <Identity>
    88    <Icon>gaia/geology_stone_2.png</Icon>
    99  </Identity>
    10   <Position>
    11     <Anchor>pitch-roll</Anchor>
    12   </Position>
    1310  <VisualActor>
    1411    <Actor>geology/stonemine_desert_small.xml</Actor>
    1512  </VisualActor>
  • binaries/data/mods/public/simulation/templates/gaia/geology_stone_greek.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22<Entity parent="template_gaia_geo_rock">
    3   <Position>
    4     <Anchor>pitch-roll</Anchor>
    5   </Position>
    63  <VisualActor>
    74    <Actor>geology/stonemine_granite_greek.xml</Actor>
    85  </VisualActor>
  • binaries/data/mods/public/simulation/templates/gaia/geology_stone_mediterranean.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22<Entity parent="template_gaia_geo_rock">
    3   <Position>
    4     <Anchor>pitch-roll</Anchor>
    5   </Position>
    63  <VisualActor>
    74    <Actor>geology/stonemine_mediterranean.xml</Actor>
    85  </VisualActor>
  • binaries/data/mods/public/simulation/templates/gaia/geology_stone_savanna_small.xml

     
    77  <Identity>
    88    <Icon>gaia/geology_stone_2.png</Icon>
    99  </Identity>
    10   <Position>
    11     <Anchor>pitch-roll</Anchor>
    12   </Position>
    1310  <VisualActor>
    1411    <Actor>geology/stonemine_savanna_small.xml</Actor>
    1512  </VisualActor>
  • binaries/data/mods/public/simulation/templates/gaia/geology_stone_temperate.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22<Entity parent="template_gaia_geo_rock">
    3   <Position>
    4     <Anchor>pitch-roll</Anchor>
    5   </Position>
    63  <VisualActor>
    74    <Actor>geology/stonemine_granite.xml</Actor>
    85  </VisualActor>
  • binaries/data/mods/public/simulation/templates/gaia/geology_stone_tropic_a.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22<Entity parent="template_gaia_geo_rock">
    3   <Position>
    4     <Anchor>pitch-roll</Anchor>
    5   </Position>
    63  <VisualActor>
    74    <Actor>geology/stonemine_tropic.xml</Actor>
    85  </VisualActor>
  • binaries/data/mods/public/simulation/templates/template_gaia_geo.xml

     
    1010  <Obstruction>
    1111    <Static width="7.0" depth="7.0"/>
    1212  </Obstruction>
     13  <Position>
     14    <Anchor>pitch-roll</Anchor>
     15  </Position>
    1316  <Selectable>
    1417    <EditorOnly disable=""/>
    1518    <Overlay>
  • binaries/data/mods/public/simulation/templates/template_gaia_geo_mineral_slabs.xml

     
    77  <Obstruction>
    88    <Static width="13.0" depth="13.0"/>
    99  </Obstruction>
    10   <Position>
    11     <Anchor>pitch-roll</Anchor>
    12   </Position>
    1310  <ResourceSupply>
    1411    <Amount>5000</Amount>
    1512    <MaxGatherers>24</MaxGatherers>
  • binaries/data/mods/public/simulation/templates/template_gaia_geo_rock_slabs.xml

     
    77  <Obstruction>
    88    <Static width="13.0" depth="13.0"/>
    99  </Obstruction>
    10   <Position>
    11     <Anchor>pitch-roll</Anchor>
    12   </Position>
    1310  <ResourceSupply>
    1411    <Amount>5000</Amount>
    1512    <MaxGatherers>24</MaxGatherers>
  • binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry.xml

     
    4242  <Obstruction>
    4343    <Unit radius="1.0"/>
    4444  </Obstruction>
     45  <Position>
     46    <Anchor>pitch</Anchor>
     47  </Position>
    4548  <Selectable>
    4649    <Overlay>
    4750      <Texture>
  • binaries/data/mods/public/simulation/templates/template_unit_champion_elephant.xml

     
    3131  <Obstruction>
    3232    <Unit radius="4.0"/>
    3333  </Obstruction>
     34  <Position>
     35    <Anchor>pitch</Anchor>
     36  </Position>
    3437  <Selectable>
    3538    <Overlay>
    3639      <Texture>
  • binaries/data/mods/public/simulation/templates/units/maur_support_elephant.xml

     
    3838    <stone>10</stone>
    3939    <metal>10</metal>
    4040  </Loot>
     41  <Position>
     42    <Anchor>pitch</Anchor>
     43  </Position>
    4144  <ResourceDropsite>
    4245    <Types>food wood stone metal</Types>
    4346  </ResourceDropsite>
  • source/simulation2/components/CCmpPosition.cpp

     
    3030#include "maths/MathUtil.h"
    3131#include "maths/Matrix3D.h"
    3232#include "maths/Vector3D.h"
     33#include "maths/Vector2D.h"
    3334#include "ps/CLogger.h"
    3435
     36#include "graphics/Terrain.h"
     37#include "math.h"
     38
    3539/**
    3640 * Basic ICmpPosition implementation.
    3741 */
     
    5862        UPRIGHT = 0,
    5963        PITCH = 1,
    6064        PITCH_ROLL = 2,
     65        ROLL=3,
    6166    } m_AnchorType;
    6267
    6368    bool m_Floating;
     
    7378    bool m_RelativeToGround; // whether m_YOffset is relative to terrain/water plane, or an absolute height
    7479
    7580    entity_angle_t m_RotX, m_RotY, m_RotZ;
    76     float m_InterpolatedRotY; // not serialized
    7781
     82    CTerrain* m_Terrain; // not null
     83
     84    // not serialized;
     85    float m_InterpolatedRotX, m_InterpolatedRotY, m_InterpolatedRotZ;
     86    float m_LastInterpolatedRotX, m_LastInterpolatedRotZ; // not serialized
     87
     88    bool recalculateXZRotation, recalculateVisualXZRotation;
     89    bool m_ManualXZRotation;
     90
    7891    static std::string GetSchema()
    7992    {
    8093        return
     
    89102                "<choice>"
    90103                    "<value a:help='Always stand straight up'>upright</value>"
    91104                    "<value a:help='Rotate backwards and forwards to follow the terrain'>pitch</value>"
     105                    "<value a:help='Rotate sidewards to follow the terrain'>roll</value>"
    92106                    "<value a:help='Rotate in all direction to follow the terrain'>pitch-roll</value>"
    93107                "</choice>"
    94108            "</element>"
     
    110124            m_AnchorType = PITCH;
    111125        else if (anchor == L"pitch-roll")
    112126            m_AnchorType = PITCH_ROLL;
     127        else if (anchor == L"roll")
     128            m_AnchorType = ROLL;
    113129        else
    114130            m_AnchorType = UPRIGHT;
    115131
     
    123139
    124140        m_RotX = m_RotY = m_RotZ = entity_angle_t::FromInt(0);
    125141        m_InterpolatedRotY = 0;
     142        m_ManualXZRotation = false;
     143
     144        m_Terrain = &GetSimContext().GetTerrain();
     145
    126146    }
    127147
    128148    virtual void Deinit()
     
    146166        serialize.NumberFixed_Unbounded("rot z", m_RotZ);
    147167        serialize.NumberFixed_Unbounded("altitude", m_YOffset);
    148168        serialize.Bool("relative", m_RelativeToGround);
     169        serialize.Bool("manual rotation",m_ManualXZRotation);
    149170
    150171        if (serialize.IsDebug())
    151172        {
    152173            const char* anchor = "???";
    153174            switch (m_AnchorType)
    154175            {
    155             case UPRIGHT: anchor = "upright"; break;
    156             case PITCH: anchor = "pitch"; break;
    157             case PITCH_ROLL: anchor = "pitch-roll"; break;
     176            case PITCH:
     177                anchor = "pitch";
     178                break;
     179
     180            case PITCH_ROLL:
     181                anchor = "pitch-roll";
     182                break;
     183           
     184            case ROLL:
     185                anchor = "roll";
     186                break;
     187
     188            case UPRIGHT: // upright is the default
     189            default:
     190                anchor = "upright";
     191                break;
    158192            }
    159193            serialize.StringASCII("anchor", anchor, 0, 16);
    160194            serialize.Bool("floating", m_Floating);
     
    178212        deserialize.NumberFixed_Unbounded("rot z", m_RotZ);
    179213        deserialize.NumberFixed_Unbounded("altitude", m_YOffset);
    180214        deserialize.Bool("relative", m_RelativeToGround);
     215        deserialize.Bool("manual rotation",m_ManualXZRotation);
    181216        // TODO: should there be range checks on all these values?
    182217
    183218        m_InterpolatedRotY = m_RotY.ToFloat();
     219
     220        UpdateXZRotation(m_X,m_Z,m_RotY);
     221
     222        m_LastInterpolatedRotX = m_InterpolatedRotX;
     223        m_LastInterpolatedRotZ = m_InterpolatedRotZ;
     224
    184225    }
    185226
    186227    virtual bool IsInWorld()
     
    197238
    198239    virtual void MoveTo(entity_pos_t x, entity_pos_t z)
    199240    {
     241       
    200242        m_X = x;
    201243        m_Z = z;
    202244
     
    216258        m_LastZ = m_PrevZ = m_Z = z;
    217259        m_InWorld = true;
    218260
     261        UpdateXZRotation(x,z,m_RotY);
     262
     263        m_LastInterpolatedRotX = m_InterpolatedRotX;
     264        m_LastInterpolatedRotZ = m_InterpolatedRotZ;
     265
    219266        AdvertisePositionChanges();
    220267    }
    221268
     
    319366
    320367    virtual void TurnTo(entity_angle_t y)
    321368    {
     369
    322370        m_RotY = y;
    323371
    324372        AdvertisePositionChanges();
     
    329377        m_RotY = y;
    330378        m_InterpolatedRotY = m_RotY.ToFloat();
    331379
     380        UpdateXZRotation(m_X,m_Z,m_RotY);
     381
     382        m_LastInterpolatedRotX = m_InterpolatedRotX;
     383        m_LastInterpolatedRotZ = m_InterpolatedRotZ;
     384
    332385        AdvertisePositionChanges();
    333386    }
    334387
     
    336389    {
    337390        m_RotX = x;
    338391        m_RotZ = z;
     392       
     393        m_ManualXZRotation = true;
    339394
     395        UpdateXZRotation(m_X,m_Z,m_RotY);
     396
     397        m_LastInterpolatedRotX = m_InterpolatedRotX;
     398        m_LastInterpolatedRotZ = m_InterpolatedRotZ;
     399
    340400        AdvertisePositionChanges();
    341401    }
    342402
     403    virtual void UnSetXZRotation()
     404    {
     405        m_ManualXZRotation = false;
     406
     407        UpdateXZRotation(m_X,m_Z,m_RotY);
     408
     409        m_LastInterpolatedRotX = m_InterpolatedRotX;
     410        m_LastInterpolatedRotZ = m_InterpolatedRotZ;
     411
     412        AdvertisePositionChanges();
     413       
     414    }
     415
    343416    virtual CFixedVector3D GetRotation()
    344417    {
    345418        return CFixedVector3D(m_RotX, m_RotY, m_RotZ);
     
    370443        rotY = m_InterpolatedRotY;
    371444    }
    372445
     446    virtual void UpdateXZRotation(entity_pos_t x, entity_pos_t z, entity_angle_t rotY)
     447    {
     448        UpdateVisualXZRotation(x.ToFloat(), z.ToFloat(), rotY.ToFloat());
     449
     450        if(m_ManualXZRotation)
     451            return;
     452       
     453        if(m_AnchorType == UPRIGHT)
     454        {
     455            m_RotX = m_RotZ = entity_pos_t::Zero();
     456            return;
     457        }
     458
     459        CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
     460        if (!cmpTerrain || !cmpTerrain->IsLoaded())
     461        {
     462            // try again when terrain is loaded
     463            recalculateXZRotation = true;
     464            recalculateVisualXZRotation = true;
     465            return;
     466        }
     467
     468        CFixedVector3D normal = cmpTerrain->CalcNormal(x,z);
     469
     470        CFixedVector2D projected = CFixedVector2D(normal.X, normal.Z);
     471        projected = projected.Rotate(-rotY);
     472
     473        normal.X = projected.X;
     474        normal.Z = projected.Y;
     475
     476        if (m_AnchorType == PITCH || m_AnchorType == PITCH_ROLL)
     477            // project and calculate the angle
     478            m_RotX = -atan2_approx(normal.Z, normal.Y);
     479
     480        if (m_AnchorType == ROLL || m_AnchorType == PITCH_ROLL)
     481            // project and calculate the angle
     482            m_RotZ = atan2_approx(normal.X,normal.Y);
     483
     484        recalculateXZRotation = false;
     485
     486        return;
     487    }
     488
     489    virtual void UpdateVisualXZRotation(float x, float z, float rotY)
     490    {
     491
     492
     493        if (m_ManualXZRotation)
     494        {
     495            // set the visual rotations to the ones fixed by the interface
     496            m_InterpolatedRotX = m_RotX.ToFloat();
     497            m_InterpolatedRotZ = m_RotZ.ToFloat();
     498            return;
     499        }
     500       
     501        if (m_AnchorType == UPRIGHT)
     502        {
     503            m_InterpolatedRotX = m_InterpolatedRotZ = 0.f;
     504            return;
     505        }
     506
     507        if (m_Terrain->GetVerticesPerSide() == 0)
     508        {
     509            // try again when terrain is loaded
     510            recalculateVisualXZRotation = true;
     511            return;
     512        }
     513
     514        // TODO average normal (average all the tiles?) for big units or for buildings
     515        CVector3D normal = m_Terrain->CalcExactNormal(x, z);
     516
     517        // rotate the normal so the positive x direction is in the direction of the unit
     518        CVector2D projected = CVector2D(normal.X, normal.Z);
     519        projected.Rotate(rotY);
     520
     521        normal.X = projected.X;
     522        normal.Z = projected.Y;
     523
     524        if (m_AnchorType == PITCH || m_AnchorType == PITCH_ROLL)
     525            // project and calculate the angle
     526            m_InterpolatedRotX = -atan2(normal.Z, normal.Y);
     527
     528        if (m_AnchorType == ROLL || m_AnchorType == PITCH_ROLL)
     529            // project and calculate the angle
     530            m_InterpolatedRotZ = atan2(normal.X,normal.Y);
     531
     532        recalculateVisualXZRotation = false;
     533
     534        return;
     535    }
     536
    373537    virtual CMatrix3D GetInterpolatedTransform(float frameOffset, bool forceFloating)
    374538    {
     539
     540
    375541        if (!m_InWorld)
    376542        {
    377543            LOGERROR(L"CCmpPosition::GetInterpolatedTransform called on entity when IsInWorld is false");
     
    400566
    401567        float y = baseY + m_YOffset.ToFloat();
    402568
    403         // TODO: do something with m_AnchorType
    404569
    405         CMatrix3D m;
    406         m.SetXRotation(m_RotX.ToFloat());
    407         m.RotateZ(m_RotZ.ToFloat());
     570        CMatrix3D m;
     571       
     572        // linear interpolation is good enough (for RotX/Z).
     573        // As you always stay close to zero angle. 
     574        m.SetXRotation(Interpolate(m_LastInterpolatedRotX,m_InterpolatedRotX,frameOffset));
     575        m.RotateZ(Interpolate(m_LastInterpolatedRotZ,m_InterpolatedRotZ,frameOffset));
     576   
    408577        m.RotateY(rotY + (float)M_PI);
    409578        m.Translate(CVector3D(x, y, z));
    410579       
     
    417586        {
    418587        case MT_Interpolate:
    419588        {
     589
    420590            const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg);
    421591
    422592            float rotY = m_RotY.ToFloat();
    423             float delta = rotY - m_InterpolatedRotY;
    424             // Wrap delta to -M_PI..M_PI
    425             delta = fmodf(delta + (float)M_PI, 2*(float)M_PI); // range -2PI..2PI
    426             if (delta < 0) delta += 2*(float)M_PI; // range 0..2PI
    427             delta -= (float)M_PI; // range -M_PI..M_PI
    428             // Clamp to max rate
    429             float deltaClamped = clamp(delta, -m_RotYSpeed*msgData.deltaSimTime, +m_RotYSpeed*msgData.deltaSimTime);
    430             // Calculate new orientation, in a peculiar way in order to make sure the
    431             // result gets close to m_orientation (rather than being n*2*M_PI out)
    432             m_InterpolatedRotY = rotY + deltaClamped - delta;
     593           
    433594
     595            if (rotY != m_InterpolatedRotY)
     596            {
     597                float delta = rotY - m_InterpolatedRotY;
     598                // Wrap delta to -M_PI..M_PI
     599                delta = fmodf(delta + (float)M_PI, 2*(float)M_PI); // range -2PI..2PI
     600                if (delta < 0) delta += 2*(float)M_PI; // range 0..2PI
     601                delta -= (float)M_PI; // range -M_PI..M_PI
     602                // Clamp to max rate
     603                float deltaClamped = clamp(delta, -m_RotYSpeed*msgData.deltaSimTime, +m_RotYSpeed*msgData.deltaSimTime);
     604                // Calculate new orientation, in a peculiar way in order to make sure the
     605                // result gets close to m_orientation (rather than being n*2*M_PI out)
     606                m_InterpolatedRotY = rotY + deltaClamped - delta;
     607               
     608                m_LastInterpolatedRotX = m_InterpolatedRotX;
     609                m_LastInterpolatedRotZ = m_InterpolatedRotZ;
     610               
     611                // update the visual XZ rotation
     612                UpdateVisualXZRotation(m_X.ToFloat(),m_Z.ToFloat(),m_InterpolatedRotY);
     613            }
     614           
     615            if (recalculateVisualXZRotation)
     616            {
     617                // something went wrong with the previous calculation (terrain not loaded), we need to update the rotation without interpolation
     618                UpdateVisualXZRotation(m_X.ToFloat(), m_Z.ToFloat(),rotY);
     619                m_LastInterpolatedRotX = m_InterpolatedRotX;
     620                m_LastInterpolatedRotZ = m_InterpolatedRotZ;
     621            }
     622
    434623            break;
    435624        }
    436625        case MT_TurnStart:
    437         {
     626           
     627            m_LastInterpolatedRotX = m_InterpolatedRotX;
     628            m_LastInterpolatedRotZ = m_InterpolatedRotZ;
     629           
     630            if (m_LastX != m_X || m_LastZ != m_Z || recalculateXZRotation)
     631            {
     632                UpdateXZRotation(m_X, m_Z,m_RotY);
     633            }
     634
    438635            // Store the positions from the turn before
    439636            m_PrevX = m_LastX;
    440637            m_PrevZ = m_LastZ;
    441            
     638
    442639            m_LastX = m_X;
    443640            m_LastZ = m_Z;
    444 
     641               
    445642            break;
    446         }
    447         }
    448643    }
     644};
    449645
    450646private:
    451647    void AdvertisePositionChanges()
  • source/simulation2/components/ICmpPosition.cpp

     
    3737DEFINE_INTERFACE_METHOD_1("TurnTo", void, ICmpPosition, TurnTo, entity_angle_t)
    3838DEFINE_INTERFACE_METHOD_1("SetYRotation", void, ICmpPosition, SetYRotation, entity_angle_t)
    3939DEFINE_INTERFACE_METHOD_2("SetXZRotation", void, ICmpPosition, SetXZRotation, entity_angle_t, entity_angle_t)
     40DEFINE_INTERFACE_METHOD_0("UnSetXZRotation", void, ICmpPosition, UnSetXZRotation)
    4041DEFINE_INTERFACE_METHOD_0("GetRotation", CFixedVector3D, ICmpPosition, GetRotation)
    4142// Excluded: GetInterpolatedTransform (not safe for scripts)
    4243END_INTERFACE_WRAPPER(Position)
  • source/simulation2/components/ICmpPosition.h

     
    140140     */
    141141    virtual void SetXZRotation(entity_angle_t x, entity_angle_t z) = 0;
    142142
     143    /**
     144     * Unset the XZ rotation (let it handle by the Anchor and terrain)
     145     */
     146    virtual void UnSetXZRotation() = 0;
     147
     148
    143149    // NOTE: we separate Y from XZ because most code will only ever change Y;
    144150    // XZ are typically just used in the editor, and other code should never
    145151    // worry about them
  • source/simulation2/components/tests/test_RangeManager.h

     
    5555    virtual void TurnTo(entity_angle_t UNUSED(y)) { }
    5656    virtual void SetYRotation(entity_angle_t UNUSED(y)) { }
    5757    virtual void SetXZRotation(entity_angle_t UNUSED(x), entity_angle_t UNUSED(z)) { }
     58    virtual void UnSetXZRotation() { }
    5859    virtual CFixedVector3D GetRotation() { return CFixedVector3D(); }
    5960    virtual fixed GetDistanceTravelled() { return fixed::Zero(); }
    6061    virtual void GetInterpolatedPosition2D(float UNUSED(frameOffset), float& x, float& z, float& rotY) { x = z = rotY = 0; }