nurb_norm.c

Go to the documentation of this file.
00001 /*                     N U R B _ N O R M . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1991-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** @addtogroup nurb */
00023 /*@{*/
00024 /** @file nurb_norm.c
00025  *      Calulate and return the normal of a surface given the
00026  *      U,V parametric values.
00027  *
00028  *  Author -
00029  *      Paul R. Stay
00030  *
00031  *  Source -
00032  *     SECAD/VLD Computing Consortium, Bldg 394
00033  *     The U.S. Army Ballistic Research Laboratory
00034  *     Aberdeen Proving Ground, Maryland 21005
00035  *
00036  */
00037 /*@}*/
00038 
00039 #include "common.h"
00040 
00041 
00042 
00043 #include <stdio.h>
00044 #include "machine.h"
00045 #include "vmath.h"
00046 #include "raytrace.h"
00047 #include "nurb.h"
00048 
00049 /* If the order of the surface is linear either direction
00050  * than approximate it.
00051  */
00052 
00053 void
00054 rt_nurb_s_norm(struct face_g_snurb *srf, fastf_t u, fastf_t v, fastf_t *norm)
00055 {
00056         struct face_g_snurb *usrf, *vsrf;
00057         point_t uvec, vvec;
00058         fastf_t p;
00059         fastf_t se[4], ue[4], ve[4];
00060         int i;
00061 
00062         /* Case (linear, lienar) find the normal from the polygon */
00063         if( srf->order[0] == 2 && srf->order[1] == 2 )
00064         {
00065                 /* Find the correct span to get the normal */
00066                 rt_nurb_s_eval( srf, u, v, se);
00067 
00068                 p = 0.0;
00069                 for( i = 0; i < srf->u.k_size -1; i++)
00070                 {
00071                         if ( srf->u.knots[i] <= u
00072                                 && u < srf->u.knots[i+1] )
00073                         {
00074                                 p = srf->u.knots[i];
00075 
00076                                 if (u == p)
00077                                         p = srf->u.knots[i+1];
00078                                 if ( u == p && i > 1)
00079                                         p = srf->u.knots[i-1];
00080                         }
00081                 }
00082 
00083                 rt_nurb_s_eval( srf, p, v, ue);
00084 
00085                 p = 0.0;
00086                 for( i = 0; i < srf->v.k_size -1; i++)
00087                 {
00088                         if ( srf->v.knots[i] < v
00089                                 && srf->v.knots[i+1] )
00090                         {
00091                                 p = srf->v.knots[i];
00092                                 if (v == p)
00093                                         p = srf->v.knots[i+1];
00094                                 if ( v == p && i > 1)
00095                                         p = srf->v.knots[i-1];
00096                         }
00097                 }
00098 
00099                 rt_nurb_s_eval( srf, u, p, ve);
00100 
00101                 if( RT_NURB_IS_PT_RATIONAL(srf->pt_type))
00102                 {
00103                         ue[0] = ue[0] / ue[3];
00104                         ue[1] = ue[1] / ue[3];
00105                         ue[2] = ue[2] / ue[3];
00106                         ue[3] = ue[3] / ue[3];
00107 
00108                         ve[0] = ve[0] / ve[3];
00109                         ve[1] = ve[1] / ve[3];
00110                         ve[2] = ve[2] / ve[3];
00111                         ve[3] = ve[3] / ve[3];
00112 
00113                 }
00114 
00115                 VSUB2(uvec, se, ue);
00116                 VSUB2(vvec, se, ve);
00117 
00118                 VCROSS( norm, uvec, vvec);
00119                 VUNITIZE( norm );
00120 
00121                 return;
00122 
00123         }
00124         /* Case (linear, > linear) Use the linear direction to approximate
00125          * the tangent to the surface
00126          */
00127         if( srf->order[0] == 2 && srf->order[1] > 2 )
00128         {
00129                 rt_nurb_s_eval( srf, u, v, se);
00130 
00131                 p = 0.0;
00132                 for( i = 0; i < srf->u.k_size -1; i++)
00133                 {
00134                         if ( srf->u.knots[i] <= u
00135                                 && u < srf->u.knots[i+1] )
00136                         {
00137                                 p = srf->u.knots[i];
00138 
00139                                 if (u == p)
00140                                         p = srf->u.knots[i+1];
00141                                 if ( u == p && i > 1)
00142                                         p = srf->u.knots[i-1];
00143                         }
00144                 }
00145 
00146                 rt_nurb_s_eval( srf, p, v, ue);
00147 
00148                 vsrf = (struct face_g_snurb *) rt_nurb_s_diff(srf, RT_NURB_SPLIT_COL);
00149 
00150                 rt_nurb_s_eval(vsrf, u, v, ve);
00151 
00152                 if( RT_NURB_IS_PT_RATIONAL(srf->pt_type) )
00153                 {
00154                         fastf_t w, inv_w;
00155 
00156                         w = se[3];
00157                         inv_w = 1.0 / w;
00158 
00159                         ve[0] = (inv_w * ve[0]) -
00160                                 ve[3] / (w * w) * se[0];
00161                         ve[1] = (inv_w * ve[1]) -
00162                                 ve[3] / (w * w) * se[1];
00163                         ve[2] = (inv_w * ve[2]) -
00164                                 ve[3] / (w * w) * se[2];
00165 
00166                         ue[0] = ue[0] / ue[3];
00167                         ue[1] = ue[1] / ue[3];
00168                         ue[2] = ue[2] / ue[3];
00169                         ue[3] = ue[3] / ue[3];
00170 
00171                         se[0] = se[0] / se[3];
00172                         se[1] = se[1] / se[3];
00173                         se[2] = se[2] / se[3];
00174                         se[3] = se[3] / se[3];
00175                 }
00176 
00177                 VSUB2(uvec, se, ue);
00178 
00179                 VCROSS(norm, uvec, ve);
00180                 VUNITIZE(norm);
00181 
00182                 rt_nurb_free_snurb(vsrf, (struct resource *)NULL);
00183                 return;
00184         }
00185         if( srf->order[1] == 2 && srf->order[0] > 2 )
00186         {
00187                 rt_nurb_s_eval( srf, u, v, se);
00188 
00189                 p = 0.0;
00190                 for( i = 0; i < srf->v.k_size -1; i++)
00191                 {
00192                         if ( srf->v.knots[i] <= v
00193                                 && v < srf->v.knots[i+1] )
00194                         {
00195                                 p = srf->v.knots[i];
00196 
00197                                 if (v == p)
00198                                         p = srf->u.knots[i+1];
00199                                 if ( v == p && i > 1)
00200                                         p = srf->v.knots[i-1];
00201                         }
00202                 }
00203 
00204                 rt_nurb_s_eval( srf, u, p, ve);
00205 
00206                 usrf = (struct face_g_snurb *) rt_nurb_s_diff(srf, RT_NURB_SPLIT_ROW);
00207 
00208                 rt_nurb_s_eval(usrf, u, v, ue);
00209 
00210                 if( RT_NURB_IS_PT_RATIONAL(srf->pt_type) )
00211                 {
00212                         fastf_t w, inv_w;
00213 
00214                         w = se[3];
00215                         inv_w = 1.0 / w;
00216 
00217                         ue[0] = (inv_w * ue[0]) -
00218                                 ue[3] / (w * w) * se[0];
00219                         ue[1] = (inv_w * ue[1]) -
00220                                 ue[3] / (w * w) * se[1];
00221                         ue[2] = (inv_w * ue[2]) -
00222                                 ue[3] / (w * w) * se[2];
00223 
00224                         ve[0] = ve[0] / ve[3];
00225                         ve[1] = ve[1] / ve[3];
00226                         ve[2] = ve[2] / ve[3];
00227                         ve[3] = ve[3] / ve[3];
00228 
00229                         se[0] = se[0] / se[3];
00230                         se[1] = se[1] / se[3];
00231                         se[2] = se[2] / se[3];
00232                         se[3] = se[3] / se[3];
00233                 }
00234 
00235                 VSUB2(vvec, se, ve);
00236 
00237                 VCROSS(norm, ue, vvec);
00238                 VUNITIZE(norm);
00239 
00240                 rt_nurb_free_snurb(usrf, (struct resource *)NULL);
00241                 return;
00242         }
00243 
00244         /* Case Non Rational (order > 2, order > 2) */
00245         if( !RT_NURB_IS_PT_RATIONAL(srf->pt_type))
00246         {
00247 
00248                 usrf = (struct face_g_snurb *) rt_nurb_s_diff( srf, RT_NURB_SPLIT_ROW);
00249                 vsrf = (struct face_g_snurb *) rt_nurb_s_diff( srf, RT_NURB_SPLIT_COL);
00250 
00251                 rt_nurb_s_eval(usrf, u,v, ue);
00252                 rt_nurb_s_eval(vsrf, u,v, ve);
00253 
00254                 VCROSS( norm, ue, ve);
00255                 VUNITIZE( norm);
00256 
00257                 rt_nurb_free_snurb(usrf, (struct resource *)NULL);
00258                 rt_nurb_free_snurb(vsrf, (struct resource *)NULL);
00259 
00260                 return;
00261         }
00262 
00263         /* Case Rational (order > 2, order > 2) */
00264         if( RT_NURB_IS_PT_RATIONAL(srf->pt_type))
00265         {
00266                 fastf_t w, inv_w;
00267                 vect_t unorm, vnorm;
00268                 int i;
00269 
00270                 rt_nurb_s_eval(srf, u, v, se);
00271 
00272                 usrf = (struct face_g_snurb *) rt_nurb_s_diff( srf, RT_NURB_SPLIT_ROW);
00273                 vsrf = (struct face_g_snurb *) rt_nurb_s_diff( srf, RT_NURB_SPLIT_COL);
00274 
00275                 rt_nurb_s_eval(usrf, u,v, ue);
00276 
00277                 rt_nurb_s_eval(vsrf, u,v, ve);
00278 
00279                 w = se[3];
00280                 inv_w = 1.0 / w;
00281 
00282                 for(i = 0; i < 3; i++)
00283                 {
00284                         unorm[i] = (inv_w * ue[i]) -
00285                                 ue[3] / (w*w) * se[i];
00286                         vnorm[i] = (inv_w * ve[i]) -
00287                                 ve[3] / (w*w) * se[i];
00288                 }
00289 
00290                 VCROSS( norm, unorm, vnorm);
00291                 VUNITIZE( norm);
00292 
00293                 rt_nurb_free_snurb(usrf, (struct resource *)NULL);
00294                 rt_nurb_free_snurb(vsrf, (struct resource *)NULL);
00295 
00296                 return;
00297         }
00298         return;
00299 }
00300 
00301 /*
00302  * Local Variables:
00303  * mode: C
00304  * tab-width: 8
00305  * c-basic-offset: 4
00306  * indent-tabs-mode: t
00307  * End:
00308  * ex: shiftwidth=4 tabstop=8
00309  */

Generated on Mon Sep 18 01:24:55 2006 for BRL-CAD by  doxygen 1.4.6