ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

normal.c
Go to the documentation of this file.
00001 /*
00002 ** License Applicability. Except to the extent portions of this file are
00003 ** made subject to an alternative license as permitted in the SGI Free
00004 ** Software License B, Version 1.1 (the "License"), the contents of this
00005 ** file are subject only to the provisions of the License. You may not use
00006 ** this file except in compliance with the License. You may obtain a copy
00007 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
00008 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
00009 **
00010 ** http://oss.sgi.com/projects/FreeB
00011 **
00012 ** Note that, as provided in the License, the Software is distributed on an
00013 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
00014 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
00015 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
00016 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
00017 **
00018 ** Original Code. The Original Code is: OpenGL Sample Implementation,
00019 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
00020 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
00021 ** Copyright in any portions created by third parties is as indicated
00022 ** elsewhere herein. All Rights Reserved.
00023 **
00024 ** Additional Notice Provisions: The application programming interfaces
00025 ** established by SGI in conjunction with the Original Code are The
00026 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
00027 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
00028 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
00029 ** Window System(R) (Version 1.3), released October 19, 1998. This software
00030 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
00031 ** published by SGI, but has not been independently verified as being
00032 ** compliant with the OpenGL(R) version 1.2.1 Specification.
00033 **
00034 */
00035 /*
00036 ** Author: Eric Veach, July 1994.
00037 **
00038 */
00039 
00040 #include "gluos.h"
00041 #include "mesh.h"
00042 #include "tess.h"
00043 #include "normal.h"
00044 #include <math.h>
00045 #include <assert.h>
00046 
00047 #define TRUE 1
00048 #define FALSE 0
00049 
00050 #define Dot(u,v)    (u[0]*v[0] + u[1]*v[1] + u[2]*v[2])
00051 
00052 #if 0
00053 static void Normalize( GLdouble v[3] )
00054 {
00055   GLdouble len = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
00056 
00057   assert( len > 0 );
00058   len = sqrt( len );
00059   v[0] /= len;
00060   v[1] /= len;
00061   v[2] /= len;
00062 }
00063 #endif
00064 
00065 #undef  ABS
00066 #define ABS(x)  ((x) < 0 ? -(x) : (x))
00067 
00068 static int LongAxis( GLdouble v[3] )
00069 {
00070   int i = 0;
00071 
00072   if( ABS(v[1]) > ABS(v[0]) ) { i = 1; }
00073   if( ABS(v[2]) > ABS(v[i]) ) { i = 2; }
00074   return i;
00075 }
00076 
00077 static void ComputeNormal( GLUtesselator *tess, GLdouble norm[3] )
00078 {
00079   GLUvertex *v, *v1, *v2;
00080   GLdouble c, tLen2, maxLen2;
00081   GLdouble maxVal[3], minVal[3], d1[3], d2[3], tNorm[3];
00082   GLUvertex *maxVert[3], *minVert[3];
00083   GLUvertex *vHead = &tess->mesh->vHead;
00084   int i;
00085 
00086   maxVal[0] = maxVal[1] = maxVal[2] = -2 * GLU_TESS_MAX_COORD;
00087   minVal[0] = minVal[1] = minVal[2] = 2 * GLU_TESS_MAX_COORD;
00088 
00089   for( v = vHead->next; v != vHead; v = v->next ) {
00090     for( i = 0; i < 3; ++i ) {
00091       c = v->coords[i];
00092       if( c < minVal[i] ) { minVal[i] = c; minVert[i] = v; }
00093       if( c > maxVal[i] ) { maxVal[i] = c; maxVert[i] = v; }
00094     }
00095   }
00096 
00097   /* Find two vertices separated by at least 1/sqrt(3) of the maximum
00098    * distance between any two vertices
00099    */
00100   i = 0;
00101   if( maxVal[1] - minVal[1] > maxVal[0] - minVal[0] ) { i = 1; }
00102   if( maxVal[2] - minVal[2] > maxVal[i] - minVal[i] ) { i = 2; }
00103   if( minVal[i] >= maxVal[i] ) {
00104     /* All vertices are the same -- normal doesn't matter */
00105     norm[0] = 0; norm[1] = 0; norm[2] = 1;
00106     return;
00107   }
00108 
00109   /* Look for a third vertex which forms the triangle with maximum area
00110    * (Length of normal == twice the triangle area)
00111    */
00112   maxLen2 = 0;
00113   v1 = minVert[i];
00114   v2 = maxVert[i];
00115   d1[0] = v1->coords[0] - v2->coords[0];
00116   d1[1] = v1->coords[1] - v2->coords[1];
00117   d1[2] = v1->coords[2] - v2->coords[2];
00118   for( v = vHead->next; v != vHead; v = v->next ) {
00119     d2[0] = v->coords[0] - v2->coords[0];
00120     d2[1] = v->coords[1] - v2->coords[1];
00121     d2[2] = v->coords[2] - v2->coords[2];
00122     tNorm[0] = d1[1]*d2[2] - d1[2]*d2[1];
00123     tNorm[1] = d1[2]*d2[0] - d1[0]*d2[2];
00124     tNorm[2] = d1[0]*d2[1] - d1[1]*d2[0];
00125     tLen2 = tNorm[0]*tNorm[0] + tNorm[1]*tNorm[1] + tNorm[2]*tNorm[2];
00126     if( tLen2 > maxLen2 ) {
00127       maxLen2 = tLen2;
00128       norm[0] = tNorm[0];
00129       norm[1] = tNorm[1];
00130       norm[2] = tNorm[2];
00131     }
00132   }
00133 
00134   if( maxLen2 <= 0 ) {
00135     /* All points lie on a single line -- any decent normal will do */
00136     norm[0] = norm[1] = norm[2] = 0;
00137     norm[LongAxis(d1)] = 1;
00138   }
00139 }
00140 
00141 
00142 static void CheckOrientation( GLUtesselator *tess )
00143 {
00144   GLdouble area;
00145   GLUface *f, *fHead = &tess->mesh->fHead;
00146   GLUvertex *v, *vHead = &tess->mesh->vHead;
00147   GLUhalfEdge *e;
00148 
00149   /* When we compute the normal automatically, we choose the orientation
00150    * so that the the sum of the signed areas of all contours is non-negative.
00151    */
00152   area = 0;
00153   for( f = fHead->next; f != fHead; f = f->next ) {
00154     e = f->anEdge;
00155     if( e->winding <= 0 ) continue;
00156     do {
00157       area += (e->Org->s - e->Dst->s) * (e->Org->t + e->Dst->t);
00158       e = e->Lnext;
00159     } while( e != f->anEdge );
00160   }
00161   if( area < 0 ) {
00162     /* Reverse the orientation by flipping all the t-coordinates */
00163     for( v = vHead->next; v != vHead; v = v->next ) {
00164       v->t = - v->t;
00165     }
00166     tess->tUnit[0] = - tess->tUnit[0];
00167     tess->tUnit[1] = - tess->tUnit[1];
00168     tess->tUnit[2] = - tess->tUnit[2];
00169   }
00170 }
00171 
00172 #ifdef FOR_TRITE_TEST_PROGRAM
00173 #include <stdlib.h>
00174 extern int RandomSweep;
00175 #define S_UNIT_X    (RandomSweep ? (2*drand48()-1) : 1.0)
00176 #define S_UNIT_Y    (RandomSweep ? (2*drand48()-1) : 0.0)
00177 #else
00178 #if defined(SLANTED_SWEEP)
00179 /* The "feature merging" is not intended to be complete.  There are
00180  * special cases where edges are nearly parallel to the sweep line
00181  * which are not implemented.  The algorithm should still behave
00182  * robustly (ie. produce a reasonable tesselation) in the presence
00183  * of such edges, however it may miss features which could have been
00184  * merged.  We could minimize this effect by choosing the sweep line
00185  * direction to be something unusual (ie. not parallel to one of the
00186  * coordinate axes).
00187  */
00188 #define S_UNIT_X    0.50941539564955385 /* Pre-normalized */
00189 #define S_UNIT_Y    0.86052074622010633
00190 #else
00191 #define S_UNIT_X    1.0
00192 #define S_UNIT_Y    0.0
00193 #endif
00194 #endif
00195 
00196 /* Determine the polygon normal and project vertices onto the plane
00197  * of the polygon.
00198  */
00199 void __gl_projectPolygon( GLUtesselator *tess )
00200 {
00201   GLUvertex *v, *vHead = &tess->mesh->vHead;
00202   GLdouble norm[3];
00203   GLdouble *sUnit, *tUnit;
00204   int i, computedNormal = FALSE;
00205 
00206   norm[0] = tess->normal[0];
00207   norm[1] = tess->normal[1];
00208   norm[2] = tess->normal[2];
00209   if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) {
00210     ComputeNormal( tess, norm );
00211     computedNormal = TRUE;
00212   }
00213   sUnit = tess->sUnit;
00214   tUnit = tess->tUnit;
00215   i = LongAxis( norm );
00216 
00217 #if defined(FOR_TRITE_TEST_PROGRAM) || defined(TRUE_PROJECT)
00218   /* Choose the initial sUnit vector to be approximately perpendicular
00219    * to the normal.
00220    */
00221   Normalize( norm );
00222 
00223   sUnit[i] = 0;
00224   sUnit[(i+1)%3] = S_UNIT_X;
00225   sUnit[(i+2)%3] = S_UNIT_Y;
00226 
00227   /* Now make it exactly perpendicular */
00228   w = Dot( sUnit, norm );
00229   sUnit[0] -= w * norm[0];
00230   sUnit[1] -= w * norm[1];
00231   sUnit[2] -= w * norm[2];
00232   Normalize( sUnit );
00233 
00234   /* Choose tUnit so that (sUnit,tUnit,norm) form a right-handed frame */
00235   tUnit[0] = norm[1]*sUnit[2] - norm[2]*sUnit[1];
00236   tUnit[1] = norm[2]*sUnit[0] - norm[0]*sUnit[2];
00237   tUnit[2] = norm[0]*sUnit[1] - norm[1]*sUnit[0];
00238   Normalize( tUnit );
00239 #else
00240   /* Project perpendicular to a coordinate axis -- better numerically */
00241   sUnit[i] = 0;
00242   sUnit[(i+1)%3] = S_UNIT_X;
00243   sUnit[(i+2)%3] = S_UNIT_Y;
00244 
00245   tUnit[i] = 0;
00246   tUnit[(i+1)%3] = (norm[i] > 0) ? -S_UNIT_Y : S_UNIT_Y;
00247   tUnit[(i+2)%3] = (norm[i] > 0) ? S_UNIT_X : -S_UNIT_X;
00248 #endif
00249 
00250   /* Project the vertices onto the sweep plane */
00251   for( v = vHead->next; v != vHead; v = v->next ) {
00252     v->s = Dot( v->coords, sUnit );
00253     v->t = Dot( v->coords, tUnit );
00254   }
00255   if( computedNormal ) {
00256     CheckOrientation( tess );
00257   }
00258 }

Generated on Sat May 26 2012 04:22:20 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.