mirror of
https://codeberg.org/icewind/vbspview.git
synced 2026-06-03 18:24:09 +02:00
props wip
This commit is contained in:
parent
2d3a399433
commit
1b477dfb40
4 changed files with 278 additions and 12 deletions
113
Cargo.lock
generated
113
Cargo.lock
generated
|
|
@ -78,6 +78,15 @@ version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407"
|
checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ansi_term"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "approx"
|
name = "approx"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
@ -1309,6 +1318,15 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matchers"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||||
|
dependencies = [
|
||||||
|
"regex-automata",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matches"
|
name = "matches"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
|
|
@ -1928,6 +1946,15 @@ dependencies = [
|
||||||
"regex-syntax",
|
"regex-syntax",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||||
|
dependencies = [
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.6.25"
|
version = "0.6.25"
|
||||||
|
|
@ -2122,6 +2149,15 @@ dependencies = [
|
||||||
"opaque-debug",
|
"opaque-debug",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sharded-slab"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shared_library"
|
name = "shared_library"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
|
|
@ -2317,6 +2353,15 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread_local"
|
||||||
|
version = "1.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "three-d"
|
name = "three-d"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
|
|
@ -2432,9 +2477,21 @@ checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"tracing-attributes",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-attributes"
|
||||||
|
version = "0.1.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-core"
|
name = "tracing-core"
|
||||||
version = "0.1.23"
|
version = "0.1.23"
|
||||||
|
|
@ -2442,6 +2499,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c"
|
checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"valuable",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-log"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"tracing-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-subscriber"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e0ab7bdc962035a87fba73f3acca9b8a8d0034c2e6f60b84aeaaddddc155dce"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_term",
|
||||||
|
"lazy_static",
|
||||||
|
"matchers",
|
||||||
|
"regex",
|
||||||
|
"sharded-slab",
|
||||||
|
"smallvec",
|
||||||
|
"thread_local",
|
||||||
|
"tracing",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-log",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-tree"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3ce989c9962c7f61fe084dd4a230eec784649dfc2392467c790007c3a6e134e7"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_term",
|
||||||
|
"atty",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-log",
|
||||||
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2522,6 +2622,12 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "valuable"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vbsp"
|
name = "vbsp"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
@ -2551,12 +2657,16 @@ dependencies = [
|
||||||
name = "vbspview"
|
name = "vbspview"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"cgmath",
|
||||||
"delaunator",
|
"delaunator",
|
||||||
"itertools",
|
"itertools",
|
||||||
"miette",
|
"miette",
|
||||||
"steamlocate",
|
"steamlocate",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"three-d",
|
"three-d",
|
||||||
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
|
"tracing-tree",
|
||||||
"vbsp",
|
"vbsp",
|
||||||
"vmdl",
|
"vmdl",
|
||||||
"vpk",
|
"vpk",
|
||||||
|
|
@ -2584,13 +2694,12 @@ dependencies = [
|
||||||
"itertools",
|
"itertools",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vpk"
|
name = "vpk"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b7d3cd4401c0b2a781c6ef77ba639b1235b483147c021d4cc845b70063a6b79c"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"binread",
|
"binread",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,12 @@ thiserror = "1.0.30"
|
||||||
delaunator = "1.0.1"
|
delaunator = "1.0.1"
|
||||||
itertools = "0.10.3"
|
itertools = "0.10.3"
|
||||||
steamlocate = "1.0.1"
|
steamlocate = "1.0.1"
|
||||||
vpk = "0.1.2"
|
vpk = { version = "0.1.2", path = "../vpk-rs" }
|
||||||
vmdl = { version = "*", path = "../vmdl" }
|
vmdl = { version = "*", path = "../vmdl" }
|
||||||
|
tracing = "0.1.29"
|
||||||
|
tracing-subscriber = { version = "0.3.3", features = ["env-filter"] }
|
||||||
|
tracing-tree = "0.2.0"
|
||||||
|
cgmath = "0.18.0"
|
||||||
|
|
||||||
[profile.dev.package."*"]
|
[profile.dev.package."*"]
|
||||||
opt-level = 2
|
opt-level = 2
|
||||||
54
src/loader.rs
Normal file
54
src/loader.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
use crate::Error;
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use steamlocate::SteamDir;
|
||||||
|
use tracing::{debug, error};
|
||||||
|
use vpk::VPK;
|
||||||
|
|
||||||
|
pub struct Loader {
|
||||||
|
tf_dir: PathBuf,
|
||||||
|
vpks: Vec<VPK>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Loader {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("Loader")
|
||||||
|
.field("tf_dir", &self.tf_dir)
|
||||||
|
.finish_non_exhaustive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Loader {
|
||||||
|
pub fn new() -> Result<Self, Error> {
|
||||||
|
let tf_dir = SteamDir::locate()
|
||||||
|
.ok_or("Can't find steam directory")?
|
||||||
|
.app(&440)
|
||||||
|
.ok_or("Can't find tf2 directory")?
|
||||||
|
.path
|
||||||
|
.join("tf");
|
||||||
|
let vpks = tf_dir
|
||||||
|
.read_dir()?
|
||||||
|
.filter_map(|item| item.ok())
|
||||||
|
.filter_map(|item| Some(item.path().to_str()?.to_string()))
|
||||||
|
.filter(|path| path.ends_with(".vpk"))
|
||||||
|
.map(|path| vpk::from_path(&path))
|
||||||
|
.filter_map(|res| res.ok())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(Loader { tf_dir, vpks })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
pub fn load(&self, name: &str) -> Result<Vec<u8>, Error> {
|
||||||
|
debug!("loading file from vpk");
|
||||||
|
for vpk in self.vpks.iter() {
|
||||||
|
if let Some(entry) = vpk.tree.get(name) {
|
||||||
|
let data = entry.get()?.into_owned();
|
||||||
|
debug!("got {} bytes", data.len());
|
||||||
|
return Ok(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error!("Failed to find file in vpk");
|
||||||
|
Err(Error::Other("Can't find file in vpks"))
|
||||||
|
}
|
||||||
|
}
|
||||||
117
src/main.rs
117
src/main.rs
|
|
@ -1,38 +1,67 @@
|
||||||
mod camera;
|
mod camera;
|
||||||
|
mod loader;
|
||||||
|
|
||||||
use camera::FirstPerson;
|
use camera::FirstPerson;
|
||||||
|
use cgmath::Euler;
|
||||||
use itertools::Either;
|
use itertools::Either;
|
||||||
|
use loader::Loader;
|
||||||
use std::env::args;
|
use std::env::args;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use three_d::*;
|
use three_d::*;
|
||||||
use vbsp::{Bsp, Handle};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Registry};
|
||||||
|
use tracing_tree::HierarchicalLayer;
|
||||||
|
use vbsp::{Bsp, Handle, StaticPropLump};
|
||||||
|
use vmdl::mdl::Mdl;
|
||||||
|
use vmdl::vtx::Vtx;
|
||||||
|
use vmdl::vvd::Vvd;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
enum Error {
|
pub enum Error {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Three(#[from] Box<dyn std::error::Error>),
|
Three(#[from] Box<dyn std::error::Error>),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Bsp(#[from] vbsp::BspError),
|
Bsp(#[from] vbsp::BspError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
IO(#[from] std::io::Error),
|
IO(#[from] std::io::Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
Vpk(#[from] vpk::Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
Mdl(#[from] vmdl::ModelError),
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Other(&'static str),
|
Other(&'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&'static str> for Error {
|
||||||
|
fn from(e: &'static str) -> Self {
|
||||||
|
Error::Other(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> Result<(), Error> {
|
||||||
miette::set_panic_hook();
|
miette::set_panic_hook();
|
||||||
|
Registry::default()
|
||||||
|
.with(EnvFilter::from_default_env())
|
||||||
|
.with(
|
||||||
|
HierarchicalLayer::new(2)
|
||||||
|
.with_targets(true)
|
||||||
|
.with_bracketed_fields(true),
|
||||||
|
)
|
||||||
|
.init();
|
||||||
|
|
||||||
let mut args = args();
|
let mut args = args();
|
||||||
let bin = args.next().unwrap();
|
let _bin = args.next().unwrap();
|
||||||
let file = match args.next() {
|
let file = match args.next() {
|
||||||
Some(file) => file,
|
Some(file) => file,
|
||||||
None => {
|
None => {
|
||||||
eprintln!("usage: {} <file.bsp>", bin);
|
"koth_bagel_rc2a.bsp".into()
|
||||||
return Ok(());
|
// eprintln!("usage: {} <file.bsp>", bin);
|
||||||
|
// return Ok(());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let loader = Loader::new()?;
|
||||||
|
|
||||||
let window = Window::new(WindowSettings {
|
let window = Window::new(WindowSettings {
|
||||||
title: file.clone(),
|
title: file.clone(),
|
||||||
max_size: Some((1920, 1080)),
|
max_size: Some((1920, 1080)),
|
||||||
|
|
@ -45,8 +74,7 @@ fn main() -> Result<(), Error> {
|
||||||
|
|
||||||
let context = window.gl().unwrap();
|
let context = window.gl().unwrap();
|
||||||
|
|
||||||
let mut cpu_mesh = model_to_mesh(world_model);
|
let cpu_mesh = model_to_mesh(world_model);
|
||||||
cpu_mesh.compute_normals();
|
|
||||||
let forward_pipeline = ForwardPipeline::new(&context).unwrap();
|
let forward_pipeline = ForwardPipeline::new(&context).unwrap();
|
||||||
let mut camera = Camera::new_perspective(
|
let mut camera = Camera::new_perspective(
|
||||||
&context,
|
&context,
|
||||||
|
|
@ -72,7 +100,12 @@ fn main() -> Result<(), Error> {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let model = Model::new_with_material(&context, &cpu_mesh, material)?;
|
let mut model = Model::new_with_material(&context, &cpu_mesh, material.clone())?;
|
||||||
|
// model.set_transformation(Mat4::from_angle_x(degrees(-90.0)));
|
||||||
|
let props = bsp
|
||||||
|
.static_props()
|
||||||
|
.map(|prop| load_prop(&loader, prop, &context, material.clone()))
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
let mut lights = Lights {
|
let mut lights = Lights {
|
||||||
ambient: Some(AmbientLight {
|
ambient: Some(AmbientLight {
|
||||||
|
|
@ -176,6 +209,13 @@ fn main() -> Result<(), Error> {
|
||||||
&camera,
|
&camera,
|
||||||
&lights,
|
&lights,
|
||||||
)?;
|
)?;
|
||||||
|
for prop in &props {
|
||||||
|
prop.render_with_material(
|
||||||
|
&NormalMaterial::from_physical_material(&model.material),
|
||||||
|
&camera,
|
||||||
|
&lights,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DebugType::DEPTH => {
|
DebugType::DEPTH => {
|
||||||
let mut depth_material = DepthMaterial::default();
|
let mut depth_material = DepthMaterial::default();
|
||||||
|
|
@ -233,12 +273,71 @@ fn model_to_mesh(model: Handle<vbsp::data::Model>) -> CPUMesh {
|
||||||
.map(|verts| Either::Left(verts))
|
.map(|verts| Either::Left(verts))
|
||||||
.unwrap_or_else(|| Either::Right(face.triangulate().flat_map(|verts| verts)))
|
.unwrap_or_else(|| Either::Right(face.triangulate().flat_map(|verts| verts)))
|
||||||
})
|
})
|
||||||
.flat_map(|vertex| [-vertex.x, vertex.z, vertex.y])
|
.flat_map(<[f32; 3]>::from)
|
||||||
.map(|c| c * UNIT_SCALE)
|
.map(|c| c * UNIT_SCALE)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let mut mesh = CPUMesh {
|
||||||
|
positions,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
mesh.compute_normals();
|
||||||
|
|
||||||
|
mesh
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_prop<M: Material>(
|
||||||
|
loader: &Loader,
|
||||||
|
prop: Handle<StaticPropLump>,
|
||||||
|
context: &Context,
|
||||||
|
material: M,
|
||||||
|
) -> Result<Model<M>, Error> {
|
||||||
|
let mesh = load_prop_mesh(loader, prop.model())?;
|
||||||
|
let mut model = Model::new_with_material(context, &mesh, material)?;
|
||||||
|
let translation = Mat4::from_translation(<[f32; 3]>::from(prop.origin * UNIT_SCALE).into());
|
||||||
|
let rotation = Mat4::from(Euler {
|
||||||
|
x: degrees(prop.angles[0]),
|
||||||
|
y: degrees(prop.angles[1]),
|
||||||
|
z: degrees(prop.angles[2]),
|
||||||
|
});
|
||||||
|
let world = Mat4::from_angle_x(degrees(-90.0));
|
||||||
|
model.set_transformation(translation);
|
||||||
|
Ok(model)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(loader))]
|
||||||
|
fn load_prop_mesh(loader: &Loader, name: &str) -> Result<CPUMesh, Error> {
|
||||||
|
let mdl = Mdl::read(&loader.load(name)?)?;
|
||||||
|
let vtx = Vtx::read(&loader.load(&name.replace(".mdl", ".dx90.vtx"))?)?;
|
||||||
|
let vvd = Vvd::read(&loader.load(&name.replace(".mdl", ".vvd"))?)?;
|
||||||
|
|
||||||
|
let model = vmdl::Model::from_parts(mdl, vtx, vvd);
|
||||||
|
Ok(prop_to_mesh(&model))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prop_to_mesh(model: &vmdl::Model) -> CPUMesh {
|
||||||
|
let positions: Vec<f32> = model
|
||||||
|
.vertices()
|
||||||
|
.iter()
|
||||||
|
.flat_map(|vertex| vertex.position.iter().map(|pos| pos * UNIT_SCALE))
|
||||||
|
.collect();
|
||||||
|
let normals: Vec<f32> = model
|
||||||
|
.vertices()
|
||||||
|
.iter()
|
||||||
|
.flat_map(|vertex| vertex.normal.iter())
|
||||||
|
.collect();
|
||||||
|
let indices = Indices::U32(
|
||||||
|
model
|
||||||
|
.vertex_strip_indices()
|
||||||
|
.flat_map(|strip| strip.map(|index| index as u32))
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
|
||||||
CPUMesh {
|
CPUMesh {
|
||||||
positions,
|
positions,
|
||||||
|
normals: Some(normals),
|
||||||
|
indices: Some(indices),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue