SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GridSectorizer.cpp
Go to the documentation of this file.
1 /*
2 * Original work: Copyright (c) 2014, Oculus VR, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2017, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
16 #include "slikenet/assert.h"
17 #include "slikenet/GridSectorizer.h"
18 //#include <stdlib.h>
19 #include <math.h>
20
21 GridSectorizer::GridSectorizer()
22 {
23 grid=0;
24 }
25 GridSectorizer::~GridSectorizer()
26 {
27 if (grid)
28 SLNet::OP_DELETE_ARRAY(grid, _FILE_AND_LINE_);
29 }
30 void GridSectorizer::Init(const float _maxCellWidth, const float _maxCellHeight, const float minX, const float minY, const float maxX, const float maxY)
31 {
32 RakAssert(_maxCellWidth > 0.0f && _maxCellHeight > 0.0f);
33 if (grid)
34 SLNet::OP_DELETE_ARRAY(grid, _FILE_AND_LINE_);
35
36 cellOriginX=minX;
37 cellOriginY=minY;
38 gridWidth=maxX-minX;
39 gridHeight=maxY-minY;
40 gridCellWidthCount=(int) ceil(gridWidth/_maxCellWidth);
41 gridCellHeightCount=(int) ceil(gridHeight/_maxCellHeight);
42 // Make the cells slightly smaller, so we allocate an extra unneeded cell if on the edge. This way we don't go outside the array on rounding errors.
43 cellWidth=gridWidth/gridCellWidthCount;
44 cellHeight=gridHeight/gridCellHeightCount;
45 invCellWidth = 1.0f / cellWidth;
46 invCellHeight = 1.0f / cellHeight;
47
48 #ifdef _USE_ORDERED_LIST
49 grid = SLNet::OP_NEW<DataStructures::OrderedList<void*, void*>>(gridCellWidthCount*gridCellHeightCount, _FILE_AND_LINE_ );
50 DataStructures::OrderedList<void*,void*>::IMPLEMENT_DEFAULT_COMPARISON();
51 #else
52 grid = SLNet::OP_NEW_ARRAY<DataStructures::List<void*> >(gridCellWidthCount*gridCellHeightCount, _FILE_AND_LINE_ );
53 #endif
54 }
55 void GridSectorizer::AddEntry(void *entry, const float minX, const float minY, const float maxX, const float maxY)
56 {
57 RakAssert(cellWidth>0.0f);
58 RakAssert(minX < maxX && minY < maxY);
59
60 int xStart, yStart, xEnd, yEnd, xCur, yCur;
61 xStart=WorldToCellXOffsetAndClamped(minX);
62 yStart=WorldToCellYOffsetAndClamped(minY);
63 xEnd=WorldToCellXOffsetAndClamped(maxX);
64 yEnd=WorldToCellYOffsetAndClamped(maxY);
65
66 for (xCur=xStart; xCur <= xEnd; ++xCur)
67 {
68 for (yCur=yStart; yCur <= yEnd; ++yCur)
69 {
70 #ifdef _USE_ORDERED_LIST
71 grid[yCur*gridCellWidthCount+xCur].Insert(entry,entry, true);
72 #else
73 grid[yCur*gridCellWidthCount+xCur].Insert(entry, _FILE_AND_LINE_);
74 #endif
75 }
76 }
77 }
78 #ifdef _USE_ORDERED_LIST
79 void GridSectorizer::RemoveEntry(void *entry, const float minX, const float minY, const float maxX, const float maxY)
80 {
81 RakAssert(cellWidth>0.0f);
82 RakAssert(minX <= maxX && minY <= maxY);
83
84 int xStart, yStart, xEnd, yEnd, xCur, yCur;
85 xStart=WorldToCellXOffsetAndClamped(minX);
86 yStart=WorldToCellYOffsetAndClamped(minY);
87 xEnd=WorldToCellXOffsetAndClamped(maxX);
88 yEnd=WorldToCellYOffsetAndClamped(maxY);
89
90 for (xCur=xStart; xCur <= xEnd; ++xCur)
91 {
92 for (yCur=yStart; yCur <= yEnd; ++yCur)
93 {
94 grid[yCur*gridCellWidthCount+xCur].RemoveIfExists(entry);
95 }
96 }
97 }
98 void GridSectorizer::MoveEntry(void *entry, const float sourceMinX, const float sourceMinY, const float sourceMaxX, const float sourceMaxY,
99 const float destMinX, const float destMinY, const float destMaxX, const float destMaxY)
100 {
101 RakAssert(cellWidth>0.0f);
102 RakAssert(sourceMinX < sourceMaxX && sourceMinY < sourceMaxY);
103 RakAssert(destMinX < destMaxX && destMinY < destMaxY);
104
105 if (PositionCrossesCells(sourceMinX, sourceMinY, destMinX, destMinY)==false &&
106 PositionCrossesCells(destMinX, destMinY, destMinX, destMinY)==false)
107 return;
108
109 int xStartSource, yStartSource, xEndSource, yEndSource;
110 int xStartDest, yStartDest, xEndDest, yEndDest;
111 int xCur, yCur;
112 xStartSource=WorldToCellXOffsetAndClamped(sourceMinX);
113 yStartSource=WorldToCellYOffsetAndClamped(sourceMinY);
114 xEndSource=WorldToCellXOffsetAndClamped(sourceMaxX);
115 yEndSource=WorldToCellYOffsetAndClamped(sourceMaxY);
116
117 xStartDest=WorldToCellXOffsetAndClamped(destMinX);
118 yStartDest=WorldToCellYOffsetAndClamped(destMinY);
119 xEndDest=WorldToCellXOffsetAndClamped(destMaxX);
120 yEndDest=WorldToCellYOffsetAndClamped(destMaxY);
121
122 // Remove source that is not in dest
123 for (xCur=xStartSource; xCur <= xEndSource; ++xCur)
124 {
125 for (yCur=yStartSource; yCur <= yEndSource; ++yCur)
126 {
127 if (xCur < xStartDest || xCur > xEndDest ||
128 yCur < yStartDest || yCur > yEndDest)
129 {
130 grid[yCur*gridCellWidthCount+xCur].RemoveIfExists(entry);
131 }
132 }
133 }
134
135 // Add dest that is not in source
136 for (xCur=xStartDest; xCur <= xEndDest; ++xCur)
137 {
138 for (yCur=yStartDest; yCur <= yEndDest; ++yCur)
139 {
140 if (xCur < xStartSource || xCur > xEndSource ||
141 yCur < yStartSource || yCur > yEndSource)
142 {
143 grid[yCur*gridCellWidthCount+xCur].Insert(entry,entry, true);
144 }
145 }
146 }
147 }
148 #endif
149 void GridSectorizer::GetEntries(DataStructures::List<void*>& intersectionList, const float minX, const float minY, const float maxX, const float maxY)
150 {
151 #ifdef _USE_ORDERED_LIST
152 DataStructures::OrderedList<void*, void*>* cell;
153 #else
154 DataStructures::List<void*>* cell;
155 #endif
156 int xStart, yStart, xEnd, yEnd, xCur, yCur;
157 unsigned index;
158 xStart=WorldToCellXOffsetAndClamped(minX);
159 yStart=WorldToCellYOffsetAndClamped(minY);
160 xEnd=WorldToCellXOffsetAndClamped(maxX);
161 yEnd=WorldToCellYOffsetAndClamped(maxY);
162
163 intersectionList.Clear(true, _FILE_AND_LINE_);
164 for (xCur=xStart; xCur <= xEnd; ++xCur)
165 {
166 for (yCur=yStart; yCur <= yEnd; ++yCur)
167 {
168 cell = grid+yCur*gridCellWidthCount+xCur;
169 for (index=0; index < cell->Size(); ++index)
170 intersectionList.Insert(cell->operator [](index), _FILE_AND_LINE_);
171 }
172 }
173 }
174 bool GridSectorizer::PositionCrossesCells(const float originX, const float originY, const float destinationX, const float destinationY) const
175 {
176 return originX/cellWidth!=destinationX/cellWidth || originY/cellHeight!=destinationY/cellHeight;
177 }
178 int GridSectorizer::WorldToCellX(const float input) const
179 {
180 return (int)((input-cellOriginX)*invCellWidth);
181 }
182 int GridSectorizer::WorldToCellY(const float input) const
183 {
184 return (int)((input-cellOriginY)*invCellHeight);
185 }
186 int GridSectorizer::WorldToCellXOffsetAndClamped(const float input) const
187 {
188 int cell=WorldToCellX(input);
189 cell = cell > 0 ? cell : 0; // __max(cell,0);
190 cell = gridCellWidthCount-1 < cell ? gridCellWidthCount-1 : cell; // __min(gridCellWidthCount-1, cell);
191 return cell;
192 }
193 int GridSectorizer::WorldToCellYOffsetAndClamped(const float input) const
194 {
195 int cell=WorldToCellY(input);
196 cell = cell > 0 ? cell : 0; // __max(cell,0);
197 cell = gridCellHeightCount-1 < cell ? gridCellHeightCount-1 : cell; // __min(gridCellHeightCount-1, cell);
198 return cell;
199 }
200 void GridSectorizer::Clear(void)
201 {
202 int cur;
203 int count = gridCellWidthCount*gridCellHeightCount;
204 for (cur=0; cur<count;cur++)
205 grid[cur].Clear(true, _FILE_AND_LINE_);
206 }