home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.hitl.washington.edu
/
ftp.hitl.washington.edu.tar
/
ftp.hitl.washington.edu
/
pub
/
people
/
peter
/
ER
/
mmvr_demo.cxx
< prev
next >
Wrap
C/C++ Source or Header
|
1998-07-07
|
65KB
|
2,082 lines
/*
* mmvr_demo.cc -- Laparoscopy in the virtual ER
*
*/
//#define IR_DEMO // Enables extra features;
// use if running the demo on fast machine
// or a machine with lots of texture memory.
//#define O2_DEMO // Uses monocular viewer.
//#define VIDEO_DEMO // Include a live video window.
#define SAVE_FRAME_RATE // Cuts out a few extra objects to squeeze more frames.
#include <iostream.h>
#include <ctype.h>
#include <list.h>
#include <vector.h>
#include "mmvr_demo.h"
#include "v3dSystem.h"
#include "v3dUniverse.h"
#include "v3dViewpoint.h"
#include "v3dColor.h"
#include "v3dCollide.h"
#include "v3dLight.h"
#include "v3dKeyboard.h"
#include "v3dMouse.h"
#include "v3dMaterial.h"
#include "v3dButtonBox.h"
#include "ECG_driver.h"
#include "ECG_plot.h"
#include "ECG_heart_model.h"
#include "BP_driver.h"
#include "BP_plot.h"
#include "ImageSequenceViewer.h"
#include "ThickObject.h"
#include "SoundClient.h"
#include "ObjectSelectionTracker.h"
#include "PivotTracker.h"
#include "CmdLine.h"
#include "x3dITGoGo.h"
#ifdef VIDEO_DEMO
#include "VideoObject.h"
#endif // VIDEO_DEMO
////////////////////////////////////////////////////////////////////////////////
// Global objects in the simulation
////////////////////////////////////////////////////////////////////////////////
v3dUnit* Universe_Unit;
ImageSequenceViewer *User_1_Rep = 0; // Representations of user 1 and 2.
#ifdef VIDEO_DEMO
VideoObject *User_2_Rep = 0;
#else
ImageSequenceViewer *User_2_Rep = 0;
#endif // VIDEO_DEMO
ImageSequenceViewer *MRI_Viewer = 0; // Head MRI.
const int NUM_MRI_SERIES = 6;
int Num_MRI_Textures_Per_Series[8] = { 11, 26, 124, 28, 24, 28 };
int Current_MRI_Series = -1;
ObjectSelectionTracker *Selection_Tracker;
// Variables related to the user's hand.
v3dActionPoint *Hand_1_AP, *Hand_2_AP;
bool Use_2_Hands = false;
x3dInteractionTechnique *Current_IT_1 = 0, *Current_IT_2 = 0;
// Position and direction of the light in the room.
const v3dPos LIGHT_POS(1200, -800, -1000);
const v3dDir LIGHT_DIR( -.68, .48, .58);
// Starting positions and sizes of various objects in the world.
const v3dPos USER_2_START_POS (1.145, 0.828, -0.069);
v3dObject *Patient;
v3dObject *Inner_Abd;
v3dObject *Cyl1, *Cyl2, *Cyl3, *Cyl4, *HV_Floor;
#ifdef IR_DEMO
v3dObject *Mash_Floor;
v3dObject *Outside_Cyl1, *Outside_Cyl2, *Outside_Cyl3, *Outside_Cyl4,
*Outside_Floor;
v3dTexture *Outside_Tex_1, *Outside_Tex_2, *Outside_Tex_3, *Outside_Tex_4;
#endif // IR_DEMO;
v3dTexture *HV_1, *HV_2, *HV_3, *HV_4;
SoundClient *Sound_Client = 0;
////////////////////////////////////////////////////////////////////////////////
// Structures for storing object information
////////////////////////////////////////////////////////////////////////////////
typedef struct {
v3dObject* object;
int object_ID;
int object_type_ID;
bool is_interactive;
v3dPos original_position;
v3dOrient original_orientation;
} ObjectInfo;
typedef map<int, ObjectInfo*, less<int> > ObjectMap;
ObjectMap Objects; // The list of all objects in the simulation.
ObjectMap Interactive_Objects;
// The list of all interactive objects in the sim.
////////////////////////////////////////////////////////////////////////////////
// Window-related variables
////////////////////////////////////////////////////////////////////////////////
// The WTK windows to be used in the simulation.
WTwindow *WRight, *WLeft;
WTwindow *WLeft_Endo, *WRight_Endo;
// The viewpoint for the users.
v3dViewPoint *User_1_View, *User_2_View;
// The viewpoint for the endoscopic view.
v3dViewPoint *Endo_View;
// Window dimensions
const long WINDOW_WIDTH = 640;
const long WINDOW_HEIGHT = 480;
const long WINDOW_2_LEFT_POS = 642;
// Parameters for the endoscopic view window.
const int ENDO_VIEW_WIDTH = 200;
const int ENDO_VIEW_HEIGHT = 150;
const int ENDO_VIEW_BORDER = 10;
const int ENDO_WINDOW_MAX_POS = 3;
int Endo_Window_Current_Pos = 0;
long Endo_View_X[ENDO_WINDOW_MAX_POS] =
{ WINDOW_WIDTH - ENDO_VIEW_BORDER - 2 * ENDO_VIEW_WIDTH,
2 * ENDO_VIEW_BORDER,
WINDOW_WIDTH - ENDO_VIEW_BORDER - 2 * ENDO_VIEW_WIDTH };
// WINDOW_WIDTH + ENDO_VIEW_BORDER };
long Endo_View_Y[ENDO_WINDOW_MAX_POS] =
{ ENDO_VIEW_BORDER,
2 * ENDO_VIEW_BORDER,
WINDOW_HEIGHT + ENDO_VIEW_BORDER };
// WINDOW_HEIGHT - ENDO_VIEW_BORDER - ENDO_VIEW_HEIGHT }
const float ENDO_VIEW_ANGLE = 30 * PI / 180.0;
float Normal_View_Angle;
bool Show_User_2 = false, Show_Endo_View = true;
//////////////////////////////////////////////////////////////////////////////
// Global variables for the cauterization task.
//////////////////////////////////////////////////////////////////////////////
// The list of cautery objects.
//const int CAUTERY_NUM = 19;
const int CAUTERY_NUM = 15;
// The number of cauterization objects to load.
const int CAUTERY_TEXTURE_INDEX_START = 2;
// The index of the first cauterization object to load.
const int CAUTERY_TEXTURE_FLIP_NUM = 9;
// The index of the cauterization past which point all textures
// should be flipped.
int Cauterized_Count = 0;
// The number of cauterization objects the user has successfully
// cauterized.
typedef vector<v3dObject *> CauteryList;
CauteryList Cautery_Objects;
// The array of cautery objects.
typedef vector<bool> CauteryStatusList;
CauteryStatusList Cautery_Status;
// An array of cautery status flags.
// true = cauterized
// false = not cauterized
v3dCustomObject *Gall_Bladder;
v3dPos Gall_Bladder_Initial_Pos;
v3dOrient Gall_Bladder_Initial_Orient;
// The object that represents the gall bladder and its initial position
// and orientation. The gall bladder is hidden until the user
// successfully completes the cauterization task. After it is shown,
// the gall bladder can be picked up with the forceps.
v3dCustomObject *Under_Gall_Bladder;
// The object to be displayed under the gall bladder after the
// cauterization task has been successfully completed.
bool Gall_Bladder_Picked = false;
// True if the user has the gall bladder in the forceps,
// false otherwise.
PivotObject *Endoscope, *Forceps, *Electrode;
// The laparoscopic instruments in the simulation.
PivotTracker *Pivot_Tracker;
// The class responsible for handling manipulation of the laparoscopic
// instruments.
const v3dPos FORCEPS_INITIAL_POS (0.06, 0.7, -0.21);
const v3dPos ELECTRODE_INITIAL_POS (0.06, 0.75, 0.21);
const v3dPos ENDOSCOPE_INITIAL_POS (0.1, 0.75, 0);
// The initial positions of the instruments.
//////////////////////////////////////////////////////////////////////////////
// Function prototypes.
//////////////////////////////////////////////////////////////////////////////
// Function prototypes for event handlers.
v3dEventHandlerCallback key_press_handler, mouse_press_handler,
pivot_object_collide, pivot_object_collide_2_hands,
button_box_press_handler, button_box_down_handler,
object_select_handler, object_pick_handler, object_unpick_handler,
object_set_pivot_handler, object_unset_pivot_handler;
// Prototypes for cauterization-relation functions.
void cauterize();
void toggle_jaws(v3dActionPoint *hand_AP);
void move_hand_to_camera();
void correct_viewpoint(WTobject *obj);
void correct_viewpoint_CB(const v3dEventMessage *message);
float sens_coef(float v_l, float g_l, float res);
void calculate_extents (v3dObject *object,
v3dPos &min_point, v3dPos &max_point);
void user_2_vp_move_CB(const v3dEventMessage *message);
void endo_vp_move_CB(const v3dEventMessage *message);
bool load_MRI_series(int new_series_number);
void create_room();
void create_patient();
bool load_configuration_file(char *config_filename);
bool skip_comment(FILE *infile);
v3dObject* get_object_by_ID(int object_ID);
ECGDriver* get_ECG_driver(FILE* fp, int ECG_driver_type);
////////////////////////////////////////////////////////////////////////////////
// main
////////////////////////////////////////////////////////////////////////////////
main(int argc, char *argv[])
{
// Parse the command line options.
CmdLine *cl = CmdLine::getInstanceOf();
cl->makeCaseInsensitive();
cl->addArgument("config", "config.data",
"Specify target data configuration file");
cl->addArgument("serial", 2, "Serial port for Fastrak");
cl->addArgument("baud", 19200, "Baud rate for Fastrak");
cl->addArgument("buttons", "Use Chris Shaw's Polhemus button box");
cl->addArgument("stereo", "Run world in stereo view");
cl->addArgument("twousers", "Show second user view");
cl->addArgument("noendo", "Don't show endoscopic view");
cl->addArgument("twohands", "Use two hands");
cl->addArgument("usesound", "Add sound effects to the simulation");
cl->addArgument("soundhost", "siksik",
"Host computer of the sound server");
cl->addArgument("soundport", 2500,
"Socket port to use for the sound server");
if (!(cl->parse(argc, argv)))
return;
int serial_port_int = cl->queryInt("serial");
v3dSerial serial_port, button_serial_port;
if (serial_port_int == 2) {
serial_port = Serial_2;
button_serial_port = Serial_1;
} else if (serial_port_int == 1) {
serial_port = Serial_1;
button_serial_port = Serial_2;
} else {
fprintf (stderr, "*** Bad serial port: %d\n*** Using port 2\n",
serial_port_int);
serial_port = Serial_2;
button_serial_port = Serial_1;
}
int fastrak_baud = cl->queryInt("baud");
Use_2_Hands = cl->queryFlag("twohands");
Show_User_2 = cl->queryFlag("twousers");
Show_Endo_View = !cl->queryFlag("noendo");
bool use_button_box = cl->queryFlag("buttons"),
use_stereo = cl->queryFlag("stereo"),
use_sound = cl->queryFlag("usesound");
// Get the file name of the scenario configuration file.
char *config_file = cl->queryString("config");
// Initialize the sound client, if requested.
char *sound_host = cl->queryString("soundhost");
int sound_port = cl->queryInt("soundport");
if (use_sound) {
Sound_Client = new SoundClient();
fprintf (stderr, "Opening sound client to host %s port %d\n",
sound_host, sound_port);
if (!Sound_Client->OpenSocket(sound_host, sound_port)) {
fprintf (stderr, "Unable to open sound client\n");
delete Sound_Client;
Sound_Client = 0;
}
}
cout << "Initializing the system ...\n";
v3dSystem *system;
if (use_stereo)
system = v3dSystem::StartUp(v3dSystem::Stereo_2_Windows);
else
system = v3dSystem::StartUp(v3dSystem::Mono);
// Set initial background color to black
v3dUniverse *universe = system->GetCurrentUniverse();
universe->SetBgColor(v3dColor(0, 0, 0));
// Set ambient light
universe->SetAmbient(0.5);
cout << "Loading lights ... \n";
v3dLight light (LIGHT_POS, LIGHT_DIR, 1.0);
// Create the simulation room.
create_room();
// Set units to meters. We will consider the room to be 5 meters long.
Universe_Unit = new v3dUnit(Meter, universe->GetDimensions().max()/4.5);
v3dUnit &unit = *Universe_Unit;
;
// Create the patient.
create_patient();
// Add the endoscopic tools.
v3dPos center_pos = Inner_Abd->GetAbsolutePosition();
float center_obj_radius = Inner_Abd->GetSize().max() / 2.0;
Inner_Abd->Hide();
Forceps = new PivotObject(center_pos, center_obj_radius,
"Laparoscopy/forceps10.tube.obj",
"Laparoscopy/forceps10.handle.obj",
"Laparoscopy/forceps9.jaws.open.obj",
"Laparoscopy/forceps9.jaws.closed.obj");
Electrode = new PivotObject(center_pos, center_obj_radius,
"Laparoscopy/forceps10.tube.obj",
"Laparoscopy/forceps10.handle.obj",
"Laparoscopy/forceps9.cauterhead.obj");
Endoscope = new PivotObject(center_pos, center_obj_radius,
"Laparoscopy/endoscope2.tube.obj",
"Laparoscopy/endoscope2.head.obj");
v3dDim dim = Forceps->GetSize();
float factor = 0.08/unit.ConvToUnits(dim.max());
Forceps->Scale(factor);
Forceps->UpdatePosition(unit.ConvToPoints(FORCEPS_INITIAL_POS),
v3dOrient());
dim = Endoscope->GetSize();
factor = 0.08/unit.ConvToUnits(dim.max());
Endoscope->Scale(factor);
Endoscope->SetColor(v3dColor(160, 160, 190));
Endoscope->UpdatePosition(unit.ConvToPoints(ENDOSCOPE_INITIAL_POS),
v3dOrient());
dim = Electrode->GetSize();
factor = 0.08/unit.ConvToUnits(dim.max());
Electrode->Scale(factor);
Electrode->UpdatePosition(unit.ConvToPoints(ELECTRODE_INITIAL_POS),
v3dOrient());
// Read in the scenario configuration file.
if (!load_configuration_file(config_file)) {
fprintf(stderr, "*** Error loading configuration file\n***Exiting\n");
exit(1);
}
// Set up keyboard and mouse
v3dMouse mouse;
v3dAutoEventReceiver mouse_press_receiver (&mouse,
v3dMouse::MOUSE_BUTTON_PRESS,
&mouse_press_handler, 0);
mouse.SetSensitivity(0.005 * universe->GetRadius());
v3dKeyboard keyboard;
v3dAutoEventReceiver keyboard_receiver (&keyboard,
v3dKeyboard::KEYBOARD_KEY_PRESS,
&key_press_handler, 0);
// Set up button box.
v3dButtonBox *button_box;
v3dAutoEventReceiver *button_press_receiver, *button_down_receiver;
if (use_button_box) {
button_box = new v3dButtonBox(button_serial_port);
button_press_receiver = new v3dAutoEventReceiver(button_box,
v3dButtonBox::BUTTON_BOX_BUTTON_PRESS,
&button_box_press_handler, 0);
button_down_receiver = new v3dAutoEventReceiver(button_box,
v3dButtonBox::BUTTON_BOX_BUTTON_DOWN,
&button_box_down_handler, 0);
}
// Open the Polhemus Fastrak sensors.
v3dFastrak *view_sensor = new v3dFastrak(serial_port, 1, fastrak_baud);
v3dFastrak *hand_1_sensor = new v3dFastrak (serial_port, 2, fastrak_baud);
// Set up second hand tracker, if requested.
v3dFastrak *hand_2_sensor;
if (Use_2_Hands)
hand_2_sensor = new v3dFastrak (serial_port, 3, fastrak_baud);
// Get viewpoint from the Universe
User_1_View = universe->GetCurrentViewPoint();
User_1_View->AttachSensor (view_sensor);
float height = (Patient->GetSize()).max();
// CHANGE: Replace constants with numbers based on scale.
view_sensor->SetSensitivity (sens_coef(1.8, height, 0.015));
hand_1_sensor->SetSensitivity(sens_coef(1.8, height, 0.015));
if (Use_2_Hands)
hand_2_sensor->SetSensitivity(sens_coef(1.8, height, 0.015));
// Set parallax
User_1_View->SetParallax(2.6437);
User_1_View->Translate (unit.ConvToPoints(v3dPos (-.1, .5, -.2)),
Frame_World);
// Add representations of the two users to the scene.
v3dCustomObject *tom_head = new v3dCustomObject("tom1.nff");
User_1_Rep = new ImageSequenceViewer(tom_head, 1, false);
User_1_Rep->LoadNewSequence("ivan", ".rgb", 1, 1, false);
dim = User_1_Rep->GetSize();
factor = 0.5/unit.ConvToUnits(dim.max());
User_1_Rep->MoveAbsolute(User_1_View->GetAbsolutePosition());
User_1_Rep->SetAbsoluteOrientation(User_1_View->GetAbsoluteOrientation());
User_1_Rep->Scale(factor);
User_1_Rep->AttachSensor(view_sensor);
#ifdef VIDEO_DEMO
User_2_Rep = VideoObject::GetInstance();
dim = User_2_Rep->GetSize();
cerr << "Video size: " << dim << endl;
User_2_Rep->SetOrientation(v3dOrient(v3dDir(1,0,0)));
cerr << "Video start pos: " << unit.ConvToPoints(USER_2_START_POS) << endl;
cerr << "Video size: " << User_2_Rep->GetSize() << " Video scale factor: " << factor << endl;
#else // VIDEO_DEMO
User_2_Rep = new ImageSequenceViewer(tom_head, 1, false);
User_2_Rep->LoadNewSequence("tom", ".rgb", 1, 2, false);
User_2_Rep->SetOrientation(v3dOrient(v3dDir(-1,0,0)));
#endif // VIDEO_DEMO
dim = User_2_Rep->GetSize();
factor = 0.5/unit.ConvToUnits(dim.max());
User_2_Rep->Move(unit.ConvToPoints(USER_2_START_POS));
User_2_Rep->Scale(factor);
RestoreInfo::Add(User_2_Rep);
delete tom_head;
// Create the user's hands.
v3dCustomObject *hand_1_object = new v3dCustomObject("hand2.nff");
dim = hand_1_object->GetSize(); // get size of the hand in points
factor = 0.125/unit.ConvToUnits(dim.max());
hand_1_object->Scale(factor);
hand_1_object->MoveToOrigin();
v3dCustomObject *hand_2_object;
if (Use_2_Hands) {
hand_2_object = new v3dCustomObject("hand2.nff");
hand_2_object->Scale(factor);
hand_2_object->MoveToOrigin();
}
Hand_1_AP = new v3dActionPoint (hand_1_sensor, hand_1_object);
if (Use_2_Hands) {
Hand_2_AP = new v3dActionPoint (hand_2_sensor, hand_2_object);
}
move_hand_to_camera();
// Register the interactive objects in the simulation with the
// selection tracker.
Selection_Tracker = new ObjectSelectionTracker();
Selection_Tracker->RegisterActionPoint(Hand_1_AP);
Selection_Tracker->RegisterObject(User_2_Rep);
for (ObjectMap::iterator it = Interactive_Objects.begin();
it != Interactive_Objects.end(); ++it)
Selection_Tracker->RegisterObject((*it).second->object);
// Initialize the pivot object tracker.
Pivot_Tracker = new PivotTracker;
Pivot_Tracker->RegisterActionPoint(Hand_1_AP);
Pivot_Tracker->RegisterObject(Endoscope);
Pivot_Tracker->RegisterObject(Forceps);
Pivot_Tracker->RegisterObject(Electrode);
v3dAutoEventReceiver *object_select_receiver, *object_pick_receiver,
*object_unpick_receiver, *pivot_object_select_receiver,
*pivot_object_pick_receiver, *pivot_object_unpick_receiver,
*pivot_object_set_pivot_receiver,
*pivot_object_unset_pivot_receiver;
if (Sound_Client) {
object_select_receiver = new v3dAutoEventReceiver(
Selection_Tracker,
ObjectSelectionTracker::OBJECT_SELECT,
&object_select_handler, 0);
object_pick_receiver = new v3dAutoEventReceiver(
Selection_Tracker,
ObjectSelectionTracker::OBJECT_PICK,
&object_pick_handler, 0);
object_unpick_receiver = new v3dAutoEventReceiver(
Selection_Tracker,
ObjectSelectionTracker::OBJECT_UNPICK,
&object_unpick_handler, 0);
pivot_object_select_receiver = new v3dAutoEventReceiver(
Pivot_Tracker,
PivotTracker::OBJECT_SELECT,
&object_select_handler, 0);
pivot_object_pick_receiver = new v3dAutoEventReceiver(
Pivot_Tracker,
PivotTracker::OBJECT_PICK,
&object_pick_handler, 0);
pivot_object_unpick_receiver = new v3dAutoEventReceiver(
Pivot_Tracker,
PivotTracker::OBJECT_UNPICK,
&object_unpick_handler, 0);
pivot_object_set_pivot_receiver = new v3dAutoEventReceiver(
Pivot_Tracker,
PivotTracker::OBJECT_SET_PIVOT,
&object_set_pivot_handler, 0);
pivot_object_unset_pivot_receiver = new v3dAutoEventReceiver(
Pivot_Tracker,
PivotTracker::OBJECT_UNSET_PIVOT,
&object_unset_pivot_handler, 0);
}
if (Use_2_Hands) {
Selection_Tracker->RegisterActionPoint(Hand_2_AP);
Pivot_Tracker->RegisterActionPoint(Hand_2_AP);
}
// Hack to correct for offset of viewpoint sensor on headmount.
v3dAutoEventReceiver vp_correction_receiver (universe,
v3dUniverse::UNIVERSE_SIMULATION_LOOP, &correct_viewpoint_CB);
v3dObject* dummy = new v3dBlockObject(1,1,1);
WTobject_settask((WTobject *)dummy->GetHandler(), correct_viewpoint);
dummy->Hide();
WLeft = WTuniverse_getwindows();
WTwindow_setposition(WLeft, 1, 1, WINDOW_WIDTH, WINDOW_HEIGHT);
// Create the second user's viewpoint.
if (Show_User_2) {
WRight = WTwindow_new(WINDOW_2_LEFT_POS, 1, WINDOW_WIDTH,
WINDOW_HEIGHT, WTWINDOW_NOBORDER);
WTwindow_setrootnode(WRight, WTwindow_getrootnode(WLeft));
User_2_View = new v3dViewPoint();
WTwindow_setviewpoint(WRight,
(WTviewpoint *)User_2_View->GetImplement()->GetHandler());
}
v3dAutoEventReceiver user_2_vp_move (universe,
Show_User_2 ? v3dUniverse::UNIVERSE_SIMULATION_LOOP : 100,
&user_2_vp_move_CB, 0);
// Create the endoscopic views.
Endo_View = new v3dViewPoint();
Normal_View_Angle = WTwindow_getviewangle(WLeft);
if (Show_Endo_View) {
WLeft_Endo = WTwindow_new(
Endo_View_X[0], Endo_View_Y[0],
ENDO_VIEW_WIDTH, ENDO_VIEW_HEIGHT, WTWINDOW_NOBORDER);
WTwindow_setviewangle(WLeft_Endo, ENDO_VIEW_ANGLE);
WTwindow_setrootnode(WLeft_Endo, WTwindow_getrootnode(WLeft));
WTwindow_setviewpoint(WLeft_Endo,
(WTviewpoint *)Endo_View->GetImplement()->GetHandler());
if (Show_User_2) {
WRight_Endo = WTwindow_new(
WINDOW_2_LEFT_POS + WINDOW_WIDTH -
ENDO_VIEW_BORDER - ENDO_VIEW_WIDTH,
1 + WINDOW_HEIGHT - ENDO_VIEW_BORDER -
ENDO_VIEW_HEIGHT,
ENDO_VIEW_WIDTH, ENDO_VIEW_HEIGHT,
WTWINDOW_NOBORDER);
WTwindow_setviewangle(WRight_Endo, ENDO_VIEW_ANGLE);
WTwindow_setrootnode(WRight_Endo,
WTwindow_getrootnode(WLeft));
WTwindow_setviewpoint(WRight_Endo,
(WTviewpoint *)Endo_View->GetImplement()->GetHandler());
}
}
v3dAutoEventReceiver endo_vp_move (universe,
v3dUniverse::UNIVERSE_SIMULATION_LOOP, &endo_vp_move_CB, 0);
// Enter main loop
cout << "Starting an application!\n";
system->Go();
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// Create room
////////////////////////////////////////////////////////////////////////////////
// This function creates the room used in the simulation by loading four
// quarter-cylinders and covering them with ER textures.
void
create_room()
{
// Create cylindrical walls of the emergency room and apply
// the ER texture maps to them.
Cyl1 = new v3dCustomObject("cyl1.obj");
HV_1 = new v3dTexture("pan_2.rgb");
HV_1->SetLinearXYWrapMode(1.);
HV_1->ApplyToObject(*Cyl1);
Cyl2 = new v3dCustomObject("cyl2.obj");
HV_2 = new v3dTexture("pan_1.rgb");
HV_2->SetLinearXYWrapMode(1.);
HV_2->ApplyToObject(*Cyl2);
Cyl3 = new v3dCustomObject("cyl3.obj");
HV_3 = new v3dTexture("pan_0.rgb");
HV_3->SetLinearXYWrapMode(1.);
HV_3->ApplyToObject(*Cyl3);
Cyl4 = new v3dCustomObject("cyl4.obj");
HV_4 = new v3dTexture("pan_3.rgb");
HV_4->SetLinearXYWrapMode(1.);
HV_4->ApplyToObject(*Cyl4);
HV_Floor = new v3dCustomObject("floor");
#ifdef IR_DEMO
Outside_Cyl1 = new v3dCustomObject("cyl1.obj");
Outside_Tex_1 = new v3dTexture("field.pan.2.rgb");
Outside_Tex_1->SetLinearXYWrapMode(1.);
Outside_Tex_1->ApplyToObject(*Outside_Cyl1);
Outside_Cyl2 = new v3dCustomObject("cyl2.obj");
Outside_Tex_2 = new v3dTexture("field.pan.1.rgb");
Outside_Tex_2->SetLinearXYWrapMode(1.);
Outside_Tex_2->ApplyToObject(*Outside_Cyl2);
Outside_Cyl3 = new v3dCustomObject("cyl3.obj");
Outside_Tex_3 = new v3dTexture("field.pan.0.rgb");
Outside_Tex_3->SetLinearXYWrapMode(1.);
Outside_Tex_3->ApplyToObject(*Outside_Cyl3);
Outside_Cyl4 = new v3dCustomObject("cyl4.obj");
Outside_Tex_4 = new v3dTexture("field.pan.3.rgb");
Outside_Tex_4->SetLinearXYWrapMode(1.);
Outside_Tex_4->ApplyToObject(*Outside_Cyl4);
Mash_Floor = new v3dCustomObject("mash_floor");
Mash_Floor->Hide();
Outside_Floor = new v3dCustomObject("outside_floor");
Outside_Floor->Hide();
Outside_Cyl1->Hide();
Outside_Cyl2->Hide();
Outside_Cyl3->Hide();
Outside_Cyl4->Hide();
#endif // IR_DEMO;
// Calculate the extents of the cylindrical walls, find the center,
// then move that center to (0, 0, 0).
v3dPos obj_center = Cyl1->GetAbsolutePosition();
v3dDim obj_size = Cyl1->GetSize();
v3dPos min_point = obj_center - (obj_size / 2),
max_point = obj_center + (obj_size / 2);
calculate_extents (Cyl2, min_point, max_point);
calculate_extents (Cyl3, min_point, max_point);
calculate_extents (Cyl4, min_point, max_point);
calculate_extents (HV_Floor, min_point, max_point);
obj_size = max_point - min_point;
obj_center = max_point + min_point;
obj_center /= 2;
// Make a placeholder object to glue the walls and floor together.
v3dBlockObject *uni_box = new v3dBlockObject (obj_size);
uni_box->MoveAbsolute(obj_center);
uni_box->Hide();
uni_box->Add(Cyl1);
uni_box->Add(Cyl2);
uni_box->Add(Cyl3);
uni_box->Add(Cyl4);
uni_box->Add(HV_Floor);
uni_box->MoveAbsolute(v3dPos(0, 0, 0));
#ifdef IR_DEMO
v3dBlockObject *outside_box = new v3dBlockObject(obj_size);
outside_box->MoveAbsolute(obj_center);
outside_box->Hide();
outside_box->Add(Outside_Cyl1);
outside_box->Add(Outside_Cyl2);
outside_box->Add(Outside_Cyl3);
outside_box->Add(Outside_Cyl4);
outside_box->Add(Outside_Floor);
outside_box->MoveAbsolute(v3dPos(0, 0, 0));
#endif // IR_DEMO
// Scale the room up around the patient.
Cyl1->Scale(130, v3dPos(0, 0, 0));
Cyl2->Scale(130, v3dPos(0, 0, 0));
Cyl3->Scale(130, v3dPos(0, 0, 0));
Cyl4->Scale(130, v3dPos(0, 0, 0));
HV_Floor->Scale(130, v3dPos(0, 0, 0));
#ifdef IR_DEMO
Mash_Floor->Scale(130, v3dPos(0, 0, 0));
Outside_Cyl1->Scale(1.3, v3dPos(0, 0, 0));
Outside_Cyl2->Scale(1.3, v3dPos(0, 0, 0));
Outside_Cyl3->Scale(1.3, v3dPos(0, 0, 0));
Outside_Cyl4->Scale(1.3, v3dPos(0, 0, 0));
Outside_Floor->Scale(1.3, v3dPos(0, 0, 0));
// Stretch the room even more for the outside textures.
Outside_Cyl1->Scale(v3dVector (260, 130, 260), v3dPos(0, 0, 0));
Outside_Cyl2->Scale(v3dVector (260, 130, 260), v3dPos(0, 0, 0));
Outside_Cyl3->Scale(v3dVector (260, 130, 260), v3dPos(0, 0, 0));
Outside_Cyl4->Scale(v3dVector (260, 130, 260), v3dPos(0, 0, 0));
Outside_Floor->Scale(v3dVector (260, 130, 260), v3dPos(0, 0, 0));
#endif // IR_DEMO
}
// Given an object and a previously-initialized min point and max point, this
// function determines if the extents of the object exceed the min or max
// points, and if so then the points are updated accordingly.
void
calculate_extents (v3dObject *object, v3dPos &min_point, v3dPos &max_point)
{
v3dPos obj_center = object->GetAbsolutePosition();
v3dDim obj_size = object->GetSize() / 2;
v3dPos obj_min = obj_center - obj_size,
obj_max = obj_center + obj_size;
if (obj_min.x() < min_point.x())
min_point.x(obj_min.x());
if (obj_min.y() < min_point.y())
min_point.y(obj_min.y());
if (obj_min.z() < min_point.z())
min_point.z(obj_min.z());
if (obj_max.x() > max_point.x())
max_point.x(obj_max.x());
if (obj_max.y() > max_point.y())
max_point.y(obj_max.y());
if (obj_max.z() > max_point.z())
max_point.z(obj_max.z());
}
////////////////////////////////////////////////////////////////////////////////
// Create patient
////////////////////////////////////////////////////////////////////////////////
// This function loads the models that make up the patient.
void
create_patient()
{
cout << "Load patient's body...\n";
// Patient = new v3dCustomObject("patient.nff");
Patient = new v3dCustomObject("body.obj");
Patient->SetColor(v3dColor(73, 74, 216));
v3dObject *head = new v3dCustomObject("patient_head.obj");
v3dObject *torso = new v3dCustomObject("torso4.obj");
v3dObject *inner_torso = new v3dCustomObject("torso4.inside.obj");
v3dObject *arms = new v3dCustomObject("arms.obj");
v3dObject *legs = new v3dCustomObject("legs_closed.obj");
v3dObject *patient_hf = new v3dCustomObject("patient_hf.obj");
Inner_Abd = new v3dCustomObject("sphere5.obj");
v3dObject *guts = new v3dCustomObject("Laparoscopy/guts.obj");
v3dObject *liver = new v3dCustomObject("Laparoscopy/liver.obj");
v3dObject *rightabd = new v3dCustomObject("Laparoscopy/rightabd.obj");
v3dObject *leftabd = new v3dCustomObject("Laparoscopy/leftabd.obj");
Gall_Bladder = new v3dCustomObject("Laparoscopy/gb.obj");
Gall_Bladder->Hide();
Under_Gall_Bladder = new v3dCustomObject("Laparoscopy/undergb.obj");
Under_Gall_Bladder->Hide();
// Set height of the patient to be 1.5 meters and move it 1 meter down.
v3dDim dim = Patient->GetSize();
float factor = 1.5/Universe_Unit->ConvToUnits(dim.max());
Patient->Scale(factor);
Patient->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 1.0, 0)));
head->Scale(factor, v3dPos(0,0,0));
head->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 1.0, 0)));
head->SetAbsoluteOrientation(v3dOrient(v3dDir(0, 1, 0)));
v3dTexture head_texture("peter3.rgb");
head_texture.SetLinearXYWrapMode(1.);
head_texture.ApplyToObject(*head);
patient_hf->Scale(factor, v3dPos(0,0,0));
patient_hf->Translate(Universe_Unit->ConvToPoints(
v3dDir(0.0, 1.00, 0)));
patient_hf->SetColor(v3dColor(222,170,147));
torso->Scale(factor, v3dPos(0, 0, 0));
torso->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 1.0, 0)));
torso->SetColor(v3dColor(73, 74, 216));
inner_torso->Scale(factor, v3dPos(0, 0, 0));
inner_torso->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 1.0, 0)));
inner_torso->SetColor(v3dColor(180, 112, 143));
arms->Scale(factor, v3dPos(0, 0, 0));
arms->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 1.0, 0)));
arms->SetColor(v3dColor(73, 74, 216));
legs->Scale(factor, v3dPos(0, 0, 0));
legs->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 1.0, 0)));
legs->SetColor(v3dColor(73, 74, 216));
Inner_Abd->Scale(factor, v3dPos(0, 0, 0));
Inner_Abd->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 1.0, 0)));
guts->Scale(factor, v3dPos(0, 0, 0));
guts->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 1.0, 0)));
v3dTexture guts_tex("Laparoscopy/guts.2048.jpg");
guts_tex.SetTransparency(true);
guts_tex.ApplyToObject(*guts);
liver->Scale(factor, v3dPos(0, 0, 0));
liver->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 1.0, 0)));
v3dTexture liver_tex("Laparoscopy/liver.1024.rgb");
liver_tex.SetTransparency(true);
liver_tex.ApplyToObject(*liver);
rightabd->Scale(factor, v3dPos(0, 0, 0));
rightabd->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 1.0, 0)));
v3dTexture rightabd_tex("Laparoscopy/rightabd.1024.rgb");
rightabd_tex.ApplyToObject(*rightabd);
leftabd->Scale(factor, v3dPos(0, 0, 0));
leftabd->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 1.0, 0)));
v3dTexture leftabd_tex("Laparoscopy/leftabd.1024.rgb");
leftabd_tex.ApplyToObject(*leftabd);
Gall_Bladder->Scale(factor, v3dPos(0, 0, 0));
Gall_Bladder->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 1.0, 0)));
Gall_Bladder_Initial_Pos = Gall_Bladder->GetAbsolutePosition();
Gall_Bladder_Initial_Orient = Gall_Bladder->GetAbsoluteOrientation();
v3dTexture Gall_Bladder_tex("Laparoscopy/gb.rgb");
Gall_Bladder_tex.SetTransparency(true);
Gall_Bladder_tex.ApplyToObject(*Gall_Bladder);
Under_Gall_Bladder->Scale(factor, v3dPos(0, 0, 0));
Under_Gall_Bladder->Translate(Universe_Unit->ConvToPoints(
v3dDir(0, 1.0, 0)));
v3dTexture Under_Gall_Bladder_tex("Laparoscopy/undergb.rgb");
Under_Gall_Bladder_tex.SetTransparency(true);
Under_Gall_Bladder_tex.ApplyToObject(*Under_Gall_Bladder);
// Load the cautery objects.
v3dTexture cautery_tex("Laparoscopy/cautery.rgb");
v3dTexture cautery_flip_tex("Laparoscopy/cautery_flip.rgb");
for (int i = CAUTERY_TEXTURE_INDEX_START;
i < CAUTERY_TEXTURE_INDEX_START + CAUTERY_NUM; ++i) {
char cautery_filename[20];
sprintf(cautery_filename, "Laparoscopy/cautery%d.obj", i);
v3dCustomObject *cautery_obj =
new v3dCustomObject(cautery_filename);
cautery_obj->Scale(factor, v3dPos(0, 0, 0));
cautery_obj->Translate(Universe_Unit->ConvToPoints(
v3dDir(0, 1.0, 0)));
cautery_obj->Hide();
if (i < CAUTERY_TEXTURE_FLIP_NUM)
cautery_tex.ApplyToObject(*cautery_obj);
else
cautery_flip_tex.ApplyToObject(*cautery_obj);
Cautery_Objects.push_back(cautery_obj);
Cautery_Status.push_back(false);
}
// Create an object information record for the patient.
ObjectInfo *patient_info = new ObjectInfo;
patient_info->object = Patient;
patient_info->original_position = Patient->GetAbsolutePosition();
patient_info->original_orientation = Patient->GetAbsoluteOrientation();
patient_info->is_interactive = false;
patient_info->object_ID = 1;
patient_info->object_type_ID = 0;
Objects[1] = patient_info;
Patient->Hide();
}
////////////////////////////////////////////////////////////////////////////////
// Decoration object initialization
////////////////////////////////////////////////////////////////////////////////
bool load_configuration_file(char *config_filename)
{
// Open the file.
FILE *fp;
if ((fp = fopen(config_filename, "r")) == NULL) {
// File not found, return false.
fprintf (stderr, "Error opening configuration file %s\n",
config_filename);
return false;
}
// Read in the number of object records.
int num_records;
if (!skip_comment(fp))
return false;
fscanf(fp, "%d\n", &num_records);
fprintf(stderr, "\n%d object records\n\n", num_records);
for (int i = 0; i < num_records; ++i) {
if (!skip_comment(fp))
return false;
ObjectInfo* object_record = new ObjectInfo;
// Read in the object record header.
int object_ID, object_type, interactivity_level,
pos_reference_frame;
fscanf(fp, "%d %d %d %d",
&object_ID, &object_type, &interactivity_level,
&pos_reference_frame);
fprintf(stderr, "Object %d:\n\tType %d\t%s\n", object_ID,
object_type, interactivity_level ? "Interactive"
: "Non-interactive");
object_record->object_ID = object_ID;
object_record->object_type_ID = object_type;
object_record->is_interactive =
interactivity_level ? true : false;
// Read in the positional data, if specified.
fprintf(stderr, "\tPosition: ");
float px, py, pz;
int rel_pos_obj_ID;
if (pos_reference_frame > 0) {
fscanf(fp, "%f %f %f", &px, &py, &pz);
fprintf(stderr, "%f %f %f", px, py, pz);
if (pos_reference_frame == 1) {
object_record->original_position =
Universe_Unit->ConvToPoints(
v3dPos(px, py, pz));
} else if (pos_reference_frame == 2) {
fscanf(fp, "%d", &rel_pos_obj_ID);
fprintf(stderr, " (relative to object %d)", rel_pos_obj_ID);
v3dObject *rel_object =
get_object_by_ID(rel_pos_obj_ID);
if (rel_object)
object_record->original_position =
rel_object->GetCoordSystem().LocalPosToAbsolute(Universe_Unit->ConvToPoints(v3dPos(px, py, pz)));
else
fprintf(stderr, "** Object %d not found **\n", rel_pos_obj_ID);
}
} else
fprintf(stderr, "not specified");
fprintf(stderr, "\n");
// Read in the orientation type and data, if specified.
int orient_type;
int rel_orient_obj_ID;
float ox, oy, oz, twist;
fscanf(fp, "%d", &orient_type);
fprintf(stderr, "\tOrientation: ");
switch (orient_type) {
case 0: // Don't orient
fprintf(stderr, "not specified\n");
break;
case 1: // Same as other object
{
fscanf(fp, "%d", &rel_orient_obj_ID);
fprintf(stderr, "Same as object %d\n",
rel_orient_obj_ID);
v3dObject *rel_object =
get_object_by_ID(rel_orient_obj_ID);
if (rel_object)
object_record->original_orientation =
rel_object->GetAbsoluteOrientation();
else
fprintf(stderr, "** Object %d not found **\n", rel_orient_obj_ID);
break;
}
case 2: // Direction
fscanf(fp, "%f %f %f", &ox, &oy, &oz);
fprintf(stderr, "Dir: %f %f %f\n", ox, oy, oz);
object_record->original_orientation =
v3dOrient(v3dDir(ox, oy, oz));
break;
case 3: // Direction and twist
fscanf(fp, "%f %f %f %f",
&ox, &oy, &oz, &twist);
fprintf(stderr, "Dir: %f %f %f Twist: %f\n",
ox, oy, oz, twist);
object_record->original_orientation =
v3dOrient(v3dDir(ox, oy, oz), twist);
break;
case 4: // Euler angles
fscanf(fp, "%f %f %f", &ox, &oy, &oz);
fprintf(stderr, "Angles: %f %f %f\n",
ox, oy, oz);
object_record->original_orientation =
v3dOrient(v3dEulerAngle(ox, oy, oz));
break;
default: // Unknown
fprintf(stderr,
"** Unknown orientation type: %d **\n",
orient_type);
break;
}
// Read in the size type and data, if specified.
int size_type;
float sx, sy, sz, size_factor;
fscanf(fp, "%d", &size_type);
fprintf(stderr, "\tSize: ");
switch (size_type) {
case 0: // Don't size
fprintf(stderr, "not specified\n");
break;
case 1: // Stretch to specified size
fscanf(fp, "%f %f %f", &sx, &sy, &sz);
fprintf(stderr, "%f %f %f\n", sx, sy, sz);
break;
case 2: // Scale longest axis to size
fscanf(fp, "%f", &size_factor);
fprintf(stderr, "Long axis: %f\n", size_factor);
break;
default: // Unknown
fprintf(stderr, "** Unknown size type: %d **\n",
size_type);
break;
}
// Finally, read in the object-specific data.
fprintf(stderr, "\tType: ");
object_record->object = 0;
switch (object_type) {
case 1: // Custom object
{
char object_filename[80];
fscanf(fp, "%s\n", &object_filename);
fprintf(stderr, "Custom object: %s\n",
object_filename);
object_record->object =
new v3dCustomObject(object_filename);
break;
}
case 2: // Thick object
{
int encased_obj_ID;
float thickness;
fscanf(fp, "%d %f",
&encased_obj_ID, &thickness);
fprintf(stderr, "Thick object: %d %d\n",
encased_obj_ID, thickness);
v3dObject *encased_object =
get_object_by_ID(encased_obj_ID);
if (encased_object)
object_record->object =
new ThickObject(encased_object,
Universe_Unit->ConvToPoints(
thickness));
else
fprintf(stderr, "** Object %d not found **\n", encased_obj_ID);
break;
}
case 3: // ECG plot
{
float dx, dy, dz;
int incr_num, ECG_driver_type;
fscanf(fp, "%f %f %f %d %d",
&dx, &dy, &dz, &incr_num,
&ECG_driver_type);
fprintf(stderr, "ECG plot: Size: %f %f %f\n\tIncrements: %d Driver type: %d\n",
dx, dy, dz, incr_num, ECG_driver_type);
ECGDriver *ECG_driver =
get_ECG_driver(fp, ECG_driver_type);
if (ECG_driver) {
object_record->object = new ECGPlot(
ECG_driver,
Universe_Unit->ConvToPoints(
v3dPos(dx, dy, dz)),
incr_num);
}
break;
}
case 4: // ECG heart model
{
int ECG_driver_type;
char AV_node_filename[80],
SA_node_filename[80],
atria_filename[80],
ventricles_filename[80],
atrial_bundles_filename[80],
ventricular_bundles_filename[80];
fscanf(fp, "%s %s %s %s %s %s %d",
&AV_node_filename,
&SA_node_filename,
&atria_filename,
&ventricles_filename,
&atrial_bundles_filename,
&ventricular_bundles_filename,
&ECG_driver_type);
fprintf(stderr, "ECG heart model: Files:\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\tDriver type: %d",
AV_node_filename,
SA_node_filename,
atria_filename,
ventricles_filename,
atrial_bundles_filename,
ventricular_bundles_filename,
ECG_driver_type);
ECGDriver *ECG_driver =
get_ECG_driver(fp, ECG_driver_type);
if (ECG_driver) {
object_record->object =
new ECGHeartModel(
ECG_driver,
AV_node_filename,
SA_node_filename,
atria_filename,
ventricles_filename,
atrial_bundles_filename,
ventricular_bundles_filename);
}
break;
}
case 5: // Simple image sequence viewer
{
char display_obj_filename[80],
texture_prefix[80], texture_suffix[80];
int transparency,
first_image_num, last_image_num;
fscanf(fp, "%s %d %s %s %d %d",
&display_obj_filename,
&transparency, &texture_prefix,
&texture_suffix, &first_image_num,
&last_image_num);
fprintf(stderr, "Simple image seqeunce viewer\n\tDisplay object: %s\n\tFirst file: %s%d%s\n\tLast file: %s%d%s\n\t%s\n",
display_obj_filename,
texture_prefix, first_image_num,
texture_suffix, texture_prefix,
last_image_num, texture_suffix,
transparency ? "Transparent" : "Opaque");
v3dObject *panel_obj =
new v3dCustomObject(
display_obj_filename);
object_record->object = new ImageSequenceViewer(
panel_obj, 1, false);
delete panel_obj;
((ImageSequenceViewer*)object_record->object)->
LoadNewSequence(texture_prefix,
texture_suffix, first_image_num,
last_image_num,
transparency ? true : false);
((ImageSequenceViewer*)object_record->object)->
Play();
break;
}
case 6: // MRI viewer
{
char display_obj_filename[80];
int num_panels;
fscanf(fp, "%s %d",
&display_obj_filename, &num_panels);
fprintf(stderr, "MRI viewer\n\tDisplay object: %s Panels: %d\n",
display_obj_filename, num_panels);
v3dObject *panel_obj =
new v3dCustomObject(
display_obj_filename);
MRI_Viewer = new ImageSequenceViewer(
panel_obj, num_panels);
object_record->object = MRI_Viewer;
delete panel_obj;
load_MRI_series(1);
break;
}
case 7: // Blood pressure plot
{
float dx, dy, dz;
int incr_num;
char BP_data_filename[80];
fscanf(fp, "%f %f %f %d %s",
&dx, &dy, &dz, &incr_num,
&BP_data_filename);
fprintf(stderr, "BP plot: Size: %f %f %f\n\tIncrements: %d\n\tData file: %s\n",
dx, dy, dz, incr_num, BP_data_filename);
object_record->object = new BPPlot(
new BPDriver(BP_data_filename),
Universe_Unit->ConvToPoints(
v3dDim(dx, dy, dz)),
incr_num);
break;
}
case 8: // VideoPanel
object_record->object =
VideoObject::GetInstance();
break;
default: // Unknown
fprintf(stderr,
"** Unknown object type: %d **\n",
object_type);
break;
}
// If the object was created, then move, orient, and scale it,
// and add it to the list of objects in the simulation.
if (object_record->object) {
// First, scale the object.
if (size_type == 1) {
object_record->object->Scale(
Universe_Unit->ConvToPoints(
v3dDim(sx, sy, sz)));
} else if (size_type == 2) {
object_record->object->Scale(
size_factor /
Universe_Unit->ConvToUnits(
object_record->object->GetSize().max()));
}
// Next, position the object.
if (pos_reference_frame)
object_record->object->MoveAbsolute(
object_record->original_position);
else
object_record->original_position =
object_record->object->GetAbsolutePosition();
// Next, orient the object.
if (orient_type)
object_record->object->SetAbsoluteOrientation(
object_record->original_orientation);
else
object_record->original_orientation =
object_record->object->GetAbsoluteOrientation();
// Finally, add the object record to the map of records.
Objects[object_ID] = object_record;
if (object_record->is_interactive)
Interactive_Objects[object_ID] = object_record;
} else {
fprintf(stderr, "\n\n*** Object %d not created ***\n\n",
object_ID);
delete object_record;
}
}
fclose(fp);
return true;
}
// Skips over blank lines and comments in the configuration file, i.e., lines
// that begin with "#".
// Returns true if there is something to be read, false if the EOF is reached.
bool
skip_comment(FILE *infile)
{
int curr;
do {
// Skip any whitespace.
do {
curr = getc(infile);
} while (!feof(infile) && isspace(curr));
if (curr == '#')
// Read to the end of the line.
while (!feof(infile) && ((curr = getc(infile)) != '\n'))
;
else
break;
} while (!feof(infile));
if (!feof(infile)) {
// Put the non-comment character back in the input stream.
ungetc(curr, infile);
return true;
} else
return false;
}
// Given an object ID, this function returns a pointer to the object by
// checking the object record map.
v3dObject*
get_object_by_ID(int object_ID)
{
ObjectMap::iterator finder = Objects.find(object_ID);
if (finder == Objects.end())
return 0;
else
return (*finder).second->object;
}
// Given a file pointer to an open configuration file and an ECG driver
// type, this function will read in the ECG driver parameters from the file
// and return a pointer to the driver.
ECGDriver*
get_ECG_driver(FILE* fp, int ECG_driver_type)
{
if (ECG_driver_type == 0) {
// Create a new ECG_driver.
char sequence_filename[80];
float min_val, max_val;
fscanf(fp, "%s %f %f", &sequence_filename,
&min_val, &max_val);
fprintf(stderr, "\tSequence file: %s\n\tMin value: %f Max value: %f\n",
sequence_filename, min_val, max_val);
return new ECGDriver(sequence_filename, min_val, max_val);
} else if ((ECG_driver_type == 1) || (ECG_driver_type == 2)) {
// Use driver from an ECG plot or an ECG heart model
int other_ECG_ID;
fscanf(fp, "%d", &other_ECG_ID);
fprintf(stderr, "\tOther ECG ID: %d\n", other_ECG_ID);
v3dObject* other_ECG = get_object_by_ID(other_ECG_ID);
if (!other_ECG) {
fprintf(stderr, "** ECG object %d not found **\n",
other_ECG_ID);
return 0;
}
if (ECG_driver_type == 1) {
return ((ECGPlot*)other_ECG)->GetECGDriver();
}
} else {
fprintf(stderr, "** Unknown ECG driver type: %d **\n",
ECG_driver_type);
return 0;
}
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Moves the hand action point to the position of the camera, then translates
// it by the hand camera offset.
void move_hand_to_camera ()
{
Hand_1_AP->MoveAbsolute(
v3dSystem::GetCurrentUniverse()->
GetCurrentViewPoint()->GetPosition());
if (Use_2_Hands)
Hand_2_AP->MoveAbsolute(Hand_1_AP->GetAbsolutePosition());
}
// This is a formula for calculating sensetivity of both sensors.
// it gives amount of virtual move in respond to the actual one
// v_l - length of the world in meters,
// g_l - legth of the world in dots,
// res - resolution of sensor in meters
float
sens_coef(float v_l, float g_l, float res)
{
return (g_l * res) / v_l;
}
////////////////////////////////////////////////////////////////////////////////
// Camera management
////////////////////////////////////////////////////////////////////////////////
// CHANGE: Replace constants with numbers based on scale.
//v3dVector off(0, 3, 0), noff(0, -3, 0);
//v3dVector off(0, 0.041, 0), noff(0, -0.041, 0);
v3dVector off(0, 0.05, 0), noff(0, -0.05, 0);
// Corect viewpoint move it UP!
void correct_viewpoint(WTobject *obj)
{
static bool first_correct = false;
static v3dVector u_noff = Universe_Unit->ConvToPoints(noff);
if(first_correct)
v3dSystem::GetCurrentUniverse()->GetCurrentViewPoint()->Translate(u_noff, Frame_VPoint);
else
first_correct = true;
}
// Corect viewpoint move it DOWN!
void correct_viewpoint_CB(const v3dEventMessage *message)
{
static v3dVector u_off = Universe_Unit->ConvToPoints(off);
v3dSystem::GetCurrentUniverse()->GetCurrentViewPoint()->Translate(u_off, Frame_VPoint);
}
// Move the viewpoint for user 2 to coincide with user 2's object
// representation.
void
user_2_vp_move_CB(const v3dEventMessage *message)
{
User_2_View->MoveAbsolute(User_2_Rep->GetAbsolutePosition());
User_2_View->SetAbsoluteOrientation(
User_2_Rep->GetAbsoluteOrientation());
User_2_View->Translate(v3dDir(0,0,5), Frame_VPoint);
}
// Move the viewpoint for the endoscope to coincide with the end of the scope.
void
endo_vp_move_CB(const v3dEventMessage *message)
{
v3dPos endo_pos;
Endo_View->MoveAbsolute(Endoscope->GetEndPosition());
Endo_View->SetDirection(
Endoscope->GetAbsoluteOrientation().GetDirection() * -1);
}
////////////////////////////////////////////////////////////////////////////////
// MRI viewer management
////////////////////////////////////////////////////////////////////////////////
bool
load_MRI_series(int new_series_number)
{
if (!MRI_Viewer)
return;
if (new_series_number > NUM_MRI_SERIES)
return false;
fprintf (stderr, "MRI series: %d # of images: %d\n", new_series_number+1,
Num_MRI_Textures_Per_Series[new_series_number]);
char MRI_file_prefix[80];
sprintf (MRI_file_prefix, "E6248/E6248S%dI", new_series_number+1);
Current_MRI_Series = new_series_number;
MRI_Viewer->LoadNewSequence(MRI_file_prefix, ".rgb", 1,
Num_MRI_Textures_Per_Series[Current_MRI_Series], false,
new_series_number + 1);
}
////////////////////////////////////////////////////////////////////////////////
// Sounds for various events
////////////////////////////////////////////////////////////////////////////////
void object_select_handler(const v3dEventMessage* message)
{
Sound_Client->SendSound("click1");
}
void object_pick_handler(const v3dEventMessage* message)
{
Sound_Client->SendSound("pick1");
}
void object_unpick_handler(const v3dEventMessage* message)
{
Sound_Client->SendSound("drop1");
}
void object_set_pivot_handler(const v3dEventMessage* message)
{
Sound_Client->SendSound("poke.wav");
}
void object_unset_pivot_handler(const v3dEventMessage* message)
{
Sound_Client->SendSound("boing.wav");
}
////////////////////////////////////////////////////////////////////////////////
// Swich user and endoscopic viewpoints.
////////////////////////////////////////////////////////////////////////////////
// Toggles windows between normal and endoscopic viewpoints.
void
switch_viewpoints()
{
static bool Endo_View_on = false;
if (!Endo_View_on) { // Switch to endoscopic view.
WTwindow_setviewpoint(WLeft,
(WTviewpoint *)Endo_View->GetImplement()->GetHandler());
WTwindow_setviewangle(WLeft, ENDO_VIEW_ANGLE);
if (Show_Endo_View) {
WTwindow_setviewpoint(WLeft_Endo,
(WTviewpoint *)User_1_View->GetImplement()->GetHandler());
WTwindow_setviewangle(WLeft_Endo, Normal_View_Angle);
}
if (Show_User_2) {
WTwindow_setviewpoint(WRight,
(WTviewpoint *)Endo_View->GetImplement()->GetHandler());
WTwindow_setviewangle(WRight, ENDO_VIEW_ANGLE);
if (Show_Endo_View) {
WTwindow_setviewpoint(WRight_Endo,
(WTviewpoint *)User_2_View->GetImplement()->GetHandler());
WTwindow_setviewangle(WRight_Endo, Normal_View_Angle);
}
}
Endo_View_on = true;
} else { // Switch back to normal view.
WTwindow_setviewpoint(WLeft,
(WTviewpoint *)User_1_View->GetImplement()->GetHandler());
WTwindow_setviewangle(WLeft, Normal_View_Angle);
if (Show_Endo_View) {
WTwindow_setviewpoint(WLeft_Endo,
(WTviewpoint *)Endo_View->GetImplement()->GetHandler());
WTwindow_setviewangle(WLeft_Endo, ENDO_VIEW_ANGLE);
}
if (Show_User_2) {
WTwindow_setviewpoint(WRight,
(WTviewpoint *)User_2_View->GetImplement()->GetHandler());
WTwindow_setviewangle(WRight, Normal_View_Angle);
if (Show_Endo_View) {
WTwindow_setviewpoint(WRight_Endo,
(WTviewpoint *)Endo_View->GetImplement()->GetHandler());
WTwindow_setviewangle(WRight_Endo, ENDO_VIEW_ANGLE);
}
}
Endo_View_on = false;
}
}
////////////////////////////////////////////////////////////////////////////////
// Mouse handler
////////////////////////////////////////////////////////////////////////////////
void mouse_press_handler(const v3dEventMessage *message)
{
v3dMouse::v3dMouseButtons button =
*(v3dMouse::v3dMouseButtons *) message->GetCallData();
if (button & v3dMouse::Mouse_L_Button) {
Selection_Tracker->TogglePick(Hand_1_AP);
Pivot_Tracker->TogglePick(Hand_1_AP);
} else if (button & v3dMouse::Mouse_R_Button) {
Selection_Tracker->TogglePick(Hand_1_AP);
Pivot_Tracker->TogglePick(Hand_1_AP);
} else if (button & v3dMouse::Mouse_M_Button) {
Selection_Tracker->ToggleHeadStabilization(Hand_1_AP);
Pivot_Tracker->TogglePivot(Hand_1_AP);
}
}
////////////////////////////////////////////////////////////////////////////////
// Polhemus button box handler
////////////////////////////////////////////////////////////////////////////////
void button_box_press_handler(const v3dEventMessage *message)
{
v3dButtonBoxButtons buttons
= *(v3dButtonBoxButtons *)message->GetCallData();
// Check buttons for hand 1.
if (buttons & v3dButtonBox::ButtonBox_Button_1) {
Selection_Tracker->TogglePick(Hand_1_AP);
Pivot_Tracker->TogglePick(Hand_1_AP);
} else if (buttons & v3dButtonBox::ButtonBox_Button_3) {
// Find if the cauterization tool is being held by
// this action point.
if (Sound_Client &&
(Pivot_Tracker->GetPickingActionPoint(Electrode) == Hand_1_AP))
Sound_Client->SendSound("bop");
fprintf(stderr, "%d out of %d cauterized\n", Cauterized_Count, CAUTERY_NUM);
toggle_jaws(Hand_1_AP);
} else if (buttons & v3dButtonBox::ButtonBox_Button_2) {
Selection_Tracker->ToggleHeadStabilization(Hand_1_AP);
Pivot_Tracker->TogglePivot(Hand_1_AP);
}
if (Use_2_Hands) {
// Check buttons for hand 2.
if (buttons & v3dButtonBox::ButtonBox_Button_4) {
Selection_Tracker->TogglePick(Hand_2_AP);
Pivot_Tracker->TogglePick(Hand_1_AP);
} else if (buttons & v3dButtonBox::ButtonBox_Button_6) {
// Find if the cauterization tool is being held by
// this action point.
if (Sound_Client &&
(Pivot_Tracker->GetPickingActionPoint(Electrode) == Hand_1_AP))
Sound_Client->SendSound("bop");
toggle_jaws(Hand_2_AP);
} else if (buttons & v3dButtonBox::ButtonBox_Button_5) {
Selection_Tracker->ToggleHeadStabilization(Hand_2_AP);
Pivot_Tracker->TogglePivot(Hand_2_AP);
}
}
}
void button_box_down_handler(const v3dEventMessage *message)
{
v3dButtonBoxButtons buttons
= *(v3dButtonBoxButtons *)message->GetCallData();
// Check buttons for hand 1.
if (buttons & v3dButtonBox::ButtonBox_Button_3) {
// Find if the cauterization tool is being held by
// this action point.
if ((Cauterized_Count < CAUTERY_NUM) &&
(Pivot_Tracker->GetPickingActionPoint(Electrode) == Hand_1_AP))
cauterize();
}
if (Use_2_Hands) {
// Check buttons for hand 2.
if (buttons & v3dButtonBox::ButtonBox_Button_6) {
// Find if the cauterization tool is being held by
// this action point.
if ((Cauterized_Count < CAUTERY_NUM) &&
(Pivot_Tracker->GetPickingActionPoint(Electrode) == Hand_2_AP))
cauterize();
}
}
}
////////////////////////////////////////////////////////////////////////////////
// Cauterization functions
////////////////////////////////////////////////////////////////////////////////
// Checks for collision with the ends of the cautization tool and the
// cautery objects. If there is a collision, then the cautery object is
// shown. If all cautery objects have been collided with, then the
// gall bladder object is shown and made available for moving.
void cauterize()
{
v3dObject *jaws = Electrode->GetExtraObject();
for (int i = 0; i < CAUTERY_NUM; ++i) {
if (!Cautery_Status[i] &&
Cautery_Objects[i]->Intersects(jaws)) {
fprintf(stderr, "Intersection with cautery %d\n", i);
Cautery_Objects[i]->Show();
Cautery_Status[i] = true;
++Cauterized_Count;
if (Sound_Client)
Sound_Client->SendSound("pop");
}
}
// See if all cauterizations have been made.
if (Cauterized_Count >= CAUTERY_NUM) {
Gall_Bladder->Show();
Under_Gall_Bladder->Show();
if (Sound_Client)
Sound_Client->SendSound("applause");
}
}
// This function is called to toggle the open and closed state of the forceps,
// and to pick up or drop the call bladder if it has been cauterized.
void toggle_jaws(v3dActionPoint *hand_AP)
{
static bool Forceps_Jaws_Open = true; // The forceps jaws start out open.
// Find if the forceps are being held by this action point.
if (Pivot_Tracker->GetPickingActionPoint(Forceps) != hand_AP)
return;
// Drop the gall bladder if it's picked up.
if (Gall_Bladder_Picked && !Forceps_Jaws_Open) {
Forceps->GetExtraObject()->Remove(Gall_Bladder);
Gall_Bladder_Picked = false;
}
// Toggle the jaws open/closed.
Forceps->SwitchExtraObjects();
Forceps_Jaws_Open = !Forceps_Jaws_Open;
// See if the gall bladder has been picked by the instrument tip.
if ((Cauterized_Count >= CAUTERY_NUM) && !Gall_Bladder_Picked
&& !Forceps_Jaws_Open)
if (Forceps->GetExtraObject()->Intersects(Gall_Bladder)) {
Forceps->GetExtraObject()->Add(Gall_Bladder);
Gall_Bladder_Picked = true;
}
}
////////////////////////////////////////////////////////////////////////////////
// Keyboard handler
////////////////////////////////////////////////////////////////////////////////
void key_press_handler(const v3dEventMessage *message)
{
int key = *(KEY_TYPE *) message->GetCallData();
v3dUniverse *universe = v3dSystem::GetCurrentUniverse();
v3dViewPoint *viewpoint = universe->GetCurrentViewPoint();
bool is_playing, is_reverse_playing;
switch (key) {
case WTKEY_LEFTARROW: case WTKEY_RIGHTARROW:
{
x3dGoGoIT *gogo_IT;
if (Current_IT_1) {
gogo_IT = (x3dGoGoIT *)Current_IT_1;
if (key == WTKEY_LEFTARROW) {
if (gogo_IT->GetWorkingRadius() > 5)
gogo_IT->SetWorkingRadius(gogo_IT->GetWorkingRadius()-1);
} else
gogo_IT->SetWorkingRadius (gogo_IT->GetWorkingRadius()+1);
cout << "Radius of working area: " << gogo_IT->GetWorkingRadius() << endl;
}
}
break;
case WTKEY_UPARROW: case WTKEY_DOWNARROW:
{
x3dGoGoIT *gogo_IT;
if (Current_IT_1) {
gogo_IT = (x3dGoGoIT *)Current_IT_1;
if (key == WTKEY_DOWNARROW) {
gogo_IT->SetNonLinearGainCoefficient (gogo_IT->GetNonLinearGainCoefficient()/1.1);
} else
gogo_IT->SetNonLinearGainCoefficient (gogo_IT->GetNonLinearGainCoefficient()*1.1);
cout << "Non-linear gain: " << gogo_IT->GetNonLinearGainCoefficient() << endl;
}
}
break;
case 'r': // Reset original size and position for all
// objects in the simulation.
{
RestoreInfo::RestoreAll();
Forceps->UpdatePosition(
Universe_Unit->ConvToPoints(FORCEPS_INITIAL_POS),
v3dOrient());
Endoscope->UpdatePosition(
Universe_Unit->ConvToPoints(ENDOSCOPE_INITIAL_POS),
v3dOrient());
Electrode->UpdatePosition(
Universe_Unit->ConvToPoints(ELECTRODE_INITIAL_POS),
v3dOrient());
for (ObjectMap::iterator it =
Interactive_Objects.begin();
it != Interactive_Objects.end(); ++it) {
ObjectInfo* object_info = (*it).second;
object_info->object->MoveAbsolute(
object_info->original_position);
object_info->object->SetAbsoluteOrientation(
object_info->original_orientation);
}
}
break;
case 'c': // Reset the cauterization procedure.
{
fprintf(stderr, "Reseting cauterization\n");
Cauterized_Count = 0;
if (Gall_Bladder_Picked) {
Forceps->GetExtraObject()->Remove(Gall_Bladder);
Forceps = 0;
Gall_Bladder_Picked = false;
}
Gall_Bladder->MoveAbsolute(Gall_Bladder_Initial_Pos);
Gall_Bladder->SetAbsoluteOrientation(Gall_Bladder_Initial_Orient);
Gall_Bladder->Hide();
Under_Gall_Bladder->Hide();
for (int i = 0; i < CAUTERY_NUM; ++i) {
Cautery_Objects[i]->Hide();
Cautery_Status[i] = false;
}
}
break;
case 'C': // Finish the cauterization procedure.
{
fprintf(stderr, "Finishing cauterization\n");
Cauterized_Count = CAUTERY_NUM;
for (int i = 0; i < CAUTERY_NUM; ++i) {
Cautery_Objects[i]->Show();
Cautery_Status[i] = true;
}
Gall_Bladder->Show();
Under_Gall_Bladder->Show();
if (Sound_Client)
Sound_Client->SendSound("applause");
}
break;
case 'g': // Toggle Go-Go interaction technique
if (Current_IT_1) {
cout << "Removing Go-Go interaction technique" << endl;
delete Current_IT_1;
Current_IT_1 = 0;
if (Use_2_Hands) {
delete Current_IT_2;
Current_IT_2 = 0;
}
} else {
cerr << "Using Go-Go interaction technique" << endl;
Current_IT_1 = new x3dGoGoIT(viewpoint, Hand_1_AP,
Universe_Unit->ConvToPoints(0.1793),
Universe_Unit->ConvToPoints(0.0414),
Universe_Unit->ConvToPoints(0.0414));
if (Use_2_Hands) {
Current_IT_2 = new x3dGoGoIT(viewpoint, Hand_2_AP,
Universe_Unit->ConvToPoints(0.1793),
Universe_Unit->ConvToPoints(0.0414),
Universe_Unit->ConvToPoints(0.0414));
}
}
break;
case 'h':
if (Use_2_Hands)
Hand_1_AP->MoveAbsolute(Hand_2_AP->GetAbsolutePosition());
break;
case 'H':
if (Use_2_Hands)
Hand_2_AP->MoveAbsolute(Hand_1_AP->GetAbsolutePosition());
break;
case '-': // Move hand down.
if (Current_IT_1)
((x3dGoGoIT *)Current_IT_1)->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 0.1, 0)));
else
Hand_1_AP->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 0.1, 0)));
if (Use_2_Hands)
if (Current_IT_2)
((x3dGoGoIT *)Current_IT_2)->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 0.1, 0)));
else
Hand_2_AP->Translate(Universe_Unit->ConvToPoints(v3dDir(0, 0.1, 0)));
break;
case '=': // Move hand up.
if (Current_IT_1)
((x3dGoGoIT *)Current_IT_1)->Translate(Universe_Unit->ConvToPoints(v3dDir(0, -0.1, 0)));
else
Hand_1_AP->Translate(Universe_Unit->ConvToPoints(v3dDir(0, -0.1, 0)));
if (Use_2_Hands)
if (Current_IT_2)
((x3dGoGoIT *)Current_IT_2)->Translate(Universe_Unit->ConvToPoints(v3dDir(0, -0.1, 0)));
else
Hand_2_AP->Translate(Universe_Unit->ConvToPoints(v3dDir(0, -0.1, 0)));
break;
case 't': // Toggle pivoting for selected pivot objects.
Pivot_Tracker->TogglePivot(Hand_1_AP);
break;
case 'e': // Switch between normal and endoscopic views.
switch_viewpoints();
break;
case 'w': // Move the endoscopic viewpoint window.
if (Show_Endo_View) {
Endo_Window_Current_Pos = (Endo_Window_Current_Pos + 1) % ENDO_WINDOW_MAX_POS;
WTwindow_setposition(WLeft_Endo,
Endo_View_X[Endo_Window_Current_Pos],
Endo_View_Y[Endo_Window_Current_Pos],
ENDO_VIEW_WIDTH, ENDO_VIEW_HEIGHT);
}
break;
case 'n': // Move to the next MRI series.
if (!MRI_Viewer)
return;
is_playing = MRI_Viewer->IsPlaying();
is_reverse_playing = MRI_Viewer->IsReversePlaying();
load_MRI_series((Current_MRI_Series + 1)
% NUM_MRI_SERIES);
if (is_playing)
MRI_Viewer->Play();
else if (is_reverse_playing)
MRI_Viewer->ReversePlay();
break;
case 'N': // Move to the previous MRI series.
if (!MRI_Viewer)
return;
is_playing = MRI_Viewer->IsPlaying();
if (Current_MRI_Series == 0)
load_MRI_series(NUM_MRI_SERIES - 1);
else
load_MRI_series((Current_MRI_Series - 1)
% NUM_MRI_SERIES);
if (is_playing)
MRI_Viewer->Play();
break;
case 'x': // Go to the next image in the MRI series.
if (!MRI_Viewer)
return;
MRI_Viewer->NextImage();
break;
case 'z': // Go to the previous image in the MRI series.
if (!MRI_Viewer)
return;
MRI_Viewer->PreviousImage();
break;
case 'a': // Decrease the number of panels.
if (!MRI_Viewer)
return;
MRI_Viewer->SetPanelNum(MRI_Viewer->GetPanelNum() - 1);
break;
case 's': // Increase the number of panels.
if (!MRI_Viewer)
return;
MRI_Viewer->SetPanelNum(MRI_Viewer->GetPanelNum() + 1);
break;
case '.':
if (!MRI_Viewer)
return;
MRI_Viewer->TogglePlay();
break;
case ',':
if (!MRI_Viewer)
return;
MRI_Viewer->ToggleReversePlay();
break;
case '/':
if (!MRI_Viewer)
return;
MRI_Viewer->Stop();
break;
case 'd': // Increase the delay;
// slow down the sequence animation.
if (!MRI_Viewer)
return;
MRI_Viewer->SetDelay(MRI_Viewer->GetDelay() + 1);
break;
case 'f': // Decrease the delay;
// speed up the sequence animation.
if (!MRI_Viewer)
return;
MRI_Viewer->SetDelay(MRI_Viewer->GetDelay() - 1);
break;
case 'v': // Make a copy of the current radiology image.
#if 0
{
if (!MRI_Viewer)
return;
v3dObject *new_image;
new_image = MRI_Viewer->CopyCurrentImage();
new_image->Translate(
v3dDir(Universe_Unit->ConvToUnits(0.1), 0, 0));
TempObject::Add(new_image, Hand_1_AP, &object_collide);
}
#endif
break;
case 'b': // Get rid of all the temporary objects.
TempObject::RemoveAll();
break;
case '[':
viewpoint->SetParallax(viewpoint->GetParallax() * 1.2);
cout << "Parallax: " << viewpoint->GetParallax()
<< endl;
break;
case ']':
viewpoint->SetParallax(viewpoint->GetParallax() / 1.2);
cout << "Parallax: " << viewpoint->GetParallax()
<< endl;
break;
case 'P': // Print the frame rate.
fprintf (stderr, "Frame rate: %f\n",
WTuniverse_framerate());
break;
#ifdef IR_DEMO
case '0':
case '1': case '2':
{
char *pan4, *pan1, *pan2, *pan3;
HV_Floor->Show();
Mash_Floor->Show();
Cyl1->Show();
Cyl2->Show();
Cyl3->Show();
Cyl4->Show();
Outside_Cyl1->Hide();
Outside_Cyl2->Hide();
Outside_Cyl3->Hide();
Outside_Cyl4->Hide();
Outside_Floor->Hide();
universe->SetBgColor(v3dColor(0,0,0));
if (key == '1') {
// load mash unit texture 1 for walls
pan1 = "mash.pan.0.rgb";
pan3 = "mash.pan.2.rgb";
pan2 = "mash.pan.1.rgb";
pan4 = "mash.pan.3.rgb";
HV_Floor->Hide();
Mash_Floor->Show();
} else if (key == '2') {
// load mash unit texture 1 for walls
pan1 = "m1panel0.rgb";
pan3 = "m1panel2.rgb";
pan2 = "m1panel1.rgb";
pan4 = "m1panel3.rgb";
HV_Floor->Hide();
Mash_Floor->Show();
} else if (key == '0') {
// load original ER texture for walls
pan1 = "pan_2.rgb";
pan3 = "pan_0.rgb";
pan2 = "pan_1.rgb";
pan4 = "pan_3.rgb";
Mash_Floor->Hide();
HV_Floor->Show();
}
delete(HV_1); HV_1 = new v3dTexture(pan1);
delete(HV_2); HV_2 = new v3dTexture(pan2);
delete(HV_3); HV_3 = new v3dTexture(pan3);
delete(HV_4); HV_4 = new v3dTexture(pan4);
HV_1->SetLinearXYWrapMode(1.);
HV_2->SetLinearXYWrapMode(1.);
HV_3->SetLinearXYWrapMode(1.);
HV_4->SetLinearXYWrapMode(1.);
HV_1->ApplyToObject(*Cyl1);
HV_2->ApplyToObject(*Cyl2);
HV_3->ApplyToObject(*Cyl3);
HV_4->ApplyToObject(*Cyl4);
}
break;
case '3':
HV_Floor->Hide();
Mash_Floor->Hide();
Cyl1->Hide();
Cyl2->Hide();
Cyl3->Hide();
Cyl4->Hide();
Outside_Cyl1->Show();
Outside_Cyl2->Show();
Outside_Cyl3->Show();
Outside_Cyl4->Show();
Outside_Floor->Show();
universe->SetBgColor(v3dColor(60,97,158));
break;
#endif // IR_DEMO
case 'q':
cout << "Quit \n";
exit(1);
break;
default:
cout << "\nWrong key! Press ? for help.\n";
}
}