0
votes

I'm trying to use THREE.js and been looking at some examples, Voxel Painter exmaple

I'm trying to get it so that every time you click to create a new cube the roll over mesh will always move on top of the cube just pasted rather than being at the point of intersecting of the current mouse position...

All of the source code can be viewed from the link but I believe what I'm trying to do has something to do with this...

You click the mouse to add a Voxel, when onMouseDown() function is active it will check if current mouse position is intersecting with the plane and if CTRL button has been pressed for either a new cube or delete a cube.

function onDocumentMouseDown( event ) {

    event.preventDefault();

    var intersects = raycaster.intersectObjects( scene.children );
    
    if ( intersects.length > 0 ) {

        intersector = getRealIntersector( intersects );

        // delete cube

            if ( isCtrlDown ) {

                if ( intersector.object != plane ) {

                    scene.remove( intersector.object );

            }

    } 
// create cube
else {



intersector = getRealIntersector( intersects);
        
setVoxelPosition( intersector );
                    
var voxel = new THREE.Mesh( cubeGeo, cubeMaterial );
voxel.position.copy( voxelPosition );    
voxel.matrixAutoUpdate = false;
voxel.updateMatrix();
             
scene.add( voxel );
                     
                 
}

}    
}

When creating a new cube I believe THREE.js grabs the current point where the mouse intersects intersector = getRealIntersector( intersects); and then sets the new Voxel position with the function setVoxelPosition( intersector ); with the intersect point being passed in.

This is the setVoxelPosition function

function setVoxelPosition( intersector ) {

      normalMatrix.getNormalMatrix( intersector.object.matrixWorld );

      tmpVec.copy( intersector.face.normal );
      tmpVec.applyMatrix3( normalMatrix ).normalize();

      voxelPosition.addVectors( intersector.point, tmpVec );

      voxelPosition.x = Math.floor( voxelPosition.x / 50 ) * 50 + 25;
      voxelPosition.y = Math.floor( voxelPosition.y / 50 ) * 50 + 25;
      voxelPosition.z = Math.floor( voxelPosition.z / 50 ) * 50 + 25;
}

and the render loop

function render() {

    if ( isShiftDown )
    theta += mouse2D.x * 1.5;

    raycaster = projector.pickingRay( mouse2D.clone(), camera )
    var intersects = raycaster.intersectObjects( scene.children );
            
            
    if ( intersects.length > 0 ) {

    intersector = getRealIntersector( intersects );
    if ( intersector ) {

        setVoxelPosition( intersector );
        rollOverMesh.position = voxelPosition;
                    
        }

    } 
camera.position.x = 1400 * Math.sin( THREE.Math.degToRad( theta ) );
camera.position.z = 1400 * Math.cos( THREE.Math.degToRad( theta ) );

camera.lookAt( scene.position );

renderer.render( scene, camera );

}

I have tried to pass in different values into setVoxelPosition( intersector ) but I can't seem to get it right..

Could someone please point me in the right direction?

Thanks.

1

1 Answers

1
votes

There are several ways of doing this. I'm not going to sugar coat this answer because frankly, reverse engineering this code will do you some good. I will say, having worked with this voxel code myself, it's important you understand what's happening when you click the mouse button and create a new voxel box.

You're correct in understanding that, this function is in fact taking the current mouse position and creating the box. When the click is complete and the box has been made, the process starts over so the program again looks to where the mouse is and places the Ghost box. In this case the Ghost box is not on top of the previously made box, so you'd have to move the mouse up manually a few pixels to get it there.

Rather than fool around with the setVoxelPosition function directly, I'd recommend you 'temporarly change the x,y,z position of the ghost in relation to the matrix intersect mouse position of your computer. Upon a successful click, increase the matrixIntersect.x .y .z properties of this matrixIntersects object, increasing these values only a little so you get the 'box-on-top' effect you want directly after a click. Remember to change them back when the users mouse moves off the object otherwise the Ghost box will no longer be directly under the mouse and things can get messy fast if these properties grow after every click.