1

I want to create isometric 2D game. I use modern LWJGL (vertex arrays, shaders etc.) I found true isometric projection with opengl and: I tried to rotate my projection matrix, but it created black triangles on corners of screen. I tried to rotate model matrix, but I found that I can't rotate x and y on ortho matrix (because it's 2D), it doesenter image description here but I need to rotate x and y axis to get isometric matrix. Then I found this https://www.gamedev.net/blog/33/entry-2250273-isometric-map-in-sfml/ and it says that I only need place tiles on right spots. Who is right? And why in first link they rotate model matrix in old OpenGL even though it's 2D projection matrix and I can't rotate it on modern OpenGL? (Sorry for my bad English)

Edit: How I create model matrix (I use joml for them): public Matrix4f getModel(GameItem item){ Vector3f rot = item.getRotation(); return new Matrix4f().translate(item.getPosition()).rotateX((float)Math.toRadians(-rot.x)).rotateY((float)Math.toRadians(-rot.y)).rotateZ((float)Math.toRadians(-rot.z)).scale(item.getScale()); } How I create projection matrix: public void updateProjectionMatrix(Window window){ projectionMatrix2D.identity().ortho2D(-window.getWidth(), window.getWidth(), -window.getHeight(), window.getHeight()); } If I rotate matrix before ortho2D() everything is rotated correctly, however there are black triangles on two of screen's corners. If I rotate it after ortho2D() it does exactly like rotating model matrix (shrinks object). In render() I pass matrixes to vertex shader:

#version 330

layout (location=0) in vec3 position;
layout (location=1) in vec2 texCoord;

out vec2 outTexCoord;


uniform mat4 projectionMatrix;
uniform mat4 model;

void main()
{
 gl_Position = projectionMatrix*  model * vec4(position, 1.0);
 outTexCoord = texCoord;
}

Edit 2: Creating view matrix works:

With view matrix

