forked from StrafesNET/strafe-project
rbx_loader: refactor primitive types
This commit is contained in:
parent
ae1497741f
commit
c6c1d620ab
lib/rbx_loader/src
@ -4,7 +4,7 @@ use strafesnet_common::model::Mesh;
|
|||||||
use strafesnet_deferred_loader::{loader::Loader,texture::Texture};
|
use strafesnet_deferred_loader::{loader::Loader,texture::Texture};
|
||||||
|
|
||||||
use crate::data::RobloxMeshBytes;
|
use crate::data::RobloxMeshBytes;
|
||||||
use crate::rbx::RobloxFaceTextureDescription;
|
use crate::rbx::RobloxPartDescription;
|
||||||
|
|
||||||
fn read_entire_file(path:impl AsRef<std::path::Path>)->Result<Vec<u8>,std::io::Error>{
|
fn read_entire_file(path:impl AsRef<std::path::Path>)->Result<Vec<u8>,std::io::Error>{
|
||||||
let mut file=std::fs::File::open(path)?;
|
let mut file=std::fs::File::open(path)?;
|
||||||
@ -104,7 +104,7 @@ pub enum MeshType<'a>{
|
|||||||
mesh_data:&'a [u8],
|
mesh_data:&'a [u8],
|
||||||
physics_data:&'a [u8],
|
physics_data:&'a [u8],
|
||||||
size_float_bits:[u32;3],
|
size_float_bits:[u32;3],
|
||||||
part_texture_description:[Option<RobloxFaceTextureDescription>;6],
|
part_texture_description:RobloxPartDescription,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
#[derive(Hash,Eq,PartialEq)]
|
#[derive(Hash,Eq,PartialEq)]
|
||||||
@ -124,7 +124,7 @@ impl MeshIndex<'_>{
|
|||||||
mesh_data:&'a [u8],
|
mesh_data:&'a [u8],
|
||||||
physics_data:&'a [u8],
|
physics_data:&'a [u8],
|
||||||
size:&rbx_dom_weak::types::Vector3,
|
size:&rbx_dom_weak::types::Vector3,
|
||||||
part_texture_description:crate::rbx::RobloxPartDescription,
|
part_texture_description:RobloxPartDescription,
|
||||||
)->MeshIndex<'a>{
|
)->MeshIndex<'a>{
|
||||||
MeshIndex{
|
MeshIndex{
|
||||||
mesh_type:MeshType::Union{
|
mesh_type:MeshType::Union{
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::rbx::{RobloxPartDescription,RobloxWedgeDescription,RobloxCornerWedgeDescription};
|
||||||
use strafesnet_common::model::{Color4,TextureCoordinate,Mesh,IndexedGraphicsGroup,IndexedPhysicsGroup,IndexedVertex,PolygonGroupId,PolygonGroup,PolygonList,PositionId,TextureCoordinateId,NormalId,ColorId,VertexId,RenderConfigId};
|
use strafesnet_common::model::{Color4,TextureCoordinate,Mesh,IndexedGraphicsGroup,IndexedPhysicsGroup,IndexedVertex,PolygonGroupId,PolygonGroup,PolygonList,PositionId,TextureCoordinateId,NormalId,ColorId,VertexId,RenderConfigId};
|
||||||
use strafesnet_common::integer::{vec3,Planar64Vec3};
|
use strafesnet_common::integer::{vec3,Planar64Vec3};
|
||||||
|
|
||||||
@ -9,7 +10,22 @@ pub enum Primitives{
|
|||||||
Wedge,
|
Wedge,
|
||||||
CornerWedge,
|
CornerWedge,
|
||||||
}
|
}
|
||||||
#[derive(Hash,PartialEq,Eq)]
|
#[derive(Debug)]
|
||||||
|
pub struct PrimitivesError;
|
||||||
|
impl TryFrom<u32> for Primitives{
|
||||||
|
type Error=PrimitivesError;
|
||||||
|
fn try_from(value:u32)->Result<Self,Self::Error>{
|
||||||
|
match value{
|
||||||
|
0=>Ok(Primitives::Sphere),
|
||||||
|
1=>Ok(Primitives::Cube),
|
||||||
|
2=>Ok(Primitives::Cylinder),
|
||||||
|
3=>Ok(Primitives::Wedge),
|
||||||
|
4=>Ok(Primitives::CornerWedge),
|
||||||
|
_=>Err(PrimitivesError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Clone,Copy,Hash,PartialEq,Eq)]
|
||||||
pub enum CubeFace{
|
pub enum CubeFace{
|
||||||
Right,
|
Right,
|
||||||
Top,
|
Top,
|
||||||
@ -18,6 +34,22 @@ pub enum CubeFace{
|
|||||||
Bottom,
|
Bottom,
|
||||||
Front,
|
Front,
|
||||||
}
|
}
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct CubeFaceError;
|
||||||
|
impl TryFrom<u32> for CubeFace{
|
||||||
|
type Error=CubeFaceError;
|
||||||
|
fn try_from(value:u32)->Result<Self,Self::Error>{
|
||||||
|
match value{
|
||||||
|
0=>Ok(CubeFace::Right),
|
||||||
|
1=>Ok(CubeFace::Top),
|
||||||
|
2=>Ok(CubeFace::Back),
|
||||||
|
3=>Ok(CubeFace::Left),
|
||||||
|
4=>Ok(CubeFace::Bottom),
|
||||||
|
5=>Ok(CubeFace::Front),
|
||||||
|
_=>Err(CubeFaceError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
const CUBE_DEFAULT_TEXTURE_COORDS:[TextureCoordinate;4]=[
|
const CUBE_DEFAULT_TEXTURE_COORDS:[TextureCoordinate;4]=[
|
||||||
TextureCoordinate::new(0.0,0.0),
|
TextureCoordinate::new(0.0,0.0),
|
||||||
TextureCoordinate::new(1.0,0.0),
|
TextureCoordinate::new(1.0,0.0),
|
||||||
@ -43,50 +75,34 @@ const CUBE_DEFAULT_NORMALS:[Planar64Vec3;6]=[
|
|||||||
vec3::int( 0, 0,-1),//CubeFace::Front
|
vec3::int( 0, 0,-1),//CubeFace::Front
|
||||||
];
|
];
|
||||||
|
|
||||||
#[derive(Hash,PartialEq,Eq)]
|
pub struct CubeFaceDescription([FaceDescription;Self::FACES]);
|
||||||
pub enum WedgeFace{
|
|
||||||
Right,
|
|
||||||
TopFront,
|
|
||||||
Back,
|
|
||||||
Left,
|
|
||||||
Bottom,
|
|
||||||
}
|
|
||||||
#[derive(Hash,PartialEq,Eq)]
|
|
||||||
pub enum CornerWedgeFace{
|
|
||||||
Right,
|
|
||||||
TopBack,
|
|
||||||
TopLeft,
|
|
||||||
Bottom,
|
|
||||||
Front,
|
|
||||||
}
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct CubeFaceDescription([Option<FaceDescription>;6]);
|
|
||||||
impl CubeFaceDescription{
|
impl CubeFaceDescription{
|
||||||
pub fn insert(&mut self,index:CubeFace,value:FaceDescription){
|
pub const FACES:usize=6;
|
||||||
self.0[index as usize]=Some(value);
|
pub fn new(RobloxPartDescription(part_description):RobloxPartDescription,textureless_render_id:RenderConfigId)->Self{
|
||||||
}
|
Self(part_description.map(|face_description|match face_description{
|
||||||
pub fn pairs(self)->impl Iterator<Item=(usize,FaceDescription)>{
|
Some(roblox_texture_transform)=>roblox_texture_transform.to_face_description(),
|
||||||
self.0.into_iter().enumerate().filter_map(|(i,v)|v.map(|u|(i,u)))
|
None=>FaceDescription::new_with_render_id(textureless_render_id),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Default)]
|
pub struct WedgeFaceDescription([FaceDescription;Self::FACES]);
|
||||||
pub struct WedgeFaceDescription([Option<FaceDescription>;5]);
|
|
||||||
impl WedgeFaceDescription{
|
impl WedgeFaceDescription{
|
||||||
pub fn insert(&mut self,index:WedgeFace,value:FaceDescription){
|
pub const FACES:usize=5;
|
||||||
self.0[index as usize]=Some(value);
|
pub fn new(RobloxWedgeDescription(part_description):RobloxWedgeDescription,textureless_render_id:RenderConfigId)->Self{
|
||||||
}
|
Self(part_description.map(|face_description|match face_description{
|
||||||
pub fn pairs(self)->std::iter::FilterMap<std::iter::Enumerate<std::array::IntoIter<Option<FaceDescription>,5>>,impl FnMut((usize,Option<FaceDescription>))->Option<(usize,FaceDescription)>>{
|
Some(roblox_texture_transform)=>roblox_texture_transform.to_face_description(),
|
||||||
self.0.into_iter().enumerate().filter_map(|v|v.1.map(|u|(v.0,u)))
|
None=>FaceDescription::new_with_render_id(textureless_render_id),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Default)]
|
pub struct CornerWedgeFaceDescription([FaceDescription;Self::FACES]);
|
||||||
pub struct CornerWedgeFaceDescription([Option<FaceDescription>;5]);
|
|
||||||
impl CornerWedgeFaceDescription{
|
impl CornerWedgeFaceDescription{
|
||||||
pub fn insert(&mut self,index:CornerWedgeFace,value:FaceDescription){
|
pub const FACES:usize=5;
|
||||||
self.0[index as usize]=Some(value);
|
pub fn new(RobloxCornerWedgeDescription(part_description):RobloxCornerWedgeDescription,textureless_render_id:RenderConfigId)->Self{
|
||||||
}
|
Self(part_description.map(|face_description|match face_description{
|
||||||
pub fn pairs(self)->std::iter::FilterMap<std::iter::Enumerate<std::array::IntoIter<Option<FaceDescription>,5>>,impl FnMut((usize,Option<FaceDescription>))->Option<(usize,FaceDescription)>>{
|
Some(roblox_texture_transform)=>roblox_texture_transform.to_face_description(),
|
||||||
self.0.into_iter().enumerate().filter_map(|v|v.1.map(|u|(v.0,u)))
|
None=>FaceDescription::new_with_render_id(textureless_render_id),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +113,7 @@ pub struct FaceDescription{
|
|||||||
pub color:Color4,
|
pub color:Color4,
|
||||||
}
|
}
|
||||||
impl FaceDescription{
|
impl FaceDescription{
|
||||||
pub fn new_with_render_id(render:RenderConfigId)->Self {
|
pub fn new_with_render_id(render:RenderConfigId)->Self{
|
||||||
Self{
|
Self{
|
||||||
render,
|
render,
|
||||||
transform:glam::Affine2::IDENTITY,
|
transform:glam::Affine2::IDENTITY,
|
||||||
@ -105,7 +121,7 @@ impl FaceDescription{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn generate_partial_unit_cube(face_descriptions:CubeFaceDescription)->Mesh{
|
pub fn generate_partial_unit_cube(CubeFaceDescription(face_descriptions):CubeFaceDescription)->Mesh{
|
||||||
const CUBE_DEFAULT_POLYS:[[[u32;2];4];6]=[
|
const CUBE_DEFAULT_POLYS:[[[u32;2];4];6]=[
|
||||||
// right (1, 0, 0)
|
// right (1, 0, 0)
|
||||||
[
|
[
|
||||||
@ -160,7 +176,7 @@ pub fn generate_partial_unit_cube(face_descriptions:CubeFaceDescription)->Mesh{
|
|||||||
let mut physics_group=IndexedPhysicsGroup::default();
|
let mut physics_group=IndexedPhysicsGroup::default();
|
||||||
let mut transforms=Vec::new();
|
let mut transforms=Vec::new();
|
||||||
//note that on a cube every vertex is guaranteed to be unique, so there's no need to hash them against existing vertices.
|
//note that on a cube every vertex is guaranteed to be unique, so there's no need to hash them against existing vertices.
|
||||||
for (face_id,face_description) in face_descriptions.pairs(){
|
for (face_id,face_description) in face_descriptions.into_iter().enumerate(){
|
||||||
//assume that scanning short lists is faster than hashing.
|
//assume that scanning short lists is faster than hashing.
|
||||||
let transform_index=if let Some(transform_index)=transforms.iter().position(|&transform|transform==face_description.transform){
|
let transform_index=if let Some(transform_index)=transforms.iter().position(|&transform|transform==face_description.transform){
|
||||||
transform_index
|
transform_index
|
||||||
@ -227,7 +243,7 @@ pub fn generate_partial_unit_cube(face_descriptions:CubeFaceDescription)->Mesh{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//don't think too hard about the copy paste because this is all going into the map tool eventually...
|
//don't think too hard about the copy paste because this is all going into the map tool eventually...
|
||||||
pub fn generate_partial_unit_wedge(face_descriptions:WedgeFaceDescription)->Mesh{
|
pub fn generate_partial_unit_wedge(WedgeFaceDescription(face_descriptions):WedgeFaceDescription)->Mesh{
|
||||||
const WEDGE_DEFAULT_POLYS:[&[[u32;2]];5]=[
|
const WEDGE_DEFAULT_POLYS:[&[[u32;2]];5]=[
|
||||||
// right (1, 0, 0)
|
// right (1, 0, 0)
|
||||||
&[
|
&[
|
||||||
@ -280,7 +296,7 @@ pub fn generate_partial_unit_wedge(face_descriptions:WedgeFaceDescription)->Mesh
|
|||||||
let mut physics_group=IndexedPhysicsGroup::default();
|
let mut physics_group=IndexedPhysicsGroup::default();
|
||||||
let mut transforms=Vec::new();
|
let mut transforms=Vec::new();
|
||||||
//note that on a cube every vertex is guaranteed to be unique, so there's no need to hash them against existing vertices.
|
//note that on a cube every vertex is guaranteed to be unique, so there's no need to hash them against existing vertices.
|
||||||
for (face_id,face_description) in face_descriptions.pairs(){
|
for (face_id,face_description) in face_descriptions.into_iter().enumerate(){
|
||||||
//assume that scanning short lists is faster than hashing.
|
//assume that scanning short lists is faster than hashing.
|
||||||
let transform_index=if let Some(transform_index)=transforms.iter().position(|&transform|transform==face_description.transform){
|
let transform_index=if let Some(transform_index)=transforms.iter().position(|&transform|transform==face_description.transform){
|
||||||
transform_index
|
transform_index
|
||||||
@ -347,7 +363,7 @@ pub fn generate_partial_unit_wedge(face_descriptions:WedgeFaceDescription)->Mesh
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_partial_unit_cornerwedge(face_descriptions:CornerWedgeFaceDescription)->Mesh{
|
pub fn generate_partial_unit_cornerwedge(CornerWedgeFaceDescription(face_descriptions):CornerWedgeFaceDescription)->Mesh{
|
||||||
const CORNERWEDGE_DEFAULT_POLYS:[&[[u32;2]];5]=[
|
const CORNERWEDGE_DEFAULT_POLYS:[&[[u32;2]];5]=[
|
||||||
// right (1, 0, 0)
|
// right (1, 0, 0)
|
||||||
&[
|
&[
|
||||||
@ -398,7 +414,7 @@ pub fn generate_partial_unit_cornerwedge(face_descriptions:CornerWedgeFaceDescri
|
|||||||
let mut physics_group=IndexedPhysicsGroup::default();
|
let mut physics_group=IndexedPhysicsGroup::default();
|
||||||
let mut transforms=Vec::new();
|
let mut transforms=Vec::new();
|
||||||
//note that on a cube every vertex is guaranteed to be unique, so there's no need to hash them against existing vertices.
|
//note that on a cube every vertex is guaranteed to be unique, so there's no need to hash them against existing vertices.
|
||||||
for (face_id,face_description) in face_descriptions.pairs(){
|
for (face_id,face_description) in face_descriptions.into_iter().enumerate(){
|
||||||
//assume that scanning short lists is faster than hashing.
|
//assume that scanning short lists is faster than hashing.
|
||||||
let transform_index=if let Some(transform_index)=transforms.iter().position(|&transform|transform==face_description.transform){
|
let transform_index=if let Some(transform_index)=transforms.iter().position(|&transform|transform==face_description.transform){
|
||||||
transform_index
|
transform_index
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use crate::loader::MeshIndex;
|
use crate::loader::MeshIndex;
|
||||||
use crate::primitives;
|
use crate::primitives::{self,CubeFace,CubeFaceDescription,WedgeFaceDescription,CornerWedgeFaceDescription,FaceDescription,Primitives};
|
||||||
use strafesnet_common::aabb::Aabb;
|
use strafesnet_common::aabb::Aabb;
|
||||||
use strafesnet_common::map;
|
use strafesnet_common::map;
|
||||||
use strafesnet_common::model;
|
use strafesnet_common::model;
|
||||||
@ -347,17 +347,40 @@ impl RobloxFaceTextureDescription{
|
|||||||
transform:self.transform.to_bits(),
|
transform:self.transform.to_bits(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn to_face_description(&self)->primitives::FaceDescription{
|
pub fn to_face_description(&self)->FaceDescription{
|
||||||
primitives::FaceDescription{
|
FaceDescription{
|
||||||
render:self.render,
|
render:self.render,
|
||||||
transform:self.transform.affine(),
|
transform:self.transform.affine(),
|
||||||
color:self.color,
|
color:self.color,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub type RobloxPartDescription=[Option<RobloxFaceTextureDescription>;6];
|
macro_rules! impl_description_index{
|
||||||
type RobloxWedgeDescription=[Option<RobloxFaceTextureDescription>;5];
|
($description:ident,$index:ty)=>{
|
||||||
type RobloxCornerWedgeDescription=[Option<RobloxFaceTextureDescription>;5];
|
impl core::ops::Index<$index> for $description{
|
||||||
|
type Output=Option<RobloxFaceTextureDescription>;
|
||||||
|
fn index(&self,index:$index)->&Self::Output{
|
||||||
|
&self.0[index as usize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl core::ops::IndexMut<$index> for $description{
|
||||||
|
fn index_mut(&mut self,index:$index)->&mut Self::Output{
|
||||||
|
&mut self.0[index as usize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Default,Eq,Hash,PartialEq)]
|
||||||
|
pub struct RobloxPartDescription(pub(crate)[Option<RobloxFaceTextureDescription>;6]);
|
||||||
|
impl_description_index!(RobloxPartDescription,CubeFace);
|
||||||
|
|
||||||
|
#[derive(Clone,Default,Eq,Hash,PartialEq)]
|
||||||
|
pub struct RobloxWedgeDescription(pub(crate)[Option<RobloxFaceTextureDescription>;5]);
|
||||||
|
|
||||||
|
#[derive(Clone,Default,Eq,Hash,PartialEq)]
|
||||||
|
pub struct RobloxCornerWedgeDescription(pub(crate)[Option<RobloxFaceTextureDescription>;5]);
|
||||||
|
|
||||||
#[derive(Clone,Eq,Hash,PartialEq)]
|
#[derive(Clone,Eq,Hash,PartialEq)]
|
||||||
enum RobloxBasePartDescription{
|
enum RobloxBasePartDescription{
|
||||||
Sphere(RobloxPartDescription),
|
Sphere(RobloxPartDescription),
|
||||||
@ -374,7 +397,7 @@ fn get_texture_description<'a>(
|
|||||||
size:&rbx_dom_weak::types::Vector3,
|
size:&rbx_dom_weak::types::Vector3,
|
||||||
)->RobloxPartDescription{
|
)->RobloxPartDescription{
|
||||||
//use the biggest one and cut it down later...
|
//use the biggest one and cut it down later...
|
||||||
let mut part_texture_description:RobloxPartDescription=[None,None,None,None,None,None];
|
let mut part_texture_description=RobloxPartDescription::default();
|
||||||
temp_objects.clear();
|
temp_objects.clear();
|
||||||
recursive_collect_superclass(temp_objects,&dom,object,"Decal");
|
recursive_collect_superclass(temp_objects,&dom,object,"Decal");
|
||||||
for &mut decal_ref in temp_objects{
|
for &mut decal_ref in temp_objects{
|
||||||
@ -391,8 +414,7 @@ fn get_texture_description<'a>(
|
|||||||
decal.properties.get("Transparency"),
|
decal.properties.get("Transparency"),
|
||||||
) {
|
) {
|
||||||
let render_id=render_config_deferred_loader.acquire_render_config_id(Some(content.as_ref()));
|
let render_id=render_config_deferred_loader.acquire_render_config_id(Some(content.as_ref()));
|
||||||
let normal_id=normalid.to_u32();
|
if let Ok(cube_face)=normalid.to_u32().try_into(){
|
||||||
if normal_id<6{
|
|
||||||
let (roblox_texture_color,roblox_texture_transform)=if decal.class=="Texture"{
|
let (roblox_texture_color,roblox_texture_transform)=if decal.class=="Texture"{
|
||||||
//generate tranform
|
//generate tranform
|
||||||
if let (
|
if let (
|
||||||
@ -407,14 +429,13 @@ fn get_texture_description<'a>(
|
|||||||
decal.properties.get("StudsPerTileV"),
|
decal.properties.get("StudsPerTileV"),
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
let (size_u,size_v)=match normal_id{
|
let (size_u,size_v)=match cube_face{
|
||||||
0=>(size.z,size.y),//right
|
CubeFace::Right=>(size.z,size.y),//right
|
||||||
1=>(size.x,size.z),//top
|
CubeFace::Top=>(size.x,size.z),//top
|
||||||
2=>(size.x,size.y),//back
|
CubeFace::Back=>(size.x,size.y),//back
|
||||||
3=>(size.z,size.y),//left
|
CubeFace::Left=>(size.z,size.y),//left
|
||||||
4=>(size.x,size.z),//bottom
|
CubeFace::Bottom=>(size.x,size.z),//bottom
|
||||||
5=>(size.x,size.y),//front
|
CubeFace::Front=>(size.x,size.y),//front
|
||||||
_=>unreachable!(),
|
|
||||||
};
|
};
|
||||||
(
|
(
|
||||||
glam::vec4(decal_color3.r,decal_color3.g,decal_color3.b,1.0-*decal_transparency),
|
glam::vec4(decal_color3.r,decal_color3.g,decal_color3.b,1.0-*decal_transparency),
|
||||||
@ -433,13 +454,13 @@ fn get_texture_description<'a>(
|
|||||||
}else{
|
}else{
|
||||||
(glam::Vec4::ONE,RobloxTextureTransform::identity())
|
(glam::Vec4::ONE,RobloxTextureTransform::identity())
|
||||||
};
|
};
|
||||||
part_texture_description[normal_id as usize]=Some(RobloxFaceTextureDescription{
|
part_texture_description[cube_face]=Some(RobloxFaceTextureDescription{
|
||||||
render:render_id,
|
render:render_id,
|
||||||
color:roblox_texture_color,
|
color:roblox_texture_color,
|
||||||
transform:roblox_texture_transform,
|
transform:roblox_texture_transform,
|
||||||
});
|
});
|
||||||
}else{
|
}else{
|
||||||
println!("NormalId={} is invalid",normal_id);
|
println!("NormalId is invalid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -447,7 +468,7 @@ fn get_texture_description<'a>(
|
|||||||
part_texture_description
|
part_texture_description
|
||||||
}
|
}
|
||||||
enum Shape{
|
enum Shape{
|
||||||
Primitive(primitives::Primitives),
|
Primitive(Primitives),
|
||||||
MeshPart,
|
MeshPart,
|
||||||
PhysicsData,
|
PhysicsData,
|
||||||
}
|
}
|
||||||
@ -533,25 +554,18 @@ pub fn convert<'a>(
|
|||||||
//TODO: also detect "CylinderMesh" etc here
|
//TODO: also detect "CylinderMesh" etc here
|
||||||
let shape=match object.class.as_str(){
|
let shape=match object.class.as_str(){
|
||||||
"Part"=>if let Some(rbx_dom_weak::types::Variant::Enum(shape))=object.properties.get("Shape"){
|
"Part"=>if let Some(rbx_dom_weak::types::Variant::Enum(shape))=object.properties.get("Shape"){
|
||||||
Shape::Primitive(match shape.to_u32(){
|
Shape::Primitive(shape.to_u32().try_into().expect("Funky roblox PartType"))
|
||||||
0=>primitives::Primitives::Sphere,
|
|
||||||
1=>primitives::Primitives::Cube,
|
|
||||||
2=>primitives::Primitives::Cylinder,
|
|
||||||
3=>primitives::Primitives::Wedge,
|
|
||||||
4=>primitives::Primitives::CornerWedge,
|
|
||||||
other=>panic!("Funky roblox PartType={};",other),
|
|
||||||
})
|
|
||||||
}else{
|
}else{
|
||||||
panic!("Part has no Shape!");
|
panic!("Part has no Shape!");
|
||||||
},
|
},
|
||||||
"TrussPart"=>Shape::Primitive(primitives::Primitives::Cube),
|
"TrussPart"=>Shape::Primitive(Primitives::Cube),
|
||||||
"WedgePart"=>Shape::Primitive(primitives::Primitives::Wedge),
|
"WedgePart"=>Shape::Primitive(Primitives::Wedge),
|
||||||
"CornerWedgePart"=>Shape::Primitive(primitives::Primitives::CornerWedge),
|
"CornerWedgePart"=>Shape::Primitive(Primitives::CornerWedge),
|
||||||
"MeshPart"=>Shape::MeshPart,
|
"MeshPart"=>Shape::MeshPart,
|
||||||
"UnionOperation"=>Shape::PhysicsData,
|
"UnionOperation"=>Shape::PhysicsData,
|
||||||
_=>{
|
_=>{
|
||||||
println!("Unsupported BasePart ClassName={}; defaulting to cube",object.class);
|
println!("Unsupported BasePart ClassName={}; defaulting to cube",object.class);
|
||||||
Shape::Primitive(primitives::Primitives::Cube)
|
Shape::Primitive(Primitives::Cube)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -560,34 +574,34 @@ pub fn convert<'a>(
|
|||||||
//TODO: TAB TAB
|
//TODO: TAB TAB
|
||||||
let part_texture_description=get_texture_description(&mut temp_objects,render_config_deferred_loader,dom,object,size);
|
let part_texture_description=get_texture_description(&mut temp_objects,render_config_deferred_loader,dom,object,size);
|
||||||
//obscure rust syntax "slice pattern"
|
//obscure rust syntax "slice pattern"
|
||||||
let [
|
let RobloxPartDescription([
|
||||||
f0,//Cube::Right
|
f0,//Cube::Right
|
||||||
f1,//Cube::Top
|
f1,//Cube::Top
|
||||||
f2,//Cube::Back
|
f2,//Cube::Back
|
||||||
f3,//Cube::Left
|
f3,//Cube::Left
|
||||||
f4,//Cube::Bottom
|
f4,//Cube::Bottom
|
||||||
f5,//Cube::Front
|
f5,//Cube::Front
|
||||||
]=part_texture_description;
|
])=part_texture_description;
|
||||||
let basepart_description=match primitive_shape{
|
let basepart_description=match primitive_shape{
|
||||||
primitives::Primitives::Sphere=>RobloxBasePartDescription::Sphere([f0,f1,f2,f3,f4,f5]),
|
Primitives::Sphere=>RobloxBasePartDescription::Sphere(RobloxPartDescription([f0,f1,f2,f3,f4,f5])),
|
||||||
primitives::Primitives::Cube=>RobloxBasePartDescription::Part([f0,f1,f2,f3,f4,f5]),
|
Primitives::Cube=>RobloxBasePartDescription::Part(RobloxPartDescription([f0,f1,f2,f3,f4,f5])),
|
||||||
primitives::Primitives::Cylinder=>RobloxBasePartDescription::Cylinder([f0,f1,f2,f3,f4,f5]),
|
Primitives::Cylinder=>RobloxBasePartDescription::Cylinder(RobloxPartDescription([f0,f1,f2,f3,f4,f5])),
|
||||||
//use front face texture first and use top face texture as a fallback
|
//use front face texture first and use top face texture as a fallback
|
||||||
primitives::Primitives::Wedge=>RobloxBasePartDescription::Wedge([
|
Primitives::Wedge=>RobloxBasePartDescription::Wedge(RobloxWedgeDescription([
|
||||||
f0,//Cube::Right->Wedge::Right
|
f0,//Cube::Right->Wedge::Right
|
||||||
f5.or(f1),//Cube::Front|Cube::Top->Wedge::TopFront
|
f5.or(f1),//Cube::Front|Cube::Top->Wedge::TopFront
|
||||||
f2,//Cube::Back->Wedge::Back
|
f2,//Cube::Back->Wedge::Back
|
||||||
f3,//Cube::Left->Wedge::Left
|
f3,//Cube::Left->Wedge::Left
|
||||||
f4,//Cube::Bottom->Wedge::Bottom
|
f4,//Cube::Bottom->Wedge::Bottom
|
||||||
]),
|
])),
|
||||||
//TODO: fix Left+Back texture coordinates to match roblox when not overwridden by Top
|
//TODO: fix Left+Back texture coordinates to match roblox when not overwridden by Top
|
||||||
primitives::Primitives::CornerWedge=>RobloxBasePartDescription::CornerWedge([
|
Primitives::CornerWedge=>RobloxBasePartDescription::CornerWedge(RobloxCornerWedgeDescription([
|
||||||
f0,//Cube::Right->CornerWedge::Right
|
f0,//Cube::Right->CornerWedge::Right
|
||||||
f2.or(f1.clone()),//Cube::Back|Cube::Top->CornerWedge::TopBack
|
f2.or(f1.clone()),//Cube::Back|Cube::Top->CornerWedge::TopBack
|
||||||
f3.or(f1),//Cube::Left|Cube::Top->CornerWedge::TopLeft
|
f3.or(f1),//Cube::Left|Cube::Top->CornerWedge::TopLeft
|
||||||
f4,//Cube::Bottom->CornerWedge::Bottom
|
f4,//Cube::Bottom->CornerWedge::Bottom
|
||||||
f5,//Cube::Front->CornerWedge::Front
|
f5,//Cube::Front->CornerWedge::Front
|
||||||
]),
|
])),
|
||||||
};
|
};
|
||||||
//make new model if unit cube has not been created before
|
//make new model if unit cube has not been created before
|
||||||
let mesh_id=if let Some(&mesh_id)=mesh_id_from_description.get(&basepart_description){
|
let mesh_id=if let Some(&mesh_id)=mesh_id_from_description.get(&basepart_description){
|
||||||
@ -599,64 +613,9 @@ pub fn convert<'a>(
|
|||||||
let mesh=match basepart_description{
|
let mesh=match basepart_description{
|
||||||
RobloxBasePartDescription::Sphere(part_texture_description)
|
RobloxBasePartDescription::Sphere(part_texture_description)
|
||||||
|RobloxBasePartDescription::Cylinder(part_texture_description)
|
|RobloxBasePartDescription::Cylinder(part_texture_description)
|
||||||
|RobloxBasePartDescription::Part(part_texture_description)=>{
|
|RobloxBasePartDescription::Part(part_texture_description)=>primitives::generate_partial_unit_cube(CubeFaceDescription::new(part_texture_description,textureless_render_group)),
|
||||||
let mut cube_face_description=primitives::CubeFaceDescription::default();
|
RobloxBasePartDescription::Wedge(wedge_texture_description)=>primitives::generate_partial_unit_wedge(WedgeFaceDescription::new(wedge_texture_description,textureless_render_group)),
|
||||||
for (face_id,roblox_face_description) in part_texture_description.iter().enumerate(){
|
RobloxBasePartDescription::CornerWedge(cornerwedge_texture_description)=>primitives::generate_partial_unit_cornerwedge(CornerWedgeFaceDescription::new(cornerwedge_texture_description,textureless_render_group)),
|
||||||
cube_face_description.insert(
|
|
||||||
match face_id{
|
|
||||||
0=>primitives::CubeFace::Right,
|
|
||||||
1=>primitives::CubeFace::Top,
|
|
||||||
2=>primitives::CubeFace::Back,
|
|
||||||
3=>primitives::CubeFace::Left,
|
|
||||||
4=>primitives::CubeFace::Bottom,
|
|
||||||
5=>primitives::CubeFace::Front,
|
|
||||||
_=>unreachable!(),
|
|
||||||
},
|
|
||||||
match roblox_face_description{
|
|
||||||
Some(roblox_texture_transform)=>roblox_texture_transform.to_face_description(),
|
|
||||||
None=>primitives::FaceDescription::new_with_render_id(textureless_render_group),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
primitives::generate_partial_unit_cube(cube_face_description)
|
|
||||||
},
|
|
||||||
RobloxBasePartDescription::Wedge(wedge_texture_description)=>{
|
|
||||||
let mut wedge_face_description=primitives::WedgeFaceDescription::default();
|
|
||||||
for (face_id,roblox_face_description) in wedge_texture_description.iter().enumerate(){
|
|
||||||
wedge_face_description.insert(
|
|
||||||
match face_id{
|
|
||||||
0=>primitives::WedgeFace::Right,
|
|
||||||
1=>primitives::WedgeFace::TopFront,
|
|
||||||
2=>primitives::WedgeFace::Back,
|
|
||||||
3=>primitives::WedgeFace::Left,
|
|
||||||
4=>primitives::WedgeFace::Bottom,
|
|
||||||
_=>unreachable!(),
|
|
||||||
},
|
|
||||||
match roblox_face_description{
|
|
||||||
Some(roblox_texture_transform)=>roblox_texture_transform.to_face_description(),
|
|
||||||
None=>primitives::FaceDescription::new_with_render_id(textureless_render_group),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
primitives::generate_partial_unit_wedge(wedge_face_description)
|
|
||||||
},
|
|
||||||
RobloxBasePartDescription::CornerWedge(cornerwedge_texture_description)=>{
|
|
||||||
let mut cornerwedge_face_description=primitives::CornerWedgeFaceDescription::default();
|
|
||||||
for (face_id,roblox_face_description) in cornerwedge_texture_description.iter().enumerate(){
|
|
||||||
cornerwedge_face_description.insert(
|
|
||||||
match face_id{
|
|
||||||
0=>primitives::CornerWedgeFace::Right,
|
|
||||||
1=>primitives::CornerWedgeFace::TopBack,
|
|
||||||
2=>primitives::CornerWedgeFace::TopLeft,
|
|
||||||
3=>primitives::CornerWedgeFace::Bottom,
|
|
||||||
4=>primitives::CornerWedgeFace::Front,
|
|
||||||
_=>unreachable!(),
|
|
||||||
},
|
|
||||||
match roblox_face_description{
|
|
||||||
Some(roblox_texture_transform)=>roblox_texture_transform.to_face_description(),
|
|
||||||
None=>primitives::FaceDescription::new_with_render_id(textureless_render_group),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
primitives::generate_partial_unit_cornerwedge(cornerwedge_face_description)
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
primitive_meshes.push(mesh);
|
primitive_meshes.push(mesh);
|
||||||
mesh_id
|
mesh_id
|
||||||
@ -768,7 +727,7 @@ fn acquire_union_id_from_render_config_id<'a>(
|
|||||||
let union_id=model::MeshId::new(primitive_meshes.len() as u32);
|
let union_id=model::MeshId::new(primitive_meshes.len() as u32);
|
||||||
let mut union_clone=union_with_aabb.mesh.clone();
|
let mut union_clone=union_with_aabb.mesh.clone();
|
||||||
//set the render groups
|
//set the render groups
|
||||||
for (graphics_group,maybe_face_texture_description) in union_clone.graphics_groups.iter_mut().zip(part_texture_description){
|
for (graphics_group,maybe_face_texture_description) in union_clone.graphics_groups.iter_mut().zip(part_texture_description.0){
|
||||||
if let Some(face_texture_description)=maybe_face_texture_description{
|
if let Some(face_texture_description)=maybe_face_texture_description{
|
||||||
graphics_group.render=face_texture_description.render;
|
graphics_group.render=face_texture_description.render;
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ pub fn convert(
|
|||||||
roblox_physics_data:&[u8],
|
roblox_physics_data:&[u8],
|
||||||
roblox_mesh_data:&[u8],
|
roblox_mesh_data:&[u8],
|
||||||
size:glam::Vec3,
|
size:glam::Vec3,
|
||||||
part_texture_description:crate::rbx::RobloxPartDescription,
|
crate::rbx::RobloxPartDescription(part_texture_description):crate::rbx::RobloxPartDescription,
|
||||||
)->Result<model::Mesh,Error>{
|
)->Result<model::Mesh,Error>{
|
||||||
const NORMAL_FACES:usize=6;
|
const NORMAL_FACES:usize=6;
|
||||||
let mut polygon_groups_normal_id=vec![Vec::new();NORMAL_FACES];
|
let mut polygon_groups_normal_id=vec![Vec::new();NORMAL_FACES];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user