File: ModelRenderContainer.h

package info (click to toggle)
spring 106.0%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 55,316 kB
  • sloc: cpp: 543,954; ansic: 44,800; python: 12,575; java: 12,201; awk: 5,889; sh: 1,796; asm: 1,546; xml: 655; perl: 405; php: 211; objc: 194; makefile: 76; sed: 2
file content (102 lines) | stat: -rw-r--r-- 2,485 bytes parent folder | download | duplicates (3)
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
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef MODEL_RENDER_CONTAINER_HDR
#define MODEL_RENDER_CONTAINER_HDR

#define MDL_TYPE(o) (o->model->type)
#define TEX_TYPE(o) (o->model->textureType)

#include <array>
#include <vector>

#include "Rendering/Models/3DModel.h"
#include "System/ContainerUtil.h"

template<typename TObject>
class ModelRenderContainer {
private:
	// note: there can be no more texture-types than S3DModel instances
	std::array< int, MAX_MODEL_OBJECTS > keys;
	std::vector< std::vector<TObject*> > bins;

	typedef  typename decltype(bins)::value_type  ObjectBin;

	size_t numObjs = 0;
	size_t numBins = 0;

private:
	int CalcObjectBinIdx(const TObject* o) const { return (TEX_TYPE(o)); }

public:
	void Kill() {}
	void Init() {
		keys.fill(0);
		bins.reserve(32);

		// reuse inner vectors when reloading
		for (auto& bin: bins) {
			bin.clear();
		}

		numObjs = 0;
		numBins = 0;
	}


	void AddObject(const TObject* o) {
		const auto kb = keys.begin();
		const auto ke = keys.begin() + numBins;
		const auto ki = std::find(kb, ke, CalcObjectBinIdx(o));

		if (ki == ke)
			keys[numBins++] = CalcObjectBinIdx(o);

		if (bins.size() < numBins)
			bins.emplace_back();

		auto& bin = bins[ki - kb];

		if (bin.empty())
			bin.reserve(256);

		// numBins += (ki == ke);
		// cast since updating an object's draw-position requires mutability
		numObjs += spring::VectorInsertUnique(bin, const_cast<TObject*>(o));
	}

	void DelObject(const TObject* o) {
		const auto kb = keys.begin();
		const auto ke = keys.begin() + numBins;
		const auto ki = std::find(kb, ke, CalcObjectBinIdx(o));

		if (ki == ke)
			return;

		auto& bin = bins[ki - kb];

		// object can be legally absent from this container
		// e.g. UnitDrawer invokes DelObject on both opaque
		// and alpha containers (since it does not know the
		// cloaked state) which also means the tex-type key
		// might not exist here
		numObjs -= spring::VectorErase(bin, const_cast<TObject*>(o));
		numBins -= (bin.empty());

		if (!bin.empty())
			return;

		// keep empty bin, just remove it from the key-set
		std::swap(bins[ki - kb], bins[ke - 1 - kb]);
		std::swap(*ki, *(ke - 1));
	}


	unsigned int GetNumObjects() const { return numObjs; }
	unsigned int GetNumObjectBins() const { return numBins; }
	unsigned int GetObjectBinKey(unsigned int idx) const { return keys[idx]; }

	const ObjectBin& GetObjectBin(unsigned int idx) const { return bins[idx]; }
};

#endif