molgfx-core 0.2.1

The semantic scene graph: columnar tables, GPU record layouts, the borrowed coordinate seam.
Documentation
use super::{insert, invalid, raw, resolve_structure, same_array_bits, value_hash};
use crate::scene::{BoundOccupancy, Scene, StoredVolume};
use crate::serialization::types::{OccupancyDescription, VolumeDescription};
use crate::{CoreError, StructureHandle};

pub(super) fn rehydrate(
    scene: &mut Scene,
    descriptions: &[VolumeDescription],
    sources: &[crate::ScalarVolume],
    structures: &[StructureHandle],
) -> Result<(), CoreError> {
    let mut sources = sources.iter();
    for description in descriptions {
        if let Some(occupancy) = &description.occupancy {
            rehydrate_occupancy(scene, description, occupancy, structures)?;
            continue;
        }
        let Some(value) = sources.next() else {
            return invalid("scalar volume source is absent");
        };
        if value.dimensions() != description.dimensions
            || !same_array_bits(value.range(), description.range)
            || !same_array_bits(
                value.voxel_to_world().to_cols_array(),
                description.voxel_to_world,
            )
            || value_hash(value.values()) != description.content_hash
        {
            return invalid("supplied scalar volume does not match its manifest");
        }
        let raw = raw(description.row, description.generation);
        insert(
            scene.volumes.insert_at(
                raw,
                StoredVolume {
                    value: Some(value.clone()),
                    occupancy: None,
                    revision: 0,
                },
            ),
            "volume identity collision",
        )?;
    }
    Ok(())
}

fn rehydrate_occupancy(
    scene: &mut Scene,
    description: &VolumeDescription,
    occupancy: &OccupancyDescription,
    structures: &[StructureHandle],
) -> Result<(), CoreError> {
    let structure = resolve_structure(structures, occupancy.structure)?;
    let transform = molgfx_math::Mat4::from_cols_array(&occupancy.voxel_to_model);
    let spacing = molgfx_math::Vec3::new(
        transform.x_axis.truncate().length(),
        transform.y_axis.truncate().length(),
        transform.z_axis.truncate().length(),
    );
    let stream = crate::OccupancyStream::new(
        description.dimensions,
        transform.w_axis.truncate(),
        spacing,
        occupancy.decay,
        occupancy.deposit,
        occupancy.maximum,
    )?;
    let atom_count = scene
        .structure(structure)
        .map_or(0, |placed| placed.atoms.len());
    if occupancy
        .atom_rows
        .windows(2)
        .any(|rows| rows[0] >= rows[1])
        || occupancy.atom_rows.iter().any(|&row| row >= atom_count)
    {
        return invalid("occupancy atom rows are invalid");
    }
    let raw = raw(description.row, description.generation);
    insert(
        scene.volumes.insert_at(
            raw,
            StoredVolume {
                value: None,
                occupancy: Some(BoundOccupancy {
                    stream,
                    structure,
                    atom_rows: std::sync::Arc::from(occupancy.atom_rows.clone()),
                }),
                revision: 0,
            },
        ),
        "volume identity collision",
    )
}