Esempio n. 1
0
  Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v) {
    Vec3r res;
    for (unsigned i = 0; i < 3; i++) {
      res[i] = 0;
      for (unsigned j = 0; j < 3; j++)
	res[i] += mat(i, j) * v[j];
    }
    res.normalize();
    return res;
  }
bool Line::intersect(const SphereVolume &sphere,
                           Real         &enter, 
                           Real         &exit  ) const
{
    Vec3r v;
    Pnt3r center;

    sphere.getCenter(center);

    Real radius;
    Real h;
    Real b;
    Real d;
    Real t1;
    Real t2;

    radius = sphere.getRadius();

    v = center - _pos;

    h = (v.dot(v))-(radius * radius);
    b = (v.dot(_dir));

    if(h >= 0.f && b <= 0.f)
        return false;

    d = b * b - h;

    if(d < 0.f)
        return false;

    d  = osgSqrt(d);
    t1 = b - d;

//    if (t1 > 1)
//        return false;

    t2 = b + d;

    if( t1 < TypeTraits<Real>::getDefaultEps() )
    {
        if( t2 < TypeTraits<Real>::getDefaultEps() /*|| t2 > 1*/)
        {
            return false;
        }
    }

    enter = t1;
    exit  = t2;

    return true;
}
Esempio n. 3
0
void FEdgeXDetector::preProcessFace(WXFace *iFace){
    Vec3r firstPoint = iFace->GetVertex(0)->GetVertex();
    Vec3r N = iFace->GetNormal();

    // Compute the dot product between V (=_Viewpoint - firstPoint) and N:
    Vec3r V(_Viewpoint - firstPoint);
    N.normalize();
    V.normalize();
    iFace->SetDotP(N * V);

    // compute the distance between the face center and the viewpoint:
    Vec3r dist_vec(iFace->center() - _Viewpoint);
    iFace->SetZ(dist_vec.norm());
}
Esempio n. 4
0
inline static real angle(WOEdge *h)
{
	const Vec3r& n1 = h->GetbFace()->GetNormal();
	const Vec3r& n2 = h->GetaFace()->GetNormal();
	const Vec3r v = h->GetVec();
	real sine = (n1 ^ n2) * v / v.norm();
	if (sine >= 1.0) {
		return M_PI / 2.0;
	}
	if (sine <= -1.0) {
		return -M_PI / 2.0;
	}
	return ::asin(sine);
}
Esempio n. 5
0
void FEdgeXDetector::ProcessSilhouetteFace(WXFace *iFace, bool meshSilhouettes)
{

    real NdotVepsilonHack = 0;// 0.05; //0.1; //0.01; //0.1;

    // SILHOUETTE LAYER
    // Compute the dot products between View direction and N at each vertex
    // of the face:
    Vec3r point;
    int closestPointId = 0;
    real dist, minDist = FLT_MAX;
    int numVertices = iFace->numberOfVertices();
    WXFaceLayer * faceLayer = new WXFaceLayer(iFace, Nature::SILHOUETTE, true);

    Vec3r normal;
    if(meshSilhouettes){
        // Use per face normal
        normal = (iFace->GetVertex(2)->GetVertex() - iFace->GetVertex(0)->GetVertex()) ^ (iFace->GetVertex(1)->GetVertex() - iFace->GetVertex(0)->GetVertex());
        normal.normalize();
    }

    for(int i=0; i<numVertices; i++){
        point = iFace->GetVertex(i)->GetVertex();
        if(!meshSilhouettes){
            // Use per vertex normal
            normal = iFace->GetVertexNormal(i);
            normal.normalize();
        }
        Vec3r V(_Viewpoint - point);
        V.normalize();
        real d = normal * V + NdotVepsilonHack;
        faceLayer->PushDotP(d);
        // Find the point the closest to the viewpoint
        Vec3r dist_vec(point - _Viewpoint);
        dist = dist_vec.norm();
        if(dist < minDist) {
            minDist = dist;
            closestPointId = i;
        }

        // store ndotv at the vertex for use in the region-based visibility
        //    assert(dynamic_cast<WXVertex*>(iFace->GetVertex(i))!=NULL);
        ((WXVertex*)iFace->GetVertex(i))->setNdotV(d);
    }
    // Set the closest point id:
    faceLayer->SetClosestPointIndex(closestPointId);
    // Add this layer to the face:
    iFace->AddSmoothLayer(faceLayer);
}
Esempio n. 6
0
static real angle_from_cotan(WVertex *vo, WVertex *v1, WVertex *v2)
{
	/* cf. Appendix B and the caption of Table 1 from [Meyer et al 2002] */
	real udotv, denom;

	Vec3r u (v1->GetVertex() - vo->GetVertex());
	Vec3r v(v2->GetVertex() - vo->GetVertex());

	udotv = u * v;
	denom = sqrt(u.squareNorm() * v.squareNorm() - udotv * udotv);

	/* Note: I assume this is what they mean by using atan2(). -Ray Jones */

	/* tan = denom/udotv = y/x (see man page for atan2) */
	return (fabs(atan2(denom, udotv)));
}
Esempio n. 7
0
void MonaghanKernel::monaghanGradient( const Vec3r& r, Vec3r& gradient )
{
    HReal dist = r.length();
    HReal q = dist*m_invH;
    gradient.fill(0.0);
    if( q >= 0 && q < 1 )
    {
        HReal scalar = -3.0f*(2-q)*(2-q);
        scalar += 12.0f*(1-q)*(1-q);
        gradient = (m_g*m_invH*scalar/dist)*r;
    }
    else if ( q >=1 && q < 2 )
    {
        HReal scalar = -3.0f*(2-q)*(2-q);
        gradient = (m_g*scalar*m_invH/dist)*r;
    }
}
Esempio n. 8
0
void Grid::castInfiniteRay(const Vec3r& orig,
			   const Vec3r& dir,
			   OccludersSet& occluders,
			   unsigned timestamp) {
  Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
  bool inter = initInfiniteRay(orig, dir, timestamp);
  if(!inter)
      return;
  allOccludersGridVisitor visitor(occluders);
  castRayInternal(visitor);
}
Esempio n. 9
0
// precondition1: P is inside the sphere
// precondition2: P,V points to the outside of the sphere (i.e. OP.V > 0)
static bool sphere_clip_vector(const Vec3r& O, real r, const Vec3r& P, Vec3r& V)
{
	Vec3r W = P - O;
	real a = V.squareNorm();
	real b = 2.0 * V * W;
	real c = W.squareNorm() - r * r;
	real delta = b * b - 4 * a * c;
	if (delta < 0) {
		// Should not happen, but happens sometimes (numerical precision)
		return true;
	}
	real t = - b + ::sqrt(delta) / (2.0 * a);
	if (t < 0.0) {
		// Should not happen, but happens sometimes (numerical precision)
		return true;
	}
	if (t >= 1.0) {
		// Inside the sphere
		return false;
	}

	V[0] = (t * V.x());
	V[1] = (t * V.y());
	V[2] = (t * V.z());

	return true;
}
void FEdgeXDetector::preProcessFace(WXFace *iFace)
{
	Vec3r firstPoint = iFace->GetVertex(0)->GetVertex();
	Vec3r N = iFace->GetNormal();

	// Compute the dot product between V (=_Viewpoint - firstPoint) and N:
	Vec3r V;
	if (_orthographicProjection) {
		V = Vec3r(0.0, 0.0, _Viewpoint.z() - firstPoint.z());
	}
	else {
		V = Vec3r(_Viewpoint - firstPoint);
	}
	N.normalize();
	V.normalize();
	iFace->setDotP(N * V);

	// compute the distance between the face center and the viewpoint:
	if (_orthographicProjection) {
		iFace->setZ(iFace->center().z() - _Viewpoint.z());
	}
	else {
		Vec3r dist_vec(iFace->center() - _Viewpoint);
		iFace->setZ(dist_vec.norm());
	}
}
Esempio n. 11
0
    void VelocityMotor::internal_update()
    {
        // check if we have a solid
        if (mData.solid == NULL || isEnabled() == false) return ;

        Vec3r targetVelocity = mData.velocity;
        Solid * solid = mData.solid;

        Vec3r currentAchievedVelocity = solid->getGlobalLinearVel();

        if (doesGravityAffectSolid())
        {
            Vec3r gravity = mSimulator->getGravity();
            if (gravity.length() > 0)
            {
                Vec3r gravity_velocity = project(gravity, currentAchievedVelocity);
                currentAchievedVelocity -= gravity_velocity;
            }
        }

        Vec3r deltaVelocity = targetVelocity - currentAchievedVelocity;

        Vec3r forceVector = deltaVelocity / mSimulator->getStepSize() * solid->getMass();
        if (!doesGravityAffectSolid())
            forceVector -= mSimulator->getGravity() * solid->getMass();

        if (forceVector.length() > getMaximumForce())
        {
            forceVector.normalize();
            forceVector *= getMaximumForce();
        }

        Force controllingForce;
        controllingForce.duration = 0;
        controllingForce.singleStep = true;
        controllingForce.type = GLOBAL_FORCE;
        controllingForce.vec = forceVector;

        solid->addForce(controllingForce);
    }
