void D3D9RenderTargetTexture::GetData(Bitmap &B, const Rectangle2i &Source, const Rectangle2i &Dest)
{
    D3DAlwaysValidate(_Device->GetRenderTargetData(_Surface, _SurfacePlain), "GetRenderTargetData");

    if(_SurfaceResizing == NULL)
    {
        D3DAlwaysValidate(_Device->CreateOffscreenPlainSurface(_Width, _Height, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &_SurfaceResizing, NULL), "CreateOffscreenPlainSurface");
    }
    D3DAlwaysValidate(_Device->UpdateSurface(_SurfacePlain, NULL, _SurfaceResizing, NULL), "UpdateSurface");

    RECT SourceRect = Source.ToRect();
    RECT DestRect = Rectangle2i(Vec2i::Origin, Dest.Dimensions()).ToRect();
    D3DAlwaysValidate(_Device->StretchRect(_SurfaceResizing, &SourceRect, _Surface, &DestRect, D3DTEXF_LINEAR), "StretchRect");

    D3DAlwaysValidate(_Device->GetRenderTargetData(_Surface, _SurfacePlain), "GetRenderTargetData");

    D3DLOCKED_RECT LockedRect;
    D3DAlwaysValidate(_SurfacePlain->LockRect(&LockedRect, NULL, 0), "LockRect");

    Assert(int(B.Width()) >= Dest.Max.x && int(B.Height()) >= Dest.Max.y, "Bitmap too small");

    RGBColor *SurfData = (RGBColor*)LockedRect.pBits;
    for(int y = Dest.Min.y; y < Dest.Max.y; y++)
    {
        //memcpy(B[_Height - 1 - y], &SurfData[y * LockedRect.Pitch / 4], _Width * 4);
        memcpy(B[y] + Dest.Min.x, &SurfData[(y - Dest.Min.y) * LockedRect.Pitch / 4], Dest.Dimensions().x * 4);
    }

    _SurfacePlain->UnlockRect();
}
Esempio n. 2
0
	void ClipmapRenderer::drawSampleRectangle( const Rectangle2i& rect, const Color3f& color, const WorldTransformation& worldTrans ) const
	{
		Pnt2f from = worldTrans.sampleToWorldPos( rect.getTopLeft() );
		Pnt2f to = worldTrans.sampleToWorldPos( rect.getBottomRight() - Pnt2i( 1, 1 ) );

		glColor3f( color[ 0 ], color[ 1 ], color[ 2 ] );

		glBegin( GL_LINE_STRIP );

		glVertex3f( from[ 0 ], 0, from[ 1 ] );
		glVertex3f(   to[ 0 ], 0, from[ 1 ] );
		glVertex3f(   to[ 0 ], 0,   to[ 1 ] );
		glVertex3f( from[ 0 ], 0,   to[ 1 ] );
		glVertex3f( from[ 0 ], 0, from[ 1 ] );

		glEnd();	
	}
void D3D9RenderTargetTexture::RenderStringToBmp(const D3D9Font &Font, const String &Text, const Rectangle2i &Region, RGBColor FontColor, RGBColor BackgroundColor, Bitmap &Bmp)
{
    D3D9ProtectRenderTarget Protection(_Device, true, true);

    SetAsRenderTarget();
    _Device->Clear(0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, D3DCOLOR_ARGB(BackgroundColor.a, BackgroundColor.r, BackgroundColor.g, BackgroundColor.b), 1.0f, 0 );
    Font.DrawString(Text, Vec2f(Region.Min), float(Region.Width()), FontColor);
    GetData(Bmp);
}
Esempio n. 4
0
void D3D9Font::DrawString(const String &Text, const Rectangle2i &Rect, RGBColor Color) const
{
    RECT CurRect = Rect.ToRect();
    HRESULT CoopLevel = _Device->TestCooperativeLevel();
    if(CoopLevel == D3D_OK)
    {
        _Font->DrawText( NULL, Text.CString(), Text.Length(), &CurRect, DT_WORDBREAK | DT_CALCRECT, 0 );
        _Font->DrawText( NULL, Text.CString(), Text.Length(), &CurRect, DT_WORDBREAK | DT_NOCLIP, D3DXCOLOR(Color.r / 255.0f, Color.g / 255.0f, Color.b / 255.0f, 1.0f ));
    }
}
void CpuClipmapRenderer::createBlockIndices( GeometryClipmapLevel& level, const Rectangle2i& blockRect, int levelSampleCount, IndexList& indices )
{
    // todo: this needs rework..
    if( blockRect.isEmpty() )
    {
        return;
    }

    assert( blockRect._x0 >= 0 );
    assert( blockRect._y0 >= 0 );
    assert( blockRect._x1 > blockRect._x0 );
    assert( blockRect._y1 > blockRect._y0 );
    assert( blockRect._x0 < levelSampleCount );
    assert( blockRect._y0 < levelSampleCount );
    assert( blockRect._x1 < levelSampleCount );
    assert( blockRect._y1 < levelSampleCount );

    for( int y = blockRect._y0; y < blockRect._y1; ++y )
    {
        assert( y + 1 < levelSampleCount );
        const int row0 = ( level.blockOrigin[ 1 ] + y ) % levelSampleCount;
        const int row1 = ( level.blockOrigin[ 1 ] + y + 1 ) % levelSampleCount;

        for( int x = blockRect._x0; x < blockRect._x1; ++x )
        {
            assert( x + 1 < levelSampleCount );
            const int col0 = ( level.blockOrigin[ 0 ] + x ) % levelSampleCount;
            const int col1 = ( level.blockOrigin[ 0 ] + x + 1 ) % levelSampleCount;

            const int idx0 = row0 * levelSampleCount + col0;
            const int idx1 = row0 * levelSampleCount + col1;
            const int idx2 = row1 * levelSampleCount + col0;
            const int idx3 = row1 * levelSampleCount + col1;

            assert( idx0 < 65536 );
            assert( idx1 < 65536 );
            assert( idx2 < 65536 );
            assert( idx3 < 65536 );

            indices.push_back( idx0 );
            indices.push_back( idx2 );
            indices.push_back( idx1 );

            indices.push_back( idx1 );
            indices.push_back( idx2 );
            indices.push_back( idx3 );
        }
    }
}
	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 );					
			}			
		}
	}
