void SeLct::_fpathmake ( FunnelPath* fpath, GsPolygon& path, float radius, float dang )
 {
   // init path:
   path.open ( true );
   path.size ( 0 );

   // check trivial case:
   if ( fpath->size()==2 ) // only endpoints inserted
    { path.push() = fpath->get(0);
      path.push() = fpath->top();
      return;
    }
   path.push() = fpath->get(0);

   GsPnt2 lp ( fpath->get(1) );
   tangents ( 'p', fpath->get(1).optop(), fpath->get(0), lp, 0, fpath->get(1).dist );
   
   int size = fpath->size();
   char code[2];
   float ra, rb;
   GsPnt2 a, b;
   for ( int i=2; i<size; i++ )
    {
      a=fpath->get(i-1); b=fpath->get(i);
      ra=fpath->get(i-1).dist; rb=fpath->get(i).dist;
      code[0]=fpath->get(i-1).optop();
      code[1]=fpath->get(i).opside();
      tangents ( code[0], code[1], a, b, ra, rb );
      GsPnt2& cent = fpath->get(i-1);
      path.arc ( cent, lp-cent/*v1*/, a-cent/*v2*/, ra, code[0]=='b'? dang:-dang );
      lp=b;
    }
   path.push() = fpath->top();
 }
void panzer::ProjectToEdges<EvalT, Traits>::
evaluateFields(typename Traits::EvalData workset)
{ 
  const shards::CellTopology & parentCell = *basis->getCellTopology();
  const int intDegree = basis->order();
  TEUCHOS_ASSERT(intDegree == 1);
  Intrepid2::DefaultCubatureFactory<double,Kokkos::DynRankView<double,PHX::Device>,Kokkos::DynRankView<double,PHX::Device>> quadFactory;
  Teuchos::RCP< Intrepid2::Cubature<double,Kokkos::DynRankView<double,PHX::Device>,Kokkos::DynRankView<double,PHX::Device>> > edgeQuad;

  // Collect the reference edge information. For now, do nothing with the quadPts.
  const unsigned num_edges = parentCell.getEdgeCount();
  std::vector<double> refEdgeWt(num_edges, 0.0);
  for (unsigned e=0; e<num_edges; e++) {
    edgeQuad = quadFactory.create(parentCell.getCellTopologyData(1,e), intDegree);
    const int numQPoints = edgeQuad->getNumPoints();
    Kokkos::DynRankView<double,PHX::Device> quadWts("quadWts",numQPoints);
    Kokkos::DynRankView<double,PHX::Device> quadPts("quadPts",numQPoints,num_dim);
    edgeQuad->getCubature(quadPts,quadWts);
    for (int q=0; q<numQPoints; q++)
      refEdgeWt[e] += quadWts(q);
  }

  // Loop over the edges of the workset cells.
  for (index_t cell = 0; cell < workset.num_cells; ++cell) {
    for (int p = 0; p < num_pts; ++p) {
      result(cell,p) = ScalarT(0.0);
      for (int dim = 0; dim < num_dim; ++dim)
        result(cell,p) += vector_values(cell,p,dim) * tangents(cell,p,dim);
      result(cell,p) *= refEdgeWt[p];
    }
  }

}
Esempio n. 3
0
void Mesh::calcTangents()
{
	std::vector<glm::vec3> tangents(mVertices.size());

	for (GLuint i = 0; i < mIndices.size(); i += 3) {
		const auto i0 = mIndices[i];
		const auto i1 = mIndices[i + 1];
		const auto i2 = mIndices[i + 2];

		const auto& edge1 = mVertices[i1].position - mVertices[i0].position;
		const auto& edge2 = mVertices[i2].position - mVertices[i0].position;

		const auto& delta1 = mVertices[i1].texCoord - mVertices[i0].texCoord;
		const auto& delta2 = mVertices[i2].texCoord - mVertices[i0].texCoord;

		GLfloat dividend = (delta1.x * delta2.y - delta2.x * delta1.y);
		GLfloat f = dividend == 0.0f ? 0.0f : 1.0f / dividend;

		const glm::vec3 tangent =
		{
			f * (delta2.y * edge1.x - delta1.y * edge2.x),
			f * (delta2.y * edge1.y - delta1.y * edge2.y),
			f * (delta2.y * edge1.z - delta1.y * edge2.z)
		};

		tangents[i0] += tangent;
		tangents[i1] += tangent;
		tangents[i2] += tangent;
	}


	for (GLuint i = 0; i < tangents.size(); ++i) {
		mVertices[i].normal = glm::normalize(tangents[i]);
	}
}
static bool isgoalopening ( const SeFunnelPt& fa, const SeFunnelPt& fb, GsPnt2 c, float /*radius*/ )
 {
   GsPnt2 a=fa;
   GsPnt2 b=fb;
   GsPnt2 p=b;

   tangents ( fb.side, fa.side, b, a, fb.dist, fa.dist );
   tangents (   'p',   fb.side, c, p, 0,       fb.dist );

   c.x = b.x+(c.x-p.x);
   c.y = b.y+(c.y-p.y);

   if ( fb.side=='t' )
    { return gs_ccw(a.x,a.y,b.x,b.y,c.x,c.y)>0? true:false;
	}
   else
    { return gs_ccw(b.x,b.y,a.x,a.y,c.x,c.y)>0? true:false;
	}
 }
