Projection matrix isn't calculated correctly

I’ve been trying to convert over to “modern” OpenGL, and one of the first steps I took was to try to figure out how to use matrices and specifically model the glm library. I honestly had to research and stitch code together a lot, so that’s probably my issue. But I don’t know enough about matrices to even try to guess what’s wrong!

So, I tried to create a function similar to the glm::perspective one. It is quite simply this:

public static Matrix4f perspective(float fovy, float aspect, float zNear, float zFar) {
		final float halfFov = (float) Math.toRadians((fovy / 2.0f));
		final float range = (float) Math.tan(halfFov) * zNear;
		final float left = -range * aspect;
		final float right = range * aspect;
		final float bottom = -range;
		final float top = range;
		
		Matrix4f res = new Matrix4f();
		res.m00 = (2 * zNear) / (right - left);
		res.m11 = (2f * zNear) / (top - bottom);
		res.m22 = -(zFar + zNear) / (zFar - zNear);
		res.m23 = -1f;
		res.m32 = -(2f * zFar * zNear) / (zFar - zNear);
		
		return res;
	}

And then I tried to create a glm::lookAt function:

public static Matrix4f lookAt(Vector3f eye, Vector3f center, Vector3f up) {
		Vector3f f = new Vector3f(), u = new Vector3f(), s = new Vector3f();
		Vector3f.sub(center, eye, f);
		up.normalise(u);
		Vector3f cross = Vector3f.cross(f, u, s);
		cross.normalise(s);
		Vector3f.cross(s, f, u);
		
		Matrix4f res = new Matrix4f();
		res.m00 = s.x;
		res.m10 = s.y;
		res.m20 = s.z;
		res.m01 = u.x;
		res.m11 = u.y;
		res.m21 = u.z;
		res.m02 = -f.x;
		res.m12 = -f.y;
		res.m22 = -f.z;
		
		return res;
	}

I then use it like this:

		projection = MatrixUtils.perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.0f);
		view = MatrixUtils.lookAt(new Vector3f(0, 0, 0), new Vector3f(0, 0, -1), new Vector3f(0, 1, 0));
		model = new Matrix4f();

(Model being a “identity” matrix.)

I then pass all those matrices into my shaders, and I multiply them together:

layout(location = 0) in vec3 pos;

uniform mat4 projection, view, model;

void main()
{
	gl_Position = (projection * view * model) * vec4(pos, 1);	
}

My issue is that I try to use the Matrix4f.translate function to translate the geometry. But, instead of actually translating, the vertices simply “rotate” around a point, which actually seems to be the “Z-axis”. Here’s a picture to clarify what I mean:

This is the square being drawn “unmodified (no translations)”:

And then, I just add this line of code:

	Matrix4f.translate(new Vector2f(1, 0), model, model);

Which results in this:

I expected the square to just move over to the left of the screen, but it looks as if it has rotated somehow and stretched itself. Here is the entire class:


public class World {

	private Matrix4f projection, view, model;
	private Shader shader;
	private int vertexBuffer = 0, vbo = 0;

	float[] vData = {
			// Left bottom triangle
			-0.5f, 0.5f, 0f,
			-0.5f, -0.5f, 0f,
			0.5f, -0.5f, 0f,
			// Right top triangle
			0.5f, -0.5f, 0f,
			0.5f, 0.5f, 0f,
			-0.5f, 0.5f, 0f
	};

	private FloatBuffer buffer;
	
	public World() {
		projection = MatrixUtils.perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.0f);
		view = MatrixUtils.lookAt(new Vector3f(0, 0, 0), new Vector3f(0, 0, -1), new Vector3f(0, 1, 0));
		model = new Matrix4f();
		Matrix4f.translate(new Vector2f(1, 0), model, model);
		shader = new Shader("/shaders/basic.vert", "/shaders/basic.frag");

		shader.addUniform("projection");
		shader.addUniform("view");
		shader.addUniform("model");

		buffer = Utils.createFloatBuffer(vData.length);
		buffer.put(vData);
		buffer.flip();
		
		vertexBuffer = GL30.glGenVertexArrays();
		GL30.glBindVertexArray(vertexBuffer);
		
		vbo = GL15.glGenBuffers();
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
		
		GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		
		GL30.glBindVertexArray(0);
	}

	public void update() {
	}

	public void render() {
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
		shader.use();
		shader.setUniformMat("projection", projection);
		shader.setUniformMat("view", view);
		shader.setUniformMat("model", model);
		
		GL30.glBindVertexArray(vertexBuffer);
		GL20.glEnableVertexAttribArray(0);
		
		GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 2 * 3);
		
		GL20.glDisableVertexAttribArray(0);
		GL30.glBindVertexArray(0);
	}
}

(Please excuse the mess!)
Does anyone have idea what I could be doing wrong?