Ticket #1988: anchor_only_visual.diff

File anchor_only_visual.diff, 33.5 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
    3536/**
     
    5859        UPRIGHT = 0,
    5960        PITCH = 1,
    6061        PITCH_ROLL = 2,
     62        ROLL=3,
    6163    } m_AnchorType;
    6264
    6365    bool m_Floating;
     
    7375    bool m_RelativeToGround; // whether m_YOffset is relative to terrain/water plane, or an absolute height
    7476
    7577    entity_angle_t m_RotX, m_RotY, m_RotZ;
    76     float m_InterpolatedRotY; // not serialized
    7778
     79    // not serialized;
     80    float m_InterpolatedRotX, m_InterpolatedRotY, m_InterpolatedRotZ;
     81    float m_LastInterpolatedRotX, m_LastInterpolatedRotZ; // not serialized
     82
     83    bool recalculateXZRotation;
     84
     85    CTerrain* m_Terrain;
     86
    7887    static std::string GetSchema()
    7988    {
    8089        return
     
    8998                "<choice>"
    9099                    "<value a:help='Always stand straight up'>upright</value>"
    91100                    "<value a:help='Rotate backwards and forwards to follow the terrain'>pitch</value>"
     101                    "<value a:help='Rotate sidewards to follow the terrain'>roll</value>"
    92102                    "<value a:help='Rotate in all direction to follow the terrain'>pitch-roll</value>"
    93103                "</choice>"
    94104            "</element>"
     
    110120            m_AnchorType = PITCH;
    111121        else if (anchor == L"pitch-roll")
    112122            m_AnchorType = PITCH_ROLL;
     123        else if (anchor == L"roll")
     124            m_AnchorType = ROLL;
    113125        else
    114126            m_AnchorType = UPRIGHT;
    115127
     
    123135
    124136        m_RotX = m_RotY = m_RotZ = entity_angle_t::FromInt(0);
    125137        m_InterpolatedRotY = 0;
     138
     139        m_Terrain = &GetSimContext().GetTerrain();
     140
    126141    }
    127142
    128143    virtual void Deinit()
     
    152167            const char* anchor = "???";
    153168            switch (m_AnchorType)
    154169            {
    155             case UPRIGHT: anchor = "upright"; break;
    156             case PITCH: anchor = "pitch"; break;
    157             case PITCH_ROLL: anchor = "pitch-roll"; break;
     170            case PITCH:
     171                anchor = "pitch";
     172                break;
     173
     174            case PITCH_ROLL:
     175                anchor = "pitch-roll";
     176                break;
     177           
     178            case ROLL:
     179                anchor = "roll";
     180                break;
     181
     182            case UPRIGHT: // upright is the default
     183            default:
     184                anchor = "upright";
     185                break;
    158186            }
    159187            serialize.StringASCII("anchor", anchor, 0, 16);
    160188            serialize.Bool("floating", m_Floating);
     
    181209        // TODO: should there be range checks on all these values?
    182210
    183211        m_InterpolatedRotY = m_RotY.ToFloat();
     212
     213        m_Terrain = &GetSimContext().GetTerrain();
     214
     215        UpdateXZRotation(m_X.ToFloat(), m_Z.ToFloat(), m_InterpolatedRotY);
    184216    }
    185217
    186218    virtual bool IsInWorld()
     
    197229
    198230    virtual void MoveTo(entity_pos_t x, entity_pos_t z)
    199231    {
     232       
    200233        m_X = x;
    201234        m_Z = z;
    202235
     
    216249        m_LastZ = m_PrevZ = m_Z = z;
    217250        m_InWorld = true;
    218251
     252        UpdateXZRotation(x.ToFloat(),z.ToFloat(),m_RotY.ToFloat());
     253
     254        m_LastInterpolatedRotX = m_InterpolatedRotX;
     255        m_LastInterpolatedRotZ = m_InterpolatedRotZ;
     256
    219257        AdvertisePositionChanges();
    220258    }
    221259
     
    319357
    320358    virtual void TurnTo(entity_angle_t y)
    321359    {
     360
    322361        m_RotY = y;
    323362
    324363        AdvertisePositionChanges();
     
    329368        m_RotY = y;
    330369        m_InterpolatedRotY = m_RotY.ToFloat();
    331370
     371        UpdateXZRotation(m_X.ToFloat(),m_Z.ToFloat(),m_InterpolatedRotY);
     372
     373        m_LastInterpolatedRotX = m_InterpolatedRotX;
     374        m_LastInterpolatedRotZ = m_InterpolatedRotZ;
     375
    332376        AdvertisePositionChanges();
    333377    }
    334378
     
    337381        m_RotX = x;
    338382        m_RotZ = z;
    339383
     384        UpdateXZRotation(m_X.ToFloat(),m_Z.ToFloat(),m_RotY.ToFloat());
     385
     386        m_LastInterpolatedRotX = m_InterpolatedRotX;
     387        m_LastInterpolatedRotZ = m_InterpolatedRotZ;
     388
    340389        AdvertisePositionChanges();
    341390    }
    342391
     
    370419        rotY = m_InterpolatedRotY;
    371420    }
    372421
     422
     423    virtual void UpdateXZRotation(float x, float z, float rotY)
     424    {
     425
     426
     427        if (!m_RotZ.IsZero() || !m_RotX.IsZero())
     428        {
     429            // set the visual rotations to the ones fixed by the interface
     430            m_InterpolatedRotX = m_RotX.ToFloat();
     431            m_InterpolatedRotZ = m_RotZ.ToFloat();
     432            return;
     433        }
     434       
     435        if (m_AnchorType == UPRIGHT)
     436            // change nothing if anchor is upright
     437            return;
     438
     439        if (m_Terrain->GetVerticesPerSide() == 0)
     440        {
     441            // try again when terrain is loaded
     442            recalculateXZRotation = true;
     443            return;
     444        }
     445
     446        // TODO average normal (average all the tiles?) for big units or for buildings
     447        CVector3D normal = m_Terrain->CalcExactNormal(x, z);
     448
     449        // rotate the normal so the positive x direction is in the direction of the unit
     450        CVector2D projected = CVector2D(normal.X, normal.Z);
     451        projected.Rotate(rotY);
     452
     453        normal.X = projected.X;
     454        normal.Z = projected.Y;
     455
     456        if (m_AnchorType == PITCH || m_AnchorType == PITCH_ROLL)
     457            // project and calculate the angle
     458            m_InterpolatedRotX = -atan2(normal.Z, normal.Y);
     459
     460        if (m_AnchorType == ROLL || m_AnchorType == PITCH_ROLL)
     461            // project and calculate the angle
     462            m_InterpolatedRotZ = atan2(normal.X,normal.Y);
     463
     464        recalculateXZRotation = false;
     465       
     466        return;
     467    }
     468
    373469    virtual CMatrix3D GetInterpolatedTransform(float frameOffset, bool forceFloating)
    374470    {
     471
     472
    375473        if (!m_InWorld)
    376474        {
    377475            LOGERROR(L"CCmpPosition::GetInterpolatedTransform called on entity when IsInWorld is false");
     
    400498
    401499        float y = baseY + m_YOffset.ToFloat();
    402500
    403         // TODO: do something with m_AnchorType
    404501
    405         CMatrix3D m;
    406         m.SetXRotation(m_RotX.ToFloat());
    407         m.RotateZ(m_RotZ.ToFloat());
     502        CMatrix3D m;
     503       
     504        // linear interpolation is good enough (for RotX/Z).
     505        // As you always stay close to zero angle. 
     506        m.SetXRotation(Interpolate(m_LastInterpolatedRotX,m_InterpolatedRotX,frameOffset));
     507        m.RotateZ(Interpolate(m_LastInterpolatedRotZ,m_InterpolatedRotZ,frameOffset));
     508   
    408509        m.RotateY(rotY + (float)M_PI);
    409510        m.Translate(CVector3D(x, y, z));
    410511       
     
    417518        {
    418519        case MT_Interpolate:
    419520        {
     521
    420522            const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg);
    421523
    422524            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;
     525           
    433526
     527            if (rotY != m_InterpolatedRotY)
     528            {
     529                float delta = rotY - m_InterpolatedRotY;
     530                // Wrap delta to -M_PI..M_PI
     531                delta = fmodf(delta + (float)M_PI, 2*(float)M_PI); // range -2PI..2PI
     532                if (delta < 0) delta += 2*(float)M_PI; // range 0..2PI
     533                delta -= (float)M_PI; // range -M_PI..M_PI
     534                // Clamp to max rate
     535                float deltaClamped = clamp(delta, -m_RotYSpeed*msgData.deltaSimTime, +m_RotYSpeed*msgData.deltaSimTime);
     536                // Calculate new orientation, in a peculiar way in order to make sure the
     537                // result gets close to m_orientation (rather than being n*2*M_PI out)
     538                m_InterpolatedRotY = rotY + deltaClamped - delta;
     539               
     540                m_LastInterpolatedRotX = m_InterpolatedRotX;
     541                m_LastInterpolatedRotZ = m_InterpolatedRotZ;
     542               
     543                // update the visual XZ rotation
     544                UpdateXZRotation(m_X.ToFloat(),m_Z.ToFloat(),m_InterpolatedRotY);
     545            }
     546           
     547            if (recalculateXZRotation)
     548            {
     549                // something went wrong with the previous calculation (terrain not loaded), we need to update the rotation without interpolation
     550                UpdateXZRotation(m_X.ToFloat(), m_Z.ToFloat(),m_RotY.ToFloat());
     551                m_LastInterpolatedRotX = m_InterpolatedRotX;
     552                m_LastInterpolatedRotZ = m_InterpolatedRotZ;
     553            }
     554
    434555            break;
    435556        }
    436557        case MT_TurnStart:
    437         {
     558           
     559            m_LastInterpolatedRotX = m_InterpolatedRotX;
     560            m_LastInterpolatedRotZ = m_InterpolatedRotZ;
     561           
     562            if (m_LastX != m_X || m_LastZ != m_Z)
     563            {
     564                UpdateXZRotation(m_X.ToFloat(), m_Z.ToFloat(),m_RotY.ToFloat());
     565            }
     566
    438567            // Store the positions from the turn before
    439568            m_PrevX = m_LastX;
    440569            m_PrevZ = m_LastZ;
    441            
     570
    442571            m_LastX = m_X;
    443572            m_LastZ = m_Z;
    444 
     573               
    445574            break;
    446         }
    447         }
    448575    }
     576};
    449577
    450578private:
    451579    void AdvertisePositionChanges()