Esempio n. 5
0
void compute_smooth_vertex_tangents_base_pose(MeshObject& object)
{
    assert(object.get_vertex_tangent_count() == 0);
    assert(object.get_tex_coords_count() > 0);

    const size_t vertex_count = object.get_vertex_count();
    const size_t triangle_count = object.get_triangle_count();

    vector<GVector3> tangents(vertex_count, GVector3(0.0));

    for (size_t i = 0; i < triangle_count; ++i)
    {
        const Triangle& triangle = object.get_triangle(i);

        if (!triangle.has_vertex_attributes())
            continue;

        const GVector2 v0_uv = object.get_tex_coords(triangle.m_a0);
        const GVector2 v1_uv = object.get_tex_coords(triangle.m_a1);
        const GVector2 v2_uv = object.get_tex_coords(triangle.m_a2);

        //
        // Reference:
        //
        //   Physically Based Rendering, first edition, pp. 128-129
        //

        const GScalar du0 = v0_uv[0] - v2_uv[0];
        const GScalar dv0 = v0_uv[1] - v2_uv[1];
        const GScalar du1 = v1_uv[0] - v2_uv[0];
        const GScalar dv1 = v1_uv[1] - v2_uv[1];
        const GScalar det = du0 * dv1 - dv0 * du1;

        if (det == GScalar(0.0))
            continue;

        const GVector3& v2 = object.get_vertex(triangle.m_v2);
        const GVector3 dp0 = object.get_vertex(triangle.m_v0) - v2;
        const GVector3 dp1 = object.get_vertex(triangle.m_v1) - v2;
        const GVector3 tangent = normalize(dv1 * dp0 - dv0 * dp1);

        tangents[triangle.m_v0] += tangent;
        tangents[triangle.m_v1] += tangent;
        tangents[triangle.m_v2] += tangent;
    }

    object.reserve_vertex_tangents(vertex_count);

    for (size_t i = 0; i < vertex_count; ++i)
        object.push_vertex_tangent(safe_normalize(tangents[i]));
}
Esempio n. 6
0
static void kdBinCreateTangents(u::vector<kdBinVertex> &vertices, const u::vector<kdBinTriangle> &triangles) {
    // Computing Tangent Space Basis Vectors for an Arbitrary Mesh (Lengyel’s Method)
    // Section 7.8 (or in Section 6.8 of the second edition).
    const size_t vertexCount = vertices.size();
    const size_t triangleCount = triangles.size();
    u::vector<m::vec3> normals(vertexCount);
    u::vector<m::vec3> tangents(vertexCount);
    u::vector<m::vec3> bitangents(vertexCount);
    m::vec3 normal;
    m::vec3 tangent;
    m::vec3 bitangent;

    for (size_t i = 0; i < triangleCount; i++) {
        kdBinCalculateTangent(triangles, vertices, i, normal, tangent, bitangent);
        const size_t x = triangles[i].v[0];
        const size_t y = triangles[i].v[1];
        const size_t z = triangles[i].v[2];

        normals[x] += normal;
        normals[y] += normal;
        normals[z] += normal;
        tangents[x] += tangent;
        tangents[y] += tangent;
        tangents[z] += tangent;
        bitangents[x] += bitangent;
        bitangents[y] += bitangent;
        bitangents[z] += bitangent;
    }

    for (size_t i = 0; i < vertexCount; i++) {
        // Gram-Schmidt orthogonalize
        // http://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process
        vertices[i].normal = normals[i].normalized();
        const m::vec3 &n = vertices[i].normal;
        m::vec3 t = tangents[i];
        m::vec3 tangent = (t - n * (n * t)).normalized();

        if (!tangent.isNormalized()) {
            // Couldn't calculate vertex tangent for vertex, so we fill it in along
            // the x axis.
            tangent = m::vec3::xAxis;
            t = tangent;
        }

        // bitangents are only stored by handness in the W component (-1.0f or 1.0f).
        vertices[i].tangent = m::vec4(tangent, (((n ^ t) * bitangents[i]) < 0.0f) ? -1.0f : 1.0f);
    }
}
static bool isopening ( const SeFunnelPt& fa, const SeFunnelPt& fb, const SeFunnelPt& fc, float /*r*/, int& fcase )
 {
   GsPnt2 a = fa;
   GsPnt2 b = fb;
   GsPnt2 p = b;
   GsPnt2 c = fc;
   char sori;

   if ( fb.side==fc.side && !fb.apex ) // same as 1st
    { tangents ( fc.side, fb.side, c, p, fc.dist, fb.dist );
      tangents ( fb.side, fa.side, b, a, fb.dist, fa.dist );
      fcase = 1;
      sori = fc.side;
    }
   else if ( fb.side==fc.side ) // here fb.apex is 1
    { tangents ( fc.side, fb.side, c, p, fc.dist, fb.dist );
      tangents ( fa.side, fc.side, b, a, fa.dist, fc.dist );
      fcase = 2;
      sori = fa.side;
    }
   else if ( fb.Pnt() )
    { tangents ( fc.side, fb.side, c, p, fc.dist, fb.dist );
      tangents ( fa.side, fb.side, a, b, fa.dist, fb.dist );
      fcase = 3;
      sori = fa.side;
    }
   else // fc.side!=fb.side
    { tangents ( fc.side, fa.side, c, p, fc.dist, fa.dist );
      tangents ( fa.side, fa.side, a, b, fa.dist, fa.dist );
      fcase = 4;
      sori = fa.side;
    }
   
   c.x = b.x+(c.x-p.x);
   c.y = b.y+(c.y-p.y);

   if ( sori=='t' )
    { return gs_ccw(a.x,a.y,b.x,b.y,c.x,c.y)>0? true:false;
	}
   else
    { return gs_ccw(b.x,b.y,a.x,a.y,c.x,c.y)>0? true:false;
	}
 }
void SeLct::_fpathpush ( FunnelPath* fpath, const FunnelPt& fp3, float radius )
 {
   char c3 = fp3.opside();
   GsPnt2 p1, p2, p3, q2, q3;

   if ( fpath->size()==0 )
    { fpath->push()=fp3;
      if ( fpath->autolen ) fpath->len=0;
      return;
    }

   // The following test is rarely needed but examples needing it have been found, even in LCTs.
   // The r-funnel algorithm remains linear since the overall number of pops is bounded by n.
   #ifdef PATH_CORRECTION
   while ( fpath->size()>=2 )
    { SeFunnelPt& fp1 = fpath->top(1);
      SeFunnelPt& fp2 = fpath->top();
      p1=fp1; p2=fp2; p3=fp3; q2=p2;
      char c1 = fp1.opside();
      char c2 = fp2.optop();

      tangents ( c1, c2, p1, p2, fp1.dist, fp2.dist );
      tangents ( c2, c3, q2, p3, fp2.dist, fp3.dist );
      q3 = p2 + (p3-q2);

      double ccw = gs_ccw ( p1.x,p1.y,p2.x,p2.y,q3.x,q3.y );
      if ( GS_NEXT(ccw,0,1.0E-9) || (c2=='b' && ccw<=0) || (c2=='t' && ccw>=0) )
       { if ( fpath->autolen && fpath->size()>2 ) // discount lenght of the region being popped
          { SeFunnelPt& fp = fpath->top(2);
            GsPnt2 p = fp;
            GsPnt2 p0 = fp1;
            tangents ( fp.opside(), c1, p, p0, fp.dist, fp1.dist );
            fpath->len -= ArcAndTanLen ( p0, p1, fp1, p2, radius );
          }
         fpath->pop();
       }
      else
       { if ( fpath->autolen ) fpath->len += ArcAndTanLen ( p2, q2, fp2, p3, radius );
         fpath->push()=fp3;
         break;
       }
    }
   #else
   if ( fpath->size()>=2 )
    { SeFunnelPt& fp1 = fpath->top(1);
      SeFunnelPt& fp2 = fpath->top();
      p1=fp1; p2=fp2; p3=fp3; q2=p2;
      if ( fpath->autolen ) fpath->len += ArcAndTanLen ( p2, q2, fp2, p3, radius );
      fpath->push()=fp3;
      return;
    }
   #endif

   if ( fpath->size()==1 )
    { if ( fpath->autolen )
       { p3 = fp3;
         tangents ( 'p', fp3.opside(), fpath->get(0), p3, radius, radius );
         fpath->len = dist ( fpath->get(0), p3 );
       }
      fpath->push()=fp3;
    }
 }
