void renderclip(entity &e) { float xradius = max(float(e.attr2), 0.1f), yradius = max(float(e.attr3), 0.1f); vec bbmin(e.x - xradius, e.y - yradius, float(S(e.x, e.y)->floor+e.attr1)), bbmax(e.x + xradius, e.y + yradius, bbmin.z + max(float(e.attr4), 0.1f)); glDisable(GL_TEXTURE_2D); switch(e.type) { case CLIP: linestyle(1, 0xFF, 0xFF, 0); break; // yellow case MAPMODEL: linestyle(1, 0, 0xFF, 0); break; // green case PLCLIP: linestyle(1, 0xFF, 0, 0xFF); break; // magenta default: linestyle(1, 0xFF, 0, 0); break; // red } glBegin(GL_LINES); glVertex3f(bbmin.x, bbmin.y, bbmin.z); loopi(2) glVertex3f(bbmax.x, bbmin.y, bbmin.z); loopi(2) glVertex3f(bbmax.x, bbmax.y, bbmin.z); loopi(2) glVertex3f(bbmin.x, bbmax.y, bbmin.z); glVertex3f(bbmin.x, bbmin.y, bbmin.z); glVertex3f(bbmin.x, bbmin.y, bbmax.z); loopi(2) glVertex3f(bbmax.x, bbmin.y, bbmax.z); loopi(2) glVertex3f(bbmax.x, bbmax.y, bbmax.z); loopi(2) glVertex3f(bbmin.x, bbmax.y, bbmax.z); glVertex3f(bbmin.x, bbmin.y, bbmax.z); loopi(8) glVertex3f(i&2 ? bbmax.x : bbmin.x, i&4 ? bbmax.y : bbmin.y, i&1 ? bbmax.z : bbmin.z); glEnd(); glEnable(GL_TEXTURE_2D); }
void onMouseDrag( GLFWwindow* window, double fx, double fy) { int x=fx; int y=fy; #else void onMouseDrag( int x, int y) { #endif if (isDrag) { printf( "in drag mode %d\n", isDrag); if (isDrag==V_DRAG && cowFlag) { // vertical dragging // TODO: // create a dragging plane perpendicular to the ray direction, // and test intersection with the screen ray. // When dragged just change Y position Ray ray; screenCoordToRay(clickX, y, ray); PickInfo &pp=pickInfo; std::pair<bool, double> c=ray.intersects(dragPlane); vector3 currentPos=ray.getPoint(c.second); matrix4 T; T.setTranslation(currentPos - pp.cowPickPosition, false); cow2wld.mult(T, pp.cowPickConfiguration); } else { // horizontal dragging // Hint: read carefully the following block to implement vertical dragging. if(cursorOnCowBoundingBox) { Ray ray; screenCoordToRay(x, y, ray); PickInfo &pp=pickInfo; Plane p(vector3(0,1,0), pp.cowPickPosition); std::pair<bool, double> c=ray.intersects(p); vector3 currentPos=ray.getPoint(c.second); matrix4 T; T.setTranslation(currentPos-pp.cowPickPosition, false); cow2wld.mult(T, pp.cowPickConfiguration); } } } else { Ray ray; screenCoordToRay(x, y, ray); std::vector<Plane> planes; vector3 bbmin(cow->bbmin.x, cow->bbmin.y, cow->bbmin.z); vector3 bbmax(cow->bbmax.x, cow->bbmax.y, cow->bbmax.z); planes.push_back(makePlane(bbmin, bbmax, vector3(0,1,0))); planes.push_back(makePlane(bbmin, bbmax, vector3(0,-1,0))); planes.push_back(makePlane(bbmin, bbmax, vector3(1,0,0))); planes.push_back(makePlane(bbmin, bbmax, vector3(-1,0,0))); planes.push_back(makePlane(bbmin, bbmax, vector3(0,0,1))); planes.push_back(makePlane(bbmin, bbmax, vector3(0,0,-1))); std::pair<bool,double> o=ray.intersects(planes); cursorOnCowBoundingBox=o.first; PickInfo &pp=pickInfo; pp.cursorRayT=o.second; pp.cowPickPosition=ray.getPoint(pp.cursorRayT); pp.cowPickConfiguration=cow2wld; matrix4 invWorld; invWorld.inverse(cow2wld); // the local position (relative to the cow frame) of the pick position. pp.cowPickPositionLocal=invWorld*pp.cowPickPosition; } } /********************************************************************************* * Call this part whenever user types keyboard. **********************************************************************************/ #if GLFW_VERSION_MAJOR==3 void onKeyPress(GLFWwindow *__win, int key, int __scancode, int action, int __mods) #else void onKeyPress( int key, int action) #endif { if (action==GLFW_RELEASE) return ; // do nothing // If 'c' or space bar are pressed, alter the camera. // If a number is pressed, alter the camera corresponding the number. if ((key == ' ') || (key == 'c')) { printf( "Toggle camera %d\n", cameraIndex ); cameraIndex += 1; } else if ((key >= '0') && (key <= '9')) cameraIndex = key - '0'; if (cameraIndex >= (int)wld2cam.size() ) cameraIndex = 0; } void screenCoordToRay(int x, int y, Ray& ray) { int height , width; #if GLFW_VERSION_MAJOR==3 glfwGetWindowSize(g_window, &width, &height); #else glfwGetWindowSize(&width, &height); #endif matrix4 matProjection; matProjection.getCurrentOpenGLmatrix(GL_PROJECTION_MATRIX); matProjection*=wld2cam[cameraIndex]; matrix4 invMatProjection; invMatProjection.inverse(matProjection); vector3 vecAfterProjection, vecAfterProjection2; // -1<=v.x<1 when 0<=x<width // -1<=v.y<1 when 0<=y<height vecAfterProjection.x = ((double)(x - 0)/(double)width)*2.0-1.0; vecAfterProjection.y = ((double)(y - 0)/(double)height)*2.0-1.0; vecAfterProjection.y*=-1; vecAfterProjection.z = -10; //std::cout<<"cowPosition in clip coordinate (NDC)"<<matProjection*cow2wld.getTranslation()<<std::endl; vector3 vecBeforeProjection=invMatProjection*vecAfterProjection; // camera position ray.origin()=cam2wld[cameraIndex].getTranslation(); ray.direction()=vecBeforeProjection-ray.origin(); ray.direction().normalize(); //std::cout<<"dir" <<ray.direction()<<std::endl; }
void VoronoiFractureDemo::initPhysics() { srand(13); useGenericConstraint = !useGenericConstraint; printf("useGenericConstraint = %d\n", useGenericConstraint); setTexturing(true); setShadows(true); setCameraDistance(btScalar(20.)); ///collision configuration contains default setup for memory, collision setup m_collisionConfiguration = new btDefaultCollisionConfiguration(); //m_collisionConfiguration->setConvexConvexMultipointIterations(); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); useMpr = 1 - useMpr; if (useMpr) { printf("using GJK+MPR convex-convex collision detection\n"); btConvexConvexMprAlgorithm::CreateFunc* cf = new btConvexConvexMprAlgorithm::CreateFunc; m_dispatcher->registerCollisionCreateFunc(CONVEX_HULL_SHAPE_PROXYTYPE, CONVEX_HULL_SHAPE_PROXYTYPE, cf); m_dispatcher->registerCollisionCreateFunc(CONVEX_HULL_SHAPE_PROXYTYPE, BOX_SHAPE_PROXYTYPE, cf); m_dispatcher->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE, CONVEX_HULL_SHAPE_PROXYTYPE, cf); } else { printf("using default (GJK+EPA) convex-convex collision detection\n"); } m_broadphase = new btDbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; m_solver = sol; m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); m_dynamicsWorld->getSolverInfo().m_splitImpulse = true; m_dynamicsWorld->setDebugDrawer(&sDebugDraw); m_dynamicsWorld->setGravity(btVector3(0,-10,0)); ///create a few basic rigid bodies btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); m_collisionShapes.push_back(groundShape); btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0,-50,0)); //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here: { btScalar mass(0.); //rigidbody is dynamic if and only if mass is non zero, otherwise static bool isDynamic = (mass != 0.f); btVector3 localInertia(0,0,0); if (isDynamic) groundShape->calculateLocalInertia(mass,localInertia); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); //add the body to the dynamics world m_dynamicsWorld->addRigidBody(body); } { btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(10.),btScalar(8.),btScalar(1.))); btScalar mass(0.); //rigidbody is dynamic if and only if mass is non zero, otherwise static bool isDynamic = (mass != 0.f); btVector3 localInertia(0,0,0); if (isDynamic) groundShape->calculateLocalInertia(mass,localInertia); groundTransform.setOrigin(btVector3(0,0,0)); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); //add the body to the dynamics world m_dynamicsWorld->addRigidBody(body); } // ==> Voronoi Shatter Basic Demo: Random Cuboid // Random size cuboid (defined by bounding box max and min) btVector3 bbmax(btScalar(rand() / btScalar(RAND_MAX)) * 12. +0.5, btScalar(rand() / btScalar(RAND_MAX)) * 1. +0.5, btScalar(rand() / btScalar(RAND_MAX)) * 1. +0.5); btVector3 bbmin = -bbmax; // Place it 10 units above ground btVector3 bbt(0,15,0); // Use an arbitrary material density for shards (should be consitent/relative with/to rest of RBs in world) btScalar matDensity = 1; // Using random rotation btQuaternion bbq(btScalar(rand() / btScalar(RAND_MAX)) * 2. -1.,btScalar(rand() / btScalar(RAND_MAX)) * 2. -1.,btScalar(rand() / btScalar(RAND_MAX)) * 2. -1.,btScalar(rand() / btScalar(RAND_MAX)) * 2. -1.); bbq.normalize(); // Generate random points for voronoi cells btAlignedObjectArray<btVector3> points; btVector3 point; btVector3 diff = bbmax - bbmin; for (int i=0; i < VORONOIPOINTS; i++) { // Place points within box area (points are in world coordinates) point = quatRotate(bbq, btVector3(btScalar(rand() / btScalar(RAND_MAX)) * diff.x() -diff.x()/2., btScalar(rand() / btScalar(RAND_MAX)) * diff.y() -diff.y()/2., btScalar(rand() / btScalar(RAND_MAX)) * diff.z() -diff.z()/2.)) + bbt; points.push_back(point); } m_perfmTimer.reset(); voronoiBBShatter(points, bbmin, bbmax, bbq, bbt, matDensity); printf("Total Time: %f seconds\n", m_perfmTimer.getTimeMilliseconds()/1000.); for (int i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--) { btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i]; obj->getCollisionShape()->setMargin(CONVEX_MARGIN+0.01); } m_dynamicsWorld->performDiscreteCollisionDetection(); for (int i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--) { btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i]; obj->getCollisionShape()->setMargin(CONVEX_MARGIN); } attachFixedConstraints(); }