Basic Terrain editor help

Started by
4 comments, last by Sivx 8 years, 9 months ago

This is the rendering code to render and do a pick test on the terrain

What i want todo next is increase the picked triangles vertices for mouse 1 and decrease for mouse 2 , so that i can sculpt it to how i like

I know i have to lock the vertex buffer but i am unsure how to get the positions and adjust them and when todo it


// Clear the backbuffer and depth buffer.
    HR(gd3dDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffeeeeee, 1.0f, 0));

    HR(gd3dDevice->BeginScene());

    // Setup the rendering FX
    HR(mFX->SetMatrix(mhViewProj, &(mView*mProj)));
    HR(mFX->SetTechnique(mhTech));
    UINT numPasses = 0;
    HR(mFX->Begin(&numPasses, 0));
    HR(mFX->BeginPass(0));
    HR(gd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME));
    HR(mTerrainMesh->DrawSubset(0));


    // Switch back to solid mode.
    HR(gd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID));

    // Did we pick anything?
    D3DXVECTOR3 originW(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 dirW(0.0f, 0.0f, 0.0f);
    if( gDInput->mouseButtonDown(0) )
    {
        getWorldPickingRay(originW, dirW);

        BOOL hit = 0;
        DWORD faceIndex = -1;
        float u = 0.0f;
        float v = 0.0f;
        float dist = 0.0f;
        ID3DXBuffer* allhits = 0;
        DWORD numHits = 0;
        HR(D3DXIntersect(mTerrainMesh, &originW, &dirW, &hit,
            &faceIndex, &u, &v, &dist, &allhits, &numHits));
        ReleaseCOM(allhits);

        // We hit anything?
        if( hit )
        {
            // Yes, draw the picked triangle in solid mode.
            IDirect3DVertexBuffer9* vb = 0;
            IDirect3DIndexBuffer9* ib = 0;
            HR(mTerrainMesh->GetVertexBuffer(&vb));
            HR(mTerrainMesh->GetIndexBuffer(&ib));

            HR(gd3dDevice->SetIndices(ib));
            HR(gd3dDevice->SetVertexDeclaration(VertexPNT::Decl));
            HR(gd3dDevice->SetStreamSource(0, vb, 0, sizeof(VertexPNT)));

            // faceIndex identifies the picked triangle to draw.
            HR(gd3dDevice->DrawIndexedPrimitive(
                D3DPT_TRIANGLELIST, 0, 0, mTerrainMesh->GetNumVertices(), faceIndex*3, 1))
            
            ReleaseCOM(vb);
            ReleaseCOM(ib);
        }
    }
    HR(mFX->EndPass());
    HR(mFX->End());
    
    mGfxStats->display();

    HR(gd3dDevice->EndScene());

    // Present the backbuffer.
    HR(gd3dDevice->Present(0, 0, 0, 0));
:)
Advertisement

I handle this all through shaders, but it was a bit of work to get setup. I'm not sure the performance implications this may have( testing and experience would dictate) but when you lock a buffer you are able to move bytes into and out of it. I would try keeping a local copy of the vertex data, and lock/fill the vb each time you adjust the mesh.

As for the adjusting, you have the triangle index, and with it you can find the exact vertices that this triangle is made up of. simply change the height component of those 3 vertices, lock and fill, and render as normal.

In my terrain editor in progress, http://www.gamedev.net/blog/900/entry-2259765-slow-days/, I use a height map for elevation data. When using the raise/lower tool, if the mouse is down while updating, i pick the terrain to get an x,z pair at the intersection, use those to get uv coordinates, and use the UV coords to render a small brush to the height map, which raises or lowers the heights in the area that the brush intersects.


I know i have to lock the vertex buffer but i am unsure how to get the positions and adjust them and when todo it

Given a face index (say FI), you first get the 3 vertex indices from the index buffer. E.g.,


UINT vidx[3];
vidx[0] = ib[ FI*3 + 0 ];
vidx[1] = ib[ FI*3  + 1 ];
vidx[2] = ib[ FI*3 + 2 ];

Then adjust the position value for each of those three vertices. E.g.,


for( int i = 0; i < 3; ++i )
{
   vb[ vidx[ i ] ].position += D3DXVECTOR3( ... some offset ... );
}

As Burnt_Fyr suggests, if you keep a copy of the vertex and index buffers, you can do those calcs on the copy, then lock the vertex buffer, update just the 3 vertices you've repositioned, unlock the vertex buffer and be on your way.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

when i do this

UINT vidx[3];
vidx[0] = ib[ faceIndex*3 + 0 ];
vidx[1] = ib[ faceIndex*3 + 1 ];
vidx[2] = ib[ faceIndex*3 + 2 ];

also where does .position come from?
:)

You need to look at the intent of the code and try to understand it, rather than just copy-and-paste.

Lock the index buffer (if you're not using a copy), and cast the data pointer to a pointer to the index buffer data format. Use that pointer instead of ib in the code snippet. Be sure to unlock the index buffer when you're done with it.

Similar for vb. vb in the code snippet is intended to be a pointer to VertexPNT (if that's the format of your vertex structures).


where does .position come from?

You declare your vertex structure as VertexPNT. That normally means the vertex is comprised of a Position, a Normal, and Texture coordinates. Position is the position part of the vertex.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Good work btw, personally.. I would recommend sculptris because it provides sculpting of a plane and the features ur talking about and more free, you just gotta load the particular obj in. Let me know if you have any questions about that approach. Also u can the terrain in smaller blocks and then add them together and I'm sure your ninja coding skills can "glue" the parts together. Think Tony hawks level editor back in the day.

This topic is closed to new replies.

Advertisement