I have a complex web application, with several sub-views / widgets that add objects to the main scene.
Most simple THREE.js examples have a continous render loop, that re-renders the scene periodically.
This seems like a waste of ressources to me.
Therfore, I only want to re-render the scene if something has changed.
However, the sub-views / widgets do change things (like position of objects) in the scene on their own.
Is there something like a "scene.hasChanged" flag, that I can use to deceide if the scene needs to be rerendered? Or do I have to implement a parallel flag or notification structure myself?
Or is there another common solution to this?
Based on what you have written so far, it seems you have to implement a custom solution. Certain three.js examples like webgl_loader_gltf do not use an animation loop but utilize change events from the controls. The relevant line of code is
controls.addEventListener( 'change', render );
However, if more factors than just the user interaction trigger renderings, it's necessary to build some sort of notification/event system by yourself.
three.js R113
I have a "cover" image for the top of one of my views that i'd love to be able to blur out as you scroll it out of view as a cool effect.
My state contains a blurRadius property, which i am binding to the blurRadius={this.state.blurRadius} prop on my <Image> component.
I have a <ScrollView> and am monitoring when it's scrolled with onScroll, where i am calling setState({blurRadius: value}) - value being the distance that you've scrolled the view.
I've also set the scrollEventThrottle={30} prop on the scrollview so that i'm receiving the event regularly as the user scrolls.
The issue seems to be that the blurRadius updates but after a significant delay - and only to the maximum value. Am i missing something in order to make the image apply the new blurRadius with every call of setState?
Could it be that the image is just too large?
You should not use setState to set anything as a response to onScroll, as this leads to poor performance. The reason is that the whole view will rerender for every call to setState, which leads to "view thrashing".
Instead, you should use the Animated API, as this 'declares' the animation to the native UI thread, thus avoiding rerenders.
Brent Vatne (from the Expo team) gives a great explanation of Animated as well as a concrete example of animations as a response to onScroll events in ScrollView here
Hope it helps someone :-)
You can try using setNativeProps instead of setState to see if the performance improves. You just need to give your Image a ref.
this.refs.myImage.setNativeProps({ blurRadius: myValue });
Reducing the image size would also help as it would not need to blur as many pixels.
I have a hypothetical question:
Is it possible to simulate an animation of objects without rendering it to the canvas. I just want to capture objects' position using Vector.project(camera) and present it using CSS. And THREE.DeviceOrientationControls controls how the camera "view" the simulation.
I tried commenting THREE.WebGLRenderer, but it seems that THREE.PerpectiveCamera cannot update it's MatrixWorld property. Hence, the camera seems to not move and the Vector.project(camera) gives a static value. I do this because I need to put my three.js codes within a web worker.
Do I need still need to use THREE.WebGLRenderer to have a working simulation?
UPDATE:
I checked the following:
I digged deeper into ((three.scene.getObjectByName("one")).matrixWorld.getPosition()).project(three.camera);, I inspect the following values, having the above requirement (inside web worker, no renderer), using this example:
matrix: {"elements":{"0":3.2167603969573975,"1":0,"2":0,"3":0,"4":0,"5":2.1445069313049316,"6":0,"7":0,"8":0,"9":0,"10":-1.000100016593933,"11":-1,"12":5.4684929847717285,"13":2.1445069313049316,"14":-0.2000100016593933,"15":0}}
camera.projectionMatrix: {"elements":{"0":3.2167603969573975,"1":0,"2":0,"3":0,"4":0,"5":2.1445069313049316,"6":0,"7":0,"8":0,"9":0,"10":-1.000100016593933,"11":-1,"12":0,"13":0,"14":-0.2000100016593933,"15":0}}
camera.matrixWorld: {"elements":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":1,"6":0,"7":0,"8":0,"9":0,"10":1,"11":0,"12":-1.7000000476837158,"13":-1,"14":0,"15":1}}
matrix.getInverse(camera.matrixWorld): {"elements":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":1,"6":0,"7":0,"8":0,"9":0,"10":1,"11":0,"12":1.7000000476837158,"13":1,"14":0,"15":1}}
matrix.multiplyMatrices(camera.projectionMatrix, matrix.getInverse(camera.matrixWorld)): {"elements":{"0":3.2167603969573975,"1":0,"2":0,"3":0,"4":0,"5":2.1445069313049316,"6":0,"7":0,"8":0,"9":0,"10":-1.000100016593933,"11":-1,"12":5.4684929847717285,"13":2.1445069313049316,"14":-0.2000100016593933,"15":0}}
But, when normal (no modification), I inspect the following:
matrix: {"elements":{"0":3.2167603969573975,"1":0,"2":0,"3":0,"4":0,"5":2.1445069313049316,"6":0,"7":0,"8":0,"9":0,"10":-1.000100016593933,"11":-1,"12":5.4684929847717285,"13":2.1445069313049316,"14":-0.2000100016593933,"15":0}}
camera.projectionMatrix: {"elements":{"0":3.2167603969573975,"1":0,"2":0,"3":0,"4":0,"5":2.1445069313049316,"6":0,"7":0,"8":0,"9":0,"10":-1.000100016593933,"11":-1,"12":0,"13":0,"14":-0.2000100016593933,"15":0}}
camera.matrixWorld: {"elements":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":-2.220446049250313e-16,"6":-1,"7":0,"8":0,"9":1,"10":-2.220446049250313e-16,"11":0,"12":-1.7000000476837158,"13":-1,"14":0,"15":1}}
matrix.getInverse(camera.matrixWorld): {"elements":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":-2.220446049250313e-16,"6":1,"7":0,"8":0,"9":-1,"10":-2.220446049250313e-16,"11":0,"12":1.7000000476837158,"13":-2.220446049250313e-16,"14":1,"15":1}}
matrix.multiplyMatrices(camera.projectionMatrix, matrix.getInverse(camera.matrixWorld)): {"elements":{"0":3.2167603969573975,"1":0,"2":0,"3":0,"4":0,"5":-4.761761943205948e-16,"6":-1.000100016593933,"7":-1,"8":0,"9":-2.1445069313049316,"10":2.2206681307011713e-16,"11":2.220446049250313e-16,"12":5.4684929847717285,"13":-4.761761943205948e-16,"14":-1.2001099586486816,"15":-1}}
I noticed that the camera.matrixWorld property has significant difference in both condition. I do not understand what makes the difference.
Apparently, the following lines from THREE.WebGLRenderer.render are still needed to update camera.matrixWorld property:
scene.updateMatrixWorld();
camera.updateMatrixWorld();
camera.matrixWorldInverse.getInverse(vs._3.camera.matrixWorld);
If I wanted to, using Qt, simply have some circles move around in a white box, or a graphic, what would be the best method of this?
Would I need to draw white/the graphic behind where the circle moved from every time? Is there a simple way of accomplishing this in Qt?
Create QGraphicsView object to your widget and added a QGraphicsScene to view.
Add a QGraphicsEllipseItem to scene
Use QPropertyAnimation to change the "pos" property of the ellipse item.
If you need more advanced features, you can build your own animation class on QPropertyAnimation.
enjoy it:)
Update: You can read Qt's Next Generation UI for more information.
Subclass a QWidget. Start a timerEvent() to animate the positions of the circles, then call update() at the end to schedule a repaint of the widget. Override the widget's paintEvent() - in there you draw your background and circles, using a QPainter object. The Qt Assistant has examples of how to use QPainter.
Qt also has a new animation framework that may facilitate something like this, but I have not looked into it.