All pastes #2104243 Raw Edit

Mine

public text v1 · immutable
#2104243 ·published 2012-01-20 02:26 UTC
rendered paste body
#include <stdio.h>
#include <math.h>

typedef char bool;
#define FALSE 0
#define TRUE 1

typedef float vec_t;
typedef vec_t vec3_t[3];
typedef vec_t vec4_t[4];
/* plane is the unit normal [0-2] and the distance from pos [3], point on plane can be derived by multiplying the normal by the distance. */
typedef vec4_t plane_t;

typedef struct sphere_s
{
	vec3_t pos;
	vec_t radius;
} sphere_t;

typedef struct line_s
{
	vec3_t pos;
	vec3_t dir;
} line_t;

typedef line_t ray_t;

#define EPSILON 0.00000001f

void Vec3Copy(vec3_t r, vec3_t a)
{
	r[0] = a[0];
	r[1] = a[1];
	r[2] = a[2];
}

vec_t DotProduct3(vec3_t a, vec3_t b)
{
	return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}

void CrossProduct3(vec3_t r, vec3_t a, vec3_t b)
{
	r[0] = a[1] * b[2] - a[2] * b[1];
	r[1] = a[2] * b[0] - a[0] * b[2];
	r[2] = a[0] * b[1] - a[1] * b[0];
}

void Vec3Add(vec3_t r, vec3_t a, vec3_t b)
{
	r[0] = a[0] + b[0];
	r[1] = a[1] + b[1];
	r[2] = a[2] + b[2];
}

void Vec3Subtract(vec3_t r, vec3_t a, vec3_t b)
{
	r[0] = a[0] - b[0];
	r[1] = a[1] - b[1];
	r[2] = a[2] - b[2];
}

void Vec3Scale(vec3_t r, vec_t s, vec3_t a)
{
	r[0] = s * a[0];
	r[1] = s * a[1];
	r[2] = s * a[2];
}

vec_t Vec3Length(vec3_t a)
{
	return (float)sqrt((double)DotProduct3(a,a));
}

void Vec3Normalize(vec3_t a)
{
	vec_t length = Vec3Length(a);
	
	if (length < EPSILON)
	{
		return;
	}
		
	Vec3Scale(a, 1.0f/Vec3Length(a), a);
}

bool LinePlaneIntersection(line_t line, plane_t plane, vec_t *distance)
{
	vec_t u;
	vec3_t pointOnPlane;
	vec3_t w;
	        
        u = DotProduct3(line.dir, plane);
        
        if (fabs(u) < EPSILON)
        {
		return FALSE;
	}
	
	Vec3Scale(pointOnPlane, plane[3], plane);
	
	Vec3Subtract(w, pointOnPlane, line.pos);

	*distance = DotProduct3(plane, w) / u;

	return TRUE;
}

bool RayPlaneIntersection(ray_t ray, plane_t plane, vec_t *distance)
{
	bool result = LinePlaneIntersection(ray, plane, distance);
	
	if (!result || (*distance < 0.0f))
		return FALSE;
		
	return TRUE;
}

bool RaySphereIntersection(ray_t ray, sphere_t sphere, vec_t *distance)
{
	vec3_t s2ro;
	vec_t a, b, c, dd, d, q, t0, t1;
	
	Vec3Subtract(s2ro, ray.pos, sphere.pos);
	a = DotProduct3(ray.dir, ray.dir);
	b = 2.0f * DotProduct3(ray.dir, s2ro);
	c = DotProduct3(s2ro, s2ro) - (sphere.radius * sphere.radius);

	dd = b * b - 4.0f * a * c;
	if (dd < 0)
	{
		return FALSE;
	}
	
	d = (float)sqrt((double)(dd));
	
	if (b < 0)
	{
		d = -d;
	}
	
	q = (d - b) / 2.0f;
	
	t0 = q / a;
	t1 = c / q;
	
	if (t0 > t1)
	{
		vec_t swap = t0;
		t0 = t1;
		t1 = swap;
	}
	
	if (t1 < 0)
	{
		return FALSE;
	}
	
	if (t0 < 0)
	{
		*distance = t1;
	}
	else
	{
		*distance = t0;
	}

	return TRUE;	
}

