[2.2] Terra modify heightmap issue

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


Lax
Gnoll
Posts: 659
Joined: Mon Aug 06, 2007 12:53 pm
Location: Saarland, Germany
x 63

[2.2] Terra modify heightmap issue

Post by Lax »

Hi,

I updated to newst Ogre version (the version with vulcan). I also updated to newest Terra version carefully. I made some sanity tests, if everything is working. But now, when I modify terra, the data structure is modified correctly, as ray-casts are working correctly and I even see changes in the heightmap, but the terrain itself is not growing anymore. It remains flat. See the attached video:

http://www.lukas-kalinowski.com/Homepag ... yIssue.mp4

What could cause this?

I use 3 functions for modifcation: start (create staging texture), modify (pixmap), finish (staging texture).

Code: Select all

void Terra::modifyTerrainStart(const Ogre::Vector3& position, float strength)
{
	m_oldHeightData.resize(m_width * m_depth, 0);
        m_newHeightData.resize(m_width * m_depth, 0);
        TextureGpuManager* textureManager = mManager->getDestinationRenderSystem()->getTextureGpuManager();
        // Important: Only create once, and after that work on that staging texture, else the heights get resetted every time
        if (nullptr == m_heightMapStagingTexture)
        {
            m_heightMapStagingTexture = textureManager->getStagingTexture(m_heightMapTex->getWidth(), m_heightMapTex->getHeight(), 1u, 1u, m_heightMapTex->getPixelFormat());
        }
        
        m_heightMapStagingTexture->startMapRegion();

        TextureBox texBox = m_heightMapStagingTexture->mapRegion(m_heightMapTex->getWidth(), m_heightMapTex->getHeight(), 1u, 1u, m_heightMapTex->getPixelFormat());

        memcpy(&m_oldHeightData[0], texBox.data, m_heightMapStagingTexture->_getSizeBytes());

        m_heightMapStagingTexture->stopMapRegion();
        
        this->applyHeightDiff(position, m_brushData, m_brushSize, strength);
}

void Terra::applyHeightDiff(const Ogre::Vector3& position, const std::vector<float>& data, int boxSize, float strength)
    {
        if (data.size() != boxSize * boxSize)
            return;

        // assert(data.size() == boxSize * boxSize);

        Ogre::GridPoint point = this->worldToGrid(position);
        //Offset the box so that the corner isn't the centre.
        point.x -= boxSize / 2;
        point.z -= boxSize / 2;

        int x = point.x;
        int y = point.z;
        
        TextureGpuManager* textureManager = mManager->getDestinationRenderSystem()->getTextureGpuManager();
        // Important: Only create once, and after that work on that staging texture, else the heights get resetted every time
        if (nullptr == m_heightMapStagingTexture)
        {
            m_heightMapStagingTexture = textureManager->getStagingTexture(m_heightMapTex->getWidth(), m_heightMapTex->getHeight(), 1u, 1u, m_heightMapTex->getPixelFormat());
        }
        if (m_heightMapTex->getNextResidencyStatus() != Ogre::GpuResidency::Resident)
        {
            m_heightMapTex->_transitionTo(Ogre::GpuResidency::Resident, (Ogre::uint8*)0);
            m_heightMapTex->_setNextResidencyStatus(Ogre::GpuResidency::Resident);
        }
        m_heightMapStagingTexture->startMapRegion();

        TextureBox texBox = m_heightMapStagingTexture->mapRegion(m_heightMapTex->getWidth(), m_heightMapTex->getHeight(), 1u, 1u, m_heightMapTex->getPixelFormat());

        float fBpp = (float)(PixelFormatGpuUtils::getBytesPerPixel(m_heightMapTex->getPixelFormat()) << 3u);
        const float maxValue = powf(2.0f, fBpp) - 1.0f;
        m_invMaxValue = 1.0f / maxValue;

        uint32 movAmount;
        uint32 shouldMoveAmount;
        int boxStartX, boxStartY, boxWidth, boxHeight;
        _calculateBoxSpecification(x, y, boxSize, m_heightMapTex->getWidth(), m_heightMapTex->getHeight(), &movAmount, &shouldMoveAmount, &boxStartX, &boxStartY, &boxWidth, &boxHeight);

        if (m_heightMapTex->getPixelFormat() == PFG_R16_UNORM)
        {
           
            for (int by = boxStartY; by < boxHeight; by++)
            {
                unsigned int posY = y + by;
                uint16* RESTRICT_ALIAS pixBoxData = reinterpret_cast<uint16 * RESTRICT_ALIAS>(texBox.at(0, posY, 0));

                for (int bx = boxStartX; bx < boxWidth; bx++)
                {
                    unsigned int posX = x + bx;

                    uint16 oldValue = pixBoxData[posX];
  
                    float determinedValue = oldValue + data[by * boxSize + bx] * strength;
                    if (determinedValue < 0.0f)
                    {
                        determinedValue = 0.0f;
                    }

                    //If value is 0 (we're lowering the terrain), the value should never be greater than what it previously was (possible with integer wrap-arounds).
                    if (strength < 0 && determinedValue > oldValue)
                    { 
                        determinedValue = 0;
                    }
                    else if (strength > 0 && determinedValue < oldValue)
                    {
                        determinedValue =  heightToVal<float>(m_height);
                    }

                    pixBoxData[posX] = determinedValue;
                    const float targetValue = this->valToHeight<float>(determinedValue);
                    m_heightMap[movAmount] = targetValue;

                    movAmount++;
                }
                movAmount += shouldMoveAmount; //Align to the start of the next line.
            }
        }

        m_heightMapStagingTexture->stopMapRegion();
        m_heightMapStagingTexture->upload(texBox, m_heightMapTex, 0, 0, 0);
       
        if (false == m_heightMapTex->isDataReady())
            m_heightMapTex->notifyDataIsReady();

        // is this necessary?
        updateHeightTextures();

        calculateOptimumSkirtSize();
    }
    
    std::pair<std::vector<Ogre::uint16>, std::vector<Ogre::uint16>> Terra::modifyTerrainFinished(void)
    {
        TextureGpuManager* textureManager = mManager->getDestinationRenderSystem()->getTextureGpuManager();
        // Important: Only create once, and after that work on that staging texture, else the heights get resetted every time
        if (nullptr == m_heightMapStagingTexture)
        {
            m_heightMapStagingTexture = textureManager->getStagingTexture(m_heightMapTex->getWidth(), m_heightMapTex->getHeight(), 1u, 1u, m_heightMapTex->getPixelFormat());
        }
        
        m_heightMapStagingTexture->startMapRegion();

        TextureBox texBox = m_heightMapStagingTexture->mapRegion(m_heightMapTex->getWidth(), m_heightMapTex->getHeight(), 1u, 1u, m_heightMapTex->getPixelFormat());

        memcpy(&m_newHeightData[0], texBox.data, m_heightMapStagingTexture->_getSizeBytes());

        m_heightMapStagingTexture->stopMapRegion();

        return std::move(std::make_pair(m_oldHeightData, m_newHeightData));
    }
