trimeshes and materials

vicviper
Posts: 21
Joined: Thu Jun 01, 2006 9:55 pm

trimeshes and materials

Post by vicviper »

In the last project I did (a golf simulation game), I used a custom collision detection library I made specifically for that game, the field was stored as a BVH triangle mesh, but also, for every triangle, I included a reference to a physical properties table. That was important because in a golf game, different surfaces matter a lot in the game, like the green area versus a sand bunker area.

I noticed that right now bullet only support a single physical properties set for the whole trimesh. I don't need that feature right now, but, I was wondering what you would propose in case someone would need it.

Thanks in advance

Vic
Last edited by vicviper on Fri Aug 11, 2006 11:57 am, edited 1 time in total.
Eltharyon
Posts: 13
Joined: Wed Jun 07, 2006 12:55 pm

Post by Eltharyon »

materials per triangle are a requested feature and can be found on the TODO list here: http://www.continuousphysics.com/mediaw ... BulletTodo

no word as to when these will be done as far as I'm aware of, but they should be done eventually ;)
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Post by Erwin Coumans »

There is already some preparations inside the BVH that identifies the triangle (by index/part number). This will be used for your request.

It has been added to the new google code repository, see Issues in
http://code.google.com/p/bullet/

Either 'soon' or 'when its done' ;-)

Thanks,
Erwin
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Post by Erwin Coumans »

Bullet now supports per-trangle materials.

Per-triangle friction/restitution requires a ContactAddedCallback implementation. This callback can calculate and overwrite the friction and/or restitution in the contact point.
Each CollisionObject that needs this material-callback has to set the collisionFlag to ccdObjectCi.m_collisionFlags = CollisionObject::customMaterialCallback;
See ConcaveDemo for an example, in particular CustomMaterialCombinerCallback.

Download 1.8d source zip

This needs testing.
Thanks,
Erwin
vicviper
Posts: 21
Joined: Thu Jun 01, 2006 9:55 pm

Post by vicviper »

Hi, I've been reading the triangle mesh interface code, I had no time yet to test something with it, but I'm beginning to find it quite complex to follow.

I would like to propose an alternative method to load a triangle mesh into Bullet, to see what people thinks:

bvhTriangleShape* myShape = new bvhTriangleShape;

TriangleGeometry* myGeom = myShape->LockGeometry();

myGeom->AddMaterial("Sand",restitution,friction);
myGeom->AddMaterial("Rock",restitution,friction);
myGeom->AddMaterial("Wood",restitution,friction);
myGeom->AddMaterial("HotLava",restitution,friction);
.
.

myGeom->AddVertex(x,y,z);
myGeom->AddVertex(x,y,z);
.
.

myGeom->AddTriangle(v1,v2,v3,"Sand");
myGeom->AddTriangle(v1,v2,v3,"Sand");
myGeom->AddTriangle(v1,v2,v3,"HotLava");
.
.
.

myShape->UnlockGeometry(myGeom);

Basically "TriangleGeometry" class would store a raw list of materials, vertices and triangles. When you do the "Lock", any hierarchy previously stored in myShape is deleted, and when we call "Unlock", the hierarchy for the given geometry is computed and optimized (this mechanism also gives the hability to modify the given geometry if needed, by just locking/modifying/unlocking again)


Of course, this method means that the geometry would be stored internally by Bullet, and it would not share the renderable vertex and index buffers of the graphics interface.

About the External, shared geometry vs internally stored geometry, I know a good amount of people arround here preffer shared geometry, because it saves memory, but I would like you to consider this:

In a real application, where we have a game level with 20.000 triangles and 300 different materials, it is more than possible than different vertex formats are required. Also, for lightning calculations, it is common to split the levels per rooms, or even less, so, a level is actually comprised by a lot of tiny vertex/index buffers, not a large one. Just this makes impossible to share the geometry with a physics engine.

Also, the "saving memory" argument may not be true either: Any modern rendering engine uses index/vertex buffers to store geometry, once they're unlocked after being filled, they can't be shared anymore by any API other than the graphics system itself. Actually, we cannot be sure if the buffer still exists in memory, but in the graphics card VRAM.

The only time when we can use a vertex/index buffer is at load time, when we're filling it, but after we unlock it, it will become invalid for us to continue using it.

The only type of geometry that would be bad to store in the physics engine would be a terrain heightmap. For heightmaps, game engines usually provide an interface from which the graphics engine "sucks" triangles on demand, a Physics engine should provide something like that, so the large terrain heightmap can be shared with the graphics engine and the physics engine.

maybe a "TerrainShape" ?

Please discuss!

Vic
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Post by Erwin Coumans »

It's a good idea to provide a user-friendly high-level 'MultimaterialTriangleMeshShape' class that manages all the complexity. Can you help with such class, or do you want me to provide an example?

Currently Bullet has a multi-layer API, mid-level C++ API, and low-level C++ API. Once things are in place, I intend to add a high-level C-API tha t makes it all very easy. Once you want more control, you go C++.
This requires documentation too, which requires time on my side, which is a sparce resource :-)

