bool sphereplane(vector3d& sp,vector3d pn,vector3d p1,vector3d p2,vector3d p3,vector3d p4, float r)
{
		//if the distance is greater then the radius, there is no collision
		if(rayplanedist(pn.x,pn.y,pn.z,p1.x,p1.y,p1.z,sp.x,sp.y,sp.z,-pn.x,-pn.y,-pn.z)>r || rayplanedist(-pn.x,-pn.y,-pn.z,p1.x,p1.y,p1.z,sp.x,sp.y,sp.z,pn.x,pn.y,pn.z)>r)
			return false;
	//if the ray from the center of the sphere is intersect the plane, there is a collision
	if(rayplane(pn.x,pn.y,pn.z,p1.x,p1.y,p1.z,sp.x,sp.y,sp.z,-pn.x,-pn.y,-pn.z,p1,p2,p3,p4) || rayplane(-pn.x,-pn.y,-pn.z,p1.x,p1.y,p1.z,sp.x,sp.y,sp.z,pn.x,pn.y,pn.z,p1,p2,p3,p4))
	{
		float raycol=rayplanedist(pn.x,pn.y,pn.z,p1.x,p1.y,p1.z,sp.x,sp.y,sp.z,-pn.x,-pn.y,-pn.z);	//we calculate how far we are
		if(raycol)	//if not zero
		{
			sp.x=sp.x+pn.x*(r-raycol);	//calculate the point, and calculate our new location
			sp.y=sp.y+pn.y*(r-raycol);
			sp.z=sp.z+pn.z*(r-raycol);		
		}else	//else if we are in the opposite side, then the normal vector
		{
			raycol=rayplanedist(-pn.x,-pn.y,-pn.z,p1.x,p1.y,p1.z,sp.x,sp.y,sp.z,pn.x,pn.y,pn.z);
			sp.x=sp.x-pn.x*(r-raycol);
			sp.y=sp.y-pn.y*(r-raycol);
			sp.z=sp.z-pn.z*(r-raycol);				
		}

		return true;	//we return true, to indicate the collision, but the main thing is, that we changged the sp (so the sphere position) to the new position)
	}
	return false;
}
Esempio n. 2
0
bool collision::sphereplane(vector3d& sp, vector3d pn, vector3d p1, vector3d p2, vector3d p3, vector3d p4, float r)
{
	float dist1 = 0, dist2 = 0;

	if (rayplane(pn.x, pn.y, pn.z, p1.x, p1.y, p1.z, sp.x, sp.y, sp.z, -pn.x, -pn.y, -pn.z, p1, p2, p3, p4, &dist1) || rayplane(-pn.x, -pn.y, -pn.z, p1.x, p1.y, p1.z, sp.x, sp.y, sp.z, pn.x, pn.y, pn.z, p1, p2, p3, p4, &dist2))
	{
		if (dist1>r || dist2>r)
		{
			return false;
		}
		
		if (dist1>0)	//if not zero
		{

			// if plane normal y dimension is lower than 1, it means we go "upstairs", it means we have to raise y dimension value by small value so we are not 
			//forced to "stand in place"
			sp.x = pn.y > 0 && pn.y < 1 ? sp.x : sp.x + pn.x*(r - dist1);	//calculate the point, and calculate our new location
			sp.y = pn.y > 0 && pn.y < 1 ? sp.y + pn.y*(r - dist1) + 0.001 : sp.y + pn.y*(r - dist1);
			sp.z = pn.y > 0 && pn.y < 1 ? sp.z : sp.z + pn.z*(r - dist1);
		}
		else	//else if we are in the opposite side, then the normal vector
		{
			sp.x = sp.x - pn.x*(r - dist2);
			sp.y = sp.y - pn.y*(r - dist2);
			sp.z = sp.z - pn.z*(r - dist2);
		}

		return true;	//we return true, to indicate the collision, but the main thing is, that we changged the sp (so the sphere position) to the new position)
	}
	//	if(pn.x==0 && pn.y==1 && pn.z==0)
	//std::cout << "returning false (2): " << pn << dist1 << " " << dist2 << std::endl;
	return false;
}
Esempio n. 3
0
bool sphereplane(coordinate& sp, coordinate vn,coordinate p1,coordinate p2,coordinate p3, coordinate p4,float r) {
	float dist1=0,dist2=0;
	if(rayplane(-vn.x,-vn.y,-vn.z,sp.x,sp.y,sp.z,vn.x,vn.y,vn.z,p1,p2,p3,p4,&dist1) || rayplane(vn.x,vn.y,vn.z,sp.x,sp.y,sp.z,-vn.x,-vn.y,-vn.z,p1,p2,p3,p4,&dist2)) {
		if(dist1>r || dist2>r)
			return false;
		if(dist1>0) {
			sp.x=sp.x-vn.x*(r-dist1);
			sp.y=sp.y-vn.y*(r-dist1);
			sp.z=sp.z-vn.z*(r-dist1);
		}
		else {
			sp.x=sp.x+vn.x*(r-dist2);
			sp.y=sp.y+vn.y*(r-dist2);
			sp.z=sp.z+vn.z*(r-dist2);		
		}
		return 1;
	}
	return 0;
}
Esempio n. 4
0
bool Functions:: sphereplane(vector3d& sp, vector3d vn,vector3d p1,vector3d p2,vector3d p3, vector3d p4,float r)
{
        //float nx,float ny,float nz,float xs,float ys,float zs,float xd,float yd,float zd,vector3d p1,vector3d p2,vector3d p3,vector3d p4,float* dist,coordinate* point)
        float dist1=0,dist2=0;
        if(rayplane(-vn.x,-vn.y,-vn.z,sp.x,sp.y,sp.z,vn.x,vn.y,vn.z,p1,p2,p3,p4,&dist1) || rayplane(vn.x,vn.y,vn.z,sp.x,sp.y,sp.z,-vn.x,-vn.y,-vn.z,p1,p2,p3,p4,&dist2))
        {
                if(dist1>r || dist2>r)
                        return false;
                if(dist1>0)
                {
                        //sp.x=sp.x-vn.x*(r-dist1);
                        sp.y=sp.y-vn.y*(r-dist1);
                        sp.z=sp.z-vn.z*(r-dist1);
                }else{
                        //sp.x=sp.x+vn.x*(r-dist2);
                        sp.y=sp.y+vn.y*(r-dist2);
                        sp.z=sp.z+vn.z*(r-dist2);              
                }
                return 1;
        }
        return 0;
} 
void display()
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glLoadIdentity();

  cam->Control(0.2, 0.2, mousein, screen->w, screen->h);
  sky->Draw();
  cam->Update();

  float lightposition[] = {-1.0, 1.0, -2.0, 1.0};
  glLightfv(GL_LIGHT0, GL_POSITION, lightposition);

  // DRAW RAY

  glDisable(GL_LIGHTING);

  //if (raysphere(spherecenter.x, spherecenter.y, spherecenter.z, 0.0, 0.0, 1.0, raystart.x, raystart.y, raystart.z, 1.0))
  if (rayplane(0.0, 0.0, 1.0, raystart.x, raystart.y, raystart.z, raydirection.x, raydirection.y, raydirection.z, p1, p2, p3, p4, NULL, NULL))
  {
    glColor3f(1.0, 0.0, 0.0);
  }
  else
  {
    glColor3f(1.0, 1.0, 1.0);
  }

  // xs + t*xd
  glBegin(GL_LINES);
  glVertex3f(raystart.x, raystart.y, raystart.z);
  glVertex3f(raystart.x + raydistance*raydirection.x, raystart.y + raydistance*raydirection.y, raystart.z + raydistance*raydirection.z);
  glEnd();

  // END DRAW RAY


  // START DRAW PLANE

  glBegin(GL_QUADS);
  glVertex3f(-5.0, 5.0, -5.0);
  glVertex3f(5.0, 5.0, -5.0);
  glVertex3f(5.0, -5.0, -5.0);
  glVertex3f(-5.0, -5.0, -5.0);
  glEnd();

  // END DRAW PLANE


  // DRAW OBJECT

  glEnable(GL_LIGHTING);

  glColor3f(1.0, 1.0, 1.0);

  glPushMatrix();

  //glTranslatef(0.0, 0.0, -10.0);
  glRotatef(angle, 1.0, 1.0, 1.0);
  glCallList(cube);

  glPopMatrix();

  // END DRAW OBJECT

  return;
}
Color traceRay(Point ray, Point st, int depth)
{
	Color illum = {0,0,0};
	if (depth > MAX_DEPTH) return illum;
	
	// find closest ray object/intersection;
	// for each object in scene, get distance or 0 if no intersect
	int closestIndex = -1;
	float closestDist = 9999;
	float res = 0;
	for (int i=0; i<9; i++) // for each sphere
	{
		res = raysphere(s[i].c,ray,st,s[i].radius); // get t from raysphere()
		if(res!=0 && res < closestDist)
		{
			closestDist = res;
			closestIndex = i;
		}
	}
	
	if (closestIndex == -1) // no intersection with sphere, check versus floor
	{
		res = rayplane(ray,st,-50.0); // get t from rayplane()
		if (res!=0)
		{
			closestDist = res;
			closestIndex = 9;  // mirror floor
		}
	}
	
	if (closestIndex != -1) // if intersection exists
	{ 
		Point inter = {(st.x+(closestDist*ray.x)),(st.y+(closestDist*ray.y)),(st.z+(closestDist*ray.z))};
		
		// if toggled, compute shadows
		Point shad_ray = {light_pos.x-inter.x, light_pos.y-inter.y, light_pos.z-inter.z};
		float mag = sqrt(shad_ray.x*shad_ray.x + shad_ray.y*shad_ray.y + shad_ray.z*shad_ray.z);
		shad_ray.x /= mag;
		shad_ray.y /= mag;
		shad_ray.z /= mag;
		int shadIndex = -1; // default no shadow
		float shadDist = 9999;
		if (SHOW_SHADOWS)
		{
			for (int j=0; j<9; j++) // for each sphere,
			{
				res = raysphere(s[j].c,shad_ray,inter,s[j].radius);
				if(res!=0 && res < shadDist) // check if point is occluded by shadow
				{
					shadDist = res;
					shadIndex = j;
				}
			}
		}
		
		Point norm;
		if (closestIndex==9) // calculate normal for floor
		{
			float nmag = sqrt(inter.x*inter.x + (-49)*(-49) + inter.z*inter.z);
			norm.x = inter.x/nmag;
			norm.y = -49/nmag;
			norm.z = inter.z/nmag;
		}
		else // calculate normal for sphere
		{
			float nmag = sqrt( (inter.x-s[closestIndex].c.x)*(inter.x-s[closestIndex].c.x) + (inter.y-s[closestIndex].c.y)*(inter.y-s[closestIndex].c.y) + (inter.z-s[closestIndex].c.z)*(inter.z-s[closestIndex].c.z) );
			norm.x = ((inter.x-s[closestIndex].c.x)/nmag);
			norm.y = ((inter.y-s[closestIndex].c.y)/nmag);
			norm.z = ((inter.z-s[closestIndex].c.z)/nmag);
		}

		if (shadIndex==-1) // if no obstruction to light
		{
			float L_N = shad_ray.x*norm.x + shad_ray.y*norm.y + shad_ray.z*norm.z;
			Point H = {(shad_ray.x+ray.x)/2,(shad_ray.y+ray.y)/2,(shad_ray.z+ray.z)/2};
			float H_N = H.x*norm.x + H.y*norm.y + H.z*norm.z; // halfway vector *dot* normal
			
			illum.r += s[closestIndex].rgb[0] * L_N + pow(H_N,spec_exp); // Phong illum.:
			illum.g += s[closestIndex].rgb[1] * L_N + pow(H_N,spec_exp); // diffuse + specular
			illum.b += s[closestIndex].rgb[2] * L_N + pow(H_N,spec_exp);
		}

		// if surface is reflective
		if (s[closestIndex].reflect > 0)
		{
			float n_d = 2.0*(norm.x*ray.x + norm.y*ray.y + norm.z*ray.z);
			Point refl_ray = {ray.x-(n_d*norm.x),ray.y-(n_d*norm.y),ray.z-(n_d*norm.z)};
			float mag = sqrt(refl_ray.x*refl_ray.x + refl_ray.y*refl_ray.y + refl_ray.z*refl_ray.z);
			refl_ray.x /= mag;
			refl_ray.y /= mag;
			refl_ray.z /= mag;
			Color refl = traceRay(refl_ray, inter, depth+1); // recursive here
			illum.r += refl.r * s[closestIndex].reflect;
			illum.g += refl.g * s[closestIndex].reflect;
			illum.b += refl.b * s[closestIndex].reflect;
		}
	}
	return illum;
}