ROOT logo
// $Id: TringuCam.cxx 2456 2010-10-17 18:31:40Z 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/.

//__________________________________________________________________________
// TringuCam
//
//

#include "TringuCam.h"
#include "Glasses/TSPupilInfo.h"
#include "TringuRep.h"
#include "Extendio.h"
#include "Statico.h"
#include "Dynamico.h"

#include <Glasses/ZQueen.h>
#include <Glasses/ZHashList.h>
#include <Glasses/ScreenText.h>
#include <Glasses/WGlWidget.h>
#include <Glasses/Eventor.h>
#include <Glasses/TimeMaker.h>
#include <Glasses/WSTube.h>

#include "TringuCam.c7"

#include "TringulaTester.h"

#include "TriMesh.h"
#include "ParaSurf.h"

#include <RnrBase/Fl_Event_Enums.h>

#include <TMath.h>

ClassImp(TringuCam);

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

void TringuCam::_init()
{
  bKeysVerbose = bMouseVerbose = false;

  //                                acc/inc | decay,    | timeout
  mChgParCameraMove.SetValueParams (1, 0.5,   1.2, 0.4,   0.05);
  mChgParCameraMove.SetDesireParams(1, 0.3,   1,   0.1,   0.2);

  mFwdBck.fChangeParams = &mChgParCameraMove;
  mFwdBck.SetMinMax(-20, 100);
  mKeyStateMap['w'] = &mFwdBck.fIncKey;
  mKeyStateMap['s'] = &mFwdBck.fDecKey;

  // Sustain mode ... in this case happens too fast.
  // Should really be attached to:
  // a) throttle controls;
  // b) use different change params - no exponential approach.
  // mFwdBck.fSustain = true;

  mLftRgt.fChangeParams = &mChgParCameraMove;
  mLftRgt.SetMinMax(-10, 10);
  mKeyStateMap['a'] = &mLftRgt.fIncKey;
  mKeyStateMap['d'] = &mLftRgt.fDecKey;

  mUpDown.fChangeParams = &mChgParCameraMove;

  mUpDown.SetMinMax(-30, 30);
  mKeyStateMap['r'] = &mUpDown.fIncKey;
  mKeyStateMap['f'] = &mUpDown.fDecKey;

  //                                  acc/inc   | decay     | timeout
  mChgParCameraRotate.SetValueParams (0.1, 0.5,   1.2, 0.4,   0.05);
  mChgParCameraRotate.SetDesireParams(0.1, 0.3,   0.1, 0.1,   0.2);

  mSpinUp.fChangeParams = &mChgParCameraRotate;
  mSpinUp.SetMinMax(-TMath::Pi(), TMath::Pi());
  mKeyStateMap['q'] = &mSpinUp.fIncKey;
  mKeyStateMap['e'] = &mSpinUp.fDecKey;


  // MouseAction
  mMouseAction  = MA_PickExtendios;
  mExpectBeta   = EB_Nothing;
  mRayLength    = 0;

  bMouseDown    = false;

  mStampInterval = 25;
  mStampCount    = 0;
  mHeight = 0;

  mRayColl.SetCulling   (true);
  mRayColl.SetClosestHit(true);
  mRayColl.SetDestination(&mCollFaces);
  mCollVertex = -1;
}

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

WSTube* TringuCam::make_tube(Statico* stato0, Statico* stato1, const TString& grad_name)
{
  WSTube* tube = new WSTube(GForm("Tube %s - %s; %s", stato0->GetName(), stato1->GetName(), grad_name.Data()));

  tube->SetTransSource(WSTube::TS_Transes);

  const HTransF& tA = stato0->ref_last_trans();
  const HTransF& tB = stato1->ref_last_trans();

  tube->RefTransA().SetFromArray(tA);
  tube->RefTransA().MoveLF(3, 2.0*stato0->get_tring_tvor()->mCtrExtBox[5]);
  tube->RefTransB().SetFromArray(tB);
  tube->RefTransB().MoveLF(3, 2.0*stato1->get_tring_tvor()->mCtrExtBox[5]);

  tube->RefVecA().SetXYZT(0, 0,  2, 1);
  tube->RefVecB().SetXYZT(0, 0, -2, 1);

  tube->SetTexture((ZImage*) mQueen->FindLensByPath(GForm("var/gradients/%s",
                                                          grad_name.Data())));

  tube->SetFat(false);
  tube->SetLineW(1.6);
  tube->SetTLevel(30);
  tube->SetPLevel(3);
  tube->SetDefWidth(0.04);
  tube->SetDefTension(1.5);
  tube->SetTexUScale(2);
  tube->SetDtexU(-0.3);

  return tube;
}

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

inline TringuCam::KeyInfo* TringuCam::FindKeyInfo(Int_t key)
{
  map<Int_t, KeyInfo*>::iterator i = mKeyStateMap.find(key);
  return (i != mKeyStateMap.end()) ? i->second : 0;
}

//------------------------------------------------------------------------------

Int_t TringuCam::KeyDown(Int_t key)
{
  KeyInfo* ki = FindKeyInfo(key);
  if (ki == 0) return 0;

  if (ki->fIsDown == false)
  {
    ki->fIsDown = true;

    ValueInfo            *vi =   ki->fValueInfo;
    KeyValueChangeParams &C  = * vi->fChangeParams;
    // KeyInfo*  oki = ki->fIsInc ? &vi->fDecKey : &vi->fIncKey;

    if (vi->fSustain)
    {
      if (ki->fDecayTimeout > 0)
      {
	// if pressed during timeout, set sustain-desire
	vi->fSustainSet = true;
	if (ki->fIsInc)
	{
	  if (vi->fSustainDesire < 0) vi->fSustainDesire = 0;
	  else                        vi->fSustainDesire = vi->fMaxValue;
	}
	else
	{
	  if (vi->fSustainDesire > 0) vi->fSustainDesire = 0;
	  else                        vi->fSustainDesire = vi->fMinValue;
	}
      }
      else
      {
	// else ... hmmh, set key desire, for no apparent reason.
	ki->fDesiredValue = ki->fIsInc ? vi->fMaxValue : - vi->fMinValue;
      }      
    }
    else
    {
      if (ki->fDecayTimeout > 0)
      {
	// if pressed during timeout: inc + delta_factor
	ki->fDesiredValue += C.fDesireIncDeltaFactor * ki->fDesiredValue;
	ki->fDesiredValue += C.fDesireIncStep;
      }
      else
      {
	// else round-up.
	ki->fDesiredValue = TMath::Ceil(ki->fDesiredValue + 0.001);
      }
    }

    // Make sure we do not exceed limits.
    if (ki->fIsInc)
    {
      if (ki->fDesiredValue > vi->fMaxValue)
        ki->fDesiredValue = vi->fMaxValue;
    }
    else
    {
      if (ki->fDesiredValue > -vi->fMinValue)
        ki->fDesiredValue = - vi->fMinValue;
    }
  }

  return 1;
}

