LoginSignup
2
0

More than 1 year has passed since last update.

paiza.ioでelixir その71

Posted at

概要

paiza.ioでelixirやってみた。
Ray Tracerやってみた。

参考にしたページ

サンプルコード


defmodule Vector do
    defmodule Vec3 do
        defstruct x: 0.0, y: 0.0, z: 0.0
        alias Vector.Vec3, as: Vec3
        def vec3(list) when is_list(list) do
            [x | rest] = list
            [y | [z]] = rest
            %Vec3{x: x, y: y, z: z}
        end
        def ones() do
            %Vec3{x: 1.0, y: 1.0, z: 1.0}
        end
        def add(vec1, vec2) do
            %Vec3{x: vec1.x + vec2.x, y: vec1.y + vec2.y, z: vec1.z + vec2.z }
        end
        def dot(vec1, vec2) do
            vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z
        end
        def mult(vec1, vec2) do
            %Vec3{x: vec1.x * vec2.x, y: vec1.y * vec2.y, z: vec1.z * vec2.z }
        end
        def scale(vec, s) do
            %Vec3{x: vec.x * s, y: vec.y * s, z: vec.z * s }
        end
        def sub(vec1, vec2) when is_map vec2 do
            %Vec3{x: vec1.x - vec2.x, y: vec1.y - vec2.y, z: vec1.z - vec2.z }
        end
        def sub(vec, s) do
            %Vec3{x: vec.x - s, y: vec.y - s, z: vec.z - s}
        end
        def len(vec) do
            :math.sqrt(lengthSqr(vec))
        end
        def lengthSqr(vec) do
            vec.x * vec.x + vec.y * vec.y + vec.z * vec.z
        end
        def div(vec, scalar) do
            %Vec3{x: vec.x / scalar, y: vec.y / scalar, z: vec.z / scalar}
        end     
        def unit_vector(vec) do
            s = len(vec)
            Vec3.div(vec, s)
        end
        def cross(vec1, vec2) do
            x = vec1.y * vec2.z - vec1.z * vec2.y
            y = vec1.z * vec2.x - vec1.x * vec2.z
            z = vec1.x * vec2.y - vec1.y * vec2.x
            %Vec3{x: x, y: y, z: z}
        end
        def to_list(vec3) do
            [vec3.x, vec3.y, vec3.z]
        end
    end
end
defmodule Ray do
    alias Vector.Vec3, as: Vec3
    defstruct pos: %Vec3{}, dir: %Vec3{}
    def at(vec, t), do: Vec3.add(vec.pos, (Vec3.scale(vec.dir, t)))
end
IO.puts """
<!doctype html>
<html>
  <head>
    <link rel="stylesheet" href="lib/style.css">
  </head>
  <body>
    <canvas id="canvas" width="80" height="60"></canvas>
    <script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var img = ctx.createImageData(80, 60);
var data = img.data;
var v = [
"""
defmodule Main do
    require Vector
    require Ray
    alias Vector.Vec3, as: Vec3
    def hit_sphere(center, radius, ray) do
        oc = Vec3.sub(ray.pos, center)
        a = Vec3.dot(ray.dir, ray.dir)
        b = Vec3.dot(oc, ray.dir) * 2.0
        c = Vec3.dot(oc, oc) - radius * radius
        discriminant = b * b - 4 * a * c
        discriminant > 0.0
    end
    def sphere_color(ray) do
        if hit_sphere(Vec3.vec3([0.0, 0.0, -1.0]), 0.5, ray) do
            Vec3.vec3([1.0, 0.0, 0.0])
        else
            unit_vec = Vec3.unit_vector(ray.dir)
            t = 0.5 * (unit_vec.y + 1.0)
            Vec3.scale(Vec3.ones(), (1.0 - t))
            |> Vec3.add(Vec3.scale(Vec3.vec3([0.5, 0.7, 1.0]), t))
        end
    end
    def main do
        nx = 80
        ny = 60
        low_left = Vec3.vec3([-2.0, -1.0, -1.0])
        horizontal = Vec3.vec3([4.0, 0.0, 0.0])
        vertical = Vec3.vec3([0.0, 2.0, 0.0])
        origin = Vec3.vec3([0.0, 0.0, 0.0])
        for y <- ny - 1..0 do
            for x <- 0..nx - 1 do
                u = x / nx
                v = y / ny
                ray = %Ray{
                    pos: origin, 
                    dir: Vec3.scale(horizontal, u) 
                    |> Vec3.add(Vec3.scale(vertical, v)) 
                    |> Vec3.add(low_left)
                }   
                unit_vec = Vec3.unit_vector(ray.dir)
                t = 0.5 * (unit_vec.y + 1.0)
                color = sphere_color(ray)
                [color.x, color.y, color.z] 
                |> Enum.map(fn n ->
                    255 * n
                    |> floor
                    |> IO.write
                    IO.write ","
		        end)
		        IO.write "255,"
            end
        end
    end
end
Main.main
IO.puts """

0];
for (var i = 0; i < 80 * 60 * 4; i++) 
{
	data[i] = v[i];
}
    ctx.putImageData(img, 0, 0);
//alert(v[2]);
    </script>
  </body>
</html>
"""


実行結果

image.png

成果物

以上。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0