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

reset camera WorldToLocalTransform after add new object to scene #75

Closed
MerlinTwi opened this issue Jan 16, 2013 · 5 comments
Closed

reset camera WorldToLocalTransform after add new object to scene #75

MerlinTwi opened this issue Jan 16, 2013 · 5 comments
Labels

Comments

@MerlinTwi
Copy link
Contributor

branch:dev ed6f953

    public class Main extends MinkoExampleApplication {

        override protected function initializeScene() : void {
            super.initializeScene();

            this.timer = new Timer(1000);
            this.timer.addEventListener(TimerEvent.TIMER, timerEvent);
            this.timer.start();
        }

        private function timerEvent(e:TimerEvent):void {
            // 1. test camera WorldToLocalTransform
            var m1:Matrix4x4 = camera.getWorldToLocalTransform();
            trace('m1', m1.toString());

            // 2. add new object
            scene.addChild(new Mesh(CubeGeometry.cubeGeometry));

            // 3. test camera WorldToLocalTransform
            var m2:Matrix4x4 = camera.getWorldToLocalTransform();
            trace('m2', m2.toString());
        }

        private var timer:Timer;
    }

Output:
m1 [Matrix4x4 (1,-3.7493993930529855e-33,-6.123234262925839e-17,0,0,1,-6.123234262925839e-17,0,6.123234262925839e-17,6.123234262925839e-17,1,0,1.3234889800848443e-23,1.3234889800848443e-23,5,1]
m2 [Matrix4x4 (1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]

@JMLX42
Copy link
Member

JMLX42 commented Jan 16, 2013

Hello and thank you for your report!

This is not a bug: if you don't set the forceUpdate argument to true, ISceneNode.getWorldToLocalTransform() will return the matrix computed to the last batched update.

Now the fact that you add a new mesh will tell the TransformController that the transforms list has to be invalidated. If you don't set forceUpdate to true, the list is indeed rebuilt but the values are not init.

So if you just do:

var m2:Matrix4x4 = camera.getWorldToLocalTransform(true);

It should work fine.

One might argue that invalidating the transforms list should always force an update.
We could also avoid init. this list with blank values and use the existing ones when they make sense.
This is debatable.

Regards,

@JMLX42 JMLX42 closed this as completed Jan 16, 2013
@JMLX42 JMLX42 reopened this Jan 16, 2013
@MerlinTwi
Copy link
Contributor Author

forceUpdate in every call will lead to huge calculations overhead and everything will slowdown to the 2.1 version. And what's the profit of new TransformController in this case?
It seems it must do calculations only when it is necessary.

And I don't understand how adding a new object to scene changing camera's WorldToLocal ?

@JMLX42
Copy link
Member

JMLX42 commented Jan 17, 2013

forceUpdate in every call will lead to huge calculations overhead and everything will slowdown

No: forceUpdate will tell the TransformController to attempt to update the localToWorld of the node.
As you can see in TransformController.updateAncestorsAndSelfLocalToWorld(), we find the "dirtyRoot" of the sub-scene of the node first. If nothing is "dirty", nothing gets updated.

So if you call camera.getWorldToLocalTransform(true) twice (or more) in a row, the second call will do nothing but try to find that dirty root. And that operation's complexity depends on the height of the tree, so it's likely to be painless.

this.timer = new Timer(1000);

Using a timer actually makes it harder for you to see what happens here I guess. If you simply try to get the localToWorld from a node right after it has been added to the scene, you'll notice that it's the identity matrix except when you use forceUpdate = true.

But as you're using a timer here, some frames get rendered before you call camera.getLocalToWorldTransform(). Therefore, as frames get rendered, the localToWorld of the camera is updated by the TransformController and it's perfectly logic it has the right value when you try to read it in your timer.

But that's because the Scene.renderingBegin signal triggered the batched update of the TransformController and hides the fact that the computations are done in a lazy fashion. Always.

And what's the profit of new TransformController in this case?

If the localToWorld doesn't change after you read it then the TransformController will not update it when Scene.renderingBegin is executed. So the TransformController really doesn't do the same computation twice ever.

I don't understand how adding a new object to scene changing camera's WorldToLocal ?

It doesn't.

But adding new objects to a (sub)scene will require to re-build the list of localToWorld transforms stored in the TransformController. Indeed: in order to provide the best performances for a batched update, the controller stores the hierarchy of transforms as a breadth first list. In 99% of the cases, updating this list is less efficient than simply re-building it.

That's where the debatable part is: when this list is built, localToWorld values are init. with the identity matrix. Why ? Because that's how we do it for now :) But again, using forceUpdate = true will update that matrix anyway and it won't cause re-computation if that transform doesn't change afterward. Again this is a choice - a debatable one - but a choice, not a bug or a glitch since it's the expected behavior.

Now, I agree this behavior is neither efficient nor intuitive. Therefore, I've changed TransformController.updateTransformsList() to use the "old" values if they exist:

4ead668

I think this should work without any problem and would give you the result you expected.
Please confirm.

But the localToWorld of the Mesh you add between those two camera.getWorldToLocalTransform() will still be the identity matrix has long as you don't call getLocalToWorld(true) or a frame gets rendered: that's the whole point of "lazy" computations.

Regards,

@MerlinTwi
Copy link
Contributor Author

Please confirm

yes, work without problem.
Next bugreport :)

package {
    import aerys.minko.render.geometry.primitive.CubeGeometry;
    import aerys.minko.scene.node.Mesh;
    import aerys.minko.type.math.Vector4;
    import flash.events.Event;

    public class Main extends MinkoExampleApplication {

        override protected function initializeScene() : void {
            super.initializeScene();

            scene.addChild(new Mesh(CubeGeometry.cubeGeometry));

            _lookAt = new Vector4();
            _position = new Vector4();
        }

        override protected function enterFrameHandler(event : Event) : void
        {
            rotateX += 0.01;

            _position.set(
                _lookAt.x + 5 * Math.sin(rotateX),
                _lookAt.y + 5 * Math.cos(rotateX),
                _lookAt.z
            );

            camera.transform.lookAt(_lookAt, _position, Vector4.Y_AXIS);

            // camera.getWorldToLocalTransform(true);

            super.enterFrameHandler(event);
        }

        private var rotateX:Number = 0;
        private var _lookAt:Vector4;
        private var _position:Vector4;
    }
}

At this example, camera rotating around cube.
If uncomment "camera.getWorldToLocalTransform(true);", camera will stop rotating.

@JMLX42
Copy link
Member

JMLX42 commented Jan 17, 2013

please push this in another issue so that we can mark it as a bug (if relevant) and make sure we can track it properly
thank you!

@JMLX42 JMLX42 closed this as completed Jan 17, 2013
citruslee pushed a commit to CitrusForks/minko that referenced this issue Jan 11, 2023
…oid-cmake-build' into 'master'

Resolve "Change AndroidLogSink.hpp in order to implement Android CMake build."

Closes aerys#75

See merge request aerys/smartshape-engine!75
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants