Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  geometry.rs   Sprache: unbekannt

 
use std::{
    mem::{size_of, transmute},
    sync::Arc,
};

use glam::{
    f32::{Mat4, Vec3, Vec4},
    Vec4Swizzles,
};

use metal::*;

pub const GEOMETRY_MASK_TRIANGLE: u32 = 1;
pub const GEOMETRY_MASK_SPHERE: u32 = 2;
pub const GEOMETRY_MASK_LIGHT: u32 = 4;

pub const FACE_MASK_NONE: u16 = 0;
pub const FACE_MASK_NEGATIVE_X: u16 = 1 << 0;
pub const FACE_MASK_POSITIVE_X: u16 = 1 << 1;
pub const FACE_MASK_NEGATIVE_Y: u16 = 1 << 2;
pub const FACE_MASK_POSITIVE_Y: u16 = 1 << 3;
pub const FACE_MASK_NEGATIVE_Z: u16 = 1 << 4;
pub const FACE_MASK_POSITIVE_Z: u16 = 1 << 5;
pub const FACE_MASK_ALL: u16 = (1 << 6) - 1;

pub trait Geometry {
    fn upload_to_buffers(&mut self) {
        todo!()
    }
    fn clear(&mut self) {
        todo!()
    }
    fn get_geometry_descriptor(&self) -> AccelerationStructureGeometryDescriptor {
        todo!()
    }
    fn get_resources(&self) -> Vec<Resource> {
        todo!()
    }
    fn get_intersection_function_name(&self) -> Option<&str> {
        None
    }
}

pub fn compute_triangle_normal(v0: &Vec3, v1: &Vec3, v2: &Vec3) -> Vec3 {
    let e1 = Vec3::normalize(*v1 - *v0);
    let e2 = Vec3::normalize(*v2 - *v0);
    return Vec3::cross(e1, e2);
}

#[derive(Default)]
#[repr(C)]
pub struct Triangle {
    pub normals: [Vec4; 3],
    pub colours: [Vec4; 3],
}

pub fn get_managed_buffer_storage_mode() -> MTLResourceOptions {
    return MTLResourceOptions::StorageModeManaged;
}

pub struct TriangleGeometry {
    pub device: Device,
    pub name: String,
    pub index_buffer: Option<Buffer>,
    pub vertex_position_buffer: Option<Buffer>,
    pub vertex_normal_buffer: Option<Buffer>,
    pub vertex_colour_buffer: Option<Buffer>,
    pub per_primitive_data_buffer: Option<Buffer>,
    pub indices: Vec<u16>,
    pub vertices: Vec<Vec4>,
    pub normals: Vec<Vec4>,
    pub colours: Vec<Vec4>,
    pub triangles: Vec<Triangle>,
}

impl TriangleGeometry {
    pub fn new(device: Device, name: String) -> Self {
        Self {
            device,
            name,
            index_buffer: None,
            vertex_position_buffer: None,
            vertex_normal_buffer: None,
            vertex_colour_buffer: None,
            per_primitive_data_buffer: None,
            indices: Vec::new(),
            vertices: Vec::new(),
            normals: Vec::new(),
            colours: Vec::new(),
            triangles: Vec::new(),
        }
    }

