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