Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

THREE.js SphereGeometry Panorama hotspots using DOMElements

I've created a simple WebGL 3D Panorama application using a SphereGeometry, PerspectiveCamera and a CanvasTexture. Now, I'm looking to bring the scene to life by adding "HotSpots" over certain parts of the SphereGeometry. The problem I'm having is understanding how to update the various DOMElements so that their position is reflective of the updated Camera position.

Basically, as the Camera rotates the various DOMElements would move in and out of view relative to the direction the camera is spinning. I tried positioning a <div> absolute to the <canvas> and translating the X and Y position using the returned PerspectiveCamera camera.rotation but it didn't really work; here's my JS & CSS implentation:

CSS

#TestHotSpot {
    /* not sure if using margins is the best method to position hotspot */
    margin-top: 50px;
    margin-left: 50px;
    width: 50px;
    height: 50px;
    background: red;
    position: absolute;
}

JavaScript

/** 
   CONFIG is my stored object variable; it contains the PerspectiveCamera instance 
   code is being called inside of my RequestAnimationFrame
**/

config.camera.updateProjectionMatrix();
config.controls.update(delta);

document.getElementById("TestHotSpot").style.transform = "translate("+ config.camera.rotation.x +"px, "+ config.camera.rotation.y +"px)";

Here is also a live example of the desired effect.

What would be the best solution to fix this problem? What I noticed when I ran this that the DOMElements would only slightly move; I also noticed that they wouldn't really take in account where along the SphereGeometry they were placed (for example, being positioned "behind" the Camera; really complex!

I'm happy to use any plugins for the THREE.js engine as well as follow any tutorials. Thank you so much for replying in advance!

like image 240
lindsay Avatar asked Aug 04 '15 07:08

lindsay


Video Answer


2 Answers

  1. Try to set a planemesh/mesh to the desired point.
  2. Copy the position of the css elements (domElements created with three.js cssObject [if you already know]) along with planemesh/mesh 's position.

And you will be done !!

like image 93
serious_luffy Avatar answered Sep 21 '22 18:09

serious_luffy


Okay, chiming in on my own question! I had a few problems but I've figured out how to get CSS3d mixing in with THREE.js WebGL scenes.

So the first thing I had to do was update my THREE.js Library; I was running 71 from an earlier download but I needed to update it to the library Mr.Doob was using in this example. I also updated my CSS3d library to the file included in that same example.

I then used this method (the same specified in the link) to create a demo scene.

var camera, scene, renderer;

var scene2, renderer2;

var controls;

init();
animate();

function init() {

    camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
    camera.position.set( 200, 200, 200 );

    controls = new THREE.TrackballControls( camera );

    scene = new THREE.Scene();
    scene2 = new THREE.Scene();

    var material = new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, wireframeLinewidth: 1, side: THREE.DoubleSide } );

            //

    for ( var i = 0; i < 10; i ++ ) {

        var element = document.createElement( 'div' );
            element.style.width = '100px';
            element.style.height = '100px';
            element.style.opacity = 0.5;
            element.style.background = new THREE.Color( Math.random() * 0xffffff ).getStyle();

        var object = new THREE.CSS3DObject( element );
            object.position.x = Math.random() * 200 - 100;
            object.position.y = Math.random() * 200 - 100;
            object.position.z = Math.random() * 200 - 100;
            object.rotation.x = Math.random();
            object.rotation.y = Math.random();
            object.rotation.z = Math.random();
            object.scale.x = Math.random() + 0.5;
            object.scale.y = Math.random() + 0.5;
        scene2.add( object );

        var geometry = new THREE.PlaneGeometry( 100, 100 );
        var mesh = new THREE.Mesh( geometry, material );
            mesh.position.copy( object.position );
            mesh.rotation.copy( object.rotation );
            mesh.scale.copy( object.scale );
        scene.add( mesh );

    }

            //

    renderer = new THREE.WebGLRenderer();
    renderer.setClearColor( 0xf0f0f0 );
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );

    renderer2 = new THREE.CSS3DRenderer();
    renderer2.setSize( window.innerWidth, window.innerHeight );
    renderer2.domElement.style.position = 'absolute';
    renderer2.domElement.style.top = 0;
    document.body.appendChild( renderer2.domElement );

}

function animate() {

    requestAnimationFrame( animate );

    controls.update();

    renderer.render( scene, camera );
    renderer2.render( scene2, camera );

}

After I had that working, I re-purposed the CSS3d scene, CSS3d object and the CSS3d renderer to be included in my scene.

Good luck to anyone else and hopefully this helps!

like image 31
lindsay Avatar answered Sep 19 '22 18:09

lindsay