Int_t TringuCam::KeyUp(Int_t key)
{
  KeyInfo* ki = FindKeyInfo(key);
  if (ki == 0) return 0;

  if (ki->fIsDown == true)
  {
    ki->fIsDown = false;

    ValueInfo* vi = ki->fValueInfo;
    KeyInfo*  oki = ki->fIsInc ? &vi->fDecKey : &vi->fIncKey;
    KeyValueChangeParams& C = * vi->fChangeParams;

    ki->fDecayTimeout = C.fDesireDecayTimeout;
    if (oki->fIsDown == false)
    {
      if (vi->fSustain)
      {
	if (!vi->fSustainSet)
	  vi->fSustainDesire = vi->fValue;
	vi->fSustainSet = false;
      }
      else
      {
	vi->fDecayTimeout = C.fValueDecayTimeout;
      }
    }
  }

  return 1;
}

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

void TringuCam::MouseDown(A_Rnr::Fl_Event& ev)
{
  static const Exc_t _eh("TringuCam::MouseDown ");

  bMouseDown = true;

  switch (mMouseAction)
  {
    case MA_Nothing:
    {
      break;
    }
    case MA_RayCollide:
    {
      TringulaTester *tt = dynamic_cast<TringulaTester*>(mTringuRep->GetElementByName("TringulaTester"));
      if (tt)
      {
	CalculateMouseRayVectors();
	tt->SetRayVectors(mMouseRayPos, mMouseRayDir);
	tt->RayCollideTerrain();
      }
      else
      {
	ISwarn(_eh + "can not get TringulaTester as child of TringuRep.");
      }
      break;
    }
    case MA_AddField:
    {
      CalculateMouseRayVectors();
      MouseRayCollide();
      mTringuRep->AddField(mCollPoint, mCollVertex, 1.0f);
      break;
    }
    case MA_SprayField:
    {
      mTringuRep->BeginSprayField();
      // Field is added in time-tick.
      break;
    }
    case MA_PickExtendios:
    {
      CalculateMouseRayVectors();
      Opcode::Ray ray(&mMouseRayPos[0], &mMouseRayDir[0]);
      Float_t     rng = mTringula->RayCollideClosestHit(ray, true);
      Extendio	 *ext = mTringula->PickExtendios(ray, rng);

      if (bMouseVerbose)
        printf("TringuCam::MouseDown picked %s, state=0x%x\n",
               ext ? ext->GetName() : "<none>", ev.fState);

      if (mExpectBeta == EB_ConnectStaticos)
      {
	Statico* stato = dynamic_cast<Statico*>(ext);
	if (stato)
	{
	  Statico* beta = dynamic_cast<Statico*>(*mPrepBeta);
	  if (beta) {
	    WSTube* tube = make_tube(beta, stato, mGradName);
            mQueen->CheckIn(tube);
            {
              GLensWriteHolder _wlck(*mTringula);
              mTringula->GetTubes()->Add(tube);
            }
            tube->AnimateConnect();
	  }
	}
        mExpectBeta = EB_Nothing;
        SetPrepBeta(0);
      }
      else
      {
	mPupilInfo->SelectExtendio(ext, ev.fState & FL_CTRL);
      }

      break;
    }
    case MA_NewLandMark:
    {
      printf ("Sucking new landmark\n");

      CalculateMouseRayVectors();
      MouseRayCollide();

      if (mCollVertex != -1)
      {
	TriMesh *mesh = dynamic_cast<TriMesh*>(mQueen->FindLensByPath("var/meshes/LandMark"));
	GLensReadHolder _tlck(*mTringula);
	mTringula->AddLandMark(mesh, mCollPoint);
      }

      mMouseAction = mPrevAction;
      Stamp(FID());
      break;
    }
    default:
    {
      printf("Unhandled case!!!!\n");
      break;
    }
  }
}

void TringuCam::MouseUp()
{
  bMouseDown = false;
 
  if (mMouseAction == MA_SprayField)
  {
    mTringuRep->EndSprayField();
  }
}

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

void TringuCam::CalculateMouseRayVectors()
{
  mPupilInfo->TransformMouseRayVectors(*mTringula, mMouseRayPos, mMouseRayDir);
}

void TringuCam::MouseRayCollide()
{
  // Collide current mouse-ray with tringula terrain.

  Opcode::Ray ray(mMouseRayPos, mMouseRayDir);

  mRayColl.SetMaxDist(mRayLength > 0 ? mRayLength : Opcode::MAX_FLOAT);

  Bool_t status = mRayColl.Collide(ray, *mTringula->GetMesh()->GetOPCModel());

  if (bMouseVerbose)
    printf("TringuCam::MouseRayCollide status=%d, n_faces=%d\n",
           status, mCollFaces.GetNbFaces());

  if (status && mCollFaces.GetNbFaces() > 0)
  {
    using namespace Opcode;
    const CollisionFace& cf = mCollFaces.GetFaces()[0];

    if (bMouseVerbose)
      printf("  fc=%6d  d=%7.3f  u=%7.3f v=%7.3f\n",
             cf.mFaceID, cf.mDistance, cf.mU, cf.mV);

    TringTvor& TT = * mTringula->GetMesh()->GetTTvor();
    Int_t   *t  = TT.Triangle(cf.mFaceID);
    Float_t *v0 = TT.Vertex(t[0]);
    Float_t *v1 = TT.Vertex(t[1]);
    Float_t *v2 = TT.Vertex(t[2]);

    Point e1(v1[0] - v0[0], v1[1] - v0[1], v1[2] - v0[2]);
    Point e2(v2[0] - v0[0], v2[1] - v0[1], v2[2] - v0[2]);

    mCollFace = cf;
    mCollPoint.Set(v0); mCollPoint += cf.mU*e1 + cf.mV*e2;
    Int_t ci = (cf.mU + cf.mV <= 0.5) ? 0 : (cf.mU >= cf.mV) ? 1 : 2;
    mCollVertex = t[ci];
    if (bMouseVerbose)
      printf("  x=%7.3f  y=%7.3f  z=%7.3f   closest index=%d  vertex=%d\n",
             mCollPoint.x, mCollPoint.y, mCollPoint.z, ci, mCollVertex);
  }
  else
  {
    mCollVertex = -1;
  }
}

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

