Irr1.8c++| How can i project a useable grid on to my Terrain

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Ultraporing
Posts: 34
Joined: Tue Nov 06, 2007 7:22 pm
Location: Würzburg, Germany

Re: Irr1.8c++| How can i project a useable grid on to my Ter

Post by Ultraporing »

I like to know the total size after the terrain is created with the patches, width and height. The heighmap points Y-Axis do I get with getHeight.
I have used the heightmap texture to get the size till now, but the terrain size is diffrent after it got created and I'm drawing my grid too large because of this.
zerochen
Posts: 273
Joined: Wed Jan 07, 2009 1:17 am
Location: Germany

Re: Irr1.8c++| How can i project a useable grid on to my Ter

Post by zerochen »

hi,

the api can help you there

http://irrlicht.sourceforge.net/docu/cl ... 86a47d8af5

ITerrainSceneNode::getBoundingBox()
ITerrainSceneNode::getBoundingBox(s32 patchX, s32 patchZ)

regards
zerochen
STTrife
Posts: 33
Joined: Sun Jan 13, 2013 3:43 pm

Re: Irr1.8c++| How can i project a useable grid on to my Ter

Post by STTrife »

You are creating this terrain scenenode yourself right? So you provide it with a heightmap (which you know the size of, or can get), and you also supply the patch size. Now if you heightmap is for example 256 wide, then you get 255 patches. So multiply that with patchsize and you should have the total width.
I don't see the problem here... how can you not know the size of your heightmap when you are the one who creates it in the first place :)

Maybe you can provide some more information. Where do you get your height values from? I was assuming a bitmap? If this is the case, then either you made the bitmap yourself, so you know the with and height, or you can load the bitmap as a texture and query it's with and height. If you get it from another source there is always some way to know the width and height of the heightmap you are using (and I'm talking about the map with height information, not about the terrain itself)

Now I must say I never actually used the terrainscenenode, but from what I can see it:
-assumes equal with and height
-creates patches between height-points

so if your height-information map is 256*256, and your patchsize is set to 20, your rendered terrain will be (256-1)*20 = 5100 in width and in height.
Ultraporing
Posts: 34
Joined: Tue Nov 06, 2007 7:22 pm
Location: Würzburg, Germany

Re: Irr1.8c++| How can i project a useable grid on to my Ter

Post by Ultraporing »

STTrife wrote:You are creating this terrain scenenode yourself right? So you provide it with a heightmap (which you know the size of, or can get), and you also supply the patch size. Now if you heightmap is for example 256 wide, then you get 255 patches. So multiply that with patchsize and you should have the total width.
I don't see the problem here... how can you not know the size of your heightmap when you are the one who creates it in the first place :)

Maybe you can provide some more information. Where do you get your height values from? I was assuming a bitmap? If this is the case, then either you made the bitmap yourself, so you know the with and height, or you can load the bitmap as a texture and query it's with and height. If you get it from another source there is always some way to know the width and height of the heightmap you are using (and I'm talking about the map with height information, not about the terrain itself)

Now I must say I never actually used the terrainscenenode, but from what I can see it:
-assumes equal with and height
-creates patches between height-points

so if your height-information map is 256*256, and your patchsize is set to 20, your rendered terrain will be (256-1)*20 = 5100 in width and in height.

I know the Heightmap size and im using it like this to calculate the amount of cells needed: HeightmapWidth / CellSize = AmountOfCellsInWitdth.
My heightmap bmp is 256*256, but the problem is that I draw more cells then the terrain width. I upload the program so you can see for yourself:
https://www.dropbox.com/s/p6og0a9ddtfz6 ... 20proj.rar
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Irr1.8c++| How can i project a useable grid on to my Ter

Post by CuteAlien »

I think it's as STTrife wrote... use 256-1 and not 256. The heightmap probably gives the corners, not the centers of the grids (so you need one more).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Ultraporing
Posts: 34
Joined: Tue Nov 06, 2007 7:22 pm
Location: Würzburg, Germany

Re: Irr1.8c++| How can i project a useable grid on to my Ter

Post by Ultraporing »

but when i increase the patchsize the terrain get smaller so 5100 is probably in pixels not in units. I have one time set the patchsize to 192 then the terrain was tiny and i have still drawn the same amount of cells as it were 17.
So the question still remains how can i get the real size of the terrain in units.
STTrife
Posts: 33
Joined: Sun Jan 13, 2013 3:43 pm

