mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 11:17:05 -04:00
Add Frustum Culling.
This commit is contained in:
parent
e6659675b2
commit
faa018093f
@ -141,10 +141,10 @@ pub const BlockPalette = struct {
|
||||
try self.palette.append(try allocator.dupe(u8, "cubyz:air"));
|
||||
} else {
|
||||
var palette = try main.threadAllocator.alloc(?[]const u8, jsonObject.JsonObject.count());
|
||||
defer main.threadAllocator.free(palette);
|
||||
for(palette) |*val| {
|
||||
val.* = null;
|
||||
}
|
||||
defer main.threadAllocator.free(palette);
|
||||
var iterator = jsonObject.JsonObject.iterator();
|
||||
while(iterator.next()) |entry| {
|
||||
palette[entry.value_ptr.as(usize, std.math.maxInt(usize))] = entry.key_ptr.*;
|
||||
|
16
src/game.zig
16
src/game.zig
@ -8,25 +8,25 @@ const graphics = @import("graphics.zig");
|
||||
const Fog = graphics.Fog;
|
||||
|
||||
pub const camera = struct {
|
||||
var rotation: Vec3f = Vec3f{.x = 0, .y = 0, .z = 0};
|
||||
var direction: Vec3f = Vec3f{0, 0, 0};
|
||||
var rotation: Vec3f = Vec3f{.x=0, .y=0, .z=0};
|
||||
var direction: Vec3f = Vec3f{.x=0, .y=0, .z=0};
|
||||
pub var viewMatrix: Mat4f = Mat4f.identity();
|
||||
pub fn moveRotation(mouseX: f32, mouseY: f32) void {
|
||||
// Mouse movement along the x-axis rotates the image along the y-axis.
|
||||
rotation.x += mouseY;
|
||||
if(rotation.x > std.math.pi/2) {
|
||||
rotation.x = std.math.pi/2;
|
||||
} else if(rotation.x < -std.math.pi/2) {
|
||||
rotation.x = -std.math.pi/2;
|
||||
if(rotation.x > std.math.pi/2.0) {
|
||||
rotation.x = std.math.pi/2.0;
|
||||
} else if(rotation.x < -std.math.pi/2.0) {
|
||||
rotation.x = -std.math.pi/2.0;
|
||||
}
|
||||
// Mouse movement along the y-axis rotates the image along the x-axis.
|
||||
rotation.y += mouseX;
|
||||
|
||||
direction = Vec3f.rotateX(Vec3f{0, 0, -1}, rotation.x).rotateY(rotation.y);
|
||||
direction = Vec3f.rotateX(Vec3f{.x=0, .y=0, .z=-1}, rotation.x).rotateY(rotation.y);
|
||||
}
|
||||
|
||||
pub fn updateViewMatrix() void {
|
||||
viewMatrix = Mat4f.rotationY(rotation.y).mul(Mat4f.rotationX(rotation.x));
|
||||
viewMatrix = Mat4f.rotationX(rotation.x).mul(Mat4f.rotationY(rotation.y));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -7,6 +7,7 @@ const game = @import("game.zig");
|
||||
const graphics = @import("graphics.zig");
|
||||
const renderer = @import("renderer.zig");
|
||||
const network = @import("network.zig");
|
||||
const settings = @import("settings.zig");
|
||||
const utils = @import("utils.zig");
|
||||
|
||||
const Vec2f = @import("vec.zig").Vec2f;
|
||||
@ -61,7 +62,7 @@ pub const Window = struct {
|
||||
std.log.info("Framebuffer: {}, {}", .{newWidth, newHeight});
|
||||
width = @intCast(u31, newWidth);
|
||||
height = @intCast(u31, newHeight);
|
||||
renderer.updateViewport(width, height, 45);// TODO: Get fov from settings.
|
||||
renderer.updateViewport(width, height, settings.fov);
|
||||
}
|
||||
fn glDebugOutput(_: c_uint, typ: c_uint, _: c_uint, severity: c_uint, length: c_int, message: [*c]const u8, _: ?*const anyopaque) callconv(.C) void {
|
||||
if(typ == c.GL_DEBUG_TYPE_ERROR or typ == c.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR or typ == c.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR or typ == c.GL_DEBUG_TYPE_PORTABILITY or typ == c.GL_DEBUG_TYPE_PERFORMANCE) {
|
||||
@ -196,6 +197,7 @@ pub fn main() !void {
|
||||
std.log.err("Got opengl error: {}", .{err});
|
||||
}
|
||||
}
|
||||
game.camera.moveRotation(0.01, 0);
|
||||
c.glfwSwapBuffers(Window.window);
|
||||
c.glfwPollEvents();
|
||||
try renderer.RenderOctree.update(conn2, .{.x = 25, .y = 11, .z = -703}, 4, 2.0);
|
||||
|
@ -213,11 +213,8 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, directionalLight: Vec3f,
|
||||
// Meshes.cleanUp();
|
||||
game.camera.updateViewMatrix();
|
||||
|
||||
//TODO: // Uses FrustumCulling on the chunks.
|
||||
// Matrix4f frustumMatrix = new Matrix4f();
|
||||
// frustumMatrix.set(frustumProjectionMatrix);
|
||||
// frustumMatrix.mul(Camera.getViewMatrix());
|
||||
// frustumInt.set(frustumMatrix);
|
||||
// Uses FrustumCulling on the chunks.
|
||||
var frustum = Frustum.init(Vec3f{.x=0, .y=0, .z=0}, game.camera.viewMatrix, settings.fov, zFarLOD, main.Window.width, main.Window.height);
|
||||
|
||||
const time = @intCast(u32, std.time.milliTimestamp() & std.math.maxInt(u32));
|
||||
const waterFog = Fog{.active=true, .color=.{.x=0.0, .y=0.1, .z=0.2}, .density=0.1};
|
||||
@ -243,7 +240,7 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, directionalLight: Vec3f,
|
||||
// SimpleList<ReducedChunkMesh> visibleReduced = new SimpleList<ReducedChunkMesh>(new ReducedChunkMesh[64]);
|
||||
var meshes = std.ArrayList(*chunk.meshing.ChunkMesh).init(main.threadAllocator);
|
||||
defer meshes.deinit();
|
||||
try RenderOctree.getRenderChunks(playerPos, &meshes);
|
||||
try RenderOctree.getRenderChunks(playerPos, frustum, &meshes);
|
||||
// for (ChunkMesh mesh : Cubyz.chunkTree.getRenderChunks(frustumInt, x0, y0, z0)) {
|
||||
// if (mesh instanceof NormalChunkMesh) {
|
||||
// visibleChunks.add((NormalChunkMesh)mesh);
|
||||
@ -351,9 +348,6 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, directionalLight: Vec3f,
|
||||
//TODO EntityRenderer.renderNames(playerPosition);
|
||||
}
|
||||
|
||||
// private final Matrix4f frustumProjectionMatrix = new Matrix4f();
|
||||
// private final FrustumIntersection frustumInt = new FrustumIntersection();
|
||||
//
|
||||
// private float playerBobbing;
|
||||
// private boolean bobbingUp;
|
||||
//
|
||||
@ -395,6 +389,45 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, directionalLight: Vec3f,
|
||||
// }
|
||||
//}
|
||||
|
||||
pub const Frustum = struct {
|
||||
const Plane = struct {
|
||||
pos: Vec3f,
|
||||
norm: Vec3f,
|
||||
};
|
||||
planes: [5]Plane, // Who cares about the near plane anyways?
|
||||
|
||||
pub fn init(cameraPos: Vec3f, rotationMatrix: Mat4f, fovY: f32, _zFar: f32, width: u31, height: u31) Frustum {
|
||||
var invRotationMatrix = rotationMatrix.transpose();
|
||||
var cameraDir = Vec3f.xyz(invRotationMatrix.mulVec(Vec4f{.x=0, .y=0, .z=1, .w=1}));
|
||||
var cameraUp = Vec3f.xyz(invRotationMatrix.mulVec(Vec4f{.x=0, .y=1, .z=0, .w=1}));
|
||||
var cameraRight = Vec3f.xyz(invRotationMatrix.mulVec(Vec4f{.x=1, .y=0, .z=0, .w=1}));
|
||||
|
||||
const halfVSide = _zFar*std.math.tan(std.math.degreesToRadians(f32, fovY)*0.5);
|
||||
const halfHSide = halfVSide*@intToFloat(f32, width)/@intToFloat(f32, height);
|
||||
const frontMultFar = cameraDir.mulScalar(_zFar);
|
||||
|
||||
var self: Frustum = undefined;
|
||||
self.planes[0] = Plane{.pos = cameraPos.add(frontMultFar), .norm=cameraDir.mulScalar(-1)}; // far
|
||||
self.planes[1] = Plane{.pos = cameraPos, .norm=cameraUp.cross(frontMultFar.add(cameraRight.mulScalar(halfHSide)))}; // right
|
||||
self.planes[2] = Plane{.pos = cameraPos, .norm=frontMultFar.sub(cameraRight.mulScalar(halfHSide)).cross(cameraUp)}; // left
|
||||
self.planes[3] = Plane{.pos = cameraPos, .norm=cameraRight.cross(frontMultFar.sub(cameraUp.mulScalar(halfVSide)))}; // top
|
||||
self.planes[4] = Plane{.pos = cameraPos, .norm=frontMultFar.add(cameraUp.mulScalar(halfVSide)).cross(cameraRight)}; // bottom
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn testAAB(self: Frustum, pos: Vec3f, dim: Vec3f) bool {
|
||||
inline for(self.planes) |plane| {
|
||||
var dist: f32 = pos.sub(plane.pos).dot(plane.norm);
|
||||
// Find the most positive corner:
|
||||
dist += @maximum(0, dim.x*plane.norm.x);
|
||||
dist += @maximum(0, dim.y*plane.norm.y);
|
||||
dist += @maximum(0, dim.z*plane.norm.z);
|
||||
if(dist < 128) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
pub const RenderOctree = struct {
|
||||
pub var allocator: std.mem.Allocator = undefined;
|
||||
var gpa: std.heap.GeneralPurposeAllocator(.{}) = undefined;
|
||||
@ -490,17 +523,25 @@ pub const RenderOctree = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn getChunks(self: *Node, playerPos: Vec3d, meshes: *std.ArrayList(*chunk.meshing.ChunkMesh)) !void {
|
||||
fn getChunks(self: *Node, playerPos: Vec3d, frustum: Frustum, meshes: *std.ArrayList(*chunk.meshing.ChunkMesh)) !void {
|
||||
self.mutex.lock();
|
||||
defer self.mutex.unlock();
|
||||
if(self.children) |children| {
|
||||
for(children) |child| {
|
||||
try child.getChunks(playerPos, meshes);
|
||||
try child.getChunks(playerPos, frustum, meshes);
|
||||
}
|
||||
} else {
|
||||
// TODO: if(testFrustum(frustumInt, x0, y0, z0)) {
|
||||
if(frustum.testAAB(Vec3f{
|
||||
.x = @floatCast(f32, @intToFloat(f64, self.mesh.pos.wx) - playerPos.x),
|
||||
.y = @floatCast(f32, @intToFloat(f64, self.mesh.pos.wy) - playerPos.y),
|
||||
.z = @floatCast(f32, @intToFloat(f64, self.mesh.pos.wz) - playerPos.z),
|
||||
}, Vec3f{
|
||||
.x = @intToFloat(f32, self.size),
|
||||
.y = @intToFloat(f32, self.size),
|
||||
.z = @intToFloat(f32, self.size),
|
||||
})) {
|
||||
try meshes.append(&self.mesh);
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO:
|
||||
@ -693,12 +734,12 @@ pub const RenderOctree = struct {
|
||||
try updatableList.append(mesh);
|
||||
}
|
||||
|
||||
pub fn getRenderChunks(playerPos: Vec3d, meshes: *std.ArrayList(*chunk.meshing.ChunkMesh)) !void {
|
||||
pub fn getRenderChunks(playerPos: Vec3d, frustum: Frustum, meshes: *std.ArrayList(*chunk.meshing.ChunkMesh)) !void {
|
||||
mutex.lock();
|
||||
defer mutex.unlock();
|
||||
var iterator = roots.valueIterator();
|
||||
while(iterator.next()) |node| {
|
||||
try node.*.getChunks(playerPos, meshes);
|
||||
try node.*.getChunks(playerPos, frustum, meshes);
|
||||
}
|
||||
}
|
||||
// TODO:
|
||||
|
@ -5,4 +5,8 @@ pub const connectionTimeout = 60000;
|
||||
|
||||
pub const version = "0.12.0";
|
||||
|
||||
pub const highestLOD: u5 = 5;
|
||||
pub const highestLOD: u5 = 5;
|
||||
|
||||
|
||||
|
||||
pub var fov: f32 = 45;
|
36
src/vec.zig
36
src/vec.zig
@ -39,6 +39,18 @@ pub const Vec3f = extern struct {// This one gets a bit of extra functionality f
|
||||
.z = self.z,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn cross(self: @This(), other: @This()) @This() {
|
||||
return @This() {
|
||||
.x = self.y*other.z - self.z*other.y,
|
||||
.y = self.z*other.x - self.x*other.z,
|
||||
.z = self.x*other.y - self.y*other.x,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn xyz(self: Vec4f) Vec3f {
|
||||
return Vec3f{.x=self.x, .y=self.y, .z=self.z};
|
||||
}
|
||||
};
|
||||
pub const Vec3d = GenericVector3(f64);
|
||||
pub const Vec4i = GenericVector4(i32);
|
||||
@ -71,6 +83,14 @@ fn GenericVectorMath(comptime Vec: type, comptime T: type) type {
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn mulScalar(self: Vec, scalar: T) Vec {
|
||||
var result: Vec = undefined;
|
||||
inline for(@typeInfo(Vec).Struct.fields) |field| {
|
||||
@field(result, field.name) = @field(self, field.name) * scalar;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn div(self: Vec, other: Vec) Vec {
|
||||
if(@typeInfo(T) == .Float) {
|
||||
var result: Vec = undefined;
|
||||
@ -117,6 +137,12 @@ fn GenericVectorMath(comptime Vec: type, comptime T: type) type {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mulEqualScalar(self: *Vec, scalar: T) Vec {
|
||||
inline for(@typeInfo(Vec).Struct.fields) |field| {
|
||||
@field(self, field.name) *= scalar;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn divEqual(self: *Vec, other: Vec) void {
|
||||
if(@typeInfo(T) == .Float) {
|
||||
inline for(@typeInfo(Vec).Struct.fields) |field| {
|
||||
@ -251,4 +277,14 @@ pub const Mat4f = struct {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn mulVec(self: Mat4f, vec: Vec4f) Vec4f {
|
||||
var transposeSelf = self.transpose();
|
||||
var result: Vec4f = undefined;
|
||||
result.x = transposeSelf.columns[0].dot(vec);
|
||||
result.y = transposeSelf.columns[1].dot(vec);
|
||||
result.z = transposeSelf.columns[2].dot(vec);
|
||||
result.w = transposeSelf.columns[3].dot(vec);
|
||||
return result;
|
||||
}
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user