void ThirdPersonCamera::LookAt(const Vec3r &eye, const Vec3r &target, const Vec3r &up)
{
    m_eye = eye;
    m_target = target;
    m_targetYAxis = up;

    m_zAxis = eye - target;
    m_zAxis.Normalise();

    m_viewDir = m_zAxis * -1;

    m_xAxis = Vec3r::CrossProduct(up, m_zAxis);
    m_xAxis.Normalise();

    m_yAxis = Vec3r::CrossProduct(m_zAxis, m_xAxis);
    m_yAxis.Normalise();
   // m_xAxis.Normalise();

    m_viewMatrix.Access(0,0) = m_xAxis.X;
    m_viewMatrix.Access(1,0) = m_xAxis.Y;
    m_viewMatrix.Access(2,0) = m_xAxis.Z;
	m_viewMatrix.Access(3,0) = -Vec3r::DotProduct(m_xAxis, eye);

    m_viewMatrix.Access(0,1) = m_yAxis.X;
    m_viewMatrix.Access(1,1) = m_yAxis.Y;
    m_viewMatrix.Access(2,1) = m_yAxis.Z;
	m_viewMatrix.Access(3,1) = -Vec3r::DotProduct(m_yAxis, eye);
				
    m_viewMatrix.Access(0,2) = m_zAxis.X;
    m_viewMatrix.Access(1,2) = m_zAxis.Y;
    m_viewMatrix.Access(2,2) = m_zAxis.Z;    
	m_viewMatrix.Access(3,2) = -Vec3r::DotProduct(m_zAxis, eye);

	m_orientation.FromMatrix(m_viewMatrix.m_matrix);

    Vec3r offset = m_target - m_eye;

	m_offsetDistance = offset.Length();
}
Esempio n. 13
0
HReal MonaghanKernel::monaghanValue( const Vec3r & r )
{
    HReal value = 0.0;
    HReal q = r.length()*m_invH;
    if( q >= 0 && q < 1 )
    {
        value = m_v*( (2-q)*(2-q)*(2-q) - 4.0f*(1-q)*(1-q)*(1-q));
    }
    else if ( q >=1 && q < 2 )
    {
        value = m_v*( (2-q)*(2-q)*(2-q) );
    }
    else
    {
        value = 0.0f;
    }
    return value;
}
void FEdgeXDetector::ProcessSilhouetteFace(WXFace *iFace)
{
	// SILHOUETTE LAYER
	Vec3r normal;
	// Compute the dot products between View direction and N at each vertex of the face:
	Vec3r point;
	int closestPointId = 0;
	real dist, minDist = FLT_MAX;
	int numVertices = iFace->numberOfVertices();
	WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SILHOUETTE, true);
	for (int i = 0; i < numVertices; i++) {
		point = iFace->GetVertex(i)->GetVertex();
		normal = iFace->GetVertexNormal(i);
		normal.normalize();
		Vec3r V;
		if (_orthographicProjection) {
			V = Vec3r(0.0, 0.0, _Viewpoint.z() - point.z());
		}
		else {
			V = Vec3r(_Viewpoint - point);
		}
		V.normalize();
		real d = normal * V;
		faceLayer->PushDotP(d);
		// Find the point the closest to the viewpoint
		if (_orthographicProjection) {
			dist = point.z() - _Viewpoint.z();
		}
		else {
			Vec3r dist_vec(point - _Viewpoint);
			dist = dist_vec.norm();
		}
		if (dist < minDist) {
			minDist = dist;
			closestPointId = i;
		}
	}
	// Set the closest point id:
	faceLayer->setClosestPointIndex(closestPointId);
	// Add this layer to the face:
	iFace->AddSmoothLayer(faceLayer);
}
Esempio n. 15
0
real CurvePoint::curvature2d_as_angle() const
{
#if 0
	Vec3r edgeA = (_FEdges[0])->orientation2d();
	Vec3r edgeB = (_FEdges[1])->orientation2d();
	Vec2d N1(-edgeA.y(), edgeA.x());
	N1.normalize();
	Vec2d N2(-edgeB.y(), edgeB.x());
	N2.normalize();
	return acos((N1 * N2));
#endif
	if (__A == 0)
		return __B->curvature2d_as_angle();
	if (__B == 0)
		return __A->curvature2d_as_angle();
	return ((1 - _t2d) * __A->curvature2d_as_angle() + _t2d * __B->curvature2d_as_angle());
}
Esempio n. 16
0
    bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir,   // ray origin and direction
        const Vec3r& boxMin, const Vec3r& boxMax, // the bbox
        real t0, real t1,
        real& tmin, real& tmax,                  // I0=orig+tmin*dir is the first intersection, I1=orig+tmax*dir is the second intersection
        real epsilon){

            float tymin, tymax, tzmin, tzmax;
            Vec3r inv_direction(1.0/dir[0], 1.0/dir[1], 1.0/dir[2]);
            int sign[3];
            sign[0] = (inv_direction.x() < 0);
            sign[1] = (inv_direction.y() < 0);
            sign[2] = (inv_direction.z() < 0);

            Vec3r bounds[2];
            bounds[0] = boxMin;
            bounds[1] = boxMax;

            tmin = (bounds[sign[0]].x() - orig.x()) * inv_direction.x();
            tmax = (bounds[1-sign[0]].x() - orig.x()) * inv_direction.x();
            tymin = (bounds[sign[1]].y() - orig.y()) * inv_direction.y();
            tymax = (bounds[1-sign[1]].y() - orig.y()) * inv_direction.y();
            if ( (tmin > tymax) || (tymin > tmax) )
                return false;
            if (tymin > tmin)
                tmin = tymin;
            if (tymax < tmax)
                tmax = tymax;
            tzmin = (bounds[sign[2]].z() - orig.z()) * inv_direction.z();
            tzmax = (bounds[1-sign[2]].z() - orig.z()) * inv_direction.z();
            if ( (tmin > tzmax) || (tzmin > tmax) )
                return false;
            if (tzmin > tmin)
                tmin = tzmin;
            if (tzmax < tmax)
                tmax = tzmax;
            return ( (tmin < t1) && (tmax > t0) );
        }
