ManualObject problem

APXEOLOG

03-02-2010 12:16:47

hi i have some troubles with this class. i can draw lines but triangles dont drawing. give me example of textured square based on OT_TRINGLE_STRIP pls

WarehouseJim

04-02-2010 10:04:24

http://www.ogre3d.org/addonforums/viewtopic.php?f=8&t=11747 has a discussion of using ManualObject to make 3D shapes, in which I posted some code samples. However, they use a different OT_TRIANGLE_LIST not OT_TRINGLE_STRIP. http://www.ogre3d.org/addonforums/viewtopic.php?f=8&t=11763 might also be useful.

If you really want to use OT_TRIANGLE_STRIP, then http://en.wikipedia.org/wiki/Polygon_mesh will probably be useful for explaining how to add vertices correctly. The API documentation might also provide some hints.

Have a look over that stuff, and if you're still stuck, I'm happy to help out some more.

APXEOLOG

04-02-2010 14:19:15

Ok ty. Now i'm explain my new problem. I'm making a terrain. I use ManualObject because i have maps in specific format. it has cells 64*64 units, each corner have height and this cell has a texture. So i draw this map, but it really slow in rendering. I think i have about 5-10 fps, when on standart terrain i have great number of fps. Why it is so slow and how make it faster? In my map i have 144*144 cells. (41472 triangles)
for (int i = 0; i < _map_height; i++)
{
for (int j = 0; j < _map_width; j++)
{

moTerrain.Begin(tile_name[i, j], RenderOperation.OperationTypes.OT_TRIANGLE_LIST);
moTerrain.Position(64.0f * i, hm2[i, j], 64.0f * j);
moTerrain.TextureCoord(1.0f, 1.0f);
moTerrain.Position(64.0f * i, hm2[i, j + 1], 64.0f * (j + 1));
moTerrain.TextureCoord(1.0f, 0.0f);
moTerrain.Position(64.0f * (i + 1), hm2[i + 1, j], 64.0f * j);
moTerrain.TextureCoord(0.0f, 1.0f);
moTerrain.Position(64.0f * (i + 1), hm2[i + 1, j + 1], 64.0f * (j + 1));
moTerrain.TextureCoord(0.0f, 0.0f);
moTerrain.Position(64.0f * (i + 1), hm2[i + 1, j], 64.0f * j);
moTerrain.TextureCoord(0.0f, 1.0f);
moTerrain.Position(64.0f * i, hm2[i, j + 1], 64.0f * (j + 1));
moTerrain.TextureCoord(1.0f, 0.0f);
moTerrain.End();
}
}


sceneMgr.RootSceneNode.AttachObject(moTerrain);

Also need explanation of using ManualObject.SetMaterial() - can't understand what is 'subindex'
And how to use indexed geometry in my case (i think it would be faster)

WarehouseJim

04-02-2010 23:03:13

My initial thoughts about your poor frame rate are that your batch count is high. This happens if you have too many moveable objects in the scene and leads to you program being CPU limited. To get around this, you really want to try to create a very large mesh with as few materials as possible. If you have several meshes with the same material, then you can use http://www.ogre3d.org/docs/api/html/classOgre_1_1StaticGeometry.html to group them together, assuming they aren't going to move.

