Editable Terrain Manager [v2.2 released]

A place to show off your latest screenshots and for people to comment on them. Only start a new thread here if you have some nice images to show off!
Post Reply
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

Awesome, changing to Z instead of Y made the terrain appear correctly. :)

I thought the maps had 4 channels, RGBA? 3 channel maps with 4 splats per pass means there will always be a second coverage map using just 1 channel, right? Is there a way to use 4-channel maps?

If I could get 6 splats per pass, then the code would be something more like this, right?

Code: Select all

int numPasses = 1; 
if( numSplattingTextures > 12 ) numPasses = 3; 
else if( numSplattingTextures > 6 ) numPasses = 2; 
[Edit] I'm making a variable called mSplatsPerPass. I guess what I need to know is, following your shaders and your demo, how many splats can I have per pass, and how many splatting textures are used per coverage map? I originally thought it would be 4/map 4/pass, but now it sounds like 3/map 6/pass (on DirectX. 4/pass GL). [\Edit]

Thanks for the help! =)
CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
x 58
Contact:

Post by CABAListic »

The maps have as many channels as you specify them to have in the constructor of the SplattingManager (1 to 4 is allowed).
How many textures you can splat per pass depends entirely upon the capabilities of the graphics hardware, mainly the shader capabilities and the number of texture units. But since I think I've read that OGRE currently does not allow more than 8 texture units, 6 splats per texture is the maximum you'll get done in one pass.

How many coverage maps you need depends entirely on the number of textures per pass you want to splat. For 6 splats, clearly one coverage map is not enough, because it can have at most 4 channels. So you need two, and the obvious choice here is 3 channels per map.
Splatting 5 textures per pass is no good, because you can't align the maps accordingly.
Splatting 4 textures is possible via one 4-channel map, though you could also use 2 2-channel ones, if you like.
(etc.)

Splatting more than 6 textures would require more than 8 texture units, so that's your limit.


BTW. to determine the number of passes needed, this one would be an entirely more flexible approach:

Code: Select all

uint numPasses = (numSplattingTextures-1) / mSplatsPerPass + 1;
User avatar
ahmedali
Gnome
Posts: 302
Joined: Fri Feb 20, 2004 8:52 pm
Location: Lahore, Pakistan

Post by ahmedali »

I have been using ETSM in my WIP Editor.
I just want to say that Im loving using it, keep up the good work. :D And expecting improvements.... :twisted:

The editor is being made using wxPython, but not python-ogre.

Image
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Post by jacmoe »

Nice screenshot! :)
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
x 58
Contact:

Post by CABAListic »

Very cool :)

I'll definitely keep working on ETM, especially now that I'm finally beginning to press forward with my own project for which I wrote it, to begin with. But the majority of the work will likely be small improvements and bug fixes, because for the time being I see no need for additional features (but feel free to make suggestions ;) ).
Next release will probably focus on Linux. I noticed today that the current released version does not compile out of the box under Linux. The necessary fixes are no big deal, but still :)
User avatar
ahmedali
Gnome
Posts: 302
Joined: Fri Feb 20, 2004 8:52 pm
Location: Lahore, Pakistan

Post by ahmedali »

...
Last edited by ahmedali on Mon May 28, 2007 1:35 pm, edited 1 time in total.
User avatar
ahmedali
Gnome
Posts: 302
Joined: Fri Feb 20, 2004 8:52 pm
Location: Lahore, Pakistan

Post by ahmedali »

thanks guys.

@CABAListic
I can understand, I also have my own priorities with my game and editor so im not in any mood to make some improvements, buts heres my personal wish list, nothing urgent, just some ideas.

- A way to add new terrain deform tools by the user. Without either modifiy or derive the terrain manager. Which I intent to do by exposing methods to the terrain manager like "updateTiles()" and others.

- With the possibilty of adding new deforming tools, it will also be possible to implement "sampling" based terrain deforming tools. which will be provide more accuracy to the artist.

new deforming tools (ie FarCry's sandbox editor)
- deform height to absolute value
- smooth/blur and sharpen
- roughing/noise ( which I guess can be made using brush bitmaps )
- smudging tool ( very usefull for creating slopes and other geo features)
Obviously there are dozens of other possilble tools too, but a standard way for creating deform tools by the user will be helpfull.

- Automated creation of shader and terrain material which KungFooMasta is already doing.

- Similar to deforming tools, A way to add new painting/splatting algorithms by the user for implementing custom tools like flood painting, slope & height based painting and fillers etc etc.
CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
x 58
Contact:

Post by CABAListic »

There already is functionality to retrieve and set the absolute heights of vertices via brushes (ET::TerrainManager::get/setHeights). I think that with these you can principally implement any terrain deformation you want. It's really just an interface to the vertex heights which I find convenient for usual cases. I did a sort of smoothing algorithm for the terrain on top of that (it's by no means perfect, but that's due to a weak algorithm rather than the interface :) ).
But if that does not fit your needs or if you find the interface too cumbersome, please elaborate your wishes further :)
User avatar
ahmedali
Gnome
Posts: 302
Joined: Fri Feb 20, 2004 8:52 pm
Location: Lahore, Pakistan