Esempio n. 17
0
/**
 * @brief 円柱を設定
 * @param [in]     R        Controlクラスのポインタ
 * @param [in]     pos_x     中心座標(x,y) (無次元)
 * @param [in]     pos_y     中心座標(x,y) (無次元)
 * @param [in]     radius    半径 (無次元)
 * @param [in]     len_z     円柱のZ方向の長さ (無次元)
 * @param [in]     mid_solid 固体媒質ID
 * @param [out]    cut       カット情報
 * @param [out]    bid       境界ID
 */
void IP_Cylinder::setCircle(Control* R,
                            const REAL_TYPE pos_x,
                            const REAL_TYPE pos_y,
                            const REAL_TYPE radius,
                            const REAL_TYPE len_z,
                            const int mid_solid,
                            long long* cut,
                            int* bid)
{
  Vec3r pch(pitch);      ///< 無次元格子幅
  Vec3r org(origin);     ///< ノードローカル基点座標の無次元値

  
  REAL_TYPE dx = pitch[0];
  REAL_TYPE dy = pitch[1];
  REAL_TYPE dz = pitch[2];
  
  REAL_TYPE cx = pos_x;  ///< 円柱の中心座標(無次元)
  REAL_TYPE cy = pos_y;  ///< 円柱の中心座標(無次元)
  REAL_TYPE rs = radius; ///< 円柱の半径(無次元)
  
  int mid_s = mid_solid;
  
  // 球のbbox
  Vec3r box_min;  ///< Bounding boxの最小値
  Vec3r box_max;  ///< Bounding boxの最大値
  Vec3i box_st;   ///< Bounding boxの始点インデクス
  Vec3i box_ed;   ///< Bounding boxの終点インデクス
  box_min.assign( -(REAL_TYPE)rs+cx, -(REAL_TYPE)rs+cy, 0.0 ); // Z方向はダミー
  box_max.assign(  (REAL_TYPE)rs+cx,  (REAL_TYPE)rs+cy, 0.0 );
  box_st = find_index(box_min, org, pch);
  box_ed = find_index(box_max, org, pch);
  
  int ix = size[0];
  int jx = size[1];
  int kx = size[2];
  int gd = guide;
  
  
  // ローカルな無次元基点座標
  REAL_TYPE ox = origin[0];
  REAL_TYPE oy = origin[1];
  REAL_TYPE oz = origin[2];
  
  // グローバルな無次元座標
  REAL_TYPE zs = oz;
  REAL_TYPE ze;
  
  if ( mode == dim_2d )
  {
    ze = oz + region[2] + dz; // Z方向には全セルを対象, dzは安全係数
  }
  else
  {
    ze = oz + len_z; // Z-面からの距離
  }
  
  
  // カット情報
  Vec3r p[5];
  Vec3r base;  // セルのシフト量
  Vec3r b;     // セルセンタ座標
  REAL_TYPE lb[5]; // 内外判定フラグ
  
  for (int k=1; k<=kx; k++) {
    for (int j=box_st.y-1; j<=box_ed.y+1; j++) {
      for (int i=box_st.x-1; i<=box_ed.x+1; i++) {
        
        REAL_TYPE z = org.z + 0.5*dz + dz*(REAL_TYPE)(k-1);
        
        if ( z <= ze )
        {
          base.assign((REAL_TYPE)i-0.5, (REAL_TYPE)j-0.5, (REAL_TYPE)k-0.5);
          b = org + base*pch;
          
          p[0].assign(b.x   , b.y   , b.z   ); // p
          p[1].assign(b.x-dx, b.y   , b.z   ); // w
          p[2].assign(b.x+dx, b.y   , b.z   ); // e
          p[3].assign(b.x   , b.y-dy, b.z   ); // s
          p[4].assign(b.x   , b.y+dy, b.z   ); // n
          
          // (cx, cy, *)が球の中心
          for (int l=0; l<5; l++) {
            REAL_TYPE x = p[l].x - cx;
            REAL_TYPE y = p[l].y - cy;
            REAL_TYPE rr = sqrt(x*x + y*y);
            lb[l] = ( rr <= rs ) ? -1.0 : 1.0; // 内側がマイナス
          }
          
          // cut test  注意! インデクスが1-4
          for (int l=1; l<=4; l++)
          {
            if ( lb[0]*lb[l] < 0.0 )
            {
              REAL_TYPE s = cut_line_2d(p[0], l, rs);
              size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd);
              
              int r = quantize9(s);

              setCut9(cut[m], r, l-1);
              setBit5(bid[m], mid_s, l-1);
              
              int rr = quantize9(1.0-s);

              size_t m1;
              
              switch (l-1) {
                case X_minus:
                  m1 = _F_IDX_S3D(i-1, j, k, ix, jx, kx, gd);
                  setBit5(bid[m1], mid_s, X_plus);
                  setCut9(cut[m1], rr, X_plus);
                  break;
                  
                case X_plus:
                  m1 = _F_IDX_S3D(i+1, j, k, ix, jx, kx, gd);
                  setBit5(bid[m1], mid_s, X_minus);
                  setCut9(cut[m1], rr, X_minus);
                  break;
                  
                case Y_minus:
                  m1 = _F_IDX_S3D(i, j-1, k, ix, jx, kx, gd);
                  setBit5(bid[m1], mid_s, Y_plus);
                  setCut9(cut[m1], rr, Y_plus);
                  break;
                  
                case Y_plus:
                  m1 = _F_IDX_S3D(i, j+1, k, ix, jx, kx, gd);
                  setBit5(bid[m1], mid_s, Y_minus);
                  setCut9(cut[m1], rr, Y_minus);
                  break;
              }

            }
          }
        } // if z branch

      }
    }
  }
  
  if ( mode == dim_2d ) return;

  
  // Z+方向