If I have understood your post correctly, what you should do is put all your textures in one big image (or if you're feeling more fancy, I think you could use up to 8 in the same material). In my experience, I think you are limited to a maximum of about 8192x8192 pixels per texture. When you create your mesh, you should have all of the parts created in the same manualObject.Begin()..... manualObject.End() part, and use texture coordinates appropriately to link the vertices with the sub-parts of your large texture. When you have several Begin()...End() parts, it creates a sub-mesh which, as I understand it, will lead to essentially another batch being required.

As for indexed geometry, which I think is the same as instancing, I don't think that it will be the solution to your problem. My ten seconds of google suggests it's what I'm actually looking into doing for my project at the moment. If you have lots of identical objects e.g. hundreds of boxes, then you re-use one mesh on the graphics card (rather than duplicating it before sending to the graphics card). I expect you can't use lots of different materials here efficiently. Given your mesh is 41472, which for a modern graphics card should be no issue handle as a complete mesh, I would go with a single mesh and a single material.

I'm not too sure about ManualObject.SetMaterial's subindex, but I expect it might be to do with the index of each Begin()... End() part of when you are creating you mesh.

APXEOLOG

05-02-2010 06:09:14

Ty! Indexed geometry and single Begin()-End() block make my rendering much faster, but when i'm trying to make static geometry i have error on build().
uint offset = 0;
for (int i = 0; i < Map.map_height; i++)
{
for (int j = 0; j < Map.map_width; j++)
{
moTerrain.Position(64.0f * i, Map.heights_map[i, j], 64.0f * j);
moTerrain.TextureCoord(0.0f, 0.0f);

moTerrain.Position(64.0f * i, Map.heights_map[i, j + 1], 64.0f * (j + 1));
moTerrain.TextureCoord(1.0f, 0.0f);

moTerrain.Position(64.0f * (i + 1), Map.heights_map[i + 1, j], 64.0f * j);
moTerrain.TextureCoord(0.0f, 1.0f);

moTerrain.Position(64.0f * (i + 1), Map.heights_map[i + 1, j + 1], 64.0f * (j + 1));
moTerrain.TextureCoord(1.0f, 1.0f);
/*
moTerrain.Position(64.0f * (i + 1), Map.heights_map[i + 1, j], 64.0f * j);
moTerrain.TextureCoord(0.0f, 1.0f);
moTerrain.Position(64.0f * i, Map.heights_map[i, j + 1], 64.0f * (j + 1));
moTerrain.TextureCoord(1.0f, 0.0f);
*/

moTerrain.Triangle((ushort)offset, (ushort)(offset + 1), (ushort)(offset + 2));
moTerrain.Triangle((ushort)(offset + 3), (ushort)(offset + 2), (ushort)(offset + 1));
offset += 4;
}
}
moTerrain.End();

moTerrain.ConvertToMesh("ter_mesh");

Entity ent = sceneMgr.CreateEntity("newter", "ter_mesh");

StaticGeometry stTer = sceneMgr.CreateStaticGeometry("ter2");
stTer.AddEntity(ent, Vector3.ZERO);
stTer.CastShadows = false;

stTer.Build(); // Error here :(

WarehouseJim

05-02-2010 09:58:24

Please post the error message you get.

I use StaticGeometry by adding an entities to a SceneNode and then doing staticGeometry.AddSceneNode(..). If you do this, you need to be careful that you don't have the SceneNode visible in the scene. The best way to go about this is to never attach it to the scene graph i.e. use SceneNode staticNode = sceneManager.CreateSceneNode(); not SceneNode staticNode = sceneManager.RootSceneNode.CreateChildSceneNode();

You probably won't get much better performance by using StaticGeometry if you now only have one mesh. Let me know whether it does improve your frame rate.

APXEOLOG

05-02-2010 14:30:11

I still have great troubles... i have no idea how to link different materials to quads. Now i can do it only with repeating of Begin()-End() and in this case when i'm trying to convert it to Entity my program freeze. If i make single-texture and single-block ManualObject, i convert it to mesh, then to entity, ams when i'm doing StaticGeometry.Build() i have "OGRE EXCEPTION(7:InternalErrorException): Somehow we couldn't fit the requested geometry even in a brand new GeometryBucket!! Must be a bug, please report. in StaticGeometry::MaterialBucket::assign at ..\\src\\OgreStaticGeometry.cpp (line 1262)"
So i dont know what to do....the only solution i see - merge all my quad's tiles in one material and work with it without static geometry. But i dont like this variant... =(

APXEOLOG

05-02-2010 17:12:04

About StaticGeometry: when i make all my map with same height (0.0f) - it's works. but whem each vertex have own height - it's crashed...

WarehouseJim

08-02-2010 10:14:08

Ignore the static geometry for the moment, I don't think that it's relevant to your current problem.

How large are the textures for your terrain? If they are only 10x10 pixels, then you could create one large texture out of them all which would be 1440x1440 pixels. If you do this, then when you create each cell in manual object, give the four corners of your quad texture coordinates (i/144,j/144); ((i+1)/144, j/144); (i/144, (j+1)/144); ( (i+1)/144, (j+1)/144) where i,j are integer indexes of vertices in you terrain - i.e. only reference one small part of your texture (assuming the texture is set up to have texture (U,V) coordinates going from 0-1) for each quad of your texture. If you are repeating textures, then you can just adjust the texture coordinates to repeatedly look at the same part of the combined texture.

If the combined texture is bigger than say 8192x8192, then you probably need to use a different method. Either split the terrain into 8192x8192 or smaller blocks, or maybe use some other method. I don't have any experience with large detailed terrains, but there are special scene managers to help with it. See http://www.ogre3d.org/wiki/index.php/SceneManagersFAQ and then look around for stuff related to that. There may also be some info in the tutorials (possibly look at non-Mogre tutorials).

APXEOLOG

19-02-2010 14:08:11

I done single texture as you wrote. But i still have some 'lags' when move my camera around map. I have fixed angle but when i change position of camera (and position on viewpoint) i have some rotating of map, which lasts some miliseconds. (Same effect was when i build many quads, each with own Begin() End(), but it lasts for a second)

WarehouseJim

22-02-2010 10:54:44

As in you have high FPS when not moving the camera, and then you move to view a different part and it stutters? If so, I get the same (I've only just been implementing something with a very large texture), and I don't know why it is. If nobody gives an answer here, try the main Ogre forum and let us know what the result is. I'm guessing it's something to do with how Ogre moves data between RAM (or even your hard disk) and the graphics card.