void TringuCam::TimeTick(Double_t t, Double_t dt)
{
  // Handle currently pressed keys.
  //
  // Mouse-2 camera rotation is handled in GL_Rnr.

  mFwdBck.TimeTick(dt);
  if (mFwdBck.fValue) MoveLF(1, dt*mFwdBck.fValue);

  mLftRgt.TimeTick(dt);
  if (mLftRgt.fValue) MoveLF(2, dt*mLftRgt.fValue);

  mUpDown.TimeTick(dt);
  if (mUpDown.fValue) mHeight += dt*mUpDown.fValue;
  if (mHeight > mTringula->GetMaxCameraH())
    mHeight = mTringula->GetMaxCameraH();

  mSpinUp.TimeTick(dt);
  if (mSpinUp.fValue) RotateLF(1, 2, dt*mSpinUp.fValue);

  { // Restore up-direction and height
    Float_t pos[3], fgh[3], hdir[3];
    mTrans.GetPos(pos);
    mTringula->GetParaSurf()->pos2fgh (pos, fgh);
    mTringula->GetParaSurf()->fgh2hdir(fgh, hdir);
    // printf("pos(%.2f, %.2f, %.2f) | fgh(%.2f, %.2f, %.2f) | hdir(%.2f, %.2f, %.2f)\n",
    //        pos[0], pos[1], pos[2], fgh[0], fgh[1], fgh[2], hdir[0],  hdir[2],  hdir[2]);

    mTrans.SetBaseVec(3, hdir);
    mTrans.OrtoNorm3Column(1, 3);
    mTrans.SetBaseVecViaCross(2);
    mTrans.MoveLF(3, mHeight - fgh[2]);
  }

  if (*mInfoTxt != 0)
    mInfoTxt->SetText
      (GForm("FWD: + %5.2f | %+5.2f | - %5.2f  ||  "
             "LFT: + %5.2f | %+5.2f | - %5.2f  || "
             " UP: + %5.2f | %+5.2f | - %5.2f",
             mFwdBck.fIncKey.fDesiredValue, mFwdBck.fValue, mFwdBck.fDecKey.fDesiredValue,
             mLftRgt.fIncKey.fDesiredValue, mLftRgt.fValue, mLftRgt.fDecKey.fDesiredValue,
             mUpDown.fIncKey.fDesiredValue, mUpDown.fValue, mUpDown.fDecKey.fDesiredValue));


  // This should be handled elsewhere, elsewise.
  if (bMouseDown && mMouseAction == MA_SprayField && mTringuRep->GetField() != 0)
  {
    CalculateMouseRayVectors();
    MouseRayCollide();
    mTringuRep->AddField(mCollPoint, mCollVertex, dt);
  }

  if (mStampInterval && --mStampCount < 0)
  {
    mStampCount = mStampInterval;
    Stamp();
  }
}


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

/**************************************************************************/
// TringuCam::ValueInfo
/**************************************************************************/

void
TringuCam::ValueInfo::IncValue(Float_t& value, Float_t desire,
                               Float_t  step,  Float_t delta_fac)
{
  if (value < desire)
  {
    if (delta_fac) step += delta_fac*(desire - value);
    value += step;
    if (value > desire) value = desire;
  }
}

void
TringuCam::ValueInfo::DecValue(Float_t& value, Float_t desire,
                               Float_t  step,  Float_t delta_fac)
{
  desire = -desire;
  if (value > desire)
  {
    if (delta_fac) step += delta_fac*(value - desire);
    value -= step;
    if (value < desire) value = desire;
  }
}

void
TringuCam::ValueInfo::DecayValue(Float_t& value, Float_t decay,
                                 Float_t delta_fac)
{
  if (value > 0)
  {
    if (delta_fac)      decay += delta_fac*value;
    if (value > decay)  value -= decay;
    else                value  = 0;
  }
  else
  {
    if (delta_fac)      decay -= delta_fac*value;
    if (-value > decay) value += decay;
    else                value  = 0;
  }
}

void
TringuCam::ValueInfo::DecayTimeoutOrValue(Float_t& timeout, Float_t& value,
                                          Float_t  dt,      Float_t  decay,
                                          Float_t  delta_fac)
{
  if (timeout != 0)
    DecayValue(timeout, dt);
  else if (value != 0)
    DecayValue(value, decay, delta_fac);
}

void
TringuCam::ValueInfo::ApproachValue(Float_t& value, Float_t desire,
				    Float_t inc_step, Float_t inc_delta_fac,
				    Float_t dec_step, Float_t dec_delta_fac)
{
  if (value < desire)
    IncValue(value, desire, inc_step, inc_delta_fac);
  else if (value > desire)
    DecValue(value, -desire, dec_step, dec_delta_fac);
  // !!! the -desire is hack, together with -desire in DecValue
  // need better encapsulation of all this shit.
}

// ------------------------------------------------------------------------

