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; }
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; }
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; }
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; }