Bug found when using rotateLocal()

OK so i was trying to get my players sword to rotate when clicking the left mouse button…
But when i set the rotation it goes all jittery and doesnt rotate… here is the launch link:
Here is my code:

var Sword = pc.createScript('sword');

// initialize code called once per entity
Sword.prototype.initialize = function() {
    this.app.root.findByName('sword');
};

// update code called every frame
Sword.prototype.update = function(dt) {
    var angle = 90;
    
    if (this.app.keyboard.wasPressed(pc.MOUSEBUTTON_LEFT)) {
        this.angle = 0;
    } else {
        this.angle = 90;
    }
    this.entity.rotateLocal(90,angle,-90);
};

Maybe its because im updating the rotation?

You are rotating it by 90 degrees much EACH frame. Which means you are rotating it 90 degrees at potentially 60fps.

Yes but as you can see i have it rotating only when the mouse is clicked…And i have this.entity.rotateLocal(90,angle,-90); because i think thats where it was supposed to go… but i think i know what you mean im rotating the entiity when i click the mouse and it continually rotates… How do i recall the rotation and stop it? should i move it to the initialize? or move it the if statement?

You misunderstand. Even if it was this.entity.rotateLocal(90,0,-90); it would still be rotating it 90 degrees on the X axis and -90 on the Z axis from it’s current rotation every frame.

rotateLocal doesn’t set the rotation, it rotates the amount you pass it from it’s current rotation.

Ohhhh ok so if i wanted it to rotate like so how i use it? EulerAngles?

It sounds like you just want it to rotate when clicked. Maybe you want to also rotate it back on release?
So just create an onMouseDown function to rotate and an onMouseRelease function to restore back when the button is released.

1 Like

i am not quite sure what u mean: something like this?

LoadSceneOnEvent.prototype.initialize = function(dt) {
    this.app.on(this.listenEventName, this.changeScenes, this);

    this.on('destroy', function() {
        this.app.off(this.listenEventName, this.changeScenes, this);
    });
};
LoadSceneOnEvent.prototype.loadScene = function (name, callback) {
    var app = this.app;
    // Get the path to the scene
    var url = this.app.getSceneUrl(name);
    if (url) {
        // Load the scenes entity hierarchy
        app.loadSceneHierarchy(url, function (err, parent) {
            if (!err) {
                app.loadSceneSettings(url, function (err, parent) {
                    if (!err) {
                        callback(parent);
                    } else {
                        console.error (err);
                    }
                });
                callback(parent);
            } else {
                console.error (err);
            }
        });        
    } else {
        console.log("Can't find scene named: " + name);
    }
};

Where the Event name is called as a event

this.app.on(this.listenEventName, this.changeScenes, this);

then make a function?

LoadSceneOnEvent.prototype.listenEventName

But even if i used the onMouseDown as a function i still dont know how that would help

Well, I maybe shouldn’t jump in since I’m quite the newbie at this, but I made a modification to the picker_raycast script in this little “testing stuff out” project of mine so that the capsule will tilt when clicked and then tilt back when the mouse is released. Just pretend it is a sword. :^)

https://playcanvas.com/editor/scene/689042

In fiddling around with this, I noticed that simply rotating in the negative direction when you have modified more than one angle does not yield intuitive results. So you may want to use setEulerAngles instead.

1 Like

thank you very much this was very helpful :slight_smile:

I didn’t point it out because I started fiddling with it later on, but I added code for rotating the capsule with the right mouse button that lets you tune the timing of the rotation in the Editor. This code uses .update and delta time. I also added code to correct for any overshoot of the desired angles. That overshoot will vary depending on the frame playback rate or dt interval. The interesting thing is that even though I’m specifically setting a whole number value, I never get it when I monitor via the console. I only get something very close like -89.99999999999999 instead of -90. This happens on all the browsers I can test and I’m a bit curious as to why.

1 Like

I am not sure but i can fork the project and look at it

It is just a curiosity that I’d like an answer to if someone happens to know. No need to investigate. I’ve been noticing this for months now and it is a problem easily dealt with. It just seems fundamentally “messy” that the equality isn’t exact. And I don’t like that. :^)

Oh ok well let me know what happens!

It’s to do with how float numbers are represented in memory. They are very rarely exact (eg 0.5 + 0.5 doesn’t equal 1.0) This stack overflow page does a decent job in explaining how it is stored https://stackoverflow.com/questions/7644699/how-are-floating-point-numbers-are-stored-in-memory

Thanks. I figured it was something like that.

But I looked up the conversion and it seems that both “90” and “45” should convert with zero error. Two online converters confirm this and these converters are only using 32 bit float float while Javascript is supposed to be double precisions, using 64 bit float(https://modernweb.com/what-every-javascript-developer-should-know-about-floating-points/ ).
https://www.h-schmidt.net/FloatConverter/IEEE754.html
http://www.binaryconvert.com/result_float.html?decimal=057048

I found a calculator that will convert using 16 bit float and in that case, 90 is not represented as exact 89.984. But it is less exact than what I see in the console.So it doesn’t appear to be either 16 bit floating point or 32 or 64 bit floating point.
(http://weitz.de/ieee/ go to bottom of page to switch to 16 bit conversion).

Even more interesting is that the console returned value of “-89.99999999999999” cannot be stored accurately at 32 bit float but can be stored without error in 64 bit float.
https://baseconvert.com/ieee-754-floating-point

Anyway, to be clear, I’m not trying to be argumentative. It is just a point of curiosity for me.

Note that the number printed to the console may get truncated or rounded to a decimal point.

Sure, but I’m setting a value to 90 exactly. Shouldn’t that number be stored exactly as 90 using floating point 32 or 6? There should be nothing to round. If it were a number that were calculated. Right?

I see your point that there may be more decimal places in a calculated result than can be displayed by the console. And maybe that’s what’s happening since I’m setting a Euler angle. Maybe that actually causes a calculation to be made and what is happening behind the scene isn’t as simple as setting a variable to a value? I’m seeing precision variance in a situation where I’m setting a Euler Angle to -90 or -45

Anyway. Thanks for noodling on it.

Sorry, have I missed something? Are doing

var a = 90;
console.log(a);

And it’s showing 89.99999999?

Or is there some code in-between?

I’m touching up the angle after a series of rotations done in a .update function. There’s always some overshoot and the idea is to reset to a nice even number.This isn’t strictly necessary, but I’ve made it fairly standard when I let a value change in steps like this. I just want to set it back to where it started.

if (this.releaseR_toggle === true && this.capsule.getLocalEulerAngles().x <= -90){
    this.capsule.setLocalEulerAngles(-90.0,0,0);
    this.releaseR_toggle = false;
    console.log ('postUpdate angle fix', this.capsule.getLocalEulerAngles().x);
    console.log ('postUpdate angle fix', this.capAngle.x);
}

Here’s the full project. It is just a project I use for figuring stuff out and I was fiddling in it to help answer the original question on this topic. So it’s kind of a seemingly pointless nonsense project the way it sits. The code is in picker_raycast.js .

https://playcanvas.com/project/598559/overview/object-selection-materials

Note: The only reason I’ve used 90.0 was to see if that affected the console statement. It made no difference.

@wturber - here’s a quick thing to try - can you try holding the mouse down on one of the cubes for about 4 seconds, then release the mouse button without moving the mouse.

It seems like the event sticks, until you then move the mouse again.