File: ModelBreakdown.h

package info (click to toggle)
darkradiant 3.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 41,080 kB
  • sloc: cpp: 264,743; ansic: 10,659; python: 1,852; xml: 1,650; sh: 92; makefile: 21
file content (134 lines) | stat: -rw-r--r-- 2,569 bytes parent folder | download | duplicates (4)
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