bool Face::triangle_intersect(const Ray &r, Hit &h, Vertex *a, Vertex *b, Vertex *c, bool intersect_backfacing) const {

  // compute the intersection with the plane of the triangle
  Hit h2 = Hit(h);
  if (!plane_intersect(r,h2,intersect_backfacing)) return 0;  

  // figure out the barycentric coordinates:
  glm::vec3 Ro = r.getOrigin();
  glm::vec3 Rd = r.getDirection();
  // [ ax-bx   ax-cx  Rdx ][ beta  ]     [ ax-Rox ] 
  // [ ay-by   ay-cy  Rdy ][ gamma ]  =  [ ay-Roy ] 
  // [ az-bz   az-cz  Rdz ][ t     ]     [ az-Roz ] 
  // solve for beta, gamma, & t using Cramer's rule
  
  glm::mat3 detA_mat(a->get().x-b->get().x,a->get().x-c->get().x,Rd.x,
                     a->get().y-b->get().y,a->get().y-c->get().y,Rd.y,
                     a->get().z-b->get().z,a->get().z-c->get().z,Rd.z);
  float detA = glm::determinant(detA_mat);

  if (fabs(detA) <= 0.000001) return 0;
  assert (fabs(detA) >= 0.000001);
  
  glm::mat3 beta_mat(a->get().x-Ro.x,a->get().x-c->get().x,Rd.x,
                     a->get().y-Ro.y,a->get().y-c->get().y,Rd.y,
                     a->get().z-Ro.z,a->get().z-c->get().z,Rd.z);
  
  glm::mat3 gamma_mat(a->get().x-b->get().x,a->get().x-Ro.x,Rd.x,
                      a->get().y-b->get().y,a->get().y-Ro.y,Rd.y,
                      a->get().z-b->get().z,a->get().z-Ro.z,Rd.z);

  float beta = glm::determinant(beta_mat) / detA;
  float gamma = glm::determinant(gamma_mat) / detA;

  if (beta >= -0.00001 && beta <= 1.00001 &&
      gamma >= -0.00001 && gamma <= 1.00001 &&
      beta + gamma <= 1.00001) {
    h = h2;
    // interpolate the texture coordinates
    float alpha = 1 - beta - gamma;
    float t_s = alpha * a->get_s() + beta * b->get_s() + gamma * c->get_s();
    float t_t = alpha * a->get_t() + beta * b->get_t() + gamma * c->get_t();
    h.setTextureCoords(t_s,t_t);
    assert (h.getT() >= EPSILON);
    return 1;
  }

  return 0;
}
示例#2
0
GimpRGB
get_ray_color_plane (GimpVector3 *pos)
{
  GimpRGB color = background;

  static gint         inside = FALSE;
  static GimpVector3  ray, spos;
  static gdouble      vx, vy;

  /* Construct a line from our VP to the point */
  /* ========================================= */

  gimp_vector3_sub (&ray, pos, &mapvals.viewpoint);
  gimp_vector3_normalize (&ray);

  /* Check for intersection. This is a quasi ray-tracer. */
  /* =================================================== */

  if (plane_intersect (&ray, &mapvals.viewpoint, &spos, &vx, &vy) == TRUE)
    {
      color = get_image_color (vx, vy, &inside);

      if (color.a != 0.0 && inside == TRUE &&
	  mapvals.lightsource.type != NO_LIGHT)
        {
          /* Compute shading at this point */
          /* ============================= */

          color = phong_shade (&spos,
			       &mapvals.viewpoint,
			       &mapvals.normal,
			       &mapvals.lightsource.position,
			       &color,
			       &mapvals.lightsource.color,
			       mapvals.lightsource.type);

          gimp_rgb_clamp (&color);
        }
    }

  if (mapvals.transparent_background == FALSE && color.a < 1.0)
    {
      gimp_rgb_composite (&color, &background,
			  GIMP_RGB_COMPOSITE_BEHIND);
    }

  return color;
}
示例#3
0
bool Face::triangle_intersect(const Ray &r, Hit &h, Vertex *a, Vertex *b, Vertex *c, bool intersect_backfacing, bool* backfacing_hit) {

	*backfacing_hit = false;
	// compute the intersection with the plane of the triangle
	Hit h2 = Hit(h);
	if (!plane_intersect(r,h2,intersect_backfacing, backfacing_hit)) return 0;	

	// figure out the barycentric coordinates:
	Vec3f Ro = r.getOrigin();
	Vec3f Rd = r.getDirection();
	// [ ax-bx	 ax-cx	Rdx ][ beta	]		 [ ax-Rox ] 
	// [ ay-by	 ay-cy	Rdy ][ gamma ]	=	[ ay-Roy ] 
	// [ az-bz	 az-cz	Rdz ][ t		 ]		 [ az-Roz ] 
	// solve for beta, gamma, & t using Cramer's rule
	
	double detA = Matrix::det3x3(a->get().x()-b->get().x(),a->get().x()-c->get().x(),Rd.x(),
						 a->get().y()-b->get().y(),a->get().y()-c->get().y(),Rd.y(),
						 a->get().z()-b->get().z(),a->get().z()-c->get().z(),Rd.z());
	
	if (fabs(detA) <= 0.000001) return 0;
	assert (fabs(detA) >= 0.000001);

	double beta	= Matrix::det3x3(a->get().x()-Ro.x(),a->get().x()-c->get().x(),Rd.x(),
				a->get().y()-Ro.y(),a->get().y()-c->get().y(),Rd.y(),
				a->get().z()-Ro.z(),a->get().z()-c->get().z(),Rd.z()) / detA;
	
	double gamma = Matrix::det3x3(a->get().x()-b->get().x(),a->get().x()-Ro.x(),Rd.x(),
				a->get().y()-b->get().y(),a->get().y()-Ro.y(),Rd.y(),
				a->get().z()-b->get().z(),a->get().z()-Ro.z(),Rd.z()) / detA;

	//Case of an intersection
	if (beta >= -0.00001 && beta <= 1.00001 &&
			gamma >= -0.00001 && gamma <= 1.00001 &&
			beta + gamma <= 1.00001) {
		h = h2;
		// interpolate the texture coordinates
		double alpha = 1 - beta - gamma;
		double t_s = alpha * a->get_s() + beta * b->get_s() + gamma * c->get_s();
		double t_t = alpha * a->get_t() + beta * b->get_t() + gamma * c->get_t();
		h.setTextureCoords(t_s,t_t);
		assert (h.getT() >= EPSILON);
		return 1;
	}

	return 0;
}
示例#4
0
bool triangle_intersect(vector_t a, vector_t b, vector_t c, vector_t normal, vector_t ray_start, vector_t ray_direction, vector_t* hit, float* u, float* v, float* w)
{
    vector_t plane_hit;
    if (!plane_intersect((plane_t) {a, normal}, ray_start, ray_direction, &plane_hit))
        return false;

    float tmp_u, tmp_v, tmp_w;
    barycentric(a, b, c, normal, plane_hit, &tmp_u, &tmp_v, &tmp_w);
    if (tmp_u < 0.0 || tmp_v < 0.0 || tmp_w < 0.0)
        return false;

    *hit = plane_hit;
    *u = tmp_u;
    *v = tmp_v;
    *w = tmp_w;
    return true;
}
示例#5
0
Color lambertian(Ray normal, const Scene* s, Sphere* sphere, Plane* plane)
{
	Color result;
	result.r = 0;
	result.g = 0;
	result.b = 0;
	bool blocked;

	for(int i = 0; i < s->lights.size(); i++)
	{
		blocked = false;
		Light current_light = s->lights.at(i);
		Ray lightRay;
		lightRay.p0 = current_light.origin;
		lightRay.dir = sub(normal.p0, current_light.origin);
		lightRay.dir = normalize(lightRay.dir);

		// check that point of interest is not shadowed by other objects
		float distFromLight = dist(normal.p0, current_light.origin);
		float distClosestObject = fInfinity; // distance between light and closest object along ray to normal initial point
		for(int k = 0; k < s->planes.size(); k++)
		{
			Plane current_plane = s->planes.at(k);
			if(!areEqual(&current_plane, plane))
			{
				distClosestObject = plane_intersect(&current_plane, &lightRay);

				// check if current object would block the light
				if(distClosestObject < distFromLight)
				{
					blocked = true;
					break;
				}
			}
		}

		for(int k = 0; k < s->spheres.size(); k++)
		{
			Sphere current_sphere = s->spheres.at(k);
			if(!areEqual(&current_sphere, sphere))
			{
				distClosestObject = sphere_intersect(&current_sphere, &lightRay);

				// check if current object would block the light
				if(distClosestObject < distFromLight)
				{
					blocked = true;
					break;
				}
			}
		}

		// check that the light source isn't behind the object
		Vec3 lv = lightRay.dir;
		Vec3 nv = normalize(normal.dir);
		if(dot(lv, nv) > 0.0)
			blocked = true;

		if(!blocked)
		{
			// add this light's contribution to the pixel color
			float coef = abs(dot(lv, nv));

			if(sphere != NULL)
			{
				result.r += (sphere->material.color.r * current_light.color.r) * coef;
				result.g += (sphere->material.color.g * current_light.color.g) * coef;
				result.b += (sphere->material.color.b * current_light.color.b) * coef;
			}
			else if(plane != NULL)
			{
				if(plane->hastexture)
				{
					Color textureColor = getTextureColor(getTexel(normal,plane),plane);

					result.r += textureColor.r * current_light.color.r * coef;
					result.g += textureColor.g * current_light.color.g * coef;
					result.b += textureColor.b * current_light.color.b * coef;
				}
				else 
				{
					result.r += (plane->material.color.r * current_light.color.r) * coef;
					result.g += (plane->material.color.g * current_light.color.g) * coef;
					result.b += (plane->material.color.b * current_light.color.b) * coef;
				}
			}
		}
	}

	return result;
}
示例#6
0
Color traceRay(Ray pixel_ray, Scene* s, Camera* c, int depth)
{
	Color pixelColor;
	Ray normal[2];
	pixelColor.r = 0;
	pixelColor.g = 0;
	pixelColor.b = 0;

	Sphere *closestSphere = NULL;
	Plane *closestPlane = NULL;
	float closestSphereDist = fInfinity;
	float closestPlaneDist = fInfinity;

	if (depth <= 0) return {0,0,0};

	for (int i = 0; i < s->spheres.size(); i++) {
		float dist = sphere_intersect(&s->spheres[i], &pixel_ray);
		if (dist != fInfinity) {
			if(closestSphereDist == fInfinity || 
				(closestSphereDist > dist && abs(closestSphereDist-dist) > 0.0001))
			{
				closestSphereDist = dist;
				closestSphere = &s->spheres[i];
				Point intersection = add(pixel_ray.p0, mul(pixel_ray.dir, dist));
				Ray sphereNorm;
				sphereNorm.p0 = intersection;
				sphereNorm.dir = normalize(sub(intersection, closestSphere->center));
				normal[0] = sphereNorm;
			}
		}
	}

	for (int i = 0; i < s->planes.size(); i++) {
		float dist = plane_intersect(&s->planes[i], &pixel_ray);
		if (dist != fInfinity) {
			if(closestPlaneDist == fInfinity || 
				(closestPlaneDist > dist && abs(closestPlaneDist-dist) > 0.0001))
			{
				closestPlaneDist = dist;
				closestPlane = &s->planes[i];
				Point intersection = add(pixel_ray.p0, mul(pixel_ray.dir, dist));
				Ray planeNorm;
				planeNorm.p0 = intersection;
				planeNorm.dir = normalize(closestPlane->normal);
				normal[1] = planeNorm;
			}
		}
	}

	if (closestPlane != NULL && closestSphere != NULL) {
		if (closestPlaneDist < closestSphereDist) {
			closestSphere = NULL;
		} else 
			closestPlane = NULL;
	}

	if (closestPlane != NULL) {
		Color lambert = lambertian(normal[1], s, NULL, closestPlane);
		pixelColor.r = lambert.r;
		pixelColor.g = lambert.g;
		pixelColor.b = lambert.b;

		if(depth != 0)
		{
			if(closestPlane->material.transparency != 0.0)
			{
				Ray transRay;
				transRay.dir = pixel_ray.dir;
				transRay.p0 = mul(normal[1].p0, 1.01f);

				Color transparent = traceRay(transRay, s, c, depth-1);

				pixelColor.r = pixelColor.r * (1 - closestPlane->material.transparency) +
					transparent.r * closestPlane->material.transparency;
				pixelColor.g = pixelColor.g * (1 - closestPlane->material.transparency) +
					transparent.g * closestPlane->material.transparency;
				pixelColor.b = pixelColor.b * (1 - closestPlane->material.transparency) +
					transparent.b * closestPlane->material.transparency;
			}
			
			if(closestPlane->material.reflection != 0.0)
			{
				Ray reflRay = reflect(pixel_ray, normal[1]);
				Color reflection = traceRay( reflRay, s, c, depth-1 );

				pixelColor.r = pixelColor.r * (1 - closestPlane->material.reflection) +
					reflection.r * closestPlane->material.reflection;
				pixelColor.g = pixelColor.g * (1 - closestPlane->material.reflection) +
					reflection.g * closestPlane->material.reflection;
				pixelColor.b = pixelColor.b * (1 - closestPlane->material.reflection) +
					reflection.b * closestPlane->material.reflection;
			}
		}

	} else if (closestSphere != NULL) {
		Color lambert = lambertian(normal[0], s, closestSphere, NULL);
		pixelColor.r += lambert.r;
		pixelColor.g += lambert.g;
		pixelColor.b += lambert.b;

		if(depth != 0) 
		{
			if(closestSphere->material.transparency != 0.0)
			{
				Ray transRay;
				transRay.dir = pixel_ray.dir;
				transRay.p0 = normal[0].p0;

				Color transparent = traceRay(transRay, s, c, depth-1);
				
				pixelColor.r = pixelColor.r * (1 - closestSphere->material.transparency) +
					transparent.r * closestSphere->material.transparency;
				pixelColor.g = pixelColor.g * (1 - closestSphere->material.transparency) +
					transparent.g * closestSphere->material.transparency;
				pixelColor.b = pixelColor.b * (1 - closestSphere->material.transparency) +
					transparent.b * closestSphere->material.transparency;
			}

			if(closestSphere->material.reflection != 0.0)
			{
				Ray reflRay;
				reflRay = reflect(pixel_ray, normal[0]);

				Color reflection = traceRay(reflRay, s, c, depth-1);
				
				pixelColor.r = pixelColor.r * (1 - closestSphere->material.reflection) +
					reflection.r * closestSphere->material.reflection;
				pixelColor.g = pixelColor.g * (1 - closestSphere->material.reflection) +
					reflection.g * closestSphere->material.reflection;
				pixelColor.b = pixelColor.b * (1 - closestSphere->material.reflection) +
					reflection.b * closestSphere->material.reflection;
			}
		}
	}

	if(pixelColor.r > 1)
	{
		//printf("cut off red\n");
		pixelColor.r = 1.0;
	}
	if(pixelColor.g > 1)
	{
		//printf("cut off green\n");
		pixelColor.g = 1.0;
	}
	if(pixelColor.b > 1)
	{
		//printf("cut off blue\n");
		pixelColor.b = 1.0;
	}

	return pixelColor;
}
示例#7
0
// return 1 if this patch needs to be subdivided 
// ( triangles intersect the normal to the opposite direction)
// return 0 if ok
int EncQuadBezier::make_lam()
{
    VEC  nor, bend, hv0, hv1; // bend = bdir
    double  lam, h;
    int  i,j, m, sm,sp,s2, idx[4][2], sd, ii,jj,
         nsgn, nnsgn, cr,ncr; // booleans
    VEC  env[2][4]; // env[1]=(upper)=outer

	int  need_subdiv = 0; // return value

    for (i=0; i<d1; i++) 
        for (j=0; j<d1; j++) 
            lambda[i][j][0]= lambda[i][j][1]= 0;
    for (i=0; i<segu; i++) {
        for (j=0; j<segv; j++) {
            // normal at center determines which bilinear
            // to choose, eg +++ in all components means
            //  ubd ubd ubd = outer
            //  lbd lbd lbd = inner
            // determine diagonal:
            // curvature  - +
            //            + -
            VEC mid[2][2];

            for(m=0;m<DIM;m++) {
                mid[0][0][m] =(get_enc(1,i,j)[m]   + get_enc(0,i,j)[m])/2;
                mid[0][1][m] =(get_enc(1,i,j+1)[m] + get_enc(0,i,j+1)[m])/2;
                mid[1][0][m] =(get_enc(1,i+1,j)[m] + get_enc(0,i+1,j)[m])/2;
                mid[1][1][m] =(get_enc(1,i+1,j+1)[m] + get_enc(0,i+1,j+1)[m])/2;
            }

            for (m=0; m<DIM; m++) 
                bend[m] = mid[0][0][m]+mid[1][1][m]-mid[0][1][m]-mid[1][0][m];

            VVminus(mid[1][1],mid[0][0],hv0);
            VVminus(mid[0][1],mid[1][0],hv1);
            VVcross(hv0,hv1, nor);

            // if (crease >= 0)  // triangles |/| or flat
            h = VVmult(sup_nor[i][j],nor);
            if (h < 0) printf("h %lf\n",h);
            h = VVmult(bend,nor);
            cr = (h >=  0); // convex up in normal direction == cr=1

            cralong[i*(segv)+j] = cr; // record crease of bilinear

            // translation table 
            // 3 2
            // 0 1
            idx[0][0] = i; idx[0][1] = j;
            idx[1][0] = i+1; idx[1][1] = j;
            idx[2][0] = i+1; idx[2][1] = j+1;
            idx[3][0] = i; idx[3][1] = j+1;


            // quadrant of the normal decides on choice of bilinear
            // depends on whether the normal is "outward" pointing
            // bd[1]...[x]: x component larger
            for (m=0; m<DIM; m++) {
                nsgn = (nor[m] >= 0); // if 1 then want bd[1] -- except when
                // normal is inward pointing (cube)
                nnsgn = (nsgn+1)%2;
                for (sd=0; sd<4; sd++) {
                    // (nsgn=1) want upper bd in normal dir (env[1]..)
                    ii = idx[sd][0]; jj = idx[sd][1];
                    env[1][sd][m] = get_enc(nsgn,ii,jj)[m]; 
                    env[0][sd][m] = get_enc(nnsgn,ii,jj)[m];
                }
            }

            if(0) // draw the nor (put it in the center of the quad)
            {
                VEC center, sum;
                for(m=0;m<DIM;m++)
                {
                    // center of all four up-enclosure corners
                    center[m] = (env[1][0][m] + env[1][1][m] +
                                 env[1][2][m] + env[1][3][m])/4;
                }
                Normalize(nor);
                VVadd(1.0, center, 20, nor, sum);
                glDisable(GL_LIGHTING);
                glColor3f(0.3,0.0, 1.0);
                glBegin(GL_LINES);
                glVertex4dv(center);
                glVertex4dv(sum);
                glEnd();
                glEnable(GL_LIGHTING);
            }

            // compute lambdas based on crease orientation 
            // cr==1 for ridge 02 in normal direction 
            //       isect with  2 env[1] and 1 env[0]
            for (sd=0; sd<4; sd++) { // intersect with 3 total!

                ii = idx[sd][0]; jj = idx[sd][1];
                sp = (sd+1)%4; s2 = (sd+2)%4; sm = (sd+3)%4;
                ncr = (cr+1)%2;
                //  sm---s2
                //   |    |
                //  sd---sp

                lam = plane_intersect(sup_pt[ii][jj], sup_nor[ii][jj],
                    env[cr][sd], env[cr][sp], env[cr][s2]);

                // Why (cr) selection? if cr then q=nor same dir as bend, as
                // supnor  -- so compare with the two planes of the
                // triangles (cr) and then with the other (ncr)
                //
                if (cr) { if (lam > lambda[ii][jj][1])  lambda[ii][jj][1] = lam;
                } else  { 
                    if (lam < lambda[ii][jj][0])  { lambda[ii][jj][0] = lam; }
                }

                if ((cr && (lam < -tol) ) || (ncr && (lam > tol)))
                {
                    printf("not ok 1 cr %d lam %lf iijj %d %d \n",cr,lam,ii,jj);
					need_subdiv = 1; // need to be subdivied
                }
                    if(debugchoice & EXTTRI) {
                        set_color(ncr);
                        if(!ncr)  // only outter enclosure
                        DrawTri(env[cr][sd], env[cr][sp], env[cr][s2]);
                    }


                //else printf(" ok 1 \n");
                lam = plane_intersect(sup_pt[ii][jj], sup_nor[ii][jj], 
                    env[cr][sd], env[cr][s2], env[cr][sm]);
                if (cr) { if (lam > lambda[ii][jj][1])  lambda[ii][jj][1] = lam;
                } else  { 
                    if (lam < lambda[ii][jj][0]){ lambda[ii][jj][0] = lam; }
                }

                if ((cr && (lam < -tol) ) || (ncr && (lam > tol)))
                {
                    printf("not ok 2 cr %d lam %lf iijj %d %d \n",cr,lam,ii,jj);
					need_subdiv = 1; // need to be subdivied
                }
                    if(debugchoice & EXTTRI) {
                        set_color(ncr);
                        if(!ncr)  // only outter enclosure
                        DrawTri(env[cr][sd], env[cr][s2], env[cr][sm]);
                    }
                //else printf(" ok 2 \n");

                lam = plane_intersect(sup_pt[ii][jj], sup_nor[ii][jj], 
                    env[ncr][sd], env[ncr][sp], env[ncr][sm]);
                if (ncr) { if (lam > lambda[ii][jj][1])  lambda[ii][jj][1] = lam;
                } else  { 
                    if (lam < lambda[ii][jj][0]) { lambda[ii][jj][0] = lam; }
                }


                if ((cr && (lam > tol) ) || (ncr && (lam < -tol)))
                {
                    printf("not ok 3 cr %d lam %lf iijj %d %d \n",cr,lam,ii,jj);
					need_subdiv = 1; // need to be subdivied
                }
                    if(debugchoice & EXTTRI) {
                        set_color(cr);
                        if(!cr)  // only outter enclosure
                        DrawTri(env[ncr][sd], env[ncr][sp], env[ncr][sm]);
                    }

                //else printf(" ok 3 \n");

                cr = ncr;  // crease opposite at next point
            }
            // w...[1] has pos (in normal dir) values
        }
    }

	// subdivide the patch if needed
	return need_subdiv;
}