- ç°¡ç¥åãããOpenGLãRustã§äœæãã-ããŒã1ïŒç·ãåŒãïŒ
- Rustã§ã®ç°¡æOpenGLã®äœæ-ããŒã2ïŒã¯ã€ã€ãŒã¬ã³ããªã³ã°ïŒ
é£èŒèšäºã®åºç€ã¯ã haqreuã® ãã³ã³ãã¥ãŒã¿ã°ã©ãã£ãã¯ã¹ã®çæã³ãŒã¹ãã§ããããšãæãåºããŠãã ãã ã åã®èšäºã§ã¯ãç§ã¯ããŸãéãè¡ããŸããã§ããã å®éãã³ãŒã¹ã®1ã€ã®èšäºã«å¯ŸããŠ2ã€ã®èšäºããããŸããã ããã¯ãç§ã®èšäºã§äž»ã«Rustã§äœæ¥ãã埮åŠãªãã¥ã¢ã³ã¹ã«çŠç¹ãåœãŠãŠãããšããäºå®ã«ãããã®ã§ãããæ°ããèšèªãåŠç¿ããã ãã§ããã°ããã®éããã°ã©ãã³ã°ãè¡ã£ãŠãããšããããå€ãã®æ°ãã埮åŠãªãã¥ã¢ã³ã¹ã«åºäŒãããšã«ãªããŸãã ããã«Rustã䜿çšãããšã¬ãŒããå°ãªããªããå ã®ã³ãŒã¹ã®èšäºã«å¯Ÿããèšäºã®æ¯çã調æŽããŸãã
ãã®éãç§ã¯äŒçµ±çã«Rustã3Dã°ã©ãã£ãã¯ã¹ã®å°é家ã§ã¯ãªãã®ã§ãèšäºãæžãéçšã§ãããã®ããšãæ£ããç 究ããŠããã®ã§ãããã¯å€ãã®ãã³ã»ã³ã¹ã«ãªãå¯èœæ§ããããšèŠåããŠããŸããã ããã«æ°ä»ããããã³ã¡ã³ããæžããŠãã ãã-ãšã©ãŒãä¿®æ£ããŸãã ãããŠãã¡ããããã®èšäºã«ã¯ããªããåæããªããããããªãå€ãã®å人çãªå°è±¡ããããŸãã 建èšçãªæ¹å€ã¯å€§æè¿ã§ãã

ãã®èšäºã®çµæãšããŠåŸããããã®
äžè§åœ¢ã®ããã¢ãã«ãæã
ãã¹ãŠããã®ãããªãã®ã§ããã説æãããã®ã¯äœããããŸããã ã³ãŒãã¯ããªããžããªã®å¯Ÿå¿ããã¹ãããã·ã§ããã«ãããŸã ã
ãããŠãããã«ç§ãæ®ã£ãåçããããŸãã