Esempio n. 9
0
void MonotonicInterpolate(const vector<Vector>& pts,vector<GeneralizedCubicBezierCurve>& paths,CSpace* space,GeodesicManifold* manifold)
{
  Assert(pts.size() >= 2);
  
  paths.resize(pts.size()-1);
  for(size_t i=0;i<paths.size();i++) {
    paths[i].x0 = pts[i];
    paths[i].x3 = pts[i+1];
    paths[i].space = space;
    paths[i].manifold = manifold;
  }
  vector<Vector> tangents(pts.size()),inslopes(pts.size()-1),outslopes(pts.size()-1);
  if(pts.size() == 2) {
    paths[0].SetSmoothTangents(NULL,NULL);
    return;
  }
  paths[0].SetSmoothTangents(NULL,&pts[2]);
  paths[0].Deriv(0,tangents[0]);
  paths.back().x0 = pts[pts.size()-2];
  paths.back().x3 = pts[pts.size()-1];
  paths.back().SetSmoothTangents(&pts[pts.size()-3],NULL);
  paths.back().Deriv(1,tangents.back());
  for(size_t i=1;i<pts.size();i++) {
    if(!manifold) {
      inslopes[i-1] = pts[i]-pts[i-1];
      outslopes[i-1].setRef(inslopes[i-1]);
    }
    else {
      manifold->InterpolateDeriv(pts[i-1],pts[i],0,inslopes[i-1]);
      manifold->InterpolateDeriv(pts[i],pts[i-1],0,outslopes[i-1]);
      outslopes[i-1].inplaceNegative();
    }
    if(i+1<pts.size()) {
      if(!manifold)
	tangents[i] = (pts[i+1]-pts[i-1])*0.5;
      else {
	Vector n,p;
	manifold->InterpolateDeriv(pts[i],pts[i+1],0,n);
	manifold->InterpolateDeriv(pts[i],pts[i-1],0,p);
	tangents[i] = (n-p)*0.5;
      }
    }
  }
  int n=pts[0].n;
  for(size_t i=0;i<pts.size();i++) {
    if(tangents[i].n != n) printf("%d / %d\n",i,tangents.size());
    Assert(tangents[i].n == n);
  }
  for(size_t i=0;i+1<pts.size();i++) {
    for(int j=0;j<n;j++) {
      if(Sign(tangents[i][j]) != Sign(inslopes[i][j]))
	tangents[i][j] = 0;
      else {
	if(tangents[i][j]>0) {
	  if(tangents[i][j] > 3.0*inslopes[i][j])
	    tangents[i][j] = 3.0*inslopes[i][j];
	}
	else {
	  if(tangents[i][j] < 3.0*inslopes[i][j])
	    tangents[i][j] = 3.0*inslopes[i][j];
	}
      }
      if(Sign(tangents[i+1][j]) != Sign(outslopes[i][j]))
	tangents[i+1][j] = 0;
      else {
	if(tangents[i+1][j]>0) {
	  if(tangents[i+1][j] > 3.0*outslopes[i][j])
	    tangents[i+1][j] = 3.0*outslopes[i][j];
	}
	else {
	  if(tangents[i+1][j] < 3.0*outslopes[i][j])
	    tangents[i+1][j] = 3.0*outslopes[i][j];
	}
      }
    }
  }
  for(size_t i=0;i+1<pts.size();i++) {
    paths[i].SetNaturalTangents(tangents[i],tangents[i+1]);
  }
}
Esempio n. 10
0
void MonotonicAccelInterpolate(const vector<Vector>& pts,vector<GeneralizedCubicBezierCurve>& paths,CSpace* space,GeodesicManifold* manifold)
{
  Assert(pts.size() >= 2);
  
  vector<Vector> tangents(pts.size()),inslopes(pts.size()-1),outslopes(pts.size()-1);
  paths.resize(pts.size()-1);
  for(size_t i=0;i<paths.size();i++) {
    paths[i].x0 = pts[i];
    paths[i].x3 = pts[i+1];
    paths[i].space = space;
    paths[i].manifold = manifold;
  }
  paths[0].x0 = pts[0];
  paths[0].x3 = pts[1];
  if(pts.size() == 2) {
    paths[0].SetSmoothTangents(NULL,NULL);
    return;
  }
  paths[0].SetSmoothTangents(NULL,&pts[2]);
  paths[0].Deriv(0,tangents[0]);
  paths.back().x0 = pts[pts.size()-2];
  paths.back().x3 = pts[pts.size()-1];
  paths.back().SetSmoothTangents(&pts[pts.size()-3],NULL);
  paths.back().Deriv(1,tangents.back());
  for(size_t i=1;i<pts.size();i++) {
    if(!manifold) {
      inslopes[i-1] = pts[i]-pts[i-1];
      outslopes[i-1].setRef(inslopes[i-1]);
    }
    else {
      manifold->InterpolateDeriv(pts[i-1],pts[i],0,inslopes[i-1]);
      manifold->InterpolateDeriv(pts[i],pts[i-1],0,outslopes[i-1]);
      outslopes[i-1].inplaceNegative();
    }
    if(i+1<pts.size()) {
      if(!manifold)
	tangents[i] = (pts[i+1]-pts[i-1])*0.5;
      else {
	Vector n,p;
	manifold->InterpolateDeriv(pts[i],pts[i+1],0,n);
	manifold->InterpolateDeriv(pts[i],pts[i-1],0,p);
	tangents[i] = (n-p)*0.5;
      }
    }
  }
  int n=pts[0].n;
  for(size_t i=0;i<pts.size();i++) {
    if(tangents[i].n != n) printf("%d / %d\n",i,tangents.size());
    Assert(tangents[i].n == n);
  }
  for(size_t i=0;i+1<pts.size();i++) {
    if(i == 1)
      cout<<"Orig tangent 2: "<<tangents[i+1]<<endl;
    for(int j=0;j<n;j++) {
      if(j==0) {
	printf("Segment %d: accel in %g, out %g\n",i,3.0*inslopes[i][j] - tangents[i+1][j]-2*tangents[i][j],2*tangents[i+1][j]+tangents[i][j] - 3.0*outslopes[i][j]);
      }
      if(Sign(3.0*inslopes[i][j] - tangents[i+1][j] - 2*tangents[i][j]) != Sign(2*tangents[i+1][j]+tangents[i][j] - 3.0*outslopes[i][j])) {
	//(3.0*mi - x - 2*t0)*(2*x+t0 - 3.0*mo) = 0
	//(- x + 3.0*mi - 2*t0)*(2*x+t0 - 3.0*mo) = 
	//    -2x^2 + x*(-t0+3mo+6mi-4t0) + (3mi-2t0)(t0-3mo) = 0
	//solve quadratic to set tangents[i+1][j] so one accel becomes
	//nullified
	Real a = -2.0;
	Real b = 6*inslopes[i][j] + 3*outslopes[i][j]-5*tangents[i][j];
	Real c = (3*inslopes[i][j]-2*tangents[i][j])*(tangents[i][j]-3*outslopes[i][j]);
	Real t1,t2;
	int res=quadratic(a,b,c,t1,t2);
	if(res == 0) {
	  if(j==0) 
	    printf("No solution to quadratic %g %g %g\n",a,b,c);
	}
	else {
	  assert(res > 0);
	  if(res == 2) {
	    //pick the closer one to the existing tangent
	    if(Abs(t1 - tangents[i+1][j]) > Abs(t2 - tangents[i+1][j]))
	      t1 = t2;
	  }
	  tangents[i+1][j] = t1;
	  if(j==0) {
	    printf("New accel in %g, out %g\n",3.0*inslopes[i][j] - tangents[i+1][j]-2*tangents[i][j],2*tangents[i+1][j]+tangents[i][j] - 3.0*outslopes[i][j]);
	  }
	}
      }
    }
    if(i == 1)
      cout<<"New tangent 2: "<<tangents[i+1]<<endl;
  }
  for(size_t i=0;i+1<pts.size();i++) {
    paths[i].SetNaturalTangents(tangents[i],tangents[i+1]);
    Vector temp,temp2;
    paths[i].Accel(0,temp);
    paths[i].Accel(1,temp2);
    cout<<"in "<<temp[0]<<" out "<<temp2[0]<<endl;
  }
}
Esempio n. 11
0
void MonotonicInterpolate(const vector<Vector>& pts,const vector<Real>& times,vector<GeneralizedCubicBezierCurve>& paths,CSpace* space,GeodesicManifold* manifold)
{
  Assert(times.size()==pts.size());
  Assert(pts.size() >= 2);
  
  paths.resize(pts.size()-1);
  for(size_t i=0;i<paths.size();i++) {
    paths[i].x0 = pts[i];
    paths[i].x3 = pts[i+1];
    paths[i].space = space;
    paths[i].manifold = manifold;
  }
  vector<Real> durations(pts.size()-1);
  vector<Real> rates(pts.size()-1);
  for(size_t i=0;i+1<pts.size();i++) {
    durations[i] = times[i+1]-times[i];
    rates[i] = 1.0/durations[i];
  }
  vector<Vector> tangents(pts.size()),inslopes(pts.size()-1),outslopes(pts.size()-1);
  if(pts.size() == 2) {
    paths[0].SetSmoothTangents(NULL,NULL);
    return;
  }
  paths[0].SetSmoothTangents(NULL,&pts[2],1.0,durations[1]*rates[0]);
  paths[0].Deriv(0,tangents[0]);
  paths.back().x0 = pts[pts.size()-2];
  paths.back().x3 = pts[pts.size()-1];
  paths.back().SetSmoothTangents(&pts[pts.size()-3],NULL,durations[durations.size()-2]*rates.back(),1.0);
  paths.back().Deriv(1,tangents.back());
  for(size_t i=1;i<pts.size();i++) {
    if(!manifold) {
      inslopes[i-1] = pts[i]-pts[i-1];
      inslopes[i-1] *= rates[i-1];
      outslopes[i-1].setRef(inslopes[i-1]);
    }
    else {
      manifold->InterpolateDeriv(pts[i-1],pts[i],0,inslopes[i-1]);
      manifold->InterpolateDeriv(pts[i],pts[i-1],0,outslopes[i-1]);
      outslopes[i-1].inplaceNegative();
      inslopes[i-1] *= rates[i-1];
      outslopes[i-1] *= rates[i-1];
    }
    /* xi = y(0)
     * xp = y(-dtp)
     * xn = y(dtn)
     * fit a quadratic 
     *   y(u) = a u^2 + b u + c
     * and find y'(0)=b
     * 
     * c = xi
     * a dtn^2 + b dtn = xn-xi
     * a dtp^2 - b dtp = xp-xi
     * [dtn^2  dtn][a] = [xn-xi]
     * [dtp^2 -dtp][b]   [xp-xi]
     * -1/(dtn dtp)(dtn + dtp) [ -dtp   -dtn ][xn-xi] = [a]
     *                         [ -dtp^2 dtn^2][xp-xi]   [b]
     * b = dtp^2/(dtn dtp)(dtn + dtp) (xn-xi) - dtn^2/(dtn dtp)(dtn + dtp)(xp-xi)
     *   = 1/(dtn+dtp) (dtp/dtn (xn-xi) - dtn/dtp (xp-xi))
     */
    if(i+1<pts.size()) {
      Vector n,p;
      Real s1 = durations[i-1]*rates[i];
      Real s2 = durations[i]*rates[i-1];
      if(!manifold) {
	n = pts[i+1] - pts[i];
	p = pts[i-1] - pts[i];
      }
      else {
	manifold->InterpolateDeriv(pts[i],pts[i+1],0,n);
	manifold->InterpolateDeriv(pts[i],pts[i-1],0,p);
      }
      tangents[i] = (s2*n-s1*p)/(durations[i-1]+durations[i]);
    }
  }
  int n=pts[0].n;
  for(size_t i=0;i<pts.size();i++) {
    if(tangents[i].n != n) printf("%d / %d\n",i,tangents.size());
    Assert(tangents[i].n == n);
  }
  for(size_t i=0;i+1<pts.size();i++) {
    for(int j=0;j<n;j++) {
      if(Sign(tangents[i][j]) != Sign(inslopes[i][j]))
	tangents[i][j] = 0;
      else {
	if(tangents[i][j]>0) {
	  if(tangents[i][j] > 3.0*inslopes[i][j])
	    tangents[i][j] = 3.0*inslopes[i][j];
	}
	else {
	  if(tangents[i][j] < 3.0*inslopes[i][j])
	    tangents[i][j] = 3.0*inslopes[i][j];
	}
      }
      if(Sign(tangents[i+1][j]) != Sign(outslopes[i][j]))
	tangents[i+1][j] = 0;
      else {
	if(tangents[i+1][j]>0) {
	  if(tangents[i+1][j] > 3.0*outslopes[i][j])
	    tangents[i+1][j] = 3.0*outslopes[i][j];
	}
	else {
	  if(tangents[i+1][j] < 3.0*outslopes[i][j])
	    tangents[i+1][j] = 3.0*outslopes[i][j];
	}
      }
    }
  }
  for(size_t i=0;i+1<pts.size();i++) {
    paths[i].SetNaturalTangents(tangents[i]*durations[i],tangents[i+1]*durations[i]);
  }
}
Esempio n. 12
0
    static void BuildCurves(float3* points, int count, bool isClosed,
        std::vector<BezierCurve>* out)
    {
        assert(count > 1);

        float3 cp[4];
        if(count == 2)
        {
            cp[0] = points[0];
            cp[3] = points[1];
            cp[1] = cp[0] + 0.3333f * (cp[3] - cp[0]);
            cp[2] = cp[0] + 0.6666f * (cp[3] - cp[0]);
            out->push_back(BezierCurve(cp));
        }
        else
        {
            float3 zerov(0.0f,0.0f,0.0f);
            std::vector<float3> tangents(count,zerov);            
            CalcPointTangents(points,&tangents[0],count,isClosed);
            for (int i = 1; i < count; i++)
            {
                float3 chord = points[i] - points[i - 1];
                float segLen = length(chord) * 0.3333f;                
                cp[0] = points[i - 1];
                cp[3] = points[i];

                float3 tangent1 = tangents[i - 1];
                if (dot(chord, tangent1) < 0)
                    tangent1 = -tangent1;
                cp[1] = cp[0] + (tangent1 * segLen);


                float3 tangent2 = tangents[i];
                if (dot(-chord, tangent2) < 0)
                    tangent2 = -tangent2;
                cp[2] = cp[3] + (tangent2 * segLen);
               
                BezierCurve curve(cp);
                out->push_back(curve);
            }

            // Calculate last curve if is closed
            if (isClosed)
            {           
                float3 lastcp1 = cp[1];
                float3 lastcp2 = cp[2];
                
                cp[0] = points[count - 1];
                cp[3] = points[0];
                
                BezierCurve lastCurve = out->back();
                float tanLen = length(cp[3] - cp[0]) * 0.3333f;
               
                float3 v = normalize(lastCurve.GetControlPoint(2) - cp[0]);                
                cp[1] = cp[0] - (v * tanLen);

                BezierCurve firstCurve = out->front();

                v = normalize(firstCurve.GetControlPoint(1) - cp[3]);
                cp[2] = cp[3] - (v * tanLen);
              
                BezierCurve curve(cp);
                out->push_back(curve);
            }
        }
    }
