In the following html page I create a scene with some points, in which you can zoom comfortably by using the mouse wheel.
But what I want to do is to drag that scene after I have zoomed in. I want to press the left mouse button, keep it pressed and then move the mouse. I want the scene to move accordingly (e.g. by changing the x/y coordinates of the camera).
I tried to create a listener to listen to clicks, but when I click somewhere I do not see any console output.
I also searched and found the suggestion to use DragControls, but this does not seem to be defined in THREE. At least I get an error when I uncomment these lines.
So how to implement something so I can drag the whole scene (or the camera)?
Code:
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.min.js"></script>
<title>Test</title>
</head>
<body>
<script>
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 0, 150);
scene = new THREE.Scene();
scene.add(camera);
renderer = new THREE.WebGLRenderer({
clearAlpha: 1
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x228B22, 1);
document.body.appendChild(renderer.domElement);
// Define a standard Circle
circle = new THREE.CircleGeometry(1, 20);
var max = 50;
var min = -50;
for (var i = 0; i < 100; i++) {
var object = new THREE.Mesh( circle.clone(), new THREE.MeshBasicMaterial( { color: new THREE.Color('yellow'), opacity: 0.5 } ) );
object.position.x = Math.random() * (max - min) + min;
object.position.y = Math.random() * (max - min) + min;
object.position.z = 0;
scene.add( object );
}
document.addEventListener( 'mousewheel', onDocumentMouseWheel, false );
function onDocumentMouseWheel( event ) {
var fovMAX = 100;
var fovMIN = 1;
camera.fov -= event.wheelDeltaY * 0.05;
camera.fov = Math.max( Math.min( camera.fov, fovMAX ), fovMIN );
camera.projectionMatrix = new THREE.Matrix4().makePerspective(camera.fov, window.innerWidth / window.innerHeight, camera.near, camera.far);
}
document.addEventListener( 'mouseclick', onDocumentMouseClick, false );
function onDocumentMouseClick( event ) {
console.log("mouseclick! " + event.offsetX + "-" + event.offsetY, );
}
animate();
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
//// undefined:
//var controls = new THREE.DragControls( objects, camera, renderer.domElement );
//controls.addEventListener( 'dragstart', function ( event ) {
// event.object.material.emissive.set( 0xaaaaaa );
//} );
//
//controls.addEventListener( 'dragend', function ( event ) {
// event.object.material.emissive.set( 0x000000 );
//} );
</script>
</body>
</html>
Maybe there is a better way to do this, but I found a way (see below). The trick is to have a flag that tells if the mouse button is pressed, and then you have an algorithm to determine the difference on the previous position, and move the camera accordingly.
var mouseDown = false;
var mousePos = [0,0];
var cameraPos = 0;
document.addEventListener('mousedown', onMouseDown, false);
function onMouseDown( event ) {
mouseDown = true;
mousePos = [event.offsetX, event.offsetY];
cameraPos = camera.position;
}
document.addEventListener('mouseup', onMouseUp, false);
function onMouseUp( event ) {
mouseDown = false;
}
document.addEventListener('mousemove', onMouseMove, false);
function onMouseMove( event ) {
if (mouseDown) {
// scale factor takes into account the current FOV
scale = Math.tan(camera.fov/2 * Math.PI / 180)/1.5;
dx = mousePos[0] - event.offsetX;
dy = mousePos[1] - event.offsetY;
x = cameraPos.x + scale*dx;
y = cameraPos.y - scale*dy;
camera.position.x = x;
camera.position.y = y;
mousePos = [event.offsetX, event.offsetY];
cameraPos = camera.position;
}
}
Related
I’m kind of new to Three.js
I’m trying to load GLTF model, add mouseover and mouseout events, where first will change the GLTF color, while the second will revert it back to the original.
So far I have been able to achieve it - partially, as it appear in this video, it doesn’t change anything, unless the mouse pointer come from (out of focus maybe?) directly into the GLTF model without going through the black background.
The code I’m using:
const loader = new GLTFLoader();
loader.load('models/box.glb', function (gltf) {
gltf.scene.traverse(function (child) {
if (child.isMesh) {
let m = child;
m.receiveShadow = true;
m.castShadow = true;
m.material.flatShading = true;
sceneMeshes.push(m);
}
if (child.isLight) {
let l = child;
l.castShadow = true;
l.shadow.bias = -.003;
l.shadow.mapSize.width = 2048;
l.shadow.mapSize.height = 2048;
}
});
scene.add(gltf.scene);
console.log(gltf.scene);
}, (xhr) => {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
}, (error) => {
console.log(error);
});
const raycaster = new THREE.Raycaster();
const sceneMeshes = new Array();
renderer.domElement.addEventListener('mouseover', onMouseMove, false);
renderer.domElement.addEventListener('mouseout', onMouseOut, false);
function onMouseMove(event) {
const mouse = {
x: (event.clientX / renderer.domElement.clientWidth) * 2 - 1,
y: -(event.clientY / renderer.domElement.clientHeight) * 2 + 1
};
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(sceneMeshes, false);
if (intersects.length > 0) {
intersects[0].object.material.color.set(0xffff00);
}
}
function onMouseOut(event) {
const mouse = {
x: (event.clientX / renderer.domElement.clientWidth) * 2 - 1,
y: -(event.clientY / renderer.domElement.clientHeight) * 2 + 1
};
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(sceneMeshes, false);
if (intersects.length > 0) {
intersects[0].object.material.color.set(0xff0000);
}
}
Any idea what i might be done wrong?
Try it with this simplified code:
let camera, scene, renderer, mesh;
let raycaster, mouse;
let currentIntersection = null;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
camera.position.z = 4;
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
scene = new THREE.Scene();
const geometry = new THREE.BoxBufferGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.domElement.addEventListener('pointermove', onMouseMove, false);
}
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
renderer.render(scene, camera);
}
function onMouseMove(event) {
mouse.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1;
mouse.y = -(event.clientY / renderer.domElement.clientHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObject(scene, true);
if (intersects.length > 0) {
currentIntersection = intersects[0].object;
currentIntersection.material.color.set(0xffff00);
} else {
if (currentIntersection !== null) {
currentIntersection.material.color.set(0xff0000);
currentIntersection = null;
}
}
}
body {
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.120.1/build/three.js"></script>
You normally only need a pointermove event listener to implement a "hover" effect.
I got it solved by using mousemove event, and the following code inside onMouseMove event:
if (intersects.length > 0) {
INTERSECTED = intersects[0].object;
if (intersects[0].object) {
INTERSECTED.material.color.set(0xff0000);
console.log("Touching")
}
} else {
INTERSECTED.material.color.set(0xfff000);
console.log("Not touching")
}
Basically i was using the else statement in the wrong place - right after the if (intersects[0].object)
I want a dat.GUI() instance to show up when a click occurs inside a mesh, and when its clicked again to disapear.
Obviosouly, when it is reclicked, i want to it reapper.
I tried many different things but i cannot get the behaviour i want...
For example chick this code:
function onDocumentMouseClick(event) //if we detect a click event
{
// the following line would stop any other event handler from firing
// (such as the mouse's TrackballControls)
event.preventDefault();
// update the mouse variable
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// calculate objects intersecting the picking ray
var intersects = raycaster.intersectObjects( scene.children );
//if mouse is on top of the mesh when the click occurs, change color of mesh and render GUI
if ( intersects.length > 0 && intersects[ 0 ].object === cube && isClicked === false)
{
isClicked = true;
cube.material.color.set( 0xF7F7F7 );
var params = {
textField: "Enter value:"
}
var item = gui.add(params, "textField").onFinishChange(function (value) {
//Do something with the new value
console.log(value);
});
}
//if mouse is on top of the mesh when the click occurs, but it already marked as 'clicked', now mark it as 'unclicked'
else if ( intersects.length > 0 && intersects[ 0 ].object === cube && isClicked === true)
{
isClicked = false;
cube.material.color.set( cube.userData.originalColor );
dat.GUI.toggleHide();
//gui.toggleHide()
}
}
Now when i click the mesh, the GUi is created, when i reclick it dissaperas, but when i click again weird stuff happens.
Sometimes the hide button does not work, but ultimately i end up with many different GUIS, where i only want one.
And have the option to make it appear / dissapear.
You can do it this way:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var geometry = new THREE.BoxGeometry();
var material = new THREE.MeshBasicMaterial({
color: 0x00ff00
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
params = {
zAxis: "1"
}
var gui = new dat.GUI();
gui.add(params, "zAxis").onFinishChange(val => {
cube.scale.z = parseFloat(val);
});
var mouse = new THREE.Vector2();
var raycaster = new THREE.Raycaster();
var intersects;
window.addEventListener("click", event => {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
intersects = raycaster.intersectObject(cube);
if (intersects.length > 0) {
let vis = gui.domElement.style.visibility;
gui.domElement.style.visibility = vis == "" ? "hidden" : "";
}
});
var animate = function() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
};
animate();
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/libs/dat.gui.min.js"></script>
I have a simple three.js graphics, and I tried to use the answers in this and this question to make the created plot zoomable by the mouse wheel. By using the mouse wheel I would like to zoom in to the graphics or to zoom out.
Here is the complete code: pastebin link
However, when turning the mouse wheel nothing happens, and I do not get an error message. Maybe I am missing something?
DEMO
var container, camera, scene, renderer, colors;
var selected = 0;
var selectedObject;
var objects = [];
// DOM element...
container = document.createElement('div');
document.body.appendChild(container);
// Camera...
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 0, 150);
// Scene...
scene = new THREE.Scene();
scene.add(camera);
// Renderer...
renderer = new THREE.WebGLRenderer({
clearAlpha: 1
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xffffff, 1);
document.body.appendChild(renderer.domElement);
// Scatter plot...
scatterPlot = new THREE.Object3D();
scene.add(scatterPlot);
// Plot some random points...
circle = new THREE.CircleGeometry(1, 20);
colors = [];
var max = 50;
var min = -50;
for (var i = 0; i < 10; i++) {
var object = new THREE.Mesh( circle.clone(), new THREE.MeshBasicMaterial( { color: new THREE.Color('black'), opacity: 0.5 } ) );
object.position.x = Math.random() * (max - min) + min;
object.position.y = Math.random() * (max - min) + min;
object.position.z = 0;
scene.add( object );
objects.push( object );
}
animate();
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'mousewheel', onDocumentMouseWheel, false );
function onDocumentMouseDown( event ) {
event.preventDefault();
mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( objects );
if ( intersects.length > 0 ) {
//intersects[ 0 ].object.material.color.set('red');
//intersects[ 0 ].object.geometry.scale(1.1,1.1,1.1);
if (selected === 0) {
selected = 1;
selectedObject = intersects[ 0 ].object;
selectedObject.material.color.set('red');
console.log(selectedObject.position.x);
} else {
selected = 0;
var geometry = new THREE.Geometry();
geometry.vertices.push(intersects[ 0 ].object.position);
geometry.vertices.push(selectedObject.position);
var line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color: 0x0000ff }));
scene.add(line);
selectedObject.material.color.set('black');
}
}
}
function onWindowResize() {
camera.left = window.innerWidth / - 2;
camera.right = window.innerWidth / 2;
camera.top = window.innerHeight / 2;
camera.bottom = window.innerHeight / - 2;
camera.aspect = window.innerWidth / window.innerHeight;
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseWheel( event ) {
var fovMAX = 160;
var fovMIN = 1;
camera.fov -= event.wheelDeltaY * 0.05;
camera.fov = Math.max( Math.min( camera.fov, fovMAX ), fovMIN );
camera.projectionMatrix = new THREE.Matrix4().makePerspective(camera.fov, window.innerWidth / window.innerHeight, camera.near, camera.far);
}
body { margin: 0; }
canvas { width: 100%; height: 100% }
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/54/three.js"></script>
In your code add event listener
document.addEventListener( 'mousewheel', onDocumentMouseWheel, false );
document.addEventListener( 'mousewheel', (event) => {
camera.position.z +=event.deltaY/500;
});
The mousewheel event is supported only in Webkit browsers.
For cross-browser compaitibility use the wheel event.
I have added a sphere and plane geometry to the scene when clicked on plane geometry it is linked to a website
now when hover on plane geometry the "mouse cursor" should change to "mouse pointer (hand)" and when not hovered
on plane geometry the mouse should retain its original style.
I tried using this statement "$('html,body').css('cursor','pointer');" but mouse cursor is not changing on
hovering, its changing when clicked on plane geometry and its cursor is not retaining to its original position.
can someone please help me how to solve the problem. I have also uploaded the code.
<html>
<head>
<body>
<script type="text/javascript" src="jquery-1.11.3.js"></script>
<script src ="./three.js-master/build/three.js"></script>
<script src ="./three.js-master/examples/js/controls/OrbitControls.js">
</script>
<script src ="./three.js-master/examples/js/renderers/Projector.js">
</script>
<script type="text/javascript" src="math.min.js"></script>
<script type="text/javascript">
window.onload = createsphere();
function createsphere()
{
var controls,scene,camera,renderer;
var planes = [];
var baseVector = new THREE.Vector3(0, 0, 1);
var camDir = new THREE.Vector3();
var planeLookAt = new THREE.Vector3();
function init()
{
var spriteResponse = [];
spriteResponse[0] = {ID:1, x: 0, y: 0};
spriteResponse[1] = {ID:2, x: 0, y: 0.1};
spriteResponse[2] = {ID:3, x: 0, y: 0.5};
spriteResponse[3] = {ID:4, x: 0.5, y: 0};
spriteResponse[4] = {ID:5, x: 0.25, y: 0.5 };
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
//camera.position.y = 1;
camera.position.z = 1 ;
var width = window.innerWidth;
var height = window.innerHeight;
renderer = new THREE.WebGLRenderer( {antialias:true} );
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);
/* ------------------------ creating the geometry of sphere------------------------------*/
var radius = 2.5;
var spheregeometry = new THREE.SphereGeometry(radius, 20, 20, 0, -6.283, 1, 1);
//var texture = THREE.ImageUtils.loadTexture ('rbi00000083.jpg');
//texture.minFilter = THREE.NearestFilter;
//var spherematerial = new THREE.MeshBasicMaterial({map: texture});
var spherematerial = new THREE.MeshBasicMaterial({color: '#A9A9A9'});
var sphere = new THREE.Mesh(spheregeometry, spherematerial);
scene.add(sphere);
scene.add(camera);
scene.autoUpdate = true;
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.minPolarAngle = Math.PI/4;
controls.maxPolarAngle = 3*Math.PI/4;
for(var i=0; i<spriteResponse.length;i++)
{
//var spriteAlignment = new THREE.Vector2(0,0) ;
material_plane = new THREE.MeshBasicMaterial( {color: 0xffffff,side: THREE.DoubleSide } );
material_plane.needsUpdate = true;
//material.transparent=true;
geometry_plane = new THREE.PlaneGeometry(0.3, 0.2);
plane = new THREE.Mesh( geometry_plane, material_plane );
plane.database_id = spriteResponse[i].ID;
plane.LabelText = spriteResponse[i].name;
plane.position.set(spriteResponse[i].x,spriteResponse[i].y,-1);
scene.add(plane);
//plane.userData = { keepMe: true };
planes.push(plane);
//plane.id = cardinal.ID;
//var direction = camera.getWorldDirection();
camera.updateMatrixWorld();
var vector = camera.position.clone();
vector.applyMatrix3( camera.matrixWorld );
plane.lookAt(vector);
plane.userData = { URL: "http://stackoverflow.com"};
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
}
function onDocumentMouseDown( event )
{
//clearScene();
event.preventDefault();
var mouse = new THREE.Vector2();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( planes );
var matched_marker = null;
if(intersects.length != 0)
{
$('html,body').css('cursor','pointer');//mouse cursor change
for ( var i = 0; intersects.length > 0 && i < intersects.length; i++)
{
window.open(intersects[0].object.userData.URL);
}
}
else
$('html,body').css('cursor','cursor');//mouse cursor change
}//onDocumentMouseDown( event )
}
function animate()
{
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
init();
animate();
}
</script>
</body>
</head>
</html>
There are a number of ways to do it, but to keep it simple and make it easier for you to understand, my example includes a method that keeps with the format of the code you provided in your question.
I added a mousemove event to your init() function. The handler looks like this:
function onDocumentMouseMove(event) {
var mouse = new THREE.Vector2();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( planes );
if(intersects.length > 0) {
$('html,body').css('cursor', 'pointer');
} else {
$('html,body').css('cursor', 'default');
}
}
All this does is check whether or not one of your planes is intersected each time you move the mouse.
The reason this wasn't working before is because you only changed the cursor on mouse-down which won't give the desired 'hover' effect.
Here's a working fiddle. Just note that I've commented out any controls related code to get the fiddle working quicker, it won't change the solution.
You can't change hover state within JS as stated here:
https://stackoverflow.com/a/11371599/5001964
I think easiest solution would be to make it with css:
body:hover {
cursor: pointer;
}
Although it would be better if instead body you choose a specific DOM node to make the hover effect.
I am trying to visualize 3d model of a car with three.js, and I have couple of issues(my code is below):
1)
The 3d model is made in Maya 2016, and then exported as .obj and a .mtl files. I want the parts of the car to be selectable( i mean when u select it, it highlights in green color, when you click again on selected part, it goes back to normal color.
I've already done that, but the problem is that the raycast selects all the objects in the path of the ray, i mean when I select door, everything behind it gets selected and I want to select the door only.
2)
The second problem is that the renderer doesn't visualize transparent materials for ex. the windows and headlights. And I've seen some 3d car visualizers that can display transparent materials.
3)
The third issue goes back to number 1. When I select a part, i want to store it's previous material color(before I apply the highlight color), so when I de-select it, it could bring back the normal color, I've put the color of the car paint, which is just wrong because when i de-select windows they go red.
So, here is my index.html code:
<code><html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.1">
<script src="JavaScript/three.js"></script>
<script src="JavaScript/Detector.js"></script>
<script src="JavaScript/OrbitControls.js"></script>
<script src="JavaScript/OBJLoader.js"></script>
<script src="JavaScript/MTLLoader.js"></script>
<script src="JavaScript/Projector.js"></script>
<link rel="stylesheet" type="text/css" href="css/site.css">
</head>
<body>
<div class="left">
<p>Low-Poly Croupière<p>
<p>manu.ninja</p>
</div>
<div id="test" class="left" hidden="true">
<p>xaxaxaxaxaaxaaxx<p>
</div>
<a class="right" href="https://github.com/Lorti/webgl-3d-model-viewer-using-three.js" target="_top">
<img src="https://camo.githubusercontent.com/652c5b9acfaddf3a9c326fa6bde407b87f7be0f4/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67">
</a>
<script>
if (!Detector.webgl) {
Detector.addGetWebGLMessage();
}
var container;
var camera, controls, scene, renderer;
var lighting, ambient, keyLight, fillLight, backLight;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var objects = [];
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
/* Camera */
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 140;
/* Scene */
scene = new THREE.Scene();
lighting = true;
ambient = new THREE.AmbientLight(0xefefff, 1.0);
scene.add(ambient);
keyLight = new THREE.DirectionalLight(new THREE.Color('hsl(60, 100%, 75%)'), 3.0);
keyLight.position.set(-100, 0, 100);
fillLight = new THREE.DirectionalLight(new THREE.Color('hsl(540, 100%, 75%)'), 1.75);
fillLight.position.set(100, 0, 100);
backLight = new THREE.DirectionalLight(0xe3ffef, 1.0);
backLight.position.set(100, 0, -100).normalize();
/* Model */
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl('assets/');
mtlLoader.setPath('assets/');
mtlLoader.load('e46_red_5.mtl', function (materials) {
materials.preload();
//materials.materials.default.map.magFilter = THREE.NearestFilter;
// materials.materials.default.map.minFilter = THREE.LinearFilter;
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.setPath('assets/');
objLoader.load('e46_red_5.obj', function (object) {
scene.add(object);
objects.push(object);
});
});
/* Renderer */
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(new THREE.Color("hsl(0, 0%, 10%)"));
container.appendChild(renderer.domElement);
/* Controls */
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = false;
/* Events */
window.addEventListener('resize', onWindowResize, false);
window.addEventListener('keydown', onKeyboardEvent, false);
//window.addEventListener( 'mousemove', onMouseMove, false );
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onKeyboardEvent(e) {
if (e.code === 'KeyL') {
lighting = !lighting;
if (lighting) {
ambient.intensity = 0.25;
scene.add(keyLight);
scene.add(fillLight);
scene.add(backLight);
} else {
ambient.intensity = 1.0;
scene.remove(keyLight);
scene.remove(fillLight);
scene.remove(backLight);
}
}
}
function animate() {
requestAnimationFrame(animate);
controls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
var already_selected = false;
function onDocumentMouseDown( event ) {
event.preventDefault();
var projector = new THREE.Projector();
mouseVector = new THREE.Vector3();
mouseVector.x = 2 * (event.clientX / window.innerWidth) - 1;
mouseVector.y = 1 - 2 * ( event.clientY / window.innerHeight );
//var mouse3D = new THREE.Vector3( ( event.clientX / window.innerWidth ) * 2 - 1,
// -( event.clientY / window.innerHeight ) * 2 + 1,
// 0.5 );
//var raycaster = projector.pickingRay( mouseVector.clone(), camera );
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera( mouseVector, camera );
var intersects = raycaster.intersectObjects( objects[0].children );
console.log(intersects)
if ( intersects.length > 0 ) {
var door = document.getElementById("test");
door.hidden =false;
for (var i = 0; i < intersects.length; i++) {
//intersects[i].object.material.color.setHex( Math.random() * 0xffffff );
//var currentColor = new THREE.Color(intersects[i].object.material.color);
var currentColor = +'0x' + intersects[i].object.material.color.getHex().toString( 16 );
if (already_selected == true) {
intersects[i].object.material.color.setHex( 0x380000 );
//intersects[i].object.material.color.setHex( currentColor );
already_selected = false;
}
else {
intersects[i].object.material.color.setHex( 0xccffcc );
already_selected = true;
}
}
}
}
</script>
</body>
</html></code>
1) For your raycaster issue, in your intersects array, you would only want to access intersects[0] since that is the first object that the raycast intersects. I do not see the point in going through the whole array if you don't want to select items behind the first one
2) In order to see transparency, You have to set
(object here).material.transparent = true;
I had to do this in order to make see through objects when you click on them, but I also had to set opacity. Assuming your object has an opacity assigned already, then it would need only the transparency flag, otherwise you can also set
(object here).material.opacity = some number;
3) What I have done when I want to 'highlight' a material is I actually change intersects[0].object.material.emissive.set('#(insert color)');
Then when the mouse moves of the object, you reset the emissive to #000000.
Emissive is better because you're not actually changing the color, just an outward appearance.