#pragma omp parallel for firstprivate(ix, jx, kx, gd, mid_s, ox, oy, oz, dx, dy, dz, ze, rs, cx, cy) schedule(static)
  for (int k=1; k<=kx; k++) {
    for (int j=1; j<=jx; j++) {
      for (int i=1; i<=ix; i++) {
        size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd);
        REAL_TYPE x = ox + 0.5*dx + dx*(i-1); // position of cell center
        REAL_TYPE y = oy + 0.5*dy + dy*(j-1);
        REAL_TYPE z = oz + 0.5*dz + dz*(k-1);
        REAL_TYPE s = (ze - z)/dz;
        
        REAL_TYPE xx = x - cx;
        REAL_TYPE yy = y - cy;
        
        if ( (xx*xx + yy*yy) <= rs*rs )
        {
          
          if ( (z <= ze) && (ze < z+dz) )
          {
            setBit5(bid[m], mid_s, Z_plus);
            int r = quantize9(s);
            setCut9(cut[m], r, Z_plus);

            size_t m1 = _F_IDX_S3D(i, j, k+1, ix, jx, kx, gd);
            setBit5(bid[m1], mid_s, Z_minus);
            int rr = quantize9(1.0-s);
            setCut9(cut[m1], rr, Z_minus);
          }
          else if ( (z-dz < ze) && (ze < z) )
          {
            setBit5(bid[m], mid_s, Z_minus);
            int r = quantize9(-s);
            setCut9(cut[m], r, Z_minus);

            size_t m1 = _F_IDX_S3D(i, j, k-1, ix, jx, kx, gd);
            setBit5(bid[m1], mid_s, Z_plus);
            int rr = quantize9(1.0+s);
            setCut9(cut[m1], rr, Z_plus);
          }
          
        }
        
      }
    }
  }

  
  // Z-方向
