Skip to content

Commit

Permalink
store camera orientation as matrix
Browse files Browse the repository at this point in the history
  • Loading branch information
ashpil committed Dec 3, 2024
1 parent 85eeb2d commit 691c2a4
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 54 deletions.
30 changes: 15 additions & 15 deletions src/bin/online.zig
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const vector = engine.vector;
const F32x4 = vector.Vec4(f32);
const F32x3 = vector.Vec3(f32);
const F32x2 = vector.Vec2(f32);
const Mat4 = vector.Mat4(f32);
const Mat3 = vector.Mat3(f32);
const Mat3x4 = vector.Mat3x4(f32);

const vk = @import("vulkan");
Expand Down Expand Up @@ -263,12 +263,7 @@ pub fn main() !void {
var changed = imgui.sliderAngle("Vertical FOV", &scene.camera.lenses.items[0].vfov, 1, 179);
changed = imgui.dragScalar(f32, "Focus distance", &scene.camera.lenses.items[0].focus_distance, 0.1, -std.math.inf(f32), std.math.inf(f32)) or changed;
changed = imgui.dragScalar(f32, "Aperture size", &scene.camera.lenses.items[0].aperture, 0.01, 0.0, std.math.inf(f32)) or changed;
changed = imgui.dragVector(F32x3, "Origin", &scene.camera.lenses.items[0].origin, 0.1, -std.math.inf(f32), std.math.inf(f32)) or changed;
changed = imgui.dragVector(F32x3, "Forward", &scene.camera.lenses.items[0].forward, 0.1, -1.0, 1.0) or changed;
changed = imgui.dragVector(F32x3, "Up", &scene.camera.lenses.items[0].up, 0.1, -1.0, 1.0) or changed;
if (changed) {
scene.camera.lenses.items[0].forward = scene.camera.lenses.items[0].forward.unit();
scene.camera.lenses.items[0].up = scene.camera.lenses.items[0].up.unit();
scene.camera.sensors.items[active_sensor].clear();
}
imgui.popItemWidth();
Expand Down Expand Up @@ -376,11 +371,13 @@ pub fn main() !void {
);
if (imgui.isMouseDragging(.right)) {
window.setCursorMode(.disabled);
const delta = F32x2.new(0.5, 0.5).add(imgui.getMouseDragDelta(.right).componentDiv(window_size));
const delta = imgui.getMouseDragDelta(.right).componentDiv(window_size);
imgui.resetMouseDragDelta(.right);
if (!std.meta.eql(delta, F32x2.new(0.5, 0.5))) {
const aspect = window_size.x / window_size.y;
scene.camera.lenses.items[0].forward = scene.camera.lenses.items[0].directionFromUv(F32x2.new(delta.x, delta.y), aspect);
if (!std.meta.eql(delta, F32x2.new(0.0, 0.0))) {
const left_right = Mat3.fromAxisAngle(F32x3.new(0, 0, 1), delta.x);
const up_down = Mat3.fromAxisAngle(F32x3.new(0, -1, 0), delta.y);
const rotation = up_down.mul(left_right);
scene.camera.lenses.items[0].transform = scene.camera.lenses.items[0].transform.mul(Mat3x4.fromTransformTranslation(rotation, F32x3.zero));
scene.camera.sensors.items[active_sensor].clear();
}
} else {
Expand All @@ -395,15 +392,18 @@ pub fn main() !void {
}
if (!imgui.getIO().WantCaptureKeyboard) {
const old_lens = scene.camera.lenses.items[0];
const side = old_lens.forward.cross(old_lens.up).unit();
var new_lens = scene.camera.lenses.items[0];

const left = old_lens.transform.mulVector(F32x3.new(0, -1, 0));
const forward = old_lens.transform.mulVector(F32x3.new(1, 0, 0));
const origin = old_lens.transform.extractTranslation();

const speed = imgui.getIO().DeltaTime;

if (imgui.isKeyDown(.w)) new_lens.origin = new_lens.origin.add(new_lens.forward.scale(speed * 30));
if (imgui.isKeyDown(.s)) new_lens.origin = new_lens.origin.sub(new_lens.forward.scale(speed * 30));
if (imgui.isKeyDown(.a)) new_lens.origin = new_lens.origin.add(side.scale(speed * 30));
if (imgui.isKeyDown(.d)) new_lens.origin = new_lens.origin.sub(side.scale(speed * 30));
if (imgui.isKeyDown(.w)) new_lens.transform = new_lens.transform.withTranslation(origin.add(forward.scale(speed * 30)));
if (imgui.isKeyDown(.s)) new_lens.transform = new_lens.transform.withTranslation(origin.sub(forward.scale(speed * 30)));
if (imgui.isKeyDown(.a)) new_lens.transform = new_lens.transform.withTranslation(origin.add(left.scale(speed * 30)));
if (imgui.isKeyDown(.d)) new_lens.transform = new_lens.transform.withTranslation(origin.sub(left.scale(speed * 30)));
if (imgui.isKeyDown(.f) and new_lens.aperture > 0.0) new_lens.aperture -= speed / 10;
if (imgui.isKeyDown(.r)) new_lens.aperture += speed / 10;
if (imgui.isKeyDown(.q)) new_lens.focus_distance -= speed * 10;
Expand Down
31 changes: 7 additions & 24 deletions src/lib/hrtsystem/Camera.zig
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ const F32x4 = vector.Vec4(f32);
const Mat3x4 = vector.Mat3x4(f32);

pub const Lens = extern struct {
origin: F32x3,
forward: F32x3,
up: F32x3,
transform: Mat3x4,
vfov: f32, // radians
aperture: f32,
focus_distance: f32,
Expand All @@ -43,33 +41,18 @@ pub const Lens = extern struct {
F32x4.new(0, 1, 0, 0),
) };

const w = transform.mulVector(F32x3.new(0.0, 0.0, -1.0)).unit();
const u = transform.mulVector(F32x3.new(0.0, 1.0, 0.0)).unit().cross(w).unit();
const v = u.cross(w);
const origin = transform.mulPoint(F32x3.new(0.0, 0.0, 0.0));

return Lens {
.origin = transform.mulPoint(F32x3.new(0.0, 0.0, 0.0)),
.forward = transform.mulVector(F32x3.new(0.0, 0.0, -1.0)).unit(),
.up = transform.mulVector(F32x3.new(0.0, 1.0, 0.0)).unit(),
.transform = Mat3x4.fromColumns(w, u, v, origin),
.vfov = yfov,
.aperture = 0.0,
.focus_distance = 1.0,
};
}

// should correspond to GPU-side generateRay
pub fn directionFromUv(self: Lens, uv: F32x2, aspect: f32) F32x3 {
const w = self.forward;
const u = self.up.cross(w).unit();
const v = u.cross(w);

const h = std.math.tan(self.vfov / 2);
const viewport_height = 2 * h * self.focus_distance;
const viewport_width = aspect * viewport_height;

const horizontal = u.scale(viewport_width);
const vertical = v.scale(viewport_height);

const lower_left_corner = self.origin.sub(horizontal.scale(1.0 / 2.0)).sub(vertical.scale(1.0 / 2.0)).add(w.scale(self.focus_distance));

return (lower_left_corner.add(horizontal.scale(uv.x)).add(vertical.scale(uv.y)).sub(self.origin)).unit();
}
};

sensors: std.ArrayListUnmanaged(Sensor) = .{},
Expand Down
10 changes: 1 addition & 9 deletions src/lib/shaders/hrtsystem/camera.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@ struct ThinLens {
};

struct Camera {
float3 origin;
float3 forward;
float3 up;
row_major float3x4 toWorld;
float vfov;
float aperture;
float focusDistance;
Expand All @@ -49,12 +47,6 @@ struct Camera {
const ThinLens thinLens = {vfov, aspect, aperture, focusDistance};
const Ray rayCameraSpace = thinLens.generateRay(rand, uv);

const float3 w = forward;
const float3 u = normalize(cross(up, w));
const float3 v = cross(u, w);
const float4x3 toWorldTransposed = {w, u, v, origin};
const float3x4 toWorld = transpose(toWorldTransposed);

return rayCameraSpace.transformed(toWorld);
}
};
Expand Down
9 changes: 3 additions & 6 deletions src/lib/tests.zig
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const F32x3 = vector.Vec3(f32);
const F32x2 = vector.Vec2(f32);
const U32x3 = vector.Vec3(u32);
const Mat3x4 = vector.Mat3x4(f32);
const Mat3 = vector.Mat3(f32);

const vk_helpers = engine.core.vk_helpers;

Expand Down Expand Up @@ -329,9 +330,7 @@ test "white sphere on white background is white" {

var camera = Camera {};
_ = try camera.appendLens(allocator, Camera.Lens {
.origin = F32x3.new(-3, 0, 0),
.forward = F32x3.new(1, 0, 0),
.up = F32x3.new(0, 0, 1),
.transform = Mat3x4.fromTransformTranslation(Mat3.identity, F32x3.new(-3, 0, 0)),
.vfov = std.math.pi / 4.0,
.aperture = 0,
.focus_distance = 1,
Expand Down Expand Up @@ -431,9 +430,7 @@ test "inside illuminating sphere is white" {

var camera = Camera {};
_ = try camera.appendLens(allocator, Camera.Lens {
.origin = F32x3.new(0, 0, 0),
.forward = F32x3.new(1, 0, 0),
.up = F32x3.new(0, 0, 1),
.transform = Mat3x4.identity,
.vfov = std.math.pi / 3.0,
.aperture = 0,
.focus_distance = 1,
Expand Down

0 comments on commit 691c2a4

Please sign in to comment.