ROOT logo
// $Id: Flyer.cxx 2325 2010-01-07 22:45:36Z matevz $

// Copyright (C) 1999-2008, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.

#include "Flyer.h"
#include "Flyer.c7"

#include "Tringula.h"
#include "ParaSurf.h"

// Flyer

//______________________________________________________________________________
//
//

ClassImp(Flyer);

//==============================================================================

void Flyer::_init()
{
  mHeight       = 0;    // Height above current surface - there always is one for now.

  mGravHChange  = 0;    // Integrated up/down path between gravity changes.
  bGravFixUpDir = true; // Rotate after change in gravity direction.

  mTerrainSafety      = 0;
  mTerrainProbeRadius = 0;
}

Flyer::Flyer(const Text_t* n, const Text_t* t) :
  Dynamico(n, t)
{
  _init();
}

Flyer::~Flyer()
{}

//==============================================================================

void Flyer::TimeTick(Double_t t, Double_t dt)
{
  // Move flyer in for given dt.
  // 1. Move with current velocity.
  // 2. Perform rotations.
  // 3. Check boundaries
  // 4. Check gravity change
  // 5. Calculate velocities for the next step.

  static const Exc_t _eh("Flyer::TimeTick ");

  Opcode::Point velocity; // Velocity in master frame.
  Float_t       velocity_mag2, velocity_mag, step_length;

calculate_velocity:
  mTrans.RotateVec3(mVVec, velocity);
  velocity_mag2 = velocity.SquareMagnitude();
  velocity_mag  = sqrtf(velocity_mag2);

  step_length   = velocity_mag * dt + mExtraStep;
  mExtraStep    = 0;

  // XXXYY Here I was using gravity direction for calculation of
  // height correction - but this didn't work very well on torus as
  // down (towards closes ring) and gravity are not parallel.
  // With current state of flight mechanics I have to use down direction
  // to properly apply the correction.
  //
  // This doesn't conserve the potential energy ... so revisit this once
  // better control for flight parameters is available (auto-steering, corrections).
  //
  // In particular, the flyers could internally strive towards straight flight. As
  // we have the gravity direction, we can calculate which angular velocities
  // (in local frame) need to be tweaked for stabilization of flight. This should
  // be damped critically ... or even more.
  //
  // There are several spots in this function marked with XXXYY.

  const Float_t dh = - (mGrav.Down() | velocity) * dt;
  // XXXYY const Float_t dh = (mGrav.Dir() | velocity) * dt;
  if (mHeight + dh > mTringula->GetMaxFlyerH())
  {
    // This is another steaming hack - to prevent flyers form exceeding max-h.
    // Subtract the vertical velocity and redo the calculation.

    // We can't do much if it is already beyond max-height.
    if (mHeight < mTringula->GetMaxFlyerH())
    {
      printf("Fixing speed for %s, hp=%f, mh=%f\n", GetName(), mHeight + dh, mTringula->GetMaxFlyerH());

      velocity.TMac(mGrav.Down(), dh / dt);
      mTrans.RotateBackVec3(velocity, mVVec);

      goto calculate_velocity;
    }
  }
  mHeight      += dh;
  mGravHChange += dh;

  // Use velocity - is needed afterwards, too.
  // [But can be changed by CheckBoundaries()!]
  // mTrans.Move3LF(mVVec.x * dt, mVVec.y * dt, mVVec.z * dt);
  mTrans.Move3PF(velocity.x * dt, velocity.y * dt, velocity.z * dt);

  mTrans.RotateLF(1, 2, dt*mWVec.x);
  mTrans.RotateLF(2, 3, dt*mWVec.y);
  mTrans.RotateLF(3, 1, dt*mWVec.z);

  mSafety -= step_length;
  if (mSafety < 0)
  {
    // Check boundaries - this can result in tringula switch.
    Bool_t trans_changed = mTringula->CheckBoundaries(this, mSafety);

    if (trans_changed)
    {
      // Recalculate velocity
      mTrans.RotateVec3(mVVec, velocity);
      velocity_mag2 = velocity.SquareMagnitude();
      velocity_mag  = sqrtf(velocity_mag2);

      // Invalidate position dependant caches.
      // GravData should be fine as it is supposedly smooth. But anyway,
      // it is reset via SetTringula() which leaves safeties at 0.
      // Terrain safety ok, too, we should check neighbouring meshes
      // when calculating it anyway.
    }
  }

  if (mGrav.DecaySafeties(dt, step_length))
  {
    // Cache values from old grav-data needed for position fixes.
    Float_t       assumed_h = mGrav.fH + mGravHChange;
    // XXXYY Opcode::Point old_grav_dir(mGrav.fDir);
    Opcode::Point old_grav_dir(mGrav.fDown);

    mTringula->GetParaSurf()->pos2grav(ref_trans().ArrT(), mGrav);

    Float_t vl = mGrav.Dir() | velocity;  if (vl < 0) vl = -vl;
    Float_t vt = sqrtf(velocity_mag2 - vl*vl);

    update_grav_safeties(vl, vt);

    // Fix height difference due to change in gravity direction.
    // This assures we keep proper potential energy.

    Float_t fdh = mGrav.fH - assumed_h;
    // XXXYY mTrans.Move3PF(mGrav.fDir[0] * fdh, mGrav.fDir[1] * fdh, mGrav.fDir[2] * fdh);
    mTrans.Move3PF(mGrav.fDown[0] * fdh, mGrav.fDown[1] * fdh, mGrav.fDown[2] * fdh);

    mHeight      = assumed_h;
    mGrav.fH     = assumed_h;
    mGravHChange = 0;

    // Optionally rotate for difference in gravity direction.

    if (bGravFixUpDir)
    {
      Opcode::Matrix3x3 m;
      // XXXYY m.FromTo(old_grav_dir, mGrav.Dir());
      m.FromTo(old_grav_dir, mGrav.Down());
      mTrans.MultLeft3x3(m);
    }

    // Testing printout.
    if (mDebugBits & DB_GravData)
    {
      mGrav.Print();
      printf("  v_mag=%f, vl=%f, vt=%f, t_safe=%f, d_safe=%f (d/v)=%f\n",
             velocity_mag, vl, vt, mGrav.fSafeTime, mGrav.fSafeDistance,
             mGrav.fSafeDistance / velocity_mag);
    }
  }

  mTerrainSafety -= step_length;
  if (mTerrainSafety < 0)
  {
    static const Float_t probe_inc_fac = 1.414;
    static const Float_t probe_dec_fac = 0.707;

    Float_t min_r = mMesh->GetTTvor()->GetMaxVertexDistance();

    Opcode::SphereCache    SCache;
    Opcode::SphereCollider SC;
    SC.SetFirstContact(true);

    Opcode::Sphere S(ref_pos(), 0);

    while (mTerrainProbeRadius >= min_r)
    {
      S.SetRadius(mTerrainProbeRadius);

      bool cs = SC.Collide(SCache, S, *mTringula->GetMesh()->GetOPCModel());
      if (cs)
      {
        if (SC.GetContactStatus())
        {
          mTerrainProbeRadius *= probe_dec_fac;
        }
        else
        {
          mTerrainSafety = mTerrainProbeRadius;
          mTerrainProbeRadius *= probe_inc_fac;
          break;
        }
      }
      else
      {
        printf("%s something wrong in sphere-terrain collision test.\n",
               _eh.Data());
      }
    }

    if (mTerrainProbeRadius < min_r)
    {
      CollisionSegments segments;
      Int_t ns = collide_with_tringula(segments);
      if (ns > 0)
      {
        // Do this trivially ... if it is coming closer to the collision
        // point, turn it around, otherwise do nothing.

        Opcode::Point dr(segments.RefCenter());
        dr.Sub(ref_pos());
        if ((dr | velocity) > 0)
        {
          mTrans.RotateLF(1, 2, TMath::Pi());
        }

        // If extra move of flyer is done, also add it to mExtraStep.
      }
      mTerrainSafety      = 0;
      mTerrainProbeRadius = min_r;
    }
  }
}
 Flyer.cxx:1
 Flyer.cxx:2
 Flyer.cxx:3
 Flyer.cxx:4
 Flyer.cxx:5
 Flyer.cxx:6
 Flyer.cxx:7
 Flyer.cxx:8
 Flyer.cxx:9
 Flyer.cxx:10
 Flyer.cxx:11
 Flyer.cxx:12
 Flyer.cxx:13
 Flyer.cxx:14
 Flyer.cxx:15
 Flyer.cxx:16
 Flyer.cxx:17
 Flyer.cxx:18
 Flyer.cxx:19
 Flyer.cxx:20
 Flyer.cxx:21
 Flyer.cxx:22
 Flyer.cxx:23
 Flyer.cxx:24
 Flyer.cxx:25
 Flyer.cxx:26
 Flyer.cxx:27
 Flyer.cxx:28
 Flyer.cxx:29
 Flyer.cxx:30
 Flyer.cxx:31
 Flyer.cxx:32
 Flyer.cxx:33
 Flyer.cxx:34
 Flyer.cxx:35
 Flyer.cxx:36
 Flyer.cxx:37
 Flyer.cxx:38
 Flyer.cxx:39
 Flyer.cxx:40
 Flyer.cxx:41
 Flyer.cxx:42
 Flyer.cxx:43
 Flyer.cxx:44
 Flyer.cxx:45
 Flyer.cxx:46
 Flyer.cxx:47
 Flyer.cxx:48
 Flyer.cxx:49
 Flyer.cxx:50
 Flyer.cxx:51
 Flyer.cxx:52
 Flyer.cxx:53
 Flyer.cxx:54
 Flyer.cxx:55
 Flyer.cxx:56
 Flyer.cxx:57
 Flyer.cxx:58
 Flyer.cxx:59
 Flyer.cxx:60
 Flyer.cxx:61
 Flyer.cxx:62
 Flyer.cxx:63
 Flyer.cxx:64
 Flyer.cxx:65
 Flyer.cxx:66
 Flyer.cxx:67
 Flyer.cxx:68
 Flyer.cxx:69
 Flyer.cxx:70
 Flyer.cxx:71
 Flyer.cxx:72
 Flyer.cxx:73
 Flyer.cxx:74
 Flyer.cxx:75
 Flyer.cxx:76
 Flyer.cxx:77
 Flyer.cxx:78
 Flyer.cxx:79
 Flyer.cxx:80
 Flyer.cxx:81
 Flyer.cxx:82
 Flyer.cxx:83
 Flyer.cxx:84
 Flyer.cxx:85
 Flyer.cxx:86
 Flyer.cxx:87
 Flyer.cxx:88
 Flyer.cxx:89
 Flyer.cxx:90
 Flyer.cxx:91
 Flyer.cxx:92
 Flyer.cxx:93
 Flyer.cxx:94
 Flyer.cxx:95
 Flyer.cxx:96
 Flyer.cxx:97
 Flyer.cxx:98
 Flyer.cxx:99
 Flyer.cxx:100
 Flyer.cxx:101
 Flyer.cxx:102
 Flyer.cxx:103
 Flyer.cxx:104
 Flyer.cxx:105
 Flyer.cxx:106
 Flyer.cxx:107
 Flyer.cxx:108
 Flyer.cxx:109
 Flyer.cxx:110
 Flyer.cxx:111
 Flyer.cxx:112
 Flyer.cxx:113
 Flyer.cxx:114
 Flyer.cxx:115
 Flyer.cxx:116
 Flyer.cxx:117
 Flyer.cxx:118
 Flyer.cxx:119
 Flyer.cxx:120
 Flyer.cxx:121
 Flyer.cxx:122
 Flyer.cxx:123
 Flyer.cxx:124
 Flyer.cxx:125
 Flyer.cxx:126
 Flyer.cxx:127
 Flyer.cxx:128
 Flyer.cxx:129
 Flyer.cxx:130
 Flyer.cxx:131
 Flyer.cxx:132
 Flyer.cxx:133
 Flyer.cxx:134
 Flyer.cxx:135
 Flyer.cxx:136
 Flyer.cxx:137
 Flyer.cxx:138
 Flyer.cxx:139
 Flyer.cxx:140
 Flyer.cxx:141
 Flyer.cxx:142
 Flyer.cxx:143
 Flyer.cxx:144
 Flyer.cxx:145
 Flyer.cxx:146
 Flyer.cxx:147
 Flyer.cxx:148
 Flyer.cxx:149
 Flyer.cxx:150
 Flyer.cxx:151
 Flyer.cxx:152
 Flyer.cxx:153
 Flyer.cxx:154
 Flyer.cxx:155
 Flyer.cxx:156
 Flyer.cxx:157
 Flyer.cxx:158
 Flyer.cxx:159
 Flyer.cxx:160
 Flyer.cxx:161
 Flyer.cxx:162
 Flyer.cxx:163
 Flyer.cxx:164
 Flyer.cxx:165
 Flyer.cxx:166
 Flyer.cxx:167
 Flyer.cxx:168
 Flyer.cxx:169
 Flyer.cxx:170
 Flyer.cxx:171
 Flyer.cxx:172
 Flyer.cxx:173
 Flyer.cxx:174
 Flyer.cxx:175
 Flyer.cxx:176
 Flyer.cxx:177
 Flyer.cxx:178
 Flyer.cxx:179
 Flyer.cxx:180
 Flyer.cxx:181
 Flyer.cxx:182
 Flyer.cxx:183
 Flyer.cxx:184
 Flyer.cxx:185
 Flyer.cxx:186
 Flyer.cxx:187
 Flyer.cxx:188
 Flyer.cxx:189
 Flyer.cxx:190
 Flyer.cxx:191
 Flyer.cxx:192
 Flyer.cxx:193
 Flyer.cxx:194
 Flyer.cxx:195
 Flyer.cxx:196
 Flyer.cxx:197
 Flyer.cxx:198
 Flyer.cxx:199
 Flyer.cxx:200
 Flyer.cxx:201
 Flyer.cxx:202
 Flyer.cxx:203
 Flyer.cxx:204
 Flyer.cxx:205
 Flyer.cxx:206
 Flyer.cxx:207
 Flyer.cxx:208
 Flyer.cxx:209
 Flyer.cxx:210
 Flyer.cxx:211
 Flyer.cxx:212
 Flyer.cxx:213
 Flyer.cxx:214
 Flyer.cxx:215
 Flyer.cxx:216
 Flyer.cxx:217
 Flyer.cxx:218
 Flyer.cxx:219
 Flyer.cxx:220
 Flyer.cxx:221
 Flyer.cxx:222
 Flyer.cxx:223
 Flyer.cxx:224
 Flyer.cxx:225
 Flyer.cxx:226
 Flyer.cxx:227
 Flyer.cxx:228
 Flyer.cxx:229
 Flyer.cxx:230
 Flyer.cxx:231
 Flyer.cxx:232
 Flyer.cxx:233
 Flyer.cxx:234
 Flyer.cxx:235
 Flyer.cxx:236
 Flyer.cxx:237
 Flyer.cxx:238
 Flyer.cxx:239
 Flyer.cxx:240