/************************************************************************ Yutaka Ohtake Smoother.cpp Smoothing methods Copyright (c) 1999-2001 The University of Aizu. All Rights Reserved. ************************************************************************/ #include "stdafx.h" #include "MeshEditor.h" #include "Smoother.h" #include "FieldEnergy.h" #include "EnergyMinimizer.h" #include "Membrace.h" #include "ThinPlate.h" #include "NormalError.h" #include "PBCG.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif #define E 2.7182818284590 #define PI 3.14159265 ////////////////////////////////////////////////////////////////////// // \z/ ////////////////////////////////////////////////////////////////////// Smoother::Smoother() { T = NULL; sigma = NULL; } Smoother::~Smoother() { if(sigma != NULL) delete[] sigma; if(T != NULL) delete[] T; } void Smoother::LaplacianFlow(int iter, float dt) { /* int n = mesh->vertex_N; Membrace e; e.link = mesh->vertex_link_v; e.degree = mesh->degree_v; e.vertex = mesh->vertex; e.n = mesh->vertex_N; EnergyMinimizer mini; mini.energy = &e; ThinPlate e; e.mesh = mesh; EnergyMinimizer mini; mini.energy = &e; int iter1; float fret; float *p = new float[3*n]; for(int i=0; ivertex[i][0]; p[3*i+1] = mesh->vertex[i][1]; p[3*i+2] = mesh->vertex[i][2]; } mini.frprmn(p, 3*n, 0.000001f, &iter1, &fret); for(i=0; ivertex[i][0] = p[3*i]; mesh->vertex[i][1] = p[3*i+1]; mesh->vertex[i][2] = p[3*i+2]; }*/ int vertex_N = mesh->vertex_N; //L is Lplacian vectors double (*L)[3] = new double[vertex_N][3]; for(int i=0; iisBound[j]){ L[j][0] = L[j][1] = L[j][2] = 0; } else{ mesh->laplacian(j, L[j]); } } for(j=0; jvertex[j]; //replace each vertex p[0] += (float)(dt*L[j][0]); p[1] += (float)(dt*L[j][1]); p[2] += (float)(dt*L[j][2]); } } delete[] L; } void Smoother::meanCurvatureFlow(int iter, float dt) { int vertex_N = mesh->vertex_N; //Hn is mean curvature normals double (*Hn)[3] = new double[vertex_N][3]; for(int i=0; iisBound[j]){ Hn[j][0] = Hn[j][1] = Hn[j][2] = 0; } else{ //compute mean curvature normal mesh->meanCurvatureNormal(j, Hn[j]); } } for(j=0; jvertex[j]; //replace each vertex p[0] -= (float)(dt*Hn[j][0]); p[1] -= (float)(dt*Hn[j][1]); p[2] -= (float)(dt*Hn[j][2]); } } delete[] Hn; } void Smoother::setMeshData(MeshData *mesh) { this->mesh = mesh; } void Smoother::GaussianNoise(float size) { int vertex_N = mesh->vertex_N; float (*vertex)[3] = mesh->vertex; float (*normal)[3] = mesh->normal; float noise; srand(100); for(int i=0; i= 1.0 || r == 0.0); double f = sqrt(-2.0*log(r)/r); //if(vertex[i][1] > 0) //r1 = 0; noise = (float)(size*r1*f); vertex[i][0] += normal[i][0]*noise; vertex[i][1] += normal[i][1]*noise; vertex[i][2] += normal[i][2]*noise; if(++i == vertex_N) return; else{ //if(vertex[i][1] > 0) //r2 = 0; noise = (float)(size*r2*f); vertex[i][0] += normal[i][0]*noise; vertex[i][1] += normal[i][1]*noise; vertex[i][2] += normal[i][2]*noise; } } } void Smoother::computeNRingMeanCurvature(int n) { int vertex_N = mesh->vertex_N; float (*vertex)[3] = mesh->vertex; if(T != NULL) delete[] T; T = new float[vertex_N][3]; for(int i=0; igetConsistentNRings(i, n, nei, nei_N); float total_w = 0; float total_Hn[3]; total_Hn[0] = total_Hn[1] = total_Hn[2] = 0; for(int j=n-1; jisBound[nei[j][0]]) continue; float A_j = 0; float Hn_j[3]; Hn_j[0] = Hn_j[1] = Hn_j[2] = 0; for(int k=0; kvertex_N; float (*vertex)[3] = mesh->vertex; //Hn is mean curvature normals double (*Hn)[3] = new double[vertex_N][3]; // index of 2-ring int **nei2, *nei2_N; nei2 = (int **)new int[vertex_N]; nei2_N = new int[vertex_N]; for(int i=0; igetConsistentNRings(i, 2, nei, nei_N); nei2_N[i] = nei_N[1]; nei2[i] = nei[1]; delete[] nei[0]; delete[] nei; delete[] nei_N; } for(i=0; iisBound[j]){ Hn[j][0] = Hn[j][1] = Hn[j][2] = 0; } else{ //compute mean curvature normal mesh->meanCurvatureNormal(j, Hn[j]); if(nei2_N[j] == 0 || mesh->isBound[nei2[j][0]]) continue; float A_2 = 0; float Hn_2[3]; Hn_2[0] = Hn_2[1] = Hn_2[2] = 0; for(int k=0; k (1.0f+e)*H2){ Hn[j][0] *= (1.0f-H2/H12); Hn[j][1] *= (1.0f-H2/H12); Hn[j][2] *= (1.0f-H2/H12); } //else if(H12 < (1.0f-e)*H2){ //Hn[j][0] *= (H2/H12-1.0f); //Hn[j][1] *= (H2/H12-1.0f); //Hn[j][2] *= (H2/H12-1.0f); //} else{ Hn[j][0] = Hn[j][1] = Hn[j][2] = 0; } } } for(j=0; jvertex_N; float (*vertex)[3] = mesh->vertex; BOOL *isFeature = new BOOL[vertex_N]; for(int i=0; iisRidge[i] || mesh->isRavine[i]); //L is Lplacian vectors double (*L)[3] = new double[vertex_N][3]; for(i=0; icomputeFaceNormal(); mesh->computeNormal(); for(int j=0; jisBound[j]){ int *nei, nei_N; mesh->getConsistent1Ring(j, nei, nei_N); if(nei_N == 0){ L[j][0] = L[j][1] = L[j][2] = 0; continue; } int cnt = 0; if(isFeature[j]){ for(int k=0; klaplacian(j, L[j]); if(cnt == 1){ mesh->laplacian(j, L[j]); double inner = MeshData::DOT(mesh->normal[j], L[j]); L[i][0] = inner*mesh->normal[j][0]; L[i][1] = inner*mesh->normal[j][1]; L[i][2] = inner*mesh->normal[j][2]; } } } for(j=0; jvertex[j]; //replace each vertex p[0] += (float)(dt*L[j][0]); p[1] += (float)(dt*L[j][1]); p[2] += (float)(dt*L[j][2]); } } delete[] L; delete[] isFeature; } void Smoother::smoothTmaxTmin(int iter, float T) { int vertex_N = mesh->vertex_N; double (*t_max)[3] = mesh->t_max; double (*t_min)[3] = mesh->t_min; float (*vertex)[3] = mesh->vertex; double (*t_max1)[3] = new double[vertex_N][3]; double (*t_min1)[3] = new double[vertex_N][3]; for(int i=0; igetConsistent1Ring(j, nei, nei_N); if(nei_N == 0){ t_max1[j][0] = t_max[j][0]; t_max1[j][1] = t_max[j][1]; t_max1[j][2] = t_max[j][2]; t_min1[j][0] = t_min[j][0]; t_min1[j][1] = t_min[j][1]; t_min1[j][2] = t_min[j][2]; continue; } t_max1[j][0] = t_max1[j][1] = t_max1[j][2] = 0; t_min1[j][0] = t_min1[j][1] = t_min1[j][2] = 0; for(int k=0; knormal; for(i=0; ik_max[i]) > fabs(mesh->k_min[i])){ MeshData::CROSS(n, normal[i], t_max[i]); double len = MeshData::LENGTH(n); if((float)len != 0){ t_min[i][0] = n[0]/len; t_min[i][1] = n[1]/len; t_min[i][2] = n[2]/len; } } else{ MeshData::CROSS(n, t_min[i], normal[i]); double len = MeshData::LENGTH(n); if((float)len != 0){ t_max[i][0] = n[0]/len; t_max[i][1] = n[1]/len; t_max[i][2] = n[2]/len; } } } } void Smoother::smoothKmaxKmin(int iter, float T) { int vertex_N = mesh->vertex_N; double *k_max = mesh->k_max; double *k_min = mesh->k_min; float (*vertex)[3] = mesh->vertex; double *k_max1 = new double[vertex_N]; double *k_min1 = new double[vertex_N]; for(int i=0; igetConsistent1Ring(j, nei, nei_N); if(nei_N == 0){ k_max1[j] = k_max[j]; k_min1[j] = k_min[j]; continue; } double total_max = 0; double total_min = 0; k_max1[j] = k_min1[j] = 0; for(int k=0; kvertex_N; float (*vertex)[3] = mesh->vertex; float (*normal)[3]; int *dist = new int[vertex_N]; int max_dist = 3; Node** ridge = mesh->ridge_edge; Node** ravine = mesh->ravine_edge; Node** tag = new Node*[vertex_N]; for(int i=0; inext!=NULL; current=current->next) tag[i]->append(current->v, -1); for(current = ravine[i]; current->next!=NULL; current=current->next) tag[i]->append(current->v, -1); if(tag[i]->next!=NULL) dist[i] = 0; else dist[i] = 10000; } for(i=0; iget1Ring(j, nei, nei_N); if(nei_N == 0) continue; for(int k=0; kcomputeFaceNormal(); mesh->computeNormal(); normal = mesh->normal; for(int j=0; jnext!=NULL; current=current->next){ m++; L[j][0] += vertex[current->v][0]; L[j][1] += vertex[current->v][1]; L[j][2] += vertex[current->v][2]; } if(m == 2){ L[j][0] = L[j][0]/(float)m - vertex[j][0]; L[j][1] = L[j][1]/(float)m - vertex[j][1]; L[j][2] = L[j][2]/(float)m - vertex[j][2]; double inner = MeshData::DOT(L[j], normal[j]); L[j][0] = L[j][0] - inner*normal[j][0]; L[j][1] = L[j][1] - inner*normal[j][1]; L[j][2] = L[j][2] - inner*normal[j][2]; } else{ L[j][0] = L[j][1] = L[j][2] = 0; } } for(j=0; j max_dist) continue; int *nei, nei_N; mesh->get1Ring(j, nei, nei_N); if(nei_N == 0) continue; for(int k=0; k= max_dist) continue; int *nei, nei_N; mesh->get1Ring(j, nei, nei_N); if(nei_N == 0) continue; for(int k=0; knext!=NULL; current=current->next){ m++; BL[j][0] += L[current->v][0]; BL[j][1] += L[current->v][1]; BL[j][2] += L[current->v][2]; } if(m!=0){ BL[j][0] = BL[j][0]/(float)m - L[j][0]; BL[j][1] = BL[j][1]/(float)m - L[j][1]; BL[j][2] = BL[j][2]/(float)m - L[j][2]; } */ } for(j=0; jisBound[j]){ vertex[j][0] -= (float)(dt*BL[j][0]); vertex[j][1] -= (float)(dt*BL[j][1]); vertex[j][2] -= (float)(dt*BL[j][2]); } } } delete[] L; delete[] BL; delete[] dist; for(i=0; ivertex; float (*normal)[3] = mesh->normal_f; int (*face)[3] = mesh->face; int face_N = mesh->face_N; float (*tmp_normal)[3] = new float[face_N][3]; int (*ad_face)[3] = mesh->face_link_E; for(int i=0; i 1) dot = 1; else if(dot < -1) dot = -1; double k = acos(dot); if(d_type == 0) k /= d; double w; if(f_type == 1) w = area*exp(-T*k*k); else if(f_type == 0) w = area/(1+T*k*k); else w = area; total_w += w; sum_n[0] += w*normal[pair][0]; sum_n[1] += w*normal[pair][1]; sum_n[2] += w*normal[pair][2]; } if((float)total_w != 0){ tmp_normal[i][0] = (float)(sum_n[0]/total_w); tmp_normal[i][1] = (float)(sum_n[1]/total_w); tmp_normal[i][2] = (float)(sum_n[2]/total_w); double len = MeshData::LENGTH(tmp_normal[i]); if((float)len != 0){ tmp_normal[i][0] = (float)(tmp_normal[i][0]/len); tmp_normal[i][1] = (float)(tmp_normal[i][1]/len); tmp_normal[i][2] = (float)(tmp_normal[i][2]/len); } else{ tmp_normal[i][0] = normal[i][0]; tmp_normal[i][1] = normal[i][1]; tmp_normal[i][2] = normal[i][2]; } } else{ tmp_normal[i][0] = normal[i][0]; tmp_normal[i][1] = normal[i][1]; tmp_normal[i][2] = normal[i][2]; } } delete[] normal; mesh->normal_f = tmp_normal; } void Smoother::moveNormal(float dt) { int vertex_N = mesh->vertex_N; float (*vertex)[3] = mesh->vertex; int (*face)[3] = mesh->face; float (*normal_f)[3] = mesh->normal_f; double (*dp)[3] = new double[vertex_N][3]; for(int i=0; iisBound[i]){ dp[i][0] = dp[i][1] = dp[i][2] = 0; continue; } int *nei, *nei_v, nei_N; mesh->getConsistent1Ring(i, nei_v, nei, nei_N); if(nei_N == 0){ dp[i][0] = dp[i][1] = dp[i][2] = 0; continue; } double total_w = 0; double pro[3]; pro[0] = pro[1] = pro[2] = 0; BOOL flip_flag = false; for(int j = 0; j 0.7){ //flip_flag = true; //break; //TRACE("FLIP\n"); //} } if(flip_flag){ mesh->laplacian(i, dp[i]); /* dp[i][0] = dp[i][1] = dp[i][2] = 0; for(int j=0; jcomputeFaceNormal(); //mesh->computeNormal(); for(i=0; iface_link_V == NULL) mesh->generateFaceLinkV(); for(i=0; icomputeFaceNormal(); if(rate != 0){ //float *sigma = new float[mesh->face_N]; //this->decideSigma(sigma, T, ave_iter); //this->smoothNormalGaussian(ave_iter, sigma); //delete[] sigma; for(j=0; jsmoothNormalV(T,rate, f_type, d_type); //float e = mesh->averageOfEdgeLength(); //computeOptimalGaussian(0.05, 1.0, 0.05); //computeOptimalGaussian(0.25f*e, 2.5f*e, 0.25f*e, T*e*e); } else for(j=0; jsmoothNormal(T, f_type, d_type); if(int_type == 0){ for(j=0; jmoveNormal(int_step); } else{ if(L_deg != 1){ for(j=0; jmoveNormalAreaD(int_step, L_deg); } else{ //for(j=0; jminimizeNormalErr(); //this->IntegrateNormalImplicit(int_step); for(j=0; jmoveNormalAreaD(int_step); } } } } void Smoother::curvatureAlongMedian(int iter, float dt) { int vertex_N = mesh->vertex_N; float (*vertex)[3] = mesh->vertex; double (*dp)[3] = new double[vertex_N][3]; for(int i=0; iisBound[j]){ dp[j][0] = dp[j][1] = dp[j][2] = 0; continue; } double L[3], Hn[3]; mesh->laplacian(j, L); mesh->meanCurvatureNormal(j, Hn); Hn[0] *= -1; Hn[1] *= -1; Hn[2] *= -1; double dot = L[0]*Hn[0] + L[1]*Hn[1] + L[2]*Hn[2]; double H2 = Hn[0]*Hn[0] + Hn[1]*Hn[1] + Hn[2]*Hn[2]; double L2 = L[0]*L[0] + L[1]*L[1] + L[2]*L[2]; if(dot == 0){ dp[j][0] = L[0]; dp[j][1] = L[1]; dp[j][2] = L[2]; } else if(dot > 0){//.1*sqrt(H2)*sqrt(L2)){ dp[j][0] = dt*(float)(H2*L[0]/dot); dp[j][1] = dt*(float)(H2*L[1]/dot); dp[j][2] = dt*(float)(H2*L[2]/dot); double lenL = L[0]*L[0] + L[1]*L[1] + L[2]*L[2]; double lenDp = dp[j][0]*dp[j][0] + dp[j][1]*dp[j][1] + dp[j][2]*dp[j][2]; if(lenL < lenDp){ dp[j][0] = L[0]; dp[j][1] = L[1]; dp[j][2] = L[2]; } } else if(dot < 0){ //-0.1*sqrt(H2)*sqrt(L2)){ dp[j][0] = dt*(float)(2.0*Hn[0] - H2*L[0]/dot); dp[j][1] = dt*(float)(2.0*Hn[1] - H2*L[1]/dot); dp[j][2] = dt*(float)(2.0*Hn[2] - H2*L[2]/dot); double lenL = L[0]*L[0] + L[1]*L[1] + L[2]*L[2]; double lenDp = dp[j][0]*dp[j][0] + dp[j][1]*dp[j][1] + dp[j][2]*dp[j][2]; if(lenL < lenDp){ dp[j][0] = L[0] - 2.0*dot*Hn[0]/H2; dp[j][1] = L[1] - 2.0*dot*Hn[1]/H2; dp[j][2] = L[2] - 2.0*dot*Hn[2]/H2; } } else{ dp[j][0] = dp[j][1] = dp[j][2] = 0; } } for(j=0; jvertex; float (*normal)[3] = mesh->normal_f; int (*face)[3] = mesh->face; int face_N = mesh->face_N; float (*tmp_normal)[3] = new float[face_N][3]; int (*ad_face)[3] = mesh->face_link_E; int **ad_face2 = mesh->face_link_V; int *ad_face2_N = mesh->face_link_V_N; for(int i=0; i 1) dot = 1; else if(dot < -1) dot = -1; double k = acos(dot); if(d_type == 0) k /= d; double w; if(f_type == 1) w = area*exp(-T*k*k); else if(f_type == 0) w = area/(1.0+T*k*k); else w = 1; //area; total_w += w; sum_n[0] += w*normal[pair][0]; sum_n[1] += w*normal[pair][1]; sum_n[2] += w*normal[pair][2]; } for(j=0; j= face_N) continue; double c1[3]; c1[0] = (vertex[face[pair][0]][0] + vertex[face[pair][1]][0] + vertex[face[pair][2]][0])/3.0; c1[1] = (vertex[face[pair][0]][1] + vertex[face[pair][1]][1] + vertex[face[pair][2]][1])/3.0; c1[2] = (vertex[face[pair][0]][2] + vertex[face[pair][1]][2] + vertex[face[pair][2]][2])/3.0; double d = MeshData::DIST(c,c1); if((float)d == 0) continue; double area = MeshData::AREA(vertex[face[pair][0]], vertex[face[pair][1]], vertex[face[pair][2]]); double dot = MeshData::DOT(normal[i], normal[pair]); if(dot > 1) dot = 1; else if(dot < -1) dot = -1; double k = acos(dot); if(d_type == 0) k /= d; double w; if(f_type == 1) w = rate*area*exp(-T*k*k); else if(f_type == 0) w = rate*area/(1.0+T*k*k); else w = rate; //rate*area; total_w += w; sum_n[0] += w*normal[pair][0]; sum_n[1] += w*normal[pair][1]; sum_n[2] += w*normal[pair][2]; } if((float)total_w != 0){ tmp_normal[i][0] = (float)(sum_n[0]/total_w); tmp_normal[i][1] = (float)(sum_n[1]/total_w); tmp_normal[i][2] = (float)(sum_n[2]/total_w); double len = MeshData::LENGTH(tmp_normal[i]); if((float)len != 0){ tmp_normal[i][0] = (float)(tmp_normal[i][0]/len); tmp_normal[i][1] = (float)(tmp_normal[i][1]/len); tmp_normal[i][2] = (float)(tmp_normal[i][2]/len); } else{ tmp_normal[i][0] = normal[i][0]; tmp_normal[i][1] = normal[i][1]; tmp_normal[i][2] = normal[i][2]; } } else{ tmp_normal[i][0] = normal[i][0]; tmp_normal[i][1] = normal[i][1]; tmp_normal[i][2] = normal[i][2]; } } delete[] normal; mesh->normal_f = tmp_normal; } void Smoother::smoothNormalV(int iter, float T, float rate) { /* float (*vertex)[3] = mesh->vertex; float (*normal)[3] = mesh->normal_f; int (*face)[3] = mesh->face; int face_N = mesh->face_N; float (*tmp_normal)[3] = new float[face_N][3]; int (*ad_face)[3] = mesh->face_link_E; int **ad_face2 = mesh->face_link_V; int *ad_face2_N = mesh->face_link_V_N; for(int m=0; m= face_N) continue; double c1[3]; c1[0] = (vertex[face[pair][0]][0] + vertex[face[pair][1]][0] + vertex[face[pair][2]][0])/3.0f; c1[1] = (vertex[face[pair][0]][1] + vertex[face[pair][1]][1] + vertex[face[pair][2]][1])/3.0f; c1[2] = (vertex[face[pair][0]][2] + vertex[face[pair][1]][2] + vertex[face[pair][2]][2])/3.0f; double d = MeshData::DIST(c,c1); if((float)d == 0) continue; float area = MeshData::AREA(vertex[face[pair][0]], vertex[face[pair][1]], vertex[face[pair][2]]); float k = acos(MeshData::DOT(normal[i], normal[pair]))/d; float w = rate*area*exp(-(k/T)*(k/T)); total_w += w; tmp_normal[i][0] += w*normal[pair][0]; tmp_normal[i][1] += w*normal[pair][1]; tmp_normal[i][2] += w*normal[pair][2]; } if(total_w != 0){ tmp_normal[i][0] /= total_w; tmp_normal[i][1] /= total_w; tmp_normal[i][2] /= total_w; float len = MeshData::LENGTH(tmp_normal[i]); if(len != 0){ tmp_normal[i][0] /= len; tmp_normal[i][1] /= len; tmp_normal[i][2] /= len; } else{ tmp_normal[i][0] = normal[i][0]; tmp_normal[i][1] = normal[i][1]; tmp_normal[i][2] = normal[i][2]; } } else{ tmp_normal[i][0] = normal[i][0]; tmp_normal[i][1] = normal[i][1]; tmp_normal[i][2] = normal[i][2]; } } } for(int i=0; inormal_f = tmp_normal; */ } void Smoother::moveMinPosition() { int vertex_N = mesh->vertex_N; int face_N = mesh->face_N; float (*vertex)[3] = mesh->vertex; int (*face)[3] = mesh->face; float (*normal)[3] = mesh->normal_f; int *type = mesh->isBound; int **link = mesh->vertex_link_f; int *degree = mesh->degree_f; double (*center)[3] = new double[face_N][3]; for(int i=0; ifaceCenter(center[i], i); for(i=0; ifaceArea(l[j]); total_a += a; MAT_TIMES(A, a); MAT_SUM(S, A); double d = MeshData::DOT(n, center[l[j]]); b[0] += a*d*n[0]; b[1] += a*d*n[1]; b[2] += a*d*n[2]; } if((float)total_a !=0){ for(int k=0; k<6; k++) S[k] /= total_a; b[0] /= total_a; b[1] /= total_a; b[2] /= total_a; } double InS[6]; if(INVERSE(InS, S)){ double p[3]; MAT_BY_VEC(p, InS, b); //zone BOOL flag = true; for(j=0; jvertex_N; double (*t_max)[3] = mesh->ridge_dir; double (*t_min)[3] = mesh->ravine_dir; float (*vertex)[3] = mesh->vertex; double (*t_max1)[3] = new double[vertex_N][3]; double (*t_min1)[3] = new double[vertex_N][3]; for(int i=0; igetConsistent1Ring(j, nei, nei_N); if(nei_N == 0){ t_max1[j][0] = t_max[j][0]; t_max1[j][1] = t_max[j][1]; t_max1[j][2] = t_max[j][2]; t_min1[j][0] = t_min[j][0]; t_min1[j][1] = t_min[j][1]; t_min1[j][2] = t_min[j][2]; continue; } t_max1[j][0] = t_max1[j][1] = t_max1[j][2] = 0; t_min1[j][0] = t_min1[j][1] = t_min1[j][2] = 0; for(int k=0; kvertex_N; double (*t_max)[3] = mesh->t_max; double (*t_min)[3] = mesh->t_min; float (*vertex)[3] = mesh->vertex; double (*t_max1)[3] = new double[vertex_N][3]; double (*t_min1)[3] = new double[vertex_N][3]; float (*normal)[3] = mesh->normal; for(int i=0; igetConsistent1Ring(j, nei, nei_N); if(nei_N == 0){ t_max1[j][0] = t_max[j][0]; t_max1[j][1] = t_max[j][1]; t_max1[j][2] = t_max[j][2]; t_min1[j][0] = t_min[j][0]; t_min1[j][1] = t_min[j][1]; t_min1[j][2] = t_min[j][2]; continue; } double angle_max = 0; double angle_min = 0; double w_max = 0; double w_min = 0; for(int k=0; k 1.0) dot = 1; else if(dot < -1.0) dot = -1; GENERATE_MAT(R, acos(dot), cross); } double tmp1[3], tmp2[3]; MAT_VEC(tmp1, R, t_max[pair]); MAT_VEC(tmp2, R, t_min[pair]); double dot = MeshData::DOT(t_max[j], tmp1); if(dot > 1.0) dot = 1.0; else if(dot < -1.0) dot = -1.0; double dk = acos(fabs(dot)); double w = exp(-dk*dk/d2/(T*T)); w = 1.0; w_max += w; MeshData::CROSS(cross, t_max[j], tmp1); if(MeshData::DOT(cross, normal[j]) < 0) dk = -dk; angle_max += w*dk; dot = MeshData::DOT(t_min[j], tmp2); if(dot > 1.0) dot = 1.0; else if(dot < -1.0) dot = -1.0; dk = acos(fabs(dot)); w = exp(-dk*dk/d2/(T*T)); w = 1.0; w_min += w; MeshData::CROSS(cross, t_min[j], tmp2); if(MeshData::DOT(cross, normal[j]) < 0) dk = -dk; angle_min += w*dk; } if(w_max != 0){ angle_max /= w_max; double R[3][3]; GENERATE_MAT(R, angle_max, normal[j]); MAT_VEC(t_max1[j], R, t_max[j]); } else{ t_max1[j][0] = t_max[j][0]; t_max1[j][1] = t_max[j][1]; t_max1[j][2] = t_max[j][2]; } if(w_min != 0){ angle_min /= w_min; double R[3][3]; GENERATE_MAT(R, angle_min, normal[j]); MAT_VEC(t_min1[j], R, t_min[j]); } else{ t_min1[j][0] = t_min[j][0]; t_min1[j][1] = t_min[j][1]; t_min1[j][2] = t_min[j][2]; } } for(j=0; jk_max[i]) > fabs(mesh->k_min[i])){ double len = MeshData::LENGTH(t_max[i]); if(len != 0){ t_max[i][0] /= len; t_max[i][1] /= len; t_max[i][2] /= len; MeshData::CROSS(t_min[i], normal[i], t_max[i]); } else{ t_max[i][0] = t_max[i][1] = t_max[i][2] = 0; t_min[i][0] = t_min[i][1] = t_min[i][2] = 0; } } else{ double len = MeshData::LENGTH(t_min[i]); if(len != 0){ t_min[i][0] /= len; t_min[i][1] /= len; t_min[i][2] /= len; MeshData::CROSS(t_max[i], t_min[i], normal[i]); } else{ t_max[i][0] = t_max[i][1] = t_max[i][2] = 0; t_min[i][0] = t_min[i][1] = t_min[i][2] = 0; } } } for(i=0; ivertex_N; double (*t_max)[3] = mesh->ridge_dir; double (*t_min)[3] = mesh->ravine_dir; float (*vertex)[3] = mesh->vertex; double (*t_max1)[3] = new double[vertex_N][3]; double (*t_min1)[3] = new double[vertex_N][3]; float (*normal)[3] = mesh->normal; for(int i=0; igetConsistent1Ring(j, nei, nei_N); if(nei_N == 0){ t_max1[j][0] = t_max[j][0]; t_max1[j][1] = t_max[j][1]; t_max1[j][2] = t_max[j][2]; t_min1[j][0] = t_min[j][0]; t_min1[j][1] = t_min[j][1]; t_min1[j][2] = t_min[j][2]; continue; } double angle_max = 0; double angle_min = 0; double w_max = 0; double w_min = 0; for(int k=0; k 1.0) dot = 1; else if(dot < -1.0) dot = -1; GENERATE_MAT(R, acos(dot), cross); } double tmp1[3], tmp2[3]; MAT_VEC(tmp1, R, t_max[pair]); MAT_VEC(tmp2, R, t_min[pair]); double dot = MeshData::DOT(t_max[j], tmp1); if(dot > 1.0) dot = 1.0; else if(dot < -1.0) dot = -1.0; double dk = acos(fabs(dot)); double w = exp(-dk*dk/d2/(T*T)); w_max += w; MeshData::CROSS(cross, t_max[j], tmp1); if(MeshData::DOT(cross, normal[j]) < 0) dk = -dk; angle_max += w*dk; dot = MeshData::DOT(t_min[j], tmp2); if(dot > 1.0) dot = 1.0; else if(dot < -1.0) dot = -1.0; dk = acos(fabs(dot)); w = exp(-dk*dk/d2/(T*T)); w_min += w; MeshData::CROSS(cross, t_min[j], tmp2); if(MeshData::DOT(cross, normal[j]) < 0) dk = -dk; angle_min += w*dk; } if(w_max != 0){ angle_max /= w_max; double R[3][3]; GENERATE_MAT(R, angle_max, normal[j]); MAT_VEC(t_max1[j], R, t_max[j]); } else{ t_max1[j][0] = t_max[j][0]; t_max1[j][1] = t_max[j][1]; t_max1[j][2] = t_max[j][2]; } if(w_min != 0){ angle_min /= w_min; double R[3][3]; GENERATE_MAT(R, angle_min, normal[j]); MAT_VEC(t_min1[j], R, t_min[j]); } else{ t_min1[j][0] = t_min[j][0]; t_min1[j][1] = t_min[j][1]; t_min1[j][2] = t_min[j][2]; } } for(j=0; jvertex_N; double (*t_max)[3] = mesh->ridge_dir; double (*t_min)[3] = mesh->ravine_dir; float (*vertex)[3] = mesh->vertex; double (*t_max1)[3] = new double[vertex_N][3]; double (*t_min1)[3] = new double[vertex_N][3]; float (*normal)[3] = mesh->normal; for(int i=0; igetConsistent1Ring(j, nei, nei_N); if(nei_N == 0){ t_max1[j][0] = t_max[j][0]; t_max1[j][1] = t_max[j][1]; t_max1[j][2] = t_max[j][2]; t_min1[j][0] = t_min[j][0]; t_min1[j][1] = t_min[j][1]; t_min1[j][2] = t_min[j][2]; continue; } double max_tmp[3] = {0,0,0}; double min_tmp[3] = {0,0,0}; for(int k=0; k 1.0) dot = 1; else if(dot < -1.0) dot = -1; GENERATE_MAT(R, acos(dot), cross); } double tmp1[3], tmp2[3]; MAT_VEC(tmp1, R, t_max[pair]); MAT_VEC(tmp2, R, t_min[pair]); double dot = MeshData::DOT(t_max[j], tmp1); if(dot > 1.0) dot = 1.0; else if(dot < -1.0) dot = -1.0; double dk = acos(fabs(dot)); double w = exp(-dk*dk/d2/(T*T)); if(dot < 0) w = -w; max_tmp[0] += w*tmp1[0]; max_tmp[1] += w*tmp1[1]; max_tmp[2] += w*tmp1[2]; dot = MeshData::DOT(t_min[j], tmp2); if(dot > 1.0) dot = 1.0; else if(dot < -1.0) dot = -1.0; dk = acos(fabs(dot)); w = exp(-dk*dk/d2/(T*T)); if(dot < 0) w = -w; min_tmp[0] += w*tmp2[0]; min_tmp[1] += w*tmp2[1]; min_tmp[2] += w*tmp2[2]; } double len = MeshData::LENGTH(max_tmp); if((float)len != 0){ t_max1[j][0] = max_tmp[0]/len; t_max1[j][1] = max_tmp[1]/len; t_max1[j][2] = max_tmp[2]/len; } else{ t_max1[j][0] = t_max[j][0]; t_max1[j][1] = t_max[j][1]; t_max1[j][2] = t_max[j][2]; } len = MeshData::LENGTH(min_tmp); if((float)len != 0){ t_min1[j][0] = min_tmp[0]/len; t_min1[j][1] = min_tmp[1]/len; t_min1[j][2] = min_tmp[2]/len; } else{ t_min1[j][0] = t_min[j][0]; t_min1[j][1] = t_min[j][1]; t_min1[j][2] = t_min[j][2]; } } for(j=0; jvertex_N; double (*t_max)[3] = mesh->t_max; double (*t_min)[3] = mesh->t_min; float (*vertex)[3] = mesh->vertex; double (*t_max1)[3] = new double[vertex_N][3]; double (*t_min1)[3] = new double[vertex_N][3]; float (*normal)[3] = mesh->normal; for(int i=0; igetConsistent1Ring(j, nei, nei_N); if(nei_N == 0){ t_max1[j][0] = t_max[j][0]; t_max1[j][1] = t_max[j][1]; t_max1[j][2] = t_max[j][2]; t_min1[j][0] = t_min[j][0]; t_min1[j][1] = t_min[j][1]; t_min1[j][2] = t_min[j][2]; continue; } double max_tmp[3] = {0,0,0}; double min_tmp[3] = {0,0,0}; for(int k=0; k 1.0) dot = 1; else if(dot < -1.0) dot = -1; GENERATE_MAT(R, acos(dot), cross); } double tmp1[3], tmp2[3]; MAT_VEC(tmp1, R, t_max[pair]); MAT_VEC(tmp2, R, t_min[pair]); double dot = MeshData::DOT(t_max[j], tmp1); if(dot > 1.0) dot = 1.0; else if(dot < -1.0) dot = -1.0; double dk = acos(fabs(dot)); double w = exp(-dk*dk/d2/(T*T)); //w = 1.0f; if(dot < 0) w = -w; max_tmp[0] += w*tmp1[0]; max_tmp[1] += w*tmp1[1]; max_tmp[2] += w*tmp1[2]; dot = MeshData::DOT(t_min[j], tmp2); if(dot > 1.0) dot = 1.0; else if(dot < -1.0) dot = -1.0; dk = acos(fabs(dot)); w = exp(-dk*dk/d2/(T*T)); //w = 1.0f; if(dot < 0) w = -w; min_tmp[0] += w*tmp2[0]; min_tmp[1] += w*tmp2[1]; min_tmp[2] += w*tmp2[2]; } double len = MeshData::LENGTH(max_tmp); if((float)len != 0){ t_max1[j][0] = max_tmp[0]/len; t_max1[j][1] = max_tmp[1]/len; t_max1[j][2] = max_tmp[2]/len; } else{ t_max1[j][0] = t_max[j][0]; t_max1[j][1] = t_max[j][1]; t_max1[j][2] = t_max[j][2]; } len = MeshData::LENGTH(min_tmp); if((float)len != 0){ t_min1[j][0] = min_tmp[0]/len; t_min1[j][1] = min_tmp[1]/len; t_min1[j][2] = min_tmp[2]/len; } else{ t_min1[j][0] = t_min[j][0]; t_min1[j][1] = t_min[j][1]; t_min1[j][2] = t_min[j][2]; } } for(j=0; jk_max[i]) > fabs(mesh->k_min[i])){ double len = MeshData::LENGTH(t_max[i]); if(len != 0){ t_max[i][0] /= len; t_max[i][1] /= len; t_max[i][2] /= len; MeshData::CROSS(t_min[i], normal[i], t_max[i]); } else{ t_max[i][0] = t_max[i][1] = t_max[i][2] = 0; t_min[i][0] = t_min[i][1] = t_min[i][2] = 0; } } else{ double len = MeshData::LENGTH(t_min[i]); if(len != 0){ t_min[i][0] /= len; t_min[i][1] /= len; t_min[i][2] /= len; MeshData::CROSS(t_max[i], t_min[i], normal[i]); } else{ t_max[i][0] = t_max[i][1] = t_max[i][2] = 0; t_min[i][0] = t_min[i][1] = t_min[i][2] = 0; } } } for(i=0; ivertex_N; double *k_max = mesh->k_max; double *k_min = mesh->k_min; float (*vertex)[3] = mesh->vertex; double *k_max1 = new double[vertex_N]; double *k_min1 = new double[vertex_N]; for(int i=0; igetConsistent1Ring(j, nei, nei_N); if(nei_N == 0){ continue; } double total_max = 0;//1; double total_min = 0;//1; for(int k=0; kvertex_N; double (*t_max)[3] = mesh->t_max; double (*t_min)[3] = mesh->t_min; float (*vertex)[3] = mesh->vertex; double (*t_max1)[3] = new double[vertex_N][3]; double (*t_min1)[3] = new double[vertex_N][3]; float (*normal)[3] = mesh->normal; for(int i=0; igetConsistent1Ring(j, nei, nei_N); if(nei_N == 0){ t_max1[j][0] = t_max[j][0]; t_max1[j][1] = t_max[j][1]; t_max1[j][2] = t_max[j][2]; t_min1[j][0] = t_min[j][0]; t_min1[j][1] = t_min[j][1]; t_min1[j][2] = t_min[j][2]; continue; } double max_tmp[3]; max_tmp[0] = t_max[j][0]; max_tmp[1] = t_max[j][1]; max_tmp[2] = t_max[j][2]; double min_tmp[3]; min_tmp[0] = t_min[j][0]; min_tmp[1] = t_min[j][1]; min_tmp[2] = t_min[j][2]; for(int k=0; k 1.0) dot = 1; else if(dot < -1.0) dot = -1; GENERATE_MAT(R, acos(dot), cross); } double tmp1[3], tmp2[3]; MAT_VEC(tmp1, R, t_max[pair]); MAT_VEC(tmp2, R, t_min[pair]); double dot = MeshData::DOT(t_max[j], tmp1); if(dot > 1.0) dot = 1.0; else if(dot < -1.0) dot = -1.0; double dk = acos(fabs(dot)); double w = exp(-dk*dk/d2/(T*T)); //w = 1.0f; if(dot < 0) w = -w; max_tmp[0] += w*tmp1[0]; max_tmp[1] += w*tmp1[1]; max_tmp[2] += w*tmp1[2]; dot = MeshData::DOT(t_min[j], tmp2); if(dot > 1.0) dot = 1.0; else if(dot < -1.0) dot = -1.0; dk = acos(fabs(dot)); w = exp(-dk*dk/d2/(T*T)); //w = 1.0f; if(dot < 0) w = -w; min_tmp[0] += w*tmp2[0]; min_tmp[1] += w*tmp2[1]; min_tmp[2] += w*tmp2[2]; } double len = MeshData::LENGTH(max_tmp); if((float)len != 0){ t_max1[j][0] = max_tmp[0]/len; t_max1[j][1] = max_tmp[1]/len; t_max1[j][2] = max_tmp[2]/len; } else{ t_max1[j][0] = t_max[j][0]; t_max1[j][1] = t_max[j][1]; t_max1[j][2] = t_max[j][2]; } len = MeshData::LENGTH(min_tmp); if((float)len != 0){ t_min1[j][0] = min_tmp[0]/len; t_min1[j][1] = min_tmp[1]/len; t_min1[j][2] = min_tmp[2]/len; } else{ t_min1[j][0] = t_min[j][0]; t_min1[j][1] = t_min[j][1]; t_min1[j][2] = t_min[j][2]; } } for(j=0; jk_max[i]) > fabs(mesh->k_min[i])){ double len = MeshData::LENGTH(t_max[i]); if(len != 0){ t_max[i][0] /= len; t_max[i][1] /= len; t_max[i][2] /= len; MeshData::CROSS(t_min[i], normal[i], t_max[i]); } else{ t_max[i][0] = t_max[i][1] = t_max[i][2] = 0; t_min[i][0] = t_min[i][1] = t_min[i][2] = 0; } } else{ double len = MeshData::LENGTH(t_min[i]); if(len != 0){ t_min[i][0] /= len; t_min[i][1] /= len; t_min[i][2] /= len; MeshData::CROSS(t_max[i], t_min[i], normal[i]); } else{ t_max[i][0] = t_max[i][1] = t_max[i][2] = 0; t_min[i][0] = t_min[i][1] = t_min[i][2] = 0; } } } for(i=0; inormal_f; int (*face)[3] = mesh->face; int face_N = mesh->face_N; float (*tmp_normal)[3] = new float[face_N][3]; int (*ad_face)[3] = mesh->face_link_E; for(int i=0; ifaceCenter(c1, i); mesh->faceCenter(c2, pair); double d = MeshData::DIST(c1, c2); double a = 0; if(d != 0) a = 1.0/d; */ double a = 1; sum_n[0] += a*normal[pair][0]; sum_n[1] += a*normal[pair][1]; sum_n[2] += a*normal[pair][2]; } double len = MeshData::LENGTH(sum_n); if(len != 0){ tmp_normal[i][0] = (float)(sum_n[0]/len); tmp_normal[i][1] = (float)(sum_n[1]/len); tmp_normal[i][2] = (float)(sum_n[2]/len); } else{ tmp_normal[i][0] = normal[i][0]; tmp_normal[i][1] = normal[i][1]; tmp_normal[i][2] = normal[i][2]; } } delete[] normal; mesh->normal_f = tmp_normal; } void Smoother::smoothTmaxTminSIG1(int iter, float T) //T is not used. { int vertex_N = mesh->vertex_N; double (*t_max)[3] = mesh->t_max; double (*t_min)[3] = mesh->t_min; float (*vertex)[3] = mesh->vertex; int *degree = mesh->degree_v; int **link = mesh->vertex_link_v; float (*normal)[3] = mesh->normal; double *theta_max = new double[vertex_N]; double *theta_min = new double[vertex_N]; double **phi = new double*[vertex_N]; for(int i=0; itangent(t0, i, l[0]); for(int j=1; jtangent(tj, i, l[j]); double dot = MeshData::DOT(t0, tj); if(dot > 1) dot = 1; else if(dot < -1) dot = -1; p[j] = acos(dot); double c[3]; MeshData::CROSS(c, t0, tj); if(MeshData::DOT(c, normal[i]) < 0) p[j] = -p[j]; } double dot_max = MeshData::DOT(t0, t_max[i]); if(dot_max > 1) dot_max = 1; else if(dot_max < -1) dot_max = -1; theta_max[i] = acos(dot_max); double c[3]; MeshData::CROSS(c, t0, t_max[i]); if(MeshData::DOT(c, normal[i]) < 0) theta_max[i] = -theta_max[i]; double dot_min = MeshData::DOT(t0, t_min[i]); if(dot_min > 1) dot_min = 1; else if(dot_min < -1) dot_min = -1; theta_min[i] = acos(dot_min); MeshData::CROSS(c, t0, t_min[i]); if(MeshData::DOT(c, normal[i]) < 0) theta_min[i] = -theta_min[i]; } double *theta_max1 = new double[vertex_N]; double *theta_min1 = new double[vertex_N]; for(i=0; itangent(t0, i, link[i][0]); GENERATE_MAT(R, theta_max[i], axis); MAT_VEC(t_max[i], R, t0); GENERATE_MAT(R, theta_min[i], axis); MAT_VEC(t_min[i], R, t0); } delete[] theta_max; delete[] theta_min; for(i=0; ik_max[i]) > fabs(mesh->k_min[i])){ double len = MeshData::LENGTH(t_max[i]); if(len != 0){ t_max[i][0] /= len; t_max[i][1] /= len; t_max[i][2] /= len; MeshData::CROSS(t_min[i], normal[i], t_max[i]); } else{ t_max[i][0] = t_max[i][1] = t_max[i][2] = 0; t_min[i][0] = t_min[i][1] = t_min[i][2] = 0; } } else{ double len = MeshData::LENGTH(t_min[i]); if(len != 0){ t_min[i][0] /= len; t_min[i][1] /= len; t_min[i][2] /= len; MeshData::CROSS(t_max[i], t_min[i], normal[i]); } else{ t_max[i][0] = t_max[i][1] = t_max[i][2] = 0; t_min[i][0] = t_min[i][1] = t_min[i][2] = 0; } } } for(i=0; ivertex_N; double (*t_max)[3] = mesh->t_max; double (*t_min)[3] = mesh->t_min; float (*vertex)[3] = mesh->vertex; int *degree = mesh->degree_v; int **link = mesh->vertex_link_v; float (*normal)[3] = mesh->normal; float *theta_max = new float[vertex_N]; float *theta_min = new float[vertex_N]; double **phi = new double*[vertex_N]; for(int i=0; itangent(t0, i, l[0]); for(int j=1; jtangent(tj, i, l[j]); double dot = MeshData::DOT(t0, tj); if(dot > 1) dot = 1; else if(dot < -1) dot = -1; p[j] = acos(dot); double c[3]; MeshData::CROSS(c, t0, tj); if(MeshData::DOT(c, normal[i]) < 0) p[j] = -p[j]; } double dot_max = MeshData::DOT(t0, t_max[i]); if(dot_max > 1) dot_max = 1; else if(dot_max < -1) dot_max = -1; theta_max[i] = (float)acos(dot_max); double c[3]; MeshData::CROSS(c, t0, t_max[i]); if(MeshData::DOT(c, normal[i]) < 0) theta_max[i] = -theta_max[i]; double dot_min = MeshData::DOT(t0, t_min[i]); if(dot_min > 1) dot_min = 1; else if(dot_min < -1) dot_min = -1; theta_min[i] = (float)acos(dot_min); MeshData::CROSS(c, t0, t_min[i]); if(MeshData::DOT(c, normal[i]) < 0) theta_min[i] = -theta_min[i]; } //conjugate gradient algorithm FieldEnergy e; // = new FieldEnergy; e.initData(vertex_N, phi, link, degree); EnergyMinimizer mini; // = new EnergyMinimizer; mini.energy = &e; int iter; float fret; for(i=0; i<5; i++){ mini.frprmn(theta_max, vertex_N, 0.0001f, &iter, &fret); mini.frprmn(theta_min, vertex_N, 0.0001f, &iter, &fret); } // compute t_{max,min} from theta_{max,min} for(i=0; itangent(t0, i, link[i][0]); GENERATE_MAT(R, theta_max[i], axis); MAT_VEC(t_max[i], R, t0); GENERATE_MAT(R, theta_min[i], axis); MAT_VEC(t_min[i], R, t0); } delete[] theta_max; delete[] theta_min; for(i=0; ik_max[i]) > fabs(mesh->k_min[i])){ double len = MeshData::LENGTH(t_max[i]); if(len != 0){ t_max[i][0] /= len; t_max[i][1] /= len; t_max[i][2] /= len; MeshData::CROSS(t_min[i], normal[i], t_max[i]); } else{ t_max[i][0] = t_max[i][1] = t_max[i][2] = 0; t_min[i][0] = t_min[i][1] = t_min[i][2] = 0; } } else{ double len = MeshData::LENGTH(t_min[i]); if(len != 0){ t_min[i][0] /= len; t_min[i][1] /= len; t_min[i][2] /= len; MeshData::CROSS(t_max[i], t_min[i], normal[i]); } else{ t_max[i][0] = t_max[i][1] = t_max[i][2] = 0; t_min[i][0] = t_min[i][1] = t_min[i][2] = 0; } } } for(i=0; ivertex_N; float (*vertex)[3] = mesh->vertex; int (*face)[3] = mesh->face; float (*normal_f)[3] = mesh->normal_f; double (*dp)[3] = new double[vertex_N][3]; int **link_f = mesh->vertex_link_f; int *degree = mesh->degree_v; for(int i=0; iisBound[i]){ dp[i][0] = dp[i][1] = dp[i][2] = 0; continue; } int *nei = link_f[i]; int nei_N = degree[i]; if(nei_N == 0){ dp[i][0] = dp[i][1] = dp[i][2] = 0; continue; } double total_w = 0; double df[3]; df[0] = df[1] = df[2] = 0; for(int j = 0; jvertex_N; float (*vertex)[3] = mesh->vertex; BOOL *isFeature = new BOOL[vertex_N]; for(int i=0; iisRidge[i] || mesh->isRavine[i]); //L is Lplacian vectors double (*L)[3] = new double[vertex_N][3]; double (*LL)[3] = new double[vertex_N][3]; int **link = mesh->vertex_link_v; int *degree = mesh->degree_v; BOOL *isBound = mesh->isBound; for(i=0; icomputeNormal(); for(int j=0; jlaplacian(j, L[j]); } else mesh->laplacian(j, L[j]); } for(j=0; jlaplacian(j, L[j]); double inner = MeshData::DOT(mesh->normal[j], L[j]); L[i][0] = inner*mesh->normal[j][0]; L[i][1] = inner*mesh->normal[j][1]; L[i][2] = inner*mesh->normal[j][2]; }*/ } for(j=0; jvertex[j]; //replace each vertex p[0] -= (float)(dt*LL[j][0]); p[1] -= (float)(dt*LL[j][1]); p[2] -= (float)(dt*LL[j][2]); } } delete[] L; delete[] LL; delete[] isFeature; } void Smoother::BilaplacianWithRidge2(int iter, float dt) { int vertex_N = mesh->vertex_N; float (*vertex)[3] = mesh->vertex; BOOL *isFeature = new BOOL[vertex_N]; for(int i=0; iisRidge[i] || mesh->isRavine[i]); //L is Lplacian vectors double (*L)[3] = new double[vertex_N][3]; double (*LL)[3] = new double[vertex_N][3]; int **link = mesh->vertex_link_v; int *degree = mesh->degree_v; BOOL *isBound = mesh->isBound; for(i=0; icomputeNormal(); for(int j=0; jlaplacian(j, L[j]); for(j=0; jlaplacian(j, L[j]); double inner = MeshData::DOT(mesh->normal[j], L[j]); L[i][0] = inner*mesh->normal[j][0]; L[i][1] = inner*mesh->normal[j][1]; L[i][2] = inner*mesh->normal[j][2]; }*/ } for(j=0; jvertex_N; int face_N = mesh->face_N; float (*normal)[3] = mesh->normal_f; float (*vertex)[3] = mesh->vertex; int (*face)[3] = mesh->face; double (*dp)[3] = new double[vertex_N][3]; double *total_w = new double[vertex_N]; for(int i=0; ivertex_N; float (*vertex)[3] = mesh->vertex; double (*M)[3] = new double[vertex_N][3]; double (*L)[3] = new double[vertex_N][3]; int **link = mesh->vertex_link_v; int *degree = mesh->degree_v; for(int i=0; ilaplacian(i, M[i]); //mesh->meanCurvatureNormal(i, M[i]); for(int k=0; k<10; k++){ for(i=0; icomputeNormal(); float (*normal)[3] = mesh->normal; for(i=0; ilaplacian(i, L[i]); /* mesh->meanCurvatureNormal(i, L[i]); double U[3]; float *n = normal[i]; mesh->laplacian(i, U); double dot = MeshData::DOT(U, n); U[0] = U[0] - dot*n[0]; U[1] = U[1] - dot*n[1]; U[2] = U[2] - dot*n[2]; L[i][0] -= 0.1*U[0]/dt; L[i][1] -= 0.1*U[1]/dt; L[i][2] -= 0.1*U[2]/dt; */ } for(i=0; ivertex_N; int *degree = mesh->degree_v; int **link = mesh->vertex_link_v; float (*vertex)[3] = mesh->vertex; double (*L)[3] = new double[vertex_N][3]; float dt1 = dt; float dt2 = (float)(dt/(dt*low_pass - 1.0)); for(int i=0; i<2*iter; i++){ if(i%2 == 0) dt = dt1; else dt = dt2; if(type == 0){ for(int j=0; jisBound[j]){ L[j][0] = L[j][1] = L[j][2] = 0; } else{ mesh->laplacian(j, L[j]); } } } else if(type == 1){ for(int j=0; jisBound[j]) continue; double total_w = 0; int deg = degree[j]; int *l = link[j]; float *p = vertex[j]; for(int k=0; kisBound[j]) continue; double total_w = 0; int deg = degree[j]; int *l = link[j]; float *p = vertex[j]; for(int k=0; kvertex[j]; //replace each vertex p[0] += (float)(dt*L[j][0]); p[1] += (float)(dt*L[j][1]); p[2] += (float)(dt*L[j][2]); } } delete[] L; } void Smoother::moveNormalAreaD(float dt) { int vertex_N = mesh->vertex_N; float (*vertex)[3] = mesh->vertex; float (*normal_f)[3] = mesh->normal_f; double (*dp)[3] = new double[vertex_N][3]; int **link_f = mesh->vertex_link_f; int **link_v = mesh->vertex_link_v; int *degree = mesh->degree_v; for(int i=0; iisBound[i]){ dp[i][0] = dp[i][1] = dp[i][2] = 0; continue; } int deg = degree[i]; if(deg == 0){ dp[i][0] = dp[i][1] = dp[i][2] = 0; continue; } int *l_f = link_f[i]; int *l_v = link_v[i]; double df[3]; df[0] = df[1] = df[2] = 0; float* p =vertex[i]; double total_w = 0; for(int j = 0; jvertex; float (*normal)[3] = mesh->normal_f; int (*face)[3] = mesh->face; int face_N = mesh->face_N; float (*tmp_normal)[3] = new float[face_N][3]; int (*ad_face)[3] = mesh->face_link_E; int **ad_face2 = mesh->face_link_V; int *ad_face2_N = mesh->face_link_V_N; for(int i=0; ifaceArea(i); /* double c[3]; c[0] = (vertex[face[i][0]][0] + vertex[face[i][1]][0] + vertex[face[i][2]][0])/3.0; c[1] = (vertex[face[i][0]][1] + vertex[face[i][1]][1] + vertex[face[i][2]][1])/3.0; c[2] = (vertex[face[i][0]][2] + vertex[face[i][1]][2] + vertex[face[i][2]][2])/3.0; */ for(int j=0; j<3; j++){ int pair = ad_face[i][j]; if(pair < 0) continue; double al = mesh->faceArea(pair); if(al + a == 0) continue; double edge = MeshData::DIST(vertex[face[i][j]], vertex[face[i][(j+1)%3]]); double dot = MeshData::DOT(normal[i], normal[pair]); if(dot > 1) dot = 1; else if(dot < -1) dot = -1; double k = acos(dot)*edge/(a+al);; double w; if(f_type == 0) w = al/(1.0+(k/T)*(k/T)); else w = al*exp(-(k/T)*(k/T)); total_w += w; sum_n[0] += w*normal[pair][0]; sum_n[1] += w*normal[pair][1]; sum_n[2] += w*normal[pair][2]; } /* for(j=0; j= face_N) continue; double c1[3]; c1[0] = (vertex[face[pair][0]][0] + vertex[face[pair][1]][0] + vertex[face[pair][2]][0])/3.0; c1[1] = (vertex[face[pair][0]][1] + vertex[face[pair][1]][1] + vertex[face[pair][2]][1])/3.0; c1[2] = (vertex[face[pair][0]][2] + vertex[face[pair][1]][2] + vertex[face[pair][2]][2])/3.0; double d = MeshData::DIST(c,c1); if((float)d == 0) continue; double area = MeshData::AREA(vertex[face[pair][0]], vertex[face[pair][1]], vertex[face[pair][2]]); double dot = MeshData::DOT(normal[i], normal[pair]); if(dot > 1) dot = 1; else if(dot < -1) dot = -1; double k = acos(dot)/d; double w; if(f_type == 0) w = rate*area/(1.0+(k/T)*(k/T)); else w = rate*area*exp(-(k/T)*(k/T)); total_w += w; sum_n[0] += w*normal[pair][0]; sum_n[1] += w*normal[pair][1]; sum_n[2] += w*normal[pair][2]; }*/ if((float)total_w != 0){ tmp_normal[i][0] = (float)(sum_n[0]/total_w); tmp_normal[i][1] = (float)(sum_n[1]/total_w); tmp_normal[i][2] = (float)(sum_n[2]/total_w); double len = MeshData::LENGTH(tmp_normal[i]); if((float)len != 0){ tmp_normal[i][0] = (float)(tmp_normal[i][0]/len); tmp_normal[i][1] = (float)(tmp_normal[i][1]/len); tmp_normal[i][2] = (float)(tmp_normal[i][2]/len); } else{ tmp_normal[i][0] = normal[i][0]; tmp_normal[i][1] = normal[i][1]; tmp_normal[i][2] = normal[i][2]; } } else{ tmp_normal[i][0] = normal[i][0]; tmp_normal[i][1] = normal[i][1]; tmp_normal[i][2] = normal[i][2]; } } delete[] normal; mesh->normal_f = tmp_normal; } void Smoother::moveNormalAreaD(float dt, int power) { int vertex_N = mesh->vertex_N; float (*vertex)[3] = mesh->vertex; float (*normal_f)[3] = mesh->normal_f; double (*dp)[3] = new double[vertex_N][3]; int **link_f = mesh->vertex_link_f; int **link_v = mesh->vertex_link_v; int *degree = mesh->degree_v; for(int i=0; iisBound[i]){ dp[i][0] = dp[i][1] = dp[i][2] = 0; continue; } int deg = degree[i]; if(deg == 0){ dp[i][0] = dp[i][1] = dp[i][2] = 0; continue; } int *l_f = link_f[i]; int *l_v = link_v[i]; double df[3]; df[0] = df[1] = df[2] = 0; float* p =vertex[i]; double total_w = 0; for(int j = 0; jvertex_N; float (*vertex)[3] = mesh->vertex; float (*normal)[3]; int *dist = new int[vertex_N]; int max_dist = 3; Node** ridge = mesh->ridge_edge; Node** ravine = mesh->ravine_edge; Node** tag = new Node*[vertex_N]; for(int i=0; inext!=NULL; current=current->next) tag[i]->append(current->v, -1); for(current = ravine[i]; current->next!=NULL; current=current->next) tag[i]->append(current->v, -1); if(tag[i]->next!=NULL) dist[i] = 0; else dist[i] = 10000; } for(i=0; iget1Ring(j, nei, nei_N); if(nei_N == 0) continue; for(int k=0; k 0) near_N++; } int* tag_index = new int[tag_N]; int* tag_deg = new int[tag_N]; tag_N = 0; int* near_index = new int[near_N]; near_N = 0; for(i=0; inext != NULL; current=current->next) c++; tag_deg[tag_N] = c; tag_N++; } else if(dist[i] > 0){ near_index[near_N++] = i; } } double (*L)[3] = new double[vertex_N][3]; double (*BL)[3] = new double[vertex_N][3]; for(i=0; icomputeFaceNormal(); mesh->computeNormal(); normal = mesh->normal; for(int j=0; jnext!=NULL; current=current->next){ m++; L[j][0] += vertex[current->v][0]; L[j][1] += vertex[current->v][1]; L[j][2] += vertex[current->v][2]; } if(m > 1){ L[j][0] = L[j][0]/(float)m - vertex[j][0]; L[j][1] = L[j][1]/(float)m - vertex[j][1]; L[j][2] = L[j][2]/(float)m - vertex[j][2]; double inner = MeshData::DOT(L[j], normal[j]); L[j][0] = L[j][0] - inner*normal[j][0]; L[j][1] = L[j][1] - inner*normal[j][1]; L[j][2] = L[j][2] - inner*normal[j][2]; } else{ L[j][0] = L[j][1] = L[j][2] = 0; } } for(j=0; j max_dist) continue; int *nei, nei_N; mesh->get1Ring(j, nei, nei_N); if(nei_N == 0) continue; for(int k=0; k= max_dist) continue; int *nei, nei_N; mesh->get1Ring(j, nei, nei_N); if(nei_N == 0) continue; for(int k=0; knext!=NULL; current=current->next){ m++; BL[j][0] += L[current->v][0]; BL[j][1] += L[current->v][1]; BL[j][2] += L[current->v][2]; } if(m!=0){ BL[j][0] = BL[j][0]/(float)m - L[j][0]; BL[j][1] = BL[j][1]/(float)m - L[j][1]; BL[j][2] = BL[j][2]/(float)m - L[j][2]; } */ } for(j=0; jisBound[j]){ vertex[j][0] -= (float)(dt*BL[j][0]); vertex[j][1] -= (float)(dt*BL[j][1]); vertex[j][2] -= (float)(dt*BL[j][2]); } } } delete[] L; delete[] BL; delete[] dist; for(i=0; inormal_f; float (*vertex)[3] = mesh->vertex; Node** ridge_edge = mesh->ridge_edge; } void Smoother::Bilaplacian(int iter, float dt) { int vertex_N = mesh->vertex_N; double (*L)[3] = new double[vertex_N][3]; double (*B)[3] = new double[vertex_N][3]; BOOL *isBound = mesh->isBound; int **link = mesh->vertex_link_v; int *degree = mesh->degree_v; float (*vertex)[3] = mesh->vertex; for(int i=0; ilaplacian(j, L[j]); } for(j=0; jnormal_f; int (*face)[3] = mesh->face; int face_N = mesh->face_N; float (*tmp_normal)[3] = new float[face_N][3]; int (*ad_face)[3] = mesh->face_link_E; int count = 0; for(int k=0; kcomputeFaceNormal(); mesh->computeNormal(); float (*normal)[3] = mesh->normal_f; int (*face)[3] = mesh->face; int face_N = mesh->face_N; int (*ad_face)[3] = mesh->face_link_E; float (*normal_v)[3] = mesh->normal; int count = 0; for(int i=0; inormal_f; int (*face)[3] = mesh->face; int face_N = mesh->face_N; float (*tmp_normal)[3] = new float[face_N][3]; int (*ad_face)[3] = mesh->face_link_E; int **ad_face2 = mesh->face_link_V; int *ad_face2_N = mesh->face_link_V_N; mesh->computeCenter(); float (*center)[3] = mesh->center; for(int i=0; i= face_N) continue; n++; } //compute diffrences int *f_index = new int[n]; double *diff = new double[n]; float *nP = normal[i]; n=0; for(j=0; j<3; j++){ int pair = ad_face[i][j]; if(pair < 0) continue; f_index[n] = pair; double dot = MeshData::DOT(nP, normal[pair]); if(dot > 1) dot = 1; if(dot < -1) dot = -1; diff[n] = acos(dot); if(d_type == 1){ double dist = MeshData::DIST(center[i], center[pair]); if(dist != 0) diff[n] /= dist; else diff[n] = 0; } n++; if(isWeighted){ diff[n] = diff[n-1]; f_index[n] = f_index[n-1]; n++; } } for(j=0; j= face_N) continue; f_index[n] = pair; double dot = MeshData::DOT(nP, normal[pair]); if(dot > 1) dot = 1; if(dot < -1) dot = -1; diff[n] = acos(dot); if(d_type == 1){ double dist = MeshData::DIST(center[i], center[pair]); if(dist != 0) diff[n] /= dist; else diff[n] = 0; } n++; } int m = n/2; if(m%2 != 0) m += 1; for(j=0; j diff[k]) min = k; int tmp = f_index[j]; f_index[j] = f_index[min]; f_index[min] = tmp; double tmp_d = diff[j]; diff[j] = diff[min]; diff[min] = tmp_d; } m = f_index[m-1]; tmp_normal[i][0] = normal[m][0]; tmp_normal[i][1] = normal[m][1]; tmp_normal[i][2] = normal[m][2]; delete[] f_index; delete[] diff; } delete[] normal; mesh->normal_f = tmp_normal; } void Smoother::adaptiveSmoothingM(int iter, BOOL isWeighted, int int_type, int inner_iter, float int_step, int d_type, int ave_iter, int L_deg) { int i,j; if(mesh->face_link_V == NULL) mesh->generateFaceLinkV(); for(i=0; icomputeFaceNormal(); for(j=0; jsmoothNormalMedian(isWeighted, d_type); if(int_type == 0){ for(j=0; jmoveNormal(int_step); } else{ if(L_deg != 1){ for(j=0; jmoveNormalAreaD(int_step, L_deg); } else{ for(j=0; jmoveNormalAreaD(int_step); } } } } void Smoother::LaplacianFlowImplicit(float dt) { PBCG *pbcg = new PBCG; setupPBCG(pbcg); unsigned long k; int n = mesh->vertex_N; int *degree = mesh->degree_v; int **link = mesh->vertex_link_v; double *sa = pbcg->sa; unsigned long *ija = pbcg->ija; for (int j=1;j<=n;j++) sa[j]= 1.0 + dt; ija[1]=n+2; k=n+1; for(int i=1;i<=n;i++){ int deg = degree[i-1]; if(deg == 0 || mesh->isBound[i-1]){ sa[i] = 1.0; ija[i+1]=k+1; continue; } int *tmp = new int[deg]; int *l = link[i-1]; for(int j=0; j tmp[t]){ int i_tmp = tmp[s]; tmp[s] = tmp[t]; tmp[t] = i_tmp; } } } for(j=0; jvertex; //for x for(i=0; ilinbcg(n, old_vertex, new_vertex, 1, 1e-3, 100, &iter, &err); for(i=0; ilinbcg(n, old_vertex, new_vertex, 1, 1e-3, 100, &iter, &err); for(i=0; ilinbcg(n, old_vertex, new_vertex, 1, 1e-3, 100, &iter, &err); for(i=0; ivertex_N; int *degree = mesh->degree_v; int size = vertex_N; for(int i=0; isa = new double[size+2]; pbcg->ija = new unsigned long[size+2]; } void Smoother::MeanCurvatureFlowImplicit(float dt) { PBCG *pbcg = new PBCG; setupPBCG(pbcg); unsigned long k; int n = mesh->vertex_N; int *degree = mesh->degree_v; int **link = mesh->vertex_link_v; float (*vertex)[3] = mesh->vertex; BOOL *isBound = mesh->isBound; double *sa = pbcg->sa; unsigned long *ija = pbcg->ija; ija[1]=n+2; k=n+1; for(int i=1;i<=n;i++){ int ii = i-1; int deg = degree[ii]; if(deg == 0 || isBound[ii]){ sa[i] = 1.0; ija[i+1]=k+1; continue; } int *l = link[ii]; double *w = new double[deg]; for(int j=0; j 0){ A += Ai; double dot1 = -MeshData::DOT(PQ1, QQ); double dot2 = MeshData::DOT(PQ2,QQ); double cot1 = dot1/Ai; double cot2 = dot2/Ai; w[j] += cot1; w[(j+1)%deg] += cot2; total_cot += cot1 + cot2; } } A *= 2.0; if(A > 0){ sa[i] = 1.0 + dt*total_cot/A; for(int k=0; k tmp[t]){ int i_tmp = tmp[s]; tmp[s] = tmp[t]; tmp[t] = i_tmp; double w_tmp = w[s]; w[s] = w[t]; w[t] = w_tmp; } } } for(j=0; jlinbcg(n, old_vertex, new_vertex, 1, 1e-5, 100, &iter, &err); for(i=0; ilinbcg(n, old_vertex, new_vertex, 1, 1e-5, 100, &iter, &err); for(i=0; ilinbcg(n, old_vertex, new_vertex, 1, 1e-5, 100, &iter, &err); for(i=0; ivertex_N; int *degree = mesh->degree_v; int **link = mesh->vertex_link_v; float (*vertex)[3] = mesh->vertex; float (*normal)[3] = mesh->normal_f; int **link_f = mesh->vertex_link_f; BOOL *isBound = mesh->isBound; float o[] = {0,0,0}; double *sa = pbcg->sa; unsigned long *ija = pbcg->ija; ija[1]=n+2; k=n+1; for(int i=1;i<=n;i++){ int ii = i-1; int deg = degree[ii]; if(deg == 0 || isBound[ii]){ sa[i] = 1.0; ija[i+1]=k+1; continue; } int *l = link[ii]; int *l_f = link_f[ii]; double *w = new double[deg]; double *w_P = new double[deg]; for(int j=0; j tmp[t]){ int i_tmp = tmp[s]; tmp[s] = tmp[t]; tmp[t] = i_tmp; double w_tmp = w[s]; w[s] = w[t]; w[t] = w_tmp; w_tmp = w_P[s]; w_P[s] = w_P[t]; w_P[t] = w_tmp; } } } for(j=0; jlinbcg(n, old_vertex, new_vertex, 1, 1e-3, 100, &iter, &err); for(i=0; ilinbcg(n, old_vertex, new_vertex, 1, 1e-3, 100, &iter, &err); for(i=0; ilinbcg(n, old_vertex, new_vertex, 1, 1e-3, 100, &iter, &err); for(i=0; ivertex_N; int iter1; float fret; float *p = new float[3*n]; for(int i=0; ivertex[i][0]; p[3*i+1] = mesh->vertex[i][1]; p[3*i+2] = mesh->vertex[i][2]; } mini.frprmn(p, 3*n, 0.1f, &iter1, &fret); for(i=0; ivertex[i][0] = p[3*i]; mesh->vertex[i][1] = p[3*i+1]; mesh->vertex[i][2] = p[3*i+2]; } } void Smoother::smoothNormalGaussian(int size, float *sigma) { int face_N = mesh->face_N; float (*normal)[3] = mesh->normal_f; int (*link)[3] = mesh->face_link_E; double (*tmp_normal)[3] = new double[face_N][3]; double *area = new double[face_N]; double *geo = new double[face_N]; float (*dist)[3] = new float[face_N][3]; mesh->computeCenter(); float (*center)[3] = mesh->center; int *visit = new int[face_N]; for(int i=0; ifaceArea(i); for(int j=0; j<3; j++){ int ad = link[i][j]; if(ad < 0) continue; if(ad < i){ int k; if(link[ad][0] == i) k = 0; else if(link[ad][1] == i) k = 1; else k = 2; dist[i][j] = dist[ad][k]; } else{ float d = (float)MeshData::DIST(center[i], center[ad]); dist[i][j] = d; } } visit[i] = -1; } for(i=0; iappend(i, 0); visit[i] = i; geo[i] = 0; float *nf = normal[i]; while(Q->next != NULL){ int c = Q->v; int r = Q->f; Node* tmp = Q; Q = Q->next; Q->tail = tmp->tail; tmp->next = NULL; delete tmp; if(geo[c] > 4*sqrt(sigma[i])) continue; //double diff = 1.5*(1.0-MeshData::DOT(normal[i], normal[c])); double w; if(geo[c] <= 2.0*sqrt(sigma[i])) w = exp(-geo[c]*geo[c]/sigma[i]); // - diff); else w = 0.0625*pow(4.0 - geo[c]/sqrt(sigma[c]), 4.0)/(E*E); nor[0] += area[c]*w*normal[c][0]; nor[1] += area[c]*w*normal[c][1]; nor[2] += area[c]*w*normal[c][2]; //if(r == size) //continue; int* l = link[c]; for(int j=0; j<3; j++){ int k = l[j]; if(k < 0) continue; if(visit[k] == i) continue; Q->append(k, r+1); visit[k] = i; int* l_ad = link[k]; geo[k] = 100000; double w1 = (1.0 - MeshData::DOT(nf,normal[k])); //double b = 1.0+20.0*sqrt(1.0-dot); float w = 5.0; if(visit[l_ad[0]] == i){ double w2 = (1.0 - MeshData::DOT(nf,normal[l_ad[0]])); double w3 = (1.0 - MeshData::DOT(normal[k],normal[l_ad[0]]))/3.0; geo[k] = geo[l_ad[0]] + (1.0+w*(w1+w2+w3))*dist[k][0]; } if(visit[l_ad[1]] == i){ double w2 = (1.0 - MeshData::DOT(nf,normal[l_ad[1]])); double w3 = (1.0 - MeshData::DOT(normal[k],normal[l_ad[1]]))/3.0; double d_tmp = geo[l_ad[1]] + (1.0+w*(w1+w2+w3))*dist[k][1]; if(geo[k] > d_tmp) geo[k] = d_tmp; } if(visit[l_ad[2]] == i){ double w2 = (1.0 - MeshData::DOT(nf,normal[l_ad[2]])); double w3 = (1.0 - MeshData::DOT(normal[k],normal[l_ad[2]]))/3.0; double d_tmp = geo[l_ad[2]] + (1.0+w*(w1+w2+w3))*dist[k][2]; if(geo[k] > d_tmp) geo[k] = d_tmp; } /* float dot = MeshData::DOT(nf,normal[k]); if(dot > 1.0) dot = 1; else if(dot < -1) dot = -1; double b = 1.0+20.0*sqrt(1.0-dot); if(visit[l_ad[0]] == i) geo[k] = geo[l_ad[0]] + b*dist[k][0]; if(visit[l_ad[1]] == i){ double d_tmp = geo[l_ad[1]] + b*dist[k][1]; if(geo[k] > d_tmp) geo[k] = d_tmp; } if(visit[l_ad[2]] == i){ double d_tmp = geo[l_ad[2]] + b*dist[k][2]; if(geo[k] > d_tmp) geo[k] = d_tmp; }*/ //geo[k] = geo[c] + dist[c][j]; } } delete Q; tmp_normal[i][0] = nor[0]; tmp_normal[i][1] = nor[1]; tmp_normal[i][2] = nor[2]; } for(i=0; iface_N; int (*link)[3] = mesh->face_link_E; float (*normal)[3] = mesh->normal_f; int *visit = new int[face_N]; for(int i=0; iappend(i, 0); visit[i] = i; while(Q->next != NULL){ int c = Q->v; int r = Q->f; Node* tmp = Q; Q = Q->next; Q->tail = tmp->tail; tmp->next = NULL; delete tmp; M[0] += normal[c][0]; M[1] += normal[c][1]; M[2] += normal[c][2]; n++; if(r == size) continue; int* l = link[c]; for(int j=0; j<3; j++){ int k = l[j]; if(k < 0) continue; if(visit[k] == i) continue; Q->append(k, r+1); visit[k] = i; } } delete Q; M[0] /= n; M[1] /= n; M[2] /= n; sigma[i] = c*c; //*(1.0 - MeshData::DOT(M, M)); } } void Smoother::checkGaussianSupport(int f, float sigma, float T) { int face_N = mesh->face_N; float (*normal)[3] = mesh->normal_f; int (*link)[3] = mesh->face_link_E; double *geo = new double[face_N]; float (*dist)[3] = new float[face_N][3]; mesh->computeCenter(); float (*center)[3] = mesh->center; int(*face)[3] = mesh->face; float (*vertex)[3] = mesh->vertex; if(mesh->triangle_id == NULL) mesh->triangle_id = new int[face_N]; int *id = mesh->triangle_id; for(int i=0; iappend(f, 0); id[f] = 0; geo[f] = 0; float *nf = normal[f]; int count = 0; while(Q->next != NULL){ count++; int c = Q->v; int r = Q->f; Node* tmp = Q; Q = Q->next; Q->tail = tmp->tail; tmp->next = NULL; delete tmp; if(geo[c] > 4*sigma){ id[c] = -1; continue; } //if(geo[c] > 2.0*sigma) //id[c] = 2; id[c] = (int)(255 - 255*geo[c]/(4*sigma)); int* l = link[c]; for(int j=0; j<3; j++){ int k = l[j]; if(k < 0) continue; if(id[k] >= 0) continue; Q->append(k, r+1); id[k] = 1; int* l_ad = link[k]; geo[k] = 100000; double w1 = (1.0 - MeshData::DOT(nf,normal[k])); //double b = 1.0+20.0*sqrt(1.0-dot); if(l_ad[0] >= 0 && id[l_ad[0]] >= 0){ double w2 = (1.0 - MeshData::DOT(nf,normal[l_ad[0]])); double w3 = (1.0 - MeshData::DOT(normal[k],normal[l_ad[0]]))/3.0; geo[k] = geo[l_ad[0]] + (1.0+T*(w1+w2+w3))*dist[k][0]; } if(l_ad[1] >= 0 && id[l_ad[1]] >= 0){ double w2 = (1.0 - MeshData::DOT(nf,normal[l_ad[1]])); double w3 = (1.0 - MeshData::DOT(normal[k],normal[l_ad[1]]))/3.0; double d_tmp = geo[l_ad[1]] + (1.0+T*(w1+w2+w3))*dist[k][1]; if(geo[k] > d_tmp) geo[k] = d_tmp; } if(l_ad[2] >= 0 && id[l_ad[2]] >= 0){ double w2 = (1.0 - MeshData::DOT(nf,normal[l_ad[2]])); double w3 = (1.0 - MeshData::DOT(normal[k],normal[l_ad[2]]))/3.0; double d_tmp = geo[l_ad[2]] + (1.0+T*(w1+w2+w3))*dist[k][2]; if(geo[k] > d_tmp) geo[k] = d_tmp; } } } delete Q; delete[] dist; delete[] geo; } float Smoother::computeSigma1(int f, int size) { int face_N = mesh->face_N; int (*link)[3] = mesh->face_link_E; float (*normal)[3] = mesh->normal_f; int *visit = new int[face_N]; for(int i=0; iappend(f, 0); visit[f] = f; while(Q->next != NULL){ int c = Q->v; int r = Q->f; Node* tmp = Q; Q = Q->next; Q->tail = tmp->tail; tmp->next = NULL; delete tmp; M[0] += normal[c][0]; M[1] += normal[c][1]; M[2] += normal[c][2]; n++; if(r == size) continue; int* l = link[c]; for(int j=0; j<3; j++){ int k = l[j]; if(k < 0) continue; if(visit[k] == f) continue; Q->append(k, r+1); visit[k] = f; } } delete Q; M[0] /= n; M[1] /= n; M[2] /= n; return (float)(1.0 - MeshData::DOT(M, M)); } float Smoother::computeSigma2(int f, int size) { int face_N = mesh->face_N; int (*link)[3] = mesh->face_link_E; float (*normal)[3] = mesh->normal_f; int *visit = new int[face_N]; for(int i=0; iappend(f, 0); visit[f] = f; while(Q->next != NULL){ int c = Q->v; int r = Q->f; Node* tmp = Q; Q = Q->next; Q->tail = tmp->tail; tmp->next = NULL; delete tmp; double dot = MeshData::DOT(nf, normal[c]); if(dot > 1.0) dot = 1; else if(dot < -1.0) dot = -1.0; double a = acos(dot); M += a; sum += a*a; n++; if(r == size) continue; int* l = link[c]; for(int j=0; j<3; j++){ int k = l[j]; if(k < 0) continue; if(visit[k] == f) continue; Q->append(k, r+1); visit[k] = f; } } delete Q; M /= n; sum /= n; return (float)(sum - M*M); } void Smoother::computeOptimalGaussian(float s_min, float s_max, float step, float c) { int face_N = mesh->face_N; float (*normal)[3] = mesh->normal_f; int (*link)[3] = mesh->face_link_E; double (*tmp_normal)[3] = new double[face_N][3]; double *area = new double[face_N]; double *geo = new double[face_N]; float (*dist)[3] = new float[face_N][3]; mesh->computeCenter(); float (*center)[3] = mesh->center; int *visit = new int[face_N]; int (*face)[3] = mesh->face; float (*vertex)[3] = mesh->vertex; if(sigma != NULL) delete[] sigma; sigma = new float[face_N]; //float c = 0.001; //float c = 0.00005; //float total_e = 0; //int n = 0; for(int i=0; ifaceArea(i); for(int j=0; j<3; j++){ int ad = link[i][j]; if(ad < 0) continue; if(ad < i){ int k; if(link[ad][0] == i) k = 0; else if(link[ad][1] == i) k = 1; else k = 2; dist[i][j] = dist[ad][k]; } else{ float *p1 = vertex[face[i][j]]; float *p2 = vertex[face[i][(j+1)%3]]; float p[3]; p[0] = 0.5f*(p1[0] + p2[0]); p[1] = 0.5f*(p1[1] + p2[1]); p[2] = 0.5f*(p1[2] + p2[2]); //float d1 = (float)MeshData::DIST(center[i], center[ad]); float d = (float)(MeshData::DIST(center[i], p) + MeshData::DIST(p, center[ad])); dist[i][j] = d; //n++; //total_e += dist[i][j]; } } visit[i] = -1; } int N = (int)((s_max-s_min)/step) + 1; double (*ns)[3] = new double[N][3]; float *si = new float[N]; double *total_w = new double[N]; for(i=0; iappend(i, 0); visit[i] = i; geo[i] = 0; while(Q->next != NULL){ int c = Q->v; int r = Q->f; Node* tmp = Q; Q = Q->next; Q->tail = tmp->tail; tmp->next = NULL; delete tmp; for(n=0; n 4*si[n]) continue; double w; if(geo[c] <= 2.0*si[n]) w = area[c]*exp(-geo[c]*geo[c]/(si[n]*si[n])); else w = area[c]*0.0625*pow(4.0 - geo[c]/si[n], 4.0)/(E*E); ns[n][0] += w*normal[c][0]; ns[n][1] += w*normal[c][1]; ns[n][2] += w*normal[c][2]; total_w[n] += w; } if(geo[c] > 4*s_max) continue; int* l = link[c]; for(int j=0; j<3; j++){ int k = l[j]; if(k < 0) continue; if(visit[k] == i) continue; Q->append(k, r+1); visit[k] = i; int* l_ad = link[k]; geo[k] = 100000; if(l_ad[0] >= 0 && visit[l_ad[0]] == i){ geo[k] = geo[l_ad[0]] + dist[k][0]; } if(l_ad[1] >= 0 && visit[l_ad[1]] == i){ double d_tmp = geo[l_ad[1]] + dist[k][1]; if(geo[k] > d_tmp) geo[k] = d_tmp; } if(l_ad[2] >= 0 && visit[l_ad[2]] == i){ double d_tmp = geo[l_ad[2]] + dist[k][2]; if(geo[k] > d_tmp) geo[k] = d_tmp; } } } delete Q; float *ni = normal[i]; double min = 100000000; int opt; for(n=0; n v){ opt = n; min = v; } } sigma[i] = (si[opt] - s_min)/(s_max - s_min); double len = MeshData::LENGTH(ns[opt]); tmp_normal[i][0] = ns[opt][0]/len; tmp_normal[i][1] = ns[opt][1]/len; tmp_normal[i][2] = ns[opt][2]/len; } delete[] ns; delete[] si; delete[] total_w; for(i=0; idegree_v; int* deg_f = mesh->degree_f; int **link_v = mesh->vertex_link_v; int **link_f = mesh->vertex_link_f; int (*link_e)[3] = mesh->face_link_E; BOOL* isBound = mesh->isBound; int (*face)[3] = mesh->face; if(isBound[i1] || isBound[i2]) return false; int deg1 = deg_v[i1]; int deg2 = deg_v[i2]; if(deg1 < 4 || deg2 < 4) return false; int* lv1 = link_v[i1]; int* lv2 = link_v[i2]; int* lf1 = link_f[i1]; int* lf2 = link_f[i2]; int f1, f2; for(int i=0; inormal_f; float (*vertex)[3] = mesh->vertex; float v1[3], v2[3]; int *f = face[f1]; MeshData::VEC(v1, vertex[f[0]], vertex[f[1]]); MeshData::VEC(v2, vertex[f[0]], vertex[f[2]]); double n[3]; MeshData::CROSS(n, v1, v2); double len = MeshData::LENGTH(n); if((float)len != 0){ normal[f1][0] = (float)(n[0]/len); normal[f1][1] = (float)(n[1]/len); normal[f1][2] = (float)(n[2]/len); } else normal[f1][0] = normal[f1][1] = normal[f1][2] = 0; f = face[f2]; MeshData::VEC(v1, vertex[f[0]], vertex[f[1]]); MeshData::VEC(v2, vertex[f[0]], vertex[f[2]]); MeshData::CROSS(n, v1, v2); len = MeshData::LENGTH(n); if((float)len != 0){ normal[f2][0] = (float)(n[0]/len); normal[f2][1] = (float)(n[1]/len); normal[f2][2] = (float)(n[2]/len); } else normal[f2][0] = normal[f2][1] = normal[f2][2] = 0; //update face link int *e1 = link_e[f1]; int *e2 = link_e[f2]; int index1, index2, f12, f21; for(i=0; i<3; i++){ if(e1[i] == f2){ index1 = (i+2)%3; f12 = e1[index1]; e1[index1] = f2; index1 = i; break; } } for(i=0; i<3; i++){ if(e2[i] == f1){ index2 = (i+2)%3; f21 = e2[index2]; e2[index2] = f1; index2 = i; break; } } e1[index1] = f21; e2[index2] = f12; e1 = link_e[f12]; for(i=0; i<3; i++){ if(e1[i] == f1){ e1[i] = f2; break; } } e2 = link_e[f21]; for(i=0; i<3; i++){ if(e2[i] == f2){ e2[i] = f1; break; } } return true; } void Smoother::antialiasingEdgeFlip() { int face_N = mesh->face_N; int (*face)[3] = mesh->face; int (*f_link)[3] = mesh->face_link_E; float (*normal)[3] = mesh->normal_f; int vertex_N = mesh->vertex_N; int **e_table = new int*[vertex_N]; int *degree = mesh->degree_v; int *edge_count = new int[vertex_N]; for(int i=0; i -0.0000001){ index[i] = -1; continue; } //insert; heap[++last_heap] = i; index[i] = last_heap; upheap(q, last_heap, last_heap, heap, index); } while(last_heap != 0){ int min = heap[1]; index[min] = -1; //remove if(last_heap != 1){ heap[1] = heap[last_heap--]; index[heap[1]] = 1; downheap(q, last_heap, 1, heap, index); } else last_heap = 0; int i1 = edge[min][0]; int i2 = edge[min][1]; int i3, i4; if(!flipEdge(i1, i2, i3, i4)) continue; edge[min][0] = i3; edge[min][1] = i4; int deg1 = degree[i1]; int *oe1 = e_table[i1]; int *ne1 = new int[deg1]; int c = 0; for(int i=0; i -0.0000001) continue; else{ //continue; //insert into Q heap[++last_heap] = e; index[e] = last_heap; upheap(q, last_heap, last_heap, heap, index); } } else{ if(q[e] > -0.0000001){ //delete from Q float tmp = q[e]; q[e] = -1000000; upheap(q, last_heap, index[e], heap, index); index[e] = -1; heap[1] = heap[last_heap--]; index[heap[1]] = 1; downheap(q, last_heap, 1, heap, index); q[e] = tmp; } else{ //update Q if(index[e] != 1 && q[e] < q[heap[index[e]/2]]) upheap(q, last_heap, index[e], heap, index); else downheap(q, last_heap, index[e], heap, index); } } } int deg2 = degree[i2]; int *oe2 = e_table[i2]; int *ne2 = new int[deg2]; c = 0; for(i=0; i -0.0000001) continue; else{ //continue; //insert into Q heap[++last_heap] = e; index[e] = last_heap; upheap(q, last_heap, last_heap, heap, index); } } else{ if(q[e] > -0.0000001){ //delete from Q float tmp = q[e]; q[e] = -1000000; upheap(q, last_heap, index[e], heap, index); index[e] = -1; heap[1] = heap[last_heap--]; index[heap[1]] = 1; downheap(q, last_heap, 1, heap, index); q[e] = tmp; } else{ //update Q if(index[e] != 1 && q[e] < q[heap[index[e]/2]]) upheap(q, last_heap, index[e], heap, index); else downheap(q, last_heap, index[e], heap, index); } } } int deg3 = degree[i3]; int *oe3 = e_table[i3]; int *ne3 = new int[deg3]; for(i=0; i -0.0000001) continue; else{ //continue; //insert into Q heap[++last_heap] = e; index[e] = last_heap; upheap(q, last_heap, last_heap, heap, index); } } else{ if(q[e] > -0.0000001){ //delete from Q float tmp = q[e]; q[e] = -1000000; upheap(q, last_heap, index[e], heap, index); index[e] = -1; heap[1] = heap[last_heap--]; index[heap[1]] = 1; downheap(q, last_heap, 1, heap, index); q[e] = tmp; } else{ //update Q if(index[e] != 1 && q[e] < q[heap[index[e]/2]]) upheap(q, last_heap, index[e], heap, index); else downheap(q, last_heap, index[e], heap, index); } } } int deg4 = degree[i4]; int *oe4 = e_table[i4]; int *ne4 = new int[deg4]; for(i=0; i -0.0000001) continue; else{ //continue; //insert into Q heap[++last_heap] = e; index[e] = last_heap; upheap(q, last_heap, last_heap, heap, index); } } else{ if(q[e] > -0.0000001){ //delete from Q float tmp = q[e]; q[e] = -1000000; upheap(q, last_heap, index[e], heap, index); index[e] = -1; heap[1] = heap[last_heap--]; index[heap[1]] = 1; downheap(q, last_heap, 1, heap, index); q[e] = tmp; } else{ //update Q if(index[e] != 1 && q[e] < q[heap[index[e]/2]]) upheap(q, last_heap, index[e], heap, index); else downheap(q, last_heap, index[e], heap, index); } } } } delete[] q; delete[] edge; delete[] heap; delete[] index; for(i=0; i 1 && a[p[k/2]] >= a[v]){ p[k] = p[k/2]; q[p[k/2]] = k; k = k/2; } p[k] = v; q[v] = k; } inline void Smoother::downheap(float *a, int N, int k, int *p, int *q) { int j, v; v = p[k]; while(k <= N/2){ j = k+k; if(j < N && a[p[j]] > a[p[j+1]]) j++; if(a[v] <= a[p[j]]) break; p[k] = p[j]; q[p[j]] = k; k = j; } p[k] = v; q[v] = k; } float Smoother::computeAliasingMeasure(int i1, int i2) { int f1, index1; int deg = mesh->degree_f[i1]; int *link_v = mesh->vertex_link_v[i1]; int *link_f = mesh->vertex_link_f[i1]; for(int i=0; iface[f1]; if(v1[0] == i1){ if(v1[1] == i2) index1 = 0; else index1 = 2; } else if(v1[1] == i1){ if(v1[0] == i2) index1 = 0; else index1 = 1; } else{ if(v1[0] == i2) index1 = 2; else index1 = 1; } int *l1 = mesh->face_link_E[f1]; int f2 = l1[index1]; if(f2 < 0) return 0; int *v2 = mesh->face[f2]; int *l2 = mesh->face_link_E[f2]; float *p1 = mesh->vertex[v1[index1]]; float *p2 = mesh->vertex[v1[(index1+1)%3]]; float *p3 = mesh->vertex[v1[(index1+2)%3]]; float *p4; int index2; if(l2[0] == f1){ p4 = mesh->vertex[v2[2]]; index2 = 0; } else if(l2[1] == f1){ p4 = mesh->vertex[v2[0]]; index2 = 1; } else { p4 = mesh->vertex[v2[1]]; index2 = 2; } float (*normal)[3] = mesh->normal_f; float *n1 = normal[f1]; if(l1[(index1+1)%3] < 0) return 0; float *n1f = normal[l1[(index1+1)%3]]; if(l1[(index1+2)%3] < 0) return 0; float *n1b = normal[l1[(index1+2)%3]]; float *n2 = normal[f2]; if(l2[(index2+2)%3] < 0) return 0; float *n2f = normal[l2[(index2+2)%3]]; if(l2[(index2+1)%3] < 0) return 0; float *n2b = normal[l2[(index2+1)%3]]; float b1, b2, b1m, b2m; b1 = b2 = b1m = b2m = (float)MeshData::DOT(n1, n2); float dot = (float)MeshData::DOT(n1, n1f); b1 += dot; b1m = min(b1m, dot); dot = (float)MeshData::DOT(n1, n1b); b1 += dot; b1m = min(b1m, dot); //b1 -= b1m; dot = (float)MeshData::DOT(n2, n2f); b2 += dot; b2m = min(b2m, dot); dot = (float)MeshData::DOT(n2, n2b); b2 += dot; b2m = min(b2m, dot); //b2 -= b2m; float m1[3], m2[3]; float e1[3], e2[3]; MeshData::VEC(e1, p2, p3); MeshData::VEC(e2, p2, p4); double n[3]; MeshData::CROSS(n, e1, e2); double len = MeshData::LENGTH(n); if((float)len != 0){ m1[0] = (float)(n[0]/len); m1[1] = (float)(n[1]/len); m1[2] = (float)(n[2]/len); } else return 0; if(MeshData::DOT(n1,m1) < 0 || MeshData::DOT(n2,m1) < 0) return 0; MeshData::VEC(e1, p1, p4); MeshData::VEC(e2, p1, p3); n[3]; MeshData::CROSS(n, e1, e2); len = MeshData::LENGTH(n); if((float)len != 0){ m2[0] = (float)(n[0]/len); m2[1] = (float)(n[1]/len); m2[2] = (float)(n[2]/len); } else return 0; if(MeshData::DOT(n1,m2) < 0 || MeshData::DOT(n2,m2) < 0) return 0; float a1, a2, a1m, a2m; a1 = a2 = a1m = a2m = (float)MeshData::DOT(m1, m2); dot = (float)MeshData::DOT(m1, n1f); a1 += dot; a1m = min(a1m, dot); dot = (float)MeshData::DOT(m1, n2f); a1 += dot; a1m = min(a1m, dot); //a1 -= a1m; dot = (float)MeshData::DOT(m2, n1b); a2 += dot; a2m = min(a2m, dot); dot = (float)MeshData::DOT(m2, n2b); a2 += dot; a2m = min(a2m, dot); //a2 -= a2m; return (a1 + a2) - (b1 + b2); } void Smoother::adaptiveGaussianSmoothing(float c, BOOL is_anistoropic, float w) { float e = mesh->averageOfEdgeLength(); /*********************************** int face_N = mesh->face_N; float (*normal)[3] = mesh->normal_f; float (*o_normal)[3] = new float[face_N][3];; for(int i=0; iface_N; float (*normal)[3] = mesh->normal_f; int (*link)[3] = mesh->face_link_E; double (*tmp_normal)[3] = new double[face_N][3]; double *area = new double[face_N]; double *geo = new double[face_N]; float (*dist)[3] = new float[face_N][3]; mesh->computeCenter(); float (*center)[3] = mesh->center; int *visit = new int[face_N]; int (*face)[3] = mesh->face; float (*vertex)[3] = mesh->vertex; if(sigma != NULL) delete[] sigma; sigma = new float[face_N]; //float c = 0.001; //float c = 0.00005; //float total_e = 0; //int n = 0; for(int i=0; ifaceArea(i); for(int j=0; j<3; j++){ int ad = link[i][j]; if(ad < 0) continue; if(ad < i){ int k; if(link[ad][0] == i) k = 0; else if(link[ad][1] == i) k = 1; else k = 2; dist[i][j] = dist[ad][k]; } else{ float *p1 = vertex[face[i][j]]; float *p2 = vertex[face[i][(j+1)%3]]; float p[3]; p[0] = 0.5f*(p1[0] + p2[0]); p[1] = 0.5f*(p1[1] + p2[1]); p[2] = 0.5f*(p1[2] + p2[2]); //float d1 = (float)MeshData::DIST(center[i], center[ad]); float d = (float)(MeshData::DIST(center[i], p) + MeshData::DIST(p, center[ad])); dist[i][j] = d; //float d = (float)MeshData::DIST(center[i], center[ad]); //dist[i][j] = d; //n++; //total_e += dist[i][j]; } } visit[i] = -1; } int N = (int)((s_max-s_min)/step) + 1; double (*ns)[3] = new double[N][3]; float *si = new float[N]; double *total_w = new double[N]; for(i=0; iappend(i, 0); visit[i] = i; geo[i] = 0; float *nf = normal[i]; while(Q->next != NULL){ int c = Q->v; int r = Q->f; Node* tmp = Q; Q = Q->next; Q->tail = tmp->tail; tmp->next = NULL; delete tmp; for(n=0; n 4*si[n]) continue; double w; if(geo[c] <= 2.0*si[n]) w = area[c]*exp(-geo[c]*geo[c]/(si[n]*si[n])); else w = area[c]*0.0625*pow(4.0 - geo[c]/si[n], 4.0)/(E*E); ns[n][0] += w*normal[c][0]; ns[n][1] += w*normal[c][1]; ns[n][2] += w*normal[c][2]; total_w[n] += w; } if(geo[c] > 4*s_max) continue; int* l = link[c]; for(int j=0; j<3; j++){ int k = l[j]; if(k < 0) continue; if(visit[k] == i) continue; Q->append(k, r+1); visit[k] = i; int* l_ad = link[k]; geo[k] = 100000; double w1 = (1.0 - MeshData::DOT(nf,normal[k])); //double b = 1.0+20.0*sqrt(1.0-dot); if(l_ad[0] >= 0 && visit[l_ad[0]] == i){ double w2 = (1.0 - MeshData::DOT(nf,normal[l_ad[0]])); double w3 = (1.0 - MeshData::DOT(normal[k],normal[l_ad[0]]))/3.0; geo[k] = geo[l_ad[0]] + (1.0+T*(w1+w2+w3))*dist[k][0]; } if(l_ad[1] >= 0 && visit[l_ad[1]] == i){ double w2 = (1.0 - MeshData::DOT(nf,normal[l_ad[1]])); double w3 = (1.0 - MeshData::DOT(normal[k],normal[l_ad[1]]))/3.0; double d_tmp = geo[l_ad[1]] + (1.0+T*(w1+w2+w3))*dist[k][1]; if(geo[k] > d_tmp) geo[k] = d_tmp; } if(l_ad[2] >= 0 && visit[l_ad[2]] == i){ double w2 = (1.0 - MeshData::DOT(nf,normal[l_ad[2]])); double w3 = (1.0 - MeshData::DOT(normal[k],normal[l_ad[2]]))/3.0; double d_tmp = geo[l_ad[2]] + (1.0+T*(w1+w2+w3))*dist[k][2]; if(geo[k] > d_tmp) geo[k] = d_tmp; } } } delete Q; float *ni = normal[i]; double min = 100000000; int opt; for(n=0; n v){ opt = n; min = v; } } sigma[i] = (si[opt] - s_min)/(s_max - s_min); double len = MeshData::LENGTH(ns[opt]); tmp_normal[i][0] = ns[opt][0]/len; tmp_normal[i][1] = ns[opt][1]/len; tmp_normal[i][2] = ns[opt][2]/len; } delete[] ns; delete[] si; delete[] total_w; for(i=0; ivertex_N; float (*vertex)[3] = mesh->vertex; float (*normal)[3] = mesh->normal; int **link = mesh->vertex_link_v; int *degree = mesh->degree_v; float noise; srand(100); float size = mesh->averageOfEdgeLength(); for(int i=0; i= 1.0 || r == 0.0); double f = sqrt(-2.0*log(r)/r); //if(vertex[i][1] > 0) //r1 = 0; noise = (float)(size*rate*r1*f); vertex[i][0] += normal[i][0]*noise; vertex[i][1] += normal[i][1]*noise; vertex[i][2] += normal[i][2]*noise; if(++i == vertex_N) return; else{ //if(vertex[i][1] > 0) //r2 = 0; noise = (float)(size*rate*r2*f); vertex[i][0] += normal[i][0]*noise; vertex[i][1] += normal[i][1]*noise; vertex[i][2] += normal[i][2]*noise; } } } void Smoother::checkGauusianSupportDikstra(int f, float sigma, float w) { int face_N = mesh->face_N; float (*normal)[3] = mesh->normal_f; int (*link)[3] = mesh->face_link_E; double *geo = new double[face_N]; float (*dist)[3] = new float[face_N][3]; mesh->computeCenter(); float (*center)[3] = mesh->center; int(*face)[3] = mesh->face; float (*vertex)[3] = mesh->vertex; for(int i=0; itriangle_id; if(mesh->triangle_id == NULL){ mesh->triangle_id = new int[face_N]; id = mesh->triangle_id; for(i=0; i= 0) continue; double w1 = 0;//(1.0 - MeshData::DOT(nf,normal[u])); double w2 = 0; //(1.0 - MeshData::DOT(nf,normal[v])); double w3 = (1.0 - MeshData::DOT(normal[u],normal[v])); //3.0; double g = (1.0+10*w*(w1+w2+w3))*dist[u][j]; double M = geo[u] + g; if(M > 4*sigma) continue; if(!visit[v]){ geo[v] = M; //insert; heap[++last_heap] = v; index[v] = last_heap; visit[v] = true; //upheap; upheap(geo, last_heap, last_heap, heap, index); } else if(M < geo[v]){ geo[v] = M; //change; if(index[v] != 1 && M < geo[heap[index[v]/2]]) //upheap; upheap(geo, last_heap, index[v], heap, index); else //downheap; downheap(geo, last_heap, index[v], heap, index); } } if(last_heap == 0) break; //delete; u = heap[1]; heap[1] = heap[last_heap--]; index[heap[1]] = 1; //down heap; downheap(geo, last_heap, 1, heap, index); if(last_heap == 0) break; } delete[] index; delete[] heap; delete[] dist; delete[] geo; delete[] visit; } inline void Smoother::upheap(double *a, int N, int k, int *p, int *q) { int v; v = p[k]; while(k > 1 && a[p[k/2]] >= a[v]){ p[k] = p[k/2]; q[p[k/2]] = k; k = k/2; } p[k] = v; q[v] = k; } inline void Smoother::downheap(double *a, int N, int k, int *p, int *q) { int j, v; v = p[k]; while(k <= N/2){ j = k+k; if(j < N && a[p[j]] > a[p[j+1]]) j++; if(a[v] <= a[p[j]]) break; p[k] = p[j]; q[p[j]] = k; k = j; } p[k] = v; q[v] = k; } void Smoother::computeOptimalGaussianDikstra(float s_min, float s_max, float step, float c) { int face_N = mesh->face_N; float (*normal)[3] = mesh->normal_f; int (*link)[3] = mesh->face_link_E; double (*tmp_normal)[3] = new double[face_N][3]; double *area = new double[face_N]; double *geo = new double[face_N]; float (*dist)[3] = new float[face_N][3]; mesh->computeCenter(); float (*center)[3] = mesh->center; int (*face)[3] = mesh->face; float (*vertex)[3] = mesh->vertex; int *visit = new int[face_N]; bool *decide = new bool[face_N]; if(sigma != NULL) delete[] sigma; sigma = new float[face_N]; //float c = 0.001; //float c = 0.00005; //float total_e = 0; //int n = 0; for(int i=0; ifaceArea(i); for(int j=0; j<3; j++){ int ad = link[i][j]; if(ad < 0) continue; if(ad < i){ int k; if(link[ad][0] == i) k = 0; else if(link[ad][1] == i) k = 1; else k = 2; dist[i][j] = dist[ad][k]; } else{ float *p1 = vertex[face[i][j]]; float *p2 = vertex[face[i][(j+1)%3]]; float p[3]; p[0] = 0.5f*(p1[0] + p2[0]); p[1] = 0.5f*(p1[1] + p2[1]); p[2] = 0.5f*(p1[2] + p2[2]); //float d1 = (float)MeshData::DIST(center[i], center[ad]); float d = (float)(MeshData::DIST(center[i], p) + MeshData::DIST(p, center[ad])); dist[i][j] = d; //n++; //total_e += dist[i][j]; } } visit[i] = -1; decide[i] = false; } int N = (int)((s_max-s_min)/step) + 1; double (*ns)[3] = new double[N][3]; float *si = new float[N]; double *total_w = new double[N]; for(i=0; i 4*si[n]) continue; double w; if(geo[u] <= 2.0*si[n]) w = area[u]*exp(-geo[u]*geo[u]/(2*si[n]*si[n])); else w = area[u]*0.0625*pow(4.0 - geo[u]/si[n], 4.0)/(E*E); ns[n][0] += w*normal[u][0]; ns[n][1] += w*normal[u][1]; ns[n][2] += w*normal[u][2]; total_w[n] += w; } int *nei = link[u]; for(int j=0; j<3; j++){ int v = nei[j]; if(v < 0 || (visit[v] == i && decide[v])) continue; double M = geo[u] + dist[u][j]; if(M > 4*s_max) continue; if(visit[v] != i){ geo[v] = M; //insert; heap[++last_heap] = v; index[v] = last_heap; visit[v] = i; decide[v] = false; //upheap; upheap(geo, last_heap, last_heap, heap, index); } else if(M < geo[v]){ geo[v] = M; //change; if(index[v] != 1 && M < geo[heap[index[v]/2]]) //upheap; upheap(geo, last_heap, index[v], heap, index); else //downheap; downheap(geo, last_heap, index[v], heap, index); } } if(last_heap == 0) break; //delete; u = heap[1]; heap[1] = heap[last_heap--]; index[heap[1]] = 1; //down heap; downheap(geo, last_heap, 1, heap, index); if(last_heap == 0) break; } float *ni = normal[i]; double min = 100000000; int opt; for(n=0; n v){ opt = n; min = v; } } sigma[i] = (si[opt] - s_min)/(s_max - s_min); double len = MeshData::LENGTH(ns[opt]); tmp_normal[i][0] = ns[opt][0]/len; tmp_normal[i][1] = ns[opt][1]/len; tmp_normal[i][2] = ns[opt][2]/len; } delete[] index; delete[] heap; delete[] dist; delete[] geo; delete[] visit; delete[] decide; delete[] area; delete[] ns; delete[] si; delete[] total_w; for(i=0; iface_N; float (*normal)[3] = mesh->normal_f; int (*link)[3] = mesh->face_link_E; double (*tmp_normal)[3] = new double[face_N][3]; double *area = new double[face_N]; double *geo = new double[face_N]; float (*dist)[3] = new float[face_N][3]; mesh->computeCenter(); float (*center)[3] = mesh->center; int (*face)[3] = mesh->face; float (*vertex)[3] = mesh->vertex; int *visit = new int[face_N]; bool *decide = new bool[face_N]; if(sigma != NULL) delete[] sigma; sigma = new float[face_N]; //float c = 0.001; //float c = 0.00005; //float total_e = 0; //int n = 0; for(int i=0; ifaceArea(i); for(int j=0; j<3; j++){ int ad = link[i][j]; if(ad < 0) continue; if(ad < i){ int k; if(link[ad][0] == i) k = 0; else if(link[ad][1] == i) k = 1; else k = 2; dist[i][j] = dist[ad][k]; } else{ float *p1 = vertex[face[i][j]]; float *p2 = vertex[face[i][(j+1)%3]]; float p[3]; p[0] = 0.5f*(p1[0] + p2[0]); p[1] = 0.5f*(p1[1] + p2[1]); p[2] = 0.5f*(p1[2] + p2[2]); //float d1 = (float)MeshData::DIST(center[i], center[ad]); float d = (float)(MeshData::DIST(center[i], p) + MeshData::DIST(p, center[ad])); dist[i][j] = d; //n++; //total_e += dist[i][j]; } } visit[i] = -1; decide[i] = false; } int N = (int)((s_max-s_min)/step) + 1; double (*ns)[3] = new double[N][3]; float *si = new float[N]; double *total_w = new double[N]; for(i=0; i 4*si[n]) continue; double w; if(geo[u] <= 2.0*si[n]) w = area[u]*exp(-geo[u]*geo[u]/(2*si[n]*si[n])); else w = area[u]*0.0625*pow(4.0 - geo[u]/si[n], 4.0)/(E*E); ns[n][0] += w*normal[u][0]; ns[n][1] += w*normal[u][1]; ns[n][2] += w*normal[u][2]; total_w[n] += w; } int *nei = link[u]; for(int j=0; j<3; j++){ int v = nei[j]; if(v < 0 || (visit[v] == i && decide[v])) continue; double w1 = (1.0 - MeshData::DOT(nf,normal[u])); double w2 = (1.0 - MeshData::DOT(nf,normal[v])); double w3 = (1.0 - MeshData::DOT(normal[u],normal[v]))/3.0; double g = (1.0+T*(w1+w2+w3))*dist[u][j]; double M = geo[u] + g; if(M > 4*s_max) continue; if(visit[v] != i){ geo[v] = M; //insert; heap[++last_heap] = v; index[v] = last_heap; visit[v] = i; decide[v] = false; //upheap; upheap(geo, last_heap, last_heap, heap, index); } else if(M < geo[v]){ geo[v] = M; //change; if(index[v] != 1 && M < geo[heap[index[v]/2]]) //upheap; upheap(geo, last_heap, index[v], heap, index); else //downheap; downheap(geo, last_heap, index[v], heap, index); } } if(last_heap == 0) break; //delete; u = heap[1]; heap[1] = heap[last_heap--]; index[heap[1]] = 1; //down heap; downheap(geo, last_heap, 1, heap, index); if(last_heap == 0) break; } float *ni = normal[i]; double min = 100000000; int opt; for(n=0; n v){ opt = n; min = v; } } sigma[i] = (si[opt] - s_min)/(s_max - s_min); double len = MeshData::LENGTH(ns[opt]); tmp_normal[i][0] = ns[opt][0]/len; tmp_normal[i][1] = ns[opt][1]/len; tmp_normal[i][2] = ns[opt][2]/len; } delete[] index; delete[] heap; delete[] dist; delete[] geo; delete[] visit; delete[] decide; delete[] area; delete[] ns; delete[] si; delete[] total_w; for(i=0; iface_N; float (*normal)[3] = mesh->normal_f; int (*link)[3] = mesh->face_link_E; double (*tmp_normal)[3] = new double[face_N][3]; double *area = new double[face_N]; double *geo = new double[face_N]; float (*dist)[3] = new float[face_N][3]; mesh->computeCenter(); float (*center)[3] = mesh->center; int (*face)[3] = mesh->face; float (*vertex)[3] = mesh->vertex; int *visit = new int[face_N]; bool *decide = new bool[face_N]; if(sigma != NULL) delete[] sigma; sigma = new float[face_N]; for(int i=0; ifaceArea(i); for(int j=0; j<3; j++){ int ad = link[i][j]; if(ad < 0) continue; if(ad < i){ int k; if(link[ad][0] == i) k = 0; else if(link[ad][1] == i) k = 1; else k = 2; dist[i][j] = dist[ad][k]; } else{ float *p1 = vertex[face[i][j]]; float *p2 = vertex[face[i][(j+1)%3]]; float p[3]; p[0] = 0.5f*(p1[0] + p2[0]); p[1] = 0.5f*(p1[1] + p2[1]); p[2] = 0.5f*(p1[2] + p2[2]); float d = (float)(MeshData::DIST(center[i], p) + MeshData::DIST(p, center[ad])); dist[i][j] = d; } } visit[i] = -1; decide[i] = false; } int N = (int)((s_max-s_min)/step) + 1; double (*ns)[3] = new double[N][3]; float *si = new float[N]; double *total_w = new double[N]; for(i=0; iappend(-1, u); decide[u] = true; for(n=0; n 4*si[n]) continue; double w; if(geo[u] <= 2.0*si[n]) w = area[u]*exp(-geo[u]*geo[u]/(si[n]*si[n])); else w = area[u]*0.0625*pow(4.0 - geo[u]/si[n], 4.0)/(E*E); ns[n][0] += w*normal[u][0]; ns[n][1] += w*normal[u][1]; ns[n][2] += w*normal[u][2]; total_w[n] += w; } int *nei = link[u]; for(int j=0; j<3; j++){ int v = nei[j]; if(v < 0 || (visit[v] == i && decide[v])) continue; double w1 = (1.0 - MeshData::DOT(nf,normal[u])); double w2 = (1.0 - MeshData::DOT(nf,normal[v])); double w3 = (1.0 - MeshData::DOT(normal[u],normal[v]))/3.0; double g = (1.0+T*(w1+w2+w3))*dist[u][j]; double M = geo[u] + g; if(M > 4*s_max) continue; if(visit[v] != i){ geo[v] = M; //insert; heap[++last_heap] = v; index[v] = last_heap; visit[v] = i; decide[v] = false; //upheap; upheap(geo, last_heap, last_heap, heap, index); } else if(M < geo[v]){ geo[v] = M; //change; if(index[v] != 1 && M < geo[heap[index[v]/2]]) //upheap; upheap(geo, last_heap, index[v], heap, index); else //downheap; downheap(geo, last_heap, index[v], heap, index); } } if(last_heap == 0) break; //delete; u = heap[1]; heap[1] = heap[last_heap--]; index[heap[1]] = 1; //down heap; downheap(geo, last_heap, 1, heap, index); if(last_heap == 0) break; } float *ni = normal[i]; double min = 100000000; int opt; for(n=0; nnext!=NULL; current=current->next){ int c = current->f; if(geo[c] > 4.0f*si[n]) continue; double w; if(geo[c] <= 2.0*si[n]) w = area[c]*exp(-geo[c]*geo[c]/(si[n]*si[n])); else w = area[c]*0.0625*pow(4.0 - geo[c]/si[n], 4.0)/(E*E); double dot = MeshData::DOT(ns[n], normal[c]); angle += w*acos(dot); } double v = c/(si[n]*si[n]) + angle/(PI*total_w[n]);; if(min > v){ opt = n; min = v; } } sigma[i] = (si[opt] - s_min)/(s_max - s_min); double len = MeshData::LENGTH(ns[opt]); tmp_normal[i][0] = ns[opt][0]; //len; tmp_normal[i][1] = ns[opt][1]; //len; tmp_normal[i][2] = ns[opt][2]; //len; delete Q; } delete[] index; delete[] heap; delete[] dist; delete[] geo; delete[] visit; delete[] decide; delete[] area; delete[] ns; delete[] si; delete[] total_w; for(i=0; iface_N; float (*normal_o)[3] = mesh->normal_f; int (*link)[3] = mesh->face_link_E; double *geo = new double[face_N]; float (*dist)[3] = new float[face_N][3]; mesh->computeCenter(); float (*center)[3] = mesh->center; int(*face)[3] = mesh->face; float (*vertex)[3] = mesh->vertex; mesh->normal_f = NULL; mesh->computeFaceNormal(); //for(int i=0; i<5; i++) //smoothNormal(0, 0, 0); float (*normal)[3] = mesh->normal_f; for(int i=0; i 1.0) dot = 1; else if(dot < -1.0) dot = -1; double a = acos(dot); dist[i][j] = (1.0f + (float)(w*a*a))*d; */ } } } int *id = mesh->triangle_id; if(mesh->triangle_id == NULL){ mesh->triangle_id = new int[face_N]; id = mesh->triangle_id; for(i=0; i= 0) continue; double M = geo[u] + dist[u][j]; if(M > 4*sigma) continue; if(!visit[v]){ geo[v] = M; //insert; heap[++last_heap] = v; index[v] = last_heap; visit[v] = true; //upheap; upheap(geo, last_heap, last_heap, heap, index); } else if(M < geo[v]){ geo[v] = M; //change; if(index[v] != 1 && M < geo[heap[index[v]/2]]) //upheap; upheap(geo, last_heap, index[v], heap, index); else //downheap; downheap(geo, last_heap, index[v], heap, index); } } if(last_heap == 0) break; //delete; u = heap[1]; heap[1] = heap[last_heap--]; index[heap[1]] = 1; //down heap; downheap(geo, last_heap, 1, heap, index); if(last_heap == 0) break; } delete[] index; delete[] heap; delete[] dist; delete[] geo; delete[] visit; delete[] normal; mesh->normal_f = normal_o; } void Smoother::computeOptimalGaussianDikstra2(float s_min, float s_max, float step, float c) { int face_N = mesh->face_N; float (*normal)[3] = mesh->normal_f; mesh->normal_f = NULL; mesh->computeFaceNormal(); float (*normal_o)[3] = mesh->normal_f; int (*link)[3] = mesh->face_link_E; double (*tmp_normal)[3] = new double[face_N][3]; double *area = new double[face_N]; double *geo = new double[face_N]; float (*dist)[3] = new float[face_N][3]; mesh->computeCenter(); float (*center)[3] = mesh->center; int (*face)[3] = mesh->face; float (*vertex)[3] = mesh->vertex; int *visit = new int[face_N]; bool *decide = new bool[face_N]; if(sigma != NULL) delete[] sigma; sigma = new float[face_N]; //float c = 0.001; //float c = 0.00005; //float total_e = 0; //int n = 0; for(int i=0; ifaceArea(i); for(int j=0; j<3; j++){ int ad = link[i][j]; if(ad < 0) continue; if(ad < i){ int k; if(link[ad][0] == i) k = 0; else if(link[ad][1] == i) k = 1; else k = 2; dist[i][j] = dist[ad][k]; } else{ float *p1 = vertex[face[i][j]]; float *p2 = vertex[face[i][(j+1)%3]]; float p[3]; p[0] = 0.5f*(p1[0] + p2[0]); p[1] = 0.5f*(p1[1] + p2[1]); p[2] = 0.5f*(p1[2] + p2[2]); //float d1 = (float)MeshData::DIST(center[i], center[ad]); float d = (float)(MeshData::DIST(center[i], p) + MeshData::DIST(p, center[ad])); dist[i][j] = d; //n++; //total_e += dist[i][j]; } } visit[i] = -1; decide[i] = false; } int N = (int)((s_max-s_min)/step) + 1; double (*ns)[3] = new double[N][3]; double (*ns_o)[3] = new double[N][3]; float *si = new float[N]; double *total_w = new double[N]; for(i=0; i 4*si[n]) continue; double w; if(geo[u] <= 2.0*si[n]) w = area[u]*exp(-geo[u]*geo[u]/(2*si[n]*si[n])); else w = area[u]*0.0625*pow(4.0 - geo[u]/si[n], 4.0)/(E*E); ns[n][0] += w*normal[u][0]; ns[n][1] += w*normal[u][1]; ns[n][2] += w*normal[u][2]; ns_o[n][0] += w*normal_o[u][0]; ns_o[n][1] += w*normal_o[u][1]; ns_o[n][2] += w*normal_o[u][2]; total_w[n] += w; } int *nei = link[u]; for(int j=0; j<3; j++){ int v = nei[j]; if(v < 0 || (visit[v] == i && decide[v])) continue; double M = geo[u] + dist[u][j]; if(M > 4*s_max) continue; if(visit[v] != i){ geo[v] = M; //insert; heap[++last_heap] = v; index[v] = last_heap; visit[v] = i; decide[v] = false; //upheap; upheap(geo, last_heap, last_heap, heap, index); } else if(M < geo[v]){ geo[v] = M; //change; if(index[v] != 1 && M < geo[heap[index[v]/2]]) //upheap; upheap(geo, last_heap, index[v], heap, index); else //downheap; downheap(geo, last_heap, index[v], heap, index); } } if(last_heap == 0) break; //delete; u = heap[1]; heap[1] = heap[last_heap--]; index[heap[1]] = 1; //down heap; downheap(geo, last_heap, 1, heap, index); if(last_heap == 0) break; } float *ni = normal[i]; double min = 100000000; int opt; for(n=0; n v){ opt = n; min = v; } } sigma[i] = (si[opt] - s_min)/(s_max - s_min); double len = MeshData::LENGTH(ns_o[opt]); tmp_normal[i][0] = ns_o[opt][0]/len; tmp_normal[i][1] = ns_o[opt][1]/len; tmp_normal[i][2] = ns_o[opt][2]/len; } delete[] index; delete[] heap; delete[] dist; delete[] geo; delete[] visit; delete[] decide; delete[] area; delete[] ns; delete[] si; delete[] total_w; delete[] normal; delete[] ns_o; for(i=0; iface_N; int (*link)[3] = mesh->face_link_E; double (*tmp_normal)[3] = new double[face_N][3]; double *area = new double[face_N]; double *geo = new double[face_N]; float (*dist)[3] = new float[face_N][3]; mesh->computeCenter(); float (*center)[3] = mesh->center; int (*face)[3] = mesh->face; float (*vertex)[3] = mesh->vertex; int *visit = new int[face_N]; bool *decide = new bool[face_N]; if(sigma != NULL) delete[] sigma; sigma = new float[face_N]; //float c = 0.001; //float c = 0.00005; //float total_e = 0; //int n = 0; //for(int i=0; i<5; i++) //smoothNormal(0,0,0); float (*normal)[3] = mesh->normal_f; for(int i=0; ifaceArea(i); for(int j=0; j<3; j++){ int ad = link[i][j]; if(ad < 0) continue; if(ad < i){ int k; if(link[ad][0] == i) k = 0; else if(link[ad][1] == i) k = 1; else k = 2; dist[i][j] = dist[ad][k]; } else{ float *p1 = vertex[face[i][j]]; float *p2 = vertex[face[i][(j+1)%3]]; float p[3]; p[0] = 0.5f*(p1[0] + p2[0]); p[1] = 0.5f*(p1[1] + p2[1]); p[2] = 0.5f*(p1[2] + p2[2]); //float d1 = (float)MeshData::DIST(center[i], center[ad]); double PM = MeshData::DIST(center[i], p); double MQ = MeshData::DIST(p, center[ad]); //float d = (float)(MeshData::DIST(center[i], p) + MeshData::DIST(p, center[ad])); double dot = MeshData::DOT(normal[i], normal[ad]); dist[i][j] = (float)(PM + MQ + T*(PM*PM + MQ*MQ -2.0*dot*PM*MQ)/pow(PM+MQ, 3.0)); /* if(dot > 1.0) dot = 1; else if(dot < -1.0) dot = -1; double a = acos(dot); */ //dist[i][j] = (1.0f + (float)(T*a*a))*d; //dist[i][j] = d; //n++; //total_e += dist[i][j]; } } visit[i] = -1; decide[i] = false; } mesh->computeFaceNormal(); normal = mesh->normal_f; int N = (int)((s_max-s_min)/step) + 1; double (*ns)[3] = new double[N][3]; float *si = new float[N]; double *total_w = new double[N]; for(i=0; i 4*si[n]) continue; double w; if(geo[u] <= 2.0*si[n]) w = area[u]*exp(-geo[u]*geo[u]/(2*si[n]*si[n])); else w = area[u]*0.0625*pow(4.0 - geo[u]/si[n], 4.0)/(E*E); ns[n][0] += w*normal[u][0]; ns[n][1] += w*normal[u][1]; ns[n][2] += w*normal[u][2]; total_w[n] += w; } int *nei = link[u]; for(int j=0; j<3; j++){ int v = nei[j]; if(v < 0 || (visit[v] == i && decide[v])) continue; double M = geo[u] + dist[u][j]; if(M > 4*s_max) continue; if(visit[v] != i){ geo[v] = M; //insert; heap[++last_heap] = v; index[v] = last_heap; visit[v] = i; decide[v] = false; //upheap; upheap(geo, last_heap, last_heap, heap, index); } else if(M < geo[v]){ geo[v] = M; //change; if(index[v] != 1 && M < geo[heap[index[v]/2]]) //upheap; upheap(geo, last_heap, index[v], heap, index); else //downheap; downheap(geo, last_heap, index[v], heap, index); } } if(last_heap == 0) break; //delete; u = heap[1]; heap[1] = heap[last_heap--]; index[heap[1]] = 1; //down heap; downheap(geo, last_heap, 1, heap, index); if(last_heap == 0) break; } float *ni = normal[i]; double min = 100000000; int opt; for(n=0; n v){ opt = n; min = v; } } sigma[i] = (si[opt] - s_min)/(s_max - s_min); double len = MeshData::LENGTH(ns[opt]); tmp_normal[i][0] = ns[opt][0]/len; tmp_normal[i][1] = ns[opt][1]/len; tmp_normal[i][2] = ns[opt][2]/len; } delete[] index; delete[] heap; delete[] dist; delete[] geo; delete[] visit; delete[] decide; delete[] area; delete[] ns; delete[] si; delete[] total_w; for(i=0; i