mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
@@ -65,6 +65,7 @@ clap = { version = "4", features = ["derive"] }
|
||||
winit = { version = "0.29.2", features = ["serde"] }
|
||||
half = "2.2.1"
|
||||
fast_image_resize = "2.7.0"
|
||||
base64 = "0.21.0"
|
||||
|
||||
[features]
|
||||
enable_profiler = ["fyrox-core/enable_profiler"]
|
||||
|
||||
@@ -7,6 +7,7 @@ pub enum FbxAttribute {
|
||||
Long(i64),
|
||||
Bool(bool),
|
||||
String(String), // ASCII Fbx always have every attribute in string form
|
||||
RawData(Vec<u8>),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for FbxAttribute {
|
||||
@@ -18,6 +19,7 @@ impl std::fmt::Display for FbxAttribute {
|
||||
FbxAttribute::Long(long) => write!(f, "{}", long),
|
||||
FbxAttribute::Bool(boolean) => write!(f, "{}", boolean),
|
||||
FbxAttribute::String(string) => write!(f, "{}", string),
|
||||
FbxAttribute::RawData(raw) => write!(f, "{:?}", raw),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,6 +36,7 @@ impl FbxAttribute {
|
||||
Ok(i) => Ok(i),
|
||||
Err(_) => Err(format!("Unable to convert string {} to i32", val)),
|
||||
},
|
||||
FbxAttribute::RawData(_) => Err("Unable to convert raw data to i32".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +51,7 @@ impl FbxAttribute {
|
||||
Ok(i) => Ok(i),
|
||||
Err(_) => Err(format!("Unable to convert string {} to i64", val)),
|
||||
},
|
||||
FbxAttribute::RawData(_) => Err("Unable to convert raw data to i64".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +66,7 @@ impl FbxAttribute {
|
||||
Ok(i) => Ok(i),
|
||||
Err(_) => Err(format!("Unable to convert string {} to f64", val)),
|
||||
},
|
||||
FbxAttribute::RawData(_) => Err("Unable to convert raw data to f64".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +81,7 @@ impl FbxAttribute {
|
||||
Ok(i) => Ok(i),
|
||||
Err(_) => Err(format!("Unable to convert string {} to f32", val)),
|
||||
},
|
||||
FbxAttribute::RawData(_) => Err("Unable to convert raw data to f32".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +93,7 @@ impl FbxAttribute {
|
||||
FbxAttribute::Long(val) => val.to_string(),
|
||||
FbxAttribute::Bool(val) => val.to_string(),
|
||||
FbxAttribute::String(val) => val.clone(),
|
||||
FbxAttribute::RawData(val) => String::from_utf8_lossy(val).to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,9 +143,12 @@ where
|
||||
.attributes
|
||||
.push(read_string(file)?),
|
||||
b'R' => {
|
||||
// Ignore Raw data
|
||||
let length = i64::from(file.read_u32::<LittleEndian>()?);
|
||||
file.seek(SeekFrom::Current(length))?;
|
||||
let mut data = vec![0; length as usize];
|
||||
file.read_exact(&mut data)?;
|
||||
pool.borrow_mut(node_handle)
|
||||
.attributes
|
||||
.push(FbxAttribute::RawData(data));
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
+45
-30
@@ -10,6 +10,7 @@ mod document;
|
||||
pub mod error;
|
||||
mod scene;
|
||||
|
||||
use crate::resource::texture::{TextureImportOptions, TextureResource, TextureResourceExtension};
|
||||
use crate::{
|
||||
asset::manager::ResourceManager,
|
||||
core::{
|
||||
@@ -59,6 +60,7 @@ use crate::{
|
||||
};
|
||||
use fxhash::{FxHashMap, FxHashSet};
|
||||
use fyrox_resource::io::ResourceIo;
|
||||
use fyrox_resource::untyped::ResourceKind;
|
||||
use std::{cmp::Ordering, path::Path};
|
||||
|
||||
/// Input angles in degrees
|
||||
@@ -308,47 +310,60 @@ async fn create_surfaces(
|
||||
let path = texture.get_file_path();
|
||||
|
||||
if let Some(filename) = path.file_name() {
|
||||
let texture_path = match model_import_options.material_search_options {
|
||||
MaterialSearchOptions::MaterialsDirectory(ref directory) => {
|
||||
Some(directory.join(filename))
|
||||
}
|
||||
MaterialSearchOptions::RecursiveUp => {
|
||||
let mut texture_path = None;
|
||||
let mut path = model_path.to_owned();
|
||||
while let Some(parent) = path.parent() {
|
||||
let candidate = parent.join(filename);
|
||||
if io.exists(&candidate).await {
|
||||
texture_path = Some(candidate);
|
||||
break;
|
||||
}
|
||||
path.pop();
|
||||
let texture_path = if texture.content.is_empty() {
|
||||
match model_import_options.material_search_options {
|
||||
MaterialSearchOptions::MaterialsDirectory(ref directory) => {
|
||||
Some(directory.join(filename))
|
||||
}
|
||||
texture_path
|
||||
}
|
||||
MaterialSearchOptions::WorkingDirectory => {
|
||||
let mut texture_path = None;
|
||||
MaterialSearchOptions::RecursiveUp => {
|
||||
let mut texture_path = None;
|
||||
let mut path = model_path.to_owned();
|
||||
while let Some(parent) = path.parent() {
|
||||
let candidate = parent.join(filename);
|
||||
if io.exists(&candidate).await {
|
||||
texture_path = Some(candidate);
|
||||
break;
|
||||
}
|
||||
path.pop();
|
||||
}
|
||||
texture_path
|
||||
}
|
||||
MaterialSearchOptions::WorkingDirectory => {
|
||||
let mut texture_path = None;
|
||||
|
||||
let path = Path::new(".");
|
||||
let path = Path::new(".");
|
||||
|
||||
if let Ok(iter) = io.walk_directory(path).await {
|
||||
for dir in iter {
|
||||
if io.is_dir(&dir).await {
|
||||
let candidate = dir.join(filename);
|
||||
if candidate.exists() {
|
||||
texture_path = Some(candidate);
|
||||
break;
|
||||
if let Ok(iter) = io.walk_directory(path).await {
|
||||
for dir in iter {
|
||||
if io.is_dir(&dir).await {
|
||||
let candidate = dir.join(filename);
|
||||
if candidate.exists() {
|
||||
texture_path = Some(candidate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
texture_path
|
||||
texture_path
|
||||
}
|
||||
MaterialSearchOptions::UsePathDirectly => Some(path.clone()),
|
||||
}
|
||||
MaterialSearchOptions::UsePathDirectly => Some(path.clone()),
|
||||
} else {
|
||||
Some(path.clone())
|
||||
};
|
||||
|
||||
if let Some(texture_path) = texture_path {
|
||||
let texture = resource_manager.request::<Texture>(texture_path.as_path());
|
||||
let texture = if texture.content.is_empty() {
|
||||
resource_manager.request::<Texture>(texture_path.as_path())
|
||||
} else {
|
||||
TextureResource::load_from_memory(
|
||||
ResourceKind::External(texture_path.clone()),
|
||||
&texture.content,
|
||||
TextureImportOptions::default(),
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
// Make up your mind, Autodesk and Blender.
|
||||
// Handle all possible combinations of links to auto-import materials.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::resource::fbx::scene::video::FbxVideo;
|
||||
use crate::{
|
||||
core::{
|
||||
algebra::{Matrix4, Vector3},
|
||||
@@ -24,6 +25,7 @@ pub mod geometry;
|
||||
pub mod light;
|
||||
pub mod model;
|
||||
pub mod texture;
|
||||
pub mod video;
|
||||
|
||||
pub struct FbxScene {
|
||||
components: Pool<FbxComponent>,
|
||||
@@ -83,6 +85,12 @@ impl FbxScene {
|
||||
nodes,
|
||||
)?));
|
||||
}
|
||||
"Video" => {
|
||||
if object.get_attrib(2)?.as_string() == "Clip" {
|
||||
component_handle = components
|
||||
.spawn(FbxComponent::Video(FbxVideo::read(*object_handle, nodes)?));
|
||||
}
|
||||
}
|
||||
"NodeAttribute" => {
|
||||
if object.attrib_count() > 2 && object.get_attrib(2)?.as_string() == "Light" {
|
||||
component_handle = components
|
||||
@@ -207,6 +215,11 @@ fn link_child_with_parent_component(
|
||||
channel.geometry = child_handle;
|
||||
}
|
||||
}
|
||||
FbxComponent::Texture(texture) => {
|
||||
if let FbxComponent::Video(video) = child {
|
||||
texture.content = video.content.clone();
|
||||
}
|
||||
}
|
||||
// Ignore rest
|
||||
_ => (),
|
||||
}
|
||||
@@ -217,6 +230,7 @@ pub enum FbxComponent {
|
||||
Cluster(FbxCluster),
|
||||
BlendShapeChannel(FbxBlendShapeChannel),
|
||||
Texture(FbxTexture),
|
||||
Video(FbxVideo),
|
||||
Light(FbxLight),
|
||||
Model(Box<FbxModel>),
|
||||
Material(FbxMaterial),
|
||||
|
||||
@@ -6,6 +6,7 @@ use std::path::PathBuf;
|
||||
|
||||
pub struct FbxTexture {
|
||||
filename: PathBuf,
|
||||
pub content: Vec<u8>,
|
||||
}
|
||||
|
||||
impl FbxTexture {
|
||||
@@ -15,6 +16,7 @@ impl FbxTexture {
|
||||
) -> Result<Self, String> {
|
||||
let mut texture = FbxTexture {
|
||||
filename: PathBuf::new(),
|
||||
content: Default::default(),
|
||||
};
|
||||
if let Ok(relative_file_name_node) =
|
||||
nodes.get_by_name(texture_node_handle, "RelativeFilename")
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
use crate::{
|
||||
core::pool::Handle,
|
||||
resource::fbx::document::{attribute::FbxAttribute, FbxNode, FbxNodeContainer},
|
||||
};
|
||||
use base64::Engine;
|
||||
|
||||
pub struct FbxVideo {
|
||||
pub content: Vec<u8>,
|
||||
}
|
||||
|
||||
impl FbxVideo {
|
||||
pub(in crate::resource::fbx) fn read(
|
||||
video_node_handle: Handle<FbxNode>,
|
||||
nodes: &FbxNodeContainer,
|
||||
) -> Result<Self, String> {
|
||||
if let Ok(content_node) = nodes.get_by_name(video_node_handle, "Content") {
|
||||
let attrib = content_node.get_attrib(0)?;
|
||||
|
||||
let content = match attrib {
|
||||
FbxAttribute::String(base64) => base64::engine::general_purpose::STANDARD
|
||||
.decode(base64)
|
||||
.expect("FBX cannot contain invalid base64-encoded data."),
|
||||
FbxAttribute::RawData(raw) => raw.clone(),
|
||||
_ => Default::default(),
|
||||
};
|
||||
|
||||
Ok(Self { content })
|
||||
} else {
|
||||
Ok(Self {
|
||||
content: Default::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user