#pragma omp parallel for firstprivate(ix, jx, kx, gd, mid_s, ox, oy, oz, dx, dy, dz, zs, rs, cx, cy) schedule(static)
  for (int k=1; k<=kx; k++) {
    for (int j=1; j<=jx; j++) {
      for (int i=1; i<=ix; i++) {
        size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd);
        REAL_TYPE x = ox + 0.5*dx + dx*(i-1); // position of cell center
        REAL_TYPE y = oy + 0.5*dy + dy*(j-1);
        REAL_TYPE z = oz + 0.5*dz + dz*(k-1);
        REAL_TYPE s = (zs - z)/dz;
        
        REAL_TYPE xx = x - cx;
        REAL_TYPE yy = y - cy;
        
        if ( (xx*xx + yy*yy) <= rs*rs )
        {
          
          if ( (z <= zs) && (zs < z+dz) )
          {
            setBit5(bid[m], mid_s, Z_plus);
            int r = quantize9(s);
            setCut9(cut[m], r, Z_plus);
            
            size_t m1 = _F_IDX_S3D(i, j, k+1, ix, jx, kx, gd);
            setBit5(bid[m1], mid_s, Z_minus);
            int rr = quantize9(1.0-s);
            setCut9(cut[m1], rr, Z_minus);
          }
          else if ( (z-dz < zs) && (zs < z) )
          {
            setBit5(bid[m], mid_s, Z_minus);
            int r = quantize9(-s);
            setCut9(cut[m], r, Z_minus);
            
            size_t m1 = _F_IDX_S3D(i, j, k-1, ix, jx, kx, gd);
            setBit5(bid[m1], mid_s, Z_plus);
            int rr = quantize9(1.0+s);
            setCut9(cut[m1], rr, Z_plus);
          }
          
        }
        
      }
    }
  }
  
  
}
Esempio n. 18
0
bool Line::intersect(const CylinderVolume &cyl, 
                           Real           &enter,  
                           Real           &exit ) const
{
    Real  radius = cyl.getRadius();

    Vec3r adir;
    Vec3r o_adir;
    Pnt3r apos;

    cyl.getAxis(apos, adir);

    o_adir = adir;
    adir.normalize();

    bool isect;

    Real  ln;
    Real  dl;
    Vec3r RC;
    Vec3r n;
    Vec3r D;

    RC = _pos - apos;

    n  = _dir.cross (adir);
    ln =  n  .length(    );

    if(ln == 0.f)    // IntersectionLine is parallel to CylinderAxis
    {
        D  = RC - (RC.dot(adir)) * adir;
        dl = D.length();

        if(dl <= radius)   // line lies in cylinder
        {
            enter = 0.f;
            exit  = Inf;
        }
        else
        {
            return false;
        }
    }
    else
    {
        n.normalize();

        dl    = osgAbs(RC.dot(n));        //shortest distance
        isect = (dl <= radius);

        if(isect)
        {                 // if ray hits cylinder
            Real  t;
            Real  s;
            Vec3r O;

            O = RC.cross(adir);
            t = - (O.dot(n)) / ln;
            O = n.cross(adir);

            O.normalize();

            s = osgAbs (
                (osgSqrt ((radius * radius) - (dl * dl))) / (_dir.dot(O)));

            exit = t + s;

            if(exit < 0.f)
                return false;

            enter = t - s;

            if(enter < 0.f)
                enter = 0.f;
        }
        else
        {
            return false;
        }
    }

    Real t;

    Plane bottom(-adir, apos);

    if(bottom.intersect(*this, t))
    {
        if(bottom.isInHalfSpace(_pos))
        {
            if(t > enter) 
                enter = t;
        }
        else
        {
            if(t < exit) 
                exit = t;
        }
    }
    else
    {
        if(bottom.isInHalfSpace(_pos))
            return false;
    }
    
    Plane top(adir, apos + o_adir);

    if(top.intersect(*this, t))
    {
        if(top.isInHalfSpace(_pos))
        {
            if(t > enter)
                enter = t;
        }
        else
        {
            if(t < exit)
                exit = t;
        }
    }
    else
    {
        if(top.isInHalfSpace(_pos))
            return false;
    }

    return (enter < exit);
}
Esempio n. 19
0
/*! Intersect the line with a triangle.
    \param [in] v0,v1,v2  Points definiting a triangle in CW orientation.
    \param [out] t  If hit, this returns the distance the hit is down the line.
    \param [in,out] norm If non-NULL, this is set to the normal at the point of
            intersection
    \returns True if there is an intersection.

    This algorithm is based on "Fast, Minimum Storage Ray/Triangle Instersection" by
    T. Moeller and B. Trumbore, with the addition of avoiding the computation of
    inv_det when no intersection happens.
 */
