Ejemplo n.º 1
0
frame3f mesh_frame(Mesh* mesh, int elementid, const vec2f& uv) {
    auto f = mesh_triangle_face(mesh,elementid);
    frame3f ff;
    ff.x = normalize(mesh->pos[f.y]-mesh->pos[f.x]);
    ff.y = normalize(mesh->pos[f.z]-mesh->pos[f.x]);
    if(not mesh->norm.empty()) ff.z = normalize(interpolate_baricentric_triangle(mesh->norm,f,uv));
    else if(elementid < mesh->triangle.size()) ff.z = triangle_normal(mesh->pos[f.x], mesh->pos[f.y], mesh->pos[f.z]);
    else { auto f = mesh->quad[(elementid-mesh->triangle.size())/2]; ff.z = quad_normal(mesh->pos[f.x], mesh->pos[f.y], mesh->pos[f.z], mesh->pos[f.w]); }
    ff.o = interpolate_baricentric_triangle(mesh->pos,f,uv);
    ff = orthonormalize(ff);
    return ff;
}
Ejemplo n.º 2
0
void shape_smooth_frames(Shape* shape) {
    if(is<TriangleMesh>(shape)) {
        auto mesh = cast<TriangleMesh>(shape);
        mesh->norm.resize(mesh->pos.size(),zero3f);
        for(auto f : mesh->triangle) for(auto vid : f) mesh->norm[vid] += triangle_normal(mesh->pos[f.x],mesh->pos[f.y],mesh->pos[f.z]);
        for(auto &n : mesh->norm) n = normalize(n);
    }
    else if(is<Mesh>(shape)) {
        auto mesh = cast<Mesh>(shape);
        mesh->norm.resize(mesh->pos.size(),zero3f);
        for(auto f : mesh->triangle) for(auto vid : f) mesh->norm[vid] += triangle_normal(mesh->pos[f.x],mesh->pos[f.y],mesh->pos[f.z]);
        for(auto f : mesh->quad) for(auto vid : f) mesh->norm[vid] += quad_normal(mesh->pos[f.x],mesh->pos[f.y],mesh->pos[f.z],mesh->pos[f.w]);
        for(auto &n : mesh->norm) n = normalize(n);
    }
}
Ejemplo n.º 3
0
/*!
  the distortion of a quad
*/
C_FUNC_DEF VERDICT_REAL v_quad_distortion( int num_nodes, VERDICT_REAL coordinates[][3] )
{
// To calculate distortion for linear and 2nd order quads
   // distortion = {min(|J|)/actual area}*{parent area}
   // parent area = 4 for a quad.
   // min |J| is the minimum over nodes and gaussian integration points
   // created by Ling Pan, CAT on 4/30/01

   double element_area =0.0,distrt,thickness_gauss;
   double cur_jacobian=0., sign_jacobian, jacobian ;
   VerdictVector  aa, bb, cc,normal_at_point, xin;


   //use 2x2 gauss points for linear quads and 3x3 for 2nd order quads
   int   number_of_gauss_points=0;
   if (num_nodes ==4)
      //2x2 quadrature rule
      number_of_gauss_points = 2;
   else if (num_nodes ==8)
      //3x3 quadrature rule
      number_of_gauss_points = 3;


   int total_number_of_gauss_points = number_of_gauss_points*number_of_gauss_points;

   VerdictVector face_normal = quad_normal( coordinates );

   double distortion = VERDICT_DBL_MAX;

   VerdictVector first, second;

   int i;
    //Will work out the case for collapsed quad later
   if ( is_collapsed_quad( coordinates ) == VERDICT_TRUE )
   {
      for (  i=0; i<3; i++ )
      {
 
         first.set( coordinates[i][0] - coordinates[(i+1)%3][0],
        coordinates[i][1] - coordinates[(i+1)%3][1],
        coordinates[i][2] - coordinates[(i+1)%3][2] );
 
         second.set( coordinates[i][0] - coordinates[(i+2)%3][0],
         coordinates[i][1] - coordinates[(i+2)%3][1],
         coordinates[i][2] - coordinates[(i+2)%3][2] );

         sign_jacobian = (face_normal % ( first * second )) > 0? 1.:-1.;
         cur_jacobian = sign_jacobian*(first * second).length();
         distortion = VERDICT_MIN(distortion, cur_jacobian);
      }
      element_area = (first*second).length()/2.0;
      distortion /= element_area;
   }
else
   {
      double shape_function[maxTotalNumberGaussPoints][maxNumberNodes];
      double dndy1[maxTotalNumberGaussPoints][maxNumberNodes];
      double dndy2[maxTotalNumberGaussPoints][maxNumberNodes];
      double weight[maxTotalNumberGaussPoints];

      //create an object of GaussIntegration
      GaussIntegration::initialize(number_of_gauss_points,num_nodes );
      GaussIntegration::calculate_shape_function_2d_quad();
      GaussIntegration::get_shape_func(shape_function[0], dndy1[0], dndy2[0], weight);

      // calculate element area
      int ife,ja;
      for ( ife=0;ife<total_number_of_gauss_points; ife++)
      {
         aa.set(0.0,0.0,0.0);
         bb.set(0.0,0.0,0.0);

         for (ja=0;ja<num_nodes;ja++)
         {
            xin.set(coordinates[ja][0], coordinates[ja][1], coordinates[ja][2]);
            aa += dndy1[ife][ja]*xin;
            bb += dndy2[ife][ja]*xin;
         }
         normal_at_point = aa*bb;
         jacobian = normal_at_point.length();
         element_area += weight[ife]*jacobian;
      }


      double dndy1_at_node[maxNumberNodes][maxNumberNodes];
      double dndy2_at_node[maxNumberNodes][maxNumberNodes];

      GaussIntegration::calculate_derivative_at_nodes( dndy1_at_node,  dndy2_at_node);

      VerdictVector normal_at_nodes[9];


      //evaluate normal at nodes and distortion values at nodes
      int jai;
      for (ja =0; ja<num_nodes; ja++)
      {
         aa.set(0.0,0.0,0.0);
         bb.set(0.0,0.0,0.0);
         for (jai =0; jai<num_nodes; jai++)
         {
            xin.set(coordinates[jai][0], coordinates[jai][1], coordinates[jai][2]);
            aa += dndy1_at_node[ja][jai]*xin;
            bb += dndy2_at_node[ja][jai]*xin;
         }
         normal_at_nodes[ja] = aa*bb;
         normal_at_nodes[ja].normalize();

      }

      //determine if element is flat
      bool flat_element =true;
      double dot_product;

      for ( ja=0; ja<num_nodes;ja++)
      {
         dot_product = normal_at_nodes[0]%normal_at_nodes[ja];
         if (fabs(dot_product) <0.99)
         {
     flat_element = false;
            break;
         }
      }

      // take into consideration of the thickness of the element
      double thickness;
      //get_quad_thickness(face, element_area, thickness );
      thickness = 0.001*sqrt(element_area);

      //set thickness gauss point location
      double zl = 0.5773502691896;
      if (flat_element) zl =0.0;

      int no_gauss_pts_z = (flat_element)? 1 : 2;
      double thickness_z;
      int igz;
      //loop on Gauss points
      for (ife=0;ife<total_number_of_gauss_points;ife++)
      {
         //loop on the thickness direction gauss points
         for ( igz=0;igz<no_gauss_pts_z;igz++)
         {
            zl = -zl;
            thickness_z = zl*thickness/2.0;

            aa.set(0.0,0.0,0.0);
            bb.set(0.0,0.0,0.0);
            cc.set(0.0,0.0,0.0);

            for (ja=0;ja<num_nodes;ja++)
            {
               xin.set(coordinates[ja][0], coordinates[ja][1], coordinates[ja][2]);
               xin += thickness_z*normal_at_nodes[ja];
               aa  += dndy1[ife][ja]*xin;
               bb  += dndy2[ife][ja]*xin;
               thickness_gauss = shape_function[ife][ja]*thickness/2.0;
               cc  += thickness_gauss*normal_at_nodes[ja];
            }

            normal_at_point = aa*bb;
            jacobian = normal_at_point.length();
            distrt = cc%normal_at_point;
            if (distrt < distortion) distortion = distrt;
         }
      }

      //loop through nodal points
      for ( ja =0; ja<num_nodes; ja++)
      {
         for ( igz=0;igz<no_gauss_pts_z;igz++)
         {
            zl = -zl;
            thickness_z = zl*thickness/2.0;

            aa.set(0.0,0.0,0.0);
            bb.set(0.0,0.0,0.0);
            cc.set(0.0,0.0,0.0);

            for ( jai =0; jai<num_nodes; jai++)
            {
               xin.set(coordinates[jai][0], coordinates[jai][1], coordinates[jai][2]);
               xin += thickness_z*normal_at_nodes[ja];
               aa += dndy1_at_node[ja][jai]*xin;
               bb += dndy2_at_node[ja][jai]*xin;
               if (jai == ja)
     thickness_gauss = thickness/2.0;
               else
                  thickness_gauss = 0.;
               cc  += thickness_gauss*normal_at_nodes[jai];
            }

         }
         normal_at_point = aa*bb;
         double sign_jacobian = (face_normal % normal_at_point) > 0? 1.:-1.;
         distrt = sign_jacobian  * (cc%normal_at_point);

         if (distrt < distortion) distortion = distrt;
      }

      if (element_area*thickness !=0)
         distortion *=8./( element_area*thickness);
      else
         distortion *=8.;

   }

   return (VERDICT_REAL)distortion;
}