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

Revision 2, 14.4 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

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