TrinityCore
Loading...
Searching...
No Matches
model.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS 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 "vmapexport.h"
19#include "Errors.h"
20#include "model.h"
21#include "StringFormat.h"
22#include "wmo.h"
23#include "adtfile.h"
24#include "mpq_libmpq.h"
25#include "VMapDefinitions.h"
26#include <G3D/Quat.h>
27#include <algorithm>
28#include <cstdio>
29#include <limits>
30
31Model::Model(std::string &filename) : filename(filename), header(), vertices(nullptr), indices(nullptr)
32{
33}
34
36{
37 MPQFile f(filename.c_str());
38
39 if (f.isEof())
40 {
41 f.close();
42 // Do not show this error on console to avoid confusion, the extractor can continue working even if some models fail to load
43 //printf("Error loading model %s\n", filename.c_str());
44 return false;
45 }
46
47 _unload();
48
49 memcpy(&header, f.getBuffer(), sizeof(ModelHeader));
51 {
52 f.seek(0);
56 for (uint32 i=0; i<header.nBoundingVertices; i++)
58 f.seek(0);
62 f.close();
63 }
64 else
65 {
66 //printf("not included %s\n", filename.c_str());
67 f.close();
68 return false;
69 }
70 return true;
71}
72
73bool Model::ConvertToVMAPModel(const char * outfilename)
74{
75 int N[12] = { };
76 FILE* output = fopen(outfilename, "wb");
77 if (!output)
78 {
79 printf("Can't create the output file '%s'\n", outfilename);
80 return false;
81 }
82 fwrite(VMAP::RAW_VMAP_MAGIC, 8, 1, output);
84 fwrite(&nVertices, sizeof(int), 1, output);
85 uint32 nofgroups = 1;
86 fwrite(&nofgroups, sizeof(uint32), 1, output);
87 fwrite(N, 4 * 3, 1, output);// rootwmoid, flags, groupid
88 fwrite(N, sizeof(float), 3 * 2, output);//bbox, only needed for WMO currently
89 fwrite(N, 4, 1, output);// liquidflags
90 fwrite("GRP ", 4, 1, output);
91 uint32 branches = 1;
92 int wsize;
93 wsize = sizeof(branches) + sizeof(uint32) * branches;
94 fwrite(&wsize, sizeof(int), 1, output);
95 fwrite(&branches, sizeof(branches), 1, output);
97 fwrite(&nIndexes, sizeof(uint32), 1, output);
98 fwrite("INDX", 4, 1, output);
99 wsize = sizeof(uint32) + sizeof(unsigned short) * nIndexes;
100 fwrite(&wsize, sizeof(int), 1, output);
101 fwrite(&nIndexes, sizeof(uint32), 1, output);
102 if (nIndexes > 0)
103 {
104 for (uint32 i = 0; i < nIndexes; ++i)
105 {
106 if ((i % 3) - 1 == 0 && i + 1 < nIndexes)
107 {
108 uint16 tmp = indices[i];
109 indices[i] = indices[i + 1];
110 indices[i + 1] = tmp;
111 }
112 }
113 fwrite(indices, sizeof(unsigned short), nIndexes, output);
114 }
115
116 fwrite("VERT", 4, 1, output);
117 wsize = sizeof(int) + sizeof(float) * 3 * nVertices;
118 fwrite(&wsize, sizeof(int), 1, output);
119 fwrite(&nVertices, sizeof(int), 1, output);
120 if (nVertices > 0)
121 {
122 for (uint32 vpos = 0; vpos < nVertices; ++vpos)
123 {
124 float tmp = vertices[vpos].y;
125 vertices[vpos].y = -vertices[vpos].z;
126 vertices[vpos].z = tmp;
127 }
128
129 fwrite(vertices, sizeof(float) * 3, nVertices, output);
130 }
131
132 fclose(output);
133
134 return true;
135}
136
138{
139 return Vec3D(v.x, v.z, -v.y);
140}
141
142void Doodad::Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile)
143{
144 std::string tempname = Trinity::StringFormat("{}/{}", szWorkDirWmo, ModelInstName);
145 FILE* input = fopen(tempname.c_str(), "r+b");
146
147 if (!input)
148 return;
149
150 fseek(input, 8, SEEK_SET); // get the correct no of vertices
151 int nVertices;
152 int count = fread(&nVertices, sizeof(int), 1, input);
153 fclose(input);
154
155 if (count != 1 || nVertices == 0)
156 return;
157
158 // scale factor - divide by 1024. blizzard devs must be on crack, why not just use a float?
159 float sc = doodadDef.Scale / 1024.0f;
160
161 Vec3D position = fixCoords(doodadDef.Position);
162
163 uint16 nameSet = 0;// not used for models
164 uint32 uniqueId = GenerateUniqueObjectId(doodadDef.UniqueId, 0);
165 uint32 tcflags = MOD_M2;
166 if (tileX == 65 && tileY == 65)
167 tcflags |= MOD_WORLDSPAWN;
168
169 //write mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, name
170 fwrite(&mapID, sizeof(uint32), 1, pDirfile);
171 fwrite(&tileX, sizeof(uint32), 1, pDirfile);
172 fwrite(&tileY, sizeof(uint32), 1, pDirfile);
173 fwrite(&tcflags, sizeof(uint32), 1, pDirfile);
174 fwrite(&nameSet, sizeof(uint16), 1, pDirfile);
175 fwrite(&uniqueId, sizeof(uint32), 1, pDirfile);
176 fwrite(&position, sizeof(Vec3D), 1, pDirfile);
177 fwrite(&doodadDef.Rotation, sizeof(Vec3D), 1, pDirfile);
178 fwrite(&sc, sizeof(float), 1, pDirfile);
179 uint32 nlen = strlen(ModelInstName);
180 fwrite(&nlen, sizeof(uint32), 1, pDirfile);
181 fwrite(ModelInstName, sizeof(char), nlen, pDirfile);
182}
183
184void Doodad::ExtractSet(WMODoodadData const& doodadData, ADT::MODF const& wmo, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile)
185{
186 if (wmo.DoodadSet >= doodadData.Sets.size())
187 return;
188
189 G3D::Vector3 wmoPosition(wmo.Position.z, wmo.Position.x, wmo.Position.y);
190 G3D::Matrix3 wmoRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::toRadians(wmo.Rotation.y), G3D::toRadians(wmo.Rotation.x), G3D::toRadians(wmo.Rotation.z));
191
192 uint16 doodadId = 0;
193 WMO::MODS const& doodadSetData = doodadData.Sets[wmo.DoodadSet];
194 for (uint16 doodadIndex : doodadData.References)
195 {
196 if (doodadIndex < doodadSetData.StartIndex ||
197 doodadIndex >= doodadSetData.StartIndex + doodadSetData.Count)
198 continue;
199
200 WMO::MODD const& doodad = doodadData.Spawns[doodadIndex];
201
202 std::string ModelInstName = GetPlainName(&doodadData.Paths[doodad.NameIndex]);
203 uint32 nlen = ModelInstName.length();
204 FixNameCase(ModelInstName.data(), nlen);
205 FixNameSpaces(ModelInstName.data(), nlen);
206 if (ModelInstName.ends_with(".mdx") || ModelInstName.ends_with(".mdl"))
207 {
208 ModelInstName.replace(ModelInstName.length() - 2, 2, "2");
209 nlen = ModelInstName.length();
210 }
211
212 std::string tempname = Trinity::StringFormat("{}/{}", szWorkDirWmo, ModelInstName);
213 FILE* input = fopen(tempname.c_str(), "r+b");
214 if (!input)
215 continue;
216
217 fseek(input, 8, SEEK_SET); // get the correct no of vertices
218 int nVertices;
219 int count = fread(&nVertices, sizeof(int), 1, input);
220 fclose(input);
221
222 if (count != 1 || nVertices == 0)
223 continue;
224
225 ASSERT(doodadId < std::numeric_limits<uint16>::max());
226 ++doodadId;
227
228 G3D::Vector3 position = wmoPosition + (wmoRotation * G3D::Vector3(doodad.Position.x, doodad.Position.y, doodad.Position.z));
229
230 Vec3D rotation;
231 (G3D::Quat(doodad.Rotation.X, doodad.Rotation.Y, doodad.Rotation.Z, doodad.Rotation.W)
232 .toRotationMatrix() * wmoRotation)
233 .toEulerAnglesXYZ(rotation.z, rotation.x, rotation.y);
234
235 rotation.z = G3D::toDegrees(rotation.z);
236 rotation.x = G3D::toDegrees(rotation.x);
237 rotation.y = G3D::toDegrees(rotation.y);
238
239 uint16 nameSet = 0; // not used for models
240 uint32 uniqueId = GenerateUniqueObjectId(wmo.UniqueId, doodadId);
241 uint32 tcflags = MOD_M2;
242 if (tileX == 65 && tileY == 65)
243 tcflags |= MOD_WORLDSPAWN;
244
245 //write mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, name
246 fwrite(&mapID, sizeof(uint32), 1, pDirfile);
247 fwrite(&tileX, sizeof(uint32), 1, pDirfile);
248 fwrite(&tileY, sizeof(uint32), 1, pDirfile);
249 fwrite(&tcflags, sizeof(uint32), 1, pDirfile);
250 fwrite(&nameSet, sizeof(uint16), 1, pDirfile);
251 fwrite(&uniqueId, sizeof(uint32), 1, pDirfile);
252 fwrite(&position, sizeof(Vec3D), 1, pDirfile);
253 fwrite(&rotation, sizeof(Vec3D), 1, pDirfile);
254 fwrite(&doodad.Scale, sizeof(float), 1, pDirfile);
255 fwrite(&nlen, sizeof(uint32), 1, pDirfile);
256 fwrite(ModelInstName.c_str(), sizeof(char), nlen, pDirfile);
257 }
258}
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
#define ASSERT
Definition Errors.h:68
char const * GetPlainName(char const *FileName)
Definition adtfile.cpp:25
void FixNameCase(char *name, size_t len)
Definition adtfile.cpp:43
void FixNameSpaces(char *name, size_t len)
Definition adtfile.cpp:60
size_t read(void *dest, size_t bytes)
bool isEof()
Definition mpq_libmpq.h:91
void close()
void seek(int offset)
void seekRelative(int offset)
char * getBuffer()
Definition mpq_libmpq.h:89
Vec3D * vertices
Definition model.h:45
ModelHeader header
Definition model.h:44
uint16 * indices
Definition model.h:46
std::string filename
Definition model.h:42
bool open()
Definition model.cpp:35
void _unload()
Definition model.h:35
Model(std::string &filename)
Definition model.cpp:31
bool ConvertToVMAPModel(char const *outfilename)
Definition model.cpp:73
Definition vec3d.h:25
float x
Definition vec3d.h:27
float y
Definition vec3d.h:27
float z
Definition vec3d.h:27
Vec3D fixCoordSystem(Vec3D const &v)
Definition model.cpp:137
Vec3D fixCoordSystem(Vec3D const &v)
Definition model.cpp:137
void Extract(ADT::MDDF const &doodadDef, char const *ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE *pDirfile)
Definition model.cpp:142
void ExtractSet(WMODoodadData const &doodadData, ADT::MODF const &wmo, uint32 mapID, uint32 tileX, uint32 tileY, FILE *pDirfile)
Definition model.cpp:184
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
const char RAW_VMAP_MAGIC[]
uint32 UniqueId
Definition adtfile.h:31
Vec3D Position
Definition adtfile.h:32
Vec3D Rotation
Definition adtfile.h:33
uint16 Scale
Definition adtfile.h:34
Vec3D Rotation
Definition adtfile.h:43
uint32 UniqueId
Definition adtfile.h:41
Vec3D Position
Definition adtfile.h:42
uint16 DoodadSet
Definition adtfile.h:46
uint32 nBoundingVertices
uint32 nBoundingTriangles
uint32 ofsBoundingVertices
uint32 ofsBoundingTriangles
float X
Definition vec3d.h:246
float Z
Definition vec3d.h:246
float Y
Definition vec3d.h:246
float W
Definition vec3d.h:246
std::unordered_set< uint16 > References
Definition wmo.h:74
std::vector< WMO::MODS > Sets
Definition wmo.h:71
std::vector< WMO::MODD > Spawns
Definition wmo.h:73
std::unique_ptr< char[]> Paths
Definition wmo.h:72
Quaternion Rotation
Definition wmo.h:60
uint32 NameIndex
Definition wmo.h:58
float Scale
Definition wmo.h:61
Vec3D Position
Definition wmo.h:59
uint32 StartIndex
Definition wmo.h:51
uint32 Count
Definition wmo.h:52
uint32 GenerateUniqueObjectId(uint32 clientId, uint16 clientDoodadId)
char const * szWorkDirWmo
@ MOD_M2
Definition vmapexport.h:27
@ MOD_WORLDSPAWN
Definition vmapexport.h:28
static Vec3D fixCoords(Vec3D const &v)
Definition wmo.h:67