Search code examples
javascriptthree.js360-panorama

Three.js: Add Image to Texture Bottom in 6 Cube Panorama as a Hotspot


I am using this panorama as a base for my project. Now I want to add a small image (circle) to the bottom of one chosen texture as if this is a hotspot on the panorama floor that will respond to user click. Please see the image below with 2 circles on the floor:

enter image description here

I tried the following code to add image to one of 6 textures in panorama:

var loader = new THREE.TextureLoader();
loader.load('img/test-circle-sample.png', function ( texture ) {
    var geometry = new THREE.PlaneGeometry( 1, 1 );
    var material = new THREE.MeshBasicMaterial( { map : texture, opacity : 1, side : THREE.DoubleSide, transparent : true } );
    var sprite = new THREE.Mesh( geometry, material );
    scene.add(sprite);
});

While it seems to actually load the image, the circle is far from looking like on the picture above. It is very wide, even though its size is 256 pixels and is positioned around the camera - you can see it on very top, bottom, sides, but not in front of you as a small circle. I played around with these settings but they did not work well:

sprite.position.set(0,-360,0);
sprite.rotateOnAxis(  new THREE.Vector3( 1, 0, 0 ), THREE.Math.degToRad(90) );
sprite.scale.set( 1, 1, 1 );

I need help with positioning the image in front of camera for any chosen side (or angle) and keep it stuck to the floor, so dragging camera would adjust how this image looks (skewed effect based on angle).

Update: I created this Plunker but image now not seen at all. http://plnkr.co/edit/KS6dVMn5AIEaXr143Jv3?p=preview


Solution

  • I am not sure I understand your question - as I understand, you want the hot spot to be placed below the camera (ie at the viewers feet)? If so, it seems you're transforming the hot spot incorrectly, which may be the reason it appears warped.

    I took a copy of your live demo at http://plnkr.co/edit/KS6dVMn5AIEaXr143Jv3?p=preview and made some alterations to get the hot spot to display correctly.

    Try and update the way you transform and rotate your hot spot, as shown in the following code:

    function addHotSpot(scene){
    
        THREE.ImageUtils.crossOrigin = '';
        var loader = new THREE.TextureLoader();
        loader.load('https://i.imgur.com/vU163P4.png', function ( texture ) {
            var geometry = new THREE.PlaneGeometry( 1, 1 );
            var material = new THREE.MeshBasicMaterial( { 
                map:texture, 
                opacity : 1, 
                side : THREE.DoubleSide, 
                transparent : false  // Note, I also set this to false.
            } ); 
    
            var sprite = new THREE.Mesh( geometry, material );
    
    
            // Offset the hotspot so it is below the view origin [Updated]
            sprite.position.set(0,-5,5);
    
            // Compute the rotation for the hotspot, 90deg around the x-axis
            var rotation = new THREE.Matrix4()
            .makeRotationAxis(new THREE.Vector3(1,0,0), 1.57);
    
            // Apply rotation to the hotspot so it "sits flat below the camera"
            sprite.rotation.setFromRotationMatrix(rotation);
    
            scene.add(sprite);
        });
    }