mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-04 03:37:59 -04:00
Switch to SIMD vectors.
SIMD vectors are probably faster and support operators.
This commit is contained in:
parent
cbf784d1e9
commit
b3ea5d517c
@ -86,9 +86,9 @@ pub const ChunkPosition = struct {
|
||||
|
||||
pub fn getMinDistanceSquared(self: ChunkPosition, playerPosition: Vec3d) f64 {
|
||||
var halfWidth = @intToFloat(f64, self.voxelSize*@divExact(chunkSize, 2));
|
||||
var dx = @fabs(@intToFloat(f64, self.wx) + halfWidth - playerPosition.x);
|
||||
var dy = @fabs(@intToFloat(f64, self.wy) + halfWidth - playerPosition.y);
|
||||
var dz = @fabs(@intToFloat(f64, self.wz) + halfWidth - playerPosition.z);
|
||||
var dx = @fabs(@intToFloat(f64, self.wx) + halfWidth - playerPosition[0]);
|
||||
var dy = @fabs(@intToFloat(f64, self.wy) + halfWidth - playerPosition[1]);
|
||||
var dz = @fabs(@intToFloat(f64, self.wz) + halfWidth - playerPosition[2]);
|
||||
dx = @max(0, dx - halfWidth);
|
||||
dy = @max(0, dy - halfWidth);
|
||||
dz = @max(0, dz - halfWidth);
|
||||
@ -440,7 +440,7 @@ pub const meshing = struct {
|
||||
|
||||
c.glUniformMatrix4fv(uniforms.viewMatrix, 1, c.GL_FALSE, @ptrCast([*c]f32, &game.camera.viewMatrix));
|
||||
|
||||
c.glUniform3f(uniforms.ambientLight, ambient.x, ambient.y, ambient.z);
|
||||
c.glUniform3f(uniforms.ambientLight, ambient[0], ambient[1], ambient[2]);
|
||||
|
||||
c.glUniform1i(uniforms.time, @bitCast(i32, time));
|
||||
|
||||
@ -837,9 +837,9 @@ pub const meshing = struct {
|
||||
if(self.vertexCount == 0) return;
|
||||
c.glUniform3f(
|
||||
uniforms.modelPosition,
|
||||
@floatCast(f32, @intToFloat(f64, self.pos.wx) - playerPosition.x),
|
||||
@floatCast(f32, @intToFloat(f64, self.pos.wy) - playerPosition.y),
|
||||
@floatCast(f32, @intToFloat(f64, self.pos.wz) - playerPosition.z)
|
||||
@floatCast(f32, @intToFloat(f64, self.pos.wx) - playerPosition[0]),
|
||||
@floatCast(f32, @intToFloat(f64, self.pos.wy) - playerPosition[1]),
|
||||
@floatCast(f32, @intToFloat(f64, self.pos.wz) - playerPosition[2])
|
||||
);
|
||||
c.glUniform1i(uniforms.visibilityMask, self.visibilityMask);
|
||||
self.faceData.bind(3);
|
||||
|
@ -31,18 +31,18 @@ pub const ClientEntity = struct {
|
||||
|
||||
pub fn init(self: *ClientEntity) void {
|
||||
const pos = [_]f64 {
|
||||
self.pos.x,
|
||||
self.pos.y,
|
||||
self.pos.z,
|
||||
@floatCast(f64, self.rot.x),
|
||||
@floatCast(f64, self.rot.y),
|
||||
@floatCast(f64, self.rot.z),
|
||||
self.pos[0],
|
||||
self.pos[1],
|
||||
self.pos[2],
|
||||
@floatCast(f64, self.rot[0]),
|
||||
@floatCast(f64, self.rot[1]),
|
||||
@floatCast(f64, self.rot[2]),
|
||||
};
|
||||
self.interpolatedValues.initPosition(&pos);
|
||||
}
|
||||
|
||||
pub fn getRenderPosition(self: *const ClientEntity) Vec3d {
|
||||
return Vec3d{.x = self.pos.x, .y = self.pos.y + self.height/2, .z = self.pos.z};
|
||||
return Vec3d{self.pos[0], self.pos[1] + self.height/2, self.pos[2]};
|
||||
}
|
||||
|
||||
pub fn updatePosition(self: *ClientEntity, pos: *const [6]f64, vel: *const [6]f64, time: i16) void {
|
||||
@ -51,12 +51,12 @@ pub const ClientEntity = struct {
|
||||
|
||||
pub fn update(self: *ClientEntity, time: i16, lastTime: i16) void {
|
||||
self.interpolatedValues.update(time, lastTime);
|
||||
self.pos.x = self.interpolatedValues.outPos[0];
|
||||
self.pos.y = self.interpolatedValues.outPos[1];
|
||||
self.pos.z = self.interpolatedValues.outPos[2];
|
||||
self.rot.x = @floatCast(f32, self.interpolatedValues.outPos[3]);
|
||||
self.rot.y = @floatCast(f32, self.interpolatedValues.outPos[4]);
|
||||
self.rot.z = @floatCast(f32, self.interpolatedValues.outPos[5]);
|
||||
self.pos[0] = self.interpolatedValues.outPos[0];
|
||||
self.pos[1] = self.interpolatedValues.outPos[1];
|
||||
self.pos[2] = self.interpolatedValues.outPos[2];
|
||||
self.rot[0] = @floatCast(f32, self.interpolatedValues.outPos[3]);
|
||||
self.rot[1] = @floatCast(f32, self.interpolatedValues.outPos[4]);
|
||||
self.rot[2] = @floatCast(f32, self.interpolatedValues.outPos[5]);
|
||||
}
|
||||
};
|
||||
|
||||
@ -110,22 +110,22 @@ pub const ClientEntityManager = struct {
|
||||
|
||||
for(entities.items) |ent| {
|
||||
if(ent.id == game.Player.id or ent.name.len == 0) continue; // don't render local player
|
||||
const pos3d: Vec3d = ent.getRenderPosition().sub(playerPos);
|
||||
const pos3d: Vec3d = ent.getRenderPosition() - playerPos;
|
||||
const pos4f: Vec4f = Vec4f{
|
||||
.x = @floatCast(f32, pos3d.x),
|
||||
.y = @floatCast(f32, pos3d.y + 1.5),
|
||||
.z = @floatCast(f32, pos3d.z),
|
||||
.w = 1,
|
||||
@floatCast(f32, pos3d[0]),
|
||||
@floatCast(f32, pos3d[1] + 1.5),
|
||||
@floatCast(f32, pos3d[2]),
|
||||
1,
|
||||
};
|
||||
|
||||
const rotatedPos = game.camera.viewMatrix.mulVec(pos4f);
|
||||
const projectedPos = projMatrix.mulVec(rotatedPos);
|
||||
if(projectedPos.z < 0) continue;
|
||||
const xCenter = (1 + projectedPos.x/projectedPos.w)*@intToFloat(f32, main.Window.width/2);
|
||||
const yCenter = (1 - projectedPos.y/projectedPos.w)*@intToFloat(f32, main.Window.height/2);
|
||||
if(projectedPos[2] < 0) continue;
|
||||
const xCenter = (1 + projectedPos[0]/projectedPos[3])*@intToFloat(f32, main.Window.width/2);
|
||||
const yCenter = (1 - projectedPos[1]/projectedPos[3])*@intToFloat(f32, main.Window.height/2);
|
||||
|
||||
graphics.Draw.setColor(0xffff00ff);
|
||||
graphics.Draw.rect(.{.x=xCenter, .y=yCenter}, .{.x=100, .y=20}); // TODO: Text rendering.
|
||||
graphics.Draw.rect(.{xCenter, yCenter}, .{100, 20}); // TODO: Text rendering.
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,16 +150,16 @@ pub const ClientEntityManager = struct {
|
||||
c.glUniform1i(uniforms.materialHasTexture, c.GL_TRUE);
|
||||
c.glUniform1i(uniforms.light, @bitCast(c_int, @as(u32, 0xffffffff))); // TODO: Lighting
|
||||
|
||||
const pos: Vec3d = ent.getRenderPosition().sub(playerPos);
|
||||
const pos: Vec3d = ent.getRenderPosition() - playerPos;
|
||||
const modelMatrix = (
|
||||
Mat4f.identity() // TODO: .scale(scale);
|
||||
.mul(Mat4f.rotationZ(-ent.rot.z))
|
||||
.mul(Mat4f.rotationY(-ent.rot.y))
|
||||
.mul(Mat4f.rotationX(-ent.rot.x))
|
||||
.mul(Mat4f.rotationZ(-ent.rot[2]))
|
||||
.mul(Mat4f.rotationY(-ent.rot[1]))
|
||||
.mul(Mat4f.rotationX(-ent.rot[0]))
|
||||
.mul(Mat4f.translation(Vec3f{
|
||||
.x = @floatCast(f32, pos.x),
|
||||
.y = @floatCast(f32, pos.y),
|
||||
.z = @floatCast(f32, pos.z),
|
||||
@floatCast(f32, pos[0]),
|
||||
@floatCast(f32, pos[1]),
|
||||
@floatCast(f32, pos[2]),
|
||||
}))
|
||||
);
|
||||
const modelViewMatrix = modelMatrix.mul(game.camera.viewMatrix);
|
||||
|
90
src/game.zig
90
src/game.zig
@ -19,31 +19,31 @@ const Fog = graphics.Fog;
|
||||
const renderer = @import("renderer.zig");
|
||||
|
||||
pub const camera = struct {
|
||||
pub var rotation: Vec3f = Vec3f{.x=0, .y=0, .z=0};
|
||||
pub var direction: Vec3f = Vec3f{.x=0, .y=0, .z=0};
|
||||
pub var rotation: Vec3f = Vec3f{0, 0, 0};
|
||||
pub var direction: Vec3f = Vec3f{0, 0, 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.0) {
|
||||
rotation.x = std.math.pi/2.0;
|
||||
} else if(rotation.x < -std.math.pi/2.0) {
|
||||
rotation.x = -std.math.pi/2.0;
|
||||
rotation[0] += mouseY;
|
||||
if(rotation[0] > std.math.pi/2.0) {
|
||||
rotation[0] = std.math.pi/2.0;
|
||||
} else if(rotation[0] < -std.math.pi/2.0) {
|
||||
rotation[0] = -std.math.pi/2.0;
|
||||
}
|
||||
// Mouse movement along the y-axis rotates the image along the x-axis.
|
||||
rotation.y += mouseX;
|
||||
rotation[1] += mouseX;
|
||||
|
||||
direction = Vec3f.rotateX(Vec3f{.x=0, .y=0, .z=-1}, -rotation.x).rotateY(-rotation.y);
|
||||
direction = vec.rotateY(vec.rotateX(Vec3f{0, 0, -1}, -rotation[0]), -rotation[1]);
|
||||
}
|
||||
|
||||
pub fn updateViewMatrix() void {
|
||||
viewMatrix = Mat4f.rotationX(rotation.x).mul(Mat4f.rotationY(rotation.y));
|
||||
viewMatrix = Mat4f.rotationX(rotation[0]).mul(Mat4f.rotationY(rotation[1]));
|
||||
}
|
||||
};
|
||||
|
||||
pub const Player = struct {
|
||||
var pos: Vec3d = Vec3d{.x=0, .y=0, .z=0};
|
||||
var vel: Vec3d = Vec3d{.x=0, .y=0, .z=0};
|
||||
var pos: Vec3d = Vec3d{0, 0, 0};
|
||||
var vel: Vec3d = Vec3d{0, 0, 0};
|
||||
pub var id: u32 = 0;
|
||||
pub var isFlying: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(true);
|
||||
var mutex: std.Thread.Mutex = std.Thread.Mutex{};
|
||||
@ -73,7 +73,7 @@ pub const World = struct {
|
||||
conn: *Connection,
|
||||
manager: *ConnectionManager,
|
||||
ambientLight: f32 = 0,
|
||||
clearColor: Vec4f = Vec4f{.x=0, .y=0, .z=0, .w=1},
|
||||
clearColor: Vec4f = Vec4f{0, 0, 0, 1},
|
||||
name: []const u8,
|
||||
milliTime: i64,
|
||||
gameTime: std.atomic.Atomic(i64) = std.atomic.Atomic(i64).init(0),
|
||||
@ -106,9 +106,9 @@ pub const World = struct {
|
||||
// TODO: Consider using a per-world allocator.
|
||||
self.blockPalette = try assets.BlockPalette.init(renderer.RenderStructure.allocator, jsonObject.getChild("blockPalette"));
|
||||
var jsonSpawn = jsonObject.getChild("spawn");
|
||||
self.spawn.x = jsonSpawn.get(f32, "x", 0);
|
||||
self.spawn.y = jsonSpawn.get(f32, "y", 0);
|
||||
self.spawn.z = jsonSpawn.get(f32, "z", 0);
|
||||
self.spawn[0] = jsonSpawn.get(f32, "x", 0);
|
||||
self.spawn[1] = jsonSpawn.get(f32, "y", 0);
|
||||
self.spawn[2] = jsonSpawn.get(f32, "z", 0);
|
||||
|
||||
// TODO:
|
||||
// if(Server.world != null) {
|
||||
@ -140,34 +140,34 @@ pub const World = struct {
|
||||
var dayTime = std.math.absInt(@mod(self.gameTime.load(.Monotonic), dayCycle) -% dayCycle/2) catch 0;
|
||||
if(dayTime < dayCycle/4 - dayCycle/16) {
|
||||
self.ambientLight = 0.1;
|
||||
self.clearColor.x = 0;
|
||||
self.clearColor.y = 0;
|
||||
self.clearColor.z = 0;
|
||||
self.clearColor[0] = 0;
|
||||
self.clearColor[1] = 0;
|
||||
self.clearColor[2] = 0;
|
||||
} else if(dayTime > dayCycle/4 + dayCycle/16) {
|
||||
self.ambientLight = 1;
|
||||
self.clearColor.x = 0.8;
|
||||
self.clearColor.y = 0.8;
|
||||
self.clearColor.z = 1.0;
|
||||
self.clearColor[0] = 0.8;
|
||||
self.clearColor[1] = 0.8;
|
||||
self.clearColor[2] = 1.0;
|
||||
} else {
|
||||
// b:
|
||||
if(dayTime > dayCycle/4) {
|
||||
self.clearColor.z = @intToFloat(f32, dayTime - dayCycle/4)/@intToFloat(f32, dayCycle/16);
|
||||
self.clearColor[2] = @intToFloat(f32, dayTime - dayCycle/4)/@intToFloat(f32, dayCycle/16);
|
||||
} else {
|
||||
self.clearColor.z = 0;
|
||||
self.clearColor[2] = 0;
|
||||
}
|
||||
// g:
|
||||
if(dayTime > dayCycle/4 + dayCycle/32) {
|
||||
self.clearColor.y = 0.8;
|
||||
self.clearColor[1] = 0.8;
|
||||
} else if(dayTime > dayCycle/4 - dayCycle/32) {
|
||||
self.clearColor.y = 0.8 + 0.8*@intToFloat(f32, dayTime - dayCycle/4 - dayCycle/32)/@intToFloat(f32, dayCycle/16);
|
||||
self.clearColor[1] = 0.8 + 0.8*@intToFloat(f32, dayTime - dayCycle/4 - dayCycle/32)/@intToFloat(f32, dayCycle/16);
|
||||
} else {
|
||||
self.clearColor.y = 0;
|
||||
self.clearColor[1] = 0;
|
||||
}
|
||||
// r:
|
||||
if(dayTime > dayCycle/4) {
|
||||
self.clearColor.x = 0.8;
|
||||
self.clearColor[0] = 0.8;
|
||||
} else {
|
||||
self.clearColor.x = 0.8 + 0.8*@intToFloat(f32, dayTime - dayCycle/4)/@intToFloat(f32, dayCycle/16);
|
||||
self.clearColor[0] = 0.8 + 0.8*@intToFloat(f32, dayTime - dayCycle/4)/@intToFloat(f32, dayCycle/16);
|
||||
}
|
||||
dayTime -= dayCycle/4;
|
||||
dayTime <<= 3;
|
||||
@ -271,50 +271,50 @@ pub var world: ?*World = &testWorld;
|
||||
pub var projectionMatrix: Mat4f = Mat4f.identity();
|
||||
pub var lodProjectionMatrix: Mat4f = Mat4f.identity();
|
||||
|
||||
pub var fog = Fog{.active = true, .color=.{.x=0, .y=1, .z=0.5}, .density=1.0/15.0/256.0};
|
||||
pub var fog = Fog{.active = true, .color=.{0, 1, 0.5}, .density=1.0/15.0/256.0};
|
||||
|
||||
|
||||
pub fn update(deltaTime: f64) !void {
|
||||
var movement = Vec3d{.x=0, .y=0, .z=0};
|
||||
var forward = Vec3d.rotateY(Vec3d{.x=0, .y=0, .z=-1}, -camera.rotation.y);
|
||||
var right = Vec3d{.x=forward.z, .y=0, .z=-forward.x};
|
||||
var movement = Vec3d{0, 0, 0};
|
||||
var forward = vec.rotateY(Vec3d{0, 0, -1}, -camera.rotation[1]);
|
||||
var right = Vec3d{forward[2], 0, -forward[0]};
|
||||
if(keyboard.forward.pressed) {
|
||||
if(keyboard.sprint.pressed) {
|
||||
if(Player.isFlying.load(.Monotonic)) {
|
||||
movement.addEqual(forward.mulScalar(128));
|
||||
movement += forward*@splat(3, @as(f64, 128));
|
||||
} else {
|
||||
movement.addEqual(forward.mulScalar(8));
|
||||
movement += forward*@splat(3, @as(f64, 8));
|
||||
}
|
||||
} else {
|
||||
movement.addEqual(forward.mulScalar(4));
|
||||
movement += forward*@splat(3, @as(f64, 4));
|
||||
}
|
||||
}
|
||||
if(keyboard.backward.pressed) {
|
||||
movement.addEqual(forward.mulScalar(-4));
|
||||
movement += forward*@splat(3, @as(f64, -4));
|
||||
}
|
||||
if(keyboard.left.pressed) {
|
||||
movement.addEqual(right.mulScalar(4));
|
||||
movement += right*@splat(3, @as(f64, 4));
|
||||
}
|
||||
if(keyboard.right.pressed) {
|
||||
movement.addEqual(right.mulScalar(-4));
|
||||
movement += right*@splat(3, @as(f64, -4));
|
||||
}
|
||||
if(keyboard.jump.pressed) {
|
||||
if(Player.isFlying.load(.Monotonic)) {
|
||||
if(keyboard.sprint.pressed) {
|
||||
movement.y = 59.45;
|
||||
movement[1] = 59.45;
|
||||
} else {
|
||||
movement.y = 5.45;
|
||||
movement[1] = 5.45;
|
||||
}
|
||||
} else { // TODO: if (Cubyz.player.isOnGround())
|
||||
movement.y = 5.45;
|
||||
movement[1] = 5.45;
|
||||
}
|
||||
}
|
||||
if(keyboard.fall.pressed) {
|
||||
if(Player.isFlying.load(.Monotonic)) {
|
||||
if(keyboard.sprint.pressed) {
|
||||
movement.y = -59.45;
|
||||
movement[1] = -59.45;
|
||||
} else {
|
||||
movement.y = -5.45;
|
||||
movement[1] = -5.45;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -322,7 +322,7 @@ pub fn update(deltaTime: f64) !void {
|
||||
{
|
||||
Player.mutex.lock();
|
||||
defer Player.mutex.unlock();
|
||||
Player.pos.addEqual(movement.mulScalar(deltaTime));
|
||||
Player.pos += movement*@splat(3, deltaTime);
|
||||
}
|
||||
try world.?.update();
|
||||
}
|
@ -111,8 +111,8 @@ pub const Draw = struct {
|
||||
rectShader.bind();
|
||||
|
||||
c.glUniform2f(rectUniforms.screen, @intToFloat(f32, Window.width), @intToFloat(f32, Window.height));
|
||||
c.glUniform2f(rectUniforms.start, pos.x, pos.y);
|
||||
c.glUniform2f(rectUniforms.size, dim.x, dim.y);
|
||||
c.glUniform2f(rectUniforms.start, pos[0], pos[1]);
|
||||
c.glUniform2f(rectUniforms.size, dim[0], dim[1]);
|
||||
c.glUniform1i(rectUniforms.rectColor, color);
|
||||
|
||||
c.glBindVertexArray(rectVAO);
|
||||
@ -158,8 +158,8 @@ pub const Draw = struct {
|
||||
lineShader.bind();
|
||||
|
||||
c.glUniform2f(lineUniforms.screen, @intToFloat(f32, Window.width), @intToFloat(f32, Window.height));
|
||||
c.glUniform2f(lineUniforms.start, pos1.x, pos1.y);
|
||||
c.glUniform2f(lineUniforms.direction, pos2.x - pos1.x, pos2.y - pos1.y);
|
||||
c.glUniform2f(lineUniforms.start, pos1[0], pos1[1]);
|
||||
c.glUniform2f(lineUniforms.direction, pos2[0] - pos1[0], pos2[1] - pos1[1]);
|
||||
c.glUniform1i(lineUniforms.lineColor, color);
|
||||
|
||||
c.glBindVertexArray(lineVAO);
|
||||
@ -198,8 +198,8 @@ pub const Draw = struct {
|
||||
lineShader.bind();
|
||||
|
||||
c.glUniform2f(lineUniforms.screen, @intToFloat(f32, Window.width), @intToFloat(f32, Window.height));
|
||||
c.glUniform2f(lineUniforms.start, pos.x, pos.y); // Move the coordinates, so they are in the center of a pixel.
|
||||
c.glUniform2f(lineUniforms.direction, dim.x - 1, dim.y - 1); // The height is a lot smaller because the inner edge of the rect is drawn.
|
||||
c.glUniform2f(lineUniforms.start, pos[0], pos[1]); // Move the coordinates, so they are in the center of a pixel.
|
||||
c.glUniform2f(lineUniforms.direction, dim[0] - 1, dim[1] - 1); // The height is a lot smaller because the inner edge of the rect is drawn.
|
||||
c.glUniform1i(lineUniforms.lineColor, color);
|
||||
|
||||
c.glBindVertexArray(lineVAO);
|
||||
@ -247,7 +247,7 @@ pub const Draw = struct {
|
||||
circleShader.bind();
|
||||
|
||||
c.glUniform2f(circleUniforms.screen, @intToFloat(f32, Window.width), @intToFloat(f32, Window.height));
|
||||
c.glUniform2f(circleUniforms.center, center.x, center.y); // Move the coordinates, so they are in the center of a pixel.
|
||||
c.glUniform2f(circleUniforms.center, center[0], center[1]); // Move the coordinates, so they are in the center of a pixel.
|
||||
c.glUniform1f(circleUniforms.radius, radius); // The height is a lot smaller because the inner edge of the rect is drawn.
|
||||
c.glUniform1i(circleUniforms.circleColor, color);
|
||||
|
||||
@ -280,8 +280,8 @@ pub const Draw = struct {
|
||||
imageShader.bind();
|
||||
|
||||
c.glUniform2f(imageUniforms.screen, @intToFloat(f32, Window.width), @intToFloat(f32, Window.height));
|
||||
c.glUniform2f(imageUniforms.start, pos.x, pos.y);
|
||||
c.glUniform2f(imageUniforms.size, dim.x, dim.y);
|
||||
c.glUniform2f(imageUniforms.start, pos[0], pos[1]);
|
||||
c.glUniform2f(imageUniforms.size, dim[0], dim[1]);
|
||||
c.glUniform1i(imageUniforms.color, color);
|
||||
|
||||
c.glBindVertexArray(rectVAO);
|
||||
|
20
src/main.zig
20
src/main.zig
@ -104,25 +104,25 @@ pub const Window = struct {
|
||||
}
|
||||
// Mouse deltas are averaged over multiple frames using a circular buffer:
|
||||
const deltasLen: u2 = 3;
|
||||
var deltas: [deltasLen]Vec2f = [_]Vec2f{Vec2f{.x=0, .y=0}} ** 3;
|
||||
var deltas: [deltasLen]Vec2f = [_]Vec2f{Vec2f{0, 0}} ** 3;
|
||||
var deltaBufferPosition: u2 = 0;
|
||||
var currentPos: Vec2f = Vec2f{.x=0, .y=0};
|
||||
var currentPos: Vec2f = Vec2f{0, 0};
|
||||
var ignoreDataAfterRecentGrab: bool = true;
|
||||
fn cursorPosition(_: ?*c.GLFWwindow, x: f64, y: f64) callconv(.C) void {
|
||||
const newPos = Vec2f {
|
||||
.x = @floatCast(f32, x),
|
||||
.y = @floatCast(f32, y),
|
||||
@floatCast(f32, x),
|
||||
@floatCast(f32, y),
|
||||
};
|
||||
if(grabbed and !ignoreDataAfterRecentGrab) {
|
||||
deltas[deltaBufferPosition].addEqual(newPos.sub(currentPos).mulScalar(settings.mouseSensitivity));
|
||||
var averagedDelta: Vec2f = Vec2f{.x=0, .y=0};
|
||||
deltas[deltaBufferPosition] += (newPos - currentPos)*@splat(2, settings.mouseSensitivity);
|
||||
var averagedDelta: Vec2f = Vec2f{0, 0};
|
||||
for(deltas) |delta| {
|
||||
averagedDelta.addEqual(delta);
|
||||
averagedDelta += delta;
|
||||
}
|
||||
averagedDelta.divEqualScalar(deltasLen);
|
||||
game.camera.moveRotation(averagedDelta.x*0.0089, averagedDelta.y*0.0089);
|
||||
averagedDelta /= @splat(2, @as(f32, deltasLen));
|
||||
game.camera.moveRotation(averagedDelta[0]*0.0089, averagedDelta[1]*0.0089);
|
||||
deltaBufferPosition = (deltaBufferPosition + 1)%deltasLen;
|
||||
deltas[deltaBufferPosition] = Vec2f{.x=0, .y=0};
|
||||
deltas[deltaBufferPosition] = Vec2f{0, 0};
|
||||
}
|
||||
ignoreDataAfterRecentGrab = false;
|
||||
currentPos = newPos;
|
||||
|
@ -763,15 +763,15 @@ pub const Protocols: struct {
|
||||
}
|
||||
lastPositionSent = time;
|
||||
var data: [62]u8 = undefined;
|
||||
std.mem.writeIntBig(u64, data[0..8], @bitCast(u64, playerPos.x));
|
||||
std.mem.writeIntBig(u64, data[8..16], @bitCast(u64, playerPos.y));
|
||||
std.mem.writeIntBig(u64, data[16..24], @bitCast(u64, playerPos.z));
|
||||
std.mem.writeIntBig(u64, data[24..32], @bitCast(u64, playerVel.x));
|
||||
std.mem.writeIntBig(u64, data[32..40], @bitCast(u64, playerVel.y));
|
||||
std.mem.writeIntBig(u64, data[40..48], @bitCast(u64, playerVel.z));
|
||||
std.mem.writeIntBig(u32, data[48..52], @bitCast(u32, game.camera.rotation.x));
|
||||
std.mem.writeIntBig(u32, data[52..56], @bitCast(u32, game.camera.rotation.y));
|
||||
std.mem.writeIntBig(u32, data[56..60], @bitCast(u32, game.camera.rotation.z));
|
||||
std.mem.writeIntBig(u64, data[0..8], @bitCast(u64, playerPos[0]));
|
||||
std.mem.writeIntBig(u64, data[8..16], @bitCast(u64, playerPos[1]));
|
||||
std.mem.writeIntBig(u64, data[16..24], @bitCast(u64, playerPos[2]));
|
||||
std.mem.writeIntBig(u64, data[24..32], @bitCast(u64, playerVel[0]));
|
||||
std.mem.writeIntBig(u64, data[32..40], @bitCast(u64, playerVel[1]));
|
||||
std.mem.writeIntBig(u64, data[40..48], @bitCast(u64, playerVel[2]));
|
||||
std.mem.writeIntBig(u32, data[48..52], @bitCast(u32, game.camera.rotation[0]));
|
||||
std.mem.writeIntBig(u32, data[52..56], @bitCast(u32, game.camera.rotation[1]));
|
||||
std.mem.writeIntBig(u32, data[56..60], @bitCast(u32, game.camera.rotation[2]));
|
||||
std.mem.writeIntBig(u16, data[60..62], time);
|
||||
try conn.sendUnimportant(id, &data);
|
||||
}
|
||||
@ -993,9 +993,9 @@ pub const Protocols: struct {
|
||||
},
|
||||
type_teleport => {
|
||||
game.Player.setPosBlocking(Vec3d{
|
||||
.x = @bitCast(f64, std.mem.readIntBig(u64, data[1..9])),
|
||||
.y = @bitCast(f64, std.mem.readIntBig(u64, data[9..17])),
|
||||
.z = @bitCast(f64, std.mem.readIntBig(u64, data[17..25])),
|
||||
@bitCast(f64, std.mem.readIntBig(u64, data[1..9])),
|
||||
@bitCast(f64, std.mem.readIntBig(u64, data[9..17])),
|
||||
@bitCast(f64, std.mem.readIntBig(u64, data[17..25])),
|
||||
});
|
||||
},
|
||||
type_cure => {
|
||||
@ -1114,9 +1114,9 @@ pub const Protocols: struct {
|
||||
pub fn sendTPCoordinates(conn: *Connection, pos: Vec3d) !void {
|
||||
var data: [1+24]u8 = undefined;
|
||||
data[0] = type_teleport;
|
||||
std.mem.writeIntBig(u64, data[1..9], @bitCast(u64, pos.x));
|
||||
std.mem.writeIntBig(u64, data[9..17], @bitCast(u64, pos.y));
|
||||
std.mem.writeIntBig(u64, data[17..25], @bitCast(u64, pos.z));
|
||||
std.mem.writeIntBig(u64, data[1..9], @bitCast(u64, pos[0]));
|
||||
std.mem.writeIntBig(u64, data[9..17], @bitCast(u64, pos[1]));
|
||||
std.mem.writeIntBig(u64, data[17..25], @bitCast(u64, pos[2]));
|
||||
try conn.sendImportant(id, &data);
|
||||
}
|
||||
|
||||
|
116
src/renderer.zig
116
src/renderer.zig
@ -132,7 +132,7 @@ const buffers = struct {
|
||||
|
||||
fn clearAndBind(clearColor: Vec4f) void {
|
||||
c.glBindFramebuffer(c.GL_FRAMEBUFFER, buffer);
|
||||
c.glClearColor(clearColor.x, clearColor.y, clearColor.z, 1);
|
||||
c.glClearColor(clearColor[0], clearColor[1], clearColor[2], 1);
|
||||
c.glClear(c.GL_DEPTH_BUFFER_BIT | c.GL_STENCIL_BUFFER_BIT | c.GL_COLOR_BUFFER_BIT);
|
||||
// Clears the position separately to prevent issues with default value.
|
||||
const positionClearColor = [_]f32 {0, 0, 6.55e4, 1}; // z value corresponds to the highest 16-bit float value.
|
||||
@ -182,15 +182,15 @@ pub fn render(playerPosition: Vec3d) !void {
|
||||
if(game.world) |world| {
|
||||
// // TODO: Handle colors and sun position in the world.
|
||||
var ambient: Vec3f = undefined;
|
||||
ambient.x = @max(0.1, world.ambientLight);
|
||||
ambient.y = @max(0.1, world.ambientLight);
|
||||
ambient.z = @max(0.1, world.ambientLight);
|
||||
var skyColor = Vec3f.xyz(world.clearColor);
|
||||
ambient[0] = @max(0.1, world.ambientLight);
|
||||
ambient[1] = @max(0.1, world.ambientLight);
|
||||
ambient[2] = @max(0.1, world.ambientLight);
|
||||
var skyColor = vec.xyz(world.clearColor);
|
||||
game.fog.color = skyColor;
|
||||
// TODO:
|
||||
// Cubyz.fog.setActive(ClientSettings.FOG_COEFFICIENT != 0);
|
||||
// Cubyz.fog.setDensity(1 / (ClientSettings.EFFECTIVE_RENDER_DISTANCE*ClientSettings.FOG_COEFFICIENT));
|
||||
skyColor.mulEqualScalar(0.25);
|
||||
skyColor *= @splat(3, @as(f32, 0.25));
|
||||
|
||||
try renderWorld(world, ambient, skyColor, playerPosition);
|
||||
try RenderStructure.updateMeshes(startTime + maximumMeshTime);
|
||||
@ -209,16 +209,16 @@ pub fn render(playerPosition: Vec3d) !void {
|
||||
|
||||
pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPos: Vec3d) !void {
|
||||
_ = world;
|
||||
buffers.clearAndBind(Vec4f{.x=skyColor.x, .y=skyColor.y, .z=skyColor.z, .w=1});
|
||||
buffers.clearAndBind(Vec4f{skyColor[0], skyColor[1], skyColor[2], 1});
|
||||
// TODO:// Clean up old chunk meshes:
|
||||
// Meshes.cleanUp();
|
||||
game.camera.updateViewMatrix();
|
||||
|
||||
// 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);
|
||||
var frustum = Frustum.init(Vec3f{0, 0, 0}, game.camera.viewMatrix, settings.fov, zFarLOD, main.Window.width, main.Window.height);
|
||||
|
||||
const time = @intCast(u32, std.time.milliTimestamp() & std.math.maxInt(u32));
|
||||
var waterFog = Fog{.active=true, .color=.{.x=0.0, .y=0.1, .z=0.2}, .density=0.1};
|
||||
var waterFog = Fog{.active=true, .color=.{0.0, 0.1, 0.2}, .density=0.1};
|
||||
|
||||
// Update the uniforms. The uniforms are needed to render the replacement meshes.
|
||||
chunk.meshing.bindShaderAndUniforms(game.lodProjectionMatrix, ambientLight, time);
|
||||
@ -268,7 +268,7 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo
|
||||
// }
|
||||
c.glDepthRangef(0, 0.05);
|
||||
|
||||
entity.ClientEntityManager.render(game.projectionMatrix, ambientLight, .{.x=1, .y=0.5, .z=0.25}, playerPos);
|
||||
entity.ClientEntityManager.render(game.projectionMatrix, ambientLight, .{1, 0.5, 0.25}, playerPos);
|
||||
|
||||
// BlockDropRenderer.render(frustumInt, ambientLight, directionalLight, playerPosition);
|
||||
|
||||
@ -495,30 +495,30 @@ pub const Frustum = struct {
|
||||
|
||||
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}));
|
||||
var cameraDir = vec.xyz(invRotationMatrix.mulVec(Vec4f{0, 0, 1, 1}));
|
||||
var cameraUp = vec.xyz(invRotationMatrix.mulVec(Vec4f{0, 1, 0, 1}));
|
||||
var cameraRight = vec.xyz(invRotationMatrix.mulVec(Vec4f{1, 0, 0, 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);
|
||||
const frontMultFar = cameraDir*@splat(3, _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
|
||||
self.planes[0] = Plane{.pos = cameraPos + frontMultFar, .norm=-cameraDir}; // far
|
||||
self.planes[1] = Plane{.pos = cameraPos, .norm=vec.cross(cameraUp, frontMultFar + cameraRight*@splat(3, halfHSide))}; // right
|
||||
self.planes[2] = Plane{.pos = cameraPos, .norm=vec.cross(frontMultFar - cameraRight*@splat(3, halfHSide), cameraUp)}; // left
|
||||
self.planes[3] = Plane{.pos = cameraPos, .norm=vec.cross(cameraRight, frontMultFar - cameraUp*@splat(3, halfVSide))}; // top
|
||||
self.planes[4] = Plane{.pos = cameraPos, .norm=vec.cross(frontMultFar + cameraUp*@splat(3, halfVSide), 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);
|
||||
var dist: f32 = vec.dot(pos - plane.pos, plane.norm);
|
||||
// Find the most positive corner:
|
||||
dist += @max(0, dim.x*plane.norm.x);
|
||||
dist += @max(0, dim.y*plane.norm.y);
|
||||
dist += @max(0, dim.z*plane.norm.z);
|
||||
dist += @max(0, dim[0]*plane.norm[0]);
|
||||
dist += @max(0, dim[1]*plane.norm[1]);
|
||||
dist += @max(0, dim[2]*plane.norm[2]);
|
||||
if(dist < 128) return false;
|
||||
}
|
||||
return true;
|
||||
@ -599,27 +599,27 @@ pub const MeshSelection = struct {
|
||||
// Test blocks:
|
||||
const closestDistance: f64 = 6.0; // selection now limited
|
||||
// Implementation of "A Fast Voxel Traversal Algorithm for Ray Tracing" http://www.cse.yorku.ca/~amana/research/grid.pdf
|
||||
const stepX = @floatToInt(chunk.ChunkCoordinate, std.math.sign(dir.x));
|
||||
const stepY = @floatToInt(chunk.ChunkCoordinate, std.math.sign(dir.y));
|
||||
const stepZ = @floatToInt(chunk.ChunkCoordinate, std.math.sign(dir.z));
|
||||
const invDirX: f64 = 1/dir.x;
|
||||
const invDirY: f64 = 1/dir.y;
|
||||
const invDirZ: f64 = 1/dir.z;
|
||||
const stepX = @floatToInt(chunk.ChunkCoordinate, std.math.sign(dir[0]));
|
||||
const stepY = @floatToInt(chunk.ChunkCoordinate, std.math.sign(dir[1]));
|
||||
const stepZ = @floatToInt(chunk.ChunkCoordinate, std.math.sign(dir[2]));
|
||||
const invDirX: f64 = 1/dir[0];
|
||||
const invDirY: f64 = 1/dir[1];
|
||||
const invDirZ: f64 = 1/dir[2];
|
||||
const tDeltaX: f64 = @fabs(invDirX);
|
||||
const tDeltaY: f64 = @fabs(invDirY);
|
||||
const tDeltaZ: f64 = @fabs(invDirZ);
|
||||
var tMaxX: f64 = (@floor(pos.x) - pos.x)*invDirX;
|
||||
var tMaxY: f64 = (@floor(pos.y) - pos.y)*invDirY;
|
||||
var tMaxZ: f64 = (@floor(pos.z) - pos.z)*invDirZ;
|
||||
var tMaxX: f64 = (@floor(pos[0]) - pos[0])*invDirX;
|
||||
var tMaxY: f64 = (@floor(pos[1]) - pos[1])*invDirY;
|
||||
var tMaxZ: f64 = (@floor(pos[2]) - pos[2])*invDirZ;
|
||||
tMaxX = @max(tMaxX, tMaxX + tDeltaX*@intToFloat(f64, stepX));
|
||||
tMaxY = @max(tMaxY, tMaxY + tDeltaY*@intToFloat(f64, stepY));
|
||||
tMaxZ = @max(tMaxZ, tMaxZ + tDeltaZ*@intToFloat(f64, stepZ));
|
||||
if(dir.x == 0) tMaxX = std.math.inf_f64;
|
||||
if(dir.y == 0) tMaxY = std.math.inf_f64;
|
||||
if(dir.z == 0) tMaxZ = std.math.inf_f64;
|
||||
var x = @floatToInt(chunk.ChunkCoordinate, @floor(pos.x));
|
||||
var y = @floatToInt(chunk.ChunkCoordinate, @floor(pos.y));
|
||||
var z = @floatToInt(chunk.ChunkCoordinate, @floor(pos.z));
|
||||
if(dir[0] == 0) tMaxX = std.math.inf_f64;
|
||||
if(dir[1] == 0) tMaxY = std.math.inf_f64;
|
||||
if(dir[2] == 0) tMaxZ = std.math.inf_f64;
|
||||
var x = @floatToInt(chunk.ChunkCoordinate, @floor(pos[0]));
|
||||
var y = @floatToInt(chunk.ChunkCoordinate, @floor(pos[1]));
|
||||
var z = @floatToInt(chunk.ChunkCoordinate, @floor(pos[2]));
|
||||
|
||||
var total_tMax: f64 = 0;
|
||||
|
||||
@ -630,12 +630,12 @@ pub const MeshSelection = struct {
|
||||
if(block.typ != 0) {
|
||||
// Check the true bounding box (using this algorithm here: https://tavianator.com/2011/ray_box.html):
|
||||
const voxelModel = &models.voxelModels.items[blocks.meshes.modelIndices(block)];
|
||||
const tx1 = (@intToFloat(f64, x) + @intToFloat(f64, voxelModel.minX)/16.0 - pos.x)*invDirX;
|
||||
const tx2 = (@intToFloat(f64, x) + @intToFloat(f64, voxelModel.maxX)/16.0 - pos.x)*invDirX;
|
||||
const ty1 = (@intToFloat(f64, y) + @intToFloat(f64, voxelModel.minY)/16.0 - pos.y)*invDirY;
|
||||
const ty2 = (@intToFloat(f64, y) + @intToFloat(f64, voxelModel.maxY)/16.0 - pos.y)*invDirY;
|
||||
const tz1 = (@intToFloat(f64, z) + @intToFloat(f64, voxelModel.minZ)/16.0 - pos.z)*invDirZ;
|
||||
const tz2 = (@intToFloat(f64, z) + @intToFloat(f64, voxelModel.maxZ)/16.0 - pos.z)*invDirZ;
|
||||
const tx1 = (@intToFloat(f64, x) + @intToFloat(f64, voxelModel.minX)/16.0 - pos[0])*invDirX;
|
||||
const tx2 = (@intToFloat(f64, x) + @intToFloat(f64, voxelModel.maxX)/16.0 - pos[0])*invDirX;
|
||||
const ty1 = (@intToFloat(f64, y) + @intToFloat(f64, voxelModel.minY)/16.0 - pos[1])*invDirY;
|
||||
const ty2 = (@intToFloat(f64, y) + @intToFloat(f64, voxelModel.maxY)/16.0 - pos[1])*invDirY;
|
||||
const tz1 = (@intToFloat(f64, z) + @intToFloat(f64, voxelModel.minZ)/16.0 - pos[2])*invDirZ;
|
||||
const tz2 = (@intToFloat(f64, z) + @intToFloat(f64, voxelModel.maxZ)/16.0 - pos[2])*invDirZ;
|
||||
const tMin = @max(
|
||||
@min(tx1, tx2),
|
||||
@max(
|
||||
@ -651,7 +651,7 @@ pub const MeshSelection = struct {
|
||||
)
|
||||
);
|
||||
if(tMin <= tMax and tMin <= closestDistance and tMax > 0) {
|
||||
selectedBlockPos = Vec3i{.x=x, .y=y, .z=z};
|
||||
selectedBlockPos = Vec3i{x, y, z};
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -765,16 +765,16 @@ pub const MeshSelection = struct {
|
||||
// }
|
||||
pub fn render(projectionMatrix: Mat4f, viewMatrix: Mat4f, playerPos: Vec3d) void {
|
||||
if(selectedBlockPos) |_selectedBlockPos| {
|
||||
var block = RenderStructure.getBlock(_selectedBlockPos.x, _selectedBlockPos.y, _selectedBlockPos.z) orelse return;
|
||||
var block = RenderStructure.getBlock(_selectedBlockPos[0], _selectedBlockPos[1], _selectedBlockPos[2]) orelse return;
|
||||
var voxelModel = &models.voxelModels.items[blocks.meshes.modelIndices(block)];
|
||||
shader.bind();
|
||||
|
||||
c.glUniformMatrix4fv(uniforms.projectionMatrix, 1, c.GL_FALSE, @ptrCast([*c]const f32, &projectionMatrix));
|
||||
c.glUniformMatrix4fv(uniforms.viewMatrix, 1, c.GL_FALSE, @ptrCast([*c]const f32, &viewMatrix));
|
||||
c.glUniform3f(uniforms.modelPosition,
|
||||
@floatCast(f32, @intToFloat(f64, _selectedBlockPos.x) - playerPos.x),
|
||||
@floatCast(f32, @intToFloat(f64, _selectedBlockPos.y) - playerPos.y),
|
||||
@floatCast(f32, @intToFloat(f64, _selectedBlockPos.z) - playerPos.z)
|
||||
@floatCast(f32, @intToFloat(f64, _selectedBlockPos[0]) - playerPos[0]),
|
||||
@floatCast(f32, @intToFloat(f64, _selectedBlockPos[1]) - playerPos[1]),
|
||||
@floatCast(f32, @intToFloat(f64, _selectedBlockPos[2]) - playerPos[2])
|
||||
);
|
||||
c.glUniform3f(uniforms.lowerBounds,
|
||||
@intToFloat(f32, voxelModel.minX)/16.0,
|
||||
@ -895,9 +895,9 @@ pub const RenderStructure = struct {
|
||||
if(lastRD != renderDistance and lastFactor != LODFactor) {
|
||||
try network.Protocols.genericUpdate.sendRenderDistance(conn, renderDistance, LODFactor);
|
||||
}
|
||||
const px = @floatToInt(chunk.ChunkCoordinate, playerPos.x);
|
||||
const py = @floatToInt(chunk.ChunkCoordinate, playerPos.y);
|
||||
const pz = @floatToInt(chunk.ChunkCoordinate, playerPos.z);
|
||||
const px = @floatToInt(chunk.ChunkCoordinate, playerPos[0]);
|
||||
const py = @floatToInt(chunk.ChunkCoordinate, playerPos[1]);
|
||||
const pz = @floatToInt(chunk.ChunkCoordinate, playerPos[2]);
|
||||
|
||||
var meshRequests = std.ArrayList(chunk.ChunkPosition).init(main.threadAllocator);
|
||||
defer meshRequests.deinit();
|
||||
@ -956,13 +956,13 @@ pub const RenderStructure = struct {
|
||||
try meshRequests.append(pos);
|
||||
}
|
||||
if(frustum.testAAB(Vec3f{
|
||||
.x = @floatCast(f32, @intToFloat(f64, x) - playerPos.x),
|
||||
.y = @floatCast(f32, @intToFloat(f64, y) - playerPos.y),
|
||||
.z = @floatCast(f32, @intToFloat(f64, z) - playerPos.z),
|
||||
@floatCast(f32, @intToFloat(f64, x) - playerPos[0]),
|
||||
@floatCast(f32, @intToFloat(f64, y) - playerPos[1]),
|
||||
@floatCast(f32, @intToFloat(f64, z) - playerPos[2]),
|
||||
}, Vec3f{
|
||||
.x = @intToFloat(f32, size),
|
||||
.y = @intToFloat(f32, size),
|
||||
.z = @intToFloat(f32, size),
|
||||
@intToFloat(f32, size),
|
||||
@intToFloat(f32, size),
|
||||
@intToFloat(f32, size),
|
||||
}) and node.?.mesh.visibilityMask != 0) {
|
||||
try meshes.append(&node.?.mesh);
|
||||
}
|
||||
|
331
src/vec.zig
331
src/vec.zig
@ -1,231 +1,62 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub const Vec2i = GenericVector2(i32);
|
||||
pub const Vec2f = GenericVector2(f32);
|
||||
pub const Vec2d = GenericVector2(f64);
|
||||
pub const Vec3i = GenericVector3(i32);
|
||||
pub const Vec3f = extern struct {// This one gets a bit of extra functionality for rotating in 3d.
|
||||
x: f32,
|
||||
y: f32,
|
||||
z: f32,
|
||||
pub usingnamespace Vec3RotationMath(@This(), f32);
|
||||
pub usingnamespace Vec3SpecificMath(@This(), f32);
|
||||
pub usingnamespace GenericVectorMath(@This(), f32);
|
||||
pub const Vec2i = @Vector(2, i32);
|
||||
pub const Vec2f = @Vector(2, f32);
|
||||
pub const Vec2d = @Vector(2, f64);
|
||||
pub const Vec3i = @Vector(3, i32);
|
||||
pub const Vec3f = @Vector(3, f32);
|
||||
pub const Vec3d = @Vector(3, f64);
|
||||
pub const Vec4i = @Vector(4, i32);
|
||||
pub const Vec4f = @Vector(4, f32);
|
||||
pub const Vec4d = @Vector(4, f64);
|
||||
|
||||
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);
|
||||
pub const Vec4f = GenericVector4(f32);
|
||||
pub const Vec4d = GenericVector4(f64);
|
||||
|
||||
fn Vec3RotationMath(comptime Vec: type, comptime T: type) type {
|
||||
if(@typeInfo(Vec).Struct.fields.len == 3 and @typeInfo(T) == .Float) {
|
||||
return struct{
|
||||
pub fn rotateX(self: Vec, angle: T) Vec {
|
||||
const sin = @sin(angle);
|
||||
const cos = @cos(angle); // TODO: Consider using sqrt here.
|
||||
return Vec{
|
||||
.x = self.x,
|
||||
.y = self.y*cos - self.z*sin,
|
||||
.z = self.y*sin + self.z*cos,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn rotateY(self: Vec, angle: T) Vec {
|
||||
const sin = @sin(angle);
|
||||
const cos = @cos(angle); // TODO: Consider using sqrt here.
|
||||
return Vec{
|
||||
.x = self.x*cos + self.z*sin,
|
||||
.y = self.y,
|
||||
.z = -self.x*sin + self.z*cos,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn rotateZ(self: Vec, angle: T) Vec {
|
||||
const sin = @sin(angle);
|
||||
const cos = @cos(angle); // TODO: Consider using sqrt here.
|
||||
return Vec{
|
||||
.x = self.x*cos - self.y*sin,
|
||||
.y = self.x*sin + self.y*cos,
|
||||
.z = self.z,
|
||||
};
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return struct{};
|
||||
}
|
||||
pub fn xyz(self: anytype) @Vector(3, @typeInfo(@TypeOf(self)).Vector.child) {
|
||||
return @Vector(3, @typeInfo(@TypeOf(self)).Vector.child){self[0], self[1], self[2]};
|
||||
}
|
||||
|
||||
fn Vec3SpecificMath(comptime Vec: type, comptime T: type) type {
|
||||
_ = T;
|
||||
return struct {
|
||||
pub fn cross(self: Vec, other: Vec) Vec {
|
||||
return Vec {
|
||||
.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 dot(self: anytype, other: @TypeOf(self)) @typeInfo(@TypeOf(self)).Vector.child {
|
||||
return @reduce(.Add, self*other);
|
||||
}
|
||||
|
||||
pub fn cross(self: anytype, other: @TypeOf(self)) @TypeOf(self) {
|
||||
if(@typeInfo(@TypeOf(self)).Vector.len != 3) @compileError("Only available for vectors of length 3.");
|
||||
return @TypeOf(self) {
|
||||
self[1]*other[2] - self[2]*other[1],
|
||||
self[2]*other[0] - self[0]*other[2],
|
||||
self[0]*other[1] - self[1]*other[0],
|
||||
};
|
||||
}
|
||||
|
||||
fn GenericVectorMath(comptime Vec: type, comptime T: type) type {
|
||||
return struct {
|
||||
pub fn add(self: Vec, other: Vec) Vec {
|
||||
var result: Vec = undefined;
|
||||
inline for(@typeInfo(Vec).Struct.fields) |field| {
|
||||
@field(result, field.name) = @field(self, field.name) + @field(other, field.name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn sub(self: Vec, other: Vec) Vec {
|
||||
var result: Vec = undefined;
|
||||
inline for(@typeInfo(Vec).Struct.fields) |field| {
|
||||
@field(result, field.name) = @field(self, field.name) - @field(other, field.name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn mul(self: Vec, other: Vec) Vec {
|
||||
var result: Vec = undefined;
|
||||
inline for(@typeInfo(Vec).Struct.fields) |field| {
|
||||
@field(result, field.name) = @field(self, field.name) * @field(other, field.name);
|
||||
}
|
||||
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;
|
||||
inline for(@typeInfo(Vec).Struct.fields) |field| {
|
||||
@field(result, field.name) = @field(self, field.name) / @field(other, field.name);
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
@compileError("Not supported for integer types.");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn divScalar(self: Vec, scalar: T) Vec {
|
||||
if(@typeInfo(T) == .Float) {
|
||||
var result: Vec = undefined;
|
||||
inline for(@typeInfo(Vec).Struct.fields) |field| {
|
||||
@field(result, field.name) = @field(self, field.name) / scalar;
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
@compileError("Not supported for integer types.");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn minimum(self: Vec, other: Vec) Vec {
|
||||
var result: Vec = undefined;
|
||||
inline for(@typeInfo(Vec).Struct.fields) |field| {
|
||||
@field(result, field.name) = @min(@field(self, field.name), @field(other, field.name));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn maximum(self: Vec, other: Vec) Vec {
|
||||
var result: Vec = undefined;
|
||||
inline for(@typeInfo(Vec).Struct.fields) |field| {
|
||||
@field(result, field.name) = @max(@field(self, field.name), @field(other, field.name));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn addEqual(self: *Vec, other: Vec) void {
|
||||
inline for(@typeInfo(Vec).Struct.fields) |field| {
|
||||
@field(self, field.name) += @field(other, field.name);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn subEqual(self: *Vec, other: Vec) void {
|
||||
inline for(@typeInfo(Vec).Struct.fields) |field| {
|
||||
@field(self, field.name) -= @field(other, field.name);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mulEqual(self: *Vec, other: Vec) void {
|
||||
inline for(@typeInfo(Vec).Struct.fields) |field| {
|
||||
@field(self, field.name) *= @field(other, field.name);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mulEqualScalar(self: *Vec, scalar: T) void {
|
||||
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| {
|
||||
@field(self, field.name) /= @field(other, field.name);
|
||||
}
|
||||
} else {
|
||||
@compileError("Not supported for integer types.");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn divEqualScalar(self: *Vec, scalar: T) void {
|
||||
if(@typeInfo(T) == .Float) {
|
||||
inline for(@typeInfo(Vec).Struct.fields) |field| {
|
||||
@field(self, field.name) /= scalar;
|
||||
}
|
||||
} else {
|
||||
@compileError("Not supported for integer types.");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dot(self: Vec, other: Vec) T {
|
||||
var result: T = 0;
|
||||
inline for(@typeInfo(Vec).Struct.fields) |field| {
|
||||
result += @field(self, field.name) * @field(other, field.name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
pub fn rotateX(self: anytype, angle: @typeInfo(@TypeOf(self)).Vector.child) @TypeOf(self) {
|
||||
if(@typeInfo(@TypeOf(self)).Vector.len != 3) @compileError("Only available for vectors of length 3.");
|
||||
const sin = @sin(angle);
|
||||
const cos = @cos(angle); // TODO: Consider using sqrt here.
|
||||
return @TypeOf(self){
|
||||
self[0],
|
||||
self[1]*cos - self[2]*sin,
|
||||
self[1]*sin + self[2]*cos,
|
||||
};
|
||||
}
|
||||
|
||||
fn GenericVector2(comptime T: type) type {
|
||||
return extern struct {
|
||||
x: T,
|
||||
y: T,
|
||||
pub usingnamespace GenericVectorMath(@This(), T);
|
||||
pub fn rotateY(self: anytype, angle: @typeInfo(@TypeOf(self)).Vector.child) @TypeOf(self) {
|
||||
if(@typeInfo(@TypeOf(self)).Vector.len != 3) @compileError("Only available for vectors of length 3.");
|
||||
const sin = @sin(angle);
|
||||
const cos = @cos(angle); // TODO: Consider using sqrt here.
|
||||
return @TypeOf(self){
|
||||
self[0]*cos + self[2]*sin,
|
||||
self[1],
|
||||
-self[0]*sin + self[2]*cos,
|
||||
};
|
||||
}
|
||||
|
||||
fn GenericVector3(comptime T: type) type {
|
||||
return extern struct {
|
||||
x: T,
|
||||
y: T,
|
||||
z: T,
|
||||
pub usingnamespace Vec3RotationMath(@This(), T);
|
||||
pub usingnamespace Vec3SpecificMath(@This(), T);
|
||||
pub usingnamespace GenericVectorMath(@This(), T);
|
||||
};
|
||||
}
|
||||
|
||||
fn GenericVector4(comptime T: type) type {
|
||||
return extern struct {
|
||||
x: T,
|
||||
y: T,
|
||||
z: T,
|
||||
w: T,
|
||||
pub usingnamespace GenericVectorMath(@This(), T);
|
||||
pub fn rotateZ(self: anytype, angle: @typeInfo(@TypeOf(self)).Vector.child) @TypeOf(self) {
|
||||
if(@typeInfo(@TypeOf(self)).Vector.len != 3) @compileError("Only available for vectors of length 3.");
|
||||
const sin = @sin(angle);
|
||||
const cos = @cos(angle); // TODO: Consider using sqrt here.
|
||||
return @TypeOf(self){
|
||||
self[0]*cos - self[1]*sin,
|
||||
self[0]*sin + self[1]*cos,
|
||||
self[2],
|
||||
};
|
||||
}
|
||||
|
||||
@ -234,10 +65,10 @@ pub const Mat4f = struct {
|
||||
pub fn identity() Mat4f {
|
||||
return Mat4f {
|
||||
.columns = [4]Vec4f { // Keep in mind that this is the transpose!
|
||||
Vec4f{.x=1, .y=0, .z=0, .w=0},
|
||||
Vec4f{.x=0, .y=1, .z=0, .w=0},
|
||||
Vec4f{.x=0, .y=0, .z=1, .w=0},
|
||||
Vec4f{.x=0, .y=0, .z=0, .w=1},
|
||||
Vec4f{1, 0, 0, 0},
|
||||
Vec4f{0, 1, 0, 0},
|
||||
Vec4f{0, 0, 1, 0},
|
||||
Vec4f{0, 0, 0, 1},
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -245,10 +76,10 @@ pub const Mat4f = struct {
|
||||
pub fn translation(pos: Vec3f) Mat4f {
|
||||
return Mat4f {
|
||||
.columns = [4]Vec4f { // Keep in mind that this is the transpose!
|
||||
Vec4f{.x=1, .y=0, .z=0, .w=0},
|
||||
Vec4f{.x=0, .y=1, .z=0, .w=0},
|
||||
Vec4f{.x=0, .y=0, .z=1, .w=0},
|
||||
Vec4f{.x=pos.x, .y=pos.y, .z=pos.z, .w=1},
|
||||
Vec4f{1, 0, 0, 0},
|
||||
Vec4f{0, 1, 0, 0},
|
||||
Vec4f{0, 0, 1, 0},
|
||||
Vec4f{pos[0], pos[1], pos[2], 1},
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -258,10 +89,10 @@ pub const Mat4f = struct {
|
||||
const c = @cos(rad);
|
||||
return Mat4f {
|
||||
.columns = [4]Vec4f { // Keep in mind that this is the transpose!
|
||||
Vec4f{.x=1, .y=0, .z=0, .w=0},
|
||||
Vec4f{.x=0, .y=c, .z=s, .w=0},
|
||||
Vec4f{.x=0,.y=-s, .z=c, .w=0},
|
||||
Vec4f{.x=0, .y=0, .z=0, .w=1},
|
||||
Vec4f{1, 0, 0, 0},
|
||||
Vec4f{0, c, s, 0},
|
||||
Vec4f{0,-s, c, 0},
|
||||
Vec4f{0, 0, 0, 1},
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -271,10 +102,10 @@ pub const Mat4f = struct {
|
||||
const c = @cos(rad);
|
||||
return Mat4f {
|
||||
.columns = [4]Vec4f { // Keep in mind that this is the transpose!
|
||||
Vec4f{.x=c, .y=0,.z=-s, .w=0},
|
||||
Vec4f{.x=0, .y=1, .z=0, .w=0},
|
||||
Vec4f{.x=s, .y=0, .z=c, .w=0},
|
||||
Vec4f{.x=0, .y=0, .z=0, .w=1},
|
||||
Vec4f{c, 0,-s, 0},
|
||||
Vec4f{0, 1, 0, 0},
|
||||
Vec4f{s, 0, c, 0},
|
||||
Vec4f{0, 0, 0, 1},
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -284,10 +115,10 @@ pub const Mat4f = struct {
|
||||
const c = @cos(rad);
|
||||
return Mat4f {
|
||||
.columns = [4]Vec4f { // Keep in mind that this is the transpose!
|
||||
Vec4f{.x=c, .y=s, .z=0, .w=0},
|
||||
Vec4f{.x=-s,.y=c, .z=0, .w=0},
|
||||
Vec4f{.x=0, .y=0, .z=1, .w=0},
|
||||
Vec4f{.x=0, .y=0, .z=0, .w=1},
|
||||
Vec4f{c, s, 0, 0},
|
||||
Vec4f{-s,c, 0, 0},
|
||||
Vec4f{0, 0, 1, 0},
|
||||
Vec4f{0, 0, 0, 1},
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -297,10 +128,10 @@ pub const Mat4f = struct {
|
||||
const tanX = aspect*tanY;
|
||||
return Mat4f {
|
||||
.columns = [4]Vec4f { // Keep in mind that this is the transpose!
|
||||
Vec4f{.x=1/tanX, .y=0, .z=0, .w=0},
|
||||
Vec4f{.x=0, .y=1/tanY, .z=0, .w=0},
|
||||
Vec4f{.x=0, .y=0, .z=(far + near)/(near - far), .w=-1},
|
||||
Vec4f{.x=0, .y=0, .z=2*near*far/(near - far), .w=0},
|
||||
Vec4f{1/tanX, 0, 0, 0},
|
||||
Vec4f{0, 1/tanY, 0, 0},
|
||||
Vec4f{0, 0, (far + near)/(near - far), -1},
|
||||
Vec4f{0, 0, 2*near*far/(near - far), 0},
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -308,10 +139,10 @@ pub const Mat4f = struct {
|
||||
pub fn transpose(self: Mat4f) Mat4f {
|
||||
return Mat4f {
|
||||
.columns = [4]Vec4f { // Keep in mind that this is the transpose!
|
||||
Vec4f{.x=self.columns[0].x, .y=self.columns[1].x, .z=self.columns[2].x, .w=self.columns[3].x},
|
||||
Vec4f{.x=self.columns[0].y, .y=self.columns[1].y, .z=self.columns[2].y, .w=self.columns[3].y},
|
||||
Vec4f{.x=self.columns[0].z, .y=self.columns[1].z, .z=self.columns[2].z, .w=self.columns[3].z},
|
||||
Vec4f{.x=self.columns[0].w, .y=self.columns[1].w, .z=self.columns[2].w, .w=self.columns[3].w},
|
||||
Vec4f{self.columns[0][0], self.columns[1][0], self.columns[2][0], self.columns[3][0]},
|
||||
Vec4f{self.columns[0][1], self.columns[1][1], self.columns[2][1], self.columns[3][1]},
|
||||
Vec4f{self.columns[0][2], self.columns[1][2], self.columns[2][2], self.columns[3][2]},
|
||||
Vec4f{self.columns[0][3], self.columns[1][3], self.columns[2][3], self.columns[3][3]},
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -320,10 +151,10 @@ pub const Mat4f = struct {
|
||||
var transposeSelf = self.transpose();
|
||||
var result: Mat4f = undefined;
|
||||
for(other.columns) |_, col| {
|
||||
result.columns[col].x = transposeSelf.columns[0].dot(other.columns[col]);
|
||||
result.columns[col].y = transposeSelf.columns[1].dot(other.columns[col]);
|
||||
result.columns[col].z = transposeSelf.columns[2].dot(other.columns[col]);
|
||||
result.columns[col].w = transposeSelf.columns[3].dot(other.columns[col]);
|
||||
result.columns[col][0] = dot(transposeSelf.columns[0], other.columns[col]);
|
||||
result.columns[col][1] = dot(transposeSelf.columns[1], other.columns[col]);
|
||||
result.columns[col][2] = dot(transposeSelf.columns[2], other.columns[col]);
|
||||
result.columns[col][3] = dot(transposeSelf.columns[3], other.columns[col]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -331,10 +162,10 @@ pub const Mat4f = struct {
|
||||
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);
|
||||
result[0] = dot(transposeSelf.columns[0], vec);
|
||||
result[1] = dot(transposeSelf.columns[1], vec);
|
||||
result[2] = dot(transposeSelf.columns[2], vec);
|
||||
result[3] = dot(transposeSelf.columns[3], vec);
|
||||
return result;
|
||||
}
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user