However it does exactly like rotating projection matrix before ortho2D() - it creates black (because that's my clear color) triangles on two of screen's corners:

Black triangle

and there:

Second triangle

How do I get rid of them?

Edit 3: I rewrote my code, but nothing has changed.

To run my code, you should add to project LWJGL library, LWJGL-GLFW, LWJGL-STB, LWJGL-OpenGl and JOML library (it's not downloaded with LWJGL). You will also need a random .png image.

Main class:

import Core.Engine;

public class Main { 
    public static void main(String[] args){
        try{
        //Is vsync enabled?
        boolean vsync = true;
        Engine engine = new Engine("GAME", vsync);
        //Start program
        engine.start();

        }
        catch(Exception ex){
            ex.printStackTrace();
            System.exit(-1);
        }
    }   
}

Engine class:

package Core;

public class Engine implements Runnable{

     public static final int TARGET_FPS = 60;

        public static final int TARGET_UPS = 30;

        private final Window window;

        //Program thread
        private final Thread gameLoopThread;

        //Timer for gameLoop
        private final Timer timer;

        //Creates everything that is on screen
        private final Logic logic;

        public Engine(String windowTitle, boolean vSync) throws Exception {
            gameLoopThread = new Thread(this, "GAME_LOOP_THREAD");
            window = new Window(windowTitle, vSync);
            logic = new Logic();
            timer = new Timer();        
        }

        public void start() {
            String osName = System.getProperty("os.name");
            if ( osName.contains("Mac") ) {
                gameLoopThread.run();
            } else {
                gameLoopThread.start();
            }
        }

        @Override
        public void run() {
            try {
                init();
                gameLoop();

            } catch (Exception excp) {
                excp.printStackTrace();
            }
        }

        protected void init() throws Exception {

            window.init();
            timer.init();
            logic.init(this.window);
        }

        protected void gameLoop() {
            float elapsedTime;
            float accumulator = 0f;
            float interval = 1f / TARGET_UPS;

            boolean running = true;
            while (running && !window.shouldClose()) {

                elapsedTime = timer.getElapsedTime();
                accumulator += elapsedTime;

                input();

                while (accumulator >= interval) {
                    update(interval);
                    accumulator -= interval;
                }

                render();

                if (!window.isVsync()) {
                    sync();
                }
            }
        }

        private void sync() {
            float loopSlot = 1f / TARGET_FPS;
            double endTime = timer.getLastLoopTime() + loopSlot;
            while (Timer.getTime() < endTime) {
                try {
                    Thread.sleep(1);
                } catch (InterruptedException ie) {
                }
            }
        }
        protected void input() {

            logic.input(window);
        }
        protected void update(float interval) {

            logic.update(interval,window);
        }
    protected void render() {   
           logic.render(window);
            window.update();
        }
    }

Timer class:

package Core;

public class Timer {

private double lastLoopTime;

public void init(){
    lastLoopTime = getTime();
    }

public static double getTime(){ 

return (double)((double)System.nanoTime() / (double)1000_000_000L); 
}
public float getElapsedTime(){

    double time = getTime();
    float elapsedTime  =(float) (time-lastLoopTime);
    lastLoopTime = time;
    return elapsedTime;
}
public double getLastLoopTime(){

    return lastLoopTime;
}
}

Window class:

package Core;

import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;

import static org.lwjgl.system.MemoryUtil.*;

import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;

public class Window {

    private long window;

    private int width, height;

    private boolean vsync;

    private String title;

    public Window(String title,boolean vsync){

        this.title = title;
        this.vsync = vsync;
    }
    public long getInstance(){

        return window;
    }
    public void init(){

    GLFWErrorCallback.createPrint(System.err).set();

     if(!glfwInit()){
            // Throw an error.
           throw new IllegalStateException("GLFW initialization failed!");
          }

            glfwWindowHint(GLFW_VISIBLE, GL_TRUE); // the window will stay hidden after creation
            glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // the window will not be resizable
            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
            glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
            glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);


            GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
            width = vidmode.width();
            height = vidmode.height() -30;
            System.out.println(width + " "+ height);

            window = GLFW.glfwCreateWindow(width,height, title,NULL, NULL);

            if(window == NULL){

                throw new RuntimeException("ERROR with Window");
            }

            GLFW.glfwSetWindowPos(window, 0, 29);

            glfwMakeContextCurrent(window);
            if(vsync)
            GLFW.glfwSwapInterval(1);

            glfwShowWindow(window);
            GL.createCapabilities();
            glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    }

    public boolean isKeyPressed(int keyCode) {
        return GLFW.glfwGetKey(window, keyCode) == GLFW.GLFW_PRESS;
    }

    public void setClearColor(float r, float g, float b, float alpha) {
            glClearColor(r, g, b, alpha);
    }

    public boolean shouldClose(){

        return glfwWindowShouldClose(window);
    }
    public void update(){

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    public void setVsync(boolean aflag){
         this.vsync = aflag;
    }
    public boolean isVsync(){
         return vsync;
    }
     public int getWidth(){
         return width;
    }
    public int getHeight(){
         return height;
    }    
}

Logic class:

package Core;

import org.joml.Vector3f;
import org.lwjgl.glfw.GLFW;

public class Logic {

    private Renderer render;

    private GameItem item;

        public void init(Window window) throws Exception {
            //create object
               float[] positions = new float[]{
                        -600,  600,  0f,//0
                        -600, -600,  0f,//1
                        600, -600,  0,//2
                        600,  600,  0f//3
               };
               float[] texCoords = new float[]{
                          0,0,//0
                          0,1,//1
                          1,1,//2
                          1,0 //3                     
                  };
                    int[] indices = new int[]{
                        0, 1, 3, 3, 1, 2,
                    };
               render = new Renderer();
               render.init(window);
               Texture texture = new Texture("Textures/image.png");
               Mesh mesh = new Mesh(positions,texCoords,indices,texture);
               item = new GameItem(mesh);
               item.setPosition(-100, 0, 0);

        }


        public void input(Window window) {
            //move
            Vector3f s = item.getPosition();

            if(window.isKeyPressed(GLFW.GLFW_KEY_W)){
                item.setPosition(s.x, s.y+5, s.z);
            }
            else if(window.isKeyPressed(GLFW.GLFW_KEY_S)){
                item.setPosition(s.x, s.y-5, s.z);
            }
            else if(window.isKeyPressed(GLFW.GLFW_KEY_A)){
                item.setPosition(s.x-5, s.y, s.z);
            }
            else if(window.isKeyPressed(GLFW.GLFW_KEY_D)){
                item.setPosition(s.x+5, s.y, s.z);
            }
        }


        public void update(float interval, Window window) {
        }
        public void render(Window window) {
        render.render(window,item);
        }

        public void cleanup() {
            render.cleanup();
        }
    }

Renderer class:

package Core;

import static org.lwjgl.opengl.GL11.*;

import org.joml.Matrix4f;
import org.joml.Vector3f;

public class Renderer {

    private Matrix4f projectionMatrix2D;

    private Matrix4f view;

    private ShaderProgram shaderProgram;

    public Renderer() {

        projectionMatrix2D= new Matrix4f();
    }

    public void init(Window window) throws Exception {

        shaderProgram = new ShaderProgram();
        shaderProgram.createVertexShader(Utils.load("Shaders/vertex.vs"));
        shaderProgram.createFragmentShader(Utils.load("Shaders/fragment.fs"));
        shaderProgram.link();

        shaderProgram.createUniform("projectionMatrix");
        shaderProgram.createUniform("model");
        shaderProgram.createUniform("texture_sampler");
        shaderProgram.createUniform("view");

        view = new Matrix4f().lookAt(new Vector3f(1,1,1), new Vector3f(0), new Vector3f(0,1,0));
        updateProjectionMatrix(window);
    }

    public void clear() {
        glClear(GL_COLOR_BUFFER_BIT);
    }

    public void render(Window window,GameItem item) {
        clear();

        updateProjectionMatrix(window);
        shaderProgram.bind();

        shaderProgram.setUniform("projectionMatrix", projectionMatrix2D);
        shaderProgram.setUniform("view", view);
        shaderProgram.setUniform("texture_sampler", 0);

        Vector3f rot = item.getRotation();
        Matrix4f model = new Matrix4f().translate(item.getPosition()).rotateX((float)Math.toRadians(-rot.x))
                .rotateY((float)Math.toRadians(-rot.y))
                .rotateZ((float)Math.toRadians(-rot.z))
                .scale(item.getScale());

        shaderProgram.setUniform("model", model);
        item.getMesh().render();

        shaderProgram.unbind();
    }
   public void updateProjectionMatrix(Window window){

     projectionMatrix2D.identity().ortho2D(-window.getWidth(), window.getWidth(), -window.getHeight(), window.getHeight());
     //it creates weird triangle on right screen corner
     // projectionMatrix2D.identity().ortho2D(-1, 1, -1, 1);
   }
    public void cleanup() {

        if (shaderProgram != null) {
            shaderProgram.cleanup();
        }
    }
}

ShaderProgram class:

package Core;

import static org.lwjgl.opengl.GL20.*;

import java.nio.FloatBuffer;
import java.util.HashMap;
import java.util.Map;

import org.joml.Matrix4f;
import org.joml.Vector2f;
import org.joml.Vector3f;
import org.lwjgl.system.MemoryStack;

public class ShaderProgram {

       private final int programId;

        private int vertexShaderId;

        private int fragmentShaderId;

        private final Map<String, Integer> uniforms;

        public ShaderProgram() throws Exception {

            programId = glCreateProgram();
            if (programId == 0) {
                throw new Exception("Could not create Shader");
            }
            uniforms = new HashMap<>();
        }

        public void createUniform(String uniformName) throws Exception {
            int uniformLocation = glGetUniformLocation(programId, uniformName);
            if (uniformLocation < 0) {
                throw new Exception("Could not find uniform:" + uniformName);
            }
            uniforms.put(uniformName, uniformLocation);
        }

        public void setUniform(String uniformName, Matrix4f value) {
            try (MemoryStack stack = MemoryStack.stackPush()) {
                FloatBuffer fb = stack.mallocFloat(16);
                value.get(fb);
                glUniformMatrix4fv(uniforms.get(uniformName), false, fb);
            }
        }

        public void setUniform(String uniformName, int value) {
            glUniform1i(uniforms.get(uniformName), value);
        }

        public void setUniform(String uniformName, float value) {
            glUniform1f(uniforms.get(uniformName), value);
        }

        public void setUniform(String uniformName, Vector3f value) {
            glUniform3f(uniforms.get(uniformName), value.x, value.y, value.z);
        }

        public void setUniform(String uniformName, org.joml.Vector4f value) {
            glUniform4f(uniforms.get(uniformName), value.x, value.y, value.z, value.w);
        }

        public void setUniform(String uniformName, Vector2f vector2f) {

            glUniform2f(uniforms.get(uniformName),vector2f.x,vector2f.y);
        }
        public void createVertexShader(String shaderCode) throws Exception {
            vertexShaderId = createShader(shaderCode, GL_VERTEX_SHADER);
        }

        public void createFragmentShader(String shaderCode) throws Exception {
            fragmentShaderId = createShader(shaderCode, GL_FRAGMENT_SHADER);
        }

        protected int createShader(String shaderCode, int shaderType) throws Exception {
            int shaderId = glCreateShader(shaderType);
            if (shaderId == 0) {
                throw new Exception("Error creating shader. Type: " + shaderType);
            }

            glShaderSource(shaderId, shaderCode);
            glCompileShader(shaderId);

            if (glGetShaderi(shaderId, GL_COMPILE_STATUS) == 0) {
                throw new Exception("Error compiling Shader code: " + glGetShaderInfoLog(shaderId, 1024));
            }

            glAttachShader(programId, shaderId);

            return shaderId;
        }

        public void link() throws Exception {
            glLinkProgram(programId);
            if (glGetProgrami(programId, GL_LINK_STATUS) == 0) {
                throw new Exception("Error linking Shader code: " + glGetProgramInfoLog(programId, 1024));
            }

            if (vertexShaderId != 0) {
                glDetachShader(programId, vertexShaderId);
            }
            if (fragmentShaderId != 0) {
                glDetachShader(programId, fragmentShaderId);
            }

            glValidateProgram(programId);
            if (glGetProgrami(programId, GL_VALIDATE_STATUS) == 0) {
                System.err.println("Warning validating Shader code: " + glGetProgramInfoLog(programId, 1024));
            }
        }

        public void bind() {

            glUseProgram(programId);
        }

        public void unbind() {

            glUseProgram(0);
        }

        public void cleanup() {

            unbind();
            if (programId != 0) {
                glDeleteProgram(programId);
            }
        }
}

GameItem class:

package Core;
import org.joml.Vector3f;


public class GameItem {

    //Mesh for this gameItem
    private Mesh mesh;

    private final Vector3f position;

    private float scale = 1;

    private final Vector3f rotation;

    public GameItem() {
        position = new Vector3f(0, 0, 0);
        scale = 1;
        rotation = new Vector3f(0, 0, 0);
    }

    public GameItem(Mesh mesh) {
        this();
        this.mesh = mesh;
    }
    public GameItem(GameItem item){
        this();
         position.set(item.position);
         scale =1;
         rotation.set(item.rotation);
        this.mesh = item.mesh;
        }

    public Vector3f getPosition() {
        return position;
    }

    public void setPosition(float x, float y, float z) {
        this.position.x = x;
        this.position.y = y;
        this.position.z = z;
    }

    public float getScale() {
        return scale;
    }

    public void setScale(float scale) {
        this.scale = scale;
    }

    public Vector3f getRotation() {
        return rotation;
    }

    public void setRotation(float x, float y, float z) {
        this.rotation.x = x;
        this.rotation.y = y;
        this.rotation.z = z;
    }

    public Mesh getMesh() {
        return mesh;
    }
    public void setMesh(Mesh mesh){
 this.mesh = mesh;      

  }
}

Utils class:

package Core;

    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;

    public class Utils {
        //Load strings
        public static String load(String path){
        StringBuilder builder = new StringBuilder();

        try (InputStream in = new FileInputStream(path);
             BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
            String line;
            while ((line = reader.readLine()) != null) {
                builder.append(line).append("\n");
            }
        } catch (IOException ex) {
            throw new RuntimeException("Failed to load a shader file!"
                                       + System.lineSeparator() + ex.getMessage());
        }
       String source = builder.toString();

       return source; 
 }

}    

Mesh class:

package Core;

import java.util.List;

import org.lwjgl.system.MemoryUtil;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;


public class Mesh{ 

    private final int vaoId;

    private final List<Integer> vboIdList;

    private final int vertexCount;

    private Texture texture;

    public Mesh(float[] positions, float[] textCoords, int[] indices,Texture texture) {
        this.texture = texture;

        FloatBuffer posBuffer = null;
        FloatBuffer textCoordsBuffer = null;

        IntBuffer indicesBuffer = null;
        try {
            vertexCount = indices.length;
            vboIdList = new ArrayList<>();


            vaoId = glGenVertexArrays();
            glBindVertexArray(vaoId);

            // Position 
            int vboId = glGenBuffers();
            vboIdList.add(vboId);
            posBuffer = MemoryUtil.memAllocFloat(positions.length);
            posBuffer.put(positions).flip();
            glBindBuffer(GL_ARRAY_BUFFER, vboId);
            glBufferData(GL_ARRAY_BUFFER, posBuffer, GL_STATIC_DRAW);
            glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);

            // Texture coordinates 
            vboId = glGenBuffers();
            vboIdList.add(vboId);
            textCoordsBuffer = MemoryUtil.memAllocFloat(textCoords.length);
            textCoordsBuffer.put(textCoords).flip();
            glBindBuffer(GL_ARRAY_BUFFER, vboId);
            glBufferData(GL_ARRAY_BUFFER, textCoordsBuffer, GL_STATIC_DRAW);
            glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);

            // Index 
            vboId = glGenBuffers();
            vboIdList.add(vboId);
            indicesBuffer = MemoryUtil.memAllocInt(indices.length);
            indicesBuffer.put(indices).flip();
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_STATIC_DRAW);

            glBindBuffer(GL_ARRAY_BUFFER, 0);
            glBindVertexArray(0);
        } finally {
            if (posBuffer != null) {
                MemoryUtil.memFree(posBuffer);
            }
            if (textCoordsBuffer != null) {
                MemoryUtil.memFree(textCoordsBuffer);
            }
            if (indicesBuffer != null) {
                MemoryUtil.memFree(indicesBuffer);
            }
        }
    }

    public Texture getTexture() {

        return texture;
    }

    public void setTexture(Texture texture) {

        this.texture = texture;
    }

    public int getVaoId() {

        return vaoId;
    }

    public int getVertexCount() {

        return vertexCount;
    }

    public void cleanUp() {

        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        for (int vboId : vboIdList) {
            glDeleteBuffers(vboId);
        }
            texture.cleanup();

        glBindVertexArray(0);
        glDeleteVertexArrays(vaoId);
    }

       public void render(){

         glBindVertexArray(getVaoId());
         glEnableVertexAttribArray(0);
         glEnableVertexAttribArray(1);

         glDrawElements(GL_TRIANGLES, getVertexCount(), GL_UNSIGNED_INT, 0);

         glDisableVertexAttribArray(0);
         glDisableVertexAttribArray(1);
         glBindVertexArray(0);
    }
}

