0

So I have a sorting problem. What I want to do is construct an octree around the camera position, copy the leaf node data to a temporary container, then reset the octree and enter a new camera position. After this, check if any of the new node positions are in the old leaf nodes, and only update the data in the positions that have changed. The result should be that the positions closest to the camera have a higher level of detail and a larger number of nodes, as the octree is subdivided based on how close the node's center is to the camera position.

The image below illustrates this simply. If the black boxes represent the octree leaf nodes from the old camera position, none of them would be included in the new set as their centers are not the same as any of the pink boxes. Two overlapping octrees

Obviously, the result I'm getting with my code isn't what it should be. There are huge areas of terrain that don't load the new positions properly/overlap with existing terrain. enter image description here

I'm using an unordered set for the leaf nodes, as each one's position should be unique, and an unordered map for the chunks I want to load, so that I can load the correct chunk based on the key which is the position of the leafnode.

In the code, I update the list of chunks to create only if the amount of nodes in the world changes: if (tempNodes.size() != _octree->leafNodes.size()) The rest of the logic pertains to what I've already been explaining. It might just be some simple mistake, but I also might just be misinterpreting the way certain member functions work.

void LandscapeManager::updateCenter(glm::ivec3 newCenter)
{
    std::unordered_set<Octree*> tempNodes;
    tempNodes = _octree->leafNodes;

    // reconstruct octree
    delete _octree;
    _octree = new Octree(glm::vec3(0, 0, 0), glm::vec3(pow(2, 8), pow(2, 8), pow(2, 8)));

    // update camera position in octree
    _octree->leafNodes.clear();
    _octree->insert(newCenter);

    std::cout << "Generating: " << _octree->leafNodes.size() << " chunks...\n";

    if (tempNodes.size() != _octree->leafNodes.size())
    {

        // clear chunk list and refresh with new list generated by code below
        _chunkLoader.Clear();
        
        for (auto i : _octree->leafNodes)
        {
            // add a chunk to the chunkloader if it's position does not exist in the old octree's leaf nodes
            if (!tempNodes.count(i))
            {
                _chunkLoader.Add(i->getOrigin(), i->getHalfSize());
            }
            if (tempNodes.count(i))
            {
                // remove unchanged leaf nodes from the old list so that all
                // the remains is a list of changed leaf nodes, which will be used to delete old chunks
                tempNodes.erase(tempNodes.find(i));
            }
        
        }
        
        for (auto i : tempNodes)
        {
            if (_chunks.count(i->getOrigin()))
            {
                // unload and delete the meshes that have changed 
                auto unload = _chunks.find(i->getOrigin());
                _chunks.at(i->getOrigin())->Unload();
                delete _chunks.at(i->getOrigin());
                _chunks.erase(unload);
                
            }
        }

    }

    _center = newCenter;
}
  • Try to replace raw pointer and dynamic memory allocation with smart pointers. We do not know if you're handling the dynamic memory management correctly. Second, you should be debugging your code to see exactly what those values are that you're dealing with. – PaulMcKenzie Jul 16 '20 at 20:41
  • Thanks, I just realized I should not be copying the tempNodes as pointers. How would I dereference the ```tempNodes = _octree->leafNodes``` if ```std::unordered_set tempNodes;```? Is it something I should do in the overloaded assignment operator of Octree? – HeartUnder8lade Jul 16 '20 at 21:05
  • Until you sort out who owns the pointers, a `std::unordered_set>` may be a better choice. Then when the last entity to hold the pointer gets destroyed, the pointer automatically gets deleted (no need to call `delete` manually -- just `erase` alone will reduce the reference count). – PaulMcKenzie Jul 16 '20 at 21:15
  • Ok, I've sorted out the pointers and there is no longer undefined behavior, however, now every time I call the function, it replaces all chunks in the octree. Other than the changes to the pointers, the algorithm is the same – HeartUnder8lade Jul 16 '20 at 23:13

0 Answers0