comparison interpreters/src/th06/std.rs @ 757:21b186be2590

Split the Rust version into multiple crates.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Tue, 05 Jan 2021 02:16:32 +0100
parents src/th06/std_vm.rs@5016c09e5d7c
children
comparison
equal deleted inserted replaced
756:4d91790cf8ab 757:21b186be2590
1 //! Interpreter of STD files.
2
3 use touhou_formats::th06::std::{Stage, Call, Instruction};
4 use crate::th06::interpolator::{Interpolator3, Formula};
5 use touhou_utils::math::{Mat4, setup_camera};
6 use std::cell::RefCell;
7 use std::rc::Rc;
8
9 /// Interpreter for Stage.
10 pub struct StageRunner {
11 /// XXX: no pub.
12 pub stage: Rc<RefCell<Stage>>,
13 frame: u32,
14
15 position: Interpolator3<f32>,
16 direction: Interpolator3<f32>,
17
18 /// XXX: no pub.
19 pub fog_color: [f32; 4],
20 /// XXX: no pub.
21 pub fog_near: f32,
22 /// XXX: no pub.
23 pub fog_far: f32,
24 }
25
26 impl StageRunner {
27 /// Create a new StageRunner attached to a Stage.
28 pub fn new(stage: Rc<RefCell<Stage>>) -> StageRunner {
29 StageRunner {
30 stage,
31 frame: 0,
32 position: Interpolator3::new([0., 0., 0.], 0, [0., 0., 0.], 0, Formula::Linear),
33 direction: Interpolator3::new([0., 0., 0.], 0, [0., 0., 0.], 0, Formula::Linear),
34 fog_color: [1.; 4],
35 fog_near: 0.,
36 fog_far: 1000.,
37 }
38 }
39
40 /// Advance the simulation one frame.
41 pub fn run_frame(&mut self) {
42 let stage = self.stage.borrow();
43
44 for Call { time, instr } in stage.script.iter() {
45 let time = *time;
46 if time != self.frame {
47 continue;
48 }
49
50 println!("{} {:?}", time, instr);
51
52 match *instr {
53 Instruction::SetViewpos(x, y, z) => {
54 self.position.set_start(time, [x, y, z]);
55 for Call { time, instr } in stage.script.iter().cloned() {
56 if time <= self.frame {
57 continue;
58 }
59 if let Instruction::SetViewpos(x, y, z) = instr {
60 self.position.set_end(time, [x, y, z]);
61 break;
62 }
63 }
64 }
65 Instruction::SetFog(b, g, r, a, near, far) => {
66 self.fog_color = [r as f32 / 255., g as f32 / 255., b as f32 / 255., a as f32 / 255.];
67 self.fog_near = near;
68 self.fog_far = far;
69 }
70 Instruction::SetViewpos2(dx, dy, dz) => {
71 let direction = [dx, dy, dz];
72 self.direction.set_start(time, if time == 0 { direction } else { self.direction.values(time) });
73 self.direction.set_end_values(direction);
74 }
75 Instruction::StartInterpolatingViewpos2(frame, _, _) => {
76 self.direction.set_end_frame(time + frame);
77 }
78 Instruction::StartInterpolatingFog(frame, _, _) => {
79 }
80 Instruction::Unknown(_, _, _) => {
81 }
82 }
83 }
84
85 self.frame += 1;
86 }
87
88 /// Generate the model-view matrix for the current frame.
89 pub fn get_model_view(&self) -> Mat4 {
90 let [x, y, z] = self.position.values(self.frame);
91
92 let [dx, dy, dz] = self.direction.values(self.frame);
93
94 let view = setup_camera(dx, dy, dz);
95
96 let model = Mat4::new([[1., 0., 0., 0.],
97 [0., 1., 0., 0.],
98 [0., 0., 1., 0.],
99 [-x, -y, -z, 1.]]);
100 model * view
101 }
102 }