ROOT logo
// $Id: PupilInfo.cxx 2451 2010-09-29 20:58:29Z 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/.

//__________________________________________________________________________
// PupilInfo
//
// Configuration data for GL viewer.
//
// Camera orientation: x-forward, y-left, z-up. This should help understand
// viewing angle/size specification variables: mZFov, mYFac, mZSize, mXDist.
// ZFov & YFac used in perspective mode, mZSise & mYFac in orthographic mode.
// mXDist is used as a 'typical distance of objects' when changing from one
// mode to the other.
//
// Emits custom Rays: dump_image, resize_window, camera_home
//
// *Overlay*
//
// Two links control display and interaction with the overlay:
// _mOverlay_ is rendered after the rendering of the scene
// _mEventHandler_ if non-zero, fltk-like-events are sent to its renderer

#include "PupilInfo.h"
#include "PupilInfo.c7"
#include <Glasses/ZQueen.h>

#include <TMath.h>

#include <GL/glew.h>

ClassImp(PupilInfo);

Bool_t PupilInfo::sStereoDefault = false;

void PupilInfo::_init()
{
  // Override from SubShellInfo:
  mCtorLibset = "GledCore";
  mCtorName   = "Pupil";

  // Basic config.
  mMaxRnrDepth = 100;
  bAutoRedraw  = true;
  mWidth = 640; mHeight = 480;
  mClearColor.rgba(0,0,0);

  // CameraInfo.
  mCameraBase    = 0;

  mLookAt        = 0;
  mLookAtMinDist = 0.1;

  mUpReference   = 0;
  mUpRefAxis     = 3;
  bUpRefLockDir  = true;
  mUpRefMinAngle = 10;

  mProjMode = P_Perspective;
  mZFov     = 90;   mZSize    = 20;
  mYFac     = 1;    mXDist    = 10;
  mNearClip = 0.01; mFarClip  = 100;
  mZoomFac  = 1.1; // if fac = 1, linear zooming is used (see Pupil::handle())
  mDefZFov  = 90;   mDefZSize = 20;
  mMinZFov  = 0;
  mMaxZFov  = 160;

  // Basic rendering options.
  mFrontMode = GL_FILL; mBackMode = GL_LINE;
  bLiMo2Side = false;
  bBlend     = false;

  // User interaction and feedback.
  mMSRotFac = 1; mMSMoveFac = 2; mMoveOM = -2; mAccelExp = 0.5;

  mCHSize       = 0.03; // Cross-hair size.
  mMPSize       = 0;    // Internal mouse-pointer size.
  mHomeAnimTime = 2;    // Time of smooth-home animation.

  bShowRPS = true; bShowView = true; bRnrNames = false;
  bRnrFakeOverlayInCapture = false; // Does not work in multi-tile capture.

  mBuffSize = 4096; mPickR = 5; mPickDisp = 0; mPickMaxN = 24;

  mPopupDx = 200; mPopupDy = 0;
  mPopupFx = 0;   mPopupFy = -0.5;

  bAllowHandlerSwitchInPupil = true;

  bStereo               = sStereoDefault;
  mStereoZeroParallax   = 0;
  mStereoEyeOffsetFac   = 1;
  mStereoFrustumAsymFac = 1;

  mRnrCamFix = 0;
}

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

void PupilInfo::SetCameraBase(ZNode* camerabase)
{
  static const Exc_t _eh("PupilInfo::SetCameraBase ");

  if(camerabase != 0) {
    ZTrans* t = ToPupilFrame(camerabase);
    if(t == 0)
      throw(_eh + "camera not connected into pupil contents.");
    delete t;
  }
  set_link_or_die(mCameraBase.ref_link(), camerabase, FID());
}

void PupilInfo::SetLookAt(ZNode* lookat)
{
  static const Exc_t _eh("PupilInfo::SetLookAt ");

  if(lookat != 0) {
    ZTrans* t = ToPupilFrame(lookat);
    if(t == 0)
      throw(_eh + "camera not connected into pupil contents.");
    delete t;
  }
  set_link_or_die(mLookAt.ref_link(), lookat, FID());
}

void PupilInfo::SetUpReference(ZNode* upreference)
{
  static const Exc_t _eh("PupilInfo::SetUpReference ");

  if(upreference != 0) {
    ZTrans* t = ToPupilFrame(upreference);
    if(t == 0)
      throw("camera not connected into pupil contents.");
    delete t;
  }

  set_link_or_die(mUpReference.ref_link(), upreference, FID());
}

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

