void BSplineSurf::recalcCoords(float ds,float dt) { float s,t; float out[3]; int ns,nt; myVector<float> sv; myVector<float> tv; for (s=U[0]; s<U[1]; s+=ds) { sv.append(s); } sv.append(U[1]); for (t=V[0]; t<V[1]; t+=dt) { tv.append(t); } tv.append(V[1]); total_coords=sv.length()*tv.length(); coords=(float(*)[3])malloc(total_coords*sizeof(float[3])); total_coords=0; for (ns=0; ns<sv.length(); ns++) { s=sv.at(ns); for (nt=0; nt<tv.length(); nt++) { t=tv.at(nt); getParamPoint(s,t,coords[total_coords]); total_coords++; } } myVector<int> N; int striplen; for (ns=0; ns<sv.length()-1; ns++) { N.append(0); striplen=N.length()-1; for (nt=0; nt<tv.length(); nt++) { N.append(nt+tv.length()*ns); N.append(nt+ tv.length()*(ns+1)); } N.at(striplen)=tv.length()*2; } N.append(0); free(strip); strip=(int*)malloc(N.length()*sizeof(int)); memcpy(strip,N.getData(),N.length()*sizeof(int)); free(normals); normals=(float(*)[3])calloc(total_coords,sizeof(float[3])); int *ar,totta,k; ar=strip; while (ar[0]) { totta=ar[0]; ar++; for (k=2; k<totta; k++) { float g1[3],g2[3],g3[3]; vec_diff(g1,coords[ ar[k-2] ],coords[ ar[k-1] ]); vec_diff(g2,coords[ ar[k-1] ],coords[ ar[k] ]); vec_cross_product(g3,g1,g2); vec_normalize(g3); if (k&1) { vec_flip(g3,g3); } vec_sum(normals[ ar[k] ],normals[ ar[k] ],g3); if (k==2) { vec_sum(normals[ ar[0] ],normals[ ar[0] ],g3); vec_sum(normals[ ar[1] ],normals[ ar[1] ],g3); } } ar+=totta; } for (k=0; k<total_coords; k++) { vec_normalize(normals[k]); } }
static intersectionT findSphereIntersection(rayT* ray, surfaceT* surface) { intersectionT intersection = { 0 }; sphereSurfaceT* sphere = surface->data; intersection.surface = surface; intersection.ray = *ray; // Sphere equation: x^2+y^2+z^2=r^2 // Or, with a position: (x-c_x)^2+(y-c_y)^2+(z-c_z)^2 = r^2 // // Intersecting it with a parametric line: // // (o_x+td_x-c_x)^2+(o_y+td_y-c_y)^2+(o_z+td_z-c_z)^2 = r^2 // // Solving for t: // (o_x+td_x-c_x)^2+(o_y+td_y-c_y)^2+(o_z+td_z-c_z)^2-r^2 = 0 // // ((o_x-c_x)+td_x)^2+((o_y-c_y)+td_y)^2+((o_z-c_z)+td_z)^2-r^2 = 0 // // (o_x-c_x)^2+2*(o_x-c_x)*t*d_x+t^2d_x^2 + // (o_y-c_y)^2+2*(o_y-c_y)*t*d_y+t^2d_y^2 + // (o_z-c_z)^2+2*(o_z-c_z)*t*d_y+t^2d_y^2 - r^2 = 0 // // (o_x-c_x)^2+(o_y-c_y)^2+(o_z-c_z)^2 + // 2t((o_x-c_x)*d_x+(o_y-c_y)*d_y+(o_z-c_z)*d_y) + // t^2(d_x^2+d_y^2+d_z^2) - r^2 = 0 // // This gives us a quadratic equation of the form ax^2+bx+c=0: // // a = (d_x^2+d_y^2+d_z^2) // b = 2((o_x-c_x)*d_x+(o_y-c_y)*d_y+(o_z-c_z)*d_y) // c = (o_x-c_x)^2+(o_y-c_y)^2+(o_z-c_z)^2-r // // t^2+(b/a)t+(c/a) = 0 // // Completing the square: // // t^2+(b/a)t = -c/a // (t+0.5(b/a))^2 = -c/a+0.25(b/a)^2 // t+0.5(b/a) = +-sqrt(-c/a+0.25(b/a)^2) // t = +-sqrt(-c/a+0.25(b/a)^2) - 0.5(b/a) float a = square(ray->direction.x) + square(ray->direction.y) + square(ray->direction.z); float b = 2.0f * ((ray->origin.x - sphere->center.x) * ray->direction.x + (ray->origin.y - sphere->center.y) * ray->direction.y + (ray->origin.z - sphere->center.z) * ray->direction.z); float c = square(ray->origin.x - sphere->center.x) + square(ray->origin.y - sphere->center.y) + square(ray->origin.z - sphere->center.z) - square(sphere->radius); float d = -c/a + 0.25f*square(b/a); if (d >= 0.0f) { float t0 = -sqrtf(d) - 0.5*(b/a); float t1 = sqrtf(d) - 0.5*(b/a); float t = t0; bool inside = false; if (t <= 0.0f) { // We're inside the sphere, or the sphere is behind us. t = t1; inside = true; } intersection.t = t; intersection.position = (vec3) { ray->origin.x + t*ray->direction.x, ray->origin.y + t*ray->direction.y, ray->origin.z + t*ray->direction.z }; intersection.normal = intersection.position; vec_sub(&intersection.normal, &sphere->center, &intersection.normal); vec_normalize(&intersection.normal, &intersection.normal); if (inside) vec_flip(&intersection.normal, &intersection.normal); } return (intersection); }