use crate::GeoId;
use uuid::Uuid;
use vek::Vec3;
#[derive(Debug, Clone)]
pub struct OrganicSurfaceDetail {
pub surface_id: Uuid,
pub anchor_uv: [f32; 2],
pub local_min: [f32; 2],
pub local_size: [f32; 2],
pub flip_x: bool,
}
#[derive(Debug, Clone)]
pub struct Poly3D {
pub id: GeoId,
pub tile_id: uuid::Uuid,
pub vertices: Vec<[f32; 4]>, pub uvs: Vec<[f32; 2]>, pub organic_uvs: Vec<[f32; 2]>,
pub indices: Vec<(usize, usize, usize)>,
pub layer: i32, pub visible: bool,
pub opacity: f32,
pub tile_id2: Option<uuid::Uuid>, pub blend_weights: Vec<f32>, pub organic_detail: Option<OrganicSurfaceDetail>,
}
impl Poly3D {
#[inline]
pub fn poly(
id: GeoId,
tile_id: Uuid,
vertices: Vec<[f32; 4]>,
uvs: Vec<[f32; 2]>,
indices: Vec<(usize, usize, usize)>,
) -> Self {
Self {
id,
tile_id,
vertices,
uvs,
organic_uvs: Vec::new(),
indices,
layer: 0,
visible: true,
opacity: 1.0,
tile_id2: None,
blend_weights: Vec::new(),
organic_detail: None,
}
}
#[inline]
pub fn cube(id: GeoId, tile_id: Uuid, center: Vec3<f32>, size: f32) -> Self {
let h = 0.5 * size;
let (cx, cy, cz) = (center[0], center[1], center[2]);
let p = |x: f32, y: f32, z: f32| -> [f32; 4] { [cx + x * h, cy + y * h, cz + z * h, 1.0] };
let mut vertices: Vec<[f32; 4]> = Vec::with_capacity(24);
vertices.extend_from_slice(&[
p(-1.0, -1.0, -1.0),
p(1.0, -1.0, -1.0),
p(1.0, 1.0, -1.0),
p(-1.0, 1.0, -1.0),
p(-1.0, -1.0, 1.0),
p(-1.0, 1.0, 1.0),
p(1.0, 1.0, 1.0),
p(1.0, -1.0, 1.0),
p(-1.0, -1.0, 1.0),
p(-1.0, -1.0, -1.0),
p(-1.0, 1.0, -1.0),
p(-1.0, 1.0, 1.0),
p(1.0, -1.0, -1.0),
p(1.0, -1.0, 1.0),
p(1.0, 1.0, 1.0),
p(1.0, 1.0, -1.0),
p(-1.0, 1.0, -1.0),
p(1.0, 1.0, -1.0),
p(1.0, 1.0, 1.0),
p(-1.0, 1.0, 1.0),
p(-1.0, -1.0, 1.0),
p(1.0, -1.0, 1.0),
p(1.0, -1.0, -1.0),
p(-1.0, -1.0, -1.0),
]);
let mut uvs: Vec<[f32; 2]> = Vec::with_capacity(24);
for _ in 0..6 {
uvs.extend_from_slice(&[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]]);
}
let mut indices: Vec<(usize, usize, usize)> = Vec::with_capacity(12);
for f in 0..6 {
let b = f * 4;
indices.extend_from_slice(&[(b + 0, b + 1, b + 2), (b + 0, b + 2, b + 3)]);
}
Self {
id,
tile_id,
vertices,
uvs,
organic_uvs: Vec::new(),
indices,
layer: 0,
visible: true,
opacity: 1.0,
tile_id2: None,
blend_weights: Vec::new(),
organic_detail: None,
}
}
#[inline]
pub fn box_(
id: GeoId,
tile_id: Uuid,
center: Vec3<f32>,
size_x: f32,
size_y: f32,
size_z: f32,
) -> Self {
let (cx, cy, cz) = (center[0], center[1], center[2]);
let hx = 0.5 * size_x;
let hy = 0.5 * size_y;
let hz = 0.5 * size_z;
let p =
|x: f32, y: f32, z: f32| -> [f32; 4] { [cx + x * hx, cy + y * hy, cz + z * hz, 1.0] };
let mut vertices: Vec<[f32; 4]> = Vec::with_capacity(24);
vertices.extend_from_slice(&[
p(-1.0, -1.0, -1.0),
p(1.0, -1.0, -1.0),
p(1.0, 1.0, -1.0),
p(-1.0, 1.0, -1.0),
p(-1.0, -1.0, 1.0),
p(-1.0, 1.0, 1.0),
p(1.0, 1.0, 1.0),
p(1.0, -1.0, 1.0),
p(-1.0, -1.0, 1.0),
p(-1.0, -1.0, -1.0),
p(-1.0, 1.0, -1.0),
p(-1.0, 1.0, 1.0),
p(1.0, -1.0, -1.0),
p(1.0, -1.0, 1.0),
p(1.0, 1.0, 1.0),
p(1.0, 1.0, -1.0),
p(-1.0, 1.0, -1.0),
p(1.0, 1.0, -1.0),
p(1.0, 1.0, 1.0),
p(-1.0, 1.0, 1.0),
p(-1.0, -1.0, 1.0),
p(1.0, -1.0, 1.0),
p(1.0, -1.0, -1.0),
p(-1.0, -1.0, -1.0),
]);
let mut uvs: Vec<[f32; 2]> = Vec::with_capacity(24);
for _ in 0..6 {
uvs.extend_from_slice(&[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]]);
}
let mut indices: Vec<(usize, usize, usize)> = Vec::with_capacity(12);
for f in 0..6 {
let b = f * 4;
indices.extend_from_slice(&[(b + 0, b + 1, b + 2), (b + 0, b + 2, b + 3)]);
}
Self {
id,
tile_id,
vertices,
uvs,
organic_uvs: Vec::new(),
indices,
layer: 0,
visible: true,
opacity: 1.0,
tile_id2: None,
blend_weights: Vec::new(),
organic_detail: None,
}
}
#[inline]
pub fn sphere(
id: GeoId,
tile_id: Uuid,
center: Vec3<f32>,
radius: f32,
stacks: usize,
slices: usize,
) -> Self {
let (cx, cy, cz) = (center[0], center[1], center[2]);
let mut vertices: Vec<[f32; 4]> = Vec::new();
let mut uvs: Vec<[f32; 2]> = Vec::new();
let mut indices: Vec<(usize, usize, usize)> = Vec::new();
for stack in 0..=stacks {
let v = stack as f32 / stacks as f32;
let phi = v * std::f32::consts::PI;
for slice in 0..=slices {
let u = slice as f32 / slices as f32;
let theta = u * 2.0 * std::f32::consts::PI;
let x = theta.sin() * phi.sin();
let y = phi.cos();
let z = theta.cos() * phi.sin();
vertices.push([cx + x * radius, cy + y * radius, cz + z * radius, 1.0]);
uvs.push([u, v]);
}
}
for stack in 0..stacks {
for slice in 0..slices {
let first = (stack * (slices + 1)) + slice;
let second = first + slices + 1;
indices.push((first, second + 1, second));
indices.push((first, first + 1, second + 1));
}
}
Self {
id,
tile_id,
vertices,
uvs,
organic_uvs: Vec::new(),
indices,
layer: 0,
visible: true,
opacity: 1.0,
tile_id2: None,
blend_weights: Vec::new(),
organic_detail: None,
}
}
#[inline]
pub fn with_layer(mut self, layer: i32) -> Self {
self.layer = layer;
self
}
#[inline]
pub fn with_visible(mut self, visible: bool) -> Self {
self.visible = visible;
self
}
#[inline]
pub fn with_opacity(mut self, opacity: f32) -> Self {
self.opacity = opacity.clamp(0.0, 1.0);
self
}
#[inline]
pub fn with_vertices(mut self, vertices: Vec<[f32; 4]>) -> Self {
self.vertices = vertices;
self
}
#[inline]
pub fn with_uvs(mut self, uvs: Vec<[f32; 2]>) -> Self {
self.uvs = uvs;
self
}
#[inline]
pub fn with_indices(mut self, indices: Vec<(usize, usize, usize)>) -> Self {
self.indices = indices;
self
}
#[inline]
pub fn with_tile_id(mut self, tile_id: Uuid) -> Self {
self.tile_id = tile_id;
self
}
#[inline]
pub fn with_blend_texture(mut self, tile_id2: Uuid) -> Self {
self.tile_id2 = Some(tile_id2);
self
}
#[inline]
pub fn with_blend_weights(mut self, blend_weights: Vec<f32>) -> Self {
self.blend_weights = blend_weights;
self
}
}