å¹³ããªè²åã
ãã¯ãã«ãšã¹ã«ã©ãŒã®ç©æŒç®ãç §æã®èšç®ã«äœ¿çšããããããæ°ããæŒç®åã§å€ãè¯ãVector3Dã¯ã©ã¹ãæ¡åŒµããå¿ èŠããããŸãã Rustã§ã®æŒç®åã®ãªãŒããŒããŒãã«ã€ããŠå°ãèªãã§ã å©çšå¯èœãªãªãŒããŒããŒãã®ãªã¹ããèŠãŠã次ã®ã³ãŒããæžãããšãæ¬åœã«æ°ã«ããŸããã§ããïŒ
pub struct Vector3D { pub x: f32, pub y: f32, pub z: f32, } impl Vector3D { pub fn new(x: f32, y: f32, z: f32) -> Vector3D { Vector3D { x: x, y: y, z: z, } } pub fn norm(self) -> f32 { return (self.x*self.x+self.y*self.y+self.z*self.z).sqrt(); } pub fn normalized(self, l: f32) -> Vector3D { return self*(l/self.norm()); } } impl fmt::Display for Vector3D { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "({},{},{})", self.x, self.y, self.z) } } impl Add for Vector3D { type Output = Vector3D; fn add(self, other: Vector3D) -> Vector3D { Vector3D { x: self.x + other.x, y: self.y + other.y, z: self.z + other.z} } } impl Sub for Vector3D { type Output = Vector3D; fn sub(self, other: Vector3D) -> Vector3D { Vector3D { x: self.x - other.x, y: self.y - other.y, z: self.z - other.z} } } impl Mul for Vector3D { type Output = f32; fn mul(self, other: Vector3D) -> f32 { return self.x*other.x + self.y*other.y + self.z*other.z; } } impl Mul<f32> for Vector3D { type Output = Vector3D; fn mul(self, other: f32) -> Vector3D { Vector3D { x: self.x * other, y: self.y * other, z: self.z * other} } } impl BitXor for Vector3D { type Output = Vector3D; fn bitxor(self, v: Vector3D) -> Vector3D { Vector3D { x: self.y*vz-self.z*vy, y: self.z*vx-self.x*vz, z: self.x*vy-self.y*vx} } }
å€å®ïŒRustã®æŒç®åã®ãªãŒããŒããŒãã¯åºæ¬çã«è¡ãããŸãã
ãã ããã³ããŒã移åã«ã¯å°é£ããããŸããã Rustã§ã¯ããã¹ãŠã®ã¿ã€ãã移åå¯ââèœãŸãã¯ã³ããŒå¯èœã«ãªã£ãŠããŸãã åã移åå¯èœãªå Žåãå€æ°ã®æææš©ã¯åŒã³åºãããé¢æ°ã«å ¥ãããããã®åã®å€æ°ãåãã¡ãœããã®åŒã³åºãã¯ãã³ãŒãå ã®åŸç¶ã®ãã¹ãŠã®åŒã³åºãããã¢ã¯ã»ã¹ã§ããªããªããŸãã ã€ãŸãããã®ãããªã³ãŒãã¯ãšã©ãŒã®åå ã«ãªããŸãã
let x = Vector3D::new(1.0, 1.0, 1.0); let y = x*2.0; do_something_else(x); // error!
ä¹ç®é¢æ°ã«æž¡ãããå€æ°xã®æææš©ãå€æ°ã¯é¢æ°ã®ããŒã«ã«å€æ°ã«ç§»åãããé¢æ°ãçµäºããåŸã«åé€ãããŸãããè¿ãããªãã£ãããã§ãã å®éã
normalized()
é¢æ°ã§ãã®ã¿ã€ãã®ãšã©ãŒãçºçããŸãã
normalized()
ã芧ã®ãšããã
self
ã¯ä¹ç®æŒç®åã®å³åŽãšå·ŠåŽã®äž¡æ¹ã«ç«ã£ãŠããããã§ãã ã€ãŸããé£ç¶ããŠ2å移åããããšããŠããŸãã ããã©ã«ãã§ã¯ãRustã®ãã¹ãŠã®ãŠãŒã¶ãŒæ§é ã¯ç§»åå¯èœã§ãã
2ã€ã®è§£æ±ºçããããŸããããã©ã«ãã§å€æ°ãã³ããŒããããæŒç®åã®å®è£ ãå€ã§ã¯ãªããªã³ã¯ãåãå ¥ããããã«ãããã§ãã 2çªç®ã®ãªãã·ã§ã³ãéžæããŸããã ãããå®è£ ããã«ã¯ãæ§é äœã®å®£èšã®åã«
#[derive(Copy, Clone)]
ãšæžãã ãã§ååã§ãã ããã¯ãæ§é ãã³ããŒå¯èœã§ãããåçŽãªãã€ãè€è£œã«ãã£ãŠã³ããŒã§ããããšãã³ã³ãã€ã©ã«äŒããŸãã ããã§ãäžèšã®ãããªåŒã³åºãã§ã¯ãããŒã¿ã®ã³ããŒããªãã¬ãŒã¿ãŒã«è»¢éãããåŒã³åºãåŸãå ã®ããŒã¿ãå©çšå¯èœã«ãªããŸãã è€éã«èŠããŸããããã®è¿œå ã®è€éãã®ããã«ãã³ã³ãã€ã©ãŒã¯ã¡ã¢ãªãŒã»ãšã©ãŒã®ããã³ãŒãïŒäŸãã°ã Use After Free ïŒãæžãããšãèš±å¯ããŸããã
ã¡ãªã¿ã«ãRustã«ã¯ãªãã·ã§ã³ã®ãã©ã¡ãŒã¿ãŒã¯ãªããéåžžã®æ¹æ³ã§ãšãã¥ã¬ãŒãããããšãã§ããŸãããåãååã§ç°ãªãåŒæ°ã®ã»ããã䜿çšããŠé¢æ°ãäœæããããšãã§ããŸãã ããã¯ã ãã¬ã€ãã䜿çšããããšã§éšåçã«åé¿ã§ããŸãã ãããããã®æ¹æ³ã¯ãã¹ãŠã®å Žåã«é©ããŠããããã§ã¯ãªããç§ã®æèŠã§ã¯ãããäžå¿ èŠã«åé·ã§ãã äžè¬ã«ãã©ã¹ãã®ã¿ã€ãã¯ãäžå¿ èŠãªåé·æ§ã®å°è±¡ãæ®ããŸãã ã©ã³ã¿ã€ã ã«ãªãŒããŒããããè¿œå ããããšãªããã¡ã¢ãªãæäœããéã®ãšã©ãŒã«å¯Ÿããä¿è·ã«éåããããšãªããç°ãªãæ¹æ³ã§å®è¡ã§ãããã©ããã¯ããããŸããããçŸåšã®å®è£ ã§ã¯ãç¹æ§ãå¯èœãªéã䜿çšããªããšããåæãããŠããŸãã
ããã«ãã©ã€ãã£ã³ã°ã䜿çšããŠã¢ãã«ãæç»ããããã®ã³ãŒãã¯ãããŸãåéºãªãã§äœæãããŸããã
ããã¯åœŒãç§ãã¡ã®ããã«æãããã®ã§ã

