00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "renderworld.h"
00021 #include "phyjoint.h"
00022
00023 #include <QImage>
00024 #include <QColor>
00025 #include <QKeyEvent>
00026 #include <QMenu>
00027 #include <QAction>
00028 #include <QList>
00029 #include <cmath>
00030 #include <QDir>
00031 #include <QLinkedList>
00032 #include <QMutexLocker>
00033 #include <QEvent>
00034
00035
00036
00037 #ifdef FARSA_MAC
00038 # include <GLUT/glut.h>
00039 #else
00040 # include <GL/glu.h>
00041 #endif
00042
00043 using namespace qglviewer;
00044
00045 #define GLMultMatrix glMultMatrixf
00046
00047
00048 #include "qglviewer/camera.h"
00049 #if QT_VERSION >= 0x040000
00050 # include <QWheelEvent>
00051 #endif
00052
00053 namespace farsa {
00054
00055 QMap<QString, QImage>* RenderWObjectContainer::textmap = NULL;
00056 unsigned int RenderWObjectContainer::textmapRefCounter = 0;
00057
00058 RenderWObjectContainer::RenderWObjectContainer( QString wResName ) :
00059 worldResourceName(wResName),
00060 worldv(NULL),
00061 mutex(QMutex::Recursive)
00062 {
00063 if ( textmap == NULL ) {
00064 textmap = new QMap<QString, QImage>();
00065 (*textmap)["tile1"].load( ":/tiles/16tile10.jpg" );
00066 (*textmap)["tile2"].load( ":/tiles/16tile07.jpg" );
00067 (*textmap)["white"].load( ":/white.jpg" );
00068 (*textmap)["tile3"].load( ":/tiles/16tile11.jpg" );
00069 (*textmap)["tile4"].load( ":/tiles/16tile-B.jpg" );
00070 (*textmap)["tile5"].load( ":/tiles/16tile12.jpg" );
00071 (*textmap)["tile6"].load( ":/tiles/16tile04.jpg" );
00072 (*textmap)["tile7"].load( ":/tiles/tile01.jpg" );
00073 (*textmap)["tile8"].load( ":/tiles/16tile02.jpg" );
00074 (*textmap)["tile9"].load( ":/tiles/16tile05.jpg" );
00075 (*textmap)["tile10"].load( ":/tiles/16tile08.jpg" );
00076 (*textmap)["icub"].load( ":/tiles/16tile11.jpg" );
00077 (*textmap)["icubFace"].load( ":/covers/face.jpg" );
00078 (*textmap)["blueye"].load( ":/covers/eyep2_b.jpg" );
00079 (*textmap)["metal"].load( ":/metal/iron05.jpg" );
00080 (*textmap)["marXbot_12leds"].load( ":/covers/marxbot_12leds.jpg" );
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 (*textmap)["skyb0"].load( ":/skybox/sb2_top.jpg" );
00095 (*textmap)["skyb1"].load( ":/skybox/sb2_back.jpg" );
00096 (*textmap)["skyb2"].load( ":/skybox/sb2_front.jpg" );
00097 (*textmap)["skyb3"].load( ":/ground/cobbles01.jpg" );
00098 (*textmap)["skyb4"].load( ":/skybox/sb2_right.jpg" );
00099 (*textmap)["skyb5"].load( ":/skybox/sb2_left.jpg" );
00100 }
00101 textmapRefCounter++;
00102
00103 usableResources(QStringList() << worldResourceName);
00104 }
00105
00106 RenderWObjectContainer::~RenderWObjectContainer() {
00107 foreach( RenderWObject* ro, graphs ) {
00108 delete ro;
00109 }
00110 textmapRefCounter--;
00111 if (textmapRefCounter == 0) {
00112 delete textmap;
00113 textmap = NULL;
00114 }
00115 }
00116
00117 bool RenderWObjectContainer::addTextureImage( QString filename, QString texturename ) {
00118 QMutexLocker locker(&mutex);
00119
00120 return ((*textmap)[texturename].load( filename ));
00121 }
00122
00123 void RenderWObjectContainer::setWorld( World* newworld ) {
00124
00125 declareResource( worldResourceName, newworld );
00126 }
00127
00128 RenderWObject* RenderWObjectContainer::operator[]( const WObject* obj ) {
00129 QMutexLocker locker(&mutex);
00130
00131
00132 for( int i=0; i<graphs.size(); i++ ) {
00133 if ( graphs[i]->object() == obj ) {
00134 return graphs[i];
00135 }
00136 }
00137 return NULL;
00138 }
00139
00140 RenderWObject* RenderWObjectContainer::createRenderWObjectFor( const WObject* obj, RenderWObjectContainer* container ) {
00141 initFactory();
00142 const QMetaObject* metaObj = obj->metaObject();
00143 while( metaObj ) {
00144 QString classname = metaObj->className();
00145 if (fac->contains(classname)) {
00146 return (*fac)[classname]->create( (WObject*)obj, container );
00147 }
00148 metaObj = metaObj->superClass();
00149 }
00150
00151
00152
00153 return (*fac)["farsa::WObject"]->create( (WObject*)obj, container );
00154 }
00155
00156 void RenderWObjectContainer::addObject( WObject* wobj ) {
00157
00158 ResourcesLocker resourceLocker(this);
00159 QMutexLocker locker(&mutex);
00160
00161 graphs.append( createRenderWObjectFor( wobj, this ) );
00162 }
00163
00164 void RenderWObjectContainer::removeObject( WObject* wobj ) {
00165
00166 ResourcesLocker resourceLocker(this);
00167 QMutexLocker locker(&mutex);
00168
00169 for( int i=0; i<graphs.size(); i++ ) {
00170 if ( graphs[i]->object() == wobj ) {
00171 RenderWObject* ro = graphs[i];
00172 graphs.remove( i );
00173 ro->objectAlreadyDestroyed();
00174 delete ro;
00175 break;
00176 }
00177 }
00178 }
00179
00180 void RenderWObjectContainer::resourceChanged(QString name, ResourceChangeType changeType)
00181 {
00182 QMutexLocker locker(&mutex);
00183
00184
00185 if (name != worldResourceName) {
00186 return;
00187 }
00188
00189
00190 foreach( RenderWObject* ro, graphs ) {
00191 delete ro;
00192 }
00193 graphs.clear();
00194
00195
00196
00197 if (changeType == Deleted) {
00198 worldv = NULL;
00199 } else {
00200 worldv = getResource<World>();
00201 }
00202
00203
00204 if (worldv != NULL) {
00205 foreach( WObject* obj, worldv->objects() ) {
00206 graphs.append( createRenderWObjectFor( obj, this ) );
00207 }
00208 }
00209 }
00210
00211 void RenderWObjectContainer::applyTexture( QGLContext* gw, QString texts ) {
00212 QMutexLocker locker(&mutex);
00213
00214 if ( textmap->contains( texts ) ) {
00215 if ( !textGLId.contains( texts ) ) {
00216 textGLId[texts] = gw->bindTexture( (*textmap)[texts], GL_TEXTURE_2D, GL_RGB );
00217 }
00218 glBindTexture( GL_TEXTURE_2D, textGLId[texts] );
00219 glEnable( GL_TEXTURE_2D );
00220 }
00221
00222
00223 }
00224
00225 void RenderWObjectContainer::setupColorTexture( QGLContext* gw, RenderWObject* robj ) {
00226
00227 ResourcesLocker resourceLocker(this);
00228 QMutexLocker locker(&mutex);
00229
00230
00231 glShadeModel( GL_SMOOTH );
00232 glEnable( GL_BLEND );
00233 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00234 WObject* obj = robj->object();
00235 while ( obj->useColorTextureOfOwner() && ( obj->owner() != NULL ) ) {
00236 WObject *const owner = dynamic_cast<WObject *>(obj->owner());
00237 if ( owner != NULL ) {
00238 obj = owner;
00239 } else {
00240 break;
00241 }
00242 }
00243 QColor colorv = obj->color();
00244 glColor4f( colorv.redF(), colorv.greenF(), colorv.blueF(), colorv.alphaF() );
00245 applyTexture( gw, obj->texture() );
00246 }
00247
00248 void RenderWObjectContainer::drawSkyGroundBox( QGLContext* gw ) {
00249
00250 ResourcesLocker resourceLocker(this);
00251 QMutexLocker locker(&mutex);
00252
00253 if (worldv == NULL) {
00254 return;
00255 }
00256 wVector min, max;
00257 worldv->size( min, max );
00258 wVector m_size = wVector( fabs(max[0]-min[0]), fabs(max[1]-min[1]), fabs(max[1]-min[1]) );
00259
00260 resourceLocker.unlock();
00261
00262 glDisable( GL_LIGHTING );
00263 glShadeModel( GL_FLAT );
00264 glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
00265
00266
00267
00268
00269
00270
00271
00272
00273 applyTexture( gw, "skyb0" );
00274 glBegin(GL_QUADS);
00275 glTexCoord2f(0.0, 1.0); glVertex3f( min.x, max.y, max.z);
00276 glTexCoord2f(0.0, 0.0); glVertex3f( max.x, max.y, max.z);
00277 glTexCoord2f(1.0, 0.0); glVertex3f( max.x, min.y, max.z);
00278 glTexCoord2f(1.0, 1.0); glVertex3f( min.x, min.y, max.z);
00279 glEnd();
00280
00281 applyTexture( gw, "skyb1" );
00282 glBegin(GL_QUADS);
00283 glTexCoord2f(1.0, 0.0); glVertex3f( min.x, max.y, min.z);
00284 glTexCoord2f(1.0, 1.0); glVertex3f( min.x, max.y, max.z);
00285 glTexCoord2f(0.0, 1.0); glVertex3f( min.x, min.y, max.z);
00286 glTexCoord2f(0.0, 0.0); glVertex3f( min.x, min.y, min.z);
00287 glEnd();
00288
00289 applyTexture( gw, "skyb2" );
00290 glBegin(GL_QUADS);
00291 glTexCoord2f(0.0, 1.0); glVertex3f(max.x, max.y, max.z);
00292 glTexCoord2f(0.0, 0.0); glVertex3f(max.x, max.y, min.z);
00293 glTexCoord2f(1.0, 0.0); glVertex3f(max.x, min.y, min.z);
00294 glTexCoord2f(1.0, 1.0); glVertex3f(max.x, min.y, max.z);
00295 glEnd();
00296
00297 applyTexture( gw, "skyb3" );
00298
00299
00300 float bfs = m_size[1]/0.4;
00301 float bft = m_size[0]/0.4;
00302 glBegin(GL_QUADS);
00303 glTexCoord2f(0.0, bft); glVertex3f( max.x, max.y, min.z);
00304 glTexCoord2f(0.0, 0.0); glVertex3f( min.x, max.y, min.z);
00305 glTexCoord2f(bfs, 0.0); glVertex3f( min.x, min.y, min.z);
00306 glTexCoord2f(bfs, bft); glVertex3f( max.x, min.y, min.z);
00307 glEnd();
00308
00309 applyTexture( gw, "skyb4" );
00310 glBegin(GL_QUADS);
00311 glTexCoord2f(1.0, 1.0); glVertex3f( min.x, min.y, max.z);
00312 glTexCoord2f(0.0, 1.0); glVertex3f( max.x, min.y, max.z);
00313 glTexCoord2f(0.0, 0.0); glVertex3f( max.x, min.y, min.z);
00314 glTexCoord2f(1.0, 0.0); glVertex3f( min.x, min.y, min.z);
00315 glEnd();
00316
00317 applyTexture( gw, "skyb5" );
00318 glBegin(GL_QUADS);
00319 glTexCoord2f(0.0, 0.0); glVertex3f( min.x, max.y, min.z);
00320 glTexCoord2f(1.0, 0.0); glVertex3f( max.x, max.y, min.z);
00321 glTexCoord2f(1.0, 1.0); glVertex3f( max.x, max.y, max.z);
00322 glTexCoord2f(0.0, 1.0); glVertex3f( min.x, max.y, max.z);
00323 glEnd();
00324 }
00325
00326 class StandardCamera : public qglviewer::Camera {
00327 public :
00328 StandardCamera() {
00329 orthoSize = 1.0;
00330 };
00331 virtual float zNear() const {
00332 return 0.001f;
00333 };
00334 virtual float zFar() const {
00335 return 1000.0f;
00336 };
00337 void changeOrthoFrustumSize(int delta) {
00338 if (delta > 0) {
00339 orthoSize *= 1.1f;
00340 } else {
00341 orthoSize /= 1.1f;
00342 }
00343 };
00344 virtual void getOrthoWidthHeight(GLdouble &halfWidth, GLdouble &halfHeight) const {
00345 halfHeight = orthoSize;
00346 halfWidth = aspectRatio() * orthoSize;
00347 };
00348 private :
00349 float orthoSize;
00350 };
00351
00352 class MyCameraConstraint : public qglviewer::Constraint {
00353 public:
00355 MyCameraConstraint( qglviewer::Vec min, qglviewer::Vec max ) {
00356
00357 qglviewer::Vec pad(0.1,0.1,0.1);
00358 minP = min + pad;
00359 maxP = max - pad;
00360 };
00361 virtual void constrainTranslation( qglviewer::Vec& t, qglviewer::Frame* const fr ) {
00362
00363 const qglviewer::Frame* ls = fr;
00364 if ( fr->referenceFrame() != NULL ) {
00365 qDebug() << "Using Reference";
00366 ls = fr->referenceFrame();
00367 }
00368
00369 qglviewer::Vec tw = ls->inverseTransformOf( t );
00370 qglviewer::Vec pos = fr->position();
00371 if ( (pos.x + tw.x > maxP.x && t.x > 0) || (pos.x + tw.x < minP.x && t.x < 0) ||
00372 (pos.y + tw.y > maxP.y && t.y > 0) || (pos.y + tw.y < minP.y && t.y < 0) ||
00373 (pos.z + tw.z > maxP.z && t.z > 0) || (pos.z + tw.z < minP.z && t.z < 0) ) {
00374 t.z = 0.0;
00375 t.x = 0.0;
00376 t.y = 0.0;
00377 }
00378 };
00379
00380 qglviewer::Vec minP;
00381 qglviewer::Vec maxP;
00382 };
00383
00384 namespace {
00385
00386 class ForceRenderWorldUpdateEvent : public QEvent
00387 {
00388 public:
00389 ForceRenderWorldUpdateEvent() :
00390 QEvent(QEvent::User)
00391 {
00392 }
00393
00394 virtual ~ForceRenderWorldUpdateEvent()
00395 {
00396 }
00397 };
00398 }
00399
00400
00401 RenderWorld::RenderWorld( QWidget* parent, QString wResName )
00402 : QGLViewer( parent ), RenderWObjectContainer( wResName ) {
00403 wiref = false;
00404 showskygroundbox = true;
00405 showobjs = true;
00406 showjoints = false;
00407 showaabbs = false;
00408 showcontacts = true;
00409 showforces = false;
00410 currentSelected = -1;
00411
00412 setStateFileName( QString() );
00413
00414 setCamera( new StandardCamera() );
00415
00416 setContextMenuPolicy( Qt::CustomContextMenu );
00417 }
00418
00419 RenderWorld::~RenderWorld() {
00420 if ( ! stateFileName().isNull() ) {
00421 saveStateToFile();
00422 }
00423 }
00424
00425 void RenderWorld::slotRemoveObject( WObject* w ) {
00426
00427 removeObject( w );
00428 }
00429
00430 void RenderWorld::slotAddObject( WObject* w ) {
00431
00432 addObject( w );
00433 }
00434
00435 void RenderWorld::onWorldResize() {
00436
00437 ResourcesLocker resourceLocker(this);
00438 QMutexLocker locker(&mutex);
00439
00440 if (world() == NULL) {
00441 return;
00442 }
00443
00444 MyCameraConstraint* tmp = dynamic_cast<MyCameraConstraint*>( camera()->frame()->constraint() );
00445 if ( tmp != NULL ) {
00446 wVector min, max;
00447 world()->size( min, max );
00448 setSceneBoundingBox( qglviewer::Vec( min[0], min[1], min[2] ),
00449 qglviewer::Vec( max[0], max[1], max[2] ) );
00450 tmp->minP = qglviewer::Vec( min[0], min[1], min[2] );
00451 tmp->maxP = qglviewer::Vec( max[0], max[1], max[2] );
00452 }
00453 }
00454
00455 void RenderWorld::wireframe( bool b ) {
00456 QMutexLocker locker(&mutex);
00457 wiref = b;
00458 }
00459
00460 void RenderWorld::showSkyGround( bool b ) {
00461 QMutexLocker locker(&mutex);
00462 showskygroundbox = b;
00463 }
00464
00465 void RenderWorld::showObjects( bool b ) {
00466 QMutexLocker locker(&mutex);
00467 showobjs = b;
00468 }
00469
00470 void RenderWorld::showJoints( bool b ) {
00471 QMutexLocker locker(&mutex);
00472 showjoints = b;
00473 }
00474
00475 void RenderWorld::showAABBs( bool b ) {
00476 QMutexLocker locker(&mutex);
00477 showaabbs = b;
00478 }
00479
00480 void RenderWorld::showContacts( bool b ) {
00481 QMutexLocker locker(&mutex);
00482 showcontacts = b;
00483 }
00484
00485 void RenderWorld::showForces( bool b ) {
00486 QMutexLocker locker(&mutex);
00487 showforces = b;
00488 }
00489
00490 void RenderWorld::contextMenu( const QPoint& pos ) {
00492 QList<QAction*> acts;
00493 QAction* act;
00494 if ( showskygroundbox ) {
00495 act = new QAction( "Hide Sky-Ground", this );
00496 } else {
00497 act = new QAction( "Show Sky-Ground", this );
00498 }
00499 act->setCheckable( true );
00500 act->setChecked( showskygroundbox );
00501 connect( act, SIGNAL( toggled(bool) ),
00502 this, SLOT( showSkyGround(bool) ) );
00503 acts.append( act );
00504 if ( wiref ) {
00505 act = new QAction( "Hide Wireframe", this );
00506 } else {
00507 act = new QAction( "Show Wireframe", this );
00508 }
00509 act->setCheckable( true );
00510 act->setChecked( wiref );
00511 connect( act, SIGNAL( toggled(bool) ),
00512 this, SLOT( wireframe(bool) ) );
00513 acts.append( act );
00514
00515 if ( showobjs ) {
00516 act = new QAction( "Hide Objects", this );
00517 } else {
00518 act = new QAction( "Show Objects", this );
00519 }
00520 act->setCheckable( true );
00521 act->setChecked( showobjs );
00522 connect( act, SIGNAL( toggled(bool) ),
00523 this, SLOT( showObjects(bool) ) );
00524 acts.append( act );
00525
00526 if ( showjoints ) {
00527 act = new QAction( "Hide Joints", this );
00528 } else {
00529 act = new QAction( "Show Joints", this );
00530 }
00531 act->setCheckable( true );
00532 act->setChecked( showjoints );
00533 connect( act, SIGNAL( toggled(bool) ),
00534 this, SLOT( showJoints(bool) ) );
00535 acts.append( act );
00536
00537 if ( showaabbs ) {
00538 act = new QAction( "Hide AABBs", this );
00539 } else {
00540 act = new QAction( "Show AABBs", this );
00541 }
00542 act->setCheckable( true );
00543 act->setChecked( showaabbs );
00544 connect( act, SIGNAL( toggled(bool) ),
00545 this, SLOT( showAABBs(bool) ) );
00546 acts.append( act );
00547
00548 if ( showcontacts ) {
00549 act = new QAction( "Hide Contacts", this );
00550 } else {
00551 act = new QAction( "Show Contacts", this );
00552 }
00553 act->setCheckable( true );
00554 act->setChecked( showcontacts );
00555 connect( act, SIGNAL( toggled(bool) ),
00556 this, SLOT( showContacts(bool) ) );
00557 acts.append( act );
00558
00559 if ( showforces ) {
00560 act = new QAction( "Hide Forces", this );
00561 } else {
00562 act = new QAction( "Show Forces", this );
00563 }
00564 act->setCheckable( true );
00565 act->setChecked( showforces );
00566 connect( act, SIGNAL( toggled(bool) ),
00567 this, SLOT( showForces(bool) ) );
00568 acts.append( act );
00569
00570 QMenu::exec( acts, pos );
00571 }
00572
00573 void RenderWorld::init() {
00574
00575 ResourcesLocker resourceLocker(this);
00576 QMutexLocker locker(&mutex);
00577
00578 if (world() == NULL) {
00579 return;
00580 }
00581
00582 if ( ! stateFileName().isNull() ) {
00583 if ( !restoreStateFromFile() ) {
00584 }
00585 }
00586 wVector min, max;
00587 world()->size( min, max );
00588 camera()->frame()->setConstraint( new MyCameraConstraint( qglviewer::Vec( min[0], min[1], min[2] ), qglviewer::Vec( max[0], max[1], max[2] ) ) );
00589
00590 glEnable(GL_LIGHT0);
00591 }
00592
00593 void RenderWorld::draw() {
00594
00595 ResourcesLocker resourceLocker(this);
00596 QMutexLocker locker(&mutex);
00597
00598 if (world() == NULL) {
00599 return;
00600 }
00601
00602 if ( showskygroundbox ) {
00603 glPushAttrib( GL_ALL_ATTRIB_BITS );
00604 glPushMatrix();
00605 drawSkyGroundBox( (QGLContext*)( QGLContext::currentContext() ) );
00606 glPopMatrix();
00607 glPopAttrib();
00608 }
00609
00610
00611 float pos[4] = {1.0, 0.5, 1.0, 0.0};
00612
00613 camera()->frame()->getPosition(pos[0], pos[1], pos[2]);
00614 glLightfv( GL_LIGHT0, GL_POSITION, pos );
00615
00616
00617 if ( showcontacts ) {
00618 glPushAttrib( GL_ALL_ATTRIB_BITS );
00619
00620 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00621 glDisable( GL_LIGHTING );
00622
00623 contactMapIterator itera( world()->contacts() );
00624 while( itera.hasNext() ) {
00625 itera.next();
00626 const contactVec& vec = itera.value();
00627 for( int i=0; i<vec.size(); i++ ) {
00628 drawSphere( vec[i].worldPos, 0.008f );
00629 }
00630 }
00631 glPopAttrib();
00632 }
00633
00634 int alpha = 255;
00635 if ( showjoints ) {
00636 glPushAttrib( GL_ALL_ATTRIB_BITS );
00637
00638 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00639 glDisable( GL_LIGHTING );
00640 drawKineChains();
00641 alpha = 130;
00642 glPopAttrib();
00643 }
00644
00645 if ( showobjs ) {
00646 glPushAttrib( GL_ALL_ATTRIB_BITS );
00647
00648 if ( wiref ) {
00649 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00650 } else {
00651 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00652 }
00653 glEnable( GL_LIGHTING );
00654 PhyObject* pr;
00655 for( int i=0; i<graphics().size(); i++ ) {
00656 RenderWObject* r = graphics()[i];
00657 if ( r->object()->isInvisible() ) continue;
00658 if ( showforces && ( pr=dynamic_cast<PhyObject*>(r->object()) ) ) {
00659 glPushAttrib( GL_ALL_ATTRIB_BITS );
00660 glColor4f( 1.0, 0.0, 0.0, 1.0 );
00661 drawArrow( pr->matrix().w_pos, pr->matrix().w_pos + pr->force(), 0.1f );
00662 glColor4f( 0.0, 1.0, 0.0, 1.0 );
00663 drawArrow( pr->matrix().w_pos, pr->matrix().w_pos + pr->torque(), 0.1f );
00664 alpha = 130;
00665 glPopAttrib();
00666 }
00667 r->object()->setAlpha( alpha );
00668 glPushAttrib( GL_ALL_ATTRIB_BITS );
00669 r->render( (QGLContext*)( QGLContext::currentContext() ) );
00670 glPopAttrib();
00671 if ( showaabbs && currentSelected == i ) {
00672 glPushAttrib( GL_ALL_ATTRIB_BITS );
00673 r->renderAABB( this );
00674 glPopAttrib();
00675 wVector dims, minPoint, maxPoint;
00676 r->calculateOBB( dims, minPoint, maxPoint );
00677 glPushAttrib( GL_ALL_ATTRIB_BITS );
00678 drawWireBox( minPoint, maxPoint, r->object()->matrix() );
00679 glPopAttrib();
00680 }
00681 }
00682 }
00683
00684
00685 glPushAttrib( GL_ALL_ATTRIB_BITS );
00686 glColor4f( 1.0, 0.0, 0.0, 1.0 );
00687 drawText( 80, 15, QString("time: %1 step: %2")
00688 .arg(world()->elapsedTime())
00689 .arg((int)(world()->elapsedTime()/world()->timeStep()))
00690 );
00691 glPopAttrib();
00692 }
00693
00694 void RenderWorld::drawWithNames() {
00695 QMutexLocker locker(&mutex);
00696
00697 for( int i=0; i< graphics().size(); i++ ) {
00698 glPushName(i);
00699 graphics()[i]->render( (QGLContext*)( QGLContext::currentContext() ) );
00700 glPopName();
00701 }
00702 }
00703
00704 void RenderWorld::postSelection(const QPoint& point) {
00705 QMutexLocker locker(&mutex);
00706
00707 UNUSED_PARAM( point );
00708 int i = selectedName();
00709 if ( i != -1 && i != currentSelected ) {
00710 graphics()[qMax(0,currentSelected)]->object()->setColor( Qt::white );
00711 graphics()[i]->object()->setColor( Qt::yellow );
00712 currentSelected = i;
00713 }
00714 }
00715
00716 void RenderWorld::keyPressEvent(QKeyEvent *e) {
00717 QMutexLocker locker(&mutex);
00718
00719
00720 #if QT_VERSION < 0x040000
00721
00722 const Qt::ButtonState modifiers = (Qt::ButtonState)(e->state() & Qt::KeyButtonMask);
00723 #else
00724 const Qt::KeyboardModifiers modifiers = e->modifiers();
00725 #endif
00726
00727
00728
00729
00730 bool handled = false;
00731 if ((e->key()==Qt::Key_Left) && (modifiers==Qt::NoButton)) {
00732
00733 Quaternion qcur = camera()->orientation();
00734 Quaternion qnew = qcur * Quaternion( Vec(0,1,0), 3.1415/30 );
00735 camera()->setOrientation( qnew );
00736 handled = true;
00737 updateGL();
00738 } else if ((e->key()==Qt::Key_Right) && (modifiers==Qt::NoButton)) {
00739
00740 Quaternion qcur = camera()->orientation();
00741 Quaternion qnew = qcur * Quaternion( Vec(0,1,0), -3.1415/30 );
00742 camera()->setOrientation( qnew );
00743 handled = true;
00744 updateGL();
00745 }
00746 if ((e->key()==Qt::Key_Up) && (modifiers==Qt::NoButton)) {
00747
00748 Quaternion qcur = camera()->orientation();
00749 Quaternion qnew = qcur * Quaternion( Vec(1,0,0), 3.1415/30 );
00750 camera()->setOrientation( qnew );
00751 handled = true;
00752 updateGL();
00753 } else if ((e->key()==Qt::Key_Down) && (modifiers==Qt::NoButton)) {
00754
00755 Quaternion qcur = camera()->orientation();
00756 Quaternion qnew = qcur * Quaternion( Vec(1,0,0), -3.1415/30 );
00757 camera()->setOrientation( qnew );
00758 handled = true;
00759 updateGL();
00760 }
00761
00762 if ((e->key()==Qt::Key_M) && (modifiers==Qt::NoButton)) {
00763 contextMenu( mapToGlobal(QPoint(10,10)) );
00764 handled = true;
00765 }
00766
00767 if (!handled) {
00768 QGLViewer::keyPressEvent(e);
00769 }
00770 }
00771
00772 void RenderWorld::resourceChanged(QString name, ResourceChangeType changeType)
00773 {
00774 QMutexLocker locker(&mutex);
00775
00776
00777 RenderWObjectContainer::resourceChanged(name, changeType);
00778
00779 if (world() == NULL) {
00780 return;
00781 }
00782
00783
00784
00785
00786 connect( world(), SIGNAL( removedObject( WObject* ) ),
00787 this, SLOT( slotRemoveObject( WObject* ) ), Qt::DirectConnection );
00788 connect( world(), SIGNAL( addedObject( WObject* ) ),
00789 this, SLOT( slotAddObject( WObject* ) ), Qt::DirectConnection );
00790 connect( world(), SIGNAL( resized() ),
00791 this, SLOT( onWorldResize() ), Qt::DirectConnection );
00792
00793 connect( world(), SIGNAL( advanced() ),
00794 this, SLOT( update() ) );
00795
00796
00797 MyCameraConstraint* tmp = dynamic_cast<MyCameraConstraint*>( camera()->frame()->constraint() );
00798 if ( tmp != NULL ) {
00799 wVector min, max;
00800 world()->size( min, max );
00801 setSceneBoundingBox( qglviewer::Vec( min[0], min[1], min[2] ),
00802 qglviewer::Vec( max[0], max[1], max[2] ) );
00803 tmp->minP = qglviewer::Vec( min[0], min[1], min[2] );
00804 tmp->maxP = qglviewer::Vec( max[0], max[1], max[2] );
00805 }
00806
00807
00808 QCoreApplication::postEvent(this, new ForceRenderWorldUpdateEvent());
00809 }
00810
00811 void RenderWorld::drawDOF( PhyDOF* dof, bool drawAxes ) {
00812
00813
00814 if ( dof->joint() == NULL ) return;
00815
00816
00817 if ( dof->translate() ) return;
00818
00819 wMatrix mat;
00820 mat.x_ax = dof->xAxis();
00821 mat.y_ax = dof->yAxis();
00822 mat.z_ax = dof->axis();
00823 mat.w_pos = dof->centre();
00824 mat.sanitifize();
00825
00826 PhyJoint* joint = dof->joint();
00827 PhyObject* child = joint->child();
00828 PhyObject* parent= joint->parent();
00829 RenderWorld& rw = *this;
00830 wVector dims, minP, maxP;
00831
00832 rw[ child ]->calculateOBB( dims, minP, maxP );
00833 real cube = (dims[0]+dims[1]+dims[2])/3.0;
00834 if ( parent ) {
00835 rw[ parent ]->calculateOBB( dims, minP, maxP );
00836 real cube2 = (dims[0]+dims[1]+dims[2])/3.0;
00837 cube = min( cube2, cube );
00838 }
00839 real len = cube * 0.70;
00840 real rad = len * 0.25;
00841
00842 mat.w_pos = dof->centre() - dof->axis().scale(len/2.0);
00843 drawCylinder( mat, len, rad, QColor(Qt::cyan) );
00844 if ( dof->isLimited() ) {
00845
00846 real lo, hi;
00847 dof->limits( lo, hi );
00848 real ang = hi-lo;
00849 mat.w_pos = wVector(0,0,0);
00850 mat = mat * wMatrix( wQuaternion( dof->axis(), lo ), wVector(0,0,0) );
00851 mat.w_pos = dof->centre() + dof->axis().scale(len/2.0);
00852 drawTorus( rad, rad*0.6, mat, ang );
00853 } else {
00854 mat.w_pos = dof->centre() + dof->axis().scale(len/2.0);
00855 drawTorus( rad, rad*0.6, mat );
00856 }
00857
00858 mat.x_ax = dof->xAxis();
00859 mat.y_ax = dof->yAxis();
00860 mat.z_ax = dof->axis();
00861 mat.w_pos = wVector(0,0,0);
00862 mat.sanitifize();
00863 mat = mat * wMatrix( wQuaternion( dof->axis(), dof->position()-0.05 ), wVector(0,0,0) );
00864 mat.w_pos = dof->centre() + dof->axis().scale(len/2.0);
00865 drawTorus( rad, rad*0.55f, mat, 0.1f, Qt::green );
00866
00867 if ( drawAxes ) {
00868 drawArrow( dof->centre(), dof->centre()+dof->xAxis().scale(len*1.2), rad*0.4, 12, Qt::magenta );
00869 drawArrow( dof->centre(), dof->centre()+dof->yAxis().scale(len*1.2), rad*0.5, 12, Qt::yellow );
00870 }
00871 }
00872
00873 void RenderWorld::drawKineChains() {
00874
00875
00876 if (world() == NULL) {
00877 return;
00878 }
00879
00880 foreach( PhyJoint* jn, world()->joints()) {
00881
00882 float dist1 = 0.0f, dist2 = 0.0f;
00883 wVector start = jn->centre();
00884 wVector end1 = jn->child()->matrix().w_pos;
00885 wVector end2 = start;
00886 dist1 = wVector::distance( start, end1 );
00887 if ( jn->parent() ) {
00888 end2 = jn->parent()->matrix().w_pos;
00889 dist2 = wVector::distance( start, end2 );
00890 }
00891 real rad = (dist1 + dist2) * 0.04;
00892 drawCylinder( start, end1, rad*0.6 );
00893 drawCylinder( start, end2, rad*0.6 );
00894
00895 QVector<PhyDOF*> ds = jn->dofs();
00896 for( int k=0; k<ds.size(); k++ ) {
00897 drawDOF( ds[k], true );
00898 }
00899 }
00900 }
00901
00902 void RenderWorld::customEvent(QEvent* event)
00903 {
00904 if (event->type() == QEvent::User) {
00905
00906 update();
00907 }
00908 }
00909
00910 void RenderWObjectContainer::drawSphere( wVector pos, real radius ) {
00911 GLUquadricObj *pObj;
00912
00913
00914 glShadeModel( GL_SMOOTH );
00915 glColor4f( 0.0f, 1.0f, 0.0f, 1.0f );
00916
00917 wMatrix mat = wMatrix::identity();
00918 mat.w_pos = pos;
00919 mat.x_ax = mat.x_ax.scale( radius );
00920 mat.y_ax = mat.y_ax.scale( radius );
00921 mat.z_ax = mat.z_ax.scale( radius );
00922 glPushMatrix();
00923 GLMultMatrix(&mat[0][0]);
00924
00925
00926 pObj = gluNewQuadric();
00927
00928 gluQuadricTexture(pObj, true);
00929 gluSphere(pObj, 1.0f, 20, 20);
00930
00931 gluDeleteQuadric(pObj);
00932 glPopMatrix();
00933 }
00934
00935 void RenderWObjectContainer::drawCylinder( wVector axis, wVector centre, float h, float rad, QColor c ) {
00936 GLUquadricObj *pObj;
00937
00938 glPushMatrix();
00939
00940
00941 glShadeModel( GL_SMOOTH );
00942 glColor4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
00943
00944 wVector recentre = axis.scale( -h*0.5 ) + centre;
00945 glTranslatef( recentre[0], recentre[1], recentre[2] );
00946
00947 Vec xg(0,0,1);
00948 Vec ax( axis[0], axis[1], axis[2] );
00949 Quaternion quad( xg, ax );
00950 glMultMatrixd( quad.matrix() );
00951
00952
00953 pObj = gluNewQuadric();
00954 gluQuadricTexture(pObj, true);
00955 gluCylinder(pObj, rad, rad, h, 20, 2);
00956
00957
00958 gluQuadricOrientation(pObj, GLU_INSIDE);
00959 gluDisk(pObj, 0.0f, rad, 20, 1);
00960
00961 glTranslatef (0.0f, 0.0f, h);
00962 gluQuadricOrientation(pObj, GLU_OUTSIDE);
00963 gluDisk(pObj, 0.0f, rad, 20, 1);
00964
00965 gluDeleteQuadric(pObj);
00966 glPopMatrix();
00967 }
00968
00969 void RenderWObjectContainer::drawCylinder( wVector start, wVector end, float rad, QColor c ) {
00970 float h = wVector::distance( start, end );
00971 if ( h < 0.0001 ) return;
00972
00973 GLUquadricObj *pObj;
00974
00975 glPushMatrix();
00976
00977
00978 glShadeModel( GL_SMOOTH );
00979 glColor4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
00980
00981 wVector zaxis = end - start;
00982 zaxis.normalize();
00983 wMatrix tm = wMatrix::grammSchmidt( zaxis );
00984 tm.w_pos = start;
00985 GLMultMatrix( &tm[0][0] );
00986
00987
00988 pObj = gluNewQuadric();
00989 gluQuadricTexture(pObj, true);
00990 gluCylinder(pObj, rad, rad, h, 20, 2);
00991
00992
00993 gluQuadricOrientation(pObj, GLU_INSIDE);
00994 gluDisk(pObj, 0.0f, rad, 20, 1);
00995
00996 glTranslatef (0.0f, 0.0f, h);
00997 gluQuadricOrientation(pObj, GLU_OUTSIDE);
00998 gluDisk(pObj, 0.0f, rad, 20, 1);
00999
01000 gluDeleteQuadric(pObj);
01001 glPopMatrix();
01002 }
01003
01004 void RenderWObjectContainer::drawCylinder( const wMatrix& mat, float h, float rad, QColor c ) {
01005 GLUquadricObj *pObj;
01006
01007 glPushMatrix();
01008
01009
01010 glShadeModel( GL_SMOOTH );
01011 glColor4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
01012
01013 GLMultMatrix(&mat[0][0]);
01014
01015
01016 pObj = gluNewQuadric();
01017 gluQuadricTexture(pObj, true);
01018 gluCylinder(pObj, rad, rad, h, 20, 2);
01019
01020
01021 gluQuadricOrientation(pObj, GLU_INSIDE);
01022 gluDisk(pObj, 0.0f, rad, 20, 1);
01023
01024 glTranslatef (0.0f, 0.0f, h);
01025 gluQuadricOrientation(pObj, GLU_OUTSIDE);
01026 gluDisk(pObj, 0.0f, rad, 20, 1);
01027
01028 gluDeleteQuadric(pObj);
01029 glPopMatrix();
01030 }
01031
01032 void RenderWObjectContainer::drawWireBox( wVector dims, wMatrix matrix ) {
01033 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
01034 glPushMatrix();
01035
01036
01037 glShadeModel( GL_SMOOTH );
01038 glColor4f( 1.0f, 1.0f, 0.0f, 1.0f );
01039
01040 float hdx = (dims[0]/2.0);
01041 float hdy = (dims[1]/2.0);
01042 float hdz = (dims[2]/2.0);
01043 GLMultMatrix(&matrix[0][0]);
01044
01045
01046
01047
01048 glBegin(GL_QUADS);
01049
01050 glNormal3f(0.0, 0.0, 1.0);
01051 glVertex3f(-hdx, -hdy, hdz);
01052 glVertex3f( hdx, -hdy, hdz);
01053 glVertex3f( hdx, hdy, hdz);
01054 glVertex3f(-hdx, hdy, hdz);
01055
01056
01057 glNormal3f(0.0, 0.0, -1.0);
01058 glVertex3f( hdx, -hdy, -hdz);
01059 glVertex3f(-hdx, -hdy, -hdz);
01060 glVertex3f(-hdx, hdy, -hdz);
01061 glVertex3f( hdx, hdy, -hdz);
01062
01063
01064 glNormal3f(0.0, 1.0, 0.0);
01065 glVertex3f(-hdx, hdy, hdz);
01066 glVertex3f( hdx, hdy, hdz);
01067 glVertex3f( hdx, hdy, -hdz);
01068 glVertex3f(-hdx, hdy, -hdz);
01069
01070
01071 glNormal3f(0.0, -1.0, 0.0);
01072 glVertex3f(-hdx, -hdy, -hdz);
01073 glVertex3f( hdx, -hdy, -hdz);
01074 glVertex3f( hdx, -hdy, hdz);
01075 glVertex3f(-hdx, -hdy, hdz);
01076
01077
01078 glNormal3f(-1.0, 0.0, 0.0);
01079 glVertex3f(-hdx, -hdy, -hdz);
01080 glVertex3f(-hdx, -hdy, hdz);
01081 glVertex3f(-hdx, hdy, hdz);
01082 glVertex3f(-hdx, hdy, -hdz);
01083
01084
01085 glNormal3f(1.0, 0.0, 0.0);
01086 glVertex3f(hdx, -hdy, hdz);
01087 glVertex3f(hdx, -hdy, -hdz);
01088 glVertex3f(hdx, hdy, -hdz);
01089 glVertex3f(hdx, hdy, hdz);
01090 glEnd();
01091
01092 glPopMatrix();
01093 }
01094
01095 void RenderWObjectContainer::drawWireBox( wVector min, wVector max, const wMatrix& matrix ) {
01096 glPushMatrix();
01097 GLMultMatrix(&matrix[0][0]);
01098 drawWireBox( min, max );
01099 glPopMatrix();
01100 }
01101
01102 void RenderWObjectContainer::drawWireBox( wVector min, wVector max ) {
01103 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
01104 glPushMatrix();
01105
01106
01107 glShadeModel( GL_SMOOTH );
01108 glColor4f( 1.0f, 1.0f, 0.0f, 1.0f );
01109
01110 float dx = fabs( max[0]-min[0] );
01111 float dy = fabs( max[1]-min[1] );
01112 float dz = fabs( max[2]-min[2] );
01113 float hdx = (dx/2.0);
01114 float hdy = (dy/2.0);
01115 float hdz = (dz/2.0);
01116 float minX = qMin(min[0], max[0]);
01117 float minY = qMin(min[1], max[1]);
01118 float minZ = qMin(min[2], max[2]);
01119 glTranslatef( minX+hdx, minY+hdy, minZ+hdz );
01120
01121
01122
01123
01124 glBegin(GL_QUADS);
01125
01126 glNormal3f(0.0, 0.0, 1.0);
01127 glVertex3f(-hdx, -hdy, hdz);
01128 glVertex3f( hdx, -hdy, hdz);
01129 glVertex3f( hdx, hdy, hdz);
01130 glVertex3f(-hdx, hdy, hdz);
01131
01132
01133 glNormal3f(0.0, 0.0, -1.0);
01134 glVertex3f( hdx, -hdy, -hdz);
01135 glVertex3f(-hdx, -hdy, -hdz);
01136 glVertex3f(-hdx, hdy, -hdz);
01137 glVertex3f( hdx, hdy, -hdz);
01138
01139
01140 glNormal3f(0.0, 1.0, 0.0);
01141 glVertex3f(-hdx, hdy, hdz);
01142 glVertex3f( hdx, hdy, hdz);
01143 glVertex3f( hdx, hdy, -hdz);
01144 glVertex3f(-hdx, hdy, -hdz);
01145
01146
01147 glNormal3f(0.0, -1.0, 0.0);
01148 glVertex3f(-hdx, -hdy, -hdz);
01149 glVertex3f( hdx, -hdy, -hdz);
01150 glVertex3f( hdx, -hdy, hdz);
01151 glVertex3f(-hdx, -hdy, hdz);
01152
01153
01154 glNormal3f(-1.0, 0.0, 0.0);
01155 glVertex3f(-hdx, -hdy, -hdz);
01156 glVertex3f(-hdx, -hdy, hdz);
01157 glVertex3f(-hdx, hdy, hdz);
01158 glVertex3f(-hdx, hdy, -hdz);
01159
01160
01161 glNormal3f(1.0, 0.0, 0.0);
01162 glVertex3f(hdx, -hdy, hdz);
01163 glVertex3f(hdx, -hdy, -hdz);
01164 glVertex3f(hdx, hdy, -hdz);
01165 glVertex3f(hdx, hdy, hdz);
01166 glEnd();
01167
01168 glPopMatrix();
01169 }
01170
01171 void RenderWObjectContainer::drawTorus( real outRad, real innRad, const wMatrix& matrix, real angle, QColor c ) {
01172 glPushMatrix();
01173
01174
01175 glShadeModel( GL_SMOOTH );
01176 glColor4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
01177
01178 GLMultMatrix(&matrix[0][0]);
01179
01180 int numc = 8;
01181 int numt = 25;
01182 int i, j, k;
01183 double s, t, x, y, z, twopi;
01184 real tubeRad = (outRad-innRad)/2.0;
01185 real toruRad = outRad - tubeRad;
01186 twopi = 2 * PI_GRECO;
01187 for (i = 0; i < numc; i++) {
01188 glBegin(GL_QUAD_STRIP);
01189 for (j = 0; j <= numt; j++) {
01190 for (k = 1; k >= 0; k--) {
01191 s = (i + k) % numc + 0.5;
01192 t = j;
01193
01194 x = (toruRad+tubeRad*cos(s*twopi/numc))*cos(t*(angle)/numt);
01195 y = (toruRad+tubeRad*cos(s*twopi/numc))*sin(t*(angle)/numt);
01196 z = tubeRad * sin(s * twopi / numc);
01197 glVertex3f(x, y, z);
01198 }
01199 }
01200 glEnd();
01201 }
01202
01203 glPopMatrix();
01204 }
01205
01206 void RenderWObjectContainer::drawTorus( wVector axis, wVector centre, real outRad, real innRad, real angle ) {
01207 glPushMatrix();
01208
01209
01210 glShadeModel( GL_SMOOTH );
01211 glColor4f( 1.0f, 0.0f, 0.0f, 1.0f );
01212
01213 wMatrix tm = wMatrix::grammSchmidt( axis );
01214 tm.w_pos = centre;
01215 GLMultMatrix( &tm[0][0] );
01216
01217 int numc = 8;
01218 int numt = 25;
01219 int i, j, k;
01220 double s, t, x, y, z, twopi;
01221 real tubeRad = (outRad-innRad)/2.0;
01222 real toruRad = outRad - tubeRad;
01223 twopi = 2 * PI_GRECO;
01224 for (i = 0; i < numc; i++) {
01225 glBegin(GL_QUAD_STRIP);
01226 for (j = 0; j <= numt; j++) {
01227 for (k = 1; k >= 0; k--) {
01228 s = (i + k) % numc + 0.5;
01229 t = j;
01230
01231 x = (toruRad+tubeRad*cos(s*twopi/numc))*cos(t*(angle)/numt);
01232 y = (toruRad+tubeRad*cos(s*twopi/numc))*sin(t*(angle)/numt);
01233 z = tubeRad * sin(s * twopi / numc);
01234 glVertex3f(x, y, z);
01235 }
01236 }
01237 glEnd();
01238 }
01239
01240 glPopMatrix();
01241 }
01242
01243 void RenderWorld::drawArrow( const wVector& start, const wVector& end, float radius, int nbSubdivisions, QColor c ) {
01244 glPushMatrix();
01245 glColor4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
01246
01247 wVector zaxis = end - start;
01248 real len = zaxis.norm();
01249 zaxis.normalize();
01250 wMatrix tm = wMatrix::grammSchmidt( zaxis );
01251 tm.w_pos = start;
01252 GLMultMatrix( &tm[0][0] );
01253
01254 QGLViewer::drawArrow( len, radius, nbSubdivisions );
01255
01256 glPopMatrix();
01257 }
01258
01259 }