Example #1
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;
}
Example #2
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;
}
void b3GpuRaycast::castRaysHost(const b3AlignedObjectArray<b3RayInfo>& rays,	b3AlignedObjectArray<b3RayHit>& hitResults,
		int numBodies,const struct b3RigidBodyCL* bodies, int numCollidables,const struct b3Collidable* collidables, const struct b3GpuNarrowPhaseInternalData* narrowphaseData)
{

//	return castRays(rays,hitResults,numBodies,bodies,numCollidables,collidables);

	B3_PROFILE("castRaysHost");
	for (int r=0;r<rays.size();r++)
	{
		b3Vector3 rayFrom = rays[r].m_from;
		b3Vector3 rayTo = rays[r].m_to;
		float hitFraction = hitResults[r].m_hitFraction;

		int hitBodyIndex= -1;
		b3Vector3 hitNormal;

		for (int b=0;b<numBodies;b++)
		{
				
			const b3Vector3& pos = bodies[b].m_pos;
			const b3Quaternion& orn = bodies[b].m_quat;
			
			switch (collidables[bodies[b].m_collidableIdx].m_shapeType)
			{
			case SHAPE_SPHERE:
				{
					b3Scalar radius = collidables[bodies[b].m_collidableIdx].m_radius;
					if (sphere_intersect(pos,  radius, rayFrom, rayTo,hitFraction))
					{
						hitBodyIndex = b;
						b3Vector3 hitPoint;
						hitPoint.setInterpolate3(rays[r].m_from, rays[r].m_to,hitFraction);
						hitNormal = (hitPoint-bodies[b].m_pos).normalize();
					}
				}
			case SHAPE_CONVEX_HULL:
				{

					b3Transform convexWorldTransform;
					convexWorldTransform.setIdentity();
					convexWorldTransform.setOrigin(bodies[b].m_pos);
					convexWorldTransform.setRotation(bodies[b].m_quat);
					b3Transform convexWorld2Local = convexWorldTransform.inverse();

					b3Vector3 rayFromLocal = convexWorld2Local(rayFrom);
					b3Vector3 rayToLocal = convexWorld2Local(rayTo);
					
					
					int shapeIndex = collidables[bodies[b].m_collidableIdx].m_shapeIndex;
					const b3ConvexPolyhedronCL& poly = narrowphaseData->m_convexPolyhedra[shapeIndex];
					if (rayConvex(rayFromLocal, rayToLocal,poly,narrowphaseData->m_convexFaces, hitFraction, hitNormal))
					{
						hitBodyIndex = b;
					}

					
					break;
				}
			default:
				{
					static bool once=true;
					if (once)
					{
						once=false;
						b3Warning("Raytest: unsupported shape type\n");
					}
				}
			}
		}
		if (hitBodyIndex>=0)
		{

			hitResults[r].m_hitFraction = hitFraction;
			hitResults[r].m_hitPoint.setInterpolate3(rays[r].m_from, rays[r].m_to,hitFraction);
			hitResults[r].m_hitNormal = hitNormal;
			hitResults[r].m_hitBody = hitBodyIndex;
		}

	}
}