Best Regards
Lax

http://www.lukas-kalinowski.com/Homepage/?page_id=1631
Please support Second Earth Technic Base built of Lego bricks for Lego ideas: https://ideas.lego.com/projects/81b9bd1 ... b97b79be62

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5446
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1348

Re: [2.2] Terra modify heightmap issue

Post by dark_sylinc »

I only took a quick look, but this doesn't look right:

Code: Select all

memcpy(&m_newHeightData[0], texBox.data, m_heightMapStagingTexture->_getSizeBytes());
StagingTextures are for CPU->GPU transfers and you're memcpy'ing in the opposite direction. You do this in multiple places.
Lax
Gnoll
Posts: 659
Joined: Mon Aug 06, 2007 12:53 pm
Location: Saarland, Germany
x 63

Re: [2.2] Terra modify heightmap issue

Post by Lax »

Hi dark_sylinc,
memcpy(&m_newHeightData[0], texBox.data, m_heightMapStagingTexture->_getSizeBytes());
hm ok, how can I get the texBox data into the m_newHeightData list? I do this, because I use undo-redo for terrain modification, so I swap the painted data between containers.

Best Regards
Lax

http://www.lukas-kalinowski.com/Homepage/?page_id=1631
Please support Second Earth Technic Base built of Lego bricks for Lego ideas: https://ideas.lego.com/projects/81b9bd1 ... b97b79be62

User avatar
Zonder
Ogre Magi
Posts: 1172
Joined: Mon Aug 04, 2008 7:51 pm
Location: Manchester - England
x 76

Re: [2.2] Terra modify heightmap issue

Post by Zonder »

I think you need to use "textureGpuManager->createAsyncTextureTicket" then download the data once fetched.
There are 10 types of people in the world: Those who understand binary, and those who don't...
Lax
Gnoll
Posts: 659
Joined: Mon Aug 06, 2007 12:53 pm
Location: Saarland, Germany
x 63

Re: [2.2] Terra modify heightmap issue

Post by Lax »

Hi all,

Code: Select all

textureGpuManager->createSyncTextureTicket
Ok, I will check that out.

But still, I'm having problems, getting terra working propertly. I now compared the forth time, the source and shaders, what could be wrong, but found nothing.

I created a simplest scenario: I just load the heightmap.png like in the Tutorial_Terrain and this is the result:

