Legends-of-Azeroth-Pandaria-5.4.8

Форк
0
222 строки · 8.3 Кб
1
/*
2
* This file is part of the Pandaria 5.4.8 Project. See THANKS file for Copyright information
3
*
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License as published by the
6
* Free Software Foundation; either version 2 of the License, or (at your
7
* option) any later version.
8
*
9
* This program is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
* more details.
13
*
14
* You should have received a copy of the GNU General Public License along
15
* with this program. If not, see <http://www.gnu.org/licenses/>.
16
*/
17

18
#include "ModelInstance.h"
19
#include "WorldModel.h"
20
#include "MapTree.h"
21
#include "VMapDefinitions.h"
22

23
using G3D::Vector3;
24
using G3D::Ray;
25

26
namespace VMAP
27
{
28
    ModelInstance::ModelInstance(ModelSpawn const& spawn, WorldModel* model): ModelSpawn(spawn), iModel(model)
29
    {
30
        iInvRot = G3D::Matrix3::fromEulerAnglesZYX(G3D::pif()*iRot.y/180.f, G3D::pif()*iRot.x/180.f, G3D::pif()*iRot.z/180.f).inverse();
31
        iInvScale = 1.f/iScale;
32
    }
33

34
    bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
35
    {
36
        if (!iModel)
37
        {
38
            //std::cout << "<object not loaded>\n";
39
            return false;
40
        }
41
        float time = pRay.intersectionTime(iBound);
42
        if (time == G3D::inf())
43
        {
44
//            std::cout << "Ray does not hit '" << name << "'\n";
45

46
            return false;
47
        }
48
//        std::cout << "Ray crosses bound of '" << name << "'\n";
49
/*        std::cout << "ray from:" << pRay.origin().x << ", " << pRay.origin().y << ", " << pRay.origin().z
50
                  << " dir:" << pRay.direction().x << ", " << pRay.direction().y << ", " << pRay.direction().z
51
                  << " t/tmax:" << time << '/' << pMaxDist;
52
        std::cout << "\nBound lo:" << iBound.low().x << ", " << iBound.low().y << ", " << iBound.low().z << " hi: "
53
                  << iBound.high().x << ", " << iBound.high().y << ", " << iBound.high().z << std::endl; */
54
        // child bounds are defined in object space:
55
        Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale;
56
        Ray modRay(p, iInvRot * pRay.direction());
57
        float distance = pMaxDist * iInvScale;
58
        bool hit = iModel->IntersectRay(modRay, distance, pStopAtFirstHit, ignoreFlags);
59
        if (hit)
60
        {
61
            distance *= iScale;
62
            pMaxDist = distance;
63
        }
64
        return hit;
65
    }
66

67
    void ModelInstance::intersectPoint(const G3D::Vector3& p, AreaInfo &info) const
68
    {
69
        if (!iModel)
70
        {
71
#ifdef VMAP_DEBUG
72
            std::cout << "<object not loaded>\n";
73
#endif
74
            return;
75
        }
76

77
        // M2 files don't contain area info, only WMO files
78
        if (flags & MOD_M2)
79
            return;
80
        if (!iBound.contains(p))
81
            return;
82
        // child bounds are defined in object space:
83
        Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
84
        Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
85
        float zDist;
86
        if (iModel->IntersectPoint(pModel, zDirModel, zDist, info))
87
        {
88
            Vector3 modelGround = pModel + zDist * zDirModel;
89
            // Transform back to world space. Note that:
90
            // Mat * vec == vec * Mat.transpose()
91
            // and for rotation matrices: Mat.inverse() == Mat.transpose()
92
            float world_Z = ((modelGround * iInvRot) * iScale + iPos).z;
93
            if (info.ground_Z < world_Z)
94
            {
95
                info.ground_Z = world_Z;
96
                info.adtId = adtId;
97
            }
98
        }
99
    }
100

101
    bool ModelInstance::GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const
102
    {
103
        if (!iModel)
104
        {
105
#ifdef VMAP_DEBUG
106
            std::cout << "<object not loaded>\n";
107
#endif
108
            return false;
109
        }
110

111
        // M2 files don't contain area info, only WMO files
112
        if (flags & MOD_M2)
113
            return false;
114
        if (!iBound.contains(p))
115
            return false;
116
        // child bounds are defined in object space:
117
        Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
118
        Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
119
        float zDist;
120
        if (iModel->GetLocationInfo(pModel, zDirModel, zDist, info))
121
        {
122
            Vector3 modelGround = pModel + zDist * zDirModel;
123
            // Transform back to world space. Note that:
124
            // Mat * vec == vec * Mat.transpose()
125
            // and for rotation matrices: Mat.inverse() == Mat.transpose()
126
            float world_Z = ((modelGround * iInvRot) * iScale + iPos).z;
127
            if (info.ground_Z < world_Z) // hm...could it be handled automatically with zDist at intersection?
128
            {
129
                info.ground_Z = world_Z;
130
                info.hitInstance = this;
131
                return true;
132
            }
133
        }
134
        return false;
135
    }
136

137
    bool ModelInstance::GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const
138
    {
139
        // child bounds are defined in object space:
140
        Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
141
        //Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
142
        float zDist;
143
        if (info.hitModel->GetLiquidLevel(pModel, zDist))
144
        {
145
            // calculate world height (zDist in model coords):
146
            // assume WMO not tilted (wouldn't make much sense anyway)
147
            liqHeight = zDist * iScale + iPos.z;
148
            return true;
149
        }
150
        return false;
151
    }
152

153
    bool ModelSpawn::readFromFile(FILE* rf, ModelSpawn &spawn)
154
    {
155
        uint32 check = 0, nameLen;
156
        check += fread(&spawn.flags, sizeof(uint32), 1, rf);
157
        // EoF?
158
        if (!check)
159
        {
160
            if (ferror(rf))
161
                std::cout << "Error reading ModelSpawn!\n";
162
            return false;
163
        }
164
        check += fread(&spawn.adtId, sizeof(uint16), 1, rf);
165
        check += fread(&spawn.ID, sizeof(uint32), 1, rf);
166
        check += fread(&spawn.iPos, sizeof(float), 3, rf);
167
        check += fread(&spawn.iRot, sizeof(float), 3, rf);
168
        check += fread(&spawn.iScale, sizeof(float), 1, rf);
169
        bool has_bound = (spawn.flags & MOD_HAS_BOUND) != 0;
170
        if (has_bound) // only WMOs have bound in MPQ, only available after computation
171
        {
172
            Vector3 bLow, bHigh;
173
            check += fread(&bLow, sizeof(float), 3, rf);
174
            check += fread(&bHigh, sizeof(float), 3, rf);
175
            spawn.iBound = G3D::AABox(bLow, bHigh);
176
        }
177
        check += fread(&nameLen, sizeof(uint32), 1, rf);
178
        if (check != uint32(has_bound ? 17 : 11))
179
        {
180
            std::cout << "Error reading ModelSpawn!\n";
181
            return false;
182
        }
183
        char nameBuff[500];
184
        if (nameLen > 500) // file names should never be that long, must be file error
185
        {
186
            std::cout << "Error reading ModelSpawn, file name too long!\n";
187
            return false;
188
        }
189
        check = fread(nameBuff, sizeof(char), nameLen, rf);
190
        if (check != nameLen)
191
        {
192
            std::cout << "Error reading ModelSpawn!\n";
193
            return false;
194
        }
195
        spawn.name = std::string(nameBuff, nameLen);
196
        return true;
197
    }
198

199
    bool ModelSpawn::writeToFile(FILE* wf, const ModelSpawn &spawn)
200
    {
201
        uint32 check=0;
202
        check += fwrite(&spawn.flags, sizeof(uint32), 1, wf);
203
        check += fwrite(&spawn.adtId, sizeof(uint16), 1, wf);
204
        check += fwrite(&spawn.ID, sizeof(uint32), 1, wf);
205
        check += fwrite(&spawn.iPos, sizeof(float), 3, wf);
206
        check += fwrite(&spawn.iRot, sizeof(float), 3, wf);
207
        check += fwrite(&spawn.iScale, sizeof(float), 1, wf);
208
        bool has_bound = (spawn.flags & MOD_HAS_BOUND) != 0;
209
        if (has_bound) // only WMOs have bound in MPQ, only available after computation
210
        {
211
            check += fwrite(&spawn.iBound.low(), sizeof(float), 3, wf);
212
            check += fwrite(&spawn.iBound.high(), sizeof(float), 3, wf);
213
        }
214
        uint32 nameLen = spawn.name.length();
215
        check += fwrite(&nameLen, sizeof(uint32), 1, wf);
216
        if (check != uint32(has_bound ? 17 : 11)) return false;
217
        check = fwrite(spawn.name.c_str(), sizeof(char), nameLen, wf);
218
        if (check != nameLen) return false;
219
        return true;
220
    }
221

222
}
223

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.