mieki256's diary



2017/12/20(水) [n年前の日記]

#1 [love2d] 直線と球の交点の求め方を調べてたり

昨日、直線と球の交点をatan()やcos()で求めてたけど。もっと簡単(?)に求める方法があるはずだよなとググって調べてみたり。以下のページが参考になった。

_球面と直線の交点 -点P(Px,Py,Pz)から方向ベクトル(x,y,z)にのびた直線- 数学 | 教えて!goo

直線の原点が P(Px, Py, Pz) で、方向ベクトルが (x, y, z) の場合、直線は (X,Y,Z) = (Px, Py, Pz) + t * (x, y, z) と書ける…けど、今回は原点を (0, 0, 0) としてるので、
X = t * x
Y = t * y
Z = t * z
と書けるなと。

そして球は、X^2 + Y^2 + Z^2 = r^2 だから…。X,Y,Zに直線のソレを代入して…。
X^2 + Y^2 + Z^2 = r^2
(t * x) * (t * x) + (t * y) * (t * y) + (t * z) * (t * z) = r * r
t^2 * (x^2 + y^2 + z^2) = r^2
t^2 = (r^2) / (x^2 + y^2 + z^2)
t = sqrt( (r^2) / (x^2 + y^2 + z^2) )
例えば、直線が x = 0, y = 0 の時、z = 1.0 になるだろうから…。
t = sqrt( (r^2) / (0^2 + 0^2 + 1.0^2) )
  = sqrt( (r^2) / 1.0 )
  = sqrt( r^2 )
  = r
t = r にしちゃっていい、のかなと。ホントかな。怪しいな。

ということは、x, y が決まっている時、z値は…。
(t * x)^2 + (t * y)^2 + (t * z)^2 = r^2
(t * z)^2 = r^2 - (t * x)^2 - (t * y)^2

t = r

(r * z)^2 = r^2 - (r * x)^2 - (r * y)^2
r^2 * z^2 = r^2 * (1.0 - x^2 - y^2)
z^2 = (1.0 - x^2 - y^2)
z = sqrt(1.0 - x^2 - y^2)
アレ? 球の半径 r が式の中から無くなってしまった…。これで合ってるのかな…? どうなのよ。

love2d の Shader で動作確認。 :

love2d の Shader を使って、どんな結果になるか確認。

shader_test11_sphere2_ss01.png

歪み方は以前のやり方と似たような感じになった。ただ、球の半径 r を変更してもテクスチャの拡大縮小はされなくなった。式の中に r が入ってないから当たり前だろうけど。

どこかで何かを間違えてる気がしないでもないけど、それっぽく表示されたから、まあ、いいか…。

ソースは以下。

_conf.lua
_main.lua

変更したところだけメモ。
function love.load()
  love.graphics.setDefaultFilter("nearest", "nearest")
  scr_w, scr_h = 640, 480
  canvas = love.graphics.newCanvas(scr_w, scr_h)

  img = love.graphics.newImage("star_bg_1024x1024.png")
  -- img = love.graphics.newImage("uvcheckermap01-1024.png")
  img:setFilter("linear", "linear")

  -- make shader
  local shadercode = [[
    extern number scr_dist;
    extern number scale;
    extern number start_x;
    extern number start_y;
    // extern number r;

    vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ) {
      float sx = (screen_coords.x - (love_ScreenSize.x / 2)) / love_ScreenSize.x;
      float sy = (screen_coords.y - (love_ScreenSize.y / 2)) / love_ScreenSize.x;
      vec3 ray = normalize(vec3(sx, sy, scr_dist));
      // float qz = sqrt( r * r * (1.0 - ray.x * ray.x - ray.y * ray.y) / (r * r));
      float qz = sqrt( 1.0 - ray.x * ray.x - ray.y * ray.y);
      float u = sx * qz / scr_dist;
      float v = sy * qz / scr_dist;
      texture_coords.x = mod((u + start_x) * scale + 0.5, 1.0);
      texture_coords.y = mod((v + start_y) * scale + 0.5, 1.0);
      vec4 texcolor = Texel(texture, texture_coords);
      return texcolor * color;
    }
  ]]

  myshader = love.graphics.newShader(shadercode)
  local angle_of_view = 60
  local scr_dist = math.cos(math.rad(angle_of_view/2))
  myshader:send("scr_dist", scr_dist)
  -- myshader:send("r", scr_dist + 0.1)
  myshader:send("scale", 0.4)
  myshader:send("start_x", 0.0)
  myshader:send("start_y", 0.0)

  ang_a = 0.0
  ang_b = 0.0
  px = (scr_w - img:getWidth()) / 2
  py = (scr_h - img:getHeight()) / 2
end

以上、1 日分です。

過去ログ表示

Prev - 2017/12 -
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project