http://www.lukas-kalinowski.com/Homepag ... Height.png

The terrain remains totally flat. What could that be? Or is there an issue on Ogre side?

Best Regards
Lax

http://www.lukas-kalinowski.com/Homepage/?page_id=1631
Please support Second Earth Technic Base built of Lego bricks for Lego ideas: https://ideas.lego.com/projects/81b9bd1 ... b97b79be62

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5446
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1348

Re: [2.2] Terra modify heightmap issue

Post by dark_sylinc »

Terra added a new variable: Terra::m_heightUnormScaled used workaround an Android issue.
Looks like something in your code wasn't updated correctly; and now the vertex shader isn't applying the height scale (this is just a guess).

Additionally HlmsTerra and its shaders were slightly changed to fix some issues when binding the textures. If they hadn't been updated properly, the heightmap may not be bound to the vertex shader, causing this problem.

Is this D3D11 or GL?

A RenderDoc capture may reveal more.
Lax
Gnoll
Posts: 659
Joined: Mon Aug 06, 2007 12:53 pm
Location: Saarland, Germany
x 63

Re: [2.2] Terra modify heightmap issue

Post by Lax »

Terra added a new variable: Terra::m_heightUnormScaled used workaround an Android issue.
Yes I know and I carefully adapted the code, so that m_heightUnormScaled is used properly.
Is this D3D11 or GL?
its D3D11.

http://www.lukas-kalinowski.com/Homepage/?page_id=1631
Please support Second Earth Technic Base built of Lego bricks for Lego ideas: https://ideas.lego.com/projects/81b9bd1 ... b97b79be62

Lax
Gnoll
Posts: 659
Joined: Mon Aug 06, 2007 12:53 pm
Location: Saarland, Germany
x 63

Re: [2.2] Terra modify heightmap issue

Post by Lax »

Hi dark_sylinc,

I found out, that it must be an Ogre bug. I now started my engine with OpenGL and this is the result:

http://www.lukas-kalinowski.com/Homepag ... OpenGL.png

Best Regards
Lax

http://www.lukas-kalinowski.com/Homepage/?page_id=1631
Please support Second Earth Technic Base built of Lego bricks for Lego ideas: https://ideas.lego.com/projects/81b9bd1 ... b97b79be62

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5446
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1348

Re: [2.2] Terra modify heightmap issue

Post by dark_sylinc »

Your code is assuming StagingTexture is bidirectional which is wrong.
This may work (or appear to work) in one RenderSystem, but may fail on others.

It's not just the memcpy. You also perform:

Code: Select all

uint16 oldValue = pixBoxData[posX];
which you shouldn't do. The value you read from there may be garbage.

CPU -> GPU transfers are taken care by StagingTexture
GPU -> CPU transfers are taken care by AsyncTextureTicket

Also if you provide RenderDoc capture would greatly help to let us see what's going on during rendering. If you can upload both a D3D11 and GL captures, that'd be great.

Cheers
Lax
Gnoll
Posts: 659
Joined: Mon Aug 06, 2007 12:53 pm
Location: Saarland, Germany
x 63

Re: [2.2] Terra modify heightmap issue

Post by Lax »

Your code is assuming StagingTexture is bidirectional which is wrong.
Hm, I just use the memcpy as back, in order to be able to undo/redo the data nothing more. Do you mean, this could still cause issues? Because I could successfully undo/redo terrain modification and terrain paint.
Also if you provide RenderDoc capture would greatly help to let us see what's going on during rendering. If you can upload both a D3D11 and GL captures, that'd be great.
Ok I captured a frame:
* d3d: http://www.lukas-kalinowski.com/Homepag ... rraD3D.rdc
* openGL: http://www.lukas-kalinowski.com/Homepag ... OpenGL.rdc

http://www.lukas-kalinowski.com/Homepage/?page_id=1631
Please support Second Earth Technic Base built of Lego bricks for Lego ideas: https://ideas.lego.com/projects/81b9bd1 ... b97b79be62

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5446
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1348

Re: [2.2] Terra modify heightmap issue

Post by dark_sylinc »

I couldn't check your captures this weekend. Sorry for the delay. I'll try to see them when I get some free time.
Lax
Gnoll
Posts: 659
Joined: Mon Aug 06, 2007 12:53 pm
Location: Saarland, Germany
x 63

Re: [2.2] Terra modify heightmap issue

Post by Lax »

I couldn't check your captures this weekend. Sorry for the delay. I'll try to see them when I get some free time.
No problem, take your time. I know you are really busy :)

http://www.lukas-kalinowski.com/Homepage/?page_id=1631
Please support Second Earth Technic Base built of Lego bricks for Lego ideas: https://ideas.lego.com/projects/81b9bd1 ... b97b79be62