void ImageHeightDataSource::fillHeightData( GeometryClipmapLevel& level, const Rectangle2i& targetRect ) const { // check validity of the input data: assert( targetRect.getWidth() > 0 ); assert( targetRect.getHeight() > 0 ); // todo: clip data to the existing data: (saves per pixel clipping) // iterate over the target pixels and fill them with the image height data: Pnt2i samplePos; for( int y = targetRect.y0; y < targetRect.y1; ++y ) { float* targetPtr = &level.heightmap.samples[ y * level.heightmap.size ]; for( int x = targetRect.x0; x < targetRect.x1; ++x ) { // todo: make this incremental: samplePos = level.blockPosToSamplePos( Pnt2i( x, y ) ); targetPtr[ x ] = heightScale_ * getHeightSample( samplePos ); } } }
void CpuClipmapRenderer::onBuildVertices( GeometryClipmapLevel& level, const GeometryClipmapLevel* coarserLevel, const Rectangle2i& blockRect ) { const int levelSampleCount = level.heightmap.size; TerrainLevelRenderData& levelRenderData = levels_[ level.index ]; // loop over the changed vertices: Pnt2i samplePos; Pnt2f worldPos; const Pnt2i worldSampleCount = geoClipmaps_->getWorldSampleCount(); for( int y = blockRect._y0; y < blockRect._y1; ++y ) { const int index = y * levelSampleCount + blockRect._x0; const float* samplePtr = &level.heightmap.samples[ index ]; OpenGLTerrainVertex* vertexPtr = &levelRenderData.vertices[ index ]; for( int x = blockRect._x0; x < blockRect._x1; ++x ) { // todo: make this incremental samplePos = level.blockPosToSamplePos( Pnt2i( x, y ) ); vertexPtr->pos[ 0 ] = samplePos[ 0 ]; vertexPtr->pos[ 1 ] = *samplePtr; vertexPtr->pos[ 2 ] = samplePos[ 1 ]; vertexPtr->pos[ 3 ] = *samplePtr; // todo: correct uv coordinates: vertexPtr->uv.setValues( float(samplePos[ 0 ]) / float(worldSampleCount[ 0 ]), float(samplePos[ 1 ]) / float(worldSampleCount[ 1 ]) ); //vertexPtr->uv.setValues( float( x ) / float( levelSampleCount - 1 ), float( y ) / float( levelSampleCount - 1 ) ); samplePtr++; vertexPtr++; } } if( coarserLevel ) { // todo: fill in the interpolated positions of the coarser level: const int coarserLevelSpacing = coarserLevel->sampleSpacing; #ifdef OSG_DEBUG const int coarserLevelSampleCount = coarserLevel->heightmap.size; #endif // todo: make this faster for( int y = blockRect._y0; y < blockRect._y1; ++y ) { const int index = y * levelSampleCount + blockRect._x0; OpenGLTerrainVertex* vertexPtr = &levelRenderData.vertices[ index ]; for( int x = blockRect._x0; x < blockRect._x1; ++x, ++vertexPtr ) { // todo: make this incremental samplePos = level.blockPosToSamplePos( Pnt2i( x, y ) ); Pnt2i blendWeights = componentModulo( samplePos, coarserLevelSpacing ); if( blendWeights[ 0 ] == 0 && blendWeights[ 1 ] == 0 ) { continue; } Pnt2i coarserSamplePos = samplePos - blendWeights; Pnt2i coarserSamplePos10 = componentAdd( coarserSamplePos, Pnt2i( coarserLevelSpacing, 0 ) ); Pnt2i coarserSamplePos01 = componentAdd( coarserSamplePos, Pnt2i( 0, coarserLevelSpacing ) ); // todo: clip on a higher level (not per pixel) if( !coarserLevel->containsSample( coarserSamplePos ) || !coarserLevel->containsSample( coarserSamplePos10 ) || !coarserLevel->containsSample( coarserSamplePos01 ) ) { // no data} continue; } Pnt2i coarserBlockPos = coarserLevel->samplePosToBlockPos( coarserSamplePos ); #ifdef OSG_DEBUG assert( coarserBlockPos[ 0 ] < coarserLevelSampleCount && coarserBlockPos[ 1 ] < coarserLevelSampleCount ); #endif Pnt2i coarserBlockPos10 = coarserLevel->samplePosToBlockPos( coarserSamplePos10 ); Pnt2i coarserBlockPos01 = coarserLevel->samplePosToBlockPos( coarserSamplePos01 ); if( ( blendWeights[ 0 ] != 0 ) && ( blendWeights[ 1 ] != 0 ) ) { // todo: is this case important? } else if( blendWeights[ 0 ] != 0 ) { const float coarserSample00 = coarserLevel->getBlockSample( coarserBlockPos ); const float coarserSample10 = coarserLevel->getBlockSample( coarserBlockPos10 ); vertexPtr->pos[ 3 ] = ( coarserSample00 + coarserSample10 ) / 2.0f; } else if( blendWeights[ 1 ] != 0 ) { const float coarserSample00 = coarserLevel->getBlockSample( coarserBlockPos ); const float coarserSample01 = coarserLevel->getBlockSample( coarserBlockPos01 ); vertexPtr->pos[ 3 ] = ( coarserSample00 + coarserSample01 ) / 2.0f; } } } } if( levelRenderData.vertexBuffer.isValid() ) { // todo: upload only the changed data rect: // const int vertexCount = levelRenderData.vertices.size(); //std::cerr << "Uploading Vbo Data " << blockRect << std::endl; const int vboLineLength = sizeof( OpenGLTerrainVertex ) * blockRect.getWidth(); for( int y = blockRect._y0; y < blockRect._y1; ++y ) { const int index = y * levelSampleCount + blockRect._x0; const int vboOffset = index * sizeof( OpenGLTerrainVertex ); levelRenderData.vertexBuffer.uploadData( &levelRenderData.vertices[ index ], vboOffset, vboLineLength ); } // testing: upload the complete vbo: //std::cerr << "Uploading VBO Data" << std::endl; //levelRenderData.vertexBuffer.uploadData( &levelRenderData.vertices[ 0 ], 0, sizeof( OpenGLTerrainVertex ) * vertexCount ); //checkVboConsistency( levelRenderData, levelSampleCount ); levelRenderData.vertexBuffer.deactivate(); } }