[4378] * src/shared/vmap/: Applied MaNGOS coding style, set
[mangos-git.git] / src / shared / vmap / SubModel.cpp
blobe16061357ccaab582ed37917e6f6bcc5ec9b547b
1 /*
2 * Copyright (C) 2005,2006,2007 MaNGOS <http://www.mangosproject.org/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "SubModel.h"
21 #ifdef _ASSEMBLER_DEBUG
22 extern FILE *::g_df;
23 #endif
25 namespace VMAP
28 //==========================================================
29 /**
30 Functions to use ModelContainer with a AABSPTree
32 unsigned int hashCode(const SubModel& pSm)
34 return pSm.getNTriangles();
37 bool operator==(const SubModel& pSm1, const SubModel& pSm2)
39 bool result = false;
41 if(pSm1.getNNodes() == pSm2.getNNodes() &&
42 pSm1.getNTriangles() == pSm2.getNTriangles() &&
43 pSm1.getBasePosition() == pSm2.getBasePosition() &&
44 pSm1.getNodesPos() == pSm2.getNodesPos() &&
45 pSm1.getTrianglesPos() == pSm2.getTrianglesPos())
47 result = true;
49 return result;
52 void getBounds(const SubModel& pSm, G3D::AABox& pAABox)
54 ShortBox box = pSm.getReletiveBounds();
55 pAABox.set(box.getLo().getVector3()+pSm.getBasePosition(), box.getHi().getVector3()+pSm.getBasePosition());
58 void getBounds(const SubModel* pSm, G3D::AABox& pAABox)
60 ShortBox box = pSm->getReletiveBounds();
61 pAABox.set(box.getLo().getVector3()+pSm->getBasePosition(), box.getHi().getVector3()+pSm->getBasePosition());
64 //==========================================================
65 //==========================================================
66 //==========================================================
67 //==========================================================
68 SubModel::SubModel(unsigned int pNTriangles, TriangleBox *pTriangles, unsigned int pTrianglesPos, unsigned int pNNodes, TreeNode *pTreeNodes, unsigned int pNodesPos) :
69 BaseModel(pNNodes, pTreeNodes, pNTriangles, pTriangles)
71 iTrianglesPos = pTrianglesPos;
72 iNodesPos = pNodesPos;
73 iHasInternalMemAlloc = false;
76 //==========================================================
78 SubModel::~SubModel(void)
80 if(iHasInternalMemAlloc)
82 free();
86 //==========================================================
88 enum BIN_POSITIONS
90 BP_iNTriangles=8,
91 BP_iNNodes=12,
92 BP_iBasePosition=16,
93 BP_iNodesPos=28,
94 BP_iTrianglesPos=32,
95 BP_iHasInternalMemAlloc=36,
96 BP_iBox=38,
98 /**
99 This is ugly, but due to compatibility and 64 bit support we have to do that ... sorry
101 void SubModel::initFromBinBlock(void *pBinBlock)
103 iNTriangles = *((unsigned int *)(((char *) pBinBlock) + BP_iNTriangles));
104 iNNodes = *((unsigned int *) (((char *) pBinBlock) + BP_iNNodes));
105 iBasePosition = *((Vector3 *) (((char *) pBinBlock) + BP_iBasePosition));
106 iNodesPos = *((unsigned int *) (((char *) pBinBlock) + BP_iNodesPos));
107 iTrianglesPos = *((unsigned int *) (((char *) pBinBlock) + BP_iTrianglesPos));
108 iHasInternalMemAlloc = *((bool *) (((char *) pBinBlock) + BP_iHasInternalMemAlloc));
109 iBox = *((ShortBox *) (((char *) pBinBlock) + BP_iBox));
112 //==========================================================
114 void SubModel::countNodesAndTriangles(AABSPTree<Triangle>::Node& pNode, int &pNNodes, int &pNTriabgles)
116 pNNodes++;
117 pNTriabgles += pNode.valueArray.size();
119 #ifdef _ASSEMBLER_DEBUG
120 fprintf(::g_df, "Nodes: %d, Tris: %d\n",pNNodes, pNTriabgles);
121 #endif
123 if(pNode.child[0] != 0)
125 countNodesAndTriangles(*pNode.child[0], pNNodes, pNTriabgles);
127 if(pNode.child[1] != 0)
129 countNodesAndTriangles(*pNode.child[1], pNNodes, pNTriabgles);
133 //==========================================================
135 void SubModel::fillContainer(const AABSPTree<Triangle>::Node& pNode, int &pTreeNodePos, int &pTrianglePos, Vector3& pLo, Vector3& pHi)
137 TreeNode treeNode = TreeNode(pNode.valueArray.size(), pTrianglePos);
138 treeNode.setSplitAxis(pNode.splitAxis);
139 treeNode.setSplitLocation(pNode.splitLocation);
141 int currentTreeNodePos = pTreeNodePos++;
143 Vector3 lo = Vector3(inf(),inf(),inf());
144 Vector3 hi = Vector3(-inf(),-inf(),-inf());
146 for(int i=0;i<pNode.valueArray.size(); i++)
148 AABSPTree<Triangle>::Handle h= pNode.valueArray[i];
149 Triangle t = h.value;
150 TriangleBox triangleBox = TriangleBox(t.vertex(0),t.vertex(1), t.vertex(2));
151 lo = lo.min(triangleBox.getBounds().getLo().getVector3());
152 hi = hi.max(triangleBox.getBounds().getHi().getVector3());
154 getTriangles()[pTrianglePos++] = triangleBox;
157 if(pNode.child[0] != 0)
159 treeNode.setChildPos(0, pTreeNodePos);
160 fillContainer(*pNode.child[0], pTreeNodePos, pTrianglePos, lo, hi);
162 if(pNode.child[1] != 0)
164 treeNode.setChildPos(1, pTreeNodePos);
165 fillContainer(*pNode.child[1], pTreeNodePos, pTrianglePos, lo, hi);
168 treeNode.setBounds(lo,hi);
170 // get absolute bounds
171 pLo = pLo.min(lo);
172 pHi = pHi.max(hi);
174 getTreeNodes()[currentTreeNodePos] = treeNode;
177 //==========================================================
179 SubModel::SubModel(AABSPTree<Triangle> *pTree)
181 int nNodes, nTriangles;
182 nNodes = nTriangles = 0;
183 countNodesAndTriangles(*pTree->root, nNodes, nTriangles);
185 init(nNodes, nTriangles);
187 iTrianglesPos = 0; // this is the global array
188 iNodesPos = 0; // this is the global array
189 iHasInternalMemAlloc = true;
190 int treeNodePos, trianglePos;
191 treeNodePos = trianglePos = 0;
193 Vector3 lo = Vector3(inf(),inf(),inf());
194 Vector3 hi = Vector3(-inf(),-inf(),-inf());
196 fillContainer(*pTree->root, treeNodePos, trianglePos, lo, hi);
197 setReletiveBounds(lo, hi);
200 //==========================================================
202 RayIntersectionIterator<TreeNode, TriangleBox> SubModel::beginRayIntersection(const Ray& ray, double pMaxTime, bool skipAABoxTests) const
204 NodeValueAccess<TreeNode, TriangleBox> vna = NodeValueAccess<TreeNode, TriangleBox>(getTreeNodes(), getTriangles());
205 return RayIntersectionIterator<TreeNode, TriangleBox>(vna, ray, &getTreeNode(0), pMaxTime, skipAABoxTests);
208 RayIntersectionIterator<TreeNode, TriangleBox> SubModel::endRayIntersection() const
210 return RayIntersectionIterator<TreeNode, TriangleBox>();
213 //==========================================================================
215 typedef RayIntersectionIterator<TreeNode, TriangleBox> IT;
217 inline RealTime testIntersectionWithTriangle(const IT& pIterater,const Triangle& pTriangle, const Ray& pRay)
219 static const double epsilon = 0.00001;
221 RealTime t = pRay.intersectionTime(pTriangle);
223 Often methods like "distanceUntilIntersection" can be made more
224 efficient by providing them with the time at which to start and
225 to give up looking for an intersection; that is,
226 obj.minDistance and iMin(firstDistance, obj.maxDistance).
228 if ((t >= inf()) ||
229 (t > pIterater.maxDistance + epsilon) ||
230 (t < pIterater.minDistance - epsilon))
232 t = inf();
234 return(t);
236 //==========================================================
237 #ifdef _DEBUG_VMAPS
238 #ifndef gBoxArray
239 extern Vector3 p1,p2,p3,p4,p5,p6,p7;
240 extern Array<AABox>gBoxArray;
241 extern int gCount1, gCount2, gCount3, gCount4;
242 extern bool myfound;
243 #endif
244 #endif
246 RealTime SubModel::getIntersectionTime(const Ray& pRay, bool pExitAtFirst, float pMaxDist) const
248 TriangleBox const *firstObject;
249 double firstDistance = inf();
251 #ifdef _DEBUG_VMAPS
252 int debugCount =0;
253 #endif
254 Ray relativeRay = Ray::fromOriginAndDirection(pRay.origin - getBasePosition(), pRay.direction);
256 const IT end = endRayIntersection();
257 IT obj = beginRayIntersection(relativeRay,pMaxDist,false);
259 Triangle testT;
260 for ( ;obj != end; ++obj) // (preincrement is *much* faster than postincrement!)
263 Call your accurate intersection test here. It is guaranteed
264 that the ray hits the bounding box of obj. (*obj) has type T,
265 so you can call methods directly using the "->" operator.
267 const TriangleBox *tri = &(*obj);
269 testT = Triangle(tri->vertex(0).getVector3(),tri->vertex(1).getVector3(),tri->vertex(2).getVector3());
270 double t = testIntersectionWithTriangle(obj,testT, relativeRay);
271 #ifdef _DEBUG_VMAPS
272 if(debugCount == 5)
274 firstObject = tri;
275 firstDistance = 1;
277 ++debugCount;
278 #endif
279 if(t != inf())
282 Tell the iterator that we've found at least one
283 intersection. It will finish looking at all
284 objects in this node and then terminate.
286 obj.markBreakNode();
287 if(firstDistance > t && pMaxDist >= t)
289 firstDistance = t;
290 firstObject = tri;
291 if(pExitAtFirst) break;
294 else
296 // This might the wrong side of the triangle... Turn it and test again
297 testT = Triangle(tri->vertex(2).getVector3(),tri->vertex(1).getVector3(),tri->vertex(0).getVector3());
298 t = testIntersectionWithTriangle(obj, testT,relativeRay);
299 if(t != inf())
301 obj.markBreakNode();
302 if(firstDistance > t && pMaxDist >= t)
304 firstDistance = t;
305 firstObject = tri;
306 if(pExitAtFirst) break;
311 #ifdef _DEBUG_VMAPS
312 if(firstDistance < inf())
314 myfound = true;
315 p1 = firstObject->vertex(0).getVector3()+ getBasePosition();
316 p2 = firstObject->vertex(1).getVector3()+ getBasePosition();
317 p3 = firstObject->vertex(2).getVector3()+ getBasePosition();
318 p4 = relativeRay.origin + getBasePosition();
319 p5 = relativeRay.intersection(testT.plane()) + getBasePosition();
320 float dist1 = (p5-p4).magnitude();
321 double dist2 = relativeRay.intersectionTime(testT);
322 float dist3 = relativeRay.direction.magnitude();
323 double dist4 = relativeRay.intersectionTime(testT);
325 #endif
327 return(firstDistance);
330 //==========================================================