ãããŠãããããªããžããªã®å¯Ÿå¿ããã¹ãããã·ã§ããã§ã ã
Z-ãããã¡
ããã°ã©ãã³ã°ãå§ãããšããZ-bufferã¯Vector3Dã¯ã©ã¹ãæŽæ°åº§æšãšå®åº§æšã®äž¡æ¹ã§ããå¿ èŠãããããšã«æ°ä»ããŸããã è¢ããŸãããäžè¬åãããã¿ã€ããšã¿ã€ãã䜿çšããŠæžãçŽãå§ããŸããã ãããç±ã®è¡ãå ã§ãã Rustã®ç¹åŸŽã¯è€éãªæ§æãæã£ãŠããããšãè¿°ã¹ãŸãããïŒ èªåã§ã³ãŒããèŠãŠãã ããïŒ
use std::fmt; use std::ops::Add; use std::ops::Sub; use std::ops::Mul; use std::ops::BitXor; use num::traits::NumCast; #[derive(Copy, Clone)] pub struct Vector3D<T> { pub x: T, pub y: T, pub z: T, } impl<T> Vector3D<T> { pub fn new(x: T, y: T, z: T) -> Vector3D<T> { Vector3D { x: x, y: y, z: z, } } } impl<T: NumCast> Vector3D<T> { pub fn to<V: NumCast>(self) -> Vector3D<V> { Vector3D { x: NumCast::from(self.x).unwrap(), y: NumCast::from(self.y).unwrap(), z: NumCast::from(self.z).unwrap(), } } } impl Vector3D<f32> { pub fn norm(self) -> f32 { return (self.x*self.x+self.y*self.y+self.z*self.z).sqrt(); } pub fn normalized(self, l: f32) -> Vector3D<f32> { return self*(l/self.norm()); } } impl<T: fmt::Display> fmt::Display for Vector3D<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "({},{},{})", self.x, self.y, self.z) } } impl<T: Add<Output = T>> Add for Vector3D<T> { type Output = Vector3D<T>; fn add(self, other: Vector3D<T>) -> Vector3D<T> { Vector3D { x: self.x + other.x, y: self.y + other.y, z: self.z + other.z} } } impl<T: Sub<Output = T>> Sub for Vector3D<T> { type Output = Vector3D<T>; fn sub(self, other: Vector3D<T>) -> Vector3D<T> { Vector3D { x: self.x - other.x, y: self.y - other.y, z: self.z - other.z} } } impl<T: Mul<Output = T> + Add<Output = T>> Mul for Vector3D<T> { type Output = T; fn mul(self, other: Vector3D<T>) -> T { return self.x*other.x + self.y*other.y + self.z*other.z; } } impl<T: Mul<Output = T> + Copy> Mul<T> for Vector3D<T> { type Output = Vector3D<T>; fn mul(self, other: T) -> Vector3D<T> { Vector3D { x: self.x * other, y: self.y * other, z: self.z * other} } } impl<T: Mul<Output = T> + Sub<Output = T> + Copy> BitXor for Vector3D<T> { type Output = Vector3D<T>; fn bitxor(self, v: Vector3D<T>) -> Vector3D<T> { Vector3D { x: self.y*vz-self.z*vy, y: self.z*vx-self.x*vz, z: self.x*vy-self.y*vx} } }
ããã«ãããã®ãšãã®çç±ãç°¡åã«èª¬æããŠãã ããã Täžã®ã³ãã³ã®åŸã«ãå¢çãæžã蟌ãŸããŸãïŒT.ãå®è£ ãã¹ãç¹æ§ããšãã°ãBitXoræäœã®å ŽåãTã¯ãã芧ã®ãšãããä¹ç®ãæžç®ãããã³ã³ããŒãå®è£ ããå¿ èŠããããŸãã æåã®2ã€ã§ãä¹ç®ãšæžç®ãè¡ãé¢æ°ã³ãŒãã§ã¯ããããTã§æå¹ã§ããããšã¯è«ççã§ããã³ããŒããã®ã¯ãªãã§ããïŒ ãã€ã³ãã¯ããã§ã«äžèšã§èª¬æããç¶æ³ã§ããå¥ã®é¢æ°ã«ç§»åãããå€æ°ãåå©çšããããšã¯ã§ããŸããã ãããã£ãŠãç®è¡
x: self.y*vz-self.z*vy, y: self.z*vx-self.x*vz, z: self.x*vy-self.y*vx
ããªã³ã¯ã䜿çšããŠ
x: self.y*vz-self.z*vy, y: self.z*vx-self.x*vz, z: self.x*vy-self.y*vx
ãŸããŸãã¯ãTãã³ããŒå¯èœã§ããããšã確èªããŠãã ããã Rustã®ãã¹ãŠã®åºæ¬åã¯ã³ããŒå¯èœã§ãã äžè¬ã«ããªã¹ãããã¡ã€ã«ãxãyãzããŸãã¯ä»ã®è€éãªãã®ã«è©°ã蟌ãããšã誰ãæåŸ ããªããããã³ããŒãªãã·ã§ã³ãé©ããŠããŸãã ããããŠããã®
<Output = T>
äœã§ããïŒã-æ°é ãã®ããèªè ãå°ããŸãã ãã®ãšã³ããªããªããã°ãã³ãŒãã¯æ©èœããŸããã å®éã®ãšãããRustã¯å ç®ãŸãã¯ä¹ç®ã®çµæããªãã©ã³ããšåãåã«ãªãããšãä¿èšŒããŸããã ãããã£ãŠãããã§ã¯ãä¹ç®ã®çµæãTåã«ãªãããã«ä¹ç®ãå®è£ ããTãå¿ èŠã§ããããšãããã«æ確ã«ããŸããããã¯é£ããã§ããïŒ ç§ã¯ããªãã«èŠåããŸããã
toïŒïŒã¡ãœããã¯ãããã¿ã€ãã®ãã¯ãã«ãå¥ã®ã¿ã€ãã«å€æããããšãå¯èœã«ããŸãããç¹çã«å€ããŸãã ããšãã°ãå®æ°ããæŽæ°ãžã ããã§ãããããã«ãNumCastãå®è£ ããä»»æã®åã¯ãNumCastãå®è£ ããä»»æã®åã«å€æã§ããŸãã Rustã®ãã¹ãŠã®ããªããã£ãåã¯ãããå®è£ ããŠãããããïŒãã®åã«ã€ããŠåŠç¿ããã®ã«ãããæéãæ°ããããšãªãïŒå®å šã«ç¡çã§ãã¯ã¿ãŒã®åå€æãåãåããŸããã
æ®ãã®å€æŽã¯ããã»ã©è€éã§ã¯ãããŸããã§ããã ãã®çµæã ãªããžããªã®å¯Ÿå¿ããã¹ãããã·ã§ããã§èŠãããšãã§ããã³ãŒããåŸãŸããã
ãããŠåœŒã¯ã©ããªçµµãæã

