theatre-js / theatre

Motion design editor for the web
https://www.theatrejs.com
Apache License 2.0
11.38k stars 361 forks source link

theatre/r3f: Modify R3F Euler rotations in degrees, not radians #86

Open donmccurdy opened 2 years ago

donmccurdy commented 2 years ago

Using radians to keyframe Euler rotations feels less natural to me, coming from software like Blender where these edits are done in degrees. For example, keyframing to Y=90º is easier than Y=1.5707963. We could change the @theatre/r3f bindings to work with Euler rotations (e.g. THREE.Euler) in degrees, instead. This could potentially just be a UI change, where the keyframe data is still serialized and stored in radians. Would a PR for this change be welcome? Thanks!

AndrewPrifer commented 2 years ago

Hey @donmccurdy, this makes sense! The PR is definitely welcome! So to summarize, we take input in degrees and store and sterilize in radians, right?

Ultimately the goal is that while we should always serialize to a canonical unit (in this case radians), we could support data entry and display in different units, like degrees for rotation, km for translation, or F for temperature, if someone makes a custom prop for that sometime. :D

donmccurdy commented 2 years ago

So to summarize, we take input in degrees and store and sterilize in radians, right?

If there's some reason it's better to store degrees (I don't know of any) I'd be open to that approach too. But yes — "input and display in degrees, store in radians" sounds great.

This isn't my use case at the moment, but I could easily imagine needing a similar solution for interpolating color, e.g. input and display in sRGB, store and interpolate in Linear-sRGB or ACEScg.

AndrewPrifer commented 2 years ago

Glad you mentioned this, I already made an internal design doc for the future architecture of props, the current one is only there to serve the most immediate needs. Basically I see 3 different individually configurable aspects to props:

For example in the case of colors, you might want to input it in HLS, interpolate in LAB, and have the output be in sRGB, so even the interpolation could have its own bespoke space to happen in.

None of this is set in stone, just something we are thinking about.

donmccurdy commented 2 years ago

The easy fix of updating a couple lines in @theatre/r3f would result in storing degrees rather than radians, and I guess would also be backward-incompatible... that's not ideal, correct? Did you have new options in mind for the property API, like this?

export const number = (
  defaultValue: number,
  opts?: {
    nudgeFn?: PropTypeConfig_Number['nudgeFn']
    range?: PropTypeConfig_Number['range']
    nudgeMultiplier?: number
    label?: string
    sanitize?: Sanitizer<number>
    interpolate?: Interpolator<number>

    // ✨ NEW
    transformInput: Transform<number>
    transformOutput: Transform<number>
  },
  ...

...Or something deeper in the architecture?

AndrewPrifer commented 2 years ago

Considering this would be a bandaid until we overhaul the deeper architecture a little, which is a bit down the road, it best be arranged at extension level for now. I'd hide it behind a configuration option that defaults to radians to take care of backwards compatibility, should be enough imo.

donmccurdy commented 2 years ago

Just to share another possible difference in handling rotations vs. vectors here – I'm finding it much more natural to keyframe rotations on cameras using the ZYX (roll, yaw, pitch) order rather than XYZ (pitch, yaw, roll). For example, camera.rotation.set(x, y, z, 'ZYX').