fcor / arjs-gestures

Rotate and zoom with touch gestures on any Image tracking or Marker Based AR.js scene
MIT License
162 stars 97 forks source link

Customise scaling of height and width #14

Closed Zian00 closed 3 years ago

Zian00 commented 3 years ago

Hi, I was wondering if we can do customise scaling of the height and width for the 3d model indivdually, i have tried adding threefingermove and fourfingermove for customising the width and height respectively. However, it seems like not working due to the scaling calculation for the change of model size.

This is the part for the init:

init: function () {
    this.customScaleHorizontal = this.customScaleHorizontal.bind(this);
    this.customScaleVertical = this.customScaleVertical.bind(this);
    this.handleScale = this.handleScale.bind(this);
    this.handleRotation = this.handleRotation.bind(this);

    this.initialScale = this.el.object3D.scale.clone();
    this.scaleFactor = 1;
  },

This is the part for updating the eventlistener:

update: function () {
    if (this.data.enabled) {
        this.el.sceneEl.addEventListener("onefingermove", this.handleRotation);
        this.el.sceneEl.addEventListener("twofingermove", this.handleScale);
        this.el.sceneEl.addEventListener("threefingermove", this.customScaleHorizontal);
        this.el.sceneEl.addEventListener("fourfingermove",this.customScaleVertical);

    } else {

        this.el.sceneEl.removeEventListener("onefingermove", this.handleRotation);
        this.el.sceneEl.removeEventListener("twofingermove", this.handleScale);
        this.el.sceneEl.removeEventListener("threefingermove", this.customScaleHorizontal);
        this.el.sceneEl.removeEventListener("fourfingermove", this.customScaleVertical);

    }
  },

This is the part for removing the eventlistener:

remove: function () {
    this.el.sceneEl.removeEventListener("onefingermove", this.handleRotation);
    this.el.sceneEl.removeEventListener("twofingermove", this.handleScale);
    this.el.sceneEl.removeEventListener("threefingermove", this.customScaleHorizontal);
    this.el.sceneEl.removeEventListener("fourfingermove", this.customScaleVertical);

  },

This is the part for customizing the width:

customScaleHorizontal: function (event) {
     this.scaleFactor *=
      1 + event.detail.spreadChange / event.detail.startSpread;

    this.scaleFactor = Math.min(
       Math.max(this.scaleFactor, this.data.minScale),
       this.data.maxScale
     );

    this.el.object3D.scale.x = this.scaleFactor * this.initialScale.x;
    this.el.object3D.scale.y = this.el.object3D.scale.y;
    this.el.object3D.scale.z = this.el.object3D.scale.z;

   },

This is the part for customizing the height:

customScaleVertical: function (event) {
      this.scaleFactor *=
        1 + event.detail.spreadChange / event.detail.startSpread;

      this.scaleFactor = Math.min(
        Math.max(this.scaleFactor, this.data.minScale),
        this.data.maxScale
      );

      this.el.object3D.scale.x = this.el.object3D.scale.x;
      this.el.object3D.scale.y = this.scaleFactor * this.initialScale.y;
      this.el.object3D.scale.z = this.el.object3D.scale.z;
    },

And this is the only part i have changed for gesture-detector part:

getEventPrefix(touchCount) {
        const numberNames = ["one", "two", "three", "four"];

        return numberNames[Math.min(touchCount, 4) - 1];
    }

I'm not sure whether is my logic wrong or what, please help me. Thank you!

fcor commented 3 years ago

Hi! Sorry for my late response. Did you check if three and four finger events were triggered? What are the results right now? Keep in mind that you could see some weird results if you scale a model on just one axis, and also you should double check which is the axis that corresponds to width and which one corresponds to height since it depends on the marker orientation (this happens to me all the time).

Let me know if you managed to solve it :)

Zian00 commented 3 years ago

Hi fcor, thanks for your reply. Three and four finger events are triggered, but they are kind of too sensitive.

this.el.object3D.scale.x = this.scaleFactor * this.initialScale.x; Due to the above line of code, whenever i scales its x-axis, it would recalculate from the initial scale of x, instead of the currently value of x, so i was wondering how to continue scaling from current x, instead of initial x.

I have tried this.el.object3D.scale.x = this.scaleFactor * this.el.object3D.scale.x;, however it would increase or decrease the x extremely to too oversized or disappear respectively.

I was wondering if there's a way to calculate the current value of x?

thanks in advance .

fcor commented 3 years ago

You are calculating the current value of x correctly: this.el.object3D.scale.x. Could you try adding the scale factor instead of multiplying it? At least this whay it will always increase x by the same value on each iteration. I'm not sure how good it will be but worth trying :)

Other option could be reducing the impact of finger movement on the scale factor, which could be different depending on how many fingers you use for the gesture event. Something like this.scaleFactor *= 1 + (event.detail.spreadChange/event.detail.startSpread) * 0.5;.

I think the issue with using the current x value is that if we multiply it by some factor, it will increase or decrease too fast since gesture events are too sensitive and could run multiple times for a single touch.

Finally, just in case you want to dig deeper, in three.js scale is a Vector3, so you have acces to all this properties/functions: https://threejs.org/docs/#api/en/math/Vector3

Hope this helps!

Zian00 commented 3 years ago

Thanks a lot man!

Just wondering, as the 8th wall demo has the hold and drag model component and I know that their demo doesnt require a marker. If i want to adapt that to your code, is it do-able? and how could i achieve that ?

Thanks in advance.

fcor commented 3 years ago

Hi!

Unfortunately that is not compatible yet with AR.js :(

Take a look at model-viewer, on WebXR compatible phones AR mode it works pretty well.

Zian00 commented 3 years ago

Hi, thanks for your fast reply!

May i know which model-viewer are you referring to ? could you link me the url ? Thanks a lot man.

fcor commented 3 years ago

This one: https://modelviewer.dev/

Hope it helps