    pub fn add_cube_face_with_cube_vertices(
        &mut self,
        cube_vertices: &[Vec3],
        colour: Vec3,
        i0: u16,
        i1: u16,
        i2: u16,
        i3: u16,
        inward_normals: bool,
    ) {
        let v0 = cube_vertices[i0 as usize];
        let v1 = cube_vertices[i1 as usize];
        let v2 = cube_vertices[i2 as usize];
        let v3 = cube_vertices[i3 as usize];

        let n0 = compute_triangle_normal(&v0, &v1, &v2) * if inward_normals { -1f32 } else { 1f32 };
        let n1 = compute_triangle_normal(&v0, &v2, &v3) * if inward_normals { -1f32 } else { 1f32 };

        let first_index = self.indices.len();
        let base_index = self.vertices.len() as u16;

        self.indices.push(base_index + 0);
        self.indices.push(base_index + 1);
        self.indices.push(base_index + 2);
        self.indices.push(base_index + 0);
        self.indices.push(base_index + 2);
        self.indices.push(base_index + 3);

        self.vertices.push(From::from((v0, 0.0)));
        self.vertices.push(From::from((v1, 0.0)));
        self.vertices.push(From::from((v2, 0.0)));
        self.vertices.push(From::from((v3, 0.0)));

        self.normals
            .push(From::from((Vec3::normalize(n0 + n1), 0.0)));
        self.normals.push(From::from((n0, 0.0)));
        self.normals
            .push(From::from((Vec3::normalize(n0 + n1), 0.0)));
        self.normals.push(From::from((n1, 0.0)));

        for _ in 0..4 {
            self.colours.push(From::from((colour, 0.0)));
        }

        for triangle_index in 0..2 {
            let mut triangle = Triangle::default();
            for i in 0..3 {
                let index = self.indices[first_index + triangle_index * 3 + i];
                triangle.normals[i] = self.normals[index as usize];
                triangle.colours[i] = self.colours[index as usize];
            }
            self.triangles.push(triangle);
        }
    }

    pub fn add_cube_with_faces(
        &mut self,
        face_mask: u16,
        colour: Vec3,
        transform: Mat4,
        inward_normals: bool,
    ) {
        let mut cube_vertices = [
            Vec3::new(-0.5, -0.5, -0.5),
            Vec3::new(0.5, -0.5, -0.5),
            Vec3::new(-0.5, 0.5, -0.5),
            Vec3::new(0.5, 0.5, -0.5),
            Vec3::new(-0.5, -0.5, 0.5),
            Vec3::new(0.5, -0.5, 0.5),
            Vec3::new(-0.5, 0.5, 0.5),
            Vec3::new(0.5, 0.5, 0.5),
        ];

        for i in 0..8 {
            let transformed_vertex = Vec4::from((cube_vertices[i], 1.0));
            let transformed_vertex = transform * transformed_vertex;
            cube_vertices[i] = transformed_vertex.xyz();
        }

        const CUBE_INDICES: [[u16; 4]; 6] = [
            [0, 4, 6, 2],
            [1, 3, 7, 5],
            [0, 1, 5, 4],
            [2, 6, 7, 3],
            [0, 2, 3, 1],
            [4, 5, 7, 6],
        ];

        for face in 0..6 {
            if face_mask & (1 << face) != 0 {
                self.add_cube_face_with_cube_vertices(
                    &cube_vertices,
                    colour,
                    CUBE_INDICES[face][0],
                    CUBE_INDICES[face][1],
                    CUBE_INDICES[face][2],
                    CUBE_INDICES[face][3],
                    inward_normals,
                );
            }
        }
    }
}