Re: Irr1.8c++| How can i project a useable grid on to my Ter

Post by STTrife »

Ok the patch size is not what I thought it was....

If you look at the code: the patchsize in the terrainscene node are not the render width of each ' square' in your heightmap, but these are used only for the LOD stuff... which is very nice, but also puts some restraints on what sort of heightmap you can use.

the patchsize you provide has to be of type E_TERRAIN_PATCH_SIZE, which can be
ETPS_9 = 9,
ETPS_17 = 17,
ETPS_33 = 33,
ETPS_65 = 65,
ETPS_129 = 129

The terrain is devided into patches of <patchsize * patchsize> heightpoints, and depending on the distance of the camera, patches are rendered at a certain LOD. If the LOD decreases, the renderer takes larger steps to skip vertices, so each step of less LOD (LOD level increase = less details), the amount of triangles are decreased by 2*2 = 4. The patch size puts a maximum on the level of details it can decrease. So if you pick larger patch sizes, it can switch to more level of details (for when the camera is far away), which give more render speed.

So the patch size has nothing to do with the render size, but rather in how much patches you want to 'divide' your terrain. For huge terrains, you can choose larger patch sizes so you can go to more levels of details than with small patches. But with small terrains, if you choose a big patch size, it will render most of the terrain in the same LOD, cause you only have 1 or a few patches, and then the whole LOD stuff doesn't work as well as you'd hope :)

If you look at how the vertices are created: the x and z are just set to 1,2,3,4,5,6 etc. so the size of your field should only be dependent on the size of your heightmap (in pixels) and the scale you provide when creating the TerrainSceneNode.

so basically you do: (heightmap.width-1) * scale.x to get the terrain width, if I'm not mistaken. So don't look at the patchsize at all for that!

look at the code:

Code: Select all

for (s32 x = 0; x < TerrainData.Size; ++x)
        {
            float fz=0.f;
            float fz2=0.f;
            for (s32 z = 0; z < TerrainData.Size; ++z)
            {
                video::S3DVertex2TCoords& vertex= static_cast<video::S3DVertex2TCoords*>(mb->getVertexBuffer().pointer())[index++];
                vertex.Normal.set(0.0f, 1.0f, 0.0f);
                vertex.Color = vertexColor;
                vertex.Pos.X = fx;
                vertex.Pos.Y = (f32) heightMap->getPixel(TerrainData.Size-x-1,z).getLightness();
                vertex.Pos.Z = fz;
 
                vertex.TCoords.X = vertex.TCoords2.X = 1.f-fx2;
                vertex.TCoords.Y = vertex.TCoords2.Y = fz2;
 
                ++fz;
                fz2 += tdSize;
            }
            ++fx;
            fx2 += tdSize;
        }
the x and z coordinates are just set to fx and fz, which are increased by one for each pixel in your heightmap. Later on in the code they are multiplied by the scale that you provided.
So if you use a bitmap image of 256 x 256, and you use a scale of <1,1,1>, then your map will be rendered with a width of 255

The patch size should probably be set to ETPS_9 = 9 if your map is only 256x256, but obviously if your terrain is larger, you can use larger patch sizes., but for the small terrain of 256, defenitly not at ETPS_129 or some other number that you choose yourself. Stick to the list, or else the patch algorithm will not work well. Also I can't quickly see if the code takes into accounts heightmaps which are not a precice multiple of (patchsize-1). So if you choose patch size ETPS_17, then your terrain size should be a multiple of 16, or else there will be patches which are half-filled, and I have no idea what will happen then.

another thing: the terrainscenenode ASSUMES you have a square heightmap, so width = height, or things will go bad.

idea: try putting a custom box next to your terrain with a width and depth provided by you so you have an idea of how big your terrain is.
Ultraporing
Posts: 34
Joined: Tue Nov 06, 2007 7:22 pm
Location: Würzburg, Germany

Re: Irr1.8c++| How can i project a useable grid on to my Ter

Post by Ultraporing »

Ok now my grid gets drawn with verticies and I still got 335 fps while drawing with cellspacing 1 unit :).
I draw now only the horizontal and vertical lines.
I have to fix the issue with the grid clipping into the terrain, and I also have to clean up the class and optimise it.

But here is what I got so far:

Image
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Irr1.8c++| How can i project a useable grid on to my Ter

Post by CuteAlien »