Post by ahmedali »

hmm, I'll look into it.
tgraupmann
Gnoll
Posts: 696
Joined: Sun Feb 20, 2005 5:28 am
Contact:

Post by tgraupmann »

You might want to provide the resources file or mention this needs to be added to resource.cfg

Code: Select all

[ET]
FileSystem=../../media/ET
Pretty neat tho. I think you can give ZBrush and MudBox a run for their money.

I get about 9 frames per second when the edits are happening. You might want to stagger reloading the height map.
CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
x 58
Contact:

Post by CABAListic »

IIRC I included a resources.cfg at least in the release dir, unless I forgot to do so.

Yeah, the edits are kinda performance hungry, but it's kind of difficult for the terrain manager to optimise them further. Most benefits would come from reducing the number of edit steps you do, which is best left in hands of your own app. The demo program just sends them every frame, which I agree is probably not the best approach ;)

The splatting manager, on the other hand, still has potential improvements for its editing capabilities because currently it rewrites the full splatting textures even on partial edits. But I'll need to change the internal structure of the splatting manager to improve on this.

In any case, for me at least performance is quite acceptable when compiling in release mode. After all, terrain editing is probably not what you do all the time in your game :)
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

I've finally gotten around to working on ETM + OgreOpcode. I used your sample code, and everything compiles, but I get a crash when trying to create the shape. I've asked Jacmoe to help me look into this, as I am not so familiar with Opcode's internals.

Crash is inside this line:

Code: Select all

tempTerrainShape->load(vertex_size, index_size, vertices, indices);
Modifed your function a little:

Code: Select all

void setupTerrainCollisionObject()
	{
		Ogre::Vector3 offset = mTerrainInfo->getOffset(); 
		Ogre::Vector3 scale = mTerrainInfo->getScaling(); 

		size_t tWidth = mTerrainInfo->getWidth();
		size_t tHeight = mTerrainInfo->getHeight();

		//Create indices 
		size_t index_size = (tWidth - 1) * (tHeight - 1) * 6; 
		int* indices = new int[index_size]; 
		for( size_t x = 0; x < tWidth - 1; x++) 
		{ 
			for( size_t y=0; y < mTerrainInfo->getHeight() - 1; y++) 
			{ 
				indices[(x+y*(tWidth-1))*6] = (x+1)+(y+1) * tWidth; 
				indices[(x+y*(tWidth-1))*6+1] = (x+1)+y * tWidth; 
				indices[(x+y*(tWidth-1))*6+2] = x+y * tWidth; 

				indices[(x+y*(tWidth-1))*6+3] = (x+1)+(y+1) * tWidth; 
				indices[(x+y*(tWidth-1))*6+4] = x+y * tWidth; 
				indices[(x+y*(tWidth-1))*6+5] = x+(y+1) * tWidth; 
			} 
		} 

		// Create vertices 
		size_t vertex_size = tWidth * tHeight; 
		float* vertices = new float[vertex_size*3]; 
		size_t index = 0; 
		for(size_t z = 0; z < tHeight; z++) 
		{ 
			for(size_t x = 0; x < tWidth; x++) 
			{ 
				Real height = offset.y + mTerrainInfo->at(x, z)*scale.y; 
				vertices[index + 0] = offset.x + x * scale.x; 
				vertices[index + 1] = offset.y + mTerrainInfo->at(x,z)*scale.y; 
				vertices[index + 2] = offset.z + z*scale.z; 
				index += 3; 
			} 
		} 

		// create new shapes here! 
		OgreOpcode::PtrCollisionShape* tempTerrainShape; 
		OgreOpcode::CollisionObject* tempCollObject; 
		String shapeName = "terrainShape"; 
		tempCollObject = mCollisionContext->createObject(shapeName); 
		tempTerrainShape = mCollisionManager->createPtrCollisionShape(shapeName); 
		
		// CRASH NEXT LINE
		tempTerrainShape->load(vertex_size, index_size, vertices, indices); 
		// CRASH PREVIOUS LINE
		
		tempCollObject->setCollClass("terrain"); 
		tempCollObject->setShape(tempTerrainShape); 
		mCollisionContext->addObject(tempCollObject); 
		delete[] vertices; 
		delete[] indices; 
	}
The OgreOpcode forum thread is:
http://ogreconglo.sourceforge.net/phpBB ... =1185#1185

