Пример #1
0
//=================================================================================================================================
/// 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;
}
Пример #2
0
/*!
	@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;
		}
	}
}
Пример #3
0
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;
}