Forum

m_trans.set_matrix does not respect linear algebra.

18 March 2018 18:16
I tried to scale an object on a specific dimension with the set_matrix function from the transform module. Here is an example transformation matrix.:

a 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

where a is 0.1

Expectation: It should be scaled to 0.1 on X,.

transformation.png
Left is the original cube, the right is transformed with the matrix as defined above.

Result: was scaled down approximately 0.8 on X, Y and Z.

then I assigned different values to a, and find two anomalies.

  • The transformation is not linear.
  • and happens on all 3D axes. (it should be carried out only on X)

The funniest case when a is freakin' zero, because in this setting the transformation matrix spans only to 2 dimensions, which should collapse the cube to a square… well it makes it a slightly smaller cube, but at least collapsed my mind to the null space, which is something.

I made a self contained example in a project , extract it into your project folder:

Download: link

I changed two things on the b4w starter file:
  • Reseted the cube transformation to the identity. (it is translated on Z by 1 on default scene )
  • turned on the physics on the cube object, so it can be transformed.


and wrote a very simple, commented code, which reproduces what I described…

Extra: You can update the transformation matrix of the cube from the inspector, using the updateMat(ind, val), function, for example:
updateMat(12, 1) will translate the cube 1 unit on x.
updateMat(5, 0.01) will scale the cube to 1/100 on… oh wait it will not.

My environment:
NixOS 17.09 “Hummingbird” (GNU/Linux)
Blender 2.79a
Blend4Web 17.12.0
19 March 2018 13:03
In the next release we will add axes-aligned non-uniform scale. Currently only uniform scale is supported.
Alexander (Blend4Web Team)
twitter
19 March 2018 15:24
Thanks, you saved me a lot of time , it is bit of surprise though, since Blend4Web is so feature rich.

Regardless I was able to solve this problem by using set_frame from the animation module. Basically I created a scale animation on X, and the code interpolates between its frames as the window resizes to a new ratio.

the relevant code snippet:

function registerSliderResize(railObj, knobObj, frameNum) {

    var etalonRatio = 16 / 9;

    function resize() {

      var ratio = window.innerWidth / window.innerHeight;
      var frameInd = Math.floor(ratio / etalonRatio * frameNum);

      if (frameInd > frameNum)
        frameInd = frameNum;
      else if (frameInd < 1)
        frameInd = 1;

      // invert frameInd
      frameInd = frameNum - frameInd;

      m_anim.apply(railObj, "rail-resize", m_anim.SLOT_0);
      m_anim.set_behavior(railObj, m_anim.AB_FINISH_STOP, m_anim.SLOT_0);
      m_anim.play(railObj, null, m_anim.SLOT_0);
      console.log(frameInd);
      m_anim.set_frame(railObj, frameInd, m_anim.SLOT_0);
      m_anim.stop(railObj, m_anim.SLOT_0);

      m_anim.apply(knobObj, "knob-resize", m_anim.SLOT_0);
      m_anim.set_behavior(railObj, m_anim.AB_FINISH_STOP, m_anim.SLOT_0);
      m_anim.play(railObj, null, m_anim.SLOT_0);
      console.log(frameInd);
      m_anim.set_frame(railObj, frameInd, m_anim.SLOT_0);
      m_anim.stop(railObj, m_anim.SLOT_0);
    };

    resize();

    window.addEventListener("resize", resize);

  }
22 March 2018 00:31
Regardless I was able to solve this problem by using set_frame from the animation module. Basically I created a scale animation on X, and the code interpolates between its frames as the window resizes to a new ratio.
Shape keys are also option for such cases.
Alexander (Blend4Web Team)
twitter
 
Please register or log in to leave a reply.