impl Geometry for TriangleGeometry {
    fn upload_to_buffers(&mut self) {
        self.index_buffer = Some(unsafe {
            self.device.new_buffer_with_data(
                transmute(self.indices.as_ptr()),
                (self.indices.len() * size_of::<u16>()) as NSUInteger,
                get_managed_buffer_storage_mode(),
            )
        });
        self.vertex_position_buffer = Some(unsafe {
            self.device.new_buffer_with_data(
                transmute(self.vertices.as_ptr()),
                (self.vertices.len() * size_of::<Vec4>()) as NSUInteger,
                get_managed_buffer_storage_mode(),
            )
        });
        self.vertex_normal_buffer = Some(unsafe {
            self.device.new_buffer_with_data(
                transmute(self.normals.as_ptr()),
                (self.normals.len() * size_of::<Vec4>()) as NSUInteger,
                get_managed_buffer_storage_mode(),
            )
        });
        self.vertex_colour_buffer = Some(unsafe {
            self.device.new_buffer_with_data(
                transmute(self.colours.as_ptr()),
                (self.colours.len() * size_of::<Vec4>()) as NSUInteger,
                get_managed_buffer_storage_mode(),
            )
        });
        self.per_primitive_data_buffer = Some(unsafe {
            self.device.new_buffer_with_data(
                transmute(self.triangles.as_ptr()),
                (self.triangles.len() * size_of::<Triangle>()) as NSUInteger,
                get_managed_buffer_storage_mode(),
            )
        });
        self.index_buffer
            .as_ref()
            .unwrap()
            .did_modify_range(NSRange::new(
                0,
                self.index_buffer.as_ref().unwrap().length(),
            ));
        self.vertex_position_buffer
            .as_ref()
            .unwrap()
            .did_modify_range(NSRange::new(
                0,
                self.vertex_position_buffer.as_ref().unwrap().length(),
            ));
        self.vertex_normal_buffer
            .as_ref()
            .unwrap()
            .did_modify_range(NSRange::new(
                0,
                self.vertex_normal_buffer.as_ref().unwrap().length(),
            ));
        self.vertex_colour_buffer
            .as_ref()
            .unwrap()
            .did_modify_range(NSRange::new(
                0,
                self.vertex_colour_buffer.as_ref().unwrap().length(),
            ));
        self.per_primitive_data_buffer
            .as_ref()
            .unwrap()
            .did_modify_range(NSRange::new(
                0,
                self.per_primitive_data_buffer.as_ref().unwrap().length(),
            ));

        self.index_buffer
            .as_ref()
            .unwrap()
            .set_label(&format!("index buffer of {}", self.name));
        self.vertex_position_buffer
            .as_ref()
            .unwrap()
            .set_label(&format!("vertex position buffer of {}", self.name));
        self.vertex_normal_buffer
            .as_ref()
            .unwrap()
            .set_label(&format!("vertex normal buffer of {}", self.name));
        self.vertex_colour_buffer
            .as_ref()
            .unwrap()
            .set_label(&format!("vertex colour buffer of {}", self.name));
        self.per_primitive_data_buffer
            .as_ref()
            .unwrap()
            .set_label(&format!("per primitive data buffer of {}", self.name));
    }

    fn clear(&mut self) {
        self.indices.clear();
        self.vertices.clear();
        self.normals.clear();
        self.colours.clear();
        self.triangles.clear();
    }

    fn get_geometry_descriptor(&self) -> AccelerationStructureGeometryDescriptor {
        let descriptor = AccelerationStructureTriangleGeometryDescriptor::descriptor();

        descriptor.set_index_buffer(Some(self.index_buffer.as_ref().unwrap()));
        descriptor.set_index_type(MTLIndexType::UInt16);
        descriptor.set_vertex_buffer(Some(self.vertex_position_buffer.as_ref().unwrap()));
        descriptor.set_vertex_stride(size_of::<Vec4>() as NSUInteger);
        descriptor.set_triangle_count((self.indices.len() / 3) as NSUInteger);
        descriptor
            .set_primitive_data_buffer(Some(self.per_primitive_data_buffer.as_ref().unwrap()));
        descriptor.set_primitive_data_stride(size_of::<Triangle>() as NSUInteger);
        descriptor.set_primitive_data_element_size(size_of::<Triangle>() as NSUInteger);
        From::from(descriptor)
    }

    fn get_resources(&self) -> Vec<Resource> {
        vec![
            From::from(self.index_buffer.as_ref().unwrap().clone()),
            From::from(self.vertex_normal_buffer.as_ref().unwrap().clone()),
            From::from(self.vertex_colour_buffer.as_ref().unwrap().clone()),
        ]
    }
}

#[repr(C)]
pub struct BoundingBox {
    pub min: Vec3,
    pub max: Vec3,
}

#[repr(C)]
pub struct Sphere {
    pub origin_radius_squared: Vec4,
    pub colour_radius: Vec4,
}

