オブジェクトを作る < Rust製ラスタライザ
from 点を描くところから始めるRust製ソフトウェアラスタライザ
オブジェクトを作る < Rust製ラスタライザ
モデルデータを定義する。
Actorに複数枚のポリゴンを合わせられるようにする。
https://gyazo.com/de1a6672197e3f2c2f3e28cd985f5913
定義を全体的に書き換え
code:actor.rs
pub struct Actor {
pub polygons:Vec<Polygon>,
pub position:Vec4,
pub axis:Vec4,
pub theta:f64
}
pub struct Polygon {
pub vertices: Vec4; 3,
pub color: Vec4; 3,
}
impl Actor {
pub fn model_conversion(&self) -> Mat4x4 {
Mat4x4::translate(&self.position)
* Mat4x4::rotation(&self.axis, self.theta)
}
}
cameraのsnapshot関数を書き換え...
code:rs
pub fn snapshot(&mut self, canvas:&mut Canvas, actors:&Vec<Actor>) {
let perspective = self.perspective_conversion();
let view = self.view_conversion();
let pv = perspective*view;
for actor in actors {
let model = actor.model_conversion();
let pvm = &pv * &model;
for polygon in &actor.polygons {
let projected = [
Vec4Project::new(&pvm * &polygon.vertices0).into_screen(&canvas.size()),
Vec4Project::new(&pvm * &polygon.vertices1).into_screen(&canvas.size()),
Vec4Project::new(&pvm * &polygon.vertices2).into_screen(&canvas.size()),
];
canvas.draw_triangle(projected, &polygon.color);
}
}
}
そして、mainのコードを次のように書き換え
code:main.rs
let world:Vec<Actor> = vec![
Actor{
polygons: vec![
Polygon{
vertices:Vec4::newpoint(1., 2., 3.), Vec4::newpoint(1., -2., 0.), Vec4::newpoint(-1., -1., -3.),
color: red.clone(), blue.clone(), red.clone()
},
Polygon{
vertices:Vec4::newpoint(1., 2., -3.), Vec4::newpoint(-1., -1., 3.), Vec4::newpoint(1., -2., 0.),
color: green.clone(), blue.clone(), green.clone()
},
],
position: Vec4::newpoint(0., 0., 0.),
axis: Vec4::newvec(0., 0., 0.),
theta: 0.0,
}
];
https://gyazo.com/ab4591c737d147a18e83e51646f70b5a
サンプルモデルとして、四面体を作ろう!appbird.icon
単位球に内接する4点は次のとおり
$ v_1 = (0, 1, 0)
$ v_2 = (\cos0, -1/3, \sin 0)
$ v_3 = (\cos\frac{2}{3}\pi, -1/3, \sin \frac{2}{3}\pi)
$ v_4 = (\cos\frac{4}{3}\pi, -1/3, \sin \frac{4}{3}\pi)
これらで面を構成してみる。
$ P_{234}, P_{134}, P_{124}, P_{123}
これらの面の重心ベクトルを求めた上で、重心を中心に面を0.95倍に縮小する。
code:rs
pub fn tetrahedron(vert_color:Vec4; 3) -> Vec<Polygon> {
let vectors = [
Vec4::newpoint(0., 1., 0.),
Vec4::newpoint(f64::cos(0.), -1./3., f64::sin(0.)),
Vec4::newpoint(f64::cos(2.*PI/3.), -1./3., f64::sin(2.*PI/3.)),
Vec4::newpoint(f64::cos(4.*PI/3.), -1./3., f64::sin(4.*PI/3.)),
];
let indecies: [usize; 3; 4] = [
1, 2, 3,
0, 2, 3,
0, 1, 3,
0, 1, 2,
];
let mut polygons: Vec<Polygon> = vec![];
for index_array in indecies {
let mut vertex = [
vectors[index_array0].clone(),
vectors[index_array1].clone(),
vectors[index_array2].clone()
];
let g = (&(&vertex0 + &vertex1) + (&vertex2)) / 3.;
for i in 0..3 {
vertexi = &((&vertexi - &g) * 0.95) + &g;
}
polygons.push(
Polygon {
vertices: vertex,
color: vert_color.clone()
}
);
};
polygons
}
https://gyazo.com/275fa618c89c252f6437cb31b19c7274
https://gyazo.com/de1a6672197e3f2c2f3e28cd985f5913
最後に思いっきりいっぱい生成してぶっ飛ばしてみないか?appbird.icon
Actorにvelとacc, angular_vel, angular_accに追加する