23#include <boost/filesystem.hpp>
28template<>
struct BoundsTrait<
VMAP::ModelSpawn*>
37 G3D::Vector3 out = pIn *
iScale;
45 : iDestDir(pDestDirName), iSrcDir(pSrcDirName)
47 boost::filesystem::create_directories(
iDestDir);
60 float constexpr invTileSize = 1.0f / 533.33333f;
69 std::vector<ModelSpawn*> mapSpawns;
71 printf(
"Calculating model bounds for map %u...\n", data.
MapId);
79 mapSpawns.push_back(&entry->second);
84 G3D::AABox
const& bounds = entry->second.iBound;
85 G3D::Vector2int16 low(
int16(bounds.low().x * invTileSize),
int16(bounds.low().y * invTileSize));
86 G3D::Vector2int16 high(
int16(bounds.high().x * invTileSize),
int16(bounds.high().y * invTileSize));
87 for (
int x = low.x; x <= high.x; ++x)
88 for (
int y = low.y; y <= high.y; ++y)
92 printf(
"Creating map tree for map %u...\n", data.
MapId);
97 pTree.
build(mapSpawns, BoundsTrait<ModelSpawn*>::getBounds);
99 catch (std::exception& e)
101 printf(
"Exception ""%s"" when calling pTree.build", e.what());
108 std::stringstream mapfilename;
109 mapfilename <<
iDestDir <<
'/' << std::setfill(
'0') << std::setw(4) << data.
MapId <<
".vmtree";
110 FILE* mapfile = fopen(mapfilename.str().c_str(),
"wb");
114 printf(
"Cannot open %s\n", mapfilename.str().c_str());
119 if (success && fwrite(
VMAP_MAGIC, 1, 8, mapfile) != 8) success =
false;
121 if (success && fwrite(
"NODE", 4, 1, mapfile) != 1) success =
false;
125 uint32 mapSpawnsSize = mapSpawns.size();
126 if (success && fwrite(
"SIDX", 4, 1, mapfile) != 1) success =
false;
127 if (success && fwrite(&mapSpawnsSize,
sizeof(
uint32), 1, mapfile) != 1) success =
false;
128 for (
uint32 i = 0; i < mapSpawnsSize; ++i)
130 if (success && fwrite(&mapSpawns[i]->ID,
sizeof(
uint32), 1, mapfile) != 1) success =
false;
143 if (FILE* tileFile = fopen(tileFileName.c_str(),
"wb"))
145 std::set<uint32>
const& parentTileEntries = data.
ParentTileEntries[tileItr->first];
147 uint32 nSpawns = tileItr->second.size() + parentTileEntries.size();
150 if (success && fwrite(
VMAP_MAGIC, 1, 8, tileFile) != 8) success =
false;
152 if (success && fwrite(&nSpawns,
sizeof(
uint32), 1, tileFile) != 1) success =
false;
154 for (
auto spawnItr = tileItr->second.begin(); spawnItr != tileItr->second.end() && success; ++spawnItr)
157 for (
auto spawnItr = parentTileEntries.begin(); spawnItr != parentTileEntries.end() && success; ++spawnItr)
168 std::cout <<
"\nConverting Model Files" << std::endl;
171 std::cout <<
"Converting " << spawnedModelFile << std::endl;
174 std::cout <<
"error converting " << spawnedModelFile << std::endl;
185 std::string fname =
iSrcDir +
"/dir_bin";
186 FILE* dirf = fopen(fname.c_str(),
"rb");
189 printf(
"Could not read dir_bin file!\n");
192 printf(
"Read coordinate mapping...\n");
194 std::map<uint32, MapSpawns> data;
198 check = fread(&mapID,
sizeof(
uint32), 1, dirf);
206 auto map_iter = data.emplace(std::piecewise_construct, std::forward_as_tuple(mapID), std::forward_as_tuple());
209 map_iter.first->second.MapId = mapID;
210 printf(
"spawning Map %u\n", mapID);
213 map_iter.first->second.UniqueEntries.emplace(spawn.
ID, spawn);
218 for (
auto src = data.begin(); src != data.end(); ++src, ++dst)
219 *dst = std::move(src->second);
221 bool success = (ferror(dirf) == 0);
228 std::string modelFilename(
iSrcDir);
229 modelFilename.push_back(
'/');
230 modelFilename.append(spawn.
name);
235 modelPosition.
init();
238 if (!raw_model.
Read(modelFilename.c_str()))
243 printf(
"Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str());
245 G3D::AABox rotated_bounds;
246 for (
int i = 0; i < 8; ++i)
268 std::string filename =
iSrcDir;
269 if (filename.length() >0)
270 filename.push_back(
'/');
271 filename.append(pModelFilename);
274 if (!raw_model.
Read(filename.c_str()))
283 std::vector<GroupModel> groupsArray;
286 for (
uint32 g = 0; g < groups; ++g)
291 groupsArray.back().setLiquidData(raw_group.
liquid);
304 FILE*
model_list = fopen((
iSrcDir +
"/" +
"temp_gameobject_models").c_str(),
"rb");
316 if (!model_list_copy)
324 uint32 name_length, displayId;
333 || name_length >=
sizeof(buff)
334 || fread(&buff,
sizeof(
char), name_length,
model_list) != name_length)
336 std::cout <<
"\nFile 'temp_gameobject_models' seems to be corrupted" << std::endl;
340 std::string model_name(buff, name_length);
343 if (!raw_model.
Read((
iSrcDir +
"/" + model_name).c_str()) )
349 for (G3D::Vector3
const& vertice : groupModel.
vertexArray)
350 bounds.merge(vertice);
352 if (bounds.isEmpty())
354 std::cout <<
"\nModel " << std::string(buff, name_length) <<
" has empty bounding box" << std::endl;
358 if (!bounds.isFinite())
360 std::cout <<
"\nModel " << std::string(buff, name_length) <<
" has invalid bounding box" << std::endl;
364 fwrite(&displayId,
sizeof(
uint32), 1, model_list_copy);
365 fwrite(&name_length,
sizeof(
uint32), 1, model_list_copy);
366 fwrite(&buff,
sizeof(
char), name_length, model_list_copy);
367 fwrite(&bounds.low(),
sizeof(G3D::Vector3), 1, model_list_copy);
368 fwrite(&bounds.high(),
sizeof(G3D::Vector3), 1, model_list_copy);
372 fclose(model_list_copy);
376#define READ_OR_RETURN(V, S) if (fread((V), (S), 1, rf) != 1) { \
377 fclose(rf); printf("%s readfail, op = %s\n", __FUNCTION__, #V); return(false); }
378#define READ_OR_RETURN_WITH_DELETE(V, S) if (fread((V), (S), 1, rf) != 1) { \
379 fclose(rf); printf("%s readfail, op = %s\n", __FUNCTION__, #V); delete[] V; return(false); };
380#define CMP_OR_RETURN(V, S) if (strcmp((V), (S)) != 0) { \
381 fclose(rf); printf("%s cmpfail, %s!=%s\n", __FUNCTION__, V, S);return(false); }
392 G3D::Vector3 vec1, vec2;
406 for (
uint32 b=0; b<branches; ++b)
424 for (
uint32 i=0; i<nindexes; i+=3)
425 triangles.push_back({ .idx0 = indexarray[i], .idx1 = indexarray[i + 1], .idx2 = indexarray[i + 2] });
439 float *vectorarray =
new float[nvectors*3];
441 for (
uint32 i=0; i<nvectors; ++i)
442 vertexArray.push_back(G3D::Vector3(vectorarray + 3*i) );
444 delete[] vectorarray;
482 FILE* rf = fopen(path,
"rb");
485 printf(
"ERROR: Can't open raw model file: %s\n", path);
506 for (
uint32 g = 0; g < groups && succeed; ++g)
515 #undef READ_OR_RETURN
516 #undef READ_OR_RETURN_WITH_DELETE
#define READ_OR_RETURN_WITH_DELETE(V, S)
#define READ_OR_RETURN(V, S)
#define CMP_OR_RETURN(V, S)
void build(PrimArray const &primitives, BoundsFunc &getBounds, uint32 leafSize=3, bool printStats=false)
bool writeToFile(FILE *wf) const
G3D::Vector3 transform(const G3D::Vector3 &pIn) const
static uint32 packTileID(uint32 tileX, uint32 tileY)
static void unpackTileID(uint32 ID, uint32 &tileX, uint32 &tileY)
void exportGameobjectModels()
bool convertRawFile(const std::string &pModelFilename)
TileAssembler(const std::string &pSrcDirName, const std::string &pDestDirName)
std::set< std::string > spawnedModelFiles
bool calculateTransformedBound(ModelSpawn &spawn)
float * GetHeightStorage()
uint8 * GetFlagsStorage()
void setRootWmoID(uint32 id)
void setFlags(ModelFlags flags)
void setGroupModels(std::vector< GroupModel > &models)
pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry!
bool writeFile(const std::string &filename)
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
constexpr std::size_t size()
const char RAW_VMAP_MAGIC[]
const char GAMEOBJECT_MODELS[]
static void getBounds(VMAP::ModelSpawn const *const &obj, G3D::AABox &out)
std::vector< G3D::Vector3 > vertexArray
std::vector< MeshTriangle > triangles
std::map< uint32, ModelSpawn > UniqueEntries
std::map< uint32, std::set< uint32 > > TileEntries
std::map< uint32, std::set< uint32 > > ParentTileEntries
G3D::AABox const & getBounds() const
static bool readFromFile(FILE *rf, ModelSpawn &spawn)
static bool writeToFile(FILE *rw, ModelSpawn const &spawn)
bool Read(const char *path)
std::vector< GroupModel_Raw > groupsArray