added tsm scene; smoothunion, more transforms, fix mat3 product; expose problem with lua api

main
Codinget 3 years ago
parent eacc585127
commit ed05131b84
  1. BIN
      prod/tsm.png
  2. 7
      scenes/smolgalaxy.lua
  3. 157
      scenes/tsm.lua
  4. 16
      src/consts.rs
  5. 2
      src/lua/mat3.rs
  6. 8
      src/lua/obj.rs
  7. 20
      src/lua/transform.rs
  8. 2
      src/lua/util.lua
  9. 5
      src/main.rs
  10. 2
      src/object/mod.rs
  11. 42
      src/object/smoothunion.rs
  12. 81
      src/object/transform.rs
  13. 2
      src/structs/mat3.rs
  14. 3
      test

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

@ -70,7 +70,7 @@ local function randomtorus()
local thickness = util.randab(radius/4, radius) local thickness = util.randab(radius/4, radius)
local orientation = randomorientation() local orientation = randomorientation()
return obj.affinetransform(obj.torus(pos, radius, thickness), orientation, vec3.O) return util.transform(obj.torus(pos, radius, thickness), orientation)
end end
local function randomcuboid() local function randomcuboid()
@ -86,13 +86,12 @@ local function randomcylinder()
local height = util.randab(0, SCALE) local height = util.randab(0, SCALE)
local orientation = randomorientation() local orientation = randomorientation()
return obj.affinetransform( return util.transform(
obj.intersection( obj.intersection(
obj.cylinder(pos, radius), obj.cylinder(pos, radius),
obj.cuboid(pos, vec3.new(radius, height, radius)) obj.cuboid(pos, vec3.new(radius, height, radius))
), ),
orientation, orientation
vec3.O
) )
end end