Esempio n. 13
0
int HCURL_TRI_In_FEM_Test01(const bool verbose) {

  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing

  if (verbose)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs,       false);

  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);

  typedef typename
      Kokkos::Impl::is_space<DeviceSpaceType>::host_mirror_space::execution_space HostSpaceType ;

//  *outStream << "DeviceSpace::  "; DeviceSpaceType::print_configuration(*outStream, false);
//  *outStream << "HostSpace::    ";   HostSpaceType::print_configuration(*outStream, false);

  *outStream
  << "===============================================================================\n"
  << "|                                                                             |\n"
  << "|                      Unit Test HCURL_TRI_In_FEM                             |\n"
  << "|                                                                             |\n"
  << "|  Questions? Contact  Pavel Bochev  ([email protected]),                    |\n"
  << "|                      Robert Kirby  ([email protected]),                |\n"
  << "|                      Denis Ridzal  ([email protected]),                    |\n"
  << "|                      Kara Peterson ([email protected]),                    |\n"
  << "|                      Kyungjoo Kim  ([email protected]),                     |\n"
  << "|                      Mauro Perego  ([email protected]).                    |\n"
  << "|                                                                             |\n"
  << "===============================================================================\n";

  typedef Kokkos::DynRankView<PointValueType,DeviceSpaceType> DynRankViewPointValueType;
  typedef Kokkos::DynRankView<OutValueType,DeviceSpaceType> DynRankViewOutValueType;
  typedef typename ScalarTraits<OutValueType>::scalar_type scalar_type;
  typedef Kokkos::DynRankView<scalar_type, DeviceSpaceType> DynRankViewScalarValueType;
  typedef Kokkos::DynRankView<scalar_type, HostSpaceType> DynRankViewHostScalarValueType;

