Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SUPPORT] Making consecutive scene.pick calls results in some unpredictible behavior #1314

Closed
hamza-hajji opened this issue Dec 25, 2023 · 1 comment

Comments

@hamza-hajji
Copy link
Contributor

hamza-hajji commented Dec 25, 2023

Describe the bug
Making consecutive calls to scene.pick leads to some unpredictible results
To Reproduce
Steps to reproduce the behavior:

  1. Make a scene.pick call with canvasPos
  2. Make another pick using origin/direction

I added the following code to the example xkt_vbo_Duplex.html

let trigger = false;

viewer.scene.input.on("mousedown", (coords) => {
  const hit = viewer.scene.pick({
    canvasPos: coords,
    pickSurface: true,
  });
   
  // trigger to mousemove to start dragging  
  if (hit) {
    trigger = true;
    viewer.cameraControl.active = false;
  }
});

viewer.scene.input.on("mouseup", () => {
  // trigger to mousemove to stop dragging
  trigger = false;
  viewer.cameraControl.active = true;
});

viewer.scene.input.on("mousemove", (coords) => {
  // first hit to determine point A
  const hit = viewer.scene.pick({
    canvasPos: coords,
    pickSurface: true,
  });

  if (!hit || !trigger) return;

  // second I use the first hit's normal as direction and worl position as origin
  // this is supposed to pick the point facing the first point A  
  const otherHit = viewer.scene.pick({
    origin: hit.worldPos,
    direction: hit.worldNormal,
    pickSurface: true,
  });

  // annotations to make the hit points clear
  annotations.createAnnotation({
    id: "myAnnotation" + Object.keys(annotations.annotations).length,
    worldPos: hit.worldPos,
    markerShown: true,
    labelShown: true,
    values: {
      glyph: "A",
      title: "My Annotation",
      description: "This is my annotation.",
    },
  });

  if (otherHit) {
    annotations.createAnnotation({
      id: "otherAnnotation" + Object.keys(annotations.annotations).length,
      worldPos: otherHit.worldPos,
      markerShown: true,
      labelShown: true,
      values: {
        glyph: "B",
        title: "My Annotation",
        description: "This is my annotation.",
      },
    });
  }
});

I made a recording of the behavior when I drag my mouse

Expected behavior
I see an annotation A then another annotation B in the opposite direction.

Screenshots

First test: when nothing is facing the first hit point (A), point A is affected making its hit.worldPos null

Second test: when there is a facing wall to the first hit point (A), the first point is wrong but the second is correct (on the roof)

https://imgur.com/a/xfuhefa

Additional context
I'm trying to implement moving models (Sphere in the sketch) while dragging my mouse so I pick first with canvasPos to determine where my mouse is and move the model using model.position = hit.worldPos which moves its center. Then I pick using origin/direction in order to calculate the distance between the center and surface of the model in order to snap it to nearest surface.

demo

xeolabs added a commit that referenced this issue Apr 20, 2024
@xeolabs
Copy link
Member

xeolabs commented Apr 20, 2024

I think this is because the way you're doing Scene.pick() you're reusing the same singleton PickResult that the method always uses, when you don't provide one yourself.

What was happening was that the worldPos on the singleton PickResult was getting modified on each pick. By instantiating a fresh PickResult each time, that won't happen.

Try updating to the latest release and, passing in your own PickResult instance to each pick call, as shown below.

I just exposed PickResult as a class in the latest release, to enable the usage shown below: https://github.com/xeokit/xeokit-sdk/releases/tag/v2.6.0-beta-16

let trigger = false;

    viewer.scene.input.on("mousedown", (coords) => {
        const hit = viewer.scene.pick({
            canvasPos: coords,
            pickSurface: true,
        });

        // trigger to mousemove to start dragging
        if (hit) {
            trigger = true;
            viewer.cameraControl.active = false;
        }
    });

    viewer.scene.input.on("mouseup", () => {
        // trigger to mousemove to stop dragging
        trigger = false;
        viewer.cameraControl.active = true;
    });

    viewer.scene.input.on("mousemove", (coords) => {
        // first hit to determine point A
        const hit = viewer.scene.pick({
            canvasPos: coords,
            pickSurface: true,
        }, new PickResult());

        if (!hit || !trigger || !hit.worldPos) return;

        // second I use the first hit's normal as direction and worl position as origin
        // this is supposed to pick the point facing the first point A
        const otherHit = viewer.scene.pick({
            origin: hit.worldPos,
            direction: hit.worldNormal,
            pickSurface: true,
        }, new PickResult());

        // annotations to make the hit points clear
        annotations.createAnnotation({
            id: "myAnnotation" + Object.keys(annotations.annotations).length,
            worldPos: hit.worldPos,
            markerShown: true,
            labelShown: true,
            values: {
                glyph: "A",
                title: "My Annotation",
                description: "This is my annotation.",
            },
        });

        if (otherHit) {
            annotations.createAnnotation({
                id: "otherAnnotation" + Object.keys(annotations.annotations).length,
                worldPos: otherHit.worldPos,
                markerShown: true,
                labelShown: true,
                values: {
                    glyph: "B",
                    title: "My Annotation",
                    description: "This is my annotation.",
                },
            });
        }
    });

@xeolabs xeolabs closed this as completed Apr 20, 2024
@xeolabs xeolabs changed the title Making consecutive scene.pick calls results in some unpredictible behavior [SUPPORT] Making consecutive scene.pick calls results in some unpredictible behavior Apr 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants