# Tutorial 105: - Basic Materials

Template:Languages
This tutorial introduces how to use basic materials

Select project Tutorial_105_BasicMaterials as startup project in Visual Studio and open the file CreateScene in the editor and find the function CreateScene:

```void CreateScene (NewtonWorld* world, SceneManager* sceneManager)
{
Entity* floor;
Entity* smilly;
Entity* frowny;
NewtonBody* floorBody;
NewtonBody* smillyBody;
NewtonBody* frownyBody;
NewtonCollision* shape;

// Create the material for this scene
CreateMaterials (world, sceneManager);

// Create a large body to be the floor
floor = sceneManager->CreateEntity();

shape = CreateNewtonBox (world, floor, 0);
floorBody = CreateRigidBody (world, floor, shape, 0.0f);
NewtonReleaseCollision (world, shape);

// set the Transformation Matrix for this rigid body
dMatrix matrix (floor->m_curRotation, floor->m_curPosition);
NewtonBodySetMatrix (floorBody, &matrix[0][0]);

// now we will use the properties of this body to set a proper world size.
dVector minBox;
dVector maxBox;
NewtonCollisionCalculateAABB (shape, &matrix[0][0], &minBox[0], &maxBox[0]);

minBox.m_x -=  50.0f;
minBox.m_y -= 500.0f;
minBox.m_z -=  50.0f;

maxBox.m_x +=  50.0f;
maxBox.m_y += 500.0f;
maxBox.m_z +=  50.0f;

// set the new world size
NewtonSetWorldSize (world, &minBox[0], &maxBox[0]);

// assign an Material ID to this body
NewtonBodySetMaterialGroupID (floorBody, g_floorMaterial);

dFloat y0 = FindFloor (world, 0.0f, 0.0f) + 10.0f;
for (int i = 0; i < 5; i ++) {
smilly = sceneManager->CreateEntity();
smilly->m_curPosition.m_y = y0;
y0 += 2.0f;
smilly->m_prevPosition = smilly->m_curPosition;

// add a body with a box shape
shape = CreateNewtonBox (world, smilly, 0);
smillyBody = CreateRigidBody (world, smilly, shape, 10.0f);
NewtonReleaseCollision (world, shape);

// assign an Material ID to this body
NewtonBodySetMaterialGroupID (smillyBody, g_metalMaterial);
}

y0 = FindFloor (world, 0.0f, 0.4f) + 10.5f;
for (int i = 0; i < 5; i ++) {
frowny = sceneManager->CreateEntity();
frowny->m_curPosition.m_z = 0.4f;
frowny->m_curPosition.m_y = y0;
y0 += 2.0f;
frowny->m_prevPosition = frowny->m_curPosition;

// add a body with a Convex hull shape
shape = CreateNewtonConvex (world, frowny, 0);
frownyBody = CreateRigidBody (world, frowny, shape, 10.0f);
NewtonReleaseCollision (world, shape);

// assign an Material ID to this body
NewtonBodySetMaterialGroupID (frownyBody, g_woodMaterial);
}
}
```

This function creates a standard physics scene with one large static rigid body and few smaller dynamic rigid bodies bouncing around. The difference between this scene and the scenes in previous tutorials is that in this scene, each time a rigid body is in contact with another rigid body in the scene, we want to generate a different event.

For this tutorial we will represent different events by playing a different impact sound. To do this, the material graph must first be configured by calling the function CreateMaterials:

```void CreateMaterials (NewtonWorld* world, SceneManager* sceneManager)
{
SoundManager* sndManager;

sndManager = sceneManager->GetSoundManager();

// create the Material IDs,
g_floorMaterial = NewtonMaterialCreateGroupID (world);
g_woodMaterial = NewtonMaterialCreateGroupID (world);
g_metalMaterial = NewtonMaterialCreateGroupID (world);

woodOnFloor.m_manager = sndManager;

metalOnFloor.m_manager = sndManager;

woodOnMetal.m_manager = sndManager;

metalOnMetal.m_manager = sndManager;

woodOnWood.m_manager = sndManager;

//configure the Material interactions
NewtonMaterialSetCollisionCallback (world, g_woodMaterial, g_floorMaterial, &woodOnFloor, NULL,  GenericContactProcess);
NewtonMaterialSetCollisionCallback (world, g_metalMaterial, g_floorMaterial, &metalOnFloor, NULL,  GenericContactProcess);
NewtonMaterialSetCollisionCallback (world, g_metalMaterial, g_woodMaterial, &woodOnMetal, NULL,  GenericContactProcess);

NewtonMaterialSetCollisionCallback (world, g_woodMaterial, g_woodMaterial, &woodOnWood, NULL,  GenericContactProcess);
NewtonMaterialSetCollisionCallback (world, g_metalMaterial, g_metalMaterial, &metalOnMetal, NULL,  GenericContactProcess);
}
```

