TexGen
MeshOctreeClasses.cpp
Go to the documentation of this file.
1/*=============================================================================
2TexGen: Geometric textile modeller.
3Copyright (C) 2006 Martin Sherburn
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18=============================================================================*/
19
20#include "PrecompiledHeaders.h"
21#include "MeshOctreeClasses.h"
22#include "Mesh.h"
23
24using namespace TexGen;
25bool COctreeAgentNode::isOverlappingCell(const pair<int, XYZ>& item, const Vector3f& lowerCorner, const Vector3f& upperCorner) const
26{
27 return (item.second.x >= lowerCorner.getX() - m_dTolerance && item.second.y >= lowerCorner.getY() - m_dTolerance && item.second.z >= lowerCorner.getZ() - m_dTolerance &&
28 item.second.x <= upperCorner.getX() + m_dTolerance && item.second.y <= upperCorner.getY() + m_dTolerance && item.second.z <= upperCorner.getZ() + m_dTolerance);
29}
30
31dword COctreeAgentNode::getSubcellOverlaps(const pair<int, XYZ>& item, const Vector3f& lower, const Vector3f& middle, const Vector3f& upper) const
32{
36
37 dword flags = 0;
38
39 const Vector3f* lowMidPoints[] = { &lower, &middle };
40 const Vector3f* midHighPoints[] = { &middle, &upper };
41
42 for (dword i = 8; i-- > 0; )
43 {
44 Vector3f lowerCorner( lowMidPoints[ i & 1]->getX(),
45 lowMidPoints[(i >> 1) & 1]->getY(),
46 lowMidPoints[(i >> 2) & 1]->getZ() );
47 Vector3f upperCorner( midHighPoints[ i & 1]->getX(),
48 midHighPoints[(i >> 1) & 1]->getY(),
49 midHighPoints[(i >> 2) & 1]->getZ() );
50 flags |= dword(isOverlappingCell( item, lowerCorner, upperCorner )) << i;
51 }
52
53 return flags;
54}
55
56
57void COctreeVisitorMergeNodes::visitRoot(const OctreeCell* pRootCell, const OctreeData& octreeData)
58{
59 if (pRootCell != 0)
60 {
62// m_DeletedNodes.resize(m_Mesh.GetNumNodes(), false);
63
64 pRootCell->visit(octreeData, *this);
65
66// cout << "Num nodes removed " <<
68// cout << endl;
69 }
70}
71
72void COctreeVisitorMergeNodes::visitBranch(const OctreeCell* subCells[8], const OctreeData& octreeData)
73{
74 for (dword i = 0; i < 8; ++i)
75 {
76 const OctreeCell* pSubCell = subCells[i];
77 if(pSubCell != 0)
78 {
79 const OctreeData subCellData(octreeData, i);
80 pSubCell->visit(subCellData, *this);
81 }
82 }
83}
84
85void COctreeVisitorMergeNodes::visitLeaf(const Array<const pair<int, XYZ>*>& items, const OctreeData& octreeData)
86{
87 int i, j;
88 int iNumItems = items.getLength();
89 for (i=0; i<iNumItems; ++i)
90 {
91 // A possible optimisation would be j = i+1. However this causes nodes not to be merged correctly in rare cases, please leave it like this!
92 for (j=0; j<iNumItems; ++j)
93 {
94 if (i == j)
95 continue;
96 if (GetLengthSquared(items[i]->second, items[j]->second) < m_dToleranceSquared)
97 {
99 if (items[i]->first < items[j]->first)
100 {
101 m_Mesh.ChangeNodeIndices(items[i]->first, items[j]->first, m_NodeElementReferences);
102// m_DeletedNodes[items[j]->first] = true;
103 m_DeletedNodes.insert(items[j]->first);
104 }
105 else if (items[i]->first > items[j]->first)
106 {
107 m_Mesh.ChangeNodeIndices(items[j]->first, items[i]->first, m_NodeElementReferences);
108// m_DeletedNodes[items[i]->first] = true;
109 m_DeletedNodes.insert(items[i]->first);
110 }
111 else
112 assert(false);
113 }
114 }
115 }
116}
117
118bool COctreeAgentElement::isOverlappingCell(const MESH_ELEMENT& item, const Vector3f& lowerCorner, const Vector3f& upperCorner) const
119{
120 vector<int>::const_iterator itNodeIndex;
121 XYZ Min, Max;
122 for (itNodeIndex = item.NodeIndices.begin(); itNodeIndex != item.NodeIndices.end(); ++itNodeIndex)
123 {
124 cout << *itNodeIndex << endl;
125 if (itNodeIndex == item.NodeIndices.begin())
126 Min = Max = m_Mesh.GetNode(*itNodeIndex);
127 else
128 {
129 Min = TexGen::Min(Min, m_Mesh.GetNode(*itNodeIndex));
130 Max = TexGen::Max(Max, m_Mesh.GetNode(*itNodeIndex));
131 }
132 }
133 return (Max.x >= lowerCorner.getX() && Max.y >= lowerCorner.getY() && Max.z >= lowerCorner.getZ() &&
134 Min.x <= upperCorner.getX() && Min.y <= upperCorner.getY() && Min.z <= upperCorner.getZ());
135}
136
137dword COctreeAgentElement::getSubcellOverlaps(const MESH_ELEMENT& item, const Vector3f& lower, const Vector3f& middle, const Vector3f& upper) const
138{
139 vector<int>::const_iterator itNodeIndex;
140 XYZ Min, Max;
141 for (itNodeIndex = item.NodeIndices.begin(); itNodeIndex != item.NodeIndices.end(); ++itNodeIndex)
142 {
143 cout << *itNodeIndex << endl;
144 if (itNodeIndex == item.NodeIndices.begin())
145 Min = Max = m_Mesh.GetNode(*itNodeIndex);
146 else
147 {
148 Min = TexGen::Min(Min, m_Mesh.GetNode(*itNodeIndex));
149 Max = TexGen::Max(Max, m_Mesh.GetNode(*itNodeIndex));
150 }
151 }
152
153 dword flags = 0;
154
155 const Vector3f* lowMidPoints[] = { &lower, &middle };
156 const Vector3f* midHighPoints[] = { &middle, &upper };
157
158 for (dword i = 8; i-- > 0; )
159 {
160 Vector3f lowerCorner( lowMidPoints[ i & 1]->getX(),
161 lowMidPoints[(i >> 1) & 1]->getY(),
162 lowMidPoints[(i >> 2) & 1]->getZ() );
163 Vector3f upperCorner( midHighPoints[ i & 1]->getX(),
164 midHighPoints[(i >> 1) & 1]->getY(),
165 midHighPoints[(i >> 2) & 1]->getZ() );
166 if (Max.x >= lowerCorner.getX() && Max.y >= lowerCorner.getY() && Max.z >= lowerCorner.getZ() &&
167 Min.x <= upperCorner.getX() && Min.y <= upperCorner.getY() && Min.z <= upperCorner.getZ())
168 {
169 flags |= 1 << i;
170 }
171// flags |= dword(isOverlappingCell( item, lowerCorner, upperCorner )) << i;
172 }
173
174 return flags;
175}
176
177void COctreeVisitorElementNearLine::visitRoot(const OctreeCell* pRootCell, const OctreeData& octreeData)
178{
179 if (pRootCell != 0)
180 {
181 m_Used.clear();
182 pRootCell->visit(octreeData, *this);
183 }
184}
185
186void COctreeVisitorElementNearLine::visitBranch(const OctreeCell* subCells[8], const OctreeData& octreeData)
187{
188 const Vector3f &LowerCorner = octreeData.getBound().getLowerCorner();
189 const Vector3f &UpperCorner = octreeData.getBound().getUpperCorner();
190 const Vector3f &Center = octreeData.getBound().getCenter();
191 XYZ Bounds[3];
192 Bounds[0] = XYZ(LowerCorner.getX(), LowerCorner.getY(), LowerCorner.getZ()); // Min
193 Bounds[1] = XYZ(Center.getX(), Center.getY(), Center.getZ()); // Mid
194 Bounds[2] = XYZ(UpperCorner.getX(), UpperCorner.getY(), UpperCorner.getZ()); // Max
195 vector<bool> IntersectingCells;
196 IntersectingCells.resize(8, false);
197 XYZ P;
198 double u;
199 double dDenom;
200 int i, j;
201 int x, y, z;
202
204 // Find out if the line intersects any of the planes that build up the subcells
206
207 // i represents the plane direction (0 - x, 1 - y, 2 - z)
208 for (i=0; i<3; ++i)
209 {
210 x = i;
211 y = (i+1)%3;
212 z = (i+2)%3;
213 // j represents the plane distance (0 - min, 1 - mid, 2 - max)
214 dDenom = m_P2[x] - m_P1[x];
215 if (abs(dDenom) > 1e-6)
216 {
217 for (j=0; j<3; ++j)
218 {
219 u = (Bounds[j][x] - m_P1[x]) / dDenom;
220 if (u < 0 && m_TrimLine.first)
221 continue;
222 if (u > 1 && m_TrimLine.second)
223 continue;
224 P = m_P1 + (m_P2 - m_P1) * u;
225 if (Bounds[0][y] <= P[y] && P[y] <= Bounds[1][y])
226 {
227 if (Bounds[0][z] <= P[z] && P[z] <= Bounds[1][z])
228 {
229 if (j <= 2)
230 {
231 IntersectingCells[(0<<x) | (0<<y) | (0<<z)] = true;
232 }
233 if (j >= 0)
234 {
235 IntersectingCells[(1<<x) | (0<<y) | (0<<z)] = true;
236 }
237 }
238 else if (Bounds[1][z] <= P[z] && P[z] <= Bounds[2][z])
239 {
240 if (j <= 2)
241 {
242 IntersectingCells[(0<<x) | (0<<y) | (1<<z)] = true;
243 }
244 if (j >= 0)
245 {
246 IntersectingCells[(1<<x) | (0<<y) | (1<<z)] = true;
247 }
248 }
249 }
250 else if (Bounds[1][y] <= P[y] && P[y] <= Bounds[2][y])
251 {
252 if (Bounds[0][z] <= P[z] && P[z] <= Bounds[1][z])
253 {
254 if (j <= 2)
255 {
256 IntersectingCells[(0<<x) | (1<<y) | (0<<z)] = true;
257 }
258 if (j >= 0)
259 {
260 IntersectingCells[(1<<x) | (1<<y) | (0<<z)] = true;
261 }
262 }
263 else if (Bounds[1][z] <= P[z] && P[z] <= Bounds[2][z])
264 {
265 if (j <= 2)
266 {
267 IntersectingCells[(0<<x) | (1<<y) | (1<<z)] = true;
268 }
269 if (j >= 0)
270 {
271 IntersectingCells[(1<<x) | (1<<y) | (1<<z)] = true;
272 }
273 }
274 }
275 }
276 }
277 }
278
280 // Find out if one of the line ends is inside the cell if both m_TrimLine are set
282
283 if (m_TrimLine.first && m_TrimLine.second)
284 {
285 if (m_P1.x >= Bounds[0].x && m_P1.y >= Bounds[0].y && m_P1.z >= Bounds[0].z &&
286 m_P1.x <= Bounds[2].x && m_P1.y <= Bounds[2].y && m_P1.z <= Bounds[2].z)
287 {
288 dword dwCell = 0;
289 if (m_P1.x > Bounds[1].x)
290 dwCell |= 1 << 0;
291 if (m_P1.y > Bounds[1].y)
292 dwCell |= 1 << 1;
293 if (m_P1.z > Bounds[1].z)
294 dwCell |= 1 << 2;
295 IntersectingCells[dwCell] = true;
296 }
297 }
298
299
300 for (dword i = 0; i < 8; ++i)
301 {
302 const OctreeCell* pSubCell = subCells[i];
303 if(IntersectingCells[i] == true && pSubCell != 0)
304 {
305 const OctreeData subCellData(octreeData, i);
306 pSubCell->visit(subCellData, *this);
307 }
308 }
309}
310
311void COctreeVisitorElementNearLine::visitLeaf(const Array<const MESH_ELEMENT*>& items, const OctreeData& octreeData)
312{
313 int i;
314 int iNumItems = items.getLength();
315 for (i=0; i<iNumItems; ++i)
316 {
317 const MESH_ELEMENT &Element = *items[i];
318 if (Element.iIndex >= (int)m_Used.size())
319 {
320 m_Used.resize(Element.iIndex+1, false);
321 }
322 if (m_Used[Element.iIndex] == false)
323 {
324 m_Elements.push_back(Element.NodeIndices);
325 m_Used[Element.iIndex] = true;
326 }
327 }
328}
329
330
331
332
void ChangeNodeIndices(int iChangeTo, int iChangeFrom)
Change all the indices from one number to another.
Definition: Mesh.cpp:107
void GetNodeElementReferences(vector< vector< int * > > &References)
Get a list of elements which reference each node.
Definition: Mesh.cpp:1504
const XYZ & GetNode(int iIndex) const
Get the node with given ID.
Definition: Mesh.cpp:2636
int DeleteNodes(const set< int > &Nodes)
Delete nodes and adjust node indices.
Definition: Mesh.cpp:728
dword getSubcellOverlaps(const MESH_ELEMENT &item, const Vector3f &lower, const Vector3f &middle, const Vector3f &upper) const
bool isOverlappingCell(const MESH_ELEMENT &item, const Vector3f &lowerCorner, const Vector3f &upperCorner) const
bool isOverlappingCell(const pair< int, XYZ > &item, const Vector3f &lowerCorner, const Vector3f &upperCorner) const
dword getSubcellOverlaps(const pair< int, XYZ > &item, const Vector3f &lower, const Vector3f &middle, const Vector3f &upper) const
void visitBranch(const OctreeCell *subCells[8], const OctreeData &octreeData)
void visitRoot(const OctreeCell *pRootCell, const OctreeData &octreeData)
void visitLeaf(const Array< const MESH_ELEMENT * > &items, const OctreeData &octreeData)
void visitBranch(const OctreeCell *subCells[8], const OctreeData &octreeData)
void visitRoot(const OctreeCell *pRootCell, const OctreeData &octreeData)
void visitLeaf(const Array< const pair< int, XYZ > * > &items, const OctreeData &octreeData)
vector< vector< int * > > m_NodeElementReferences
Namespace containing a series of customised math operations not found in the standard c++ library.
double GetLengthSquared(const XYZ &Point1, const XYZ &Point2)
Get the length squared between two points.
Definition: mymath.h:548
double Max(XYZ &Vector)
Get maximum element of vector and return it.
Definition: mymath.h:642
XYZ Min(const XYZ &P1, const XYZ &P2)
Given two points, return a new point who's coordinates are the smaller of the two.
Definition: mymath.h:1142
Elements of a given, is used in conjunction with COctreeAgentElement.
vector< int > NodeIndices
Struct for representing points in 3D space.
Definition: mymath.h:56
double z
Definition: mymath.h:57
double x
Definition: mymath.h:57
double y
Definition: mymath.h:57