How use terrain in irrlicht? Have you any example?
How use terrain in irrlicht? Have you any example?
I cannot find example or explanation, how create terrin in irrlicht, please give me any source code, thank you.
I too would like a nice simple tutorial to work from :)
-= Want your C code to control real life robots? www.users.on.net/~symes =-
Code: Select all
video::IImage* heightmap1 = 0;
heightmap1=driver->createImageFromFile("media\\ext\\t3.bmp");
video::IImage* texture1 = 0;
texture1=driver->createImageFromFile("media\\ext\\t2.jpg");
scene::IAnimatedMesh* terr1 = smgr->addTerrainMesh ("1",texture1,heightmap1,core::dimension2d<f32>(90.0f, 90.0f),200.0f );
scene::ISceneNode* q3node3 = 0;
q3node3 = smgr->addMeshSceneNode(terr1->getMesh(0));
q3node3->setPosition(core::vector3df(-1900,-44.7,-1800));
q3node3->setMaterialFlag(video::EMF_LIGHTING, false);
selector = smgr->createTriangleSelector(terr1->getMesh(0), q3node3);
metaSelector->addTriangleSelector(selector);
selector->drop();
-
- Posts: 292
- Joined: Sun Mar 14, 2004 5:28 pm
- Location: Germany
- Contact:
Thats not right! I use a 512x512 terrain and it runs with about 50fps. But it needs very long to loadpuh wrote:t3.bmp MUST BE 64x64, else the terrain will be building TOO LONG and collision will be SLOWCode: Select all
video::IImage* heightmap1 = 0; heightmap1=driver->createImageFromFile("media\\ext\\t3.bmp"); video::IImage* texture1 = 0; texture1=driver->createImageFromFile("media\\ext\\t2.jpg"); scene::IAnimatedMesh* terr1 = smgr->addTerrainMesh ("1",texture1,heightmap1,core::dimension2d<f32>(90.0f, 90.0f),200.0f ); scene::ISceneNode* q3node3 = 0; q3node3 = smgr->addMeshSceneNode(terr1->getMesh(0)); q3node3->setPosition(core::vector3df(-1900,-44.7,-1800)); q3node3->setMaterialFlag(video::EMF_LIGHTING, false); selector = smgr->createTriangleSelector(terr1->getMesh(0), q3node3); metaSelector->addTriangleSelector(selector); selector->drop();
http://www.games-forge.de - Die Community für Nachwuchsprogrammierer
Thanks guys for the response
-= Want your C code to control real life robots? www.users.on.net/~symes =-
I got my terrain to run at about 900 fps because I controlled what triangles were being added to the triangleselector each frame. I simply got a pointer to the list of triangles in the triangleselector, and updated them with only a few triangles that were directly around the player. This way I'm only doing collision tests on about 8 - 16 polygons each frame, instead of about 1,000 or so :-p
You should try this instead and your terrain will run a lot faster.
You should try this instead and your terrain will run a lot faster.
-
- Posts: 292
- Joined: Sun Mar 14, 2004 5:28 pm
- Location: Germany
- Contact:
@soconne:
Are you using the ICollisionResponseAnimator?
Are you using the ICollisionResponseAnimator?
http://www.games-forge.de - Die Community für Nachwuchsprogrammierer
Here's how I did my collision. There's a lot of source code, so I tried to narrow it down to the important parts.
Here is my main draw loop
CTriangleSelector *selector=0;
selector = (CTriangleSelector *)smgr->createTriangleSelector(landscape->GetCollisionMesh(camera->getPosition().X, camera->getPosition().Z), landscape);
landscape->setTriangleSelector(selector);
selector->drop();
scene::IMetaTriangleSelector *mselector=0;
mselector = smgr->createMetaTriangleSelector();
mselector->addTriangleSelector(selector);
anim = (CSceneNodeAnimatorCollisionResponse *)smgr->createCollisionResponseAnimator(mselector,
camera, core::vector3df(1,1,1), core::vector3df(0,0,0), 0.0,
core::vector3df(0,1,0), .0005);
camera->addAnimator(anim);
scene::IMesh *collMesh;
while(device->run() && !quit)
{
collMesh = landscape->GetCollisionMesh(camera->getPosition().X, camera->getPosition().Z);
if(collMesh) {
selector = (CTriangleSelector *)smgr->createTriangleSelector(collMesh, landscape);
mselector->removeAllTriangleSelectors();
mselector->addTriangleSelector(selector);
anim->setWorld(mselector);
}
driver->beginScene(true, true, video::SColor(0,200,200,200));
smgr->drawAll();
guienv->drawAll();
driver->endScene();
}
Then here's the code that comes from the landscape->GetCollisionMesh(...)
scene::IMesh* GetCollisionMesh(f32 X, f32 Z)
{
static int lastcol=-1, lastrow=-1;
//get row and col of terrain where collision will occur
int col = floor( ( (X+(Width/2.0)) / (float)Width) * Cols);
int row = floor( ( (Z+(Length/2.0)) / (float)Length) * Rows);
if(lastcol == col && lastrow == row) return NULL;
lastcol = col;
lastrow = row;
//get pointer to mesh data
scene::SMeshBufferLightMap* tempBuffer = (scene::SMeshBufferLightMap* )Meshes[0].getMeshBuffer(0);
collBuff->Vertices.clear();
collBuff->Indices.clear();
int index=0;
for(int j=row-1; j <= row + 1; j++)
{
if(j < 0 || j >= Rows-1) continue;
for(int i=col-1; i <= col + 1; i++)
{
if(i < 0 || i >= Cols-1) continue;
collBuff->Vertices.push_back(tempBuffer->Vertices[j*Cols+i]);
collBuff->Vertices.push_back(tempBuffer->Vertices[(j+1)*Cols+i]);
collBuff->Vertices.push_back(tempBuffer->Vertices[(j+1)*Cols+i+1]);
collBuff->Vertices.push_back(tempBuffer->Vertices[j*Cols+i+1]);
collBuff->Indices.push_back(index);
collBuff->Indices.push_back(index+1);
collBuff->Indices.push_back(index+2);
collBuff->Indices.push_back(index);
collBuff->Indices.push_back(index+2);
collBuff->Indices.push_back(index+3);
index+=4;
}
}
//collMesh->MeshBuffers[0] = collBuff;
return collMesh;
}
Okay and now for an explanation. I basically just initialize a single triangleselector before my main loop to set the 'exact' size it will be for the remainder of the program, meaning 18 triangles if you look at the GetCollisionMesh functions. And during the main loop, I simply call GetCollisionMesh to change or update those triangles depending on where I am on the terrain. I also make sure that if the position hasn't moved enough from the last position, then no update is made, this makes it run faster.
Then the MetaTriangleSelector I declared above is then updated, but first all selectors are removed first, then the one I got from my landscape is added to it, then the CollisionResponseAnimator is then set to use this new MetaTriangleSelector variable.
I know it seems like a lot, but its very straightforward once you understand it. It took me forever to figure out how to do this without getting memory errors and my program crashing, ect....
Also, if anybody sees any memory leeks, please let me know. I think there might be, but I'm still unsure of how Irrlicht releases memory, ect...
Oh, and the collMesh variable inside of the landscape->GetCollisionMesh is declared within my terrain class so that it is only declared once and reused over and over, this speeds it up a lot also.
And its declared like so...
scene::SMeshBufferLightMap *collBuff;
Anyway, if anybody can think of a way to speed this up let me know, but like I said before when I use this method for collision with my terrain, I get about 900 fps, and just using the regular old send everything to an Octree method, I get about 150-200fps. And I'm also running this on a P4 2.8Ghz HT, 1GB PC3200, Radeon 9800 Pro. So don't expect to get the exact same framerate, but a lot better than before.
Here is my main draw loop
CTriangleSelector *selector=0;
selector = (CTriangleSelector *)smgr->createTriangleSelector(landscape->GetCollisionMesh(camera->getPosition().X, camera->getPosition().Z), landscape);
landscape->setTriangleSelector(selector);
selector->drop();
scene::IMetaTriangleSelector *mselector=0;
mselector = smgr->createMetaTriangleSelector();
mselector->addTriangleSelector(selector);
anim = (CSceneNodeAnimatorCollisionResponse *)smgr->createCollisionResponseAnimator(mselector,
camera, core::vector3df(1,1,1), core::vector3df(0,0,0), 0.0,
core::vector3df(0,1,0), .0005);
camera->addAnimator(anim);
scene::IMesh *collMesh;
while(device->run() && !quit)
{
collMesh = landscape->GetCollisionMesh(camera->getPosition().X, camera->getPosition().Z);
if(collMesh) {
selector = (CTriangleSelector *)smgr->createTriangleSelector(collMesh, landscape);
mselector->removeAllTriangleSelectors();
mselector->addTriangleSelector(selector);
anim->setWorld(mselector);
}
driver->beginScene(true, true, video::SColor(0,200,200,200));
smgr->drawAll();
guienv->drawAll();
driver->endScene();
}
Then here's the code that comes from the landscape->GetCollisionMesh(...)
scene::IMesh* GetCollisionMesh(f32 X, f32 Z)
{
static int lastcol=-1, lastrow=-1;
//get row and col of terrain where collision will occur
int col = floor( ( (X+(Width/2.0)) / (float)Width) * Cols);
int row = floor( ( (Z+(Length/2.0)) / (float)Length) * Rows);
if(lastcol == col && lastrow == row) return NULL;
lastcol = col;
lastrow = row;
//get pointer to mesh data
scene::SMeshBufferLightMap* tempBuffer = (scene::SMeshBufferLightMap* )Meshes[0].getMeshBuffer(0);
collBuff->Vertices.clear();
collBuff->Indices.clear();
int index=0;
for(int j=row-1; j <= row + 1; j++)
{
if(j < 0 || j >= Rows-1) continue;
for(int i=col-1; i <= col + 1; i++)
{
if(i < 0 || i >= Cols-1) continue;
collBuff->Vertices.push_back(tempBuffer->Vertices[j*Cols+i]);
collBuff->Vertices.push_back(tempBuffer->Vertices[(j+1)*Cols+i]);
collBuff->Vertices.push_back(tempBuffer->Vertices[(j+1)*Cols+i+1]);
collBuff->Vertices.push_back(tempBuffer->Vertices[j*Cols+i+1]);
collBuff->Indices.push_back(index);
collBuff->Indices.push_back(index+1);
collBuff->Indices.push_back(index+2);
collBuff->Indices.push_back(index);
collBuff->Indices.push_back(index+2);
collBuff->Indices.push_back(index+3);
index+=4;
}
}
//collMesh->MeshBuffers[0] = collBuff;
return collMesh;
}
Okay and now for an explanation. I basically just initialize a single triangleselector before my main loop to set the 'exact' size it will be for the remainder of the program, meaning 18 triangles if you look at the GetCollisionMesh functions. And during the main loop, I simply call GetCollisionMesh to change or update those triangles depending on where I am on the terrain. I also make sure that if the position hasn't moved enough from the last position, then no update is made, this makes it run faster.
Then the MetaTriangleSelector I declared above is then updated, but first all selectors are removed first, then the one I got from my landscape is added to it, then the CollisionResponseAnimator is then set to use this new MetaTriangleSelector variable.
I know it seems like a lot, but its very straightforward once you understand it. It took me forever to figure out how to do this without getting memory errors and my program crashing, ect....
Also, if anybody sees any memory leeks, please let me know. I think there might be, but I'm still unsure of how Irrlicht releases memory, ect...
Oh, and the collMesh variable inside of the landscape->GetCollisionMesh is declared within my terrain class so that it is only declared once and reused over and over, this speeds it up a lot also.
And its declared like so...
scene::SMeshBufferLightMap *collBuff;
Anyway, if anybody can think of a way to speed this up let me know, but like I said before when I use this method for collision with my terrain, I get about 900 fps, and just using the regular old send everything to an Octree method, I get about 150-200fps. And I'm also running this on a P4 2.8Ghz HT, 1GB PC3200, Radeon 9800 Pro. So don't expect to get the exact same framerate, but a lot better than before.
-
- Posts: 37
- Joined: Fri Jul 02, 2004 5:36 pm
- Location: Albany, NY
- Contact:
I'm having some issues implementing this, and I think they mostly stem from irrlicht telling my that the scene::C________ (ie. CSceneNodeAnimator) functions are not a part of scene:: - even though they appear as members in the list.
I've tried switching these to I__________ functions, and that results in a bunch of other stuff not working - the members of C__________ not being members of I_________
Any ideas why irrlicht might be sassing me about scene::C______'s?
Also, I was wondering if there's any way you could post a link to your main.cpp - a further problem for me that's coming up is that my camera is a 3rd person, tied to a mesh node - the animators for both the map and the model are 3rd person, and that conflicts with your camera animators. I'd like to try to merge the two different directions - so that I can have a third person view with terrain maps.
I've tried switching these to I__________ functions, and that results in a bunch of other stuff not working - the members of C__________ not being members of I_________
Any ideas why irrlicht might be sassing me about scene::C______'s?
Also, I was wondering if there's any way you could post a link to your main.cpp - a further problem for me that's coming up is that my camera is a 3rd person, tied to a mesh node - the animators for both the map and the model are 3rd person, and that conflicts with your camera animators. I'd like to try to merge the two different directions - so that I can have a third person view with terrain maps.
------------------------------------------
A monkey poured coffee in my boots.
------------------------------------------
A monkey poured coffee in my boots.
------------------------------------------
Yeah sure, here's the file
http://cs.selu.edu/~soconnell/MyIrrlicht.cpp
Don't mind all the other code for the terrain initialization, the important stuff is after that. Let me know if you have any problems or questions.
http://cs.selu.edu/~soconnell/MyIrrlicht.cpp
Don't mind all the other code for the terrain initialization, the important stuff is after that. Let me know if you have any problems or questions.
-
- Posts: 37
- Joined: Fri Jul 02, 2004 5:36 pm
- Location: Albany, NY
- Contact:
Well, I don't really think I can merge your code into mine - there's too many unobvious things to me (I know about 40% of the code that I should to be doing all the basic programming myself ^_^" I love opensource... )
However, I have come up with an extremely simple optimization for the initial code - this brought me from @27 fps (!) up to @250 (much better) with a bigger map, higher raising, and better looking to boot.
It's really a question of your process, and your parameters.
To start with, make your terrain like this - pick your terrain size in a multiple of 2 (I've used 256x256), and make your terrain height bitmap with that.
Now paint over it to make the terrain texture jpg. Be as precise as you want.
Save the jpg as 256x256 (or whatever you picked), and go ahead and scale the height bmp to 32x32 and save it. (Trust me, I'm a doctor, I do this for a living.)
now in the parameters, the ones given in the code example are this
Go ahead and change
(90.0f, 90.0f),200.0f );
to
(JPG_Width.0f, JPG_Height.0f),Multiple_of_2.0f);
I like 512...
You've lost some precision in the height department with this, but that's not such a bad thing - nature is usually a bit more rounded than it is angular. I suggest making the map with an airbrush tool to accompany this concept, as the blends come naturally from the process. If you desperately wanted a cliff, take a pixel tool and edit the 32x32 manually.
However, the texture is nice and crisp and clean - just like mom used to make. You could even use an aerial photo, so long as it's the size of your terrain, or vice-versa, and stretching will be kept to a minimum.
However, I have come up with an extremely simple optimization for the initial code - this brought me from @27 fps (!) up to @250 (much better) with a bigger map, higher raising, and better looking to boot.
It's really a question of your process, and your parameters.
To start with, make your terrain like this - pick your terrain size in a multiple of 2 (I've used 256x256), and make your terrain height bitmap with that.
Now paint over it to make the terrain texture jpg. Be as precise as you want.
Save the jpg as 256x256 (or whatever you picked), and go ahead and scale the height bmp to 32x32 and save it. (Trust me, I'm a doctor, I do this for a living.)
now in the parameters, the ones given in the code example are this
Code: Select all
irr::scene::IAnimatedMesh* terr1 = smgr->addTerrainMesh ("1",texture1,heightmap1,irr::core::dimension2d<irr::f32>(90.0f, 90.0f),200.0f );
(90.0f, 90.0f),200.0f );
to
(JPG_Width.0f, JPG_Height.0f),Multiple_of_2.0f);
I like 512...
You've lost some precision in the height department with this, but that's not such a bad thing - nature is usually a bit more rounded than it is angular. I suggest making the map with an airbrush tool to accompany this concept, as the blends come naturally from the process. If you desperately wanted a cliff, take a pixel tool and edit the 32x32 manually.
However, the texture is nice and crisp and clean - just like mom used to make. You could even use an aerial photo, so long as it's the size of your terrain, or vice-versa, and stretching will be kept to a minimum.
------------------------------------------
A monkey poured coffee in my boots.
------------------------------------------
A monkey poured coffee in my boots.
------------------------------------------