1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
#pragma once
#include <map>
#include <string>
#include "iscenegraph.h"
#include "imodel.h"
#include "modelskin.h"
namespace scene
{
/**
* greebo: This object traverses the scenegraph on construction
* counting all occurrences of each model (plus skins).
*/
class ModelBreakdown :
public scene::NodeVisitor
{
public:
struct ModelCount
{
std::size_t count;
std::size_t polyCount;
typedef std::map<std::string, std::size_t> SkinCountMap;
SkinCountMap skinCount;
ModelCount() :
count(0)
{}
};
// The map associating model names with occurrences
typedef std::map<std::string, ModelCount> Map;
private:
mutable Map _map;
public:
ModelBreakdown()
{
_map.clear();
GlobalSceneGraph().root()->traverseChildren(*this);
}
bool pre(const scene::INodePtr& node) override
{
// Check if this node is a model
model::ModelNodePtr modelNode = Node_getModel(node);
if (modelNode)
{
// Get the actual model from the node
const model::IModel& model = modelNode->getIModel();
Map::iterator found = _map.find(model.getModelPath());
if (found == _map.end())
{
auto result = _map.emplace(model.getModelPath(), ModelCount());
found = result.first;
// Store the polycount in the map
found->second.polyCount = model.getPolyCount();
found->second.skinCount.clear();
}
// The iterator "found" is valid at this point
// Get a shortcut reference
ModelCount& modelCount = found->second;
modelCount.count++;
// Increase the skin count, check if we have a skinnable model
auto skinned = std::dynamic_pointer_cast<SkinnedModel>(node);
if (skinned)
{
std::string skinName = skinned->getSkin();
auto foundSkin = modelCount.skinCount.find(skinName);
if (foundSkin == modelCount.skinCount.end())
{
auto result = modelCount.skinCount.emplace(skinName, 0);
foundSkin = result.first;
}
foundSkin->second++;
}
}
return true;
}
// Accessor method to retrieve the entity breakdown map
const Map& getMap() const
{
return _map;
}
std::size_t getNumSkins() const
{
std::set<std::string> skinMap;
// Determine the number of distinct skins
for (auto m = _map.begin(); m != _map.end(); ++m)
{
for (auto s = m->second.skinCount.begin(); s != m->second.skinCount.end(); ++s)
{
if (!s->first.empty())
{
skinMap.insert(s->first);
}
}
}
return skinMap.size();
}
Map::const_iterator begin() const
{
return _map.begin();
}
Map::const_iterator end() const
{
return _map.end();
}
};
} // namespace
|