static void genPlaneResult(unsigned int width, unsigned int height, ci::TriMesh& mesh)
{
    mesh.clear();

    float demiW = static_cast<float>(width / 2);
    float demiH = static_cast<float>(height / 2);

    for (float j = -demiH; j < demiH; ++j)
    {
        for (float i = -demiW; i < demiW; ++i)
        {
            mesh.appendVertex(ci::Vec3f(i, j, 0.0f));
            
            mesh.appendTexCoord(ci::Vec2f(
                (i + demiW) / width,
                (j + demiH) / height
                ));
        }
    }

    //For create face algorithme
    size_t w = width - 1;
    size_t h = height - 1;

    for (size_t j = 0; j < h; ++j)
    {
        for (size_t i = 0; i < w; ++i)
        {
            mesh.appendTriangle(width * j + i, width * (j + 1) + i, width * j + i + 1);
            mesh.appendTriangle(width * j + i + 1, width * (j + 1) + i, width * (j + 1) + i + 1);
        }
    }
}
void ZoaDebugFunctions::trimeshDrawNormals( ci::TriMesh &mesh )
{
	std::vector<ci::Vec3f> meshVertices = mesh.getVertices();
	std::vector<ci::Vec3f> meshNormals = mesh.getNormals();
	for( size_t i = 3; i < meshNormals.size(); i+=4 )
	{
		float t = 0.5f; // Because T is 0.5 it's not really necessary but the we could project along the plane this way
		ci::Vec3f midPoint = ci::Vec3f( (1.0f - t) * ( meshVertices[i-2] ) + t * ( meshVertices[i] ) );
		ci::Vec3f normal = meshNormals[i]*10;
		ci::gl::drawVector( midPoint, midPoint+normal, 10, 2.5);
	}
}
void DelaunayMeshMaker::fileDrop( FileDropEvent event ){
	try {
		mSurface = loadImage( event.getFile( 0 ) );

		int width = mSurface.getWidth();
		int height = mSurface.getHeight();
		app::setWindowSize( width, height );

		mFbo = gl::Fbo( width, height, false );

		mBorderPoints.clear();
		mBorderPoints.push_back( Vec2f::zero() );
		mBorderPoints.push_back( Vec2f( (float)width, 0 ) );
		mBorderPoints.push_back( Vec2f( (float)width ,(float)height ) );
		mBorderPoints.push_back( Vec2f( 0 ,(float)height ) );

		mSteinerPoints.clear();
		mMesh.clear();

		tesselate();
	}
	catch( ... ) {
		console() << "unable to load the texture file!" << std::endl;
	};
	
}
void DelaunayMeshMaker::setup()
{
	mSurface = loadImage( app::loadAsset( "texture0.jpg" ) );
	
	int width = mSurface.getWidth();
	int height = mSurface.getHeight();
	app::setWindowSize( width, height );

	mFbo = gl::Fbo( width, height, false );

	mBorderPoints.push_back( Vec2f::zero() );
	mBorderPoints.push_back( Vec2f( (float)width, 0 ) );
	mBorderPoints.push_back( Vec2f( (float)width ,(float)height ) );
	mBorderPoints.push_back( Vec2f( 0 ,(float)height ) );

	mMesh.clear();

	mParams = params::InterfaceGl( "Parameters", Vec2i( 300, 250 ) );
	mParams.addParam( "Alpha", &mAlpha, "max=1.0 min=0.0 step=0.005" );
	mParams.addParam( "Blend", &mBlend );
	mParams.addParam( "Phong Shading", &mApplyPhongShading );
	mParams.addParam( "Depth Offset", &mDepthOffset, "step=0.1" );
	mParams.addParam( "Draw wireframe", &mDrawWireframe );
	
	mParams.addSeparator();
	mParams.addText("Edge detection");
	mParams.addParam( "Edge detection scale down", &mScaleDown, "min=1" );
	mParams.addParam( "Minimum threshold", &mCannyMinThreshold, "min=0.0f" );
	mParams.addParam( "Maximum threshold", &mCannyMaxThreshold, "min=0.0f" );

	mParams.addSeparator();
	mParams.addButton( "Tesselate", std::bind( &DelaunayMeshMaker::tesselate, this ) );

	mScaleDown			= 8;
	mScaleDownPrev		= mScaleDown;
	mCannyMinThreshold	= 60.0;
	mCannyMaxThreshold	= 70.0;
	mAlpha				= 0.0f;
	mBlend				= false;
	mApplyPhongShading	= false;
	mDrawWireframe		= false;
	mDepthOffset		= 0.0f;
	mPrevDepthOffset	= mDepthOffset;
	mPrevBlend			= mBlend;

	mPhongShader = gl::GlslProg( loadAsset("phong_vert.glsl"), loadAsset("phong_frag.glsl") );

	mEdgeDetectSurface = edgeDetect( Surface8u( mSurface ), mCannyMinThreshold, mCannyMaxThreshold, mScaleDownPrev );

	mTesselator = Tesselator::makeTesselator();
	mTesselator->sDone.connect( boost::bind( &DelaunayMeshMaker::onTesselationDone, this ) );
}
void DelaunayMeshMaker::update(){
	mTesselator->update();

	if( mNeedsProcessing && mTesselator->isRunning() ){
		mTesselator->interrupt();
	}else if( mNeedsProcessing && !mTesselator->isRunning() ){
		mNeedsProcessing = false;
		mTesselator->process( mBorderPoints, mSteinerPoints, mBlend, mSurface, mDepthOffset );
	}

	if( mBlend != mPrevBlend ){
		mPrevBlend = mBlend;
	}
	
	if( mDepthOffset != mPrevDepthOffset ){
		std::vector<Vec3f> verts = mMesh.getVertices();
		std::vector<Vec3f> newVerts;

		int count = 0;
		for( auto itr = verts.begin(); itr != verts.end(); ++itr ){
			float z = (*itr).z;

			newVerts.push_back( Vec3f( (*itr).x, (*itr).y, mDepthRandom[count] * mDepthOffset ) );
			count++;
		}

		mMesh.getVertices().swap( newVerts );
		mMesh.recalculateNormals();

		mVboMesh = gl::VboMesh( mMesh );
		mPrevDepthOffset = mDepthOffset;
	}

	if( mScaleDown != mScaleDownPrev ){
		mScaleDownPrev = mScaleDown;
		mEdgeDetectSurface = edgeDetect( Surface8u( mSurface ), mCannyMinThreshold, mCannyMaxThreshold, mScaleDownPrev );
	}
}
void ZoaDebugFunctions::calculateTriMeshNormals( ci::TriMesh &mesh )
{
	const std::vector<ci::Vec3f>& vertices = mesh.getVertices();
	const std::vector<uint32_t>& indices = mesh.getIndices();

	// remove all current normals
	std::vector<ci::Vec3f>& normals = mesh.getNormals();
	normals.reserve( mesh.getNumVertices() );
	normals.clear();

	// set the normal for each vertex to (0, 0, 0)
	for(size_t i=0; i < mesh.getNumVertices(); ++i)
		normals.push_back( ci::Vec3f::zero() );

	// Average out the normal for each vertex at an index
	for(size_t i=0; i< mesh.getNumTriangles(); ++i)
	{
		ci::Vec3f v0 = vertices[ indices[i * 3] ];
		ci::Vec3f v1 = vertices[ indices[i * 3 + 1] ];
		ci::Vec3f v2 = vertices[ indices[i * 3 + 2] ];

		// calculate normal and normalize it, so each of the normals equally contributes to the final result
		ci::Vec3f e0 = v2 - v0;
		ci::Vec3f e1 = v2 - v1;
		ci::Vec3f n = e0.cross(e1).normalized();

		// add the normal to the final result, so we get an average of the normals of each triangle
		normals[ indices[i * 3] ] += n;
		normals[ indices[i * 3 + 1] ] += n;
		normals[ indices[i * 3 + 2] ] += n;
	}

	// the normals are probably not normalized by now, so make sure their lengths will be 1.0 as expected
	for(size_t i=0;i< normals.size();++i) {
		normals[i].normalize();
	}
}
void ZoaDebugFunctions::addQuadToMesh( ci::TriMesh& mesh, const ci::Vec3f& P0, const ci::Vec3f& P1, const ci::Vec3f& P2, const ci::Vec3f& P3, const ci::ColorA& color )
{
	ci::Vec3f e0 = P2 - P0;
	ci::Vec3f e1 = P2 - P1;
	ci::Vec3f n = e0.cross(e1).normalized();

	mesh.appendVertex( P0 );
	mesh.appendColorRGBA( color );
	mesh.appendNormal( n );

	mesh.appendVertex( P1 );
	mesh.appendColorRGBA( color );
	mesh.appendNormal( n );

	mesh.appendVertex( P2 );
	mesh.appendColorRGBA( color );
	mesh.appendNormal( n );

	mesh.appendVertex( P3 );
	mesh.appendColorRGBA( color );
	mesh.appendNormal( n );

	int vert0 = mesh.getNumVertices() - 4;
	int vert1 = mesh.getNumVertices() - 1;
	int vert2 = mesh.getNumVertices() - 2;
	int vert3 = mesh.getNumVertices() - 3;

	mesh.appendTriangle( vert0, vert3, vert1 );
	mesh.appendTriangle( vert3, vert2, vert1 );
}
void DelaunayMeshMaker::draw()
{
	gl::clear();

	gl::pushMatrices();

	gl::pushModelView();
		gl::color( ColorA::white() );

		if( mMesh.getNumTriangles() > 0 ){
			if( mApplyPhongShading )
				mPhongShader.bind();

			gl::enableDepthRead();
			gl::enableDepthWrite();

			gl::disableAlphaBlending();

			if( mDrawWireframe )
				gl::enableWireframe();

			gl::draw( mVboMesh );

			if( mDrawWireframe )
				gl::disableWireframe();

			if( mApplyPhongShading )
				mPhongShader.unbind();
		}

		if( mAlpha > 0.0f ){
			gl::disableDepthRead();
			gl::disableDepthWrite();

			gl::enableAlphaBlending();

			gl::color( ColorA( 1,1,1, mAlpha ) );
			gl::draw( mSurface );
		}
	gl::popModelView();

	gl::popMatrices();

	if( mTesselator->isRunning() ){
		gl::disableDepthRead();
		gl::disableDepthWrite();

		gl::enableAlphaBlending();

		gl::color( ColorA(0.0f, 0.0f, 0.0f, 0.5f ) );
		gl::drawSolidRect( Rectf( 0, 0, app::getWindowWidth(), app::getWindowHeight() ) );

		gl::pushModelView();
			gl::translate( app::getWindowSize()/2 );
			double time = getElapsedSeconds();
			double fraction = time - (int) time;
			int numFractions = 12;

			for(int i=0;i<numFractions;++i) {
				float a = (float) (fraction + i * (1.0f / (float)numFractions));
				a -= (int) a;

				gl::pushModelView();
				gl::rotate( i * ( -360.0f/(float)numFractions ) );
				gl::color( ColorA(1,1,1,1-a) );
				gl::drawSolidRect( Rectf(-6.0f, -44.0f, +6.0f, -31.0f) );
				gl::popModelView();
			}
		gl::popModelView();
	}

	mParams.draw();
}
TriMesh MeshHelper::subdivide( const ci::TriMesh &triMesh, uint32_t division, bool normalize )
{
	if ( division <= 1 || triMesh.getNumIndices() == 0 || triMesh.getNumVertices() == 0 ) {
		return triMesh;
	}

	vector<uint32_t> indices	= triMesh.getIndices();
	vector<Vec3f> normals		= triMesh.getNormals();
	vector<Vec3f> positions		= triMesh.getVertices();
	vector<Vec2f> texCoords		= triMesh.getTexCoords();

	vector<uint32_t> indicesBuffer( indices );
	indices.clear();
	indices.reserve( indicesBuffer.size() * 4 );
 
	uint32_t index0;
	uint32_t index1;
	uint32_t index2;
	uint32_t index3;
	uint32_t index4;
	uint32_t index5;
	for ( vector<uint32_t>::const_iterator iter = indicesBuffer.begin(); iter != indicesBuffer.end(); ) {
		index0 = *iter;
		++iter;
		index1 = *iter;
		++iter;
		index2 = *iter;
		++iter;

		if ( normalize ) {
			index3 = positions.size();
			positions.push_back( positions.at( index0 ).lerp( 0.5f, positions.at( index1 ) ).normalized() * 0.5f );
			index4 = positions.size();
			positions.push_back( positions.at( index1 ).lerp( 0.5f, positions.at( index2 ) ).normalized() * 0.5f );
			index5 = positions.size();
			positions.push_back( positions.at( index2 ).lerp( 0.5f, positions.at( index0 ) ).normalized() * 0.5f );
		} else {
			index3 = positions.size(); 
			positions.push_back( positions.at( index0 ).lerp( 0.5f, positions.at( index1 ) ) );
			index4 = positions.size();
			positions.push_back( positions.at( index1 ).lerp( 0.5f, positions.at( index2 ) ) );
			index5 = positions.size();
			positions.push_back( positions.at( index2 ).lerp( 0.5f, positions.at( index0 ) ) );
		}
	
		if ( !normals.empty() ) {
			normals.push_back( normals.at( index0 ).lerp( 0.5f, normals.at( index1 ) ) );
			normals.push_back( normals.at( index1 ).lerp( 0.5f, normals.at( index2 ) ) );
			normals.push_back( normals.at( index2 ).lerp( 0.5f, normals.at( index0 ) ) );
		}

		if ( !texCoords.empty() ) {
			texCoords.push_back( texCoords.at( index0 ).lerp( 0.5f, texCoords.at( index1 ) ) );
			texCoords.push_back( texCoords.at( index1 ).lerp( 0.5f, texCoords.at( index2 ) ) );
			texCoords.push_back( texCoords.at( index2 ).lerp( 0.5f, texCoords.at( index0 ) ) );
		}

		indices.push_back( index0 ); 
		indices.push_back( index3 ); 
		indices.push_back( index5 );
		
		indices.push_back( index3 ); 
		indices.push_back( index1 );
		indices.push_back( index4 );
		
		indices.push_back( index5 ); 
		indices.push_back( index4 ); 
		indices.push_back( index2 );
		
		indices.push_back( index3 ); 
		indices.push_back( index4 ); 
		indices.push_back( index5 );
	}

	ci::TriMesh mesh = create( indices, positions, normals, texCoords );
	
	indices.clear();
	normals.clear();
	positions.clear();
	texCoords.clear();

	return subdivide( mesh, division - 1, normalize );
}
Exemple #10
0
void World::generateMesh(ci::TriMesh & mesh)
{
   using namespace ci;
   
   Vec3f offset = Vec3f(m_size * -0.5f, m_size * -0.5f, m_size * -0.5f);
   
   for (size_t z = 0; z < m_size; ++z)
      for (size_t y = 0; y < m_size; ++y)
         for (size_t x = 0; x < m_size; ++x)
         {
            if (cell(x, y, z) == AIR)
            {
               for (size_t i = 0; i < 6; ++i)
               {
                  int index = getNeigbour(x, y, z, i);
                  
                  if (index != -1)
                  {
                     if (cell(index) == DIRT)
                     {
                        Vec3f normal = getNeigbourOffset(i);
                        Vec3f up = std::abs(normal.dot(Vec3f::yAxis())) > 0.9f ? Vec3f::zAxis() : Vec3f::yAxis();                   
                        Vec3f side = normal.cross(up) * 0.5f;
                        up = up * 0.5f;
                        
                        Vec3f pos = offset + Vec3f(x, y, z) + (normal * 0.5f);
                        
                        size_t indexStart = mesh.getNumVertices();
                        
                        
                        // Layout of the quad
                        //
                        // 0 --------------- 3
                        // |        ^ up     |
                        // |        |        |
                        // |  side  |        |
                        // |  <-----o pos    |
                        // |                 |
                        // |                 |
                        // |                 |
                        // 1 --------------- 2
                        
                        // Create the vertex data
                        mesh.appendVertex(pos + side + up);
                        mesh.appendVertex(pos + side - up);
                        mesh.appendVertex(pos - side - up);
                        mesh.appendVertex(pos - side + up);
                        mesh.appendNormal(-normal);
                        mesh.appendNormal(-normal);
                        mesh.appendNormal(-normal);
                        mesh.appendNormal(-normal);
                        
                        // Create triangle data
                        mesh.appendTriangle(indexStart + 0, indexStart + 1, indexStart + 2);
                        mesh.appendTriangle(indexStart + 0, indexStart + 2, indexStart + 3);
                     }
                  }
               }
            }
         }
}