root/trunk/src/shared/vmap/ModelContainer.cpp @ 102

Revision 102, 14.5 kB (checked in by yumileroy, 17 years ago)

[svn] Fixed copyright notices to comply with GPL.

Original author: w12x
Date: 2008-10-23 03:29:52-05:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
4 * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <iostream>
22#include <fstream>
23
24#include <string.h>
25
26#include "ModelContainer.h"
27#include "VMapDefinitions.h"
28
29using namespace G3D;
30
31namespace VMAP
32{
33    //==========================================================
34    /**
35    Functions to use ModelContainer with a AABSPTree
36    */
37    size_t hashCode(const ModelContainer& pMc)
38    {
39        return (pMc.getBasePosition() * pMc.getNTriangles()).hashCode();
40    }
41    //==========================================================
42
43    ModelContainer::ModelContainer(unsigned int pNTriangles, unsigned int pNNodes, unsigned int pNSubModel) :
44    BaseModel(pNNodes, pNTriangles)
45    {
46
47        iNSubModel = pNSubModel;
48        iSubModel = 0;
49        if(pNSubModel > 0) iSubModel = new SubModel[iNSubModel];
50    }
51
52    //==========================================================
53
54    bool ModelContainer::operator==(const ModelContainer& pMc2) const
55    {
56        if (this->iNSubModel == 0 && pMc2.iNSubModel == 0 && this->iSubModel == 0 && pMc2.iSubModel == 0)
57            return true;
58        return this == &pMc2;
59    }
60
61    //==========================================================
62
63    void ModelContainer::countSubModelsAndNodesAndTriangles(AABSPTree<SubModel *>::Node& pNode, int& nSubModels, int& nNodes, int& nTriangles)
64    {
65        // For this node we will need a TreeNode as well as for the internal nodes
66        ++nNodes;
67
68        nSubModels += pNode.valueArray.size();
69        for(int i=0;i<pNode.valueArray.size(); i++)
70        {
71            G3D::_AABSPTree::Handle<SubModel*>* h= pNode.valueArray[i];
72            SubModel *m = h->value;
73            // add the internal nodes as well
74            nNodes += m->getNNodes();
75            nTriangles += m->getNTriangles();
76        }
77
78        if(pNode.child[0] != 0)
79        {
80            countSubModelsAndNodesAndTriangles(*pNode.child[0], nSubModels, nNodes, nTriangles);
81        }
82        if(pNode.child[1] != 0)
83        {
84            countSubModelsAndNodesAndTriangles(*pNode.child[1],  nSubModels, nNodes, nTriangles);
85        }
86    }
87    //==========================================================
88
89    void ModelContainer::fillContainer(const AABSPTree<SubModel *>::Node& pNode, int &pSubModelPos, int &pTreeNodePos, int &pTrianglePos, Vector3& pLo, Vector3& pHi, Vector3& pFinalLo, Vector3& pFinalHi)
90    {
91        // TreeNode for the SubModel
92        TreeNode treeNode = TreeNode(pNode.valueArray.size(), pSubModelPos);
93        treeNode.setSplitAxis(pNode.splitAxis);
94        treeNode.setSplitLocation(pNode.splitLocation);
95        int currentTreeNodePos = pTreeNodePos++;
96
97        Vector3 lo = Vector3(inf(),inf(),inf());
98        Vector3 hi = Vector3(-inf(),-inf(),-inf());
99
100        for(int i=0;i<pNode.valueArray.size(); i++)
101        {
102            G3D::_AABSPTree::Handle<SubModel*>* h= pNode.valueArray[i];
103            SubModel *m = h->value;
104
105            memcpy(&getTreeNodes()[pTreeNodePos], &m->getTreeNode(0), sizeof(TreeNode) * m->getNNodes());
106            memcpy(&getTriangles()[pTrianglePos], &m->getTriangle(0), sizeof(TriangleBox) * m->getNTriangles());
107
108            SubModel newModel = SubModel(m->getNTriangles(), getTriangles(), pTrianglePos, m->getNNodes(), getTreeNodes(), pTreeNodePos);
109            newModel.setReletiveBounds(m->getReletiveBounds().getLo(), m->getReletiveBounds().getHi());
110            newModel.setBasePosition(m->getBasePosition());
111            iSubModel[pSubModelPos++] = newModel;
112
113            pTreeNodePos += m->getNNodes();
114            pTrianglePos += m->getNTriangles();
115
116            AABox box = m->getAABoxBounds();
117            lo = lo.min(box.low());
118            hi = hi.max(box.high());
119            pFinalLo = pFinalLo.min(lo);
120            pFinalHi = pFinalHi.max(hi);
121        }
122        /*
123        if(pNode.valueArray.size() == 0) {
124        int xxx = 0; // just for the breakpoint
125        }
126        */
127        // get absolute bounds
128
129        if(pNode.child[0] != 0)
130        {
131            treeNode.setChildPos(0, pTreeNodePos);
132            fillContainer(*pNode.child[0], pSubModelPos, pTreeNodePos, pTrianglePos, lo, hi,pFinalLo,pFinalHi);
133        }
134        if(pNode.child[1] != 0)
135        {
136            treeNode.setChildPos(1, pTreeNodePos);
137            fillContainer(*pNode.child[1], pSubModelPos, pTreeNodePos, pTrianglePos, lo, hi,pFinalLo,pFinalHi);
138        }
139
140        pLo = pLo.min(lo);
141        pHi = pHi.max(hi);
142
143        treeNode.setBounds(lo,hi);
144
145        setTreeNode(treeNode, currentTreeNodePos);
146
147    }
148
149    //==========================================================
150    /**
151    Create the structure out of a AABSPTree
152    */
153
154    ModelContainer::ModelContainer(AABSPTree<SubModel *> *pTree)
155    {
156
157        int nSubModels, nNodes, nTriangles;
158        nSubModels = nNodes = nTriangles = 0;
159        countSubModelsAndNodesAndTriangles(*pTree->root, nSubModels, nNodes, nTriangles);
160
161        init(nNodes, nTriangles);
162
163        iNSubModel = nSubModels;
164
165        iSubModel = new SubModel[iNSubModel];
166
167        int subModelPos,treeNodePos, trianglePos;
168        subModelPos = treeNodePos = trianglePos = 0;
169
170        Vector3 lo = Vector3(inf(),inf(),inf());
171        Vector3 hi = Vector3(-inf(),-inf(),-inf());
172        Vector3 finalLo, finalHi;
173        finalLo = lo;
174        finalHi = hi;
175
176        fillContainer(*pTree->root, subModelPos, treeNodePos, trianglePos, lo, hi, finalLo, finalHi);
177        setBounds(finalLo, finalHi);
178    }
179
180    //==========================================================
181
182    ModelContainer::~ModelContainer(void)
183    {
184        free();
185        if(iSubModel != 0) delete [] iSubModel;
186    }
187    //==========================================================
188
189    bool ModelContainer::writeFile(const char *filename)
190    {
191        bool result = false;
192        unsigned int flags=0;
193        unsigned int size;
194
195        FILE *wf =fopen(filename,"wb");
196        if(wf)
197        {
198            fwrite(VMAP_MAGIC,1,8,wf);
199            result = true;
200            if(result && fwrite("CTREE01",8,1,wf) != 1) result = false;
201            if(result && fwrite(&flags,sizeof(unsigned int),1,wf) != 1) result = false;
202
203            if(result && fwrite("POS ",4,1,wf) != 1) result = false;
204            size = sizeof(float)*3;
205            if(result && fwrite(&size,4,1,wf) != 1) result = false;
206            Vector3 basePos = getBasePosition();
207            if(result && fwrite(&basePos,sizeof(float),3,wf) != 3) result = false;
208
209            if(result && fwrite("BOX ",4,1,wf) != 1) result = false;
210            size = sizeof(float)*6;
211            if(result && fwrite(&size,4,1,wf) != 1) result = false;
212            Vector3 low = iBox.low();
213            if(result && fwrite(&low,sizeof(float),3,wf) != 3) result = false;
214            Vector3 high = iBox.high();
215            if(result && fwrite(&high,sizeof(float),3,wf) != 3) result = false;
216
217            if(result && fwrite("NODE",4,1,wf) != 1) result = false;
218            size = sizeof(unsigned int)+ sizeof(TreeNode)*getNNodes();
219            if(result && fwrite(&size,4,1,wf) != 1) result = false;
220            unsigned int val = getNNodes();
221            if(result && fwrite(&val,sizeof(unsigned int),1,wf) != 1) result = false;
222            if(result && fwrite(getTreeNodes(),sizeof(TreeNode),getNNodes(),wf) != getNNodes()) result = false;
223
224            if(result && fwrite("TRIB",4,1,wf) != 1) result = false;
225            size = sizeof(unsigned int)+ sizeof(TriangleBox)*getNTriangles();
226            if(result && fwrite(&size,4,1,wf) != 1) result = false;
227            val = getNTriangles();
228            if(result && fwrite(&val,sizeof(unsigned int),1,wf) != 1) result = false;
229            if(result && fwrite(getTriangles(),sizeof(TriangleBox),getNTriangles(),wf) != getNTriangles()) result = false;
230
231            if(result && fwrite("SUBM",4,1,wf) != 1) result = false;
232            size = sizeof(unsigned int)+ sizeof(SubModel)*iNSubModel;
233            if(result && fwrite(&size,4,1,wf) != 1) result = false;
234            if(result && fwrite(&iNSubModel,sizeof(unsigned int),1,wf) != 1) result = false;
235            if(result && fwrite(iSubModel,sizeof(SubModel),iNSubModel,wf) != iNSubModel) result = false;
236
237            fclose(wf);
238        }
239
240        return(result);
241    }
242
243    //===============================================================
244
245    bool ModelContainer::readFile(const char *filename)
246    {
247        bool result = false;
248        unsigned int flags;
249        unsigned int size;
250        char ident[8];
251        char chunk[4];
252        unsigned int ival;
253        FILE *rf = fopen(filename, "rb");
254        if(rf)
255        {
256            free();
257
258            result = true;
259            char magic[8];                          // Ignore the added magic header
260            fread(magic,1,8,rf);
261            if(strncmp(VMAP_MAGIC,magic,8)) result = false;
262            if(result && fread(ident,8,1,rf) != 1) result = false;
263            if(result && fread(&flags,sizeof(unsigned int),1,rf) != 1) result = false;
264            //POS
265            if(result && fread(chunk,4,1,rf) != 1) result = false;
266            if(result && fread(&size,4,1,rf) != 1) result = false;
267            Vector3 basePos;
268            if(result && fread(&basePos,sizeof(float),3,rf) != 3) result = false;
269            setBasePosition(basePos);
270
271            //---- Box
272            if(result && fread(chunk,4,1,rf) != 1) result = false;
273            if(result && fread(&size,4,1,rf) != 1) result = false;
274            Vector3 low,high;
275            if(result && fread(&low,sizeof(float),3,rf) != 3) result = false;
276            if(result && fread(&high,sizeof(float),3,rf) != 3) result = false;
277            setBounds(low, high);
278
279            //---- TreeNodes
280            if(result && fread(chunk,4,1,rf) != 1) result = false;
281            if(result && fread(&size,4,1,rf) != 1) result = false;
282
283            if(result && fread(&ival,sizeof(unsigned int),1,rf) != 1) result = false;
284            if(result) setNNodes(ival);
285            if(result) setTreeNodeArray(new TreeNode[getNNodes()]);
286            if(result && fread(getTreeNodes(),sizeof(TreeNode),getNNodes(),rf) != getNNodes()) result = false;
287
288            //---- TriangleBoxes
289            if(result && fread(chunk,4,1,rf) != 1) result = false;
290            if(result && fread(&size,4,1,rf) != 1) result = false;
291
292            if(result && fread(&ival,sizeof(unsigned int),1,rf) != 1) result = false;
293            setNTriangles(ival);
294            if(result) setTriangleArray(new TriangleBox[getNTriangles()]);
295            if(result && fread(getTriangles(),sizeof(TriangleBox),getNTriangles(),rf) != getNTriangles()) result = false;
296
297            //---- SubModel
298            if(result && fread(chunk,4,1,rf) != 1) result = false;
299            if(result && fread(&size,4,1,rf) != 1) result = false;
300
301            if(result && fread(&iNSubModel,sizeof(unsigned int),1,rf) != 1) result = false;
302            if(result) iSubModel = new SubModel[iNSubModel];
303
304            if(result)
305            {
306                for(unsigned int i=0;i<iNSubModel && result; ++i)
307                {
308                    unsigned char readBuffer[52];           // this is the size of SubModel on 32 bit systems
309                    if(fread(readBuffer,sizeof(readBuffer),1,rf) != 1) result = false;
310                    iSubModel[i].initFromBinBlock(readBuffer);
311                    iSubModel[i].setTriangleArray(getTriangles());
312                    iSubModel[i].setTreeNodeArray(getTreeNodes());
313                }
314            }
315            fclose(rf);
316        }
317        return result;
318    }
319
320    //=================================================================
321
322    size_t ModelContainer::getMemUsage()
323    {
324                                                            // BaseModel is included in ModelContainer
325        return(iNSubModel * sizeof(SubModel) + BaseModel::getMemUsage() + sizeof(ModelContainer) - sizeof(BaseModel));
326    }
327
328    //=================================================================
329#ifdef _DEBUG_VMAPS
330#ifndef gBoxArray
331    extern Vector3 p1,p2,p3,p4,p5,p6,p7;
332    extern Array<AABox>gBoxArray;
333    extern int gCount1, gCount2, gCount3, gCount4;
334    extern bool myfound;
335#endif
336#endif
337
338    void ModelContainer::intersect(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, G3D::Vector3& /*pOutLocation*/, G3D::Vector3& /*pOutNormal*/) const
339    {
340        IntersectionCallBack<SubModel> intersectCallback;
341        NodeValueAccess<TreeNode, SubModel> vna = NodeValueAccess<TreeNode, SubModel>(getTreeNodes(), iSubModel);
342        Ray relativeRay = Ray::fromOriginAndDirection(pRay.origin - getBasePosition(), pRay.direction);
343        iTreeNodes[0].intersectRay(pRay, intersectCallback, pMaxDist, vna, pStopAtFirstHit, false);
344    }
345
346    //==========================================================
347
348    bool ModelContainer::intersect(const G3D::Ray& pRay, float& pMaxDist) const
349    {
350        return BaseModel::intersect(getAABoxBounds(), pRay, pMaxDist);
351    }
352
353    //=================================================================
354
355    template<typename RayCallback>
356    void ModelContainer::intersectRay(const G3D::Ray& pRay, RayCallback& intersectCallback, float& pMaxDist, bool pStopAtFirstHit, bool intersectCallbackIsFast)
357    {
358        if(intersect(pRay, pMaxDist))
359        {
360            NodeValueAccess<TreeNode, SubModel> vna = NodeValueAccess<TreeNode, SubModel>(getTreeNodes(), iSubModel);
361            iTreeNodes[0].intersectRay(pRay, intersectCallback, distance, vna, pStopAtFirstHit, true);
362        }
363    }
364    //=================================================================
365    void getBounds(const ModelContainer& pMc, G3D::AABox& pAABox)
366    {
367        pAABox = pMc.getAABoxBounds();
368    }
369
370    //=================================================================
371
372    void getBounds(const ModelContainer* pMc, G3D::AABox& pAABox)
373    {
374        pAABox = pMc->getAABoxBounds();
375    }
376    //=================================================================
377}                                                           // VMAP
Note: See TracBrowser for help on using the browser.