#include #include #include #include #include #include #include #include #include #include //////////////////////////////////////////////////////////// // // (C) Copyright 2000 // David C. Banks // Florida State University // // Make a sphere bounce around inside a unit cube. const SbVec3f CubeMin = SbVec3f(-1.0, -1.0, -1.0); const SbVec3f CubeMax = SbVec3f( 1.0, 1.0, 1.0); //////////////////////////////////////////////////////////// // // The scene graph is constructed as indicated in the // diagram below. // // root // | // ------------------- // | | // sphereSep cubeSep // | | // --------------- --------------- // | | | | | // trans mat sphere vertexList lineSet // SoSeparator * makeScene (float radius) { SoSeparator *root = new SoSeparator(); // Put a red sphere in the scene SoSeparator *sphereSep = new SoSeparator(); root->addChild(sphereSep); SoTransform *sphereTrans = new SoTransform(); sphereTrans->translation.setValue(0.0, 0.0, 0.0); // start at origin sphereSep->addChild(sphereTrans); SoMaterial *sphereMat = new SoMaterial(); sphereMat->diffuseColor.setValue(1.0, 0.0, 0.0); // red sphereSep->addChild(sphereMat); SoSphere *sphere = new SoSphere(); sphere->radius = radius; sphereSep->addChild(sphere); // Put a wireframe cube in the scene. SoSeparator *cubeSep = new SoSeparator(); root->addChild(cubeSep); //////////////////////////////////////////////////////////// // // Create an array of points at the vertices of the cube. // // y // ^ // 2 | 3 // .-----------|----------------. // / | /| // / | | / | // / / | // 7 / | 6 / | // .----------------------------. | // | | | | // | | | // | | | ------> x // | | | // | | | | // | | | // | | | | // | .- - - - - - - - - - - -|- - . // | 0 | / 1 // | / | / // | | / // |/ |/ // .----------------------------. // 4 5 const int numCubeVerts = 8; static float cubeVerts[numCubeVerts][3] = { { CubeMin[0], CubeMin[1], CubeMax[2] }, // vert 0 { CubeMax[0], CubeMin[1], CubeMax[2] }, // vert 1 { CubeMin[0], CubeMax[1], CubeMax[2] }, // vert 2 { CubeMax[0], CubeMax[1], CubeMax[2] }, // vert 3 { CubeMin[0], CubeMin[1], CubeMin[2] }, // vert 4 { CubeMax[0], CubeMin[1], CubeMin[2] }, // vert 5 { CubeMin[0], CubeMax[1], CubeMin[2] }, // vert 6 { CubeMax[0], CubeMax[1], CubeMin[2] } // vert 7 }; //////////////////////////////////////////////////////////// // // Index into the array of vertices to create segments // defining the edges of the cube. // // For example, 0, 1, -1 will designate a segment from // cubeVerts[0] to cubeVerts[1]. SoVertexProperty *vertexList = new SoVertexProperty(); vertexList->vertex.setValues( 0, numCubeVerts, cubeVerts); root->addChild(vertexList); const int numEdgeIndexes = 36; static int32_t cubeIndex[numEdgeIndexes] = { 0, 1, -1, // -1 terminates the edge. 2, 3, -1, 0, 2, -1, 1, 3, -1, 4, 5, -1, 6, 7, -1, 4, 6, -1, 5, 7, -1, 0, 4, -1, 1, 5, -1, 2, 6, -1, 3, 7, -1, }; SoIndexedLineSet *vertIndex = new SoIndexedLineSet(); vertIndex->coordIndex.setValues(0, numEdgeIndexes, cubeIndex); root->addChild(vertIndex); return root; } //////////////////////////////////////////////////////////// // // This routine is repeatedly called from the Inventor // main loop. void animate(void *data, SoSensor *) { static SbVec3f velocity = SbVec3f(0.02, 0.03, 0.05); SbVec3f position; // Retrieve the sphere and its transform from the scene graph. SoSeparator *root = (SoSeparator *) data; SoSeparator *sphereSep = (SoSeparator *) (root->getChild(0)); SoTransform *sphereTrans = (SoTransform *) (sphereSep->getChild(0)); SoSphere *sphere = (SoSphere *) (sphereSep->getChild(2)); // Update the sphere's position. position = sphereTrans->translation.getValue(); position += velocity; sphereTrans->translation.setValue(position); float radius = sphere->radius.getValue(); // Make the sphere bounce if it hits a face of the cube. for (int i = 0; i < 3; i++) { if ( (position[i] - radius < CubeMin[i]) || (position[i] + radius > CubeMax[i]) ) { velocity[i] = -velocity[i]; } } } //////////////////////////////////////////////////////////// // // The main program gets a window from X, // puts an interactive 3D examinerViewer in it, // attaches the scene graph to the viewer, // renders the scene graph, // and hands control over to the Inventor main loop. void main(int, char **argv) { float radius = 0.2; // radius of the sphere in the cube. // Initialize Inventor and Xt Widget myWindow = SoXt::init(argv[0]); if (myWindow == NULL) exit(1); // Create a scene graph SoSeparator *root = makeScene(radius); SoTimerSensor *sensor = new SoTimerSensor(animate, root); sensor->setInterval(SbTime(0.02)); // 50 frames per second sensor->schedule(); SoXtExaminerViewer *myViewer = new SoXtExaminerViewer(myWindow); myViewer->setSceneGraph(root); myViewer->setTitle("Sphere in Cube"); myViewer->show(); SoXt::show(myWindow); SoXt::mainLoop(); }