Nice progress :-)
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Ultraporing
Posts: 34
Joined: Tue Nov 06, 2007 7:22 pm
Location: Würzburg, Germany

Re: Irr1.8c++| How can i project a useable grid on to my Ter

Post by Ultraporing »

Im back with some problems and was wondering if someone seen this before or know maybe how to fix it.

Problem 1: If I make my grid smaller than 18 cells the render function goes apeshit, but my debug output dont indicate that the points are wrong.

17 Cells (apeshit):
Image

Debug Output (X = iteration X axis, Z = iteration Z axis, Vec3 is the 3df vector point):
http://pastebin.com/BPD9KE21

18 Cells (All nice and dandy):
Image

Debug Output (X = iteration X axis, Z = iteration Z axis, Vec3 is the 3df vector point):
http://pastebin.com/qhGy8Xt6

Problem 2: When I use diffrent values for the width and height the program crashes and dies at the start of my render loop or at

Code: Select all

 
//Here
Box.addInternalPoint(v1); 
 
// Here after removing the addInternalPoint
while (device->run() && videoDrv)
 
My Grid Point Creation function:

Code: Select all

 
void EDE_GridSceneNode::createGridOnPositionTerrain(ITerrainSceneNode* terrainSceneNode)
{
    std::ofstream debugFile;
    debugFile.open("debugFile.txt");
 
    for (int x = 0; x < widthInCells + 1; x++)
    {
        for (int z = 0; z < heightInCells + 1; z++)
        {
            vector3df v1 = vector3df(
                (terrainSceneNode->getAbsolutePosition().X + gridPos.X) + ((x+1)*this->cellSize), 
                terrainSceneNode->getHeight((terrainSceneNode->getAbsolutePosition().X + gridPos.X) + ((x+1)*this->cellSize),
                                            (terrainSceneNode->getAbsolutePosition().Z + gridPos.Z) + ((z+1)*this->cellSize)), 
                (terrainSceneNode->getAbsolutePosition().Z + gridPos.Z) + ((z+1)*this->cellSize));
 
            verticesVertical[z][x].Pos = v1;
            verticesVertical[z][x].Color = this->color;
            uIndicesVertical[z][x] = x;
 
            verticesHorizontal[x][z].Pos = v1;
            verticesHorizontal[x][z].Color = this->color;
            uIndicesHorizontal[x][z] = z;
 
            Box.addInternalPoint(v1);
 
            debugFile << "X=" << x << " Z=" << z << " Vec3=("<< v1.X << ", " << v1.Y << ", " << v1.Z << ")\n";
        }
    }
    debugFile.close();
}
 
 
My Grid Render function:

Code: Select all

 
void EDE_GridSceneNode::renderGrid(IVideoDriver* driver, SColor color)
{
    
    driver->setMaterial(this->Material);
    driver->setTransform(ETS_WORLD, matrix4());
 
    for (int z = 0; z < heightInCells + 1; z++)
    {
        driver->drawVertexPrimitiveList(&verticesVertical[z][0], heightInCells, &uIndicesVertical[z][0], heightInCells, EVT_STANDARD, EPT_LINE_STRIP);
        driver->drawVertexPrimitiveList(&verticesHorizontal[z][0], widthInCells, &uIndicesHorizontal[z][0], widthInCells, EVT_STANDARD, EPT_LINE_STRIP);
    }
    
}
 
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Irr1.8c++| How can i project a useable grid on to my Ter

Post by CuteAlien »

Sounds a little bit like a memory problem. How do you declare and allocate your arrays?
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Ultraporing
Posts: 34
Joined: Tue Nov 06, 2007 7:22 pm
Location: Würzburg, Germany

Re: Irr1.8c++| How can i project a useable grid on to my Ter

Post by Ultraporing »

Like this:

Code: Select all

 
 