@ -0,0 +1,157 @@
-- Scene developed by TSM71
-- Also this took 30 hours to render
local COLOR_BLACK = colorvec.new(0, 0, 0, 0)
local GRAY = material.newfromdiagonal(
COLOR_BLACK,
colorvec.new(0.5, 0.5, 0.5, 0.5),
surfacetype.DIFFUSE
)
local CYAN = material.newfromdiagonal(
COLOR_BLACK,
colorvec.new(0, 1, 1, 0),
surfacetype.DIFFUSE
)
local PINK = material.newfromdiagonal(
COLOR_BLACK,
colorvec.new(1, .5, .5, 0),
surfacetype.DIFFUSE
)
local RED = material.newfromdiagonal(
COLOR_BLACK,
colorvec.new(1, 0, 0, 0),
surfacetype.DIFFUSE
)
local MAGENTA = material.newfromdiagonal(
COLOR_BLACK,
colorvec.new(1, 0, 1, 0),
surfacetype.DIFFUSE
)
local MIRROR = material.newfromdiagonal(
COLOR_BLACK,
colorvec.new(1, 1, 1, 1),
surfacetype.REFLECTIVE
)
local FLUORESCENT = material.new(
COLOR_BLACK,
colormat.new(
.25, 0, 0, .25,
0, .25, 0, .75,
0, 0, .25, 0,
0, 0, 0, 0
),
surfacetype.DIFFUSE
)
--[[
obj.transformaround = function(a, b, c)
return util.translate(
util.transform(
util.translate(
a,
-c
),
b
),
c
)
end
--]]
--obj.transformaround = function(a, _b, _c) return a end
--obj.affinetransform = function(a, _b, _c) return a end
--obj.smoothunion = function(a, b, _r) return obj.union(a, b) end
---[[
util.stacktransforms = function(list)
--do return list[1] end
--do return list[#list] end
local n = #list
local a = mat3.I
--for i=n, 1, -1 do
for i=1, n do
a = list[i] * a
--a = a * list[i]
end
return a
end
--]]
return obj.withlights(
obj.transformaround(
obj.withlights(
util.union({
util.intersection({
util.union({
obj.withmaterial(
obj.negation(
util.union({
obj.cuboid(vec3.new(0, 0, 0), vec3.new(.5, 1, 4)),
obj.cuboid(vec3.new(0, 0, 0), vec3.new(4, 1, .5))
})
),
GRAY
),
obj.withmaterial(
util.intersection({
util.union({
obj.cuboid(vec3.new(0, 1, 0), vec3.new(.4, .1, 3.9)),
obj.cuboid(vec3.new(0, 1, 0), vec3.new(3.9, .1, .4))
}),
obj.negation(
util.union({
obj.cuboid(vec3.new(0, 1, 0), vec3.new(.3, 1, 3.8)),
obj.cuboid(vec3.new(0, 1, 0), vec3.new(3.8, 1, .3))
})
)
}),
FLUORESCENT
),
obj.smoothunion(
obj.withmaterial(
obj.sphere(vec3.new(0, .75, 0), .25),
CYAN
),
obj.withmaterial( -- withdynamicmaterial
obj.sphere(vec3.new(-.5, .5, 0), .25),
MAGENTA --dynamicmaterial.missingtexture(vec3.new(-.5, .5, 0))
),
.5
)
}),
obj.withmaterial(
obj.negation(
obj.cuboid(vec3.new(0, 0, 0), vec3.new(2, .25, 2))
),
PINK
)
}),
obj.withmaterial(
obj.cylinder(vec3.new(1, 0, 0), .375),
RED
),
util.transform(
obj.withmaterial(
obj.torus(vec3.new(0, 0, -1), .375, .125),
MIRROR
),
transform.SWAPYZ
)
}),
{
light.new(vec3.new(.45, 1-.2, -.45), colorvec.new(0, 0, 0, .1)),
--light.new(vec3.new(.45, 1-.2, -.45), colorvec.new(0, 0, 0, 1)),
}
),
util.stacktransforms({
transform.scalexyz(1, -1, 1),
transform.rotatez(10*math.pi/180),
}),
vec3.new(0, 0, -1.5)
),
{
light.new(vec3.new(0, .9375, 0), colorvec.new(.5, .25, 0, 0)),
light.new(vec3.new(0, .9375, -.625), colorvec.new(0, 0, 1, 0)),
--light.new(vec3.new(0, .9375, 0), colorvec.new(5, 2.5, 0, 0)),
--light.new(vec3.new(0, .9375, -.625), colorvec.new(0, 0, 10, 0)),
}
)

@ -20,21 +20,21 @@ pub const ANGLE_POWER: f64 = 2.;
//pub const IMG_WIDTH: usize = 480; //pub const IMG_WIDTH: usize = 480;
//pub const IMG_WIDTH: usize = 1280; //pub const IMG_WIDTH: usize = 1280;
//pub const IMG_WIDTH: usize = 1080; //pub const IMG_WIDTH: usize = 1080;
//pub const IMG_WIDTH: usize = 1920; pub const IMG_WIDTH: usize = 1920;
pub const IMG_WIDTH: usize = 4961; //pub const IMG_WIDTH: usize = 4961;
//pub const IMG_HEIGHT: usize = 480; //pub const IMG_HEIGHT: usize = 480;
//pub const IMG_HEIGHT: usize = 720; //pub const IMG_HEIGHT: usize = 720;
//pub const IMG_HEIGHT: usize = 1080; pub const IMG_HEIGHT: usize = 1080;
pub const IMG_HEIGHT: usize = 3508; //pub const IMG_HEIGHT: usize = 3508;
pub const IMG_DIM: usize = if IMG_HEIGHT > IMG_WIDTH { IMG_HEIGHT } else { IMG_WIDTH }; pub const IMG_DIM: usize = if IMG_HEIGHT > IMG_WIDTH { IMG_HEIGHT } else { IMG_WIDTH };
pub const IMG_SIZE: usize = IMG_WIDTH * IMG_HEIGHT; pub const IMG_SIZE: usize = IMG_WIDTH * IMG_HEIGHT;
pub const IMG_BYTE_SIZE: usize = IMG_SIZE * 3; pub const IMG_BYTE_SIZE: usize = IMG_SIZE * 3;
pub const SUPERSAMPLING: usize = 1; //pub const SUPERSAMPLING: usize = 1;
//pub const SUPERSAMPLING: usize = 2; pub const SUPERSAMPLING: usize = 2;
pub const RAYS_PER_PIXEL: usize = 1; //pub const RAYS_PER_PIXEL: usize = 1;
//pub const RAYS_PER_PIXEL: usize = 50; //pub const RAYS_PER_PIXEL: usize = 50;
//pub const RAYS_PER_PIXEL: usize = 500; pub const RAYS_PER_PIXEL: usize = 500;
//pub const MAX_BOUNCES: u32 = 1; //pub const MAX_BOUNCES: u32 = 1;
//pub const MAX_BOUNCES: u32 = 4; //pub const MAX_BOUNCES: u32 = 4;
//pub const MAX_BOUNCES: u32 = 8; //pub const MAX_BOUNCES: u32 = 8;

@ -7,7 +7,7 @@ impl UserData for Mat3 {
methods.add_meta_method(MetaMethod::Sub, |ctx, a: &Self, b: Self| Ok(*a-b)); methods.add_meta_method(MetaMethod::Sub, |ctx, a: &Self, b: Self| Ok(*a-b));
methods.add_meta_method(MetaMethod::Mul, |ctx, a: &Self, b: Self| Ok(*a*b)); methods.add_meta_method(MetaMethod::Mul, |ctx, a: &Self, b: Self| Ok(*a*b));
methods.add_meta_method(MetaMethod::Unm, |ctx, a: &Self, b: ()| Ok(-*a)); methods.add_meta_method(MetaMethod::Unm, |ctx, a: &Self, b: ()| Ok(-*a));
methods.add_meta_method(MetaMethod::Mul, |ctx, a: &Self, b: f64| Ok(*a*b)); //methods.add_meta_method(MetaMethod::Mul, |ctx, a: &Self, b: f64| Ok(*a*b)); //TODO find a way to make it cohabit
methods.add_meta_method(MetaMethod::Div, |ctx, a: &Self, b: f64| Ok(*a/b)); methods.add_meta_method(MetaMethod::Div, |ctx, a: &Self, b: f64| Ok(*a/b));
methods.add_method("a", |ctx, x, ()| Ok(x.a())); methods.add_method("a", |ctx, x, ()| Ok(x.a()));

@ -54,6 +54,10 @@ pub fn obj<'lua>(ctx: Context<'lua>, _env: Table<'lua>) -> rlua::Result<Table<'l
|ctx, (normal, offset): (Vec3, f64)| LuaObject::new(Plane::new(normal, offset)) |ctx, (normal, offset): (Vec3, f64)| LuaObject::new(Plane::new(normal, offset))
)?)?; )?)?;
module.set("smoothunion", ctx.create_function(
|ctx, (a, b, r): (LuaObject, LuaObject, f64)| LuaObject::new(SmoothUnion::new(a.get(), b.get(), r))
)?)?;
module.set("sphere", ctx.create_function( module.set("sphere", ctx.create_function(
|ctx, (pos, radius): (Vec3, f64)| LuaObject::new(Sphere::new(pos, radius)) |ctx, (pos, radius): (Vec3, f64)| LuaObject::new(Sphere::new(pos, radius))
)?)?; )?)?;
@ -66,6 +70,10 @@ pub fn obj<'lua>(ctx: Context<'lua>, _env: Table<'lua>) -> rlua::Result<Table<'l
|ctx, (obj, trans, disp): (LuaObject, Mat3, Vec3)| LuaObject::new(AffineTransform::new(obj.get(), trans, disp)) |ctx, (obj, trans, disp): (LuaObject, Mat3, Vec3)| LuaObject::new(AffineTransform::new(obj.get(), trans, disp))
)?)?; )?)?;
module.set("transformaround", ctx.create_function(
|ctx, (obj, trans, center): (LuaObject, Mat3, Vec3)| LuaObject::new(TransformAround::new(obj.get(), trans, center))
)?)?;
module.set("union", ctx.create_function( module.set("union", ctx.create_function(
|ctx, (a, b): (LuaObject, LuaObject)| LuaObject::new(Union::new(a.get(), b.get())) |ctx, (a, b): (LuaObject, LuaObject)| LuaObject::new(Union::new(a.get(), b.get()))
)?)?; )?)?;

