Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

Winding.cpp

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 
00023 
00024 #include "stdafx.h"
00025 #include <assert.h>
00026 #include "qe3.h"
00027 #include "winding.h"
00028 
00029 #define BOGUS_RANGE 18000
00030 
00031 /*
00032 =============
00033 Plane_Equal
00034 =============
00035 */
00036 #define NORMAL_EPSILON  0.0001
00037 #define DIST_EPSILON    0.02
00038 
00039 int Plane_Equal(plane_t *a, plane_t *b, int flip)
00040 {
00041     vec3_t normal;
00042     float dist;
00043 
00044     if (flip) {
00045         normal[0] = - b->normal[0];
00046         normal[1] = - b->normal[1];
00047         normal[2] = - b->normal[2];
00048         dist = - b->dist;
00049     }
00050     else {
00051         normal[0] = b->normal[0];
00052         normal[1] = b->normal[1];
00053         normal[2] = b->normal[2];
00054         dist = b->dist;
00055     }
00056     if (
00057        fabs(a->normal[0] - normal[0]) < NORMAL_EPSILON
00058     && fabs(a->normal[1] - normal[1]) < NORMAL_EPSILON
00059     && fabs(a->normal[2] - normal[2]) < NORMAL_EPSILON
00060     && fabs(a->dist - dist) < DIST_EPSILON )
00061         return true;
00062     return false;
00063 }
00064 
00065 /*
00066 ============
00067 Plane_FromPoints
00068 ============
00069 */
00070 int Plane_FromPoints(vec3_t p1, vec3_t p2, vec3_t p3, plane_t *plane)
00071 {
00072     vec3_t v1, v2;
00073 
00074     VectorSubtract(p2, p1, v1);
00075     VectorSubtract(p3, p1, v2);
00076     //CrossProduct(v2, v1, plane->normal);
00077     CrossProduct(v1, v2, plane->normal);
00078     if (VectorNormalize(plane->normal) < 0.1) return false;
00079     plane->dist = DotProduct(p1, plane->normal);
00080     return true;
00081 }
00082 
00083 /*
00084 =================
00085 Point_Equal
00086 =================
00087 */
00088 int Point_Equal(vec3_t p1, vec3_t p2, float epsilon)
00089 {
00090     int i;
00091 
00092     for (i = 0; i < 3; i++)
00093     {
00094         if (fabs(p1[i] - p2[i]) > epsilon) return false;
00095     }
00096     return true;
00097 }
00098 
00099 
00100 /*
00101 =================
00102 Winding_BaseForPlane
00103 =================
00104 */
00105 winding_t *Winding_BaseForPlane (plane_t *p)
00106 {
00107     int     i, x;
00108     vec_t   max, v;
00109     vec3_t  org, vright, vup;
00110     winding_t   *w;
00111     
00112     // find the major axis
00113 
00114     max = -BOGUS_RANGE;
00115     x = -1;
00116     for (i=0 ; i<3; i++)
00117     {
00118         v = fabs(p->normal[i]);
00119         if (v > max)
00120         {
00121             x = i;
00122             max = v;
00123         }
00124     }
00125     if (x==-1)
00126         Error ("Winding_BaseForPlane: no axis found");
00127         
00128     VectorCopy (vec3_origin, vup);  
00129     switch (x)
00130     {
00131     case 0:
00132     case 1:
00133         vup[2] = 1;
00134         break;      
00135     case 2:
00136         vup[0] = 1;
00137         break;      
00138     }
00139 
00140 
00141     v = DotProduct (vup, p->normal);
00142     VectorMA (vup, -v, p->normal, vup);
00143     VectorNormalize (vup);
00144         
00145     VectorScale (p->normal, p->dist, org);
00146     
00147     CrossProduct (vup, p->normal, vright);
00148     
00149     VectorScale (vup, BOGUS_RANGE, vup);
00150     VectorScale (vright, BOGUS_RANGE, vright);
00151 
00152     // project a really big axis aligned box onto the plane
00153     w = Winding_Alloc (4);
00154     
00155     VectorSubtract (org, vright, w->points[0]);
00156     VectorAdd (w->points[0], vup, w->points[0]);
00157     
00158     VectorAdd (org, vright, w->points[1]);
00159     VectorAdd (w->points[1], vup, w->points[1]);
00160     
00161     VectorAdd (org, vright, w->points[2]);
00162     VectorSubtract (w->points[2], vup, w->points[2]);
00163     
00164     VectorSubtract (org, vright, w->points[3]);
00165     VectorSubtract (w->points[3], vup, w->points[3]);
00166     
00167     w->numpoints = 4;
00168     
00169     return w;   
00170 }
00171 
00172 /*
00173 ==================
00174 Winding_Alloc
00175 ==================
00176 */
00177 winding_t *Winding_Alloc (int points)
00178 {
00179     winding_t   *w;
00180     int         size;
00181     
00182     if (points > MAX_POINTS_ON_WINDING)
00183         Error ("Winding_Alloc: %i points", points);
00184     
00185     size = (int)((winding_t *)0)->points[points];
00186     w = (winding_t*) malloc (size);
00187     memset (w, 0, size);
00188     w->maxpoints = points;
00189     
00190     return w;
00191 }
00192 
00193 
00194 void Winding_Free (winding_t *w)
00195 {
00196     free(w);
00197 }
00198 
00199 
00200 /*
00201 ==================
00202 Winding_Clone
00203 ==================
00204 */
00205 winding_t *Winding_Clone(winding_t *w)
00206 {
00207     int         size;
00208     winding_t   *c;
00209     
00210     size = (int)((winding_t *)0)->points[w->numpoints];
00211     c = (winding_t*)qmalloc (size);
00212     memcpy (c, w, size);
00213     return c;
00214 }
00215 
00216 /*
00217 ==================
00218 ReverseWinding
00219 ==================
00220 */
00221 winding_t *Winding_Reverse(winding_t *w)
00222 {
00223     int         i;
00224     winding_t   *c;
00225 
00226     c = Winding_Alloc(w->numpoints);
00227     for (i = 0; i < w->numpoints; i++)
00228     {
00229         VectorCopy (w->points[w->numpoints-1-i], c->points[i]);
00230     }
00231     c->numpoints = w->numpoints;
00232     return c;
00233 }
00234 
00235 
00236 /*
00237 ==============
00238 Winding_RemovePoint
00239 ==============
00240 */
00241 void Winding_RemovePoint(winding_t *w, int point)
00242 {
00243     if (point < 0 || point >= w->numpoints)
00244         Error("Winding_RemovePoint: point out of range");
00245 
00246     if (point < w->numpoints-1)
00247     {
00248         memmove(&w->points[point], &w->points[point+1], (int)((winding_t *)0)->points[w->numpoints - point - 1]);
00249     }
00250     w->numpoints--;
00251 }
00252 
00253 /*
00254 =============
00255 Winding_InsertPoint
00256 =============
00257 */
00258 winding_t *Winding_InsertPoint(winding_t *w, vec3_t point, int spot)
00259 {
00260     int i, j;
00261     winding_t *neww;
00262 
00263     if (spot > w->numpoints)
00264     {
00265         Error("Winding_InsertPoint: spot > w->numpoints");
00266     } //end if
00267     if (spot < 0)
00268     {
00269         Error("Winding_InsertPoint: spot < 0");
00270     } //end if
00271     neww = Winding_Alloc(w->numpoints + 1);
00272     neww->numpoints = w->numpoints + 1;
00273     for (i = 0, j = 0; i < neww->numpoints; i++)
00274     {
00275         if (i == spot)
00276         {
00277             VectorCopy(point, neww->points[i]);
00278         }
00279         else
00280         {
00281             VectorCopy(w->points[j], neww->points[i]);
00282             j++;
00283         }
00284     }
00285     return neww;
00286 }
00287 
00288 /*
00289 ==============
00290 Winding_IsTiny
00291 ==============
00292 */
00293 #define EDGE_LENGTH 0.2
00294 
00295 int Winding_IsTiny (winding_t *w)
00296 {
00297     int     i, j;
00298     vec_t   len;
00299     vec3_t  delta;
00300     int     edges;
00301 
00302     edges = 0;
00303     for (i=0 ; i<w->numpoints ; i++)
00304     {
00305         j = i == w->numpoints - 1 ? 0 : i+1;
00306         VectorSubtract (w->points[j], w->points[i], delta);
00307         len = VectorLength (delta);
00308         if (len > EDGE_LENGTH)
00309         {
00310             if (++edges == 3)
00311                 return false;
00312         }
00313     }
00314     return true;
00315 }
00316 
00317 /*
00318 ==============
00319 Winding_IsHuge
00320 ==============
00321 */
00322 int Winding_IsHuge(winding_t *w)
00323 {
00324     int     i, j;
00325 
00326     for (i=0 ; i<w->numpoints ; i++)
00327     {
00328         for (j=0 ; j<3 ; j++)
00329             if (w->points[i][j] < -BOGUS_RANGE+1 || w->points[i][j] > BOGUS_RANGE-1)
00330                 return true;
00331     }
00332     return false;
00333 }
00334 
00335 /*
00336 =============
00337 Winding_PlanesConcave
00338 =============
00339 */
00340 #define WCONVEX_EPSILON     0.2
00341 
00342 int Winding_PlanesConcave(winding_t *w1, winding_t *w2,
00343                              vec3_t normal1, vec3_t normal2,
00344                              float dist1, float dist2)
00345 {
00346     int i;
00347 
00348     if (!w1 || !w2) return false;
00349 
00350     // check if one of the points of winding 1 is at the back of the plane of winding 2
00351     for (i = 0; i < w1->numpoints; i++)
00352     {
00353         if (DotProduct(normal2, w1->points[i]) - dist2 > WCONVEX_EPSILON) return true;
00354     }
00355     // check if one of the points of winding 2 is at the back of the plane of winding 1
00356     for (i = 0; i < w2->numpoints; i++)
00357     {
00358         if (DotProduct(normal1, w2->points[i]) - dist1 > WCONVEX_EPSILON) return true;
00359     }
00360 
00361     return false;
00362 }
00363 
00364 /*
00365 ==================
00366 Winding_Clip
00367 
00368 Clips the winding to the plane, returning the new winding on the positive side
00369 Frees the input winding.
00370 If keepon is true, an exactly on-plane winding will be saved, otherwise
00371 it will be clipped away.
00372 ==================
00373 */
00374 winding_t *Winding_Clip (winding_t *in, plane_t *split, qboolean keepon)
00375 {
00376     vec_t   dists[MAX_POINTS_ON_WINDING];
00377     int     sides[MAX_POINTS_ON_WINDING];
00378     int     counts[3];
00379     vec_t   dot;
00380     int     i, j;
00381     vec_t   *p1, *p2;
00382     vec3_t  mid;
00383     winding_t   *neww;
00384     int     maxpts;
00385     
00386     counts[0] = counts[1] = counts[2] = 0;
00387 
00388     // determine sides for each point
00389     for (i=0 ; i<in->numpoints ; i++)
00390     {
00391         dot = DotProduct (in->points[i], split->normal);
00392         dot -= split->dist;
00393         dists[i] = dot;
00394         if (dot > ON_EPSILON)
00395             sides[i] = SIDE_FRONT;
00396         else if (dot < -ON_EPSILON)
00397             sides[i] = SIDE_BACK;
00398         else
00399         {
00400             sides[i] = SIDE_ON;
00401         }
00402         counts[sides[i]]++;
00403     }
00404     sides[i] = sides[0];
00405     dists[i] = dists[0];
00406     
00407     if (keepon && !counts[0] && !counts[1])
00408         return in;
00409         
00410     if (!counts[0])
00411     {
00412         Winding_Free (in);
00413         return NULL;
00414     }
00415     if (!counts[1])
00416         return in;
00417     
00418     maxpts = in->numpoints+4;   // can't use counts[0]+2 because
00419                                 // of fp grouping errors
00420     neww = Winding_Alloc (maxpts);
00421         
00422     for (i=0 ; i<in->numpoints ; i++)
00423     {
00424         p1 = in->points[i];
00425         
00426         if (sides[i] == SIDE_ON)
00427         {
00428             VectorCopy (p1, neww->points[neww->numpoints]);
00429             neww->numpoints++;
00430             continue;
00431         }
00432     
00433         if (sides[i] == SIDE_FRONT)
00434         {
00435             VectorCopy (p1, neww->points[neww->numpoints]);
00436             neww->numpoints++;
00437         }
00438         
00439         if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
00440             continue;
00441             
00442         // generate a split point
00443         p2 = in->points[(i+1)%in->numpoints];
00444         
00445         dot = dists[i] / (dists[i]-dists[i+1]);
00446         for (j=0 ; j<3 ; j++)
00447         {   // avoid round off error when possible
00448             if (split->normal[j] == 1)
00449                 mid[j] = split->dist;
00450             else if (split->normal[j] == -1)
00451                 mid[j] = -split->dist;
00452             else
00453                 mid[j] = p1[j] + dot*(p2[j]-p1[j]);
00454         }
00455             
00456         VectorCopy (mid, neww->points[neww->numpoints]);
00457         neww->numpoints++;
00458     }
00459     
00460     if (neww->numpoints > maxpts)
00461         Error ("Winding_Clip: points exceeded estimate");
00462         
00463     // free the original winding
00464     Winding_Free (in);
00465     
00466     return neww;
00467 }
00468 
00469 /*
00470 =============
00471 Winding_SplitEpsilon
00472 
00473   split the input winding with the plane
00474   the input winding stays untouched
00475 =============
00476 */
00477 void Winding_SplitEpsilon (winding_t *in, vec3_t normal, double dist, 
00478                 vec_t epsilon, winding_t **front, winding_t **back)
00479 {
00480     vec_t   dists[MAX_POINTS_ON_WINDING+4];
00481     int     sides[MAX_POINTS_ON_WINDING+4];
00482     int     counts[3];
00483     vec_t   dot;
00484     int     i, j;
00485     vec_t   *p1, *p2;
00486     vec3_t  mid;
00487     winding_t   *f, *b;
00488     int     maxpts;
00489     
00490     counts[0] = counts[1] = counts[2] = 0;
00491 
00492     // determine sides for each point
00493     for (i = 0; i < in->numpoints; i++)
00494     {
00495         dot = DotProduct (in->points[i], normal);
00496         dot -= dist;
00497         dists[i] = dot;
00498         if (dot > epsilon)
00499             sides[i] = SIDE_FRONT;
00500         else if (dot < -epsilon)
00501             sides[i] = SIDE_BACK;
00502         else
00503         {
00504             sides[i] = SIDE_ON;
00505         }
00506         counts[sides[i]]++;
00507     }
00508     sides[i] = sides[0];
00509     dists[i] = dists[0];
00510     
00511     *front = *back = NULL;
00512 
00513     if (!counts[0])
00514     {
00515         *back = Winding_Clone(in);
00516         return;
00517     }
00518     if (!counts[1])
00519     {
00520         *front = Winding_Clone(in);
00521         return;
00522     }
00523 
00524     maxpts = in->numpoints+4;   // cant use counts[0]+2 because
00525                                 // of fp grouping errors
00526 
00527     *front = f = Winding_Alloc (maxpts);
00528     *back = b = Winding_Alloc (maxpts);
00529         
00530     for (i = 0; i < in->numpoints; i++)
00531     {
00532         p1 = in->points[i];
00533         
00534         if (sides[i] == SIDE_ON)
00535         {
00536             VectorCopy (p1, f->points[f->numpoints]);
00537             f->numpoints++;
00538             VectorCopy (p1, b->points[b->numpoints]);
00539             b->numpoints++;
00540             continue;
00541         }
00542     
00543         if (sides[i] == SIDE_FRONT)
00544         {
00545             VectorCopy (p1, f->points[f->numpoints]);
00546             f->numpoints++;
00547         }
00548         if (sides[i] == SIDE_BACK)
00549         {
00550             VectorCopy (p1, b->points[b->numpoints]);
00551             b->numpoints++;
00552         }
00553 
00554         if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
00555             continue;
00556             
00557         // generate a split point
00558         p2 = in->points[(i+1)%in->numpoints];
00559         
00560         dot = dists[i] / (dists[i]-dists[i+1]);
00561         for (j = 0; j < 3; j++)
00562         {
00563             // avoid round off error when possible
00564             if (normal[j] == 1)
00565                 mid[j] = dist;
00566             else if (normal[j] == -1)
00567                 mid[j] = -dist;
00568             else
00569                 mid[j] = p1[j] + dot*(p2[j]-p1[j]);
00570         }
00571             
00572         VectorCopy (mid, f->points[f->numpoints]);
00573         f->numpoints++;
00574         VectorCopy (mid, b->points[b->numpoints]);
00575         b->numpoints++;
00576     }
00577     
00578     if (f->numpoints > maxpts || b->numpoints > maxpts)
00579         Error ("Winding_Clip: points exceeded estimate");
00580     if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING)
00581         Error ("Winding_Clip: MAX_POINTS_ON_WINDING");
00582 }
00583 
00584 /*
00585 =============
00586 Winding_TryMerge
00587 
00588 If two windings share a common edge and the edges that meet at the
00589 common points are both inside the other polygons, merge them
00590 
00591 Returns NULL if the windings couldn't be merged, or the new winding.
00592 The originals will NOT be freed.
00593 
00594 if keep is true no points are ever removed
00595 =============
00596 */
00597 #define CONTINUOUS_EPSILON  0.005
00598 
00599 winding_t *Winding_TryMerge(winding_t *f1, winding_t *f2, vec3_t planenormal, int keep)
00600 {
00601     vec_t       *p1, *p2, *p3, *p4, *back;
00602     winding_t   *newf;
00603     int         i, j, k, l;
00604     vec3_t      normal, delta;
00605     vec_t       dot;
00606     qboolean    keep1, keep2;
00607     
00608 
00609     //
00610     // find a common edge
00611     //  
00612     p1 = p2 = NULL; // stop compiler warning
00613     j = 0;          // 
00614     
00615     for (i = 0; i < f1->numpoints; i++)
00616     {
00617         p1 = f1->points[i];
00618         p2 = f1->points[(i+1) % f1->numpoints];
00619         for (j = 0; j < f2->numpoints; j++)
00620         {
00621             p3 = f2->points[j];
00622             p4 = f2->points[(j+1) % f2->numpoints];
00623             for (k = 0; k < 3; k++)
00624             {
00625                 if (fabs(p1[k] - p4[k]) > 0.1)//EQUAL_EPSILON) //ME
00626                     break;
00627                 if (fabs(p2[k] - p3[k]) > 0.1)//EQUAL_EPSILON) //ME
00628                     break;
00629             } //end for
00630             if (k==3)
00631                 break;
00632         } //end for
00633         if (j < f2->numpoints)
00634             break;
00635     } //end for
00636     
00637     if (i == f1->numpoints)
00638         return NULL;            // no matching edges
00639 
00640     //
00641     // check slope of connected lines
00642     // if the slopes are colinear, the point can be removed
00643     //
00644     back = f1->points[(i+f1->numpoints-1)%f1->numpoints];
00645     VectorSubtract (p1, back, delta);
00646     CrossProduct (planenormal, delta, normal);
00647     VectorNormalize (normal);
00648     
00649     back = f2->points[(j+2)%f2->numpoints];
00650     VectorSubtract (back, p1, delta);
00651     dot = DotProduct (delta, normal);
00652     if (dot > CONTINUOUS_EPSILON)
00653         return NULL;            // not a convex polygon
00654     keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON);
00655     
00656     back = f1->points[(i+2)%f1->numpoints];
00657     VectorSubtract (back, p2, delta);
00658     CrossProduct (planenormal, delta, normal);
00659     VectorNormalize (normal);
00660 
00661     back = f2->points[(j+f2->numpoints-1)%f2->numpoints];
00662     VectorSubtract (back, p2, delta);
00663     dot = DotProduct (delta, normal);
00664     if (dot > CONTINUOUS_EPSILON)
00665         return NULL;            // not a convex polygon
00666     keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON);
00667 
00668     //
00669     // build the new polygon
00670     //
00671     newf = Winding_Alloc (f1->numpoints + f2->numpoints);
00672     
00673     // copy first polygon
00674     for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints)
00675     {
00676         if (!keep && k==(i+1)%f1->numpoints && !keep2)
00677             continue;
00678         
00679         VectorCopy (f1->points[k], newf->points[newf->numpoints]);
00680         newf->numpoints++;
00681     }
00682     
00683     // copy second polygon
00684     for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints)
00685     {
00686         if (!keep && l==(j+1)%f2->numpoints && !keep1)
00687             continue;
00688         VectorCopy (f2->points[l], newf->points[newf->numpoints]);
00689         newf->numpoints++;
00690     }
00691 
00692     return newf;
00693 }
00694 
00695 /*
00696 ============
00697 Winding_Plane
00698 ============
00699 */
00700 void Winding_Plane (winding_t *w, vec3_t normal, double *dist)
00701 {
00702     vec3_t v1, v2;
00703     int i;
00704 
00705     //find two vectors each longer than 0.5 units
00706     for (i = 0; i < w->numpoints; i++)
00707     {
00708         VectorSubtract(w->points[(i+1) % w->numpoints], w->points[i], v1);
00709         VectorSubtract(w->points[(i+2) % w->numpoints], w->points[i], v2);
00710         if (VectorLength(v1) > 0.5 && VectorLength(v2) > 0.5) break;
00711     }
00712     CrossProduct(v2, v1, normal);
00713     VectorNormalize(normal);
00714     *dist = DotProduct(w->points[0], normal);
00715 }
00716 
00717 /*
00718 =============
00719 Winding_Area
00720 =============
00721 */
00722 float Winding_Area (winding_t *w)
00723 {
00724     int     i;
00725     vec3_t  d1, d2, cross;
00726     float   total;
00727 
00728     total = 0;
00729     for (i=2 ; i<w->numpoints ; i++)
00730     {
00731         VectorSubtract (w->points[i-1], w->points[0], d1);
00732         VectorSubtract (w->points[i], w->points[0], d2);
00733         CrossProduct (d1, d2, cross);
00734         total += 0.5 * VectorLength ( cross );
00735     }
00736     return total;
00737 }
00738 
00739 /*
00740 =============
00741 Winding_Bounds
00742 =============
00743 */
00744 void Winding_Bounds (winding_t *w, vec3_t mins, vec3_t maxs)
00745 {
00746     vec_t   v;
00747     int     i,j;
00748 
00749     mins[0] = mins[1] = mins[2] = 99999;
00750     maxs[0] = maxs[1] = maxs[2] = -99999;
00751 
00752     for (i=0 ; i<w->numpoints ; i++)
00753     {
00754         for (j=0 ; j<3 ; j++)
00755         {
00756             v = w->points[i][j];
00757             if (v < mins[j])
00758                 mins[j] = v;
00759             if (v > maxs[j])
00760                 maxs[j] = v;
00761         }
00762     }
00763 }
00764 
00765 
00766 /*
00767 =================
00768 Winding_PointInside
00769 =================
00770 */
00771 int Winding_PointInside(winding_t *w, plane_t *plane, vec3_t point, float epsilon)
00772 {
00773     int i;
00774     vec3_t dir, normal, pointvec;
00775 
00776     for (i = 0; i < w->numpoints; i++)
00777     {
00778         VectorSubtract(w->points[(i+1) % w->numpoints], w->points[i], dir);
00779         VectorSubtract(point, w->points[i], pointvec);
00780         //
00781         CrossProduct(dir, plane->normal, normal);
00782         //
00783         if (DotProduct(pointvec, normal) < -epsilon) return false;
00784     }
00785     return true;
00786 }
00787 
00788 /*
00789 =================
00790 Winding_VectorIntersect
00791 =================
00792 */
00793 int Winding_VectorIntersect(winding_t *w, plane_t *plane, vec3_t p1, vec3_t p2, float epsilon)
00794 {
00795     float front, back, frac;
00796     vec3_t mid;
00797 
00798     front = DotProduct(p1, plane->normal) - plane->dist;
00799     back = DotProduct(p2, plane->normal) - plane->dist;
00800     //if both points at the same side of the plane
00801     if (front < -epsilon && back < -epsilon) return false;
00802     if (front > epsilon && back > epsilon) return false;
00803     //get point of intersection with winding plane
00804     if (fabs(front-back) < 0.001)
00805     {
00806         VectorCopy(p2, mid);
00807     }
00808     else
00809     {
00810         frac = front/(front-back);
00811         mid[0] = p1[0] + (p2[0] - p1[0]) * frac;
00812         mid[1] = p1[1] + (p2[1] - p1[1]) * frac;
00813         mid[2] = p1[2] + (p2[2] - p1[2]) * frac;
00814     }
00815     return Winding_PointInside(w, plane, mid, epsilon);
00816 }
00817 

Generated on Thu Aug 25 12:38:43 2005 for Quake III Arena by  doxygen 1.3.9.1