File: NodeLayer.cpp

package info (click to toggle)
spring 88.0%2Bdfsg1-1.1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 41,524 kB
  • sloc: cpp: 343,114; ansic: 38,414; python: 12,257; java: 12,203; awk: 5,748; sh: 1,204; xml: 997; perl: 405; objc: 192; makefile: 181; php: 134; sed: 2
file content (126 lines) | stat: -rwxr-xr-x 4,084 bytes parent folder | download
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
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#include "NodeLayer.hpp"
#include "PathManager.hpp"
#include "Node.hpp"
#include "Sim/Misc/GlobalSynced.h"
#include "Sim/MoveTypes/MoveInfo.h"
#include "Sim/MoveTypes/MoveMath/MoveMath.h"
#include "System/myMath.h"
#include "System/Rectangle.h"

#define PM QTPFS::PathManager

static int GetSpeedModBin(float absSpeedMod, float relSpeedMod) {
	// NOTE:
	//     bins N and N+1 are reserved for modifiers <= min and >= max
	//     respectively; blocked squares MUST be in their own category
	const int defBin = int(PM::NUM_SPEEDMOD_BINS * relSpeedMod);
	const int maxBin = int(PM::NUM_SPEEDMOD_BINS - 1);

	int speedModBin = Clamp(defBin, 0, maxBin);

	if (absSpeedMod <= PM::MIN_SPEEDMOD_VALUE) { speedModBin = PM::NUM_SPEEDMOD_BINS + 0; }
	if (absSpeedMod >= PM::MAX_SPEEDMOD_VALUE) { speedModBin = PM::NUM_SPEEDMOD_BINS + 1; }

	return speedModBin;
}



void QTPFS::NodeLayer::RegisterNode(INode* n) {
	for (unsigned int hmx = n->xmin(); hmx < n->xmax(); hmx++) {
		for (unsigned int hmz = n->zmin(); hmz < n->zmax(); hmz++) {
			nodeGrid[hmz * xsize + hmx] = n;
		}
	}
}

void QTPFS::NodeLayer::Init(unsigned int n) {
	// pre-count the root
	numLeafNodes = 1;
	layerNumber = n;

	xsize = gs->mapx;
	zsize = gs->mapy;

	nodeGrid.resize(xsize * zsize, NULL);

	curSpeedMods.resize(xsize * zsize, 0.0f);
	oldSpeedMods.resize(xsize * zsize, 0.0f);
	oldSpeedBins.resize(xsize * zsize, -1);
	curSpeedBins.resize(xsize * zsize, -1);
}

void QTPFS::NodeLayer::Clear() {
	nodeGrid.clear();

	curSpeedMods.clear();
	oldSpeedMods.clear();
	oldSpeedBins.clear();
	curSpeedBins.clear();
}

bool QTPFS::NodeLayer::Update(const SRectangle& r, const MoveData* md, const CMoveMath* mm) {
	// NOTE:
	//   we need a fixed range that does not become wider / narrower
	//   during terrain deformations (otherwise the bins would change
	//   across ALL nodes)
	static const float speedModRng = PM::MAX_SPEEDMOD_VALUE - PM::MIN_SPEEDMOD_VALUE;
	static const float minSpeedMod = PM::MIN_SPEEDMOD_VALUE;
	static const float maxSpeedMod = PM::MAX_SPEEDMOD_VALUE;

	#ifdef QTPFS_IGNORE_MAP_EDGES
	const unsigned int mdxsh = md->xsizeh;
	const unsigned int mdzsh = md->zsizeh;
	#endif

	unsigned int numNewBinSquares = 0;

	// divide speed-modifiers into bins
	for (unsigned int hmx = r.x1; hmx < r.x2; hmx++) {
		for (unsigned int hmz = r.z1; hmz < r.z2; hmz++) {
			const unsigned int sqrIdx = hmz * xsize + hmx;

			#ifdef QTPFS_IGNORE_MAP_EDGES
			const unsigned int smx = Clamp(hmx, mdxsh, r.x2 - mdxsh - 1);
			const unsigned int smz = Clamp(hmz, mdzsh, r.z2 - mdzsh - 1);
			#else
			const unsigned int smx = hmx;
			const unsigned int smz = hmz;
			#endif

			// NOTE: GetPosSpeedMod only checks terrain (height/slope/type), not the blocking-map
			const CMoveMath::BlockType blockBits = mm->IsBlockedNoSpeedModCheck(*md, smx, smz);

			const float rawAbsSpeedMod = mm->GetPosSpeedMod(*md, smx, smz);
			const float tmpAbsSpeedMod = Clamp(rawAbsSpeedMod, minSpeedMod, maxSpeedMod);
			const float newAbsSpeedMod = ((blockBits & CMoveMath::BLOCK_STRUCTURE) == 0)? tmpAbsSpeedMod: 0.0f;
			const float newRelSpeedMod = (newAbsSpeedMod - minSpeedMod) / speedModRng;
			const float curRelSpeedMod = curSpeedMods[sqrIdx];

			const int newSpeedModBin = GetSpeedModBin(newAbsSpeedMod, newRelSpeedMod);
			const int curSpeedModBin = curSpeedBins[sqrIdx];

			numNewBinSquares += (newSpeedModBin != curSpeedModBin)? 1: 0;

			// need to keep track of these for Tesselate
			oldSpeedMods[sqrIdx] = curRelSpeedMod;
			curSpeedMods[sqrIdx] = newRelSpeedMod;

			oldSpeedBins[sqrIdx] = curSpeedModBin;
			curSpeedBins[sqrIdx] = newSpeedModBin;
		}
	}

	// if at least one square changed bin, we need to re-tesselate
	// all nodes in the subtree of the deepest-level node that fully
	// contains <r>
	//
	// during initialization of the root this is true for ALL squares,
	// but we might NOT need to split it (ex. if the map is 100% flat)
	// if each square happened to change to the SAME bin
	//
	return (numNewBinSquares > 0);
}