Shadowrun: Awakened 29 September 2011 - Build 871
grid.cpp
Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2010 Intel Corporation.  All Rights Reserved.
00003 
00004     This file is part of Threading Building Blocks.
00005 
00006     Threading Building Blocks is free software; you can redistribute it
00007     and/or modify it under the terms of the GNU General Public License
00008     version 2 as published by the Free Software Foundation.
00009 
00010     Threading Building Blocks is distributed in the hope that it will be
00011     useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00012     of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with Threading Building Blocks; if not, write to the Free Software
00017     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019     As a special exception, you may use this file as part of a free software
00020     library without restriction.  Specifically, if other files instantiate
00021     templates or use macros or inline functions from this file, or you compile
00022     this file and link it with other files to produce an executable, this
00023     file does not by itself cause the resulting executable to be covered by
00024     the GNU General Public License.  This exception does not however
00025     invalidate any other reasons why the executable file might be covered by
00026     the GNU General Public License.
00027 */
00028 
00029 /*
00030     The original source for this example is
00031     Copyright (c) 1994-2008 John E. Stone
00032     All rights reserved.
00033 
00034     Redistribution and use in source and binary forms, with or without
00035     modification, are permitted provided that the following conditions
00036     are met:
00037     1. Redistributions of source code must retain the above copyright
00038        notice, this list of conditions and the following disclaimer.
00039     2. Redistributions in binary form must reproduce the above copyright
00040        notice, this list of conditions and the following disclaimer in the
00041        documentation and/or other materials provided with the distribution.
00042     3. The name of the author may not be used to endorse or promote products
00043        derived from this software without specific prior written permission.
00044 
00045     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00046     OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00047     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00048     ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00049     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00050     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00051     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00052     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00053     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00054     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00055     SUCH DAMAGE.
00056 */
00057 
00058 /*
00059  * grid.c - spatial subdivision efficiency structures
00060  *
00061  * $Id: grid.cpp,v 1.2 2007-02-22 17:54:15 dpoulsen Exp $
00062  * 
00063  */
00064 
00065 #include "machine.h"
00066 #include "types.h"
00067 #include "macros.h"
00068 #include "vector.h"
00069 #include "intersect.h"
00070 #include "util.h"
00071 
00072 #define GRID_PRIVATE
00073 #include "grid.h"
00074 
00075 #ifndef cbrt
00076 #define     cbrt(x)     ((x) > 0.0 ? pow((double)(x), 1.0/3.0) : \
00077                           ((x) < 0.0 ? -pow((double)-(x), 1.0/3.0) : 0.0))
00078 
00079 #define     qbrt(x)     ((x) > 0.0 ? pow((double)(x), 1.0/4.0) : \
00080                           ((x) < 0.0 ? -pow((double)-(x), 1.0/4.0) : 0.0))
00081 
00082 #endif
00083 
00084 static object_methods grid_methods = {
00085   (void (*)(void *, void *))(grid_intersect),
00086   (void (*)(void *, void *, void *, void *))(NULL),
00087   grid_bbox, 
00088   grid_free 
00089 };
00090 
00091 object * newgrid(int xsize, int ysize, int zsize, vector min, vector max) {
00092   grid * g;
00093 
00094   g = (grid *) rt_getmem(sizeof(grid));
00095   memset(g, 0, sizeof(grid));  
00096 
00097   g->methods = &grid_methods;
00098   g->id = new_objectid();
00099 
00100   g->xsize = xsize;
00101   g->ysize = ysize;
00102   g->zsize = zsize;
00103 
00104   g->min = min;
00105   g->max = max;
00106 
00107   VSub(&g->max, &g->min, &g->voxsize);
00108   g->voxsize.x /= (flt) g->xsize; 
00109   g->voxsize.y /= (flt) g->ysize; 
00110   g->voxsize.z /= (flt) g->zsize; 
00111 
00112   g->cells = (objectlist **) rt_getmem(xsize*ysize*zsize*sizeof(objectlist *));
00113   memset(g->cells, 0, xsize*ysize*zsize * sizeof(objectlist *));
00114 
00115 /* fprintf(stderr, "New grid, size: %8d %8d %8d\n", g->xsize, g->ysize, g->zsize); */
00116 
00117   return (object *) g;
00118 }
00119 
00120 static int grid_bbox(void * obj, vector * min, vector * max) {
00121   grid * g = (grid *) obj;
00122  
00123   *min = g->min;
00124   *max = g->max;
00125 
00126   return 1;
00127 }
00128 
00129 static void grid_free(void * v) {
00130   int i, numvoxels;
00131   grid * g = (grid *) v;
00132  
00133   /* loop through all voxels and free the object lists */
00134   numvoxels = g->xsize * g->ysize * g->zsize; 
00135   for (i=0; i<numvoxels; i++) {
00136     objectlist * lcur, * lnext;
00137 
00138     lcur = g->cells[i];
00139     while (lcur != NULL) {
00140       lnext = lcur->next;
00141       free(lcur);
00142     }
00143   }
00144 
00145   /* free the grid cells */ 
00146   free(g->cells);
00147 
00148   /* free all objects on the grid object list */
00149   free_objects(g->objects);   
00150 
00151   free(g);
00152 }
00153 
00154 static void globalbound(object ** rootlist, vector * gmin, vector * gmax) {
00155   vector min, max;
00156   object * cur;
00157 
00158   if (*rootlist == NULL)  /* don't bound non-existant objects */
00159     return;
00160 
00161   gmin->x =  FHUGE;   gmin->y =  FHUGE;   gmin->z =  FHUGE;
00162   gmax->x = -FHUGE;   gmax->y = -FHUGE;   gmax->z = -FHUGE;
00163 
00164   cur=*rootlist;
00165   while (cur != NULL)  {  /* Go! */
00166     min.x = -FHUGE; min.y = -FHUGE; min.z = -FHUGE;
00167     max.x =  FHUGE; max.y =  FHUGE; max.z =  FHUGE;
00168 
00169     if (cur->methods->bbox((void *) cur, &min, &max)) {
00170       gmin->x = MYMIN( gmin->x , min.x);
00171       gmin->y = MYMIN( gmin->y , min.y);
00172       gmin->z = MYMIN( gmin->z , min.z);
00173 
00174       gmax->x = MYMAX( gmax->x , max.x);
00175       gmax->y = MYMAX( gmax->y , max.y);
00176       gmax->z = MYMAX( gmax->z , max.z);
00177     }
00178 
00179     cur=(object *)cur->nextobj;
00180   }
00181 }
00182 
00183 
00184 static int cellbound(grid *g, gridindex *index, vector * cmin, vector * cmax) {
00185   vector min, max, cellmin, cellmax;
00186   objectlist * cur;
00187   int numinbounds = 0;
00188 
00189   cur = g->cells[index->z*g->xsize*g->ysize + index->y*g->xsize + index->x]; 
00190 
00191   if (cur == NULL)  /* don't bound non-existant objects */
00192     return 0;
00193 
00194   cellmin.x = voxel2x(g, index->x); 
00195   cellmin.y = voxel2y(g, index->y); 
00196   cellmin.z = voxel2z(g, index->z); 
00197 
00198   cellmax.x = cellmin.x + g->voxsize.x;
00199   cellmax.y = cellmin.y + g->voxsize.y;
00200   cellmax.z = cellmin.z + g->voxsize.z;
00201 
00202   cmin->x =  FHUGE;   cmin->y =  FHUGE;   cmin->z =  FHUGE;
00203   cmax->x = -FHUGE;   cmax->y = -FHUGE;   cmax->z = -FHUGE;
00204 
00205   while (cur != NULL)  {  /* Go! */
00206     min.x = -FHUGE; min.y = -FHUGE; min.z = -FHUGE;
00207     max.x =  FHUGE; max.y =  FHUGE; max.z =  FHUGE;
00208 
00209     if (cur->obj->methods->bbox((void *) cur->obj, &min, &max)) {
00210       if ((min.x >= cellmin.x) && (max.x <= cellmax.x) &&
00211           (min.y >= cellmin.y) && (max.y <= cellmax.y) &&
00212           (min.z >= cellmin.z) && (max.z <= cellmax.z)) {
00213       
00214         cmin->x = MYMIN( cmin->x , min.x);
00215         cmin->y = MYMIN( cmin->y , min.y);
00216         cmin->z = MYMIN( cmin->z , min.z);
00217 
00218         cmax->x = MYMAX( cmax->x , max.x);
00219         cmax->y = MYMAX( cmax->y , max.y);
00220         cmax->z = MYMAX( cmax->z , max.z);
00221       
00222         numinbounds++;
00223       }
00224     }
00225 
00226     cur=cur->next;
00227   }
00228  
00229   /* in case we get a 0.0 sized axis on the cell bounds, we'll */
00230   /* use the original cell bounds */
00231   if ((cmax->x - cmin->x) < EPSILON) {
00232     cmax->x += EPSILON;
00233     cmin->x -= EPSILON;
00234   }
00235   if ((cmax->y - cmin->y) < EPSILON) {
00236     cmax->y += EPSILON;
00237     cmin->y -= EPSILON;
00238   }
00239   if ((cmax->z - cmin->z) < EPSILON) {
00240     cmax->z += EPSILON;
00241     cmin->z -= EPSILON;
00242   }
00243 
00244   return numinbounds;
00245 }
00246 
00247 static int countobj(object * root) {
00248   object * cur;     /* counts the number of objects on a list */
00249   int numobj;
00250 
00251   numobj=0;
00252   cur=root;
00253 
00254   while (cur != NULL) {
00255     cur=(object *)cur->nextobj;
00256     numobj++;
00257   }
00258   return numobj;
00259 }
00260 
00261 static int countobjlist(objectlist * root) {
00262   objectlist * cur;
00263   int numobj;
00264 
00265   numobj=0; 
00266   cur = root;
00267 
00268   while (cur != NULL) {
00269     cur = cur->next;
00270     numobj++;
00271   }
00272   return numobj;
00273 }
00274 
00275 int engrid_scene(object ** list) {
00276   grid * g;
00277   int numobj, numcbrt;
00278   vector gmin, gmax;
00279   gridindex index;
00280  
00281   if (*list == NULL)
00282     return 0;
00283 
00284   numobj = countobj(*list);
00285 
00286 fprintf(stderr, "Scene contains %d bounded objects.\n", numobj);
00287 
00288   if (numobj > 16) {
00289     numcbrt = (int) cbrt(4*numobj);
00290     globalbound(list, &gmin, &gmax);
00291 
00292     g = (grid *) newgrid(numcbrt, numcbrt, numcbrt, gmin, gmax);
00293     engrid_objlist(g, list);
00294 
00295     numobj = countobj(*list);
00296     g->nextobj = *list;
00297     *list = (object *) g;
00298 
00299     /* now create subgrids.. */
00300     for (index.z=0; index.z<g->zsize; index.z++) {
00301       for (index.y=0; index.y<g->ysize; index.y++) {
00302         for (index.x=0; index.x<g->xsize; index.x++) {
00303           engrid_cell(g, &index);
00304         }
00305       }
00306     } 
00307   }
00308 
00309   return 1;
00310 }
00311 
00312 
00313 void engrid_objlist(grid * g, object ** list) {
00314   object * cur, * next, **prev;
00315 
00316   if (*list == NULL) 
00317     return;
00318   
00319   prev = list; 
00320   cur = *list;
00321 
00322   while (cur != NULL) {
00323     next = (object *)cur->nextobj;
00324 
00325     if (engrid_object(g, cur)) 
00326       *prev = next;
00327     else 
00328       prev = (object **) &cur->nextobj;
00329 
00330     cur = next;
00331   } 
00332 }
00333 
00334 static int engrid_cell(grid * gold, gridindex *index) {
00335   vector gmin, gmax, gsize;
00336   flt len;
00337   int numobj, numcbrt, xs, ys, zs;
00338   grid * g;
00339   objectlist **list;
00340   objectlist * newobj;
00341 
00342   list = &gold->cells[index->z*gold->xsize*gold->ysize + 
00343                      index->y*gold->xsize  + index->x];
00344 
00345   if (*list == NULL)
00346     return 0;
00347 
00348   numobj =  cellbound(gold, index, &gmin, &gmax);
00349 
00350   VSub(&gmax, &gmin, &gsize);
00351   len = 1.0 / (MYMAX( MYMAX(gsize.x, gsize.y), gsize.z ));
00352   gsize.x *= len;  
00353   gsize.y *= len;  
00354   gsize.z *= len;  
00355 
00356   if (numobj > 16) {
00357     numcbrt = (int) cbrt(2*numobj); 
00358     
00359     xs = (int) ((flt) numcbrt * gsize.x);
00360     if (xs < 1) xs = 1;
00361     ys = (int) ((flt) numcbrt * gsize.y);
00362     if (ys < 1) ys = 1;
00363     zs = (int) ((flt) numcbrt * gsize.z);
00364     if (zs < 1) zs = 1;
00365 
00366     g = (grid *) newgrid(xs, ys, zs, gmin, gmax);
00367     engrid_objectlist(g, list);
00368 
00369     newobj = (objectlist *) rt_getmem(sizeof(objectlist));    
00370     newobj->obj = (object *) g;
00371     newobj->next = *list;
00372     *list = newobj;
00373 
00374     g->nextobj = gold->objects;
00375     gold->objects = (object *) g;
00376   }
00377 
00378   return 1;
00379 }
00380 
00381 static int engrid_objectlist(grid * g, objectlist ** list) {
00382   objectlist * cur, * next, **prev;
00383   int numsucceeded = 0; 
00384 
00385   if (*list == NULL) 
00386     return 0;
00387   
00388   prev = list; 
00389   cur = *list;
00390 
00391   while (cur != NULL) {
00392     next = cur->next;
00393 
00394     if (engrid_object(g, cur->obj)) {
00395       *prev = next;
00396       free(cur);
00397       numsucceeded++;
00398     }
00399     else {
00400       prev = &cur->next;
00401     }
00402 
00403     cur = next;
00404   } 
00405 
00406   return numsucceeded;
00407 }
00408 
00409 
00410 
00411 static int engrid_object(grid * g, object * obj) {
00412   vector omin, omax; 
00413   gridindex low, high;
00414   int x, y, z, zindex, yindex, voxindex;
00415   objectlist * tmp;
00416  
00417   if (obj->methods->bbox(obj, &omin, &omax)) { 
00418     if (!pos2grid(g, &omin, &low) || !pos2grid(g, &omax, &high)) {
00419       return 0; /* object is not wholly contained in the grid */
00420     }
00421   }
00422   else {
00423     return 0; /* object is unbounded */
00424   }
00425 
00426   /* add the object to the complete list of objects in the grid */
00427   obj->nextobj = g->objects;
00428   g->objects = obj;
00429 
00430   /* add this object to all voxels it inhabits */
00431   for (z=low.z; z<=high.z; z++) {
00432     zindex = z * g->xsize * g->ysize;
00433     for (y=low.y; y<=high.y; y++) {
00434       yindex = y * g->xsize;
00435       for (x=low.x; x<=high.x; x++) {
00436         voxindex = x + yindex + zindex; 
00437         tmp = (objectlist *) rt_getmem(sizeof(objectlist));
00438         tmp->next = g->cells[voxindex];
00439         tmp->obj = obj;
00440         g->cells[voxindex] = tmp;
00441       }
00442     }
00443   }
00444  
00445   return 1;
00446 }
00447 
00448 static int pos2grid(grid * g, vector * pos, gridindex * index) {
00449   index->x = (int) ((pos->x - g->min.x) / g->voxsize.x);
00450   index->y = (int) ((pos->y - g->min.y) / g->voxsize.y);
00451   index->z = (int) ((pos->z - g->min.z) / g->voxsize.z);
00452   
00453   if (index->x == g->xsize)
00454     index->x--;
00455   if (index->y == g->ysize)
00456     index->y--;
00457   if (index->z == g->zsize)
00458     index->z--;
00459 
00460   if (index->x < 0 || index->x > g->xsize ||
00461       index->y < 0 || index->y > g->ysize ||
00462       index->z < 0 || index->z > g->zsize) 
00463     return 0;
00464 
00465   if (pos->x < g->min.x || pos->x > g->max.x ||
00466       pos->y < g->min.y || pos->y > g->max.y ||
00467       pos->z < g->min.z || pos->z > g->max.z) 
00468     return 0; 
00469 
00470   return 1;
00471 }
00472 
00473 
00474 /* the real thing */
00475 static void grid_intersect(grid * g, ray * ry) {
00476   flt tnear, tfar, offset;
00477   vector curpos, tmax, tdelta, pdeltaX, pdeltaY, pdeltaZ, nXp, nYp, nZp;
00478   gridindex curvox, step, out; 
00479   int voxindex;
00480   objectlist * cur;
00481 
00482   if (ry->flags & RT_RAY_FINISHED)
00483     return;
00484 
00485   if (!grid_bounds_intersect(g, ry, &tnear, &tfar))
00486     return;
00487  
00488   if (ry->maxdist < tnear)
00489     return;
00490  
00491   curpos = Raypnt(ry, tnear); 
00492   pos2grid(g, &curpos, &curvox);
00493   offset = tnear;
00494 
00495   /* Setup X iterator stuff */
00496   if (fabs(ry->d.x) < EPSILON) {
00497     tmax.x = FHUGE;
00498     tdelta.x = 0.0;
00499     step.x = 0;
00500     out.x = 0; /* never goes out of bounds on this axis */
00501   }
00502   else if (ry->d.x < 0.0) {
00503     tmax.x = offset + ((voxel2x(g, curvox.x) - curpos.x) / ry->d.x); 
00504     tdelta.x = g->voxsize.x / - ry->d.x;
00505     step.x = out.x = -1;
00506   }
00507   else {
00508     tmax.x = offset + ((voxel2x(g, curvox.x + 1) - curpos.x) / ry->d.x);
00509     tdelta.x = g->voxsize.x / ry->d.x;
00510     step.x = 1;
00511     out.x = g->xsize;
00512   }
00513 
00514   /* Setup Y iterator stuff */
00515   if (fabs(ry->d.y) < EPSILON) {
00516     tmax.y = FHUGE;
00517     tdelta.y = 0.0; 
00518     step.y = 0;
00519     out.y = 0; /* never goes out of bounds on this axis */
00520   }
00521   else if (ry->d.y < 0.0) {
00522     tmax.y = offset + ((voxel2y(g, curvox.y) - curpos.y) / ry->d.y);
00523     tdelta.y = g->voxsize.y / - ry->d.y;
00524     step.y = out.y = -1;
00525   }
00526   else {
00527     tmax.y = offset + ((voxel2y(g, curvox.y + 1) - curpos.y) / ry->d.y);
00528     tdelta.y = g->voxsize.y / ry->d.y;
00529     step.y = 1;
00530     out.y = g->ysize;
00531   }
00532 
00533   /* Setup Z iterator stuff */
00534   if (fabs(ry->d.z) < EPSILON) {
00535     tmax.z = FHUGE;
00536     tdelta.z = 0.0; 
00537     step.z = 0;
00538     out.z = 0; /* never goes out of bounds on this axis */
00539   }
00540   else if (ry->d.z < 0.0) {
00541     tmax.z = offset + ((voxel2z(g, curvox.z) - curpos.z) / ry->d.z);
00542     tdelta.z = g->voxsize.z / - ry->d.z;
00543     step.z = out.z = -1;
00544   }
00545   else {
00546     tmax.z = offset + ((voxel2z(g, curvox.z + 1) - curpos.z) / ry->d.z);
00547     tdelta.z = g->voxsize.z / ry->d.z;
00548     step.z = 1;
00549     out.z = g->zsize;
00550   }
00551 
00552   pdeltaX = ry->d;
00553   VScale(&pdeltaX, tdelta.x);
00554   pdeltaY = ry->d;
00555   VScale(&pdeltaY, tdelta.y);
00556   pdeltaZ = ry->d;
00557   VScale(&pdeltaZ, tdelta.z);
00558 
00559   nXp = Raypnt(ry, tmax.x);
00560   nYp = Raypnt(ry, tmax.y);
00561   nZp = Raypnt(ry, tmax.z);
00562 
00563   voxindex = curvox.z*g->xsize*g->ysize + curvox.y*g->xsize + curvox.x; 
00564   while (1) {
00565     if (tmax.x < tmax.y && tmax.x < tmax.z) {
00566       cur = g->cells[voxindex];
00567       while (cur != NULL) {
00568         if (ry->mbox[cur->obj->id] != ry->serial) {
00569           ry->mbox[cur->obj->id] = ry->serial; 
00570           cur->obj->methods->intersect(cur->obj, ry);
00571         }
00572         cur = cur->next;
00573       }
00574       curvox.x += step.x;
00575       if (ry->maxdist < tmax.x || curvox.x == out.x) 
00576         break; 
00577       voxindex += step.x;
00578       tmax.x += tdelta.x;
00579       curpos = nXp;
00580       nXp.x += pdeltaX.x;
00581       nXp.y += pdeltaX.y;
00582       nXp.z += pdeltaX.z;
00583     }
00584     else if (tmax.z < tmax.y) {
00585       cur = g->cells[voxindex];
00586       while (cur != NULL) {
00587         if (ry->mbox[cur->obj->id] != ry->serial) {
00588           ry->mbox[cur->obj->id] = ry->serial; 
00589           cur->obj->methods->intersect(cur->obj, ry);
00590         }
00591         cur = cur->next;
00592       }
00593       curvox.z += step.z;
00594       if (ry->maxdist < tmax.z || curvox.z == out.z) 
00595         break;
00596       voxindex += step.z*g->xsize*g->ysize;
00597       tmax.z += tdelta.z;
00598       curpos = nZp;
00599       nZp.x += pdeltaZ.x;
00600       nZp.y += pdeltaZ.y;
00601       nZp.z += pdeltaZ.z;
00602     }
00603     else {
00604       cur = g->cells[voxindex];
00605       while (cur != NULL) {
00606         if (ry->mbox[cur->obj->id] != ry->serial) {
00607           ry->mbox[cur->obj->id] = ry->serial; 
00608           cur->obj->methods->intersect(cur->obj, ry);
00609         }
00610         cur = cur->next;
00611       }
00612       curvox.y += step.y;
00613       if (ry->maxdist < tmax.y || curvox.y == out.y) 
00614         break;
00615       voxindex += step.y*g->xsize;
00616       tmax.y += tdelta.y;
00617       curpos = nYp;
00618       nYp.x += pdeltaY.x;
00619       nYp.y += pdeltaY.y;
00620       nYp.z += pdeltaY.z;
00621     }
00622 
00623     if (ry->flags & RT_RAY_FINISHED)
00624       break;
00625   }
00626 }
00627 
00628 static void voxel_intersect(grid * g, ray * ry, int voxindex) {
00629   objectlist * cur;
00630 
00631   cur = g->cells[voxindex];
00632   while (cur != NULL) {
00633     cur->obj->methods->intersect(cur->obj, ry);
00634     cur = cur->next;
00635   }
00636 }
00637 
00638 static int grid_bounds_intersect(grid * g, ray * ry, flt *near, flt *far) {
00639   flt a, tx1, tx2, ty1, ty2, tz1, tz2;
00640   flt tnear, tfar;
00641 
00642   tnear= -FHUGE;
00643   tfar= FHUGE;
00644 
00645   if (ry->d.x == 0.0) {
00646     if ((ry->o.x < g->min.x) || (ry->o.x > g->max.x)) return 0;
00647   }
00648   else {
00649     tx1 = (g->min.x - ry->o.x) / ry->d.x;
00650     tx2 = (g->max.x - ry->o.x) / ry->d.x;
00651     if (tx1 > tx2) { a=tx1; tx1=tx2; tx2=a; }
00652     if (tx1 > tnear) tnear=tx1;
00653     if (tx2 < tfar)   tfar=tx2;
00654   }
00655   if (tnear > tfar) return 0;
00656   if (tfar < 0.0) return 0;
00657 
00658   if (ry->d.y == 0.0) {
00659     if ((ry->o.y < g->min.y) || (ry->o.y > g->max.y)) return 0;
00660   }
00661   else {
00662     ty1 = (g->min.y - ry->o.y) / ry->d.y;
00663     ty2 = (g->max.y - ry->o.y) / ry->d.y;
00664     if (ty1 > ty2) { a=ty1; ty1=ty2; ty2=a; }
00665     if (ty1 > tnear) tnear=ty1;
00666     if (ty2 < tfar)   tfar=ty2;
00667   }
00668   if (tnear > tfar) return 0;
00669   if (tfar < 0.0) return 0;
00670 
00671   if (ry->d.z == 0.0) {
00672     if ((ry->o.z < g->min.z) || (ry->o.z > g->max.z)) return 0;
00673   }
00674   else {
00675     tz1 = (g->min.z - ry->o.z) / ry->d.z;
00676     tz2 = (g->max.z - ry->o.z) / ry->d.z;
00677     if (tz1 > tz2) { a=tz1; tz1=tz2; tz2=a; }
00678     if (tz1 > tnear) tnear=tz1;
00679     if (tz2 < tfar)   tfar=tz2;
00680   }
00681   if (tnear > tfar) return 0;
00682   if (tfar < 0.0) return 0;
00683 
00684   *near = tnear;
00685   *far = tfar; 
00686   return 1;
00687 }

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net