viewing source for "objects.c"

last commit

commit 2fcfc3b2e8e18bd4ab667b82d939cc2ba9b6a5d3 Author: Andrew Rader <andrew.r.rader@gmail.com> Date: Sun Jan 13 09:25:46 2008 -0800
Initial Commit

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: }