void btGImpactMeshShapePart::processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom, const btVector3& rayTo) const { lockChildShapes(); btAlignedObjectArray<int> collided; btVector3 rayDir(rayTo - rayFrom); rayDir.normalize(); m_box_set.rayQuery(rayDir, rayFrom, collided); if(collided.size()==0) { unlockChildShapes(); return; } int part = (int)getPart(); btPrimitiveTriangle triangle; int i = collided.size(); while(i--) { getPrimitiveTriangle(collided[i],triangle); callback->processTriangle(triangle.m_vertices,part,collided[i]); } unlockChildShapes(); }
void Physics::update(Game *game) { // Prepare for simulation. Typically we use a time step of 1/60 of a // second (60Hz) and 10 iterations. This provides a high quality simulation // in most game scenarios. float32 timeStep = 1.0f / 60.0f; int32 velocityIterations = 6; int32 positionIterations = 2; // This is our little game loop. for (int32 i = 0; i < 60; ++i) { // Instruct the world to perform a single step of simulation. // It is generally best to keep the time step and iterations fixed. box2DWorld->Step(timeStep, velocityIterations, positionIterations); } list<b2Body*>::iterator bodiesIterator; bodiesIterator = bodiesToDestroy.begin(); while (bodiesIterator != bodiesToDestroy.end()) { b2Body* body = *bodiesIterator; bodiesIterator++; box2DWorld->DestroyBody(body); } bodiesToDestroy.clear(); if(explosionThisFrame) { list<Explosion*>::iterator explosionsIterator; explosionsIterator = explosions.begin(); while (explosionsIterator != explosions.end()) { Explosion* explosion = *explosionsIterator; explosionsIterator++; int numRays = explosion->numOfRays; b2Vec2 center = explosion->explosionEpicenter; float blastRadius = explosion->blastRadius; for (int i = 0; i < numRays; i++) { float angle = (i / (float)numRays) * 360 * DEGTORAD; b2Vec2 rayDir( sinf(angle), cosf(angle) ); b2Vec2 rayEnd = center + pixelsToMeters(blastRadius) * rayDir; //check what this ray hits ExplosionCallback callback;//basic callback to record body and hit point box2DWorld->RayCast(&callback, center, rayEnd); if ( callback.getClosestFixture() ) applyBlastImpulse(callback.getClosestFixture()->GetBody(), center, callback.getImplusePoint(), (explosion->blastPower / (float)numRays)); } } explosions.clear(); explosionThisFrame = false; } }
//---------------------------------------------------------------------------------------------------------------------- ngl::Vec3 NGLDraw::getWorldSpace(const int _x, const int _y) { ngl::Mat4 m; m = m*m_mouseGlobalTX; ngl::Mat4 t=m_cam->getProjectionMatrix(); ngl::Mat4 v=m_cam->getViewMatrix(); // as ngl:: and OpenGL use different formats need to transpose the matrix. t.transpose(); v.transpose(); m.transpose(); ngl::Mat4 inverse=(t*v*m).inverse(); ngl::Vec4 tmp(0,0,-1.0f,1.0f); // convert into NDC tmp.m_x=(2.0f * _x) / m_width- 1.0f; tmp.m_y=1.0f - (2.0f * _y) / m_height; // scale by inverse MV * Project transform ngl::Vec4 near(tmp.m_x,tmp.m_y,-1.0f,1.0f); ngl::Vec4 far(tmp.m_x,tmp.m_y,1.0f,1.0f); //get world point on near and far clipping planes ngl::Vec4 obj_near=inverse*near; ngl::Vec4 obj_far=inverse*far; // Scale by w obj_near/=obj_near.m_w; obj_far/=obj_far.m_w; ngl::Vec3 nearPoint(obj_near.m_x,obj_near.m_y,obj_near.m_z); ngl::Vec3 farPoint(obj_far.m_x,obj_far.m_y,obj_far.m_z); //create ray ngl::Vec3 rayDir(farPoint-nearPoint); if(rayDir.lengthSquared() == 0.0f) { std::cout<<"Ray Direction in getWorldSpace equals zero, can't normalise"<<std::endl; } else { rayDir.normalize(); } //calculate distance to zx plane float dist = (-nearPoint.m_y)/rayDir.m_y; //set world space coordinate where y = 0 ngl::Vec3 obj(nearPoint.m_x + (dist*rayDir.m_x),nearPoint.m_y + (dist*rayDir.m_y),nearPoint.m_z + (dist*rayDir.m_z)); obj.m_y = 0.0; return obj; }
/** * Picks a single scene object from the scene. If the object has a mesh collider, the picker will calculate the * texture coordinates and barycentric coordinates of the corresponding hit-point. Note that this will do nothing * if the scene object doesn't have a collider. */ void Picker::pickSceneObject(const SceneObject *scene_object, float ox, float oy, float oz, float dx, float dy, float dz, ColliderData &colliderData){ Collider* collider = scene_object->collider(); if(collider == nullptr){ return; } else if (collider->enabled() && scene_object->enabled()) { glm::vec3 rayStart(ox, oy, oz); glm::vec3 rayDir(dx, dy, dz); colliderData = collider->isHit(rayStart, rayDir); } }
static Eigen::Vector3d mapToSphere( Eigen::Matrix4d invProjMatrix, Eigen::Vector2d const p, Eigen::Vector3d viewSphereCenter, double viewSpaceRadius) { Eigen::Vector4d viewP = invProjMatrix * Eigen::Vector4d(p(0), p(1), -1.0, 1.0); //viewP(0) /= viewP(3); //viewP(1) /= viewP(3); //viewP(2) /= viewP(3); Eigen::Vector3d rayOrigin(0.0, 0.0, 0.0); Eigen::Vector3d rayDir(viewP(0), viewP(1), viewP(2)); rayDir.normalize(); Eigen::Vector3d CO = rayOrigin - viewSphereCenter; double a = 1.0; double bPrime = CO.dot(rayDir); double c = CO.dot(CO) - viewSpaceRadius * viewSpaceRadius; double delta = bPrime * bPrime - a * c; if (delta < 0.0) { double t = -CO.z() / rayDir.z(); Eigen::Vector3d point = rayOrigin + t * rayDir; Eigen::Vector3d dir = point - viewSphereCenter; dir.normalize(); return viewSphereCenter + dir * viewSpaceRadius; } double root[2] = { (-bPrime - sqrt(delta)) / a, (-bPrime + sqrt(delta)) / a }; if (root[0] >= 0.0) { Eigen::Vector3d intersectionPoint = rayOrigin + root[0] * rayDir; return intersectionPoint; } else if (root[1] >= 0.0) { Eigen::Vector3d intersectionPoint = rayOrigin + root[1] * rayDir; return intersectionPoint; } else { double t = -CO.z() / rayDir.z(); Eigen::Vector3d point = rayOrigin + t * rayDir; Eigen::Vector3d dir = point - viewSphereCenter; dir.normalize(); return viewSphereCenter + dir * viewSpaceRadius; } }
std::vector<vec3> Orthographic::render(std::vector<std::unique_ptr<WorldObject>> &objects, std::vector<std::unique_ptr<Light>> &lights, vec2 imageSize, double imageAspectRatio, int aaDepth) { std::vector<vec3> frameBuffer; for (int y = 0; y < imageSize.y; y++) { for (int x = 0; x < imageSize.x; x++) { vec3 pixel; std::vector<vec3> aaData; for (int aay = 0; aay < aaDepth; aay++) { for (int aax = 0; aax < aaDepth; aax++) { // normalize ray pos (-> NDC) // add 0.5 so that the final ray passes through the middle of the pixel pixel.x = (x + ((1.0 / (aaDepth - 1.0)) * aax)) / imageSize.x; pixel.y = (y + ((1.0 / (aaDepth - 1.0)) * aay)) / imageSize.y; // map from [0;1] to [-imageAspectRatio;imageAspectRatio] pixel.x = 2.0 * pixel.x - 1.0; pixel.x *= imageAspectRatio; pixel.y = 1.0 - 2.0 * pixel.y; double scale = tan(MyMath::degToRad(fov / 2.0)); pixel.x *= scale; pixel.y *= scale; vec3 rayOrig(-pixel.x, -pixel.y, 0.0f); vec3 rayDir(0.0f, 0.0f, -1.0f); rayDir -= rayOrig; rayDir = rayDir.normalize(); Ray ray(rayOrig, rayDir); aaData.push_back(ray.cast(objects, lights, 3)); } } vec3 sum; for (vec3 color : aaData) { sum += color; } sum = sum / aaData.size(); frameBuffer.push_back(sum); } } return frameBuffer; }
/* * Pick against the scene bounding box. * The input ray is in world coordinates. * To pick against the bounding box, we create a bounding box mesh * from the original mesh. This new mesh is in mesh coordinates * so we must apply the inverse of the model matrix from the scene object * to the ray to put it into mesh coordinates. */ glm::vec3 Picker::pickSceneObjectAgainstBoundingBox(const SceneObject* scene_object, float ox, float oy, float oz, float dx, float dy, float dz) { RenderData* rd = scene_object->render_data(); if ((rd == NULL) || (rd->mesh() == NULL)) { return glm::vec3(std::numeric_limits<float>::infinity()); } glm::mat4 model_inverse = glm::affineInverse(scene_object->transform()->getModelMatrix()); const BoundingVolume& bounds = rd->mesh()->getBoundingVolume(); glm::vec3 rayStart(ox, oy, oz); glm::vec3 rayDir(dx, dy, dz); glm::normalize(rayDir); Collider::transformRay(model_inverse, rayStart, rayDir); ColliderData data = MeshCollider::isHit(bounds, rayStart, rayDir); if (data.IsHit) { return data.HitPosition; } return glm::vec3(std::numeric_limits<float>::infinity()); }
DecoColor Shading(const vector3& realIntersectPt, const vector3& norm, const vector3& lightPos, const vector3& viewPos, const vector3& lightDiffuse, const vector3& lightSpecular, const vector3& lightAmbient, const vector3& matDiffuse, const vector3& matSpecular, const vector3&matAmbient) { vector3 col(0, 0, 0); vector3 rayDir(lightPos - realIntersectPt); vector3 viewDir(viewPos - realIntersectPt); vector3 normal = norm; viewDir.normalize(); rayDir.normalize(); normal.normalize(); vector3 halfDir = (viewDir + rayDir) / 2; halfDir.normalize(); col += vector3(lightDiffuse.x * matDiffuse.x, lightDiffuse.y * matDiffuse.y, lightDiffuse.z * matDiffuse.z) * max(0.0, DotProduct(normal, rayDir)); //col += vector3(lightAmbient.x * matAmbient.x, lightAmbient.y * matAmbient.y, lightAmbient.z * matAmbient.z); DOUBLE dotHalfAngle = max(0.0, DotProduct(halfDir, normal)); col += vector3(lightSpecular.x * matSpecular.x, lightSpecular.y * matSpecular.y, lightSpecular.z * matSpecular.z) * dotHalfAngle * dotHalfAngle; return DecoColor(vector4(col.x, col.y, col.z, 1)); }
bool ComTerrain::GetHeight(float & height, const D3DXVECTOR3 & pos) { D3DXVECTOR3 rayPos(pos.x, pos.y + m_rayDistance, pos.z); D3DXVECTOR3 rayDir(0, -1, 0); float distance = 0.0f; for (int i = 0; i < m_vecIndices.size(); i += 3) { D3DXVECTOR3 v1 = m_vecVertices[m_vecIndices[i]].p; D3DXVECTOR3 v2 = m_vecVertices[m_vecIndices[i + 1]].p; D3DXVECTOR3 v3 = m_vecVertices[m_vecIndices[i + 2]].p; if (D3DXIntersectTri(&v1, &v2, &v3, &rayPos, &rayDir, NULL, NULL, &distance)) { height = rayPos.y - distance; return true; } } return false; }
void Bomb::explode() { if (exploded == false) { exploded = true; b2Vec2 center = bodies[0].body_ptr->GetPosition(); float power = 300; float blast_radius = 15; //apply impulse to bodies size_t rays = 50; for (size_t i = 0; i < rays; i++) { float angle = (i / (float)rays) * 6.282; b2Vec2 rayDir( sinf(angle), cosf(angle) ); b2Vec2 rayEnd = center + blast_radius * rayDir; //check what this ray hits RayCastClosestCallback callback; world.RayCast(&callback, center, rayEnd); if ( callback.m_body ) { applyImpulse(callback.m_body, center, callback.m_point, power); } } } }
bool ConvexShape::castRay( const Point3F &start, const Point3F &end, RayInfo *info ) { if ( mPlanes.empty() ) return false; const Vector< PlaneF > &planeList = mPlanes; const U32 planeCount = planeList.size(); F32 t; F32 tmin = F32_MAX; S32 hitFace = -1; Point3F hitPnt, pnt; VectorF rayDir( end - start ); rayDir.normalizeSafe(); if ( false ) { PlaneF plane( Point3F(0,0,0), Point3F(0,0,1) ); Point3F sp( 0,0,-1 ); Point3F ep( 0,0,1 ); F32 t = plane.intersect( sp, ep ); Point3F hitPnt; hitPnt.interpolate( sp, ep, t ); } for ( S32 i = 0; i < planeCount; i++ ) { // Don't hit the back-side of planes. if ( mDot( rayDir, planeList[i] ) >= 0.0f ) continue; t = planeList[i].intersect( start, end ); if ( t >= 0.0f && t <= 1.0f && t < tmin ) { pnt.interpolate( start, end, t ); S32 j = 0; for ( ; j < planeCount; j++ ) { if ( i == j ) continue; F32 dist = planeList[j].distToPlane( pnt ); if ( dist > 1.0e-004f ) break; } if ( j == planeCount ) { tmin = t; hitFace = i; } } } if ( hitFace == -1 ) return false; info->face = hitFace; info->material = mMaterialInst; info->normal = planeList[ hitFace ]; info->object = this; info->t = tmin; //mObjToWorld.mulV( info->normal ); return true; }
void PhysicalCamera::grasp() { if (!mGraspedObject) { // Fire a ray into the scene to find an object to grasp. If // an object is found, attach it to the grasping Motor and, // if using long range grasping mode, store the intersection // position relative to the camera as the grasp offset. // First update the ray casting Sensor's ray. Ogre::Vector3 camForward = mOgreCamera->getDerivedDirection(); if (0 != camForward.squaredLength()) { camForward.normalise(); } opal::Vec3r rayDir(camForward[0], camForward[1], camForward[2]); if (PHYSICAL == mType) { // The ray's origin will be updated automatically since // it is attached to the camera's Solid. Its direction // should be set manually here because we constantly // reset the camera's orientation. opal::Point3r dummyPoint; opal::Rayr r(dummyPoint, rayDir); mGraspingSensor->setRay(r); } else { // The ray should start at the camera's position and fire // straight forward into the scene. Ogre::Vector3 ogreCamPos = mOgreCamera->getDerivedPosition(); opal::Point3r opalCamPos(ogreCamPos[0], ogreCamPos[1], ogreCamPos[2]); opal::Rayr r(opalCamPos, rayDir); mGraspingSensor->setRay(r); } // Fire the ray. opal::RaycastResult result = mGraspingSensor->fireRay(mMaxReach); if (result.solid) // && !result.solid->isStatic()) { // Store the grasped object. mGraspedObject = result.solid; // Initialize the grasping Motor with the new data. opal::SpringMotorData data; data.solid = result.solid; data.mode = mGraspingMotorMode; data.linearKs = mGraspingLinearKs; data.linearKd = mGraspingLinearKd; data.angularKs = mGraspingAngularKs; data.angularKd = mGraspingAngularKd; opal::Matrix44r solidTransform = result.solid->getTransform(); //data.desiredUp = solidTransform.getUp(); //data.desiredForward = solidTransform.getForward(); //data.desiredRight = solidTransform.getRight(); // Desired position will be updated in the "update" // function. mGraspingMotor->init(data); if (PHYSICAL == mType) { //// Grab it where the ray intersected it. //mGraspingMotor->setGlobalAttachPoint(result.intersection); // Just grab it in the middle. mGraspingMotor->setGlobalAttachPoint(result.solid-> getPosition()); } else { mGraspingMotor->setGlobalAttachPoint(result.intersection); // Set the offset (from the camera) to be the same distance // as when it was grasped. mPhysicalGraspOffset.set(0, 0, -result.distance); } // Compute the grasped object's offset transform from the camera // which is only used for desired orientation. Ogre::Matrix4 ogreMat; mOgreCamera->getParentSceneNode()->getWorldTransforms(&ogreMat); opal::Matrix44r camTransform( ogreMat[0][0], ogreMat[1][0], ogreMat[2][0], ogreMat[3][0], ogreMat[0][1], ogreMat[1][1], ogreMat[2][1], ogreMat[3][1], ogreMat[0][2], ogreMat[1][2], ogreMat[2][2], ogreMat[3][2], ogreMat[0][3], ogreMat[1][3], ogreMat[2][3], ogreMat[3][3]); camTransform.invert(); opal::Matrix44r objTransInv = mGraspedObject->getTransform(); objTransInv.invert(); mGraspedObjectOffsetTransform = objTransInv * camTransform; // Set the desired transform for orientation only (the position // part should be overwritten below). opal::Matrix44r desiredObjTransform = mGraspedObjectOffsetTransform * camTransform; desiredObjTransform.invert(); mGraspingMotor->setDesiredTransform(desiredObjTransform); // Update the the desired position. mGraspingMotor->setDesiredPosition(getGraspGlobalPos()); // Apply extra angular damping. result.solid->setAngularDamping(3); } } }