bool Line::intersect(const Pnt3r &v0, 
                     const Pnt3r &v1,
                     const Pnt3r &v2, 
                           Real  &t,
                           Vec3r *norm) const
{
    // Eps (1E-6f) didn't work with very small geometries!
    static const Real sEps = 1E-10f;

    // find vectors for two edges sharing v0.
    Vec3r edge1 = v1 - v0;
    Vec3r edge2 = v2 - v0;

    // begin calculating determinant - also used to calculate U parameter.
    Vec3r pvec = _dir.cross(edge2);

    // if determinant is near zero, ray lies in plane of triangle.
    Real det = edge1.dot(pvec);

    Vec3r qvec;

    if(det > sEps)
    {
        // calculate distance from v0 to ray origin.
        Vec3r tvec = _pos - v0;

        // calculate U parameter and test bounds.
        Real u = tvec.dot(pvec);

        if(u < 0.f || u > det)
        {
            return false;
        }

        // prepare to test V parameter.
        qvec = tvec.cross(edge1);

        // calculate V parameter and test bounds.
        Real v = _dir.dot(qvec);

        if(v < 0.f || u + v > det)
        {
            return false;
        }
    }
    else if(det < -sEps)
    {
        // calculate distance from v0 to ray origin.
        Vec3r tvec = _pos - v0;

        // calculate U parameter and test bounds.
        Real u = tvec.dot(pvec);

        if(u > 0.f || u < det)
        {
            return false;
        }

        // prepare to test V parameter.
        qvec = tvec.cross(edge1);

        // calculate V parameter and test bounds.
        Real v = _dir.dot(qvec);

        if(v > 0.f || u + v < det)
        {
            return false;
        }
    }
    else
    {
        return false;  // ray is parallel to the plane of the triangle.
    }

    Real inv_det = 1.0f / det;

    // calculate t, ray intersects triangle.
    t = edge2.dot(qvec) * inv_det;

    if(norm != NULL)
    {
        *norm = edge1.cross(edge2);
        norm->normalize();
    }

    return true;
}
Esempio n. 20
0
// assume the point is inside the triangle
Vec3r ComputeBarycentricCoords(const Vec3r A,const Vec3r B,const Vec3r C,const Vec3r P)
{
  Vec3r BA = B-A;
  Vec3r CA = C-A;
  Vec3r N = BA^CA;
  
  Vec3r PA = A-P;
  Vec3r PB = B-P;
  Vec3r PC = C-P;

  double areaA = (PB^PC) * N;
  double areaB = (PC^PA) * N;
  double areaC = (PA^PB) * N;

#if 0
  // checking
  printf("Barycentric debug: ----------------------------------\n");
  printf("A = [%f %f %f], B = [%f %f %f], C = [%f %f %f]\n",
	 A.x(), A.y(), A.z(),	 B.x(), B.y(), B.z(),	 C.x(), C.y(), C.z());
  printf("P = [%f %f %f]\n", P.x(), P.y(), P.z());
  printf("areas = [%f %f %f]\n", areaA, areaB, areaC);
  printf("plot3([%f %f %f %f],[%f %f %f %f],[%f %f %f %f],'r-');\n",
	 A.x(), B.x(), C.x(), A.x(),
	 A.y(), B.y(), C.y(), A.y(),
	 A.z(), B.z(), C.z(), A.z());
  printf("hold on; plot3(%f,%f,%f,'bo');\n",
	 P.x(),P.y(),P.z());
#endif


  assert(areaA > -0.1 && areaB > -0.1 && areaC > -0.1);
  if (areaA < 0)
    areaA = 0;
  if (areaB < 0)
    areaB = 0;
  if (areaC < 0)
    areaC = 0;

  double totalArea = areaA + areaB + areaC;

  double a = areaA / totalArea;
  double b = areaB / totalArea;
  double c = areaC / totalArea;


  //  printf("c = [%f %f %f]\n", a,b,c);

  Vec3r result(a,b,c);

  return result;
}
Esempio n. 21
0
bool FEdge::intersectParametric(FEdge & fe2, Vec3r viewpoint, real t3D, real u3D)
{
  Vec3r A1 = vertexA()->getPoint3D();
  Vec3r B1 = vertexB()->getPoint3D();
  Vec3r A2 = fe2.vertexA()->getPoint3D();
  Vec3r B2 = fe2.vertexB()->getPoint3D();

  if (sameSide(A1,B1,viewpoint, A2, B2) || sameSide(A2, B2, viewpoint, A1, B1))
    return false;

  // now, there *must* be an intersection.

  // for each edge, the normal of the plane containing the edge and the viewpoint
  Vec3r N1 = (A1-viewpoint) ^ (B1-viewpoint);
  Vec3r N2 = (A2-viewpoint) ^ (B2-viewpoint);

  // direction vector of the intersection of the two planes.
  Vec3r V = N1 ^ N2;

  // check if the planes coincide (i.e., source edges are colinear)
  assert(V.norm() > 0);
  
  // ----- compute t parameter ------

  // form a plane for line 1, normal to the plane containing the viewpoint

  Vec3r BA1 = B1 - A1;
  Vec3r hsNormal1 = N1 ^ BA1;
  
  // intersect ray in direction of V through the plane
  real w1;
  GeomUtils::intersection_test res1 = GeomUtils::intersectLinePlanePN(viewpoint, V, hsNormal1, A1, w1);

  if (res1 != GeomUtils::DO_INTERSECT)
    {
      printf("res1 = %d\n", res1);
      printf("viewpoint = [%f %f %f]\n", viewpoint[0], viewpoint[1], viewpoint[2]);
      printf("A1 = [%f %f %f]\n", A1[0], A1[1], A1[2]);
      printf("B1 = [%f %f %f]\n", B1[0], B1[1], B1[2]);
      printf("A2 = [%f %f %f]\n", A2[0], A2[1], A2[2]);
      printf("B2 = [%f %f %f]\n", B2[0], B2[1], B2[2]);
      printf("N1 = [%f %f %f]\n", N1[0], N1[1], N1[2]);
      printf("N2 = [%f %f %f]\n", N2[0], N2[1], N2[2]);
      printf("V = [%f %f %f]\n", V[0], V[1], V[2]);
      printf("hsNormal1 = [%f %f %f]\n", hsNormal1[0], hsNormal1[1], hsNormal1[2]);
    }

  assert(res1 == GeomUtils::DO_INTERSECT);

  Vec3r pt1 = viewpoint + w1 * V;

  t3D = ((pt1 - A1) * BA1) / (BA1*BA1);

  assert(t3D >=0 && t3D <= 1);

  // if (t3D < 0 || t3D > 1)
    //    return false;


  // ----- compute u parameter ------

  // form a half-space plane for line 2

  Vec3r BA2 = B2 - A2;
  Vec3r hsNormal2 = N2 ^ BA2;
  
  real w2;
  GeomUtils::intersection_test res2 = GeomUtils::intersectLinePlanePN(viewpoint, V, hsNormal2, A2, w2);

  if (res2 != GeomUtils::DO_INTERSECT)
    {
      printf("res1 = %d\n", res1);
      printf("viewpoint = [%f %f %f]\n", viewpoint[0], viewpoint[1], viewpoint[2]);
      printf("A1 = [%f %f %f]\n", A1[0], A1[1], A1[2]);
      printf("B1 = [%f %f %f]\n", B1[0], B1[1], B1[2]);
      printf("A2 = [%f %f %f]\n", A2[0], A2[1], A2[2]);
      printf("B2 = [%f %f %f]\n", B2[0], B2[1], B2[2]);
      printf("N1 = [%f %f %f]\n", N1[0], N1[1], N1[2]);
      printf("N2 = [%f %f %f]\n", N2[0], N2[1], N2[2]);
      printf("V = [%f %f %f]\n", V[0], V[1], V[2]);
      printf("hsNormal2 = [%f %f %f]\n", hsNormal2[0], hsNormal2[1], hsNormal2[2]);
    }

  assert(res2 == GeomUtils::DO_INTERSECT);

  Vec3r pt2 = viewpoint + w2 * V;

  u3D = ((pt2 - A2) * BA2) / (BA2*BA2);

  assert( u3D >=0 && u3D <=1);

  //  if (u3D < 0 || u3D > 1)
  //    return false;


  
  return true;
}
Esempio n. 22
0
Vec2r SilhouetteGeomEngine::WorldToImage2(const Vec3r & M)
{
  Vec3r newPoint = WorldToImage(M);
  return Vec2r(newPoint.x(), newPoint.y());
}
FEdge *ViewEdgeXBuilder::BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer& ifl)
{
	WOEdge *woea, *woeb;
	real ta, tb;
	SVertex *va, *vb;
	FEdgeSmooth *fe;
	// retrieve exact silhouette data
	WXSmoothEdge *se = ifl.fl->getSmoothEdge();

	if (ifl.order) {
		woea = se->woea();
		woeb = se->woeb();
		ta = se->ta();
		tb = se->tb();
	}
	else {
		woea = se->woeb();
		woeb = se->woea();
		ta = se->tb();
		tb = se->ta();
	}

	Vec3r normal;
	// Make the 2 Svertices
	if (feprevious == 0) { // that means that we don't have any vertex already built for that face
		Vec3r A1(woea->GetaVertex()->GetVertex());
		Vec3r A2(woea->GetbVertex()->GetVertex());
		Vec3r A(A1 + ta * (A2 - A1));

		va = MakeSVertex(A, false);
		// Set normal:
		Vec3r NA1(ifl.fl->getFace()->GetVertexNormal(woea->GetaVertex()));
		Vec3r NA2(ifl.fl->getFace()->GetVertexNormal(woea->GetbVertex()));
		Vec3r na((1 - ta) * NA1 + ta * NA2);
		na.normalize();
		va->AddNormal(na);
		normal = na;

		// Set CurvatureInfo
		CurvatureInfo *curvature_info_a =
		        new CurvatureInfo(*(dynamic_cast<WXVertex*>(woea->GetaVertex())->curvatures()),
		                          *(dynamic_cast<WXVertex*>(woea->GetbVertex())->curvatures()), ta);
		va->setCurvatureInfo(curvature_info_a);
	}
	else {
		va = feprevious->vertexB();
	}

	Vec3r B1(woeb->GetaVertex()->GetVertex());
	Vec3r B2(woeb->GetbVertex()->GetVertex());
	Vec3r B(B1 + tb * (B2 - B1));

	if (feprevious && (B - va->point3D()).norm() < 1.0e-6)
		return feprevious;

	vb = MakeSVertex(B, false);
	// Set normal:
	Vec3r NB1(ifl.fl->getFace()->GetVertexNormal(woeb->GetaVertex()));
	Vec3r NB2(ifl.fl->getFace()->GetVertexNormal(woeb->GetbVertex()));
	Vec3r nb((1 - tb) * NB1 + tb * NB2);
	nb.normalize();
	normal += nb;
	vb->AddNormal(nb);

	// Set CurvatureInfo
	CurvatureInfo *curvature_info_b =
	        new CurvatureInfo(*(dynamic_cast<WXVertex*>(woeb->GetaVertex())->curvatures()),
	                          *(dynamic_cast<WXVertex*>(woeb->GetbVertex())->curvatures()), tb);
	vb->setCurvatureInfo(curvature_info_b);

	// Creates the corresponding feature edge
	fe = new FEdgeSmooth(va, vb);
	fe->setNature(ifl.fl->nature());
	fe->setId(_currentFId);
	fe->setFrsMaterialIndex(ifl.fl->getFace()->frs_materialIndex());
	fe->setFace(ifl.fl->getFace());
	fe->setFaceMark(ifl.fl->getFace()->GetMark());
	if (feprevious == 0)
		normal.normalize();
	fe->setNormal(normal);
	fe->setPreviousEdge(feprevious);
	if (feprevious)
		feprevious->setNextEdge(fe);
	_pCurrentSShape->AddEdge(fe);
	va->AddFEdge(fe);
	vb->AddFEdge(fe);

	++_currentFId;
	ifl.fl->userdata = fe;
	return fe;
}
Esempio n. 24
0
bool inBox(const Vec3r& inter, const Vec3r& box_min, const Vec3r& box_max){
    if(((inter.x()>=box_min.x()) && (inter.x() <box_max.x()))
        && ((inter.y()>=box_min.y()) && (inter.y() <box_max.y()))
        && ((inter.z()>=box_min.z()) && (inter.z() <box_max.z()))
        ){
            return true;
        }
        return false;
}
Esempio n. 25
0
/*! gts_vertex_principal_directions:
 *  @v: a #WVertex.
 *  @s: a #GtsSurface.
 *  @Kh: mean curvature normal (a #Vec3r).
 *  @Kg: Gaussian curvature (a real).
 *  @e1: first principal curvature direction (direction of largest curvature).
 *  @e2: second principal curvature direction.
 *
 *  Computes the principal curvature directions at a point given @Kh and @Kg, the mean curvature normal and
 *  Gaussian curvatures at that point, computed with gts_vertex_mean_curvature_normal() and
 *  gts_vertex_gaussian_curvature(), respectively.
 *
 *  Note that this computation is very approximate and tends to be unstable. Smoothing of the surface or the principal
 *  directions may be necessary to achieve reasonable results.
 */
