Code:
#include <DMM.h>
#include <Scene.h>
#include <Object.h>
#include <Node.h>
#include <Material.h>
// This is a primitive cube as created by the DMM Plugin
// It has 12 tets, each of them using a triangle of the cube
// shape as its base and the center of the cube as its top
// List of nodes (vertices)
const size_t numNodes = 9;
Pixelux::real cubeNodes[numNodes][3] = {
{ -0.5, -0.5, 0.5 }, // Corner #0
{ 0.5, -0.5, 0.5 }, // ...
{ 0.5, 0.5, 0.5 }, // ...
{ -0.5, 0.5, 0.5 }, // ...
{ 0.5, 0.5, -0.5 }, // ...
{ -0.5, 0.5, -0.5 }, // ...
{ 0.5, -0.5, -0.5 }, // ...
{ -0.5, -0.5, -0.5 }, // Corner #7
{ 0.0, 0.0, 0.0 } }; // Center
// List of indices making the tets
const size_t numTets = 12;
size_t cubeTets[numTets][4] = {
{ 1, 0, 8, 3 }, // Tet #0
{ 7, 0, 8, 1 }, // ...
{ 5, 0, 3, 8 }, // ...
{ 5, 0, 8, 7 }, // ...
{ 2, 1, 8, 3 }, // ...
{ 6, 1, 8, 2 }, // ...
{ 1, 8, 7, 6 }, // ...
{ 2, 3, 8, 5 }, // ...
{ 2, 4, 5, 8 }, // ...
{ 4, 8, 2, 6 }, // ...
{ 4, 8, 6, 5 }, // ...
{ 6, 5, 8, 7 } }; // Tet #11
// List of tet nodes making the tet's triangles
size_t tetFaceNode[4][3] = {
{ 0, 1, 2 }, // Triangle #0
{ 2, 3, 0 }, // ...
{ 2, 1, 3 }, // ...
{ 3, 1, 0 } }; // Triangle #3
// Storage space for the simulated node's positions
Pixelux::Vec3 nodePositions[4 * numTets];
// The DMM singleton
Pixelux::DMM* pDMM = NULL;
// The DMM scene
Pixelux::Scene* pDMMScene = NULL;
// Initialize DMM and create the Scene
bool InitDMM()
{
bool success = false;
// Get DMM
pDMM = Pixelux::GetDMM(PXX_DMM_VERSION);
if (pDMM == NULL)
{
// Couldn't get DMM - probably wrong version number
}
else
{
// Create the scene
pDMMScene = pDMM->CreateScene();
success = true;
}
return success;
}
// Deletes the DMM scene
void DeleteDMMScene()
{
if ((pDMM != NULL) && (pDMMScene != NULL))
{
pDMM->DeleteScene(pDMMScene);
pDMMScene = NULL;
}
}
// Add a DMM cube primitive to the scene, with a scale and a translation
Pixelux::Object* CreateDMMCube(const Pixelux::Vec3& scale, const Pixelux::Vec3& trans)
{
// Create the object
Pixelux::Object* pObject = pDMMScene->CreateObject(4 * numTets, numTets);
if (pObject != NULL)
{
// Create the nodes (vertices)
for (size_t i = 0; i < numNodes; ++i)
{
// Initialize a Vec3 with the node position
Pixelux::Vec3 v;
v.x = cubeNodes[i][0];
v.y = cubeNodes[i][1];
v.z = cubeNodes[i][2];
// Scale and translate
v.mult(scale);
v.add(trans);
// Create node
pObject->CreateNode(v);
}
// Create the tets
Pixelux::Node** beginNodes = pObject->BeginNodes();
for (size_t i = 0; i < numTets; ++i)
{
// Get the 4 nodes forming the tet
size_t n0 = cubeTets[i][0];
size_t n1 = cubeTets[i][1];
size_t n2 = cubeTets[i][2];
size_t n3 = cubeTets[i][3];
Pixelux::Node* nodes[] = {
beginNodes[n0], beginNodes[n1], beginNodes[n2], beginNodes[n3] };
// Create the tet
pObject->CreateTet(nodes);
}
}
return pObject;
}
bool CreateDMMObjects()
{
if (pDMMScene == NULL)
{
return false;
}
// Create a new material
Pixelux::Material* pMaterial = pDMMScene->CreateMaterial();
if (pMaterial == NULL)
{
return false;
}
// Make it quite heavy and mushy
pMaterial->SetName("myMaterial");
pMaterial->Set(Pixelux::MATERIAL_DENSITY, 1e4);
pMaterial->Set(Pixelux::MATERIAL_YOUNGS_MODULUS, 1e6);
// Set it as the default material
// (every newly created tet will use that material)
pDMMScene->SetDefaultMaterial(pMaterial);
// Create a cube that's translated it upwards,
Pixelux::Vec3 scale(1);
Pixelux::Vec3 trans(0);
trans.y = 4;
Pixelux::Object* pObject = CreateDMMCube(scale, trans);
if (pObject == NULL)
{
return false;
}
// Create another cube, flattened and translated downward
scale.x *= 10;
scale.y *= 0.2;
scale.z *= 10;
trans.y = -2;
pObject = CreateDMMCube(scale, trans);
if (pObject == NULL)
{
return false;
}
// Let the first cube fall down on the second cube
// => drive the node's positions of the second cube so it won't move
// (it would be a passive object in the DMM Plugin)
// To do that, iterate each node of the second cube
for (Pixelux::Node** it = pObject->BeginNodes(), ** end = pObject->EndNodes()
; it != end; ++it)
{
// And set the node as "driven"
Pixelux::Node* pNode = *it;
pNode->SetNodeState(Pixelux::NODE_DRIVEN_BIT);
}
return true;
}
void StepDMMSim()
{
if (pDMMScene != NULL)
{
// Mode 10 ms forward in the DMM simulation
pDMMScene->Step(0.01);
// Wait for 5 ms before returning
// This is very innacurate, it's just to emulate
// other computations that would be done in a game engine
Sleep(5);
}
}
void DrawDMMObjects()
{
// Reset the model-view matrix
glLoadIdentity();
// And translate and rotate the objects so to better see them
glTranslatef(0.0f,0.0f,-7.0f);
glRotatef(30,0.0f,1.0f,0.0f);
// Iterate the DMM objects
for (Pixelux::Object** it = pDMMScene->BeginObjects(), ** end = pDMMScene->EndObjects()
; it != end; ++it)
{
// Get the node positions for this DMM object
Pixelux::Object* pObject = *it;
pObject->GetTetsNodesPos(pObject->BeginTets(), pObject->EndTets(), &nodePositions[0]);
// Start drawing triangles
glBegin(GL_TRIANGLES);
// Iterate the tets
for (size_t i = 0; i < numTets; ++i)
{
// Iterate the tet's triangles
for (size_t j = 0; j < 4; ++j)
{
// Get the node's positions for this triangle
Pixelux::Vec3& v0 = nodePositions[4 * i + tetFaceNode[j][0]];
Pixelux::Vec3& v1 = nodePositions[4 * i + tetFaceNode[j][1]];
Pixelux::Vec3& v2 = nodePositions[4 * i + tetFaceNode[j][2]];
// Draw one face (triangle) of the tet
// 1st vertex, green
glColor3f(0, 1, 0);
glVertex3f(v0.x, v0.y, v0.z);
// 2nd vertex, red
glColor3f(1, 0, 0);
glVertex3f(v1.x, v1.y, v1.z);
// 3rd vertex, blue
glColor3f(0, 0, 1);
glVertex3f(v2.x, v2.y, v2.z);
}
}
// Done with drawing the tets
glEnd();
}
}
Bookmarks