ROOT logo
// $Id: Dynamico.cxx 2340 2010-01-20 21:53:31Z 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/.

//__________________________________________________________________________
// Dynamico
//
// We have those reference data-members mV and mW here ... they are needed so
// that we can have WGlValuator widgets that pick up all the stuff from the
// dictionaries. 

#include "Dynamico.h"
#include "Dynamico.c7"

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

#include <Stones/TringTvor.h>

#include <TMath.h>

ClassImp(Dynamico);

/**************************************************************************/

void Dynamico::_init()
{
  mLastTransPtr = &mLastTrans;
  mLastAABBPtr  = &mLastAABB;

  mSafety = mExtraStep = 0;

  mOPCRCCache = Opcode::OPC_INVALID_ID;
}

Dynamico:: Dynamico(const Text_t* n, const Text_t* t) :
  Extendio(n,t),
  mV(mVVec.x),
  mW(mWVec.x)
{
  _init();
}

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

void Dynamico::SetTringula(Tringula* tring)
{
  // Set tringula to which the extendio is attached.
  // Sub-classes override this to reinitialize cached data.

  PARENT_GLASS::SetTringula(tring);

  mTringula->GetParaSurf()->pos2grav(mTrans.ArrT(), mGrav);
  mOPCRCCache = Opcode::OPC_INVALID_ID;
}

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

void Dynamico::update_grav_safeties(Float_t vl, Float_t vt)
{
  // Calculate time and distance over which we can keep this gravity data.
  // There hard-coded limits here!
  //
  // Safe time:
  // ----------
  // For non-accelerated motion this is:
  //   t = (6 epsilon / g' v)^1/3
  // Where epsilon is precision in position and "g' v" is the product of
  // gravitational acceleration derivative and corresponding velocity.
  // Thus we search for maximal one.
  // Epsilon is set to 0.1m - this could be more, probably.
  //
  // Problem is, if the unit accelerates during the period. This
  // is not handled at all. Maybe could take current / max accel
  // into account - or use distance instead of time!
  //
  // Also - some limits need to be imposed.
  // 1. Maximal time is set to max_time. This is somewhat arbitrary.
  //    This way we enforce re-checking of the field periodically.
  // 2. Minimal time we bother to calculate is min_time which should be
  //    about the order of dt.
  //
  // Safe distance:
  // --------------
  // Maximum distance - where gravity changes for more then certain
  // value eta:
  //   L = eta / g'

  static const Float_t epsilon    = 6 * 0.1;  // Precision of position.
  static const Float_t max_time   = 10;
  static const Float_t min_time   = 0.01;
  static const Float_t lim_gv_low = epsilon / (max_time*max_time*max_time);
  static const Float_t lim_gv_hi  = epsilon / (min_time*min_time*min_time);

  static const Float_t eta        = 0.1;
  static const Float_t max_dist   = 1000;
  static const Float_t lim_g_low  = eta / max_dist;

  Float_t max_gv = TMath::Max(mGrav.fLDer * vl, mGrav.fTDer * vt);

  if (max_gv < lim_gv_low)
    mGrav.fSafeTime = max_time;
  else if (max_gv > lim_gv_hi)
    mGrav.fSafeTime = 0;
  else
    mGrav.fSafeTime = powf(epsilon / max_gv, 0.3333333333f);

  Float_t max_g = TMath::Max(mGrav.fLDer, mGrav.fTDer);

  if (max_g < lim_g_low)
    mGrav.fSafeDistance = max_dist;
  else
    mGrav.fSafeDistance = eta / max_g;
}


/**************************************************************************/

