WPARAM MainLoop() { MSG msg; while(1) // Do our infinite loop { // Check if there was a message if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if(msg.message == WM_QUIT) // If the message wasn't to quit break; TranslateMessage(&msg); // Find out what the message does DispatchMessage(&msg); // Execute the message } else // if there wasn't a message { if(AnimateNextFrame(60)) // Make sure we only animate 60 FPS { g_Camera.Update(); // Update the camera info RenderScene(); // Render the scene every frame } else { Sleep(1); // Let other processes work } } } /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // Go through all the objects in the scene and free them for(int i = 0; i < g_World.numOfObjects; i++) { // Free the faces, normals, vertices, and texture coordinates. delete [] g_World.pObject[i].pFaces; delete [] g_World.pObject[i].pNormals; delete [] g_World.pObject[i].pVerts; delete [] g_World.pObject[i].pTexVerts; delete [] g_World.pObject[i].pIndices; } // When using display lists, we need to free them when we are finished using // the ID's. This OpenGL function does just that. We pass in the base ID and // the total ID's we used. glDeleteLists(g_Octree.GetDisplayListID(), g_EndNodeCount); /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * DeInit(); // Clean up and free all allocated memory return(msg.wParam); // Return from the program }
void Init(HWND hWnd) { g_hWnd = hWnd; // Assign the window handle to a global window handle GetClientRect(g_hWnd, &g_rRect); // Assign the windows rectangle to a global RECT InitializeOpenGL(g_rRect.right, g_rRect.bottom); // Init OpenGL with the global rect /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // Initialize the camera position g_Camera.PositionCamera(0, 3.5f, 30, 0, 0, 0, 0, 1, 0); // Here we load the world from a .3ds file g_Load3DS.Import3DS(&g_World, FILE_NAME); // Go through all the materials for(int i = 0; i < g_World.numOfMaterials; i++) { // Check to see if there is a file name to load in this material if(strlen(g_World.pMaterials[i].strFile) > 0) { // Use the name of the texture file to load the bitmap, with a texture ID (i). // We pass in our global texture array, the name of the texture, and an ID to reference it. CreateTexture(g_Texture[i], g_World.pMaterials[i].strFile); } // Set the texture ID for this material g_World.pMaterials[i].texureId = i; } // The first thing that needs to happen before creating our octree is to find // the total width of the initial root node. Now we pass in our t3DModel object // to GetSceneDimensions(), instead of vertices and a vertex count, as done // in the last octree tutorials. This will store the initial root node cube width. g_Octree.GetSceneDimensions(&g_World); // Since our model structures stores multiple objects, we can't easily access the // total triangle count in the scene with out manually going through and counting the total. // This is what we do below. With the result, we pass this into our CreateNode() function. int TotalTriangleCount = g_Octree.GetSceneTriangleCount(&g_World); // To create the first node we need the world data, the total triangle count in the scene, // along with the initial root node center and width. This function will then recursively // subdivide the rest of the world, according to the global restrictions. g_Octree.CreateNode(&g_World, TotalTriangleCount, g_Octree.GetCenter(), g_Octree.GetWidth()); // The octree should be created by now. To better increase our efficiency we use display // lists for every end node. This way, we just have to call a display list ID to draw // a node, verses the slow loops we normal had. Vertex arrays are also used to optimize // our rendering of the octree. // Below we get the display list base ID and store it in the root node. This should return 1 // since we don't use display lists anywhere before this. Notice that we use our global // variable that stores our end node count to pass in the total amount of list ID's needed. // If you are unfamiliar with displays, basically what you do is section off a certain // amount of ID's, and then you are returns a base pointer to the start of those ID's. // You can use the ID's from the base pointer to the base pointer ID + the number of // ID's that were saved off for that base pointer. Each of the ID's correspond to a // bunch of OpenGL commands. That means that each end node has it's own ID that // corresponds to a bunch of OpenGL commands. So, for instance, if pass in a bunch // of vertices to OpenGL, we can assign this action to a display list. That way we // just call a display list ID to perform that action. Think of it as a function. // You just need to call a function to do a bunch of tasks, which eliminates extra // code, and also is saved on the video card for faster processing. g_Octree.SetDisplayListID( glGenLists(g_EndNodeCount) ); // Now we go through every single end node and create a display list for them all. // That way, when we draw the end node, we just use it's display list ID to render // the node, instead of looping through all the objects and manually give the verts to opengl. // The parameters for this function is the node (starting with the root node), // the world data and current display list base ID. The base ID is stored in the root // node's ID, so we just pass that in. The reason we do this is because, if you create // other display lists before you create the octree, you don't want to assume the octree // ID's go from 1 to the end node count. By passing in the base ID, we then will add // this ID to other nodes. Right now, when they are created they are assigned the // end node count at the time upon creating them. This will make more sense when looking // at the octree code. g_Octree.CreateDisplayList(&g_Octree, &g_World, g_Octree.GetDisplayListID()); // Hide our cursor since we are using first person camera mode ShowCursor(FALSE); /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * glEnable(GL_LIGHT0); // Turn on a light with defaults set glEnable(GL_LIGHTING); // Turn on lighting glEnable(GL_COLOR_MATERIAL); // Allow color }