// Subdivider.cpp: Subdivider クラスのインプリメンテーション // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "MeshEditor.h" #include "Subdivider.h" #include #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // 構築/消滅 ////////////////////////////////////////////////////////////////////// Subdivider::Subdivider() { vertex_index = NULL; } Subdivider::~Subdivider() { if(vertex_index != NULL) delete[] vertex_index; } void Subdivider::setMeshData(MeshData *mesh) { this->mesh = mesh; } void Subdivider::linear() { int (*face)[3] = mesh->face; float (*vertex)[3] = mesh->vertex; int face_N = mesh->face_N; int vertex_N = mesh->vertex_N; int (*link)[3] = mesh->face_link_E; BOOL* flag = new BOOL[face_N]; for(int i=0; i 0) flag[i] = true; //else //flag[i] = false; } this->subdivideTopology(flag); for(i=0; iupdateMesh(); } void Subdivider::LOOP() { int (*face)[3] = mesh->face; float (*vertex)[3] = mesh->vertex; int face_N = mesh->face_N; int vertex_N = mesh->vertex_N; int (*link_f)[3] = mesh->face_link_E; BOOL* isBound = mesh->isBound; BOOL* flag = new BOOL[face_N]; for(int i=0; isubdivideTopology(flag); for(i=0; igetConsistent1Ring(i, link, link_N); if(link_N == 0){ new_vertex[i][0] = vertex[i][0]; new_vertex[i][1] = vertex[i][1]; new_vertex[i][2] = vertex[i][2]; continue; } double b = (0.625 - (0.375 + 0.25*cos(2.0*PI/(double)link_N)) *(0.375 + 0.25*cos(2.0*PI/(double)link_N)))/(double)link_N; double sum[3]; sum[0] = sum[1] = sum[2] = 0; for(int j=0; jgetConsistent1Ring(i, link, link_N); int i1 = link[0]; int i2 = link[link_N-1]; new_vertex[i][0] = (float)(0.125*(vertex[i1][0] + vertex[i2][0] + 6.0*vertex[i][0])); new_vertex[i][1] = (float)(0.125*(vertex[i1][1] + vertex[i2][1] + 6.0*vertex[i][1])); new_vertex[i][2] = (float)(0.125*(vertex[i1][2] + vertex[i2][2] + 6.0*vertex[i][2])); } else{ new_vertex[i][0] = vertex[i][0]; new_vertex[i][1] = vertex[i][1]; new_vertex[i][2] = vertex[i][2]; } } for(i=0; i= 0 && i4 >= 0)){ new_vertex[index][0] = (float)(0.125*(3.0*(vertex[i1][0] + vertex[i2][0]) + vertex[i3][0] + vertex[i4][0])); new_vertex[index][1] = (float)(0.125*(3.0*(vertex[i1][1] + vertex[i2][1]) + vertex[i3][1] + vertex[i4][1])); new_vertex[index][2] = (float)(0.125*(3.0*(vertex[i1][2] + vertex[i2][2]) + vertex[i3][2] + vertex[i4][2])); } else{ new_vertex[index][0] = 0.5f*(vertex[i1][0] + vertex[i2][0]); new_vertex[index][1] = 0.5f*(vertex[i1][1] + vertex[i2][1]); new_vertex[index][2] = 0.5f*(vertex[i1][2] + vertex[i2][2]); } } } } delete[] flag; delete[] vertex_index; vertex_index = NULL; this->updateMesh(); } void Subdivider::subdivideTopology(BOOL *flag) { int face_N = mesh->face_N; int vertex_N = mesh->vertex_N; int (*link)[3] = mesh->face_link_E; float (*vertex)[3] = mesh->vertex; int (*face)[3] = mesh->face; BOOL grow = true; while(grow){ grow = false; for(int i=0; i 1){ flag[i] = true; grow = true; } } } if(vertex_index != NULL) delete[] vertex_index; vertex_index = new int[face_N][3]; for(int i=0; i= 0){ if(link[pair][0] == i) vertex_index[pair][0] = new_vertex_N; else if(link[pair][1] == i) vertex_index[pair][1] = new_vertex_N; else vertex_index[pair][2] = new_vertex_N; } new_vertex_N++; } } } new_vertex = new float[new_vertex_N][3]; new_face_N = face_N; for(i=0; ideleteLinkData(); mesh->vertex_N = new_vertex_N; mesh->vertex = new_vertex; mesh->face_N = new_face_N; mesh->face = new_face; mesh->generateVertexLink(); mesh->generateFaceLink(); mesh->computeFaceNormal(); mesh->computeNormal(); } void Subdivider::butterfly() { int (*face)[3] = mesh->face; float (*vertex)[3] = mesh->vertex; int face_N = mesh->face_N; int vertex_N = mesh->vertex_N; int (*link_f)[3] = mesh->face_link_E; BOOL* isBound = mesh->isBound; int* degree = mesh->degree_v; BOOL* flag = new BOOL[face_N]; for(int i=0; i 0) flag[i] = true; //else //flag[i] = false; } this->subdivideTopology(flag); for(i=0; igetConsistent1Ring(i1, link1, link1_N); mesh->getConsistent1Ring(i2, link2, link2_N); if(pair < 0 && isBound[i1] == BOUNDARY && isBound[i2] == BOUNDARY){ int i3 = link1[0]; if(i3 == i2) i3 = link1[link1_N-1]; int i4 = link2[0]; if(i4 == i1) i4 = link2[link2_N-1]; new_vertex[index][0] = (float)(0.0625*(9.0*(vertex[i1][0] + vertex[i2][0]) - (vertex[i3][0] + vertex[i4][0]))); new_vertex[index][1] = (float)(0.0625*(9.0*(vertex[i1][1] + vertex[i2][1]) - (vertex[i3][1] + vertex[i4][1]))); new_vertex[index][2] = (float)(0.0625*(9.0*(vertex[i1][2] + vertex[i2][2]) - (vertex[i3][2] + vertex[i4][2]))); continue; } int i3, i4; i3 = face[i][(j+2)%3]; if(link_f[pair][0] == i) i4 = face[pair][2]; else if(link_f[pair][1] == i) i4 = face[pair][0]; else i4 = face[pair][1]; if(isBound[i1] == INNER && isBound[i2] == INNER){ if(degree[i1] == 6 && degree[i2] == 6){ int index1, index2; for(int k=0; kupdateMesh(); } void Subdivider::normalAverage() { float (*vertex)[3] = mesh->vertex; int face_N = mesh->face_N; int (*face)[3] = new int[face_N][3]; int vertex_N = mesh->vertex_N; int (*link)[3] = new int[face_N][3]; double (*L)[3] = new double[vertex_N][3]; for(int i=0; ilaplacian(i, L[i]); for(i=0; iface_link_E[i][0]; link[i][1] = mesh->face_link_E[i][1]; link[i][2] = mesh->face_link_E[i][2]; face[i][0] = mesh->face[i][0]; face[i][1] = mesh->face[i][1]; face[i][2] = mesh->face[i][2]; } BOOL* flag = new BOOL[face_N]; for(i=0; i 0) flag[i] = true; //else //flag[i] = false; } this->subdivideTopology(flag); for(i=0; iupdateMesh(); mesh->computeFaceNormal(); float (*normal)[3] = mesh->normal_f; double (*new_normal)[3] = new double[new_face_N][3]; //face = mesh->face; vertex = mesh->vertex; int **link_f = mesh->vertex_link_f; int **link_v = mesh->vertex_link_v; int *degree_f = mesh->degree_f; int *degree_v = mesh->degree_v; for(i=0; ifaceCenter(c1, f1); mesh->faceCenter(c2, f2); /* m[0] = 0.5*(vertex[i][0] + vertex[k][0]); m[1] = 0.5*(vertex[i][1] + vertex[k][1]); m[2] = 0.5*(vertex[i][2] + vertex[k][2]); length[j] = MeshData::DIST(c1,m) + MeshData::DIST(m,c2); */ double v1[3], v2[3]; MeshData::VEC(v1, vertex[i], c1); MeshData::VEC(v2, vertex[i], c2); double dot = MeshData::DOT(v1, v2)/(MeshData::LENGTH(v1)*MeshData::LENGTH(v2)); length[j] = acos(dot); //length[j] = mesh->faceArea(f1) + mesh->faceArea(f2); total_length += length[j]; } for(j=0; j 1) dot = 1; else if(dot < -1) dot = -1; double angle = w*acos(dot)/(total_w+w); double R[3][3]; GENERATE_MAT(R, angle, ro); double tmp[3]; tmp[0] = nj[0]; tmp[1] = nj[1]; tmp[2] = nj[2]; MAT_VEC(nj, R, tmp); } total_w += w; } new_normal[l[j]][0] = nj[0]; new_normal[l[j]][1] = nj[1]; new_normal[l[j]][2] = nj[2]; /* double U[3][3]; double nj[3]; nj[0] = normal[l[j]][0]; nj[1] = normal[l[j]][1]; nj[2] = normal[l[j]][2]; double c[3]; mesh->faceCenter(c, l[j]); double m[3]; MeshData::VEC(m, vertex[i], c); ROTATION_MATRIX(U, nj, m); double test[3]; MAT_VEC(test, U, m); double theta = 0; double phi = 0; for(int k=0; kfaceArea(fi); n[0] += area*normal[fi][0]; n[1] += area*normal[fi][1]; n[2] += area*normal[fi][2]; A[0] += area*new_normal[fi][0] * new_normal[fi][0]; A[1] += area*new_normal[fi][0] * new_normal[fi][1]; A[2] += area*new_normal[fi][0] * new_normal[fi][2]; A[3] += area*new_normal[fi][1] * new_normal[fi][1]; A[4] += area*new_normal[fi][1] * new_normal[fi][2]; A[5] += area*new_normal[fi][2] * new_normal[fi][2]; double dot; if(k < 2) dot = MeshData::DOT(new_normal[fi], vertex[i1]); else dot = MeshData::DOT(new_normal[fi], vertex[i2]); d[0] += area*dot*new_normal[fi][0]; d[1] += area*dot*new_normal[fi][1]; d[2] += area*dot*new_normal[fi][2]; /* float c[3]; mesh->faceCenter(c, fi); p[0] += 0.25*c[0]; p[1] += 0.25*c[1]; p[2] += 0.25*c[2];*/ } //n[0] = L[i1][0] + L[i2][0]; //n[1] = L[i1][1] + L[i2][1]; //n[2] = L[i1][2] + L[i2][2]; //t = ((d-Ap).n)/((An).n) p[0] = vertex[index][0]; p[1] = vertex[index][1]; p[2] = vertex[index][2]; /* for(int m=0; mface_N; int vertex_N = mesh->vertex_N; int **link = mesh->vertex_link_f; float (*vertex)[3] = mesh->vertex; float (*center)[3] = mesh->center; int (*face)[3] = mesh->face; int* degree = mesh->degree_f; new_vertex_N = vertex_N + face_N; new_vertex = new float[new_vertex_N][3]; new_face_N = face_N; for(int i=0; iupdateMesh(); } void Subdivider::decideCenterForSqrt3() { mesh->computeCenter(); mesh->computeFaceNormal(); int face_N = mesh->face_N; int (*link)[3] = mesh->face_link_E; float (*vertex)[3] = mesh->vertex; float (*center)[3] = mesh->center; int (*face)[3] = mesh->face; float (*normal)[3] = mesh->normal_f; double (*tmp_normal)[3][3] = new double[face_N][3][3]; /* for(int i=0; i 1) dot = 1; else if(dot < -1) dot = -1; double angle = 1.0*acos(dot)/2.0; double R[3][3]; GENERATE_MAT(R, angle, ro); double tmp[3]; tmp[0] = n[0]; tmp[1] = n[1]; tmp[2] = n[2]; MAT_VEC(ni[j], R, tmp); } else{ ni[j][0] = n[0]; ni[j][1] = n[1]; ni[j][2] = n[2]; } } for(j=0; j<3; j++){ double ro[3]; double* n1 = ni[j]; double* n2 = ni[(j+2)%3]; MeshData::CROSS(ro, n1, n2); double len = MeshData::LENGTH(ro); if(len != 0){ ro[0] /= len; ro[1] /= len; ro[2] /= len; double dot = MeshData::DOT(n1, n2); if(dot > 1) dot = 1; else if(dot < -1) dot = -1; double angle = 0.0*acos(dot); double R[3][3]; GENERATE_MAT(R, angle, ro); MAT_VEC(tmp_normal[i][2*j], R, n1); angle = -angle; GENERATE_MAT(R, angle, ro); MAT_VEC(tmp_normal[i][2*j+1], R, n2); } else{ tmp_normal[i][2*j][0] = n1[0]; tmp_normal[i][2*j][1] = n1[1]; tmp_normal[i][2*j][2] = n1[2]; tmp_normal[i][2*j+1][0] = n2[0]; tmp_normal[i][2*j+1][1] = n2[1]; tmp_normal[i][2*j+1][2] = n2[2]; } } }*/ int **link_f = mesh->vertex_link_f; int **link_v = mesh->vertex_link_v; int vertex_N = mesh->vertex_N; int *degree = mesh->degree_f; for(int i=0; ifaceCenter(c1, f1); mesh->faceCenter(c2, f2); /* m[0] = 0.5*(vertex[i][0] + vertex[k][0]); m[1] = 0.5*(vertex[i][1] + vertex[k][1]); m[2] = 0.5*(vertex[i][2] + vertex[k][2]); length[j] = MeshData::DIST(c1,m) + MeshData::DIST(m,c2); */ double v1[3], v2[3]; MeshData::VEC(v1, vertex[i], c1); MeshData::VEC(v2, vertex[i], c2); double dot = MeshData::DOT(v1, v2)/(MeshData::LENGTH(v1)*MeshData::LENGTH(v2)); length[j] = acos(dot); //length[j] = mesh->faceArea(f1) + mesh->faceArea(f2); total_length += length[j]; } for(j=0; j 1) dot = 1; else if(dot < -1) dot = -1; double angle = w*acos(dot)/(total_w+w); double R[3][3]; GENERATE_MAT(R, angle, ro); double tmp[3]; tmp[0] = nj[0]; tmp[1] = nj[1]; tmp[2] = nj[2]; MAT_VEC(nj, R, tmp); } total_w += w; } int f = l[j]; int index; if(face[f][0] == i) index = 0; else if(face[f][1] == i) index = 1; else if(face[f][2] == i) index = 2; else int a = 0; tmp_normal[f][index][0] = nj[0]; tmp_normal[f][index][1] = nj[1]; tmp_normal[f][index][2] = nj[2]; } } float (*tmp_center)[3] = new float[face_N][3]; //for(int k=0; k<10; k++){ for(i=0;icomputeNormal(); for(i=0;inormal[i]; for(int j=0; jlaplacian(i, n); float *p = vertex[i]; double over = (d[0]-A[0]*p[0] - A[1]*p[1] - A[2]*p[2])*n[0] + (d[1]-A[1]*p[0] - A[3]*p[1] - A[4]*p[2])*n[1] + (d[2]-A[2]*p[0] - A[4]*p[1] - A[5]*p[2])*n[2] ; double under = (A[0]*n[0] + A[1]*n[1] + A[2]*n[2])*n[0] + (A[1]*n[0] + A[3]*n[1] + A[4]*n[2])*n[1] + (A[2]*n[0] + A[4]*n[1] + A[5]*n[2])*n[2] ; if(under == 0) continue; double t = over/under; vertex[i][0] += (float)(t*n[0]); vertex[i][1] += (float)(t*n[1]); vertex[i][2] += (float)(t*n[2]); //double B[6]; //if(INVERSE(B, A)){ //double v[3]; //MAT_BY_VEC(v, B, d); //vertex[i][0] = v[0]; //vertex[i][1] = v[1]; //vertex[i][2] = v[2]; //} }*/ delete[] tmp_normal; delete[] tmp_center; } void Subdivider::subdivideTopologyBary() { decideCenterForSqrt3(); int face_N = mesh->face_N; int vertex_N = mesh->vertex_N; int **link = mesh->vertex_link_f; float (*vertex)[3] = mesh->vertex; float (*center)[3] = mesh->center; int (*face)[3] = mesh->face; int* degree = mesh->degree_f; new_vertex_N = vertex_N + face_N; new_vertex = new float[new_vertex_N][3]; new_face_N = 3*face_N; new_face = new int[new_face_N][3]; int face_id = 0; for(int i=0; iupdateMesh(); }