viewing source for "objects.c"
last commit
commit 2fcfc3b2e8e18bd4ab667b82d939cc2ba9b6a5d3
Date: Sun Jan 13 09:25:46 2008 -0800
source code
001: #include <math.h>
002: #include <stdlib.h>
003: #include "objects.h"
004: #include "vector.h"
005:
006: #define EPSILON 0.001f
007:
008: intersection* box_isect( primitive *prim, ray *r ) {
009: intersection *isect = NULL;
010: box_data *data = (box_data*)prim->data;
011: float dist[] = {-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f};
012: vector ip[6];
013: vector v2;
014: float rc;
015:
016: char hit = 0;
017: float distance = 0.0f;
018: int index = 0;
019: char inside = 0;
020: int i;
021:
022: vect_copy( &v2, &data->point );
023: vect_add( &v2, &data->size );
024:
025: if( r->dir->x != 0.0f ) {
026: rc = 1.0f / r->dir->x;
027: dist[0] = (data->point.x - r->origin->x) * rc;
028: dist[3] = (v2.x - r->origin->x) * rc;
029: }
030: if( r->dir->y != 0.0f ) {
031: rc = 1.0f / r->dir->y;
032: dist[1] = (data->point.y - r->origin->y) * rc;
033: dist[4] = (v2.y - r->origin->y) * rc;
034: }
035: if( r->dir->z != 0.0f ) {
036: rc = 1.0f / r->dir->z;
037: dist[2] = (data->point.z - r->origin->z) * rc;
038: dist[5] = (v2.z - r->origin->z) * rc;
039: }
040:
041: for( i = 0; i < 6; i++ ) {
042: if( dist[i] > 0.0f ) {
043: vect_copy( &ip[i], r->dir );
044: vect_multf( &ip[i], dist[i] );
045: vect_add( &ip[i], r->origin );
046:
047: if( ip[i].x > (data->point.x - EPSILON) &&
048: ip[i].x < (v2.x + EPSILON) &&
049: ip[i].y > (data->point.y - EPSILON) &&
050: ip[i].y < (v2.y + EPSILON) &&
051: ip[i].z > (data->point.z - EPSILON) &&
052: ip[i].z < (v2.z + EPSILON) ) {
053:
054: if( !hit || dist[i] < distance ) {
055: hit = 1;
056: distance = dist[i];
057: index = i;
058: }
059: }
060: }
061: }
062:
063: if( hit ) {
064: if( prim->mat.is_refr ) {
065: switch( index ) {
066: case 0:
067: inside = r->dir->x < 0.0f ? 1 : 0;
068: break;
069: case 1:
070: inside = r->dir->y < 0.0f ? 1 : 0;
071: break;
072: case 2:
073: inside = r->dir->z < 0.0f ? 1 : 0;
074: break;
075: case 3:
076: inside = r->dir->x > 0.0f ? 1 : 0;
077: break;
078: case 4:
079: inside = r->dir->y > 0.0f ? 1 : 0;
080: break;
081: case 5:
082: inside = r->dir->z > 0.0f ? 1 : 0;
083: break;
084: default:
085: inside = 0;
086: }
087: }
088:
089: isect = (intersection*)malloc( sizeof( intersection ) );
090: isect->prim = prim;
091: isect->dist = distance;
092: isect->inside = inside;
093:
094: return isect;
095: }
096:
097: return NULL;
098: }
099:
100: void box_normal( primitive *box, vector *isect, vector *ret ) {
101: box_data *data = (box_data*)box->data;
102: float dist[6];
103: int best = 0, i;
104: float best_dist;
105:
106: dist[0] = fabsf( isect->x - data->point.x );
107: dist[1] = fabsf( isect->x - (data->point.x + data->size.x) );
108: dist[2] = fabsf( isect->y - data->point.y );
109: dist[3] = fabsf( isect->y - (data->point.y + data->size.y) );
110: dist[4] = fabsf( isect->z - data->point.z );
111: dist[5] = fabsf( isect->z - (data->point.z + data->size.z) );
112:
113: best_dist = dist[0];
114: for( i = 1; i < 6; i++ ) {
115: if( dist[i] < best_dist ) {
116: best_dist = dist[i];
117: best = i;
118: }
119: }
120:
121: if( best == 0 ) {
122: ret->x = -1.0f;
123: ret->y = 0.0f;
124: ret->z = 0.0f;
125: }
126: else if( best == 1 ) {
127: ret->x = 1.0f;
128: ret->y = 0.0f;
129: ret->z = 0.0f;
130: }
131: else if( best == 2 ) {
132: ret->x = 0.0f;
133: ret->y = -1.0f;
134: ret->z = 0.0f;
135: }
136: else if( best == 3 ) {
137: ret->x = 0.0f;
138: ret->y = 1.0f;
139: ret->z = 0.0f;
140: }
141: else if( best == 4 ) {
142: ret->x = 0.0f;
143: ret->y = 0.0f;
144: ret->z = -1.0f;
145: }
146: else {
147: ret->x = 0.0f;
148: ret->y = 0.0f;
149: ret->z = 1.0f;
150: }
151: }
152:
153: intersection* sphere_isect( primitive *prim, ray *r ) {
154: intersection *isect;
155: vector v;
156: float b;
157: float det;
158: float dist = 0.0f;
159: int hit = 0;
160: int inside = 0;
161: float i1, i2;
162:
163: sphere_data *sphere = (sphere_data*)prim->data;
164:
165: vect_copy( &v, r->origin );
166: vect_sub( &v, &sphere->center );
167:
168: b = -(vect_dot( &v, r->dir ) );
169: det = (b*b) - vect_dot( &v, &v ) + (sphere->radius * sphere->radius);
170:
171: if( det > 0 ) {
172: det = sqrtf( det );
173: i1 = b - det;
174: i2 = b + det;
175: if( i2 > 0 ) {
176: if( i1 < 0 ) {
177: dist = i2;
178: hit = 1;
179: inside = 1;
180: }
181: else {
182: dist = i1;
183: hit = 1;
184: inside = 0;
185: }
186: }
187: }
188:
189: if( hit ) {
190: isect = (intersection*)malloc( sizeof(intersection) );
191: isect->prim = prim;
192: isect->dist = dist;
193: isect->inside = inside;
194:
195: return isect;
196: }
197: else {
198: return NULL;
199: }
200: }
201:
202: void sphere_normal( primitive *sphere, vector *v, vector *ret ) {
203: vect_copy( ret, v );
204: vect_sub( ret, &sphere->center );
205: vect_multf( ret, 1.0f / ((sphere_data*)sphere->data)->radius );
206: }
207:
208: intersection* plane_isect( primitive *prim, ray *r ) {
209: plane_data *data = (plane_data*)prim->data;
210: float d = vect_dot( &data->normal, r->dir );
211: float t;
212: intersection *isect = NULL;
213:
214: if( d < 0.0f ) {
215: t = -( vect_dot( &data->normal, r->origin ) + data->dist ) / d;
216:
217: if( t > 0.0f ) {
218: isect = (intersection*)malloc( sizeof( intersection ) );
219: isect->prim = prim;
220: isect->dist = t;
221: isect->inside = 0.0f;
222: return isect;
223: }
224: }
225:
226: return NULL;
227: }
228:
229: void plane_normal( primitive *plane, vector *v, vector *ret ) {
230: vect_copy( ret, &((plane_data*)plane->data)->normal );
231: }