#define ConstructWithLabelScalar(obj, ...) obj(#obj, __VA_ARGS__)

  const scalar_type tol = tolerence();
  int errorFlag = 0;
  constexpr ordinal_type dim =2;

  typedef Basis_HCURL_TRI_In_FEM<DeviceSpaceType,OutValueType,PointValueType> TriBasisType;
  typedef Basis_HDIV_TRI_In_FEM<DeviceSpaceType,OutValueType,PointValueType> TriBasisHDivType;
  constexpr ordinal_type maxOrder = Parameters::MaxOrder ;

//  constexpr ordinal_type dim = 2;

  try {

    *outStream
    << "\n"
    << "===============================================================================\n"
    << "| TEST 1: Testing OPERATOR_VALUE (Kronecker property using getDofCoeffs)      |\n"
    << "===============================================================================\n";


    const ordinal_type order = std::min(4, maxOrder);
    TriBasisType triBasis(order, POINTTYPE_WARPBLEND);

    const ordinal_type cardinality = triBasis.getCardinality();
    DynRankViewScalarValueType ConstructWithLabelScalar(dofCoords_scalar, cardinality, dim);
    triBasis.getDofCoords(dofCoords_scalar);

    DynRankViewPointValueType ConstructWithLabelPointView(dofCoords, cardinality , dim);
    RealSpaceTools<DeviceSpaceType>::clone(dofCoords,dofCoords_scalar);

    DynRankViewScalarValueType ConstructWithLabelScalar(dofCoeffs, cardinality , dim);
    triBasis.getDofCoeffs(dofCoeffs);

    DynRankViewOutValueType ConstructWithLabelOutView(basisAtDofCoords, cardinality , cardinality, dim);
    triBasis.getValues(basisAtDofCoords, dofCoords, OPERATOR_VALUE);

    auto h_basisAtDofCoords = Kokkos::create_mirror_view(basisAtDofCoords);
    Kokkos::deep_copy(h_basisAtDofCoords, basisAtDofCoords);

    auto h_dofCoeffs = Kokkos::create_mirror_view(dofCoeffs);
    Kokkos::deep_copy(h_dofCoeffs, dofCoeffs);

    // test for Kronecker property
    for (int i=0;i<cardinality;i++) {
      for (int j=0;j<cardinality;j++) {
        OutValueType dofValue = 0;
        for (ordinal_type k=0;k<dim; k++)
          dofValue += h_basisAtDofCoords(i,j,k)*h_dofCoeffs(j,k);

        if ( i==j && std::abs( dofValue - 1.0 ) > tol ) {
          errorFlag++;
          *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
          *outStream << " Basis function " << i << " does not have unit value at its node (" << dofValue <<")\n";
        }
        if ( i!=j && std::abs( dofValue ) > tol ) {
          errorFlag++;
          *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
          *outStream << " Basis function " << i << " does not vanish at node " << j << "(" << dofValue <<")\n";
        }

      }
    }
  } catch (std::exception err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };

  try {

    *outStream
    << "\n"
    << "=======================================================================================\n"
    << "| TEST 2: Testing OPERATOR_VALUE (Kronecker property, reconstructing dofs using tags) |\n"
    << "=======================================================================================\n";


    const ordinal_type order = std::min(4, maxOrder);
    TriBasisType triBasis(order, POINTTYPE_WARPBLEND);

    const ordinal_type cardinality = triBasis.getCardinality();
    DynRankViewScalarValueType ConstructWithLabelScalar(dofCoords_scalar, cardinality , dim);
    triBasis.getDofCoords(dofCoords_scalar);

    DynRankViewPointValueType ConstructWithLabelPointView(dofCoords, cardinality , dim);
    RealSpaceTools<DeviceSpaceType>::clone(dofCoords,dofCoords_scalar);

    DynRankViewOutValueType ConstructWithLabelOutView(basisAtDofCoords, cardinality , cardinality, dim);
    triBasis.getValues(basisAtDofCoords, dofCoords, OPERATOR_VALUE);

    auto h_basisAtDofCoords = Kokkos::create_mirror_view(basisAtDofCoords);
    Kokkos::deep_copy(h_basisAtDofCoords, basisAtDofCoords);

    // Dimensions for the output arrays:
    const ordinal_type numFields = triBasis.getCardinality();

    //Normals at each edge
    DynRankViewHostScalarValueType ConstructWithLabelScalar(tangents, numFields,dim); // normals at each point basis point
    tangents(0,0)  =  1.0; tangents(0,1)  = 0.0;
    tangents(1,0)  =  -1.0; tangents(1,1)  =  1.0;
    tangents(2,0)  =  0.0; tangents(2,1)  =  -1.0;

    const auto allTags = triBasis.getAllDofTags();

    // test for Kronecker property
    for (int i=0;i<numFields;i++) {
      for (int j=0;j<numFields;j++) {
        OutValueType dofValue = 0;
        if(allTags(j,0) == dim-1) { //edge
          auto edgeId = allTags(j,1);
          for (ordinal_type k=0;k<dim; k++)
            dofValue += h_basisAtDofCoords(i,j,k)*tangents(edgeId,k);
        }
        else { //elem
          auto elemDofId =  allTags(j,2);
          dofValue = h_basisAtDofCoords(i,j,elemDofId%dim);
        }

        if ( i==j && std::abs( dofValue - 1.0 ) > tol ) {
          errorFlag++;
          *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
          *outStream << " Basis function " << i << " does not have unit value at its node (" << dofValue <<")\n";
        }
        if ( i!=j && std::abs( dofValue ) > tol ) {
          errorFlag++;
          *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
          *outStream << " Basis function " << i << " does not vanish at node " << j << "(" << dofValue <<")\n";
        }

      }
    }

  } catch (std::exception err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };

  try {

    *outStream
    << "\n"
    << "===============================================================================\n"
    << "| TEST 3: Testing OPERATOR_VALUE (orthogonality with HDiv)                    |\n"
    << "===============================================================================\n";


    const ordinal_type order = 1;

    TriBasisType triBasis(order, POINTTYPE_EQUISPACED);
    TriBasisHDivType triBasisHDiv(order, POINTTYPE_EQUISPACED);

    shards::CellTopology tri_3(shards::getCellTopologyData<shards::Triangle<3> >());
    const ordinal_type np_lattice = PointTools::getLatticeSize(tri_3, order,0);
    const ordinal_type cardinality = triBasis.getCardinality();
    DynRankViewHostScalarValueType ConstructWithLabelScalar(lattice_host_scalar, np_lattice , dim);
    PointTools::getLattice(lattice_host_scalar, tri_3, order, 0, POINTTYPE_EQUISPACED);

    auto lattice_scalar = Kokkos::create_mirror_view(typename DeviceSpaceType::memory_space(), lattice_host_scalar);
    deep_copy(lattice_scalar, lattice_host_scalar);

    DynRankViewPointValueType ConstructWithLabelPointView(lattice, np_lattice , dim);
    RealSpaceTools<DeviceSpaceType>::clone(lattice,lattice_scalar);

    DynRankViewOutValueType ConstructWithLabelOutView(basisAtLattice, cardinality , np_lattice, dim);
    triBasis.getValues(basisAtLattice, lattice, OPERATOR_VALUE);
    DynRankViewOutValueType ConstructWithLabelOutView(basisHDivAtLattice, cardinality , np_lattice, dim);
    triBasisHDiv.getValues(basisHDivAtLattice, lattice, OPERATOR_VALUE);

    auto h_basisAtLattice = Kokkos::create_mirror_view(basisAtLattice);
    Kokkos::deep_copy(h_basisAtLattice, basisAtLattice);
    auto h_basisHDivAtLattice = Kokkos::create_mirror_view(basisHDivAtLattice);
    Kokkos::deep_copy(h_basisHDivAtLattice, basisHDivAtLattice);
    const ordinal_type numFields = triBasis.getCardinality();

    for (int i=0;i<numFields;i++) {
      for (int j=0;j<np_lattice;j++) {
        if (std::abs( h_basisHDivAtLattice(i,j,1) + h_basisAtLattice(i,j,0) ) > tol ) {
          errorFlag++;
          *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
          // Output the multi-index of the value where the error is:
          *outStream << " At multi-index { ";
          *outStream << i << " " << j << " and component 0";
          *outStream << "}  computed value: " << h_basisAtLattice(i,j,0)
                            << " but correct value: " << -h_basisHDivAtLattice(i,j,1) << "\n";
          *outStream << "Difference: " << std::abs( h_basisAtLattice(i,j,0) + h_basisHDivAtLattice(i,j,1) ) << "\n";
        }
        if (std::abs( h_basisHDivAtLattice(i,j,0) - h_basisAtLattice(i,j,1) ) > tol ) {
          errorFlag++;
          *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
          // Output the multi-index of the value where the error is:
          *outStream << " At multi-index { ";
          *outStream << i << " " << j << " and component 1";
          *outStream << "}  computed value: " << h_basisAtLattice(i,j,1)
                            << " but correct value: " << h_basisHDivAtLattice(i,j,0) << "\n";
          *outStream << "Difference: " << std::abs( h_basisAtLattice(i,j,1) - h_basisHDivAtLattice(i,j,1) ) << "\n";
        }
      }
    }

  } catch (std::exception err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };



  try {

    *outStream
    << "\n"
    << "===============================================================================\n"
    << "| TEST 4: Testing OPERATOR_VALUE (FIAT Values)                                |\n"
    << "===============================================================================\n";


    constexpr ordinal_type order = 2;
    if(order <= maxOrder) {
      TriBasisType triBasis(order, POINTTYPE_EQUISPACED);

      shards::CellTopology tri_3(shards::getCellTopologyData<shards::Triangle<3> >());
      const ordinal_type np_lattice = PointTools::getLatticeSize(tri_3, order,0);
      const ordinal_type cardinality = triBasis.getCardinality();
      DynRankViewHostScalarValueType ConstructWithLabelScalar(lattice_host_scalar, np_lattice , dim);
      PointTools::getLattice(lattice_host_scalar, tri_3, order, 0, POINTTYPE_EQUISPACED);

      auto lattice_scalar = Kokkos::create_mirror_view(typename DeviceSpaceType::memory_space(), lattice_host_scalar);
      deep_copy(lattice_scalar, lattice_host_scalar);

      DynRankViewPointValueType ConstructWithLabelPointView(lattice, np_lattice , dim);
      RealSpaceTools<DeviceSpaceType>::clone(lattice,lattice_scalar);

      DynRankViewOutValueType ConstructWithLabelOutView(basisAtLattice, cardinality , np_lattice, dim);
      triBasis.getValues(basisAtLattice, lattice, OPERATOR_VALUE);

      auto h_basisAtLattice = Kokkos::create_mirror_view(basisAtLattice);
      Kokkos::deep_copy(h_basisAtLattice, basisAtLattice);

      const scalar_type fiat_vals[] = {
          2.000000000000000e+00, 0.000000000000000e+00,
          5.000000000000000e-01, 2.500000000000000e-01,
          -1.000000000000000e+00, -1.000000000000000e+00,
          2.500000000000000e-01, 0.000000000000000e+00,
          -5.000000000000000e-01, -5.000000000000000e-01,
          0.000000000000000e+00, 0.000000000000000e+00,
          -1.000000000000000e+00, 0.000000000000000e+00,
          5.000000000000000e-01, 2.500000000000000e-01,
          2.000000000000000e+00, 2.000000000000000e+00,
          -5.000000000000000e-01, 0.000000000000000e+00,
          2.500000000000000e-01, 2.500000000000000e-01,
          0.000000000000000e+00, 0.000000000000000e+00,
          0.000000000000000e+00, 0.000000000000000e+00,
          0.000000000000000e+00, 2.500000000000000e-01,
          0.000000000000000e+00, 2.000000000000000e+00,
          5.000000000000000e-01, 0.000000000000000e+00,
          -2.500000000000000e-01, 2.500000000000000e-01,
          1.000000000000000e+00, 0.000000000000000e+00,
          0.000000000000000e+00, 0.000000000000000e+00,
          0.000000000000000e+00, -5.000000000000000e-01,
          0.000000000000000e+00, -1.000000000000000e+00,
          -2.500000000000000e-01, 0.000000000000000e+00,
          -2.500000000000000e-01, 2.500000000000000e-01,
          -2.000000000000000e+00, 0.000000000000000e+00,
          0.000000000000000e+00, 1.000000000000000e+00,
          0.000000000000000e+00, 5.000000000000000e-01,
          0.000000000000000e+00, 0.000000000000000e+00,
          -2.500000000000000e-01, -5.000000000000000e-01,
          -2.500000000000000e-01, -2.500000000000000e-01,
          -2.000000000000000e+00, -2.000000000000000e+00,
          0.000000000000000e+00, -2.000000000000000e+00,
          0.000000000000000e+00, -2.500000000000000e-01,
          0.000000000000000e+00, 0.000000000000000e+00,
          -2.500000000000000e-01, -5.000000000000000e-01,
          5.000000000000000e-01, 5.000000000000000e-01,
          1.000000000000000e+00, 1.000000000000000e+00,
          0.000000000000000e+00, 0.000000000000000e+00,
          0.000000000000000e+00, -7.500000000000000e-01,
          0.000000000000000e+00, 0.000000000000000e+00,
          1.500000000000000e+00, 0.000000000000000e+00,
          7.500000000000000e-01, 7.500000000000000e-01,
          0.000000000000000e+00, 0.000000000000000e+00,
          0.000000000000000e+00, 0.000000000000000e+00,
          0.000000000000000e+00, 1.500000000000000e+00,
          0.000000000000000e+00, 0.000000000000000e+00,
          -7.500000000000000e-01, 0.000000000000000e+00,
          7.500000000000000e-01, 7.500000000000000e-01,
          0.000000000000000e+00, 0.000000000000000e+00
      };

      ordinal_type cur=0;
      for (ordinal_type i=0;i<cardinality;i++) {
        for (ordinal_type j=0;j<np_lattice;j++) {
          for (ordinal_type k=0;k<dim; k++) {
            if (std::abs( h_basisAtLattice(i,j,k) - fiat_vals[cur] ) > tol ) {
              errorFlag++;
              *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

              // Output the multi-index of the value where the error is:
              *outStream << " At multi-index { ";
              *outStream << i << " " << j << " " << k;
              *outStream << "}  computed value: " <<  h_basisAtLattice(i,j,k)
                            << " but correct value: " << fiat_vals[cur] << "\n";
              *outStream << "Difference: " << std::fabs(  h_basisAtLattice(i,j,k) - fiat_vals[cur] ) << "\n";
            }
            cur++;
          }
        }
      }
    }

  } catch (std::exception err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };

  try {

    *outStream
    << "\n"
    << "===============================================================================\n"
    << "| TEST 5: Testing Operator CURL                                               |\n"
    << "===============================================================================\n";


    constexpr ordinal_type order = 2;
    if(order <= maxOrder) {
      shards::CellTopology tri_3(shards::getCellTopologyData<shards::Triangle<3> >());
      TriBasisType triBasis(order, POINTTYPE_EQUISPACED);
      const ordinal_type cardinality = triBasis.getCardinality();
      const ordinal_type np_lattice = PointTools::getLatticeSize(tri_3, order,0);
      DynRankViewHostScalarValueType ConstructWithLabelScalar(lattice_host_scalar, np_lattice , dim);
      PointTools::getLattice(lattice_host_scalar, tri_3, order, 0, POINTTYPE_EQUISPACED);

      auto lattice_scalar = Kokkos::create_mirror_view(typename DeviceSpaceType::memory_space(), lattice_host_scalar);
      deep_copy(lattice_scalar, lattice_host_scalar);

      DynRankViewPointValueType ConstructWithLabelPointView(lattice, np_lattice , dim);
      RealSpaceTools<DeviceSpaceType>::clone(lattice,lattice_scalar);

      DynRankViewOutValueType ConstructWithLabelOutView(basisDivAtLattice, cardinality , np_lattice);
      triBasis.getValues(basisDivAtLattice, lattice, OPERATOR_CURL);


      auto h_basisDivAtLattice = Kokkos::create_mirror_view(basisDivAtLattice);
      Kokkos::deep_copy(h_basisDivAtLattice, basisDivAtLattice);

      const scalar_type fiat_divs[] = {
        7.000000000000000e+00,
        2.500000000000000e+00,
        -2.000000000000000e+00,
        2.500000000000000e+00,
        -2.000000000000000e+00,
        -2.000000000000000e+00,
        -2.000000000000000e+00,
        2.500000000000000e+00,
        7.000000000000000e+00,
        -2.000000000000000e+00,
        2.500000000000000e+00,
        -2.000000000000000e+00,
        -2.000000000000000e+00,
        2.500000000000000e+00,
        7.000000000000000e+00,
        -2.000000000000000e+00,
        2.500000000000000e+00,
        -2.000000000000000e+00,
        -2.000000000000000e+00,
        -2.000000000000000e+00,
        -2.000000000000000e+00,
        2.500000000000000e+00,
        2.500000000000000e+00,
        7.000000000000000e+00,
        -2.000000000000000e+00,
        -2.000000000000000e+00,
        -2.000000000000000e+00,
        2.500000000000000e+00,
        2.500000000000000e+00,
        7.000000000000000e+00,
        7.000000000000000e+00,
        2.500000000000000e+00,
        -2.000000000000000e+00,
        2.500000000000000e+00,
        -2.000000000000000e+00,
        -2.000000000000000e+00,
        -9.000000000000000e+00,
        -4.500000000000000e+00,
        0.000000000000000e+00,
        0.000000000000000e+00,
        4.500000000000000e+00,
        9.000000000000000e+00,
        9.000000000000000e+00,
        0.000000000000000e+00,
        -9.000000000000000e+00,
        4.500000000000000e+00,
        -4.500000000000000e+00,
        0.000000000000000e+00
    };


    ordinal_type cur=0;
    for (ordinal_type i=0;i<cardinality;i++) {
      for (ordinal_type j=0;j<np_lattice;j++) {
        if (std::abs( h_basisDivAtLattice(i,j) - fiat_divs[cur] ) > tol ) {
          errorFlag++;
          *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

          // Output the multi-index of the value where the error is:
          *outStream << " At multi-index { ";
          *outStream << i << " " << j;
          *outStream << "}  computed value: " <<  h_basisDivAtLattice(i,j)
                          << " but correct value: " << fiat_divs[cur] << "\n";
          *outStream << "Difference: " << std::fabs(  h_basisDivAtLattice(i,j) - fiat_divs[cur] ) << "\n";
        }
        cur++;
      }
    }
    }
  } catch (std::exception err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };

  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";

  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);

  return errorFlag;
}
Esempio n. 14
0
std::vector<glm::vec3> generate_tangents(tinyobj::mesh_t const& model) {
    // containers for vetex attributes
    std::vector<glm::vec3> positions(model.positions.size() / 3);
    std::vector<glm::vec3> normals(model.positions.size() / 3);
    std::vector<glm::vec2> texcoords(model.positions.size() / 3);
    std::vector<glm::vec3> tangents(model.positions.size() / 3, glm::vec3{0.0f});

    // get vertex positions and texture coordinates from mesh_t
    for (unsigned i = 0; i < model.positions.size(); i+=3) {
        positions[i / 3] = glm::vec3{model.positions[i],
                                     model.positions[i + 1],
                                     model.positions[i + 2]};
        normals[i / 3] = glm::vec3{model.normals[i],
                                   model.normals[i + 1],
                                   model.normals[i + 2]};
    }
    for (unsigned i = 0; i < model.texcoords.size(); i+=2) {
        texcoords[i / 2] = glm::vec2{model.texcoords[i], model.texcoords[i + 1]};
    }

    // calculate tangent for triangles
    for (unsigned i = 0; i < model.indices.size() / 3; i++) {
        // indices of vertices of this triangle, access any attribute of first vert with "attribute[indices[0]]"
        unsigned indices[3] = {model.indices[i * 3],
                               model.indices[i * 3 + 1],
                               model.indices[i * 3 + 2]
                              };

        auto p0 = positions[indices[0]];
        auto p1 = positions[indices[1]];
        auto p2 = positions[indices[2]];

        auto t0 = texcoords[indices[0]];
        auto t1 = texcoords[indices[1]];
        auto t2 = texcoords[indices[2]];

        auto dp1 = p1 - p0;
        auto dp2 = p2 - p0;

        auto dt1 = t1 - t0;
        auto dt2 = t2 - t0;

        float inv_t = 1 / dt1.x * dt2.y - dt2.x * dt1.y;

        glm::mat2x2 M = {{dt2.y, -dt1.y}, {-dt2.x, dt1.x}};
        glm::mat3x2 N = {{dp1.x, dp2.x}, {dp1.y, dp2.y}, {dp1.z, dp2.z}};

        auto tangentsWithBi = inv_t * M * N;

        glm::vec3 tangent = glm::transpose(tangentsWithBi)[0];
        tangent = glm::normalize(tangent);

        tangents[indices[0]] = tangent;
        tangents[indices[1]] = tangent;
        tangents[indices[2]] = tangent;
    }

    for (unsigned i = 0; i < tangents.size(); ++i) {
        // orthogonalization and normalization
        auto t = tangents[i];
        auto n = normals[i];
        auto t_prime = t - n * glm::dot(n, t);

        tangents[i] = glm::normalize(t_prime);
    }

    return tangents;
}