diff --git a/Common/Context.h b/Common/Context.h index ba835e87c2b0e6d20f417d9d10360537f58b378f..602c0075b9b7624dcf94c4c625586b96524000de 100644 --- a/Common/Context.h +++ b/Common/Context.h @@ -182,6 +182,8 @@ public : int oldxtrude, oldxtrude_recombine, check_duplicates; int allow_degenerated_extrude, save_all; char *triangle_options; + int smooth_normals; + double angle_smooth_normals; } mesh; // post processing options diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h index e1ea0cd62bd80d337db46b6f0e7b767d4dccdd95..af8e8eedc7d0ec6c42a0c181bec3c6b37d65486c 100644 --- a/Common/DefaultOptions.h +++ b/Common/DefaultOptions.h @@ -705,6 +705,8 @@ StringXNumber MeshOptions_Number[] = { "3D mesh algorithm (1=isotropic, 4=netgen)" }, { F, "AllowDegeneratedExtrude" , opt_mesh_allow_degenerated_extrude , 0. , "Allow the generation of degenerated hexahedra or prisms during extrusion" }, + { F|O, "AngleSmoothNormals" , opt_mesh_angle_smooth_normals , 180.0 , + "Threshold angle below which normals are not smoothed" }, { F|O, "CharacteristicLengthFactor" , opt_mesh_lc_factor , 1.0 , "Factor applied to all characteristic lengths (and background meshes)" }, @@ -813,6 +815,8 @@ StringXNumber MeshOptions_Number[] = { "Global scaling factor applied to the saved mesh" }, { F|O, "Smoothing" , opt_mesh_nb_smoothing , 1. , "Number of smoothing steps applied to the final mesh" }, + { F|O, "SmoothNormals" , opt_mesh_smooth_normals , 0. , + "Smooth the mesh normals?" }, { F|O, "SpeedMax" , opt_mesh_speed_max , 0. , "Disable dubious point insertion tests" }, { F|O, "SurfaceEdges" , opt_mesh_surfaces_edges , 1. , diff --git a/Common/Makefile b/Common/Makefile index aba189345f35e62b6ef223cf36e27ef528be262b..fa0302204a1bdf4a0560d4cc5b0e9b30e9bc383d 100644 --- a/Common/Makefile +++ b/Common/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.58 2004-06-15 18:20:53 geuzaine Exp $ +# $Id: Makefile,v 1.59 2004-07-16 18:02:19 geuzaine Exp $ # # Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle # @@ -35,6 +35,7 @@ SRC = Context.cpp\ Visibility.cpp\ Trackball.cpp\ VertexArray.cpp\ + SmoothNormals.cpp\ License.cpp OBJ = ${SRC:.cpp=.o} diff --git a/Common/Options.cpp b/Common/Options.cpp index fe63dac2fdc5ec072aacdb13dfb18aa2edd2e5c4..613ef79990301146c779bf3cfd0d07f04b926c76 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -1,4 +1,4 @@ -// $Id: Options.cpp,v 1.170 2004-07-02 20:03:22 geuzaine Exp $ +// $Id: Options.cpp,v 1.171 2004-07-16 18:02:19 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -3427,6 +3427,32 @@ double opt_mesh_vertex_arrays(OPT_ARGS_NUM) return CTX.mesh.vertex_arrays; } +double opt_mesh_smooth_normals(OPT_ARGS_NUM) +{ + if(action & GMSH_SET) { + if(CTX.mesh.smooth_normals != val) CTX.mesh.changed = 1; + CTX.mesh.smooth_normals = (int)val; + } +#if defined(HAVE_FLTK) + if(WID && (action & GMSH_GUI)) + WID->mesh_butt[19]->value(CTX.mesh.smooth_normals); +#endif + return CTX.mesh.smooth_normals; +} + +double opt_mesh_angle_smooth_normals(OPT_ARGS_NUM) +{ + if(action & GMSH_SET) { + if(CTX.mesh.angle_smooth_normals != val) CTX.mesh.changed = 1; + CTX.mesh.angle_smooth_normals = val; + } +#if defined(HAVE_FLTK) + if(WID && (action & GMSH_GUI)) + WID->mesh_value[18]->value(CTX.mesh.angle_smooth_normals); +#endif + return CTX.mesh.angle_smooth_normals; +} + double opt_mesh_light(OPT_ARGS_NUM) { if(action & GMSH_SET) @@ -3444,7 +3470,7 @@ double opt_mesh_light_two_side(OPT_ARGS_NUM) CTX.mesh.light_two_side = (int)val; #if defined(HAVE_FLTK) if(WID && (action & GMSH_GUI)) - WID->mesh_butt[23]->value(CTX.mesh.light_two_side); + WID->mesh_butt[18]->value(CTX.mesh.light_two_side); #endif return CTX.mesh.light_two_side; } diff --git a/Common/Options.h b/Common/Options.h index 910ee4a52db2ca2ea933463da8b94b66f68c49ac..e772ce1221a4dbef4315f5d86270921ab5e37167 100644 --- a/Common/Options.h +++ b/Common/Options.h @@ -363,6 +363,8 @@ double opt_mesh_point_type(OPT_ARGS_NUM); double opt_mesh_line_width(OPT_ARGS_NUM); double opt_mesh_line_type(OPT_ARGS_NUM); double opt_mesh_vertex_arrays(OPT_ARGS_NUM); +double opt_mesh_smooth_normals(OPT_ARGS_NUM); +double opt_mesh_angle_smooth_normals(OPT_ARGS_NUM); double opt_mesh_light(OPT_ARGS_NUM); double opt_mesh_light_two_side(OPT_ARGS_NUM); double opt_mesh_format(OPT_ARGS_NUM); diff --git a/Common/SmoothNormals.cpp b/Common/SmoothNormals.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d34413b02aff39c8d59b1329b5f04cd7d5d2c871 --- /dev/null +++ b/Common/SmoothNormals.cpp @@ -0,0 +1,146 @@ +// $Id: SmoothNormals.cpp,v 1.1 2004-07-16 18:02:19 geuzaine Exp $ +// +// Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to <gmsh@geuz.org>. + +#include "Gmsh.h" +#include "Numeric.h" +#include "SmoothNormals.h" + +double xyzv::eps = 1.e-12; + +xyzv::xyzv(double xx, double yy, double zz) + : x(xx), y(yy), z(zz), vals(0), nbvals(0), nboccurences(0) +{ +} + +xyzv::~xyzv() +{ + if(vals) + delete [] vals; +} + +xyzv::xyzv(const xyzv & other) +{ + x = other.x; + y = other.y; + z = other.z; + nbvals = other.nbvals; + nboccurences = other.nboccurences; + if(other.vals && other.nbvals) { + vals = new double[other.nbvals]; + for(int i = 0; i < nbvals; i++) + vals[i] = other.vals[i]; + } +} + +xyzv & xyzv::operator =(const xyzv & other) +{ + if(this != &other) { + x = other.x; + y = other.y; + z = other.z; + nbvals = other.nbvals; + nboccurences = other.nboccurences; + if(other.vals && other.nbvals) { + vals = new double[other.nbvals]; + for(int i = 0; i < nbvals; i++) + vals[i] = other.vals[i]; + } + } + return *this; +} + +void xyzv::update(int n, double *v) +{ + int i; + if(!vals) { + vals = new double[n]; + for(i = 0; i < n; i++) + vals[i] = 0.0; + nbvals = n; + nboccurences = 0; + } + else if(nbvals != n) { + printf("throw!!\n"); + throw n; + } + + double x1 = (double)(nboccurences) / (double)(nboccurences + 1); + double x2 = 1. / (double)(nboccurences + 1); + for(i = 0; i < nbvals; i++) + vals[i] = (x1 * vals[i] + x2 * v[i]); + nboccurences++; + + //printf("val(%d,%f,%f,%f) = %f\n",nboccurences,x,y,z,vals[0]); +} + +double smooth_normals::get_angle(double *aa, double *bb) +{ + double angplan, cosc, sinc, a[3], b[3], c[3]; + if(!aa || !bb) + return 0.; + a[0] = aa[0]; + a[1] = aa[1]; + a[2] = aa[2]; + b[0] = bb[0]; + b[1] = bb[1]; + b[2] = bb[2]; + norme(a); + norme(b); + prodve(a, b, c); + prosca(a, b, &cosc); + sinc = sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]); + angplan = myatan2(sinc, cosc); + return angplan * 180. / Pi; +} + +void smooth_normals::add(double x, double y, double z, + double nx, double ny, double nz) +{ + double n[3] = { nx, ny, nz }; + xyzv xyz(x, y, z); + xyziter it = c.find(xyz); + if(it == c.end()) { + xyz.update(3, n); + c.insert(xyz); + } + else { + xyzv *xx = (xyzv *) & (*it); + xx->update(3, n); + } +} + +bool smooth_normals::get(double x, double y, double z, + double &nx, double &ny, double &nz, double tol) +{ + double n[3] = { nx, ny, nz }; + xyzv xyz(x, y, z); + xyziter it = c.find(xyz); + if(it == c.end()) + return false; + double angle = get_angle((*it).vals, n); + if(fabs(angle) < tol) { + nx = (*it).vals[0]; + ny = (*it).vals[1]; + nz = (*it).vals[2]; + } + return true; +} + diff --git a/Common/SmoothNormals.h b/Common/SmoothNormals.h new file mode 100644 index 0000000000000000000000000000000000000000..0a3a30262850028133bd268507591e4e39fe88f8 --- /dev/null +++ b/Common/SmoothNormals.h @@ -0,0 +1,72 @@ +#ifndef _SMOOTH_NORMALS_H_ +#define _SMOOTH_NORMALS_H_ + +// Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to <gmsh@geuz.org>. + +#include <set> + +using namespace std; + +struct xyzv +{ + double x, y, z, *vals; + int nbvals; + int nboccurences; + static double eps; + void update(int nbVals, double *); + xyzv(double x, double y, double z); + ~xyzv(); + xyzv & operator =(const xyzv &); + xyzv(const xyzv &); +}; + +struct lessthanxyzv +{ + bool operator () (const xyzv & p2, const xyzv & p1)const + { + if(p1.x - p2.x > xyzv::eps) + return true; + if(p1.x - p2.x < -xyzv::eps) + return false; + if(p1.y - p2.y > xyzv::eps) + return true; + if(p1.y - p2.y < -xyzv::eps) + return false; + if(p1.z - p2.z > xyzv::eps) + return true; + return false; + } +}; + +typedef set < xyzv, lessthanxyzv > xyzcont; +typedef xyzcont::const_iterator xyziter; + +class smooth_normals{ + private: + double get_angle(double *aa, double *bb); + public: + xyzcont c; + void add(double x, double y, double z, + double nx, double ny, double nz); + bool get(double x, double y, double z, + double &nx, double &ny, double &nz, double angletol = 180.0); +}; + +#endif diff --git a/Common/Views.cpp b/Common/Views.cpp index a66844f2c753c4b2addbea250eaf72930177c95b..aeb981331148d7b5f28c1d5e6c946097e210bce7 100644 --- a/Common/Views.cpp +++ b/Common/Views.cpp @@ -1,4 +1,4 @@ -// $Id: Views.cpp,v 1.125 2004-07-05 15:20:06 geuzaine Exp $ +// $Id: Views.cpp,v 1.126 2004-07-16 18:02:19 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -26,6 +26,7 @@ #include "Context.h" #include "Options.h" #include "ColorTable.h" +#include "SmoothNormals.h" extern Context_T CTX; @@ -150,7 +151,7 @@ Post_View *BeginView(int allocate) v->DuplicateOf = 0; v->ScalarOnly = 1; v->TextOnly = 1; - v->normals = NULL; + v->normals = new smooth_normals; v->Min = VAL_INF; v->Max = -VAL_INF; for(i = 0; i < 3; i++) { @@ -578,9 +579,9 @@ void FreeView(Post_View * v) v->SY = v->VY = v->TY = NULL; v->T2D = v->T2C = NULL; v->T3D = v->T3C = NULL; - v->reset_normals(); - if(v->TriVertexArray) - delete v->TriVertexArray; + if(v->normals) delete v->normals; + v->normals = NULL; + if(v->TriVertexArray) delete v->TriVertexArray; v->TriVertexArray = NULL; } @@ -1037,118 +1038,15 @@ void WriteView(Post_View *v, char *filename, int binary, int append) // Smoothing -using namespace std; - -struct xyzv -{ -private: -public: - double x, y, z, *vals; - int nbvals; - int nboccurences; - static double eps; - void update(int nbVals, double *); - xyzv(double x, double y, double z); - ~xyzv(); - xyzv & operator =(const xyzv &); - xyzv(const xyzv &); -}; - -double xyzv::eps = 0.0; - -xyzv::xyzv(double xx, double yy, double zz) -:x(xx), y(yy), z(zz), vals(0), nbvals(0), nboccurences(0) -{ -} - -xyzv::~xyzv() -{ - if(vals) - delete[]vals; -} - -xyzv::xyzv(const xyzv & other) -{ - x = other.x; - y = other.y; - z = other.z; - nbvals = other.nbvals; - nboccurences = other.nboccurences; - if(other.vals && other.nbvals) { - vals = new double[other.nbvals]; - for(int i = 0; i < nbvals; i++) - vals[i] = other.vals[i]; - } -} - -xyzv & xyzv::operator =(const xyzv & other) -{ - if(this != &other) { - x = other.x; - y = other.y; - z = other.z; - nbvals = other.nbvals; - nboccurences = other.nboccurences; - if(other.vals && other.nbvals) { - vals = new double[other.nbvals]; - for(int i = 0; i < nbvals; i++) - vals[i] = other.vals[i]; - } - } - return *this; -} - -void xyzv::update(int n, double *v) +void Post_View::reset_normals() { - int i; - if(!vals) { - vals = new double[n]; - for(i = 0; i < n; i++) - vals[i] = 0.0; - nbvals = n; - nboccurences = 0; - } - else if(nbvals != n) { - throw n; - } - - double x1 = (double)(nboccurences) / (double)(nboccurences + 1); - double x2 = 1. / (double)(nboccurences + 1); - for(i = 0; i < nbvals; i++) - vals[i] = (x1 * vals[i] + x2 * v[i]); - nboccurences++; - - //printf("val(%d,%f,%f,%f) = %f\n",nboccurences,x,y,z,vals[0]); + if(normals) + delete normals; + normals = new smooth_normals; } -struct lessthanxyzv -{ - bool operator () (const xyzv & p2, const xyzv & p1)const - { - if(p1.x - p2.x > xyzv::eps) - return true; - if(p1.x - p2.x < -xyzv::eps) - return false; - if(p1.y - p2.y > xyzv::eps) - return true; - if(p1.y - p2.y < -xyzv::eps) - return false; - if(p1.z - p2.z > xyzv::eps) - return true; - return false; - } -}; - -typedef set < xyzv, lessthanxyzv > mycont; -typedef mycont::const_iterator iter; - -class smooth_container -{ - public: mycont c; -}; - void generate_connectivities(List_T * list, int nbList, int nbTimeStep, int nbVert, - mycont & connectivities) + xyzcont & connectivities) { double *x, *y, *z, *v; int i, j, k; @@ -1167,7 +1065,7 @@ void generate_connectivities(List_T * list, int nbList, int nbTimeStep, int nbVe for(k = 0; k < nbTimeStep; k++) vals[k] = v[j + k * nbVert]; xyzv xyz(x[j], y[j], z[j]); - iter it = connectivities.find(xyz); + xyziter it = connectivities.find(xyz); if(it == connectivities.end()) { xyz.update(nbTimeStep, vals); connectivities.insert(xyz); @@ -1184,7 +1082,7 @@ void generate_connectivities(List_T * list, int nbList, int nbTimeStep, int nbVe } void smooth_list(List_T * list, int nbList, double *min, double *max, - int nbTimeStep, int nbVert, mycont & connectivities) + int nbTimeStep, int nbVert, xyzcont & connectivities) { double *x, *y, *z, *v; int i, j, k; @@ -1203,7 +1101,7 @@ void smooth_list(List_T * list, int nbList, double *min, double *max, v = (double *)List_Pointer_Fast(list, i + 3 * nbVert); for(j = 0; j < nbVert; j++) { xyzv xyz(x[j], y[j], z[j]); - iter it = connectivities.find(xyz); + xyziter it = connectivities.find(xyz); if(it != connectivities.end()) { for(k = 0; k < nbTimeStep; k++) { v[j + k * nbVert] = (*it).vals[k]; @@ -1222,7 +1120,7 @@ void Post_View::smooth() xyzv::eps = CTX.lc * 1.e-8; if(NbSL || NbST || NbSQ || NbSS || NbSH || NbSI || NbSY) { - mycont con; + xyzcont con; Msg(INFO, "Smoothing scalar primitives in View[%d]", Index); generate_connectivities(SL, NbSL, NbTimeStep, 2, con); generate_connectivities(ST, NbST, NbTimeStep, 3, con); @@ -1242,81 +1140,6 @@ void Post_View::smooth() } } -// Normal smoothing - -void Post_View::reset_normals() -{ - if(normals) - delete normals; - normals = 0; -} - -void Post_View::add_normal(double x, double y, double z, - double nx, double ny, double nz) -{ - if(!normals) - normals = new smooth_container; - - double n[3] = { nx, ny, nz }; - xyzv xyz(x, y, z); - - iter it = normals->c.find(xyz); - - if(it == normals->c.end()) { - xyz.update(3, n); - normals->c.insert(xyz); - } - else { - xyzv *xx = (xyzv *) & (*it); - xx->update(3, n); - } -} - -double get_angle(double *aa, double *bb) -{ - double angplan, cosc, sinc, a[3], b[3], c[3]; - if(!aa || !bb) - return 0.; - a[0] = aa[0]; - a[1] = aa[1]; - a[2] = aa[2]; - b[0] = bb[0]; - b[1] = bb[1]; - b[2] = bb[2]; - norme(a); - norme(b); - prodve(a, b, c); - prosca(a, b, &cosc); - sinc = sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]); - angplan = myatan2(sinc, cosc); - return angplan * 180. / Pi; -} - -bool Post_View::get_normal(double x, double y, double z, - double &nx, double &ny, double &nz) -{ - if(!normals) - return false; - - double n[3] = { nx, ny, nz }; - xyzv xyz(x, y, z); - - iter it = normals->c.find(xyz); - - if(it == normals->c.end()) - return false; - - double angle = get_angle((*it).vals, n); - - if(fabs(angle) < AngleSmoothNormals) { - nx = (*it).vals[0]; - ny = (*it).vals[1]; - nz = (*it).vals[2]; - } - - return true; -} - // Transformation static void transform(double mat[3][3], double v[3], diff --git a/Common/Views.h b/Common/Views.h index 143007aea8b54629d89fc69642762015afc2aac9..c503a26c7da3548d07b532f9d3e8579201329a2c 100644 --- a/Common/Views.h +++ b/Common/Views.h @@ -23,13 +23,12 @@ #include "ColorTable.h" #include "List.h" #include "VertexArray.h" +#include "SmoothNormals.h" #define VIEW_NB_ELEMENT_TYPES (8*3) #define VIEW_MAX_ELEMENT_NODES 8 #define VAL_INF 1.e200 -class smooth_container; - class Post_View{ public : // intrinsic to a view @@ -90,13 +89,9 @@ class Post_View{ int (*GIFV) (double min, double max, int nb, double value); // smooth the view void smooth(); - // smooth the normals - smooth_container *normals; + // smooth normals + smooth_normals *normals; void reset_normals(); - void add_normal(double x, double y, double z, - double nx, double ny, double nz); - bool get_normal(double x, double y, double z, - double &nx, double &ny, double &nz); // transform the view void transform(double mat[3][3]); diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp index 6a3d40e9a26bfdcfce26b64e3acae42a73c1f59b..7ee0b3bd16465bcffc14e7998b44d7df452aa4ca 100644 --- a/Fltk/Callbacks.cpp +++ b/Fltk/Callbacks.cpp @@ -1,4 +1,4 @@ -// $Id: Callbacks.cpp,v 1.253 2004-07-08 17:21:27 geuzaine Exp $ +// $Id: Callbacks.cpp,v 1.254 2004-07-16 18:02:19 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -989,7 +989,8 @@ void mesh_options_ok_cb(CALLBACK_ARGS) opt_mesh_use_cut_plane(0, GMSH_SET, WID->mesh_butt[16]->value()); opt_mesh_cut_plane_as_surface(0, GMSH_SET, WID->mesh_butt[22]->value()); opt_mesh_light(0, GMSH_SET, WID->mesh_butt[17]->value()); - opt_mesh_light_two_side(0, GMSH_SET, WID->mesh_butt[23]->value()); + opt_mesh_light_two_side(0, GMSH_SET, WID->mesh_butt[18]->value()); + opt_mesh_smooth_normals(0, GMSH_SET, WID->mesh_butt[19]->value()); opt_mesh_nb_smoothing(0, GMSH_SET, WID->mesh_value[0]->value()); opt_mesh_scaling_factor(0, GMSH_SET, WID->mesh_value[1]->value()); @@ -1008,6 +1009,7 @@ void mesh_options_ok_cb(CALLBACK_ARGS) opt_mesh_cut_planeb(0, GMSH_SET, WID->mesh_value[15]->value()); opt_mesh_cut_planec(0, GMSH_SET, WID->mesh_value[16]->value()); opt_mesh_cut_planed(0, GMSH_SET, WID->mesh_value[17]->value()); + opt_mesh_angle_smooth_normals(0, GMSH_SET, WID->mesh_value[18]->value()); opt_mesh_point_type(0, GMSH_SET, WID->mesh_choice[0]->value()); opt_mesh_line_type(0, GMSH_SET, WID->mesh_choice[1]->value()); diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp index 93c79b99961023fecfface0032f6aa4cae87a230..7534bad7afdc99e953cbfb6ca1cf21db8312ae24 100644 --- a/Fltk/GUI.cpp +++ b/Fltk/GUI.cpp @@ -1,4 +1,4 @@ -// $Id: GUI.cpp,v 1.322 2004-07-01 19:13:44 geuzaine Exp $ +// $Id: GUI.cpp,v 1.323 2004-07-16 18:02:20 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -1878,24 +1878,29 @@ void GUI::create_option_window() Fl_Group *o = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Aspect"); o->hide(); mesh_butt[17] = new Fl_Check_Button(2 * WB, 2 * WB + 1 * BH, BW, BH, "Enable lighting"); - mesh_butt[17]->type(FL_TOGGLE_BUTTON); - mesh_butt[17]->down_box(TOGGLE_BOX); - mesh_butt[17]->selection_color(TOGGLE_COLOR); + mesh_butt[18] = new Fl_Check_Button(2 * WB, 2 * WB + 2 * BH, BW, BH, "Use two-side lighting"); + mesh_butt[19] = new Fl_Check_Button(2 * WB, 2 * WB + 3 * BH, BW, BH, "Smooth normals"); + for(i = 17; i <= 19; i++) { + mesh_butt[i]->type(FL_TOGGLE_BUTTON); + mesh_butt[i]->down_box(TOGGLE_BOX); + mesh_butt[i]->selection_color(TOGGLE_COLOR); + } - mesh_butt[23] = new Fl_Check_Button(2 * WB, 2 * WB + 2 * BH, BW, BH, "Use two-side lighting"); - mesh_butt[23]->type(FL_TOGGLE_BUTTON); - mesh_butt[23]->down_box(TOGGLE_BOX); - mesh_butt[23]->selection_color(TOGGLE_COLOR); + mesh_value[18] = new Fl_Value_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Angle"); + mesh_value[18]->minimum(0.); + mesh_value[18]->maximum(180.); + mesh_value[18]->step(1.); + mesh_value[18]->align(FL_ALIGN_RIGHT); - mesh_value[9] = new Fl_Value_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Explode elements"); + mesh_value[9] = new Fl_Value_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Explode elements"); mesh_value[9]->minimum(0); mesh_value[9]->maximum(1); mesh_value[9]->step(0.01); - mesh_value[10] = new Fl_Value_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Point size"); + mesh_value[10] = new Fl_Value_Input(2 * WB, 2 * WB + 7 * BH, IW, BH, "Point size"); mesh_value[10]->minimum(0.1); mesh_value[10]->maximum(50); mesh_value[10]->step(0.1); - mesh_value[11] = new Fl_Value_Input(2 * WB, 2 * WB + 7 * BH, IW, BH, "Line width"); + mesh_value[11] = new Fl_Value_Input(2 * WB, 2 * WB + 9 * BH, IW, BH, "Line width"); mesh_value[11]->minimum(0.1); mesh_value[11]->maximum(50); mesh_value[11]->step(0.1); @@ -1903,11 +1908,11 @@ void GUI::create_option_window() mesh_value[i]->align(FL_ALIGN_RIGHT); } - mesh_choice[0] = new Fl_Choice(2 * WB, 2 * WB + 4 * BH, IW, BH, "Point display"); + mesh_choice[0] = new Fl_Choice(2 * WB, 2 * WB + 6 * BH, IW, BH, "Point display"); mesh_choice[0]->menu(menu_point_display); mesh_choice[0]->align(FL_ALIGN_RIGHT); - mesh_choice[1] = new Fl_Choice(2 * WB, 2 * WB + 6 * BH, IW, BH, "Line display"); + mesh_choice[1] = new Fl_Choice(2 * WB, 2 * WB + 8 * BH, IW, BH, "Line display"); mesh_choice[1]->menu(menu_line_display); mesh_choice[1]->align(FL_ALIGN_RIGHT); mesh_choice[1]->deactivate(); // don't give false hopes, as it's not used anywhere right now diff --git a/Graphics/Iso.cpp b/Graphics/Iso.cpp index 986fc64c089f3f08f423e69e257b47ac43eff81f..f63046eb326262e4bc389ee7e64a73fe6c4d6376 100644 --- a/Graphics/Iso.cpp +++ b/Graphics/Iso.cpp @@ -1,4 +1,4 @@ -// $Id: Iso.cpp,v 1.28 2004-07-02 23:15:04 geuzaine Exp $ +// $Id: Iso.cpp,v 1.29 2004-07-16 18:02:20 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -356,7 +356,7 @@ void EnhanceSimplexPolygon(Post_View * View, int nb, // nb of points in polyg if(View->SmoothNormals) { if(preproNormals) { for(i = 0; i < nb; i++) { - View->add_normal(Xp[i], Yp[i], Zp[i], n[0], n[1], n[2]); + View->normals->add(Xp[i], Yp[i], Zp[i], n[0], n[1], n[2]); } return; } @@ -365,8 +365,9 @@ void EnhanceSimplexPolygon(Post_View * View, int nb, // nb of points in polyg norms[3 * i] = n[0]; norms[3 * i + 1] = n[1]; norms[3 * i + 2] = n[2]; - View->get_normal - (Xp[i], Yp[i], Zp[i], norms[3 * i], norms[3 * i + 1], norms[3 * i + 2]); + View->normals->get(Xp[i], Yp[i], Zp[i], + norms[3 * i], norms[3 * i + 1], norms[3 * i + 2], + View->AngleSmoothNormals); } } } diff --git a/Graphics/Mesh.cpp b/Graphics/Mesh.cpp index 6642a03afd6295283974c80bdef2f37d0b61284b..cf7d2085a67ac08a1a7f53ed22387be377c68471 100644 --- a/Graphics/Mesh.cpp +++ b/Graphics/Mesh.cpp @@ -1,4 +1,4 @@ -// $Id: Mesh.cpp,v 1.100 2004-07-09 18:26:56 geuzaine Exp $ +// $Id: Mesh.cpp,v 1.101 2004-07-16 18:02:20 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -235,6 +235,8 @@ void Draw_Mesh_Volume(void *a, void *b) Tree_Action(v->Pyramids, Draw_Mesh_Pyramid); } +static int preproNormals = 0; + void Draw_Mesh_Surface(void *a, void *b) { Surface *s = *(Surface **) a; @@ -245,6 +247,16 @@ void Draw_Mesh_Surface(void *a, void *b) theColor = s->Color; thePhysical = getFirstPhysical(MSH_PHYSICAL_SURFACE, s->Num); + if(CTX.mesh.changed && CTX.mesh.smooth_normals){ + Msg(DEBUG, "pre-processing smooth normals"); + if(s->normals) delete s->normals; + s->normals = new smooth_normals; + preproNormals = 1; + Tree_Action(s->Simplexes, Draw_Mesh_Triangle); + Tree_Action(s->Quadrangles, Draw_Mesh_Quadrangle); + preproNormals = 0; + } + if(CTX.mesh.vertex_arrays){ if(CTX.mesh.changed){ Msg(DEBUG, "regenerate surface mesh vertex arrays"); @@ -454,13 +466,41 @@ void _triFace(double x0, double y0, double z0, double x1, double y1, double z1, double x2, double y2, double z2) { - double n[3]; - if(CTX.mesh.light){ + double n[3], ns[3]; + + if(CTX.mesh.light || (theSurface && preproNormals)){ _normal3points(x0, y0, z0, x1, y1, z1, x2, y2, z2, n); + if(theSurface && preproNormals){ + theSurface->normals->add(x0, y0, z0, n[0], n[1], n[2]); + theSurface->normals->add(x1, y1, z1, n[0], n[1], n[2]); + theSurface->normals->add(x2, y2, z2, n[0], n[1], n[2]); + return; + } glNormal3dv(n); } + + if(CTX.mesh.light && theSurface && CTX.mesh.smooth_normals){ + ns[0] = n[0]; ns[1] = n[1]; ns[2] = n[2]; + theSurface->normals->get(x0, y0, z0, ns[0], ns[1], ns[2], + CTX.mesh.angle_smooth_normals); + glNormal3dv(ns); + } glVertex3d(x0, y0, z0); + + if(CTX.mesh.light && theSurface && CTX.mesh.smooth_normals){ + ns[0] = n[0]; ns[1] = n[1]; ns[2] = n[2]; + theSurface->normals->get(x1, y1, z1, ns[0], ns[1], ns[2], + CTX.mesh.angle_smooth_normals); + glNormal3dv(ns); + } glVertex3d(x1, y1, z1); + + if(CTX.mesh.light && theSurface && CTX.mesh.smooth_normals){ + ns[0] = n[0]; ns[1] = n[1]; ns[2] = n[2]; + theSurface->normals->get(x2, y2, z2, ns[0], ns[1], ns[2], + CTX.mesh.angle_smooth_normals); + glNormal3dv(ns); + } glVertex3d(x2, y2, z2); } @@ -478,16 +518,52 @@ void _triFace2(double *x, double *y, double *z, void _quadFace(double *x, double *y, double *z, int i0, int i1, int i2, int i3) { - double n[3]; - if(CTX.mesh.light){ + double n[3], ns[3]; + + if(CTX.mesh.light || (theSurface && preproNormals)){ _normal3points(x[i0], y[i0], z[i0], x[i1], y[i1], z[i1], x[i2], y[i2], z[i2], n); + if(theSurface && preproNormals){ + theSurface->normals->add(x[i0], y[i0], z[i0], n[0], n[1], n[2]); + theSurface->normals->add(x[i1], y[i1], z[i1], n[0], n[1], n[2]); + theSurface->normals->add(x[i2], y[i2], z[i2], n[0], n[1], n[2]); + theSurface->normals->add(x[i3], y[i3], z[i3], n[0], n[1], n[2]); + return; + } glNormal3dv(n); } + + if(CTX.mesh.light && theSurface && CTX.mesh.smooth_normals){ + ns[0] = n[0]; ns[1] = n[1]; ns[2] = n[2]; + theSurface->normals->get(x[i0], y[i0], z[i0], ns[0], ns[1], ns[2], + CTX.mesh.angle_smooth_normals); + glNormal3dv(ns); + } glVertex3d(x[i0], y[i0], z[i0]); + + if(CTX.mesh.light && theSurface && CTX.mesh.smooth_normals){ + ns[0] = n[0]; ns[1] = n[1]; ns[2] = n[2]; + theSurface->normals->get(x[i1], y[i1], z[i1], ns[0], ns[1], ns[2], + CTX.mesh.angle_smooth_normals); + glNormal3dv(ns); + } glVertex3d(x[i1], y[i1], z[i1]); + + if(CTX.mesh.light && theSurface && CTX.mesh.smooth_normals){ + ns[0] = n[0]; ns[1] = n[1]; ns[2] = n[2]; + theSurface->normals->get(x[i2], y[i2], z[i2], ns[0], ns[1], ns[2], + CTX.mesh.angle_smooth_normals); + glNormal3dv(ns); + } glVertex3d(x[i2], y[i2], z[i2]); + + if(CTX.mesh.light && theSurface && CTX.mesh.smooth_normals){ + ns[0] = n[0]; ns[1] = n[1]; ns[2] = n[2]; + theSurface->normals->get(x[i3], y[i3], z[i3], ns[0], ns[1], ns[2], + CTX.mesh.angle_smooth_normals); + glNormal3dv(ns); + } glVertex3d(x[i3], y[i3], z[i3]); } @@ -602,18 +678,24 @@ void Draw_Mesh_Triangle(void *a, void *b) } } - if(CTX.mesh.normals || CTX.mesh.light || - (theSurface && theSurface->TriVertexArray && theSurface->TriVertexArray->fill)){ - _normal3points(X[0], Y[0], Z[0], - X[1], Y[1], Z[1], - X[2], Y[2], Z[2], n); - glNormal3dv(n); - } - if(theSurface && theSurface->TriVertexArray){ - if(theSurface->TriVertexArray->fill){ + if(preproNormals || theSurface->TriVertexArray->fill) + _normal3points(X[0], Y[0], Z[0], + X[1], Y[1], Z[1], + X[2], Y[2], Z[2], n); + if(preproNormals){ for(int i = 0; i < 3; i++) - theSurface->TriVertexArray->add(X[i], Y[i], Z[i], n[0], n[1], n[2], col); + theSurface->normals->add(X[i], Y[i], Z[i], n[0], n[1], n[2]); + return; + } + if(theSurface->TriVertexArray->fill){ + for(int i = 0; i < 3; i++){ + double ns[3] = {n[0], n[1], n[2]}; + if(CTX.mesh.smooth_normals) + theSurface->normals->get(X[i], Y[i], Z[i], ns[0], ns[1], ns[2], + CTX.mesh.angle_smooth_normals); + theSurface->TriVertexArray->add(X[i], Y[i], Z[i], ns[0], ns[1], ns[2], col); + } theSurface->TriVertexArray->num++; } } @@ -637,9 +719,7 @@ void Draw_Mesh_Triangle(void *a, void *b) if(CTX.mesh.surfaces_edges) glEnable(GL_POLYGON_OFFSET_FILL); if(!s->VSUP) { glBegin(GL_TRIANGLES); - glVertex3d(X[0], Y[0], Z[0]); - glVertex3d(X[1], Y[1], Z[1]); - glVertex3d(X[2], Y[2], Z[2]); + _triFace(X[0], Y[0], Z[0], X[1], Y[1], Z[1], X[2], Y[2], Z[2]); glEnd(); } else { @@ -679,6 +759,9 @@ void Draw_Mesh_Triangle(void *a, void *b) } if(CTX.mesh.normals) { + _normal3points(X[0], Y[0], Z[0], + X[1], Y[1], Z[1], + X[2], Y[2], Z[2], n); glColor4ubv((GLubyte *) & CTX.color.mesh.normals); n[0] *= CTX.mesh.normals * CTX.pixel_equiv_x / CTX.s[0]; n[1] *= CTX.mesh.normals * CTX.pixel_equiv_x / CTX.s[1]; @@ -744,18 +827,24 @@ void Draw_Mesh_Quadrangle(void *a, void *b) } } - if(CTX.mesh.normals || CTX.mesh.light || - (theSurface && theSurface->QuadVertexArray && theSurface->QuadVertexArray->fill)){ - _normal3points(X[0], Y[0], Z[0], - X[1], Y[1], Z[1], - X[2], Y[2], Z[2], n); - glNormal3dv(n); - } - if(theSurface && theSurface->QuadVertexArray){ - if(theSurface->QuadVertexArray->fill){ + if(preproNormals || theSurface->QuadVertexArray->fill) + _normal3points(X[0], Y[0], Z[0], + X[1], Y[1], Z[1], + X[2], Y[2], Z[2], n); + if(preproNormals){ for(int i = 0; i < 4; i++) - theSurface->QuadVertexArray->add(X[i], Y[i], Z[i], n[0], n[1], n[2], col); + theSurface->normals->add(X[i], Y[i], Z[i], n[0], n[1], n[2]); + return; + } + if(theSurface->QuadVertexArray->fill){ + for(int i = 0; i < 4; i++){ + double ns[3] = {n[0], n[1], n[2]}; + if(CTX.mesh.smooth_normals) + theSurface->normals->get(X[i], Y[i], Z[i], ns[0], ns[1], ns[2], + CTX.mesh.angle_smooth_normals); + theSurface->QuadVertexArray->add(X[i], Y[i], Z[i], ns[0], ns[1], ns[2], col); + } theSurface->QuadVertexArray->num++; } } @@ -779,10 +868,7 @@ void Draw_Mesh_Quadrangle(void *a, void *b) if(CTX.mesh.surfaces_edges) glEnable(GL_POLYGON_OFFSET_FILL); if(!q->VSUP) { glBegin(GL_QUADS); - glVertex3d(X[0], Y[0], Z[0]); - glVertex3d(X[1], Y[1], Z[1]); - glVertex3d(X[2], Y[2], Z[2]); - glVertex3d(X[3], Y[3], Z[3]); + _quadFace(X, Y, Z, 0, 1, 2, 3); glEnd(); } else { @@ -823,6 +909,9 @@ void Draw_Mesh_Quadrangle(void *a, void *b) if(CTX.mesh.normals) { glColor4ubv((GLubyte *) & CTX.color.mesh.normals); + _normal3points(X[0], Y[0], Z[0], + X[1], Y[1], Z[1], + X[2], Y[2], Z[2], n); n[0] *= CTX.mesh.normals * CTX.pixel_equiv_x / CTX.s[0]; n[1] *= CTX.mesh.normals * CTX.pixel_equiv_x / CTX.s[1]; n[2] *= CTX.mesh.normals * CTX.pixel_equiv_x / CTX.s[2]; diff --git a/Graphics/PostElement.cpp b/Graphics/PostElement.cpp index fa98b16fdde3086856b2ac1ff92e835a8f2e4473..d0eac927b0b0acd6d2d6f00ddfd31a3438a719d1 100644 --- a/Graphics/PostElement.cpp +++ b/Graphics/PostElement.cpp @@ -1,4 +1,4 @@ -// $Id: PostElement.cpp,v 1.38 2004-07-09 18:26:56 geuzaine Exp $ +// $Id: PostElement.cpp,v 1.39 2004-07-16 18:02:20 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -437,7 +437,7 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals, } if(preproNormals){ for(int i = 0; i < 3; i++) - View->add_normal(xx[i], yy[i], zz[i], nn[0], nn[1], nn[2]); + View->normals->add(xx[i], yy[i], zz[i], nn[0], nn[1], nn[2]); return; } for(int i = 0; i < 3; i++) { @@ -447,7 +447,8 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals, } if(View->SmoothNormals) for(int i = 0; i < 3; i++) - View->get_normal(xx[i], yy[i], zz[i], norms[3*i], norms[3*i+1], norms[3*i+2]); + View->normals->get(xx[i], yy[i], zz[i], norms[3*i], norms[3*i+1], norms[3*i+2], + View->AngleSmoothNormals); if(View->TriVertexArray && View->TriVertexArray->fill){ unsigned int col; @@ -482,7 +483,7 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals, } if(preproNormals){ for(int i = 0; i < nb; i++) - View->add_normal(xx[i], yy[i], zz[i], nn[0], nn[1], nn[2]); + View->normals->add(xx[i], yy[i], zz[i], nn[0], nn[1], nn[2]); return; } for(int i = 0; i < nb; i++) { @@ -492,7 +493,8 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals, } if(View->SmoothNormals) for(int i = 0; i < nb; i++) - View->get_normal(xx[i], yy[i], zz[i], norms[3*i], norms[3*i+1], norms[3*i+2]); + View->normals->get(xx[i], yy[i], zz[i], norms[3*i], norms[3*i+1], norms[3*i+2], + View->AngleSmoothNormals); if(View->TriVertexArray && View->TriVertexArray->fill){ for(int i = 2; i < nb; i++) { @@ -543,7 +545,7 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals, } if(preproNormals){ for(int i = 0; i < nb; i++) - View->add_normal(xx[i], yy[i], zz[i], nn[0], nn[1], nn[2]); + View->normals->add(xx[i], yy[i], zz[i], nn[0], nn[1], nn[2]); } else{ for(int i = 0; i < nb; i++) { @@ -553,7 +555,8 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals, } if(View->SmoothNormals) for(int i = 0; i < nb; i++) - View->get_normal(xx[i], yy[i], zz[i], norms[3*i], norms[3*i+1], norms[3*i+2]); + View->normals->get(xx[i], yy[i], zz[i], norms[3*i], norms[3*i+1], norms[3*i+2], + View->AngleSmoothNormals); if(View->TriVertexArray && View->TriVertexArray->fill){ for(int i = 2; i < nb; i++) { diff --git a/Mesh/Create.cpp b/Mesh/Create.cpp index 0edf45c0903e01274ee76cbdcb27a378eb47e506..cdbcfb3015328f2dbc6c430486a9c5e8d7e52b17 100644 --- a/Mesh/Create.cpp +++ b/Mesh/Create.cpp @@ -1,4 +1,4 @@ -// $Id: Create.cpp,v 1.61 2004-06-28 19:00:22 geuzaine Exp $ +// $Id: Create.cpp,v 1.62 2004-07-16 18:02:20 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -671,6 +671,7 @@ Surface *Create_Surface(int Num, int Typ) pS->STL = NULL; pS->TriVertexArray = NULL; pS->QuadVertexArray = NULL; + pS->normals = new smooth_normals; return (pS); } @@ -697,6 +698,8 @@ void Free_Surface(void *a, void *b) delete pS->TriVertexArray; if(pS->QuadVertexArray) delete pS->QuadVertexArray; + if(pS->normals) + delete pS->normals; Free(pS); pS = NULL; } diff --git a/Mesh/Mesh.h b/Mesh/Mesh.h index aeb301db909711e4bd3206c19789206e3cbafbf8..487b5689e169f03a1d233de828c7e0b6fd402ab5 100644 --- a/Mesh/Mesh.h +++ b/Mesh/Mesh.h @@ -29,6 +29,7 @@ #include "ExtrudeParams.h" #include "STL.h" #include "VertexArray.h" +#include "SmoothNormals.h" #define FORMAT_MSH 1 #define FORMAT_UNV 2 @@ -258,6 +259,7 @@ struct _Surf{ DrawingColor Color; VertexArray * TriVertexArray; VertexArray * QuadVertexArray; + smooth_normals * normals; }; typedef struct _Surf Surface; diff --git a/Mesh/Utils.cpp b/Mesh/Utils.cpp index 951cb44df04889849ba5eb4aba76ee28a75bc73b..6d2ecd433e93935d1de4c89952f051a6ba4f22c4 100644 --- a/Mesh/Utils.cpp +++ b/Mesh/Utils.cpp @@ -1,4 +1,4 @@ -// $Id: Utils.cpp,v 1.25 2004-04-18 03:23:02 geuzaine Exp $ +// $Id: Utils.cpp,v 1.26 2004-07-16 18:02:20 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -281,15 +281,15 @@ void find_bestuv(Surface * s, double X, double Y, *V = minv; } -void invert_singular_matrix3x3(double _M[3][3], double _I[3][3]) +void invert_singular_matrix3x3(double MM[3][3], double II[3][3]) { int i, j, k, n = 3; - double _T[3][3]; + double TT[3][3]; for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { - _I[i - 1][j - 1] = 0.0; - _T[i - 1][j - 1] = 0.0; + II[i - 1][j - 1] = 0.0; + TT[i - 1][j - 1] = 0.0; } } @@ -300,7 +300,7 @@ void invert_singular_matrix3x3(double _M[3][3], double _I[3][3]) gsl_vector *TMPVEC = gsl_vector_alloc(3); for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { - gsl_matrix_set(M, i - 1, j - 1, _M[i - 1][j - 1]); + gsl_matrix_set(M, i - 1, j - 1, MM[i - 1][j - 1]); } } gsl_linalg_SV_decomp(M, V, W, TMPVEC); @@ -308,15 +308,15 @@ void invert_singular_matrix3x3(double _M[3][3], double _I[3][3]) for(j = 1; j <= n; j++) { double ww = gsl_vector_get(W, i - 1); if(fabs(ww) > 1.e-16) { //singular value precision - _T[i - 1][j - 1] += gsl_matrix_get(M, j - 1, i - 1) / ww; + TT[i - 1][j - 1] += gsl_matrix_get(M, j - 1, i - 1) / ww; } } } for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { for(k = 1; k <= n; k++) { - _I[i - 1][j - 1] += - gsl_matrix_get(V, i - 1, k - 1) * _T[k - 1][j - 1]; + II[i - 1][j - 1] += + gsl_matrix_get(V, i - 1, k - 1) * TT[k - 1][j - 1]; } } } @@ -330,21 +330,21 @@ void invert_singular_matrix3x3(double _M[3][3], double _I[3][3]) double *W = dvector(1, 3); for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { - M[i][j] = _M[i - 1][j - 1]; + M[i][j] = MM[i - 1][j - 1]; } } dsvdcmp(M, n, n, W, V); for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { if(fabs(W[i]) > 1.e-16) { //singular value precision - _T[i - 1][j - 1] += M[j][i] / W[i]; + TT[i - 1][j - 1] += M[j][i] / W[i]; } } } for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { for(k = 1; k <= n; k++) { - _I[i - 1][j - 1] += V[i][k] * _T[k - 1][j - 1]; + II[i - 1][j - 1] += V[i][k] * TT[k - 1][j - 1]; } } } diff --git a/doc/VERSIONS b/doc/VERSIONS index 713fb8eed82a0863272b9b281905fb12723643b7..0387387e360d7620a8b6a60eb2e7f26e8cf86827 100644 --- a/doc/VERSIONS +++ b/doc/VERSIONS @@ -1,7 +1,8 @@ -$Id: VERSIONS,v 1.235 2004-07-14 22:42:27 geuzaine Exp $ +$Id: VERSIONS,v 1.236 2004-07-16 18:02:20 geuzaine Exp $ -New since 1.54: added background mesh support for Triangle; small bug -fixes. +New since 1.54: added background mesh support for Triangle; meshes can +now be displayed using "smoothed" normals (like post-processing +views); small bug fixes. New in 1.54: integrated Netgen (3D mesh quality optimization + alternative 3D algorithm); Extrude Surface now always automatically