How to efficiently rotate an env map used in an IBL pipeline? - three.js

I use an equirectangular EXR image to light my scenes. To achieve this, I re-used the code found in this threejs example. This works as expected.
Now, I want users to be able to rotate this map around the vertical axis in real time.
After looking at the code of the loader EquirectangularToCubeGenerator.js, I figured out that I could rotate the boxMesh around the Y-axis using this simple code:
var radRotation = Math.PI;
this.boxMesh.rotateY(radRotation);
That works OK for a set angle however it doesn't work for angles changing in real time. It is too slow as it reloads the texture and goes through the generation process for every new value.
Is there a simple and fast way to change the rotation for an environment map already generated?
Thank you for your help.

Related

Three.js sprite sheet offsets in THREE.Points

I'm trying to get a sprite sheet texture in THREE.PointsMaterial to use offsets, so point particles can have different visuals.
Apparently this should be possible using THREE.ShaderMaterial, instead of PointsMaterial.
This answer seems to get so close to my solution, but the fiddle is broken and I'm having a hard time reconstructing it.
Shaders are new to me and I could use some help achieving the goal: get point particles to use different sections of a sprite sheet.
With a single image texture it's easy, like this, but trying to use a sprite sheet with offsets is killing me ;)

How to prevent culling or simply redraw on iTowns globe rotation outside of mouse, touch or key events?

I'm attempting to rotate the "globe" in iTowns in real time by adding a frame requester (in three.js this would be the requestAnimationFrame loop).
I am attempting to use iTowns to provide a real time 3D earth map simulation. As part of this I have an interval firing every second and playhead controls to manipulate time. I'm trying to rotate an earth representation along the z-axis because in iTowns that is the polar axis. I need to check the time every frame because I can calculate the earth rotation in radians/sec quite easily and as I manipulate the playhead to speed up time I can get a fluidly rotating earth. Also I'm utilizing the default Ortho layer provided in iTowns to add a geographic layer on top of the blue marble default.
// this.view is an iTowns/src/Core/Prefab/GlobeView
const globeLayer = this.view.getLayerById("globe");
const globe = globeLayer.object3d;
this.view.addFrameRequester(MAIN_LOOP_EVENTS.UPDATE_START, () => {
globe.rotation.z = ConversionUtils.toRadians(this.globals.getSceneRotation());
});
The globe rotates, however I believe iTowns is performing some sort of culling of the map tiles/globe. What happens is at some point as the earth rotation is taking place a portion of the globe no longer renders. If this was related to the Ortho layer I believe the blue marble would still show. We have another version of the application without any iTowns and we can rotate a Three.js SphereGeometry without any culling using the same mechanics; so I am 99% sure it is not an issue with Three.js unless iTowns is doing something I don't see.
How do I prevent the culling, which I see is documented as an optimization? Better yet, how can I tell it to redraw properly?
I've tried the following but to no apparent effect:
this.view.notifyChange(globeLayer, true);
this.view.notifyChange(undefined, true);
this.view.notifyChange(this.view.controls.camera, true);
globe.updateMatrixWorld(true);
There is "culling" logic in:
- iTowns/src/Core/Prefab/GlobeLayer.js
- iTowns/src/Layer/TiledGeometryLayer.js
This is invoked from iTowns/src/Core/MainLoop.js. Bubbling up to the method scheduleViewUpdate which is invoked on iTowns/src/Core/View.js notifyChange.
Further digging leads me to believe iTowns/src/Controls/GlobeControls.js, specifically the cameraTarget attribute that I can't manipulate, is either the answer or is related.
I am hoping I am missing something and there is a way to code this up. Alternatively, I realize the suggestion may be fork or PR iTowns.
It is worth noting I do not want to change the camera position, just rotate the globe because there are other objects also moving in the scene i.e. satellites in orbit.

Set a Maximum Range for Face Rendering in AFrame scene

i got a Scene which loads a very large .obj File (a lot of faces), this results in low fps ...
I want to set a maximum distance from camera where faces should be rendered.
So far i only tried to use the fog component, which does not what i expected...
Anyone got a idea ?
I believe you can achieve this by a THREE.PerspectiveCamera property called far which determines the camera frustum far plane.
You can check it out in the docs. It can be easily set it like this:
let scene = document.querySelector("a-scene")
scene.camera.far = 3 // default is 1000 afaik
Check it out in this fiddle (move around a bit).
Here i threw it into an aframe component.

Threejs - Detect canvas limits in the camera world

Is there a way to determine the max / min values for height and width in the threejs coordinate system?
I'm (kinda) aware of the Frustum / Projection matrix thing, but I can't quite see the whole picture, I'd be glad if someone could illuminate me on this, with some practical example, since I'm pretty new to all this and I'm struggling a little to get my head around it.
The first think that came to my head to solve this problem was to create a mesh and use it as a dummy to detect the boundaries of the canvas, but I was wondering if it would be a more convenient way to achieve this.
Just FYI I need this for a script that should draw a 2d grid of lines, with a fixed camera.

How to rotate Decal over more then one axis at moment

I'm working on Libdx app using Decals.
Decals are 2d sprites in 3d world.
I have problem that when I say:
decal.setRotationX(angle)
everything works fine, but when I say:
decal.setRotationX(angle);
decal.setRotationY(angle2);
The decal rotates over Y axis only.
How to manage that problem?
I have found that Decal in source code uses Quaternion for rotation, but currently I don't know how to customize that to face my requirements.
Tnx in advance!
EDIT:
I have managed to rotate decal around multiple axis with:
decal.getRotation().setEulerAngles(yaw,pitch,roll);
Now my question is how to animate this with TweenEngine?
In get values method I have:
returnValues[0] = target.getRotation().getYaw();
returnValues[1] = target.getRotation().getPitch();
returnValues[2] = target.getRotation().getRoll();
In set values method I have:
target.getRotation().setEulerAngles(newValues[0], newValues[1],
newValues[2]);
But decal is not moving or animating, it's stucked in one position (slightly rotated over XYZ axis).
Any idea, values in TweenEngine are correct but somehow decal is not refreshing and rotating.
If you want to do it only once, you can do it like this:
decal.rotateX(angleX);
decal.rotateY(angleY);
decal.rotateZ(angleZ);
This will "add" the given angle to the current one though.
An alternative way would be to use the rotation Quaternion of the Decal:
decal.getRotation().setEulerAngles(yaw, pitch, roll);
The following image shows what "yaw", "pitch" and "roll" means:
Roll, pitch, yaw http://i.msdn.microsoft.com/dynimg/IC79189.gif
EDIT: I've just seen the JavaDoc of Decal.getRotation() and it says that the returned quaternion should not be modified! I've also checked the code and every other method of Decal sets an internal update flag which will cause the decal to change the next time it's rendered. Decal.getRotation() does not set this flag and thus the changes to it won't get recognized.
It seems like currently there is no really clean and easy way to set the rotation on all three axes at the same time. A workaround might look like this:
decal.setRotationX(0);
decal.setRotationY(0);
decal.setRotationZ(0);
decal.rotateX(angleX);
decal.rotateY(angleY);
decal.rotateZ(angleZ);
It first resets all angles to 0 and then rotates on each axis while not overwriting any other axis.

Resources