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 // Position our camera g_Camera.PositionCamera(0, 30, 120, 0, 0, 0, 0, 1, 0); // This loads the vertices for the terrain LoadVertices(); // Calculate the bounding box of our scene. This will give us a width of // the cube that is needed to surround the whole world. We want to pass in // the vertices and the vertex count into this function to find the farthest point // from the center of the world. That will then be our width. Depending on the // world this doesn't always surround it perfectly. In the next tutorial we will fix that. g_Octree.GetSceneDimensions(g_pVertices, g_NumberOfVerts); // Here we pass in the information to create the root node. This will then // recursively subdivide the root node into the rest of the node. g_Octree.CreateNode(g_pVertices, g_NumberOfVerts, g_Octree.GetCenter(), g_Octree.GetWidth()); // Here, we turn on a light and enable lighting. We don't need to // set anything else for lighting because we will just take the defaults. // We also want color, so we turn that on too. We don't load any normals from // our .raw file so we will calculate some simple face normals to get a decent // perspective of the terrain. glEnable(GL_LIGHT0); // Turn on a light with defaults set glEnable(GL_LIGHTING); // Turn on lighting glEnable(GL_COLOR_MATERIAL); // Allow color }
void RecreateOctree() { // You will not need this function for the octree. It is just for the tutorial // every time we change our subdivision information. g_EndNodeCount = 0; // Reset the end node count g_Debug.Clear(); // Clear the list of debug lines g_Octree.DestroyOctree(); // Destroy the octree and start again // Get the new scene dimensions since we destroyed the previous octree g_Octree.GetSceneDimensions(g_pVertices, g_NumberOfVerts); // Create our new octree with the new subdivision information g_Octree.CreateNode(g_pVertices, g_NumberOfVerts, g_Octree.GetCenter(), g_Octree.GetWidth()); }
UITRANSFORMAXIS CMapTranslate::selectAxis(const CRay& ray, float zNear, float zFar) { COctree oct; for(int i=0;i<3;i++) { oct.set(m_axisBoxesLo[i], m_axisBoxesHi[i]); oct.translate(m_pos); if(oct.intersect(ray, zNear, zFar)) { TheUITransform::Instance().axis = (UITRANSFORMAXIS)i; this->createWidget(); return (UITRANSFORMAXIS)i; } } return uiaFree; }
void CFieldCache::NotifyFieldBoundsChanged( const COctree& bounds ) { if (bounds.isValid()) { m_pCache->SetVoxelSize( bounds, CFieldCacheManager::Get()->GetDefaultCacheResolution() ); } else { m_pCache->SetVoxelSize(m_children[0]->getOctree(), CFieldCacheManager::Get()->GetDefaultCacheResolution() ); } }
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 RenderScene() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // Reset The matrix // Position the camera g_Camera.Look(); // Each frame we calculate the new frustum. In reality you only need to // calculate the frustum when we move the camera. g_Frustum.CalculateFrustum(); // Initialize the total node count that is being draw per frame g_TotalNodesDrawn = 0; /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // Here we draw the octree, starting with the root node and recursing down each node. // This time, we pass in the root node and just the original world model. You could // just store the world in the root node and not have to keep the original data around. // This is up to you. I like this way better because it's easy, though it could be // more error prone. g_Octree.DrawOctree(&g_Octree, &g_World); // Render the cubed nodes to visualize the octree (in wire frame mode) if( g_bDisplayNodes ) g_Debug.RenderDebugLines(); // Create a buffer to store the octree information for the title bar static char strBuffer[255] = {0}; // Display in window mode the current subdivision information. We now display the // max triangles per node, the max level of subdivision, total end nodes, current nodes drawn // and frames per second we are receiving. sprintf(strBuffer, "Triangles: %d Subdivisions: %d EndNodes: %d NodesDraw: %d FPS: %s", g_MaxTriangles, g_MaxSubdivisions, g_EndNodeCount, g_TotalNodesDrawn, g_strFrameRate); /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // Set our window title bar to the subdivision information SetWindowText(g_hWnd, strBuffer); // Swap the backbuffers to the foreground SwapBuffers(g_hDC); }
void RenderScene() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer glLoadIdentity(); // Reset The matrix // Give OpenGL our camera position g_Camera.Look(); /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // Each frame we calculate the new frustum. In reality you only need to // calculate the frustum when we move the camera. g_Frustum.CalculateFrustum(); // Initialize the total node count that is being draw per frame g_TotalNodesDrawn = 0; /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // Here we draw the octree, starting with the root node and recursing down each node. // When we get to each of the end nodes we will draw the vertices assigned to them. g_Octree.DrawOctree(&g_Octree); // Render the cube'd nodes to visualize the octree (in wire frame mode) g_Debug.RenderDebugLines(); SwapBuffers(g_hDC); // Swap the backbuffers to the foreground char strBuffer[255] = {0}; // Create a character buffer // To view our octree information I set the window's title bar to the some basic // information such as the max triangles per node, the max subdivisions, // total end nodes and the total drawn end nodes that are currently in the frustum. // Display in window mode the current subdivision information sprintf(strBuffer, "MaxTriangles: %d MaxSubdivisions: %d TotalEndNodes: %d TotalNodesDraw: %d", g_MaxTriangles, g_MaxSubdivisions, g_EndNodeCount, g_TotalNodesDrawn); // Set our window title bar to the subdivision data SetWindowText(g_hWnd, strBuffer); }
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 }