pub struct SphereGeometry {
    pub device: Device,
    pub sphere_buffer: Option<Buffer>,
    pub bounding_box_buffer: Option<Buffer>,
    pub per_primitive_data_buffer: Option<Buffer>,
    pub spheres: Vec<Sphere>,
}

impl SphereGeometry {
    pub fn new(device: Device) -> Self {
        Self {
            device,
            sphere_buffer: None,
            bounding_box_buffer: None,
            per_primitive_data_buffer: None,
            spheres: Vec::new(),
        }
    }

    pub fn add_sphere_with_origin(&mut self, origin: Vec3, radius: f32, colour: Vec3) {
        self.spheres.push(Sphere {
            origin_radius_squared: Vec4::from((origin, radius * radius)),
            colour_radius: Vec4::from((colour, radius)),
        });
    }
}

impl Geometry for SphereGeometry {
    fn upload_to_buffers(&mut self) {
        self.sphere_buffer = Some(unsafe {
            self.device.new_buffer_with_data(
                transmute(self.spheres.as_ptr()),
                (self.spheres.len() * size_of::<Sphere>()) as NSUInteger,
                get_managed_buffer_storage_mode(),
            )
        });
        self.sphere_buffer
            .as_ref()
            .unwrap()
            .set_label("sphere buffer");
        let mut bounding_boxes = Vec::new();
        for sphere in &self.spheres {
            bounding_boxes.push(BoundingBox {
                min: sphere.origin_radius_squared.xyz() - sphere.colour_radius.w,
                max: sphere.origin_radius_squared.xyz() + sphere.colour_radius.w,
            });
        }
        self.bounding_box_buffer = Some(unsafe {
            self.device.new_buffer_with_data(
                transmute(bounding_boxes.as_ptr()),
                (bounding_boxes.len() * size_of::<BoundingBox>()) as NSUInteger,
                get_managed_buffer_storage_mode(),
            )
        });
        self.bounding_box_buffer
            .as_ref()
            .unwrap()
            .set_label("bounding box buffer");
        self.sphere_buffer
            .as_ref()
            .unwrap()
            .did_modify_range(NSRange::new(
                0,
                self.sphere_buffer.as_ref().unwrap().length(),
            ));
        self.bounding_box_buffer
            .as_ref()
            .unwrap()
            .did_modify_range(NSRange::new(
                0,
                self.bounding_box_buffer.as_ref().unwrap().length(),
            ));
    }

    fn clear(&mut self) {
        self.spheres.clear();
    }

    fn get_geometry_descriptor(&self) -> AccelerationStructureGeometryDescriptor {
        let descriptor = AccelerationStructureBoundingBoxGeometryDescriptor::descriptor();
        descriptor.set_bounding_box_buffer(Some(self.bounding_box_buffer.as_ref().unwrap()));
        descriptor.set_bounding_box_count(self.spheres.len() as NSUInteger);
        descriptor.set_primitive_data_buffer(Some(&self.sphere_buffer.as_ref().unwrap()));
        descriptor.set_primitive_data_stride(size_of::<Sphere>() as NSUInteger);
        descriptor.set_primitive_data_element_size(size_of::<Sphere>() as NSUInteger);
        From::from(descriptor)
    }

    fn get_resources(&self) -> Vec<Resource> {
        return vec![From::from(self.sphere_buffer.as_ref().unwrap().clone())];
    }

    fn get_intersection_function_name(&self) -> Option<&str> {
        Some("sphereIntersectionFunction")
    }
}

pub struct GeometryInstance {
    pub geometry: Arc<dyn Geometry>,
    pub transform: Mat4,
    pub mask: u32,
    pub index_in_scene: NSUInteger,
}

#[repr(C)]
pub struct AreaLight {
    pub position: Vec4,
    pub forward: Vec4,
    pub right: Vec4,
    pub up: Vec4,
    pub colour: Vec4,
}

[ Dauer der Verarbeitung: 0.25 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge