Mesh material

Mesh material

Hi!

I'm new to Havok and I'd like to know what would be the best practice for setting up mesh materials for shapes to assign material properties like wood, road, dirt to a rigid body.

I'm working on a racing game and I'd like to add effects and different driving behaviour depending on the ground the vehicle is driving on.

I'd also like to know whether and how these material properties could be assigned using a design tool like Maya or 3dsmax.

Thank you for your help!

10 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
sean.thurston's picture

Hi S_W,

There are a few ways to go about doing these different materials for your game. They range from somewhat easy, but not very extensible or elegant, to a way which is a little more difficult to understand and implement, but has its own advantages. I'll do my best to give the basic ideas for each.

This first one deals with assigning one "material" type to a rigid body(on a per body basis, instead of on a per-face basis).

#1 This one is the easiest, just give each rigid body the name you want the material to have("Grass", "Dirt," etc.) and get all the fixed geometry of that type into one fixed rigid body. Export those rigid bodies.

Then you need to look at hkpVehicleRaycastWheelCollide. You'll need to overwrite one or more of the methods in your own extended class(specifically calcSingleWheelGroundFriction might be one to look at). The idea is that you cast a ray down from each wheel and determine which shape your wheel is on. Then add the line

vehicle.m_wheelCollide = new MyVehicleRaycastWheelCollide;

when you are setting up your vehicle.

Inside the calcSingleWheelGroundFriction() function you can check the rigid body your wheel ray collided with for the "Dirt" or "Grass" name that you gave your rigid bodies and adjust friction accordingly. There is an example of how to use this function with the vehicle demos, the class name is FrictionMapVehicleRaycastWheelCollide. The disadvantage here is that having multiple rigid bodies (and multiple bvtrees for terrain) can hurt performace.

#2 You can add properties to rigid bodies directly in code. Then using the same calcSingleWheelGroundFriction(), you can check for that property. Pretty much works same as above. As described here, this would be done in code. This is how it is done in the vehicle demos for the "icy" patch.

#3 The more difficult ways is to set up a custom filter to grab information from the editor. The basic idea is that you can use the Parameter Editor to add your own information into the scene. The filter could then grab this information. You should be familiar with the section Havok Content Tools/Integrating with the Havok Content Tools/Tutorial : Extending the Toolchain. You should also look at the modeler specific sections in the Integrating with Havok Content Tools chapter of the docs. There is an explanation of one way to do materials at the bottom. If you have any questions about doing this, please ask. Writing a custom filter probably gives you the most options including allowing you to do per-face materials with some extra work.

There are advantages and disadvantages to each and these are not the only ways this can be done. I'm sure there are others ways this can be done. I hope this helps.

Thanks,
Sean

Developer Support Engineer Havok www.havok.com

Hi Sean,

#3 seems to be best choice for me, so I'll read the specific sections about writing a custom filter in the manual again.

Right now I've taken a quick look at section "9.6.3.1.Using user-defined "materials" to override rigid body properties".
Regrettably this sounds more like one single material per rigid body to me and I actually don't know what the best way would be to do per-face materials. Our artists are using Maya and as far as I know there are only custom attributes for a whole mesh, not for a single face (although I'm not 100% sure).

The only idea for a solution I could think of now is to try to find out the name of the material used on a face in Maya and use this name to apply a corresponding material id to the rigid body's face, but I'm also not sure whether this could be done in Maya.

Maybe there's a better solution I'm not aware of?

Thanks again for the reply!
S_W

Hi S_W,

Just letting you know that a mesh shape is a collection shape of triangle shapes. Each of the child shapes also has user data, as well as the rigid body itself, which can be used to save material information.

Thanks,
Daniel

itten's picture

Quoting - havokdaniel
Just letting you know that a mesh shape is a collection shape of triangle shapes. Each of the child shapes also has user data, as well as the rigid body itself, which can be used to save material information.

Hi

i tied to use triangle shapes to store my data (just a number) and didn't succeed. I found function

hkpShapeContainer::getChildShape which i wanted to use to access triangle shapes and then invoke setUserData for them.

But this functon returns constant shape:

virtual const hkpShape * getChildShape (hkpShapeKey key, ShapeBuffer &buffer) const=0;

So, i can't modify shapes. Of course i can use const_cast, but here are two things.

1)const_cast is usually a sign of bad code

2)i tried const_cast (just for test) and my data were not stored. it seems, likegetChildShape constructs new shape every time it is called. I think i saw something like that in docs.

Is there another way to access triangle shapes and store user data in them?

sean.thurston's picture

Hi itten,

That post by Daniel is actually not correct. The problem is that getChildShape looks at the shape data which is stored as vertices and vertex indices (faces). The triangle objects are constructed on the fly when you call getChildShape from that information. You are going to want to store material information in the hkpMeshMaterial. I think the discussion above covers a lot of it. Check out the MeshMaterialsDemo for an example of how to set that up.

Thanks,
Sean

Developer Support Engineer Havok www.havok.com

Quoting - s_w
#3 seems to be best choice for me, so I'll read the specific sections about writing a custom filter in the manual again.

Right now I've taken a quick look at section "9.6.3.1.Using user-defined "materials" to override rigid body properties".
Regrettably this sounds more like one single material per rigid body to me and I actually don't know what the best way would be to do per-face materials. Our artists are using Maya and as far as I know there are only custom attributes for a whole mesh, not for a single face (although I'm not 100% sure).

