Пример #1
0
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;

}
Пример #2
0
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();
}
Пример #3
0
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());
}
Пример #4
0
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();
    }
}
Пример #5
0
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();
}
Пример #6
0
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();
    }
}
Пример #7
0
// 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;
}
Пример #8
0
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);
}
Пример #9
0
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;
}
Пример #10
0
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();
}
Пример #11
0
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);
    }
}
Пример #12
0
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;
}
Пример #14
0
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);
  }


}
Пример #16
0
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 );
	}
	
}
Пример #18
0
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;
}
Пример #19
0
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);
}