//================================================================================================================================= /// Computes the object overdraw for the triangle soup the ray tracing implementation /// /// \param pfVB A pointer to the vertex buffer. The pointer pVB must point to the vertex position. The vertex /// position must be a 3-component floating point value (X,Y,Z). /// \param pnIB The index buffer. Must be a triangle list. /// \param nVertices The number of vertices. This must be non-zero and less than TOOTLE_MAX_VERTICES. /// \param nFaces The number of indices. This must be non-zero and less than TOOTLE_MAX_FACES. /// \param pViewpoints The viewpoints to use to measure overdraw /// \param nViewpoints The number of viewpoints in the array /// \param bCullCCW Set to true to cull CCW faces, otherwise cull CW faces. /// \param fODAvg (Output) Average overdraw /// \param fODMax (Output) Maximum overdraw /// \return TOOTLE_OK, TOOTLE_OUT_OF_MEMORY //================================================================================================================================= TootleResult ODObjectOverdrawRaytrace(const float* pfVB, const unsigned int* pnIB, unsigned int nVertices, unsigned int nFaces, const float* pViewpoints, unsigned int nViewpoints, bool bCullCCW, float& fAvgOD, float& fMaxOD) { assert(pfVB); assert(pnIB); // compute face normals of the triangles float* pFaceNormals; try { pFaceNormals = new float [ 3 * nFaces ]; } catch (std::bad_alloc&) { return TOOTLE_OUT_OF_MEMORY; } ComputeFaceNormals(pfVB, pnIB, nFaces, pFaceNormals); TootleRaytracer tr; if (!tr.Init(pfVB, pnIB, pFaceNormals, nVertices, nFaces, NULL)) { delete[] pFaceNormals; return TOOTLE_OUT_OF_MEMORY; } // generate the per-cluster overdraw table if (!tr.MeasureOverdraw(pViewpoints, nViewpoints, TOOTLE_RAYTRACE_IMAGE_SIZE, bCullCCW, fAvgOD, fMaxOD)) { delete[] pFaceNormals; return TOOTLE_OUT_OF_MEMORY; } // clean up the mess tr.Cleanup(); delete[] pFaceNormals; return TOOTLE_OK; }
/*! @function FindLitFaces @abstract Determine which of the triangles face toward the light. */ static void FindLitFaces( const TQ3RationalPoint4D& inLightPos, const TQ3TriMeshData& inTMData, const TQ3Vector3D* inFaceNormals, TQ3Uns8* outFlags ) { const TQ3Uns32 kNumFaces = inTMData.numTriangles; // Compute face normals if we do not have them. E3FastArray<TQ3Vector3D> faceNormals; if (inFaceNormals == NULL) { ComputeFaceNormals( inTMData, faceNormals ); inFaceNormals = &faceNormals[0]; } TQ3Vector3D toLight; TQ3Uns32 faceNum; if (inLightPos.w == 0.0f) // directional { toLight.x = inLightPos.x; toLight.y = inLightPos.y; toLight.z = inLightPos.z; for (faceNum = 0; faceNum < kNumFaces; ++faceNum) { outFlags[ faceNum ] = Q3FastVector3D_Dot( &toLight, &inFaceNormals[ faceNum ] ) > 0.0f; } } else // point or spot { TQ3Point3D lightPos3 = { inLightPos.x, inLightPos.y, inLightPos.z }; for (faceNum = 0; faceNum < kNumFaces; ++faceNum) { Q3FastPoint3D_Subtract( &lightPos3, &inTMData.points[ inTMData.triangles[faceNum].pointIndices[0] ], &toLight ); outFlags[ faceNum ] = Q3FastVector3D_Dot( &toLight, &inFaceNormals[ faceNum ] ) > 0.0f; } } }
bool ON_Mesh::Morph( const ON_SpaceMorph& morph ) { if ( m_V.Count() > 0 ) { bool bHasFaceNormals = HasFaceNormals(); bool bHasVertexNormals = HasVertexNormals(); int i, count = m_V.Count(); if ( bHasVertexNormals ) { for ( i = 0; i < count; i++ ) { m_N[i] = m_V[i] + 0.0009765625f*m_N[i]; } morph.MorphPointList( 3, 0, count, 3, &m_N[0].x ); } morph.MorphPointList( 3, 0, count, 3, &m_V[0].x ); if ( bHasVertexNormals ) { for ( i = 0; i < count; i++ ) { m_N[i] -= m_V[i]; m_N[i].Unitize(); } } m_FN.SetCount(0); m_K.SetCount(0); if ( bHasFaceNormals ) { ComputeFaceNormals(); } m_Ctag.Default(); InvalidateVertexBoundingBox(); InvalidateVertexNormalBoundingBox(); InvalidateCurvatureStats(); } return true; }
//-- // // Analysis // //-- bool MultiresolutionMesh::Analysis(int) { // // HSI // #ifdef _HSI_COLOR_ std::vector<Vector3d> color_backup; if( ColorNumber() == VertexNumber() ) { color_backup = colors; Vector3d tmp_hsi; for( int i=0; i<ColorNumber(); i++ ) { Rgb2Hsi( Color(i), tmp_hsi ); Color(i) = tmp_hsi; } } #endif // // RGB 2 Grayscale // #ifdef _RGB_2_GRAYSCALE_ std::vector<Vector3d> color_backup; if( ColorNumber() == VertexNumber() ) { color_backup = colors; double tmp; for( int i=0; i<ColorNumber(); i++ ) { tmp = (Color(i)[0]+Color(i)[1]+Color(i)[2])/3.0; Color(i) = tmp; } } #endif // Initialize member variables current_level_number = -1; levels.clear(); mean_curvature.clear(); gaussian_curvature.clear(); texture.Reset(); vertex_map.clear(); edge_list.clear(); // Initialize normals ComputeFaceNormals(); ComputeVertexNormals(); // Initialize progressive decomposition BeginProgressiveDecomposition(); // Initialize curvatures // mean_curvature.resize( VertexNumber() ); // gaussian_curvature.resize( VertexNumber() ); // ComputeMeanCurvature(); // ComputeGaussianCurvature(); // Initialize texture if( (TextureNumber()!=0) && (TextureName().empty()==false) ) { use_texture = texture.ReadFile( TextureName() ); } else { use_texture = false; } if( ColorNumber() == VertexNumber() ) { use_color = true; } else { use_color = false; } use_normal = true; // permutation.assign(VertexNumber(), -1); // map.assign( VertexNumber(), -1); // Initialize vertex map // This table indicates on which vertex each vertex has collapsed to vertex_map.resize( VertexNumber() ); for( int i=0; i<VertexNumber(); i++ ) { vertex_map[i] = i; } // std::cout<<bounding_box.Center()<<std::endl; // for( int i=0; i<VertexNumber(); i++ ) { // if( // Vertex(i)[0]>-0.01 && // Vertex(i)[2]>-0.01 && // Vertex(i)[0]<0.01 && // Vertex(i)[2]<0.01 // ) // std::cout<<i<<" "<<Vertex(i)<<std::endl; // } ConstPairContractionIterator itp; ConstNeighborIterator itn; std::vector<bool> locked_vertices(VertexNumber(), false); // levels.resize( base_level ); current_level_number = 0; //-- Test -- //int vnum = VertexNumber(); //timer.Reset(); //timer.Start(); //test<<current_level_number<<'\t'<<vnum<<endl; //-- #ifdef _OUTPUT_LEVELS_ // Write the finest level statistics std::ofstream level_stats_file("levels.log"); level_stats_file<<current_level_number<<'\t'<<ValidVertexNumber()<<'\t'<<ValidFaceNumber()<<std::endl; // Write the finest level mesh (the initial mesh) char filename[255]; sprintf(filename,"level%02d.wrl",current_level_number); WriteFile(filename); #endif // // Create the levels of details // while( 1 ) { // Add a new level levels.push_back( ResolutionLevel() ); // // Select the odd vertices // Remove the odd vertices // Lock the neighbors // Odd vertices are a set of independent vertices selected to be removed // The remaining (even) vertices compose the next coarse level // while( !pair_contractions.empty() ) { #ifdef _TEST_PLAN_ // Lock one predefined vertex locked_vertices[1844] = true; // plan-20000 // locked_vertices[30670] = true; // plan-irregulier #endif // Get pair contraction with minimum cost PairContraction pair = MinimumPairContraction(); // Remove pair from contraction candidate list RemovePairContraction( pair.Candidate() ); // Do not perform bad contraction until the level of detail is very low if( pair.Cost()>=invalid_contraction_penalty && current_level_number<15 ) { locked_vertices[pair.Candidate()] = true; continue; } // Test to see if after the pair contraction, // one vertex has a valence of 3 // This case screws up the predict operator itn = NeighborVertices(pair.Candidate()).begin(); while( itn != NeighborVertices(pair.Candidate()).end() ) { if(current_level_number<15 && NeighborVertexNumber(*itn)==4 && FindNeighborVertex(pair.Target(), *itn) && !IsBorderVertex(*itn)) { locked_vertices[pair.Candidate()] = true; } ++itn; } if( locked_vertices[pair.Candidate()] ) continue; // Map the candidate to the target vertex_map[pair.Candidate()] = pair.Target(); // Lock the selected vertex and its neighbors // valid_vertices[pair.Candidate()] = false; // Collapse candidate Collapse( pair ); // Update normals UpdateNormals( pair ); // Update quadrics UpdateQuadrics(pair); // Update pair cost of surronding vertices if( pair.Target() >= 0 ) { // Compute neighbor vertex cost itn = NeighborVertices(pair.Target()).begin(); while( itn != NeighborVertices(pair.Target()).end() ) { if( locked_vertices[*itn] == false ) { RemovePairContraction(*itn); ComputeEdgeCostAtVertex(*itn); } ++itn; } } // Lock the neighborhood of the selected vertex itn = NeighborVertices(pair.Candidate()).begin(); while( itn != NeighborVertices(pair.Candidate()).end() ) { // If the vertex is not already locked if( locked_vertices[*itn] == false ) { // Remove its pair contraction estimation RemovePairContraction(*itn); // Lock it locked_vertices[*itn] = true; } // Next neighbor ++itn; } // Record pair contraction levels[current_level_number].pair_contractions.push_front( pair ); } // bool left = false; int left_vertex_number = 0; // Compute new edge collapse pairs for(int i=0; i<VertexNumber(); i++ ) { if( valid_vertices[i] == false ) continue; left_vertex_number++; locked_vertices[i] = false; ComputeEdgeCostAtVertex(i); } // Update the normals ComputeProgressiveFaceNormals(); ComputeProgressiveVertexNormals(); // Next level current_level_number++; #ifdef _OUTPUT_LEVELS_ // Write the current level statistics level_stats_file<<current_level_number<<'\t'<<ValidVertexNumber()<<'\t'<<ValidFaceNumber()<<std::endl; // Write the current level mesh sprintf(filename,"level%02d.wrl",current_level_number); WriteFile(filename); #endif // Is there any vertex left ? // if( left_vertex_number == 0 ) break; // if( left_vertex_number < 100 ) break; if( left_vertex_number < 10 ) break; } // End the progressive decomposition EndProgressiveDecomposition(); // Reset locked_vertices.clear(); // // Go back the initial fine level // Reconstruct all levels // while( current_level_number > 0 ) { // Next level current_level_number--; // Insert odd vertices itp = levels[current_level_number].pair_contractions.begin(); while( itp != levels[current_level_number].pair_contractions.end() ) { // Expand candidate of current pair contraction Expand( *itp ); // Next pair contraction ++itp; } } // Update the normals ComputeProgressiveFaceNormals(); ComputeProgressiveVertexNormals(); for( int i=0; i<(int)levels.size(); i++ ) { levels[i].Resize( VertexNumber() ); } // // Compute the details // while( current_level_number < LevelNumber() ) { // // Predict odd vertices // itp = levels[current_level_number].pair_contractions.begin(); while( itp != levels[current_level_number].pair_contractions.end() ) { // Compute wavelet coefficient PredictVertex( itp->Candidate(), ODD_VERTEX ); // Invalidate the odd vertex valid_vertices[itp->Candidate()] = false; #ifdef _TEST_PLAN_ // Null the details levels[current_level_number].geometric_details[itp->Candidate()] = 0; #endif // Next pair contraction ++itp; } // // Predict even vertices // for(int i=0; i<VertexNumber(); i++ ) { // Valid vertex ? if( valid_vertices[i] == false ) continue; // Predict even vertex PredictVertex( i, EVEN_VERTEX ); #ifdef _TEST_PLAN_ // Null the details levels[current_level_number].geometric_details[i] = 0; #endif } // // Simplify // Removed odd vertices to go to next coarse level // itp = levels[current_level_number].pair_contractions.begin(); while( itp != levels[current_level_number].pair_contractions.end() ) { // Collapse candidate Collapse( *itp ); // Next Pair contrction ++itp; } // Update the normals ComputeProgressiveFaceNormals(); ComputeProgressiveVertexNormals(); // Go to the next coarse level current_level_number++; } // Test plan #ifdef _TEST_PLAN_ Vertex(1844)[1] = -1.0; // plan-2000 // Vertex(30670)[1] = -1.0; // plan-irregulier char filename[255]; sprintf(filename,"plan-base.wrl"); WriteFile(filename); #endif //-- Test -- //timer.Stop(); //test<<VertexNumber()<<'\t'<<vnum<<'\t'<<((double)VertexNumber()/vnum - 1.0)*100.0<<'\t'<<timer.Total()<<'\t'<<memory<<endl; //-- // // HSI // /* #ifdef _HSI_COLOR_ if( ColorNumber() == VertexNumber() ) { colors = color_backup; } #endif */ return true; }