worldsim/src/renderwobjecthierarchy.cpp

00001 /********************************************************************************
00002  *  WorldSim -- library for robot simulations                                   *
00003  *  Copyright (C) 2008-2011 Gianluca Massera <emmegian@yahoo.it>                *
00004  *                                                                              *
00005  *  This program is free software; you can redistribute it and/or modify        *
00006  *  it under the terms of the GNU General Public License as published by        *
00007  *  the Free Software Foundation; either version 2 of the License, or           *
00008  *  (at your option) any later version.                                         *
00009  *                                                                              *
00010  *  This program is distributed in the hope that it will be useful,             *
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of              *
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
00013  *  GNU General Public License for more details.                                *
00014  *                                                                              *
00015  *  You should have received a copy of the GNU General Public License           *
00016  *  along with this program; if not, write to the Free Software                 *
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  *
00018  ********************************************************************************/
00019 
00020 #include "renderworld.h"
00021 #include "physphere.h"
00022 #include "phybox.h"
00023 #include "phycylinder.h"
00024 #include "phycone.h"
00025 #include "phyicub.h"
00026 #include "wcamera.h"
00027 #include "phycompoundobject.h"
00028 #include "wmesh.h"
00029 #include "graphicalwobject.h"
00030 #include "private/renderwobjecthierarchy.h"
00031 
00032 #include <QImage>
00033 #include <QColor>
00034 #include <QList>
00035 #include <QVector>
00036 #include <cmath>
00037 
00038 // These instructions are needed because QT 4.8 no longer depends on glu, so we
00039 // have to include it here explicitly
00040 #ifdef FARSA_MAC
00041 # include <GLUT/glut.h>
00042 #else
00043 # include <GL/glu.h>
00044 #endif
00045 
00046 using namespace qglviewer;
00047 
00048 #define GLMultMatrix glMultMatrixf
00049 // for double glMultMatrixd
00050 
00051 namespace farsa {
00052 
00057 class RenderGenericObject : public RenderWObject {
00058 public:
00059     RenderGenericObject( WObject* wobj, RenderWObjectContainer* container ) : RenderWObject( wobj, container ) {
00060         rad = 0.02f;
00061     };
00062     virtual ~RenderGenericObject() { };
00063     virtual void render( QGLContext* /*gw*/ ) {
00064     };
00065     virtual void renderAABB( RenderWorld* gw ) {
00066         wVector minpoint, maxpoint;
00067         calculateAABB( minpoint, maxpoint, obj->matrix() );
00068         gw->drawWireBox( minpoint, maxpoint );
00069     };
00070     virtual void calculateAABB( wVector& minPoint, wVector& maxPoint, const wMatrix tm ) {
00071         wVector rds( rad, rad, rad );
00072         minPoint = tm.w_pos - rds;
00073         maxPoint = tm.w_pos + rds;
00074     };
00075 
00076     virtual void calculateOBB( wVector& dimension, wVector& minPoint, wVector& maxPoint ) {
00077         dimension[0] = rad*2.0;
00078         dimension[1] = rad*2.0;
00079         dimension[2] = rad*2.0;
00080         wVector rds = wVector( rad, rad, rad );
00081         minPoint = -rds;
00082         maxPoint = +rds;
00083     };
00084 protected:
00085     real rad;
00086 };
00087 
00088 class RenderWMesh : public RenderWObject {
00089 public:
00090     RenderWMesh( WObject* wobj, RenderWObjectContainer* container ) : RenderWObject( wobj, container ) {
00091         wmesh = (WMesh*)wobj;
00092     };
00093     virtual ~RenderWMesh() { };
00094     virtual void render( QGLContext* gw ) {
00095         glPushMatrix();
00096         wMatrix m = wmesh->matrix();
00097         if ( wmesh->attachedTo() ) {
00098             m = m * wmesh->attachedTo()->matrix();
00099         }
00100         GLMultMatrix(&m[0][0]);
00101         int m_numMeshes = wmesh->meshesCount();
00102         WMesh::Mesh *m_pMeshes = wmesh->meshes();
00103 //      int m_numMaterials = wmesh->materialsCount();
00104         WMesh::Material *m_pMaterials = wmesh->materials();
00105 //      int m_numTriangles = wmesh->trianglesCount();
00106         WMesh::Triangle *m_pTriangles = wmesh->triangles();
00107 //      int m_numVertices = wmesh->verticesCount();
00108         WMesh::Vertex *m_pVertices = wmesh->vertices();
00109         for ( int i = 0; i < m_numMeshes; i++ ) {
00110             int materialIndex = m_pMeshes[i].m_materialIndex;
00111             if ( materialIndex >= 0 ) {
00112                 glMaterialfv( GL_FRONT, GL_AMBIENT,   m_pMaterials[materialIndex].m_ambient );
00113                 glMaterialfv( GL_FRONT, GL_DIFFUSE,   m_pMaterials[materialIndex].m_diffuse );
00114                 glMaterialfv( GL_FRONT, GL_SPECULAR,  m_pMaterials[materialIndex].m_specular );
00115                 glMaterialfv( GL_FRONT, GL_EMISSION,  m_pMaterials[materialIndex].m_emissive );
00116                 glMaterialf(  GL_FRONT, GL_SHININESS, m_pMaterials[materialIndex].m_shininess );
00117                 //container()->applyTexture( gw, wmesh->texture() );
00118                 container()->setupColorTexture( gw, this );
00119             }
00120             glBegin( GL_TRIANGLES );
00121             for ( int j = 0; j < m_pMeshes[i].m_numTriangles; j++ ) {
00122                 int triangleIndex = m_pMeshes[i].m_pTriangleIndices[j];
00123                 const WMesh::Triangle* pTri = &m_pTriangles[triangleIndex];
00124                 for ( int k = 0; k < 3; k++ ) {
00125                     int index = pTri->m_vertexIndices[k];
00126                     glNormal3fv( pTri->m_vertexNormals[k] );
00127                     glTexCoord2f( pTri->m_s[k], pTri->m_t[k] );
00128                     glVertex3fv( m_pVertices[index].m_location );
00129                 }
00130             }
00131             glEnd();
00132         }
00133         glPopMatrix();
00134     };
00135     virtual void renderAABB( RenderWorld* /*gw*/ ) {
00136     };
00137     virtual void calculateAABB( wVector& /*minPoint*/, wVector& /*maxPoint*/, const wMatrix /*tm*/ ) {
00138     };
00139     virtual void calculateOBB( wVector& /*dimension*/, wVector& /*minPoint*/, wVector& /*maxPoint*/ ) {
00140     };
00141 private:
00142     WMesh* wmesh;
00143 };
00144 
00145 class RenderPhyBox : public RenderWObject {
00146 public:
00147     RenderPhyBox( WObject* wobj, RenderWObjectContainer* container ) : RenderWObject( wobj, container ) {
00148         box = (PhyBox*)wobj;
00149         dx = box->sideX();
00150         dy = box->sideY();
00151         dz = box->sideZ();
00152     };
00153     virtual ~RenderPhyBox() { };
00154     virtual void render( QGLContext* gw ) {
00155         glPushMatrix();
00156         container()->setupColorTexture( gw, this );
00157         const wMatrix& m = box->matrix();
00158         GLMultMatrix(&m[0][0]);
00159         
00160         // the cube will just be drawn as six quads for the sake of simplicity
00161         // for each face, we specify the quad's normal (for lighting), then
00162         // specify the quad's 4 vertices and associated texture coordinates
00163         glBegin(GL_QUADS);
00164         float hdx = (dx/2.0);
00165         float hdy = (dy/2.0);
00166         float hdz = (dz/2.0);
00167         // front
00168         glNormal3f(0.0, 0.0, 1.0);
00169         glTexCoord2f(0.0, 0.0); glVertex3f(-hdx, -hdy, hdz);
00170         glTexCoord2f(1.0, 0.0); glVertex3f( hdx, -hdy, hdz);
00171         glTexCoord2f(1.0, 1.0); glVertex3f( hdx,  hdy, hdz);
00172         glTexCoord2f(0.0, 1.0); glVertex3f(-hdx,  hdy, hdz);
00173         
00174         // back
00175         glNormal3f(0.0, 0.0, -1.0);
00176         glTexCoord2f(0.0, 0.0); glVertex3f( hdx, -hdy, -hdz);
00177         glTexCoord2f(1.0, 0.0); glVertex3f(-hdx, -hdy, -hdz);
00178         glTexCoord2f(1.0, 1.0); glVertex3f(-hdx,  hdy, -hdz);
00179         glTexCoord2f(0.0, 1.0); glVertex3f( hdx,  hdy, -hdz);
00180         
00181         // top
00182         glNormal3f(0.0, 1.0, 0.0);
00183         glTexCoord2f(0.0, 0.0); glVertex3f(-hdx,  hdy,  hdz);
00184         glTexCoord2f(1.0, 0.0); glVertex3f( hdx,  hdy,  hdz);
00185         glTexCoord2f(1.0, 1.0); glVertex3f( hdx,  hdy, -hdz);
00186         glTexCoord2f(0.0, 1.0); glVertex3f(-hdx,  hdy, -hdz);
00187         
00188         // bottom
00189         glNormal3f(0.0, -1.0, 0.0);
00190         glTexCoord2f(0.0, 0.0); glVertex3f(-hdx, -hdy, -hdz);
00191         glTexCoord2f(1.0, 0.0); glVertex3f( hdx, -hdy, -hdz);
00192         glTexCoord2f(1.0, 1.0); glVertex3f( hdx, -hdy,  hdz);
00193         glTexCoord2f(0.0, 1.0); glVertex3f(-hdx, -hdy,  hdz);
00194         
00195         // left
00196         glNormal3f(-1.0, 0.0, 0.0);
00197         glTexCoord2f(0.0, 0.0); glVertex3f(-hdx, -hdy, -hdz);
00198         glTexCoord2f(1.0, 0.0); glVertex3f(-hdx, -hdy,  hdz);
00199         glTexCoord2f(1.0, 1.0); glVertex3f(-hdx,  hdy,  hdz);
00200         glTexCoord2f(0.0, 1.0); glVertex3f(-hdx,  hdy, -hdz);
00201         
00202         // right
00203         glNormal3f(1.0, 0.0, 0.0);
00204         glTexCoord2f(0.0, 0.0); glVertex3f(hdx,  -hdy,  hdz);
00205         glTexCoord2f(1.0, 0.0); glVertex3f(hdx,  -hdy, -hdz);
00206         glTexCoord2f(1.0, 1.0); glVertex3f(hdx,   hdy, -hdz);
00207         glTexCoord2f(0.0, 1.0); glVertex3f(hdx,   hdy,  hdz);
00208         
00209         glEnd();
00210         glPopMatrix();
00211     };
00212     virtual void renderAABB( RenderWorld* gw ) {
00213         wVector minpoint, maxpoint;
00214         calculateAABB( minpoint, maxpoint, obj->matrix() );
00215         gw->drawWireBox( minpoint, maxpoint );
00216     };
00217     virtual void calculateAABB( wVector& minPoint, wVector& maxPoint, const wMatrix tm ) {
00218         real tdx = fabs(tm.x_ax[0]*dx) + fabs(tm.y_ax[0]*dy) + fabs(tm.z_ax[0]*dz);
00219         real tdy = fabs(tm.x_ax[1]*dx) + fabs(tm.y_ax[1]*dy) + fabs(tm.z_ax[1]*dz);
00220         real tdz = fabs(tm.x_ax[2]*dx) + fabs(tm.y_ax[2]*dy) + fabs(tm.z_ax[2]*dz);
00221 
00222         wVector hds( tdx/2.0, tdy/2.0, tdz/2.0 );
00223         minPoint = tm.w_pos - hds;
00224         maxPoint = tm.w_pos + hds;
00225     };
00226 
00227     virtual void calculateOBB( wVector& dimension, wVector& minPoint, wVector& maxPoint ) {
00228         dimension[0] = dx;
00229         dimension[1] = dy;
00230         dimension[2] = dz;
00231         wVector hds( dx/2.0, dy/2.0, dz/2.0 );
00232         minPoint = -hds;
00233         maxPoint = +hds;
00234     };
00235 
00236 protected:
00237     PhyBox* box;
00238     real dx, dy, dz;
00239 };
00240 
00241 class RenderPhySphere : public RenderWObject {
00242 public:
00243     RenderPhySphere( WObject* wobj, RenderWObjectContainer* container ) : RenderWObject( wobj, container ) {
00244         sph = (PhySphere*)wobj;
00245         rad = sph->radius();
00246     };
00247     virtual ~RenderPhySphere() { };
00248     virtual void render( QGLContext* gw ) {
00249         glPushMatrix();
00250         GLUquadricObj *pObj;
00251         container()->setupColorTexture( gw, this );
00252         wMatrix mat = sph->matrix();
00253         mat.x_ax = mat.x_ax.scale( rad );
00254         mat.y_ax = mat.y_ax.scale( rad );
00255         mat.z_ax = mat.z_ax.scale( rad );
00256         GLMultMatrix(&mat[0][0]);
00257     
00258         // Get a new Quadric off the stack
00259         pObj = gluNewQuadric();
00260         // Get a new Quadric off the stack
00261         gluQuadricTexture(pObj, true);
00262         gluSphere(pObj, 1.0f, 20, 20);
00263         gluDeleteQuadric(pObj);
00264         glPopMatrix();
00265     };
00266     virtual void renderAABB( RenderWorld* gw ) {
00267         wVector minpoint, maxpoint;
00268         calculateAABB( minpoint, maxpoint, obj->matrix() );
00269         gw->drawWireBox( minpoint, maxpoint );
00270     };
00271     virtual void calculateAABB( wVector& minPoint, wVector& maxPoint, const wMatrix tm ) {
00272         wVector rds( rad, rad, rad );
00273         minPoint = tm.w_pos - rds;
00274         maxPoint = tm.w_pos + rds;
00275     };
00276 
00277     virtual void calculateOBB( wVector& dimension, wVector& minPoint, wVector& maxPoint ) {
00278         dimension[0] = rad*2.0;
00279         dimension[1] = rad*2.0;
00280         dimension[2] = rad*2.0;
00281         wVector rds = wVector( rad, rad, rad );
00282         minPoint = -rds;
00283         maxPoint = +rds;
00284     };
00285 protected:
00286     PhySphere* sph;
00287     real rad;
00288 };
00289 
00290 class RenderPhyCylinder : public RenderWObject {
00291 public:
00292     RenderPhyCylinder( WObject* wobj, RenderWObjectContainer* container ) : RenderWObject( wobj, container ) {
00293         cil = (PhyCylinder*)wobj;
00294         rad = cil->radius();
00295         hei = cil->height();
00296     };
00297     virtual ~RenderPhyCylinder() { };
00298     virtual void render( QGLContext* gw ) {
00299         glPushMatrix();
00300         GLUquadricObj *pObj;
00301         container()->setupColorTexture( gw, this );
00302     
00303         // opengl cylinder are aligned alogn the z axis, we want it along the x axis,
00304         // we create a rotation matrix to do the alignment
00305         wMatrix matrix = wMatrix::yaw( PI_GRECO * 0.5f );
00306         matrix.w_pos = matrix.rotateVector( wVector(0.0, 0.0, -hei*0.5f) );
00307         matrix = matrix * cil->matrix();
00308         GLMultMatrix(&matrix[0][0]);
00309             
00310         // Get a new Quadric off the stack
00311         pObj = gluNewQuadric();
00312         gluQuadricTexture(pObj, true);
00313         gluCylinder(pObj, rad, rad, hei, 20, 2);
00314     
00315         // render the caps
00316         gluQuadricOrientation(pObj, GLU_INSIDE);
00317         gluDisk(pObj, 0.0f, rad, 20, 1);
00318     
00319         glTranslatef (0.0f, 0.0f, hei);
00320         gluQuadricOrientation(pObj, GLU_OUTSIDE);
00321         gluDisk(pObj, 0.0f, rad, 20, 1);
00322     
00323         gluDeleteQuadric(pObj);
00324         glPopMatrix();
00325     };
00326     virtual void renderAABB( RenderWorld* gw ) {
00327         wVector minpoint, maxpoint;
00328         calculateAABB( minpoint, maxpoint, obj->matrix() );
00329         gw->drawWireBox( minpoint, maxpoint );
00330     };
00331     virtual void calculateAABB( wVector& minPoint, wVector& maxPoint, const wMatrix tm ) {
00332         real h2 = hei/2.0;
00333         real tdx = fabs(tm.x_ax[0]*h2) + fabs(tm.y_ax[0]*rad) + fabs(tm.z_ax[0]*rad);
00334         real tdy = fabs(tm.x_ax[1]*h2) + fabs(tm.y_ax[1]*rad) + fabs(tm.z_ax[1]*rad);
00335         real tdz = fabs(tm.x_ax[2]*h2) + fabs(tm.y_ax[2]*rad) + fabs(tm.z_ax[2]*rad);
00336         wVector hds( tdx, tdy, tdz );
00337         minPoint = tm.w_pos - hds;
00338         maxPoint = tm.w_pos + hds;
00339     };
00340 
00341     virtual void calculateOBB( wVector& dimension, wVector& minPoint, wVector& maxPoint ) {
00342         dimension[0] = hei;
00343         dimension[1] = rad*2.0;
00344         dimension[2] = rad*2.0;
00345         wVector rds = wVector( hei/2.0, rad, rad );
00346         minPoint = -rds;
00347         maxPoint = +rds;
00348     };
00349 protected:
00350     PhyCylinder* cil;
00351     real rad;
00352     real hei;
00353 };
00354 
00355 class RenderPhyCone : public RenderWObject {
00356 public:
00357     RenderPhyCone( WObject* wobj, RenderWObjectContainer* container ) : RenderWObject( wobj, container ) {
00358         cone = (PhyCone*)wobj;
00359         rad = cone->radius();
00360         hei = cone->height();
00361     };
00362     virtual ~RenderPhyCone() { };
00363     virtual void render( QGLContext* gw ) {
00364         glPushMatrix();
00365         GLUquadricObj *pObj;
00366         container()->setupColorTexture( gw, this );
00367     
00368         // opengl cylinder are aligned alogn the z axis, we want it along the x axis,
00369         // we create a rotation matrix to do the alignment
00370         wMatrix matrix = wMatrix::yaw( PI_GRECO * 0.5 );
00371         matrix.w_pos = matrix.rotateVector( wVector(0.0, 0.0, -hei*0.5) );
00372         matrix = matrix * cone->matrix();
00373         GLMultMatrix(&matrix[0][0]);
00374             
00375         // Get a new Quadric off the stack
00376         pObj = gluNewQuadric();
00377         gluQuadricTexture(pObj, true);
00378         gluCylinder(pObj, rad, 0, hei, 20, 2);
00379     
00380         // render the caps
00381         gluQuadricOrientation(pObj, GLU_INSIDE);
00382         gluDisk(pObj, 0.0f, rad, 20, 1);
00383         
00384         gluDeleteQuadric(pObj);
00385         glPopMatrix();
00386     };
00387     virtual void renderAABB( RenderWorld* gw ) {
00388         wVector minpoint, maxpoint;
00389         calculateAABB( minpoint, maxpoint, obj->matrix() );
00390         gw->drawWireBox( minpoint, maxpoint );
00391     };
00392     virtual void calculateAABB( wVector& minPoint, wVector& maxPoint, const wMatrix tm ) {
00393         real h2 = hei/2.0;
00394         real tdx = fabs(tm.x_ax[0]*h2) + fabs(tm.y_ax[0]*rad) + fabs(tm.z_ax[0]*rad);
00395         real tdy = fabs(tm.x_ax[1]*h2) + fabs(tm.y_ax[1]*rad) + fabs(tm.z_ax[1]*rad);
00396         real tdz = fabs(tm.x_ax[2]*h2) + fabs(tm.y_ax[2]*rad) + fabs(tm.z_ax[2]*rad);
00397         wVector hds( tdx, tdy, tdz );
00398         minPoint = tm.w_pos - hds;
00399         maxPoint = tm.w_pos + hds;
00400     };
00401 
00402     virtual void calculateOBB( wVector& dimension, wVector& minPoint, wVector& maxPoint ) {
00403         dimension[0] = hei;
00404         dimension[1] = rad*2.0;
00405         dimension[2] = rad*2.0;
00406         wVector rds = wVector( hei/2.0, rad, rad );
00407         minPoint = -rds;
00408         maxPoint = +rds;
00409     };
00410 protected:
00411     PhyCone* cone;
00412     real rad;
00413     real hei;
00414 };
00415 
00416 #ifdef FARSA_USE_YARP_AND_ICUB
00417 
00418 RenderICub::RenderICub( WObject* wobj, RenderWObjectContainer* container ) :
00419     RenderWObject( wobj, container )
00420 {
00421     icub = (PhyiCub*)wobj;
00422     icub->forceKinematicChainsUpdate(true);
00423     initRobjv(container);
00424 }
00425 
00426 RenderICub::~RenderICub()
00427 {
00428     if (icub != NULL) {
00429         icub->forceKinematicChainsUpdate(false);
00430     }
00431 }
00432 
00433 void RenderICub::render( QGLContext* gw )
00434 {
00435     // Nothing to do here, all components are rendered by their respective renderers
00436 }
00437 
00438 void RenderICub::renderAABB( RenderWorld* gw )
00439 {
00440     wVector minpoint, maxpoint;
00441     calculateAABB( minpoint, maxpoint, obj->matrix() );
00442     gw->drawWireBox( minpoint, maxpoint );
00443 }
00444 
00445 void RenderICub::calculateAABB( wVector& minPoint, wVector& maxPoint, const wMatrix tm )
00446 {
00447     UNUSED_PARAM( tm );
00448     QList<RenderWObject*> robjs = robjv.values();
00449     robjs[0]->calculateAABB( minPoint, maxPoint, robjs[0]->object()->matrix() );
00450     wVector minP, maxP;
00451     for( int i=1; i<robjs.size(); i++ ) {
00452         robjs[i]->calculateAABB( minP, maxP, robjs[i]->object()->matrix() );
00453         mergeAABB( minPoint, maxPoint, minP, maxP );
00454     }
00455 }
00456 
00457 void RenderICub::calculateOBB( wVector& dimension, wVector& minPoint, wVector& maxPoint )
00458 {
00459     /* ***
00460     wVector minPoint, maxPoint;
00461     wMatrix tm = wMatrix::identity();
00462     for( int i=1; i<robjv.size(); i++ ) {
00463         robjv[i]->calculateAABB( minP, maxP, tm );
00464         mergeAABB( minPoint, maxPoint, minP, maxP );
00465     }
00466     *** */
00467     calculateAABB( minPoint, maxPoint, wMatrix::identity() );
00468     dimension[0] = fabs( maxPoint[0] - minPoint[0] );
00469     dimension[1] = fabs( maxPoint[1] - minPoint[1] );
00470     dimension[2] = fabs( maxPoint[2] - minPoint[2] );
00471 }
00472 
00473 void RenderICub::objectAlreadyDestroyed()
00474 {
00475     icub = NULL;
00476 }
00477 
00478 void RenderICub::initRobjv( RenderWObjectContainer* container )
00479 {
00480     robjv.clear();
00481     foreach( RenderWObject* wobj, container->graphics() ) {
00482         if ( wobj->object()->owner() == icub ) {
00483             robjv[wobj->object()] = wobj;
00484         }
00485     }
00486     foreach( WObject* obj, icub->leftLeg() ) {
00487         obj->setUseColorTextureOfOwner(true);
00488     }
00489     foreach( WObject* obj, icub->rightLeg() ) {
00490         obj->setUseColorTextureOfOwner(true);
00491     }
00492     foreach( WObject* obj, icub->torso() ) {
00493         obj->setUseColorTextureOfOwner(true);
00494     }
00495     foreach( WObject* obj, icub->leftArm() ) {
00496         obj->setUseColorTextureOfOwner(true);
00497     }
00498     foreach( WObject* obj, icub->rightArm() ) {
00499         obj->setUseColorTextureOfOwner(true);
00500     }
00501     int i = 0;
00502     foreach( WObject* obj, icub->headNeck() ) {
00503         //--- the eye will be displayed with the texture of the eye
00504         if ( ( i == 4 ) || ( i == 5 ) ) {
00505             obj->setUseColorTextureOfOwner(false);
00506         } else {
00507             obj->setUseColorTextureOfOwner(true);
00508         }
00509         i++;
00510     }
00511     foreach( WObject* obj, icub->covers() ) {
00512         obj->setUseColorTextureOfOwner(false);
00513     }
00514 }
00515 
00516 void RenderICub::mergeAABB( wVector& minPointA, wVector& maxPointA, const wVector& minPointB, const wVector& maxPointB )
00517 {
00518     minPointA[0] = min( minPointA[0], minPointB[0] );
00519     minPointA[1] = min( minPointA[1], minPointB[1] );
00520     minPointA[2] = min( minPointA[2], minPointB[2] );
00521     maxPointA[0] = max( maxPointA[0], maxPointB[0] );
00522     maxPointA[1] = max( maxPointA[1], maxPointB[1] );
00523     maxPointA[2] = max( maxPointA[2], maxPointB[2] );
00524 }
00525 
00526 #endif
00527 
00528 class RenderCompoundObject : public RenderWObject {
00529 public:
00530     RenderCompoundObject( WObject* wobj, RenderWObjectContainer* container ) : RenderWObject( wobj, container ) {
00531         co = (PhyCompoundObject*)wobj;
00532         initRobjv( container );
00533     };
00534     virtual ~RenderCompoundObject() {
00535         foreach( RenderWObject* ro, robjv ) {
00536             delete ro;
00537         }
00538     };
00539     virtual void render( QGLContext* gw ) {
00540         glPushMatrix();
00541         container()->setupColorTexture( gw, this );
00542         wMatrix matrix = co->matrix();
00543         GLMultMatrix(&matrix[0][0]);
00544         foreach( RenderWObject* ro, robjv ) {
00545             ro->render( gw );
00546         }
00547         glPopMatrix();
00548     };
00549     virtual void renderAABB( RenderWorld* gw ) {
00550         wVector minpoint, maxpoint;
00551         calculateAABB( minpoint, maxpoint, obj->matrix() );
00552         gw->drawWireBox( minpoint, maxpoint );
00553     };
00554     virtual void calculateAABB( wVector& minPoint, wVector& maxPoint, const wMatrix tm ) {
00555         robjv[0]->calculateAABB( minPoint, maxPoint, robjv[0]->object()->matrix()*tm );
00556         wVector minP, maxP;
00557         for( int i=1; i<robjv.size(); i++ ) {
00558             robjv[i]->calculateAABB( minP, maxP, robjv[i]->object()->matrix()*tm );
00559             mergeAABB( minPoint, maxPoint, minP, maxP );
00560         }
00561     };
00562     virtual void calculateOBB( wVector& dimension, wVector& minPoint, wVector& maxPoint ) {
00563         //--- the right calculation is done calculating the AABB when
00564         //--- the transformation matrix is the identity
00565         wVector minP, maxP;
00566         if ( robjv.size() == 0 ) {
00567             qWarning( "== this point should never reached: renderwobjecthierarchy.cpp:435" );
00568             return;
00569         }
00570         robjv[0]->calculateAABB( minPoint, maxPoint, robjv[0]->object()->matrix() );
00571         for( int i=1; i<robjv.size(); i++ ) {
00572             robjv[i]->calculateAABB( minP, maxP, robjv[i]->object()->matrix() );
00573             mergeAABB( minPoint, maxPoint, minP, maxP );
00574         }
00575         dimension[0] = fabs( maxPoint[0] - minPoint[0] );
00576         dimension[1] = fabs( maxPoint[1] - minPoint[1] );
00577         dimension[2] = fabs( maxPoint[2] - minPoint[2] );
00578     };
00579 protected:
00580     PhyCompoundObject* co;
00581     QVector<RenderWObject*> robjv;
00582 private:
00583     void initRobjv( RenderWObjectContainer* container ) {
00584         foreach( WObject* obj, co->bodies() ) {
00585             robjv << RenderWObjectContainer::createRenderWObjectFor( obj, container );
00586         }
00587     };
00588     void mergeAABB( wVector& minPointA, wVector& maxPointA, const wVector& minPointB, const wVector& maxPointB ) {
00589         minPointA[0] = min( minPointA[0], minPointB[0] );
00590         minPointA[1] = min( minPointA[1], minPointB[1] );
00591         minPointA[2] = min( minPointA[2], minPointB[2] );
00592         maxPointA[0] = max( maxPointA[0], maxPointB[0] );
00593         maxPointA[1] = max( maxPointA[1], maxPointB[1] );
00594         maxPointA[2] = max( maxPointA[2], maxPointB[2] );
00595     };
00596 };
00597 
00598 #ifdef FARSA_USE_YARP_AND_ICUB
00599 
00600 class RenderWCamera : public RenderWObject {
00601 public:
00602     RenderWCamera( WObject* wobj, RenderWObjectContainer* container ) : RenderWObject( wobj, container ) {
00603         wcam = (WCamera*)(wobj);
00604         dx = 0.015f;
00605         dy = 0.01f;
00606         dz = 0.025f;
00607     };
00608     virtual ~RenderWCamera() { };
00609     virtual void render( QGLContext* gw ) {
00610         if ( wcam->attachedTo() != NULL ) return;
00611         glPushMatrix();
00612         container()->setupColorTexture( gw, this );
00613         const wMatrix& m = wcam->matrix();
00614         GLMultMatrix(&m[0][0]);
00615         // the cube will just be drawn as six quads for the sake of simplicity
00616         // for each face, we specify the quad's normal (for lighting), then
00617         // specify the quad's 4 vertices and associated texture coordinates
00618         glBegin(GL_QUADS);
00619         float hdx = (dx/2.0);
00620         float hdy = (dy/2.0);
00621         float hdz = (dz/2.0);
00622         // front
00623         glNormal3f(0.0, 0.0, 1.0);
00624         glTexCoord2f(0.0, 0.0); glVertex3f(-hdx, -hdy, hdz);
00625         glTexCoord2f(1.0, 0.0); glVertex3f( hdx, -hdy, hdz);
00626         glTexCoord2f(1.0, 1.0); glVertex3f( hdx,  hdy, hdz);
00627         glTexCoord2f(0.0, 1.0); glVertex3f(-hdx,  hdy, hdz);
00628         // back
00629         glNormal3f(0.0, 0.0, -1.0);
00630         glTexCoord2f(0.0, 0.0); glVertex3f( hdx, -hdy, -hdz);
00631         glTexCoord2f(1.0, 0.0); glVertex3f(-hdx, -hdy, -hdz);
00632         glTexCoord2f(1.0, 1.0); glVertex3f(-hdx,  hdy, -hdz);
00633         glTexCoord2f(0.0, 1.0); glVertex3f( hdx,  hdy, -hdz);
00634         // top
00635         glNormal3f(0.0, 1.0, 0.0);
00636         glTexCoord2f(0.0, 0.0); glVertex3f(-hdx,  hdy,  hdz);
00637         glTexCoord2f(1.0, 0.0); glVertex3f( hdx,  hdy,  hdz);
00638         glTexCoord2f(1.0, 1.0); glVertex3f( hdx,  hdy, -hdz);
00639         glTexCoord2f(0.0, 1.0); glVertex3f(-hdx,  hdy, -hdz);
00640         // bottom
00641         glNormal3f(0.0, -1.0, 0.0);
00642         glTexCoord2f(0.0, 0.0); glVertex3f(-hdx, -hdy, -hdz);
00643         glTexCoord2f(1.0, 0.0); glVertex3f( hdx, -hdy, -hdz);
00644         glTexCoord2f(1.0, 1.0); glVertex3f( hdx, -hdy,  hdz);
00645         glTexCoord2f(0.0, 1.0); glVertex3f(-hdx, -hdy,  hdz);
00646         // left
00647         glNormal3f(-1.0, 0.0, 0.0);
00648         glTexCoord2f(0.0, 0.0); glVertex3f(-hdx, -hdy, -hdz);
00649         glTexCoord2f(1.0, 0.0); glVertex3f(-hdx, -hdy,  hdz);
00650         glTexCoord2f(1.0, 1.0); glVertex3f(-hdx,  hdy,  hdz);
00651         glTexCoord2f(0.0, 1.0); glVertex3f(-hdx,  hdy, -hdz);
00652         // right
00653         glNormal3f(1.0, 0.0, 0.0);
00654         glTexCoord2f(0.0, 0.0); glVertex3f(hdx,  -hdy,  hdz);
00655         glTexCoord2f(1.0, 0.0); glVertex3f(hdx,  -hdy, -hdz);
00656         glTexCoord2f(1.0, 1.0); glVertex3f(hdx,   hdy, -hdz);
00657         glTexCoord2f(0.0, 1.0); glVertex3f(hdx,   hdy,  hdz);
00658         glEnd();
00659 
00660         //--- some fancy stuff for understanding the orientation of camera
00661         container()->drawCylinder( wVector(0,1,0), wVector(-hdx-0.006f,0,hdz-0.006f), 0.004f, 0.008f );
00662         container()->drawCylinder( wVector(0,1,0), wVector(-hdx,0,-hdz), 0.004f, 0.008f );
00663         container()->drawCylinder( wVector(0,0,1), wVector(0,0.0,hdz+0.003f), 0.006f, 0.004f );
00664         glPopMatrix();
00665     };
00666     virtual void renderAABB( RenderWorld* gw ) {
00667         wVector minpoint, maxpoint;
00668         calculateAABB( minpoint, maxpoint, obj->matrix() );
00669         gw->drawWireBox( minpoint, maxpoint );
00670     };
00671     virtual void calculateAABB( wVector& minPoint, wVector& maxPoint, const wMatrix tm ) {
00672         real tdx = fabs(tm.x_ax[0]*dx) + fabs(tm.y_ax[0]*dy) + fabs(tm.z_ax[0]*dz);
00673         real tdy = fabs(tm.x_ax[1]*dx) + fabs(tm.y_ax[1]*dy) + fabs(tm.z_ax[1]*dz);
00674         real tdz = fabs(tm.x_ax[2]*dx) + fabs(tm.y_ax[2]*dy) + fabs(tm.z_ax[2]*dz);
00675         wVector hds( tdx/2.0, tdy/2.0, tdz/2.0 );
00676         minPoint = tm.w_pos - hds;
00677         maxPoint = tm.w_pos + hds;
00678     };
00679     virtual void calculateOBB( wVector& dimension, wVector& minPoint, wVector& maxPoint ) {
00680         dimension[0] = dx;
00681         dimension[1] = dy;
00682         dimension[2] = dz;
00683         wVector hds( dx/2.0, dy/2.0, dz/2.0 );
00684         minPoint = -hds;
00685         maxPoint = +hds;
00686     };
00687 protected:
00688     WCamera* wcam;
00689     real dx, dy, dz;
00690 };
00691 
00692 #endif // FARSA_USE_YARP_AND_ICUB
00693 
00694 // This class is the renderer associated with GraphicalWObject. It simply
00695 // forwards calls to GraphicalWObject functions
00696 class GraphicalWObjectRenderer : public RenderWObject
00697 {
00698 public:
00699     GraphicalWObjectRenderer(WObject* obj, RenderWObjectContainer* rw) :
00700         RenderWObject(obj, rw),
00701         m_graphicalWObject(dynamic_cast<GraphicalWObject*>(obj))
00702     {
00703     }
00704 
00705     virtual ~GraphicalWObjectRenderer()
00706     {
00707     }
00708 
00709     virtual void render(QGLContext *gw)
00710     {
00711         m_graphicalWObject->updateAndRender(this, gw);
00712     }
00713 
00714     virtual void renderAABB(RenderWorld *gw)
00715     {
00716         m_graphicalWObject->updateAndRenderAABB(this, gw);
00717     }
00718 
00719     virtual void calculateAABB(wVector &minPoint, wVector &maxPoint, const wMatrix tm)
00720     {
00721         m_graphicalWObject->updateAndCalculateAABB(minPoint, maxPoint, tm);
00722     }
00723 
00724     virtual void calculateOBB(wVector &dimension, wVector &minPoint, wVector &maxPoint)
00725     {
00726         m_graphicalWObject->updateAndCalculateOBB(dimension, minPoint, maxPoint);
00727     }
00728 
00729 private:
00730     GraphicalWObject *const m_graphicalWObject;
00731 };
00732 
00733 bool RenderWObjectContainer::facInited = false;
00734 QMap<QString, WAbstractCreator*>* RenderWObjectContainer::fac;
00735 void RenderWObjectContainer::initFactory() {
00736     if ( facInited ) return;
00737 
00738     fac = new QMap<QString, WAbstractCreator*>();
00739 
00740     (*fac)["farsa::WMesh"] = new WCreator<RenderWMesh>();
00741     (*fac)["farsa::PhyBox"] = new WCreator<RenderPhyBox>();
00742     (*fac)["farsa::PhySphere"] = new WCreator<RenderPhySphere>();
00743     (*fac)["farsa::PhyCylinder"] = new WCreator<RenderPhyCylinder>();
00744     (*fac)["farsa::PhyCone"] = new WCreator<RenderPhyCone>();
00745     (*fac)["farsa::PhyCompoundObject"] = new WCreator<RenderCompoundObject>();
00746 #ifdef FARSA_USE_YARP_AND_ICUB
00747     (*fac)["farsa::WCamera"] = new WCreator<RenderWCamera>();
00748     (*fac)[PhyiCub::staticMetaObject.className()] = new WCreator<RenderICub>();
00749 #endif
00750     (*fac)["farsa::GraphicalWObject"] = new WCreator<GraphicalWObjectRenderer>();
00751 
00752     //--- FIXME a specific class should be implemented
00753     (*fac)["farsa::WObject"] = new WCreator<RenderGenericObject>();
00754     (*fac)["farsa::WorldController"] = new WCreator<RenderGenericObject>();
00755 
00756     facInited = true;
00757 }
00758 
00759 } // end namespace farsa