btVector3 PhysicsSystem::getRayPoint(float extent, float mouseX, float mouseY) { //get a ray pointing to the center of the viewport Ray centerRay = mRender.getCamera()->getCameraToViewportRay(mouseX, mouseY); btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y); /// \todo make this distance (ray length) configurable return result; }
Intersection Triangle::intersect(const Ray &r) const { const Vec3t edge1(V1-V0), edge2(V2-V0); // could precalculate Vec3t pvec(cross(r.getNormal(), edge2)); DefType det=dot(edge1,pvec); if (det < MM_EPSILON) return Intersection(); Vec3t tvec(r.getPoint()-V0); DefType u=dot(tvec,pvec); if (u < 0 || u > det) return Intersection(); Vec3t qvec(cross(tvec,edge1)); DefType v=dot(r.getPoint(),qvec); if (v < 0 || u+v > det) return Intersection(); DefType t=dot(edge2, qvec)/det; return Intersection(r.positionAtTime(t), m_normal, t, true, true); }
std::vector < std::pair <float, std::string> > PhysicsSystem::getFacedObjects () { //get a ray pointing to the center of the viewport Ray centerRay = mRender.getCamera()->getCameraToViewportRay( mRender.getViewport()->getWidth()/2, mRender.getViewport()->getHeight()/2); btVector3 from(centerRay.getOrigin().x,-centerRay.getOrigin().z,centerRay.getOrigin().y); btVector3 to(centerRay.getPoint(500).x,-centerRay.getPoint(500).z,centerRay.getPoint(500).y); return mEngine->rayTest2(from,to); }
std::pair<std::string, float> PhysicsSystem::getFacedHandle (MWWorld::World& world) { std::string handle = ""; //get a ray pointing to the center of the viewport Ray centerRay = mRender.getCamera()->getCameraToViewportRay( mRender.getViewport()->getWidth()/2, mRender.getViewport()->getHeight()/2); //let's avoid the capsule shape of the player. centerRay.setOrigin(centerRay.getOrigin() + 20*centerRay.getDirection()); btVector3 from(centerRay.getOrigin().x,-centerRay.getOrigin().z,centerRay.getOrigin().y); btVector3 to(centerRay.getPoint(500).x,-centerRay.getPoint(500).z,centerRay.getPoint(500).y); return mEngine->rayTest(from,to); }
Intersection Quad::intersect(const Ray& ray, float previousBestDistance) const { float factor= dot(ray.d,qnormal); if(factor==0.0) return Intersection::failure(); float t= dot((qv1-ray.o),qnormal)/factor; if (t> previousBestDistance || t<0.0001) return Intersection::failure(); Point p=ray.getPoint(t); /****** n = -det(PA, PQ)/det(PQ, PR) m = det(PA, PR)/det(PQ, PR) det(PA, PQ) = PA.x*PQ.y-PQ.x*PA.y ******/ bool a = dot(cross(qv2 - qv1, p - qv1), qnormal) >= 0; bool b = dot(cross(qv4 - qv2, p - qv2), qnormal) >= 0; bool c = dot(cross(qv3 - qv4, p - qv4), qnormal) >= 0; bool d = dot(cross(qv1 - qv3, p - qv3), qnormal) >= 0; if (a && b && c && d) return Intersection(t, ray, this, qnormal, p); else return Intersection::failure(); /* float n = (qspan1.x * ( p.y - qv1.y) - p.x*qspan1.y + qv1.x*qspan1.y) / (qspan2.y * qspan1.x - qspan2.x*qspan1.y); if (n < 0 || n > 1) return Intersection::failure(); float m = (p.x - qv1.x - n *qspan2.x) / qspan1.x; if (m < 0 || m > 1) return Intersection::failure(); return Intersection(t,ray,this,qnormal,p); */ }
Spectrum Camera::evaluateWe( const Ray &i_ray, glm::vec2* o_rasterPosition ) const { glm::vec3 directionWorld = Transform::transform( glm::vec3( 0.0, 0.0, -1.0 ), m_cameraToWorld ); float cosTheta = glm::dot( i_ray.getDirection(), directionWorld ); // See if they are pointing in the same direction if ( cosTheta <= 0.0f ) { return Spectrum::black(); } // Find point on plane of focus and convert that to // raster coordinates float t = ( m_aperature > 0.0f ? m_focalLength : 1.0 ) / cosTheta; glm::vec3 focusPoint = i_ray.getPoint( t ); glm::vec2 rasterPoint = glm::vec2( glm::inverse( m_rasterToCamera ) * m_worldToCamera * glm::vec4( focusPoint, 1.0) ); // Optionally return raster position if ( o_rasterPosition != nullptr ) { *o_rasterPosition = glm::vec2( rasterPoint ); } if ( !m_rasterBounds.isInside( rasterPoint ) ) { return Spectrum::black(); } float lensArea = m_aperature == 0.0f ? 1.0f : ( M_PI * m_aperature * m_aperature ); float cos2Theta = cosTheta * cosTheta; return Spectrum( 1.0f / ( m_area * lensArea * cos2Theta * cos2Theta ) ); }
const Vector3 Lambert::shade(const unsigned int threadID, const Ray& ray, const HitInfo &hit, const Scene& scene, bool isSecondary) const { Vector3 L = Vector3(0.0f, 0.0f, 0.0f); Vector3 rayD = Vector3(ray.d[0],ray.d[1],ray.d[2]); // Ray direction Vector3 viewDir = -rayD; // View direction float u, v; Vector3 N, geoN, T, BT; Vector3 diffuseColor = m_kd; Vector3 P = ray.getPoint(hit.t); hit.getAllInfos(N, geoN, T, BT, u, v); if (m_colorMap != NULL) { Vector4 texCol = m_colorMap->getLookup(u, v); diffuseColor = Vector3(texCol.x, texCol.y, texCol.z); } const Lights *lightlist = scene.lights(); // loop over all of the lights Lights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { float discard; Vector3 lightPower = (*lightIter)->sampleLight(threadID, P, N, ray.time, scene, 0, discard); L += lightPower * diffuseColor; // Calculate Diffuse component } // add the ambient component L += m_ka; return L; }
bool OsgSceneObject::intersectRay(const Ray& ray, Vector3f* hitPoint) { Vector3f rstart = ray.getOrigin(); // Compute reasonable ray length based on distance between ray origin and // owner scene node center. Vector3f center = getOwner()->getBoundCenter(); float dir = (ray.getOrigin() - center).norm(); Vector3f rend = ray.getPoint(dir * 2); osg::Vec3d orig(rstart[0], rstart[1], rstart[2]); osg::Vec3d end(rend[0], rend[1], rend[2]); Ref<osgUtil::LineSegmentIntersector> lsi = new osgUtil::LineSegmentIntersector(orig, end); osgUtil::IntersectionVisitor iv(lsi); myTransform->accept(iv); if(!lsi->containsIntersections()) return false; osgUtil::LineSegmentIntersector::Intersection i = lsi->getFirstIntersection(); osg::Vec3d intersect = i.getWorldIntersectPoint(); hitPoint->x() = intersect[0]; hitPoint->y() = intersect[1]; hitPoint->z() = intersect[2]; return true; }
bool pathDrawerState::mouseMoved(const OIS::MouseEvent& e) { //cout << _nodoSelector->getName().substr(0,_nodoSelector->getName().find("_")) << endl; //cout << "mousemove " << _nodoSelector->getName() << endl; if (InputManager_::getSingletonPtr()->getMouse()->getMouseState().buttonDown(OIS::MB_Left) && //_nodoSelector && _nodoSelector->getName() != "PlaneRoadBig") //"track1Big") _nodoSelector && _nodoSelector->getName().substr(0,_nodoSelector->getName().find("_")-1) != _checkPointInfo.nombreNodo) { Ray r = setRayQuery(e.state.X.abs, e.state.Y.abs, MASK_CIRCUITO | MASK_MARCA); RaySceneQueryResult &result = _raySceneQuery->execute(); RaySceneQueryResult::iterator it; it = result.begin(); if (it != result.end() && it->movable->getParentSceneNode()->getName() == "PlaneRoadBig") { Vector3 pos = r.getPoint(it->distance); pos.y = _planeRoadNode->getPosition().y + 1; _nodoSelector->setPosition(pos); recolocarLinea(); } } return true; }
// --------------------------------------------------------------------------------- bool ConvexPolygon::isHitBy(const Ray& ray) const { // Create a RayStart->Edge defined plane. // If the intersection of the ray to the polygon's plane is inside for all the planes, it is inside the poly // By inside, I mean the point is on positive side of the plane std::pair<bool, Real> intersection = ray.intersects(mPlane); if (!intersection.first) return false; // intersection point Vector3 ip = ray.getPoint(intersection.second); Vector3 origin = ray.getOrigin(); unsigned int pointcount = mPoints.size(); for (unsigned int idx = 0; idx < pointcount; idx++) { int iv2 = (idx + 1) % pointcount; Vector3 v1 = mPoints[idx]; Vector3 v2 = mPoints[iv2]; Plane frp(origin, v1, v2); // test whether the intersection is inside if (frp.getSide(ip) != Plane::POSITIVE_SIDE) return false; } return true; }
LRESULT Canvas::OnLeftButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { // int x = GET_X_LPARAM(lParam); int y = GET_Y_LPARAM(lParam); //_cameraController.onLeftButtonDown(x,y); bHandled = false; //拾取射线 Ray r = _camera.getCameraToViewportRay(x, y); //与xz平面的交点 Real t = -r._origin.y / r._direction.y; Vec3 p = r.getPoint(t); Vec3 ap = _getActorPosition(); p -= ap; Real len = p.length(); _positionSpeed = 0.010f / len; //目标点 _setActorPosition(p); //调整主角方向 Quaternion q; Radian angle = Euler::Basic::ATan2(p.x, p.z); q.FromAngleAxis(angle, Vec3::UNIT_Y); _angleSpeed = 0.01f; _setActorAngle(q); return 0; }
// this is called at simulation time void DemoApplication::UpdateMousePick () { bool mouseKey1 = m_mouseState.buttonDown(OIS::MB_Left); OgreNewtonRayPickManager* const rayPicker = m_physicsWorld->GetRayPickManager(); if (m_keyboard->isKeyDown(OIS::KC_LCONTROL) || m_keyboard->isKeyDown(OIS::KC_RCONTROL)) { m_cursor->setVisible(true); if (mouseKey1) { Real mx = Real (m_mouseState.X.abs) / Real(m_mouseState.width); Real my = Real (m_mouseState.Y.abs) / Real(m_mouseState.height); Ray camray (mCamera->getCameraToViewportRay(mx, my)); Vector3 start (camray.getOrigin()); Vector3 end (camray.getPoint (200.0f)); if (!m_mousePickMemory) { rayPicker->SetPickedBody (NULL); dNewtonBody* const body = rayPicker->RayCast (start, end, m_pickParam); if (body) { rayPicker->SetPickedBody (body, start + (end - start) * m_pickParam); } } else { rayPicker->SetTarget (start + (end - start) * m_pickParam); } } else { rayPicker->SetPickedBody (NULL); } } else { m_cursor->setVisible(false); rayPicker->SetPickedBody (NULL); } m_mousePickMemory = mouseKey1; }
IntersectResult Sphere::intersect(Ray &ray) { IntersectResult result(false); // Solve: // | (o + t * dir) - c | = radius // ==> ( co + t * dir ) ^ 2 - radius ^ 2 = 0 // ==> dir * dir * t ^ 2 + 2 * dir.co * t + (co.co - radius * radius) = 0 // ==> t ^ 2 + (2 * dir.co) * t + (co.co - radius * radius) = 0 // ==> t = - dir.co +- sqr((dir.co * dir.co) - (co.co - radius * radius)) Vector co = Vector(center, ray.origin); double b = ray.direction.dot(co); double delta = b * b - (co.dot(co) - radius * radius); if (delta >= 0) { delta = sqrt(delta); if (-b + delta >= 0.0005f) { result.hit = true; result.geometry = this; //result.distance = (-b - delta >= 0.0005f) ? -b - delta : -b + delta; result.distance = -b; // in the SBR algorithm, there should be only one intersection result.position = ray.getPoint(result.distance); result.normal = Vector(center, result.position).norm(); } } return result; }
void Global::updatePickingPoint_() { Ray r = getRenderContex()->getPickingRay(); float x, z; if (0) { //对于平面地表,可以这样处理 float t = -r.origion_.y / r.direction_.y; x = r.origion_.x + t * r.direction_.x; z = r.origion_.z + t * r.direction_.z; } else { sPick pk; pk.empty_ = true; calcPick(pk, r, getSceneManager()->getTerrainQuadTreeRoot()); if (pk.empty_) { return; } Vector3 p = r.getPoint(pk.ps_.z); p = (1 - pk.ps_.x - pk.ps_.y)*pk.p0_ + pk.ps_.x*pk.p1_ + pk.ps_.y*pk.p2_; x = p.x; z = p.z; } if (getSceneManager()->getTerrain()) { getSceneManager()->getTerrain()->updateVisibleChunks(x, z); } if (getGlobal() && getGlobal()->getBrushDecal()) { getGlobal()->getBrushDecal()->setCenter(Vector4(x, 0, z, 1)); } }
// Dibujado de raycast para depurar void CShootRaycast::drawRaycast(const Ray& raycast) { Graphics::CScene *scene = Graphics::CServer::getSingletonPtr()->getActiveScene(); Ogre::SceneManager *mSceneMgr = scene->getSceneMgr(); std::stringstream aux; aux << "laser" << _nameWeapon << _temporal; ++_temporal; std::string laser = aux.str(); Ogre::ManualObject* myManualObject = mSceneMgr->createManualObject(laser); Ogre::SceneNode* myManualObjectNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(laser+"_node"); myManualObject->begin("laser", Ogre::RenderOperation::OT_LINE_STRIP); Vector3 v = raycast.getOrigin(); myManualObject->position(v.x,v.y,v.z); for(int i=0; i < _distance;++i){ Vector3 v = raycast.getPoint(i); myManualObject->position(v.x,v.y,v.z); // etc } myManualObject->end(); myManualObjectNode->attachObject(myManualObject); }// drawRaycast
bool TutorialApplication::mouseMoved(const OIS::MouseEvent &arg) { auto ret = BaseApplication::mouseMoved(arg); // std::cout << "moust at (" // << arg.state.X.abs << "," // << arg.state.Y.abs << "," // << arg.state.Z.abs << ")" << std::endl; // std::cout << "plane at Y = " << m_activeLevel.d << std::endl; Ray mouseRay = getMouseRay(); if (m_verticalMode) { // ignored for now, untill I figure out how to make it intuitive } else { auto r = mouseRay.intersects(m_activeLevel); if (r.first) { auto pos = mouseRay.getPoint(r.second); auto gridPos = Vector3(floor(pos.x / GRID_SPACING) * GRID_SPACING, pos.y, floor(pos.z / GRID_SPACING) * GRID_SPACING); m_cursorNode->setPosition(gridPos); auto pointPos = Vector3(round(pos.x / GRID_SPACING) * GRID_SPACING, pos.y, round(pos.z / GRID_SPACING) * GRID_SPACING); m_pointNode->setPosition(pointPos); if (m_mode == WitchMode) { for (std::size_t i = 0; i < CONE_CASES.size(); i++) { auto c = CONE_CASES[i]; bool containsCreatures = true; for (Vector3 creature : m_ogres) { Vector3 dir = creature - gridPos; // cone is facing wrong way for creature if (dir.angleBetween(c) > Degree(45)) { containsCreatures = false; break; } // creature too far away for cone if (distance3(dir.x, dir.y, dir.z) > CONE_SIZE) { containsCreatures = false; } } if (containsCreatures) { m_coneNodes[i]->setVisible(true); } else { m_coneNodes[i]->setVisible(false); } } } } } return ret; }
void GlyphFace::_fullIntersect(const Ray& world_ray, const double world_t, Intersection& result) const { Ray ray = rayToObject(world_ray); double t = world_t*ray.t_scale; Vector p = ray.getPoint(t); Vector2 uv; // No support for UV-coordinates result = Intersection(p,t,normal,uv); intersectionToWorld(result); }
// ray r1 started at time t1 minus ray r2 started at time t2 Ray rayMinusRay(const Ray& r1, float t1, const Ray& r2, float t2) { // get points at respective times float p1[3], p2[3]; r1.getPoint(t1, p1); r2.getPoint(t2, p2); // construct new ray float p[3], d[3]; p[0] = p1[0] - p2[0]; p[1] = p1[1] - p2[1]; p[2] = p1[2] - p2[2]; d[0] = r1.getDirection()[0] - r2.getDirection()[0]; d[1] = r1.getDirection()[1] - r2.getDirection()[1]; d[2] = r1.getDirection()[2] - r2.getDirection()[2]; return Ray(p, d); }
void Sphere::_fullIntersect(const Ray& ray, const double t, Intersection& result) const { Vector p = ray.getPoint(t); Vector n = p - center; n.normalize(); Vector2 uv; if (getMaterial() != NULL && getMaterial()->requiresUV()) { //cout << "Getting UV" << endl; uv = getUV(n); } result = Intersection(p,t,n,uv); }
std::vector < std::pair <float, std::string> > PhysicsSystem::getFacedObjects (float mouseX, float mouseY) { Ray ray = mRender.getCamera()->getCameraToViewportRay(mouseX, mouseY); Ogre::Vector3 from = ray.getOrigin(); Ogre::Vector3 to = ray.getPoint(500); /// \todo make this distance (ray length) configurable btVector3 _from, _to; // OGRE to MW coordinates _from = btVector3(from.x, -from.z, from.y); _to = btVector3(to.x, -to.z, to.y); return mEngine->rayTest2(_from,_to); }
//intersect Intersection InfinitePlane::intersect(const Ray& ray, float previousBestDistance) const { float x = dot(ray.d_, normal_); if (std::abs(x)<epsilon) { return Intersection::failure(); } float distance = (dot(Vector(origin_.x_, origin_.y_, origin_.z_), normal_) - dot(Vector(ray.o_.x_, ray.o_.y_, ray.o_.z_), normal_)) / x; return Intersection(distance, ray, this, normal_, ray.getPoint(distance), true); }
bool CubeCollider::raycastALT(const Ray & ray, RaycastHit & hitInfo){ glm::vec3 position = object->getTransform()->getPosition(); glm::vec3 dirToCenter = ray.origin - position; if(glm::dot(ray.direction, dirToCenter) >= 0){ //std::cout << "ray is going in a different direction" << std::endl; return false; } transformNormals(); Plane planes[6]; for(int i = 0; i < 6; i ++){ planes[i] = Plane(transformedNormals[i],position + center + (transformedNormals[i] * size * .5f) ); } for(int i = 0; i < 6; i ++){ bool viable = true; Plane plane = planes[i]; float enter; if(plane.raycast(ray, enter)){ glm::vec3 point = ray.getPoint(enter); for(int j = 0; j < 6; j++){ if(i == j) continue; if(glm::dot(planes[i].normal, point - planes[i].point ) >= 0){ //point is behind plane } else{ //point is in front of plane viable = false; break; } } if(viable){ hitInfo.point = point; hitInfo.distance = enter; hitInfo.normal = transformedNormals[i]; hitInfo.object = object; return true; } } else{ // a ray missed one of the faces return false; } } return false; }
void ExtrudedCurve::_fullIntersect(const Ray& world_ray, const double world_t, Intersection& result) const { Ray ray = rayToObject(world_ray); double t = world_t*ray.t_scale; Vector p = ray.getPoint(t); Vector2 along = b(findClosestT(ray) + EPSILON); Vector p2 = p - Vector(along.x(), along.y(), p.z()); Vector p3 = p - Vector(p.x(), p.y(), p.z() - EPSILON); Vector n = Vector::xProduct(p3,p2); n.normalize(); Vector2 uv; // No support for UV-coordinates result = Intersection(p,t,n,uv); intersectionToWorld(result); }
bool Bullet::raycast(const Ray& ray, PhysicsIntersectResult& result) const { auto endPoint = ray.getPoint(MaxRayDistance); auto intersections = Vector<PhysicsIntersectResult>(); auto callback = RayResultCollector(ray, intersections); dynamicsWorld_->rayTest(toBullet(ray.getOrigin()), toBullet(endPoint), callback); if (intersections.empty()) return false; intersections.sort(); result = intersections[0]; return true; }
Intersection InfinitePlane::intersect(const Ray& ray, float previousBestDistance) const { float temp = dot(ray.d , normal); float distance = dot((origin - ray.o), normal) / temp; Point hit = ray.getPoint(distance); Point local = Point(hit.x - origin.x, hit.y - origin.y, hit.z - origin.z); if(distance > epsilon && distance + epsilon < previousBestDistance) { float dir = dot(ray.o - origin, normal); if(dir < 0) { return Intersection(distance, ray, this, -normal, local); } else if(dir > 0) { return Intersection(distance, ray, this, normal, local); } } return Intersection::failure(); }
double GlyphFace::_fastIntersect(const Ray& world_ray) const { Ray ray = rayToObject(world_ray); Vector d = ray.getDirection(); Vector o = ray.getOrigin(); // Find the point p where the ray intersects the xy-plane if (d.z() == 0) return -1; double t = -o.z() / d.z(); if (t < EPSILON) return -1; Vector pp = ray.getPoint(t); Vector2 p = Vector2(pp.x(), pp.y()); // Make sure that the intersection point p is inside the glyph. if (!glyph->isInside(p)) return -1; // Return the t in world scale return t / ray.t_scale; }
Real Chunks::getHeight( Real x, Real z ) { Real height = 0.0f; //遍历顶点,筛选出地形圆覆盖的顶点 for (size_t i = 0; i != mChunks.size(); ++i) { Chunk* c = mChunks[i]; //先过滤大部分的chunk { //如何判断一个点是否在一个正方形? Vec3 leftLow = mPosition + Vec3(scChunkSize * c->mPostion.x, 0.0f, -scChunkSize * c->mPostion.y); Real maxX = leftLow.x + scChunkSize; Real minX = leftLow.x; Real maxZ = leftLow.z; Real minZ = leftLow.z - scChunkSize; if (x < minX || x > maxX || z < minZ || z > maxZ) { continue; } } Mat4 m; m.makeTransform(mPosition + Vec3(scChunkSize * c->mPostion.x, 0.0f, -scChunkSize * c->mPostion.y), Vec3(scChunkSize, 1.0f, scChunkSize), Quaternion::IDENTITY); std::vector<Real> ts; Vec3 p = Vec3(x, 0.0f, z); Ray r; r._direction = Vec3::NEGATIVE_UNIT_Y; r._origin = Vec3(x, 100000.0f, z); for (size_t k = 0; k != c->mIndices.size(); k += 3) { Vec3 p0 = m * c->mVertices[c->mIndices[k]]; Vec3 p1 = m * c->mVertices[c->mIndices[k + 1]]; Vec3 p2 = m * c->mVertices[c->mIndices[k + 2]]; std::pair<bool, Real> result = Zen::intersects(r, p0, p1, p2); if (result.first) { height = r.getPoint(result.second).y; return height; } } } return height; }
Color Object::phongReflectionColor(const Ray &ray, const Point &P, Scene* scene) const { Object* tempObject; Point tempPoint; double L_N, R_V_alpha; Vector N = normalAtPoint(P), L, R; Vector V = Vector(P, ray.getPoint()).normalize(); Color ambiant = scene->getAmbiantColor(), lightColor; double red = Ka[0] * ambiant.R, green = Ka[1] * ambiant.G, blue = Ka[2] * ambiant.B; std::vector<Light*>::const_iterator l; for (l = scene->lightsBegin(); l != scene->lightsEnd(); ++l) { L = Vector(P, (*l)->getSource()).normalize(); if (L * N < 0) continue; scene->firstObjectHitByRay(Ray((*l)->getSource(), L * (-1)), tempObject, tempPoint); if (tempObject != this) continue; lightColor = (*l)->getColor(); R = L.reflectedBy(N); L_N = L * N; R_V_alpha = pow(R * V, alpha); red += lightColor.R * (Kd[0] * L_N + Ks[0] * R_V_alpha); green += lightColor.G * (Kd[1] * L_N + Ks[1] * R_V_alpha); blue += lightColor.B * (Kd[2] * L_N + Ks[2] * R_V_alpha); } return Color((unsigned char)((red > 255) ? 255 : red), (unsigned char)((green > 255) ? 255 : green), (unsigned char)((blue > 255) ? 255 : blue)); }
void SceneMouse::update(float dt) { if (App::sim_state.GetActive() == SimState::PAUSED) { return; } // Do nothing when paused if (mouseGrabState == 1 && grab_truck) { // get values Ray mouseRay = getMouseRay(); lastgrabpos = mouseRay.getPoint(mindist); // update visual line pickLine->beginUpdate(0); pickLine->position(grab_truck->nodes[minnode].AbsPosition); pickLine->position(lastgrabpos); pickLine->end(); // add forces grab_truck->mouseMove(minnode, lastgrabpos, mouseGrabForce); } }
std::pair<bool, Vector3> TerrainInfo::rayIntersects(const Ray& ray) const { AxisAlignedBox box = getExtents(); Vector3 point = ray.getOrigin(); Vector3 dir = ray.getDirection(); // first, does the ray start from inside the terrain extents? if (!box.contains(point)) { // not inside the box, so let's see if we are actually // colliding with it pair<bool, Real> res = ray.intersects(box); if (!res.first) return make_pair(false, Vector3::ZERO); // update point to the collision position point = ray.getPoint(res.second); } // now move along the ray until we intersect or leave the bounding box while (true) { // have we arived at or under the terrain height? // note that this approach means that ray queries from below won't work // correctly, but then again, that shouldn't be a usual case... float height = getHeightAt(point.x, point.z); if (point.y <= height) { point.y = height; return make_pair(true, point); } // move further... point += dir; // check if we are still inside the boundaries if (point.x < box.getMinimum().x || point.z < box.getMinimum().z || point.x > box.getMaximum().x || point.z > box.getMaximum().z) return make_pair(false, Vector3::ZERO); } }