more lua support, fixed scene 3
This commit is contained in:
@@ -19,7 +19,6 @@ A ray marching renderer in rust
|
|||||||
|
|
||||||
## What is planned
|
## What is planned
|
||||||
- Testing of more shapes
|
- Testing of more shapes
|
||||||
- Support for a lua-based scene representation DSL
|
|
||||||
- Support for controlling the whole application from lua
|
- Support for controlling the whole application from lua
|
||||||
- Support for linking against a `scene.so` exporting a scene
|
- Support for linking against a `scene.so` exporting a scene
|
||||||
- Support for using as a library
|
- Support for using as a library
|
||||||
@@ -27,6 +26,7 @@ A ray marching renderer in rust
|
|||||||
## Examples
|
## Examples
|
||||||

|

|
||||||

|

|
||||||
|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
|
|||||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
@@ -1,28 +1,20 @@
|
|||||||
local unpack = table.unpack or _G.unpack
|
local unpack = table.unpack or _G.unpack
|
||||||
math.randomseed(os.time())
|
util.seed()
|
||||||
|
|
||||||
local function randab(a, b)
|
|
||||||
return math.random() * (b-a) + a
|
|
||||||
end
|
|
||||||
|
|
||||||
local function randtable(n, a, b)
|
local function randtable(n, a, b)
|
||||||
local t = {}
|
local t = {}
|
||||||
for i=1, n do
|
for i=1, n do
|
||||||
t[i] = randab(a, b)
|
t[i] = util.randab(a, b)
|
||||||
end
|
end
|
||||||
return t
|
return t
|
||||||
end
|
end
|
||||||
|
|
||||||
local function choice(list)
|
|
||||||
return list[math.random(1, #list)]
|
|
||||||
end
|
|
||||||
|
|
||||||
local function randomsphere()
|
local function randomsphere()
|
||||||
local pos = vec3.new(unpack(randtable(3, -2, 2)))
|
local pos = vec3.new(unpack(randtable(3, -2, 2)))
|
||||||
local radius = randab(0, 0.5)
|
local radius = util.randab(0, 0.5)
|
||||||
local emission = colorvec.new(unpack(randtable(4, 0, 1)))
|
local emission = colorvec.new(unpack(randtable(4, 0, 1)))
|
||||||
local reflection = colormat.new(unpack(randtable(16, 0, 1)))
|
local reflection = colormat.new(unpack(randtable(16, 0, 1)))
|
||||||
local surfacetype = choice({surfacetype.DIFFUSE, surfacetype.REFLECTIVE, surfacetype.STOP})
|
local surfacetype = util.choice({surfacetype.DIFFUSE, surfacetype.REFLECTIVE, surfacetype.STOP})
|
||||||
|
|
||||||
return obj.withmaterial(
|
return obj.withmaterial(
|
||||||
obj.sphere(pos, radius),
|
obj.sphere(pos, radius),
|
||||||
@@ -30,23 +22,8 @@ local function randomsphere()
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function union(objs)
|
|
||||||
local n = #objs
|
|
||||||
if n == 1 then return objs[1] end
|
|
||||||
|
|
||||||
local mid = n//2
|
|
||||||
local left, right = {}, {}
|
|
||||||
for i=1, mid do
|
|
||||||
left[i] = objs[i]
|
|
||||||
end
|
|
||||||
for i=mid+1, n do
|
|
||||||
right[i-mid] = objs[i]
|
|
||||||
end
|
|
||||||
return obj.union(union(left), union(right))
|
|
||||||
end
|
|
||||||
|
|
||||||
local spheres = {}
|
local spheres = {}
|
||||||
for i=1, 100 do
|
for i=1, 100 do
|
||||||
spheres[i] = randomsphere()
|
spheres[i] = randomsphere()
|
||||||
end
|
end
|
||||||
return union(spheres)
|
return util.union(spheres)
|
||||||
+11
-34
@@ -1,30 +1,22 @@
|
|||||||
local unpack = table.unpack or _G.unpack
|
local unpack = table.unpack or _G.unpack
|
||||||
math.randomseed(os.time())
|
util.seed()
|
||||||
|
|
||||||
local SCALE = 0.3
|
local SCALE = 0.3
|
||||||
local N_EACH = 25
|
local N_EACH = 25
|
||||||
|
|
||||||
local function randab(a, b)
|
|
||||||
return math.random() * (b-a) + a
|
|
||||||
end
|
|
||||||
|
|
||||||
local function randtable(n, a, b)
|
local function randtable(n, a, b)
|
||||||
local t = {}
|
local t = {}
|
||||||
for i=1, n do
|
for i=1, n do
|
||||||
t[i] = randab(a, b)
|
t[i] = util.randab(a, b)
|
||||||
end
|
end
|
||||||
return t
|
return t
|
||||||
end
|
end
|
||||||
|
|
||||||
local function choice(list)
|
|
||||||
return list[math.random(1, #list)]
|
|
||||||
end
|
|
||||||
|
|
||||||
local MATERIALS = {surfacetype.DIFFUSE, surfacetype.REFLECTIVE, surfacetype.STOP}
|
local MATERIALS = {surfacetype.DIFFUSE, surfacetype.REFLECTIVE, surfacetype.STOP}
|
||||||
local function randommaterial()
|
local function randommaterial()
|
||||||
local emission = colorvec.new(unpack(randtable(4, 0, 1)))
|
local emission = colorvec.new(unpack(randtable(4, 0, 1)))
|
||||||
local reflection = colormat.new(unpack(randtable(16, 0, 1)))
|
local reflection = colormat.new(unpack(randtable(16, 0, 1)))
|
||||||
local surfacetype = choice(MATERIALS)
|
local surfacetype = util.choice(MATERIALS)
|
||||||
|
|
||||||
return material.new(emission, reflection, surfacetype)
|
return material.new(emission, reflection, surfacetype)
|
||||||
end
|
end
|
||||||
@@ -62,20 +54,20 @@ local ORIENTATIONS = {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
local function randomorientation()
|
local function randomorientation()
|
||||||
return choice(ORIENTATIONS)
|
return util.choice(ORIENTATIONS)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function randomsphere()
|
local function randomsphere()
|
||||||
local pos = vec3.new(unpack(randtable(3, -2, 2)))
|
local pos = vec3.new(unpack(randtable(3, -2, 2)))
|
||||||
local radius = randab(0, SCALE)
|
local radius = util.randab(0, SCALE)
|
||||||
|
|
||||||
return obj.sphere(pos, radius)
|
return obj.sphere(pos, radius)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function randomtorus()
|
local function randomtorus()
|
||||||
local pos = vec3.new(unpack(randtable(3, -2, 2)))
|
local pos = vec3.new(unpack(randtable(3, -2, 2)))
|
||||||
local radius = randab(0, SCALE)
|
local radius = util.randab(0, SCALE)
|
||||||
local thickness = 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 obj.affinetransform(obj.torus(pos, radius, thickness), orientation, vec3.O)
|
||||||
@@ -83,15 +75,15 @@ end
|
|||||||
|
|
||||||
local function randomcuboid()
|
local function randomcuboid()
|
||||||
local pos = vec3.new(unpack(randtable(3, -2, 2)))
|
local pos = vec3.new(unpack(randtable(3, -2, 2)))
|
||||||
local radius = randab(0, SCALE)
|
local radius = util.randab(0, SCALE)
|
||||||
|
|
||||||
return obj.cuboid(pos, vec3.new(radius, radius, radius))
|
return obj.cuboid(pos, vec3.new(radius, radius, radius))
|
||||||
end
|
end
|
||||||
|
|
||||||
local function randomcylinder()
|
local function randomcylinder()
|
||||||
local pos = vec3.new(unpack(randtable(3, -2, 2)))
|
local pos = vec3.new(unpack(randtable(3, -2, 2)))
|
||||||
local radius = randab(0, SCALE)
|
local radius = util.randab(0, SCALE)
|
||||||
local height = randab(0, SCALE)
|
local height = util.randab(0, SCALE)
|
||||||
local orientation = randomorientation()
|
local orientation = randomorientation()
|
||||||
|
|
||||||
return obj.affinetransform(
|
return obj.affinetransform(
|
||||||
@@ -104,25 +96,10 @@ local function randomcylinder()
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function union(objs)
|
|
||||||
local n = #objs
|
|
||||||
if n == 1 then return objs[1] end
|
|
||||||
|
|
||||||
local mid = n//2
|
|
||||||
local left, right = {}, {}
|
|
||||||
for i=1, mid do
|
|
||||||
left[i] = objs[i]
|
|
||||||
end
|
|
||||||
for i=mid+1, n do
|
|
||||||
right[i-mid] = objs[i]
|
|
||||||
end
|
|
||||||
return obj.union(union(left), union(right))
|
|
||||||
end
|
|
||||||
|
|
||||||
local objects = {}
|
local objects = {}
|
||||||
for i=1, N_EACH do table.insert(objects, randomsphere()) end
|
for i=1, N_EACH do table.insert(objects, randomsphere()) end
|
||||||
for i=1, N_EACH do table.insert(objects, randomtorus()) end
|
for i=1, N_EACH do table.insert(objects, randomtorus()) end
|
||||||
for i=1, N_EACH do table.insert(objects, randomcuboid()) end
|
for i=1, N_EACH do table.insert(objects, randomcuboid()) end
|
||||||
for i=1, N_EACH do table.insert(objects, randomcylinder()) end
|
for i=1, N_EACH do table.insert(objects, randomcylinder()) end
|
||||||
for i, object in ipairs(objects) do objects[i] = obj.withmaterial(object, randommaterial()) end
|
for i, object in ipairs(objects) do objects[i] = obj.withmaterial(object, randommaterial()) end
|
||||||
return union(objects)
|
return util.union(objects)
|
||||||
+2
-2
@@ -4,7 +4,7 @@ use rlua::{UserData, Context, Table};
|
|||||||
impl UserData for ColorVec {}
|
impl UserData for ColorVec {}
|
||||||
impl UserData for ColorMat {}
|
impl UserData for ColorMat {}
|
||||||
|
|
||||||
pub fn color_vec(ctx: Context, _: ()) -> rlua::Result<Table> {
|
pub fn color_vec<'lua>(ctx: Context<'lua>, _env: Table<'lua>) -> rlua::Result<Table<'lua>> {
|
||||||
let module = ctx.create_table()?;
|
let module = ctx.create_table()?;
|
||||||
|
|
||||||
module.set("new", ctx.create_function(
|
module.set("new", ctx.create_function(
|
||||||
@@ -16,7 +16,7 @@ pub fn color_vec(ctx: Context, _: ()) -> rlua::Result<Table> {
|
|||||||
Ok(module)
|
Ok(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn color_mat(ctx: Context, _: ()) -> rlua::Result<Table> {
|
pub fn color_mat<'lua>(ctx: Context<'lua>, _env: Table<'lua>) -> rlua::Result<Table<'lua>> {
|
||||||
let module = ctx.create_table()?;
|
let module = ctx.create_table()?;
|
||||||
|
|
||||||
module.set("new", ctx.create_function(
|
module.set("new", ctx.create_function(
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ use rlua::{UserData, Context, Table};
|
|||||||
|
|
||||||
impl UserData for Light {}
|
impl UserData for Light {}
|
||||||
|
|
||||||
pub fn light(ctx: Context, _: ()) -> rlua::Result<Table> {
|
pub fn light<'lua>(ctx: Context<'lua>, _env: Table<'lua>) -> rlua::Result<Table<'lua>> {
|
||||||
let module = ctx.create_table()?;
|
let module = ctx.create_table()?;
|
||||||
|
|
||||||
module.set("new", ctx.create_function(
|
module.set("new", ctx.create_function(
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ impl UserData for Mat3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mat3(ctx: Context, _: ()) -> rlua::Result<Table> {
|
pub fn mat3<'lua>(ctx: Context<'lua>, _env: Table<'lua>) -> rlua::Result<Table<'lua>> {
|
||||||
let module = ctx.create_table()?;
|
let module = ctx.create_table()?;
|
||||||
|
|
||||||
module.set("new", ctx.create_function(
|
module.set("new", ctx.create_function(
|
||||||
|
|||||||
+2
-2
@@ -4,7 +4,7 @@ use rlua::{UserData, Context, Table};
|
|||||||
impl UserData for SurfaceType {}
|
impl UserData for SurfaceType {}
|
||||||
impl UserData for Material {}
|
impl UserData for Material {}
|
||||||
|
|
||||||
pub fn surface_type(ctx: Context, _: ()) -> rlua::Result<Table> {
|
pub fn surface_type<'lua>(ctx: Context<'lua>, _env: Table<'lua>) -> rlua::Result<Table<'lua>> {
|
||||||
let module = ctx.create_table()?;
|
let module = ctx.create_table()?;
|
||||||
|
|
||||||
module.set("DIFFUSE", SurfaceType::Diffuse)?;
|
module.set("DIFFUSE", SurfaceType::Diffuse)?;
|
||||||
@@ -14,7 +14,7 @@ pub fn surface_type(ctx: Context, _: ()) -> rlua::Result<Table> {
|
|||||||
Ok(module)
|
Ok(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn material(ctx: Context, _: ()) -> rlua::Result<Table> {
|
pub fn material<'lua>(ctx: Context<'lua>, _env: Table<'lua>) -> rlua::Result<Table<'lua>> {
|
||||||
let module = ctx.create_table()?;
|
let module = ctx.create_table()?;
|
||||||
|
|
||||||
module.set("new", ctx.create_function(
|
module.set("new", ctx.create_function(
|
||||||
|
|||||||
+18
-13
@@ -6,6 +6,8 @@ mod mat3;
|
|||||||
mod color;
|
mod color;
|
||||||
mod material;
|
mod material;
|
||||||
mod light;
|
mod light;
|
||||||
|
mod transform;
|
||||||
|
mod util;
|
||||||
|
|
||||||
pub use obj::{LuaObject, obj};
|
pub use obj::{LuaObject, obj};
|
||||||
pub use vec3::vec3;
|
pub use vec3::vec3;
|
||||||
@@ -13,25 +15,28 @@ pub use mat3::mat3;
|
|||||||
pub use color::{color_vec, color_mat};
|
pub use color::{color_vec, color_mat};
|
||||||
pub use material::{surface_type, material};
|
pub use material::{surface_type, material};
|
||||||
pub use light::light;
|
pub use light::light;
|
||||||
|
pub use transform::transform;
|
||||||
|
pub use util::util;
|
||||||
|
|
||||||
pub fn env(ctx: Context, _: ()) -> rlua::Result<Table> {
|
pub fn add_scene_env<'lua>(ctx: Context<'lua>, env: Table<'lua>) -> rlua::Result<Table<'lua>> {
|
||||||
let module = ctx.create_table()?;
|
env.set("obj", obj(ctx, env.clone())?)?;
|
||||||
|
env.set("vec3", vec3(ctx, env.clone())?)?;
|
||||||
|
env.set("mat3", mat3(ctx, env.clone())?)?;
|
||||||
|
env.set("colorvec", color_vec(ctx, env.clone())?)?;
|
||||||
|
env.set("colormat", color_mat(ctx, env.clone())?)?;
|
||||||
|
env.set("surfacetype", surface_type(ctx, env.clone())?)?;
|
||||||
|
env.set("material", material(ctx, env.clone())?)?;
|
||||||
|
env.set("light", light(ctx, env.clone())?)?;
|
||||||
|
env.set("transform", transform(ctx, env.clone())?)?;
|
||||||
|
env.set("util", util(ctx, env.clone())?)?;
|
||||||
|
|
||||||
module.set("obj", obj(ctx, ())?)?;
|
Ok(env)
|
||||||
module.set("vec3", vec3(ctx, ())?)?;
|
|
||||||
module.set("mat3", mat3(ctx, ())?)?;
|
|
||||||
module.set("colorvec", color_vec(ctx, ())?)?;
|
|
||||||
module.set("colormat", color_mat(ctx, ())?)?;
|
|
||||||
module.set("surfacetype", surface_type(ctx, ())?)?;
|
|
||||||
module.set("material", material(ctx, ())?)?;
|
|
||||||
module.set("light", light(ctx, ())?)?;
|
|
||||||
|
|
||||||
Ok(module)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scene_from_file(file: String) -> rlua::Result<LuaObject> {
|
pub fn scene_from_file(file: String) -> rlua::Result<LuaObject> {
|
||||||
Lua::new().context(|ctx| {
|
Lua::new().context(|ctx| {
|
||||||
let env = env(ctx, ())?;
|
let env = ctx.create_table()?;
|
||||||
|
add_scene_env(ctx, env.clone())?;
|
||||||
let meta = ctx.create_table()?;
|
let meta = ctx.create_table()?;
|
||||||
meta.set("__index", ctx.globals())?;
|
meta.set("__index", ctx.globals())?;
|
||||||
env.set_metatable(Some(meta));
|
env.set_metatable(Some(meta));
|
||||||
|
|||||||
+6
-2
@@ -27,7 +27,7 @@ impl Obj for LuaObject {
|
|||||||
|
|
||||||
impl UserData for LuaObject {}
|
impl UserData for LuaObject {}
|
||||||
|
|
||||||
pub fn obj(ctx: Context, _: ()) -> rlua::Result<Table> {
|
pub fn obj<'lua>(ctx: Context<'lua>, _env: Table<'lua>) -> rlua::Result<Table<'lua>> {
|
||||||
let module = ctx.create_table()?;
|
let module = ctx.create_table()?;
|
||||||
|
|
||||||
module.set("cuboid", ctx.create_function(
|
module.set("cuboid", ctx.create_function(
|
||||||
@@ -70,10 +70,14 @@ pub fn obj(ctx: Context, _: ()) -> rlua::Result<Table> {
|
|||||||
|ctx, ()| LuaObject::new(Waves::new())
|
|ctx, ()| LuaObject::new(Waves::new())
|
||||||
)?)?;
|
)?)?;
|
||||||
|
|
||||||
module.set("withlights", ctx.create_function(
|
module.set("withlight", ctx.create_function(
|
||||||
|ctx, (obj, light): (LuaObject, Light)| LuaObject::new(WithLights::new_one(obj.get(), light))
|
|ctx, (obj, light): (LuaObject, Light)| LuaObject::new(WithLights::new_one(obj.get(), light))
|
||||||
)?)?;
|
)?)?;
|
||||||
|
|
||||||
|
module.set("withlights", ctx.create_function(
|
||||||
|
|ctx, (obj, lights): (LuaObject, Vec<Light>)| LuaObject::new(WithAnyLights::new(obj.get(), lights))
|
||||||
|
)?)?;
|
||||||
|
|
||||||
module.set("withmaterial", ctx.create_function(
|
module.set("withmaterial", ctx.create_function(
|
||||||
|ctx, (obj, material): (LuaObject, Material)| LuaObject::new(WithMaterial::new(obj.get(), material))
|
|ctx, (obj, material): (LuaObject, Material)| LuaObject::new(WithMaterial::new(obj.get(), material))
|
||||||
)?)?;
|
)?)?;
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
use rlua::{Context, Table, Error};
|
||||||
|
use crate::object::{SWAP_XY, SWAP_YZ, SWAP_XZ, scale_xyz, scale, scale_x, scale_y, scale_z};
|
||||||
|
use crate::structs::{Mat3, I3};
|
||||||
|
|
||||||
|
pub fn transform<'lua>(ctx: Context<'lua>, _env: Table<'lua>) -> rlua::Result<Table<'lua>> {
|
||||||
|
let module = ctx.create_table()?;
|
||||||
|
|
||||||
|
module.set("SWAPXY", SWAP_XY)?;
|
||||||
|
module.set("SWAPXZ", SWAP_XZ)?;
|
||||||
|
module.set("SWAPYZ", SWAP_YZ)?;
|
||||||
|
|
||||||
|
module.set("scalexyz", ctx.create_function(
|
||||||
|
|ctx, (x, y, z)| Ok(scale_xyz(x, y, z))
|
||||||
|
)?)?;
|
||||||
|
module.set("scale", ctx.create_function(
|
||||||
|
|ctx, k| Ok(scale(k))
|
||||||
|
)?)?;
|
||||||
|
|
||||||
|
module.set("scalex", ctx.create_function(
|
||||||
|
|ctx, k| Ok(scale_x(k))
|
||||||
|
)?)?;
|
||||||
|
module.set("scaley", ctx.create_function(
|
||||||
|
|ctx, k| Ok(scale_y(k))
|
||||||
|
)?)?;
|
||||||
|
module.set("scalez", ctx.create_function(
|
||||||
|
|ctx, k| Ok(scale_z(k))
|
||||||
|
)?)?;
|
||||||
|
|
||||||
|
module.set("stack", ctx.create_function(
|
||||||
|
|ctx, transforms: Vec<Mat3>| {
|
||||||
|
let mut acc = I3;
|
||||||
|
for trans in transforms.iter().rev().cloned() {
|
||||||
|
acc = trans * I3;
|
||||||
|
}
|
||||||
|
Ok(acc)
|
||||||
|
}
|
||||||
|
)?)?;
|
||||||
|
|
||||||
|
Ok(module)
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
local env = ...
|
||||||
|
local obj = env.obj
|
||||||
|
local vec3 = env.vec3
|
||||||
|
local mat3 = env.mat3
|
||||||
|
local transform = env.transform
|
||||||
|
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
-- technically a binary fold
|
||||||
|
local function binstack(objs, fn)
|
||||||
|
local n = #objs
|
||||||
|
if n == 1 then return objs[1] end
|
||||||
|
|
||||||
|
local mid = n//2
|
||||||
|
local left, right = {}, {}
|
||||||
|
for i=1, mid do
|
||||||
|
left[i] = objs[i]
|
||||||
|
end
|
||||||
|
for i=mid+1, n do
|
||||||
|
right[i-mid] = objs[i]
|
||||||
|
end
|
||||||
|
return fn(binstack(left, fn), binstack(right, fn))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- technically a fold
|
||||||
|
local function linstack(objs, fn)
|
||||||
|
local head = objs[1]
|
||||||
|
for i=2, #objs do
|
||||||
|
head = fn(head, objs[i])
|
||||||
|
end
|
||||||
|
return head
|
||||||
|
end
|
||||||
|
|
||||||
|
-- random functions
|
||||||
|
local SEED = os.getenv "SEED" or os.time()
|
||||||
|
function M.seed()
|
||||||
|
math.randomseed(SEED)
|
||||||
|
end
|
||||||
|
function M.randab(a, b)
|
||||||
|
return math.random() * (b-a) + a
|
||||||
|
end
|
||||||
|
function M.choice(list)
|
||||||
|
return list[math.random(1, #list)]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- multiple object composition
|
||||||
|
function M.union(objs)
|
||||||
|
return binstack(objs, obj.union)
|
||||||
|
end
|
||||||
|
function M.intersection(objs)
|
||||||
|
return binstack(objs, obj.intersection)
|
||||||
|
end
|
||||||
|
function M.smoothunion(objs, k)
|
||||||
|
return linstack(objs, function(a, b) return obj.smoothunion(a, b, k) end)
|
||||||
|
end
|
||||||
|
function M.smoothintersection(objs, k)
|
||||||
|
return linstack(objs, function(a, b) return obj.smoothintersection(a, b, k) end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- simpler transformations
|
||||||
|
function M.scale(object, k)
|
||||||
|
return obj.affinetransform(object, transform.scale(k), vec3.O)
|
||||||
|
end
|
||||||
|
function M.transform(object, mat)
|
||||||
|
return obj.affinetransform(object, mat, vec3.O)
|
||||||
|
end
|
||||||
|
function M.translate(object, vec)
|
||||||
|
return obj.affinetransform(object, mat3.O, vec)
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
use rlua::{Context, Table};
|
||||||
|
|
||||||
|
pub fn util<'lua>(ctx: Context<'lua>, env: Table<'lua>) -> rlua::Result<Table<'lua>> {
|
||||||
|
ctx.load(include_str!("util.lua")).call(env)
|
||||||
|
}
|
||||||
+1
-1
@@ -24,7 +24,7 @@ impl UserData for Vec3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vec3(ctx: Context, _: ()) -> rlua::Result<Table> {
|
pub fn vec3<'lua>(ctx: Context<'lua>, _env: Table<'lua>) -> rlua::Result<Table<'lua>> {
|
||||||
let module = ctx.create_table()?;
|
let module = ctx.create_table()?;
|
||||||
|
|
||||||
module.set("new", ctx.create_function(
|
module.set("new", ctx.create_function(
|
||||||
|
|||||||
+3
-3
@@ -68,8 +68,7 @@ fn default_scene2() -> Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn default_scene3() -> Scene {
|
fn default_scene3() -> Scene {
|
||||||
//TODO fix this scene
|
let s1 = WithMaterial::new(Sphere::new_xyz(4., 0., 0., 1.), MIRROR);
|
||||||
let s1 = WithMaterial::new(Sphere::new_xyz(4., 0., 0., 1.), WHITE);
|
|
||||||
let s2 = WithMaterial::new(Sphere::new_xyz(3., 1., 1., 0.5), GREEN);
|
let s2 = WithMaterial::new(Sphere::new_xyz(3., 1., 1., 0.5), GREEN);
|
||||||
let navion = WithMaterial::new(Plane::new_xyz(0., 1., -1., 3.), BLUE);
|
let navion = WithMaterial::new(Plane::new_xyz(0., 1., -1., 3.), BLUE);
|
||||||
let backwall = WithMaterial::new(Plane::new_xyz(-1., -1., -0.5, 8.), RED);
|
let backwall = WithMaterial::new(Plane::new_xyz(-1., -1., -0.5, 8.), RED);
|
||||||
@@ -86,7 +85,8 @@ fn default_scene3() -> Scene {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// get scene and camera
|
// get scene and camera
|
||||||
let scene = scene_from_file("scenes/smolgalaxy.lua".to_owned()).unwrap();
|
//let scene = scene_from_file("scenes/randomspheres.lua".to_owned()).unwrap();
|
||||||
|
let scene = default_scene3();
|
||||||
let cam = default_cam();
|
let cam = default_cam();
|
||||||
|
|
||||||
// get stats on the scene we're about to render
|
// get stats on the scene we're about to render
|
||||||
|
|||||||
+1
-1
@@ -70,6 +70,6 @@ pub use cylinder::Cylinder;
|
|||||||
pub use torus::Torus;
|
pub use torus::Torus;
|
||||||
pub use waves::Waves;
|
pub use waves::Waves;
|
||||||
pub use with_material::{WithMaterial, WithDynamicMaterial};
|
pub use with_material::{WithMaterial, WithDynamicMaterial};
|
||||||
pub use with_lights::{WithLights, WithLight};
|
pub use with_lights::{WithLights, WithLight, WithAnyLights};
|
||||||
pub use transform::*;
|
pub use transform::*;
|
||||||
pub use scene::Scene;
|
pub use scene::Scene;
|
||||||
@@ -8,18 +8,19 @@ pub struct AffineTransform<T: Obj + Clone> {
|
|||||||
obj: T,
|
obj: T,
|
||||||
transform: Mat3,
|
transform: Mat3,
|
||||||
transform_inv: Mat3,
|
transform_inv: Mat3,
|
||||||
translate: Vec3
|
translate: Vec3,
|
||||||
|
scale: f64
|
||||||
}
|
}
|
||||||
|
|
||||||
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 }
|
AffineTransform { obj, transform, transform_inv: transform.invert(), translate, scale: transform.det().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 }
|
AffineTransform { obj, transform, transform_inv: transform.invert(), translate: O, scale: transform.det().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 }
|
AffineTransform { obj, transform: I3, transform_inv: I3, translate, scale: 1. }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_rev(&self, point: Vec3) -> Vec3 {
|
fn apply_rev(&self, point: Vec3) -> Vec3 {
|
||||||
@@ -60,7 +61,7 @@ pub const fn scale_z(k: f64) -> Mat3 { scale_xyz(1., 1., k) }
|
|||||||
|
|
||||||
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.obj.distance_to(self.apply_rev(point)) * self.scale
|
||||||
}
|
}
|
||||||
fn normal_at(&self, point: Vec3) -> Vec3 {
|
fn normal_at(&self, point: Vec3) -> Vec3 {
|
||||||
self.apply_fwd(self.obj.normal_at(self.apply_rev(point))).unit()
|
self.apply_fwd(self.obj.normal_at(self.apply_rev(point))).unit()
|
||||||
|
|||||||
@@ -42,3 +42,39 @@ impl<T: Obj> WithLight<T> {
|
|||||||
WithLight { obj, lights: [light; 1] }
|
WithLight { obj, lights: [light; 1] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct WithAnyLights<T: Obj> {
|
||||||
|
obj: T,
|
||||||
|
lights: Vec<Light>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Obj> WithAnyLights<T> {
|
||||||
|
pub fn new(obj: T, lights: Vec<Light>) -> WithAnyLights<T> {
|
||||||
|
WithAnyLights { obj, lights }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_light(&mut self, light: Light) {
|
||||||
|
self.lights.push(light)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Obj> Obj for WithAnyLights<T> {
|
||||||
|
fn distance_to(&self, point: Vec3) -> f64 {
|
||||||
|
self.obj.distance_to(point)
|
||||||
|
}
|
||||||
|
fn normal_at(&self, point: Vec3) -> Vec3 {
|
||||||
|
self.obj.normal_at(point)
|
||||||
|
}
|
||||||
|
fn material_at(&self, point: Vec3) -> Material {
|
||||||
|
self.obj.material_at(point)
|
||||||
|
}
|
||||||
|
fn get_lights(&self) -> Vec<Light> {
|
||||||
|
let mut l = self.obj.get_lights();
|
||||||
|
l.extend(&self.lights);
|
||||||
|
l
|
||||||
|
}
|
||||||
|
fn node_count(&self) -> u32 {
|
||||||
|
self.obj.node_count() + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,6 @@
|
|||||||
clear
|
clear
|
||||||
cargo build --release && \
|
cargo build --release && \
|
||||||
clear && \
|
clear && \
|
||||||
time target/release/rmarcher && \
|
time SEED=0 target/release/rmarcher && \
|
||||||
printf '\n' && \
|
printf '\n' && \
|
||||||
kitty +kitten icat --align=left a.png
|
kitty +kitten icat --align=left a.png
|
||||||
|
|||||||
Reference in New Issue
Block a user