@ -1,5 +1,5 @@
use rlua::{Context, Table, Error}; use rlua::{Context, Table};
use crate::object::{SWAP_XY, SWAP_YZ, SWAP_XZ, scale_xyz, scale, scale_x, scale_y, scale_z}; use crate::object::{SWAP_XY, SWAP_YZ, SWAP_XZ, scale_xyz, scale, scale_x, scale_y, scale_z, rotate_xyz, rotate_x, rotate_z, rotate_y};
use crate::structs::{Mat3, I3}; use crate::structs::{Mat3, I3};
pub fn transform<'lua>(ctx: Context<'lua>, _env: Table<'lua>) -> rlua::Result<Table<'lua>> { pub fn transform<'lua>(ctx: Context<'lua>, _env: Table<'lua>) -> rlua::Result<Table<'lua>> {
@ -26,11 +26,25 @@ pub fn transform<'lua>(ctx: Context<'lua>, _env: Table<'lua>) -> rlua::Result<Ta
|ctx, k| Ok(scale_z(k)) |ctx, k| Ok(scale_z(k))
)?)?; )?)?;
module.set("rotatexyz", ctx.create_function(
|ctx, (x, y, z)| Ok(rotate_xyz(x, y, z))
)?)?;
module.set("rotatex", ctx.create_function(
|ctx, a| Ok(rotate_x(a))
)?)?;
module.set("rotatey", ctx.create_function(
|ctx, a| Ok(rotate_y(a))
)?)?;
module.set("rotatez", ctx.create_function(
|ctx, a| Ok(rotate_z(a))
)?)?;
module.set("stack", ctx.create_function( module.set("stack", ctx.create_function(
|ctx, transforms: Vec<Mat3>| { |ctx, transforms: Vec<Mat3>| {
let mut acc = I3; let mut acc = I3;
for trans in transforms.iter().rev().cloned() { for trans in transforms.iter().rev().cloned() {
acc = trans * I3; acc = acc * trans;
} }
Ok(acc) Ok(acc)
} }

@ -65,7 +65,7 @@ function M.transform(object, mat)
return obj.affinetransform(object, mat, vec3.O) return obj.affinetransform(object, mat, vec3.O)
end end
function M.translate(object, vec) function M.translate(object, vec)
return obj.affinetransform(object, mat3.O, vec) return obj.affinetransform(object, mat3.I, vec)
end end
return M return M

@ -85,9 +85,10 @@ fn default_scene3() -> Scene {
fn main() { fn main() {
// get scene and camera // get scene and camera
let scene = scene_from_file("scenes/randomspheres.lua".to_owned()).unwrap(); let scene = scene_from_file("scenes/tsm.lua".to_owned()).unwrap();
//let scene = default_scene3(); //let scene = default_scene3();
let cam = default_cam(); let cam = Cam::new(Z * -1.5, Z, f64::sqrt(2.));
//let cam = default_cam();
// get stats on the scene we're about to render // get stats on the scene we're about to render
let total_rpp = (RAYS_PER_PIXEL * SUPERSAMPLING * SUPERSAMPLING) as u64; let total_rpp = (RAYS_PER_PIXEL * SUPERSAMPLING * SUPERSAMPLING) as u64;

@ -8,6 +8,7 @@ use std::vec::Vec;
mod sphere; mod sphere;
mod plane; mod plane;
mod union; mod union;
mod smoothunion;
mod intersection; mod intersection;
mod exclusion; mod exclusion;
mod negation; mod negation;
@ -64,6 +65,7 @@ impl<T: 'static + Obj + Clone> ObjClone for T {
pub use sphere::Sphere; pub use sphere::Sphere;
pub use plane::Plane; pub use plane::Plane;
pub use union::Union; pub use union::Union;
pub use smoothunion::SmoothUnion;
pub use intersection::Intersection; pub use intersection::Intersection;
pub use exclusion::Exclusion; pub use exclusion::Exclusion;
pub use negation::Negation; pub use negation::Negation;

@ -0,0 +1,42 @@
use crate::object::Obj;
use crate::light::Light;
use crate::structs::Vec3;
use std::vec;
use crate::material::Material;
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct SmoothUnion<A: Obj, B: Obj> {
a: A,
b: B,
r: f64
}
impl<A: Obj, B: Obj> SmoothUnion<A, B> {
pub fn new(a: A, b: B, r: f64) -> SmoothUnion<A, B> {
SmoothUnion { a, b, r }
}
}
impl<A: Obj, B: Obj> Obj for SmoothUnion<A, B> {
fn distance_to(&self, point: Vec3) -> f64 {
let d1 = self.a.distance_to(point);
let d2 = self.b.distance_to(point);
let h = f64::max(self.r - f64::abs(d1-d2),0.);
d1.min(d2) - h*h*0.25 / self.r
}
fn material_at(&self, point: Vec3) -> Material {
if self.a.distance_to(point) < self.b.distance_to(point) {
self.a.material_at(point)
} else {
self.b.material_at(point)
}
}
fn get_lights(&self) -> vec::Vec<Light> {
let mut l = self.a.get_lights();
l.extend(self.b.get_lights());
l
}
fn node_count(&self) -> u32 {
self.a.node_count() + self.b.node_count() + 1
}
}

@ -14,10 +14,10 @@ pub struct AffineTransform<T: Obj + Clone> {
impl<T: Obj + Clone> AffineTransform<T> { impl<T: Obj + Clone> AffineTransform<T> {
pub fn new(obj: T, transform: Mat3, translate: Vec3) -> AffineTransform<T> { pub fn new(obj: T, transform: Mat3, translate: Vec3) -> AffineTransform<T> {
AffineTransform { obj, transform, transform_inv: transform.invert(), translate, scale: transform.det().cbrt() } AffineTransform { obj, transform, transform_inv: transform.invert(), translate, scale: transform.det().abs().cbrt() }
} }
pub fn new_linear(obj: T, transform: Mat3) -> AffineTransform<T> { pub fn new_linear(obj: T, transform: Mat3) -> AffineTransform<T> {
AffineTransform { obj, transform, transform_inv: transform.invert(), translate: O, scale: transform.det().cbrt() } AffineTransform { obj, transform, transform_inv: transform.invert(), translate: O, scale: transform.det().abs().cbrt() }
} }
pub fn new_translate(obj: T, translate: Vec3) -> AffineTransform<T> { pub fn new_translate(obj: T, translate: Vec3) -> AffineTransform<T> {
AffineTransform { obj, transform: I3, transform_inv: I3, translate, scale: 1. } AffineTransform { obj, transform: I3, transform_inv: I3, translate, scale: 1. }
@ -59,6 +59,37 @@ pub const fn scale_x(k: f64) -> Mat3 { scale_xyz(k, 1., 1.) }
pub const fn scale_y(k: f64) -> Mat3 { scale_xyz(1., k, 1.) } pub const fn scale_y(k: f64) -> Mat3 { scale_xyz(1., k, 1.) }
pub const fn scale_z(k: f64) -> Mat3 { scale_xyz(1., 1., k) } pub const fn scale_z(k: f64) -> Mat3 { scale_xyz(1., 1., k) }
pub fn rotate_x(a: f64) -> Mat3 {
let c = a.cos();
let s = a.sin();
Mat3::new(
1., 0., 0.,
0., c, -s,
0., s, c
)
}
pub fn rotate_y(a: f64) -> Mat3 {
let c = a.cos();
let s = a.sin();
Mat3::new(
c, 0., s,
0., 1., 0.,
-s, 0., c
)
}
pub fn rotate_z(a: f64) -> Mat3 {
let c = a.cos();
let s = a.sin();
Mat3::new(
c, -s, 0.,
s, c, 0.,
0., 0., 1.
)
}
pub fn rotate_xyz(x: f64, y: f64, z: f64) -> Mat3 {
rotate_z(z) * rotate_y(y) * rotate_x(x)
}
impl<T: Obj + Clone> Obj for AffineTransform<T> { impl<T: Obj + Clone> Obj for AffineTransform<T> {
fn distance_to(&self, point: Vec3) -> f64 { fn distance_to(&self, point: Vec3) -> f64 {
self.obj.distance_to(self.apply_rev(point)) * self.scale self.obj.distance_to(self.apply_rev(point)) * self.scale
@ -82,3 +113,49 @@ impl<T: Obj + Clone> Obj for AffineTransform<T> {
self.obj.node_count() + 1 self.obj.node_count() + 1
} }
} }
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct TransformAround<T: Obj + Clone> {
obj: T,
transform: Mat3,
transform_inv: Mat3,
center: Vec3,
scale: f64
}
impl<T: Obj + Clone> TransformAround<T> {
pub fn new(obj: T, transform: Mat3, center: Vec3) -> TransformAround<T> {
TransformAround { obj, transform, transform_inv: transform.invert(), center, scale: transform.det().abs().cbrt() }
}
fn apply_rev(&self, point: Vec3) -> Vec3 {
self.transform_inv * (point + self.center) - self.center
}
fn apply_fwd(&self, point: Vec3) -> Vec3 {
self.transform * (point - self.center) + self.center
}
}
impl<T: Obj + Clone> Obj for TransformAround<T> {
fn distance_to(&self, point: Vec3) -> f64 {
self.obj.distance_to(self.apply_rev(point)) * self.scale
}
fn normal_at(&self, point: Vec3) -> Vec3 {
self.apply_fwd(self.obj.normal_at(self.apply_rev(point))).unit()
}
fn material_at(&self, point: Vec3) -> Material {
self.obj.material_at(self.apply_rev(point))
}
fn get_lights(&self) -> Vec<Light> {
self.obj
.get_lights()
.into_iter()
.map(|light| {
Light::new(self.apply_fwd(light.pos()), light.color())
})
.collect()
}
fn node_count(&self) -> u32 {
self.obj.node_count() + 1
}
}

@ -137,7 +137,7 @@ impl Mul<Mat3> for Mat3 {
d: self.d*other.a + self.e*other.d + self.f*other.g, d: self.d*other.a + self.e*other.d + self.f*other.g,
e: self.d*other.b + self.e*other.e + self.f*other.h, e: self.d*other.b + self.e*other.e + self.f*other.h,
f: self.d*other.c + self.e*other.f + self.e*other.i, f: self.d*other.c + self.e*other.f + self.f*other.i,
g: self.g*other.a + self.h*other.d + self.i*other.g, g: self.g*other.a + self.h*other.d + self.i*other.g,
h: self.g*other.b + self.h*other.e + self.i*other.h, h: self.g*other.b + self.h*other.e + self.i*other.h,

@ -1,7 +1,8 @@
#!/bin/bash #!/bin/bash
[ -z "$SEED" ] && export SEED=0
clear clear
cargo build --release && \ cargo build --release && \
clear && \ clear && \
time SEED=0 target/release/rmarcher && \ time target/release/rmarcher && \
printf '\n' && \ printf '\n' && \
kitty +kitten icat --align=left a.png kitty +kitten icat --align=left a.png

Loading…
Cancel
Save