void TringuCam::ValueInfo::TimeTick(Float_t dt)
{
  KeyValueChangeParams& C = * fChangeParams;

  Float_t val_acc        = dt*C.fValueAccel;
  Float_t val_acc_dfac   = dt*C.fValueAccelDeltaFactor;
  Float_t val_decay      = dt*C.fValueDecay;
  Float_t val_decay_dfac = dt*C.fValueDecayDeltaFactor;

  Float_t des_decay      = dt*C.fDesireDecay;
  Float_t des_decay_dfac = dt*0.1; // !!! KONST

  if (fSustain)
  {
    if (fIncKey.fIsDown && fDecKey.fIsDown)
    {
      // do nothing ... it seems
    }
    else if ( ! fIncKey.fIsDown && ! fDecKey.fIsDown)
    {
      ApproachValue(fValue, fSustainDesire, val_acc, val_acc_dfac, val_decay, val_decay_dfac);

      DecayTimeoutOrValue(fIncKey.fDecayTimeout, fIncKey.fDesiredValue,
			  dt, des_decay, des_decay_dfac);
      DecayTimeoutOrValue(fDecKey.fDecayTimeout, fDecKey.fDesiredValue,
			  dt, des_decay, des_decay_dfac);
    }
    else
    {
      if (fIncKey.fIsDown)
      {
	ApproachValue(fValue, fMaxValue, val_acc, val_acc_dfac, val_decay, val_decay_dfac);

	DecayTimeoutOrValue(fDecKey.fDecayTimeout, fDecKey.fDesiredValue,
			    dt, des_decay, des_decay_dfac);
      }
      else
      {
	ApproachValue(fValue, fMinValue, val_acc, val_acc_dfac, val_decay, val_decay_dfac);

	DecayTimeoutOrValue(fIncKey.fDecayTimeout, fIncKey.fDesiredValue,
			    dt, des_decay, des_decay_dfac);
      }
    }

  }
  else
  {
    if (fIncKey.fIsDown && fDecKey.fIsDown)
    {
      if (fValue != 0) DecayValue(fValue, val_decay+val_acc, val_decay_dfac+val_acc_dfac);
    }
    else if ( ! fIncKey.fIsDown && ! fDecKey.fIsDown)
    {
      DecayTimeoutOrValue(fDecayTimeout, fValue, dt, val_decay, val_decay_dfac);

      DecayTimeoutOrValue(fIncKey.fDecayTimeout, fIncKey.fDesiredValue,
			  dt, des_decay, des_decay_dfac);
      DecayTimeoutOrValue(fDecKey.fDecayTimeout, fDecKey.fDesiredValue,
			  dt, des_decay, des_decay_dfac);
    }
    else
    {
      if (fIncKey.fIsDown)
      {
	IncValue(fValue, fIncKey.fDesiredValue, val_acc, val_acc_dfac);

	DecayTimeoutOrValue(fDecKey.fDecayTimeout, fDecKey.fDesiredValue,
			    dt, des_decay, des_decay_dfac);
      }
      else
      {
	DecValue(fValue, fDecKey.fDesiredValue, val_acc, val_acc_dfac);

	DecayTimeoutOrValue(fIncKey.fDecayTimeout, fIncKey.fDesiredValue,
			    dt, des_decay, des_decay_dfac);
      }
    }
  }
}

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

void TringuCam::ExtendioDetails(Extendio* ext)
{
  // Should show detailed UI, just Dump data for now,

  if (ext)
    ext->Dump();
}

void TringuCam::ExtendioExplode(Extendio* ext)
{
  // Terminate a dyno.
  // Called in a deteached thread.
  //
  // This is all wrong ... but want to try this.
  // This is much better now.

  static const Exc_t _eh("TringuCam::ExtendioExplode ");

  printf("Extendio '%s' exploding at your command!\n", ext->GetName());

  ext->TakeDamage(1000);
}

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

void TringuCam::PrepConnectStatos(Statico* stato, Int_t id, const TString& grad)
{
  // printf("TringuCam::PrepConnectStatos id=%d grad='%s'\n", id, grad.Data());

  SetPrepBeta(stato);
  mExpectBeta = EB_ConnectStaticos;
  mGradName = grad;
}

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

void TringuCam::Suspend()
{
  mEventor->Stop();
  mPupilInfo->SetAutoRedraw(true);
}

void TringuCam::Resume()
{
  mTimeMaker->SetLastTOK(false);
  mPupilInfo->SetAutoRedraw(false);
  mEventor->Start();
}

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

namespace {

const char* help_text =
  "\n"
  "================================================================================\n"
  "HELP FOR GREED-WORLD TECH-DEMO\n"
  "================================================================================\n"
  "Movement keys\n"
  "--------------------------------------------------------------------------------\n"
  "w, s - move forward / backward\n"
  "q, e - turn left / right\n"
  "a, d - move left / right\n"
  "r, f - move up / down\n"
  "Press a key several times to move faster.\n"
  "================================================================================\n"
  "Mouse buttons\n"
  "--------------------------------------------------------------------------------\n"
  "Mouse-1 - select objects\n"
  "Mouse-2 - rotate up/down, left/right\n"
  "Number-widgets can be manipulated by Mouse-drag (M2 - x10, M3 - x100)\n"
  "================================================================================\n"
  "Camera / screen controls\n"
  "--------------------------------------------------------------------------------\n"
  "Home     - look horizontally / return camera home\n"
  "Ctrl-F12 - fullscreen mode\n"
  "Ctrl-`   - go to native gled event handling (or switch back)\n"
  "--------------------------------------------------------------------------------\n";
}

void TringuCam::Help()
{
  fputs(help_text, stdout);
}

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

#include <Glasses/ZVector.h>

void TringuCam::RandomStatico()
{
  static const Exc_t _eh("TringuCam::RandomStatico ");

  ZVector *statos = dynamic_cast<ZVector*>
    (mQueen->FindLensByPath("var/meshes/rndstatos"));

  if (!statos)
    throw _eh + "stato-mesh vector not found.";

  GLensReadHolder _tlck(*mTringula);
  Statico* s = mTringula->RandomStatico(statos);
  if (s == 0)
    throw _eh + "placement seems to have failed.";
  else
    printf("%screated '%s'\n", _eh.Data(), s->GetName());
}