SVN link to my example:
https://ogreconglo.svn.sourceforge.net/ ... Controller

I know you aren't familiar with OgreOpcode either. Hopefully I can find out the problem with more digging, but it would seem that one of these arguements would be the cause of the crash: vertex_size, index_size, vertices, indices.

KungFooMasta
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

So the problem is that I cannot get the indices from the terrain correctly. I do not know what indices are or how to set them, and I can't find any useful examples. :(

Here is a post I made in the help section:
http://www.ogre3d.org/phpBB2/viewtopic. ... 826#227826

If you know the correct way to get the indices for ETM terrain, please let me know. :)

KungFooMasta
CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
x 58
Contact:

Post by CABAListic »

You cannot access ETM's indices, nor do you need to.

Indices are links to vertex positions in a vertex buffer, so to say. They select which vertices to group to triangles or whatever polygon structure.

You should debug the crash to narrow it down. This is a piece of code where you won't find the error just by looking at it (at least that's unlikely) ;)
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Post by jacmoe »

CABAListic wrote:You cannot access ETM's indices, nor do you need to.
If you have the indices, I'd want them! Hand them over! :P

I will look at your code. :wink:
CABAListic wrote:This is a piece of code where you won't find the error just by looking at it (at least that's unlikely) ;)
Let me disagree:
This is in fact one of the few times where looking actually helps find the error(s).
By means of a debug ManualObject. :)
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
x 58
Contact:

Post by CABAListic »

I consider printing results (in any form) as a part of debugging the code ;) You only do that if the error is not obvious from looking at the actual code.

ETM calculates and stores its index buffers in ETIndexHandler.cpp. But those are code sections internal to ETM which I won't expose unless for very, very good reasons. Since a collision shape should have no use for the LOD levels, creating its own index buffer for the collision vertices should not be too much work :)
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

creating its own index buffer for the collision vertices should not be too much work
This is exactly what we're trying to do! :wink:

We want to make sure we are calculating our vertice and index list properly by use of a ManualObject. If the ManualObject displays exactly the same as the terrain, then we know we are close. At the moment, I can derive the vertice list correctly, but for the indices, my list is incorrect.

