예제 #1
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);
}
예제 #2
0
void FEdgeXDetector::ProcessSuggestiveContourFace(WXFace *iFace)
{
	WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SUGGESTIVE_CONTOUR, true);
	iFace->AddSmoothLayer(faceLayer);

	unsigned int numVertices = iFace->numberOfVertices();
	for (unsigned int i = 0; i < numVertices; ++i) {
		WVertex *wv = iFace->GetVertex(i);
		WXVertex *wxv = dynamic_cast<WXVertex*>(wv);
		faceLayer->PushDotP(wxv->curvatures()->Kr);
	}

#if 0 // FIXME: find a more clever way to compute the threshold
	real threshold = _meanKr;
	if (faceLayer->nPosDotP()!=numVertices) {
		if ((fabs(faceLayer->dotP(0)) < threshold) && (fabs(faceLayer->dotP(1)) < threshold) &&
		    (fabs(faceLayer->dotP(2)) < threshold))
		{
			faceLayer->ReplaceDotP(0, 0);
			faceLayer->ReplaceDotP(1, 0);
			faceLayer->ReplaceDotP(2, 0);
		}
	}
#endif
}
예제 #3
0
// RIDGES
/////////
void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace)
{
	WXFaceLayer *flayer = new WXFaceLayer(iFace, Nature::RIDGE | Nature::VALLEY, false);
	iFace->AddSmoothLayer(flayer);

	unsigned int numVertices = iFace->numberOfVertices();
	for (unsigned int i = 0; i < numVertices; ++i) {
		WVertex *wv = iFace->GetVertex(i);
		WXVertex *wxv = dynamic_cast<WXVertex*>(wv);
		flayer->PushDotP(wxv->curvatures()->K1);
	}

#if 0 // XXX fabs(flayer->dotP(i)) < threshold cannot be true
	real threshold = 0;
	//real threshold = _maxK1 - (_maxK1 - _meanK1) / 20.0;

	if (flayer->nPosDotP() != numVertices) {
		if ((fabs(flayer->dotP(0)) < threshold) && (fabs(flayer->dotP(1)) < threshold) &&
		    (fabs(flayer->dotP(2)) < threshold))
		{
			flayer->ReplaceDotP(0, 0);
			flayer->ReplaceDotP(1, 0);
			flayer->ReplaceDotP(2, 0);
		}
	}
#endif
}
예제 #4
0
void FEdgeXDetector::ProcessSilhouetteFace(WXFace *iFace)
{
	// SILHOUETTE LAYER
	Vec3f normal;
	// Compute the dot products between View direction and N at each vertex of the face:
	Vec3f point;
	int closestPointId = 0;
	float 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();
		Vec3f V;
		if (_orthographicProjection) {
			V = Vec3f(0.0f, 0.0f, _Viewpoint.z() - point.z());
		}
		else {
			V = Vec3f(_Viewpoint - point);
		}
		V.normalize();
		float d = normal * V;
		faceLayer->PushDotP(d);
		// Find the point the closest to the viewpoint
		if (_orthographicProjection) {
			dist = point.z() - _Viewpoint.z();
		}
		else {
			Vec3f 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);
}
예제 #5
0
void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace)
{
	// RIDGE LAYER
	// Compute the RidgeFunction, that is the derivative of the ppal curvature along e1 at each vertex of the face
	WVertex *v;
	Vec3r v1v2;
	real t;
	vector<WXFaceLayer*> SmoothLayers;
	WXFaceLayer *faceLayer;
	Face_Curvature_Info *layer_info;
	real K1_a(0), K1_b(0);
	Vec3r Inter_a, Inter_b;

	// find the ridge layer of the face
	iFace->retrieveSmoothLayers(Nature::RIDGE, SmoothLayers);
	if ( SmoothLayers.size()!=1 )
		return;
	faceLayer = SmoothLayers[0];
	// retrieve the curvature info of this layer
	layer_info = (Face_Curvature_Info *)faceLayer->userdata;

	int numVertices = iFace->numberOfVertices();
	for (int i = 0; i < numVertices; i++) {
		v = iFace->GetVertex(i);
		// vec_curvature_info[i] contains the curvature info of this vertex
		Vec3r e2 = layer_info->vec_curvature_info[i]->K2*layer_info->vec_curvature_info[i]->e2;
		Vec3r e1 = layer_info->vec_curvature_info[i]->K1*layer_info->vec_curvature_info[i]->e1;
		e2.normalize();

		WVertex::face_iterator fit = v->faces_begin();
		WVertex::face_iterator fitend = v->faces_end();
		for (; fit != fitend; ++fit) {
			WXFace *wxf = dynamic_cast<WXFace*>(*fit);
			WOEdge *oppositeEdge;
			if (!(wxf->getOppositeEdge(v, oppositeEdge)))
				continue;
			v1v2 = oppositeEdge->GetbVertex()->GetVertex() - oppositeEdge->GetaVertex()->GetVertex();
			GeomUtils::intersection_test res;
			res = GeomUtils::intersectRayPlane(oppositeEdge->GetaVertex()->GetVertex(), v1v2, e2, -(v->GetVertex()*e2),
			                                   t, 1.0e-06);
			if ((res == GeomUtils::DO_INTERSECT) && (t >= 0.0) && (t <= 1.0)) {
				vector<WXFaceLayer*> second_ridge_layer;
				wxf->retrieveSmoothLayers(Nature::RIDGE, second_ridge_layer);
				if (second_ridge_layer.size() != 1)
					continue;
				Face_Curvature_Info *second_layer_info = (Face_Curvature_Info*)second_ridge_layer[0]->userdata;

				unsigned index1 = wxf->GetIndex(oppositeEdge->GetaVertex());
				unsigned index2 = wxf->GetIndex(oppositeEdge->GetbVertex());
				real K1_1 = second_layer_info->vec_curvature_info[index1]->K1;
				real K1_2 = second_layer_info->vec_curvature_info[index2]->K1;
				real K1 = (1.0 - t) * K1_1 + t * K1_2;
				Vec3r inter((1.0 - t) * oppositeEdge->GetaVertex()->GetVertex() +
				            t * oppositeEdge->GetbVertex()->GetVertex());
				Vec3r vtmp(inter - v->GetVertex());
				// is it K1_a or K1_b ?
				if (vtmp * e1 > 0) {
					K1_b = K1;
					Inter_b = inter;
				}
				else {
					K1_a = K1;
					Inter_a = inter;
				}
			}
		}
		// Once we have K1 along the ppal direction compute the derivative : K1b - K1a put it in DotP
		//real d = fabs(K1_b) - fabs(K1_a);
		real d = 0;
		real threshold = _meanK1 + (_maxK1 - _meanK1) / 7.0;
		//real threshold = _meanK1;
		//if ((fabs(K1_b) > threshold) || ((fabs(K1_a) > threshold)))
		d = (K1_b) - (K1_a) / (Inter_b - Inter_a).norm();
		faceLayer->PushDotP(d);
		//faceLayer->PushDotP(layer_info->vec_curvature_info[i]->K1);
	}

	// Make the values relevant by checking whether all principal directions have the "same" direction:
	Vec3r e0((layer_info->vec_curvature_info[0]->K1 * layer_info->vec_curvature_info[0]->e1));
	e0.normalize();
	Vec3r e1((layer_info->vec_curvature_info[1]->K1 * layer_info->vec_curvature_info[1]->e1));
	e1.normalize();
	Vec3r e2((layer_info->vec_curvature_info[2]->K1 * layer_info->vec_curvature_info[2]->e1));
	e2.normalize();
	if (e0 * e1 < 0)
		// invert dotP[1]
		faceLayer->ReplaceDotP(1, -faceLayer->dotP(1));
	if (e0 * e2 < 0)
		// invert dotP[2]
		faceLayer->ReplaceDotP(2, -faceLayer->dotP(2));

#if 0 // remove the weakest values;
	real minDiff = (_maxK1 - _minK1) / 10.0;
	real minDiff = _meanK1;
	if ((faceLayer->dotP(0) < minDiff) && (faceLayer->dotP(1) < minDiff) && (faceLayer->dotP(2) < minDiff)) {
		faceLayer->ReplaceDotP(0, 0);
		faceLayer->ReplaceDotP(1, 0);
		faceLayer->ReplaceDotP(2, 0);
	}
#endif
}
OWXFaceLayer ViewEdgeXBuilder::FindPreviousFaceLayer(const OWXFaceLayer& iFaceLayer)
{
	WXFace *previousFace = NULL;
	WOEdge *woebegin;
	real tend;
	if (iFaceLayer.order) {
		woebegin = iFaceLayer.fl->getSmoothEdge()->woea();
		tend = iFaceLayer.fl->getSmoothEdge()->ta();
	}
	else {
		woebegin = iFaceLayer.fl->getSmoothEdge()->woeb();
		tend = iFaceLayer.fl->getSmoothEdge()->tb();
	}

	// special case of EDGE_VERTEX config:
	if ((tend == 0.0) || (tend == 1.0)) {
		WVertex *previousVertex;
		if (tend == 0.0)
			previousVertex = woebegin->GetaVertex();
		else
			previousVertex = woebegin->GetbVertex();
		if (previousVertex->isBoundary()) // if it's a non-manifold vertex -> ignore
			return OWXFaceLayer(NULL, true);
		bool found = false;
		WVertex::face_iterator f = previousVertex->faces_begin();
		WVertex::face_iterator fend = previousVertex->faces_end();
		for (; (!found) && (f != fend); ++f) {
			previousFace = dynamic_cast<WXFace*>(*f);
			if ((0 != previousFace) && (previousFace != iFaceLayer.fl->getFace())) {
				vector<WXFaceLayer*> sameNatureLayers;
				previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
				// don't know... Maybe should test whether this face has also a vertex_edge configuration
				if (sameNatureLayers.size() == 1) {
					WXFaceLayer *winner = sameNatureLayers[0];
					// check face mark continuity
					if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
						return OWXFaceLayer(NULL, true);
					if (woebegin == winner->getSmoothEdge()->woeb()->twin())
						return OWXFaceLayer(winner, true);
					else
						return OWXFaceLayer(winner, false);
				}
			}
		}
	}
	else {
		previousFace = dynamic_cast<WXFace*>(iFaceLayer.fl->getFace()->GetBordingFace(woebegin));
		if (0 == previousFace)
			return OWXFaceLayer(NULL, true);
		// if the next face layer has either no smooth edge or no smooth edge of same nature, no next face
		if (!previousFace->hasSmoothEdges())
			return OWXFaceLayer(NULL, true);
		vector<WXFaceLayer*> sameNatureLayers;
		previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
		// don't know how to deal with several edges of same nature on a single face
		if ((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) {
			return OWXFaceLayer(NULL, true);
		}
		else {
			WXFaceLayer *winner = sameNatureLayers[0];
			// check face mark continuity
			if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
				return OWXFaceLayer(NULL, true);
			if (woebegin == winner->getSmoothEdge()->woeb()->twin())
				return OWXFaceLayer(winner, true);
			else
				return OWXFaceLayer(winner, false);
		}
	}
	return OWXFaceLayer(NULL, true);
}