bool CpuClipmapRenderer::buildIndices( GeometryClipmapLevel& level,
                                       const GeometryClipmapLevel* finerLevel )
{
    // todo: speedup?! (insert optimal tristrips here..)
    // and frustum culling...
    TerrainLevelRenderData& renderData = levels_[ level.index ];
    const int levelSampleCount = level.heightmap.size;

    if( !renderData.rebuildIndices )
    {
        return true;
    }
    renderData.rebuildIndices = false;

    renderData.indices.resize( 0 );

    const int levelSampleCoverage = level.getSampleCoverage();

    // we need the world extend in sample space for clipping:
    const Pnt2i worldSampleCount = geoClipmaps_->getWorldSampleCount();

    // check if this level is at least partly visible:
    if( level.sampleOrigin[ 0 ] >= worldSampleCount[ 0 ] - level.sampleSpacing ||
            level.sampleOrigin[ 1 ] >= worldSampleCount[ 1 ] - level.sampleSpacing ||
            level.sampleOrigin[ 0 ] + levelSampleCoverage < level.sampleSpacing ||
            level.sampleOrigin[ 1 ] + levelSampleCoverage < level.sampleSpacing )
    {
        // completely invisible:
        return false;
    }

    // decision:
    // either it is only one large or 8 small primitives:
    if( !finerLevel )
    {
        // ok: no finer level: only one large primitive
        // todo: possible speedup: frustum culling by dividing the level in smaller parts..
        Rectangle2i blockRect;

        blockRect.setBounds( 0, 0, levelSampleCount - 1, levelSampleCount - 1 );

        // clip rectangle to the world bounds:
        if( level.sampleOrigin[ 0 ] < 0 )
        {
            blockRect._x0 = -level.sampleOrigin[ 0 ] / level.sampleSpacing;
        }
        if( level.sampleOrigin[ 1 ] < 0 )
        {
            blockRect._y0 = -level.sampleOrigin[ 1 ] / level.sampleSpacing;
        }
        if( level.sampleOrigin[ 0 ] + levelSampleCoverage >= worldSampleCount[ 0 ] )
        {
            blockRect._x1 = ( worldSampleCount[ 0 ] - level.sampleOrigin[ 0 ] - 1 ) / level.sampleSpacing;
        }
        if( level.sampleOrigin[ 1 ] + levelSampleCoverage >= worldSampleCount[ 1 ] )
        {
            blockRect._y1 = ( worldSampleCount[ 1 ] - level.sampleOrigin[ 1 ] - 1 ) / level.sampleSpacing;
        }
        createBlockIndices( level, blockRect, levelSampleCount, renderData.indices );
    }
    else
    {
        // build 8 primitives for the level:
        // 0 1 2
        // 3   4
        // 5 6 7

        // todo: beautify this code
        int colEnd[ 3 ];
        int rowEnd[ 3 ];

        int colEndSample[ 3 ];
        int rowEndSample[ 3 ];

        colEndSample[ 0 ] = clamp( finerLevel->sampleOrigin[ 0 ], 0, worldSampleCount[ 0 ] - 1 );
        colEndSample[ 1 ] = clamp( finerLevel->sampleOrigin[ 0 ] + finerLevel->getSampleCoverage(), 0, worldSampleCount[ 0 ] - 1 );
        colEndSample[ 2 ] = clamp( level.sampleOrigin[ 0 ] + levelSampleCoverage, 0, worldSampleCount[ 0 ] - 1 );

        // convert to block space:
        colEnd[ 0 ] = clamp( ( colEndSample[ 0 ] - level.sampleOrigin[ 0 ] ) / level.sampleSpacing, 0, levelSampleCount - 1 );
        colEnd[ 1 ] = clamp( ( colEndSample[ 1 ] - level.sampleOrigin[ 0 ] ) / level.sampleSpacing, 0, levelSampleCount - 1 );
        colEnd[ 2 ] = clamp( ( colEndSample[ 2 ] - level.sampleOrigin[ 0 ] ) / level.sampleSpacing, 0, levelSampleCount - 1 );

        rowEndSample[ 0 ] = clamp( finerLevel->sampleOrigin[ 1 ], 0, worldSampleCount[ 1 ] - 1 );
        rowEndSample[ 1 ] = clamp( finerLevel->sampleOrigin[ 1 ] + finerLevel->getSampleCoverage(), 0, worldSampleCount[ 1 ] - 1 );
        rowEndSample[ 2 ] = clamp( level.sampleOrigin[ 1 ] + levelSampleCoverage, 0, worldSampleCount[ 1 ] - 1 );

        // convert to block space:
        rowEnd[ 0 ] = clamp( ( rowEndSample[ 0 ] - level.sampleOrigin[ 1 ] ) / level.sampleSpacing, 0, levelSampleCount - 1 );
        rowEnd[ 1 ] = clamp( ( rowEndSample[ 1 ] - level.sampleOrigin[ 1 ] ) / level.sampleSpacing, 0, levelSampleCount - 1 );
        rowEnd[ 2 ] = clamp( ( rowEndSample[ 2 ] - level.sampleOrigin[ 1 ] ) / level.sampleSpacing, 0, levelSampleCount - 1 );

        // clip the row start:
        int rowStart = 0;

        if( level.sampleOrigin[ 1 ] < 0 )
        {
            rowStart = -level.sampleOrigin[ 1 ] / level.sampleSpacing;
        }

        Rectangle2i blockRect;

        for( int row = 0; row < 3; ++row )
        {
            //int rowStart = 0;
            if( row > 0 )
            {
                rowStart = rowEnd[ row - 1 ];
            }

            int colStart = 0;

            if( level.sampleOrigin[ 0 ] < 0 )
            {
                colStart = -level.sampleOrigin[ 0 ] / level.sampleSpacing;
            }

            for( int col = 0; col < 3; ++col )
            {
                if( row == 1 && col == 1 )
                {
                    // this place is taken by the finer level
                    continue;
                }

                if( col > 0 )
                {
                    colStart = colEnd[ col - 1 ];
                }

                blockRect.setValues( colStart, rowStart, colEnd[ col ], rowEnd[ row ] );

                stats_.drawnBlockCount++;

                // create the indices:
                createBlockIndices( level, blockRect, levelSampleCount, renderData.indices );
            }
        }
    }

    // return false if this contains no indices -> no need to render
    return renderData.indices.size() > 0;
}
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();
    }
}
Esempio n. 9
0
int GeometryClipmaps::updateBigLevelBlock( GeometryClipmapLevel& level, const GeometryClipmapLevel* parentLevel, const Rectangle2i& targetRect )
{
    if( targetRect.isEmpty() )
    {
        return 0;
    }
    
    const int levelSampleCount = level.heightmap.size;
    
    // split the rect into up to 4 subrects and update them individually:
    Rectangle2i subRects[ 4 ];
    int subRectCount = 0;
    
#if 0
    int midY = 0;
    int maxY = 0;
    int midX = 0;
    int maxX = 0;
#endif
    
    subRects[ 0 ] = targetRect;
    subRectCount++;
    
    if( targetRect._x1 < targetRect._x0 )
    {
        // split in X:              
        subRects[ 0 ]._x1 = levelSampleCount;
        subRects[ 1 ] = targetRect;
        subRects[ 1 ]._x0 = 0;
        subRectCount++;
    }
    else if( targetRect._x1 > levelSampleCount )
    {
        // split in X:              
        subRects[ 0 ]._x1 = levelSampleCount;
        subRects[ 1 ] = targetRect;
        subRects[ 1 ]._x0 = 0;
        subRects[ 1 ]._x1 -= levelSampleCount;
        subRectCount++;
    }
    
    // ok.. we have 1 or 2 subRects already: split them on the Y axis:
    if( targetRect._y1 < targetRect._y0 )
    {
        // patch the existing ones:
        for( int i = 0; i < subRectCount; ++i )
        {
            subRects[ subRectCount + i ] = subRects[ i ];
            
            subRects[ subRectCount + i ]._y0 = 0;
            subRects[ i ]._y1 = levelSampleCount;
        }
        subRectCount += subRectCount;
    }
    else if( targetRect._y1 > levelSampleCount )
    {
        // patch the existing ones:
        for( int i = 0; i < subRectCount; ++i )
        {
            subRects[ subRectCount + i ] = subRects[ i ];
            
            subRects[ subRectCount + i ]._y0 = 0;
            subRects[ subRectCount + i ]._y1 -= levelSampleCount;
            subRects[ i ]._y1 = levelSampleCount;
        }
        subRectCount += subRectCount;
    }
    
    int sampleUpdateCount = 0;
    
    for( int i = 0; i < subRectCount; ++i )
    {
        sampleUpdateCount += updateLevelBlock( level, parentLevel, subRects[ i ] );
    }
    return sampleUpdateCount;
}