If I view just the vertices, I can see all the terrain vertices in the correct places. If I throw in indices, the terrain now has polygons, but the result looks like 1/3 strip of terrain with parts folder over each other. :(

Hopefully your code will shed some light.
CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
x 58
Contact:

Post by CABAListic »

Well, suppose, you have some terrain vertices like this:

Code: Select all

*   *   *

*   *   *

*   *   *
You'll need to create triangles like this:

Code: Select all

* - * - *
| \ | \ |
* - * - *
| \ | \ |
* - * - *
So, for every four vertices you need two triangles, whereas each triangle is described by 3 entries in the index buffer indexing 3 vertices in the vertex buffer. Of course, you need to declare your index buffer to actually define triangles, otherwise that won't work.
Anyway, for vertices numbered from left to right, up to down, i. e.:

Code: Select all

0   1   2

3   4   5

6   7   8
your index buffer should be filled similar to this:
[0, 1, 4, 0, 3, 4, 1, 2, 5, 1, 4, 5, ...]
At least that's as far as I remember ;) But that's also what the code fragment I posted for Opcode should do - I didn't invent that code, anyway, I took and modified it from the OgreOpcode demo...
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

That actually makes a lot more sense!

Does Ogre know the correct ordering of vertices?

0 1 2
3 4 5
etc.

It seems that the indice list depends on the ordering of the vertice list, I should check to make sure I obtain vertices from left to right, top to bottom. (very important, right?)

0 ... n
n+1 ... 2n
etc.

where n is the number of vertices in the x (?) direction. This is where I see terrainHeight being used. Height/width use won't matter in a square terrain, but for terrain of differing sizes, I'd probably need to know which direction to use. My guess is X, which would map to terrainWidth. (correct me if I'm wrong!)

Thanks for the help. Your diagrams should be added to comments for Ogre::ManualObject::index(Ogre::uint16 idx); :)

KungFooMasta
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

I see in ETIndexHandler:

Code: Select all

          *pIdx++ = index(i, j);
          *pIdx++ = index(i, j+step);
          *pIdx++ = index(i+step, j);
  
          *pIdx++ = index(i, j+step);
          *pIdx++ = index(i+step, j+step);
          *pIdx++ = index(i+step, j);
Shows a counter clockwise defining of triangles. What does step represent? I would imagine you can increment i by 1, but j should be incremented by numVerticesPerRow.

[Edit]
This is how I derive the ETM vertices:

Code: Select all

Ogre::ManualObject* tManualObject = new ManualObject("terrainMesh"); 
      tManualObject->begin("BaseWhiteNoLighting", RenderOperation::OT_TRIANGLE_LIST); 

      Ogre::Vector3 offset = mTerrainInfo->getOffset(); 
      Ogre::Vector3 scale = mTerrainInfo->getScaling(); 

      size_t tWidth = mTerrainInfo->getWidth(); 
      size_t tHeight = mTerrainInfo->getHeight(); 

      // Create vertices 
      std::vector<Ogre::Vector3> vertices; 
      for(size_t h = 0; h < tHeight; h++) 
      { 
         for(size_t w = 0; w < tWidth; w++) 
         {  
            tManualObject->position( 
               Ogre::Vector3( 
                  offset.x + h * scale.x, 
                  offset.y + mTerrainInfo->at(w,h) * scale.y, 
                  offset.z + w * scale.z 
               ) 
            ); 
         } 
      } 
[/Edit]
CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
x 58
Contact:

Post by CABAListic »

step is used for different LODs, for your usage it will always be 1. i and j are both incremented by 1 (or by step for LOD, but again, this doesn't concern you), since they represent x and y coordinates of a vertex. The index function is a shortcut to get the actual vertex index in the buffer from i and j (actually, j*width + i).
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

You cannot access ETM's indices, nor do you need to.
I think I might have to grab the indices straight from ETM.. I've been debugging for quite a while now and this makes no sense to me. :?


The following picture shows a ManualObject created from a list of vertices and the first 125 (out of 513) rows indexed (Note that I only do 1 of the 2 triangles for every quad, helps visibility):

Image

And now look at just row 126.. (out of 513)

Image

I have spent a long time logging index values and vertices, and nothing looks out of place. The indices are always calculated with the same value, that is, + 0 or 1 in the x direction, and + 0 or 1 * width for indexing a vertex in the next row. (which is 513 in my case)

Looking at the picture, it looks like the vertices I'm indexing are distant from each other, by my log shows all the points to be together.

Code: Select all

20:51:30: Indices
20:51:30: 1315.79 40.6409 368.421
20:51:30: 1315.79 42.0462 371.345
20:51:30: 1318.71 39.7436 368.421
20:51:30: 
20:51:30: 1318.71 39.7436 368.421
20:51:30: 1318.71 40.8606 371.345
20:51:30: 1321.64 38.5534 368.421
This is a sample of my log. Each 3 points represent a triangle. I have narrowed down my log to look at 10 triangles which stretch out across space, which represent some of the triangles seen in the second screenshot. In order for the triangle to stretch, the x coordinates between the 3 points need to be of great distance (triangle stretching from left to right). The logs show nothing like this, all x values are very close to each other.

Am I missing something? Is there a better way to investigate this? When will the hurting stop? :lol:

Is there some major design flaw in allowing access to the indices? In fact, if you did allow methods to retrieve lists of the vertices and indices, OgreOpcode won't have to link to ETM in order to make an ETShape, which would be the best solution IMO. Requiring people to link ETM to OgreOpcode is not very likely, so even if I did produce a solution, I can't really add it to the library. :(

Please consider creating const access to:
- number of vertices
- number of indices
- vertices
- indices

KungFooMasta
CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
x 58
Contact:

Post by CABAListic »

That sort of access would not help you in the least from what I understand from OgreOpcode. You still need to replicate the data, and since the indices and vertices of the ETM internals are divided by terrain tiles and also use LOD and stitching, they are mostly unusable for your purposes, anyway.

I do not wish to make internals public, and for this particular case doubly not so. The vertices are internal to the ET::Tile which itself is completely internal and at no point whatsoever exposed to the public. The indices, however, are shared among tiles and managed by ET::IndexHandler which is again never exposed at any place. It would somehow spoil the encapsulation to do so, and you'd need to include more headers etc. which I've carefully tried to avoid. So I hope that explains a bit my reluctance ;)

As I said, it wouldn't help you much, anyway. If your data at the moment is correct, then you will not get any better result from ETM's data. If it's not, then fix it :D
BTW, ETM's internal representation of the terrain is in most parts identical to that of TSM (except structured differently). If you got it working with TSM, then the same approach must work with ETM, also.
CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
x 58
Contact:

Post by CABAListic »

And now that I think of it, there's actually one other serious technical issue which speaks against giving that kind of read access: Namely, the vertex and index buffers are defined such that they are specifically NOT meant for reading. So it's a triple no-go or so ;)
Should I find some time, I'll look at Opcode. But I just can't spare the time at the moment.
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Post by jacmoe »

Dont worry! We'll think of something!
Thanks for explaining.
I will go through the code today.
And I am positive that we can get this working, especially since we just got TSM working. :)

I don't think we would want that data: we need to deep copy it, and we need to stay generic.
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
Post Reply