void PupilInfo::ImportCameraInfo(CameraInfo* cam_info)
{
  // Imports camera info data.

  // cat cbase.defs | perl -e 'undef $/; $l=<STDIN>; @x=split(/\s*=[^;]+\s*;\s*/, $l); for $d (@x) { $m=$d; $m=~s/^m|b//; print "  $d = cam_info->Get$m();\n";}'
  // + hand fixes for links/enums.

  static const Exc_t _eh("PupilInfo::ImportCameraInfo ");

  if(cam_info == 0) throw(_eh + "called with cam_info=0.");

  if(cam_info->GetFixCameraBase()) {
    SetCameraBase(cam_info->GetCameraBase());
  }
  if(cam_info->GetFixLookAt()) {
    SetLookAt(cam_info->GetLookAt());
    mLookAtMinDist = cam_info->GetLookAtMinDist();
  }
  if(cam_info->GetFixUpReference()) {
    SetUpReference(cam_info->GetUpReference());
    mUpRefAxis = cam_info->GetUpRefAxis();
    bUpRefLockDir = cam_info->GetUpRefLockDir();
    mUpRefMinAngle = cam_info->GetUpRefMinAngle();
  }
  mProjMode = (Projection_e) cam_info->GetProjMode();
  mZFov     = cam_info->GetZFov();
  mZSize    = cam_info->GetZSize();
  mYFac     = cam_info->GetYFac();
  mXDist    = cam_info->GetXDist();
  mNearClip = cam_info->GetNearClip();
  mFarClip  = cam_info->GetFarClip();
  mDefZFov  = cam_info->GetDefZFov();
  mDefZSize = cam_info->GetDefZSize();

  Stamp(FID());

  if(cam_info->GetFixCameraBase())
    EmitCameraHomeRay();
}

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

void PupilInfo::SmoothCameraHome(ZNode* new_base)
{
  if(new_base) {
    SetCameraBase(new_base);
    EmitRedrawRay(); // This forces redraw, reinitializes pupil's data.
  }
  EmitSmoothCameraHomeRay();
}

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

void PupilInfo::Zoom(Float_t delta)
{
  switch(mProjMode) {
  case P_Perspective: {
    Float_t fov = mZFov + delta;
    if (fov < mMinZFov) fov = mMinZFov;
    if (fov > mMaxZFov) fov = mMaxZFov;
    SetZFov (fov);
    SetZSize(2*mXDist*TMath::Tan(0.5*TMath::DegToRad()*fov));
    break;
  }
  case P_Orthographic: {
    SetZSize(mZSize + delta);
    SetZFov (2*TMath::RadToDeg()*TMath::ATan2(mZSize, mXDist));
  }
  }
}

void PupilInfo::ZoomFac(Float_t fac)
{
  switch(mProjMode) {
  case P_Perspective: {
    Float_t fov = fac*mZFov;
    if (fov < mMinZFov) fov = mMinZFov;
    if (fov > mMaxZFov) fov = mMaxZFov;
    SetZFov (fov);
    SetZSize(2*mXDist*TMath::Tan(0.5*TMath::DegToRad()*mZFov));
    break;
  }
  case P_Orthographic: {
    SetZSize(fac*mZSize);
    SetZFov (2*TMath::RadToDeg()*TMath::ATan2(mZSize, mXDist));
  }
  }
}

void PupilInfo::Home(Bool_t smooth)
{
  switch(mProjMode)
  {
    case P_Perspective:
    {
      if (mDefZFov && mDefZFov != mZFov)
      {
	SetZFov (mDefZFov);
	SetZSize(2*mXDist*TMath::Tan(0.5*TMath::DegToRad()*mZFov));
      }
      break;
    }
    case P_Orthographic:
    {
      SetZSize(mDefZSize);
      SetZFov (2*TMath::RadToDeg()*TMath::ATan2(mZSize, mXDist));
      break;
    }
  }
  if (smooth)
    EmitSmoothCameraHomeRay();
  else
    EmitCameraHomeRay();
}

void PupilInfo::SetupZFov(Float_t zfov)
{
  SetZFov(zfov);
  SetDefZFov(zfov);
}