Texture class:

package Core;

import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import org.lwjgl.system.MemoryStack;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL30.glGenerateMipmap;
import static org.lwjgl.stb.STBImage.*;

public class Texture {

    private final int id;

    public Texture(String fileName) throws Exception {
        this(loadTexture(fileName));
    }

    public Texture(int id) {
        this.id = id;
    }

    public void bind() {
        glBindTexture(GL_TEXTURE_2D, id);
    }

    public int getId() {
        return id;
    }

    private static int loadTexture(String fileName) throws Exception {
        int width;
        int height;
        ByteBuffer buf;

        try (MemoryStack stack = MemoryStack.stackPush()) {
            IntBuffer w = stack.mallocInt(1);
            IntBuffer h = stack.mallocInt(1);
            IntBuffer channels = stack.mallocInt(1);

            buf = stbi_load(fileName, w, h, channels, 4);

            if (buf == null) {
                throw new Exception("Image file " + fileName  + " not loaded: " + stbi_failure_reason());
            }


            width = w.get();
            height = h.get();
        }


        int textureId = glGenTextures();

        glBindTexture(GL_TEXTURE_2D, textureId);


        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);


        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
                GL_RGBA, GL_UNSIGNED_BYTE, buf);

        glGenerateMipmap(GL_TEXTURE_2D);

        stbi_image_free(buf);

        return textureId;
    }

    public void cleanup() {

        glDeleteTextures(id);
    }
}

