Exemplo n.º 1
0
void Octree::intersectRayBoth( const Ray& ray, IndexSet & tris )
{
	stack<Octree*> trees;

	Ray inverseRay(ray.inverse());

	if (boundingBox.intersects(ray) || boundingBox.intersects(inverseRay))
		trees.push(this);
	else
		return;

	while(!trees.empty())
	{
		Octree * t = trees.top(); trees.pop();

		if (!t->intersectHit(tris))
		{
			for (StdVector<Octree>::iterator child = t->children.begin(); child != t->children.end(); child++)
			{
				if (child->boundingBox.intersects(ray) || child->boundingBox.intersects(inverseRay))
				{
					trees.push(&(*child));
				}
			}
		}
	}
}
Exemplo n.º 2
0
RGBAPixel GeometricObject::rayTrace(PointLight& lightSrc, Point3D& pt, Ray& viewRay, vector<GeometricObject*>& shapes){
    
    RGBAPixel color = material.color;
    if(texture != NULL)
        color = *mapToTexture(pt);
    
    Vector3D dir(lightSrc.o,pt);
    dir.normalize();
    
    Point3D tempPt(pt+dir.reflect()*0.01);
    Ray backtraceRay(tempPt,dir.reflect(), "shadow"); //from hit point on shape to light source
    double tHitLight = lightSrc.o.distance(pt);
    bool shadow = false;
    
    Point3D trash(0,0,0);
    for(int i = 0; i < shapes.size(); i++){
        if(shapes[i]->isLightSrc)
            continue;
        double tHitAnotherShape = shapes[i]->hit(backtraceRay,trash);
        if(tHitAnotherShape < tHitLight && tHitAnotherShape > 0){
            shadow = true;
            break;
        }
    }
    
    //pt's intersection with viewRay and geometry
    Vector3D n(this->getNormal(pt));
    n.normalize();
    
    double r = 0.0;
    double g = 0.0;
    double b = 0.0;
    
    //Ambient Lighting
    r += 0.04 * 30;
    g += 0.04 * 30;
    b += 0.04 * 30;
    
    RGBAPixel temp(r*color.red, g*color.green ,b*color.blue);
    
    if(shadow){
        return temp;
    }
    
    
    //Diffuse Lighting
    Vector3D reflectRay = (dir.reflect()).hat();
    double product = reflectRay.dot(n);
    if (product > 0){
        r += color.red*product * material.kd;
        g += color.green*product * material.kd;
        b += color.blue*product * material.kd;
    }
    
    //Specular Lighting
    
    
    double epsilon = 10.0;
    Vector3D rVec(dir - (n*dir.dot(n)*2.0));
    double spec = rVec.dot(viewRay.d.reflect());
    double rw0e;
    if(spec > 0)
        rw0e = pow(spec,epsilon);
    else
        rw0e = 0;
    if(product > 0){
        r += color.red*rw0e * material.ks * 0.5;
        g += color.green*rw0e * material.ks * 0.5;
        b += color.blue*rw0e * material.ks * 0.5;
    }
    r = r*material.directScale;
    g = g*material.directScale;
    b = b*material.directScale;
    
    //Reflections
    double minTime = 100000.0;
    double tHitAnotherShape = 0.0;
    Vector3D recViewDir(viewRay.d - (2*viewRay.d*n)*n); //direction of mirror reflection
    recViewDir.normalize();
    
    Ray recViewRay(pt,recViewDir, "view");
    recViewRay.recurseLevel = viewRay.recurseLevel+1;
    Point3D recPt;
    RGBAPixel recColor;
    
    //Mirror Reflection
    if(material.reflectProperty == "mirror" && viewRay.recurseLevel < 3){
        
        GeometricObject* nextShape = NULL;
        
        for(int k = 0; k < shapes.size(); k++){
            if(shapes[k] == this)
                continue;
            
            tHitAnotherShape = shapes[k]->hit(recViewRay,recPt);
            if(tHitAnotherShape > 0.0 && tHitAnotherShape < minTime){
                nextShape = shapes[k];
                minTime = tHitAnotherShape;
            }
        }
        if(nextShape != NULL){
            recColor = nextShape->rayTrace(lightSrc, recPt, recViewRay, shapes);
            r += (recColor.red); //* (1-material.directScale);
            g += (recColor.green);// * (1-material.directScale);
            b += (recColor.blue);// * (1-material.directScale);
        }
    }
    if(material.reflectProperty == "glossy" && viewRay.recurseLevel < 3){
        
        double tempR = 0.0;
        double tempG = 0.0;
        double tempB = 0.0;
        
        Vector3D axisA = Vector3D(1,0,0).cross(recViewDir).hat() * 1;
        Vector3D axisB = axisA.cross(recViewDir).hat() * 1;

        Point3D tempPt = pt + recViewDir - 0.5*axisA - 0.5*axisB;
        Rectangle rect(tempPt, axisA, axisB);
        
        vector<Point3D> samplepts = rect.generatePoints(100);
        
        for(int i = 0; i < samplepts.size(); i++){
            Vector3D indirectDir(pt,samplepts[i]);
            Ray indirectRay(pt,indirectDir);
            indirectRay.recurseLevel = viewRay.recurseLevel + 1;
            
            GeometricObject* nextShape = NULL;
            double minTime = 100000.0;
            double tHitAnotherShape = 0.0;
            for(int k = 0; k < shapes.size(); k++){
                if(shapes[k] == this)
                    continue;
                
                tHitAnotherShape = shapes[k]->hit(indirectRay,recPt);
                if(tHitAnotherShape > 0.0 && tHitAnotherShape < minTime){
                    nextShape = shapes[k];
                    minTime = tHitAnotherShape;
                }
                if(nextShape != NULL && nextShape->material.transparency == 0){
                    recColor = nextShape->rayTrace(lightSrc, recPt, recViewRay, shapes);
                    tempR += (recColor.red);
                    tempG += (recColor.green);
                    tempB += (recColor.blue);
                }
            }
        }
        r += tempR / samplepts.size();
        g += tempG / samplepts.size();
        b += tempB / samplepts.size();
    }
    
    if(material.transparency > 0 && viewRay.recurseLevel == 0){
        double tempR = 255;
        double tempG = 255;
        double tempB = 255;
        
        Vector3D invNormal = n.reflect();
        Ray inverseRay(pt,invNormal);
        inverseRay.recurseLevel = viewRay.recurseLevel + 1;
        GeometricObject* nextShape = NULL;
        double minTime = 100000.0;
        double tHitAnotherShape = 0.0;
        for(int k = 0; k < shapes.size(); k++){
            if(shapes[k] == this)
                continue;
            
            tHitAnotherShape = shapes[k]->hit(inverseRay,recPt);
            if(tHitAnotherShape > 0.0 && tHitAnotherShape < minTime){
                nextShape = shapes[k];
                minTime = tHitAnotherShape;
            }
            if(nextShape != NULL && nextShape != this){
                recColor = nextShape->rayTrace(lightSrc, recPt, inverseRay, shapes);
                tempR = (recColor.red);
                tempG = (recColor.green);
                tempB = (recColor.blue);
            }
        }
        r = tempR * material.transparency + (r*(1-material.transparency));
        g = tempG * material.transparency + (g*(1-material.transparency));
        b = tempB * material.transparency + (b*(1-material.transparency));
    }
    
    //cap off maximum color values
    r =std::min((int)r,255);
    g =std::min((int)g,255);
    b =std::min((int)b,255);
    
    temp(r,g,b);
    return temp;
}
Exemplo n.º 3
0
void Camera3D::draw_gl ()
{
	Vector3DF pnt; 
	int va, vb;
	
	if ( !mOps[0] ) return;

	// Box testing
	//
	// NOTES: This demonstrates AABB box testing against the frustum 
	// Boxes tested are 10x10x10 size, spaced apart from each other so we can see them.
	if ( mOps[5] ) {
		glPushMatrix ();
		glEnable ( GL_LIGHTING );
		glColor3f ( 1, 1, 1 );	
		Vector3DF bmin, bmax, vmin, vmax;
		int lod;
		for (float y=0; y < 100; y += 10.0 ) {
		for (float z=-100; z < 100; z += 10.0 ) {
			for (float x=-100; x < 100; x += 10.0 ) {
				bmin.Set ( x, y, z );
				bmax.Set ( x+8, y+8, z+8 );
				if ( boxInFrustum ( bmin, bmax ) ) {				
					lod = (int) calculateLOD ( bmin, 1, 5, 300.0 );
					//rendGL->drawCube ( bmin, bmax, Vector3DF(1,1,1) );
				}
			}
		}
		}
		glPopMatrix ();
	}

	glDisable ( GL_LIGHTING );	
	glLoadMatrixf ( getViewMatrix().GetDataF() );

	// Frustum planes (world space)
	//
	// NOTE: The frustum planes are drawn as discs because
	// they are boundless (infinite). The minimum information contained in the
	// plane equation is normal direction and distance from plane to origin.
	// This sufficiently defines infinite planes for inside/outside testing,
	// but cannot be used to draw the view frustum without more information.
	// Drawing is done as discs here to verify the frustum plane equations.
	if ( mOps[2] ) {
		glBegin ( GL_POINTS );
		glColor3f ( 1, 1, 0 );
		Vector3DF norm;
		Vector3DF side, up;
		for (int n=0; n < 6; n++ ) {
			norm.Set ( frustum[n][0], frustum[n][1], frustum[n][2] );
			glColor3f ( n/6.0, 1.0- (n/6.0), 0.5 );
			side = Vector3DF(0,1,0); side.Cross ( norm ); side.Normalize ();	
			up = side; up.Cross ( norm ); up.Normalize();
			norm *= frustum[n][3];
			for (float y=-50; y < 50; y += 1.0 ) {
				for (float x=-50; x < 50; x += 1.0 ) {
					if ( x*x+y*y < 1000 ) {
						//pnt = side * x + up * y - norm; 
                        pnt = side;
                        Vector3DF tv = up;

                        tv *= y;
                        pnt *= x;
                        pnt += tv;
                        pnt -= norm;

						glVertex3f ( pnt.x, pnt.y, pnt.z );
					}
				}
			}
		}
		glEnd (); 
	}

	// Inside/outside testing
	//
	// NOTES: This code demonstrates frustum clipping 
	// tests on individual points.
	if ( mOps[4] ) {
		glColor3f ( 1, 1, 1 );
		glBegin ( GL_POINTS );
		for (float z=-100; z < 100; z += 4.0 ) {
			for (float y=0; y < 100; y += 4.0 ) {
				for (float x=-100; x < 100; x += 4.0 ) {
					if ( pointInFrustum ( x, y, z) ) {
						glVertex3f ( x, y, z );
					}
				}
			}
		}
		glEnd ();
	}
	
	// Inverse rays (world space)
	//
	// NOTES: This code demonstrates drawing 
	// inverse camera rays, as might be needed for raytracing or hit testing.
	if ( mOps[3] ) {
		glBegin ( GL_LINES );
		glColor3f ( 0, 1, 0);
		for (float x = 0; x <= 1.0; x+= 0.5 ) {
			for (float y = 0; y <= 1.0; y+= 0.5 ) {
				pnt = inverseRay ( x, y, mFar );
				pnt += from_pos;
				glVertex3f ( from_pos.x, from_pos.y, from_pos.z );		// all inverse rays originate at the camera center
				glVertex3f ( pnt.x, pnt.y, pnt.z );
			}
		}
		glEnd ();
	}

	// Projection
	//
	// NOTES: This code demonstrates 
	// perspective projection _without_ using the OpenGL pipeline.
	// Projection is done by the camera class. A cube is drawn on the near plane.
	
	// Cube geometry
	Vector3DF pnts[8];
	Vector3DI edge[12];
	pnts[0].Set (  0,  0,  0 );	pnts[1].Set ( 10,  0,  0 ); pnts[2].Set ( 10,  0, 10 ); pnts[3].Set (  0,  0, 10 );		// lower points (y=0)
	pnts[4].Set (  0, 10,  0 );	pnts[5].Set ( 10, 10,  0 ); pnts[6].Set ( 10, 10, 10 ); pnts[7].Set (  0, 10, 10 );		// upper points (y=10)
	edge[0].Set ( 0, 1, 0 ); edge[1].Set ( 1, 2, 0 ); edge[2].Set ( 2, 3, 0 ); edge[3].Set ( 3, 0, 0 );					// 4 lower edges
	edge[4].Set ( 4, 5, 0 ); edge[5].Set ( 5, 6, 0 ); edge[6].Set ( 6, 7, 0 ); edge[7].Set ( 7, 4, 0 );					// 4 upper edges
	edge[8].Set ( 0, 4, 0 ); edge[9].Set ( 1, 5, 0 ); edge[10].Set ( 2, 6, 0 ); edge[11].Set ( 3, 7, 0 );				// 4 vertical edges
	
	// -- White cube is drawn using OpenGL projection
	if ( mOps[6] ) {
		glBegin ( GL_LINES );
		glColor3f ( 1, 1, 1);
		for (int e = 0; e < 12; e++ ) {
			va = edge[e].x;
			vb = edge[e].y;
			glVertex3f ( pnts[va].x, pnts[va].y, pnts[va].z );
			glVertex3f ( pnts[vb].x, pnts[vb].y, pnts[vb].z );
		}
		glEnd ();	
	}

	//---- Draw the following in camera space..
	// NOTES:
	// The remainder drawing steps are done in 
	// camera space. This is done by multiplying by the
	// inverse_rotation matrix, which transforms from camera to world space.
	// The camera axes, near, and far planes can now be drawn in camera space.
	glPushMatrix ();
	glLoadMatrixf ( getViewMatrix().GetDataF() );
	glTranslatef ( from_pos.x, from_pos.y, from_pos.z );
	glMultMatrixf ( invrot_matrix.GetDataF() );				// camera space --to--> world space

	// -- Red cube is drawn on the near plane using software projection pipeline. See Camera3D::project
	if ( mOps[6] ) {
		glBegin ( GL_LINES );
		glColor3f ( 1, 0, 0);
		Vector4DF proja, projb;
		for (int e = 0; e < 12; e++ ) {
			va = edge[e].x;
			vb = edge[e].y;
			proja = project ( pnts[va] );
			projb = project ( pnts[vb] );
			if ( proja.w > 0 && projb.w > 0 && proja.w < 1 && projb.w < 1) {	// Very simple Z clipping  (try commenting this out and see what happens)
				glVertex3f ( proja.x, proja.y, proja.z );
				glVertex3f ( projb.x, projb.y, projb.z );
			}
		}
		glEnd ();
	}
	// Camera axes
	glBegin ( GL_LINES );
	float to_d = (from_pos - to_pos).Length();
	glColor3f ( .8,.8,.8); glVertex3f ( 0, 0, 0 );	glVertex3f ( 0, 0, -to_d );
	glColor3f ( 1,0,0); glVertex3f ( 0, 0, 0 );		glVertex3f ( 10, 0, 0 );
	glColor3f ( 0,1,0); glVertex3f ( 0, 0, 0 );		glVertex3f ( 0, 10, 0 );
	glColor3f ( 0,0,1); glVertex3f ( 0, 0, 0 );		glVertex3f ( 0, 0, 10 );
	glEnd ();

	if ( mOps[1] ) {
		// Near plane
		float sy = tan ( mFov * DEGtoRAD / 2.0);
		float sx = sy * mAspect;
		glColor3f ( 0.8, 0.8, 0.8 );
		glBegin ( GL_LINE_LOOP );
		glVertex3f ( -mNear*sx,  mNear*sy, -mNear );
		glVertex3f (  mNear*sx,  mNear*sy, -mNear );
		glVertex3f (  mNear*sx, -mNear*sy, -mNear );
		glVertex3f ( -mNear*sx, -mNear*sy, -mNear );
		glEnd ();
		// Far plane
		glBegin ( GL_LINE_LOOP );
		glVertex3f ( -mFar*sx,  mFar*sy, -mFar );
		glVertex3f (  mFar*sx,  mFar*sy, -mFar );
		glVertex3f (  mFar*sx, -mFar*sy, -mFar );
		glVertex3f ( -mFar*sx, -mFar*sy, -mFar );
		glEnd ();

		// Subview Near plane
		float l, r, t, b;
		l = -sx + 2.0*sx*mTile.x;						// Tile is in range 0 <= x,y <= 1
		r = -sx + 2.0*sx*mTile.z;
		t =  sy - 2.0*sy*mTile.y;
		b =  sy - 2.0*sy*mTile.w;
		glColor3f ( 0.8, 0.8, 0.0 );
		glBegin ( GL_LINE_LOOP );
		glVertex3f ( l * mNear, t * mNear, -mNear );
		glVertex3f ( r * mNear, t * mNear, -mNear );
		glVertex3f ( r * mNear, b * mNear, -mNear );
		glVertex3f ( l * mNear, b * mNear, -mNear );		
		glEnd ();
		// Subview Far plane
		glBegin ( GL_LINE_LOOP );
		glVertex3f ( l * mFar, t * mFar, -mFar );
		glVertex3f ( r * mFar, t * mFar, -mFar );
		glVertex3f ( r * mFar, b * mFar, -mFar );
		glVertex3f ( l * mFar, b * mFar, -mFar );		
		glEnd ();
	}

	glPopMatrix ();
}