three.js 3d models as hyperlink
Asked Answered
A

3

7

I'm trying to figure out a way to use a 3D model created with Three.js as a hyperlink. In other words, if I click on a cube (a THREE.CubeGeometry), I want another page to open.

For instance, in this threejs.org example,

how can I change it, so that instead of making little dots on the boxes, clicking on the boxes would open another page, like a hyperlink?

Alexio answered 11/7, 2014 at 5:40 Comment(2)
Hi Lisa and welcome to SO, this can be achieved with the combination of threejs with some custom javascript, but can you please tell that, the redirect link(hyperlink) will be same for every cube(or object) or will it be differentHierarchize
OMG Shiva! Thanks for the quick response! I would like every cube to be a different link. I just found some info on "tquery" so I'm looking into that voraciously... Although I'm not sure whether I'll understand it fully. haha. Thanks again!Alexio
H
21

One way to achieve it will be to associate custom userData(URL) with every cube while its being created.

So here is a sample code how we can put data in cubes while they are being generated(in jsfiddle similar logic is used between line 25-63)

var object = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({
            color: Math.random() * 0xffffff }));  

object.userData = { URL: "http://stackoverflow.com"};

Now here we use a method called raycasting to detect mouse click, so in principal when the mouse is clicked, we cast a ray(invisible) in the plane perpendicular to the click and we capture all the objects that the ray intersected.

Then we retrieve the first object from the list of intersected objects because that will be near most the screen

ray casting image

To better understand raycasting and object picking refer to this tutorial.

Now while creating the cubes we already inserted the data so we can simply retrieve(URL) it from the intersected cube and redirect the user to that page.

The sample code will be something like this(at line number 95 in the fiddle )

if (intersects.length > 0) {
        window.open(intersects[0].object.userData.URL);
    }

Here us a working jsfille hoping it helps

JSFiddle Link

Hierarchize answered 11/7, 2014 at 7:15 Comment(7)
Shiva! You're a god sent! Thank you sooooooo much! <3!Alexio
@lisa: Thanks for the comment, if the solution solved your query you can accept the answer(by selecting the green tick mark), or else if you have something else you can ask that too. :)Hierarchize
@Hierarchize This is a freaking great answer mate! Thanks for sharing this.Circumferential
@Hierarchize - Hey Shiva, thanks for the great answer! When using this technique intersects[0] is an object with multiple attributes, i.e. distance of the intersection, which face was intersected, etc. However, this is only for the entry point of the ray inside the intersected object. Is there a way to get all the info for the location where the ray exited the object?Whole
@Hierarchize - In other words, how can I get a list of all the intersections of an object with a certain ray?Whole
@Hierarchize - I found the answer here in case you're interested: for meshes, faces must be pointed towards the origin of the ray in order to be detected; intersections of the ray passing through the back of a face will not be detected. To raycast against both faces of an object, you'll want to set the material's side property to THREE.DoubleSide.Whole
Thanks for the example, one question how I open the link on the same window?Luhey
F
0

In this case, 3Dink.js is useful. It is a wrapper library of three.js for WebGL that is enabled to make 3D hyperlinks easily.

In the shortest case, It can realize click and light emission in 3 lines.

DDDINK.addURL(object, "https://www.npmjs.com/package/3dink");
DDDINK.readRendererObj( renderer, scene, camera );
DDDINK.domEvent.addFnc();

Please browse it's repository. https://github.com/takashift/3Dink.js

Fumarole answered 12/6, 2018 at 22:13 Comment(0)
M
-1

You can do it by modifying this function:

function onDocumentMouseDown( event ) {

    // ......

    if ( intersects.length > 0 ) {

        switch(intersects[0].object) {
            case google_object:
                window.open('http://google.com');
                break;
            case yahoo_object:
                window.open('http://yahoo.com');
                break;
        } 

    }

    // ......
}
Mothering answered 11/7, 2014 at 6:21 Comment(3)
hmm, so I tried this and it doesn't seem to work. I'm sure I'm somehow not implementing this correctly...Alexio
Well, since you mentioned tquery, they have an example that looks like just what you want. jeromeetienne.github.io/tquery/plugins/linkify/examplesMothering
yeah, I'll try it out with tquery! I was just thinking that there was probably a really easy solution that I am blind to. Thanks again!Alexio

© 2022 - 2024 — McMap. All rights reserved.