float RayMarcher::marchSecondary( const Ray &ray ) { const float RAY_EPSILON = 0.50f; float boxTimes[2]; if( mBoundingBox.intersect( ray, boxTimes ) != 2 ) return 0; Vec3f pointOfDeparture; if( boxTimes[0] >= 0 ) pointOfDeparture = ray.calcPosition( boxTimes[0] ); else pointOfDeparture = ray.calcPosition( boxTimes[1] ); float span = ray.getOrigin().distance( pointOfDeparture ); int numSteps = (int)( span / RAY_EPSILON ); if( numSteps <= 0 ) return 0; Vec3f step( ray.getDirection() ); step *= RAY_EPSILON; Vec3f rayPos = ray.getOrigin(); float result = 0; for( int i = 0; i < numSteps; ++i ) { float D = sampleDensity( rayPos ) * RAY_EPSILON; result += D * ( 1.0f - result ); rayPos += step; } return result; }
ptc::IntersectDescr Rectangle::intersect( const Ray& ray ) { const double dir_dot = normal_.dot( ray.getDir() ); const bool is_grazing = std::abs( dir_dot ) <= 1e-4; const bool is_wrong_side = !getIsDoubleSided() && dir_dot >= -1e-4; if( is_grazing || is_wrong_side ) { return IntersectDescr( this ); } const Vector center_vec = center_ - ray.getOrigin(); const double distance = -normal_.dot( center_vec ); const double param = distance / -dir_dot; const Vector intersect = ray.getOrigin() + param * ray.getDir(); const Vector intersect_vec = intersect - center_; const bool is_right_vec_ok = std::abs( right_.dot( intersect_vec ) ) <= .5 * width_; const bool is_up_vec_ok = std::abs( up_.dot( intersect_vec ) ) <= .5 * height_; if( is_right_vec_ok && is_up_vec_ok ) { return IntersectDescr( param, intersect, normal_, ray.getDir(), this ); } return IntersectDescr( this ); }
glm::vec3 rayTrace(Ray &ray, const float& t, const glm::vec3& normal, RayTracerState& state) { std::vector<std::shared_ptr<LightObject>>::iterator iter; glm::vec3 color; glm::vec3 p = ray.getOrigin() + t*ray.getDirection(); for(iter = state.getLights().begin(); iter != state.getLights().end(); iter++){ float shadow_value; shadow_value = (*iter)->PointInShadow(p, state); //skipping contribution from this light if the object is fully shadowed by it if(shadow_value <=0.00001f) continue; glm::vec3 pos = (*iter)->position; glm::vec3 diff = (*iter)->diff; glm::vec3 spec = (*iter)->spec; glm::vec3 v = glm::normalize(ray.getOrigin() - p); glm::vec3 l = glm::normalize(pos - p); glm::vec3 h = glm::normalize(v+l); glm::vec3 n = glm::normalize(normal); float diffuse = glm::max(0.0f, glm::dot(n, l)); float specular = glm::pow( glm::max(0.0f, glm::dot(n, h)), 50.0f); glm::vec3 new_color = glm::vec3( (diff*diffuse)+(spec*specular) ) * shadow_value ; color += new_color; } color/=state.getLights().size(); //glm::vec3 absnormal = glm::vec3(abs(normal.x),abs(normal.y),abs(normal.z)); return color;//*shadefactor; }
Point UIManagerSpherical::projectRay(const Ray& ray) const { /* Check if the line defined by the ray intersects the sphere: */ Scalar d2=Geometry::sqr(ray.getDirection()); Vector oc=ray.getOrigin()-sphere.getCenter(); Scalar ph=oc*ray.getDirection(); Scalar det=Math::sqr(ph)-(Geometry::sqr(oc)-Math::sqr(sphere.getRadius()))*d2; if(det>=Scalar(0)) { /* Calculate the point where the line exits the sphere: */ det=Math::sqrt(det); return ray((-ph+det)/d2); } else { /* Return the projection of the ray's origin onto the sphere: */ Vector d=ray.getOrigin()-sphere.getCenter(); Scalar dLen=d.mag(); if(dLen==Scalar(0)) { d=getForwardDirection(); dLen=d.mag(); } return sphere.getCenter()+d*(sphere.getRadius()/dLen); } }
Vertex Rendering::shade(Ray intersect, Scene scene, Vertex viewerDirection) { // intersect is a ray with origin at the point of intersect, // and direction of the normal of the intersected polygon Vertex shade (0,0,0); vector<Vertex> lights = scene.getDirectionalLights(); for (int a=0; a<lights.size(); a++) { // see if that light is blocked, if so, it's shadow Vertex light = Vertex(lights[a].get(0), lights[a].get(1), lights[a].get(2)); Vertex color = Vertex(lights[a].get(3), lights[a].get(4), lights[a].get(5)); light = light.scale(-1); if (!isShadowed(intersect.getOrigin(), light, scene, false)) { light = light.normalize(); float gradient = max(0.0f, light.dot(intersect.getDirection())); float specular = intersect.getDirection().reflect(light.scale(-1)).dot(viewerDirection.scale(-1).normalize()); specular = pow(max(0.0f, specular),specularConst); shade = shade.add(color.scale(gradient+specular)); } } vector<Vertex> plights = scene.getPointLights(); for (int a=0; a<plights.size(); a++) { Vertex light = Vertex(plights[a].get(0), plights[a].get(1), plights[a].get(2)); Vertex color = Vertex(plights[a].get(3), plights[a].get(4), plights[a].get(5)); light = light.sub(intersect.getOrigin()); if (!isShadowed(intersect.getOrigin(), light, scene, true)) { light = light.normalize(); float gradient = max(0.0f, light.dot(intersect.getDirection())); float specular = intersect.getDirection().reflect(light.scale(-1)).dot(viewerDirection.scale(-1).normalize()); specular = pow(max(0.0f, specular),10); shade = shade.add(color.scale(gradient+specular)); } } return shade; }
bool Rect::shadowHit(const Ray& ray, float& tmin) const { if(!castsShadows) return false; float t = glm::dot((corner - ray.getOrigin()),normal) / glm::dot(ray.getDirection(),normal); if(t<=KEpsilon) return false; glm::vec3 point = ray.getOrigin() + t * ray.getDirection(); glm::vec3 d = point - v0; float dDota = glm::dot(d, v0); if(dDota<0.0 || dDota > aLenSquared) return false; float dDotb = glm::dot(d, v1); if(dDotb<0.0f || dDotb > bLenSquared) return false; tmin = t; return true; }
Color Ray::shaded_color(const LightConstPtr& light, const Vector& lightPoint, const Ray& reflectedray, const Vector& normal, ObjektConstPtr& obj, const Color& textureColor) { Color diffuse, specular; const Vector lightDir = light->getDirection(reflectedray.getOrigin(), lightPoint); const double lightIntensity = light->getItensity(reflectedray.getOrigin(), lightPoint); // Diffuse light double ldot = lightDir.dot(normal); if (1.0 + ldot > 1.0) { Color lambert = light->getColor().scmpy(ldot); diffuse = lambert.outprodc(obj->getProperty().getReflectance()); } // Specular light double spec = reflectedray.getDirection().dot(lightDir); if (1.0 + spec > 1.0) { spec = pow(spec, obj->getProperty().getShininess()); spec *= obj->getProperty().getSpecular(); specular = light->getColor().scmpy(spec); } Color reflected_color = diffuse.addcolor(specular); if (!textureColor.isNull()) { reflected_color = reflected_color.outprodc(textureColor); } return reflected_color.scmpy(lightIntensity); } /* shaded_color() */
pair<Vec3, SceneObject*> collide(Ray &ray, vector<SceneObject*>& sceneObjects){ // init the best impact point to the ray position Vec3 best_impact_point = ray.getOrigin(); // get the origin of the ray Vec3 ray_origin = ray.getOrigin(); // declare the best scene object; SceneObject* best_sceneObject = nullptr; // declare the best distance float best_dist = numeric_limits<float>::infinity(); // declare the current distance float dist = 0.0; // declare the pair for the intersect function pair<bool, Vec3> pair_intersect; // declare impact point Vec3 impact_point; //for each object of the scene for (vector<SceneObject*>::iterator it = sceneObjects.begin(); it != sceneObjects.end(); it++){ // determine if the ray intersect the object pair_intersect = (*it)->intersect(ray); if (pair_intersect.first){ // compute the distance between the ray and the impact point impact_point = pair_intersect.second - ray_origin; dist = impact_point.length(); // if it's the best if (best_dist > dist){ best_dist = dist; best_sceneObject = *it; best_impact_point = pair_intersect.second; } } } return pair<Vec3, SceneObject*>(best_impact_point, best_sceneObject); }
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; }
pair<bool, Vec3> Planar::intersect(Ray &ray){ // declare the impact point Vec3 impact_point = ray.getOrigin(); // normalize the vector (n is already normalized) Vec3 l0 = ray.getOrigin(); Vec3 l = ray.getDirection(); // calcul the denominator float denom = l * n; // if the ray and the normal vector of the planar isn't parallel if (denom > 1e-6) { // calcul t for determinate if the ray intersect the planar float t = ((position - l0) * n) / denom; // calcul the impact point impact_point = l0 + l * t; // verif if the impact point is in the square if (impact_point.getX() < maxCoordinates().getX() && impact_point.getX() > minCoordinates().getX() && impact_point.getY() < maxCoordinates().getY() && impact_point.getY() > minCoordinates().getY() /*&& impact_point.getZ() <= maxCoordinates().getZ() && impact_point.getZ() >= minCoordinates().getZ()*/){ return pair<bool, Vec3>(t >= 0, impact_point); } else{ return pair<bool, Vec3>(false, impact_point); } } return pair<bool, Vec3>(false, impact_point); }
bool Plane::intersect( Ray& ray, hpvec3& intersectionPoint ) { if( glm::abs(glm::dot(ray.getDirection(), m_normal)) < HP_EPSILON ) { return false; } hpreal t = -(glm::dot(ray.getOrigin(), m_normal) + glm::dot(m_origin, m_normal)) / glm::dot(ray.getDirection(), m_normal); intersectionPoint = ray.getOrigin() + t*ray.getDirection(); return true; }
bool Sphere::intersect(const Ray &r, Hit &h) const { // ========================================== // ASSIGNMENT: IMPLEMENT SPHERE INTERSECTION // ========================================== // a = d (dot) d double a = r.getDirection().Dot3(r.getDirection()); // b = 2d (dot) (orginPoint - centerPoint) double b = (2*(r.getDirection())).Dot3(r.getOrigin() - center); // c = (p_0 - p_c) dot (p_0-p_c) - r^2 double c = (r.getOrigin() - center).Dot3(r.getOrigin() - center) - (radius*radius); // t = (-b +/- sqrt(b2 - 4 a c)) / (2 a) // if inside is negative, then it doesn't intersect the sphere // if zero just a slight glance of sphere // if two then you interect and leave double inside = (b*b) - 4*a*c; if(inside >= 0 ){ //inside // get the first intersection point double t = ((-1*b) - sqrt(inside)) / (2*a); if(t < 0) return false; // get pt collision Vec3f pt = r.getOrigin() + t * r.getDirection(); if(pt.Distance3f(r.getOrigin()) < EPSILON) return false; Vec3f norm((pt.x() - center.x())/radius, (pt.y() - center.y())/radius, (pt.z() - center.z())/radius); norm.Normalize(); h.set(t,getMaterial(),norm); return true; }else{ // Negative and therefore missed return false; } // return true if the sphere was intersected, and update // the hit data structure to contain the value of t for the ray at // the intersection point, the material, and the normal return false; }
bool CollisionManager::isIntersecting(const Ray& ray, Entity* entity, Real& distance) { // get a pointer to the collision model ColDet::CollisionModel3D* mColModel = modelMap[entity->getMesh()->getName()]; if(mColModel == NULL) return false; // set the world transform for the entity { Matrix4 world; entity->getParentSceneNode()->getWorldTransforms(&world); float fMatrix[16]; fMatrix[0] = world[0][0]; fMatrix[1] = world[1][0]; fMatrix[2] = world[2][0]; fMatrix[3] = world[3][0]; fMatrix[4] = world[0][1]; fMatrix[5] = world[1][1]; fMatrix[6] = world[2][1]; fMatrix[7] = world[3][1]; fMatrix[8] = world[0][2]; fMatrix[9] = world[1][2]; fMatrix[10] = world[2][2]; fMatrix[11] = world[3][2]; fMatrix[12] = world[0][3]; fMatrix[13] = world[1][3]; fMatrix[14] = world[2][3]; fMatrix[15] = world[3][3]; mColModel->setTransform(fMatrix); } // convert the ray float Origin[3], Direction[3]; Origin[0] = ray.getOrigin().x; Origin[1] = ray.getOrigin().y; Origin[2] = ray.getOrigin().z; Direction[0] = ray.getDirection().x; Direction[1] = ray.getDirection().y; Direction[2] = ray.getDirection().z; // check for a collision bool col = mColModel->rayCollision(Origin, Direction); // for testing purposes // mColModel->getCollidingTriangles(t1, t2, false); // mColModel->getCollisionPoint(colPoint, false); float collisionPoint[3]; mColModel->getCollisionPoint(collisionPoint, false); Vector displacement = ray.getOrigin() - Vector(collisionPoint[0], collisionPoint[1], collisionPoint[2]); distance = displacement.length(); return col; }
bool TrianglePatch::hit(const Ray &r,double tmax,double time,HitRecord &record)const{ Vector3 p0=animation[0](vertex[0],time); Vector3 p1=animation[1](vertex[1],time); Vector3 p2=animation[2](vertex[2],time); Vector3 n0=animation[0](vertex[0]+normal[0],time)-p0; Vector3 n1=animation[1](vertex[1]+normal[1],time)-p1; Vector3 n2=animation[2](vertex[2]+normal[2],time)-p2; double A=p0.getX()-p1.getX(); double B=p0.getY()-p1.getY(); double C=p0.getZ()-p1.getZ(); double D=p0.getX()-p2.getX(); double E=p0.getY()-p2.getY(); double F=p0.getZ()-p2.getZ(); double G=r.getDirection().getX(); double H=r.getDirection().getY(); double I=r.getDirection().getZ(); double J=p0.getX()-r.getOrigin().getX(); double K=p0.getY()-r.getOrigin().getY(); double L=p0.getZ()-r.getOrigin().getZ(); double EIHF=E*I-H*F; double GFDI=G*F-D*I; double DHEG=D*H-E*G; double denom=(A*EIHF+B*GFDI+C*DHEG); double beta=(J*EIHF+K*GFDI+L*DHEG)/denom; if((beta<=0.0f)||(beta>=1.0f)) return false; double AKJB=A*K-J*B; double JCAL=J*C-A*L; double BLKC=B*L-K*C; double gamma=(I*AKJB+H*JCAL+G*BLKC)/denom; if((gamma<=0.0f)||(gamma>=1.0f)) return false; double t=-(F*AKJB+E*JCAL+D*BLKC)/denom; if((t>=0.0f)&&(t<=tmax)){ record.t=t; record.material=std::make_shared<Material>(material); record.hitpoint=r.pointAt(t); record.normal=normalize(n0+n1+n2); record.UVcoord=(1.0f-beta-gamma)*texCoord[0]+beta*texCoord[1]+gamma*texCoord[2]; return true; } return false; }
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); }
float KDTreeRayTracer::findNearestObject(const Ray &r , Object*& nearObj) { Vector ray_entry, ray_exit; float near_dist = INT_MAX; std::stack<BoundingBox*> box_stack; // push root on to stack box_stack.push(tree_root); while (!box_stack.empty()) { BoundingBox* cur_box = box_stack.top(); box_stack.pop(); // check if we are at a leaf node if (cur_box->box_depth == tree_depth) { // there are objects in leaf node if (cur_box->objs.size() > 0) { std::list<Object*>::iterator it; for (it=cur_box->objs.begin(); it != cur_box->objs.end(); it++) { Vector pt; // if the ray doesn't intersect, continue if(!(*it)->getRayIntersection(r, pt)) continue; // if the ray intersects outside the scene, continue if (!scene.checkInScene(pt)) continue; float obj_dist = pt.length(r.getOrigin()); if(obj_dist < near_dist) { near_dist = obj_dist; nearObj = *it; } } if (near_dist < INT_MAX) // we hit an object return near_dist; } else continue; } else { // we aren't at a leaf node yet if (cur_box->l_child->containsPoint(r.getOrigin())) { // ray origin is in l_child if (cur_box->r_child->intersectsRay(r)) box_stack.push(cur_box->r_child); box_stack.push(cur_box->l_child); } else { // ray origin in r_child if (cur_box->l_child->intersectsRay(r)) box_stack.push(cur_box->l_child); box_stack.push(cur_box->r_child); } } } return near_dist; }
IntersectionCompound Triangle::getIntersection(const Ray& ray) const{ IntersectionCompound ic; if( ray.getDirection().dot(_normal)>-eps )//no lightnin return ic; ic.mat = 0; ic.px=ic.py=-1; ic.t = -1; //mehod from http://www.devmaster.net/wiki/Ray-triangle_intersection real distance = -((ray.getOrigin()-_v1).dot(_normal))/(ray.getDirection().dot(_normal)); if(distance<eps){//no hit if the triangle is hit from behind //std::cout<<"behind object"<<std::endl; ic.t = -1; return ic; } Vector3 &point = ic.hitpoint; point = ray.getOrigin()+distance*ray.getDirection(); ic.t=distance; //find dominat axis real p[2]; p[0]= _dominant==0?(point[1]-_v1[1]):(point[0]-_v1[0]); p[1]= _dominant==2?(point[1]-_v1[1]):(point[2]-_v1[2]); real u = p[1]*_ud1 + p[0]*_ud2; if(u<-eps){//not hit ic.t = -1; return ic; } real v = p[1]* _vd1 + p[0]*_vd2; //ensure u,v,w \in [0,1] if( v<-eps or u+v>1+eps){ // not hit ic.t = -1; return ic; } //calculate correct color ic.mat = getMaterial(); if(not _normalsSet ) ic.normal = _normal; else ic.normal = u*_normals[1] + v*_normals[2] + (1-u-v)*_normals[0]; ic.normal.normalize(); //normals have to be initialiased with somethng useful! ic.px = u*_px[1] + v*_px[2] + (1-u-v)*_px[0]; ic.py = u*_py[1] + v*_py[2] + (1-u-v)*_py[0]; return ic; }
BoxRayDragger::Interval BoxRayDragger::intersectBox(const Ray& ray,const Point& center,const Scalar halfSize[3]) { /* Initialize the intersection interval to the full ray range: */ Scalar l1=Scalar(0); Scalar l2=Math::Constants<Scalar>::max; /* Calculate the intersection interval of the ray with each box face and intersect the intervals: */ for(int i=0;i<3;++i) { /* Calculate top and bottom faces: */ Scalar top=center[i]+halfSize[i]; Scalar bot=center[i]-halfSize[i]; /* Calculate the ray intersections along this axis: */ Scalar lf1,lf2; /* Check the direction of the ray relatively to the box: */ if(ray.getDirection()[i]<Scalar(0)) { /* Ray intersects top face first: */ lf1=(top-ray.getOrigin()[i])/ray.getDirection()[i]; lf2=(bot-ray.getOrigin()[i])/ray.getDirection()[i]; } else if(ray.getDirection()[i]>Scalar(0)) { /* Ray intersects bottom face first: */ lf1=(bot-ray.getOrigin()[i])/ray.getDirection()[i]; lf2=(top-ray.getOrigin()[i])/ray.getDirection()[i]; } else if(center[i]-halfSize[i]<=ray.getOrigin()[i]&&ray.getOrigin()[i]<=center[i]+halfSize[i]) { /* Ray is completely between the faces: */ lf1=Scalar(0); lf2=Math::Constants<Scalar>::max; } else { /* Ray is completely outside the box: */ lf1=Scalar(-1); lf2=Scalar(-1); } /* Intersect the calculated ray intersection with the complete interval: */ if(l1<lf1) l1=lf1; if(l2>lf2) l2=lf2; } /* Return the result interval: */ return Interval(l1,l2); }
glm::vec3 rayTrace(Ray &ray, const float& t, const glm::vec3& normal, RayTracerState& state) { glm::vec3 p = ray.getOrigin() + t*ray.getDirection(); glm::vec3 v = glm::normalize(ray.getOrigin() - p); glm::vec3 l = glm::normalize(this->pos - p); glm::vec3 h = glm::normalize(v + l); glm::vec3 n = glm::normalize(normal); float diffuse = glm::max(0.0f, glm::dot(n, l)); float specular = glm::pow( glm::max(0.0f, glm::dot(n, h)), 30.0f); return glm::vec3( (diff*diffuse) + (spec*specular) ); }
bool Triangle::intersects(const Ray& ray, float* distance /*= nullptr*/, Vec3* point /*= nullptr*/) { float a,b,c,d,e,f,g,h,i,j,k,l; Vec3 dir = ray.getDirection(); a = coords[0].x - coords[1].x; b = coords[0].y - coords[1].y; c = coords[0].z - coords[1].z; d = coords[0].x - coords[2].x; e = coords[0].y - coords[2].y; f = coords[0].z - coords[2].z; g = dir.x; h = dir.y; i = dir.z; j = coords[0].x - ray.getOrigin().x; k = coords[0].y - ray.getOrigin().y; l = coords[0].z - ray.getOrigin().z; float t, beta, gama, m; m = a*(e*i - h*f) + b*(g*f - d*i) + c*(d*h-e*g); beta = ( j*(e*i-h*f) + k*(g*f-d*i) + l*(d*h-e*g) ) / m; gama = ( i*(a*k-j*b) + h*(j*c-a*l) + g*(b*l-k*c) ) / m; t = 0- (f*(a*k-j*b) + e*(j*c-a*l) + d*(b*l-k*c)) / m; if (distance) { *distance = t; } Vec3 iteration(t*dir.x, t*dir.y, t*dir.z); if (point) { *point = Vec3(ray.getOrigin().x + iteration.x, ray.getOrigin().y + iteration.y, ray.getOrigin().z + iteration.z); } if (gama <= 0 || gama >= 1) { return false; } if (beta <= 0 || beta >= 1 - gama) { return false; } if (ray.getDirection().dot(normal) < 0) { return false; } return true; }
Intersection Triangle::hit(Ray ray) { ray.setOrigin(vec3(getInverseTransform() * vec4(ray.getOrigin(),1))); ray.setDirection(glm::normalize(vec3(getInverseTransform() * vec4(ray.getDirection(),0)))); // R(t) = o + td; // ax + by + cz = d => n·X=d // n·R(t) = d // n · [o + td] = d // n·o + nt·d = d // t = (d-n·o)/(n·d) vec3 ab = m_b-m_a; vec3 ac = m_c-m_a; vec3 normal = glm::normalize(glm::cross(ab,ac)); float nd = glm::dot(normal,ray.getDirection()); if (nd == 0) // PARAREL { return Intersection(false); } float d = glm::dot(normal, m_a); float t = (d-glm::dot(normal,ray.getOrigin())) / nd; if (t < 0) { return Intersection(false); } vec3 pointq = ray.getOrigin() + t * ray.getDirection(); vec3 ap = pointq - m_a; vec3 bp = pointq - m_b; vec3 cp = pointq - m_c; vec3 bc = m_c - m_b; vec3 ca = m_a - m_c; float e1 = glm::dot(glm::cross(ab, ap),normal); float e2 = glm::dot(glm::cross(bc, bp),normal); float e3 = glm::dot(glm::cross(ca, cp),normal); if (e1 < 0 || e2 < 0 || e3 < 0) { return Intersection(false); } float dom = glm::dot(glm::cross(ab, ac),normal); float alpha = e2 /dom; float beta = e3/dom; float gamma = e1/dom; vec3 point = m_a*alpha + m_b*beta + m_c*gamma; return Intersection(true, point, normal); }
void Controller::OnMouseMove(Flags nFlags, int x, int y) { Point point(x,y); if (nFlags == LBUTTON) { Vec3 r; r.x = -(Float)(point.x - mouse.x)/3; r.y = (Float)(point.y - mouse.y)/3; r = cross(r, Vec3(0,0,1)); Matrix rot = Matrix::Rotation( r.normalized(), r.getLen()); m_Rotation = m_Rotation * rot; } if (nFlags == (LBUTTON|RBUTTON) ) { Vec3 r; r.x = -(Float)(point.x - mouse.x)/3; r.y = (Float)(point.y - mouse.y)/3; r = cross(r, Vec3(0,0,1)); Matrix rot = Matrix::Rotation( r.normalized(), r.getLen()); m_Rotation2 = m_Rotation2 * rot; } if (nFlags == RBUTTON ) { Vec3 n = transform(Vec3(0,0,-1), m_Rotation.getInverted() ); n = n.normalized(); Plane ebene = Plane(n.x, n.y, n.z, 0); Ray a = getViewport().DPtoRay(mouse.x, mouse.y); Ray b = getViewport().DPtoRay(point.x, point.y); Float ta = 0, tb = 0; ebene.getIntersectionWithLine(a.getOrigin(), a.getPointAt(1), ta); ebene.getIntersectionWithLine(b.getOrigin(), b.getPointAt(1), tb); Vec3 d = a.getPointAt(ta) - b.getPointAt(tb); m_Translation = m_Translation + transform(d, m_Rotation ); } mouse = point; }
int VirtualInputDevice::pickButton(const InputDevice* device,const Ray& ray) const { int result=-1; Point buttonPos=device->getTransformation().getOrigin(); buttonPos+=buttonOffset; buttonPos-=buttonPanelDirection*(Scalar(0.5)*buttonSpacing*Scalar(device->getNumButtons()-1)); Vector buttonStep=buttonPanelDirection*buttonSpacing; Scalar bs=Scalar(glyphRenderer->getGlyphSize())*buttonSize*Scalar(0.5); Scalar lambdaMin=Math::Constants<Scalar>::max; for(int buttonIndex=0;buttonIndex<device->getNumButtons();++buttonIndex) { Scalar lMin=Scalar(0); Scalar lMax=lambdaMin; for(int i=0;i<3;++i) { Scalar l1,l2; if(ray.getDirection()[i]<Scalar(0)) { l1=(buttonPos[i]+bs-ray.getOrigin()[i])/ray.getDirection()[i]; l2=(buttonPos[i]-bs-ray.getOrigin()[i])/ray.getDirection()[i]; } else if(ray.getDirection()[i]>Scalar(0)) { l1=(buttonPos[i]-bs-ray.getOrigin()[i])/ray.getDirection()[i]; l2=(buttonPos[i]+bs-ray.getOrigin()[i])/ray.getDirection()[i]; } else if(buttonPos[i]-bs<=ray.getOrigin()[i]&&ray.getOrigin()[i]<buttonPos[i]+bs) { l1=Scalar(0); l2=lambdaMin; } else l1=l2=Scalar(-1); if(lMin<l1) lMin=l1; if(lMax>l2) lMax=l2; } if(lMin<lMax) { result=buttonIndex; lambdaMin=lMin; } /* Go to next button: */ buttonPos+=buttonStep; } return result; }
//----------------------------------------------------------------------- bool BspRaySceneQuery::processNode(const BspNode* node, const Ray& tracingRay, RaySceneQueryListener* listener, Real maxDistance, Real traceDistance) { if (node->isLeaf()) { return processLeaf(node, tracingRay, listener, maxDistance, traceDistance); } bool res = true; std::pair<bool, Real> result = tracingRay.intersects(node->getSplitPlane()); if (result.first && result.second < maxDistance) { // Crosses the split plane, need to perform 2 queries // Calculate split point ray Vector3 splitPoint = tracingRay.getOrigin() + tracingRay.getDirection() * result.second; Ray splitRay(splitPoint, tracingRay.getDirection()); if (node->getSide(tracingRay.getOrigin()) == Plane::NEGATIVE_SIDE) { // Intersects from -ve side, so do back then front res = processNode( node->getBack(), tracingRay, listener, result.second, traceDistance); if (!res) return res; res = processNode( node->getFront(), splitRay, listener, maxDistance - result.second, traceDistance + result.second); } else { // Intersects from +ve side, so do front then back res = processNode(node->getFront(), tracingRay, listener, result.second, traceDistance); if (!res) return res; res = processNode(node->getBack(), splitRay, listener, maxDistance - result.second, traceDistance + result.second); } } else { // Does not cross the splitting plane, just cascade down one side res = processNode(node->getNextNode(tracingRay.getOrigin()), tracingRay, listener, maxDistance, traceDistance); } return res; }
vnl_matrix<double> CameraTransform(const Ray &View1, const Ray &View2) { //This function takes two rays (ie 2 sets of view points and view directions), and finds the matrix M between them (from V1 to V2) vgl_point_3d<double> A1 = View1.getOrigin(); vgl_point_3d<double> A2 = View1.PointAlong(1.0); vgl_point_3d<double> B1 = View2.getOrigin(); vgl_point_3d<double> B2 = View2.PointAlong(1.0); vtkSmartPointer<vtkLandmarkTransform> LandmarkTransform = vtkSmartPointer<vtkLandmarkTransform>::New(); vtkSmartPointer<vtkPoints> SourcePoints = vtkSmartPointer<vtkPoints>::New(); vtkSmartPointer<vtkPoints> TargetPoints = vtkSmartPointer<vtkPoints>::New(); double A1array[3] = {A1.x(), A1.y(), A1.z()}; SourcePoints->InsertNextPoint(A1array); double A2array[3] = {A2.x(), A2.y(), A2.z()}; SourcePoints->InsertNextPoint(A2array); double B1array[3] = {B1.x(), B1.y(), B1.z()}; TargetPoints->InsertNextPoint(B1array); double B2array[3] = {B2.x(), B2.y(), B2.z()}; TargetPoints->InsertNextPoint(B2array); LandmarkTransform->SetSourceLandmarks(SourcePoints); LandmarkTransform->SetTargetLandmarks(TargetPoints); LandmarkTransform->SetModeToRigidBody(); LandmarkTransform->Update(); vnl_matrix<double> Trans(4,4); vtkMatrix4x4* M = LandmarkTransform->GetMatrix(); //cout << M << endl; for(unsigned int r = 0; r < 4; r++) { for(unsigned int c = 0; c < 4; c++) { Trans(r,c) = M->GetElement(r,c); } } //cout << Trans << endl; return Trans; }
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); }
Vector3 GridSource::getIntersectionEnd(const Ray &ray, Real maxDistance) const { AxisAlignedBox box((Real)0, (Real)0, (Real)0, (Real)mWidth / mPosXScale, (Real)mHeight / mPosYScale, (Real)mDepth / mPosZScale); Vector3 direction = ray.getDirection().normalisedCopy(); Vector3 invertedDirection = (Real)-1.0 * direction; Vector3 origin = ray.getOrigin() + direction * box.getSize().length(); Ray inverted(origin, invertedDirection); std::pair<bool, Real> intersection = inverted.intersects(box); if (intersection.first) { return origin + invertedDirection * intersection.second; } return ray.getOrigin() + direction * maxDistance; }
bool Torus::hit(const Ray& ray, float& tmin, ShadeRec& sr) const { if(!bbox.hit(ray)) return false; glm::vec3 origin = ray.getOrigin(); glm::vec3 dir = ray.getDirection(); float coefs[5]; float roots[4]; //define coefficients float sumDSquared = glm::dot(dir,dir); float e = glm::dot(origin,origin) - sweptRadiusSQ - tubeRadiusSQ; float f = glm::dot(origin,dir); float fourASquared = 4.0f * sweptRadiusSQ; coefs[0] = e * e - fourASquared * (tubeRadiusSQ - origin.y * origin.y); coefs[1] = 4.0f * f * e + 2.0f * fourASquared * origin.y * dir.y; coefs[2] = 2.0f * sumDSquared * e + 4.0f * f * f + fourASquared * dir.y * dir.y; coefs[3] = 4.0f * sumDSquared * f; coefs[4] = sumDSquared * sumDSquared; int numRealRoots = solveQuartic(coefs,roots); bool intersected = false; float t = kHugeValue; if(numRealRoots == 0) return false; for(int i=0;i<numRealRoots;i++) if(roots[i] > KEpsilon) { intersected = true; if(roots[i] < t) t = roots[i]; } if(!intersected) return false; tmin = t; sr.localHitPoint = ray.getOrigin() + ray.getDirection() * t; sr.normal = computeNormals(sr.localHitPoint); return true; }
bool Sphere::intersect(const Ray& ray, RaySurfIntersection& res)const{ res.shp = NULL; //Transform ray to object space const Ray rOb = w2o(ray); const Vector o = Vector(rOb.getOrigin().x, rOb.getOrigin().y, rOb.getOrigin().z); const Vector d = rOb.getDir(); const float A = d.dot(d); const float B = 2.0f * (d.dot(o)); const float C = o.dot(o) - (r * r); struct MathUtils::QuadraticEqnRes<float> slv = MathUtils::solveQuadratic<float>(A, B, C); float tHitFinal = 0.0f; //After the below code this will eventually be set to //the first hit point in front of the camera if(slv.solCount == 0){ return false; }else if(slv.solCount == 1){ tHitFinal = slv.sol1; if(tHitFinal < 0.0f){ //No solutions in front of camera return false; } }else{ //2 solutions //Find smallest t value that is > 0.0f if(slv.sol1 < 0.0f && slv.sol2 < 0.0f){ //No solutions in front of camera return false; }else{ //At least one hit in front of camera slv.sol1 = slv.sol1 < 0.0f ? Constants::MAX_FLOAT_VAL : slv.sol1; slv.sol2 = slv.sol2 < 0.0f ? Constants::MAX_FLOAT_VAL : slv.sol2; tHitFinal = std::min<float>(slv.sol1, slv.sol2); } } //Make sure hit is in front of camera Assert(tHitFinal >= 0.0f); res.tHit = tHitFinal; res.locWS = ray(res.tHit); Vector normalVecAtHit = res.locWS - o2w(Point(0.0f,0.0f,0.0f)); res.n = normalVecAtHit.getNormalized(); res.shp = this; 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; }