Tutorial - Materials

From Newton Wiki
Jump to: navigation, search

So far we have been making rigid bodies with default physics properties, but this is not the way rigid bodies behave in the real world. Even though a real-time physics engine is only a very crude approximation of the real world, we still want to see macroscopic physical behavior like: elasticity, realistic friction, sound effects, particles effects, and even non realistic effects.

Newton’s answer for rigid body custom physics behavior is the material graph.

The material graph is an undirected graph, were the nodes are the material ID and the edges are the material interactions.

Material IDs are unique identifiers Newton uses to represent real like materials like: wood, concrete, metal etc. The material interactions are objects that store the definitions for the behavior of any two material IDs when they come into contact.

In this tutorial we are going to create a material graph consisting of three different simple materials and one special material used to assist in controlling a small ball character.

Open the project tutorial4_IntroductionToMaterials. Open the file Tutorial.cpp a go to function InitScene(). The first thing we need to do after the Newton world is created is to create the material graph for the entire scene. This is important because materials are expensive to make and they cannot be destroyed individually. So the application should decide early in the project how many materials are going to be used.

// set up all material and  material interactions
SetupMaterials (nWorld);

Next we create our first controllable player character.

// Create a ball controlable by the player
AddBallCharacter ();

Open the file Materials.cpp You will see four global variables used as material IDs

int woodID; 
int metalID; 
int levelID; 
int characterID;

Next there is a data structure the application can use to store the resources needed to provide feedback when two rigid bodies come into contact.

// structure used to hold game play especial effects
struct SpecialEffectStruct
	void *soundHandle;
	void *particleHandle;

	// create the resources for this materials effect here
	void Init (char* effectName)

	// destroy all resources for this material interaction here
	void Detroy ()

	// play the impact sound
	void PlayImpactSound (float volume)

	// play scratch sound
	void PlayScratchSound (float volume)

	NewtonBody* m_body0;
	NewtonBody* m_body1;
	dVector m_position;
	float m_contactMaxNormalSpeed;
	float m_contactMaxTangentSpeed;

There is one instance of this structure for every different special effect the application wants to define.

// structures use to hold different materials interaction 
SpecialEffectStruct wood_wood;
SpecialEffectStruct wood_metal;
SpecialEffectStruct wood_level;
SpecialEffectStruct metal_metal;
SpecialEffectStruct metal_level;

Find the function SetupMaterials. First all SpecialEffect instances are initialized

// initialize the material intaration here
wood_wood.Init ("wood_wood");
wood_metal.Init ("wood_metal");
wood_level.Init ("wood_level");
metal_metal.Init ("metal_metal");
metal_level.Init ("metal_level");

Next the application gets the default ID and sets the default physics behavior for the pair default ID – default ID

// get the default material ID
defaultID = NewtonMaterialGetDefaultGroupID (nWorld);

// Set default material properties
NewtonMaterialSetDefaultSoftness (nWorld, defaultID, defaultID, 0.05f);
NewtonMaterialSetDefaultElasticity (nWorld, defaultID, defaultID, 0.4f);
NewtonMaterialSetDefaultCollidable (nWorld, defaultID, defaultID, 1);
NewtonMaterialSetDefaultFriction (nWorld, defaultID, defaultID, 1.0f, 0.5f);
NewtonMaterialSetCollisionCallback (nWorld, woodID, woodID, &wood_wood, GenericContactBegin, GenericContactProcess, GenericContactEnd);  

It is important that the application set the properties for the default-default material interactions. This is because when new materials are created, all possible permutations of the new IDs with existing ones get their properties from the default-default pair.

Now the application creates all Material IDs that will be used with this level

// create all materials ID
woodID = NewtonMaterialCreateGroupID(nWorld);
metalID = NewtonMaterialCreateGroupID(nWorld);
levelID = NewtonMaterialCreateGroupID(nWorld);
characterID = NewtonMaterialCreateGroupID(nWorld);

Then what follows is the tedious process of setting the individual material interactions for every combination of any two materials

// set the material properties for wood on wood
NewtonMaterialSetDefaultElasticity (nWorld, woodID, woodID, 0.3f);
NewtonMaterialSetDefaultFriction (nWorld, woodID, woodID, 1.1f, 0.7f);
NewtonMaterialSetCollisionCallback (nWorld, woodID, woodID, &wood_wood, GenericContactBegin, GenericContactProcess, GenericContactEnd);

Notice that almost all material interactions use the same tree material call back but with different user data. This is very common for setting background rigid bodies. Must of the time the application is only interested in visual reaction like friction or bounciness or particle effects, or audio effects like playing different sounds when two bodies collide or slide against each other. However some times it is necessary to customize and make decisions about how the application wants the collision of two bodies to be processed. This is the case of the ball character.

// set the material properties for character on level 
NewtonMaterialSetDefaultElasticity (nWorld, levelID, characterID, 0.4f);
NewtonMaterialSetDefaultFriction (nWorld, levelID, characterID, 0.8f, 0.8f);
NewtonMaterialSetCollisionCallback (nWorld, levelID, characterID, &metal_level, GenericContactBegin, CharacterContactProcess, GenericContactEnd);

This material uses a different contact call back CharacterContactProcess. This function in turn calls the same default contact callback, but upon return it aligns the contact normal with the ball linear velocity vector, this rotation improves significantly the kinetic friction behavior of the ball with the background geometry.

Materials are not only limited to provide contact physics behaviors; they can be used to provide game logic and game play content. You can use materials in combination with static rigid bodies (bodies with infinite mass) to provided trigger volumes, like water pools, antigravity rooms. Also they can be used to create special effects like sliding surfaces or to create sensor areas for special bodies. These are advanced uses that will be covered in subsequent tutorials. We just wanted to emphasize the power of materials.

Now open the file Tutorial.cpp and find the function AddBallCharacter (). This function creates a ball and assigns a special force and torque call back function. Also, since this is going to be a player character, the auto disable functionality is turned off and the body is activated.

The function BallCharacterApplyForceAndTorque is very simple It has two modes of operations: In normal mode it applies a torque the ball making to roll, in fly mode it apply a force to the center of the ball. The force and torque are aligned to the camera heading.

To control the ball: w, s, a, d move ball space switch to fly mode. Mouse left button down and drag change the camera orientation.