How can I access the inner THREE components within web-ifc-viewer? - three.js

I'm trying to get access to inner THREE components to be able to change camera positions, add items to the scene, etc. How can I get access to these internal mechanics of THREE from this module? web-ifc-viewer: https://github.com/IFCjs/web-ifc-viewer

You can use ifcViewer.context to get the scene objects from Three.js.
Some other useful properties/ methods
ifcViewer.context.getScene()
ifcViewer.context.items
Hope this is what you're looking for.

Before changing your camera position, you need to disable cameraControls
viewer.context.ifcCamera.cameraControls.enabled = false;

Related

Add an event listener to a particular part of a 3D Object in Three.js

I am having a human body object and what I want is that my code should open a popup whenever I click on any of the specified body parts such as eyes, nose, arms, etc. The object is a single compiled .obj file and I'm unable to figure out as to how should I attach an event listener to the multiple body parts. Any kind of help is much appreciated!
PS: - I am also using orbit controls to handle the zoom and rotation of object.
Thanks in advance..
To solve this issue, it's necessary to design your model in a way such that individual components like arms, eyes etc. are independent 3D objects grouped together to build a more complex asset. This is something you have to ensure during the design phase with a tool like Blender.
In the next step export to glTF instead of OBJ, load the model with THREE.GLTFLoader into your app and then perform a recursive raycasting with the entire asset via:
raycaster.intersectObject( gltf.scene, true, intersects );
By executing this code in a pointermove or pointerdown event listener you can find out whether the user interacts with the model or not.
Notice that three.js has no system to directly assign event listeners to 3D objects. You have to use a different solution like raycasting for this.

How to look to objects using lookAt() with a-frame camera component and look-controls

Goal: I want to create a Web based experience where the user need to see a series of elements on the scene and later, I want to leave the user explore alone.
I have several objects around the scene and I want the camera to look at them one by one. I am using the lookat() method but is not working correctly. I found this example on Threejs:
http://jsfiddle.net/L0rdzbej/135/
But my example is not working like the previous example.
After the answer of #Mugen87 is working but with a little modification:
document.getElementById('cam').sceneEl.camera.lookAt
Access the camera in this way. You can see the example here:
https://glitch.com/~aframe-lookat-cam-not-working
Please click on the button "animate camera".
As mentioned in this thread, you have to remove or disable look-controls if you're overriding camera rotation manually. So you can do:
var cameraEl = document.getElementById('camera');
cameraEl.setAttribute('look-controls', {enabled: false});
to disable the controls, perform your lookAt() operations, and then enable the controls via:
cameraEl.setAttribute('look-controls', {enabled: true})
I finally could make it worked. I am new in Threejs and aframe and surely I don't understand rotation, positions,world coordinates good enough but I think I did a decent work. Here the link:
https://glitch.com/~aframe-lookat-camera-working
I hope will be useful for somebody on the future.

Group of objects on top but added to a camera

As a precision I already noticed threads about this but didn't find a way to achieve exactly what I need.
Basicaly I have a board of objects that I need remaining always on top of everything but also attached to the camera.
I first tried to add the group to the camera and it stayed as wished always in the viewport. But in this configuration the group of objects still be a part of the scene so while zooming to regular objects in the "editor" the board goes into/among these objects of the scene.
My second trial was based on this thread and work wonderfully in order to get all of the board objects rendered above everything. But on such a configuration when rotating around the axis (with orbit control) both scenes rotates. So I tried to update the foreground scene with coordinates of the camera but the update was not immediate and this scene is flickering (I suppose that while rotating the update function is not called immediately).
My best wish would have been to "attach" the foreground scene to the camera so that it would stay on top and sticked on the screen/viewport but I don't even know if it is possible and how to do that (as only groups of objects seem to be capable to be attached to the camera).
I am really stuck on that point. Thanks you for any help!
If this is what you need,
just set object.material.depthTest = false; and object.renderOrder = 1000; for all objects you need to be always on top and attached to the camera.

Three.js within web worker: Simulating animation without rendering to canvas

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);

Mesh Rendering based on distance

Is it somehow possible to filter rendered objects based on distance between camera and object ? I would like to specify that some object can be rendered only from close distance ( like details on complicated meshes etc ). I know i can handle this myself but before that I'm looking if there is any build in solution.
Yes, a feature is available for that. It is called level-of-detail ( LOD ).
See http://threejs.org/examples/webgl_lod.html. Click the mouse to see the effect.
three.js r.62

Resources