void CpuClipmapRenderer::renderBlock( const GeometryClipmapLevel& level, const GeometryClipmapLevel* coarserLevel, const ClipmapRenderParameters& renderParameters, const Color3f& debugColor ) { TerrainLevelRenderData& renderData = levels_[ level.index ]; if( renderData.indices.size() <= 0 ) { return; } // enable the texture: // todo: enable the texture of the next coarser level too, so we can blend between both if( renderData.texture != NULL ) { //renderData.texture->activate( renderParameters.renderAction ); } Pnt2i transitionSize; //transitionSize[ 0 ] = std::min( ( levelSampleCount_ / 10 ) * level.sampleDistance[ 0 ], level.minTransitionSize[ 0 ] ); //transitionSize[ 1 ] = std::min( ( levelSampleCount_ / 10 ) * level.sampleDistance[ 1 ], level.minTransitionSize[ 1 ] ); const int levelSampleSpacing = level.sampleSpacing; transitionSize[ 0 ] = levelSampleSpacing * level.heightmap.size / 10; transitionSize[ 1 ] = levelSampleSpacing * level.heightmap.size / 10; // min and max are the first,last point inside the renderregion: Pnt2f activeRegionMin = Pnt2f( level.sampleOrigin ); Pnt2f activeRegionMax = Pnt2f( componentAdd( level.sampleOrigin, Pnt2i( level.getSampleCoverage(), level.getSampleCoverage() ) ) ); Pnt2f worldTransitionSize = Pnt2f( transitionSize ); //Point2f activeRegionCenter = samplePosToWorldPos( level.outerRenderBounds.getTopLeft() + level.outerRenderBounds.getSize() / 2 ); //Point2f localViewerPos( worldViewerPosition_[ 0 ], worldViewerPosition_.z ); //Pnt2i viewerSamplePos = worldPosToSamplePos( localViewerPos ); //Point2f baseLocalViewerPos = samplePosToWorldPos( viewerSamplePos ); //localViewerPos -= baseLocalViewerPos; #ifdef OLD_GEOCLIP //beginEditCP( terrainShader_ ); terrainShader_.setUniform( "transitionWidth", Vec2f( worldTransitionSize ) ); terrainShader_.setUniform( "activeRegionMin", Vec2f( activeRegionMin ) ); terrainShader_.setUniform( "activeRegionMax", Vec2f( activeRegionMax ) ); //terrainShader_->setUniform( "activeRegionCenter", activeRegionCenter ); terrainShader_.setUniform( "localViewerPos", Vec3f( viewerPosition_ ) ); terrainShader_.setUniform( "baseColor0", colorToVector( debugColor ) ); //endEditCP( terrainShader_ ); #else _pTerrainShader->addUniformVariable( "transitionWidth", Vec2f( worldTransitionSize ) ); _pTerrainShader->addUniformVariable( "activeRegionMin", Vec2f( activeRegionMin ) ); _pTerrainShader->addUniformVariable( "activeRegionMax", Vec2f( activeRegionMax ) ); //terrainShader_->setUniform( "activeRegionCenter", activeRegionCenter ); _pTerrainShader->addUniformVariable( "localViewerPos", Vec3f( viewerPosition_ ) ); #ifdef NOTUSED _pTerrainShader->setUniformParameter( "baseColor0", colorToVector( debugColor ) ); #endif #endif if( coarserLevel ) { #ifdef OLD_GEOCLIP terrainShader_.setUniform( "baseColor1", colorToVector( getDebugColor( coarserLevel->index ) ) ); #else #ifdef NOTUSED _pTerrainShader->setUniformParameter( "baseColor1", colorToVector( getDebugColor( coarserLevel->index ) ) ); #endif #endif } else { #ifdef OLD_GEOCLIP terrainShader_.setUniform( "baseColor1", colorToVector( debugColor ) ); #else #ifdef NOTUSED _pTerrainShader->setUniformParameter( "baseColor1", colorToVector( debugColor ) ); #endif #endif } //terrainShader_->updateParameters( drawAction->getWindow(), terrainShader_->getParameters() ); if( renderParameters.useVboExtension && useVertexBufferObjects_ ) { renderData.vertexBuffer.activate(); char* base = 0; glVertexPointer( 4, GL_FLOAT, sizeof( OpenGLTerrainVertex ), base ); glEnableClientState( GL_VERTEX_ARRAY ); glTexCoordPointer( 2, GL_FLOAT, sizeof( OpenGLTerrainVertex ), base + sizeof( Pnt4f ) ); glEnableClientState( GL_TEXTURE_COORD_ARRAY ); glDrawElements( GL_TRIANGLES, GLsizei(renderData.indices.size()), GL_UNSIGNED_SHORT, &renderData.indices[ 0 ] ); renderData.vertexBuffer.deactivate(); } else { glVertexPointer( 4, GL_FLOAT, sizeof( OpenGLTerrainVertex ), &renderData.vertices[ 0 ].pos ); glEnableClientState( GL_VERTEX_ARRAY ); glTexCoordPointer( 2, GL_FLOAT, sizeof( OpenGLTerrainVertex ), &renderData.vertices[ 0 ].uv ); glEnableClientState( GL_TEXTURE_COORD_ARRAY ); glDrawElements( GL_TRIANGLES, GLsizei(renderData.indices.size()), GL_UNSIGNED_SHORT, &renderData.indices[ 0 ] ); } glDisableClientState( GL_TEXTURE_COORD_ARRAY ); glDisableClientState( GL_NORMAL_ARRAY ); glDisableClientState( GL_VERTEX_ARRAY ); stats_.drawnBlockCount++; stats_.drawnTriangleCount += int(renderData.indices.size()) / 3; stats_.transformedVertexCount += int(renderData.vertices.size()); if( renderData.texture != NULL ) { //renderData.texture->deactivate( renderParameters.renderAction ); } }
void CpuClipmapRenderer::onRender( const ClipmapRenderParameters& renderParameters ) { // activate the gpu program: //glDisable( GL_LIGHTING ); #ifdef OLD_GEOCLIP terrainShader_.activate(); if( programTextChanged_ ) { reloadShader(); programTextChanged_ = false; } #else _pTerrainShader->activate(renderParameters.drawEnv); #endif // bool useDependentTextureLookup = false; if( renderParameters.globalTextureObj != NULL ) { renderParameters.globalTextureObj->activate( renderParameters.drawEnv ); renderParameters.globalTextureEnv->activate( renderParameters.drawEnv ); } else if( renderParameters.heightColorTexture != NULL ) { // todo: use a different pixel shader here // useDependentTextureLookup = true; renderParameters.heightColorTexture->activate( renderParameters.drawEnv ); } // render all levels from finest to coarsest: const int levelCount = int(levels_.size()); // for( int i = 0; i < levelCount; ++i ) for( int i = 0; i < levelCount; ++i ) { int levelIdx = levelCount - i - 1; //std::cerr << "Rendering Level " << levelIdx << std::endl; GeometryClipmapLevel& level = geoClipmaps_->getLevel( levelIdx ); GeometryClipmapLevel* coarserLevel = 0; GeometryClipmapLevel* finerLevel = 0; if( levelIdx > 0 ) { coarserLevel = &geoClipmaps_->getLevel( levelIdx - 1 ); } if( levelIdx + 1 < levelCount ) { finerLevel = &geoClipmaps_->getLevel( levelIdx + 1 ); } const Color3f& debugColor = getDebugColor( levelIdx ); #ifdef OLD_GEOCLIP terrainShader_.setUniform( "baseColor0", colorToVector( debugColor ) ); terrainShader_.setUniform( "sampleDistance", renderParameters.worldTransform.sampleDistance ); terrainShader_.setUniform( "worldOffset", renderParameters.worldTransform.offset ); terrainShader_.setUniform( "heightScale", renderParameters.worldTransform.heightScale ); terrainShader_.setUniform( "heightOffset", renderParameters.worldTransform.heightOffset ); #else #ifdef NOTUSED _pTerrainShader->setUniformParameter( "baseColor0", colorToVector( debugColor ) ); #endif _pTerrainShader->addUniformVariable( "sampleDistance", renderParameters.worldTransform.sampleDistance ); _pTerrainShader->addUniformVariable( "worldOffset", renderParameters.worldTransform.offset ); _pTerrainShader->addUniformVariable( "heightScale", renderParameters.worldTransform.heightScale ); _pTerrainShader->addUniformVariable( "heightOffset", renderParameters.worldTransform.heightOffset ); #endif if( renderParameters.showTransitionRegions ) { // todo: add a sensible debug representation.. drawSampleRectangle( level.getCoveredSampleRect(), debugColor, renderParameters.worldTransform ); //drawSamples( level, Color3f( 0, 1, 0 ) ); //drawVertices( level, debugColor ); drawBlendLines( level, debugColor, renderParameters.worldTransform ); } if( !level.isActive ) { continue; } // only use the finer level, if it is active: if( finerLevel && !finerLevel->isActive ) { finerLevel = 0; } // buildIndices dynamically builds the indices for this level and // does frustum culling // the method returns false if nothing is visible // todo: dont rebuild the indices every time.. just rebuild them if // something changed (inside the update() call) if( buildIndices( level, finerLevel ) ) { // finally: draw the block: renderBlock( level, coarserLevel, renderParameters, debugColor ); } stats_.drawnLevelCount++; } if( renderParameters.globalTextureObj != NULL ) { renderParameters.globalTextureObj->deactivate( renderParameters.drawEnv ); renderParameters.globalTextureEnv->deactivate( renderParameters.drawEnv ); } else if(renderParameters.heightColorTexture != NULL) { renderParameters.heightColorTexture->deactivate( renderParameters.drawEnv ); } #ifdef OLD_GEOCLIP terrainShader_.deactivate(); #else _pTerrainShader->deactivate(renderParameters.drawEnv); #endif }
float computeConcavity(unsigned int vcount, const float *vertices, unsigned int tcount, const unsigned int *indices, ConvexDecompInterface *callback, float *plane, // plane equation to split on float &volume) { float cret = 0; volume = 1; HullResult result; HullLibrary hl; HullDesc desc; desc.mMaxFaces = 256; desc.mMaxVertices = 256; desc.SetHullFlag(QF_TRIANGLES); desc.mVcount = vcount; desc.mVertices = vertices; desc.mVertexStride = sizeof(float)*3; HullError ret = hl.CreateConvexHull(desc,result); if ( ret == QE_OK ) { #if 0 float bmin[3]; float bmax[3]; float dx = bmax[0] - bmin[0]; float dy = bmax[1] - bmin[1]; float dz = bmax[2] - bmin[2]; Vector3d center; center.x = bmin[0] + dx*0.5f; center.y = bmin[1] + dy*0.5f; center.z = bmin[2] + dz*0.5f; #endif volume = computeMeshVolume2( result.mOutputVertices, result.mNumFaces, result.mIndices ); #if 1 // ok..now..for each triangle on the original mesh.. // we extrude the points to the nearest point on the hull. const unsigned int *source = result.mIndices; CTriVector tris; for (unsigned int i=0; i<result.mNumFaces; i++) { unsigned int i1 = *source++; unsigned int i2 = *source++; unsigned int i3 = *source++; const float *p1 = &result.mOutputVertices[i1*3]; const float *p2 = &result.mOutputVertices[i2*3]; const float *p3 = &result.mOutputVertices[i3*3]; // callback->ConvexDebugTri(p1,p2,p3,0xFFFFFF); CTri t(p1,p2,p3,i1,i2,i3); // tris.push_back(t); } // we have not pre-computed the plane equation for each triangle in the convex hull.. float totalVolume = 0; CTriVector ftris; // 'feature' triangles. const unsigned int *src = indices; float maxc=0; if ( 1 ) { CTriVector input_mesh; if ( 1 ) { const unsigned int *src = indices; for (unsigned int i=0; i<tcount; i++) { unsigned int i1 = *src++; unsigned int i2 = *src++; unsigned int i3 = *src++; const float *p1 = &vertices[i1*3]; const float *p2 = &vertices[i2*3]; const float *p3 = &vertices[i3*3]; CTri t(p1,p2,p3,i1,i2,i3); input_mesh.push_back(t); } } CTri maxctri; for (unsigned int i=0; i<tcount; i++) { unsigned int i1 = *src++; unsigned int i2 = *src++; unsigned int i3 = *src++; const float *p1 = &vertices[i1*3]; const float *p2 = &vertices[i2*3]; const float *p3 = &vertices[i3*3]; CTri t(p1,p2,p3,i1,i2,i3); featureMatch(t, tris, callback, input_mesh ); if ( t.mConcavity > CONCAVE_THRESH ) { if ( t.mConcavity > maxc ) { maxc = t.mConcavity; maxctri = t; } float v = t.getVolume(0); totalVolume+=v; ftris.push_back(t); } } } if ( ftris.size() ) { // ok..now we extract the triangles which form the maximum concavity. CTriVector major_feature; float maxarea = 0; while ( maxc > CONCAVE_THRESH ) { unsigned int color = getDebugColor(); // CTriVector flist; bool found; float totalarea = 0; do { found = false; CTriVector::iterator i; for (i=ftris.begin(); i!=ftris.end(); ++i) { CTri &t = (*i); if ( isFeatureTri(t,flist,maxc,callback,color) ) { found = true; totalarea+=t.area(); } } } while ( found ); if ( totalarea > maxarea ) { major_feature = flist; maxarea = totalarea; } maxc = 0; for (unsigned int i=0; i<ftris.size(); i++) { CTri &t = ftris[i]; if ( t.mProcessed != 2 ) { t.mProcessed = 0; if ( t.mConcavity > maxc ) { maxc = t.mConcavity; } } } } unsigned int color = getDebugColor(); WpointVector list; for (unsigned int i=0; i<major_feature.size(); ++i) { major_feature[i].addWeighted(list,callback); major_feature[i].debug(color,callback); } getBestFitPlane( list.size(), &list[0].mPoint.x, sizeof(Wpoint), &list[0].mWeight, sizeof(Wpoint), plane ); computeSplitPlane( vcount, vertices, tcount, indices, callback, plane ); } else { computeSplitPlane( vcount, vertices, tcount, indices, callback, plane ); } #endif cret = totalVolume; hl.ReleaseResult(result); } return cret; }
void Px3World::onDebugDraw( const SceneRenderState *state ) { if ( !mScene || !mRenderBuffer ) return; mScene->setVisualizationParameter(physx::PxVisualizationParameter::eSCALE,1.0f); mScene->setVisualizationParameter(physx::PxVisualizationParameter::eBODY_AXES,1.0f); mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_SHAPES,1.0f); // Render points { physx::PxU32 numPoints = mRenderBuffer->getNbPoints(); const physx::PxDebugPoint *points = mRenderBuffer->getPoints(); PrimBuild::begin( GFXPointList, numPoints ); while ( numPoints-- ) { PrimBuild::color( getDebugColor(points->color) ); PrimBuild::vertex3fv(px3Cast<Point3F>(points->pos)); points++; } PrimBuild::end(); } // Render lines { physx::PxU32 numLines = mRenderBuffer->getNbLines(); const physx::PxDebugLine *lines = mRenderBuffer->getLines(); PrimBuild::begin( GFXLineList, numLines * 2 ); while ( numLines-- ) { PrimBuild::color( getDebugColor( lines->color0 ) ); PrimBuild::vertex3fv( px3Cast<Point3F>(lines->pos0)); PrimBuild::color( getDebugColor( lines->color1 ) ); PrimBuild::vertex3fv( px3Cast<Point3F>(lines->pos1)); lines++; } PrimBuild::end(); } // Render triangles { physx::PxU32 numTris = mRenderBuffer->getNbTriangles(); const physx::PxDebugTriangle *triangles = mRenderBuffer->getTriangles(); PrimBuild::begin( GFXTriangleList, numTris * 3 ); while ( numTris-- ) { PrimBuild::color( getDebugColor( triangles->color0 ) ); PrimBuild::vertex3fv( px3Cast<Point3F>(triangles->pos0) ); PrimBuild::color( getDebugColor( triangles->color1 ) ); PrimBuild::vertex3fv( px3Cast<Point3F>(triangles->pos1)); PrimBuild::color( getDebugColor( triangles->color2 ) ); PrimBuild::vertex3fv( px3Cast<Point3F>(triangles->pos2) ); triangles++; } PrimBuild::end(); } }
float getVolume(ConvexDecompInterface *callback) const { unsigned int indices[8*3]; unsigned int tcount = 0; addTri(indices,0,1,2,tcount); addTri(indices,3,4,5,tcount); addTri(indices,0,3,4,tcount); addTri(indices,0,4,1,tcount); addTri(indices,1,4,5,tcount); addTri(indices,1,5,2,tcount); addTri(indices,0,3,5,tcount); addTri(indices,0,5,2,tcount); const float *vertices = mP1.Ptr(); if ( callback ) { unsigned int color = getDebugColor(); #if 0 Vector3d d1 = mNear1; Vector3d d2 = mNear2; Vector3d d3 = mNear3; callback->ConvexDebugPoint(mP1.Ptr(),0.01f,0x00FF00); callback->ConvexDebugPoint(mP2.Ptr(),0.01f,0x00FF00); callback->ConvexDebugPoint(mP3.Ptr(),0.01f,0x00FF00); callback->ConvexDebugPoint(d1.Ptr(),0.01f,0xFF0000); callback->ConvexDebugPoint(d2.Ptr(),0.01f,0xFF0000); callback->ConvexDebugPoint(d3.Ptr(),0.01f,0xFF0000); callback->ConvexDebugTri(mP1.Ptr(), d1.Ptr(), d1.Ptr(),0x00FF00); callback->ConvexDebugTri(mP2.Ptr(), d2.Ptr(), d2.Ptr(),0x00FF00); callback->ConvexDebugTri(mP3.Ptr(), d3.Ptr(), d3.Ptr(),0x00FF00); #else for (unsigned int i=0; i<tcount; i++) { unsigned int i1 = indices[i*3+0]; unsigned int i2 = indices[i*3+1]; unsigned int i3 = indices[i*3+2]; const float *p1 = &vertices[ i1*3 ]; const float *p2 = &vertices[ i2*3 ]; const float *p3 = &vertices[ i3*3 ]; callback->ConvexDebugTri(p1,p2,p3,color); } #endif } float v = computeMeshVolume(mP1.Ptr(), tcount, indices ); return v; }