Bookshelf icon indicating copy to clipboard operation
Bookshelf copied to clipboard

Add quaternion operations

Open aksiome opened this issue 7 months ago • 5 comments

🗂️ Request Type

Feature

🧩 Feature or Module Name

_

📝 Description

Extend the bs.vector or bs.math module with quaternion support. Useful operations could include:

  • Rotating a vector using a quaternion
  • Quaternion multiplication
  • Applying quaternion rotation to an entity's facing direction

Given the specificity, it may also be worth considering the creation of a dedicated bs.quaternion module.

aksiome avatar May 05 '25 19:05 aksiome

An extension of the module into quaternions would probably be very helpful, especially for helping to deobfuscate them for people. To add on to this, I'd like to suggest these two other quaternion functions that I've personally found to be very helpful:

  • Generating a quaternion representing the current rotation context. This is something I've found very helpful as a convenience function when working with display entities, + using persistent entities can make this specific operation a little faster than converting from Euler angles held in scores/storage.
  • Converting a quaternion into a rotation matrix. Though I can't comment on if this approach is particularly efficient, I do this a lot when I want to get a vector basis from a quaternion.

This is something I haven't implemented, so I can't vouch for it's usefulness in real situations, but feel would be nice:

  • Interpolating between two quaternions given a t parameter.

fan-of123 avatar May 05 '25 20:05 fan-of123

In angular velocity calculations, interpolating between two orthogonal quaternion orientations proves particularly useful. Representing the process of rotation around an axis through quaternion interpolation can significantly optimize computations. When updating orientations, only the calculation of scalar tquaternion q1 + t2quaternion q2 is required. This approach reduces computational load compared to direct quaternion multiplication and avoids precision issues from iterative calculations.

Additionally, I have various quaternion normalization methods - here's one example (for quaternions close to unit length, with components scaled by 10,000):

function u.math:q/fast_normalize:
        qtemp = qx * qx
        t1 = qy * qy
        t2 = qz * qz
        t3 = qw * qw
        qtemp = qtemp + t1 + t2 + t3
        qtemp = (qtemp - 300000000)/(-20000)
        qx *= qtemp
        qy *= qtemp
        qz *= qtemp
        qw *= qtemp
        qx /= 10000
        qy /= 10000
        qz /= 10000
        qw /= 10000

Ethanout avatar May 10 '25 14:05 Ethanout

If someone wants to tackle this module, go for it! I'm a complete newbie when it comes to quaternions, and there's no way I can fit this into my backlog for the next feature update, so I won’t be working on it anytime soon 😅.

aksiome avatar May 10 '25 16:05 aksiome

I'm thinking of working on this issue and I want to discuss it first before diving in:

After reviewing the current implementations of bs.vector and bs.math, I noticed that inputs and outputs rely on in and out storages or objectives. Continuously rotating a display entity using the existing methods would be cumbersome—each calculation requires extensive use of execute store and conversions between in and out.

I think scoreboard objective operations on entities might simplify this process. To address this, we may need a dedicated module for quaternion calculations and transformation updates, for example, bs.transformation. Would this be acceptable?

Ethanout avatar May 11 '25 07:05 Ethanout

I think having a dedicated module is great and actually better. Maybe bs.quaternion is a little better than bs.transformation which is more generic? Regarding scores, bookshelf has a crazy amount of conventions that you can check here: https://docs.mcbookshelf.dev/en/latest/contribute/conventions.html We're not stuck with in and out scores at all, we also have a ctx with single letter scoreholder for faster contextual operations, and we're open to adding new ways of doing things. Maybe the first thing to do would be to draft a spec of how the module should be used (feature names, inputs, outputs, ...)

aksiome avatar May 11 '25 22:05 aksiome