//-- // // ComputeFaceNormals // //-- // Compute unit normal of every faces void Mesh::ComputeFaceNormals() { // Resize face normal array face_normals.resize( FaceNumber() ); // For every face for( int i=0; i<FaceNumber(); i++ ) { // Compute unit face normal FaceNormal(i) = ComputeFaceNormal(i); } }
CTriangle::CTriangle (CPoint3D pos, CColor col, CPoint3D pptVertices[3]) : CShape (pos, col) { m_pptVertices[0] = pptVertices[0]; m_pptVertices[1] = pptVertices[1]; m_pptVertices[2] = pptVertices[2]; m_eNormalMode = FACE_NORMAL; // VVIMP - do not forget this step! ComputeFaceNormal(); m_pShader = 0; }
void CTriangle::Init (CPoint3D pos, CColor col, CPoint3D pptVertices[3]) { objColor = col; m_ptPosition = pos; m_pptVertices[0] = pptVertices[0]; m_pptVertices[1] = pptVertices[1]; m_pptVertices[2] = pptVertices[2]; m_eNormalMode = FACE_NORMAL; // VVIMP - do not forget this step! ComputeFaceNormal(); m_pShader = 0; }
GLuint HalfEdgeModel::CreateTriangleDisplayList( unsigned int flags ) { bool normals = (flags & WITH_NORMALS) > 0; bool facetNorms = (flags & WITH_FACET_NORMALS) > 0; bool failure = false; float facetNorm[3]; Solid *sobj = (Solid *)solid; GLuint list = glGenLists( 1 ); glNewList( list, GL_COMPILE ); glBegin( GL_TRIANGLES ); Face *currFace = sobj->sfaces; for ( ; currFace; ) { Loop *loop = currFace->floop; if (!loop) { failure=true; break; } HalfEdge *he1 = loop->ledges; if (!he1) { failure=true; break; } HalfEdge *he2 = he1->next; if (!he2) { failure=true; break; } HalfEdge *he3 = he2->next; if (!he3) { failure=true; break; } if (facetNorms) { ComputeFaceNormal( facetNorm, (void *)(loop->lface) ); glNormal3fv( facetNorm ); } if (normals) glNormal3dv( he1->hvert->ncoord ); glVertex3dv( he1->hvert->vcoord ); if (normals) glNormal3dv( he2->hvert->ncoord ); glVertex3dv( he2->hvert->vcoord ); if (normals) glNormal3dv( he3->hvert->ncoord ); glVertex3dv( he3->hvert->vcoord ); currFace = currFace->next; if (!currFace || currFace == sobj->sfaces) break; } glEnd(); glEndList(); if (failure) { glDeleteLists( list, 1 ); return 0; } return (triList = list); }
GLuint HalfEdgeModel::CreateTriangleAdjacencyDisplayList( unsigned int flags ) { bool normals = (flags & WITH_NORMALS) > 0; bool facetNorms = (flags & WITH_FACET_NORMALS) > 0; bool failure = false; float centralFacetNorm[3], extFacetNorm[3]; Solid *sobj = (Solid *)solid; GLuint list = glGenLists( 1 ); glNewList( list, GL_COMPILE ); glBegin( GL_TRIANGLES_ADJACENCY_EXT ); Face *currFace = sobj->sfaces; for ( ; currFace; ) { Loop *loop = currFace->floop; if (!loop) { failure=true; break; } HalfEdge *he1 = loop->ledges; if (!he1) { failure=true; break; } HalfEdge *he2 = he1->next; if (!he2) { failure=true; break; } HalfEdge *he3 = he2->next; if (!he3) { failure=true; break; } /* vertex 1 */ if (facetNorms) { ComputeFaceNormal( centralFacetNorm, (void *)(loop->lface) ); glNormal3fv( centralFacetNorm ); } if (normals) glNormal3dv( he1->hvert->ncoord ); glVertex3dv( he1->hvert->vcoord ); /* vertex 2 */ HalfEdge *ext = (he1->hedge->he1 == he1) ? he1->hedge->he2 : he1->hedge->he1; if (ext) { ext = ext->prev; if (facetNorms) { ComputeFaceNormal( extFacetNorm, (void *)(ext->hloop->lface) ); glNormal3fv( extFacetNorm ); } if (normals) glNormal3dv( ext->hvert->ncoord ); glVertex3dv( ext->hvert->vcoord ); } else { if (normals || facetNorms) glNormal3d( 0, 0, 0 ); glVertex3d( 0, 0, 0 ); } /* vertex 3 */ if (facetNorms) glNormal3fv( centralFacetNorm ); if (normals) glNormal3dv( he2->hvert->ncoord ); glVertex3dv( he2->hvert->vcoord ); /* vertex 4 */ ext = (he3->hedge->he1 == he3) ? he3->hedge->he2 : he3->hedge->he1; if (ext) { ext = ext->prev; if (facetNorms) { ComputeFaceNormal( extFacetNorm, (void *)(ext->hloop->lface) ); glNormal3fv( extFacetNorm ); } if (normals) glNormal3dv( ext->hvert->ncoord ); glVertex3dv( ext->hvert->vcoord ); } else { if (normals || facetNorms) glNormal3d( 0, 0, 0 ); glVertex3d( 0, 0, 0 ); } /* vertex 5 */ if (facetNorms) glNormal3fv( centralFacetNorm ); if (normals) glNormal3dv( he3->hvert->ncoord ); glVertex3dv( he3->hvert->vcoord ); /* vertex 6 */ ext = (he2->hedge->he1 == he2) ? he2->hedge->he2 : he2->hedge->he1; if (ext) { ext = ext->prev; if (facetNorms) { ComputeFaceNormal( extFacetNorm, (void *)(ext->hloop->lface) ); glNormal3fv( extFacetNorm ); } if (normals) glNormal3dv( ext->hvert->ncoord ); glVertex3dv( ext->hvert->vcoord ); } else { if (normals || facetNorms) glNormal3d( 0, 0, 0 ); glVertex3d( 0, 0, 0 ); } currFace = currFace->next; if (!currFace || currFace == sobj->sfaces) break; } glEnd(); glEndList(); if (failure) { glDeleteLists( list, 1 ); return 0; } return (adjList = list); }
GLuint HalfEdgeModel::CreateEdgeDisplayList( unsigned int flags ) { bool normals = (flags & WITH_NORMALS) > 0; bool facetNorms = (flags & WITH_ADJACENT_FACE_NORMS) > 0; bool failure = false; float fnorm1[3], fnorm2[3]; Solid *sobj = (Solid *)solid; GLuint list = glGenLists( 1 ); glNewList( list, GL_COMPILE ); glBegin( GL_LINES ); Edge *currEdge = sobj->sedges; for ( ; currEdge; ) { if( !currEdge->he1 && !currEdge->he2) { currEdge = currEdge->next; if (!currEdge || currEdge == sobj->sedges) break; continue; } if (facetNorms) { if(!currEdge->he1) { fnorm1[0] = 0; fnorm1[1] = 0; fnorm1[2] = 0;} else ComputeFaceNormal( fnorm1, (void *)(currEdge->he1->hloop->lface) ); if(!currEdge->he2) { fnorm2[0] = 0; fnorm2[1] = 0; fnorm2[2] = 0; } else ComputeFaceNormal( fnorm2, (void *)(currEdge->he2->hloop->lface) ); glMultiTexCoord3fv( GL_TEXTURE6, fnorm1 ); glMultiTexCoord3fv( GL_TEXTURE7, fnorm2 ); } if(!currEdge->he1 || !currEdge->he2) { HalfEdge *he = currEdge->he1 ? currEdge->he1 : currEdge->he2; //only one halfedge was valid. if (normals) glNormal3dv( he->hvert->ncoord ); glVertex3dv( he->hvert->vcoord ); // the other halfedge is next in the loop he = he->next; if(!he) { printf("Error: Corrupted half-edge loop!\n"); failure=true; break; } else { if(normals) glNormal3dv(he->hvert->ncoord); glVertex3dv(he->hvert->vcoord); } } else { if (normals) glNormal3dv( currEdge->he1->hvert->ncoord ); glVertex3dv( currEdge->he1->hvert->vcoord ); if (normals) glNormal3dv( currEdge->he2->hvert->ncoord ); glVertex3dv( currEdge->he2->hvert->vcoord ); } currEdge = currEdge->next; if (!currEdge || currEdge == sobj->sedges) break; } glEnd(); glEndList(); if (failure) { glDeleteLists( list, 1 ); return 0; } return (edgeList = list); }
GLuint HalfEdgeModel::CreateEdgeVBO( unsigned int flags ) { bool normals = (flags & WITH_NORMALS) > 0; bool facetNorms = (flags & WITH_ADJACENT_FACE_NORMS) > 0; bool failure = false; float fnorm1[3], fnorm2[3]; int edgeCount=0; Solid *sobj = (Solid *)solid; int numComponents = 1 + (normals?1:0) + (facetNorms?2:0); // Do this in two passes. The first checks for validity and counts the number // of edges. Here's pass 1. for ( Edge *currEdge = sobj->sedges; currEdge; ) { if( !currEdge->he1 && !currEdge->he2) { currEdge = currEdge->next; if (!currEdge || currEdge == sobj->sedges) break; continue; } if(!currEdge->he1 || !currEdge->he2) { HalfEdge *he = currEdge->he1 ? currEdge->he1 : currEdge->he2; if(!he->next) { failure=true; break; } } edgeCount++; currEdge = currEdge->next; if (!currEdge || currEdge == sobj->sedges) break; } if (failure) { printf("Unable to create edge VBO. Corrupted half-edge loop!\n"); return 0; } // Allocate enough memory for all the edges unsigned int dataSize = edgeCount*6*sizeof(float)*numComponents; float *floatData = (float *)malloc( dataSize ); int currentEdge = 0; if (!floatData) { printf("Unable to allocate temporary memory for edge VBO!\n"); return 0; } // Copy data into allocated memory for (Edge *currEdge = sobj->sedges; currEdge; ) { int vertOff0 = 6*numComponents*currentEdge; int vertOff1 = vertOff0+3*numComponents; int normOff0 = vertOff0+3; int normOff1 = normOff0+3*numComponents; int fnormOff0_1 = vertOff0+3+(normals?3:0); int fnormOff1_1 = fnormOff0_1+3*numComponents; int fnormOff0_2 = fnormOff0_1+3; int fnormOff1_2 = fnormOff1_1+3; if( !currEdge->he1 && !currEdge->he2) { currEdge = currEdge->next; if (!currEdge || currEdge == sobj->sedges) break; continue; } if (facetNorms) { if(!currEdge->he1) { fnorm1[0] = 0; fnorm1[1] = 0; fnorm1[2] = 0;} else ComputeFaceNormal( fnorm1, (void *)(currEdge->he1->hloop->lface) ); if(!currEdge->he2) { fnorm2[0] = 0; fnorm2[1] = 0; fnorm2[2] = 0; } else ComputeFaceNormal( fnorm2, (void *)(currEdge->he2->hloop->lface) ); floatData[fnormOff0_1+0] = fnorm1[0]; floatData[fnormOff0_1+1] = fnorm1[1]; floatData[fnormOff0_1+2] = fnorm1[2]; floatData[fnormOff1_1+0] = fnorm1[0]; floatData[fnormOff1_1+1] = fnorm1[1]; floatData[fnormOff1_1+2] = fnorm1[2]; floatData[fnormOff0_2+0] = fnorm2[0]; floatData[fnormOff0_2+1] = fnorm2[1]; floatData[fnormOff0_2+2] = fnorm2[2]; floatData[fnormOff1_2+0] = fnorm2[0]; floatData[fnormOff1_2+1] = fnorm2[1]; floatData[fnormOff1_2+2] = fnorm2[2]; } if(!currEdge->he1 || !currEdge->he2) { HalfEdge *he = currEdge->he1 ? currEdge->he1 : currEdge->he2; //only one halfedge was valid. if (normals) { floatData[normOff0+0] = he->hvert->ncoord[0]; floatData[normOff0+1] = he->hvert->ncoord[1]; floatData[normOff0+2] = he->hvert->ncoord[2]; } floatData[vertOff0+0] = he->hvert->vcoord[0]; floatData[vertOff0+1] = he->hvert->vcoord[1]; floatData[vertOff0+2] = he->hvert->vcoord[2]; // the other halfedge is next in the loop he = he->next; if (normals) { floatData[normOff1+0] = he->hvert->ncoord[0]; floatData[normOff1+1] = he->hvert->ncoord[1]; floatData[normOff1+2] = he->hvert->ncoord[2]; } floatData[vertOff1+0] = he->hvert->vcoord[0]; floatData[vertOff1+1] = he->hvert->vcoord[1]; floatData[vertOff1+2] = he->hvert->vcoord[2]; } else { HalfEdge *he = currEdge->he1; if (normals) { floatData[normOff0+0] = he->hvert->ncoord[0]; floatData[normOff0+1] = he->hvert->ncoord[1]; floatData[normOff0+2] = he->hvert->ncoord[2]; } floatData[vertOff0+0] = he->hvert->vcoord[0]; floatData[vertOff0+1] = he->hvert->vcoord[1]; floatData[vertOff0+2] = he->hvert->vcoord[2]; he = currEdge->he2; if (normals) { floatData[normOff1+0] = he->hvert->ncoord[0]; floatData[normOff1+1] = he->hvert->ncoord[1]; floatData[normOff1+2] = he->hvert->ncoord[2]; } floatData[vertOff1+0] = he->hvert->vcoord[0]; floatData[vertOff1+1] = he->hvert->vcoord[1]; floatData[vertOff1+2] = he->hvert->vcoord[2]; } currentEdge++; currEdge = currEdge->next; if (!currEdge || currEdge == sobj->sedges) break; } vboEdgeCount = currentEdge; vboEdgeComponents = numComponents; if (edgeVBO > 0) glDeleteBuffers( 1, &edgeVBO ); glGenBuffers( 1, &edgeVBO ); glBindBuffer( GL_ARRAY_BUFFER, edgeVBO ); glBufferData( GL_ARRAY_BUFFER, dataSize, floatData, GL_STATIC_DRAW ); glBindBuffer( GL_ARRAY_BUFFER, 0 ); free( floatData ); return edgeVBO; }
//-- // // PredictVertex // //-- bool MultiresolutionMesh::PredictVertex(int v, VertexType vt) { double coef; double weight(0); ConstNeighborIterator itv1, itv2; // Initialise detail validity levels[current_level_number].vertex_types[v] = UNDEFINED_VERTEX; //-- Test -- // tmp_mem = 0; //-- // Check border vertex if( IsBorderVertex(v) ) return false; // For every neighbor vertices itv1 = NeighborVertices(v).begin(); while( itv1 != NeighborVertices(v).end() ) { // Check for topological noise // if( NeighborVertexNumber(*itv1) < 4 ) return false; coef = 0; itv2 = NeighborVertices(*itv1).begin(); while( itv2 != NeighborVertices(*itv1).end() ) { if( FindNeighborVertex(v, *itv2) ) { if( IsColinear( Vertex(*itv2), Vertex(v), Vertex(*itv1) ) ) return false; coef += Cotan( Vertex(*itv2), Vertex(v), Vertex(*itv1) ); } ++itv2; } // Laplacian relaxation // coef = 1.0 / (double)NeighborVertexNumber(v); // Save the current coeff levels[current_level_number].subdivision_weights[v].push_back( SubdivisionWeight(*itv1,coef) ); //-- Test -- //tmp_mem++; // // Add current coef to normalization coef weight += coef; ++itv1; } // Sanity check if( weight == 0 ) { return false; } // Normalize weights weight = 1.0 / weight; SubdivisionWeightList::iterator itw = levels[current_level_number].subdivision_weights[v].begin(); while( itw != levels[current_level_number].subdivision_weights[v].end() ) { itw->weight *= weight; ++itw; } // Compute predicted vertex position Vector3d relax(0,0,0); itw = levels[current_level_number].subdivision_weights[v].begin(); while( itw != levels[current_level_number].subdivision_weights[v].end() ) { relax += itw->weight * Vertex(itw->vertex); ++itw; } // Compute detail (vertex - subdivided_vertex) levels[current_level_number].geometric_details[v] = Vertex(v) - relax; //-- Test -- //tmp_mem++; // // Sanety check (degenerated detail) // if( levels[current_level_number].geometric_details[v].Length() > detail_length_tolerance ) return false; // Validate detail levels[current_level_number].vertex_types[v] = vt; // Create predicted mesh fo geometrical attribute details std::swap( Vertex(v), relax ); // Normal vector detail Vector3d relax_normal(0,0,0); itv1 = NeighborFaces(v).begin(); while( itv1 != NeighborFaces(v).end() ) { relax_normal += ComputeFaceNormal( *itv1 ); ++itv1; } relax_normal.Normalize(); // levels[current_level_number].normal_details[v] = VertexNormal(v) - relax_normal; levels[current_level_number].normal_details[v] = Vector3d(acos(VertexNormal(v) | relax_normal), 0, 0); // Gaussian curvature // relax_curvature = GaussianCurvature(this, v); // levels[current_level_number].gaussian_curvature_details[v] = gaussian_curvature[v] - relax_curvature; // Go back to the initial mesh std::swap( Vertex(v), relax ); // Color detail if( use_color ) { relax = 0.0; itw = levels[current_level_number].subdivision_weights[v].begin(); while( itw != levels[current_level_number].subdivision_weights[v].end() ) { relax += itw->weight * Color(itw->vertex); ++itw; } relax.Clamp(0,1); #ifdef _HSI_COLOR_ levels[current_level_number].color_details[v][0] = HsiDifference(Rgb2Hsi(Color(v)), Rgb2Hsi(relax)); levels[current_level_number].color_details[v][1] = 0; levels[current_level_number].color_details[v][2] = 0; #else levels[current_level_number].color_details[v] = Color(v) - relax; #endif } // Texture detail if( use_texture ) { // Vector2d relax_texture_coord(0,0); relax = 0.0; itw = levels[current_level_number].subdivision_weights[v].begin(); while( itw != levels[current_level_number].subdivision_weights[v].end() ) { // relax_texture_coord += itw->weight * Texture(itw->vertex); relax += itw->weight * Pixel(itw->vertex); ++itw; } levels[current_level_number].texture_details[v] = Pixel(v) - relax; // levels[current_level_number].texture_details[v] = Pixel(v) - Pixel(relax_texture_coord); // levels[current_level_number].texture_details[v][0] = Texture(v)[0] - relax_texture_coord[0]; // levels[current_level_number].texture_details[v][1] = Texture(v)[1] - relax_texture_coord[1]; // levels[current_level_number].texture_details[v][2] = 0; } return true; }