Beispiel #1
0
void Mesh::CalculateBackfaces(const Maths::Vector4& cameraPos)
{
	for ( int i = 0; i < m_numPolys; ++i )
	{
		Maths::Vector4 a = ( m_transformed[ m_polys[i].Indices[0] ].Position ) - ( m_transformed[ m_polys[i].Indices[1] ].Position );
		Maths::Vector4 b = ( m_transformed[ m_polys[i].Indices[2] ].Position ) - ( m_transformed[ m_polys[i].Indices[1] ].Position );
		Maths::Vector4 c = b.CrossProduct(a);
		Maths::Vector4 d;

		m_polys[i].Normal = c;
		c.Normalize();
		m_polys[i].NormalN = c;

		Vector4 p = m_transformed[ m_polys[i].Indices[0] ].Position  - cameraPos;
		if ( p.DotProduct(c) > 0.0f ) 
		{
			m_polys[i].IsCulled = true;
			m_transformed[ m_polys[i].Indices[0] ].IsCulled = true;
			m_transformed[ m_polys[i].Indices[1] ].IsCulled = true;
			m_transformed[ m_polys[i].Indices[2] ].IsCulled = true;
		}
		else
		{
			m_polys[i].IsCulled = false;
			m_transformed[ m_polys[i].Indices[0] ].IsCulled = false;
			m_transformed[ m_polys[i].Indices[1] ].IsCulled = false;
			m_transformed[ m_polys[i].Indices[2] ].IsCulled = false;
		}
	}
}
Beispiel #2
0
void OcclusionBuffer::ClipVertices(const Vector4& plane, Vector4* vertices, bool* triangles, unsigned& numTriangles)
{
    unsigned num = numTriangles;
    
    for (unsigned i = 0; i < num; ++i)
    {
        if (triangles[i])
        {
            unsigned index = i * 3;
            float d0 = plane.DotProduct(vertices[index]);
            float d1 = plane.DotProduct(vertices[index + 1]);
            float d2 = plane.DotProduct(vertices[index + 2]);
            
            // If all vertices behind the plane, reject triangle
            if (d0 < 0.0f && d1 < 0.0f && d2 < 0.0f)
            {
                triangles[i] = false;
                continue;
            }
            // If 2 vertices behind the plane, create a new triangle in-place
            else if (d0 < 0.0f && d1 < 0.0f)
            {
                vertices[index] = ClipEdge(vertices[index], vertices[index + 2], d0, d2);
                vertices[index + 1] = ClipEdge(vertices[index + 1], vertices[index + 2], d1, d2);
            }
            else if (d0 < 0.0f && d2 < 0.0f)
            {
                vertices[index] = ClipEdge(vertices[index], vertices[index + 1], d0, d1);
                vertices[index + 2] = ClipEdge(vertices[index + 2], vertices[index + 1], d2, d1);
            }
            else if (d1 < 0.0f && d2 < 0.0f)
            {
                vertices[index + 1] = ClipEdge(vertices[index + 1], vertices[index], d1, d0);
                vertices[index + 2] = ClipEdge(vertices[index + 2], vertices[index], d2, d0);
            }
            // 1 vertex behind the plane: create one new triangle, and modify one in-place
            else if (d0 < 0.0f)
            {
                unsigned newIdx = numTriangles * 3;
                triangles[numTriangles] = true;
                ++numTriangles;
                
                vertices[newIdx] = ClipEdge(vertices[index], vertices[index + 2], d0, d2);
                vertices[newIdx + 1] = vertices[index] = ClipEdge(vertices[index], vertices[index + 1], d0, d1);
                vertices[newIdx + 2] = vertices[index + 2];
            }
            else if (d1 < 0.0f)
            {
                unsigned newIdx = numTriangles * 3;
                triangles[numTriangles] = true;
                ++numTriangles;
                
                vertices[newIdx + 1] = ClipEdge(vertices[index + 1], vertices[index], d1, d0);
                vertices[newIdx + 2] = vertices[index + 1] = ClipEdge(vertices[index + 1], vertices[index + 2], d1, d2);
                vertices[newIdx] = vertices[index];
            }
            else if (d2 < 0.0f)
            {
                unsigned newIdx = numTriangles * 3;
                triangles[numTriangles] = true;
                ++numTriangles;
                
                vertices[newIdx + 2] = ClipEdge(vertices[index + 2], vertices[index + 1], d2, d1);
                vertices[newIdx] = vertices[index + 2] = ClipEdge(vertices[index + 2], vertices[index], d2, d0);
                vertices[newIdx + 1] = vertices[index + 1];
            }
        }
    }
}
Beispiel #3
0
bool Mesh::CullPolygons(const ViewFrustum& frustum, const Maths::Vector4& camPos)
{
	int cullCount = 0;
	for ( int i = 0; i < m_numPolys; ++i )
	{
		if ( m_polys[i].IsCulled )
		{
			cullCount++;
			continue;
		}

		int count = 0;
		for ( int vv = 0; vv < 3; ++vv )
		{
			//Vector4 point = m_transformed[ m_polys[i].Indices[vv] ].Position - camPos;
			Vector4 point = m_transformed[ m_polys[i].Indices[vv] ].Position - m_verts[ m_polys[i].Indices[vv] ];
			float result = point.DotProduct( frustum.Left.Normal );
			if ( result > 0.0f )
			{
				count++;
				m_transformed[ m_polys[i].Indices[vv] ].IsCulled = true;
				continue;
			}

			result = point.DotProduct( frustum.Right.Normal );
			if ( result > 0.0f )
			{
				count++;
				m_transformed[ m_polys[i].Indices[vv] ].IsCulled = true;
				continue;
			}

			result = point.DotProduct( frustum.Top.Normal );
			if ( result > 0.0f )
			{
				count++;
				m_transformed[ m_polys[i].Indices[vv] ].IsCulled = true;
				continue;
			}

			result = point.DotProduct( frustum.Bottom.Normal );
			if ( result > 0.0f )
			{
				count++;
				m_transformed[ m_polys[i].Indices[vv] ].IsCulled = true;
				continue;
			}

			//result = point.DotProduct( frustum.Near.Normal );
			//if ( result > 0.0f )
			//{
			//	count++;
			//	m_transformed[ m_polys[i].Indices[vv] ].IsCulled = true;
			//	continue;
			//}

			//result = point.DotProduct( frustum.Far.Normal );
			//if ( result > 0.0f )
			//{
			//	count++;
			//	m_transformed[ m_polys[i].Indices[vv] ].IsCulled = true;
			//	continue;
			//}
		}

		if ( count == 3 )
		{
			cullCount++;
			m_polys[i].IsCulled = true;
		}
	}

	return ( cullCount == m_numPolys );
}
Beispiel #4
0
void Mesh::CalculateLightingPoint( const std::vector<LightPoint>& light, int numLight, const Maths::Vector4& camera)
{
	Maths::Vector4 l;
	Maths::Vector4 temp, result, n, p;
	Maths::Vector4 cof( 1.0f, 1.0f, 10.0f );
	BYTE r, g, b;
	float distance = 0;
	float att = 0;
	float a = 0.05f;
	float bb = 0.05f;
	float c = 0.05f;
	float dif, spec;

	m_noLight = false;

	for ( int i = 0; i < m_numVerts; ++i )
	{
		if ( !m_transformed[i].IsCulled )
		{
			result.X = 0; //Red
			result.Y = 0; //green
			result.Z = 0; //blue

			for ( int j = 0; j < numLight; ++j )
			{
				p = light[j].Position;
				l = p - m_transformed[i].Position;
				distance = l.Length();

				//calculate the attenuation value
				att = 1 / (a + ( distance * bb ) + ( distance * distance ) * c );
				if ( att < 0 )
					att = 0;

				temp.X = light[j].Colour.GetR();
				temp.Y = light[j].Colour.GetG();
				temp.Z = light[j].Colour.GetB();
				
				n = m_transformed[i].Normal;
				n.Normalize();

				dif = max( 0.0, l.DotProduct( n ) ) * att;

				// calculate the speculation
				//Vector4 toEye = m_transformed[i].Position - camera;
				//Vector4 half = camera + p / 2;
				//toEye.Normalize();
				//half.Normalize();
				//float specPower = 1.0f;
				//float spec = pow( max( n.DotProduct( half ), 0.0f ), specPower ) * att;
				Vector4 toEye = m_transformed[i].Position - camera;
				Vector4 reflect = ( n - l ) * ( 2 * ( n.DotProduct( l ) ) );
				toEye.Normalize();
				reflect.Normalize();
				float specPower = 1.0f;
				float spec = pow( max( reflect.DotProduct( toEye ), 0.0f ), specPower ) * att;

				temp.X =  temp.X * ( (dif + spec) * m_kd_red );
				temp.Y =  temp.Y * ( (dif + spec) * m_kd_green );
				temp.Z =  temp.Z * ( (dif + spec) * m_kd_blue );

				//temp.X =  temp.X * ( dif * m_kd_red ) );
				//temp.Y =  temp.Y * ( dif * m_kd_green ) );
				//temp.Z =  temp.Z * ( dif * m_kd_blue ) );

				result += temp;
			}

			//set colour
			if ( result.X > 255.0f ) result.X = 255.0f;
			if ( result.Y > 255.0f ) result.Y = 255.0f;
			if ( result.Z > 255.0f ) result.Z = 255.0f;
			if ( result.X < 0.0f ) result.X = 0.0f;
			if ( result.Y < 0.0f ) result.Y = 0.0f;
			if ( result.Z < 0.0f ) result.Z = 0.0f;
			r = (BYTE)result.X;
			g = (BYTE)result.Y;
			b = (BYTE)result.Z;
			m_transformed[i].Colour = Gdiplus::Color::MakeARGB( 255, r, g, b );
		}
	}
}
Beispiel #5
0
void Mesh::CalculateLightingDirectional(const LightDirectional& light, int numLights, const Vector4& camera)
{
	Maths::Vector4 total;
	Maths::Vector4 temp;
	Maths::Vector4 l( light.Position.X, light.Position.Y, light.Position.Z, 1.0f );
	Maths::Vector4 n( 0, 0, 0, 0 );
	BYTE r, g, b;
	float diff, spec = 0;

	m_noLight = false;
	l.Normalize();

	for ( int i = 0; i < m_numVerts; ++i )
	{
		if ( !m_transformed[i].IsCulled )
		{
			//reset the colout to black
			total.X = 0; //Red
			total.Y = 0; //green
			total.Z = 0; //blue

			for ( int j = 0; j < numLights; ++j )
			{
				Maths::Vector4 d;
				
				//modulate intensity with coresponding reflectance co-efficient values
				temp.X = light.Colour.GetR() * light.Intensity.X;
				temp.Y = light.Colour.GetG() * light.Intensity.Y;
				temp.Z = light.Colour.GetB() * light.Intensity.Z;

				n = m_transformed[i].Normal; 
				n.Normalize();

				//attentuate the rgb values with lambertian attenuation
				diff = max(0.0, l.DotProduct( n ));
				
				Vector4 toEye = m_transformed[i].Position - camera;
				Vector4 reflect = ( n - l ) * ( 2 * ( n.DotProduct( l ) ) );
				toEye.Normalize();
				reflect.Normalize();
				float specPower = 1.0f;
				spec = pow( max( reflect.DotProduct( toEye ), 0.0f ), specPower )  * 0.01f;

				if ( diff <= 0.0f )
					spec = 0.0f;

				temp.X =  temp.X * ( (diff + spec) * m_kd_red );
				temp.Y =  temp.Y * ( (diff + spec) * m_kd_green );
				temp.Z =  temp.Z * ( (diff + spec) * m_kd_blue );

				//temp.X =  temp.X * ( diff * m_kd_red + spec ) );
				//temp.Y =  temp.Y * ( diff * m_kd_green + spec ) );
				//temp.Z =  temp.Z * ( diff * m_kd_blue + spec ) );
				total = total + temp;
			}

			if ( total.X > 255.0f ) total.X = 255.0f;
			if ( total.Y > 255.0f ) total.Y = 255.0f;
			if ( total.Z > 255.0f ) total.Z = 255.0f;
			if ( total.X < 0.0f ) total.X = 0.0f;
			if ( total.Y < 0.0f ) total.Y = 0.0f;
			if ( total.Z < 0.0f ) total.Z = 0.0f;

			r = (BYTE)total.X;
			g = (BYTE)total.Y;
			b = (BYTE)total.Z;

			m_transformed[i].Colour = Gdiplus::Color::MakeARGB( 255, r, g, b );
		}
	}
}
Beispiel #6
0
// For Shading Purposes
void RT_shade(Ray* ray, int depth) {
    
    if (depth <= MAX_DEPTH){                
        
        // Color Coefficients
        Vector4* diffuseCoeff = new Vector4();
        Vector4* specularCoeff = new Vector4();
        double shininess;
        
        // Diffuse and Specular Terms
        double diffuseTerm[3] = {0.0, 0.0, 0.0};
        double specularTerm[3] = {0.0, 0.0, 0.0};
        
        if (ray->intersectedObject == SPHERE) {

            diffuseCoeff->ReInitialize(spheres[ray->intersectID].color_diffuse);
            specularCoeff->ReInitialize(spheres[ray->intersectID].color_specular);
            shininess = spheres[ray->intersectID].shininess;
        }
        else if (ray->intersectedObject == TRIANGLE) {

            // Interpolate diffuse and specular coefficients
            double alpha, beta;
            ObtainIntermediateTriangleIntersection(ray->intersectID, ray->intersectPoint, &alpha, &beta);

            diffuseCoeff->ReInitialize();
            InterpolateTriangleProperty(triangles[ray->intersectID].v[0].color_diffuse,
                    triangles[ray->intersectID].v[1].color_diffuse,
                    triangles[ray->intersectID].v[2].color_diffuse,
                    alpha, beta, diffuseCoeff, false);

            specularCoeff->ReInitialize();
            InterpolateTriangleProperty(triangles[ray->intersectID].v[0].color_specular,
                    triangles[ray->intersectID].v[1].color_specular,
                    triangles[ray->intersectID].v[2].color_specular,
                    alpha, beta, specularCoeff, false);

            // Interpolate shininess
            if (alpha > 0) {

                double intermediateShininess = beta * triangles[ray->intersectID].v[2].shininess
                        + (1 - beta) * triangles[ray->intersectID].v[1].shininess;

                shininess = ((alpha - 1) * triangles[ray->intersectID].v[0].shininess
                        + intermediateShininess) / alpha;
            } 
            else {
                shininess = triangles[ray->intersectID].v[0].shininess;
            }
        }

        // Boundary Checking        
        assert(diffuseCoeff->HasNonNegativeEntries());
        assert(!diffuseCoeff->HasGreaterThanOneEntries());
        assert(specularCoeff->HasNonNegativeEntries());
        assert(!specularCoeff->HasGreaterThanOneEntries());
        assert(shininess >= 0);
        
        // Normal Vector: N
        Vector4* N = new Vector4(ray->normal);
        N->ConvertToUnitVector();
        
        // Viewer Direction: V = ray->intersectedPoint - ray->source = -ray->dir
        Vector4* V = new Vector4(ray->dir);
        V->Scale(-1);
        V->ConvertToUnitVector();
        
        int dontCheckObject = NONE;
        int dontCheckObjectID = NONE;
        
        if (ray->intersectedObject == TRIANGLE) {
            dontCheckObject = ray->intersectedObject;
            dontCheckObjectID = ray->intersectID;
        }
        
                
        unsigned int i;
        for (i = 0; i < num_lights; i++) {            
            
            // Shoot a ray in the direction of the light
            Vector4* lightPos = new Vector4(lights[i].position);
            Ray* checkShadow = new Ray(ray->intersectPoint, lightPos);
            bool shadow = false;            
            
            double nearestTIntersect = FindNearestTIntersection(checkShadow,dontCheckObject,dontCheckObjectID);
            double point2LightDistance = FindDistanceOfIntersectedPointWithLight(ray,i);
            if (nearestTIntersect != INFINITY 
                && nearestTIntersect< point2LightDistance)
            {
                shadow = true;    
            }

            // Point to Light Vector: L = light_pos - intersectedPoint
            Vector4* L = new Vector4(lights[i].position);
            L->Subtraction(ray->intersectPoint);
            L->ConvertToUnitVector();            

            // Reflected Ray: R = 2(N.L)N - L
            Vector4* R = new Vector4(ray->normal);
            R->Scale(2 * N->DotProduct(L));
            R->Subtraction(L);
            R->ConvertToUnitVector();

            // Dot Product of N and L: NL
            double NL = N->DotProduct(L);
            if (NL < 0) {
                NL = 0;
            }

            // Dot Product of R and V: RV
            double RV = R->DotProduct(V);
            if (RV < 0) {
                RV = 0;
            }

            assert(NL <= 1 && RV <= 1);

            double attenuationTerm =  depth==1?1:1; 
            
            if (!shadow) {                
                unsigned int j;
                for (j = 0; j < 3; j++) {
                    diffuseTerm[j] += attenuationTerm * lights[i].color[j] * diffuseCoeff->vector[j] * NL;
                    specularTerm[j] += attenuationTerm * lights[i].color[j] * specularCoeff->vector[j] * pow(RV, shininess);
                }
            }

            
            
            delete(L);
            delete(R);

            delete(lightPos);
            delete(checkShadow);
        }

        // Adding diffused light
        Vector4* diffusedColor = new Vector4(diffuseTerm);
        //          //For Debugging Purposes
        //          if(ray->intersectedObject == SPHERE){                
        //            ray->color->Display();
        //            diffusedColor->Display();
        //            cout<<"................................................."<<endl;
        //          }
        ray->color->Addition(diffusedColor);
        delete(diffusedColor);

        // Adding specular light
        Vector4* specularColor = new Vector4(specularTerm);
        ray->color->Addition(specularColor);        
        delete(specularColor);

        //R = 2*(NI)N - I ; N = N; I = V = ray->source - ray->IntersectPoint
        Vector4* R_ = new Vector4(ray->normal);
        Vector4* I = new Vector4(ray->dir);
        I->Scale(-1);
        R_->Scale(2*N->DotProduct(I));
        R_->Subtraction(I);
        Vector4* end = new Vector4(ray->intersectPoint);
        end->Addition(R_);       
        
        
        Ray* reflectedRay = new Ray(ray->intersectPoint, end);
        delete(R_);
        delete(I);
        delete(end);
        assert(dontCheckObject!=SPHERE);
        RT_trace(reflectedRay, depth+1, dontCheckObject, dontCheckObjectID);

        //For Debugging
//        if(ray->intersectedObject==TRIANGLE/* && ray->intersectPoint->vector[1]<-2*screenX/4
//                && ray->intersectPoint->vector[1]>-3*screenX/4*/){
//            cout<<ray->intersectID;            
//            cout<<"---->";
//            ray->normal->Display();
//            cout<<"------>";
//            I->Display();
//            cout<<I->DotProduct(ray->normal)<<"\t";
//            cout<<reflectedRay->dir->DotProduct(ray->normal);
//            reflectedRay->dir->Display();
//            cout<<": "<<reflectedRay->tIntersect<<"\t";            
//            reflectedRay->color->Display();
//            cout<<endl;
//        }
        
        if(reflectedRay->tIntersect!=INFINITY){          
            
            reflectedRay->color->Scale(specularCoeff->vector[0], specularCoeff->vector[1], specularCoeff->vector[2]);                       
            ray->color->Addition(reflectedRay->color);
        }
        
        delete(reflectedRay);

        delete(N);
        delete(V);
        delete(specularCoeff);
        delete(diffuseCoeff);
    }    
}
Beispiel #7
0
double FindNearestTIntersectionWithTriangle(Ray* ray, int* index, int noCheckID = NONE){
    
    assert(noCheckID==NONE || (noCheckID>=0 && noCheckID<num_triangles));
    
    double nearestTIntersect = INFINITY;
    *index = NONE;
    
    unsigned int i;    
    for (i = 0; i < num_triangles; i++) {
        
        if (i==noCheckID){
            continue;
        }
        // Vertices V0, V1 and V2
        Vector4* V0 = new Vector4(triangles[i].v[0].position);
        Vector4* V1 = new Vector4(triangles[i].v[1].position);
        Vector4* V2 = new Vector4(triangles[i].v[2].position);
        
        // Edges: VOV1, V0V2
        Vector4* V0V1 = new Vector4(V1);
        V0V1->Subtraction(V0);
        Vector4* V0V2 = new Vector4(V2);
        V0V2->Subtraction(V0);
        
        // Normal: N = V0V1 X V0V2
        Vector4* N = new Vector4(V0V1);
        N->CrossProductPost(V0V2);
        N->ConvertToUnitVector();
                
        // ray and normal should be opposite
        if (N->DotProduct(ray->dir)>0){
            N->Scale(-1);
        }
        
        // N = [A B C]
        // AX0 + BY0 + CZ0 + D = 0
        double D = -1*N->DotProduct(V0);                       
        
        if (N->DotProduct(ray->dir) != (double) 0) {
            // t = -(N.Ro + D)/ (N.Rd)
            double candidateT = -1 * (N->DotProduct(ray->source) + D) / N->DotProduct(ray->dir);            
            
            if (candidateT > 0){
                
                // P = Ro + tRd
                Vector4* point = new Vector4(ray->dir);
                point->Scale(candidateT);
                point->Addition(ray->source);

                // alpha*V0V1 + beta*V0V2 = V0P
                Vector4* V0P = new Vector4(point);
                V0P->Subtraction(V0);

                double alpha = 0.0;
                double beta = 0.0;

                //(x01)alpha + (x02)beta = x0p;
                //(y01)alpha + (y02)beta = y0p;
                //(z01)alpha + (z02)beta = z0p;
                double A1 = V0V1->vector[0];
                double B1 = V0V2->vector[0];
                double C1 = V0P->vector[0];

                double A2 = V0V1->vector[1];
                double B2 = V0V2->vector[1];
                double C2 = V0P->vector[1];
                
                double A3 = V0V1->vector[2];
                double B3 = V0V2->vector[2];
                double C3 = V0P->vector[2];

                SolveLinearEquation(A1, B1, C1, A2, B2, C2, &alpha, &beta);

                if (alpha == NONE) {
                    SolveLinearEquation(A2, B2, C2, A3, B3, C3, &alpha, &beta);
                }
                
                if (alpha == NONE) {
                    SolveLinearEquation(A1, B1, C1, A3, B3, C3, &alpha, &beta);
                }
                
//                // For Debugging Purposes
//                printf("\nTriangle: %d ==> CandidateT: %f ==> (%f,%f)",i,candidateT,alpha,beta);
                
                if (alpha > 0 && beta > 0 && (alpha + beta) < 1) {
                    if (nearestTIntersect > candidateT) {
                        nearestTIntersect = candidateT;
                        *index = i;
                    }
                }

                delete(V0P);
                delete(point); 
            }
        }
        
        delete(N);
        delete(V0V2);
        delete(V0V1);
        delete(V2);
        delete(V1);
        delete(V0);
    }
    
    return nearestTIntersect;
}