void TringuCam::MakeLandMark()
{
  if (mMouseAction != MA_NewLandMark)
    mPrevAction = mMouseAction;
  mMouseAction = MA_NewLandMark;

  Stamp(FID());
}
 TringuCam.cxx:1
 TringuCam.cxx:2
 TringuCam.cxx:3
 TringuCam.cxx:4
 TringuCam.cxx:5
 TringuCam.cxx:6
 TringuCam.cxx:7
 TringuCam.cxx:8
 TringuCam.cxx:9
 TringuCam.cxx:10
 TringuCam.cxx:11
 TringuCam.cxx:12
 TringuCam.cxx:13
 TringuCam.cxx:14
 TringuCam.cxx:15
 TringuCam.cxx:16
 TringuCam.cxx:17
 TringuCam.cxx:18
 TringuCam.cxx:19
 TringuCam.cxx:20
 TringuCam.cxx:21
 TringuCam.cxx:22
 TringuCam.cxx:23
 TringuCam.cxx:24
 TringuCam.cxx:25
 TringuCam.cxx:26
 TringuCam.cxx:27
 TringuCam.cxx:28
 TringuCam.cxx:29
 TringuCam.cxx:30
 TringuCam.cxx:31
 TringuCam.cxx:32
 TringuCam.cxx:33
 TringuCam.cxx:34
 TringuCam.cxx:35
 TringuCam.cxx:36
 TringuCam.cxx:37
 TringuCam.cxx:38
 TringuCam.cxx:39
 TringuCam.cxx:40
 TringuCam.cxx:41
 TringuCam.cxx:42
 TringuCam.cxx:43
 TringuCam.cxx:44
 TringuCam.cxx:45
 TringuCam.cxx:46
 TringuCam.cxx:47
 TringuCam.cxx:48
 TringuCam.cxx:49
 TringuCam.cxx:50
 TringuCam.cxx:51
 TringuCam.cxx:52
 TringuCam.cxx:53
 TringuCam.cxx:54
 TringuCam.cxx:55
 TringuCam.cxx:56
 TringuCam.cxx:57
 TringuCam.cxx:58
 TringuCam.cxx:59
 TringuCam.cxx:60
 TringuCam.cxx:61
 TringuCam.cxx:62
 TringuCam.cxx:63
 TringuCam.cxx:64
 TringuCam.cxx:65
 TringuCam.cxx:66
 TringuCam.cxx:67
 TringuCam.cxx:68
 TringuCam.cxx:69
 TringuCam.cxx:70
 TringuCam.cxx:71
 TringuCam.cxx:72
 TringuCam.cxx:73
 TringuCam.cxx:74
 TringuCam.cxx:75
 TringuCam.cxx:76
 TringuCam.cxx:77
 TringuCam.cxx:78
 TringuCam.cxx:79
 TringuCam.cxx:80
 TringuCam.cxx:81
 TringuCam.cxx:82
 TringuCam.cxx:83
 TringuCam.cxx:84
 TringuCam.cxx:85
 TringuCam.cxx:86
 TringuCam.cxx:87
 TringuCam.cxx:88
 TringuCam.cxx:89
 TringuCam.cxx:90
 TringuCam.cxx:91
 TringuCam.cxx:92
 TringuCam.cxx:93
 TringuCam.cxx:94
 TringuCam.cxx:95
 TringuCam.cxx:96
 TringuCam.cxx:97
 TringuCam.cxx:98
 TringuCam.cxx:99
 TringuCam.cxx:100
 TringuCam.cxx:101
 TringuCam.cxx:102
 TringuCam.cxx:103
 TringuCam.cxx:104
 TringuCam.cxx:105
 TringuCam.cxx:106
 TringuCam.cxx:107
 TringuCam.cxx:108
 TringuCam.cxx:109
 TringuCam.cxx:110
 TringuCam.cxx:111
 TringuCam.cxx:112
 TringuCam.cxx:113
 TringuCam.cxx:114
 TringuCam.cxx:115
 TringuCam.cxx:116
 TringuCam.cxx:117
 TringuCam.cxx:118
 TringuCam.cxx:119
 TringuCam.cxx:120
 TringuCam.cxx:121
 TringuCam.cxx:122
 TringuCam.cxx:123
 TringuCam.cxx:124
 TringuCam.cxx:125
 TringuCam.cxx:126
 TringuCam.cxx:127
 TringuCam.cxx:128
 TringuCam.cxx:129
 TringuCam.cxx:130
 TringuCam.cxx:131
 TringuCam.cxx:132
 TringuCam.cxx:133
 TringuCam.cxx:134
 TringuCam.cxx:135
 TringuCam.cxx:136
 TringuCam.cxx:137
 TringuCam.cxx:138
 TringuCam.cxx:139
 TringuCam.cxx:140
 TringuCam.cxx:141
 TringuCam.cxx:142
 TringuCam.cxx:143
 TringuCam.cxx:144
 TringuCam.cxx:145
 TringuCam.cxx:146
 TringuCam.cxx:147
 TringuCam.cxx:148
 TringuCam.cxx:149
 TringuCam.cxx:150
 TringuCam.cxx:151
 TringuCam.cxx:152
 TringuCam.cxx:153
 TringuCam.cxx:154
 TringuCam.cxx:155
 TringuCam.cxx:156
 TringuCam.cxx:157
 TringuCam.cxx:158
 TringuCam.cxx:159
 TringuCam.cxx:160
 TringuCam.cxx:161
 TringuCam.cxx:162
 TringuCam.cxx:163
 TringuCam.cxx:164
 TringuCam.cxx:165
 TringuCam.cxx:166
 TringuCam.cxx:167
 TringuCam.cxx:168
 TringuCam.cxx:169
 TringuCam.cxx:170
 TringuCam.cxx:171
 TringuCam.cxx:172
 TringuCam.cxx:173
 TringuCam.cxx:174
 TringuCam.cxx:175
 TringuCam.cxx:176
 TringuCam.cxx:177
 TringuCam.cxx:178
 TringuCam.cxx:179
 TringuCam.cxx:180
 TringuCam.cxx:181
 TringuCam.cxx:182
 TringuCam.cxx:183
 TringuCam.cxx:184
 TringuCam.cxx:185
 TringuCam.cxx:186
 TringuCam.cxx:187
 TringuCam.cxx:188
 TringuCam.cxx:189
 TringuCam.cxx:190
 TringuCam.cxx:191
 TringuCam.cxx:192
 TringuCam.cxx:193
 TringuCam.cxx:194
 TringuCam.cxx:195
 TringuCam.cxx:196
 TringuCam.cxx:197
 TringuCam.cxx:198
 TringuCam.cxx:199
 TringuCam.cxx:200
 TringuCam.cxx:201
 TringuCam.cxx:202
 TringuCam.cxx:203
 TringuCam.cxx:204
 TringuCam.cxx:205
 TringuCam.cxx:206
 TringuCam.cxx:207
 TringuCam.cxx:208
 TringuCam.cxx:209
 TringuCam.cxx:210
 TringuCam.cxx:211
 TringuCam.cxx:212
 TringuCam.cxx:213
 TringuCam.cxx:214
 TringuCam.cxx:215
 TringuCam.cxx:216
 TringuCam.cxx:217
 TringuCam.cxx:218
 TringuCam.cxx:219
 TringuCam.cxx:220
 TringuCam.cxx:221
 TringuCam.cxx:222
 TringuCam.cxx:223
 TringuCam.cxx:224
 TringuCam.cxx:225
 TringuCam.cxx:226
 TringuCam.cxx:227
 TringuCam.cxx:228
 TringuCam.cxx:229
 TringuCam.cxx:230
 TringuCam.cxx:231
 TringuCam.cxx:232
 TringuCam.cxx:233
 TringuCam.cxx:234
 TringuCam.cxx:235
 TringuCam.cxx:236
 TringuCam.cxx:237
 TringuCam.cxx:238
 TringuCam.cxx:239
 TringuCam.cxx:240
 TringuCam.cxx:241
 TringuCam.cxx:242
 TringuCam.cxx:243
 TringuCam.cxx:244
 TringuCam.cxx:245
 TringuCam.cxx:246
 TringuCam.cxx:247
 TringuCam.cxx:248
 TringuCam.cxx:249
 TringuCam.cxx:250
 TringuCam.cxx:251
 TringuCam.cxx:252
 TringuCam.cxx:253
 TringuCam.cxx:254
 TringuCam.cxx:255
 TringuCam.cxx:256
 TringuCam.cxx:257
 TringuCam.cxx:258
 TringuCam.cxx:259
 TringuCam.cxx:260
 TringuCam.cxx:261
 TringuCam.cxx:262
 TringuCam.cxx:263
 TringuCam.cxx:264
 TringuCam.cxx:265
 TringuCam.cxx:266
 TringuCam.cxx:267
 TringuCam.cxx:268
 TringuCam.cxx:269
 TringuCam.cxx:270
 TringuCam.cxx:271
 TringuCam.cxx:272
 TringuCam.cxx:273
 TringuCam.cxx:274
 TringuCam.cxx:275
 TringuCam.cxx:276
 TringuCam.cxx:277
 TringuCam.cxx:278
 TringuCam.cxx:279
 TringuCam.cxx:280
 TringuCam.cxx:281
 TringuCam.cxx:282
 TringuCam.cxx:283
 TringuCam.cxx:284
 TringuCam.cxx:285
 TringuCam.cxx:286
 TringuCam.cxx:287
 TringuCam.cxx:288
 TringuCam.cxx:289
 TringuCam.cxx:290
 TringuCam.cxx:291
 TringuCam.cxx:292
 TringuCam.cxx:293
 TringuCam.cxx:294
 TringuCam.cxx:295
 TringuCam.cxx:296
 TringuCam.cxx:297
 TringuCam.cxx:298
 TringuCam.cxx:299
 TringuCam.cxx:300
 TringuCam.cxx:301
 TringuCam.cxx:302
 TringuCam.cxx:303
 TringuCam.cxx:304
 TringuCam.cxx:305
 TringuCam.cxx:306
 TringuCam.cxx:307
 TringuCam.cxx:308
 TringuCam.cxx:309
 TringuCam.cxx:310
 TringuCam.cxx:311
 TringuCam.cxx:312
 TringuCam.cxx:313
 TringuCam.cxx:314
 TringuCam.cxx:315
 TringuCam.cxx:316
 TringuCam.cxx:317
 TringuCam.cxx:318
 TringuCam.cxx:319
 TringuCam.cxx:320
 TringuCam.cxx:321
 TringuCam.cxx:322
 TringuCam.cxx:323
 TringuCam.cxx:324
 TringuCam.cxx:325
 TringuCam.cxx:326
 TringuCam.cxx:327
 TringuCam.cxx:328
 TringuCam.cxx:329
 TringuCam.cxx:330
 TringuCam.cxx:331
 TringuCam.cxx:332
 TringuCam.cxx:333
 TringuCam.cxx:334
 TringuCam.cxx:335
 TringuCam.cxx:336
 TringuCam.cxx:337
 TringuCam.cxx:338
 TringuCam.cxx:339
 TringuCam.cxx:340
 TringuCam.cxx:341
 TringuCam.cxx:342
 TringuCam.cxx:343
 TringuCam.cxx:344
 TringuCam.cxx:345
 TringuCam.cxx:346
 TringuCam.cxx:347
 TringuCam.cxx:348
 TringuCam.cxx:349
 TringuCam.cxx:350
 TringuCam.cxx:351
 TringuCam.cxx:352
 TringuCam.cxx:353
 TringuCam.cxx:354
 TringuCam.cxx:355
 TringuCam.cxx:356
 TringuCam.cxx:357
 TringuCam.cxx:358
 TringuCam.cxx:359
 TringuCam.cxx:360
 TringuCam.cxx:361
 TringuCam.cxx:362
 TringuCam.cxx:363
 TringuCam.cxx:364
 TringuCam.cxx:365
 TringuCam.cxx:366
 TringuCam.cxx:367
 TringuCam.cxx:368
 TringuCam.cxx:369
 TringuCam.cxx:370
 TringuCam.cxx:371
 TringuCam.cxx:372
 TringuCam.cxx:373
 TringuCam.cxx:374
 TringuCam.cxx:375
 TringuCam.cxx:376
 TringuCam.cxx:377
 TringuCam.cxx:378
 TringuCam.cxx:379
 TringuCam.cxx:380
 TringuCam.cxx:381
 TringuCam.cxx:382
 TringuCam.cxx:383
 TringuCam.cxx:384
 TringuCam.cxx:385
 TringuCam.cxx:386
 TringuCam.cxx:387
 TringuCam.cxx:388
 TringuCam.cxx:389
 TringuCam.cxx:390
 TringuCam.cxx:391
 TringuCam.cxx:392
 TringuCam.cxx:393
 TringuCam.cxx:394
 TringuCam.cxx:395
 TringuCam.cxx:396
 TringuCam.cxx:397
 TringuCam.cxx:398
 TringuCam.cxx:399
 TringuCam.cxx:400
 TringuCam.cxx:401
 TringuCam.cxx:402
 TringuCam.cxx:403
 TringuCam.cxx:404
 TringuCam.cxx:405
 TringuCam.cxx:406
 TringuCam.cxx:407
 TringuCam.cxx:408
 TringuCam.cxx:409
 TringuCam.cxx:410
 TringuCam.cxx:411
 TringuCam.cxx:412
 TringuCam.cxx:413
 TringuCam.cxx:414
 TringuCam.cxx:415
 TringuCam.cxx:416
 TringuCam.cxx:417
 TringuCam.cxx:418
 TringuCam.cxx:419
 TringuCam.cxx:420
 TringuCam.cxx:421
 TringuCam.cxx:422
 TringuCam.cxx:423
 TringuCam.cxx:424
 TringuCam.cxx:425
 TringuCam.cxx:426
 TringuCam.cxx:427
 TringuCam.cxx:428
 TringuCam.cxx:429
 TringuCam.cxx:430
 TringuCam.cxx:431
 TringuCam.cxx:432
 TringuCam.cxx:433
 TringuCam.cxx:434
 TringuCam.cxx:435
 TringuCam.cxx:436
 TringuCam.cxx:437
 TringuCam.cxx:438
 TringuCam.cxx:439
 TringuCam.cxx:440
 TringuCam.cxx:441
 TringuCam.cxx:442
 TringuCam.cxx:443
 TringuCam.cxx:444
 TringuCam.cxx:445
 TringuCam.cxx:446
 TringuCam.cxx:447
 TringuCam.cxx:448
 TringuCam.cxx:449
 TringuCam.cxx:450
 TringuCam.cxx:451
 TringuCam.cxx:452
 TringuCam.cxx:453
 TringuCam.cxx:454
 TringuCam.cxx:455
 TringuCam.cxx:456
 TringuCam.cxx:457
 TringuCam.cxx:458
 TringuCam.cxx:459
 TringuCam.cxx:460
 TringuCam.cxx:461
 TringuCam.cxx:462
 TringuCam.cxx:463
 TringuCam.cxx:464
 TringuCam.cxx:465
 TringuCam.cxx:466
 TringuCam.cxx:467
 TringuCam.cxx:468
 TringuCam.cxx:469
 TringuCam.cxx:470
 TringuCam.cxx:471
 TringuCam.cxx:472
 TringuCam.cxx:473
 TringuCam.cxx:474
 TringuCam.cxx:475
 TringuCam.cxx:476
 TringuCam.cxx:477
 TringuCam.cxx:478
 TringuCam.cxx:479
 TringuCam.cxx:480
 TringuCam.cxx:481
 TringuCam.cxx:482
 TringuCam.cxx:483
 TringuCam.cxx:484
 TringuCam.cxx:485
 TringuCam.cxx:486
 TringuCam.cxx:487
 TringuCam.cxx:488
 TringuCam.cxx:489
 TringuCam.cxx:490
 TringuCam.cxx:491
 TringuCam.cxx:492
 TringuCam.cxx:493
 TringuCam.cxx:494
 TringuCam.cxx:495
 TringuCam.cxx:496
 TringuCam.cxx:497
 TringuCam.cxx:498
 TringuCam.cxx:499
 TringuCam.cxx:500
 TringuCam.cxx:501
 TringuCam.cxx:502
 TringuCam.cxx:503
 TringuCam.cxx:504
 TringuCam.cxx:505
 TringuCam.cxx:506
 TringuCam.cxx:507
 TringuCam.cxx:508
 TringuCam.cxx:509
 TringuCam.cxx:510
 TringuCam.cxx:511
 TringuCam.cxx:512
 TringuCam.cxx:513
 TringuCam.cxx:514
 TringuCam.cxx:515
 TringuCam.cxx:516
 TringuCam.cxx:517
 TringuCam.cxx:518
 TringuCam.cxx:519
 TringuCam.cxx:520
 TringuCam.cxx:521
 TringuCam.cxx:522
 TringuCam.cxx:523
 TringuCam.cxx:524
 TringuCam.cxx:525
 TringuCam.cxx:526
 TringuCam.cxx:527
 TringuCam.cxx:528
 TringuCam.cxx:529
 TringuCam.cxx:530
 TringuCam.cxx:531
 TringuCam.cxx:532
 TringuCam.cxx:533
 TringuCam.cxx:534
 TringuCam.cxx:535
 TringuCam.cxx:536
 TringuCam.cxx:537
 TringuCam.cxx:538
 TringuCam.cxx:539
 TringuCam.cxx:540
 TringuCam.cxx:541
 TringuCam.cxx:542
 TringuCam.cxx:543
 TringuCam.cxx:544
 TringuCam.cxx:545
 TringuCam.cxx:546
 TringuCam.cxx:547
 TringuCam.cxx:548
 TringuCam.cxx:549
 TringuCam.cxx:550
 TringuCam.cxx:551
 TringuCam.cxx:552
 TringuCam.cxx:553
 TringuCam.cxx:554
 TringuCam.cxx:555
 TringuCam.cxx:556
 TringuCam.cxx:557
 TringuCam.cxx:558
 TringuCam.cxx:559
 TringuCam.cxx:560
 TringuCam.cxx:561
 TringuCam.cxx:562
 TringuCam.cxx:563
 TringuCam.cxx:564
 TringuCam.cxx:565
 TringuCam.cxx:566
 TringuCam.cxx:567
 TringuCam.cxx:568
 TringuCam.cxx:569
 TringuCam.cxx:570
 TringuCam.cxx:571
 TringuCam.cxx:572
 TringuCam.cxx:573
 TringuCam.cxx:574
 TringuCam.cxx:575
 TringuCam.cxx:576
 TringuCam.cxx:577
 TringuCam.cxx:578
 TringuCam.cxx:579
 TringuCam.cxx:580
 TringuCam.cxx:581
 TringuCam.cxx:582
 TringuCam.cxx:583
 TringuCam.cxx:584
 TringuCam.cxx:585
 TringuCam.cxx:586
 TringuCam.cxx:587
 TringuCam.cxx:588
 TringuCam.cxx:589
 TringuCam.cxx:590
 TringuCam.cxx:591
 TringuCam.cxx:592
 TringuCam.cxx:593
 TringuCam.cxx:594
 TringuCam.cxx:595
 TringuCam.cxx:596
 TringuCam.cxx:597
 TringuCam.cxx:598
 TringuCam.cxx:599
 TringuCam.cxx:600
 TringuCam.cxx:601
 TringuCam.cxx:602
 TringuCam.cxx:603
 TringuCam.cxx:604
 TringuCam.cxx:605
 TringuCam.cxx:606
 TringuCam.cxx:607
 TringuCam.cxx:608
 TringuCam.cxx:609
 TringuCam.cxx:610
 TringuCam.cxx:611
 TringuCam.cxx:612
 TringuCam.cxx:613
 TringuCam.cxx:614
 TringuCam.cxx:615
 TringuCam.cxx:616
 TringuCam.cxx:617
 TringuCam.cxx:618
 TringuCam.cxx:619
 TringuCam.cxx:620
 TringuCam.cxx:621
 TringuCam.cxx:622
 TringuCam.cxx:623
 TringuCam.cxx:624
 TringuCam.cxx:625
 TringuCam.cxx:626
 TringuCam.cxx:627
 TringuCam.cxx:628
 TringuCam.cxx:629
 TringuCam.cxx:630
 TringuCam.cxx:631
 TringuCam.cxx:632
 TringuCam.cxx:633
 TringuCam.cxx:634
 TringuCam.cxx:635
 TringuCam.cxx:636
 TringuCam.cxx:637
 TringuCam.cxx:638
 TringuCam.cxx:639
 TringuCam.cxx:640
 TringuCam.cxx:641
 TringuCam.cxx:642
 TringuCam.cxx:643
 TringuCam.cxx:644
 TringuCam.cxx:645
 TringuCam.cxx:646
 TringuCam.cxx:647
 TringuCam.cxx:648
 TringuCam.cxx:649
 TringuCam.cxx:650
 TringuCam.cxx:651
 TringuCam.cxx:652
 TringuCam.cxx:653
 TringuCam.cxx:654
 TringuCam.cxx:655
 TringuCam.cxx:656
 TringuCam.cxx:657
 TringuCam.cxx:658
 TringuCam.cxx:659
 TringuCam.cxx:660
 TringuCam.cxx:661
 TringuCam.cxx:662
 TringuCam.cxx:663
 TringuCam.cxx:664
 TringuCam.cxx:665
 TringuCam.cxx:666
 TringuCam.cxx:667
 TringuCam.cxx:668
 TringuCam.cxx:669
 TringuCam.cxx:670
 TringuCam.cxx:671
 TringuCam.cxx:672
 TringuCam.cxx:673
 TringuCam.cxx:674
 TringuCam.cxx:675
 TringuCam.cxx:676
 TringuCam.cxx:677
 TringuCam.cxx:678
 TringuCam.cxx:679
 TringuCam.cxx:680
 TringuCam.cxx:681
 TringuCam.cxx:682
 TringuCam.cxx:683
 TringuCam.cxx:684
 TringuCam.cxx:685
 TringuCam.cxx:686
 TringuCam.cxx:687
 TringuCam.cxx:688
 TringuCam.cxx:689
 TringuCam.cxx:690
 TringuCam.cxx:691
 TringuCam.cxx:692
 TringuCam.cxx:693
 TringuCam.cxx:694
 TringuCam.cxx:695
 TringuCam.cxx:696
 TringuCam.cxx:697
 TringuCam.cxx:698
 TringuCam.cxx:699
 TringuCam.cxx:700
 TringuCam.cxx:701
 TringuCam.cxx:702
 TringuCam.cxx:703
 TringuCam.cxx:704
 TringuCam.cxx:705
 TringuCam.cxx:706
 TringuCam.cxx:707
 TringuCam.cxx:708
 TringuCam.cxx:709
 TringuCam.cxx:710
 TringuCam.cxx:711
 TringuCam.cxx:712
 TringuCam.cxx:713
 TringuCam.cxx:714
 TringuCam.cxx:715
 TringuCam.cxx:716
 TringuCam.cxx:717
 TringuCam.cxx:718
 TringuCam.cxx:719
 TringuCam.cxx:720
 TringuCam.cxx:721
 TringuCam.cxx:722
 TringuCam.cxx:723
 TringuCam.cxx:724
 TringuCam.cxx:725
 TringuCam.cxx:726
 TringuCam.cxx:727
 TringuCam.cxx:728
 TringuCam.cxx:729
 TringuCam.cxx:730
 TringuCam.cxx:731
 TringuCam.cxx:732
 TringuCam.cxx:733
 TringuCam.cxx:734
 TringuCam.cxx:735
 TringuCam.cxx:736
 TringuCam.cxx:737
 TringuCam.cxx:738
 TringuCam.cxx:739
 TringuCam.cxx:740
 TringuCam.cxx:741
 TringuCam.cxx:742
 TringuCam.cxx:743
 TringuCam.cxx:744
 TringuCam.cxx:745