Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Helper stuff for printing:
- #[external] fn print(val: int);
- #[external] fn printfl(val: float);
- #[external] fn plot(x: int, y: int, val: int);
- // System stuff:
- #[external] fn DebugBreak();
- // Libc:
- #[external] fn malloc(bytes: int) -> void ptr;
- #[external] fn memcpy(dest: void ptr, src: void ptr, bytes: int) -> void ptr;
- // Math:
- #[external] fn log(val: float) -> float;
- #[external] fn sqrtf(val: float) -> float;
- // File access:
- #[external] fn fopen(name: void ptr, access: void ptr) -> void ptr;
- #[external] fn fwrite(ptr: int ptr, size: int, count: int, stream: void ptr);
- #[external] fn fclose(stream: void ptr);
- type option<T> = None | Some(T);
- type vec3 = {
- x: float;
- y: float;
- z: float;
- fn length() -> float;
- fn length_sq() -> float;
- fn scale(s: float);
- fn cross(rhs: vec3) -> vec3;
- fn dot(rhs: vec3) -> float;
- fn normalized() -> vec3;
- fn diff(rhs: vec3) -> vec3;
- }
- fn mkvec(x: float, y: float, z: float) -> vec3 {
- return { x, y, z } : vec3;
- }
- impl vec3 {
- fn length() -> float {
- return sqrtf(x*x + y*y + z*z);
- }
- fn length_sq() -> float {
- return x*x + y*y + z*z;
- }
- fn dot(rhs: vec3) -> float {
- return x * rhs.x + y * rhs.y + z * rhs.z;
- }
- fn scale(s: float) {
- x = x / s;
- y = y / s;
- z = z / s;
- }
- fn cross(rhs: vec3) -> vec3 {
- return mkvec(
- y*rhs.z - z*rhs.y,
- z*rhs.x - x*rhs.z,
- x*rhs.y - y*rhs.x
- );
- }
- fn normalized() -> vec3 {
- let ret = {x, y, z} : vec3;
- ret.scale(ret.length());
- return ret;
- }
- fn diff(rhs: vec3) -> vec3 {
- return { x - rhs.x, y - rhs.y, z - rhs.z } : vec3;
- }
- }
- fn lerp(left: float, right: float, amount: float) -> float {
- return left + (right - left) * amount;
- }
- type sphere = {
- radius: float;
- center: vec3;
- fn ray_cast(from: vec3, dir: vec3) -> float option;
- }
- fn float_min(a: float, b: float) -> float {
- if a > b { return b; }
- return a;
- }
- type two_solution = {
- first: float;
- second: float;
- }
- type quadratic_solution = Zero | One(float) | Two(two_solution);
- fn solve_quadratic(a: float, b: float, c: float) -> quadratic_solution {
- let discriminant = b*b - 4*a*c;
- if discriminant < 0 { return Zero; }
- if discriminant == 0.0 {
- return One(-b / (2.0 * a));
- }
- let s = sqrtf(discriminant);
- let sols = {
- (-b + s) / (2 * a),
- (-b - s) / (2 * a)
- } : two_solution;
- return Two(sols);
- }
- impl sphere {
- fn ray_cast(from: vec3, dir: vec3) -> float option {
- let center_to_origin = from.diff(center);
- match solve_quadratic(1.0, 2 * dir.dot(center_to_origin), center_to_origin.length_sq() - radius*radius) {
- One(a) { return Some(a); }
- Two(b) { return Some(float_min(b.first, b.second)); }
- _ {}
- }
- return None;
- }
- }
- fn mksphere(radius: float, origin: vec3) -> sphere {
- return { radius, origin } : sphere;
- }
- // This opens a.raw through hardcoded integers that represent the ASCII strings:
- fn open_file() -> void ptr {
- let name = 512735981153; // This is 'a.raw':
- let access = 25207; // This is "wb"
- return fopen(&name : void ptr, &access : void ptr);
- }
- fn go() {
- let scanwidth = 1024;
- let scanheight = 1024;
- let f = open_file();
- let origin = mkvec(0.0, 0.0, 0.0);
- let s = mksphere(5.0, mkvec(0.0, 0.0, 50.0));
- let xpx = 0;
- while xpx < scanwidth {
- let ypx = 0;
- while ypx < scanheight {
- let x0 = lerp(-1.13446, 1.13446, xpx:float / scanwidth);
- let y0 = lerp(-1.13446, 1.13446, ypx:float / scanheight);
- let projection_dir = mkvec(x0, y0, 1.0);
- projection_dir = projection_dir.normalized();
- let val = 0;
- match s.ray_cast(origin, projection_dir) {
- Some(n) {
- val = 255;
- }
- None {}
- }
- fwrite(&val, 1, 1, f);
- ypx = ypx + 1;
- }
- xpx = xpx + 1;
- }
- fclose(f);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement