float Edge::DihedralAngle(){ /* * Warning this function returns NULL * when there is an edge without two * adjcent triangles * */ // Is there even an angle here? if(opposite == NULL) return (float)NULL; // Find the angle of the face of a triangle Triangle* a = triangle; Triangle* b = opposite->getTriangle(); Vec3f normalA = a->getNormal(); Vec3f normalB = b->getNormal(); // Using Equation theta = acos( (a . b) / (|a||b|)) double top = normalA.Dot3(normalB); double bottom = normalA.Length() * normalB.Length(); double result = acos(top/bottom); return result; }
void Plane::paint(void) { material->glSetMaterial(); glBegin(GL_QUADS); Vec3f v(1.0f, 0.0f, 0.0f); //向量平行,叉乘的模等于0 Vec3f res; Vec3f::Cross3(res, normal, v); if (res.Length() < 1e-6) v.Set(0.0f, 1.0f, 0.0f); Vec3f b1,b2; Vec3f::Cross3(b1, v, normal); Vec3f::Cross3(b2, normal, b1); int scale1 = 1e6 / max(fabs(b1.x()), fabs(b1.y()), fabs(b1.z())); b1.Scale(scale1, scale1, scale1); int scale2 = 1e6 / max(fabs(b2.x()), fabs(b2.y()), fabs(b2.z())); b2.Scale(scale2, scale2, scale2); Vec3f dis = normal*d; glNormal3f(normal.x(), normal.y(), normal.z()); glVertex3f(b1.x() + dis.x(), b1.y() + dis.y(), b1.z() + dis.z()); glVertex3f(b2.x() + dis.x(), b2.y() + dis.y(), b2.z() + dis.z()); glVertex3f(-b1.x() + dis.x(), -b1.y() + dis.y(), -b1.z() + dis.z()); glVertex3f(-b2.x() + dis.x(), -b2.y() + dis.y(), -b2.z() + dis.z()); glEnd(); }
Matrix4 Matrix4::BoundingBoxToUnitSphere(const Vec3f &boundingBoxMin, const Vec3f &boundingBoxMax) { Vec3f center = (boundingBoxMin + boundingBoxMax) * 0.5f; Vec3f variance = boundingBoxMax - center; return Matrix4::Translation(-center) * Matrix4::Scaling(1.0f / variance.Length()); }
void Indicator::RenderCylinder(GraphicsDevice &GD, MatrixController &MC, float Radius, const Vec3f &P1, const Vec3f &P2, const RGBColor &Color, bool RenderArrow, bool ColorNormals) { Vec3f Diff = P2 - P1; float Height = Diff.Length(); Matrix4 Scale = Matrix4::Scaling(Vec3f(Radius, Radius, Height)); //radius and height Matrix4 Face = Matrix4::Face(Vec3f::eZ, Diff); //direction Matrix4 Translate = Matrix4::Translation(P1); //position MC.World = Scale * Face * Translate; if(RenderArrow) { _ArrowHead.SetColor(Color); if(ColorNormals) { _ArrowHead.ColorNormalsGrayScale(Color); } _ArrowHead.Render(); } else { if(Color != _CylinderColor) { _Cylinder.SetColor(Color); _CylinderColor = Color; } if(ColorNormals) { _Cylinder.ColorNormalsGrayScale(Color); } _Cylinder.Render(); } }
void BaseMesh::ReCreateCylinder(float radius, const Vec3f &pt1, const Vec3f &pt2, UINT slices, UINT stacks) { //a merge of the CreateCylinder(radius, height, slices, stacks) and CreateCylinder(radius, pt1, pt2, slices, stacks) Vec3f Diff = pt2 - pt1; float height = Diff.Length(); float PI2_Slices = 2.0f * Math::PIf / float(slices); float Theta; int vc = 0, ic = 0; MeshVertex *V = Vertices(); DWORD *I = Indices(); MeshVertex MVtx(Vec3f::Origin, Vec3f::Origin, RGBColor::White, Vec2f::Origin); for(UINT i = 0; i <= stacks; i++) { for(UINT i2 = 0; i2 < slices; i2++) { Theta = float(i2) * PI2_Slices; MVtx.Pos = Vec3f(radius * cosf(Theta), radius * sinf(Theta), height * (float(i) / stacks - 0.5f)); V[vc++] = MVtx; } } Matrix4 T1 = Matrix4::Translation(Vec3f(0.0f,0.0f,height / 2.0f)); Matrix4 Face = Matrix4::Face(Vec3f(0.0f,0.0f,1.0f),pt2 - pt1); Matrix4 T2 = Matrix4::Translation(pt1); ApplyMatrix(T1 * Face * T2); GenerateNormals(); }
Matrix4 IndicatorShape::TransformMatrix() const { switch(Type) { case IndicatorShapeSphere: { Matrix4 Scale = Matrix4::Scaling(Radius); Matrix4 Translate = Matrix4::Translation(Pos[0]); return Scale * Translate; } case IndicatorShapeCylinder: { Vec3f Diff = Pos[1] - Pos[0]; float Height = Diff.Length(); Matrix4 Scale = Matrix4::Scaling(Vec3f(Radius, Radius, Height)); Matrix4 Face = Matrix4::Face(Vec3f::eZ, Diff); Matrix4 Translate = Matrix4::Translation(Pos[0]); return Scale * Face * Translate; } default: SignalError("Invalid shape type"); return Matrix4::Identity(); } }
// does the recursive (shadow rays & recursive/glossy rays) work Vec3f RayTracer::TraceRay(const Ray &ray, Hit &hit, int bounce_count) const { hit = Hit(); bool intersect = CastRay(ray,hit,false); Vec3f answer(args->background_color_linear); if (intersect == true) { const Material *m = hit.getMaterial(); assert (m != NULL); // rays coming from the light source are set to white, don't bother to ray trace further. if (m->getEmittedColor().Length() > 0.001) { answer = Vec3f(1,1,1); } else { // ambient light answer = args->ambient_light_linear * m->getDiffuseColor(hit.get_s(),hit.get_t()); // Shadows answer += shadows(ray, hit); // Reflections Vec3f reflectiveColor = m->getReflectiveColor(); double roughness = m->getRoughness(); if (bounce_count > 0 && reflectiveColor.Length() > MIN_COLOR_LEN) { answer += reflectiveColor * reflections(ray, hit, bounce_count, roughness); } } } return answer; }
void Indicator::RenderArrow(GraphicsDevice &GD, MatrixController &MC, const Vec3f &P1, const Vec3f &P2, const RGBColor &Color, bool ColorNormals) { Vec3f Diff = P2 - P1; Vec3f Dir = Vec3f::Normalize(Diff); float TotalHeight = Diff.Length(); float CylinderRadius = TotalHeight * 0.1f; float ArrowRadius = CylinderRadius * 2.0f; float ArrowHeight = ArrowRadius; float CylinderHeight = TotalHeight - ArrowHeight; RenderCylinder(GD, MC, CylinderRadius, P1, P1 + Dir * CylinderHeight, Color, false, ColorNormals); RenderCylinder(GD, MC, ArrowRadius, P1 + Dir * CylinderHeight, P2, Color, true, ColorNormals); }
Ray PerspectiveCamera::generateRay(Vec2f point) { float x_ndc = point.x(); float y_ndc = point.y(); #ifdef DEBUG printf("PerspectiveCamera::generateRay, x_ndc=%f, y_ndc=%f\n", x_ndc, y_ndc); #endif float screenWidth = 0.f; float screenHeight = 0.f; if (mRatio > 1.f) { screenWidth = 2 * mRatio; screenHeight = 2.f; } else { screenWidth = 2.f; screenHeight = 2 * mRatio; } #ifdef DEBUG printf("screenWidth=%f, screenHeight=%f\n", screenWidth, screenHeight); #endif //float height = 2 * tan(mAngle * PI / 360.0); //float width = height * mRatio; float left = - screenWidth / 2.0; float top = - screenHeight / 2.0; float u = x_ndc * screenWidth + left; float v = y_ndc * screenHeight + top; #ifdef DEBUG printf("u=%f, v=%f\n", u, v); #endif float near = screenHeight / (2.f * tanf(mAngle / 2.0)); #ifdef DEBUG printf("near=%f\n", near); #endif Vec3f originalDir = near * mDirection + u * mHorizontal + v * mUp; if (originalDir.Length() != 0) { originalDir.Normalize(); } Ray r(mCenter, originalDir); #ifdef DEBUG cout<<r<<endl; #endif return r; }
void Sphere::insertIntoGrid(Grid *g, Matrix *m) { #ifdef DEBUG printf("Sphere::insertIntoGrid.\n"); #endif int i; int j; int k; if (mpBox == NULL) return; Vec3f minp = mpBox->getMin(); Vec3f maxp = mpBox->getMax(); float xBox = maxp.x() - minp.x(); float yBox = maxp.y() - minp.y(); float zBox = maxp.z() - minp.z(); int xSize = g->getXSize(); int ySize = g->getYSize(); int zSize = g->getZSize(); float xDelta = xBox / xSize; float yDelta = yBox / ySize; float zDelta = zBox / zSize; for (k = 0; k < zSize; k++) for (j = 0; j < ySize; j++) for (i = 0; i < xSize; i++) { //Get the min point Vec3f curPoint(minp.x() + (i + 0.5)*xDelta, minp.y() + (j + 0.5)*yDelta, minp.z() + (k + 0.5)*zDelta ); //Computing the distance between the voxel and the center point; Vec3f temp = curPoint - mCenterPoint; float distance = temp.Length(); if (distance <= mRadius) { printf("Overlapped in %d %d %d\n", i, j, k); g->AddObjectToGrid(this, i, j, k); } } g->dumpObjectInfo(); }
Matrix4 Matrix4::Face(const Vec3f &V0, const Vec3f &V1) { // // Rotate about the cross product of the two vectors by the angle between the two vectors // Vec3f Axis = Vec3f::Cross(V0, V1); float Angle = Vec3f::AngleBetween(V0, V1); if(Angle == 0.0f || Axis.Length() < 0.0f) { return Identity(); } else { return Rotation(Axis, Angle); } }
void BaseMesh::ReCreateLozenge(float Radius, const Vec3f &Start, const Vec3f &End, UINT slices, UINT stacks) { //this is just like CreateCylinder(radius, pt1, pt2, slices, stacks) except the radius function isn't fixed; //towards the ends it rounds off into a sphere. MeshVertex *V = Vertices(); float Theta,CurZ,SqrtValue; float PI2_Slices = 2.0f * Math::PIf / float(slices), Height, LocalRadius; Vec3f Diff = End - Start; Height = Diff.Length(); for(UINT i=0; i <= stacks; i++) { for(UINT i2 = 0; i2 < slices; i2++) { Theta = float(i2) * PI2_Slices; CurZ = float(Math::LinearMap(0.0f, float(stacks), -Radius, Height+Radius, float(i))); if(CurZ < 0.0f) //if we need to round the cylinder, { LocalRadius = float(Math::LinearMap(-Radius, 0.0f, 1.0f, 0.0f, CurZ)); SqrtValue = 1.0f - LocalRadius*LocalRadius; if(SqrtValue < 0.0f) SqrtValue = 0.0f; LocalRadius = sqrtf(SqrtValue) * Radius; //compute the appropriate radius } else if(CurZ > Height) //if we're on the other end of the cylinder and need to round, { LocalRadius = float(Math::LinearMap(Height, Height+Radius, 0.0f, 1.0f, CurZ)); SqrtValue = 1.0f - LocalRadius*LocalRadius; if(SqrtValue < 0.0f) SqrtValue = 0.0f; LocalRadius = sqrtf(SqrtValue) * Radius; //do the same thing if(LocalRadius < 0.0f || LocalRadius > Radius + 1e-5f) LocalRadius = 0.0f; } else { LocalRadius = Radius; //otherwise we're in the middle and our radius is fixed like a cylinder } V[i*slices+i2].Pos = Vec3f(LocalRadius * cosf(Theta), LocalRadius * sinf(Theta), CurZ); //load the appropriate position } } Vec3f UpVec(0.0f, 0.0f, 1.0f); ApplyMatrix(Matrix4::Face(UpVec, Diff) * Matrix4::Translation(Start)); //make it face the right direction and translate it to the right position }
void QRenderOutputWidget::Zoom(float amount) { Vec3f reverseLoS = Position - FocalPoint; if (amount > 0) { reverseLoS = reverseLoS * 1.1f; } else if (amount < 0) { if (reverseLoS.Length() > 0.0005f) { reverseLoS = reverseLoS * 0.9f; } } Position = reverseLoS + FocalPoint; }
void ComplexMesh::ExplicitMeanCurvatureFlow(float TimeStep) { Vector<Vec3f> NewVertexPositions(_Vertices.Length()); float AverageDelta = 0.0f; for(UINT VertexIndex = 0; VertexIndex < _Vertices.Length(); VertexIndex++) { Vertex &CurVertex = _Vertices[VertexIndex]; Vec3f Delta = -TimeStep * CurVertex.MeanCurvatureNormal(); AverageDelta += Delta.Length(); NewVertexPositions[VertexIndex] = Delta; } AverageDelta /= _Vertices.Length(); for(UINT VertexIndex = 0; VertexIndex < _Vertices.Length(); VertexIndex++) { Vertex &CurVertex = _Vertices[VertexIndex]; if(NewVertexPositions[VertexIndex].Length() > 2.0f * AverageDelta) { NewVertexPositions[VertexIndex].SetLength(2.0f * AverageDelta); } CurVertex.Pos() += NewVertexPositions[VertexIndex]; } }
void PhotonMapping::TracePhoton(const Vec3f &position, const Vec3f &direction, const Vec3f &energy, int iter) { // ============================================== // ASSIGNMENT: IMPLEMENT RECURSIVE PHOTON TRACING // ============================================== // Trace the photon through the scene. At each diffuse or // reflective bounce, store the photon in the kd tree. // One optimization is to *not* store the first bounce, since that // direct light can be efficiently computed using classic ray // tracing. //do ray cast Ray r(position,direction*(1/direction.Length())); Hit h; raytracer->CastRay(r,h,true); if (h.getT()>1000) return; MTRand mtrand; Vec3f refl = h.getMaterial()->getReflectiveColor(); Vec3f diff = h.getMaterial()->getDiffuseColor(); double ran=mtrand.rand(); if (iter==0) ran= mtrand.rand(refl.Length()+diff.Length()); //std::cout<<iter<<" "<<h.getT()<<" "<<refl.Length()+diff.Length()<<std::endl; //send reflective photon if (iter<args->num_bounces&&ran<=refl.Length()) TracePhoton(r.pointAtParameter(h.getT()),r.getDirection()-2*(r.getDirection().Dot3(h.getNormal()))*h.getNormal(),energy,iter+1); else if (iter<args->num_bounces&&ran<=refl.Length()+diff.Length()) TracePhoton(r.pointAtParameter(h.getT()),RandomDiffuseDirection(h.getNormal()),energy,iter+1); else { Photon p(position,direction,energy,iter); kdtree->AddPhoton(p); } }
void ComplexMesh::ImplicitMeanCurvatureFlow(float TimeStep) { Vector<double> VertexAreas(_Vertices.Length()); Vector<Vec3f> NewVertexPositions(_Vertices.Length()); NewVertexPositions.Clear(Vec3f::Origin); SparseMatrix<double> M(_Vertices.Length()); for(UINT VertexIndex = 0; VertexIndex < _Vertices.Length(); VertexIndex++) { Vertex &CurVertex = _Vertices[VertexIndex]; VertexAreas[VertexIndex] = CurVertex.ComputeTriangleArea(); M.PushElement(VertexIndex, VertexIndex, VertexAreas[VertexIndex]); //M.PushElement(VertexIndex, VertexIndex, 1.0f); for(UINT EdgeIndex = 0; EdgeIndex < CurVertex.Vertices().Length(); EdgeIndex++) { Vertex &OtherVertex = *(CurVertex.Vertices()[EdgeIndex]); FullEdge &CurEdge = CurVertex.GetSharedEdge(OtherVertex); double ConstantFactor = CurEdge.GetCotanTerm() / 4.0f; Assert(ConstantFactor == ConstantFactor, "ConstantFactor invalid"); M.PushElement(VertexIndex, VertexIndex, TimeStep * ConstantFactor); M.PushElement(VertexIndex, OtherVertex.Index(), -TimeStep * ConstantFactor); } } BiCGLinearSolver<double> Solver; Solver.LoadMatrix(&M); const double ErrorTolerance = 1e-6; Solver.SetParamaters(1000, ErrorTolerance); Solver.Factor(); for(UINT ElementIndex = 0; ElementIndex < 3; ElementIndex++) { Vector<double> x, b(_Vertices.Length()); for(UINT VertexIndex = 0; VertexIndex < _Vertices.Length(); VertexIndex++) { b[VertexIndex] = _Vertices[VertexIndex].Pos()[ElementIndex] * VertexAreas[VertexIndex]; //b[VertexIndex] = _Vertices[VertexIndex].Pos().Element(ElementIndex); } Solver.Solve(x, b); Console::WriteLine(Solver.GetOutputString()); double Error = Solver.ComputeError(x, b); Console::WriteLine(String("Mean curvature error: ") + String(Error)); if(Error < ErrorTolerance) { for(UINT VertexIndex = 0; VertexIndex < _Vertices.Length(); VertexIndex++) { NewVertexPositions[VertexIndex][ElementIndex] = float(x[VertexIndex]); } } } float AverageDelta = 0.0f; for(UINT VertexIndex = 0; VertexIndex < _Vertices.Length(); VertexIndex++) { Vec3f Delta = NewVertexPositions[VertexIndex] - _Vertices[VertexIndex].Pos(); AverageDelta += Delta.Length(); } AverageDelta /= _Vertices.Length(); for(UINT VertexIndex = 0; VertexIndex < _Vertices.Length(); VertexIndex++) { Vertex &CurVertex = _Vertices[VertexIndex]; Vec3f Delta = NewVertexPositions[VertexIndex] - _Vertices[VertexIndex].Pos(); if(Delta.Length() > 2.0f * AverageDelta) { Delta.SetLength(2.0f * AverageDelta); } CurVertex.Pos() += Delta; } }
void CPlanetFinderEngine::buildSolarSystemList( std::vector< star3map::Sprite > & solarsystem ) { solarsystem.clear(); float moonN0 = 125.1228; float moonw0 = 318.0634; //float moonM0 = 115.3654; float moonN = moonN0 - 0.0529538083 * daysSince2000; float moonw = moonw0 + 0.1643573223 * daysSince2000; //float MoonM = moonM0 + 13.0649929509 * daysSince2000; moon.Init("Moon",1.23e-02,27.322,2.569519e-03,0.0549,5.145, moonN, moonN+moonw, //-- lon of peri = N + w /*moonN0+moonw0+moonM0*/ // meanlong2000 = N+w+M 218.32, //use Dave's data instead false,0.,0.,0.,0.); // This is the correction for parallax due to the earth's rotation. Vec3f earthPosition = earth.position( daysSince2000, 0.000001 ); // + (zenith * (float)(4.3e-05)); Vec3f earthToMoon = moon.position( daysSince2000, 0.000001 ); //--- Nonkeplerian perturbations for the moon: //First convert vector to spherical coords: float moonRad = earthToMoon.Length(); float moonLat = acos( -earthToMoon.z / moonRad ) - M_PI/2.0; float moonLon = atan2(earthToMoon.y, earthToMoon.x); if ( moonLon < -M_PI/2.0 ) moonLon += M_PI; if ( moonLon > M_PI/2.0 ) moonLon -= M_PI; if ( earthToMoon.x < 0.0 ) moonLon += M_PI; if ( moonLon < 0.0 ) moonLon += 2*M_PI; if ( moonLon > 2.0*M_PI ) moonLon -= 2*M_PI; moonLon = moonLon + MoonPerturbations::moonLongitudeCorrectionDegrees(daysSince2000)*M_PI/180.0; moonLat = moonLat + MoonPerturbations::moonLatitudeCorrectionDegrees(daysSince2000)*M_PI/180.0; earthToMoon = latLongToUnitVector(moonLat,moonLon); earthToMoon *= moonRad; Vec3f moonPosition = earthToMoon + earthPosition; //================================================================================ // Show planets, moon & sun //================================================================================ Vec3f planetsCenterOfMass(0, 0 , 0); Vec3f currentPosition[9]; int i; for (i= 0; i<PLANETS_NUMBER; i++) { currentPosition[i] = planets[i]->position( daysSince2000, 0.000001 ); planetsCenterOfMass += currentPosition[i] * planets[i]->mass; } Vec3f sunPosition = planetsCenterOfMass*(float)(-1.0/sunMass); for (i= -1; i<PLANETS_NUMBER; i++) { // Yuck. //==moon is when you do earth, sun is i== -1 Vec3f directionFromEarth; SetColor( Vec4f( 1, 1, 1 ) ); Texture2D *tex = NULL; std::string name; bool isSun,isMoon; isSun=false; isMoon=false; float scale = 1.0; if (i!= -1 && planets[i]!=&earth) { // a planet other than earth directionFromEarth = currentPosition[i] - earthPosition; directionFromEarth.Normalize(); tex = planets[ i ]->texture; name = planets[i]->name; scale = planets[ i ]->scale; } else { if (i== -1) { //-- sun directionFromEarth = sunPosition - earthPosition; directionFromEarth.Normalize(); tex = sunTexture; name = "Sun"; isSun = true; } else { //-- moon directionFromEarth = moonPosition - earthPosition; directionFromEarth.Normalize(); tex = moon.texture; name = "Moon"; isMoon=true; } } int dotRadius = (isSun || isMoon) ? 5 : 2; dotRadius *= scale; star3map::Sprite sp; sp.direction = directionFromEarth; sp.magnitude = 0; sp.scale = dotRadius; sp.name = name; sp.color = Vec4f( 1, 1, 1, 1 ); sp.tex = tex; solarsystem.push_back( sp ); } }
Vec3f RayTracer::traceRay(Ray &ray, float tmin, int bounces, float weight, float indexOfRefraction, Hit &hit) const { //printf("当前已有光线:\n"); //RayTree::Print(); Vec3f canswer; if (bounces > max_bounces) return Vec3f(0.0f, 0.0f, 0.0f); Camera *camera = sceneParser->getCamera(); Group *group = sceneParser->getGroup(); int num_lights = sceneParser->getNumLights(); Vec3f cambient = sceneParser->getAmbientLight(); //原来最后是这里出了问题,一旦碰到有转换的物体,那么hit带出来的值是 //转换后的视线看到的值,而非本来视线看到的值 //所以解决方案是:距离不变,根据距离重新计算焦点 if (group->intersect(ray, hit, tmin))//撞到了 { if (is_view_ray) { RayTree::SetMainSegment(ray, 0, hit.getT()); is_view_ray = false; } Vec3f cobject = hit.getMaterial()->getDiffuseColor(); Vec3f hitPoint = hit.getIntersectionPoint(); //环境光部分 canswer = cambient * cobject; Vec3f clight;//光的颜色 Vec3f light_dir;//指向光的方向 Vec3f normal_dir = hit.getNormal();//交点法线向量 float distolight;//距离光源的距离 for (int i = 0; i < num_lights; i++) { Light *light = sceneParser->getLight(i); //light_dir : the direction to the light // 该方法用于获得指向光的方向,光的颜色,和到达光的距离 // 第一个参数传递的是焦点信息 light->getIllumination(hitPoint, light_dir, clight, distolight); Ray ray2(hitPoint, light_dir); Vec3f init_normal(0, 0, 0); Hit hit2(distolight, NULL, init_normal); //阴影检测 if (shadow) { if (group->intersect(ray2, hit2, tmin)){ RayTree::AddShadowSegment(ray2, 0, hit2.getT()); continue; } RayTree::AddShadowSegment(ray2, 0, hit2.getT()); } //cpixel = cambient * cobject + SUMi [ clamped(Li . N) * clighti * cobject ] //返回局部光 canswer = canswer + hit.getMaterial()->Shade(ray, hit, light_dir, clight); } //printf("当前已有光线:\n"); //RayTree::Print(); //反射光 Material *material = hit.getMaterial(); Vec3f rc = material->getReflectiveColor(); if (rc.r() > 0 && rc.g() > 0 && rc.b() > 0) { Vec3f mirrorDir; Vec3f incoming = ray.getDirection(); mirrorDir = mirrorDirection(normal_dir, incoming); // The ray weight is simply multiplied by the magnitude of the reflected color Ray ray3(hitPoint, mirrorDir); Vec3f init_normal(0, 0, 0); Hit hit3(distolight, NULL, init_normal); //忘记乘以本身的反射光系数%………… canswer += traceRay(ray3, tmin, bounces + 1, weight*rc.Length(), indexOfRefraction, hit3)*rc; if (bounces + 1 < max_bounces) RayTree::AddReflectedSegment(ray3, 0, hit3.getT()); } //printf("当前已有光线:\n"); //RayTree::Print(); //从这里开始还都存在问题!!!!! //折射光 Vec3f transmitted; Vec3f tc = material->getTransparentColor(); float index = material->getIndexOfRefraction(); if (tc.r() > 0 && tc.g() > 0 && tc.b() > 0) { Vec3f init_normal(0, 0, 0); Hit hit4(distolight, NULL, init_normal); //在判断折射光的存在之后,要考虑光线的位置:物体内还是物体外 //这里根据normal和incoming的点积来判断 Vec3f incoming = ray.getDirection(); float judge = normal_dir.Dot3(incoming); if (judge < 0)//光线在外 { if (transmittedDirection(normal_dir, incoming, 1, index, transmitted)) { Ray ray4(hitPoint, transmitted); canswer += traceRay(ray4, tmin, bounces+1, weight*rc.Length(), index, hit4)*tc; RayTree::AddTransmittedSegment(ray4, 0, hit4.getT()); } } else//光线在内 { normal_dir.Negate(); if (transmittedDirection(normal_dir, incoming, index, 1, transmitted)) { Ray ray4(hitPoint, transmitted); canswer += traceRay(ray4, tmin, bounces+1, weight*rc.Length(), 1, hit4)*tc; RayTree::AddTransmittedSegment(ray4, 0, hit4.getT()); } } } //printf("当前已有光线:\n"); //RayTree::Print(); } else canswer = sceneParser->getBackgroundColor(); canswer.Clamp(); return canswer; }
float Edge::Length() const { Vec3f diff = start_vertex->getPos() - end_vertex->getPos(); return diff.Length(); }
Vec3f PhotonMapping::GatherIndirect(const Vec3f &point, const Vec3f &normal, const Vec3f &direction_from) const { if (kdtree == NULL) { std::cout << "WARNING: Photons have not been traced throughout the scene." << std::endl; return Vec3f(0,0,0); } int count = args->num_photons_to_collect; count = 500; //std::cout<<count<<std::endl; Vec3f xVec = Vec3f(0.25,0.25,0.25); BoundingBox newbb = BoundingBox(point-xVec, point+xVec); std::vector<Photon> photonlist; bool captured = false; while(!captured){ kdtree->CollectPhotonsInBox(newbb,photonlist); if(photonlist.size()>(unsigned int)count){ captured = true; } else{ xVec *= 2; newbb = BoundingBox(point-xVec, point+xVec); photonlist.clear(); } } std::vector<Photon> sortedPhotons; double smallest = 100; double lowerbound = -1; int index = -1; for(int i = 0; i<count; i++){ smallest = 100; for (unsigned int j = 0; j<photonlist.size(); j++){ Vec3f connector = photonlist[j].getPosition()-point; double dist = connector.Length(); if(smallest>dist && lowerbound < dist){ smallest = dist; index = j; } } //std::cout<<index<<" "<<smallest<<" "<<lowerbound<<std::endl; assert (index>=0); assert((unsigned int)index<photonlist.size()); assert(smallest>0); lowerbound = smallest; sortedPhotons.push_back(photonlist[index]); } Vec3f totalEnergy = Vec3f(0,0,0); for (unsigned int i=0; i < sortedPhotons.size(); i++){ totalEnergy += sortedPhotons[i].getEnergy(); } /*xVec = point-xVec; double radius = xVec.Length(); double surfaceArea = 4 * M_PI * (radius * radius); */ //totalEnergy *= sortedPhotons.size(); // std::cout<<totalEnergy<<std::endl; return totalEnergy; // ================================================================ // ASSIGNMENT: GATHER THE INDIRECT ILLUMINATION FROM THE PHOTON MAP // ================================================================ // collect the closest args->num_photons_to_collect photons // determine the radius that was necessary to collect that many photons // average the energy of those photons over that radius // return the color //return Vec3f(0,0,0); }