Rehti MMORPG  1.0.0
Rehti MMORPG is a free and open source MMORPG game.
MapObjLoader.hpp
Go to the documentation of this file.
1 #include "MapLoader.hpp"
2 enum WINDING_ORDER : bool
3 {
6 };
8 
9 struct Vertex
10 {
11  float x, y, z;
12  float u, v;
13  Vertex(float x, float y, float z) : x(x), y(y), z(z), u(x / Config.AREA_WIDTH), v(1.f - z / Config.AREA_HEIGHT) {}
14 };
15 
22 void writeVertex(std::ofstream& objFile, const Vertex& vertex)
23 {
24  objFile << "v " << vertex.x * Config.TILE_SIDE_SCALE << " " << vertex.y * Config.HEIGHT_MAP_SCALE << " " << vertex.z * Config.TILE_SIDE_SCALE << std::endl;
25  objFile << "vt " << vertex.u << " " << vertex.v << std::endl;
26 };
27 
36 void writeFace(std::ofstream& objFile, const int corner1, const int corner2, const int corner3)
37 {
39  {
40  objFile << "f " << corner1 << "/" << corner1 << " " << corner3 << "/" << corner3 << " " << corner2 << "/" << corner2 << std::endl;
41  }
42  else
43  objFile << "f " << corner1 << "/" << corner1 << " " << corner2 << "/" << corner2 << " " << corner3 << "/" << corner3 << std::endl;
44 };
45 
51 void generateAreaObjs(const std::vector<std::vector<int>>& heightMap, const std::vector<std::vector<std::string>>& areaMap)
52 {
53  for (int i = 0; i < areaMap.size(); i++)
54  {
55  for (int j = 0; j < areaMap[i].size(); j++)
56  {
57  const std::string area = areaMap[i][j];
58  std::cout << "Generating area " << area << i << j << std::endl;
59  const std::string filename = area + std::to_string(i) + std::to_string(j) + ".obj";
60  // Create an OBJ file for writing
61  std::ofstream objFile(Config.GENERATED_AREA_OBJ_PATH + filename);
62 
63  if (!objFile.is_open())
64  {
65  throw std::runtime_error("Could not open " + area + ".obj for writing");
66  }
67 
68  int vertexCount = 0;
69  for (int row = i * Config.AREA_HEIGHT; row < i * Config.AREA_HEIGHT + Config.AREA_HEIGHT; row++) // for each row (y)
70  {
71  for (int col = j * Config.AREA_WIDTH; col < j * Config.AREA_WIDTH + Config.AREA_WIDTH; col++) // for each column (x)
72  {
73  // A cell is divided into inner square which is at the height of the cell and surrounding the inner square are 4 trapezoids which are at the middle of the cell's and it's neighbours height.
74  // The trapezoids are further broken down into two corners and a center rectancle. The trapezoids are used to create a "SSSmooth" transition between the cells.
75 
76  float innerSquareRadius = Config.TILE_SIDE_UNIT / 4.0;
77  float squareRadius = Config.TILE_SIDE_UNIT / 2.0;
78  float xPlus = col + innerSquareRadius;
79  float xMinus = col - innerSquareRadius;
80  float zPlus = row + innerSquareRadius;
81  float zMinus = row - innerSquareRadius;
82  // The inner square
83  writeVertex(objFile, Vertex(xPlus, heightMap[row][col], zMinus)); // Top right
84  writeVertex(objFile, Vertex(xPlus, heightMap[row][col], zPlus)); // Bottom right
85  writeVertex(objFile, Vertex(xMinus, heightMap[row][col], zPlus)); // Bottom left
86  writeVertex(objFile, Vertex(xMinus, heightMap[row][col], zMinus)); // Top left
87  int innerTopRight = 1;
88  int innerBottomRight = 2;
89  int innerBottomLeft = 3;
90  int innerTopLeft = 4;
91 
92  // Next the trapezoids, two of the vertices are shared with the inner square
93 
94  TileHeight tileHeight = calculateTileHeights(heightMap, row, col);
95  float xPlusO = col + squareRadius;
96  float xMinusO = col - squareRadius;
97  float zPlusO = row + squareRadius;
98  float zMinusO = row - squareRadius;
99  // The bottom trapezoid
100  writeVertex(objFile, Vertex(xPlusO, tileHeight.bottomRight, zPlusO)); // Bottom right
101  writeVertex(objFile, Vertex(xMinusO, tileHeight.bottomLeft, zPlusO)); // Bottom left
102  writeVertex(objFile, Vertex(xMinus, tileHeight.bottom, zPlusO)); // Bottom center left
103  writeVertex(objFile, Vertex(xPlus, tileHeight.bottom, zPlusO)); // Bottom center right
104  int bottomRight = 5;
105  int bottomLeft = 6;
106  int bottomCenterLeft = 7;
107  int bottomCenterRight = 8;
108 
109  // The left trapezoid
110  writeVertex(objFile, Vertex(xMinusO, tileHeight.topLeft, zMinusO)); // Left top
111  writeVertex(objFile, Vertex(xMinusO, tileHeight.left, zMinus)); // Left center top
112  writeVertex(objFile, Vertex(xMinusO, tileHeight.left, zPlus)); // Left center bottom
113  int leftTop = 9;
114  int leftCenterTop = 10;
115  int leftCenterBottom = 11;
116 
117  // The top trapezoid
118  writeVertex(objFile, Vertex(xPlusO, tileHeight.topRight, zMinusO)); // Top right
119  writeVertex(objFile, Vertex(xMinus, tileHeight.top, zMinusO)); // Top center left
120  writeVertex(objFile, Vertex(xPlus, tileHeight.top, zMinusO)); // Top center right
121  int topRight = 12;
122  int topCenterLeft = 13;
123  int topCenterRight = 14;
124 
125  // The right trapezoid
126  writeVertex(objFile, Vertex(xPlusO, tileHeight.right, zMinus)); // Right center top
127  writeVertex(objFile, Vertex(xPlusO, tileHeight.right, zPlus)); // Right center bottom
128  int rightCenterTop = 15;
129  int rightCenterBottom = 16;
130 
131  // Define and write the triangles
132  // The inner square
133  writeFace(objFile, vertexCount + 1, vertexCount + 2, vertexCount + 3);
134  writeFace(objFile, vertexCount + 3, vertexCount + 4, vertexCount + 1);
135 
136  // The bottom trapezoid
137  writeFace(objFile, vertexCount + bottomRight, vertexCount + bottomCenterRight, vertexCount + innerBottomRight);
138  writeFace(objFile, vertexCount + bottomCenterRight, vertexCount + bottomCenterLeft, vertexCount + innerBottomLeft);
139  writeFace(objFile, vertexCount + innerBottomLeft, vertexCount + innerBottomRight, vertexCount + bottomCenterRight);
140  writeFace(objFile, vertexCount + bottomCenterLeft, vertexCount + bottomLeft, vertexCount + innerBottomLeft);
141 
142  // The left trapezoid
143  writeFace(objFile, vertexCount + leftTop, vertexCount + innerTopLeft, vertexCount + leftCenterTop);
144  writeFace(objFile, vertexCount + leftCenterTop, vertexCount + innerTopLeft, vertexCount + leftCenterBottom);
145  writeFace(objFile, vertexCount + leftCenterBottom, vertexCount + innerTopLeft, vertexCount + innerBottomLeft);
146  writeFace(objFile, vertexCount + innerBottomLeft, vertexCount + bottomLeft, vertexCount + leftCenterBottom);
147 
148  // The top trapezoid
149  writeFace(objFile, vertexCount + topRight, vertexCount + innerTopRight, vertexCount + topCenterRight);
150  writeFace(objFile, vertexCount + topCenterRight, vertexCount + innerTopRight, vertexCount + topCenterLeft);
151  writeFace(objFile, vertexCount + topCenterLeft, vertexCount + innerTopRight, vertexCount + innerTopLeft);
152  writeFace(objFile, vertexCount + innerTopLeft, vertexCount + leftTop, vertexCount + topCenterLeft);
153 
154  // The right trapezoid
155  writeFace(objFile, vertexCount + rightCenterTop, vertexCount + innerBottomRight, vertexCount + innerTopRight);
156  writeFace(objFile, vertexCount + innerTopRight, vertexCount + topRight, vertexCount + rightCenterTop);
157  writeFace(objFile, vertexCount + rightCenterBottom, vertexCount + innerBottomRight, vertexCount + rightCenterTop);
158  writeFace(objFile, vertexCount + innerBottomRight, vertexCount + rightCenterBottom, vertexCount + bottomRight);
159 
160  // Keep track of the vertex index
161  vertexCount += 16;
162  }
163  }
164 
165  objFile.close();
166  }
167  }
168 
169  std::cout << "Map object file generated" << std::endl;
170 };
void writeVertex(std::ofstream &objFile, const Vertex &vertex)
Writes a vertex to an OBJ file.
Definition: MapObjLoader.hpp:22
void generateAreaObjs(const std::vector< std::vector< int >> &heightMap, const std::vector< std::vector< std::string >> &areaMap)
Generates obj map for each area of the map.
Definition: MapObjLoader.hpp:51
void writeFace(std::ofstream &objFile, const int corner1, const int corner2, const int corner3)
Writes a face to an OBJ file.
Definition: MapObjLoader.hpp:36
WINDING_ORDER
Definition: MapObjLoader.hpp:3
@ CLOCKWISE
Definition: MapObjLoader.hpp:4
@ COUNTER_CLOCKWISE
Definition: MapObjLoader.hpp:5
Definition: MapObjLoader.hpp:10
Vertex(float x, float y, float z)
Definition: MapObjLoader.hpp:13
float y
Definition: MapObjLoader.hpp:11
float v
Definition: MapObjLoader.hpp:12
float x
Definition: MapObjLoader.hpp:11
float z
Definition: MapObjLoader.hpp:11
float u
Definition: MapObjLoader.hpp:12