Skip to content

Commit

Permalink
Merge pull request #17 from Miou-zora/transform-rotation
Browse files Browse the repository at this point in the history
Add rotation
  • Loading branch information
Miou-zora authored Apr 22, 2024
2 parents a451b11 + 8f5c18c commit 688a44a
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 10 deletions.
48 changes: 48 additions & 0 deletions src/Rotation.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const Ray = @import("Ray.zig").Ray;
const HitRecord = @import("HitRecord.zig").HitRecord;
const Vec3 = @import("Vec3.zig").Vec3;
const Plane = @import("Plane.zig").Plane;

pub const Rotation = struct {
const Self = @This();

x: f32,
y: f32,
z: f32,

pub fn ray_global_to_object(self: *const Self, ray: Ray, object: Plane) Ray {
var ray_in_object_space = Ray{
.direction = ray.direction,
.origin = ray.origin.subVec3(object.origin),
};
ray_in_object_space.direction.rotateX(self.x);
ray_in_object_space.direction.rotateY(self.y);
ray_in_object_space.direction.rotateZ(self.z);
ray_in_object_space.origin.rotateX(self.x);
ray_in_object_space.origin.rotateY(self.y);
ray_in_object_space.origin.rotateZ(self.z);
return Ray{
.direction = ray_in_object_space.direction,
.origin = ray_in_object_space.origin.addVec3(object.origin),
};
}

pub fn hitRecord_object_to_global(self: *const Self, hitrecord: HitRecord, object: Plane) HitRecord {
var hitrecord_in_object_space = HitRecord{
.intersection_point = hitrecord.intersection_point.subVec3(object.origin),
.normal = hitrecord.normal,
.hit = hitrecord.hit,
};
hitrecord_in_object_space.normal.rotateZ(-self.z);
hitrecord_in_object_space.normal.rotateY(-self.y);
hitrecord_in_object_space.normal.rotateX(-self.x);
hitrecord_in_object_space.intersection_point.rotateZ(-self.z);
hitrecord_in_object_space.intersection_point.rotateY(-self.y);
hitrecord_in_object_space.intersection_point.rotateX(-self.x);
return HitRecord{
.intersection_point = hitrecord_in_object_space.intersection_point.addVec3(object.origin),
.normal = hitrecord_in_object_space.normal,
.hit = hitrecord_in_object_space.hit,
};
}
};
13 changes: 11 additions & 2 deletions src/Transformation.zig
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
const Translation = @import("Translation.zig").Translation;
const Rotation = @import("Rotation.zig").Rotation;
const Ray = @import("Ray.zig").Ray;
const HitRecord = @import("HitRecord.zig").HitRecord;
const Plane = @import("Plane.zig").Plane;

pub const Transformation = union(enum) {
translation: Translation,
rotation: Rotation,
};

pub fn ray_global_to_object(ray: Ray, transformation: Transformation) Ray {
pub fn ray_global_to_object(ray: Ray, transformation: Transformation, object: Plane) Ray {
switch (transformation) {
Transformation.translation => |value| {
return value.ray_global_to_object(ray);
},
Transformation.rotation => |value| {
return value.ray_global_to_object(ray, object);
},
}
}

pub fn hitRecord_object_to_global(ray: HitRecord, transformation: Transformation) HitRecord {
pub fn hitRecord_object_to_global(ray: HitRecord, transformation: Transformation, object: Plane) HitRecord {
switch (transformation) {
Transformation.translation => |value| {
return value.hitRecord_object_to_global(ray);
},
Transformation.rotation => |value| {
return value.hitRecord_object_to_global(ray, object);
},
}
}
21 changes: 21 additions & 0 deletions src/Vec3.zig
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,27 @@ pub const Vec3 = struct {
pub fn dot(self: *const Self, other: Self) f32 {
return self.x * other.x + self.y * other.y + self.z * other.z;
}

pub fn rotateX(self: *Self, angle: f32) void {
const y = self.y;
const z = self.z;
self.y = y * std.math.cos(angle) - z * std.math.sin(angle);
self.z = y * std.math.sin(angle) + z * std.math.cos(angle);
}

pub fn rotateY(self: *Self, angle: f32) void {
const x = self.x;
const z = self.z;
self.x = x * std.math.cos(angle) + z * std.math.sin(angle);
self.z = -x * std.math.sin(angle) + z * std.math.cos(angle);
}

pub fn rotateZ(self: *Self, angle: f32) void {
const x = self.x;
const y = self.y;
self.x = x * std.math.cos(angle) - y * std.math.sin(angle);
self.y = x * std.math.sin(angle) + y * std.math.cos(angle);
}
};

test "subVec3" {
Expand Down
21 changes: 13 additions & 8 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,16 @@ pub fn main() !void {
},
},
};
const sphere = Sphere{
.center = .{ .x = 0, .y = 0, .z = 2 },
.radius = 0.5,
// const sphere = Sphere{
// .center = .{ .x = 0, .y = 0, .z = 2 },
// .radius = 0.5,
// };
// const sphere_translation = Transformation.Transformation{ .translation = .{ .x = -0.5, .y = 0.2, .z = 1.5 } };
const sphere = Plane{
.normal = .{ .x = 0, .y = 1, .z = 0 },
.origin = .{ .x = 0, .y = -1, .z = 1 },
};
const sphere_translation = Transformation.Transformation{ .translation = .{ .x = -0.5, .y = 0.2, .z = 1.5 } };
const sphere_translation = Transformation.Transformation{ .rotation = .{ .x = 0.3, .y = 0, .z = 0.2 } };
const light = Light{
.color = .{ .blue = 255, .green = 255, .red = 255 },
.intensity = 1,
Expand All @@ -69,17 +74,17 @@ pub fn main() !void {
const scaled_x: f32 = @as(f32, @floatFromInt(x)) / @as(f32, @floatFromInt(width));
const scaled_y: f32 = @as(f32, @floatFromInt((height - 1) - y)) / @as(f32, @floatFromInt(height));
const ray: Ray = camera.createRay(scaled_x, scaled_y);
const ray_object = Transformation.ray_global_to_object(ray, sphere_translation);
const ray_object = Transformation.ray_global_to_object(ray, sphere_translation, sphere);
var record = sphere.hits(ray_object);
record = Transformation.hitRecord_object_to_global(record, sphere_translation);
record = Transformation.hitRecord_object_to_global(record, sphere_translation, sphere);
record.intersection_point.x = record.intersection_point.x + record.normal.x * 0.001;
record.intersection_point.y = record.intersection_point.y + record.normal.y * 0.001;
record.intersection_point.z = record.intersection_point.z + record.normal.z * 0.001;
if (record.hit) {
const vec_to_light = record.intersection_point.to(light.position);
const vec_to_light_object = Transformation.ray_global_to_object(Ray{ .direction = vec_to_light, .origin = record.intersection_point }, sphere_translation);
const vec_to_light_object = Transformation.ray_global_to_object(Ray{ .direction = vec_to_light, .origin = record.intersection_point }, sphere_translation, sphere);
var obstacle = sphere.hits(vec_to_light_object);
obstacle = Transformation.hitRecord_object_to_global(obstacle, sphere_translation);
obstacle = Transformation.hitRecord_object_to_global(obstacle, sphere_translation, sphere);
if (obstacle.hit) {
image.pixels[index] = .{
.r = @as(u8, @intFromFloat(255.0 * ambiant_color_intensity)),
Expand Down

0 comments on commit 688a44a

Please sign in to comment.