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); }
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); } }
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); } }
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(); }