void gts_vertex_principal_directions(WVertex *v, Vec3r Kh, real Kg, Vec3r &e1, Vec3r &e2)
{
	Vec3r N;
	real normKh;

	Vec3r basis1, basis2, d, eig;
	real ve2, vdotN;
	real aterm_da, bterm_da, cterm_da, const_da;
	real aterm_db, bterm_db, cterm_db, const_db;
	real a, b, c;
	real K1, K2;
	real *weights, *kappas, *d1s, *d2s;
	int edge_count;
	real err_e1, err_e2;
	int e;
	WVertex::incoming_edge_iterator itE;

	/* compute unit normal */
	normKh = Kh.norm();

	if (normKh > 0.0) {
		Kh.normalize();
	}
	else {
		/* This vertex is a point of zero mean curvature (flat or saddle point). Compute a normal by averaging
		 * the adjacent triangles
		 */
		N[0] = N[1] = N[2] = 0.0;

		for (itE = v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++)
			N = Vec3r(N + (*itE)->GetaFace()->GetNormal());
		real normN = N.norm();
		if (normN <= 0.0)
			return;
		N.normalize();
	}

	/* construct a basis from N: */
	/* set basis1 to any component not the largest of N */
	basis1[0] =  basis1[1] =  basis1[2] = 0.0;
	if (fabs (N[0]) > fabs (N[1]))
		basis1[1] = 1.0;
	else
		basis1[0] = 1.0;

	/* make basis2 orthogonal to N */
	basis2 = (N ^ basis1);
	basis2.normalize();

	/* make basis1 orthogonal to N and basis2 */
	basis1 = (N ^ basis2);
	basis1.normalize();

	aterm_da = bterm_da = cterm_da = const_da = 0.0;
	aterm_db = bterm_db = cterm_db = const_db = 0.0;
	int nb_edges = v->GetEdges().size();

	weights = (real *)malloc(sizeof(real) * nb_edges);
	kappas = (real *)malloc(sizeof(real) * nb_edges);
	d1s = (real *)malloc(sizeof(real) * nb_edges);
	d2s = (real *)malloc(sizeof(real) * nb_edges);
	edge_count = 0;

	for (itE = v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++) {
		WOEdge *e;
		WFace *f1, *f2;
		real weight, kappa, d1, d2;
		Vec3r vec_edge;
		if (!*itE)
			continue;
		e = *itE;

		/* since this vertex passed the tests in gts_vertex_mean_curvature_normal(), this should be true. */
		//g_assert(gts_edge_face_number (e, s) == 2);

		/* identify the two triangles bordering e in s */
		f1 = e->GetaFace();
		f2 = e->GetbFace();

		/* We are solving for the values of the curvature tensor
		 *     B = [ a b ; b c ].
		 *  The computations here are from section 5 of [Meyer et al 2002].
		 *
		 *  The first step is to calculate the linear equations governing the values of (a,b,c). These can be computed
		 *  by setting the derivatives of the error E to zero (section 5.3).
		 *
		 *  Since a + c = norm(Kh), we only compute the linear equations for dE/da and dE/db. (NB: [Meyer et al 2002]
		 *  has the equation a + b = norm(Kh), but I'm almost positive this is incorrect).
		 *
		 *  Note that the w_ij (defined in section 5.2) are all scaled by (1/8*A_mixed). We drop this uniform scale
		 *  factor because the solution of the linear equations doesn't rely on it.
		 *
		 *  The terms of the linear equations are xterm_dy with x in {a,b,c} and y in {a,b}. There are also const_dy
		 *  terms that are the constant factors in the equations.
		 */

		/* find the vector from v along edge e */
		vec_edge = Vec3r(-1 * e->GetVec());

		ve2 = vec_edge.squareNorm();
		vdotN = vec_edge * N;

		/* section 5.2 - There is a typo in the computation of kappa. The edges should be x_j-x_i. */
		kappa = 2.0 * vdotN / ve2;

		/* section 5.2 */

		/* I don't like performing a minimization where some of the weights can be negative (as can be the case
		 *  if f1 or f2 are obtuse). To ensure all-positive weights, we check for obtuseness. */
		weight = 0.0;
		if (!triangle_obtuse(v, f1)) {
			weight += ve2 * cotan(f1->GetNextOEdge(e->twin())->GetbVertex(), e->GetaVertex(), e->GetbVertex()) / 8.0;
		}
		else {
			if (angle_obtuse(v, f1)) {
				weight += ve2 * f1->getArea() / 4.0;
			}
			else {
				weight += ve2 * f1->getArea() / 8.0;
			}
		}

		if (!triangle_obtuse(v, f2)) {
			weight += ve2 * cotan (f2->GetNextOEdge(e)->GetbVertex(), e->GetaVertex(), e->GetbVertex()) / 8.0;
		}
		else {
			if (angle_obtuse(v, f2)) {
				weight += ve2 * f1->getArea() / 4.0;
			}
			else {
				weight += ve2 * f1->getArea() / 8.0;
			}
		}

		/* projection of edge perpendicular to N (section 5.3) */
		d[0] = vec_edge[0] - vdotN * N[0];
		d[1] = vec_edge[1] - vdotN * N[1];
		d[2] = vec_edge[2] - vdotN * N[2];
		d.normalize();

		/* not explicit in the paper, but necessary. Move d to 2D basis. */
		d1 = d * basis1;
		d2 = d * basis2;

		/* store off the curvature, direction of edge, and weights for later use */
		weights[edge_count] = weight;
		kappas[edge_count] = kappa;
		d1s[edge_count] = d1;
		d2s[edge_count] = d2;
		edge_count++;

		/* Finally, update the linear equations */
		aterm_da += weight * d1 * d1 * d1 * d1;
		bterm_da += weight * d1 * d1 * 2 * d1 * d2;
		cterm_da += weight * d1 * d1 * d2 * d2;
		const_da += weight * d1 * d1 * (-kappa);

		aterm_db += weight * d1 * d2 * d1 * d1;
		bterm_db += weight * d1 * d2 * 2 * d1 * d2;
		cterm_db += weight * d1 * d2 * d2 * d2;
		const_db += weight * d1 * d2 * (-kappa);
	}

	/* now use the identity (Section 5.3) a + c = |Kh| = 2 * kappa_h */
	aterm_da -= cterm_da;
	const_da += cterm_da * normKh;

	aterm_db -= cterm_db;
	const_db += cterm_db * normKh;

	/* check for solvability of the linear system */
	if (((aterm_da * bterm_db - aterm_db * bterm_da) != 0.0) && ((const_da != 0.0) || (const_db != 0.0))) {
		linsolve(aterm_da, bterm_da, -const_da, aterm_db, bterm_db, -const_db, &a, &b);

		c = normKh - a;

		eigenvector(a, b, c, eig);
	}
	else {
		/* region of v is planar */
		eig[0] = 1.0;
		eig[1] = 0.0;
	}

	/* Although the eigenvectors of B are good estimates of the principal directions, it seems that which one is
	 * attached to which curvature direction is a bit arbitrary. This may be a bug in my implementation, or just
	 * a side-effect of the inaccuracy of B due to the discrete nature of the sampling.
	 *
	 * To overcome this behavior, we'll evaluate which assignment best matches the given eigenvectors by comparing
	 * the curvature estimates computed above and the curvatures calculated from the discrete differential operators.
	 */

	gts_vertex_principal_curvatures(0.5 * normKh, Kg, &K1, &K2);

	err_e1 = err_e2 = 0.0;
	/* loop through the values previously saved */
	for (e = 0; e < edge_count; e++) {
		real weight, kappa, d1, d2;
		real temp1, temp2;
		real delta;

		weight = weights[e];
		kappa = kappas[e];
		d1 = d1s[e];
		d2 = d2s[e];

		temp1 = fabs (eig[0] * d1 + eig[1] * d2);
		temp1 = temp1 * temp1;
		temp2 = fabs (eig[1] * d1 - eig[0] * d2);
		temp2 = temp2 * temp2;

		/* err_e1 is for K1 associated with e1 */
		delta = K1 * temp1 + K2 * temp2 - kappa;
		err_e1 += weight * delta * delta;

		/* err_e2 is for K1 associated with e2 */
		delta = K2 * temp1 + K1 * temp2 - kappa;
		err_e2 += weight * delta * delta;
	}
	free (weights);
	free (kappas);
	free (d1s);
	free (d2s);

	/* rotate eig by a right angle if that would decrease the error */
	if (err_e2 < err_e1) {
		real temp = eig[0];

		eig[0] = eig[1];
		eig[1] = -temp;
	}

	e1[0] = eig[0] * basis1[0] + eig[1] * basis2[0];
	e1[1] = eig[0] * basis1[1] + eig[1] * basis2[1];
	e1[2] = eig[0] * basis1[2] + eig[1] * basis2[2];
	e1.normalize();

	/* make N,e1,e2 a right handed coordinate sytem */
	e2 =  N ^ e1;
	e2.normalize();
}