bool Sphere::intersect(const Ray &r, Hit &h, float tmin) { Vec3f v = center - r.getOrigin(); float tp = v.Dot3(r.getDirection()); float det = tp*tp - v.Dot3(v) + radius*radius; //intersect if(det > 0) { //t' det = sqrtf(det); float t1 = tp - det; float t2 = tp + det; if(t1 > tmin && t1 < h.getT()) { Vec3f normal = (r.pointAtParameter(t1) - center); normal /= radius; normal.Normalize(); h.set(t1,material,normal,r); return 1; } else if(t2 > tmin && t2 < h.getT()) { //sphere's normal Vec3f normal = (r.pointAtParameter(t2) - center); normal /= radius; normal.Normalize(); h.set(t2,material,normal,r); return 1; } } return 0; }
/* 射线与平面求教 即直线的参数方程P = ori + t*dir 代入 平面方程 n * p + D =0 n(R0+t*Rd)+D=0 t=-(D+n*R0)/n*Rd hit 带走的信息包括: float t; Material *material; Vec3f normal; Vec3f intersectionPoint; */ bool Plane::intersect(const Ray &r, Hit &h, float tmin) { /* 需要判断射线是否与平面平行 如果t<0说明平面在视点之后 以上两个都不产生交点 */ float eps = 1e-6; float tmp = normal.Dot3(r.getDirection()); if (fabs(tmp) < eps) return false; float t = 0.0f; Vec3f r0 = r.getOrigin(); Vec3f rd = r.getDirection(); //这里一直不明白 t = (d - normal.Dot3(r0)) / normal.Dot3(rd); if (t < 0) return false; h.set(t, material, normal, r); if (t >= tmin) return true; else return false; }
bool Triangle::intersect(const Ray &r, Hit &h, float tmin) { Vec3f r0 = r.getOrigin(); Vec3f rd = r.getDirection(); Vec3f E1 = a - b; Vec3f E2 = a - c; Vec3f S = a - r0; //参数写错,rd写成r0了…… float de = det3x3(rd.x(), rd.y(), rd.z(), E1.x(), E1.y(), E1.z(), E2.x(), E2.y(), E2.z()); if (de == 0.0f) return false; float t = det3x3(S.x(), S.y(), S.z(), E1.x(), E1.y(), E1.z(), E2.x(), E2.y(), E2.z())/de; float belta = det3x3(rd.x(), rd.y(), rd.z(), S.x(), S.y(), S.z(), E2.x(), E2.y(), E2.z()) / de; float lamda = det3x3(rd.x(), rd.y(), rd.z(), E1.x(), E1.y(), E1.z(), S.x(), S.y(), S.z()) / de; Vec3f normal; Vec3f::Cross3(normal, b - a, c - a); normal.Normalize(); h.set(t, material, normal, r); if (t >= tmin && belta > 0.0f && lamda > 0.0f && belta + lamda < 1.0f) return true; else return false; }
bool Grid::intersect(const Ray &r, Hit &h, float tmin) { //Prepare the Material objects Vec3f diffuseColor(1, 1, 1); Vec3f specularColor(0, 0, 0); float exponent = 1; Vec3f reflectiveColor(0, 0, 0); Vec3f transparentColor(0, 0, 0); float indexOfRefraction = 1; PhongMaterial *m = new PhongMaterial(diffuseColor, specularColor, exponent, reflectiveColor, transparentColor, indexOfRefraction); //Start to do DDA MarchingInfo mi; initializeRayMarch(mi, r, tmin); bool hitSomething = false; int i, j, k; do { mi.getIndices(i, j, k); printf("The current point is:%d,%d,%d\n", i, j, k); if (mObjects[offset(i, j, k)].getNumObjects() > 0) { h.set(mi.get_tmin(), m, mi.getNormal(), r); return true; } mi.nextCell(); } while(i < mXSize && j < mYSize && k < mZSize); return false; }
bool Plane::intersect(const Ray & r, Hit & h, float tmin) { assert (tmin >= 0.0f); Vec3f org = r.getOrigin(); Vec3f dir = r.getDirection(); if (dir.Dot3(normal) < 1.0e-7 && dir.Dot3(normal) > -1.0e-7) { return false; } // Appromately parrell to plane float tempT = (offset - org.Dot3(normal)) / dir.Dot3(normal); if (tempT <= 1e-6) { return false; } else if (tempT >= tmin && tempT < h.getT()) { // Update Hit Point normal.Normalize(); h.set(tempT, NULL, normal, color, r); return true; } return false; }
bool Face::plane_intersect(const Ray &r, Hit &h, bool intersect_backfacing) const { // insert the explicit equation for the ray into the implicit equation of the plane // equation for a plane // ax + by + cz = d; // normal . p + direction = 0 // plug in ray // origin + direction * t = p(t) // origin . normal + t * direction . normal = d; // t = d - origin.normal / direction.normal; glm::vec3 normal = computeNormal(); float d = glm::dot(normal,(*this)[0]->get()); float numer = d - glm::dot(r.getOrigin(),normal); float denom = glm::dot(r.getDirection(),normal); if (denom == 0) return 0; // parallel to plane if (!intersect_backfacing && glm::dot(normal,r.getDirection()) >= 0) return 0; // hit the backside float t = numer / denom; if (t > EPSILON && t < h.getT()) { h.set(t,this->getMaterial(),normal); assert (h.getT() >= EPSILON); return 1; } return 0; }
bool Transform::Intersect(const Ray &r, Hit &h, float tmin) const { bool result = false; Matrix m = m_matrix; if ( m.Inverse() ) { Vec3f org = r.getOrigin(); Vec3f dir = r.getDirection(); m.Transform(org); m.TransformDirection(dir); Ray r2 (dir, org); result = m_pObject->Intersect(r2, h, tmin); if (result) { Matrix m1 = m; m1.Transpose(); Vec3f n = h.getNormal(); m1.TransformDirection(n); n.Normalize(); h.set(h.getT(), h.getMaterial(), n, r); } } return result; }
bool Face::plane_intersect(const Ray &r, Hit &h, bool intersect_backfacing, bool* backfacing_hit) { // insert the explicit equation for the ray into the implicit equation of the plane // equation for a plane // ax + by + cz = d; // normal . p + direction = 0 // plug in ray // origin + direction * t = p(t) // origin . normal + t * direction . normal = d; // t = d - origin.normal / direction.normal; Vec3f normal = computeNormal(); double d = normal.Dot3((*this)[0]->get()); double numer = d - r.getOrigin().Dot3(normal); double denom = r.getDirection().Dot3(normal); if (denom == 0) return 0; // parallel to plane if (!intersect_backfacing && normal.Dot3(r.getDirection()) >= 0) return 0; // hit the backside double t = numer / denom; if (t > EPSILON && t < h.getT()) { h.set(t,this->getMaterial(),normal,this); assert (h.getT() >= EPSILON); //hit the backside but that's okay in this case if (normal.Dot3(r.getDirection()) >= 0){ *backfacing_hit = true; } return 1; } return 0; }
bool Sphere::intersect(const Ray &r, Hit &h, float tmin) { //直线方程 P = t*D + R ① //圆方程 ||P||= raduis ② //将①带入②, 由点乘的性质(满足分配率,交换律),求得t^2+2RDt+R^2-r^2=0 //得t = -RD±sqrt(RD^2-R^2+r^2) //选择距离较近的那个点t = -RD-sqrt(RD^2-R^2+r^2) Vec3f D = r.getDirection(); Vec3f R = r.getOrigin()-center; float R2 = R.Dot3(R); float RD = R.Dot3(D); float b2_4ac = RD*RD-R2+radius*radius;//R2 RD RDRD这些其实可以存在ray里,但是算法研究以程序清晰为要 if(b2_4ac<0)return 0; float t; t = -RD - sqrt(b2_4ac); if(t<0){ t = -RD + sqrt(b2_4ac); if(t < 0)return 0; } if(t<h.getT()) { h.set(t, &color, r); } return 1; }
/* The intersect routine will first transform the ray, then delegate to the intersect routine of the contained object. Make sure to correctly transform the resulting normal according to the rule seen in lecture. You may choose to normalize the direction of the transformed ray or leave it un-normalized. If you decide not to normalize the direction, you might need to update some of your intersection code. */ bool Transform::intersect(const Ray &r, Hit &h, float tmin) { Vec3f r0 = r.getOrigin(); Vec3f rd = r.getDirection(); Matrix inv; matrix.Inverse(inv); inv.Transform(r0); inv.TransformDirection(rd); if (object != NULL) { //这里的h是有问题的,作如下修改: bool judge = object->intersect(Ray(r0,rd), h, tmin); Vec3f normal = h.getNormal(); //这里很奇怪,normal的方向没有修正,然而结果却是对的 //改了之后反而是错的!! //这里确定normal没有错,那么就是之后应用normal的 //问题 //好吧,就是这里的问题 //经过把图形摆正,发现求的法向量没有问题,但是没有单位化…………! matrix.TransformDirection(normal); normal.Normalize(); //or: //Matrix change,res; //matrix.Inverse(change); //change.Transpose(res); //res.TransformDirection(normal); h.set(h.getT(), h.getMaterial(), normal, r); return judge; } return false; }
bool Sphere::intersect(const Ray &r, Hit &h, float tmin){ /*Vector equation for sphere P*P - r^2 = 0 ((R0-c) + td)*((R0-c) + td) - r^2 = 0 (td)^2 + 2R0-c)td + (R0-c)^2 - r^2 =0 Use quadratic equation solve for t a = (d^2) b = 2(R0-c)d c = ((R0-c)^2 - r^2) */ Vec3f rayOrigin, rayDirection,segment,Q; float tpos,tneg,a,b,c,discriminant; rayOrigin = r.getOrigin(); rayDirection = r.getDirection(); segment = rayOrigin - _center; a = rayDirection.Dot3(rayDirection); b = 2*segment.Dot3(rayDirection); c = segment.Dot3(segment) - _radius*_radius; discriminant = sqrt(b*b - 4*a*c); tpos = (-b + discriminant)/(2*a); tneg = (-b - discriminant)/(2*a); if (tneg > tmin && tneg < h.getT()){ Q = r.pointAtParameter(tneg); Q = Q - _center; Q.Normalize(); h.set(tneg, _material,Q,r); return true; } else if (tpos > tmin && tpos < h.getT()){ Q = r.pointAtParameter(tpos); Q = Q - _center; Q.Normalize(); h.set(tpos,_material,Q,r); return true; } return false; }
void Track::extrapolateToLayer0() { Int_t nTracks = GetEntriesFast(); Int_t eventID = -1; if (!At(0)) { // OK, no information in first layer // now GetLayer(1) should be 1, and GetLayer(2) should be 2 // If both layer 0 and 2 are skipped, some more extrapolation should be done // maybe set new x as [1.x - slope.x * (2.z - 1.z)] Hit *slope = new Hit(); if (!At(1)) { cout << "No pointer for At(1) as well... Aborting this track extrapolation.\n"; return; } else { eventID = At(1)->getEventID(); if (getLayer(1) == 0) return; // hotfix... Why is layer 0 sometimes placed in idx 1? Must fix this. } if (At(2)) { slope->set(getX(2) - getX(1), getY(2) - getY(1), getLayer(2) - getLayer(1)); if (eventID<0) eventID = At(2)->getEventID(); } else if (!At(2) && At(3)) { slope->set(getX(3) - getX(1), getY(3) - getY(1), getLayer(3) - getLayer(1)); if (eventID<0) eventID = At(3)->getEventID(); } else { cout << "Too many holes (!At(0), At(1), !At(2), !At(3), .....), aborting this track extrapolation.\n"; return; } // must create pointer! Cluster *newStart = (Cluster*) track_.ConstructedAt(0); newStart->set(getX(1) - slope->getLayer() * slope->getX(), // new x getY(1) - slope->getLayer() * slope->getY(), // new y 0); // layer = 0 newStart->setEventID(eventID); } }
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 Triangle::intersect( const Ray& r , Hit& h , float tmin){ Vector3f R_o = r.getOrigin(); Vector3f R_d = r.getDirection(); Matrix3f A( this->a.x()-this->b.x() , this->a.x()-this->c.x() , R_d.x() , this->a.y()-this->b.y() , this->a.y()-this->c.y() , R_d.y() , this->a.z()-this->b.z() , this->a.z()-this->c.z() , R_d.z() ); Matrix3f BetaM( this->a.x()-R_o.x() , this->a.x()-this->c.x() , R_d.x() , this->a.y()-R_o.y() , this->a.y()-this->c.y() , R_d.y() , this->a.z()-R_o.z() , this->a.z()-this->c.z() , R_d.z() ); float beta = BetaM.determinant() / A.determinant(); Matrix3f GammaM( this->a.x()-this->b.x() , this->a.x()-R_o.x() , R_d.x() , this->a.y()-this->b.y() , this->a.y()-R_o.y() , R_d.y() , this->a.z()-this->b.z() , this->a.z()-R_o.z() , R_d.z() ); float gamma = GammaM.determinant() / A.determinant(); float alpha = 1.0f - beta - gamma; Matrix3f tM( this->a.x()-this->b.x() , this->a.x()-this->c.x() , this->a.x()-R_o.x() , this->a.y()-this->b.y() , this->a.y()-this->c.y() , this->a.y()-R_o.y() , this->a.z()-this->b.z() , this->a.z()-this->c.z() , this->a.z()-R_o.z() ); float t = tM.determinant() / A.determinant(); if (beta + gamma > 1){ return false; } if (beta < 0){ return false; } if (gamma < 0){ return false; } if (t > tmin && t < h.getT()){ Vector3f newNormal = (alpha*this->normals[0] + beta*this->normals[1] + gamma*this->normals[2]).normalized(); h.set(t, this->material, newNormal); Vector2f newTexCoord = (alpha*this->texCoords[0] + beta*this->texCoords[1] + gamma*this->texCoords[2]); h.setTexCoord(newTexCoord); return true; } else{ return false; } }
//normal.(r.origin + t*r.direction) +d = 0 bool Plane::intersect(const Ray &r, Hit &h, float tmin) { float isParallel = normal.Dot3(r.getDirection()); if(!Utility::isZero(isParallel)) { float dist = -(normal.Dot3(r.getOrigin())-d)/isParallel; //当时没有理解d的含义,构造是应该是ax+by+cz-d=0 if(dist > tmin && dist < h.getT()) { h.set(dist,material,normal,r); return 1; } } return 0; }
bool CylinderRing::intersect(const Ray &r, Hit &h) const { // intersect with the 4 parts of the ring double outer_t; Vec3f outer_normal; bool outer = IntersectFiniteCylinder(r,center,outer_radius,height,outer_t,outer_normal); double inner_t; Vec3f inner_normal; bool inner = IntersectFiniteCylinder(r,center,inner_radius,height,inner_t,inner_normal); double top_t; Vec3f top_normal; bool top = IntersectAnnulus(r,center+Vec3f(0,height/2.0,0),inner_radius,outer_radius,top_t,top_normal); double bottom_t; Vec3f bottom_normal; bool bottom = IntersectAnnulus(r,center-Vec3f(0,height/2.0,0),inner_radius,outer_radius,bottom_t,bottom_normal); bool answer = false; // return the closest intersection if (outer && (outer_t < h.getT())) { h.set(outer_t,this->getMaterial(),outer_normal,NULL); answer = true; } if (inner && (inner_t < h.getT())) { h.set(inner_t,this->getMaterial(),-inner_normal,NULL); answer = true; } if (top && (top_t < h.getT())) { h.set(top_t,this->getMaterial(),top_normal,NULL); answer = true; } if (bottom && (bottom_t < h.getT())) { h.set(bottom_t,this->getMaterial(),-bottom_normal,NULL); answer = true; } return answer; }
bool Plane::intersect( const Ray& r, Hit& h, float tmin ) const { float nd = this->m_normal.dot(r.getDirection()); if (nd == 0.0f) { return false; } float t = (this->m_d - (this->m_normal.dot(r.getOrigin())))/nd; if (t < h.getT() && t > tmin) { h.set(t, this->m_material, this->m_normal); return true; } return false; }
bool Transform::intersect(const Ray &r, Hit &h, float tmin) { Vec3f rTransOri = r.getOrigin(); Vec3f rTransDir = r.getDirection(); Matrix mInverse; m.Inverse(mInverse); mInverse.Transform(rTransOri); mInverse.TransformDirection(rTransDir); rTransDir.Normalize(); Ray rTrans(rTransDir,rTransOri); Hit hTrans(10000,NULL,Vec3f(0,0,0)); //need a new hit,because the x-y-z had changed 就因为这里没有使用一个新的hit导致了自己debug了两天 instance->intersect(rTrans,hTrans,tmin); if(hTrans.getT()<10000) { //world's t float t; //Vec3f hitPoint = rTransOri + rTransDir * hTrans.getT(); Vec3f hitPoint = rTrans.pointAtParameter(hTrans.getT()); m.Transform(hitPoint); Vec3f rOri = r.getOrigin(); Vec3f rDir = r.getDirection(); if((fabs(rDir[0])>=fabs(rDir[1]))&&(fabs(rDir[0])>=fabs(rDir[2]))){ t = (hitPoint[0] - rOri[0]) / rDir[0]; } else if((fabs(rDir[1])>=fabs(rDir[0]))&&(fabs(rDir[1])>=fabs(rDir[2]))){ t = (hitPoint[1] - rOri[1]) / rDir[1]; } else if((fabs(rDir[2])>=fabs(rDir[0]))&&(fabs(rDir[2])>=fabs(rDir[1]))){ t = (hitPoint[2] - rOri[2]) / rDir[2]; } //world's normal mInverse.Transpose(); Vec3f wNormal = hTrans.getNormal(); mInverse.TransformDirection(wNormal); wNormal.Normalize(); //need normalize //h.setNormal(wNormal); if(t>=tmin && t<=h.getT()) { h.set(t,hTrans.getMaterial(),wNormal,r); return 1; } } return 0; }
bool Transform::intersect( const Ray& r , Hit& h , float tmin) { Matrix4f iMatrix=TMatrix_.inverse(); Matrix4f tMatrix=TMatrix_.transposed() ; //Ray newRay = Ray((iMatrix * Vector4f(r.getOrigin(), 1.0f)).xyz(), (iMatrix* Vector4f(r.getDirection(), 0.0f)).xyz().normalized()); Ray newRay = Ray((iMatrix * Vector4f(r.getOrigin(), 1.0f)).xyz(), (iMatrix* Vector4f(r.getDirection(), 0.0f)).xyz()); if(o->intersect(newRay, h , tmin)) { h.set(h.getT(), h.getMaterial(), (iMatrix.transposed() * Vector4f(h.getNormal(), 0.0f)).xyz().normalized()); return true; } return false; }
bool Grid::intersectWithGridVisualization(const Ray & r, Hit & h, float tmin) const { RayTracing_Stats::IncrementNumIntersections(); MarchInfo mi; bool re = initializeRayMarch(mi, r, tmin); if ( re == false ) { return false; } int index_i, index_j, index_k; while ( IsCellValid(mi) ) { RayTracing_Stats::IncrementNumGridCellsTraversed(); index_i = mi.get_i(); index_j = mi.get_j(); index_k = mi.get_k(); Object3DVector & obj_array = cells[num_y * num_z * index_i + num_z * index_j + index_k].objs; int num_objs = obj_array.getNumOfObjects(); if ( num_objs > 0 ) { if ( mi.tmin < h.getT() ) { h.set(mi.tmin, selfRendering_m, mi.surfaceNormal, r); return true; } else return false; } else { mi.nextCell(); } } return false; }
bool Sphere::intersect(const Ray &r, Hit &h, float tmin) { Vec3f temp = r.getOrigin() - mCenterPoint; Vec3f rayDirection = r.getDirection(); double a = rayDirection.Dot3(rayDirection); double b = 2*rayDirection.Dot3(temp); double c = temp.Dot3(temp) - mRadius*mRadius; #ifdef DEBUG //cout << "temp=" << temp<<endl; //printf("Sphere::intersect, a=%f, b=%f, c=%f\n", a, b, c); #endif double discriminant = b*b - 4*a*c; if (discriminant > 0) { discriminant = sqrt(discriminant); double t = (- b - discriminant) / (2*a); if (t < tmin) t = (- b + discriminant) / (2*a); if (t < tmin || t > T_MAX) return false; #ifdef DEBUG // printf("Sphere::intersect, there is a hit, t=%f\n", t); #endif Vec3f normal = r.getOrigin() + t * r.getDirection() - mCenterPoint; normal.Normalize(); h.set(t, mMaterial, normal, r); return true; } return false; }
bool Transform::intersect(const Ray &r, Hit &h, float tmin) { Vec3f original = r.getOrigin(); Vec3f dir = r.getDirection(); mReverseMat.Transform(original); mReverseMat.TransformDirection(dir); Ray transformedRay(original, dir); if (mObj->intersect(transformedRay, h, tmin)) { Vec3f normal = h.getNormal(); Matrix t; mReverseMat.Transpose(t); t.TransformDirection(normal); h.set(h.getT(), h.getMaterial(), normal, r); return true; } return false; }
bool Rectangle::intersect(const Ray& r, Hit& h, float tmin) { Vector3f a = vertex0; Vector3f b = vertex0 + side_1; Vector3f c = vertex0 + side_2; Vector3f direction = r.getDirection(); Vector3f origin = r.getOrigin(); float list[9] = { (a.x()) - (b.x()),(a.y()) - (b.y()),(a.z()) - (b.z()), (a.x()) - (c.x()),(a.y()) - (c.y()),(a.z()) - (c.z()), (a[0]) - (origin[0]),(a[1]) - (origin[1]),(a[2]) - (origin[2]), }; Matrix3f A = Matrix3f(list[0], list[3], direction[0], list[1], list[4], direction[1], list[2], list[5], direction[2]); float determinant = A.determinant(); if (determinant == 0) { return false; } float t = Matrix3f::determinant3x3(list[0], list[3], list[6], list[1], list[4], list[7], list[2], list[5], list[8]) / determinant; if (t <= tmin || t >= h.getT()) { return false; } float beta = Matrix3f::determinant3x3(list[6], list[3], direction[0], list[7], list[4], direction[1], list[8], list[5], direction[2]) / determinant; float gamma = Matrix3f::determinant3x3(list[0], list[6], direction[0], list[1], list[7], direction[1], list[2], list[8], direction[2]) / determinant; if ((beta >= 0 && gamma >= 0 && beta <= 1 && gamma <= 1)) { h.set(t, this->material, normal); return true; } return false; }
bool Transform::intersect(const Ray & r, Hit & h, float tmin) { // Need to Transform Ray before do intersection Matrix reverseMat = transformMat; reverseMat.Inverse(); // cout << "Original Origin:\t" << r.getOrigin() << endl; // cout << "Original Direction:\t" << r.getDirection() << endl; Vec4f aug_origin(r.getOrigin(), 1); Vec3f aug_dir = r.getDirection(); reverseMat.Transform(aug_origin); reverseMat.TransformDirection(aug_dir); // cout << "Now Origin:\t" << r.getOrigin() << endl; // cout << "Now Direction:\t" << r.getDirection() << endl; // aug_dir.Normalize(); Ray transRay(aug_dir, Vec3f(aug_origin[0], aug_origin[1], aug_origin[2])); if ( !( object -> intersect(transRay, h, tmin) ) ) return false; // After transforming Ray, we need to transform Normal Matrix transposeRevMat = reverseMat; transposeRevMat.Transpose(); Vec3f hn = h.getNormal(); transposeRevMat.Transform(hn); hn.Normalize(); h.set(h.getT(), NULL, hn, r); return true; }
bool Grid::intersect(const Ray & r, Hit & h, float tmin) { RayTracing_Stats::IncrementNumIntersections(); MarchInfo mi; bool re = initializeRayMarch(mi, r, tmin); if ( re == false ) { return false; } int i, j, k; while ( IsCellValid(mi) ) { RayTracing_Stats::IncrementNumGridCellsTraversed(); i = mi.get_i(); j = mi.get_j(); k = mi.get_k(); if ( voxels[num_y * num_z * i + num_z * j + k] == true ) { if (mi.tmin < h.getT()) { h.set(mi.tmin, material, mi.surfaceNormal, r); return true; } else return false; } else { mi.nextCell(); } } return false; }
bool Triangle::intersect(const Ray& ray, Hit& hit, float tmin) { Vector3f direction = ray.getDirection(); Vector3f origin = ray.getOrigin(); float list[9] = { (a.x()) - (b.x()),(a.y()) - (b.y()),(a.z()) - (b.z()), (a.x()) - (c.x()),(a.y()) - (c.y()),(a.z()) - (c.z()), (a[0]) - (origin[0]),(a[1]) - (origin[1]),(a[2]) - (origin[2]), }; Matrix3f A = Matrix3f(list[0], list[3], direction[0], list[1], list[4], direction[1], list[2], list[5], direction[2]); float determinant = A.determinant(); if (determinant == 0) { return false; } float t = Matrix3f::determinant3x3(list[0], list[3], list[6], list[1], list[4], list[7], list[2], list[5], list[8]) / determinant; if (t <= tmin || t >= hit.getT()) { return false; } float beta = Matrix3f::determinant3x3(list[6], list[3], direction[0], list[7], list[4], direction[1], list[8], list[5], direction[2]) / determinant; float gamma = Matrix3f::determinant3x3(list[0], list[6], direction[0], list[1], list[7], direction[1], list[2], list[8], direction[2]) / determinant; if ((beta >= 0 && gamma >= 0 && beta + gamma <= 1) ) { if(hasTex) { hit.hasTex = true; hit.setTexCoord((1 - beta - gamma)*texCoords[0] + beta*texCoords[1] + gamma*texCoords[2]); } hit.set(t, this->material, ((1-beta-gamma)*normals[0]+beta*normals[1]+gamma*normals[2]).normalized()); return true; } return false; }
bool Plane::intersect( const Ray& r , Hit& h , float tmin) { //float a=ray.direction_.normalize().dotMul(normal_); float a=Vector3f::dot(r.getDirection(),normal_); //printf("a:%f\n",a); if(a<0) { float b=Vector3f::dot(normal_,r.getOrigin()-normal_*offset_); float t=-b/a; //if(t>=tmin&&t<FLT_MAX) h.getT() if(t>=tmin&&t< h.getT()) { h.set(t,material_,normal_); return true; }else { return false; } }else { return false; } }
void Renderer::Render(int width, int height, const std::string &outputFilename, float minDepth, float maxDepth, const std::string &depthFilename, const std::string &normalFilename) { // TODO: implement // Loop over each pixel in the image, shooting a ray // through that pixel and finding its intersection with // the scene. Write the color at the intersection to that // pixel in your output image. // // Use the Image class to write out the requested output files. SceneParser Scene(fname); //create scene here //scene is properly being read in cout << "Number of materials in scene " << Scene.getNumMaterials() << endl; //just initialize these all anyways, very little memory not to, and annoying to deal with conditional //initialization Image IM=Image(width,height); Image ID=Image(width,height); Image IN=Image(width,height); bool depth=false; if(!(depthFilename.empty())) //we will produce depth image depth=true; bool normal=false; if(!(normalFilename.empty())) //we will produce normal image normal=true; float xp; float yp; Ray R; bool hitSomething; Vector3f color; float T; for(int x=0; x<width; x++ ) { for(int y=0; y<height; y++) { Hit H; //need to reinitialize every single time //unless we want it to remmeber things like the texture state H.set(std::numeric_limits<float>::max(),NULL,Vector3f(0,0,0)); //initialization for Hit //cout << "pixel " << x<< " " <<y <<endl; //compute coordinates for ray we want to generate xp=2*((float)x)/((float)(width-1))-1; yp=2*((float)y)/((float)(height-1))-1; //generate ray object for camera R=(Scene.getCamera())->generateRay(Vector2f(xp,yp)); //cout << "generated ray " <<endl; Group * gro=Scene.getGroup(); //iterate through group objects and see which is closest hit for ray hitSomething=gro->intersect(R,(Scene.getCamera())->getTMin(),H); //cout << " hit " <<hitSomething <<endl; //set color of pixels for images based on what we get back for the ray if(hitSomething==false) //set pixel to be background color, didn't hit anything { //cout << "setbackground " <<endl; IM.setPixel(x,y,Scene.getBackgroundColor()); if(depth) ID.setPixel(x,y,Vector3f(0,0,0)); if(normal) IN.setPixel(x,y,Vector3f(0,0,0)); //cout << "finished set background"<<endl; } else { //cout << "set Material "<<endl; IM.setPixel(x,y,shade(R,H,&Scene)); //shade method is defined above //IM.setPixel(x,y,Vector3f(0.5,0.5,0.5)); if(depth) //calculate Pixel color based on depth, set to gray scale { T=H.getT(); if(T<minDepth) T=minDepth; if(T>maxDepth) T=maxDepth; color=Vector3f(1,1,1)-((T-minDepth)/(maxDepth-minDepth)*Vector3f(1,1,1)); ID.setPixel(x,y,color); } if(normal) { color=H.getNormal(); color=Vector3f(fabs(color[0]),fabs(color[1]),fabs(color[2])); IN.setPixel(x,y,color); } //cout << "finished set material " <<endl; } } } //save the images IM.savePNG(outputFilename); if(depth) //we will produce depth image ID.savePNG(depthFilename); if(normal) //we will produce depth image IN.savePNG(normalFilename); }
//用了彭老师书上介绍的求交方法,但是transform之后就有问题 bool Triangle::intersect(const Ray &r, Hit &h, float tmin) { Matrix A; A.SetToIdentity(); A.Set(0,0,a.x()-b.x()); A.Set(1,0,a.x()-c.x()); A.Set(2,0,r.getDirection().x()); A.Set(0,1,a.y()-b.y()); A.Set(1,1,a.y()-c.y()); A.Set(2,1,r.getDirection().y()); A.Set(0,2,a.z()-b.z()); A.Set(1,2,a.z()-c.z()); A.Set(2,2,r.getDirection().z()); Vec4f vr(a.x()-r.getOrigin().x(),a.y()-r.getOrigin().y(),a.z()-r.getOrigin().z(),1); if(fabs(r.getDirection().Dot3(normal))>0.0f) { A.Inverse(); A.Transform(vr); if((vr.x()+vr.y())<=1 && vr.x()>=0 && vr.y()>=0 && vr.z()>tmin && vr.z()<h.getT()) { h.set(vr.z(),material,normal,r); return 1; } } return 0; //为什么当使用transform之后,这里的求交函数就不能用了? 用没有加速的程序检测了一下,也无法求交,应该是这里的求交写错掉了 //Vec3f origin = r.getOrigin(); //Vec3f direct = r.getDirection(); //float isParallel = normal.Dot3(direct); //Vec3f tempbeta0; //Vec3f tempbeta1; //Vec3f tempbeta2; //float beta0; //float beta1; //float beta2; //if(fabs(isParallel)>0.0f) //{ // float dist = -(normal.Dot3(origin)+d)/isParallel; // Vec3f q = origin + direct*dist; // Vec3f::Cross3(tempbeta0,(c-b),(q-b)); // Vec3f::Cross3(tempbeta1,(a-c),(q-c)); // Vec3f::Cross3(tempbeta2,(b-a),(q-a)); // if(i0 == 0) // { // beta0 = tempbeta0.x()/normal.x(); // beta1 = tempbeta1.x()/normal.x(); // beta2 = tempbeta2.x()/normal.x(); // } // else if(i0 == 1) // { // beta0 = tempbeta0.y()/normal.y(); // beta1 = tempbeta1.y()/normal.y(); // beta2 = tempbeta2.y()/normal.y(); // } // else // { // beta0 = tempbeta0.z()/normal.z(); // beta1 = tempbeta1.z()/normal.z(); // beta2 = tempbeta2.z()/normal.z(); // } // if(beta0>=0 && beta0<=1 && beta1>=0 && beta1<=1 && beta2>=0 && beta2<=1) // { // if(dist > tmin && dist < h.getT()) // { // h.set(dist,material,normal,r); // return true; // } // } //} //return false; }
bool Box::intersect( const Ray& r, Hit& h, float tmin ) const { float maxToCam = (r.getOrigin() - this->m_max).length(); float minToCam = (r.getOrigin() - this->m_min).length(); Vec3f direction = r.getDirection(); Vec3f origin = r.getOrigin(); // Keep the direction values sane, we don't want to divide by zero if (direction.x == 0.0f) direction.x += EPSILON; if (direction.y == 0.0f) direction.y += EPSILON; if (direction.z == 0.0f) direction.z += EPSILON; float min, max, ymin, ymax, zmin, zmax; // Calculate the maximum and minimum on the x-axis float divx = 1.0f/direction.x; if (divx >= 0) { min = (this->m_min.x - origin.x) * divx; max = (this->m_max.x - origin.x) * divx; } else { min = (this->m_max.x - origin.x) * divx; max = (this->m_min.x - origin.x) * divx; } // Calculate the maximum and minimum on the y-axis float divy = 1.0f/direction.y; if (divy >= 0) { ymin = (this->m_min.y - origin.y) * divy; ymax = (this->m_max.y - origin.y) * divy; } else { ymin = (this->m_max.y - origin.y) * divy; ymax = (this->m_min.y - origin.y) * divy; } if ( (min > ymax) || (ymin > max) ) return false; // Make sure the tmin and tmax hold the most binding values if (ymin > min) min = ymin; if (ymax < max) max = ymax; // Calculate the maximum and minimum on the z-axis float divz = 1.0f/direction.z; if (divz >= 0) { zmin = (this->m_min.z - origin.z) * divz; zmax = (this->m_max.z - origin.z) * divz; } else { zmin = (this->m_max.z - origin.z) * divz; zmax = (this->m_min.z - origin.z) * divz; } if ( (min > zmax) || (zmin > max ) ) return false; // Make sure the tmin and tmax hold the most binding values if (zmin > min) min = zmin; if (zmax < max) max = zmax; if ( (min < h.getT() && (max > tmin)) ) { // Calculate the normal and set the values Vec3f point = r.pointAtParameter(min); Vec3f normal; if (FW::abs(point.x - this->m_min.x) < EPSILON) normal = Vec3f(-1.0f, 0.0f, 0.0f); else if (FW::abs(point.x - this->m_max.x) < EPSILON) normal = Vec3f(1.0f, 0.0f, 0.0f); else if (FW::abs(point.y - this->m_min.y) < EPSILON) normal = Vec3f(0.0f, -1.0f, 0.0f); else if (FW::abs(point.y - this->m_max.y) < EPSILON) normal = Vec3f(0.0f, 1.0f, 0.0f); else if (FW::abs(point.z - this->m_min.z) < EPSILON) normal = Vec3f(0.0f, 0.0f, -1.0f); else if (FW::abs(point.z - this->m_max.z) < EPSILON) normal = Vec3f(0.0f, 0.0f, 1.0f); else std::cerr << "ERROR: Could not calculate the normal in box intersect." << std::endl; h.set(min, this->m_material, normal); return true; } return false; }