Added raycasting method! I think...
This commit is contained in:
parent
c2958e403b
commit
c9b325da3a
|
@ -37,6 +37,10 @@ public class ChunkMesh {
|
||||||
return positionData;
|
return positionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Chunk getChunk() {
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates and loads this chunk's mesh into the allocated OpenGL buffers.
|
* Generates and loads this chunk's mesh into the allocated OpenGL buffers.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,10 +4,9 @@ import nl.andrewl.aos2_client.Camera;
|
||||||
import nl.andrewl.aos_core.model.Chunk;
|
import nl.andrewl.aos_core.model.Chunk;
|
||||||
import nl.andrewl.aos_core.model.World;
|
import nl.andrewl.aos_core.model.World;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
import org.joml.Vector3i;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
import static org.lwjgl.opengl.GL46.*;
|
import static org.lwjgl.opengl.GL46.*;
|
||||||
|
@ -26,7 +25,7 @@ public class ChunkRenderer {
|
||||||
private int viewTransformUniform;
|
private int viewTransformUniform;
|
||||||
private int chunkPositionUniform;
|
private int chunkPositionUniform;
|
||||||
|
|
||||||
private final List<ChunkMesh> chunkMeshes = new ArrayList<>();
|
private final Map<Vector3i, ChunkMesh> chunkMeshes = new HashMap<>();
|
||||||
|
|
||||||
public void setupShaderProgram() {
|
public void setupShaderProgram() {
|
||||||
this.shaderProgram = new ShaderProgram.Builder()
|
this.shaderProgram = new ShaderProgram.Builder()
|
||||||
|
@ -53,18 +52,22 @@ public class ChunkRenderer {
|
||||||
|
|
||||||
public void draw(Camera cam, World world) {
|
public void draw(Camera cam, World world) {
|
||||||
while (!meshGenerationQueue.isEmpty()) {
|
while (!meshGenerationQueue.isEmpty()) {
|
||||||
chunkMeshes.add(new ChunkMesh(meshGenerationQueue.remove(), world, chunkMeshGenerator));
|
Chunk chunk = meshGenerationQueue.remove();
|
||||||
|
ChunkMesh mesh = new ChunkMesh(chunk, world, chunkMeshGenerator);
|
||||||
|
chunkMeshes.put(chunk.getPosition(), mesh);
|
||||||
}
|
}
|
||||||
shaderProgram.use();
|
shaderProgram.use();
|
||||||
glUniformMatrix4fv(viewTransformUniform, false, cam.getViewTransformData());
|
glUniformMatrix4fv(viewTransformUniform, false, cam.getViewTransformData());
|
||||||
for (var mesh : chunkMeshes) {
|
for (var mesh : chunkMeshes.values()) {
|
||||||
glUniform3iv(chunkPositionUniform, mesh.getPositionData());
|
glUniform3iv(chunkPositionUniform, mesh.getPositionData());
|
||||||
mesh.draw();
|
mesh.draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void free() {
|
public void free() {
|
||||||
for (var mesh : chunkMeshes) mesh.free();
|
for (var mesh : chunkMeshes.values()) mesh.free();
|
||||||
|
chunkMeshes.clear();
|
||||||
|
meshGenerationQueue.clear();
|
||||||
shaderProgram.free();
|
shaderProgram.free();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,23 +82,80 @@ public class World {
|
||||||
setBlockAt(new Vector3f(x, y, z), block);
|
setBlockAt(new Vector3f(x, y, z), block);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public byte getBlockAt(int x, int y, int z) {
|
|
||||||
//// int chunkX = x / Chunk.SIZE;
|
|
||||||
//// int localX = x % Chunk.SIZE;
|
|
||||||
//// int chunkY = y / Chunk.SIZE;
|
|
||||||
//// int localY = y % Chunk.SIZE;
|
|
||||||
//// int chunkZ = z / Chunk.SIZE;
|
|
||||||
//// int localZ = z % Chunk.SIZE;
|
|
||||||
//// Vector3i chunkPos = new Vector3i(chunkX, chunkY, chunkZ);
|
|
||||||
//// Chunk chunk = chunkMap.get(chunkPos);
|
|
||||||
//// if (chunk == null) return 0;
|
|
||||||
//// return chunk.getBlockAt(localX, localY, localZ);
|
|
||||||
// }
|
|
||||||
|
|
||||||
public Chunk getChunkAt(Vector3i chunkPos) {
|
public Chunk getChunkAt(Vector3i chunkPos) {
|
||||||
return chunkMap.get(chunkPos);
|
return chunkMap.get(chunkPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the position that a system is looking at, within a distance limit.
|
||||||
|
* Usually used to determine where a player has interacted/clicked in the
|
||||||
|
* world.
|
||||||
|
* @param eyePos The origin point to look from.
|
||||||
|
* @param eyeDir The direction to look towards. This should be normalized.
|
||||||
|
* @param limit The radius out from the origin to look. Blocks outside this
|
||||||
|
* limit will not be returned.
|
||||||
|
* @return The location of the block that is looked at, or null if none
|
||||||
|
* could be found.
|
||||||
|
*/
|
||||||
|
public Vector3i getLookingAtPos(Vector3f eyePos, Vector3f eyeDir, float limit) {
|
||||||
|
if (eyeDir.lengthSquared() == 0 || limit <= 0) return null;
|
||||||
|
Vector3f pos = new Vector3f(eyePos);
|
||||||
|
Vector3f movement = new Vector3f(); // Pre-allocate this vector.
|
||||||
|
while (pos.distance(eyePos) < limit) {
|
||||||
|
// Find the coordinates of the next blocks on the x, y, and z axes.
|
||||||
|
float stepX = getNextStep(pos.x, eyeDir.x);
|
||||||
|
float stepY = getNextStep(pos.y, eyeDir.y);
|
||||||
|
float stepZ = getNextStep(pos.z, eyeDir.z);
|
||||||
|
// Get the distance from our current position to the next block on the x, y, and z axes.
|
||||||
|
float distX = Math.abs(pos.x - stepX);
|
||||||
|
float distY = Math.abs(pos.y - stepY);
|
||||||
|
float distZ = Math.abs(pos.z - stepZ);
|
||||||
|
// Get the factor required to multiply each component by to get to its next step.
|
||||||
|
float factorX = Math.abs(distX / eyeDir.x);
|
||||||
|
float factorY = Math.abs(distY / eyeDir.y);
|
||||||
|
float factorZ = Math.abs(distZ / eyeDir.z);
|
||||||
|
float minFactor = Float.MAX_VALUE;
|
||||||
|
if (factorX > 0 && factorX < minFactor) minFactor = factorX;
|
||||||
|
if (factorY > 0 && factorY < minFactor) minFactor = factorY;
|
||||||
|
if (factorZ > 0 && factorZ < minFactor) minFactor = factorZ;
|
||||||
|
// We should add dir * lowest factor to step to the first next block.
|
||||||
|
movement.set(eyeDir).mul(minFactor);
|
||||||
|
pos.add(movement);
|
||||||
|
if (getBlockAt(pos) > 0) {
|
||||||
|
return new Vector3i(
|
||||||
|
(int) Math.floor(pos.x),
|
||||||
|
(int) Math.floor(pos.y),
|
||||||
|
(int) Math.floor(pos.z)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to find the next whole number, given a current number and
|
||||||
|
* an indication of which direction the number is increasing.
|
||||||
|
* @param n The current number.
|
||||||
|
* @param sign An indication of which way the number is increasing.
|
||||||
|
* @return The next whole number up from the current number.
|
||||||
|
*/
|
||||||
|
private static float getNextStep(float n, float sign) {
|
||||||
|
if (sign > 0) {
|
||||||
|
if (Math.ceil(n) == n) {
|
||||||
|
return n + 1;
|
||||||
|
} else {
|
||||||
|
return Math.ceil(n);
|
||||||
|
}
|
||||||
|
} else if (sign < 0) {
|
||||||
|
if (Math.floor(n) == n) {
|
||||||
|
return n - 1;
|
||||||
|
} else {
|
||||||
|
return Math.floor(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the coordinates of a chunk at a given world position.
|
* Gets the coordinates of a chunk at a given world position.
|
||||||
* @param worldPos The world position.
|
* @param worldPos The world position.
|
||||||
|
|
|
@ -5,6 +5,7 @@ import org.joml.Vector3i;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
public class WorldTest {
|
public class WorldTest {
|
||||||
@Test
|
@Test
|
||||||
|
@ -31,4 +32,82 @@ public class WorldTest {
|
||||||
assertEquals(new Vector3i(1, 1, 1), World.getChunkPosAt(new Vector3f(Chunk.SIZE, Chunk.SIZE, Chunk.SIZE)));
|
assertEquals(new Vector3i(1, 1, 1), World.getChunkPosAt(new Vector3f(Chunk.SIZE, Chunk.SIZE, Chunk.SIZE)));
|
||||||
assertEquals(new Vector3i(4, 4, 4), World.getChunkPosAt(new Vector3f(Chunk.SIZE * 5 - 1, Chunk.SIZE * 5 - 1, Chunk.SIZE * 5 - 1)));
|
assertEquals(new Vector3i(4, 4, 4), World.getChunkPosAt(new Vector3f(Chunk.SIZE * 5 - 1, Chunk.SIZE * 5 - 1, Chunk.SIZE * 5 - 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetLookingAtPos() {
|
||||||
|
World world = Worlds.testingWorld();
|
||||||
|
// Spawn a block high in the air.
|
||||||
|
Vector3i blockPos = new Vector3i(20, 20, 20);
|
||||||
|
world.setBlockAt(blockPos.x, blockPos.y, blockPos.z, (byte) 5);
|
||||||
|
assertEquals( // Looking straight down onto block.
|
||||||
|
blockPos,
|
||||||
|
world.getLookingAtPos(
|
||||||
|
new Vector3f(20.5f, 25, 20.5f),
|
||||||
|
new Vector3f(0, -1, 0),
|
||||||
|
15
|
||||||
|
)
|
||||||
|
);
|
||||||
|
assertEquals( // Looking straight up.
|
||||||
|
blockPos,
|
||||||
|
world.getLookingAtPos(
|
||||||
|
new Vector3f(20.5f, 15, 20.5f),
|
||||||
|
new Vector3f(0, 1, 0),
|
||||||
|
15
|
||||||
|
)
|
||||||
|
);
|
||||||
|
assertEquals( // Looking towards -Z
|
||||||
|
blockPos,
|
||||||
|
world.getLookingAtPos(
|
||||||
|
new Vector3f(20.5f, 20.5f, 26f),
|
||||||
|
new Vector3f(0, 0, -1),
|
||||||
|
15
|
||||||
|
)
|
||||||
|
);
|
||||||
|
assertEquals( // Looking towards +Z
|
||||||
|
blockPos,
|
||||||
|
world.getLookingAtPos(
|
||||||
|
new Vector3f(20.5f, 20.5f, 15f),
|
||||||
|
new Vector3f(0, 0, 1),
|
||||||
|
15
|
||||||
|
)
|
||||||
|
);
|
||||||
|
assertEquals( // Looking towards -X
|
||||||
|
blockPos,
|
||||||
|
world.getLookingAtPos(
|
||||||
|
new Vector3f(26f, 20.5f, 20.5f),
|
||||||
|
new Vector3f(-1, 0, 0),
|
||||||
|
15
|
||||||
|
)
|
||||||
|
);
|
||||||
|
assertEquals( // Looking towards +X
|
||||||
|
blockPos,
|
||||||
|
world.getLookingAtPos(
|
||||||
|
new Vector3f(15f, 20.5f, 20.5f),
|
||||||
|
new Vector3f(1, 0, 0),
|
||||||
|
15
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Looking up into the void.
|
||||||
|
assertNull(world.getLookingAtPos(
|
||||||
|
new Vector3f(0, 30, 0),
|
||||||
|
new Vector3f(0, 1, 0),
|
||||||
|
10
|
||||||
|
));
|
||||||
|
|
||||||
|
// Looking straight down, but too far away.
|
||||||
|
assertNull(world.getLookingAtPos(
|
||||||
|
new Vector3f(0.5f, 20, 0.5f),
|
||||||
|
new Vector3f(0, -1, 0),
|
||||||
|
15
|
||||||
|
));
|
||||||
|
assertEquals( // Standing in the corner, looking into center of block.
|
||||||
|
blockPos,
|
||||||
|
world.getLookingAtPos(
|
||||||
|
new Vector3f(20f, 21f, 20f),
|
||||||
|
new Vector3f(1, -2, 1).normalize(),
|
||||||
|
15
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue