molgfx-core 0.3.0

The semantic scene graph: columnar tables, GPU record layouts, the borrowed coordinate seam.
Documentation
//! Manifest conversion for caller-authored analytic primitives.

use super::super::types::{ParticleMotionDescription, PrimitiveDescription};
use super::{identity, rgba};
use crate::handle::RawHandle;
use crate::{ParticleBoundary, ParticleShape, Primitive};
use molgfx_math::{Quat, Rgba8};

pub(crate) fn primitive_description(raw: RawHandle, value: &Primitive) -> PrimitiveDescription {
    let identity = identity(value.owner());
    let fields = primitive_fields(value);
    PrimitiveDescription {
        row: raw.row(),
        generation: raw.generation(),
        owner: identity,
        kind: fields.kind.to_owned(),
        visible: fields.visible,
        color: rgba(fields.color),
        opacity: fields.opacity,
        center: fields.center,
        orientation: fields.orientation,
        size: fields.size,
        tensor: fields.tensor,
        plane_axes: fields.plane_axes,
        shape: fields.shape.map(str::to_owned),
        shape_parameters: fields.shape_parameters,
        motion: fields.motion,
    }
}

struct PrimitiveFields {
    kind: &'static str,
    visible: bool,
    color: Rgba8,
    opacity: f32,
    center: [f32; 3],
    orientation: [f32; 4],
    size: [f32; 3],
    tensor: Option<[f32; 6]>,
    plane_axes: Option<[[f32; 3]; 3]>,
    shape: Option<&'static str>,
    shape_parameters: [f32; 2],
    motion: Option<ParticleMotionDescription>,
}

fn primitive_fields(value: &Primitive) -> PrimitiveFields {
    match *value {
        Primitive::Ellipsoid {
            value,
            color,
            opacity,
            visible,
            ..
        } => PrimitiveFields {
            kind: "ellipsoid",
            visible,
            color,
            opacity,
            center: value.center().to_array(),
            orientation: Quat::IDENTITY.to_array(),
            size: [0.0; 3],
            tensor: Some(value.tensor()),
            plane_axes: None,
            shape: None,
            shape_parameters: [1.0; 2],
            motion: None,
        },
        Primitive::Carbohydrate(value) => PrimitiveFields {
            kind: "carbohydrate",
            visible: value.visible,
            color: value.color,
            opacity: 1.0,
            center: value.center.to_array(),
            orientation: value.orientation.to_array(),
            size: value.size.to_array(),
            tensor: None,
            plane_axes: None,
            shape: Some(value.shape.stable_name()),
            shape_parameters: [1.0; 2],
            motion: None,
        },
        Primitive::Planar {
            value,
            color,
            opacity,
            visible,
        } => PrimitiveFields {
            kind: "planar",
            visible,
            color,
            opacity,
            center: value.center.to_array(),
            orientation: Quat::IDENTITY.to_array(),
            size: [value.size[0], value.size[1], 0.0],
            tensor: None,
            plane_axes: Some([
                value.normal.to_array(),
                value.tangent.to_array(),
                value.bitangent.to_array(),
            ]),
            shape: None,
            shape_parameters: [1.0; 2],
            motion: None,
        },
        Primitive::Particle(value) => PrimitiveFields {
            kind: "particle",
            visible: value.visible,
            color: value.color,
            opacity: value.opacity,
            center: value.center.to_array(),
            orientation: value.orientation.to_array(),
            size: value.size.to_array(),
            tensor: None,
            plane_axes: None,
            shape: Some(match value.shape {
                ParticleShape::Sphere => "sphere",
                ParticleShape::Box => "box",
                ParticleShape::Cylinder => "cylinder",
                ParticleShape::Spherocylinder => "spherocylinder",
                ParticleShape::Gaussian => "gaussian",
                ParticleShape::Circle => "circle",
                ParticleShape::Square => "square",
                ParticleShape::Superquadric => "superquadric",
            }),
            shape_parameters: value.shape_parameters,
            motion: value.motion.map(motion_description),
        },
    }
}

fn motion_description(value: crate::ParticleMotion) -> ParticleMotionDescription {
    ParticleMotionDescription {
        velocity: value.velocity().to_array(),
        bounds: [value.bounds().min.to_array(), value.bounds().max.to_array()],
        fixed_timestep: value.fixed_timestep(),
        seed: value.seed(),
        boundary: match value.boundary() {
            ParticleBoundary::Bounce => "bounce",
            ParticleBoundary::Wrap => "wrap",
        }
        .to_owned(),
        respawn_after_steps: value.respawn_after_steps(),
    }
}