Bullet is a general purpose physics engine, so it leaves the decision up to the developer. He can share graphics or duplicate. Notice that Bullet can directly re-use many small vertex/index buffers, each indicated by partId/triangleId. Internally there is a lock/unock mechanism that can be overridden to call the graphics API's unlock to get data back to main memory.
The only type of geometry that would be bad to store in the physics engine would be a terrain heightmap. For heightmaps, game engines usually provide an interface from which the graphics engine "sucks" triangles on demand, a Physics engine should provide something like that, so the large terrain heightmap can be shared with the graphics engine and the physics engine.

maybe a "TerrainShape" ?
Bullet allows for creating triangles "on demand", given an axis aligned bounding box. Someone already made some heightfield tutorial.

http://www.continuousphysics.com/mediaw ... ight_Field

Thanks for the feedback,
Erwin
vicviper
Posts: 21
Joined: Thu Jun 01, 2006 9:55 pm

Post by vicviper »

Erwin Coumans wrote:It's a good idea to provide a user-friendly high-level 'MultimaterialTriangleMeshShape' class that manages all the complexity. Can you help with such class, or do you want me to provide an example?
Yeah, I would like to help you with that, this would allow me to integrate it easier. Just give me some guidelines on where to catch the thread and I'll look something. The idea would be to do something in the lines of the sample in my first post.
Bullet is a general purpose physics engine, so it leaves the decision up to the developer. He can share graphics or duplicate. Notice that Bullet can directly re-use many small vertex/index buffers, each indicated by partId/triangleId. Internally there is a lock/unock mechanism that can be overridden to call the graphics API's unlock to get data back to main memory.
Well, from my experience on graphics engines, specially DirectX, locking/unlocking a buffer is a very big No-No. once a buffer is filled and locked, nobody garantees you that the graphics API does not do "things" to the buffer, like, compressing with some weird algo, or simply delete it after uploading it to graphics card VRAM.

When you do a "lock" into a vertex/index buffer to read from it, what happens is not only that the API gives you a pointer to the raw data, it can also take its time decompressing the buffer to a "readable" mode, or worse, downloading it from graphics vram. The worst case scenario is that if you lock a buffer that the graphics card is currently using for rendering, the whole system will stall, waiting for the current primitive batch to finish rendering, before returning a valid pointer (and before downloading from vram, or decompressing, etc)

I'm not sure about OpenGL, but DirectX specifically requests that, at render time, Lock/Unlock operations over a vertex/index for reading data should be kept to a bare minimum, but, given that this is a driver issue, I bet OpenGL also suffers from this.

As of today, when you create a vertex/index buffer in Managed Mode (aka, safe mode) in DirectX, DirectX keeps a copy of the buffer in system Ram, and then uploads it to graphics VRAM, only when there's more buffers than VRAM availiable, the driver uploads the buffer to VRAM and deletes old buffers on demand (and at that time, the buffers should be in unlocked mode), but generally, the buffers are lockable quite fast, because it will just give you the pointer to the copy of the buffer in RAM, but only because this is the behavior of today APIs and Drivers. This has lead a lot of people to think that the buffers are there to lock and read data easily.

But, Nobody guarantees you that in the next version of DirectX, OpenGL, or on your next driver update, the location and performance of buffer lock/unlock changes dramatically.

Another really big reason not to use vertex/index buffers for reading data is that, for all next generation systems, it is expected to do projects using multithreading, that means, running the graphics engine in one thread, and the physics/AI in another thread. The problem here will be that, if the physics engine locks a buffer to read data and perform some collision detection, the graphics engine will stall, waiting for the buffer to be unlocked. Or, if the graphics engine is rendering using that buffer, and the physics engine needs its data, the physics engine will stall, waiting to be able to lock the buffer.

In other words: a good design should lock/unlock buffers at load time, the only lockable buffers at render time should be Dynamic, Write_Only buffers (particles, morphs, animatables, etc)
The only type of geometry that would be bad to store in the physics engine would be a terrain heightmap. For heightmaps, game engines usually provide an interface from which the graphics engine "sucks" triangles on demand, a Physics engine should provide something like that, so the large terrain heightmap can be shared with the graphics engine and the physics engine.

maybe a "TerrainShape" ?
Bullet allows for creating triangles "on demand", given an axis aligned bounding box. Someone already made some heightfield tutorial.

http://www.continuousphysics.com/mediaw ... ight_Field

Thanks for the feedback,
Erwin
Good to know, I'll take a look

Thanks in advance

Vic
Eltharyon
Posts: 13
Joined: Wed Jun 07, 2006 12:55 pm

Post by Eltharyon »

Currently Bullet has a multi-layer API, mid-level C++ API, and low-level C++ API. Once things are in place, I intend to add a high-level C-API tha t makes it all very easy. Once you want more control, you go C++.
The longer this project exists and the more it develops the more I like it! Can't wait to test the new version! Keep it up.