#include "viewer.h" #include "object.h" #include "cube.h" #include using namespace std; using namespace qglviewer; namespace { void getAABB(const QVector& objects,dReal aabb[6]) { dGeomGetAABB(objects[0]->geom,aabb); foreach (Object *o,objects) { dReal aabb[6]; dGeomGetAABB(o->geom,aabb); for (int i=0;i<3;++i) { aabb[ i] = min(aabb[ i],aabb[ i]); aabb[3+i] = max(aabb[3+i],aabb[3+i]); } } } void renderPlane(dVector4 equation,float size) { Vec z = Vec(equation).unit(); Vec o = equation[3]*z; Vec x = z.orthogonalVec().unit(); Vec y = (z^x).unit(); glBegin(GL_QUADS); glNormal3fv(z); glVertex3fv(o-size*x-size*y); glVertex3fv(o+size*x-size*y); glVertex3fv(o+size*x+size*y); glVertex3fv(o-size*x+size*y); glEnd(); } void nearCallback(void *data, dGeomID o0, dGeomID o1) { reinterpret_cast(data)->handleCollisionBetween(o0,o1); } } Viewer::Viewer(QWidget *parent) : QGLViewer(QGLFormat(QGL::SampleBuffers | QGL::DoubleBuffer | QGL::DepthBuffer | QGL::Rgba | QGL::AlphaChannel | QGL::StencilBuffer),parent) { //////////////////////////////////////////////////////////// // Create world, collision space and contact group //////////////////////////////////////////////////////////// _world = dWorldCreate(); _space = dHashSpaceCreate(0); // Set up gravity force dWorldSetGravity (_world,0,0,-9.81); // Create contact group _contactgroup = dJointGroupCreate(0); //////////////////////////////////////////////////////////// // Creating objects ////////////////////////////////////////////////////////////s static const int nb = 5; for (int k=0;k<3;++k) { float z = 2.0+0.15*k; for (int i=-nb;i<=nb;++i) { float x = 0.15*i+(k%2)*0.01; for (int j=-nb;j<=nb;++j) { float y = 0.15*j+(k%2)*0.01; Cube *cube = new Cube(_world,_space,0.1,0.1,0.1,1); cube->setPosition(x,y,z); cube->color[0] = qrand()%255; cube->color[1] = qrand()%255; cube->color[2] = qrand()%255; _objects.push_back(cube); } } } // Create static planes _planes.push_back(dCreatePlane(_space,0,0,1,0)); _planes.push_back(dCreatePlane(_space,1,0,1,0.5)); // Compute the bounding box getAABB(_objects,_aabb); } Viewer::~Viewer() { ////////////////////////////////////////////////////////////// // Deleting objects ////////////////////////////////////////////////////////////// qDeleteAll(_objects); ////////////////////////////////////////////////////////////// // Terminate with ODE ////////////////////////////////////////////////////////////// dSpaceDestroy(_space); dWorldDestroy(_world); dCloseODE(); } void Viewer::init() { Vec min(_aabb); Vec max(_aabb+3); Vec center = (min+max)/2.0f; center.z = 0.0f; setSceneRadius((max-min).norm()); setSceneCenter(center); // Try to restore previous state or focus the whole scene if (!restoreStateFromFile()) { showEntireScene(); } // Setup OpenGL GLfloat ambient[] = { 0.3f, 0.3f, 0.3f }; GLfloat diffuse[] = { 0.1f, 0.1f, 0.1f , 1.0f}; GLfloat specular[] = { 0.0f, 0.0f, 0.0f , 1.0f}; glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, specular); } void Viewer::draw() { // Draw the objects foreach (Object *o,_objects) { o->render(); } // Draw the planes qglColor(Qt::white); foreach (dGeomID g,_planes) { if (dGeomGetClass(g)) { dVector4 equation; dGeomPlaneGetParams(g,equation); renderPlane(equation,sceneRadius()); } } } void Viewer::startAnimation() { _time.start(); QGLViewer::startAnimation(); } void Viewer::animate() { static float nbSecondsByStep = 0.001f; // Find the time elapsed between last time float nbSecsElapsed = _time.elapsed()/1000.0f; // Find the corresponding number of steps that must be taken int nbStepsToPerform = static_cast(nbSecsElapsed/nbSecondsByStep); // Make these steps to advance world time for (int i=0;i