TGAãã£ã³ãã¹
ãã¯ã¹ãã£ãªã³ã°ã®ããã«ãTGAãã¡ã€ã«ãèªã¿åãããšãã§ããå¿ èŠãããã®ã¯ããã¯ã¹ãã£ãé¢å¿ã®ããã¢ãã«ã«ä¿åãããŠããããã§ããããã§ã¯ããµã€ã¯ã«ã®æåã«ã¹ãããããTGAãã¡ã€ã«ã®èªã¿åãã«æ»ããŸãããã ãããŠãç§ãã¡ã¯ãŸã ããããèªãããšãåŠãã§ããã®ã§ãçµæãTGAã«æžã蟌ãCanvasã®ä»£æ¿å®è£ ãåæã«äœæããªãã®ã¯ãªãã§ããã åœç¶ãCanvasãæœè±¡åããŠãããSdlCanvasãšTgaCanvasã®2ã€ã®å®è£ ãæºåããå¿ èŠããããŸãã Javaã§ã¯ãä»ã®2ã€ã®ã¯ã©ã¹ãç¶æ¿ããåºæ¬ã¯ã©ã¹ãäœæããŸãã Rustã§ã¯ããã®æ©èœã¯äžçŽç©ã䜿çšããŠå®è£ ãããŠããŸãã èªåã§ã³ãŒããèŠãŠãã ããã Canvasã®æ··åç©ã¯æ¬¡ã®ãšããã§ãã
pub trait Canvas { fn canvas(&mut self) -> &mut Vec<Vec<u32>>; fn zbuffer(&mut self) -> &mut Vec<Vec<i32>>; fn xsize(&self) -> usize; fn ysize(&self) -> usize; fn new(x: usize, y: usize) -> Self; fn show(&mut self); fn wait_for_enter(&mut self); fn set(&mut self, x: i32, y: i32, color: u32) { if x < 0 || y < 0 { return; } if x >= self.xsize() as i32 || y >= self.ysize() as i32{ return; } self.canvas()[x as usize][y as usize] = color; } fn triangle(&mut self, mut p0: Vector3D<i32>, mut p1: Vector3D<i32>, mut p2: Vector3D<i32>, color: u32) { //... } }
SdlCanvasã¯æ¬¡ã®ãšããã§ãã
pub struct SdlCanvas { sdl_context: Sdl, renderer: Renderer, canvas: Vec<Vec<u32>>, zbuffer: Vec<Vec<i32>>, xsize: usize, ysize: usize, } impl Canvas for SdlCanvas { fn new(x: usize, y: usize) -> SdlCanvas { //... SdlCanvas { sdl_context: sdl_context, renderer: renderer, canvas: vec![vec![0;y];x], zbuffer: vec![vec![std::i32::MIN; y]; x], xsize: x, ysize: y, } } fn show(&mut self) { let mut texture = self.renderer.create_texture_streaming(PixelFormatEnum::RGB24, (self.xsize as u32, self.ysize as u32)).unwrap(); // ... self.renderer.present(); } fn wait_for_enter(&mut self) { //... } fn canvas(&mut self) -> &mut Vec<Vec<u32>>{ &mut self.canvas } fn zbuffer(&mut self) -> &mut Vec<Vec<i32>>{ &mut self.zbuffer } fn xsize(&self) -> usize{ self.xsize } fn ysize(&self) -> usize{ self.ysize } }
ç解ãè€éã«ããªãããã«ãäžçŽç©ãšãã®å®è£ ã«çŽæ¥é¢ä¿ããªãã³ãŒãã®äžéšãåé€ãã
// ...
眮ãæããŸããã èå³ã®ãã人ã¯ããªããžããªã®å¯Ÿå¿ããã¹ãããã·ã§ããã§å®å šãªã³ãŒããèŠãããšãã§ããŸã ã ã芧ã®ãšãããããã¯å°ãå€ãã£ãŠããããã«èŠããŸãããå®éã«ã¯éåžžã®ç¶æ¿ãšã€ã³ã¿ãŒãã§ãŒã¹ã«éåžžã«äŒŒãŠããŸãã ã³ãŒãã®ãµã€ãºã¯ããã»ã©å€ãããŸããã å¯äžã®ç¬éãäžçŽç©ã¯ãæ§é å ã®å€æ°ã®ååšãèŠæ±ããããšãèš±å¯ããŸããã ãã®ããããŠãããŒãµã«å®è£ ãšSdlCanvasã§å¿ èŠãªå€æ°ã®ããã€ãã®ã²ãã¿ãŒãäœæããŠãããããå®è£ ããå¿ èŠããããŸããã äžèšã®å®è£ ã§ã¯ã 察å¿ããèšäºRust by Exampleãæ¬åœã«åœ¹ç«ã¡ãŸããã
åçãèªãããã«å®éã«ã æåã®åé¡ã¯ãTGAãã¡ã€ã«ã®ããããŒãèªã¿åãããšã§ããã å ã®haqreuã³ãŒãã§ã¯ãããã¯ããªãåçŽãªãšã¬ã¬ã³ããªã³ãŒãã§è¡ãããŸãã
#pragma pack(push,1) struct TGA_Header { char idlength; char colormaptype; // ... short width; short height; char bitsperpixel; char imagedescriptor; }; #pragma pack(pop) // ... TGA_Header header; in.read((char *)&header, sizeof(header));
ãã ãããã®ã³ãŒããããªãäœã¬ãã«ã§ããããšãæããã§ãã ãã¡ã€ã«ãããã€ãé åãèªã¿åããæ§é äœã®ã¢ãã¬ã¹ã«ãããé 眮ããŸããæ§é äœã¯ããã®ãã¹ãŠã®ããŒã¿ããã¡ã€ã«ããããŒã«é 眮ãããæ¹æ³ã«å¯Ÿå¿ããããã«äºåã«å®£èšãããŠããŸãã ãã®åã«ãç§ãã¡ã¯äž»ã«ããªãé«ã¬ãã«ã®ã©ã¹ãã«ã€ããŠæžããŸããã ããã§ã¯ãäœã¬ãã«èšèªãšããŠé©çšãããå Žåã®åäœã確èªããŸãã äžè¬çã«ããã¹ãŠã®èª¿æ»ã®åŸã次ã®ã³ãŒãããããŸãã
const HEADERSIZE: usize = 18; // 18 = sizeof(TgaHeader) #[repr(C, packed)] struct TgaHeader { idlength: i8, colormaptype: i8, // ... width: i16, height: i16, bitsperpixel: i8, imagedescriptor: i8, } // ... let mut file = File::open(&path).unwrap(); let mut header_bytes: [u8; HEADERSIZE] = [0; HEADERSIZE]; file.read(&mut header_bytes); let header = unsafe { mem::transmute::<[u8; HEADERSIZE], TgaHeader>(header_bytes) };
æ§é ã®åã«ããããªããã»ããµãã£ã¬ã¯ãã£ãã¯ããã®ã¹ãã¬ãŒãžã¡ãœãããå®çŸ©ããŸãã éåžžãRustïŒããã³C ++ã§ã¯ïŒã®æ§é äœãã£ãŒã«ãã¯ãã¢ãŒããã¯ãã£ã«åŸã£ãŠé 眮ãããŸãã ããšãã°ãç§ã®ã³ã³ãã¥ãŒã¿ãŒã§ã¯ãi8ãši16ãå«ãæ§é äœã¯3ãã€ãã§ã¯ãªã4ãã€ããå æããŸããi8ã¯1ã€ã®ããã«ãã€ãã»ã«ãå æããããã«æŽåãããããã§ãã C ++ã§ã¯ãããã¯åãããã«æ©èœããŸãã ããã¯ããã®ãããã¯ã«é¢ãã圌ã®èšäºã§ k06aã«ãã£ãŠè©³çŽ°ã«èª¬æãããŸããã æ§é å ã®ããŒã¿ããã€ã
#[repr(C, packed)]
ééãªãç¶ãããã«ã
#[repr(C, packed)]
ãŸãã ãããã£ãŠãç§ãã¡ã®æ§é ã¯ãTGAãçºæããããšãã®å³ããå€ä»£ã«ãã£ãããã«ãä»ã§ã¯èšæ¶ã®äžã«ãããŸãã ããã«ãããã§ã¯å®å šã§ãªãã³ãŒãã䜿çšããŸãã ã¡ã¢ãªå ã®ãããããç¹å®ã®æ§é ãšããŠãã§ãã¯ããã«è§£éãããšãéçåä»ãã®èãæ¹ãå®å šã«åŽ©ããŸãã 幞ããªããšã«ãã»ãšãã©ã®å Žåããã®ã³ãŒãã¯æ©èœããŸãã ïŒãã ããåžžã«ã§ã¯ãããŸãããã ãã€ãé ã®ããããçš®é¡ã®ãã¥ã¢ã³ã¹ããŸã ãããŸã ïŒãããŠããã¡ããããããã¡ãµã€ãºãå®æ°ãšããŠèšå®ããŠããããšã«æ°ã¥ããŸããã ããããsizeofã«ã€ããŠã¯ã©ãã§ããããã ããŠãããã¯Rustã«ãããŸãããå®æ°åŒãšããŠèšç®ãããŸããããå®è¡æã«èæ ®ãããŸãã é åã®ãµã€ãºã¯ãã³ã³ãã€ã«æ®µéã§ããã£ãŠããå¿ èŠããããŸãã ãããã¯ãã€ã§ãã
ãã®åŸãæãèå³æ·±ãã RLEå§çž®ãªãã§RGBAïŒãã¯ã»ã«ããã4ãã€ãïŒã®ãããªåçŽãªTGAãã¡ã€ã«ãèªãæ¹æ³ãåŠãŒããšãããšããããã€ãã®è¬ããããŸããã ç§ã®ããã°ã©ã ã¯äžè¬çã«åçŽãªç»åãåŠçãããã®ãããªæ··ä¹±ãåŒãèµ·ãããŸããïŒ

ãã®æ®µéã§ã®ã³ãŒãã®ã¹ãããã·ã§ããã¯æ¬¡ã®ãšããã§ã ã èå³ãããå Žåã¯ãèšäºãèªã¿ç¶ããåã«èªåã§ãšã©ãŒãèŠã€ããŠãã ããã ãã¡ã€ã«ãèªã¿åãé¢æ°ã®ã©ããã«ãããŸãã
fn read(path: &str) -> TgaCanvas{ let path = Path::new(path); let mut file = BufReader::new(File::open(&path).unwrap()); let mut header_bytes: [u8; HEADERSIZE] = [0; HEADERSIZE]; file.read(&mut header_bytes); let header = unsafe { mem::transmute::<[u8; HEADERSIZE], TgaHeader>(header_bytes) }; let xsize = header.width as usize; let ysize = header.height as usize; debug!("read header: width = {}, height = {}", xsize, ysize); let bytespp = header.bitsperpixel>>3; debug!("bytes per pixel - {}", bytespp); let mut canvas = vec![vec![0;ysize];xsize]; for iy in 0..ysize{ for ix in 0..xsize{ if bytespp == 1 { let mut bytes: [u8; 1] = [0; 1]; file.read(&mut bytes); let intensity = bytes[0] as u32; canvas[ix][iy] = intensity + intensity*256 + intensity*256*256; } else if bytespp == 3 { let mut bytes: [u8; 3] = [0; 3]; file.read(&mut bytes); canvas[ix][iy] = bytes[2] as u32 + bytes[1] as u32*256 + bytes[0] as u32*256*256; } else if bytespp == 4 { let mut bytes: [u8; 4] = [0; 4]; file.read(&mut bytes); if ix == 0 { debug!("{} {} {} {}", bytes[0], bytes[1], bytes[2], bytes[3]); } canvas[ix][iy] = bytes[2] as u32 + ((bytes[1] as u32) << (8*1)) + ((bytes[0] as u32) << (8*2)); //debug!("{}", canvas[ix][iy]); } } debug!("{}", canvas[0][iy]); } TgaCanvas { canvas: canvas, zbuffer: vec![vec![std::i32::MIN; ysize]; xsize], xsize: xsize, ysize: ysize, } }
ç§ãæ¬åœã«å°æãããã®ã¯ã
BufReader::new(File::open(&path).unwrap());
File::open(&path).unwrap();
ããã®åŸããã°ã¯è¡šç€ºãããŸããã§ããã çè«çã«ã¯ããã€ãã¹ããªãŒã ã劚ããããšãªãããããã¡ãªã³ã°ã®ã¿ãæäŸããå¿ èŠããããããBufReaderã®ãã°ã ãšããæããŸããã
ééãã¯äœã§ããã
ããã¯ãæšæºã©ã€ãã©ãªã®èªã¿åãé¢æ°ã®äºæããªãåäœã§ãã readïŒïŒã¯ã
ãã€ããèªã¿åãããããšãä¿èšŒããŸããããããã¯ããããã±ãŒã¹ã§ãã ããããåžžã«ã§ã¯ãããŸããã ãããã¡ãŒã¯BufReaderã§çµäºããæ®ã£ãŠãããã€ãæ°ãè¿ããŸãããã®éã«ãããã¯ã°ã©ãŠã³ãã§ãããã¡ãŒãåã³åãå§ããŸãã ç§ããã€ã³ããåŸãå Žåã ãã®çµæãããæç¹ã§ãæ°ãã€ããéããŠããŸããç»åãç ŽæããŠããããšãå€æããŸããã readïŒïŒåŽã®ãã®åäœã¯ææžåãããŠããŸãããç§ã®æèŠã§ã¯ã æå°éã®é©ãã®ååã«éåããŠããŸãã ãã¶ãç§ã¯äœ¿çšãããæ¹æ³ã«é¢ãããã¹ãŠã®ããã¥ã¡ã³ããèªãã§ããªãã ãã§ãã...
buffer.len()
ãã€ããèªã¿åãããããšãä¿èšŒããŸããããããã¯ããããã±ãŒã¹ã§ãã ããããåžžã«ã§ã¯ãããŸããã ãããã¡ãŒã¯BufReaderã§çµäºããæ®ã£ãŠãããã€ãæ°ãè¿ããŸãããã®éã«ãããã¯ã°ã©ãŠã³ãã§ãããã¡ãŒãåã³åãå§ããŸãã ç§ããã€ã³ããåŸãå Žåã ãã®çµæãããæç¹ã§ãæ°ãã€ããéããŠããŸããç»åãç ŽæããŠããããšãå€æããŸããã readïŒïŒåŽã®ãã®åäœã¯ææžåãããŠããŸãããç§ã®æèŠã§ã¯ã æå°éã®é©ãã®ååã«éåããŠããŸãã ãã¶ãç§ã¯äœ¿çšãããæ¹æ³ã«é¢ãããã¹ãŠã®ããã¥ã¡ã³ããèªãã§ããªãã ãã§ãã...
次ã«ãTGAãã¡ã€ã«ã®åé¡ã¯ããã«è§£æ±ºãããŸããã TgaCanvasã®æçµããŒãžã§ã³ã®ã³ãŒãã¯ããã€ãã®ããã«ããªããžããªã®ã¹ãããã·ã§ããã§èŠãããšãã§ããŸã ã
ãã¯ã¹ãã£ãŒ
åé¡ã¯ã圌ããåŸ ããªãã£ããšããããæ¥ãŸããã Rustã¯åã«æååãé£çµããçµæãstrãšããŠè¿ãããšãã§ããªãããšãããããŸãïŒããã¯ããªããã£ãå-æååã§ãïŒã Strã«ã¯é£çµã¡ãœããããããŸããã æååã«ã¯ãã
ç解ããã«æžããå€ãããã¹ã
ãã®åŸããã¹ãŠãéåžžã«ç°¡åã§ãã çµæã¯ããªããžããªã®ã¹ã©ã€ã¹ã§ç¢ºèªã§ããã³ãŒãã§ã ã èšäºã®çŽ¹ä»ã§ç¢ºèªã§ãããŸãã«ãã®åçã衚瀺ããŸãã
察å¿ããas_strïŒïŒã¡ãœããã¯äžå®å®ã§ãã ã€ãŸããRustã®å®å®ãããªãªãŒã¹ã§ã¯äœ¿çšã§ããŸããã å®éã«ã¯åççãªæ±ºå®ããããŸã-ãã¡ã€ã«åãæååãšããŠè»¢éããŸãããstrã§ã¯ãããŸããã
ãã
ãã®ã§ãããããã§ã®åé¡ã¯ããã¹ãŠã®åŒã³åºãã§
ãªãèšè¿°ããå¿ èŠãããããš
ãããã³
ã ç§ã¯ãã®åé¯ã®ããã®èšèªã«è ¹ãç«ãŠããããŠãŸããåé¯ããããšã«æ±ºããŸããã ãããç§ã®é£çµã³ãŒãã§ãã
æåã«ãStringã¯ã©ã¹ã®ã¡ãœããã䜿çšããå®éã®é£çµãããã次ã«Stringããstrãžã®å€æããããŸãã ã©ããã£ãŠïŒ Stringã®splitïŒïŒã¡ãœãããstrã³ã¬ã¯ã·ã§ã³ã®å埩åãè¿ãããšãããããŸããã ããã«ãã®ãããªãã³ã»ã³ã¹ããããŸãã éåžžã®æ¹æ³ã§ã¯ãäœããã®çç±ã§æååããstrãååŸããããšã¯ã§ããŸããããéåžžã«æªãã§ããå Žå...äžè¬ã«ããã®ãããªæãããããã¯ã䜿çšããŠæååãstrã«å€æããå¿ èŠããããããèšèªã¯ãŸã 湿ã£ãŠããŸãã Stringãstrã«å€æããæãçŸããããã¯ã®ã³ã³ãã¹ããçºè¡šãããŸããã ã³ã¡ã³ãã«ãªãã·ã§ã³ãèšè¿°ããŸãã ïŒæ³šïŒäžå®å®ãªæ©èœãå®å šã§ãªãã³ãŒãã¯äœ¿çšã§ããŸããïŒã
new(file_path: &String) -> Model
ãã
new(file_path: &String) -> Model
ãã®ã§ãããããã§ã®åé¡ã¯ããã¹ãŠã®åŒã³åºãã§
Model::new("african_head.obj");
ãªãèšè¿°ããå¿ èŠãããããš
Model::new("african_head.obj");
ãããã³
Model::new("african_head.obj".to_string());
ã ç§ã¯ãã®åé¯ã®ããã®èšèªã«è ¹ãç«ãŠããããŠãŸããåé¯ããããšã«æ±ºããŸããã ãããç§ã®é£çµã³ãŒãã§ãã
let texture_path_string = file_path.rsplitn(2, '.').last().unwrap().to_string() + "_diffuse.tga"; let texture_path_str = texture_path_string.split("*").next().unwrap();
æåã«ãStringã¯ã©ã¹ã®ã¡ãœããã䜿çšããå®éã®é£çµãããã次ã«Stringããstrãžã®å€æããããŸãã ã©ããã£ãŠïŒ Stringã®splitïŒïŒã¡ãœãããstrã³ã¬ã¯ã·ã§ã³ã®å埩åãè¿ãããšãããããŸããã ããã«ãã®ãããªãã³ã»ã³ã¹ããããŸãã éåžžã®æ¹æ³ã§ã¯ãäœããã®çç±ã§æååããstrãååŸããããšã¯ã§ããŸããããéåžžã«æªãã§ããå Žå...äžè¬ã«ããã®ãããªæãããããã¯ã䜿çšããŠæååãstrã«å€æããå¿ èŠããããããèšèªã¯ãŸã 湿ã£ãŠããŸãã Stringãstrã«å€æããæãçŸããããã¯ã®ã³ã³ãã¹ããçºè¡šãããŸããã ã³ã¡ã³ãã«ãªãã·ã§ã³ãèšè¿°ããŸãã ïŒæ³šïŒäžå®å®ãªæ©èœãå®å šã§ãªãã³ãŒãã¯äœ¿çšã§ããŸããïŒã
ããšãã
ããããµã€ã¯ã«ã®æåŸã®èšäºã ãšæããŸãã æåã¯ãRustãç 究ããææ°ã®3Dã°ã©ãã£ãã¯ã¹ãã©ã®ããã«æ©èœããããç解ãããšãã2ã€ã®ç®æšãèšå®ããŸããã ç§ã¯ãŸã C-3Dã°ã©ãã£ãã¯ã¹ãå®æããŠããŸããããRustã¯ãã1ãæåã»ã©åã«æ £ããŠããªãèšèªã§ã¯ãããŸããã èšèªã«é¢ããæè¿ã®ãçºèŠãã®ã»ãšãã©ã¯ãããããªãã¥ã¢ã³ã¹ã§ãã ããæ°é±éãæ ¹æ¬çã«æ°ãããã®ãçºèŠããŠããŸããã ã ããæ¬è³ªçã«ãç§ã¯èšäºã§æžãããšã¯äœããªãã ãŸããã¬ã³ãã©ãŒãã«ã¡ã©ã®åããããããGuroã®è²åãã«é è¿æ³ã®æªã¿ãè¿œå ãããã®ã¿ã€ãã©ã€ã¿ãŒãèšäº1ããæç»ããŠãé¢å¿ã®ãã人ãåŒãç¶ã察å¿ãããªããžããªã§ç§ã®é²æãç£èŠã§ããããã«ããäºå®ã§ã ã èªãã§ããããã¹ãŠã®äººã«æè¬ããŸãã ãããŠãæçãªã³ã¡ã³ããæäŸããŠããã人ãã¡ã«æè¬ããŸãã