bool Dynamico::handle_collision(Dynamico            * dyno,
                                Statico             * stato,
                                Opcode::RayCollider & ray_collider,
                                Opcode::Ray         & ray,
                                Opcode::Point       & com_dyno,
                                CollisionSegments   & segments)
{
  // Handle collision between dynamico and statico.
  //
  // If com_dyno is inside statico, let it go, we're too late (or it
  // was inside to start with).
  // If collision-vertex is in front of com_dyno bounce off with change of
  // direction, otherwise just move away from collision-vertex.
  //
  // Input:
  //   com_dyno center-of-mass of dynamico
  // Return:    false if ray collision fails.

  static const Exc_t _eh("Dynamico::handle_collision ");

  if (ray_collider.Collide(ray, *stato->get_opc_model(), stato->RefTrans()))
  {
    using namespace Opcode;

    Opcode::CollisionFaces& CF = * ray_collider.GetDestination();

    // Do fixing only when nfaces is even, i.e., dyno's com_dyno is outside.
    if (CF.GetNbFaces() % 2 == 0)
    {
      // center-vertex of collision segments.
      const Point& cv = segments.RefCenter();

      Point com2cv(cv); com2cv -= com_dyno;

      HTransF& t_dyno = dyno->mTrans;

      Point vel;      t_dyno.RotateVec3(dyno->mVVec, vel);
      Point fwd(vel); fwd.Normalize();

      if ((vel | com2cv) > 0 && segments.size() > 1)
      {
        // CV is in front - turn to be parallel with collision plane
        // or a bit further as plane normal is not projected into xy
        // plane of dyno.
        // If segments.size() == 1 => plane is not defined (happens rarely).

        Plane P(segments[0].mP0, segments[0].mP1, cv);
        // turn to be parallel with collision plane or a bit further
        // as plane normal is not projected into xy plane of dyno.
        Float_t dp = fwd | P.n;
        if (dp < 0) P.n.Neg();
        Point cross = P.n ^ fwd;
        Float_t  cp = 0.5f * cross.Magnitude();
        if ((cross | *(Point*) t_dyno.PtrBaseVec(3)) < 0)
          t_dyno.RotateLF(2, 1, TMath::PiOver2() - TMath::ASin(cp));
        else
          t_dyno.RotateLF(1, 2, TMath::PiOver2() - TMath::ASin(cp));
      }
      else
      {
        // CV is behind - move away from it.
        // !!! 0.1 should be replaced with a ray from cv back towards com_dyno.
        com2cv *= -0.1f;
        t_dyno.Move3PF(com2cv.x, com2cv.y, com2cv.z);

        // When a dyno is moved in collision, safeties need to be updated, too.
        dyno->mExtraStep += com2cv.Magnitude();
      }

      // Check for nan's.
      // assert(!isnan(t_dyno[12]) && !isnan(t_dyno[0]) && !isnan(t_dyno[4]) && !isnan(t_dyno[8]));
    }
    return true;
  }
  else
  {
    return false;
  }
}

