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^2 + Y^2 + Z^2 = r^2 だから…。X,Y,Zに直線のソレを代入して…。
ということは、x, y が決まっている時、z値は…。
_球面と直線の交点 -点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 ) = rt = 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 を使って、どんな結果になるか確認。
歪み方は以前のやり方と似たような感じになった。ただ、球の半径 r を変更してもテクスチャの拡大縮小はされなくなった。式の中に r が入ってないから当たり前だろうけど。
どこかで何かを間違えてる気がしないでもないけど、それっぽく表示されたから、まあ、いいか…。
ソースは以下。
_conf.lua
_main.lua
変更したところだけメモ。
歪み方は以前のやり方と似たような感じになった。ただ、球の半径 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 日分です。
