mirror of
https://github.com/scurest/apicula.git
synced 2025-06-19 07:05:35 -04:00
Wire up the viewer for material animations
Currently they don't do anything though.
This commit is contained in:
parent
60ed16ad2d
commit
af0d02da34
@ -7,7 +7,7 @@
|
|||||||
//! out for ourselves. This modules contains the heuristics for that.
|
//! out for ourselves. This modules contains the heuristics for that.
|
||||||
|
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use db::{Database, AnimationId, TextureId, PaletteId, ModelId, PatternId};
|
use db::{Database, AnimationId, TextureId, PaletteId, ModelId, PatternId, MatAnimId};
|
||||||
use errors::Result;
|
use errors::Result;
|
||||||
|
|
||||||
/// A Connection records interrelationships between Nitro resources, namely how
|
/// A Connection records interrelationships between Nitro resources, namely how
|
||||||
@ -25,6 +25,8 @@ pub struct ModelConnection {
|
|||||||
/// List of patterns that can be applied to the model (and how to apply
|
/// List of patterns that can be applied to the model (and how to apply
|
||||||
/// them).
|
/// them).
|
||||||
pub patterns: Vec<PatternConnection>,
|
pub patterns: Vec<PatternConnection>,
|
||||||
|
/// List of material animations that can be applied to the model.
|
||||||
|
pub mat_anims: Vec<MatAnimConnection>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Result of resolving which texture/palette a material should use.
|
/// Result of resolving which texture/palette a material should use.
|
||||||
@ -118,7 +120,8 @@ impl Connection {
|
|||||||
|
|
||||||
let animations = find_applicable_animations(db, model_id, options);
|
let animations = find_applicable_animations(db, model_id, options);
|
||||||
let patterns = find_applicable_patterns(db, model_id);
|
let patterns = find_applicable_patterns(db, model_id);
|
||||||
ModelConnection { materials, animations, patterns }
|
let mat_anims = find_applicable_mat_anims(db, model_id);
|
||||||
|
ModelConnection { materials, animations, patterns, mat_anims }
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
if missing_textures {
|
if missing_textures {
|
||||||
@ -285,3 +288,20 @@ fn find_applicable_patterns(db: &Database, model_id: ModelId) -> Vec<PatternConn
|
|||||||
})
|
})
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates that a model can have the specified material animations applied to
|
||||||
|
/// it.
|
||||||
|
pub struct MatAnimConnection {
|
||||||
|
pub mat_anim_id: MatAnimId,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_applicable_mat_anims(db: &Database, model_id: ModelId) -> Vec<MatAnimConnection> {
|
||||||
|
let model = &db.models[model_id];
|
||||||
|
db.mat_anims.iter().enumerate().filter_map(|(mat_anim_id, mat_anim)| {
|
||||||
|
// Check if all the tracks target valid materials
|
||||||
|
let valid = mat_anim.tracks.iter().all(|track| {
|
||||||
|
model.materials.iter().any(|mat| mat.name == track.name)
|
||||||
|
});
|
||||||
|
if !valid { None } else { Some(MatAnimConnection { mat_anim_id }) }
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
@ -6,7 +6,7 @@ use cgmath::{Matrix4, One};
|
|||||||
use convert::image_namer::ImageNamer;
|
use convert::image_namer::ImageNamer;
|
||||||
use db::{Database, ModelId};
|
use db::{Database, ModelId};
|
||||||
use skeleton::{Skeleton, Transform, SMatrix};
|
use skeleton::{Skeleton, Transform, SMatrix};
|
||||||
use primitives::{self, Primitives};
|
use primitives::{self, Primitives, DynamicState};
|
||||||
use nitro::Model;
|
use nitro::Model;
|
||||||
use petgraph::{Direction};
|
use petgraph::{Direction};
|
||||||
use petgraph::graph::NodeIndex;
|
use petgraph::graph::NodeIndex;
|
||||||
@ -42,7 +42,17 @@ pub fn write(
|
|||||||
let objects = &model.objects.iter()
|
let objects = &model.objects.iter()
|
||||||
.map(|o| make_invertible(&o.matrix))
|
.map(|o| make_invertible(&o.matrix))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let prims = &Primitives::build(model, primitives::PolyType::TrisAndQuads, objects);
|
let uv_mats = &model.materials.iter()
|
||||||
|
.map(|mat| {
|
||||||
|
if mat.params.texcoord_transform_mode() == 1 {
|
||||||
|
mat.texture_mat
|
||||||
|
} else {
|
||||||
|
Matrix4::one()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let state = DynamicState { objects, uv_mats };
|
||||||
|
let prims = &Primitives::build(model, primitives::PolyType::TrisAndQuads, state);
|
||||||
let skel = &Skeleton::build(model, objects);
|
let skel = &Skeleton::build(model, objects);
|
||||||
|
|
||||||
let ctx = Ctx { model_id, model, db, conn, image_namer, objects, prims, skel };
|
let ctx = Ctx { model_id, model, db, conn, image_namer, objects, prims, skel };
|
||||||
|
@ -6,10 +6,10 @@ mod primitive;
|
|||||||
use nitro::Model;
|
use nitro::Model;
|
||||||
use db::{Database, ModelId};
|
use db::{Database, ModelId};
|
||||||
use connection::Connection;
|
use connection::Connection;
|
||||||
use primitives::{Primitives, PolyType};
|
use primitives::{Primitives, PolyType, DynamicState};
|
||||||
use skeleton::{Skeleton, Transform, SMatrix};
|
use skeleton::{Skeleton, Transform, SMatrix};
|
||||||
use super::image_namer::ImageNamer;
|
use super::image_namer::ImageNamer;
|
||||||
use cgmath::Matrix4;
|
use cgmath::{Matrix4, One};
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
use self::gltf::{GlTF, Buffer, ByteVec, VecExt};
|
use self::gltf::{GlTF, Buffer, ByteVec, VecExt};
|
||||||
use self::object_trs::ObjectTRSes;
|
use self::object_trs::ObjectTRSes;
|
||||||
@ -45,7 +45,17 @@ pub fn to_gltf(
|
|||||||
let objects = rest_trses.objects.iter()
|
let objects = rest_trses.objects.iter()
|
||||||
.map(Matrix4::from)
|
.map(Matrix4::from)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let prims = Primitives::build(model, PolyType::TrisAndQuads, &objects);
|
let uv_mats = model.materials.iter()
|
||||||
|
.map(|mat| {
|
||||||
|
if mat.params.texcoord_transform_mode() == 1 {
|
||||||
|
mat.texture_mat
|
||||||
|
} else {
|
||||||
|
Matrix4::one()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<Matrix4<f64>>>();
|
||||||
|
let state = DynamicState { objects: &objects, uv_mats: &uv_mats };
|
||||||
|
let prims = Primitives::build(model, PolyType::TrisAndQuads, state);
|
||||||
let prims = &encode_ngons(prims);
|
let prims = &encode_ngons(prims);
|
||||||
let skel = &Skeleton::build(model, &objects);
|
let skel = &Skeleton::build(model, &objects);
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ pub type TextureId = usize;
|
|||||||
pub type PaletteId = usize;
|
pub type PaletteId = usize;
|
||||||
pub type AnimationId = usize;
|
pub type AnimationId = usize;
|
||||||
pub type PatternId = usize;
|
pub type PatternId = usize;
|
||||||
//pub type MatAnimId = usize;
|
pub type MatAnimId = usize;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Database {
|
pub struct Database {
|
||||||
|
@ -31,6 +31,15 @@ pub enum PolyType {
|
|||||||
TrisAndQuads,
|
TrisAndQuads,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Dynamic state for a model (ie. stuff that changes during an animation, as
|
||||||
|
/// opposed to static state in the Model object).
|
||||||
|
pub struct DynamicState<'a> {
|
||||||
|
/// Object matrices to use.
|
||||||
|
pub objects: &'a [Matrix4<f64>],
|
||||||
|
/// UV-transform matrices to use for each material.
|
||||||
|
pub uv_mats: &'a [Matrix4<f64>],
|
||||||
|
}
|
||||||
|
|
||||||
/// Info about the result of a draw call, ie. the result of drawing a mesh (a set
|
/// Info about the result of a draw call, ie. the result of drawing a mesh (a set
|
||||||
/// of GPU commands) while in a particular GPU state (matrix stack, bound material,
|
/// of GPU commands) while in a particular GPU state (matrix stack, bound material,
|
||||||
/// etc.).
|
/// etc.).
|
||||||
@ -78,8 +87,8 @@ impl Default for Vertex {
|
|||||||
implement_vertex!(Vertex, position, texcoord, color, normal);
|
implement_vertex!(Vertex, position, texcoord, color, normal);
|
||||||
|
|
||||||
impl Primitives {
|
impl Primitives {
|
||||||
pub fn build(model: &Model, poly_type: PolyType, objects: &[Matrix4<f64>]) -> Primitives {
|
pub fn build(model: &Model, poly_type: PolyType, state: DynamicState) -> Primitives {
|
||||||
let mut b = Builder::new(model, poly_type, objects);
|
let mut b = Builder::new(model, poly_type, state);
|
||||||
use nitro::render_cmds::Op;
|
use nitro::render_cmds::Op;
|
||||||
for op in &model.render_ops {
|
for op in &model.render_ops {
|
||||||
match *op {
|
match *op {
|
||||||
@ -125,7 +134,7 @@ impl GpuState {
|
|||||||
|
|
||||||
struct Builder<'a, 'b> {
|
struct Builder<'a, 'b> {
|
||||||
model: &'a Model,
|
model: &'a Model,
|
||||||
objects: &'b [Matrix4<f64>],
|
state: DynamicState<'b>,
|
||||||
poly_type: PolyType,
|
poly_type: PolyType,
|
||||||
|
|
||||||
gpu: GpuState,
|
gpu: GpuState,
|
||||||
@ -140,14 +149,13 @@ struct Builder<'a, 'b> {
|
|||||||
|
|
||||||
cur_draw_call: DrawCall,
|
cur_draw_call: DrawCall,
|
||||||
next_vertex: Vertex,
|
next_vertex: Vertex,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> Builder<'a, 'b> {
|
impl<'a, 'b> Builder<'a, 'b> {
|
||||||
fn new(model: &'a Model, poly_type: PolyType, objects: &'b [Matrix4<f64>]) -> Builder<'a, 'b> {
|
fn new(model: &'a Model, poly_type: PolyType, state: DynamicState<'b>) -> Builder<'a, 'b> {
|
||||||
Builder {
|
Builder {
|
||||||
model,
|
model,
|
||||||
objects,
|
state,
|
||||||
poly_type,
|
poly_type,
|
||||||
gpu: GpuState::new(),
|
gpu: GpuState::new(),
|
||||||
vertices: vec![],
|
vertices: vec![],
|
||||||
@ -174,6 +182,9 @@ impl<'a, 'b> Builder<'a, 'b> {
|
|||||||
let vert_len = self.vertices.len() as u16;
|
let vert_len = self.vertices.len() as u16;
|
||||||
let ind_len = self.indices.len();
|
let ind_len = self.indices.len();
|
||||||
|
|
||||||
|
// Bind material
|
||||||
|
self.gpu.texture_matrix = self.state.uv_mats[mat_id as usize];
|
||||||
|
|
||||||
self.cur_draw_call = DrawCall {
|
self.cur_draw_call = DrawCall {
|
||||||
vertex_range: vert_len..vert_len,
|
vertex_range: vert_len..vert_len,
|
||||||
index_range: ind_len..ind_len,
|
index_range: ind_len..ind_len,
|
||||||
@ -215,7 +226,7 @@ impl<'a, 'b> Builder<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn mul_by_object(&mut self, object_id: u8) {
|
fn mul_by_object(&mut self, object_id: u8) {
|
||||||
self.gpu.mul_matrix(&self.objects[object_id as usize]);
|
self.gpu.mul_matrix(&self.state.objects[object_id as usize]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blend(&mut self, terms: &[SkinTerm]) {
|
fn blend(&mut self, terms: &[SkinTerm]) {
|
||||||
@ -369,12 +380,14 @@ fn run_gpu_cmds(b: &mut Builder, commands: &[u8]) {
|
|||||||
GpuCmd::TexCoord { texcoord } => {
|
GpuCmd::TexCoord { texcoord } => {
|
||||||
b.cur_draw_call.used_texcoords = true;
|
b.cur_draw_call.used_texcoords = true;
|
||||||
|
|
||||||
|
// Apply texture matrix
|
||||||
|
let texcoord = b.gpu.texture_matrix * vec4(texcoord.x, texcoord.y, 0.0, 1.0);
|
||||||
|
|
||||||
// Transform into OpenGL-type [0,1]x[0,1] texture space.
|
// Transform into OpenGL-type [0,1]x[0,1] texture space.
|
||||||
let texcoord = Point2::new(
|
let texcoord = Point2::new(
|
||||||
texcoord.x / b.cur_texture_dim.0 as f64,
|
texcoord.x / b.cur_texture_dim.0 as f64,
|
||||||
1.0 - texcoord.y / b.cur_texture_dim.1 as f64, // y-down to y-up
|
1.0 - texcoord.y / b.cur_texture_dim.1 as f64, // y-down to y-up
|
||||||
);
|
);
|
||||||
let texcoord = b.gpu.texture_matrix * vec4(texcoord.x, texcoord.y, 0.0, 0.0);
|
|
||||||
b.next_vertex.texcoord = [texcoord.x as f32, texcoord.y as f32];
|
b.next_vertex.texcoord = [texcoord.x as f32, texcoord.y as f32];
|
||||||
}
|
}
|
||||||
GpuCmd::Color { color } => {
|
GpuCmd::Color { color } => {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use super::model_viewer::{ModelViewer, MaterialTextureBinding};
|
use super::model_viewer::{ModelViewer, MaterialTextureBinding};
|
||||||
use db::{Database, ModelId, AnimationId, PatternId};
|
use db::{Database, ModelId, AnimationId, PatternId, MatAnimId};
|
||||||
use connection::Connection;
|
use connection::Connection;
|
||||||
use glium::Display;
|
use glium::Display;
|
||||||
use glium::glutin::ElementState;
|
use glium::glutin::ElementState;
|
||||||
use glium::{Frame, Surface};
|
use glium::{Frame, Surface};
|
||||||
use glium::glutin::VirtualKeyCode;
|
use glium::glutin::VirtualKeyCode;
|
||||||
use nitro::{Model, Animation, Pattern};
|
use nitro::{Model, Animation, Pattern, MaterialAnimation};
|
||||||
use primitives::{Primitives, PolyType};
|
use primitives::{Primitives, PolyType, DynamicState};
|
||||||
use cgmath::{Matrix4, InnerSpace, One, Vector3, vec3, vec2};
|
use cgmath::{Matrix4, InnerSpace, One, Vector3, vec3, vec2};
|
||||||
use super::fps::FpsCounter;
|
use super::fps::FpsCounter;
|
||||||
use super::{FRAMERATE, BG_COLOR};
|
use super::{FRAMERATE, BG_COLOR};
|
||||||
@ -18,14 +18,21 @@ pub struct Viewer {
|
|||||||
|
|
||||||
/// ID of the viewed model.
|
/// ID of the viewed model.
|
||||||
model_id: ModelId,
|
model_id: ModelId,
|
||||||
|
|
||||||
/// The connection has a list of all the animations that can be applied to
|
/// The connection has a list of all the animations that can be applied to
|
||||||
/// this model. This is the index of the current animation in that list (or
|
/// this model. This is the index of the current animation in that list (or
|
||||||
/// None if no animation is selected).
|
/// None if no animation is selected).
|
||||||
anim_idx: Option<usize>,
|
anim_idx: Option<usize>,
|
||||||
/// Current animation frame.
|
/// Current animation frame.
|
||||||
anim_frame: u16,
|
anim_frame: u16,
|
||||||
|
|
||||||
pat_idx: Option<usize>,
|
pat_idx: Option<usize>,
|
||||||
pat_anim_frame: u16,
|
pat_anim_frame: u16,
|
||||||
|
|
||||||
|
mat_anim_idx: Option<usize>,
|
||||||
|
mat_anim_frame: u16,
|
||||||
|
// TODO: refactor this
|
||||||
|
|
||||||
/// When single-stepping is enabled, the user advanced the animation
|
/// When single-stepping is enabled, the user advanced the animation
|
||||||
/// manually. When disabled, the animation advanced with time (ie. plays
|
/// manually. When disabled, the animation advanced with time (ie. plays
|
||||||
/// normally).
|
/// normally).
|
||||||
@ -56,6 +63,7 @@ pub static CONTROL_HELP: &'static str =
|
|||||||
" OP Prev/Next Animation\n",
|
" OP Prev/Next Animation\n",
|
||||||
" [] Single-step Animation\n",
|
" [] Single-step Animation\n",
|
||||||
" KL Prev/Next Pattern Animation\n",
|
" KL Prev/Next Pattern Animation\n",
|
||||||
|
" ;' Prev/Next Material Animation\n",
|
||||||
" Space Print Info\n",
|
" Space Print Info\n",
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -75,6 +83,8 @@ impl Viewer {
|
|||||||
anim_frame: 0,
|
anim_frame: 0,
|
||||||
pat_idx: None,
|
pat_idx: None,
|
||||||
pat_anim_frame: 0,
|
pat_anim_frame: 0,
|
||||||
|
mat_anim_idx: None,
|
||||||
|
mat_anim_frame: 0,
|
||||||
single_stepping: false,
|
single_stepping: false,
|
||||||
move_vector: vec3(0.0, 0.0, 0.0),
|
move_vector: vec3(0.0, 0.0, 0.0),
|
||||||
speed_idx: DEFAULT_SPEED_IDX,
|
speed_idx: DEFAULT_SPEED_IDX,
|
||||||
@ -108,6 +118,7 @@ impl Viewer {
|
|||||||
self.next_frame();
|
self.next_frame();
|
||||||
}
|
}
|
||||||
self.next_pattern_frame(display);
|
self.next_pattern_frame(display);
|
||||||
|
self.next_mat_anim_frame();
|
||||||
self.time_acc -= FRAMERATE;
|
self.time_acc -= FRAMERATE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,6 +198,18 @@ impl Viewer {
|
|||||||
self.change_pat_idx(display, new_pat_idx);
|
self.change_pat_idx(display, new_pat_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Next/prev material animation
|
||||||
|
Key::Apostrophe => {
|
||||||
|
let num = self.conn.models[self.model_id].mat_anims.len();
|
||||||
|
let new_idx = maybe_next(self.mat_anim_idx, 0..num);
|
||||||
|
self.change_mat_anim_idx(new_idx);
|
||||||
|
}
|
||||||
|
Key::Semicolon => {
|
||||||
|
let num = self.conn.models[self.model_id].mat_anims.len();
|
||||||
|
let new_idx = maybe_prev(self.mat_anim_idx, 0..num);
|
||||||
|
self.change_mat_anim_idx(new_idx);
|
||||||
|
}
|
||||||
|
|
||||||
// Speed up/down
|
// Speed up/down
|
||||||
Key::LShift => {
|
Key::LShift => {
|
||||||
if self.speed_idx != SPEEDS.len() - 1 {
|
if self.speed_idx != SPEEDS.len() - 1 {
|
||||||
@ -252,6 +275,18 @@ impl Viewer {
|
|||||||
} else {
|
} else {
|
||||||
write!(s, "No Pattern === ").unwrap()
|
write!(s, "No Pattern === ").unwrap()
|
||||||
}
|
}
|
||||||
|
if let Some(mat_anim_id) = self.mat_anim_id() {
|
||||||
|
let mat_anim = self.cur_mat_anim().unwrap();
|
||||||
|
write!(s, "{anim_name}[{anim_id}/{num_anims}] ({cur_frame}/{num_frames}) === ",
|
||||||
|
anim_name = mat_anim.name,
|
||||||
|
anim_id = mat_anim_id,
|
||||||
|
num_anims = self.db.mat_anims.len(),
|
||||||
|
cur_frame = self.mat_anim_frame,
|
||||||
|
num_frames = mat_anim.num_frames,
|
||||||
|
).unwrap()
|
||||||
|
} else {
|
||||||
|
write!(s, "No Material Animation === ").unwrap()
|
||||||
|
}
|
||||||
write!(s, "{:5.2}fps", self.fps_counter.fps()).unwrap();
|
write!(s, "{:5.2}fps", self.fps_counter.fps()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,6 +322,18 @@ impl Viewer {
|
|||||||
println!("No Pattern Animation Playing")
|
println!("No Pattern Animation Playing")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(mat_anim_id) = self.mat_anim_id() {
|
||||||
|
let mat_anim = self.cur_mat_anim().unwrap();
|
||||||
|
println!("Material Animation: {:?} [{}/{}]",
|
||||||
|
mat_anim.name,
|
||||||
|
mat_anim_id,
|
||||||
|
self.db.mat_anims.len(),
|
||||||
|
);
|
||||||
|
println!("Found in file: {}", self.db.file_paths[self.db.mat_anims_found_in[mat_anim_id]].display());
|
||||||
|
} else {
|
||||||
|
println!("No Material Animation Playing")
|
||||||
|
}
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,9 +346,21 @@ impl Viewer {
|
|||||||
self.stop_animations();
|
self.stop_animations();
|
||||||
|
|
||||||
self.model_id = model_id;
|
self.model_id = model_id;
|
||||||
|
|
||||||
let objects = self.cur_model().objects.iter()
|
let objects = self.cur_model().objects.iter()
|
||||||
.map(|ob| ob.matrix)
|
.map(|ob| ob.matrix)
|
||||||
.collect::<Vec<Matrix4<f64>>>();
|
.collect::<Vec<Matrix4<f64>>>();
|
||||||
|
let uv_mats = self.cur_model().materials.iter()
|
||||||
|
.map(|mat| {
|
||||||
|
if mat.params.texcoord_transform_mode() == 1 {
|
||||||
|
mat.texture_mat
|
||||||
|
} else {
|
||||||
|
Matrix4::one()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<Matrix4<f64>>>();
|
||||||
|
let state = DynamicState { objects: &objects, uv_mats: &uv_mats };
|
||||||
|
|
||||||
let material_map = self.conn.models[self.model_id].materials.iter().map(|mat_conn| {
|
let material_map = self.conn.models[self.model_id].materials.iter().map(|mat_conn| {
|
||||||
match mat_conn.image_id() {
|
match mat_conn.image_id() {
|
||||||
Ok(Some(image_id)) => MaterialTextureBinding::ImageId(image_id),
|
Ok(Some(image_id)) => MaterialTextureBinding::ImageId(image_id),
|
||||||
@ -309,7 +368,7 @@ impl Viewer {
|
|||||||
Err(_) => MaterialTextureBinding::Missing,
|
Err(_) => MaterialTextureBinding::Missing,
|
||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
let prims = Primitives::build(self.cur_model(), PolyType::Tris, &objects);
|
let prims = Primitives::build(self.cur_model(), PolyType::Tris, state);
|
||||||
self.model_viewer.change_model(display, &self.db, prims, material_map);
|
self.model_viewer.change_model(display, &self.db, prims, material_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,7 +394,17 @@ impl Viewer {
|
|||||||
.collect::<Vec<Matrix4<f64>>>()
|
.collect::<Vec<Matrix4<f64>>>()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let prims = Primitives::build(self.cur_model(), PolyType::Tris, &objects);
|
let uv_mats = self.cur_model().materials.iter()
|
||||||
|
.map(|mat| {
|
||||||
|
if mat.params.texcoord_transform_mode() == 1 {
|
||||||
|
mat.texture_mat
|
||||||
|
} else {
|
||||||
|
Matrix4::one()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<Matrix4<f64>>>();
|
||||||
|
let state = DynamicState { objects: &objects, uv_mats: &uv_mats };
|
||||||
|
let prims = Primitives::build(self.cur_model(), PolyType::Tris, state);
|
||||||
self.model_viewer.update_vertices(&prims.vertices);
|
self.model_viewer.update_vertices(&prims.vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,6 +505,16 @@ impl Viewer {
|
|||||||
self.update_materials(display);
|
self.update_materials(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn change_mat_anim_idx(&mut self, mat_anim_idx: Option<usize>) {
|
||||||
|
if self.mat_anim_idx == mat_anim_idx {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.mat_anim_idx = mat_anim_idx;
|
||||||
|
self.mat_anim_frame = 0;
|
||||||
|
self.update_vertices();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn next_pattern_frame(&mut self, display: &Display) {
|
pub fn next_pattern_frame(&mut self, display: &Display) {
|
||||||
let num_frames = self.cur_pattern().map(|pat| pat.num_frames);
|
let num_frames = self.cur_pattern().map(|pat| pat.num_frames);
|
||||||
if let Some(num_frames) = num_frames {
|
if let Some(num_frames) = num_frames {
|
||||||
@ -445,6 +524,15 @@ impl Viewer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn next_mat_anim_frame(&mut self) {
|
||||||
|
let num_frames = self.cur_mat_anim().map(|anim| anim.num_frames);
|
||||||
|
if let Some(num_frames) = num_frames {
|
||||||
|
self.mat_anim_frame += 1;
|
||||||
|
self.mat_anim_frame %= num_frames;
|
||||||
|
self.update_vertices();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_aspect_ratio(&mut self, aspect_ratio: f64) {
|
pub fn set_aspect_ratio(&mut self, aspect_ratio: f64) {
|
||||||
self.model_viewer.aspect_ratio = aspect_ratio as f32;
|
self.model_viewer.aspect_ratio = aspect_ratio as f32;
|
||||||
}
|
}
|
||||||
@ -461,6 +549,10 @@ impl Viewer {
|
|||||||
Some(&self.db.patterns[self.pattern_id()?])
|
Some(&self.db.patterns[self.pattern_id()?])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cur_mat_anim(&self) -> Option<&MaterialAnimation> {
|
||||||
|
Some(&self.db.mat_anims[self.mat_anim_id()?])
|
||||||
|
}
|
||||||
|
|
||||||
fn animation_id(&self) -> Option<AnimationId> {
|
fn animation_id(&self) -> Option<AnimationId> {
|
||||||
let idx = self.anim_idx?;
|
let idx = self.anim_idx?;
|
||||||
Some(self.conn.models[self.model_id].animations[idx])
|
Some(self.conn.models[self.model_id].animations[idx])
|
||||||
@ -471,6 +563,11 @@ impl Viewer {
|
|||||||
Some(self.conn.models[self.model_id].patterns[idx].pattern_id)
|
Some(self.conn.models[self.model_id].patterns[idx].pattern_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mat_anim_id(&self) -> Option<MatAnimId> {
|
||||||
|
let idx = self.mat_anim_idx?;
|
||||||
|
Some(self.conn.models[self.model_id].mat_anims[idx].mat_anim_id)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn speed(&self) -> f32 {
|
pub fn speed(&self) -> f32 {
|
||||||
SPEEDS[self.speed_idx]
|
SPEEDS[self.speed_idx]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user