Add marker on mouse click on a 3D cube

Hi, I am brand new to three js and trying to implement a 3D cube on my webpage using the three js library. When I click on the surface of the cube, a marker should be placed at that mouse click position. I tried the following code, but it is not working as desired. Any help will be greatly appreciated. Thanks!

My code:

        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000);

        var renderer = new THREE.WebGLRenderer({ alpha: true });
        renderer.setClearColor(0x000000, 0); 
        renderer.setSize(window.innerWidth / 1.5, window.innerHeight / 1.5);

        window.addEventListener('resize', function () {
            var width = window.innerWidth;
            var height = window.innerHeight;
            renderer.setSize(width, height);
            camera.aspect = width / height;
            camera.updateProjectionMatrix();
        });

        renderer.domElement.addEventListener("dblclick", ondblclick, false)
        controls = new THREE.OrbitControls(camera, renderer.domElement);
        
        //create canvas for marker
        var bitmap = document.createElement('canvas');
        var g = bitmap.getContext('2d');
        bitmap.width = 200;
        bitmap.height = 200;
        
        // canvas contents will be used for a texture
        var texture = new THREE.Texture(bitmap) 

         // create a marker   
        function changeCanvas(x, y) {
            g.font = '20px Arial';
            g.fillStyle = 'red';
            g.fillText('★', x, y);
            g.strokeStyle = 'black';
            g.strokeText('★', x, y);
            texture.needsUpdate = true;
        }

        function ondblclick(event) {
            x = (event.clientX / window.innerWidth) * 2 - 1;
            y = -(event.clientY / window.innerHeight) * 2 + 1;

            var dir = new THREE.Vector3(x, y, -1)
            dir.unproject(camera)
        
            var ray = new THREE.Raycaster(camera.position, dir.sub(camera.position).normalize())
            var intersects = ray.intersectObject(cube);

            if ( intersects.length > 0 ) {
                alert("Mark with ★");               
                const x1 = event.offsetX;
                const y1 = event.offsetY;             
                changeCanvas(x1, y1);
            }
        }

        var geometry = new THREE.BoxGeometry(2, 1, 0.5);
        var material = new THREE.MeshBasicMaterial({map : texture, color: 0xC0C0C0, wireframe: false});
        var cube = new THREE.Mesh(geometry, material);
        scene.add(cube);

        // wireframe for cube border
        var geo = new THREE.EdgesGeometry(cube.geometry);
        var mat = new THREE.LineBasicMaterial({ color: 0x000000, linewidth: 10 });
        var wireframe = new THREE.LineSegments(geo, mat);
        wireframe.renderOrder = 1; // make sure wireframes are rendered 2nd
        cube.add(wireframe);

        camera.position.z = 3;

        var render = function () {
            renderer.render(scene, camera);
        };

        var GameLoop = function () {
            requestAnimationFrame(GameLoop);
            render();
        };

        GameLoop();

Hi!

More details about what and how is not working?

Instead of

var dir = new THREE.Vector3(x, y, -1)
dir.unproject(camera)
        
var ray = new THREE.Raycaster(camera.position, dir.sub(camera.position).normalize())
            

maybe this will help

var mouse = new THREE.Vector2(x, y);
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);

Though I would re-use instances of mouse and raycaster, how it’s shown in the docs, for example: three.js docs

1 Like

Thanks for your response… I am practically trying to put a marker/sprite at the position of mouse click, but currently not able to do so as I have no idea how to place a marker on a 3D cube… can you please help! Thanks!

Check this fiddle: https://jsfiddle.net/prisoner849/x6fubr9t/
Double click sets a marker on a cube :slight_smile:

2 Likes

Really appreciate such a quick response!
Let me try this one and I will get back soon… :slight_smile:

I simply made it right after my first reply in this thread :smiley:

1 Like

And if you want something more complicated, @prisoner849 has also prepared something.

In the Collection of examples from discourse.threejs.org you will find in the year 2018
SetRemoveMarkers

From author @vasilii helped by @Mugen87 there is a matching sphere.
https://hofk.de/main/discourse.threejs/2018/LabelsOnSphere/LabelsOnSphere.html

Links to the posts in source code.

2 Likes

I can see that in the fiddle it is working perfectly, but in my local browser the marker gets placed not at the exact point of double click, but gets shifted somewhat right of the click. So, when i click at the rightmost side of the cube, I can see no marker at all as it goes outside the cube… Can I make myself clear, or is it confusing? How can I fix this issue?
Thanks for all your help!

@alokparna-wsu The best way is to show your whole project, as it seems that the problem comes from the positioning of renderer’s canvas.
Maybe this post will be helpful with setting mouse vector: Select an object using mouse click
And this topic: Raycaster fails hit test

1 Like