The only idea for a solution I could think of now is to try to find out the name of the material used on a face in Maya and use this name to apply a corresponding material id to the rigid body's face, but I'm also not sure whether this could be done in Maya.

Maybe there's a better solution I'm not aware of?

Method #3 seemed the right approach to me also and I also went through the section on creating user defined materials. Unfortunately, I also faced similar issues(I was using 3DS Max). The custom parameters can be added only to the selected Object's material and not to the Sub-Object(sub material). I didn't find any other way of adding custom paramets to materials per face. Is there any other method Sean??

Quoting - whizkid667

Method #3 seemed the right approach to me also and I also went through the section on creating user defined materials. Unfortunately, I also faced similar issues(I was using 3DS Max). The custom parameters can be added only to the selected Object's material and not to the Sub-Object(sub material). I didn't find any other way of adding custom paramets to materials per face. Is there any other method Sean??

Welcome to the club :)

I'm still trying....

If anyone cracks it please let others know.

Quoting - sean.thurston

The triangle objects are constructed on the fly when you call getChildShape from that information. You are going to want to store material information in the hkpMeshMaterial. I think the discussion above covers a lot of it. Check out the MeshMaterialsDemo for an example of how to set that up.

I checked out the MeshMaterialsDemo and also the manner in which the geometry is constructed. I made some modifications to load a mopp from an HKX file and basically do the same queries as done in the MeshMaterialsDemo. I assigned materials to the MOPP mesh in 3DSMax. But this material info was not found in the Mopp shape. How can material info be added to the MOPP shape? This is the code I've used to load the hkx file

hkString assetFile = hkAssetManagementUtil::getFilePath("Resources/Physics/Objects/Test.HKX");
m_loader = new hkLoader();
hkRootLevelContainer* container = m_loader->load( assetFile.cString() );
HK_ASSERT2(0xaefe9356, container != HK_NULL , "Could not load asset");

hkpPhysicsData* physics = static_cast( container->findObjectByType( hkpPhysicsDataClass.getName() ) );
HK_ASSERT2(0x245982ae, physics != HK_NULL, "Could not find physics data in root level object" );

hkpRigidBody* rigidBody = physics->getPhysicsSystems()[0]->getRigidBodies()[0];

const hkpShape      *mopp_shape = rigidBody->getCollidable()->getShape() ; 

//Should be HK_SHAPE_MOPP 
const hkpShapeType		world_shape_type = mopp_shape->getType() ;
m_world->addEntity(rigidBody);

const hkpMoppBvTreeShape* moppShape = static_cast(rigidBody->getCollidable()->getShape());

const hkpShape*				Container = moppShape->getShapeCollection();

const hkpExtendedMeshShape* m_mesh = static_cast(Container);

rigidBody->removeReference() ;

The code I've used to retrieve the material is given below:

const MeshMaterial* material = static_cast(m_mesh->getMeshMaterial( output.m_shapeKeys[0] ) );

The thing is that the material pointer is NULL. I checked out the XML file during export and there also no Material was listed under the mopp shape. I hope that the code I used can give the material info, if its available.

sean.thurston's picture

Hi guys,

This seems to be tripping people and it is a pretty interesting problem to get it integrated with a modeler. The long and short of it is that if you want per-triangle information exported from the modeler then you are going to need to write a custom filter to get it. I don't want to run over old ground on this one, there is a lot of information above. This is a tricky topic though, I'll do my best to explain what I can.

You are going to want to read the Havok Content Tools/Integrating with the Havok Content Tools/Tutorial : Extending the Toolchain section of the docs and take a look at the source for the hctFilterTutorial. It is also going to be helpful to look at the MeshMaterialDemo I will try to describe one way to do this, but there are others and there might be better ways to do this.

I'm going to discuss this using Max because I am more comfortable with Max, but it should also be possible with the other modelers. Bear with me if I don't know all the exact Max terminology. One way to store the information in a set of faces is to make a material group. So If you set up a plane with a bunch of faces, select a subset of the faces and apply a material to it. You can apply many different materials to the same object. You could apply a different material to every face. Now if you go to Animation->Parameter Editor... you will be able to select the different materials and add custom data to them. This data will be exported as Scene Data. You can view it with the ViewXml Filter and I would advise doing that now to make sure it works.

Now that you can store information to a set of faces, you need to get that information into your hkpExtendedMeshShape. The best place to store it is probably in the materials and material indices sections of the EMS. This is where the MeshMaterialDemo and the custom filter come in. For each of the Max Materials that you made, you will make a hkpMeshMaterial. I would recommend using the m_filterInfo field to store the custom data or an index to where the custom data will be stored a runtime. There have been issues with storing custom hkpMeshMaterials into an hkpStorageExtendedMeshShape in the past. Then you can access that data at runtime the same way it is accessed in the MeshMaterialsDemo.

There is kind of a lot of information here and I hope this answers everyone's questions. There are probably alternative ways to go about doing this. This is a pretty general approach that you can use. Let me know if you have any specific questions on this.

Thanks,
Sean

Developer Support Engineer Havok www.havok.com

Login to leave a comment.