void EDE_GridSceneNode::setupVertexArrays()
{
    // Setting Up my 2D Grid Array
    //////////////////////////////
 
    verticesVertical = new S3DVertex*[this->heightInCells + 1];
    for (int i = 0; i < this->heightInCells + 1; i++)
    {
        try
        {
            verticesVertical[i] = new S3DVertex[this->widthInCells + 1];
        }
        catch (std::bad_alloc e)
        {
            char buffer[512];
            sprintf_s(buffer, "Out of Memory: %d bytes",  sizeof(S3DVertex)*i);
 
            MessageBoxA(NULL, buffer, "Out of Memory!", MB_OK);
            exit(1);
        }
    }
 
    uIndicesVertical = new u16*[this->heightInCells + 1];
    for (int i = 0; i < this->heightInCells + 1; i++)
    {
        try
        {
            uIndicesVertical[i] = new u16[this->widthInCells + 1];
        }
        catch (std::bad_alloc e)
        {
            char buffer[512];
            sprintf_s(buffer, "Out of Memory: %d bytes",  sizeof(u16)*i);
 
            MessageBoxA(NULL, buffer, "Out of Memory!", MB_OK);
            exit(1);
        }
    }
 
    verticesHorizontal = new S3DVertex*[this->heightInCells + 1];
    for (int i = 0; i < this->heightInCells + 1; i++)
    {
        try
        {
            verticesHorizontal[i] = new S3DVertex[this->widthInCells + 1];
        }
        catch (std::bad_alloc e)
        {
            char buffer[512];
            sprintf_s(buffer, "Out of Memory: %d bytes",  sizeof(S3DVertex)*i);
 
            MessageBoxA(NULL, buffer, "Out of Memory!", MB_OK);
            exit(1);
        }
    }
 
    uIndicesHorizontal = new u16*[this->heightInCells + 1];
    for (int i = 0; i < this->heightInCells + 1; i++)
    {
        try
        {
            uIndicesHorizontal[i] = new u16[this->widthInCells + 1];
        }
        catch (std::bad_alloc e)
        {
            char buffer[512];
            sprintf_s(buffer, "Out of Memory: %d bytes",  sizeof(u16)*i);
 
            MessageBoxA(NULL, buffer, "Out of Memory!", MB_OK);
            exit(1);
        }
    }
}
 
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Irr1.8c++| How can i project a useable grid on to my Ter

Post by CuteAlien »

Allocation looks correct on a quick view (a little unusual to me, I never work with those [][] double arrays, but instead do width*height and allocate a single array usualy. Access is then with (y*width+x ) which is the same as the compiler will do anyway for the [][] arrays but allows to use a single allocation which is way faster).

One thing I notice in the code abobe is that your loop for verticesVertical and verticesHorizontal on filling switches x and z order but on drawing you both times use z for the first. So that might explain your crash when when width and height are different.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Ultraporing
Posts: 34
Joined: Tue Nov 06, 2007 7:22 pm
Location: Würzburg, Germany

Re: Irr1.8c++| How can i project a useable grid on to my Ter

Post by Ultraporing »

I have to draw every line horizontal and vertical by it self. Cant get it to work with your method.

Now got the diffrent sizes to work, but it still goes apeshit under 18 cells :(.

new renderFunction:

Code: Select all

 
void EDE_GridSceneNode::renderGrid(IVideoDriver* driver, SColor color)
{
    
    driver->setMaterial(this->Material);
    driver->setTransform(ETS_WORLD, matrix4());
 
    for (int z = 0; z < heightInCells + 1; z++)
    {
        driver->drawVertexPrimitiveList(&verticesVertical[z][0], widthInCells, &uIndicesVertical[z][0], widthInCells, EVT_STANDARD, EPT_LINE_STRIP);
    }
    
    for (int x = 0; x < widthInCells + 1; x++)
    {
        driver->drawVertexPrimitiveList(&verticesHorizontal[x][0], heightInCells, &uIndicesHorizontal[x][0], heightInCells, EVT_STANDARD, EPT_LINE_STRIP);
    }
}
 
If i get it completely to work i publish the code for everyone to use since you all helped me so much with it :D.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Irr1.8c++| How can i project a useable grid on to my Ter

Post by CuteAlien »

Could be the number of primitives should be 1 (I think that's the 4th parameter). I mean it's just one LINE_STRIP per loop with the length of widthInCells/heightInCells, right? Though I'm not certain why it works at all then or how it interprets any number > 1 for line_strips. Should probably try to draw widthInCells times a line_strip of widthInCells length, but why it doesn't crash if tje vertex given only contains 1 ... not sure. If you used a single array instead you probably wouldn't even need a loop there, but could do something like:

Code: Select all

 
driver->drawVertexPrimitiveList(&verticesVertical[0], widthInCells, &uIndicesVertical[0], heightInCells, EVT_STANDARD, EPT_LINE_STRIP);
 
Not working in your case as your memory is not continuos. But if it where this would draw heightInCells times a linestrip with widthInCells vertices.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply