透視変換を修正するまでの道のり < 点からはじめるラスタライザ
透視変換を修正するまでの道のり < 点からはじめるラスタライザ あ、同次座標を二次元座標にするときに$ wで割るの忘れてた
$ wで割ると$ w \simeq 0のときに死ぬな...
$ |w| < \varepsilonのときは$ \varepsilonで割るか?appbird.icon
code:rs
pub struct Vec4Screen(pub Vec4);
impl Vec4Screen {
/** このVec4のx, y要素をとった新たなPoint2を作る */
pub fn to_point2(&self) -> Point2 {
if self.0.w().abs() < 1e-6 { return Point2::new((self.0.x()* 1e6) as i32, (self.0.y()* 1e6) as i32) ; }
Point2::new((self.0.x() / self.0.w()) as i32, (self.0.y() / self.0.w()) as i32)
}
}
あはん
code:rs
thread 'main' panicked at src/canvas/line.rs:32:40:
attempt to multiply with overflow
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace
オーバーフロー?
$ \varepsilon \simeq 10^{-6}に対して外積のオーダーは$ O(\varepsilon^{-2})になるわけで...
i64を使うべきか?appbird.icon
でも画面座標値にi64使ってもなあ、たかだか必要なのは$ 1024程度...。
教えてチャッピー
---> 「これは「ラスタライズ自作勢あるある」ですね!途中結果だけi64にするとええんやで」
code:util/vec4.rs
pub fn cross(&self, rhs:&Self) -> i32 {
let r = (self.x as i64) * (rhs.y as i64) - (self.y as i64) * (rhs.x as i64);
r as i32
}
code:canvas/line.rs
pub fn across_y(&self, y:i32) -> ClosedInterval {
if self.p1.y == self.p2.y {
return
if self.p1.y == 0 { ClosedInterval::between(self.p1.x, self.p2.x) }
else { ClosedInterval::empty() }
}
let delta = self.delta();
let delta_x = delta.x as i64;
let delta_y = delta.y as i64;
let y_y1 = (y - self.p1.y) as i64;
let x0 = self.p1.x + round_div(delta_x*y_y1, delta_y);
let x1 = self.p1.x + round_div(delta_x*(y_y1+1), delta_y);
ClosedInterval::between(x0, x1)
}
なんか.....ビーム放ってますね....appbird.icon
https://gyazo.com/f97c14769768deae550ad39b34b093da
もしかして:カメラが近すぎる
code:rs
camera.position = Vec4::newpoint(f64::cos(k*t)*3., f64::sin(k*t)*3., 2.) ;
漆黒の闇になってしまったappbird.icon
$ z = 2
https://gyazo.com/bacf4daacd1e46debbd298545df2fdd6
$ z = 3
https://gyazo.com/e28865b89361b482fa9756be4628b09a
何この...何?
何がおかしいのか?appbird.icon
手順
1. 三角形のモデル座標を透視変換行列にかける
2. $ /wで割ってクリッピング座標系をローカル座標に
code:rs
at src/camera.rs:50
これは平面上にあるのか?
o4くん「行列式を用いるとこれら 3 点は一直線上にはありません。」
ほならここは異常ではないね
3. ローカル座標をもとに三角形を描く
code:rs
なんか一点だけとんでもないことにappbird.icon
他の2点も0あたりの値に収束してるのは変だappbird.icon
2.と3.の間に異常がある?
あappbird.icon
code:canvas/camera.rs
pub fn transform_into_screen(&self, size:Point2, p: &Vec4Project) -> Vec4Screen {
let scale = size.y as f64 / 2.;
Vec4Screen(scale * &p.0 + size.to_vec4() / 2.)
}
よく考えたらここおかしいappbird.icon
scaleを直接かけてしまうとw成分にも影響してしまうな(scaleが意味をなしていない)
code:canvas/camera.rs
pub fn transform_into_screen(&self, size:Point2, p: &Vec4Project) -> Point2 {
let scale = size.y as f64 / 2.;
Vec4Screen(Mat4x4::scale_xyz(&scale) * &p.0 + size.to_vec4() / 2.).to_point2()
}
問題はなくなりつつあるけどまだだなあ
https://gyazo.com/6af3559f204df8d7193ce442079bc495
code:rs
なんで真ん中の一点だけ変なことになってるんだappbird.icon
多分真ん中の点のオーバーフローさえなんとかすればあるいは。
w値が変ということでもないappbird.icon
変換前の点を見てみよう。
code:rs
うーむappbird.icon
うん、なんか一個だけ0.0になってるやつがおるぞappbird.icon
これは何が原因?appbird.icon
カメラ位置をもっと遠くしないといけない?
$ z = 4
https://gyazo.com/e0331b98e0cb6ba30ab0194fde95a5bd
でもそうでもないな...
よくみるとワールドの点の置き方が変($ w/3されちゃってる)
code:main.rs
code:main.rs
点とカメラが近すぎたんだなappbird.icon
どこいくねーんappbird.icon
左上にギリッギリ写ってるなappbird.icon
https://gyazo.com/93017c907163c3e2796f783fe2ad3c89
ええと、ということは割る側の$ wがデカすぎるという解釈でおk?
いやそれだと左側によるこたあないか
$ (\cos kt +10, \sin kt + 10, 5)にカメラを置いてみる
https://gyazo.com/87ecc18d678b48cd546b38260f425ecc
なんか遠くないです...??appbird.icon
一旦カメラ止めてみるか
これつまりは最初の三角形2枚写すやつはできていなかったということになるな....
$ (0, 0, 5)にカメラを置いてみる
スクリーン座標系に直す前の点はどうなっている?
code:rs
] at src/camera.rs:79
これをみると変な場所には置かれていなさそうappbird.icon
となると...appbird.icon
code:rs
pub fn transform_into_screen(&self, size:Point2, p: &Vec4Project) -> Point2 {
let scale = size.y as f64 / 2.;
let v = Mat4x4::scale_xyz(&scale) * &p.0 + size.to_vec4() / 2.;
snapshot!(&v / v.w());
Vec4Screen(&v / v.w()).to_point2()
}
お前か!
よく考えると後からw.割るの変だなappbird.icon
先にwを割らないとな
code:rs
pub fn transform_into_screen(&self, size:Point2, p: &Vec4Project) -> Point2 {
let scale = size.y as f64 / 2.;
let p = &p.0 / p.0.w();
let v = &p * scale + size.to_vec4() / 2.; // w値を気にしなくて良くなったので単純にscaleをスカラー倍するだけ
Vec4Screen(v).to_point2()
}
https://gyazo.com/0e153e96b5975cb35a17f947ad1748c9
ヨシャー!!!!!appbird.icon
と思ったけどなんか逆じゃないですか?appbird.icon