Migrate to BatchedQuads mesh
This commit is contained in:
@@ -1,288 +0,0 @@
|
||||
package com.bartlomiejpluta.base.engine.core.gl.object.mesh;
|
||||
|
||||
import com.bartlomiejpluta.base.api.camera.Camera;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
import com.bartlomiejpluta.base.internal.gc.Disposable;
|
||||
import com.bartlomiejpluta.base.internal.render.Renderable;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
import lombok.Getter;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.lwjgl.opengl.GL15.*;
|
||||
import static org.lwjgl.opengl.GL20.*;
|
||||
import static org.lwjgl.opengl.GL30.*;
|
||||
|
||||
public class BatchedQuads implements Renderable, Disposable {
|
||||
// Texture: Quad:
|
||||
// (0,1) ---- (1,1) 1 ----------- 2
|
||||
// | | | |
|
||||
// | | => | TEXTURE |
|
||||
// | | | |
|
||||
// (0,0) ---- (1,0) 0 ----------- 3
|
||||
private static final float[] DEFAULT_TEXTURE_COORDINATES = new float[] {
|
||||
0, 0, // 0 - bottom left
|
||||
0, 1, // 1 - top left
|
||||
1, 1, // 2 - top right
|
||||
1, 0 // 3 - bottom right
|
||||
};
|
||||
|
||||
private static final int POSITION_VECTOR_LAYOUT_INDEX = 0;
|
||||
private static final int POSITION_VECTOR_LENGTH = 2;
|
||||
private static final int TEXTURE_COORDINATES_VECTOR_LAYOUT_INDEX = 1;
|
||||
private static final int TEXTURE_COORDINATES_VECTOR_LENGTH = 2;
|
||||
|
||||
private static final int VERTICES_PER_QUAD = 4;
|
||||
private static final int INDICES_PER_QUAD = 6;
|
||||
|
||||
private final int maxQuads;
|
||||
private final int vaoId;
|
||||
private final List<Integer> vboIds = new ArrayList<>(3);
|
||||
private final int maxVertices;
|
||||
private final int maxIndices;
|
||||
|
||||
private final float[] vertexBuffer;
|
||||
private final float[] texCoordBuffer;
|
||||
private final int[] indexBuffer;
|
||||
|
||||
@Getter
|
||||
private int currentQuadCount = 0;
|
||||
|
||||
public BatchedQuads(int maxQuads) {
|
||||
this.maxQuads = maxQuads;
|
||||
this.maxVertices = maxQuads * VERTICES_PER_QUAD * 2;
|
||||
this.maxIndices = maxQuads * INDICES_PER_QUAD;
|
||||
|
||||
this.vertexBuffer = new float[maxVertices];
|
||||
this.texCoordBuffer = new float[maxVertices];
|
||||
this.indexBuffer = new int[maxIndices];
|
||||
|
||||
try (var stack = MemoryStack.stackPush()) {
|
||||
vaoId = glGenVertexArrays();
|
||||
glBindVertexArray(vaoId);
|
||||
|
||||
// Vertex buffer
|
||||
var vertexVboId = glGenBuffers();
|
||||
vboIds.add(vertexVboId);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertexVboId);
|
||||
glBufferData(GL_ARRAY_BUFFER, maxVertices * Float.BYTES, GL_DYNAMIC_DRAW);
|
||||
glVertexAttribPointer(POSITION_VECTOR_LAYOUT_INDEX, POSITION_VECTOR_LENGTH, GL_FLOAT, false, 0, 0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
// Texture coordinates buffer
|
||||
var texCoordVboId = glGenBuffers();
|
||||
vboIds.add(texCoordVboId);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, texCoordVboId);
|
||||
glBufferData(GL_ARRAY_BUFFER, maxVertices * Float.BYTES, GL_DYNAMIC_DRAW);
|
||||
glVertexAttribPointer(TEXTURE_COORDINATES_VECTOR_LAYOUT_INDEX, TEXTURE_COORDINATES_VECTOR_LENGTH, GL_FLOAT, false, 0, 0);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
// Index buffer
|
||||
var indexVboId = glGenBuffers();
|
||||
vboIds.add(indexVboId);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVboId);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, maxIndices * Integer.BYTES, GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
}
|
||||
|
||||
public int addQuad(Quad quad, float x, float y) {
|
||||
return addQuad(quad, x, y, DEFAULT_TEXTURE_COORDINATES);
|
||||
}
|
||||
|
||||
public int addQuad(Quad quad, float x, float y, float[] textureCoordinates) {
|
||||
if (currentQuadCount >= maxQuads) {
|
||||
throw new RuntimeException("Batch is full!");
|
||||
}
|
||||
|
||||
int quadId = currentQuadCount;
|
||||
|
||||
// Vertices
|
||||
var localVertices = quad.getVertices();
|
||||
int vertexStartIndex = currentQuadCount * VERTICES_PER_QUAD * 2;
|
||||
for (int i = 0; i < VERTICES_PER_QUAD; i++) {
|
||||
float localX = localVertices[i * 2];
|
||||
float localY = localVertices[i * 2 + 1];
|
||||
|
||||
vertexBuffer[vertexStartIndex + i * 2] = x + localX;
|
||||
vertexBuffer[vertexStartIndex + i * 2 + 1] = y + localY;
|
||||
}
|
||||
|
||||
// Texture
|
||||
var texCoordStartIndex = currentQuadCount * VERTICES_PER_QUAD * 2;
|
||||
System.arraycopy(textureCoordinates, 0, texCoordBuffer, texCoordStartIndex, textureCoordinates.length);
|
||||
|
||||
// Indices
|
||||
var indexStartIndex = currentQuadCount * INDICES_PER_QUAD;
|
||||
var vertexOffset = currentQuadCount * VERTICES_PER_QUAD;
|
||||
|
||||
int[] quadIndices = {
|
||||
// First triangle: indices 0-1-2
|
||||
// 1 ----------- 2
|
||||
// |XXXXXXXXXXX╱ |
|
||||
// |XXXXXXXX╱ |
|
||||
// |XXXXX╱ |
|
||||
// |XX╱ |
|
||||
// 0 ----------- 3
|
||||
vertexOffset + 0, vertexOffset + 1, vertexOffset + 2,
|
||||
|
||||
// Second triangle: indices 2-3-0
|
||||
// 1 ----------- 2
|
||||
// | ╱X|
|
||||
// | ╱XXXX|
|
||||
// | ╱XXXXXXX|
|
||||
// | ╱XXXXXXXXXX|
|
||||
// 0 ----------- 3
|
||||
vertexOffset + 2, vertexOffset + 3, vertexOffset + 0
|
||||
};
|
||||
|
||||
System.arraycopy(quadIndices, 0, indexBuffer, indexStartIndex, quadIndices.length);
|
||||
currentQuadCount++;
|
||||
|
||||
return quadId;
|
||||
}
|
||||
|
||||
public void setQuadTextureCoordinates(int quadId, float[] textureCoordinates) {
|
||||
if (quadId < 0 || quadId >= currentQuadCount) {
|
||||
throw new IllegalArgumentException("Invalid quad ID: " + quadId);
|
||||
}
|
||||
|
||||
var texCoordsIndex = quadId * VERTICES_PER_QUAD * 2;
|
||||
System.arraycopy(textureCoordinates, 0, texCoordBuffer, texCoordsIndex, textureCoordinates.length);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
currentQuadCount = 0;
|
||||
}
|
||||
|
||||
public void removeQuad(int quadId) {
|
||||
if (quadId < 0 || quadId >= currentQuadCount) {
|
||||
throw new IllegalArgumentException("Invalid quad ID: " + quadId);
|
||||
}
|
||||
|
||||
int lastQuadId = currentQuadCount - 1;
|
||||
|
||||
if (quadId != lastQuadId) {
|
||||
swapQuads(quadId, lastQuadId);
|
||||
}
|
||||
|
||||
currentQuadCount--;
|
||||
}
|
||||
|
||||
private void swapQuads(int quad1, int quad2) {
|
||||
// Swap vertices
|
||||
swapQuadData(vertexBuffer, quad1, quad2, VERTICES_PER_QUAD * 2);
|
||||
|
||||
// Swap texture coordinates
|
||||
swapQuadData(texCoordBuffer, quad1, quad2, VERTICES_PER_QUAD * 2);
|
||||
|
||||
// Swap indices
|
||||
swapQuadIndices(quad1, quad2);
|
||||
}
|
||||
|
||||
private void swapQuadData(float[] buffer, int quad1, int quad2, int dataSize) {
|
||||
var start1 = quad1 * dataSize;
|
||||
var start2 = quad2 * dataSize;
|
||||
|
||||
for (int i = 0; i < dataSize; i++) {
|
||||
var temp = buffer[start1 + i];
|
||||
buffer[start1 + i] = buffer[start2 + i];
|
||||
buffer[start2 + i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
private void swapQuadIndices(int quad1, int quad2) {
|
||||
var start1 = quad1 * INDICES_PER_QUAD;
|
||||
var start2 = quad2 * INDICES_PER_QUAD;
|
||||
|
||||
var vertexOffset1 = quad1 * VERTICES_PER_QUAD;
|
||||
int[] newIndices1 = {
|
||||
vertexOffset1 + 0, vertexOffset1 + 1, vertexOffset1 + 2,
|
||||
vertexOffset1 + 2, vertexOffset1 + 3, vertexOffset1 + 0
|
||||
};
|
||||
|
||||
var vertexOffset2 = quad2 * VERTICES_PER_QUAD;
|
||||
int[] newIndices2 = {
|
||||
vertexOffset2 + 0, vertexOffset2 + 1, vertexOffset2 + 2,
|
||||
vertexOffset2 + 2, vertexOffset2 + 3, vertexOffset2 + 0
|
||||
};
|
||||
|
||||
System.arraycopy(newIndices1, 0, indexBuffer, start1, INDICES_PER_QUAD);
|
||||
System.arraycopy(newIndices2, 0, indexBuffer, start2, INDICES_PER_QUAD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Screen screen, Camera camera, ShaderManager shaderManager) {
|
||||
if (currentQuadCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
glBindVertexArray(vaoId);
|
||||
|
||||
try (var stack = MemoryStack.stackPush()) {
|
||||
// Vertex buffer
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboIds.get(0));
|
||||
var vertexFloatBuffer = stack.mallocFloat(currentQuadCount * VERTICES_PER_QUAD * 2);
|
||||
for (int i = 0; i < currentQuadCount * VERTICES_PER_QUAD * 2; i++) {
|
||||
vertexFloatBuffer.put(vertexBuffer[i]);
|
||||
}
|
||||
vertexFloatBuffer.flip();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, vertexFloatBuffer);
|
||||
|
||||
// Texture coordinate buffer
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboIds.get(1));
|
||||
var texCoordFloatBuffer = stack.mallocFloat(currentQuadCount * VERTICES_PER_QUAD * 2);
|
||||
for (int i = 0; i < currentQuadCount * VERTICES_PER_QUAD * 2; i++) {
|
||||
texCoordFloatBuffer.put(texCoordBuffer[i]);
|
||||
}
|
||||
texCoordFloatBuffer.flip();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, texCoordFloatBuffer);
|
||||
|
||||
// Index buffer
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds.get(2));
|
||||
var indexIntBuffer = stack.mallocInt(currentQuadCount * INDICES_PER_QUAD);
|
||||
for (int i = 0; i < currentQuadCount * INDICES_PER_QUAD; i++) {
|
||||
indexIntBuffer.put(indexBuffer[i]);
|
||||
}
|
||||
indexIntBuffer.flip();
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexIntBuffer);
|
||||
}
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, currentQuadCount * INDICES_PER_QUAD, GL_UNSIGNED_INT, 0);
|
||||
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
vboIds.forEach(GL15::glDeleteBuffers);
|
||||
|
||||
glBindVertexArray(0);
|
||||
glDeleteVertexArrays(vaoId);
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return currentQuadCount >= maxQuads;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return currentQuadCount == 0;
|
||||
}
|
||||
}
|
||||
@@ -6,110 +6,257 @@ import com.bartlomiejpluta.base.internal.gc.Disposable;
|
||||
import com.bartlomiejpluta.base.internal.render.Renderable;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
import lombok.Getter;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector2fc;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.Math.abs;
|
||||
import static org.lwjgl.opengl.GL15.*;
|
||||
import static org.lwjgl.opengl.GL20.*;
|
||||
import static org.lwjgl.opengl.GL30.*;
|
||||
|
||||
public class Mesh implements Renderable, Disposable {
|
||||
// default.vs: layout(location=0) in vec2 position;
|
||||
// ^ ^
|
||||
// Texture: Quad:
|
||||
// (0,1) ---- (1,1) 1 ----------- 2
|
||||
// | | | |
|
||||
// | | => | TEXTURE |
|
||||
// | | | |
|
||||
// (0,0) ---- (1,0) 0 ----------- 3
|
||||
private static final float[] DEFAULT_TEXTURE_COORDINATES = new float[] {
|
||||
0, 0, // 0 - bottom left
|
||||
0, 1, // 1 - top left
|
||||
1, 1, // 2 - top right
|
||||
1, 0 // 3 - bottom right
|
||||
};
|
||||
|
||||
private static final int POSITION_VECTOR_LAYOUT_INDEX = 0;
|
||||
private static final int POSITION_VECTOR_LENGTH = 2;
|
||||
private static final int TEXTURE_COORDINATES_VECTOR_LAYOUT_INDEX = 1;
|
||||
private static final int TEXTURE_COORDINATES_VECTOR_LENGTH = 2;
|
||||
|
||||
// default.vs: layout(location=1) in vec2 texCoord;
|
||||
// ^ ^
|
||||
private static final int TEX_COORDS_VECTOR_LAYOUT_INDEX = 1;
|
||||
private static final int TEX_COORDS_VECTOR_LENGTH = 2;
|
||||
private static final int VERTICES_PER_QUAD = 4;
|
||||
private static final int INDICES_PER_QUAD = 6;
|
||||
|
||||
private final int maxQuads;
|
||||
private final int vaoId;
|
||||
private final List<Integer> vboIds = new ArrayList<>(2);
|
||||
private final int elementsCount;
|
||||
private final List<Integer> vboIds = new ArrayList<>(3);
|
||||
private final int maxVertices;
|
||||
private final int maxIndices;
|
||||
|
||||
private final float[] vertexBuffer;
|
||||
private final float[] texCoordBuffer;
|
||||
private final int[] indexBuffer;
|
||||
|
||||
@Getter
|
||||
private final Vector2fc farthestVertex;
|
||||
private int currentQuadCount = 0;
|
||||
|
||||
@Getter
|
||||
private final Vector2fc primarySize;
|
||||
public Mesh(int maxQuads) {
|
||||
this.maxQuads = maxQuads;
|
||||
this.maxVertices = maxQuads * VERTICES_PER_QUAD * 2;
|
||||
this.maxIndices = maxQuads * INDICES_PER_QUAD;
|
||||
|
||||
public Mesh(float[] vertices, float[] texCoords, int[] elements) {
|
||||
this.elementsCount = elements.length;
|
||||
this.vertexBuffer = new float[maxVertices];
|
||||
this.texCoordBuffer = new float[maxVertices];
|
||||
this.indexBuffer = new int[maxIndices];
|
||||
|
||||
var vboId = 0;
|
||||
try (var stack = MemoryStack.stackPush()) {
|
||||
vaoId = glGenVertexArrays();
|
||||
glBindVertexArray(vaoId);
|
||||
|
||||
// Vertices VBO
|
||||
vboId = glGenBuffers();
|
||||
vboIds.add(vboId);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboId);
|
||||
glBufferData(GL_ARRAY_BUFFER, stack.mallocFloat(vertices.length).put(vertices).flip(), GL_STATIC_DRAW);
|
||||
// Vertex buffer
|
||||
var vertexVboId = glGenBuffers();
|
||||
vboIds.add(vertexVboId);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertexVboId);
|
||||
glBufferData(GL_ARRAY_BUFFER, maxVertices * Float.BYTES, GL_DYNAMIC_DRAW);
|
||||
glVertexAttribPointer(POSITION_VECTOR_LAYOUT_INDEX, POSITION_VECTOR_LENGTH, GL_FLOAT, false, 0, 0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
// Texture Coordinates VBO
|
||||
vboId = glGenBuffers();
|
||||
vboIds.add(vboId);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboId);
|
||||
glBufferData(GL_ARRAY_BUFFER, stack.mallocFloat(texCoords.length).put(texCoords).flip(), GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(TEX_COORDS_VECTOR_LAYOUT_INDEX, TEX_COORDS_VECTOR_LENGTH, GL_FLOAT, false, 0, 0);
|
||||
// Texture coordinates buffer
|
||||
var texCoordVboId = glGenBuffers();
|
||||
vboIds.add(texCoordVboId);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, texCoordVboId);
|
||||
glBufferData(GL_ARRAY_BUFFER, maxVertices * Float.BYTES, GL_DYNAMIC_DRAW);
|
||||
glVertexAttribPointer(TEXTURE_COORDINATES_VECTOR_LAYOUT_INDEX, TEXTURE_COORDINATES_VECTOR_LENGTH, GL_FLOAT, false, 0, 0);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
// Elements VBO
|
||||
vboId = glGenBuffers();
|
||||
vboIds.add(vboId);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, stack.mallocInt(elementsCount).put(elements).flip(), GL_STATIC_DRAW);
|
||||
// Index buffer
|
||||
var indexVboId = glGenBuffers();
|
||||
vboIds.add(indexVboId);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVboId);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, maxIndices * Integer.BYTES, GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
}
|
||||
|
||||
var minX = Float.MAX_VALUE;
|
||||
var minY = Float.MAX_VALUE;
|
||||
var maxX = 0f;
|
||||
var maxY = 0f;
|
||||
public int addQuad(QuadTemplate template, float x, float y) {
|
||||
return addQuad(template, x, y, DEFAULT_TEXTURE_COORDINATES);
|
||||
}
|
||||
|
||||
for (int i = 0; i < vertices.length / 2; ++i) {
|
||||
var x = vertices[2 * i];
|
||||
var y = vertices[2 * i + 1];
|
||||
|
||||
if (x < minX) {
|
||||
minX = x;
|
||||
}
|
||||
|
||||
if (x > maxX) {
|
||||
maxX = x;
|
||||
}
|
||||
|
||||
if (y < minY) {
|
||||
minY = y;
|
||||
}
|
||||
|
||||
if (y > maxY) {
|
||||
maxY = y;
|
||||
}
|
||||
public int addQuad(QuadTemplate template, float x, float y, float[] textureCoordinates) {
|
||||
if (currentQuadCount >= maxQuads) {
|
||||
throw new RuntimeException("Batch is full!");
|
||||
}
|
||||
|
||||
farthestVertex = new Vector2f(abs(maxX) > abs(minX) ? maxX : minX, abs(maxY) > abs(minY) ? maxY : minY);
|
||||
primarySize = new Vector2f(maxX - minX, maxY - minY);
|
||||
int quadId = currentQuadCount;
|
||||
|
||||
// Vertices
|
||||
var localVertices = template.getVertices();
|
||||
int vertexStartIndex = currentQuadCount * VERTICES_PER_QUAD * 2;
|
||||
for (int i = 0; i < VERTICES_PER_QUAD; i++) {
|
||||
float localX = localVertices[i * 2];
|
||||
float localY = localVertices[i * 2 + 1];
|
||||
|
||||
vertexBuffer[vertexStartIndex + i * 2] = x + localX;
|
||||
vertexBuffer[vertexStartIndex + i * 2 + 1] = y + localY;
|
||||
}
|
||||
|
||||
// Texture
|
||||
var texCoordStartIndex = currentQuadCount * VERTICES_PER_QUAD * 2;
|
||||
System.arraycopy(textureCoordinates, 0, texCoordBuffer, texCoordStartIndex, textureCoordinates.length);
|
||||
|
||||
// Indices
|
||||
var indexStartIndex = currentQuadCount * INDICES_PER_QUAD;
|
||||
var vertexOffset = currentQuadCount * VERTICES_PER_QUAD;
|
||||
|
||||
int[] quadIndices = {
|
||||
// First triangle: indices 0-1-2
|
||||
// 1 ----------- 2
|
||||
// |XXXXXXXXXXX╱ |
|
||||
// |XXXXXXXX╱ |
|
||||
// |XXXXX╱ |
|
||||
// |XX╱ |
|
||||
// 0 ----------- 3
|
||||
vertexOffset + 0, vertexOffset + 1, vertexOffset + 2,
|
||||
|
||||
// Second triangle: indices 2-3-0
|
||||
// 1 ----------- 2
|
||||
// | ╱X|
|
||||
// | ╱XXXX|
|
||||
// | ╱XXXXXXX|
|
||||
// | ╱XXXXXXXXXX|
|
||||
// 0 ----------- 3
|
||||
vertexOffset + 2, vertexOffset + 3, vertexOffset + 0
|
||||
};
|
||||
|
||||
System.arraycopy(quadIndices, 0, indexBuffer, indexStartIndex, quadIndices.length);
|
||||
currentQuadCount++;
|
||||
|
||||
return quadId;
|
||||
}
|
||||
|
||||
public void setQuadTextureCoordinates(int quadId, float[] textureCoordinates) {
|
||||
if (quadId < 0 || quadId >= currentQuadCount) {
|
||||
throw new IllegalArgumentException("Invalid quad ID: " + quadId);
|
||||
}
|
||||
|
||||
var texCoordsIndex = quadId * VERTICES_PER_QUAD * 2;
|
||||
System.arraycopy(textureCoordinates, 0, texCoordBuffer, texCoordsIndex, textureCoordinates.length);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
currentQuadCount = 0;
|
||||
}
|
||||
|
||||
public void removeQuad(int quadId) {
|
||||
if (quadId < 0 || quadId >= currentQuadCount) {
|
||||
throw new IllegalArgumentException("Invalid quad ID: " + quadId);
|
||||
}
|
||||
|
||||
int lastQuadId = currentQuadCount - 1;
|
||||
|
||||
if (quadId != lastQuadId) {
|
||||
swapQuads(quadId, lastQuadId);
|
||||
}
|
||||
|
||||
currentQuadCount--;
|
||||
}
|
||||
|
||||
private void swapQuads(int quad1, int quad2) {
|
||||
// Swap vertices
|
||||
swapQuadData(vertexBuffer, quad1, quad2, VERTICES_PER_QUAD * 2);
|
||||
|
||||
// Swap texture coordinates
|
||||
swapQuadData(texCoordBuffer, quad1, quad2, VERTICES_PER_QUAD * 2);
|
||||
|
||||
// Swap indices
|
||||
swapQuadIndices(quad1, quad2);
|
||||
}
|
||||
|
||||
private void swapQuadData(float[] buffer, int quad1, int quad2, int dataSize) {
|
||||
var start1 = quad1 * dataSize;
|
||||
var start2 = quad2 * dataSize;
|
||||
|
||||
for (int i = 0; i < dataSize; i++) {
|
||||
var temp = buffer[start1 + i];
|
||||
buffer[start1 + i] = buffer[start2 + i];
|
||||
buffer[start2 + i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
private void swapQuadIndices(int quad1, int quad2) {
|
||||
var start1 = quad1 * INDICES_PER_QUAD;
|
||||
var start2 = quad2 * INDICES_PER_QUAD;
|
||||
|
||||
var vertexOffset1 = quad1 * VERTICES_PER_QUAD;
|
||||
int[] newIndices1 = {
|
||||
vertexOffset1 + 0, vertexOffset1 + 1, vertexOffset1 + 2,
|
||||
vertexOffset1 + 2, vertexOffset1 + 3, vertexOffset1 + 0
|
||||
};
|
||||
|
||||
var vertexOffset2 = quad2 * VERTICES_PER_QUAD;
|
||||
int[] newIndices2 = {
|
||||
vertexOffset2 + 0, vertexOffset2 + 1, vertexOffset2 + 2,
|
||||
vertexOffset2 + 2, vertexOffset2 + 3, vertexOffset2 + 0
|
||||
};
|
||||
|
||||
System.arraycopy(newIndices1, 0, indexBuffer, start1, INDICES_PER_QUAD);
|
||||
System.arraycopy(newIndices2, 0, indexBuffer, start2, INDICES_PER_QUAD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Screen screen, Camera camera, ShaderManager shaderManager) {
|
||||
if (currentQuadCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
glBindVertexArray(vaoId);
|
||||
|
||||
try (var stack = MemoryStack.stackPush()) {
|
||||
// Vertex buffer
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboIds.get(0));
|
||||
var vertexFloatBuffer = stack.mallocFloat(currentQuadCount * VERTICES_PER_QUAD * 2);
|
||||
for (int i = 0; i < currentQuadCount * VERTICES_PER_QUAD * 2; i++) {
|
||||
vertexFloatBuffer.put(vertexBuffer[i]);
|
||||
}
|
||||
vertexFloatBuffer.flip();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, vertexFloatBuffer);
|
||||
|
||||
// Texture coordinate buffer
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboIds.get(1));
|
||||
var texCoordFloatBuffer = stack.mallocFloat(currentQuadCount * VERTICES_PER_QUAD * 2);
|
||||
for (int i = 0; i < currentQuadCount * VERTICES_PER_QUAD * 2; i++) {
|
||||
texCoordFloatBuffer.put(texCoordBuffer[i]);
|
||||
}
|
||||
texCoordFloatBuffer.flip();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, texCoordFloatBuffer);
|
||||
|
||||
// Index buffer
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds.get(2));
|
||||
var indexIntBuffer = stack.mallocInt(currentQuadCount * INDICES_PER_QUAD);
|
||||
for (int i = 0; i < currentQuadCount * INDICES_PER_QUAD; i++) {
|
||||
indexIntBuffer.put(indexBuffer[i]);
|
||||
}
|
||||
indexIntBuffer.flip();
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexIntBuffer);
|
||||
}
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, elementsCount, GL_UNSIGNED_INT, 0);
|
||||
glDrawElements(GL_TRIANGLES, currentQuadCount * INDICES_PER_QUAD, GL_UNSIGNED_INT, 0);
|
||||
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
@@ -131,55 +278,15 @@ public class Mesh implements Renderable, Disposable {
|
||||
glDeleteVertexArrays(vaoId);
|
||||
}
|
||||
|
||||
public static Mesh quad(float width, float height, float originX, float originY) {
|
||||
// 1 ----------- 2
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// 0 ----------- 3
|
||||
var vertices = new float[]{
|
||||
-originX, -originY, // 0 - bottom left
|
||||
-originX, height - originY, // 1 - top left
|
||||
width - originX, height - originY, // 2 - top right
|
||||
width - originX, -originY // 3 - bottom right
|
||||
};
|
||||
public boolean isFull() {
|
||||
return currentQuadCount >= maxQuads;
|
||||
}
|
||||
|
||||
// Texture: Quad:
|
||||
// (0,1) ---- (1,1) 1 ----------- 2
|
||||
// | | | |
|
||||
// | | => | TEKSTURA |
|
||||
// | | | |
|
||||
// (0,0) ---- (1,0) 0 ----------- 3
|
||||
var texCoords = new float[]{
|
||||
0, 0, // 0 - bottom left
|
||||
0, 1, // 1 - top left
|
||||
1, 1, // 2 - top right
|
||||
1, 0 // 3 - bottom right
|
||||
};
|
||||
|
||||
|
||||
var elements = new int[]{
|
||||
// First triangle: indices 0-1-2
|
||||
// 1 ----------- 2
|
||||
// |XXXXXXXXXXX╱ |
|
||||
// |XXXXXXXX╱ |
|
||||
// |XXXXX╱ |
|
||||
// |XX╱ |
|
||||
// 0 ----------- 3
|
||||
0, 1, 2,
|
||||
|
||||
// Second triangle: indices 2-3-0
|
||||
// 1 ----------- 2
|
||||
// | ╱X|
|
||||
// | ╱XXXX|
|
||||
// | ╱XXXXXXX|
|
||||
// | ╱XXXXXXXXXX|
|
||||
// 0 ----------- 3
|
||||
2, 3, 0
|
||||
};
|
||||
|
||||
return new Mesh(vertices, texCoords, elements);
|
||||
public boolean isEmpty() {
|
||||
return currentQuadCount == 0;
|
||||
}
|
||||
|
||||
public static QuadMesh quad(float width, float height, float originX, float originY) {
|
||||
return new QuadMesh(width, height, originX, originY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.bartlomiejpluta.base.engine.core.gl.object.mesh;
|
||||
|
||||
import lombok.NonNull;
|
||||
|
||||
public class QuadMesh extends Mesh {
|
||||
private final int quadId;
|
||||
|
||||
QuadMesh(float width, float height, float originX, float originY) {
|
||||
this(new QuadTemplate(width, height, originX, originY));
|
||||
}
|
||||
|
||||
QuadMesh(@NonNull QuadTemplate template) {
|
||||
super(1);
|
||||
|
||||
this.quadId = addQuad(template, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeQuad(int quadId) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void setTextureCoordinates(float[] textureCoordinates) {
|
||||
super.setQuadTextureCoordinates(quadId, textureCoordinates);
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,14 @@ package com.bartlomiejpluta.base.engine.core.gl.object.mesh;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class Quad {
|
||||
public class QuadTemplate {
|
||||
private final float width;
|
||||
private final float height;
|
||||
private final float originX;
|
||||
private final float originY;
|
||||
private final float[] vertices;
|
||||
|
||||
public Quad(float width, float height, float originX, float originY) {
|
||||
public QuadTemplate(float width, float height, float originX, float originY) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.originX = originX;
|
||||
@@ -30,33 +30,4 @@ public class Quad {
|
||||
width - originX, -originY // 3 - bottom right
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
static float[] textureCoordinates = new float[]{
|
||||
0, 0, // 0 - bottom left
|
||||
0, 1, // 1 - top left
|
||||
1, 1, // 2 - top right
|
||||
1, 0 // 3 - bottom right
|
||||
};
|
||||
|
||||
static int[] elements = new int[]{
|
||||
// First triangle: indices 0-1-2
|
||||
// 1 ----------- 2
|
||||
// |XXXXXXXXXXX╱ |
|
||||
// |XXXXXXXX╱ |
|
||||
// |XXXXX╱ |
|
||||
// |XX╱ |
|
||||
// 0 ----------- 3
|
||||
0, 1, 2,
|
||||
|
||||
// Second triangle: indices 2-3-0
|
||||
// 1 ----------- 2
|
||||
// | ╱X|
|
||||
// | ╱XXXX|
|
||||
// | ╱XXXXXXX|
|
||||
// | ╱XXXXXXXXXX|
|
||||
// 0 ----------- 3
|
||||
2, 3, 0
|
||||
};
|
||||
}
|
||||
@@ -74,6 +74,16 @@ public class Texture implements Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
public float[][] getTextureCoordinatesForAllFrames() {
|
||||
var array = new float[rows*columns][];
|
||||
|
||||
for (var i=0; i<array.length; ++i) {
|
||||
array[i] = getTextureCoordinates(i);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public float[] getTextureCoordinates(int id) {
|
||||
return getTextureCoordinates(id % columns, id / columns);
|
||||
}
|
||||
@@ -93,7 +103,7 @@ public class Texture implements Disposable {
|
||||
|
||||
return new float[]{
|
||||
normalizedX, normalizedY, // bottom left
|
||||
normalizedX, yEnd, // top left
|
||||
normalizedX, yEnd, // top left
|
||||
xEnd, yEnd, // top right
|
||||
xEnd, normalizedY // bottom right
|
||||
};
|
||||
|
||||
@@ -1,43 +1,15 @@
|
||||
package com.bartlomiejpluta.base.engine.util.mesh;
|
||||
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.joml.Vector2f;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
// TODO
|
||||
@Slf4j
|
||||
@Component
|
||||
public class DefaultMeshManager implements MeshManager {
|
||||
private final Map<QuadDimension, Mesh> quads = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public Mesh createQuad(float width, float height, float originX, float originY) {
|
||||
var dim = new QuadDimension(new Vector2f(width, height), new Vector2f(originX, originY));
|
||||
var mesh = quads.get(dim);
|
||||
|
||||
if(mesh == null) {
|
||||
log.info("Creating [w:{}, h:{} | O:{}, {}] mesh and putting it into the cache", width, height, originX, originY);
|
||||
mesh = Mesh.quad(width, height, originX, originY);
|
||||
quads.put(dim, mesh);
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
log.info("Disposing meshes");
|
||||
quads.forEach((dim, mesh) -> mesh.dispose());
|
||||
log.info("{} meshes have been disposed", quads.size());
|
||||
log.info("Nothing to do for now (todo...)");
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class QuadDimension {
|
||||
private final Vector2f size;
|
||||
private final Vector2f origin;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.bartlomiejpluta.base.engine.util.mesh;
|
||||
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.internal.gc.Cleanable;
|
||||
|
||||
public interface MeshManager extends Cleanable {
|
||||
Mesh createQuad(float width, float height, float originX, float originY);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.bartlomiejpluta.base.engine.world.animation.manager;
|
||||
|
||||
import com.bartlomiejpluta.base.api.animation.Animation;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.texture.TextureManager;
|
||||
import com.bartlomiejpluta.base.engine.error.AppException;
|
||||
import com.bartlomiejpluta.base.engine.project.config.ProjectConfiguration;
|
||||
@@ -28,11 +27,10 @@ public class DefaultAnimationManager implements AnimationManager {
|
||||
private final Map<String, AnimationAsset> assets = new HashMap<>();
|
||||
private final Map<String, Vector2fc[]> frames = new HashMap<>();
|
||||
private final ProjectConfiguration configuration;
|
||||
private Mesh mesh;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
mesh = meshManager.createQuad(1, 1, 0.5f, 0.5f);
|
||||
// TODO mesh = meshManager.createQuad(1, 1, 0.5f, 0.5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,7 +60,7 @@ public class DefaultAnimationManager implements AnimationManager {
|
||||
var texture = textureManager.loadTexture(source, asset.getRows(), asset.getColumns());
|
||||
var material = Material.textured(texture);
|
||||
|
||||
return new DefaultAnimation(mesh, material, animationFrames);
|
||||
return new DefaultAnimation(material, animationFrames);
|
||||
}
|
||||
|
||||
private Vector2fc[] createFrames(int rows, int columns) {
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.bartlomiejpluta.base.engine.world.animation.model;
|
||||
import com.bartlomiejpluta.base.api.animation.Animated;
|
||||
import com.bartlomiejpluta.base.engine.core.engine.DefaultGameEngine;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.world.object.Sprite;
|
||||
import com.bartlomiejpluta.base.util.math.MathUtil;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -17,14 +16,18 @@ public abstract class AnimatedSprite extends Sprite implements Animated {
|
||||
private int intervalInMilliseconds = 100;
|
||||
protected int currentAnimationFrame;
|
||||
|
||||
public AnimatedSprite(Mesh mesh, Material material) {
|
||||
super(mesh, material);
|
||||
public AnimatedSprite(Material material) {
|
||||
super(material);
|
||||
}
|
||||
|
||||
protected abstract boolean shouldAnimate();
|
||||
|
||||
protected abstract Vector2fc[] getSpriteAnimationFramesPositions();
|
||||
|
||||
protected int[] getAvailableFrames() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAnimationSpeed(float speed) {
|
||||
intervalInMilliseconds = (int) (1 / MathUtil.clamp(speed / DefaultGameEngine.TARGET_UPS, Float.MIN_VALUE, 1.0));
|
||||
@@ -37,20 +40,24 @@ public abstract class AnimatedSprite extends Sprite implements Animated {
|
||||
|
||||
@Override
|
||||
public void setAnimationFrame(int frame) {
|
||||
var positions = getSpriteAnimationFramesPositions();
|
||||
currentAnimationFrame = frame % positions.length;
|
||||
var current = positions[currentAnimationFrame];
|
||||
material.setSpritePosition(current);
|
||||
var availableFrames = getAvailableFrames();
|
||||
|
||||
if (availableFrames == null) {
|
||||
setFrame(frame % getTextureCoordinates().length);
|
||||
return;
|
||||
}
|
||||
|
||||
setFrame(availableFrames[frame % availableFrames.length]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float dt) {
|
||||
if (shouldAnimate()) {
|
||||
time += dt * 1000;
|
||||
var positions = getSpriteAnimationFramesPositions();
|
||||
currentAnimationFrame = ((time % (positions.length * intervalInMilliseconds)) / intervalInMilliseconds);
|
||||
var current = positions[currentAnimationFrame];
|
||||
material.setSpritePosition(current);
|
||||
setAnimationFrame(time / intervalInMilliseconds * intervalInMilliseconds);
|
||||
// var maxFrames = getTextureCoordinates().length;
|
||||
// currentAnimationFrame = ((time % (maxFrames * intervalInMilliseconds)) / intervalInMilliseconds);
|
||||
// setSprite(currentAnimationFrame);
|
||||
} else {
|
||||
time = 0;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import com.bartlomiejpluta.base.api.move.AnimationMovement;
|
||||
import com.bartlomiejpluta.base.api.move.Direction;
|
||||
import com.bartlomiejpluta.base.api.move.Movement;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.world.movement.MovableSprite;
|
||||
import com.bartlomiejpluta.base.util.path.Path;
|
||||
import com.bartlomiejpluta.base.util.path.PathExecutor;
|
||||
@@ -51,8 +50,8 @@ public class DefaultAnimation extends MovableSprite implements Animation {
|
||||
@Getter
|
||||
private final CompletableFuture<Animation> future = new CompletableFuture<>();
|
||||
|
||||
public DefaultAnimation(Mesh mesh, Material material, @NonNull Vector2fc[] frames) {
|
||||
super(mesh, material);
|
||||
public DefaultAnimation(Material material, @NonNull Vector2fc[] frames) {
|
||||
super(material);
|
||||
this.frames = frames;
|
||||
this.lastFrameIndex = frames.length - 1;
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.bartlomiejpluta.base.engine.world.autotile.manager;
|
||||
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.texture.TextureManager;
|
||||
import com.bartlomiejpluta.base.engine.error.AppException;
|
||||
import com.bartlomiejpluta.base.engine.project.config.ProjectConfiguration;
|
||||
@@ -24,11 +23,10 @@ public class DefaultAutoTileSetManager implements AutoTileManager {
|
||||
private final Map<String, AutoTileSet> autoTiles = new HashMap<>();
|
||||
private final Map<String, AutoTileSetAsset> assets = new HashMap<>();
|
||||
private final ProjectConfiguration configuration;
|
||||
private Mesh mesh;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
this.mesh = meshManager.createQuad(1, 1, 0, 0);
|
||||
// TODO: this.mesh = meshManager.createQuad(1, 1, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,7 +53,7 @@ public class DefaultAutoTileSetManager implements AutoTileManager {
|
||||
|
||||
var source = configuration.projectFile("autotiles", asset.getSource());
|
||||
var texture = textureManager.loadTexture(source, asset.getRows() * asset.getLayout().getRows() * 2, asset.getColumns() * asset.getLayout().getColumns() * 2);
|
||||
autoTile = new AutoTileSet(texture, mesh, asset.getRows(), asset.getColumns(), asset.getLayout());
|
||||
autoTile = new AutoTileSet(texture, asset.getRows(), asset.getColumns(), asset.getLayout());
|
||||
log.info("Loading auto tile set from assets to cache under the key: [{}]", uid);
|
||||
autoTiles.put(uid, autoTile);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.bartlomiejpluta.base.engine.world.autotile.model;
|
||||
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.world.object.Sprite;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
@@ -14,16 +13,16 @@ public class AutoSubTile extends Sprite {
|
||||
private final Vector2fc tileSpriteSize;
|
||||
private final Vector2f tileScale = new Vector2f(1, 1);
|
||||
|
||||
public AutoSubTile(Mesh mesh, AutoTileSet autoTileSet) {
|
||||
super(mesh, Material.textured(autoTileSet.getTexture()));
|
||||
public AutoSubTile(AutoTileSet autoTileSet) {
|
||||
super(Material.textured(autoTileSet.getTexture()));
|
||||
|
||||
tileSpriteSize = material.getTexture().getSpriteSize();
|
||||
tileSpriteSize = getMaterial().getTexture().getSpriteSize();
|
||||
|
||||
super.setScale(tileSpriteSize.x() * tileScale.x, tileSpriteSize.y() * tileScale.y);
|
||||
}
|
||||
|
||||
public void recalculate(@NonNull Vector2ic spritePosition) {
|
||||
material.setSpritePosition(spritePosition.y(), spritePosition.x());
|
||||
setFrame(spritePosition.x(), spritePosition.y());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.bartlomiejpluta.base.engine.world.autotile.model;
|
||||
|
||||
import com.bartlomiejpluta.base.api.camera.Camera;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.internal.render.Renderable;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
import lombok.Getter;
|
||||
@@ -18,11 +17,11 @@ public class AutoTile implements Renderable {
|
||||
@Getter
|
||||
private int setId;
|
||||
|
||||
public AutoTile(@NonNull Mesh mesh, @NonNull AutoTileSet autoTileSet, int setId) {
|
||||
this.topLeftSubTile = new AutoSubTile(mesh, autoTileSet);
|
||||
this.topRightSubTile = new AutoSubTile(mesh, autoTileSet);
|
||||
this.bottomLeftSubTile = new AutoSubTile(mesh, autoTileSet);
|
||||
this.bottomRightSubTile = new AutoSubTile(mesh, autoTileSet);
|
||||
public AutoTile(@NonNull AutoTileSet autoTileSet, int setId) {
|
||||
this.topLeftSubTile = new AutoSubTile(autoTileSet);
|
||||
this.topRightSubTile = new AutoSubTile(autoTileSet);
|
||||
this.bottomLeftSubTile = new AutoSubTile(autoTileSet);
|
||||
this.bottomRightSubTile = new AutoSubTile(autoTileSet);
|
||||
this.autoTileSet = autoTileSet;
|
||||
this.setId = setId;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.bartlomiejpluta.base.engine.world.autotile.model;
|
||||
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
@@ -45,7 +44,6 @@ public class AutoTileSet {
|
||||
|
||||
@Getter
|
||||
private final Texture texture;
|
||||
private final Mesh mesh;
|
||||
|
||||
@Getter
|
||||
private final Vector2fc tileSize;
|
||||
@@ -58,9 +56,8 @@ public class AutoTileSet {
|
||||
@Getter
|
||||
private final int setsCount;
|
||||
|
||||
public AutoTileSet(@NonNull Texture texture, @NonNull Mesh mesh, int rows, int columns, @NonNull AutoTileLayout layout) {
|
||||
public AutoTileSet(@NonNull Texture texture, int rows, int columns, @NonNull AutoTileLayout layout) {
|
||||
this.texture = texture;
|
||||
this.mesh = mesh;
|
||||
this.rows = rows;
|
||||
this.columns = columns;
|
||||
this.tileSize = texture.getSpriteSize();
|
||||
@@ -202,6 +199,6 @@ public class AutoTileSet {
|
||||
}
|
||||
|
||||
public AutoTile createTile(int setId) {
|
||||
return new AutoTile(mesh, this, setId);
|
||||
return new AutoTile(this, setId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.bartlomiejpluta.base.engine.world.character.manager;
|
||||
|
||||
import com.bartlomiejpluta.base.api.character.Character;
|
||||
import com.bartlomiejpluta.base.api.move.Direction;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.util.mesh.MeshManager;
|
||||
import com.bartlomiejpluta.base.engine.world.character.config.CharacterSpriteConfiguration;
|
||||
import com.bartlomiejpluta.base.engine.world.character.model.DefaultCharacter;
|
||||
@@ -27,8 +26,6 @@ public class DefaultCharacterManager implements CharacterManager {
|
||||
private final Map<Direction, Integer> spriteDirectionRows;
|
||||
private final Map<Direction, Vector2fc> spriteDefaultRows;
|
||||
|
||||
private Mesh mesh;
|
||||
|
||||
@Autowired
|
||||
public DefaultCharacterManager(MeshManager meshManager, CharacterSetManager characterSetManager, CharacterSpriteConfiguration configuration) {
|
||||
this.meshManager = meshManager;
|
||||
@@ -45,12 +42,12 @@ public class DefaultCharacterManager implements CharacterManager {
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
mesh = meshManager.createQuad(1, 1, 0.5f, 1);
|
||||
// TODO mesh = meshManager.createQuad(1, 1, 0.5f, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Character createCharacter(String characterSetUid) {
|
||||
return new DefaultCharacter(mesh, characterSetManager, defaultSpriteColumn, spriteDirectionRows, spriteDefaultRows, characterSetUid);
|
||||
return new DefaultCharacter(characterSetManager, defaultSpriteColumn, spriteDirectionRows, spriteDefaultRows, characterSetUid);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,7 +8,6 @@ import com.bartlomiejpluta.base.api.move.CharacterMovement;
|
||||
import com.bartlomiejpluta.base.api.move.Direction;
|
||||
import com.bartlomiejpluta.base.api.move.Movement;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.error.AppException;
|
||||
import com.bartlomiejpluta.base.engine.world.character.manager.CharacterSetManager;
|
||||
import com.bartlomiejpluta.base.engine.world.movement.MovableSprite;
|
||||
@@ -29,6 +28,15 @@ import static java.util.Objects.requireNonNull;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DefaultCharacter extends MovableSprite implements Character {
|
||||
private static final Map<Direction, int[]> CHARSET_FRAMES = Map.of(
|
||||
Direction.DOWN, new int[]{0, 1, 2, 3},
|
||||
Direction.LEFT, new int[]{4, 5, 6, 7},
|
||||
Direction.RIGHT, new int[]{8, 9, 10, 11},
|
||||
Direction.UP, new int[]{12, 13, 14, 15}
|
||||
);
|
||||
|
||||
private static final int DEFAULT_CHARSET_FRAME_COLUMN = 0;
|
||||
|
||||
private final int defaultSpriteColumn;
|
||||
private final CharacterSetManager characterSetManager;
|
||||
private final Map<Direction, Integer> spriteDirectionRows;
|
||||
@@ -56,19 +64,21 @@ public class DefaultCharacter extends MovableSprite implements Character {
|
||||
|
||||
private final Queue<CharacterInstantAnimation> instantAnimations = new LinkedList<>();
|
||||
|
||||
public DefaultCharacter(Mesh mesh, CharacterSetManager characterSetManager, int defaultSpriteColumn, Map<Direction, Integer> spriteDirectionRows, Map<Direction, Vector2fc> spriteDefaultRows, String characterSetUid) {
|
||||
super(mesh, createMaterial(characterSetManager, characterSetUid));
|
||||
public DefaultCharacter(CharacterSetManager characterSetManager, int defaultSpriteColumn, Map<Direction, Integer> spriteDirectionRows, Map<Direction, Vector2fc> spriteDefaultRows, String characterSetUid) {
|
||||
super(createMaterial(characterSetManager, characterSetUid));
|
||||
this.defaultSpriteColumn = defaultSpriteColumn;
|
||||
this.characterSetManager = characterSetManager;
|
||||
this.spriteDirectionRows = spriteDirectionRows;
|
||||
this.faceDirection = Direction.DOWN;
|
||||
this.spriteDefaultRows = spriteDefaultRows;
|
||||
|
||||
var texture = material.getTexture();
|
||||
var texture = getMaterial().getTexture();
|
||||
if (texture != null) {
|
||||
this.characterSetSize = texture.getSpriteSize();
|
||||
super.setScale(characterSetSize.x() * characterScale.x, characterSetSize.y() * characterScale.y);
|
||||
}
|
||||
|
||||
setDefaultAnimationFrame();
|
||||
}
|
||||
|
||||
private static Material createMaterial(CharacterSetManager characterSetManager, String characterSetUid) {
|
||||
@@ -102,13 +112,13 @@ public class DefaultCharacter extends MovableSprite implements Character {
|
||||
|
||||
@Override
|
||||
protected boolean shouldAnimate() {
|
||||
return animationEnabled && material.getTexture() != null && (isMoving() || !instantAnimations.isEmpty());
|
||||
return animationEnabled && getMaterial().getTexture() != null && (isMoving() || !instantAnimations.isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Vector2fc[] getSpriteAnimationFramesPositions() {
|
||||
var row = spriteDirectionRows.get(faceDirection);
|
||||
var frames = material.getTexture().getColumns();
|
||||
var frames = getMaterial().getTexture().getColumns();
|
||||
var array = new Vector2f[frames];
|
||||
|
||||
for (int column = 0; column < frames; ++column) {
|
||||
@@ -118,15 +128,21 @@ public class DefaultCharacter extends MovableSprite implements Character {
|
||||
return array;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int[] getAvailableFrames() {
|
||||
return CHARSET_FRAMES.get(faceDirection);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setDefaultAnimationFrame() {
|
||||
material.setSpritePosition(spriteDefaultRows.get(faceDirection));
|
||||
// getMaterial().setSpritePosition(spriteDefaultRows.get(faceDirection));
|
||||
setAnimationFrame(CHARSET_FRAMES.get(faceDirection)[DEFAULT_CHARSET_FRAME_COLUMN]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeCharacterSet(String characterSetUid) {
|
||||
this.material = createMaterial(characterSetManager, characterSetUid);
|
||||
var texture = this.material.getTexture();
|
||||
setMaterial(createMaterial(characterSetManager, characterSetUid));
|
||||
var texture = this.getMaterial().getTexture();
|
||||
|
||||
if (texture != null) {
|
||||
this.characterSetSize = texture.getSpriteSize();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.bartlomiejpluta.base.engine.world.icon.manager;
|
||||
|
||||
import com.bartlomiejpluta.base.api.icon.Icon;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.util.mesh.MeshManager;
|
||||
import com.bartlomiejpluta.base.engine.world.icon.model.DefaultIcon;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -15,16 +14,15 @@ import org.springframework.stereotype.Component;
|
||||
public class DefaultIconManager implements IconManager {
|
||||
private final MeshManager meshManager;
|
||||
private final IconSetManager iconSetManager;
|
||||
private Mesh mesh;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
this.mesh = meshManager.createQuad(1, 1, 0.5f, 1);
|
||||
// TODO: this.mesh = meshManager.createQuad(1, 1, 0.5f, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon createIcon(String iconSetUid, int row, int column) {
|
||||
return new DefaultIcon(mesh, iconSetManager, iconSetUid, row, column);
|
||||
return new DefaultIcon(iconSetManager, iconSetUid, row, column);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.bartlomiejpluta.base.api.event.Event;
|
||||
import com.bartlomiejpluta.base.api.event.EventType;
|
||||
import com.bartlomiejpluta.base.api.icon.Icon;
|
||||
import com.bartlomiejpluta.base.api.map.layer.object.ObjectLayer;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.error.AppException;
|
||||
import com.bartlomiejpluta.base.engine.world.icon.manager.IconSetManager;
|
||||
import com.bartlomiejpluta.base.engine.world.object.Sprite;
|
||||
@@ -42,12 +41,12 @@ public class DefaultIcon extends Sprite implements Icon {
|
||||
@Getter
|
||||
private int zIndex;
|
||||
|
||||
public DefaultIcon(Mesh mesh, IconSetManager iconSetManager, String iconSetUid, int row, int column) {
|
||||
super(mesh, iconSetManager.loadObject(iconSetUid));
|
||||
public DefaultIcon(IconSetManager iconSetManager, String iconSetUid, int row, int column) {
|
||||
super(iconSetManager.loadObject(iconSetUid));
|
||||
this.iconSetManager = iconSetManager;
|
||||
material.setSpritePosition(column, row);
|
||||
getMaterial().setSpritePosition(column, row);
|
||||
|
||||
var texture = material.getTexture();
|
||||
var texture = getMaterial().getTexture();
|
||||
if (texture != null) {
|
||||
this.iconSetSize = texture.getSpriteSize();
|
||||
super.setScale(iconSetSize.x() * iconScale.x, iconSetSize.y() * iconScale.y);
|
||||
@@ -70,21 +69,21 @@ public class DefaultIcon extends Sprite implements Icon {
|
||||
|
||||
@Override
|
||||
public void changeIcon(int row, int column) {
|
||||
material.setSpritePosition(column, row);
|
||||
getMaterial().setSpritePosition(column, row);
|
||||
this.iconSetRow = row;
|
||||
this.iconSetColumn = column;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeIcon(String iconSetUid, int row, int column) {
|
||||
this.material = iconSetManager.loadObject(iconSetUid);
|
||||
material.setSpritePosition(column, row);
|
||||
setMaterial(iconSetManager.loadObject(iconSetUid));
|
||||
getMaterial().setSpritePosition(column, row);
|
||||
|
||||
this.iconSetUid = iconSetUid;
|
||||
this.iconSetRow = row;
|
||||
this.iconSetColumn = column;
|
||||
|
||||
var texture = material.getTexture();
|
||||
var texture = getMaterial().getTexture();
|
||||
if (texture != null) {
|
||||
this.iconSetSize = texture.getSpriteSize();
|
||||
super.setScale(iconSetSize.x() * iconScale.x, iconSetSize.y() * iconScale.y);
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.bartlomiejpluta.base.engine.world.image.manager;
|
||||
|
||||
import com.bartlomiejpluta.base.api.image.Image;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.texture.TextureManager;
|
||||
import com.bartlomiejpluta.base.engine.error.AppException;
|
||||
import com.bartlomiejpluta.base.engine.project.config.ProjectConfiguration;
|
||||
@@ -30,11 +29,10 @@ public class DefaultImageManager implements ImageManager {
|
||||
private final Map<String, ImageAsset> assets = new HashMap<>();
|
||||
private final Map<String, ByteBuffer> imageBuffers = new HashMap<>();
|
||||
private final ProjectConfiguration configuration;
|
||||
private Mesh mesh;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
mesh = meshManager.createQuad(1, 1, 0, 0);
|
||||
// TODO mesh = meshManager.createQuad(1, 1, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,7 +64,7 @@ public class DefaultImageManager implements ImageManager {
|
||||
var material = Material.textured(texture);
|
||||
log.info("Creating new image on asset with UID: [{}]", uid);
|
||||
|
||||
return new DefaultImage(mesh, material, initialWidth, initialHeight, gcd);
|
||||
return new DefaultImage(material, initialWidth, initialHeight, gcd);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.bartlomiejpluta.base.engine.world.image.model;
|
||||
|
||||
import com.bartlomiejpluta.base.api.image.Image;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.world.object.Sprite;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
@@ -17,8 +16,8 @@ public class DefaultImage extends Sprite implements Image {
|
||||
private final int width;
|
||||
private final int height;
|
||||
|
||||
public DefaultImage(@NonNull Mesh mesh, @NonNull Material texture, int primaryWidth, int primaryHeight, int factor) {
|
||||
super(mesh, texture);
|
||||
public DefaultImage(@NonNull Material texture, int primaryWidth, int primaryHeight, int factor) {
|
||||
super(texture);
|
||||
this.primaryWidth = primaryWidth;
|
||||
this.primaryHeight = primaryHeight;
|
||||
this.factor = factor;
|
||||
@@ -31,12 +30,12 @@ public class DefaultImage extends Sprite implements Image {
|
||||
|
||||
@Override
|
||||
public void setOpacity(float opacity) {
|
||||
material.setAlpha(opacity);
|
||||
getMaterial().setAlpha(opacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getOpacity() {
|
||||
return material.getColor().w();
|
||||
return getMaterial().getColor().w();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,7 +9,6 @@ import com.bartlomiejpluta.base.engine.world.location.LocationableModel;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector3fc;
|
||||
|
||||
|
||||
@@ -144,7 +144,8 @@ public class DefaultColorLayer extends BaseLayer implements ColorLayer {
|
||||
|
||||
private static class Color extends Sprite {
|
||||
public Color(@NonNull MeshManager meshManager, float red, float green, float blue, float alpha) {
|
||||
super(meshManager.createQuad(1, 1, 0, 0), Material.colored(red, green, blue, alpha));
|
||||
// TODO (Custom Mesh): super(meshManager.createQuad(1, 1, 0, 0), Material.colored(red, green, blue, alpha));
|
||||
super(Material.colored(red, green, blue, alpha));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package com.bartlomiejpluta.base.engine.world.map.layer.tile;
|
||||
|
||||
import com.bartlomiejpluta.base.api.camera.Camera;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.BatchedQuads;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Quad;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.QuadTemplate;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.shader.constant.Shader;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.shader.constant.UniformName;
|
||||
@@ -16,9 +16,9 @@ import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
|
||||
public class TileChunk extends Model implements Placeable, Renderable, Disposable, BoundingBox {
|
||||
private final Texture tileSet;
|
||||
private final BatchedQuads mesh;
|
||||
private final Mesh mesh;
|
||||
private final int chunkSize;
|
||||
private final Quad quad;
|
||||
private final QuadTemplate template;
|
||||
private final float originX;
|
||||
private final float originY;
|
||||
|
||||
@@ -29,14 +29,14 @@ public class TileChunk extends Model implements Placeable, Renderable, Disposabl
|
||||
public TileChunk(Texture tileSet, int chunkSize, float originX, float originY) {
|
||||
this.tileSet = tileSet;
|
||||
this.chunkSize = chunkSize;
|
||||
this.mesh = new BatchedQuads(chunkSize * chunkSize);
|
||||
this.quad = new Quad(tileSet.getSpriteSize().x(), tileSet.getSpriteSize().y(), originX, originY);
|
||||
this.mesh = new Mesh(chunkSize * chunkSize);
|
||||
this.template = new QuadTemplate(tileSet.getSpriteSize().x(), tileSet.getSpriteSize().y(), originX, originY);
|
||||
this.originX = originX;
|
||||
this.originY = originY;
|
||||
}
|
||||
|
||||
public int addTile(int x, int y, int tileId) {
|
||||
return mesh.addQuad(quad, x, y, tileSet.getTextureCoordinates(tileId));
|
||||
return mesh.addQuad(template, x, y, tileSet.getTextureCoordinates(tileId));
|
||||
}
|
||||
|
||||
public void removeTile(int quadId) {
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.bartlomiejpluta.base.engine.world.map.manager;
|
||||
|
||||
import com.bartlomiejpluta.base.api.context.Context;
|
||||
import com.bartlomiejpluta.base.api.map.handler.MapHandler;
|
||||
import com.bartlomiejpluta.base.api.map.layer.object.ObjectLayer;
|
||||
import com.bartlomiejpluta.base.engine.error.AppException;
|
||||
import com.bartlomiejpluta.base.engine.project.config.ProjectConfiguration;
|
||||
import com.bartlomiejpluta.base.engine.util.reflection.ClassLoader;
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.bartlomiejpluta.base.api.move.Movable;
|
||||
import com.bartlomiejpluta.base.api.move.Movement;
|
||||
import com.bartlomiejpluta.base.engine.core.engine.DefaultGameEngine;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.world.animation.model.AnimatedSprite;
|
||||
import com.bartlomiejpluta.base.internal.program.Updatable;
|
||||
import com.bartlomiejpluta.base.util.math.MathUtil;
|
||||
@@ -12,9 +11,6 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import org.joml.Vector2f;
|
||||
|
||||
import static java.lang.Math.abs;
|
||||
import static java.lang.Math.max;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public abstract class MovableSprite extends AnimatedSprite implements Movable, Updatable {
|
||||
private int moveTime = 0;
|
||||
@@ -24,8 +20,8 @@ public abstract class MovableSprite extends AnimatedSprite implements Movable, U
|
||||
@Getter
|
||||
private Movement movement;
|
||||
|
||||
public MovableSprite(Mesh mesh, Material material) {
|
||||
super(mesh, material);
|
||||
public MovableSprite(Material material) {
|
||||
super(material);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,43 +4,103 @@ import com.bartlomiejpluta.base.api.camera.Camera;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.QuadMesh;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.shader.constant.Shader;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.shader.constant.UniformName;
|
||||
import com.bartlomiejpluta.base.engine.world.location.LocationableModel;
|
||||
import com.bartlomiejpluta.base.internal.render.BoundingBox;
|
||||
import com.bartlomiejpluta.base.internal.render.Renderable;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public abstract class Sprite extends LocationableModel implements Renderable {
|
||||
private final float farthestVertexDistance;
|
||||
|
||||
protected final Mesh mesh;
|
||||
|
||||
public abstract class Sprite extends LocationableModel implements Renderable, BoundingBox {
|
||||
@NonNull
|
||||
@Setter
|
||||
@Getter
|
||||
protected Material material;
|
||||
private Material material;
|
||||
|
||||
public Sprite(Mesh mesh, Material material) {
|
||||
this.mesh = mesh;
|
||||
private final QuadMesh quad;
|
||||
private final float width = 1f;
|
||||
private final float height = 1f;
|
||||
private final float originX = .5f;
|
||||
private final float originY = 1f;
|
||||
|
||||
@Getter
|
||||
private float[][] textureCoordinates;
|
||||
|
||||
public Sprite(Material material) {
|
||||
this.material = material;
|
||||
this.quad = Mesh.quad(width, height, originX, originY);
|
||||
|
||||
this.farthestVertexDistance = this.mesh.getFarthestVertex().lengthSquared();
|
||||
updateTextureCoordinates();
|
||||
}
|
||||
|
||||
private void updateTextureCoordinates() {
|
||||
var texture = material.getTexture();
|
||||
|
||||
if (texture == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
textureCoordinates = texture.getTextureCoordinatesForAllFrames();
|
||||
}
|
||||
|
||||
public void setMaterial(@NonNull Material material) {
|
||||
this.material = material;
|
||||
updateTextureCoordinates();
|
||||
}
|
||||
|
||||
public void setFrame(int row, int column) {
|
||||
setFrame(row * material.getTexture().getColumns() + column);
|
||||
}
|
||||
|
||||
public void setFrame(int id) {
|
||||
quad.setTextureCoordinates(textureCoordinates[id]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMinX() {
|
||||
float scaledOriginX = originX * scaleX;
|
||||
return getPosition().x() - scaledOriginX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMaxX() {
|
||||
float scaledOriginX = originX * scaleX;
|
||||
float scaledChunkWidth = width * scaleX;
|
||||
return getPosition().x() + scaledChunkWidth - scaledOriginX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMinY() {
|
||||
float scaledOriginY = originY * scaleY;
|
||||
return getPosition().y() - scaledOriginY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMaxY() {
|
||||
float scaledOriginY = originY * scaleY;
|
||||
float scaledChunkHeight = height * scaleY;
|
||||
return getPosition().y() + scaledChunkHeight - scaledOriginY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Screen screen, Camera camera, ShaderManager shaderManager) {
|
||||
if (!camera.insideFrustum(position.x, position.y, farthestVertexDistance * (scaleX > scaleY ? scaleX : scaleY))) {
|
||||
if (!camera.containsBox(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
material.getTexture().activate();
|
||||
shaderManager.activateShader(Shader.BATCH.name);
|
||||
|
||||
shaderManager.setUniform(UniformName.UNI_PROJECTION_MATRIX, camera.getProjectionMatrix());
|
||||
shaderManager.setUniform(UniformName.UNI_VIEW_MODEL_MATRIX, camera.computeViewModelMatrix(getModelMatrix()));
|
||||
shaderManager.setUniform(UniformName.UNI_MODEL_MATRIX, getModelMatrix());
|
||||
material.render(screen, camera, shaderManager);
|
||||
mesh.render(screen, camera, shaderManager);
|
||||
shaderManager.setUniform(UniformName.UNI_TEXTURE_SAMPLER, 0);
|
||||
|
||||
quad.render(screen, camera, shaderManager);
|
||||
|
||||
shaderManager.deactivateShader();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.bartlomiejpluta.base.engine.world.tileset.manager;
|
||||
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.texture.TextureManager;
|
||||
import com.bartlomiejpluta.base.engine.error.AppException;
|
||||
import com.bartlomiejpluta.base.engine.project.config.ProjectConfiguration;
|
||||
@@ -24,11 +23,10 @@ public class DefaultTileSetManager implements TileSetManager {
|
||||
private final Map<String, TileSet> tileSets = new HashMap<>();
|
||||
private final Map<String, TileSetAsset> assets = new HashMap<>();
|
||||
private final ProjectConfiguration configuration;
|
||||
private Mesh mesh;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
this.mesh = meshManager.createQuad(1, 1, 0, 0);
|
||||
// TODO this.mesh = meshManager.createQuad(1, 1, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,7 +53,7 @@ public class DefaultTileSetManager implements TileSetManager {
|
||||
|
||||
var source = configuration.projectFile("tilesets", asset.getSource());
|
||||
var texture = textureManager.loadTexture(source, asset.getRows(), asset.getColumns());
|
||||
tileset = new TileSet(texture, mesh);
|
||||
tileset = new TileSet(texture);
|
||||
log.info("Loading tile set from assets to cache under the key: [{}]", uid);
|
||||
tileSets.put(uid, tileset);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.bartlomiejpluta.base.engine.world.tileset.model;
|
||||
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture;
|
||||
import com.bartlomiejpluta.base.engine.world.object.Sprite;
|
||||
import lombok.Getter;
|
||||
@@ -17,28 +16,28 @@ public class Tile extends Sprite {
|
||||
private final Vector2fc tileSpriteSize;
|
||||
|
||||
public Tile setLocation(int row, int column) {
|
||||
var stepSize = material.getTexture().getSpriteSize();
|
||||
var stepSize = getMaterial().getTexture().getSpriteSize();
|
||||
setPosition(column * stepSize.x(), row * stepSize.y());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Tile(Mesh mesh, Texture tileSet, int id) {
|
||||
super(mesh, Material.textured(tileSet));
|
||||
public Tile(Texture tileSet, int id) {
|
||||
super(Material.textured(tileSet));
|
||||
this.id = id;
|
||||
this.tileSetRow = id / tileSet.getColumns();
|
||||
this.tileSetColumn = id % tileSet.getColumns();
|
||||
material.setSpritePosition(tileSetColumn, tileSetRow);
|
||||
getMaterial().setSpritePosition(tileSetColumn, tileSetRow);
|
||||
tileSpriteSize = tileSet.getSpriteSize();
|
||||
|
||||
super.setScale(tileSpriteSize.x() * tileScale.x, tileSpriteSize.y() * tileScale.y);
|
||||
}
|
||||
|
||||
public Tile(Mesh mesh, Texture tileSet, int row, int column) {
|
||||
super(mesh, Material.textured(tileSet));
|
||||
public Tile(Texture tileSet, int row, int column) {
|
||||
super(Material.textured(tileSet));
|
||||
this.tileSetRow = row;
|
||||
this.tileSetColumn = column;
|
||||
this.id = row * tileSet.getColumns() + column;
|
||||
material.setSpritePosition(tileSetColumn, tileSetRow);
|
||||
getMaterial().setSpritePosition(tileSetColumn, tileSetRow);
|
||||
tileSpriteSize = tileSet.getSpriteSize();
|
||||
|
||||
super.setScale(tileSpriteSize.x() * tileScale.x, tileSpriteSize.y() * tileScale.y);
|
||||
|
||||
@@ -1,29 +1,25 @@
|
||||
package com.bartlomiejpluta.base.engine.world.tileset.model;
|
||||
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Getter
|
||||
public class TileSet {
|
||||
private final Texture tileSet;
|
||||
private final Mesh mesh;
|
||||
private final Material material;
|
||||
|
||||
public TileSet(@NonNull Texture tileSet, @NonNull Mesh mesh) {
|
||||
public TileSet(@NonNull Texture tileSet) {
|
||||
this.tileSet = tileSet;
|
||||
this.mesh = mesh;
|
||||
this.material = Material.textured(tileSet);
|
||||
}
|
||||
|
||||
public Tile tileById(int id) {
|
||||
return new Tile(mesh, tileSet, id);
|
||||
return new Tile(tileSet, id);
|
||||
}
|
||||
|
||||
public Tile tileAt(int row, int column) {
|
||||
return new Tile(mesh, tileSet, row, column);
|
||||
return new Tile(tileSet, row, column);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user