84 FILE* mapFile = fopen(mapFileName.c_str(),
"rb");
88 while (!mapFile && parentMapId != -1)
91 mapFile = fopen(mapFileName.c_str(),
"rb");
92 parentMapId =
sMapStore[parentMapId].ParentMapID;
104 printf(
"%s is the wrong version, please extract new .map files\n", mapFileName.c_str());
111 bool haveTerrain =
false;
112 bool haveLiquid =
false;
120 if (!haveTerrain && !haveLiquid)
133 G3D::Array<int> ltriangles;
134 G3D::Array<int> ttriangles;
139 float heightMultiplier;
150 if (count != expected)
151 printf(
"TerrainBuilder::loadMap: Failed to read some data expected %d, read %d\n", expected, count);
156 V9[i] = (
float)v9[i]*heightMultiplier + hheader.
gridHeight;
159 V8[i] = (
float)v8[i]*heightMultiplier + hheader.
gridHeight;
168 if (count != expected)
169 printf(
"TerrainBuilder::loadMap: Failed to read some data expected %d, read %d\n", expected, count);
174 V9[i] = (
float)v9[i]*heightMultiplier + hheader.
gridHeight;
177 V8[i] = (
float)v8[i]*heightMultiplier + hheader.
gridHeight;
184 if (count != expected)
185 printf(
"TerrainBuilder::loadMap: Failed to read some data expected %d, read %d\n", expected, count);
194 printf(
"TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n");
198 float xoffset = (float(tileX)-32)*
GRID_SIZE;
199 float yoffset = (float(tileY)-32)*
GRID_SIZE;
219 int indices[] = { 0, 0, 0 };
220 int loopStart = 0, loopEnd = 0, loopInc = 0;
222 for (
int i = loopStart; i < loopEnd; i+=loopInc)
226 ttriangles.append(indices[2] + count);
227 ttriangles.append(indices[1] + count);
228 ttriangles.append(indices[0] + count);
238 printf(
"TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n");
240 float* liquid_map =
nullptr;
245 printf(
"TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n");
247 printf(
"TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n");
258 liquid_map =
new float [toRead];
259 if (fread(liquid_map,
sizeof(
float), toRead, mapFile) != toRead)
261 printf(
"TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n");
263 liquid_map =
nullptr;
268 float xoffset = (float(tileX)-32)*
GRID_SIZE;
269 float yoffset = (float(tileY)-32)*
GRID_SIZE;
283 if (row < lheader.offsetY || row >= lheader.
offsetY + lheader.
height ||
284 col < lheader.offsetX || col >= lheader.
offsetX + lheader.
width)
310 int indices[] = { 0, 0, 0 };
311 int loopStart = 0, loopEnd = 0, loopInc = 0, triInc =
BOTTOM-
TOP;
315 for (
int i = loopStart; i < loopEnd; i += loopInc)
317 for (
int j =
TOP; j <=
BOTTOM; j += triInc)
320 ltriangles.append(indices[2] + count);
321 ltriangles.append(indices[1] + count);
322 ltriangles.append(indices[0] + count);
331 int loopStart = 0, loopEnd = 0, loopInc = 0, tTriCount = 4;
332 bool useTerrain, useLiquid;
335 int* ltris = ltriangles.getCArray();
337 float* tverts = meshData.
solidVerts.getCArray();
338 int* ttris = ttriangles.getCArray();
340 if ((ltriangles.size() + ttriangles.size()) == 0)
345 float* lverts_copy =
nullptr;
348 lverts_copy =
new float[meshData.
liquidVerts.size()];
349 memcpy(lverts_copy, lverts,
sizeof(
float)*meshData.
liquidVerts.size());
353 for (
int i = loopStart; i < loopEnd; i+=loopInc)
355 for (
int j = 0; j < 2; ++j)
364 if (!meshData.
liquidVerts.size() || !ltriangles.size())
384 if (!ttriangles.size())
391 float quadHeight = 0;
393 for(
uint32 idx = 0; idx < 3; idx++)
395 float h = lverts_copy[ltris[idx]*3 + 1];
404 if (validCount > 0 && validCount < 3)
406 quadHeight /= validCount;
407 for(
uint32 idx = 0; idx < 3; idx++)
409 float h = lverts[ltris[idx]*3 + 1];
411 lverts[ltris[idx]*3 + 1] = quadHeight;
421 if (useTerrain && fheader.
holesSize != 0)
425 if (useTerrain && useLiquid)
429 for(
uint32 x = 0; x < 3; x++)
431 float h = lverts[ltris[x]*3 + 1];
441 for(
uint32 x = 0; x < 6; x++)
443 float h = tverts[ttris[x]*3 + 1];
452 if (minLLevel > maxTLevel)
456 if (minTLevel > maxLLevel)
464 for (
int k = 0; k < 3; ++k)
469 for (
int k = 0; k < 3*tTriCount/2; ++k)
474 ttris += 3*tTriCount/2;
479 delete [] lverts_copy;
512 indices[0] =
square+rowOffset;
513 indices[1] =
square+1+rowOffset;
517 indices[0] =
square+rowOffset;
522 indices[0] =
square+1+rowOffset;
537 indices[0] =
square+rowOffset;
538 indices[1] =
square+1+rowOffset;
542 indices[0] =
square+rowOffset;
558 coord[2] = v[index2];
566 int cellRow = row / 8;
567 int cellCol = col / 8;
568 int holeRow = row % 8;
569 int holeCol = col % 8;
571 return (
holes[cellRow][cellCol][holeRow] & (1 << holeCol)) != 0;
579 int cellRow = row / 8;
580 int cellCol = col / 8;
582 return liquid_type[cellRow][cellCol];
589 LoadResult result = vmapManager->loadMap(
"vmaps", mapID, tileX, tileY);
594 if (result != LoadResult::Success)
598 vmapManager->getInstanceMapTree(instanceTrees);
600 if (!instanceTrees[mapID])
605 instanceTrees[mapID]->getModelInstances(models, count);
610 for (
uint32 i = 0; i < count; ++i)
622 std::vector<GroupModel>
const& groupModels = worldModel->
getGroupModels();
625 bool isM2 = worldModel->
IsM2();
628 float scale = instance.
iScale;
629 G3D::Matrix3 rotation = instance.
GetInvRot();
630 G3D::Vector3 position = instance.
iPos;
634 for (std::vector<GroupModel>::const_iterator it = groupModels.begin(); it != groupModels.end(); ++it)
636 std::vector<G3D::Vector3>
const& tempVertices = it->GetVertices();
637 std::vector<G3D::Vector3> transformedVertices;
638 std::vector<MeshTriangle>
const& tempTriangles = it->GetTriangles();
639 WmoLiquid const* liquid = it->GetLiquid();
642 transform(tempVertices, transformedVertices, scale, rotation, position);
652 std::vector<G3D::Vector3> liqVerts;
653 std::vector<int> liqTris;
654 uint32 tilesX, tilesY, vertsX, vertsY;
677 for (
uint32 x = 0; x < vertsX; ++x)
679 for (
uint32 y = 0; y < vertsY; ++y)
682 vert = vert * rotation * scale + position;
685 liqVerts.push_back(vert);
689 int idx1, idx2, idx3, idx4;
691 for (
uint32 x = 0; x < tilesX; ++x)
693 for (
uint32 y = 0; y < tilesY; ++y)
695 if ((
flags[x + y * tilesX] & 0x0f) != 0x0f)
700 idx3 =
square + tilesY + 1 + 1 + x;
701 idx4 =
square + tilesY + 1 + x;
704 liqTris.push_back(idx3);
705 liqTris.push_back(idx2);
706 liqTris.push_back(idx1);
708 liqTris.push_back(idx4);
709 liqTris.push_back(idx3);
710 liqTris.push_back(idx1);
716 for (
uint32 i = 0; i < liqVerts.size(); ++i)
717 meshData.
liquidVerts.append(liqVerts[i].y, liqVerts[i].z, liqVerts[i].x);
719 for (
uint32 i = 0; i < liqTris.size() / 3; ++i)
721 meshData.
liquidTris.append(liqTris[i * 3 + 1] + liqOffset, liqTris[i * 3 + 2] + liqOffset, liqTris[i * 3] + liqOffset);
730 vmapManager->unloadMap(mapID, tileX, tileY);
736 void TerrainBuilder::transform(std::vector<G3D::Vector3>
const& source, std::vector<G3D::Vector3>& transformedVertices,
float scale, G3D::Matrix3
const& rotation, G3D::Vector3
const& position)
738 transformedVertices.reserve(transformedVertices.size() + source.size());
739 for (G3D::Vector3
const& vertex : source)
742 G3D::Vector3 v(vertex * rotation * scale + position);
745 transformedVertices.push_back(v);
752 dest.reserve(dest.size() + source.size() * 3);
753 for (G3D::Vector3
const& vertex : source)
755 dest.push_back(vertex.y);
756 dest.push_back(vertex.z);
757 dest.push_back(vertex.x);
764 dest.reserve(dest.size() + source.size() * 3);
769 dest.push_back(triangle.idx2 + offset);
770 dest.push_back(triangle.idx1 + offset);
771 dest.push_back(triangle.idx0 + offset);
778 dest.push_back(triangle.idx0 + offset);
779 dest.push_back(triangle.idx1 + offset);
780 dest.push_back(triangle.idx2 + offset);
788 int const* src = source.getCArray();
789 dest.reserve(dest.size() + source.size());
790 for (
int32 i = 0; i < source.size(); ++i)
791 dest.append(src[i] + offset);
797 std::map<int, int> vertMap;
799 int* t = tris.getCArray();
800 float* v = verts.getCArray();
802 G3D::Array<float> cleanVerts;
803 int index, count = 0;
805 for (
int i = 0; i < tris.size(); ++i)
807 if (vertMap.find(t[i]) != vertMap.end())
809 std::pair<int, int> val;
816 cleanVerts.append(v[index * 3], v[index * 3 + 1], v[index * 3 + 2]);
821 verts.append(cleanVerts);
825 for (
int i = 0; i < tris.size(); ++i)
827 std::map<int, int>::iterator it;
828 if ((it = vertMap.find(t[i])) == vertMap.end())
840 for (
OffMeshData const& offMeshConnection : offMeshConnections)
842 if (mapID != offMeshConnection.MapId || tileX != offMeshConnection.TileX || tileY != offMeshConnection.TileY)
uint32 const MapVersionMagic
map_liquidHeaderTypeFlags
uint8 holes[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID][8]
map_liquidHeaderTypeFlags liquid_flags[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]
uint16 liquid_entry[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]
float V8[ADT_GRID_SIZE][ADT_GRID_SIZE]
float V9[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]
constexpr bool HasFlag(T flag) const
void loadOffMeshConnections(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, std::vector< OffMeshData > const &offMeshConnections)
bool isHole(int square, uint8 const holes[16][16][8])
Determines if the specific position's triangles should be rendered.
static void copyIndices(std::vector< VMAP::MeshTriangle > const &source, G3D::Array< int > &dest, int offset, bool flip)
static void cleanVertices(G3D::Array< float > &verts, G3D::Array< int > &tris)
bool m_skipLiquid
Controls whether liquids are loaded.
void getHeightTriangle(int square, Spot triangle, int *indices, bool liquid=false)
Get the triangle's vector indices for a specific position.
void loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData)
void getLiquidCoord(int index, int index2, float xOffset, float yOffset, float *coord, float *v)
Get the liquid vector coordinate for a specific position.
static void transform(std::vector< G3D::Vector3 > const &source, std::vector< G3D::Vector3 > &transformed, float scale, G3D::Matrix3 const &rotation, G3D::Vector3 const &position)
bool loadVMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData)
void getHeightCoord(int index, Grid grid, float xOffset, float yOffset, float *coord, float *v)
Get the vector coordinate for a specific position.
static void copyVertices(std::vector< G3D::Vector3 > const &source, G3D::Array< float > &dest)
void getLoopVars(Spot portion, int &loopStart, int &loopEnd, int &loopInc)
Sets loop variables for selecting only certain parts of a map's terrain.
map_liquidHeaderTypeFlags getLiquidType(int square, map_liquidHeaderTypeFlags const (&liquid_type)[16][16])
Get the liquid type for a specific position.
G3D::Matrix3 const & GetInvRot() const
WorldModel const * getWorldModel() const
void getPosInfo(uint32 &tilesX, uint32 &tilesY, G3D::Vector3 &corner) const
float * GetHeightStorage()
uint8 * GetFlagsStorage()
std::vector< GroupModel > const & getGroupModels() const
std::unique_ptr< VMAP::VMapManager2 > CreateVMapManager()
static const float GRID_SIZE
static const float INVALID_MAP_LIQ_HEIGHT_MAX
static const float GRID_PART_SIZE
static const float INVALID_MAP_LIQ_HEIGHT
static const int V9_SIZE_SQ
static const int V8_SIZE_SQ
std::unordered_map< uint32, MapEntry > sMapStore
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
std::unordered_map< uint32, StaticMapTree * > InstanceTreeMap
G3D::Array< float > liquidVerts
G3D::Array< float > offMeshConnectionRads
G3D::Array< unsigned char > offMeshConnectionDirs
G3D::Array< float > offMeshConnections
G3D::Array< unsigned short > offMeshConnectionsFlags
G3D::Array< float > solidVerts
G3D::Array< int > liquidTris
G3D::Array< int > solidTris
G3D::Array< unsigned char > offMeshConnectionsAreas
G3D::Array< uint8 > liquidType