bool Dynamico::handle_collision(Dynamico          * dyno0,
                                Dynamico          * dyno1,
                                Opcode::Point     & up_dir,
                                CollisionSegments & segments)
{
  // Handle collision of two dynamicos.
  //
  // If they are coming together, they are bounced off (momentum
  // conservation in tangential plane), otherwise they are just
  // separated for a fixed amount.
  //
  // Returns:   true, for the time being.

  using namespace Opcode;

  HTransF& t0 = dyno0->ref_trans();
  HTransF& t1 = dyno1->ref_trans();

  // Centers of mass
  Point com0; t0.MultiplyVec3(dyno0->GetMesh()->RefCOM(), 1.0f, com0);
  Point com1; t1.MultiplyVec3(dyno1->GetMesh()->RefCOM(), 1.0f, com1);
  Point dcom; dcom.Sub(com1, com0);
  // Diff of centers of mass in tangetial plane
  Point dcomp(dcom); dcomp.TMsc(up_dir, up_dir | dcom);

  // Velocities
  // Point v0(t0.PtrBaseVec(1)); v0 *= dyno0->mV;
  // Point v1(t1.PtrBaseVec(1)); v1 *= dyno1->mV;
  Point v0; t0.RotateVec3(dyno0->mVVec, v0);
  Point v1; t0.RotateVec3(dyno1->mVVec, v1);
  // Velocities in tangential plane
  Point v0p(v0); v0p.TMsc(up_dir, up_dir | v0);
  Point v1p(v1); v1p.TMsc(up_dir, up_dir | v1);

  Point dv; dv.Sub(v1p, v0p);

  if ((dcomp | dv) < 0)
  {
    // they are moving closer, bounce them off

    Point dv_dir = dv; dv_dir.Normalize();

    // Do the calculation in coord system where dyno-0 is at rest,
    // dyno-1 is coming in with v1-v0.
    Float_t w1 = dv.Magnitude();
    Float_t m0 = dyno0->GetMesh()->GetM();
    Float_t m1 = dyno1->GetMesh()->GetM();
    Float_t P    = w1 * m1; // momentum
    Float_t TwoT = w1 * P;  // two-times kinetic energy
    Float_t a = m1 * m1 + m0 * m1;
    Float_t b = -2.0f * P * m1;
    Float_t c = P * P - TwoT * m0;

    Float_t w1p = -0.5f * (b + sqrtf(b*b - 4.0f*a*c)) / a;
    Float_t w0p = (P - m1*w1p) / m0;

    // XXXX New velocities and transformations, calculated and assigned below,
    // put all velocity in the x/forward direction. In principle could also assign
    // slide-velocities, but these are not decayed in TimeTick() so the thing
    // would go sour soon.
    // Need an epsilon for min. new velocity magnitude ... see hardcoded 1e-5 below.

    v0.TMac(dv_dir, w0p);
    Float_t vm0 = v0.Magnitude();
    if (vm0 > 1e-5)
    {
      v0 *= 1.0f / vm0;
      t0.SetBaseVec(1, v0);
      t0.OrtoNorm3Column(1, 3);
      t0.SetBaseVecViaCross(2);
      dyno0->mVVec.Set(vm0, 0, 0);
    }

    v1.TMac(dv_dir, w1p - w1);
    Float_t vm1 = v1.Magnitude();
    if (vm1 > 1e-5)
    {
      v1 *= 1.0f / vm1;
      t1.SetBaseVec(1, v1);
      t1.OrtoNorm3Column(1, 3);
      t1.SetBaseVecViaCross(2);
      dyno1->mVVec.Set(vm1, 0, 0);
    }
  } else {
    // they are moving apart, just separate them some more
    dcomp *= 0.1f;
    t0.Move3PF(-dcomp.x, -dcomp.y, -dcomp.z);
    t1.Move3PF( dcomp.x,  dcomp.y,  dcomp.z);

    // When a dyno is moved in collision, safeties need to be updated, too.
    const Float_t extra_step = dcomp.Magnitude();
    dyno0->mExtraStep += extra_step;
    dyno1->mExtraStep += extra_step;
  }

  // Check for nan's.
  // assert(!isnan(t0[12]) && !isnan(t0[0]) && !isnan(t0[4]) && !isnan(t0[8]));
  // assert(!isnan(t1[12]) && !isnan(t1[0]) && !isnan(t1[4]) && !isnan(t1[8]));

  return true;
}
 Dynamico.cxx:1
 Dynamico.cxx:2
 Dynamico.cxx:3
 Dynamico.cxx:4
 Dynamico.cxx:5
 Dynamico.cxx:6
 Dynamico.cxx:7
 Dynamico.cxx:8
 Dynamico.cxx:9
 Dynamico.cxx:10
 Dynamico.cxx:11
 Dynamico.cxx:12
 Dynamico.cxx:13
 Dynamico.cxx:14
 Dynamico.cxx:15
 Dynamico.cxx:16
 Dynamico.cxx:17
 Dynamico.cxx:18
 Dynamico.cxx:19
 Dynamico.cxx:20
 Dynamico.cxx:21
 Dynamico.cxx:22
 Dynamico.cxx:23
 Dynamico.cxx:24
 Dynamico.cxx:25
 Dynamico.cxx:26
 Dynamico.cxx:27
 Dynamico.cxx:28
 Dynamico.cxx:29
 Dynamico.cxx:30
 Dynamico.cxx:31
 Dynamico.cxx:32
 Dynamico.cxx:33
 Dynamico.cxx:34
 Dynamico.cxx:35
 Dynamico.cxx:36
 Dynamico.cxx:37
 Dynamico.cxx:38
 Dynamico.cxx:39
 Dynamico.cxx:40
 Dynamico.cxx:41
 Dynamico.cxx:42
 Dynamico.cxx:43
 Dynamico.cxx:44
 Dynamico.cxx:45
 Dynamico.cxx:46
 Dynamico.cxx:47
 Dynamico.cxx:48
 Dynamico.cxx:49
 Dynamico.cxx:50
 Dynamico.cxx:51
 Dynamico.cxx:52
 Dynamico.cxx:53
 Dynamico.cxx:54
 Dynamico.cxx:55
 Dynamico.cxx:56
 Dynamico.cxx:57
 Dynamico.cxx:58
 Dynamico.cxx:59
 Dynamico.cxx:60
 Dynamico.cxx:61
 Dynamico.cxx:62
 Dynamico.cxx:63
 Dynamico.cxx:64
 Dynamico.cxx:65
 Dynamico.cxx:66
 Dynamico.cxx:67
 Dynamico.cxx:68
 Dynamico.cxx:69
 Dynamico.cxx:70
 Dynamico.cxx:71
 Dynamico.cxx:72
 Dynamico.cxx:73
 Dynamico.cxx:74
 Dynamico.cxx:75
 Dynamico.cxx:76
 Dynamico.cxx:77
 Dynamico.cxx:78
 Dynamico.cxx:79
 Dynamico.cxx:80
 Dynamico.cxx:81
 Dynamico.cxx:82
 Dynamico.cxx:83
 Dynamico.cxx:84
 Dynamico.cxx:85
 Dynamico.cxx:86
 Dynamico.cxx:87
 Dynamico.cxx:88
 Dynamico.cxx:89
 Dynamico.cxx:90
 Dynamico.cxx:91
 Dynamico.cxx:92
 Dynamico.cxx:93
 Dynamico.cxx:94
 Dynamico.cxx:95
 Dynamico.cxx:96
 Dynamico.cxx:97
 Dynamico.cxx:98
 Dynamico.cxx:99
 Dynamico.cxx:100
 Dynamico.cxx:101
 Dynamico.cxx:102
 Dynamico.cxx:103
 Dynamico.cxx:104
 Dynamico.cxx:105
 Dynamico.cxx:106
 Dynamico.cxx:107
 Dynamico.cxx:108
 Dynamico.cxx:109
 Dynamico.cxx:110
 Dynamico.cxx:111
 Dynamico.cxx:112
 Dynamico.cxx:113
 Dynamico.cxx:114
 Dynamico.cxx:115
 Dynamico.cxx:116
 Dynamico.cxx:117
 Dynamico.cxx:118
 Dynamico.cxx:119
 Dynamico.cxx:120
 Dynamico.cxx:121
 Dynamico.cxx:122
 Dynamico.cxx:123
 Dynamico.cxx:124
 Dynamico.cxx:125
 Dynamico.cxx:126
 Dynamico.cxx:127
 Dynamico.cxx:128
 Dynamico.cxx:129
 Dynamico.cxx:130
 Dynamico.cxx:131
 Dynamico.cxx:132
 Dynamico.cxx:133
 Dynamico.cxx:134
 Dynamico.cxx:135
 Dynamico.cxx:136
 Dynamico.cxx:137
 Dynamico.cxx:138
 Dynamico.cxx:139
 Dynamico.cxx:140
 Dynamico.cxx:141
 Dynamico.cxx:142
 Dynamico.cxx:143
 Dynamico.cxx:144
 Dynamico.cxx:145
 Dynamico.cxx:146
 Dynamico.cxx:147
 Dynamico.cxx:148
 Dynamico.cxx:149
 Dynamico.cxx:150
 Dynamico.cxx:151
 Dynamico.cxx:152
 Dynamico.cxx:153
 Dynamico.cxx:154
 Dynamico.cxx:155
 Dynamico.cxx:156
 Dynamico.cxx:157
 Dynamico.cxx:158
 Dynamico.cxx:159
 Dynamico.cxx:160
 Dynamico.cxx:161
 Dynamico.cxx:162
 Dynamico.cxx:163
 Dynamico.cxx:164
 Dynamico.cxx:165
 Dynamico.cxx:166
 Dynamico.cxx:167
 Dynamico.cxx:168
 Dynamico.cxx:169
 Dynamico.cxx:170
 Dynamico.cxx:171
 Dynamico.cxx:172
 Dynamico.cxx:173
 Dynamico.cxx:174
 Dynamico.cxx:175
 Dynamico.cxx:176
 Dynamico.cxx:177
 Dynamico.cxx:178
 Dynamico.cxx:179
 Dynamico.cxx:180
 Dynamico.cxx:181
 Dynamico.cxx:182
 Dynamico.cxx:183
 Dynamico.cxx:184
 Dynamico.cxx:185
 Dynamico.cxx:186
 Dynamico.cxx:187
 Dynamico.cxx:188
 Dynamico.cxx:189
 Dynamico.cxx:190
 Dynamico.cxx:191
 Dynamico.cxx:192
 Dynamico.cxx:193
 Dynamico.cxx:194
 Dynamico.cxx:195
 Dynamico.cxx:196
 Dynamico.cxx:197
 Dynamico.cxx:198
 Dynamico.cxx:199
 Dynamico.cxx:200
 Dynamico.cxx:201
 Dynamico.cxx:202
 Dynamico.cxx:203
 Dynamico.cxx:204
 Dynamico.cxx:205
 Dynamico.cxx:206
 Dynamico.cxx:207
 Dynamico.cxx:208
 Dynamico.cxx:209
 Dynamico.cxx:210
 Dynamico.cxx:211
 Dynamico.cxx:212
 Dynamico.cxx:213
 Dynamico.cxx:214
 Dynamico.cxx:215
 Dynamico.cxx:216
 Dynamico.cxx:217
 Dynamico.cxx:218
 Dynamico.cxx:219
 Dynamico.cxx:220
 Dynamico.cxx:221
 Dynamico.cxx:222
 Dynamico.cxx:223
 Dynamico.cxx:224
 Dynamico.cxx:225
 Dynamico.cxx:226
 Dynamico.cxx:227
 Dynamico.cxx:228
 Dynamico.cxx:229
 Dynamico.cxx:230
 Dynamico.cxx:231
 Dynamico.cxx:232
 Dynamico.cxx:233
 Dynamico.cxx:234
 Dynamico.cxx:235
 Dynamico.cxx:236
 Dynamico.cxx:237
 Dynamico.cxx:238
 Dynamico.cxx:239
 Dynamico.cxx:240
 Dynamico.cxx:241
 Dynamico.cxx:242
 Dynamico.cxx:243
 Dynamico.cxx:244
 Dynamico.cxx:245
 Dynamico.cxx:246
 Dynamico.cxx:247
 Dynamico.cxx:248
 Dynamico.cxx:249
 Dynamico.cxx:250
 Dynamico.cxx:251
 Dynamico.cxx:252
 Dynamico.cxx:253
 Dynamico.cxx:254
 Dynamico.cxx:255
 Dynamico.cxx:256
 Dynamico.cxx:257
 Dynamico.cxx:258
 Dynamico.cxx:259
 Dynamico.cxx:260
 Dynamico.cxx:261
 Dynamico.cxx:262
 Dynamico.cxx:263
 Dynamico.cxx:264
 Dynamico.cxx:265
 Dynamico.cxx:266
 Dynamico.cxx:267
 Dynamico.cxx:268
 Dynamico.cxx:269
 Dynamico.cxx:270
 Dynamico.cxx:271
 Dynamico.cxx:272
 Dynamico.cxx:273
 Dynamico.cxx:274
 Dynamico.cxx:275
 Dynamico.cxx:276
 Dynamico.cxx:277
 Dynamico.cxx:278
 Dynamico.cxx:279
 Dynamico.cxx:280
 Dynamico.cxx:281
 Dynamico.cxx:282
 Dynamico.cxx:283
 Dynamico.cxx:284
 Dynamico.cxx:285
 Dynamico.cxx:286
 Dynamico.cxx:287
 Dynamico.cxx:288
 Dynamico.cxx:289
 Dynamico.cxx:290
 Dynamico.cxx:291
 Dynamico.cxx:292
 Dynamico.cxx:293
 Dynamico.cxx:294
 Dynamico.cxx:295
 Dynamico.cxx:296
 Dynamico.cxx:297
 Dynamico.cxx:298
 Dynamico.cxx:299
 Dynamico.cxx:300
 Dynamico.cxx:301
 Dynamico.cxx:302