Vertex shader:

#version 330

layout (location=0) in vec3 position;
layout (location=1) in vec2 texCoord;

out vec2 outTexCoord;


uniform mat4 projectionMatrix;
uniform mat4 model;
uniform mat4 view;

void main()
{
    gl_Position = projectionMatrix  * view * model * vec4(position, 1.0); // if view is after vec4 it creates actually object, but it creates black triangles as well. Without view matrix it is just a normal square
    outTexCoord = texCoord;
}

Fragment shader:

#version 330

in  vec2 outTexCoord;

out vec4 fragColor;

uniform sampler2D texture_sampler;

void main()
{
fragColor = texture(texture_sampler,outTexCoord);
}
Mark
  • 21
  • 4
  • Please, add some code to your question showing the matrices you use, and how you use them. – Ripi2 Jun 02 '20 at 16:40
  • There isn't "right way" to do that. It depends on how everything else is going to be structured in your engine. – Yakov Galka Jun 02 '20 at 19:29
  • It seems you lack the "View Matrix". Some APIs use a "lookat" method to build such matrix. Basically, to set and orient the camera. This orientation is what you need for an isometric projection (orthogonal but not parallel to none of XYZ axis). – Ripi2 Jun 03 '20 at 16:56
  • @Ripi2 I created view matrix, but I have no idea how I should set it. – Mark Jun 04 '20 at 17:32
  • This [registry link](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluLookAt.xml) shows you how to fill the view matrix. For an isometric case, "center" may be `0,0,0` and "eye" may be `1,1,1`. The "up" vector acts as a paper rotation. – Ripi2 Jun 04 '20 at 17:37
  • @Ripi2 Thank you very much! In shader I did ````gl_Position = projectionMatrix * model * vec4(position, 1.0) * view;```` and it worked perfectly! Thank you! – Mark Jun 04 '20 at 17:50
  • Be aware of order of matrices multiplication, it's NOT commutative. Depending on row/col matrices storing, it usually is `P*V*M*vec4` or `vec4*M*V*P`. Compare with yours. – Ripi2 Jun 04 '20 at 17:58
  • If I first multiply matrixes and then vertices, object shrinks and streches. If I do vertices first, it's even worse. – Mark Jun 04 '20 at 19:57
  • Yes, isometric projection makes an effect of scale factor with value close to 0,82 – Ripi2 Jun 05 '20 at 16:04
  • @Ripi2 No, object shrinks completely. I am going to add an image. What should I do with triangles on corners? – Mark Jun 05 '20 at 16:20
  • What I see in the images is not an isometric projection. And it seems to be other issues too. If you want more help we need a [mre](https://stackoverflow.com/help/minimal-reproducible-example) – Ripi2 Jun 05 '20 at 16:28
  • Ok, I will add a full code, but I'll need a day or two to rewrite my code – Mark Jun 05 '20 at 16:38
  • Ok, I rewrote my code and added it to my question – Mark Jun 07 '20 at 19:28
  • @Ripi2 do you find any mistakes in my code? I found that if I decrease the lookat eye x and y, black parts on my screen (triangles in my case) get smaller, and if I increase it, the triangles get bigger – Mark Jun 09 '20 at 19:59
  • Your 3rd edit is the whole code, while SO prefers a [mre](https://stackoverflow.com/help/minimal-reproducible-example). Anyhow, I think your `model` matrix is wrong. It should be something like `Matrix4f().rotate(...)...scale(...).translate(...)`. The order or matrices multiplication undoubtly matters. – Ripi2 Jun 09 '20 at 23:32
  • @Ripi2 No, it is not model matrix. I changed it as you said and nothing really changed, because I don't rotate model matrix (in `Ortho2D() ` I can't rotate object's x and y axis). I tried to multiply my vertices like I do in shader, and I got: `-0.33145633 0.7901579 1.7320508 Vertice1 -0.33145633 -0.26338598 348.1422 Vertice2 0.33145633 -0.7901579 1.7320508 Vertice3 0.33145633 0.26338598 -344.6781 Vertice4` I think my problem might be caused by z coord (even though I set it to 0 in vertices array). What should I change in my matrix to get rid of z values? – Mark Jun 10 '20 at 18:00

0 Answers0