mirror of
https://codeberg.org/icewind/vbsp.git
synced 2026-06-03 18:54:05 +02:00
added most of the q3 bsp format
This commit is contained in:
parent
3da9b27815
commit
d322159d1b
1 changed files with 303 additions and 70 deletions
379
src/lib.rs
379
src/lib.rs
|
|
@ -1,87 +1,71 @@
|
||||||
|
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
|
|
||||||
use byteorder::{LittleEndian, ReadBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
use std::fs::{File};
|
|
||||||
use std::io::*;
|
use std::io::*;
|
||||||
use std::path::{Path};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Header {
|
pub struct Header {
|
||||||
pub i : char,
|
pub i: char,
|
||||||
pub b : char,
|
pub b: char,
|
||||||
pub s : char,
|
pub s: char,
|
||||||
pub p : char
|
pub p: char,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_header(cursor: &mut Cursor<Vec<u8>>) -> Result<Header> {
|
||||||
|
let i = cursor.read_u8()? as char;
|
||||||
|
let b = cursor.read_u8()? as char;
|
||||||
|
let s = cursor.read_u8()? as char;
|
||||||
|
let p = cursor.read_u8()? as char;
|
||||||
|
Ok(Header {
|
||||||
|
i: i,
|
||||||
|
b: b,
|
||||||
|
s: s,
|
||||||
|
p: p,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_version(cursor: &mut Cursor<Vec<u8>>) -> Result<i32> {
|
||||||
|
cursor.read_i32::<LittleEndian>()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DirEntry {
|
pub struct DirEntry {
|
||||||
pub offset: i32,
|
pub offset: i32,
|
||||||
pub length : i32
|
pub length: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
fn read_directories(cursor: &mut Cursor<Vec<u8>>) -> Result<Vec<DirEntry>> {
|
||||||
pub struct Entity {
|
|
||||||
pub entities: String
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Texture {
|
|
||||||
pub name : String,
|
|
||||||
pub flags : i32,
|
|
||||||
pub contents : i32
|
|
||||||
}
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Plane {
|
|
||||||
pub normal: [f32; 3],
|
|
||||||
pub dist : f32
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct BSP {
|
|
||||||
pub header : Header,
|
|
||||||
pub dir_entries : Vec<DirEntry>,
|
|
||||||
pub entities : Entity,
|
|
||||||
pub textures : Vec<Texture>,
|
|
||||||
pub planes : Vec<Plane>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_header(cursor : &mut Cursor<Vec<u8>>) -> Result<Header> {
|
|
||||||
let i = cursor.read_u8()? as char;
|
|
||||||
let b = cursor.read_u8()? as char;
|
|
||||||
let s = cursor.read_u8()? as char;
|
|
||||||
let p = cursor.read_u8()? as char;
|
|
||||||
Ok(Header {i : i, b : b, s : s, p : p})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_version(cursor : &mut Cursor<Vec<u8>>) -> Result<i32> {
|
|
||||||
cursor.read_i32::<LittleEndian>()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_directories(cursor : &mut Cursor<Vec<u8>>) -> Result<Vec<DirEntry>> {
|
|
||||||
let mut dir_entries = Vec::new();
|
let mut dir_entries = Vec::new();
|
||||||
for _ in 0 .. 16 {
|
for _ in 0..16 {
|
||||||
let offset = cursor.read_i32::<LittleEndian>()?;
|
let offset = cursor.read_i32::<LittleEndian>()?;
|
||||||
let length = cursor.read_i32::<LittleEndian>()?;
|
let length = cursor.read_i32::<LittleEndian>()?;
|
||||||
dir_entries.push( DirEntry { offset : offset, length : length });
|
dir_entries.push(DirEntry {
|
||||||
|
offset: offset,
|
||||||
|
length: length,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Ok(dir_entries)
|
Ok(dir_entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_entities(cursor : &mut Cursor<Vec<u8>>, dir_entry : &DirEntry) -> Result<Entity> {
|
#[derive(Debug)]
|
||||||
|
pub struct Entity {
|
||||||
|
pub entities: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_entities(cursor: &mut Cursor<Vec<u8>>, dir_entry: &DirEntry) -> Result<Entity> {
|
||||||
let mut entities = Vec::with_capacity(dir_entry.length as usize);
|
let mut entities = Vec::with_capacity(dir_entry.length as usize);
|
||||||
cursor.set_position(dir_entry.offset as u64);
|
cursor.set_position(dir_entry.offset as u64);
|
||||||
for _ in 0 .. dir_entry.length {
|
for _ in 0..dir_entry.length {
|
||||||
let data = cursor.read_u8()?;
|
let data = cursor.read_u8()?;
|
||||||
entities.push(data);
|
entities.push(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
let entities = String::from_utf8(entities).unwrap();
|
let entities = String::from_utf8(entities).unwrap();
|
||||||
|
Ok(Entity { entities: entities })
|
||||||
Ok (Entity { entities : entities})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_entry<F, T>(cursor : &mut Cursor<Vec<u8>>, dir_entry : &DirEntry, mut f : F ) -> Result<Vec<T>> where F : FnMut(&mut Cursor<Vec<u8>>) -> Result<T> {
|
fn read_entry<F, T>(cursor: &mut Cursor<Vec<u8>>, dir_entry: &DirEntry, mut f: F) -> Result<Vec<T>>
|
||||||
|
where F: FnMut(&mut Cursor<Vec<u8>>) -> Result<T>
|
||||||
|
{
|
||||||
let mut entries = Vec::new();
|
let mut entries = Vec::new();
|
||||||
cursor.set_position(dir_entry.offset as u64);
|
cursor.set_position(dir_entry.offset as u64);
|
||||||
let end_pos = (dir_entry.offset + dir_entry.length) as u64;
|
let end_pos = (dir_entry.offset + dir_entry.length) as u64;
|
||||||
|
|
@ -89,12 +73,19 @@ fn read_entry<F, T>(cursor : &mut Cursor<Vec<u8>>, dir_entry : &DirEntry, mut f
|
||||||
let entry = f(cursor)?;
|
let entry = f(cursor)?;
|
||||||
entries.push(entry);
|
entries.push(entry);
|
||||||
}
|
}
|
||||||
Ok (entries)
|
Ok(entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_texture(cursor : &mut Cursor<Vec<u8>>) -> Result<Texture> {
|
#[derive(Debug)]
|
||||||
|
pub struct Texture {
|
||||||
|
pub name: String,
|
||||||
|
pub flags: i32,
|
||||||
|
pub contents: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_texture(cursor: &mut Cursor<Vec<u8>>) -> Result<Texture> {
|
||||||
let mut texture = Vec::new();
|
let mut texture = Vec::new();
|
||||||
for _ in 0 .. 64 {
|
for _ in 0..64 {
|
||||||
let data = cursor.read_u8()?;
|
let data = cursor.read_u8()?;
|
||||||
if data != 0u8 {
|
if data != 0u8 {
|
||||||
texture.push(data);
|
texture.push(data);
|
||||||
|
|
@ -103,34 +94,276 @@ fn read_texture(cursor : &mut Cursor<Vec<u8>>) -> Result<Texture> {
|
||||||
let texture_name = String::from_utf8(texture).unwrap();
|
let texture_name = String::from_utf8(texture).unwrap();
|
||||||
let flags = cursor.read_i32::<LittleEndian>()?;
|
let flags = cursor.read_i32::<LittleEndian>()?;
|
||||||
let contents = cursor.read_i32::<LittleEndian>()?;
|
let contents = cursor.read_i32::<LittleEndian>()?;
|
||||||
Ok (Texture { name : texture_name, flags : flags, contents : contents })
|
Ok(Texture {
|
||||||
|
name: texture_name,
|
||||||
|
flags: flags,
|
||||||
|
contents: contents,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_plane(cursor : &mut Cursor<Vec<u8>>) -> Result<Plane> {
|
#[derive(Debug)]
|
||||||
|
pub struct Plane {
|
||||||
|
pub normal: [f32; 3],
|
||||||
|
pub dist: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_plane(cursor: &mut Cursor<Vec<u8>>) -> Result<Plane> {
|
||||||
let x = cursor.read_f32::<LittleEndian>()?;
|
let x = cursor.read_f32::<LittleEndian>()?;
|
||||||
let y = cursor.read_f32::<LittleEndian>()?;
|
let y = cursor.read_f32::<LittleEndian>()?;
|
||||||
let z = cursor.read_f32::<LittleEndian>()?;
|
let z = cursor.read_f32::<LittleEndian>()?;
|
||||||
let dist = cursor.read_f32::<LittleEndian>()?;
|
let dist = cursor.read_f32::<LittleEndian>()?;
|
||||||
let plane = Plane { normal : [x,y,z], dist : dist };
|
let plane = Plane {
|
||||||
Ok (plane)
|
normal: [x, y, z],
|
||||||
|
dist: dist,
|
||||||
|
};
|
||||||
|
Ok(plane)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_bsp(filename : &str) -> Result<BSP> {
|
#[derive(Debug)]
|
||||||
let path = Path::new(filename);
|
pub struct Node {
|
||||||
let mut file = File::open(path).unwrap();
|
pub plane: i32,
|
||||||
let mut bytes = Vec::new();
|
pub children: [i32; 2],
|
||||||
file.read_to_end(&mut bytes).unwrap();
|
pub mins: [i32; 3],
|
||||||
|
pub maxs: [i32; 3],
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_node(cursor: &mut Cursor<Vec<u8>>) -> Result<Node> {
|
||||||
|
let plane = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let children = [cursor.read_i32::<LittleEndian>()?, cursor.read_i32::<LittleEndian>()?];
|
||||||
|
let mins = [cursor.read_i32::<LittleEndian>()?,
|
||||||
|
cursor.read_i32::<LittleEndian>()?,
|
||||||
|
cursor.read_i32::<LittleEndian>()?];
|
||||||
|
let maxs = [cursor.read_i32::<LittleEndian>()?,
|
||||||
|
cursor.read_i32::<LittleEndian>()?,
|
||||||
|
cursor.read_i32::<LittleEndian>()?];
|
||||||
|
let node = Node {
|
||||||
|
plane: plane,
|
||||||
|
children: children,
|
||||||
|
mins: mins,
|
||||||
|
maxs: maxs,
|
||||||
|
};
|
||||||
|
Ok(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Leaf {
|
||||||
|
pub cluster: i32,
|
||||||
|
pub area: i32,
|
||||||
|
pub mins: [i32; 3],
|
||||||
|
pub maxs: [i32; 3],
|
||||||
|
pub leaf_face: i32,
|
||||||
|
pub num_leaf_faces: i32,
|
||||||
|
pub leaf_brush: i32,
|
||||||
|
pub num_leaf_brushes: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_leaf(cursor: &mut Cursor<Vec<u8>>) -> Result<Leaf> {
|
||||||
|
let cluster = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let area = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let mins = [cursor.read_i32::<LittleEndian>()?,
|
||||||
|
cursor.read_i32::<LittleEndian>()?,
|
||||||
|
cursor.read_i32::<LittleEndian>()?];
|
||||||
|
let maxs = [cursor.read_i32::<LittleEndian>()?,
|
||||||
|
cursor.read_i32::<LittleEndian>()?,
|
||||||
|
cursor.read_i32::<LittleEndian>()?];
|
||||||
|
let leaf_face = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let num_leaf_faces = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let leaf_brush = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let num_leaf_brushes = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let leaf = Leaf {
|
||||||
|
cluster: cluster,
|
||||||
|
area: area,
|
||||||
|
mins: mins,
|
||||||
|
maxs: maxs,
|
||||||
|
leaf_face: leaf_face,
|
||||||
|
num_leaf_faces: num_leaf_faces,
|
||||||
|
leaf_brush: leaf_brush,
|
||||||
|
num_leaf_brushes: num_leaf_brushes,
|
||||||
|
};
|
||||||
|
Ok(leaf)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct LeafFace {
|
||||||
|
pub face: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_leaf_face(cursor: &mut Cursor<Vec<u8>>) -> Result<LeafFace> {
|
||||||
|
let face = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let leaf_face = LeafFace { face: face };
|
||||||
|
Ok(leaf_face)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct LeafBrush {
|
||||||
|
pub brush: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_leaf_brush(cursor: &mut Cursor<Vec<u8>>) -> Result<LeafBrush> {
|
||||||
|
let brush = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let leaf_brush = LeafBrush { brush: brush };
|
||||||
|
Ok(leaf_brush)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Model {
|
||||||
|
pub mins: [f32; 3],
|
||||||
|
pub maxs: [f32; 3],
|
||||||
|
pub face: i32,
|
||||||
|
pub num_faces: i32,
|
||||||
|
pub brush: i32,
|
||||||
|
pub num_brushes: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_model(cursor: &mut Cursor<Vec<u8>>) -> Result<Model> {
|
||||||
|
let mins = [cursor.read_f32::<LittleEndian>()?,
|
||||||
|
cursor.read_f32::<LittleEndian>()?,
|
||||||
|
cursor.read_f32::<LittleEndian>()?];
|
||||||
|
let maxs = [cursor.read_f32::<LittleEndian>()?,
|
||||||
|
cursor.read_f32::<LittleEndian>()?,
|
||||||
|
cursor.read_f32::<LittleEndian>()?];
|
||||||
|
let face = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let num_faces = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let brush = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let num_brushes = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let model = Model {
|
||||||
|
mins: mins,
|
||||||
|
maxs: maxs,
|
||||||
|
face: face,
|
||||||
|
num_faces: num_faces,
|
||||||
|
brush: brush,
|
||||||
|
num_brushes: num_brushes,
|
||||||
|
};
|
||||||
|
Ok(model)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Brush {
|
||||||
|
pub brush_side: i32,
|
||||||
|
pub num_brush_sides: i32,
|
||||||
|
pub texture: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_brush(cursor: &mut Cursor<Vec<u8>>) -> Result<Brush> {
|
||||||
|
let brush_side = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let num_brush_sides = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let texture = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let brush = Brush {
|
||||||
|
brush_side: brush_side,
|
||||||
|
num_brush_sides: num_brush_sides,
|
||||||
|
texture: texture,
|
||||||
|
};
|
||||||
|
Ok(brush)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BrushSide {
|
||||||
|
pub plane: i32,
|
||||||
|
pub texture: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_brush_side(cursor: &mut Cursor<Vec<u8>>) -> Result<BrushSide> {
|
||||||
|
let plane = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let texture = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let brush_side = BrushSide {
|
||||||
|
plane: plane,
|
||||||
|
texture: texture,
|
||||||
|
};
|
||||||
|
Ok(brush_side)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Vertex {
|
||||||
|
pub position: [f32; 3],
|
||||||
|
pub tex_coord1: [f32; 2],
|
||||||
|
pub tex_coord2: [f32; 2],
|
||||||
|
pub normal: [f32; 3],
|
||||||
|
pub color: [u8; 4],
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_vertex(cursor: &mut Cursor<Vec<u8>>) -> Result<Vertex> {
|
||||||
|
let position = [cursor.read_f32::<LittleEndian>()?,
|
||||||
|
cursor.read_f32::<LittleEndian>()?,
|
||||||
|
cursor.read_f32::<LittleEndian>()?];
|
||||||
|
let tex_coord1 = [cursor.read_f32::<LittleEndian>()?, cursor.read_f32::<LittleEndian>()?];
|
||||||
|
let tex_coord2 = [cursor.read_f32::<LittleEndian>()?, cursor.read_f32::<LittleEndian>()?];
|
||||||
|
let normal = [cursor.read_f32::<LittleEndian>()?,
|
||||||
|
cursor.read_f32::<LittleEndian>()?,
|
||||||
|
cursor.read_f32::<LittleEndian>()?];
|
||||||
|
let color = [cursor.read_u8()?, cursor.read_u8()?, cursor.read_u8()?, cursor.read_u8()?];
|
||||||
|
let vertex = Vertex {
|
||||||
|
position: position,
|
||||||
|
tex_coord1: tex_coord1,
|
||||||
|
tex_coord2: tex_coord2,
|
||||||
|
normal: normal,
|
||||||
|
color: color,
|
||||||
|
};
|
||||||
|
Ok(vertex)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct MeshVert {
|
||||||
|
pub offset: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_mesh_vert(cursor: &mut Cursor<Vec<u8>>) -> Result<MeshVert> {
|
||||||
|
let offset = cursor.read_i32::<LittleEndian>()?;
|
||||||
|
let mesh_vert = MeshVert { offset: offset };
|
||||||
|
Ok(mesh_vert)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BSP {
|
||||||
|
pub header: Header,
|
||||||
|
pub dir_entries: Vec<DirEntry>,
|
||||||
|
pub entities: Entity,
|
||||||
|
pub textures: Vec<Texture>,
|
||||||
|
pub planes: Vec<Plane>,
|
||||||
|
pub nodes: Vec<Node>,
|
||||||
|
pub leafs: Vec<Leaf>,
|
||||||
|
pub leaf_faces: Vec<LeafFace>,
|
||||||
|
pub leaf_brushes: Vec<LeafBrush>,
|
||||||
|
pub models: Vec<Model>,
|
||||||
|
pub brushes: Vec<Brush>,
|
||||||
|
pub brush_sides: Vec<BrushSide>,
|
||||||
|
pub vertexes: Vec<Vertex>,
|
||||||
|
pub mesh_verts: Vec<MeshVert>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_bsp(bytes: Vec<u8>) -> Result<BSP> {
|
||||||
let mut cursor = Cursor::new(bytes);
|
let mut cursor = Cursor::new(bytes);
|
||||||
let header = read_header(&mut cursor)?;
|
let header = read_header(&mut cursor)?;
|
||||||
let version = read_version(&mut cursor)?;
|
let version = read_version(&mut cursor)?;
|
||||||
assert_eq!(version, 0x2e);
|
assert_eq!(version, 0x2e);
|
||||||
let dir_entries = read_directories(&mut cursor)?;
|
let dir_entries = read_directories(&mut cursor)?;
|
||||||
let entities = read_entities(&mut cursor, &dir_entries[0])?;
|
let entities = read_entities(&mut cursor, &dir_entries[0])?;
|
||||||
let textures = read_entry(&mut cursor, &dir_entries[1], read_texture)?; //read_textures(&mut cursor, &dir_entries[1])?;
|
let textures = read_entry(&mut cursor, &dir_entries[1], read_texture)?;
|
||||||
let planes = read_entry(&mut cursor, &dir_entries[2], read_plane)?;
|
let planes = read_entry(&mut cursor, &dir_entries[2], read_plane)?;
|
||||||
Ok ({ BSP { header : header,
|
let nodes = read_entry(&mut cursor, &dir_entries[3], read_node)?;
|
||||||
dir_entries : dir_entries,
|
let leafs = read_entry(&mut cursor, &dir_entries[4], read_leaf)?;
|
||||||
entities : entities,
|
let leaf_faces = read_entry(&mut cursor, &dir_entries[5], read_leaf_face)?;
|
||||||
textures : textures,
|
let leaf_brushes = read_entry(&mut cursor, &dir_entries[6], read_leaf_brush)?;
|
||||||
planes : planes }})
|
let models = read_entry(&mut cursor, &dir_entries[7], read_model)?;
|
||||||
|
let brushes = read_entry(&mut cursor, &dir_entries[8], read_brush)?;
|
||||||
|
let brush_sides = read_entry(&mut cursor, &dir_entries[9], read_brush_side)?;
|
||||||
|
let vertexes = read_entry(&mut cursor, &dir_entries[10], read_vertex)?;
|
||||||
|
let mesh_verts = read_entry(&mut cursor, &dir_entries[11], read_mesh_vert)?;
|
||||||
|
Ok({
|
||||||
|
BSP {
|
||||||
|
header: header,
|
||||||
|
dir_entries: dir_entries,
|
||||||
|
entities: entities,
|
||||||
|
textures: textures,
|
||||||
|
planes: planes,
|
||||||
|
nodes: nodes,
|
||||||
|
leafs: leafs,
|
||||||
|
leaf_faces: leaf_faces,
|
||||||
|
leaf_brushes: leaf_brushes,
|
||||||
|
models: models,
|
||||||
|
brushes: brushes,
|
||||||
|
brush_sides: brush_sides,
|
||||||
|
vertexes: vertexes,
|
||||||
|
mesh_verts: mesh_verts,
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue