i wanna finally finish Eightfold but god it's been almost two years(!!) and i gotta figure out what the hell i was doing when i last touched it

at least it's almost done lol

EDIT: oh my god, everything is commented as fuck, i'm such a big brain smartgirl for doing that, thank you past me

like, look at this, these are some ridiculously informative comments (this is from some sample code, though; the comments in the actual library are a bit less thorough):

/// Convert a `glTF` [Transform](gltf::scene::Transform) to a [nalgebra]
/// [Affine3].
///
/// An affine transformation is, in order, a non-uniform scaling, a rotation, and then a
/// translation.
///
/// A `glTF` transformation is stored either as an affine transformation matrix, or as separate
/// translation, rotation, and scale components. Therefore, the most general possible kind of
/// transformation is affine, which means that the *least* general kind of transformation we can
/// return is an [Affine3].
///
/// ## See Also
///
/// * [nalgebra's explanation of transformations](https://www.nalgebra.org/docs/user_guide/points_and_transformations/#transformations)
pub fn gltf_to_nalgebra(g: &gltf::scene::Transform) -> Affine3<f32> {
    match g {
        // the Matrix variant is stored as a column-major [[f32; 4]; 4], so we can just transmute
        // that into an [f32; 16] and use that directly.
        gltf::scene::Transform::Matrix { matrix: ref m } => {
            // the glTF spec states that matrix transformations *must* be decomposable to their
            // translation, rotation, and scale components. Therefore, a matrix from a compliant
            // glTF file can be converted directly to an Affine3.
            Affine3::<f32>::from_matrix_unchecked(Matrix4::from_column_slice(
                // arrays are stored contiguously, so, in memory, an [[f32; 4]; 4] is identical to
                // an [f32; 16], which means we can safely interpret one to the other.
                //
                // `std::mem::transmute` tells Rust's compiler that we want to interpret something of
                // type `A` as, instead, something of type `B`. It doesn't actually do anything at
                // runtime.
                unsafe { std::mem::transmute::<&[[f32; 4]; 4], &[f32; 16]>(m) }.as_slice(),
            ))
        }
        // this is a bit more complicated, because we have to convert these three components into
        // a single Transform3.
        gltf::scene::Transform::Decomposed {
            translation: ref trans, // [x, y, z]
            rotation: ref rot,      // unit quaternion, [x, y, z, w]
            scale: ref scl,         // [x, y, z]
        } => {
            // Store the resulting homogeneous Matrix4 as an Affine3.
            // We don't have to check for correctness, because we already know
            // that the matrix we're storing represents an affine transformation.
            Affine3::from_matrix_unchecked(
                // construct an Isometry (a rotation followed by a
                // translation) from `trans` and `rot`
                Isometry3::from_parts(
                    Translation3::from(*trans), // <- we can convert `trans` directly
                    Unit::new_unchecked(Quaternion::from(*rot)), // <- same with `rot`. The glTF spec
                                                                 // requires rotations to be stored as
                                                                 // unit quaternions, so we don't need
                                                                 // to validate that here.
                                                                 // Conveniently, nalgebra and glTF
                                                                 // use the same format for
                                                                 // quaternions.
                )
                // convert the Isometry3 to a homogenous Matrix4, so we can
                // apply the scaling (remember, an isometry is a rotation
                // followed by a translation; it, by definition, cannot have a
                // rotation, and the Isometry3 struct reflects that.)
                .to_homogeneous()
                // apply the scaling, resulting in a matrix M = Translation * Rotation * Scale.
                //
                // Reminder: when transforming a point using a matrix, the transformations
                // are applied to the point in the reverse of the order they were applied to the
                // matrix. So, a point transformed by a `TRS` (`Translation * Rotation * Scale`)
                // matrix is first scaled, then rotated, then translated. This is important because
                // applying those transformations in another order would produce a different end
                // result.
                .prepend_nonuniform_scaling(&Vector3::from(*scl)),
            )
        }
    }
}

been listening to friend from the internet by laryssa okada; it's really good and it's thematically appropriate for messing with websites

i was gonna embed the bandcamp player for it but i don't wanna have that automatically load whatever tracker nonsense they have going on so you're just gonna have to click the link instead

i should probably move most of the 88x31s into their own page so i'm not reuploading every page every time i change the button set

every day my urge to write an app for ao3 grows stronger

mostly just because scrolling through the "Trans Female Character" tag all the time is finicky and i wanna be able to just have a nice feed of new stories to read without having to remember all the ones i've already seen and decided not to read

i should finish flyover chapter 2 or something so the most recent post isn't the "how to block scrapers" one because it's a little too nerd emoji

I went out to look for more buttons and I'm begging everyone who has 88x31s or other pixel art on their website: please use image-rendering: crisp-edges

Posted the first chapter of another story I've been writing (it's backdated to when I published it on Ao3, so it should appear down near the bottom of the main post list).

I should probably add a "Read More" button to long posts when they're displayed on the main post feed. I also need to figure out how to get Eleventy to collect chapters / post series into single pages. Hmmmmmmmm.

Buttons

Added some buttons to the bottom of each page, since it was free real estate and I want to link to other sites that I like.

I'll probably make a dedicated page for links to other sites at some point? I might do that immediately after posting this; who knows.

Maybe next I'll write a guide to CSS grids? Since, you know, that seems like something people might want.

Also, does this note block thing look good? The one floating to the side of this post. (Or, maybe not floating to the side, if you're reading this in a future where I changed how notes look.) Maybe I should also add a comments section, somehow.

I'm also considering including some Javascript to randomize the order of buttons when you load the page, just so there's no bias towards any specific site. Maybe I'm overthinking it? Hm.