![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
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.