Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

renderpf.C

Go to the documentation of this file.
00001 //----------------------------------------------------------------------
00002 //               The Motion Strategy Library (MSL)
00003 //----------------------------------------------------------------------
00004 //
00005 // Copyright (c) 1998-2000 Iowa State University and Steve LaValle.  
00006 // All Rights Reserved.
00007 // 
00008 // Permission to use, copy, and distribute this software and its 
00009 // documentation is hereby granted free of charge, provided that 
00010 // (1) it is not a component of a commercial product, and 
00011 // (2) this notice appears in all copies of the software and
00012 //     related documentation. 
00013 // 
00014 // Iowa State University and the author make no representations
00015 // about the suitability or fitness of this software for any purpose.  
00016 // It is provided "as is" without express or implied warranty.
00017 //----------------------------------------------------------------------
00018 
00019 #include <math.h>
00020 #include <stdlib.h>
00021 
00022 #include "renderpf.h"
00023 #include "defs.h"
00024 
00025 
00026 #define CONTROLPANEL_CENTER_X -0.22
00027 #define CONTROLPANEL_CENTER_Z -0.37
00028 #define CONTROLPANEL_WIDTH 0.2
00029 #define CONTROLPANEL_HEIGHT 0.1
00030 #define CONTROLPANEL_BAR_WIDTH 0.18
00031 #define CONTROLPANEL_BAR_HEIGHT 0.005
00032 #define CONTROLPAD_WIDTH 0.01
00033 #define CONTROLPAD_HEIGHT 0.02
00034 
00035 // Range of speeds: 2^-ANIMATING_SPEED_FACTOR to 2^ANIMATING_SPEED_FACTOR
00036 #define ANIMATING_SPEED_FACTOR 10
00037 
00038 
00040 //
00041 // RenderPerformer Class
00042 //
00044 
00045 SharedData* RenderPerformer::Shared;
00046 
00047 RenderPerformer::RenderPerformer(): Render()
00048 {
00049 
00050 }
00051 
00052 
00053 RenderPerformer::RenderPerformer(string filepath=""): Render(filepath)
00054 {
00055 
00056 }
00057 
00058 
00059 RenderPerformer::RenderPerformer(Scene *s, 
00060                                  string filepath): Render(s,filepath)
00061 {
00062 
00063 }
00064 
00065 
00066 
00067 void RenderPerformer::LoadEnvironment(pfGroup *env){
00068   list<string>::iterator object;
00069   pfNode *root;
00070 
00071   forall(object, EnvList){
00072     // Append to Performer search path
00073     if (!strstr((*object).c_str(),".")) {
00074       root = LoadNativeModel(*object, 0);
00075     }
00076     else {
00077       pfFilePath(FilePath.c_str());
00078       
00079       cout << "Loading " << *object << "\n"; 
00080       root = pfdLoadFile((*object).c_str());
00081       if (root == NULL)
00082         {
00083           pfExit();
00084           exit(-1);
00085         }
00086     }
00087     env->addChild(root);    
00088   }
00089 }
00090 
00091 
00092 
00093 void RenderPerformer::LoadBodies(pfGroup *bodies){
00094   list<string>::iterator object;
00095   pfNode *root;
00096   int i;
00097 
00098   i = 0;
00099   forall(object, BodyList) {
00100     if (!strstr((*object).c_str(),".")) {
00101       root = LoadNativeModel(*object, i+1);
00102     }
00103     else {
00104       // Append to Performer search path
00105       pfFilePath(FilePath.c_str());
00106       
00107       cout << "Loading " << *object << "\n";
00108       root = pfdLoadFile((*object).c_str());
00109       if (root == NULL)
00110         {
00111           pfExit();
00112           exit(-1);
00113         }
00114     }
00115     pfDCS *piece = new pfDCS;
00116     piece->addChild(root);
00117     bodies->addChild(piece);    
00118 
00119     i++;
00120   }
00121 }
00122 
00123 
00124 
00125 pfNode* RenderPerformer::LoadNativeModel(string file, int colorindex)
00126 {
00127   pfGeode *root = new pfGeode;
00128   pfGeoSet *gset = new pfGeoSet;
00129   list<MSLTriangle> trlist;
00130   list<MSLPolygon> plist;
00131   int i, num;
00132   double d1[3],d2[3], n[3];
00133   list<MSLTriangle>::iterator t;
00134 
00135   std::ifstream fin((FilePath + file).c_str());
00136   if (S->GeomDim == 2) {
00137     fin >> plist;
00138     trlist = PolygonsToTriangles(plist,5.0); // Defined in triangle.C
00139   }
00140   else
00141     fin >> trlist;
00142   fin.close();
00143 
00144   //cout << "number of triangles: " << num << endl; 
00145   num = trlist.size();
00146   pfVec3 *tri = new pfVec3[3*num];
00147   pfVec3 *norm = new pfVec3[num];
00148   pfVec4 *color = new pfVec4[1];
00149 
00150   i = 0;
00151   forall (t,trlist) {
00152     tri[3*i].set((float) (*t).p1.xcoord(), (float) (*t).p1.ycoord(), 
00153                  (float) (*t).p1.zcoord());
00154     tri[3*i+1].set((float) (*t).p2.xcoord(), (float) (*t).p2.ycoord(), 
00155                    (float) (*t).p2.zcoord());
00156     tri[3*i+2].set((float) (*t).p3.xcoord(), (float) (*t).p3.ycoord(), 
00157                    (float) (*t).p3.zcoord());
00158 
00159     d1[0] = (*t).p2.xcoord() - (*t).p1.xcoord();
00160     d1[1] = (*t).p2.ycoord() - (*t).p1.ycoord();
00161     d1[2] = (*t).p2.zcoord() - (*t).p1.zcoord();
00162     d2[0] = (*t).p3.xcoord() - (*t).p1.xcoord();
00163     d2[1] = (*t).p3.ycoord() - (*t).p1.ycoord();
00164     d2[2] = (*t).p3.zcoord() - (*t).p1.zcoord();
00165     NormCrossProduct(d1, d2, n);
00166     norm[i].set(n[0], n[1], n[2]);
00167     i++;
00168   }
00169 
00170   color[0].set( RGBRed[colorindex % RENDERCOLORS], 
00171                 RGBGreen[colorindex % RENDERCOLORS], 
00172                 RGBBlue[colorindex % RENDERCOLORS], 0.0f );
00173 
00174   gset->setAttr(PFGS_COORD3, PFGS_PER_VERTEX, tri, NULL);
00175   gset->setAttr(PFGS_NORMAL3, PFGS_PER_PRIM, norm, NULL);
00176   gset->setAttr(PFGS_COLOR4, PFGS_OVERALL, color, NULL);
00177   gset->setPrimType(PFGS_TRIS);
00178   gset->setNumPrims(num);
00179 
00180   //Specify Geometry State
00181   pfGeoState *gstate = new pfGeoState;
00182   gstate->setMode(PFSTATE_ENLIGHTING, PF_ON);
00183   gstate->setMode(PFSTATE_CULLFACE, PF_OFF);
00184   //gstate->setMode(PFSTATE_SHADEMODEL, PFSM_GOURAUD);
00185 
00186   // Using material
00187   pfMaterial *mat = new pfMaterial;
00188   mat->setColor(PFMTL_AMBIENT, 0.0f, 0.0f, 0.0f);
00189   mat->setColor(PFMTL_SPECULAR, 0.5f, 0.5f, 0.5f);
00190   mat->setShininess(10.0f);
00191   mat->setColorMode(PFMTL_BOTH, PFMTL_CMODE_AD);
00192   //mat->apply();
00193 
00194   gstate->setAttr(PFSTATE_FRONTMTL, mat);
00195   gset->setGState(gstate);
00196 
00197   //gset->setDrawMode(PFGS_FLATSHADE, PF_ON);
00198 
00199   root->addGSet(gset);
00200   
00201   return root;
00202 }
00203 
00204 
00205 void RenderPerformer::MakeBoundingBox(pfGeode *bound){
00206   pfGeoSet *gset = new pfGeoSet;
00207   pfVec3 *ver = new pfVec3[24];
00208   pfVec3 *norm = new pfVec3[12];
00209   pfVec4 *color = new pfVec4[1];
00210 
00211   ver[0].set(S->LowerWorld[0], S->LowerWorld[1], S->LowerWorld[2]);
00212   ver[1].set(S->UpperWorld[0], S->LowerWorld[1], S->LowerWorld[2]);
00213   norm[0].set(0.0,1.0,0.0);
00214 
00215   ver[2].set(S->LowerWorld[0], S->LowerWorld[1], S->LowerWorld[2]);
00216   ver[3].set(S->LowerWorld[0], S->UpperWorld[1], S->LowerWorld[2]);
00217   norm[1].set(0.0,1.0,0.0);
00218 
00219   ver[4].set(S->LowerWorld[0], S->LowerWorld[1], S->LowerWorld[2]);
00220   ver[5].set(S->LowerWorld[0], S->LowerWorld[1], S->UpperWorld[2]);
00221   norm[2].set(0.0,1.0,0.0);
00222 
00223   ver[6].set(S->UpperWorld[0], S->LowerWorld[1], S->LowerWorld[2]);
00224   ver[7].set(S->UpperWorld[0], S->UpperWorld[1], S->LowerWorld[2]);
00225   norm[3].set(0.0,1.0,0.0);
00226 
00227   ver[8].set(S->UpperWorld[0], S->LowerWorld[1], S->LowerWorld[2]);
00228   ver[9].set(S->UpperWorld[0], S->LowerWorld[1], S->UpperWorld[2]);
00229   norm[4].set(0.0,1.0,0.0);
00230 
00231   ver[10].set(S->LowerWorld[0], S->UpperWorld[1], S->LowerWorld[2]);
00232   ver[11].set(S->UpperWorld[0], S->UpperWorld[1], S->LowerWorld[2]);
00233   norm[5].set(0.0,1.0,0.0);
00234 
00235   ver[12].set(S->LowerWorld[0], S->UpperWorld[1], S->LowerWorld[2]);
00236   ver[13].set(S->LowerWorld[0], S->UpperWorld[1], S->UpperWorld[2]);
00237   norm[6].set(0.0,1.0,0.0);
00238 
00239   ver[14].set(S->LowerWorld[0], S->LowerWorld[1], S->UpperWorld[2]);
00240   ver[15].set(S->UpperWorld[0], S->LowerWorld[1], S->UpperWorld[2]);
00241   norm[7].set(0.0,1.0,0.0);
00242 
00243   ver[16].set(S->LowerWorld[0], S->LowerWorld[1], S->UpperWorld[2]);
00244   ver[17].set(S->LowerWorld[0], S->UpperWorld[1], S->UpperWorld[2]);
00245   norm[8].set(0.0,1.0,0.0);
00246 
00247   ver[18].set(S->UpperWorld[0], S->UpperWorld[1], S->UpperWorld[2]);
00248   ver[19].set(S->LowerWorld[0], S->UpperWorld[1], S->UpperWorld[2]);
00249   norm[9].set(0.0,1.0,0.0);
00250 
00251   ver[20].set(S->UpperWorld[0], S->UpperWorld[1], S->UpperWorld[2]);
00252   ver[21].set(S->UpperWorld[0], S->LowerWorld[1], S->UpperWorld[2]);
00253   norm[10].set(0.0,1.0,0.0);
00254 
00255   ver[22].set(S->UpperWorld[0], S->UpperWorld[1], S->UpperWorld[2]);
00256   ver[23].set(S->UpperWorld[0], S->UpperWorld[1], S->LowerWorld[2]);
00257   norm[11].set(0.0,1.0,0.0);
00258 
00259   color[0].set( 1, 0, 0, 0.0f );
00260 
00261   gset->setAttr(PFGS_COORD3, PFGS_PER_VERTEX, ver, NULL);
00262   gset->setAttr(PFGS_NORMAL3, PFGS_PER_PRIM, norm, NULL);
00263   gset->setAttr(PFGS_COLOR4, PFGS_OVERALL, color, NULL);
00264   gset->setPrimType(PFGS_LINES);
00265   gset->setNumPrims(12);
00266 
00267   //Specify Geometry State
00268   pfGeoState *gstate = new pfGeoState;
00269   gstate->setMode(PFSTATE_ENLIGHTING, PF_ON);
00270   gstate->setMode(PFSTATE_CULLFACE, PF_OFF);
00271   //gstate->setMode(PFSTATE_SHADEMODEL, PFSM_GOURAUD);
00272 
00273   // Using material
00274   pfMaterial *mat = new pfMaterial;
00275   mat->setColor(PFMTL_AMBIENT, 0.0f, 0.0f, 0.0f);
00276   mat->setColor(PFMTL_SPECULAR, 0.5f, 0.5f, 0.5f);
00277   mat->setShininess(10.0f);
00278   mat->setColorMode(PFMTL_BOTH, PFMTL_CMODE_AD);
00279   gstate->setAttr(PFSTATE_FRONTMTL, mat);
00280  
00281   gset->setGState(gstate);
00282 
00283   bound->addGSet(gset);
00284 }
00285 
00286 
00287 
00288 void RenderPerformer::MakeControlPanel(pfGroup *con, pfDCS *pad){
00289   pfGeode *geopad = new pfGeode;
00290   pfGeode *geo = new pfGeode;
00291   pfGeoSet *gset_frame = new pfGeoSet;
00292   pfGeoSet *gset_pad = new pfGeoSet;
00293 
00294   //Specify Geometry State
00295   pfGeoState *gstate = new pfGeoState;
00296   gstate->setMode(PFSTATE_TRANSPARENCY, PFTR_ON);
00297   gstate->setMode(PFSTATE_ENLIGHTING, PF_ON);
00298   gstate->setMode(PFSTATE_CULLFACE, PF_OFF);
00299 
00300   // Using material
00301   pfMaterial *mat = new pfMaterial;
00302   mat->setColor(PFMTL_AMBIENT, 0.0f, 0.0f, 0.0f);
00303   mat->setColor(PFMTL_SPECULAR, 0.5f, 0.5f, 0.5f);
00304   mat->setShininess(10.0f);
00305   mat->setColorMode(PFMTL_BOTH, PFMTL_CMODE_AD);
00306   gstate->setAttr(PFSTATE_FRONTMTL, mat);
00307 
00308   pfVec3 *tri = new pfVec3[4];
00309   pfVec3 *norm = new pfVec3[1];
00310   pfVec4 *color = new pfVec4[1];
00311 
00312   tri[0].set(-CONTROLPANEL_BAR_WIDTH + CONTROLPANEL_CENTER_X, -299.0,
00313              -CONTROLPANEL_BAR_HEIGHT + CONTROLPANEL_CENTER_Z);
00314   tri[1].set(-CONTROLPANEL_BAR_WIDTH + CONTROLPANEL_CENTER_X, -299.0,
00315              CONTROLPANEL_BAR_HEIGHT + CONTROLPANEL_CENTER_Z);
00316   tri[2].set(CONTROLPANEL_BAR_WIDTH + CONTROLPANEL_CENTER_X, -299.0,
00317              CONTROLPANEL_BAR_HEIGHT + CONTROLPANEL_CENTER_Z);
00318   tri[3].set(CONTROLPANEL_BAR_WIDTH + CONTROLPANEL_CENTER_X, -299.0,
00319              -CONTROLPANEL_BAR_HEIGHT + CONTROLPANEL_CENTER_Z);
00320   norm[0].set(0.0, -1.0, 0.0);
00321   color[0].set(0.5, 0.5, 1.0, 0.5f );
00322 
00323   gset_frame->setAttr(PFGS_COORD3, PFGS_PER_VERTEX, tri, NULL);
00324   gset_frame->setAttr(PFGS_NORMAL3, PFGS_PER_PRIM, norm, NULL);
00325   gset_frame->setAttr(PFGS_COLOR4, PFGS_PER_PRIM, color, NULL);
00326   gset_frame->setPrimType(PFGS_QUADS);
00327   gset_frame->setNumPrims(1);
00328   gset_frame->setGState(gstate);
00329   geo->addGSet(gset_frame);
00330 
00331   con->addChild(geo);
00332 
00333   // Draw Control Pad
00334   pfVec3 *tri1 = new pfVec3[4];
00335   pfVec3 *norm1 = new pfVec3[1];
00336   pfVec4 *color1 = new pfVec4[1];
00337 
00338   tri1[0].set(-CONTROLPAD_WIDTH + CONTROLPANEL_CENTER_X, -299.0,
00339               -CONTROLPAD_HEIGHT + CONTROLPANEL_CENTER_Z);
00340   tri1[1].set(-CONTROLPAD_WIDTH + CONTROLPANEL_CENTER_X, -299.0,
00341               CONTROLPAD_HEIGHT + CONTROLPANEL_CENTER_Z);
00342   tri1[2].set(CONTROLPAD_WIDTH + CONTROLPANEL_CENTER_X, -299.0,
00343               CONTROLPAD_HEIGHT + CONTROLPANEL_CENTER_Z);
00344   tri1[3].set(CONTROLPAD_WIDTH + CONTROLPANEL_CENTER_X, -299.0,
00345               -CONTROLPAD_HEIGHT + CONTROLPANEL_CENTER_Z);
00346   norm1[0].set(0.0, -1.0, 0.0);
00347   color1[0].set(0.0, 0.0, 1.0, 0.5);
00348 
00349   gset_pad->setAttr(PFGS_COORD3, PFGS_PER_VERTEX, tri1, NULL);
00350   gset_pad->setAttr(PFGS_NORMAL3, PFGS_PER_PRIM, norm1, NULL);
00351   gset_pad->setAttr(PFGS_COLOR4, PFGS_PER_PRIM, color1, NULL);
00352   gset_pad->setPrimType(PFGS_QUADS);
00353   gset_pad->setNumPrims(1);
00354   gset_pad->setGState(gstate);
00355   geopad->addGSet(gset_pad);
00356   
00357   pad->addChild(geopad);
00358 }
00359 
00360 
00361 
00362 
00363 
00364 void RenderPerformer::NormCrossProduct(double v1[3], double v2[3], 
00365                                        double out[3]) {
00366   out[0] = v1[1]*v2[2] - v1[2]*v2[1];
00367   out[1] = v1[2]*v2[0] - v1[0]*v2[2];
00368   out[2] = v1[0]*v2[1] - v1[1]*v2[0];
00369 
00370   GLfloat d = sqrt(out[0]*out[0] + out[1]*out[1] + out[2]*out[2]);
00371 
00372   out[0] /= d;
00373   out[1] /= d;
00374   out[2] /= d;
00375 }
00376 
00377 
00378 
00379 void RenderPerformer::GetCurrentMousePos(double &x, double &y){
00380   pfuGetMouse(Shared->Mouse);
00381   pfuMapMouseToChan(Shared->Mouse, Shared->Chan); // no matter mouse in chan or not return a value
00382   x = (double)Shared->Mouse->xchan;
00383   y = (double)Shared->Mouse->ychan;
00384 
00385   switch(Shared->Mouse->click){
00386   case 1: // click right
00387     Shared->HoldRightMouse = true;
00388     break;
00389   case 2: // click  middle
00390     Shared->HoldMiddleMouse = true;
00391     break;
00392   case 4: // click left
00393     Shared->HoldLeftMouse = true;
00394     break;
00395   default: // none
00396     break;
00397   }
00398   
00399   switch(Shared->Mouse->release){
00400   case 5: // release right and left
00401     Shared->HoldRightMouse = false;
00402     Shared->HoldLeftMouse = false;
00403     break;
00404   case 7: // release middle;
00405     Shared->HoldMiddleMouse = false;
00406     break;
00407   default: // none
00408     break;
00409   }     
00410 }
00411 
00412 
00413 void RenderPerformer::ShowCurrentAnimationFrame() {
00414   int i,j;
00415   MSLVector conf(6),oldframe;
00416   pfMatrix orientation, rot, delta_rot;
00417 
00418   if (AnimationActive)
00419     SetCurrentAnimationFrame();
00420   
00421   // Show the bodies in their proper places
00422   for (i = 0; i < S->NumBodies; i++) {
00423     // for each robot, first read its own configuration from FrameList
00424     for (j = 0; j < 6; j++)
00425       conf[j] = CurrentAnimationFrame[6*i+j];
00426     
00427     // update coordinate system
00428     orientation.makeIdent();
00429     rot.makeIdent();
00430     // rotate x
00431     delta_rot.makeRot(conf[3]*180.0/PI, 1.0, 0.0, 0.0);
00432     rot.postMult(delta_rot);
00433     // rotate y
00434     delta_rot.makeRot(conf[4]*180.0/PI, 0.0, 1.0, 0.0);
00435     rot.postMult(delta_rot);
00436     // rotate Z
00437     delta_rot.makeRot(conf[5]*180.0/PI, 0.0, 0.0, 1.0);
00438     rot.postMult(delta_rot);
00439     
00440     // Translate
00441     orientation.postTrans(rot, conf[0], conf[1], conf[2]);
00442     
00443     pfDCS *child_robot = pfGetChild(Shared->BodiesDCS, i);
00444     child_robot->setMat(orientation);
00445   }
00446 }
00447   
00448 
00449 void RenderPerformer::Init() {
00450   Render::Init();
00451 
00452   // Initialize Performer
00453   pfInit();
00454     
00455   // Use default multiprocessing mode based on number of processors.
00456   pfMultiprocess( PFMP_DEFAULT );
00457 
00458   // allocate shared before fork()'ing parallel processes  
00459   Shared = (SharedData*)pfMalloc(sizeof(SharedData), pfGetSharedArena());
00460  
00461   // Set Performer Search Path
00462   pfFilePath(FilePath.c_str());
00463 
00464   // Load all loader DSO's before pfConfig() forks 
00465   list<string>::iterator object;
00466 
00467   forall(object, EnvList) {
00468     if( strstr((*object).c_str(),".") ) 
00469       pfdInitConverter((*object).c_str());
00470   }
00471 
00472   forall(object, BodyList) {
00473     if( strstr((*object).c_str(),".") )
00474       pfdInitConverter((*object).c_str());
00475   }
00476 
00477   // initiate multi-processing mode set in pfMultiprocess call 
00478   // FORKs for Performer processes,  CULL and DRAW, etc. happen here.
00479   pfConfig();                   
00480   
00481   // Initiate performer utility library
00482   pfuInit();
00483 
00484   // Create Mouse and InputEvents
00485   Shared->Mouse = new pfuMouse;
00486   Shared->InputEvents = new pfuEventStream;
00487     
00488   // Create a new pfScene
00489   pfScene *PerfScene = new pfScene;
00490 
00491   // Load Environment and attach it to scene
00492   Shared->ShowCase = new pfSwitch;
00493   Shared->ControlPanel = new pfGroup;
00494   Shared->ControlPad = new pfDCS;
00495   Shared->WorldDCS = new pfDCS;
00496   Shared->WorkEnv = new pfSwitch;
00497   Shared->Env = new pfGroup;
00498   Shared->BodiesDCS = new pfDCS;
00499   Shared->BoundingBox = new pfGeode;
00500 
00501   LoadEnvironment(Shared->Env);
00502   LoadBodies(Shared->BodiesDCS);
00503 
00504   MakeBoundingBox(Shared->BoundingBox);
00505   MakeControlPanel(Shared->ControlPanel, Shared->ControlPad);
00506 
00507   Shared->ControlPanel->addChild(Shared->ControlPad);
00508   Shared->WorkEnv->addChild(Shared->Env);
00509   Shared->WorkEnv->addChild(Shared->BoundingBox);
00510   Shared->WorldDCS->addChild(Shared->WorkEnv);
00511   Shared->WorldDCS->addChild(Shared->BodiesDCS);
00512   Shared->ShowCase->addChild(Shared->WorldDCS);
00513   Shared->ShowCase->addChild(Shared->ControlPanel);  
00514   PerfScene->addChild(Shared->ShowCase);
00515 
00516   // Create a pfLightSource
00517   pfLightSource *sun = new pfLightSource;
00518   sun->setPos(-100.0, -100.0, 100.0, 1.0);
00519   PerfScene->addChild(sun);
00520   pfLightSource *sun2 = new pfLightSource;
00521   sun2->setPos(0.0, 0.0, 0.0, 0.0);
00522 
00523   // Uncomment the next line to make things brighter
00524   //sun2->setAmbient(1.0, 1.0, 1.0);
00525 
00526   PerfScene->addChild(sun2);
00527 
00528   // Configure and open GL window
00529   pfPipe *Pipe = pfGetPipe(0);
00530   Shared->PW = new pfPipeWindow(Pipe);
00531   Shared->PW->setWinType(PFPWIN_TYPE_X);
00532   Shared->PW->setName("MSL Render: IRIS Performer Window");
00533   Shared->PW->setOriginSize(0,0,500,500);
00534   Shared->PW->open();
00535   
00536   // Create and configure a pfChannel.
00537   pfChannel *chan = new pfChannel(Pipe);
00538   chan->setScene(PerfScene);
00539   chan->setFOV(45.0f, 45.0f);
00540   chan->setNearFar(1.0f, 1000.0f);
00541   chan->setTravFunc(PFTRAV_DRAW, DrawChannel);
00542   chan->setViewport(0.0, 1.0, 0, 1.0);
00543   chan->setShare(PFCHAN_FOV | PFCHAN_NEARFAR
00544                  | PFCHAN_EARTHSKY 
00545                  | PFCHAN_STRESS 
00546                  | PFCHAN_LOD | PFCHAN_SWAPBUFFERS
00547                  | PFCHAN_SWAPBUFFERS_HW);
00548 
00549   Shared->Chan = chan;
00550   // Set Chan view point  
00551   // Unfortunately, this viewing transformation has to be fixed,
00552   // otherwise the control panel will disappear because of the 
00553   // way it was designed.
00554   pfCoord view;
00555   view.hpr.set(0.0, 0.0, 0.0); // z,x,y
00556   view.xyz.set(0.0, -300.0, 0.0);
00557   Shared->Chan->setView(view.xyz, view.hpr);
00558 
00559   pfEarthSky *esky = new pfEarthSky();
00560   esky->setMode(PFES_BUFFER_CLEAR, PFES_SKY_GRND);
00561   esky->setAttr(PFES_GRND_HT, -1000.0f);
00562   esky->setColor(PFES_GRND_FAR, 0.3f, 0.1f, 0.0f, 1.0f);
00563   esky->setColor(PFES_GRND_NEAR, 0.5f, 0.3f, 0.1f, 1.0f);
00564   chan->setESky(esky);
00565 
00566   // Initilize the slave channel
00567   /*pfChannel *chaneye = new pfChannel(Pipe);
00568   pfScene *eyescene = new pfScene;
00569   pfMatrix m;
00570   m.makeIdent();
00571   pfSCS *eyeworld = new pfSCS(m); 
00572   
00573   eyeworld->addChild(Shared->EnvDCS);
00574   eyeworld->addChild(Shared->BodiesDCS);
00575   eyescene->addChild(eyeworld);
00576 
00577   chaneye->setScene(eyescene);
00578   chan->attach(chaneye);
00579   chaneye->setViewport(0.0, 1.0/4.0, 3.0/4.0, 1.0);
00580   Shared->ChanEye = chaneye;
00581   PW->removeChan(ChanEye); // remove chanslaver as default
00582   */
00583 
00584   // Initilize input device
00585   pfuInitInput(Shared->PW,PFUINPUT_X);
00586 
00587   // Get frame rate and set it to FrameTime
00588   FrameTime = (double) 0.1; // (1.0/pfGetFrameRate());
00589   //cout << "FrameTime: " << FrameTime << endl;
00590 
00591   Shared->HoldRightMouse = false;
00592   Shared->HoldLeftMouse = false;
00593   Shared->HoldMiddleMouse = false;
00594   //Shared->ReleaseRightMouse = false;
00595   //Shared->ReleaseLeftMouse = false;
00596   //Shared->ReleaseMiddleMouse = false;
00597 
00598   // Here is where we have to make the initial values correspond
00599   // to what the viewing parameters from Scene dictate.
00600   Shared->TranX = 0.0;
00601   Shared->TranY = 0.0;
00602   Shared->TranZ = 0.0;
00603   Shared->RotX = 0.0;
00604   Shared->RotY = 0.0;
00605   Shared->RotZ = 0.0;
00606 
00607   //Set boundbox
00608   BoundingBoxOn = false;
00609 
00610   // By default, don't use attached camera
00611   AttachedCameraOn = false;
00612   
00613   // Set control pannel initial pos
00614   Shared->ControlPanelOn = true;
00615   Shared->FocusOnControlPad = false;
00616   Shared->PadX = 0.0;
00617   Shared->ControlPad->setTrans(Shared->PadX, 0.0, 0.0);
00618 
00619   // Make Eye initial matrix
00620   pfMatrix delta_rot;
00621   Shared->EyeMat.makeIdent();
00622   // rotate along Z 90 degrees
00623   delta_rot.makeRot(-90.0, 0.0, 0.0, 1.0);
00624   Shared->EyeMat.postMult(delta_rot);
00625   // Translate to designed position
00626   delta_rot.makeTrans(10, 10, 0);
00627   Shared->EyeMat.postMult(delta_rot);
00628 
00629   // Get courrent mouse position
00630   GetCurrentMousePos(Shared->MouseXOld, Shared->MouseYOld);
00631 }
00632 
00633 
00634 
00635 void RenderPerformer::Terminate(){
00636   // Terminate parallel processes and exit
00637   pfuExitInput();
00638   pfExit();
00639 }
00640 
00641 
00642 
00643 void RenderPerformer::HandleKeyInput(){
00644   int inkey;
00645 
00646   pfuGetEvents(Shared->InputEvents);
00647 
00648   if (Shared->InputEvents->numKeys > 0) {
00649     inkey = Shared->InputEvents->keyQ[0];
00650     pfuResetEventStream(Shared->InputEvents);
00651     //cout << inkey << endl;
00652 
00653     switch(inkey){
00654     case 'b' : 
00655       BoundingBoxOn = !BoundingBoxOn;  // Toggle
00656       break;
00657     case 'c' :
00658       Shared->ControlPanelOn = !Shared->ControlPanelOn;  // Toggle
00659       break;
00660     case 'v' :
00661       AttachedCameraOn = !AttachedCameraOn;  // Toggle
00662       break;
00663     }
00664   }
00665 }
00666 
00667 
00668 
00669 void RenderPerformer::GetControlPadSize(double &padwidth_l, 
00670                                         double &padwidth_r, 
00671                                         double &padheight_b, 
00672                                         double &padheight_top){
00673 
00674   padwidth_l = (CONTROLPANEL_CENTER_X + 
00675                 Shared->PadX - CONTROLPAD_WIDTH)/tan(22.5*PI/180.0);
00676   padwidth_r = (CONTROLPANEL_CENTER_X + 
00677                 Shared->PadX + CONTROLPAD_WIDTH)/tan(22.5*PI/180.0);
00678   padheight_b = (CONTROLPANEL_CENTER_Z - 
00679                  CONTROLPAD_HEIGHT)/tan(22.5*PI/180.0);
00680   padheight_top = (CONTROLPANEL_CENTER_Z + 
00681                    CONTROLPAD_HEIGHT)/tan(22.5*PI/180.0);
00682 
00683 }
00684 
00685 
00686 
00687 void RenderPerformer::HandleMouseEvents() {
00688   double mousex_new, mousey_new, theta;
00689   pfMatrix transform, dtransform;
00690   double padw_l, padw_r, padh_b, padh_top;
00691   MSLVector vp,vd;
00692   double vo;
00693   int i,j,k;
00694   MSLVector c,conf(6);
00695   list<MSLVector>::iterator fi;
00696 
00697   // Get control pad size
00698   GetControlPadSize(padw_l, padw_r, padh_b, padh_top);
00699 
00700   // Get current mouse position
00701   GetCurrentMousePos(mousex_new, mousey_new);
00702 
00703   // If mouse is inside the pad and ControlPanelOn is true
00704   // deal with control pannel
00705   if( Shared->MouseXOld >= padw_l
00706       && Shared->MouseXOld <= padw_r
00707       && Shared->MouseYOld >= padh_b
00708       && Shared->MouseYOld <= padh_top
00709       && Shared->HoldLeftMouse
00710       && Shared->ControlPanelOn ){
00711     Shared->FocusOnControlPad = true;    
00712   }
00713   if(!Shared->HoldLeftMouse)
00714     Shared->FocusOnControlPad = false;; 
00715 
00716   if(Shared->FocusOnControlPad){
00717     Shared->PadX = Shared->PadX + 0.3*(mousex_new - Shared->MouseXOld);
00718     if(Shared->PadX >= CONTROLPANEL_BAR_WIDTH)
00719       Shared->PadX = CONTROLPANEL_BAR_WIDTH;
00720     else
00721       if(Shared->PadX <= -CONTROLPANEL_BAR_WIDTH)
00722         Shared->PadX = -CONTROLPANEL_BAR_WIDTH;
00723 
00724     // Range of speeds: 2^-ANIMATING_SPEED_FACTOR to 2^ANIMATING_SPEED_FACTOR
00725     AnimationTimeScale = pow(2.0,ANIMATING_SPEED_FACTOR *
00726                              Shared->PadX/CONTROLPANEL_BAR_WIDTH);
00727 
00728     Shared->ControlPad->setTrans(Shared->PadX, 0.0, 0.0);    
00729   }
00730 
00731   // else set global orientation
00732   if( !Shared->FocusOnControlPad && Shared->HoldRightMouse ) {
00733     if(fabs(Shared->MouseXOld - mousex_new) > 0.00001)
00734       Shared->RotY += 40*(mousex_new - Shared->MouseXOld);
00735     if(fabs(Shared->MouseYOld - mousey_new) > 0.00001) {
00736       Shared->TranY += 60*(mousey_new - Shared->MouseYOld);
00737     }
00738   }
00739   
00740   if( !Shared->FocusOnControlPad && Shared->HoldLeftMouse ){
00741     if(fabs(Shared->MouseXOld - mousex_new) > 0.00001)
00742       Shared->RotZ -= 40*(Shared->MouseXOld - mousex_new);
00743     if(fabs(Shared->MouseYOld - mousey_new) > 0.00001)
00744       Shared->RotX += 40*(Shared->MouseYOld - mousey_new);
00745   }
00746 
00747   if( !Shared->FocusOnControlPad && Shared->HoldMiddleMouse ){
00748     if(fabs(Shared->MouseXOld - mousex_new) > 0.00001)
00749       Shared->TranX += 60*(mousex_new - Shared->MouseXOld);
00750     if(fabs(Shared->MouseYOld - mousey_new) > 0.00001)
00751       Shared->TranZ += 60*(mousey_new - Shared->MouseYOld);
00752   }
00753 
00754 
00755   // Compute the global transformation matrix
00756 
00757   // Start with identity
00758   transform.makeIdent();
00759 
00760   // Determine where to take the viewing transformations from
00761   if (AttachedCameraOn) {
00762     k = AnimationFrameIndex;
00763     fi = FrameList.begin();
00764     for (i = 0; i < (int) FrameList.size(); i++)
00765       fi++;
00766     c = *fi;
00767     for (j = 0; j < 6; j++)
00768       conf[j] = c[ 6 * S->AttachedCameraBody + j];
00769 
00770     vp = S->AttachedCameraPosition;
00771     vd = S->AttachedCameraDirection;
00772     vo = 0.0;  // THIS NEEDS TO BE COMPUTED FROM AttachedCameraZenith
00773 
00774     // Transform the camera according to the attached body
00775     dtransform.makeTrans(-conf[0], -conf[1], -conf[2]);
00776     transform.postMult(dtransform);
00777 
00778     dtransform.makeRot(-conf[5]*180.0/PI, 0.0, 0.0, 1.0);
00779     transform.postMult(dtransform);
00780 
00781     dtransform.makeRot(-conf[4]*180.0/PI, 0.0, 1.0, 0.0);
00782     transform.postMult(dtransform);
00783 
00784     dtransform.makeRot(-conf[3]*180.0/PI, 1.0, 0.0, 0.0);
00785     transform.postMult(dtransform);
00786   }
00787   else {
00788     vp = S->GlobalCameraPosition;
00789     vd = S->GlobalCameraDirection;
00790     vo = 0.0;  // THIS NEEDS TO BE COMPUTED FROM GlobalCameraZenith
00791   }
00792 
00793   // Set up the viewing direction
00794   dtransform.makeTrans(-vp[0], -vp[1], -vp[2]);
00795   transform.postMult(dtransform);
00796 
00797   dtransform.makeRot(-vo*180.0/PI, vd[0], vd[1], vd[2]);
00798   transform.postMult(dtransform);
00799 
00800   theta = -asin(sqrt(sqr(vd[0]) + sqr(vd[2])));
00801   dtransform.makeRot(theta*180.0/PI, vd[2], 0.0, -vd[0]);
00802   transform.postMult(dtransform);
00803 
00804   // Handle the translation generated by the user
00805   dtransform.makeTrans(Shared->TranX, Shared->TranY, Shared->TranZ);
00806   transform.postMult(dtransform);
00807 
00808   // Undo the forced channel viewpoint
00809   dtransform.makeTrans(0.0, -300.0, 0.0);
00810   transform.postMult(dtransform);
00811 
00812   // Handle the rotation generated by the user
00813   dtransform.makeRot(Shared->RotZ, 0.0, 0.0, 1.0);
00814   transform.postMult(dtransform);
00815   dtransform.makeRot(Shared->RotY, 0.0, 1.0, 0.0);
00816   transform.postMult(dtransform);
00817   dtransform.makeRot(Shared->RotX, 1.0, 0.0, 0.0);
00818   transform.postMult(dtransform);
00819 
00820   // Set the transformation
00821   Shared->WorldDCS->setMat(transform);
00822   
00823   //Update old mouse position
00824   Shared->MouseXOld = mousex_new;
00825   Shared->MouseYOld = mousey_new;
00826 }
00827 
00828 
00829 
00830 void RenderPerformer::HandleEvents() {
00831   // Handle events from render control window
00832   Render::HandleEvents();
00833 
00834   // Go to sleep until next frame time.
00835   pfSync();             
00836   
00837   //Collect key input events
00838   HandleKeyInput();
00839  
00840   // handle Mouse events
00841   HandleMouseEvents();
00842 
00843   // setup body animating
00844   if (AnimationActive) {
00845     ShowCurrentAnimationFrame();
00846   }
00847 
00848   // Always display world
00849   Shared->WorkEnv->setVal(Shared->WorkEnv->searchChild(Shared->Env));
00850   Shared->ShowCase->setVal(Shared->ShowCase->searchChild(Shared->WorldDCS));
00851 
00852   // Show Bounding Box
00853   if (BoundingBoxOn){
00854     Shared->WorkEnv->setVal(PFSWITCH_ON);
00855   }
00856 
00857   // Show Control Panel
00858   if(Shared->ControlPanelOn){
00859     Shared->ShowCase->setVal(PFSWITCH_ON);
00860   }
00861 
00862   // Initiate cull/draw for this frame.
00863   pfFrame();
00864 }
00865 
00866 
00867 
00868 // Draw process callback
00869 void RenderPerformer::DrawChannel(pfChannel *chan, void *) {
00870   chan->clear();
00871   pfDraw();
00872 }
00873 
00874 
Motion Strategy Library


Web page maintained by Steve LaValle
Partial support provided by NSF CAREER Award IRI-970228 (LaValle), Honda Research, and Iowa State University.
Contributors: Anna Atramentov, Peng Cheng, James Kuffner, Steve LaValle, and Libo Yang.