void PupilInfo::SetupZSize(Float_t zsize)
{
  SetZSize(zsize);
  SetDefZSize(zsize);
}

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

ZTrans* PupilInfo::ToPupilFrame(ZNode* node)
{
  // Returns transformation from node->pupil reference frame.
  //
  // In general, it is a bad idea to call this function under a lens lock.

  if (node == 0) return 0;

  ZTrans *ret;
  {
    GLensReadHolder rd_lck(node);
    ret = new ZTrans(node->RefTrans());
  }

  set<ZGlass*> top_levels;
  {
    GMutexHolder lst_lck(mListMutex);
    Stepper<ZNode> s(this);
    while (s.step())
    {
      if (*s == node)
	return ret;
      top_levels.insert(*s);
    }
  }

  node = node->GetParent();
  while (node)
  {
    {
      GLensReadHolder rd_lck(node);
      ret->MultLeft(node->RefTrans());
    }

    if (top_levels.find(node) != top_levels.end())
      return ret;

    node = node->GetParent();
  }

  delete ret;
  return 0;
}

ZTrans* PupilInfo::ToCameraFrame(ZNode* node)
{
  // Returns transformation from node->camera reference frame.
  // Camera's matrix is not multiplied in the result (as it is not known).

  ZTrans* n2p = ToPupilFrame(node);
  if(n2p == 0) return 0;

  ZNode* cam_base = mCameraBase.get();
  if(cam_base) {
    ZTrans* c2p = ToPupilFrame(cam_base);
    if(c2p == 0) {
      delete n2p;
      return 0;
    }
    c2p->Invert();
    *c2p *= *n2p;
    delete n2p;
    return c2p;
  }
  return n2p;
}

Bool_t PupilInfo::TransformMouseRayVectors(ZNode* ref, ZPoint& pos, ZPoint& dir)
{
  // Transforms last mouse-ray vectors into the frame of ref.
  // This multiples transformation matrices from camera-base upwards
  // until ref is reached -- the transformation of ref is not applied.

  pos = mMouseRayPos;
  dir = mMouseRayDir;

  // CamFix rotation is done in GLRnrDriver.
  // mRnrCamFix->MultiplyIP(pos);
  // mRnrCamFix->RotateIP  (dir);

  ZNode *node = *mCameraBase;
  while (node != ref)
  {
    if (!node)
      return false;

    GLensReadHolder rd_lck(node);

    node->ref_trans().MultiplyIP(pos);
    node->ref_trans().RotateIP  (dir);

    node = node->GetParent();
  }
  return true;
}

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

void PupilInfo::EmitResizeRay()
{
  if(mQueen && mSaturn->AcceptsRays()) {
    auto_ptr<Ray> ray
      (Ray::PtrCtor(this, PRQN_resize_window, mTimeStamp, FID()));
    mQueen->EmitRay(ray);
  }
}

void PupilInfo::EmitCameraHomeRay()
{
  if(mQueen && mSaturn->AcceptsRays()) {
    auto_ptr<Ray> ray
      (Ray::PtrCtor(this, PRQN_camera_home, mTimeStamp, FID()));
    mQueen->EmitRay(ray);
  }
}

void PupilInfo::EmitSmoothCameraHomeRay()
{
  if(mQueen && mSaturn->AcceptsRays()) {
    auto_ptr<Ray> ray
      (Ray::PtrCtor(this, PRQN_smooth_camera_home, mTimeStamp, FID()));
    mQueen->EmitRay(ray);
  }
}

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

void PupilInfo::EmitRedrawRay(Bool_t signal_p)
{
  if (mQueen && mSaturn->AcceptsRays())
  {
    auto_ptr<Ray> ray
      (Ray::PtrCtor(this, PRQN_redraw, mTimeStamp, FID()));

    ray->CustomBuffer() << signal_p;
    mQueen->EmitRay(ray);
  }
}

void PupilInfo::EmitDumpImageRay(const TString& filename, Int_t n_tiles,
                                 Bool_t copy_p, Bool_t signal_p)
{
  if (mQueen && mSaturn->AcceptsRays())
  {
    auto_ptr<Ray> ray
      (Ray::PtrCtor(this, PRQN_dump_image, mTimeStamp, FID()));

    ray->CustomBuffer() << filename << n_tiles << copy_p << signal_p;
    mQueen->EmitRay(ray);
  }
}

void PupilInfo::Redraw()
{
  EmitRedrawRay();
}