int main(int argc, char *argv[])
{
	plane_t plane;
	sphere_t sphere, sphere2;
	vec3_t cameraPos, cameraFacing;
	vec3_t lightDir;
	char *gradient = "@8OCoc:. ";
	
	int x, y;
	
	plane[0] = 0.0f;
	plane[1] = 1.0f;
	plane[2] = 0.0f;
	plane[3] = 0.0f;
	Vec3Normalize(plane);
	
	sphere.pos[0] = 0.0f;
	sphere.pos[1] = 1.0f;
	sphere.pos[2] = 0.0f;
	sphere.radius = 1.0f;
	
	sphere2.pos[0] = 0.0f;
	sphere2.pos[1] = 3.5f;
	sphere2.pos[2] = 0.0f;
	sphere2.radius = 1.0f;

	cameraPos[0] = 0.0f;
	cameraPos[1] = 1.0f;
	cameraPos[2] = 4.0f;
	
	cameraFacing[0] = 0.0f;
	cameraFacing[1] = 0.0f;
	cameraFacing[2] = -1.0f;
	
	lightDir[0] = 0.0f;
	lightDir[1] = 1.0f;
	lightDir[2] = 0.0f;
	Vec3Normalize(lightDir);
	
	for (y = 0; y < 50; y++)
	{
		for (x = 0; x < 80; x++)
		{
			ray_t sample;
			vec_t far = 999999.0f, distance;
			vec3_t normal;
			vec_t brightness = 1.0;
			int hitid=0;
			
			Vec3Copy(sample.pos, cameraPos);
			sample.dir[0] = cameraFacing[0] + (vec_t)(x - 40) / 40.0f;
			sample.dir[1] = cameraFacing[1] + (vec_t)(25 - y) / 25.0f;
			sample.dir[2] = cameraFacing[2];
			
			Vec3Normalize(sample.dir);
			
			if (RayPlaneIntersection(sample, plane, &distance))
			{
				if (far > distance)
				{
					hitid = 1;
					Vec3Copy(normal, plane);
					far = distance;
				}
			}
			
			if (RaySphereIntersection(sample, sphere, &distance))
			{
				if (far > distance)
				{
					Vec3Scale(normal, distance, sample.dir);
					Vec3Add(normal, normal, sample.pos);
					Vec3Subtract(normal, normal, sphere.pos);
					Vec3Normalize(normal);
					hitid = 2;
					far = distance;
					//printf("%f %f %f,", normal[0], normal[1], normal[2]);
				}
			}

			if (RaySphereIntersection(sample, sphere2, &distance))
			{
				if (far > distance)
				{
					Vec3Scale(normal, distance, sample.dir);
					Vec3Add(normal, normal, sample.pos);
					Vec3Subtract(normal, normal, sphere2.pos);
					Vec3Normalize(normal);
					hitid = 2;
					far = distance;
					//printf("%f %f %f,", normal[0], normal[1], normal[2]);
				}
			}
						
			if (hitid)
			{
				vec3_t localLightDir;
				Vec3Scale(localLightDir, -1.0f, lightDir);
				brightness = DotProduct3(normal, localLightDir);
				if (brightness < 0.0f)
					brightness = 0.0f;
				if (brightness > 1.0f)
					brightness = 1.0f;
			}
			
			printf("%c", gradient[(int)(brightness * 8.0f)]);
		/*	
			switch(hitid)
			{
				case 1:
					printf("X");
					break;
				case 2:
					printf("O");
					break;
				default:
					printf(" ");
					break;
			}
		*/
		}
		
		printf("\n");
	}
}