I'm experiencing a small problem with an editor I'm building. it's a terrain editor, with toolbars on the left and top, with a canvas on the bottom right. There is a beacon named 'helperHandle' in the canvas which will demonstrate which vector you are currently hovering over. however, the beacon doesn't align properly with the mouse, it seems to be using the entire window as an offset, instead of just the rendering canvas. as you can see from the image below. I've included my code below the image.
The javascript >>
$( document ).ready(function() {
var terrainMesh;
var helperHandle;
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var cameraholder;
function main() {
const canvas = document.querySelector('#terrainRender');
const renderer = new THREE.WebGLRenderer({canvas, alpha: true});
var cubes = [];
const fov = 40;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 1000;
cameraholder = new THREE.Object3D();
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0,10,20);
camera.lookAt( 0, 0, 0 );
camera.zoom = 0.5;
const scene = new THREE.Scene();
scene.background = new THREE.Color( 0x555555 );
scene.add(cameraholder);
var size = 10;
var divisions = 10;
var gridHelper = new THREE.GridHelper( size, divisions );
scene.add( gridHelper );
var axesHelper = new THREE.AxesHelper( 5 );
scene.add( axesHelper );
var ambient = new THREE.AmbientLight( 0x444444 );
scene.add( ambient );
const color = 0xFFFFFF;
const intensity = 0.1;
light = new THREE.DirectionalLight(color, intensity);
light.position.set(1, 30, 10);
light.target.position.set( 0, 0, 0 );
light.castShadow = true;
var lightHelper = new THREE.DirectionalLightHelper( light, 5 );
scene.add( lightHelper );
const controls = new THREE.OrbitControls(camera, canvas);
controls.target.set(0, 0, 0);
controls.update();
scene.add( light );
var geometry = new THREE.PlaneBufferGeometry(60, 60, 9, 9);
var material = new THREE.MeshBasicMaterial(
{color: 0x666666,
side: THREE.DoubleSide
});
rotateObject(geometry, -90, 0, 0);
geometry.computeFaceNormals(); // needed for helper
var helperHandlegeometry = new THREE.ConeBufferGeometry( 1, 3, 3 );
helperHandlegeometry.rotateX( Math.PI / 2 );
helperHandle = new THREE.Mesh( helperHandlegeometry, new THREE.MeshNormalMaterial() );
scene.add( helperHandle );
terrainMesh = new THREE.Mesh( geometry, material );
scene.add( terrainMesh );
var wireframe = new THREE.WireframeGeometry( geometry );
var line = new THREE.LineSegments( wireframe );
line.material.depthTest = false;
line.material.opacity = 0.25;
line.material.transparent = true;
scene.add( line );
function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
const direction = (new THREE.Vector3())
.subVectors(camera.position, boxCenter)
.multiply(new THREE.Vector3(1, 0, 1))
.normalize();
camera.near = boxSize / 100;
camera.far = boxSize * 100;
camera.updateProjectionMatrix();
camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = renderer.domElement.clientWidth;
const height = renderer.domElement.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render(time) {
time *= 0.001;
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = renderer.domElement.clientWidth / renderer.domElement.clientHeight;
camera.updateProjectionMatrix();
}
renderer.render(scene, camera);
requestAnimationFrame(render);
}
function onMouseMove( event ) {
mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
terrainMesh.updateMatrixWorld();
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObject( terrainMesh );
if ( intersects.length > 0 ) {
helperHandle.position.set( 0, 0, 0 );
helperHandle.lookAt( intersects[ 0 ].face.normal );
helperHandle.position.copy( intersects[ 0 ].point );
}
$('#coords').html(`X: ${mouse.x.toFixed(2)} <br>Y: ${mouse.y.toFixed(2)}`);
}
window.addEventListener( 'mousemove', onMouseMove, false );
requestAnimationFrame(render);
}
main();
});
The html >>
<div id="main">
<div id="toolBar">
</div>
<div class="editorWindow">
<div id="sideBar"></div>
<canvas id="terrainRender"></canvas>
<div id="coords"></div>
</div>
</div>
The CSS (less) >>
div{
}
body { margin: 0; }
#coords{
position: absolute;
top: 0;
width: 40px;
height: 40px;
background-color: #fff;
}
.titleBar{
height: 30px;
width: 100%;
display: block;
background-color: #e0e0e0;
}
#main{
position: relative;
background-color: #f4f4f4;
display: grid;
height: 99vh;
flex-wrap: wrap;
border: 1px solid #aaa;
padding: 0.2%;
.editorWindow{
flex: 1;
flex-direction: row;
display: flex;
}
#toolBar{
height: 60px;
}
#sideBar{
flex: 1 2 10%;
position: relative;
background-color: #f4f4f4;
border: solid 1px #aaa;
}
#terrainRender {
flex: 12 1 80%;
}
}
#terrain{
display: inline-block;
zoom: 100%;
transform-origin: center;
white-space: nowrap;
font-size: 0px;
transform-style: preserve-3d;
/*transform: rotateZ(0deg) rotateY(0deg) rotateX(45deg);*/
}