void PupilInfo::RedrawWaitSignal()
{
  // This object must NOT be locked or rendering will deadlock.

  mDirectDumpCond.Lock();
  EmitRedrawRay(true);
  mDirectDumpCond.Wait();
  mDirectDumpCond.Unlock();
}

void PupilInfo::DumpImage(const TString& filename, Int_t n_tiles, Bool_t copy_p)
{
  EmitDumpImageRay(filename, n_tiles, copy_p, false);
}

void PupilInfo::DumpImageWaitSignal(const TString& filename, Int_t n_tiles,
                                    Bool_t copy_p)
{
  // This object must NOT be locked or rendering will deadlock.

  mDirectDumpCond.Lock();
  EmitDumpImageRay(filename, n_tiles, copy_p, true);
  mDirectDumpCond.Wait();
  mDirectDumpCond.Unlock();
}

void PupilInfo::ReceiveDumpFinishedSignal()
{
  // This is called from Pupil when rendering is finished.

  mDirectDumpCond.Lock();
  mDirectDumpCond.Signal();
  mDirectDumpCond.Unlock();
}
 PupilInfo.cxx:1
 PupilInfo.cxx:2
 PupilInfo.cxx:3
 PupilInfo.cxx:4
 PupilInfo.cxx:5
 PupilInfo.cxx:6
 PupilInfo.cxx:7
 PupilInfo.cxx:8
 PupilInfo.cxx:9
 PupilInfo.cxx:10
 PupilInfo.cxx:11
 PupilInfo.cxx:12
 PupilInfo.cxx:13
 PupilInfo.cxx:14
 PupilInfo.cxx:15
 PupilInfo.cxx:16
 PupilInfo.cxx:17
 PupilInfo.cxx:18
 PupilInfo.cxx:19
 PupilInfo.cxx:20
 PupilInfo.cxx:21
 PupilInfo.cxx:22
 PupilInfo.cxx:23
 PupilInfo.cxx:24
 PupilInfo.cxx:25
 PupilInfo.cxx:26
 PupilInfo.cxx:27
 PupilInfo.cxx:28
 PupilInfo.cxx:29
 PupilInfo.cxx:30
 PupilInfo.cxx:31
 PupilInfo.cxx:32
 PupilInfo.cxx:33
 PupilInfo.cxx:34
 PupilInfo.cxx:35
 PupilInfo.cxx:36
 PupilInfo.cxx:37
 PupilInfo.cxx:38
 PupilInfo.cxx:39
 PupilInfo.cxx:40
 PupilInfo.cxx:41
 PupilInfo.cxx:42
 PupilInfo.cxx:43
 PupilInfo.cxx:44
 PupilInfo.cxx:45
 PupilInfo.cxx:46
 PupilInfo.cxx:47
 PupilInfo.cxx:48
 PupilInfo.cxx:49
 PupilInfo.cxx:50
 PupilInfo.cxx:51
 PupilInfo.cxx:52
 PupilInfo.cxx:53
 PupilInfo.cxx:54
 PupilInfo.cxx:55
 PupilInfo.cxx:56
 PupilInfo.cxx:57
 PupilInfo.cxx:58
 PupilInfo.cxx:59
 PupilInfo.cxx:60
 PupilInfo.cxx:61
 PupilInfo.cxx:62
 PupilInfo.cxx:63
 PupilInfo.cxx:64
 PupilInfo.cxx:65
 PupilInfo.cxx:66
 PupilInfo.cxx:67
 PupilInfo.cxx:68
 PupilInfo.cxx:69
 PupilInfo.cxx:70
 PupilInfo.cxx:71
 PupilInfo.cxx:72
 PupilInfo.cxx:73
 PupilInfo.cxx:74
 PupilInfo.cxx:75
 PupilInfo.cxx:76
 PupilInfo.cxx:77
 PupilInfo.cxx:78
 PupilInfo.cxx:79
 PupilInfo.cxx:80
 PupilInfo.cxx:81
 PupilInfo.cxx:82
 PupilInfo.cxx:83
 PupilInfo.cxx:84
 PupilInfo.cxx:85
 PupilInfo.cxx:86
 PupilInfo.cxx:87
 PupilInfo.cxx:88
 PupilInfo.cxx:89
 PupilInfo.cxx:90
 PupilInfo.cxx:91
 PupilInfo.cxx:92
 PupilInfo.cxx:93
 PupilInfo.cxx:94
 PupilInfo.cxx:95
 PupilInfo.cxx:96
 PupilInfo.cxx:97
 PupilInfo.cxx:98
 PupilInfo.cxx:99
 PupilInfo.cxx:100
 PupilInfo.cxx:101
 PupilInfo.cxx:102
 PupilInfo.cxx:103
 PupilInfo.cxx:104
 PupilInfo.cxx:105
 PupilInfo.cxx:106
 PupilInfo.cxx:107
 PupilInfo.cxx:108
 PupilInfo.cxx:109
 PupilInfo.cxx:110
 PupilInfo.cxx:111
 PupilInfo.cxx:112
 PupilInfo.cxx:113
 PupilInfo.cxx:114
 PupilInfo.cxx:115
 PupilInfo.cxx:116
 PupilInfo.cxx:117
 PupilInfo.cxx:118
 PupilInfo.cxx:119
 PupilInfo.cxx:120
 PupilInfo.cxx:121
 PupilInfo.cxx:122
 PupilInfo.cxx:123
 PupilInfo.cxx:124
 PupilInfo.cxx:125
 PupilInfo.cxx:126
 PupilInfo.cxx:127
 PupilInfo.cxx:128
 PupilInfo.cxx:129
 PupilInfo.cxx:130
 PupilInfo.cxx:131
 PupilInfo.cxx:132
 PupilInfo.cxx:133
 PupilInfo.cxx:134
 PupilInfo.cxx:135
 PupilInfo.cxx:136
 PupilInfo.cxx:137
 PupilInfo.cxx:138
 PupilInfo.cxx:139
 PupilInfo.cxx:140
 PupilInfo.cxx:141
 PupilInfo.cxx:142
 PupilInfo.cxx:143
 PupilInfo.cxx:144
 PupilInfo.cxx:145
 PupilInfo.cxx:146
 PupilInfo.cxx:147
 PupilInfo.cxx:148
 PupilInfo.cxx:149
 PupilInfo.cxx:150
 PupilInfo.cxx:151
 PupilInfo.cxx:152
 PupilInfo.cxx:153
 PupilInfo.cxx:154
 PupilInfo.cxx:155
 PupilInfo.cxx:156
 PupilInfo.cxx:157
 PupilInfo.cxx:158
 PupilInfo.cxx:159
 PupilInfo.cxx:160
 PupilInfo.cxx:161
 PupilInfo.cxx:162
 PupilInfo.cxx:163
 PupilInfo.cxx:164
 PupilInfo.cxx:165
 PupilInfo.cxx:166
 PupilInfo.cxx:167
 PupilInfo.cxx:168
 PupilInfo.cxx:169
 PupilInfo.cxx:170
 PupilInfo.cxx:171
 PupilInfo.cxx:172
 PupilInfo.cxx:173
 PupilInfo.cxx:174
 PupilInfo.cxx:175
 PupilInfo.cxx:176
 PupilInfo.cxx:177
 PupilInfo.cxx:178
 PupilInfo.cxx:179
 PupilInfo.cxx:180
 PupilInfo.cxx:181
 PupilInfo.cxx:182
 PupilInfo.cxx:183
 PupilInfo.cxx:184
 PupilInfo.cxx:185
 PupilInfo.cxx:186
 PupilInfo.cxx:187
 PupilInfo.cxx:188
 PupilInfo.cxx:189
 PupilInfo.cxx:190
 PupilInfo.cxx:191
 PupilInfo.cxx:192
 PupilInfo.cxx:193
 PupilInfo.cxx:194
 PupilInfo.cxx:195
 PupilInfo.cxx:196
 PupilInfo.cxx:197
 PupilInfo.cxx:198
 PupilInfo.cxx:199
 PupilInfo.cxx:200
 PupilInfo.cxx:201
 PupilInfo.cxx:202
 PupilInfo.cxx:203
 PupilInfo.cxx:204
 PupilInfo.cxx:205
 PupilInfo.cxx:206
 PupilInfo.cxx:207
 PupilInfo.cxx:208
 PupilInfo.cxx:209
 PupilInfo.cxx:210
 PupilInfo.cxx:211
 PupilInfo.cxx:212
 PupilInfo.cxx:213
 PupilInfo.cxx:214
 PupilInfo.cxx:215
 PupilInfo.cxx:216
 PupilInfo.cxx:217
 PupilInfo.cxx:218
 PupilInfo.cxx:219
 PupilInfo.cxx:220
 PupilInfo.cxx:221
 PupilInfo.cxx:222
 PupilInfo.cxx:223
 PupilInfo.cxx:224
 PupilInfo.cxx:225
 PupilInfo.cxx:226
 PupilInfo.cxx:227
 PupilInfo.cxx:228
 PupilInfo.cxx:229
 PupilInfo.cxx:230
 PupilInfo.cxx:231
 PupilInfo.cxx:232
 PupilInfo.cxx:233
 PupilInfo.cxx:234
 PupilInfo.cxx:235
 PupilInfo.cxx:236
 PupilInfo.cxx:237
 PupilInfo.cxx:238
 PupilInfo.cxx:239
 PupilInfo.cxx:240
 PupilInfo.cxx:241
 PupilInfo.cxx:242
 PupilInfo.cxx:243
 PupilInfo.cxx:244
 PupilInfo.cxx:245
 PupilInfo.cxx:246
 PupilInfo.cxx:247
 PupilInfo.cxx:248
 PupilInfo.cxx:249
 PupilInfo.cxx:250
 PupilInfo.cxx:251
 PupilInfo.cxx:252
 PupilInfo.cxx:253
 PupilInfo.cxx:254
 PupilInfo.cxx:255
 PupilInfo.cxx:256
 PupilInfo.cxx:257
 PupilInfo.cxx:258
 PupilInfo.cxx:259
 PupilInfo.cxx:260
 PupilInfo.cxx:261
 PupilInfo.cxx:262
 PupilInfo.cxx:263
 PupilInfo.cxx:264
 PupilInfo.cxx:265
 PupilInfo.cxx:266
 PupilInfo.cxx:267
 PupilInfo.cxx:268
 PupilInfo.cxx:269
 PupilInfo.cxx:270
 PupilInfo.cxx:271
 PupilInfo.cxx:272
 PupilInfo.cxx:273
 PupilInfo.cxx:274
 PupilInfo.cxx:275
 PupilInfo.cxx:276
 PupilInfo.cxx:277
 PupilInfo.cxx:278
 PupilInfo.cxx:279
 PupilInfo.cxx:280
 PupilInfo.cxx:281
 PupilInfo.cxx:282
 PupilInfo.cxx:283
 PupilInfo.cxx:284
 PupilInfo.cxx:285
 PupilInfo.cxx:286
 PupilInfo.cxx:287
 PupilInfo.cxx:288
 PupilInfo.cxx:289
 PupilInfo.cxx:290
 PupilInfo.cxx:291
 PupilInfo.cxx:292
 PupilInfo.cxx:293
 PupilInfo.cxx:294
 PupilInfo.cxx:295
 PupilInfo.cxx:296
 PupilInfo.cxx:297
 PupilInfo.cxx:298
 PupilInfo.cxx:299
 PupilInfo.cxx:300
 PupilInfo.cxx:301
 PupilInfo.cxx:302
 PupilInfo.cxx:303
 PupilInfo.cxx:304
 PupilInfo.cxx:305
 PupilInfo.cxx:306
 PupilInfo.cxx:307
 PupilInfo.cxx:308
 PupilInfo.cxx:309
 PupilInfo.cxx:310
 PupilInfo.cxx:311
 PupilInfo.cxx:312
 PupilInfo.cxx:313
 PupilInfo.cxx:314
 PupilInfo.cxx:315
 PupilInfo.cxx:316
 PupilInfo.cxx:317
 PupilInfo.cxx:318
 PupilInfo.cxx:319
 PupilInfo.cxx:320
 PupilInfo.cxx:321
 PupilInfo.cxx:322
 PupilInfo.cxx:323
 PupilInfo.cxx:324
 PupilInfo.cxx:325
 PupilInfo.cxx:326
 PupilInfo.cxx:327
 PupilInfo.cxx:328
 PupilInfo.cxx:329
 PupilInfo.cxx:330
 PupilInfo.cxx:331
 PupilInfo.cxx:332
 PupilInfo.cxx:333
 PupilInfo.cxx:334
 PupilInfo.cxx:335
 PupilInfo.cxx:336
 PupilInfo.cxx:337
 PupilInfo.cxx:338
 PupilInfo.cxx:339
 PupilInfo.cxx:340
 PupilInfo.cxx:341
 PupilInfo.cxx:342
 PupilInfo.cxx:343
 PupilInfo.cxx:344
 PupilInfo.cxx:345
 PupilInfo.cxx:346
 PupilInfo.cxx:347
 PupilInfo.cxx:348
 PupilInfo.cxx:349
 PupilInfo.cxx:350
 PupilInfo.cxx:351
 PupilInfo.cxx:352
 PupilInfo.cxx:353
 PupilInfo.cxx:354
 PupilInfo.cxx:355
 PupilInfo.cxx:356
 PupilInfo.cxx:357
 PupilInfo.cxx:358
 PupilInfo.cxx:359
 PupilInfo.cxx:360
 PupilInfo.cxx:361
 PupilInfo.cxx:362
 PupilInfo.cxx:363
 PupilInfo.cxx:364
 PupilInfo.cxx:365
 PupilInfo.cxx:366
 PupilInfo.cxx:367
 PupilInfo.cxx:368
 PupilInfo.cxx:369
 PupilInfo.cxx:370
 PupilInfo.cxx:371
 PupilInfo.cxx:372
 PupilInfo.cxx:373
 PupilInfo.cxx:374
 PupilInfo.cxx:375
 PupilInfo.cxx:376
 PupilInfo.cxx:377
 PupilInfo.cxx:378
 PupilInfo.cxx:379
 PupilInfo.cxx:380
 PupilInfo.cxx:381
 PupilInfo.cxx:382
 PupilInfo.cxx:383
 PupilInfo.cxx:384
 PupilInfo.cxx:385
 PupilInfo.cxx:386
 PupilInfo.cxx:387
 PupilInfo.cxx:388
 PupilInfo.cxx:389
 PupilInfo.cxx:390
 PupilInfo.cxx:391
 PupilInfo.cxx:392
 PupilInfo.cxx:393
 PupilInfo.cxx:394
 PupilInfo.cxx:395
 PupilInfo.cxx:396
 PupilInfo.cxx:397
 PupilInfo.cxx:398
 PupilInfo.cxx:399
 PupilInfo.cxx:400
 PupilInfo.cxx:401
 PupilInfo.cxx:402
 PupilInfo.cxx:403
 PupilInfo.cxx:404
 PupilInfo.cxx:405
 PupilInfo.cxx:406
 PupilInfo.cxx:407
 PupilInfo.cxx:408
 PupilInfo.cxx:409
 PupilInfo.cxx:410
 PupilInfo.cxx:411
 PupilInfo.cxx:412
 PupilInfo.cxx:413
 PupilInfo.cxx:414
 PupilInfo.cxx:415
 PupilInfo.cxx:416
 PupilInfo.cxx:417
 PupilInfo.cxx:418
 PupilInfo.cxx:419
 PupilInfo.cxx:420
 PupilInfo.cxx:421
 PupilInfo.cxx:422
 PupilInfo.cxx:423
 PupilInfo.cxx:424
 PupilInfo.cxx:425
 PupilInfo.cxx:426
 PupilInfo.cxx:427
 PupilInfo.cxx:428
 PupilInfo.cxx:429
 PupilInfo.cxx:430
 PupilInfo.cxx:431
 PupilInfo.cxx:432
 PupilInfo.cxx:433
 PupilInfo.cxx:434
 PupilInfo.cxx:435
 PupilInfo.cxx:436
 PupilInfo.cxx:437
 PupilInfo.cxx:438
 PupilInfo.cxx:439
 PupilInfo.cxx:440
 PupilInfo.cxx:441
 PupilInfo.cxx:442
 PupilInfo.cxx:443
 PupilInfo.cxx:444
 PupilInfo.cxx:445
 PupilInfo.cxx:446
 PupilInfo.cxx:447
 PupilInfo.cxx:448
 PupilInfo.cxx:449
 PupilInfo.cxx:450
 PupilInfo.cxx:451
 PupilInfo.cxx:452
 PupilInfo.cxx:453
 PupilInfo.cxx:454
 PupilInfo.cxx:455
 PupilInfo.cxx:456
 PupilInfo.cxx:457
 PupilInfo.cxx:458
 PupilInfo.cxx:459
 PupilInfo.cxx:460
 PupilInfo.cxx:461
 PupilInfo.cxx:462
 PupilInfo.cxx:463