Ejemplo n.º 1
0
void FEdgeXDetector::ProcessCreaseEdge(WXEdge *iEdge)
{
    // CREASE ?
    //---------
    if(iEdge->nature() & Nature::BORDER)
        return;
    WXFace * fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
    WXFace * fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();

    WVertex * aVertex = iEdge->GetaVertex();
    if((fA->GetVertexNormal(aVertex) * fB->GetVertexNormal(aVertex)) <= 0.7) // angle of 140 degrees
        iEdge->AddNature(Nature::CREASE);
}
Ejemplo n.º 2
0
void FEdgeXDetector::ProcessSilhouetteEdge(WXEdge *iEdge, bool meshSilhouettes)
{
    if(iEdge->nature() & Nature::BORDER)
        return;
    // SILHOUETTE ?
    //-------------
    WXFace * fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
    WXFace * fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();

    if((fA->front(_useConsistency))^(fB->front(_useConsistency))){ // fA->visible XOR fB->visible (true if one is 0 and the other is 1)
        // Freestyle is using a hack here to determine if these faces are "smooth" or "sharp."  Specifically,
        // if the normals disagree at a vertex, then it must be "sharp."  This hack broke with the bunny triangle mesh that had planar
        // faces in one version.  New hack includes more tests...

        if(!meshSilhouettes &&
                fA->GetVertexNormal(iEdge->GetaVertex()) == fB->GetVertexNormal(iEdge->GetaVertex()) &&
                fA->GetVertexNormal(iEdge->GetbVertex()) == fB->GetVertexNormal(iEdge->GetbVertex()) &&
                fA->GetVertexNormal(iEdge->GetaVertex()) != fA->GetVertexNormal(iEdge->GetbVertex()))
            // Aaron: added second and third conditions
        {
            //	Vec3r Aa = fA->GetVertexNormal(iEdge->GetaVertex());
            //	Vec3r Ba = fB->GetVertexNormal(iEdge->GetaVertex());
            //	Vec3r Ab = fA->GetVertexNormal(iEdge->GetbVertex());
            //	Vec3r Bb = fB->GetVertexNormal(iEdge->GetbVertex());

            //	printf("Non-silhouette detected\n");
            //	printf("%f %f %f,   %f %f %f\n", Aa[0], Aa[1], Aa[2], Ba[0], Ba[1], Ba[2]);
            //	printf("%f %f %f,   %f %f %f\n", Ab[0], Ab[1], Ab[2], Bb[0], Bb[1], Bb[2]);
            return;
        }

        iEdge->AddNature(Nature::SILHOUETTE);
        if(fB->front(_useConsistency))
            iEdge->SetOrder(1);
        else
            iEdge->SetOrder(-1);
    }
}
Ejemplo n.º 3
0
void FEdgeXDetector::ProcessSilhouetteEdge(WXEdge *iEdge)
{
	if (iEdge->nature() & Nature::BORDER)
		return;
	// SILHOUETTE ?
	//-------------
	WXFace *fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
	WXFace *fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();

	if ((fA->front()) ^ (fB->front())) { // fA->visible XOR fB->visible (true if one is 0 and the other is 1)
		// The only edges we want to set as silhouette edges in this way are the ones with 2 different normals
		// for 1 vertex for these two faces
		//--------------------
		// In reality we only test the normals for 1 of the 2 vertices.
		if (fA->GetVertexNormal(iEdge->GetaVertex()) == fB->GetVertexNormal(iEdge->GetaVertex()))
			return;
		iEdge->AddNature(Nature::SILHOUETTE);
		if (fB->front())
			iEdge->setOrder(1);
		else
			iEdge->setOrder(-1);
	}
}
Ejemplo n.º 4
0
void FEdgeXDetector::postProcessSuggestiveContourFace(WXFace *iFace) {

    // Compute the derivative of the radial curvature in the radial direction,
    // at the two extremities of the smooth edge.
    // If the derivative is smaller than a given threshold _kr_derivative_epsilon,
    // discard the edge.

    // Find the suggestive contour layer of the face (zero or one edge).
    vector<WXFaceLayer*> sc_layers;
    iFace->retrieveSmoothEdgesLayers(Nature::SUGGESTIVE_CONTOUR, sc_layers);
    if(sc_layers.empty())
        return;

    WXFaceLayer *sc_layer;
    sc_layer = sc_layers[0];

    // Compute the derivative value at each vertex of the face, and add it in a vector.
    vector<real> kr_derivatives;

    unsigned vertices_nb = iFace->numberOfVertices();
    WXVertex *v, *opposite_vertex_a, *opposite_vertex_b;
    WXFace *wxf;
    WOEdge *opposite_edge;
    Vec3r opposite_edge_vec, normal_vec, radial_normal_vec, er_vec, v_vec, inter, inter1, inter2, tmp_vec;
    GeomUtils::intersection_test res;
    real kr(0), kr1(0), kr2(0), t;

    for (unsigned i = 0; i < vertices_nb; ++i) {
        v = (WXVertex*)(iFace->GetVertex(i));

        // v is a singular vertex, skip it.
        if (v->isBoundary()) {
            kr_derivatives.push_back(0);
            continue;
        }

        v_vec = v->GetVertex();
        er_vec = v->curvatures()->er;

        // For each vertex, iterate on its adjacent faces.
        for (WVertex::face_iterator fit = v->faces_begin(), fitend = v->faces_end();
             fit != fitend;
             ++fit) {
            wxf = dynamic_cast<WXFace*>(*fit);
            if(!(wxf->getOppositeEdge(v, opposite_edge)))
                continue;

            opposite_vertex_a = (WXVertex*)opposite_edge->GetaVertex();
            opposite_vertex_b = (WXVertex*)opposite_edge->GetbVertex();
            opposite_edge_vec = opposite_vertex_b->GetVertex() - opposite_vertex_a->GetVertex();
            normal_vec = wxf->GetVertexNormal(v); // FIXME: what about e1 ^ e2 ?
            radial_normal_vec = er_vec ^ normal_vec;

            // Test wether the radial plan intersects with the edge at the opposite of v.
            res = GeomUtils::intersectRayPlane(opposite_vertex_a->GetVertex(), opposite_edge_vec,
                                               radial_normal_vec, -(v_vec * radial_normal_vec),
                                               t,
                                               1.e-06);

            // If there is an intersection, compute the value of the derivative ath that point.
            if ((res == GeomUtils::DO_INTERSECT) && (t >= 0) && (t <= 1)) {
                kr = t * opposite_vertex_a->curvatures()->Kr + (1 - t) * opposite_vertex_b->curvatures()->Kr;
                inter = opposite_vertex_a->GetVertex() + t * opposite_edge_vec;
                tmp_vec = inter - v->GetVertex();
                // Is it kr1 or kr2?
                if (tmp_vec * er_vec > 0) {
                    kr2 = kr;
                    inter2 = inter;
                } else {
                    kr1 = kr;
                    inter1 = inter;
                }
            }
        }

        // Now we have kr1 and kr2 along the radial direction, for one vertex of iFace.
        // We have to compute the derivative of kr for that vertex, equal to:
        // (kr2 - kr1) / dist(inter1, inter2).
        // Then we add it to the vector of derivatives.
        v->curvatures()->dKr = (kr2 - kr1) / (inter2 - inter1).norm();
        kr_derivatives.push_back(v->curvatures()->dKr);
    }

    // At that point, we have the derivatives for each vertex of iFace.
    // All we have to do now is to use linear interpolation to compute the values at
    // the extremities of the smooth edge.
    WXSmoothEdge *sc_edge = sc_layer->getSmoothEdge();
    WOEdge *sc_oedge = sc_edge->woea();
    t = sc_edge->ta();
    if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
            (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < _kr_derivative_epsilon) {
        sc_layer->removeSmoothEdge();
        return;
    }
    sc_oedge = sc_edge->woeb();
    t = sc_edge->tb();
    if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
            (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < _kr_derivative_epsilon)
        sc_layer->removeSmoothEdge();
}