The material system in Newton is an undirected graph were the nodes of the graphs represent the material and the edges of the graph store the physical properties between two material interactions.

To configure the Material Graph, the application for shave to create all of the material types that will be part of the Physics Scene. This is accomplished by calling the function NewtonMaterialCreateGroupID: each time this function is called a new ID is returned and the application needs to specify how this new material will interact with all other previously created materials. As you can see, the number of interactions increases with the square of the number of materials. Therefore it is the job of the application to minimize the number of materials.

To minimize the amount of work needed to set all on the material interactions for each newly created material, the engine uses the parameters of the default material to initialize all of the material interactions of the new material. When new materials are added, they will use the default behaviors already set, however new behaviors can be specified to override the defaults.

Material interactions are specified by calling functions such as NewtonMaterialSetCollisionCallback, NewtonMaterialSetDefaultSoftness, NewtonMaterialSetDefaultFriction. A complete list can be found here: Newton SDK API reference#Category:Physics_Material_Section

As you can see in this demo we only use NewtonMaterialSetCollisionCallback as we know all other interactions are set to the default interaction.

NewtonMaterialSetDefaultSoftness stores the pointer to a data structure that store some application specific data to be processed when the two materials collide. A callback function can also be stored to process the collision of the two materials:

Here is the callback function used in this tutorial:

```static void GenericContactProcess (const NewtonJoint* contactJoint, dFloat timestep, int threadIndex)
{
dFloat contactBestSpeed;
SoundEffect* bestSound;
dVector contactPosit;

bestSound = NULL;
contactBestSpeed = 0.5f;
// iterate obe all ccontact of this collision and find the contact
// tha most dominate the collision, this is the contct with thr strongest impact velocity
for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = NewtonContactJointGetNextContact (contactJoint, contact)) {
dFloat contactNormalSpeed;
NewtonMaterial* material;

// get the material for this contact;
material = NewtonContactGetMaterial (contact);

contactNormalSpeed = NewtonMaterialGetContactNormalSpeed (material);
if (contactNormalSpeed > contactBestSpeed){
// the contact is stroget teh teh previus, save it and save teh local Data for futher prossesing
contactBestSpeed = contactNormalSpeed;
dVector normal;
contactBestSpeed = contactNormalSpeed;
NewtonMaterialGetContactPositionAndNormal (material, &contactPosit[0], &normal[0]);
bestSound = (SoundEffect *)NewtonMaterialGetMaterialPairUserData (material);
}
}

// now that we found teh most dominat contact
if (bestSound) {
dFloat volume;
dFloat dist2;

// we will play a sound to signal there was a collision.
dVector eyePoint (GetCameraEyePoint() - contactPosit);
dist2 = eyePoint % eyePoint;
if (dist2 < (MAX_SOUND_DISTANCE * MAX_SOUND_DISTANCE)) {
// the sound volume is proportional to the distance from the eyepoint to the collision
volume = 1.0f;
if (dist2 > (MIN_SOUND_DISTANCE * MIN_SOUND_DISTANCE)) {
volume = 1.0f - (dSqrt (dist2) - MIN_SOUND_DISTANCE) / (MAX_SOUND_DISTANCE -  MIN_SOUND_DISTANCE);
}
bestSound->m_manager->Play(bestSound->m_sound, volume, 0);
}
}
}
```

With this we finish the implementation of a very basic sound system using Newton.

Later we will implement a more advanced material system where well use collision shape IDs to handle collisions with sub material shape stored with the rigid body. For now, this system can only control materials at the rigid body level, although it is possible to handle sub materiasl by writing a more complex contact callback. I suggest reading the advanced material system before you decide to do this.