title: 2D Diamond (isometric) map editor - Textures extended infinitely?
body: <p>I'm currently developing a 2D isometric map editor.
  I display entity(cube, player) which contains points and textures.
  Each cubes are composed by 12 points.(12 points, but handled as 3 sides of 4 points when displayed by sfml(sf::VertexArray).</p>
  
  <p>(I know I include some '.cpp' times to times, I have a problem with my IDE(visual studio) which I'm trying to resolve, please do not care about it.)</p>
  
  <p><strong>main.cpp</strong></p>
  
  <pre><code>#pragma once
  #include "globalfunctions.h" //global functions + main headers + class headers
  
  int main() {
      int mapSize = 0;
      int cubeSize = 0;
  
      cout &lt;&lt; "Map size: "; cin &gt;&gt; mapSize; cout &lt;&lt; endl;
      cout &lt;&lt; "Cube size: "; cin &gt;&gt; cubeSize; cout &lt;&lt; endl;
  
      int windowWidth = (mapSize * cubeSize) - (cubeSize * 2);
      int windowHeight = ((mapSize * cubeSize) - (cubeSize * 2)) / 2;
  
      renderWindow window(windowWidth, windowHeight, mapSize, cubeSize);
          int nbMaxTextures = 9;
          for (int t = 0; t &lt; nbMaxTextures; t++) {
              window.loadTexture("test", t);
          }
  
      window.run();
  
      return EXIT_SUCCESS;
  }
  </code></pre>
  
  <p><strong>globalfunctions.h</strong></p>
  
  <pre><code>#pragma once
  #include &lt;SFML/System.hpp&gt;
  #include &lt;SFML/Graphics.hpp&gt;
  #include &lt;SFML/Window.hpp&gt;
  #include &lt;iostream&gt;
  #include &lt;math.h&gt;
  //#include &lt;sstream&gt;
  #include &lt;vector&gt;
  
  using namespace std;
  
  sf::Vector2u isometricToCartesian(int i, int j, int cubeSize) {
      sf::Vector2u carth;
          carth.x = (j - i) * (cubeSize / 2);
          carth.y = (j + i) * (cubeSize / 4);
  
      return carth;
  }
  
  sf::Vector2u cartesianToIsometric(int x, int y, int cubeSize) {//TODO
      sf::Vector2u iso;
          iso.x = 0;
          iso.y = 0;
  
      return iso;
  }
  
  #include "entity.h"
  #include "renderWindow.h"
  </code></pre>
  
  <p><strong>renderWindow.h</strong></p>
  
  <pre><code>#pragma once
  
  class renderWindow {
      public:
          renderWindow(float WIDTH, float HEIGHT, int MAPSIZE, int CUBESIZE);
          void run();
          void loadTexture(sf::String folder, int numTexture);
  
          //SETTERS
          //...
  
          //GETTERS
          //...
  
      private:
          int mCurrentLayerID;
          int mMapSize;
          int mCubeSize;
          int mSelectedTexture;
  
          vector&lt;entity&gt; mMap;
  
          sf::RenderWindow mWindow;
          vector&lt;sf::Texture&gt; mTextures;
              sf::Texture mMemoryTexture;
  
          void processEvent();
          void update(sf::Time deltaTime);
          void render();
  
  //CUBE ACTION-------------------------------------------
          void addCube(int layerID, float x, float y);
          entity&amp; getCube(int ID);
          entity&amp; getCubeAt(float x, float y);
          vector&lt;sf::VertexArray&gt; loadCube(int cubeID);//UPDATE DATA LIKE COORDINATES -&gt; create/chnge the vertex
          void drawCube(int cubeID);//draw the vertex
  
          //VARIABLES
          vector&lt;sf::VertexArray&gt; verticesSide1;
          vector&lt;sf::VertexArray&gt; verticesSide2;
          vector&lt;sf::VertexArray&gt; verticesSide3;
  //CUBE ACTION-------------------------------------------
  };
  
  #include "renderWindow.cpp"
  </code></pre>
  
  <p><strong>renderWindow.cpp</strong></p>
  
  <pre><code>#pragma once
  
  renderWindow::renderWindow(float WIDTH, float HEIGHT, int MAPSIZE, int CUBESIZE) : mWindow(sf::VideoMode(WIDTH, HEIGHT), "") {
      mMapSize = MAPSIZE;
      mCubeSize = CUBESIZE;
  
      mSelectedTexture = 6;
  
      mCurrentLayerID = -1;
  
      int x = 0;
      int y = 0;
  
      //default layer
      for (int j = 0; j &lt; mMapSize; j++) {
          for (int i = 0; i &lt; mMapSize; i++) {
              x = isometricToCartesian(i, j, mCubeSize).x;
              y = isometricToCartesian(i, j, mCubeSize).y;
              addCube(0, x, y);
          }
      }
  
      for (int c = 0; c &lt; mMap.size(); c++) {
          verticesSide1.push_back(loadCube(c)[0]);
          verticesSide2.push_back(loadCube(c)[1]);
          verticesSide3.push_back(loadCube(c)[2]);
  
          //then only do that when something the cube's coordinate changed
      }
  }
  
  void renderWindow::run() {
      sf::Clock clock;
      sf::Time timeSinceLastUpdate = sf::Time::Zero;
      sf::Time TimePerFrame = sf::seconds(1.f / 60.f);
  
      while (mWindow.isOpen()) {
          processEvent();
  
          timeSinceLastUpdate += clock.restart();
  
          while (timeSinceLastUpdate &gt; TimePerFrame) {
              timeSinceLastUpdate -= TimePerFrame;
  
              processEvent();
              update(TimePerFrame);
          }
  
          render();
      }
  }
  
  void renderWindow::loadTexture(sf::String folder, int numTexture) {
      if (mMemoryTexture.loadFromFile("textures/" + folder + "/" + to_string(numTexture) + ".jpg"))
          mTextures.push_back(mMemoryTexture);
      else
          cout &lt;&lt; "Texture n°" &lt;&lt; numTexture &lt;&lt; " as failed to load." &lt;&lt; endl;
  }
  
  
  //SETTERS
  //...
  
  //GETTERS
  //...
  
  //PRIVATE METHODE
  void renderWindow::processEvent() {
      sf::Event event;
  
      while (mWindow.pollEvent(event)) {
          switch (event.type) {
          case sf::Event::Closed:
              mWindow.close();
              break;
  
          case sf::Event::KeyPressed:
              if (event.key.code == sf::Keyboard::Escape)
                  mWindow.close();
              break;
  
          case sf::Event::MouseButtonPressed:
              if (event.MouseButtonPressed == sf::Mouse::Left)
                  getCubeAt(event.mouseButton.x, event.mouseButton.y).setTexture(0, mSelectedTexture);//TEST
                  getCubeAt(event.mouseButton.x, event.mouseButton.y).setTexture(1, mSelectedTexture + 1);//TEST
                  getCubeAt(event.mouseButton.x, event.mouseButton.y).setTexture(2, mSelectedTexture + 2);//TEST
              break;
  
              /*case sf::Event::MouseMoved:
                  cout &lt;&lt; "(" &lt;&lt; event.mouseMove.x &lt;&lt; ", " &lt;&lt; event.mouseMove.y &lt;&lt; ")" &lt;&lt; endl;
                  break;*/
          }
      }
  }
  
  void renderWindow::update(sf::Time deltaTime) {
      //REMEMBER: distance = speed * time
      //MOVEMENT, ANIMATIONS ETC. ...
  }
  
  void renderWindow::render() {
      mWindow.clear();
  
      for (int c = 0; c &lt; mMap.size(); c++) {
          drawCube(c);
      }
  
      mWindow.display();
  }
  
  //CUBE ACTION-------------------------------------------
  void renderWindow::addCube(int layerID, float x, float y) {
      //Thoses make the code more readable:
          int half_cubeSize = mCubeSize / 2;
          int oneQuarter_cubeSize = mCubeSize / 4;
          int twoQuarter_cubeSize = oneQuarter_cubeSize * 2;
          int treeQuarter_cubeSize = oneQuarter_cubeSize * 3;
  
      mCurrentLayerID = layerID;
  
      entity dummy(mMap.size(), 0, layerID);
          dummy.addPoint(12);
          dummy.addTexture(6);
          dummy.addTexture(7);
          dummy.addTexture(8);
      //SIDE 1------------------------------------------------
          dummy.setPoint(0, x, y + oneQuarter_cubeSize);
          dummy.setPoint(1, x + half_cubeSize, y + twoQuarter_cubeSize);
          dummy.setPoint(2, x + half_cubeSize, y + mCubeSize);
          dummy.setPoint(3, x, y + treeQuarter_cubeSize);
      //SIDE 2------------------------------------------------
          dummy.setPoint(4, x + half_cubeSize, y + twoQuarter_cubeSize);
          dummy.setPoint(5, x + mCubeSize, y + oneQuarter_cubeSize);
          dummy.setPoint(6, x + mCubeSize, y + treeQuarter_cubeSize);
          dummy.setPoint(7, x + half_cubeSize, y + mCubeSize);
      //SIDE 3------------------------------------------------
          dummy.setPoint(8, x, y + oneQuarter_cubeSize);
          dummy.setPoint(9, x + half_cubeSize, y);
          dummy.setPoint(10, x + mCubeSize, y + oneQuarter_cubeSize);
          dummy.setPoint(11, x + half_cubeSize, y + twoQuarter_cubeSize);
  
      mMap.push_back(dummy);
  }
  
  entity&amp; renderWindow::getCube(int ID) {
      for (int c = 0; c &lt; mMap.size(); c++) {
          if (mMap[c].getID() == ID)
              return mMap[c];
      }
  }
  
  entity&amp; renderWindow::getCubeAt(float x, float y) {//TO DO
      return entity(-1, 0, 0);
  }
  
  vector&lt;sf::VertexArray&gt; renderWindow::loadCube(int cubeID) {
      vector&lt;sf::VertexArray&gt; vertices;
      vertices.push_back(sf::VertexArray());
      vertices.push_back(sf::VertexArray());
      vertices.push_back(sf::VertexArray());
  
      vertices[0].setPrimitiveType(sf::Quads);
      vertices[0].resize(4);
  
      vertices[1].setPrimitiveType(sf::Quads);
      vertices[1].resize(4);
  
      vertices[2].setPrimitiveType(sf::Quads);
      vertices[2].resize(4);
  
      sf::Vector2f tv0 = sf::Vector2f(0, 0);
      sf::Vector2f tv1 = sf::Vector2f(mCubeSize, 0);
      sf::Vector2f tv2 = sf::Vector2f(mCubeSize, mCubeSize);
      sf::Vector2f tv3 = sf::Vector2f(0, mCubeSize);
  
      sf::Vector2f v0 = sf::Vector2f(getCube(cubeID).getPoint(0, 0), getCube(cubeID).getPoint(0, 1));
      sf::Vector2f v1 = sf::Vector2f(getCube(cubeID).getPoint(1, 0), getCube(cubeID).getPoint(1, 1));
      sf::Vector2f v2 = sf::Vector2f(getCube(cubeID).getPoint(2, 0), getCube(cubeID).getPoint(2, 1));
      sf::Vector2f v3 = sf::Vector2f(getCube(cubeID).getPoint(3, 0), getCube(cubeID).getPoint(3, 1));
  
      sf::Vector2f v4 = sf::Vector2f(getCube(cubeID).getPoint(4, 0), getCube(cubeID).getPoint(4, 1));
      sf::Vector2f v5 = sf::Vector2f(getCube(cubeID).getPoint(5, 0), getCube(cubeID).getPoint(5, 1));
      sf::Vector2f v6 = sf::Vector2f(getCube(cubeID).getPoint(6, 0), getCube(cubeID).getPoint(6, 1));
      sf::Vector2f v7 = sf::Vector2f(getCube(cubeID).getPoint(7, 0), getCube(cubeID).getPoint(7, 1));
  
      sf::Vector2f v8 = sf::Vector2f(getCube(cubeID).getPoint(8, 0), getCube(cubeID).getPoint(8, 1));
      sf::Vector2f v9 = sf::Vector2f(getCube(cubeID).getPoint(9, 0), getCube(cubeID).getPoint(9, 1));
      sf::Vector2f v10 = sf::Vector2f(getCube(cubeID).getPoint(10, 0), getCube(cubeID).getPoint(10, 1));
      sf::Vector2f v11 = sf::Vector2f(getCube(cubeID).getPoint(11, 0), getCube(cubeID).getPoint(11, 1));
  
      vertices[0][0] = sf::Vertex(v0, tv0);
      vertices[0][1] = sf::Vertex(v1, tv1);
      vertices[0][2] = sf::Vertex(v2, tv2);
      vertices[0][3] = sf::Vertex(v3, tv3);
  
      vertices[1][0] = sf::Vertex(v4, tv0);
      vertices[1][1] = sf::Vertex(v5, tv1);
      vertices[1][2] = sf::Vertex(v6, tv2);
      vertices[1][3] = sf::Vertex(v7, tv3);
  
      vertices[2][0] = sf::Vertex(v8, tv0);
      vertices[2][1] = sf::Vertex(v9, tv1);
      vertices[2][2] = sf::Vertex(v10, tv2);
      vertices[2][3] = sf::Vertex(v11, tv3);
  
      return vertices;
  }
  
  void renderWindow::drawCube(int cubeID) {
      mWindow.draw(verticesSide1[cubeID], &amp;mTextures[getCube(cubeID).getTexture(0)]);
      mWindow.draw(verticesSide2[cubeID], &amp;mTextures[getCube(cubeID).getTexture(1)]);
      mWindow.draw(verticesSide3[cubeID], &amp;mTextures[getCube(cubeID).getTexture(2)]);
  }
  
  //CUBE ACTION-------------------------------------------
  </code></pre>
  
  <p><strong>entity.h</strong></p>
  
  <pre><code>    #pragma once
  
      class entity {
      public:
          entity();
          entity(int id, int type, int numlayer);
          void addPoint(int nbPoints);
          void addTexture(int numTexture);
  
          //SETTERS
          void setPoint(int numPoint, float x, float y);
          void setTexture(int textureID, int numTexture);
  
          //GETTERS
          int getID();
          float getPoint(int numPoint, int numIndex);//if numIndex = 0 -&gt; x || if numIndex = 1 -&gt; y
          int getType();
          int getNumLayer();
          int getTexture(int numTexture);
  
      private:
          int mID;
          int mType;
          int mNumLayer;
          vector&lt;sf::Vector2u&gt; mPoints;
          vector&lt;int&gt; mTextures;
      };
  
      #include "entity.cpp"
  </code></pre>
  
  <p><strong>entity.cpp</strong></p>
  
  <pre><code>#pragma once
  
  entity::entity() {
      mID = 0;
      mType = -1;
      mNumLayer = 0;
  }
  
  entity::entity(int id, int type, int numlayer) {
      mID = id;
      mType = type;
      mNumLayer = numlayer;
  }
  
  void entity::addPoint(int nbPoints) {
      mPoints.clear();
  
      int newSize = 0;
      for (int p = 0; p &lt; nbPoints; p++) {
          newSize++;
      }
  
      mPoints = vector&lt;sf::Vector2u&gt;(newSize);
  }
  
  void entity::addTexture(int numTexture) {
      mTextures.push_back(numTexture);
  }
  
  //SETTERS
  void entity::setPoint(int numPoint, float x, float y) {
      mPoints[numPoint].x = x;
      mPoints[numPoint].y = y;
  }
  
  void entity::setTexture(int textureID, int numTexture) {
      mTextures[textureID] = numTexture;
  }
  
  //GETTERS
  int entity::getID() {
      return mID;
  }
  
  float entity::getPoint(int numPoint, int numIndex) {
      if (numIndex == 0)
          return mPoints[numPoint].x;
      else
          return mPoints[numPoint].y;
  }
  
  int entity::getType() {
      return mType;
  }
  
  int entity::getNumLayer() {
      return mNumLayer;
  }
  
  int entity::getTexture(int numTexture) {
      return mTextures[numTexture];
  }
  </code></pre>
  
  <p>I've done a lot of test, too much, so I won't post them right now, but if you have any question, feel free to ask.</p>
  
  <p>Here is the problem described in the title :</p>
  
  <p><a href="https://i.stack.imgur.com/agNNZ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/agNNZ.png" alt="enter image description here"></a></p>
  
  <p>And here, screens with only one face displayed(in the same order in the code):</p>
  
  <p><a href="https://i.stack.imgur.com/xgnF2.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/xgnF2.png" alt="Side 1 only displayed"></a></p>
  
  <p><a href="https://i.stack.imgur.com/xD2wc.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/xD2wc.png" alt="Side 2 only displayed"></a></p>
  
  <p><a href="https://i.stack.imgur.com/d2VVe.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/d2VVe.png" alt="Side 3 only displayed"></a></p>
  
  <p><em>The only thing I don't understand is that a cube displayed alone work perfectly fine if you enter the coordinates manually. Even the extended ones. But the coordinates formula is ok... (I noticed that the cube n°50 for a 15x15 map with 64x64 cube display a rectangle 'infinite' in width)
  If the texture is extended(maybe to the infinite), it suggest that the coordinates are continuously increasing somewhere ? Then, why the cubes are still well placed ?</em></p>
  
  <p>Here are the assets(64*64 png) :
  <a href="https://i.stack.imgur.com/m4mC8.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/m4mC8.jpg" alt="enter image description here"></a><a href="https://i.stack.imgur.com/pDbyx.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/pDbyx.jpg" alt="enter image description here"></a><a href="https://i.stack.imgur.com/qdzy6.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/qdzy6.jpg" alt="enter image description here"></a>
  Directories : textures/test/</p>