KEMBAR78
Change originOffset w/ Reference Space constructor by toji · Pull Request #589 · immersive-web/webxr · GitHub
Skip to content

Conversation

@toji
Copy link
Member

@toji toji commented Apr 15, 2019

Fixes #580. Changes originOffset to be immutable and establish that the
way that the originOffset changes is by constructing a new reference
space with the base space and an additional offset to apply on top of
it. This should hopefully solve several timing issues related to
changing the originOffset mid-frame.

@toji toji added the potential breaking change Issues that may affect the core design structure. label Apr 15, 2019
index.bs Outdated
[SecureContext, Exposed=Window,
Constructor(XRReferenceSpace base, XRRigidTransform originOffset)]
interface XRReferenceSpace : XRSpace {
readonly attribute XRReferenceSpace? base;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[SameObject] on both in accordance with #588 ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In accordance with our move to remove attributes that reflect the object's creation parameters, this should probably be removed altogether.

index.bs Outdated
1. Let |refSpace| be a new {{XRReferenceSpace}}.
1. If |base|'s {{XRReferenceSpace/base}} is <code>null</code>, set |refSpace|'s {{XRReferenceSpace/base}} to |base|.
1. Else set |refSpace|'s {{XRReferenceSpace/base}} to |base|'s {{XRReferenceSpace/base}}.
1. Set |refSpace|'s {{XRReferenceSpace/originOffset}} to |originOffset| multiplied by |base|'s {{XRReferenceSpace/originOffset}}.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to clarify pre vs post multiply here.

Ideally avoid talking about multiplication at all, instead saying "Set refSpace's originOffset to a transform where base's originOffset is applied first, and originOffset is applied second".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why avoid talking about multiplication? We've got several issues that call out the need to clarify related topics like this one #582. And actually, I'd be ok filing a separate issue for this to unblock this merge.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yeah, I guess we should figure out how to consistently talk about this first instead of attempting to fix it in each use site in an ad hoc manner.

index.bs Outdated
attribute XRRigidTransform originOffset;

[SecureContext, Exposed=Window,
Constructor(XRReferenceSpace base, XRRigidTransform originOffset)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we change this pattern to not be a constructor, but rather a function on the XRReferenceSpace object being based on? Maybe XRReferenceSpace.getOffsetReferenceSpace()

Copy link
Member

@NellWaliczek NellWaliczek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a fan of making the origin offset static for a given XRReferenceSpace, though I do have a few concerns about the specifics of the approach in this PR. My hunch is that mixing constructors vs functions for the creation of an XReferenceSpace will only lead to confusion. However, I see two approaches for adding this behavior in a function-driven way:

  1. Hanging off of XRReferenceSpace. Bikeshedding aside, this could look something like XRReferenceSpace.createOffsetReferenceSpace(XRRigidTransform offset). This would have all the same behaviors of the reference space it was created off of, but with an offset origin.
  2. Hanging off of XRSession. Again, bikeshedding aside, this could look something like `XRSession.requestReferenceSpace(XRReferenceSpace, XRRigidTransform offset).
    Either way I have concerns about folks getting confused about which version is async or not...

And lastly, please include the Explainer updates in this PR :)

index.bs Outdated
1. Let |refSpace| be a new {{XRReferenceSpace}}.
1. If |base|'s {{XRReferenceSpace/base}} is <code>null</code>, set |refSpace|'s {{XRReferenceSpace/base}} to |base|.
1. Else set |refSpace|'s {{XRReferenceSpace/base}} to |base|'s {{XRReferenceSpace/base}}.
1. Set |refSpace|'s {{XRReferenceSpace/originOffset}} to |originOffset| multiplied by |base|'s {{XRReferenceSpace/originOffset}}.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why avoid talking about multiplication? We've got several issues that call out the need to clarify related topics like this one #582. And actually, I'd be ok filing a separate issue for this to unblock this merge.

index.bs Outdated

<section class="unstable">
The <dfn attribute for="XRReferenceSpace">originOffset</dfn> attribute is a {{XRRigidTransform}} that describes an additional translation and rotation to be applied to any poses queried using the {{XRReferenceSpace}}. It is initially set to an [=identity transform=]. Changes to the {{originOffset}} take effect immediately, and subsequent poses queried with the {{XRReferenceSpace}} will take into account the new transform.
The <dfn constructor for="XRReferenceSpace">XRReferenceSpace(|base|, |originOffset|)</dfn> constructor MUST perform the following steps when invoked:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned above, I think it's confusing to have a constructor that only works for what amounts to a copy. And given that initial reference space creation requires an asynchronous call, a constructor isn't really an option.

index.bs Outdated
</div>

<section class="unstable">
The <dfn attribute for="XRReferenceSpace">originOffset</dfn> attribute is a {{XRRigidTransform}} that describes an additional translation and rotation to be applied to any poses queried using the {{XRReferenceSpace}}.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: nix the word 'additional'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@toji, are you intentionally reversing the meaning of the originOffset here? If the originOffset provides the position and orientation of the offset space, where the position member is exactly the origin position in base space coordinates, queries using the offset space need to apply the inverse of the originOffset transform when returning poses, assuming you want to match the voted resolution for #477. (cf. #569 and the rough consensus from #580.)

index.bs Outdated
1. If |type| is {{stationary}}, let |referenceSpace| be a new {{XRReferenceSpace}}.
1. Else if |type| is {{bounded}}, let |referenceSpace| be a new {{XRBoundedReferenceSpace}}.
1. Else if |type| is {{unbounded}}, let |referenceSpace| be a new {{XRReferenceSpace}}.
1. Set |referenceSpace|'s {{XRReferenceSpace/originOffset}} to an [=identity transform=].
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might consider adding the origin offset as a parameter to this function...

index.bs Outdated
1. Let |refSpace| be a new {{XRBoundedReferenceSpace}}.
1. If |base|'s {{XRReferenceSpace/base}} is <code>null</code>, set |refSpace|'s {{XRReferenceSpace/base}} to |base|.
1. Else set |refSpace|'s {{XRReferenceSpace/base}} to |base|'s {{XRReferenceSpace/base}}.
1. Set |refSpace|'s {{XRReferenceSpace/originOffset}} to |originOffset| multiplied by |base|'s {{XRReferenceSpace/originOffset}}.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an existing definition what it means to multiply XRRigidTransforms? This needs to be unambiguous. I think it's backwards as written.

Let's say we set up a base space and two chained offsets like this:

let baseSpaceA = ...; starting reference space A
let offsetSpaceA = new XRBoundedReferenceSpace(baseSpaceA, originOffsetA);
let offsetSpaceB = new XRBoundedReferenceSpace(offsetSpaceA, originOffsetB);

Each originOffset's matrix is a transform from offset space to base space. Space B's base space corresponds to space A's offset space.

You can use the matrices to transform coordinates in offsetSpaceB to coordinates in baseSpaceA:

pointInBaseA = baseAFromOffsetA * offsetAFromOffsetB * pointInOffsetB;
             = offsetSpaceA.originOffset.matrix * offsetSpaceB.originOffset.matrix * pointInOffsetB

and therefore, space B's originOffset.matrix is space A's originOffset.matrix times space B's originOffset.matrix, or for spec purposes:

1. Set |refSpace|'s {{XRReferenceSpace/originOffset}} to |base|'s {{XRReferenceSpace/originOffset}} multiplied by |originOffset|.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➕ 1 to having this defined as an "algorithm" in the spec so we can easily reference it in other spec "algorithms". @klausw , do you want to post a PR with this clarification text and Brandon and I can review it? I think getting that nailed down first will go a long way towards our goal of algorithmically defining the behavior of getPose() and getViewerPose().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NellWaliczek That's what I was trying to do in my existing PR, see especially https://github.com/immersive-web/webxr/pull/569/files#diff-ec9cfa5f3f35ec1f84feb2e59686c34dR955 which tries to be quite specific about this.

Can we discuss that in that PR? I'm happy to extend this further, i.e. adding more info about chaining transforms, but I'd like to get consensus on the basics first.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I think there's a misunderstanding here between Nell and Klaus. I believe the algorithm which Nell is talking about is one that describes how two XRRigidTransforms are multiplied. (At least that's how it reads given the context.) The line in Klaus' PR that was linked details (very well) how a matrix is derived from the rigid transform.

I do think that having an in-spec algorithm that describes how transforms are multiplied would be extremely useful. That's something that Nell or I could sketch out if needed, but either way I'd want to have Klaus and/or Manish review it to ensure we're all on the same page. Then that should serve as a fundamental building block though which we can help describe a great many of the rest of these concepts.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@toji The text I have now in #569 specifies the content of a XRRigidTransform matrix and how it transforms numeric coordinates, and this should constrain implementations to one specific interpretation of how the transforms work. As a result, there should only be one correct way to chain transforms.

I don't think it makes sense to have an independent PR or discussion about chaining transforms unless we can get agreement on these basic properties of transforms. There's no separate design freedom for the underlying matrix math of XRRigidTransform multiplication. I agree it would be helpful to add an explanation to the text, but I think this would be appropriate as a followup since it's derived from the basic properties and definitions of the transforms and matrices.

I'm fairly confident that the chaining I described in my comment above matches #569, assuming usual column-major GL matrices applied to column vectors, but I'd appreciate an independent sanity check.

Would it help to schedule some time with interested parties to talk through this? I feel as if we're still a bit stuck on this issue even after discussing it in two of the weekly conf calls, and I'm unsure if there's actual disagreement or not.

Fixes #580. Changes originOffset to be immutable and establish that the
way that the originOffset changes is by constructing a new reference
space with the base space and an additional offset to apply on top of
it. This should hopefully solve several timing issues related to
changing the originOffset mid-frame.
@toji toji force-pushed the immutable_origin_offset branch from 5e40383 to 9ed76f7 Compare April 26, 2019 21:03
@toji toji changed the base branch from remove-empty-ref-spaces to define-space April 26, 2019 21:04
@toji toji closed this Apr 27, 2019
@ddorwin
Copy link
Contributor

ddorwin commented Apr 30, 2019

For reference, this PR was moved to #612 (comment).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

potential breaking change Issues that may affect the core design structure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants