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
21 #ifdef _ASSEMBLER_DEBUG
28 //==========================================================
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
)
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())
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
)
86 //==========================================================
95 BP_iHasInternalMemAlloc
=36,
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
)
117 pNTriabgles
+= pNode
.valueArray
.size();
119 #ifdef _ASSEMBLER_DEBUG
120 fprintf(::g_df
, "Nodes: %d, Tris: %d\n",pNNodes
, pNTriabgles
);
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
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).
229 (t
> pIterater
.maxDistance
+ epsilon
) ||
230 (t
< pIterater
.minDistance
- epsilon
))
236 //==========================================================
239 extern Vector3 p1
,p2
,p3
,p4
,p5
,p6
,p7
;
240 extern Array
<AABox
>gBoxArray
;
241 extern int gCount1
, gCount2
, gCount3
, gCount4
;
246 RealTime
SubModel::getIntersectionTime(const Ray
& pRay
, bool pExitAtFirst
, float pMaxDist
) const
248 TriangleBox
const *firstObject
;
249 double firstDistance
= inf();
254 Ray relativeRay
= Ray::fromOriginAndDirection(pRay
.origin
- getBasePosition(), pRay
.direction
);
256 const IT end
= endRayIntersection();
257 IT obj
= beginRayIntersection(relativeRay
,pMaxDist
,false);
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
);
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.
287 if(firstDistance
> t
&& pMaxDist
>= t
)
291 if(pExitAtFirst
) break;
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
);
302 if(firstDistance
> t
&& pMaxDist
>= t
)
306 if(pExitAtFirst
) break;
312 if(firstDistance
< inf())
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
);
327 return(firstDistance
);
330 //==========================================================