Hello I have one doubt:
I have studied:
https://threejs.org/docs/#api/materials/PointsMaterial
And I have adapted the example to work with my existing code.
The aim is to render points on top of the model which we have loaded on click position.
Here we have the code, the important part is onDocumentMouseDown(), the file, logic.js:
if (!Detector.webgl) Detector.addGetWebGLMessage();
// global variables for this scripts
let OriginalImg,
SegmentImg;
var mouse = new THREE.Vector2();
var raycaster = new THREE.Raycaster();
var mousePressed = false;
var clickCount = 0;
init();
animate();
// initilize the page
function init() {
let filename = "models/nrrd/columna01.nrrd"; // change your nrrd file
let idDiv = 'original';
OriginalImg = new InitCanvas(idDiv, filename);
OriginalImg.init();
console.log(OriginalImg);
filename = "models/nrrd/columnasegmentado01.nrrd"; // change your nrrd file
idDiv = 'segment';
SegmentImg = new InitCanvas(idDiv, filename);
SegmentImg.init();
}
let originalCanvas = document.getElementById('original');
originalCanvas.addEventListener('mousedown', onDocumentMouseDown, false);
originalCanvas.addEventListener('mouseup', onDocumentMouseUp, false);
function onDocumentMouseDown(event) {
mousePressed = true;
clickCount++;
mouse.x = ( ( event.clientX - OriginalImg.renderer.domElement.offsetLeft ) / OriginalImg.renderer.domElement.clientWidth ) * 2 - 1;
mouse.y = -( ( event.clientY - OriginalImg.renderer.domElement.offsetTop ) / OriginalImg.renderer.domElement.clientHeight ) * 2 + 1
console.log('Mouse x position is: ', mouse.x, 'the click number was: ', clickCount);
console.log('Mouse Y position is: ', mouse.y);
raycaster.setFromCamera(mouse.clone(), OriginalImg.camera);
var objects = raycaster.intersectObjects(OriginalImg.scene.children);
var pointGeometry = new THREE.Geometry();
var position = new THREE.Vector3();
position.x = objects[0].point.x;
position.y = objects[0].point.y;
position.z = objects[0].point.z;
pointGeometry.vertices.push(position);
var pointMaterial = new THREE.PointsMaterial({color: 0x888888});
var point = new THREE.Points(pointGeometry, pointMaterial);
OriginalImg.scene.add(point);
console.log(objects);
}
function onDocumentMouseUp(event) {
mousePressed = false
}
function animate() {
requestAnimationFrame(animate);
OriginalImg.animate();
SegmentImg.animate();
}
And we do add the points to the scene, but in fact they do not render, they do not show, and I wonder why?:
As you could see in the image we see that the raycaster intercepts those new created points, however the do not get drawn.
I wonder if they are too small, or just the color hides them with the background.
Could you help me please?.
Additional code:
// this class handles the load and the canva for a nrrd
// Using programming based on prototype: https://javascript.info/class
// This class should be improved:
// - Canvas Width and height
InitCanvas = function (IdDiv, Filename) {
this.IdDiv = IdDiv;
this.Filename = Filename
}
InitCanvas.prototype = {
constructor: InitCanvas,
init: function () {
this.container = document.getElementById(this.IdDiv);
// this should be changed.
debugger;
this.container.innerHeight = 600;
this.container.innerWidth = 800;
//These statenments should be changed to improve the image position
this.camera = new THREE.PerspectiveCamera(60, this.container.innerWidth / this.container.innerHeight, 0.01, 1e10);
this.camera.position.z = 300;
let scene = new THREE.Scene();
scene.add(this.camera);
// light
let dirLight = new THREE.DirectionalLight(0xffffff);
dirLight.position.set(200, 200, 1000).normalize();
this.camera.add(dirLight);
this.camera.add(dirLight.target);
// read file
let loader = new THREE.NRRDLoader();
loader.load(this.Filename, function (volume) {
//z plane
let sliceZ = volume.extractSlice('z', Math.floor(volume.RASDimensions[2] / 4));
debugger;
this.container.innerWidth = sliceZ.iLength;
this.container.innerHeight = sliceZ.jLength;
sliceZ.mesh.material.color.setRGB(0,1,1);
console.log('Our slice is: ', sliceZ);
scene.add(sliceZ.mesh);
}.bind(this));
this.scene = scene;
// renderer
this.renderer = new THREE.WebGLRenderer({alpha: true});
this.renderer.setPixelRatio(this.container.devicePixelRatio);
debugger;
this.renderer.setSize(this.container.innerWidth, this.container.innerHeight);
// add canvas in container
this.container.appendChild(this.renderer.domElement);
},
animate: function () {
this.renderer.render(this.scene, this.camera);
}
}
I wonder about the point size because if we see this example they are made with 0.05 of size:
https://github.com/mrdoob/three.js/blob/master/examples/webgl_interactive_raycasting_points.html
And in the example we see the camera being quite far away from the points being generated and they are visible:
https://threejs.org/examples/webgl_interactive_raycasting_points.html
What do you think?
You can use THREE.BufferGeometry() with .setDrawRange():
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(1, 5, 5);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var mesh = new THREE.Mesh(new THREE.SphereBufferGeometry(3, 32, 24), new THREE.MeshBasicMaterial({
wireframe: true,
color: "red"
}));
scene.add(mesh);
var idx = 0;
var maxIdx = 10;
var points = [];
for (let i = 0; i < maxIdx; i++) {
points.push(new THREE.Vector3());
}
var geometry = new THREE.BufferGeometry().setFromPoints(points);
geometry.setDrawRange(0, idx);
var points = new THREE.Points(geometry, new THREE.PointsMaterial({
size: 0.125,
color: "yellow"
}));
scene.add(points);
window.addEventListener("mousemove", onMouseMove, false);
window.addEventListener("mousedown", onMouseDown, false);
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var intersects = [];
function onMouseMove(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}
function onMouseDown(event) {
raycaster.setFromCamera(mouse, camera);
intersects = raycaster.intersectObject(mesh);
if (intersects.length === 0) return;
if (idx == maxIdx) return;
let p = intersects[0].point;
geometry.attributes.position.setXYZ(idx, p.x, p.y, p.z);
geometry.attributes.position.needsUpdate = true;
idx++;
geometry.setDrawRange(0, idx);
}
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/91/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
Related
I developed a 3D cube that moves on one axis simulating the accelerometer sensor.
Currently, I have the .obj and .mtl of a toycar which I aim to add to the scene(), but when I remove the
BoxGeometry 3D cube and replace it with the car mesh I got these errors all the time:
I also get this error saying that obj is not defined, even if I defined it globally I still have the same issue:
I checked libraries that exist locally and other function but I can't see where is the problem.
Below is how I load the car model:
const scene = new THREE.Scene();
var loader = new THREE.OBJMTLLoader();
loader.load('https://jyunming-chen.github.io/tutsplus/models/toycar.obj', 'https://jyunming-chen.github.io/tutsplus/models/toycar.mtl',
function (vehicle) {
toycar = vehicle;
toycar.rotateY(-10.99);
scene.add(toycar);
});
and this is my full .HTML code with js implementation:
This is hoq looks like now:
and this is what I am aiming to achieve:
That's my current code:
<html>
<head>
<meta charset="UTF-8">
<script src="./three.min.js"></script>
<script src="./require.js" type="text/javascript"></script>
<script src="./OrbitControls.js"></script>
<script src="./KeyboardState.js"></script>
<script src="./MTLLoader.js"></script>
<script src="./OBJMTLLoader.js"></script>
<script type="module"> import * as THREE from "./three.module.js"</script>
</head>
<body>
<canvas id="canvas" width="1000" height="600" style="border:1px solid #000000;"></canvas>
</body>
<script>
let sensorValue = 0;
let sensorAddr = 0;
var toycar;
StartRetrieveLiveData();
function main() {
const canvas = document.querySelector('#canvas');
const accelPanel = document.querySelector('#accelPanel');
const renderer = new THREE.WebGLRenderer({ alpha: true, canvas });
renderer.setClearColor( 0x626d73, 1 );
var context = canvas.getContext("2d");
var width = window.innerWidth;
var height = window.innerHeight;
const fov = 70;
const aspect = 2;
const near = 20;
const far = 500;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 50, 1.5);
camera.up.set(0, 0, 1);
camera.lookAt(0, 0, 0);
const scene = new THREE.Scene();
// var loader = new THREE.OBJMTLLoader();
// loader.load('https://jyunming-chen.github.io/tutsplus/models/toycar.obj', 'https://jyunming-chen.github.io/tutsplus/models/toycar.mtl',
// function (vehicle) {
// toycar = vehicle;
// toycar.rotateY(-10.99);
// scene.add(toycar);
// });
// An array of objects who's rotation to update
const objects = [];
const radius = 3;
const widthSegments = 3;
const heightSegments = 3;
const sphereGeometry = new THREE.BoxGeometry(radius, widthSegments, heightSegments);
const sunMaterial = new THREE.MeshBasicMaterial({ color: "green", wireframe: false });
const object = new THREE.Mesh(sphereGeometry, sunMaterial);
var cubeAxis = new THREE.AxesHelper(10);
object.add(cubeAxis);
object.scale.set(2, 2, 2);
scene.add(object);
objects.push(object);
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render() {
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
objects.forEach((obj) => {
sensorValueIndex = ((sensorValue / 16384) * 10);
obj.position.z = ((sensorValue / 16384) * 20);
console.log("AccX: ",sensorValueIndex);
// // Here I take accelerometerX and pass them to the 3D model
// if (sensorAddr === 1) {
// }
});
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
function onMsg(event) {
// console.log(`[message] Data received from server: ${event.data}`);
// console.log("event.data = " + JSON.parse(event.data));
var received_msg = event.data;
var obj = JSON.parse(JSON.parse(received_msg));
if (obj !== null) {
if (
obj.hasOwnProperty("DataMapChangedObjectsAddressValue") &&
obj["DataMapChangedObjectsAddressValue"][0]["DataMapAddress"] !==
undefined
) {
sensorAddr =
obj["DataMapChangedObjectsAddressValue"][0]["DataMapAddress"];
sensorValue =
obj["DataMapChangedObjectsAddressValue"][0]["Value"];
// if (sensorAddr === 1) {
// sensorValueIndex = (sensorValue / 16384) * 500;
// }
}
}
}
function onOpen(e) {
console.log("SSE connected");
}
function onError(e) {
// console.log(`[error] ${error.message}`);
if (e.eventPhase == EventSource.CLOSED) this.source.close();
if (e.target.readyState == EventSource.CLOSED) {
console.log("SSE Disconnected");
} else if (e.target.readyState == EventSource.CONNECTING) {
console.log("SSE Connecting ...");
}
}
function StartRetrieveLiveData() {
if (!!window.EventSource) {
this.source = new EventSource("/sse");
} else {
console.log("Your browser doesn't support SSE");
}
this.source.addEventListener("message", e => this.onMsg(e));
this.source.addEventListener("open", e => this.onOpen(e), false);
this.source.addEventListener("error", e => this.onError(e), false);
// Add here (only mozilla)
main();
// Add here
}
</script>
</html>
Note that when I used a public server the whole thing works just fine, but I used the remote server (the actual server) I get these error and the whole thing doesn't work as expected.
Would appreciate a solution for this.
I solved the problem so I am going to answer this.
Firstly, the document.querySelector('#canvas') should be removed to avoid creating two canvas, because I am calling the libraries in the . This was a silly mistake but I found it finally.
Secondly, the camera position was off and it wasn't really pointing at the car so nothing was shown on the screen. I tweaked the camera.position on the X, Y and Z axis to get it right.
There were bunches of other silly mistakes I found while carefully debugging the code, I am not an expert in the language yet so these mistakes serve as a learning experience for me.
The final working code is below:
let sensorValue = 0;
var toycar;
StartRetrieveLiveData();
var scene, renderer, camera;
var controls, keyboard = new KeyboardState();
var toycar;
function init() {
var width = window.innerWidth;
var height = window.innerHeight;
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setClearColor(0x626d73, 1);
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(10, width / height, 1, 10000);
camera.position.y = -150;
camera.lookAt(new THREE.Vector3(0, 0, 0));
var loader = new THREE.OBJMTLLoader();
loader.load('./toycar.obj', './toycar.mtl',
function (object) {
toycar = object;
toycar.rotateZ(10.99); //toycar.rotateZ(-10.99);
scene.add(toycar);
});
var gridXZ = new THREE.GridHelper(350000, 10000);
gridXZ.setColors(new THREE.Color(0xff0000), new THREE.Color(0xffffff));
scene.add(gridXZ);
var pointLight = new THREE.PointLight(0xffffff);
pointLight.position.set(350, 20, 5);
scene.add(pointLight);
var ambientLight = new THREE.AmbientLight(0x111111);
scene.add(ambientLight);
}
function animate() {
var angle = 0;
var speed = 0;
var pos = new THREE.Vector3(0, 0, 0);
var clock = new THREE.Clock();
var dt = clock.getDelta();
var dir = new THREE.Vector3(1, 0, 0);
dir.multiplyScalar(dt * speed);
dir.applyAxisAngle(new THREE.Vector3(0, 0, 0), 10);
pos.add(dir);
if (toycar != undefined) {
sensorValueIndex = ((sensorValue / 16384) * 50);
toycar.scale.set(0.1, 0.1, 0.1);
toycar.position.x = sensorValueIndex;
toycar.position.y = 0;
toycar.position.z = 0;
toycar.rotation.x = (angle + Math.PI);
}
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function onMsg(event) {
var received_msg = event.data;
var obj = JSON.parse(JSON.parse(received_msg));
if (obj !== null) {
if (
obj.hasOwnProperty("DataMapChangedObjectsAddressValue") &&
obj["DataMapChangedObjectsAddressValue"][0]["DataMapAddress"] !==
undefined
) {
let sensorAddr =
obj["DataMapChangedObjectsAddressValue"][0]["DataMapAddress"];
sensorValue =
obj["DataMapChangedObjectsAddressValue"][0]["Value"];
if (sensorAddr === 1) {
sensorValueIndex = (sensorValue / 16384) * 10;
console.log(sensorValueIndex);
}
}
}
}
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)
js for making a scene with water. I followed the official examples to create the scene, but after loading an external GLTF model I noticed that the reflection does not work well.
In the first frame everything is ok, but as soon as I move the camera all goes wrong.
I think that it's due to my own code for camera motion, but I can't understand why.
Here's the code:
let div = document.body.children[0];
let rect = div.getBoundingClientRect();
// create scene
let scene = new THREE.Scene();
// load boat model
{
let loader = new THREE.GLTFLoader();
// load a glTF resource
loader.load(
// resource URL
"https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/Duck/glTF/Duck.gltf",
// called when the resource is loaded
function (gltf) {
let duck = gltf.scene.children[0];
scene.add(duck);
},
// called while loading is progressing
function (xhr) {
console.log(xhr, (xhr.loaded / xhr.total * 100) + "% loaded");
},
// called when loading has errors
function (error) {
console.log("An error happened", error);
}
);
}
// create camera pivot to orbit around center
let cameraHorizontal = new THREE.Object3D();
let cameraVertical = new THREE.Object3D();
let cameraPlaceholder = new THREE.Object3D();
cameraPlaceholder.position.z = 10;
cameraVertical.add(cameraPlaceholder);
cameraVertical.rotation.x = -.2;
cameraHorizontal.add(cameraVertical);
cameraHorizontal.updateMatrixWorld(true);
let camera = new THREE.PerspectiveCamera(75, rect.width/rect.height, 0.1, 1000);
function updateCamera() {
let worldPosition = cameraPlaceholder.getWorldPosition();
camera.position.copy(worldPosition);
let worldQuaternion = cameraPlaceholder.getWorldQuaternion();
camera.setRotationFromQuaternion(worldQuaternion);
camera.updateProjectionMatrix();
}
// create light
let light = new THREE.DirectionalLight(0xffffff, 0.8);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff));
// create water
let waterGeometry = new THREE.PlaneBufferGeometry(10000, 10000);
let water = new THREE.Water(
waterGeometry,
{
textureWidth: 2048,
textureHeight: 2048,
waterNormals: new THREE.TextureLoader().load("https://rawgit.com/mrdoob/three.js/master/examples/textures/waternormals.jpg", function (texture) {
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
}),
alpha: 0,
sunDirection: light.position.clone().normalize(),
sunColor: 0xffffff,
waterColor: 0x001e0f,
distortionScale: 0,
fog: scene.fog !== undefined
}
);
water.rotation.x = -Math.PI / 2;
water.matrixAutoUpdate = false;
water.rotationAutoUpdate = false;
water.updateMatrix();
scene.add(water);
// create skybox
let sky = new THREE.Sky();
let uniforms = sky.material.uniforms;
uniforms.turbidity.value = 10;
uniforms.rayleigh.value = 2;
uniforms.luminance.value = 1;
uniforms.mieCoefficient.value = 0.005;
uniforms.mieDirectionalG.value = 0.8;
let parameters = {
distance: 400,
inclination: 0.2,
azimuth: 0.205
};
let cubeCamera = new THREE.CubeCamera(0.1, 1, 512);
cubeCamera.renderTarget.texture.generateMipmaps = true;
cubeCamera.renderTarget.texture.minFilter = THREE.LinearMipmapLinearFilter;
scene.background = cubeCamera.renderTarget;
// create renderer
let renderer = new THREE.WebGLRenderer();
renderer.setSize(rect.width, rect.height);
div.appendChild(renderer.domElement);
function updateSun() {
let theta = Math.PI * (parameters.inclination - 0.5);
let phi = 2 * Math.PI * (parameters.azimuth - 0.5);
light.position.x = parameters.distance * Math.cos(phi);
light.position.y = parameters.distance * Math.sin(phi) * Math.sin(theta);
light.position.z = parameters.distance * Math.sin(phi) * Math.cos(theta);
sky.material.uniforms.sunPosition.value = light.position.copy(light.position);
water.material.uniforms.sunDirection.value.copy(light.position).normalize();
cubeCamera.update(renderer, sky);
}
updateSun();
// add event listeners for rotate camera
let movingWith = null;
renderer.domElement.addEventListener("pointerdown", event => {
if (movingWith != null) {
return;
}
event.preventDefault();
movingWith = event.pointerId;
function onmove(event) {
if (event.pointerId !== movingWith) {
return;
}
event.preventDefault();
cameraVertical.rotation.x = Math.max(Math.min(cameraVertical.rotation.x - (event.movementY / 50), -.01), -(Math.PI / 2) + .2);
cameraHorizontal.rotation.y = (cameraHorizontal.rotation.y - (event.movementX / 50)) % (2 * Math.PI);
cameraHorizontal.updateMatrixWorld(true);
}
window.addEventListener("pointermove", onmove);
window.addEventListener("pointerup", function onup() {
if (event.pointerId !== movingWith) {
return;
}
event.preventDefault();
window.removeEventListener("pointermove", onmove);
window.removeEventListener("pointerup", onup);
movingWith = null;
})
});
let lastTime;
let animate = function () {
let now = Date.now();
let deltaTime = (now - lastTime) / 1000;
lastTime = now;
water.material.uniforms.time.value += deltaTime;
updateCamera();
renderer.render(scene, camera);
requestAnimationFrame(animate);
};
lastTime = Date.now();
animate();
// resize canvas with window
window.addEventListener("resize", this._onresize = () => {
let rect = div.getBoundingClientRect();
renderer.setSize(rect.width, rect.height);
camera.aspect = rect.width / rect.height;
camera.updateProjectionMatrix();
});
And Here is the codepen.
Any help is appreciated.
Thanks in advance
Thanks for sharing the codepen. This is actually a bug in Water which should be fixed with the next release R116.
I've update your codepen here with the fix: https://jsfiddle.net/q2cemtb0/1/
Respective PR at GitHub: https://github.com/mrdoob/three.js/pull/19016
I got this javascript code from somewhere, but i'm not sure how assigning js codes to classes work. I'm not so good with Js..any help will be greatly appreciated.
I would like for the js to be assigned to the 'intro-section' class. Its 3D butterfly animation.
Initially though, I wanted it to be assigned to an entire page..and maybe make it stick to the back and not move when the page scrolls down.
Index.html
<!-- Intro section start -->
<section class="intro-section sp-pad spad" id="demo">
<div class="container-fluid">
<div class="row">
<div class="col-xl-5 intro-text">
<span class="sp-sub-title">Play, Learn & Grow Together.</span>
<h3 class="sp-title">Welcome To Bright Beginnings</h3>
<p>The atmosphere of the school will be relaxed and will encourage freedom of expression as a means
to individual growth. Children should be free to be children – to act, choose, explore, test,
investigate, react, and experiment. Hence, children grow naturally in their new awareness of
themselves, their relationships towards/with others, and with the world around them.</p>
Read More
</div>
<div class="col-xl-6 offset-xl-1">
<figure class="intro-img mt-5 mt-xl-0">
<img src="img/intro.jpg" alt="">
</figure>
</div>
</div>
</div>
</section>
<!-- Intro section end -->
Javascript:
const nbButterflies = 100;
var conf, scene, camera, cameraCtrl, light, renderer;
var whw, whh;
var butterflies;
var bodyTexture, wingTexture1, wingTexture2, wingTexture3, bodyTexture4, wingTexture4;
var destination = new THREE.Vector3();
var mouse = new THREE.Vector2();
var mouseOver = false;
var mousePlane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0);
var mousePosition = new THREE.Vector3();
var raycaster = new THREE.Raycaster();
function init() {
conf = {
attraction: 0.03,
velocityLimit: 1.2,
move: true,
followMouse: true,
shuffle: shuffle
};
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000);
cameraCtrl = new THREE.OrbitControls(camera);
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
initScene();
const gui = new dat.GUI();
gui.add(conf, 'move');
gui.add(conf, 'followMouse');
gui.add(conf, 'attraction', 0.01, 0.1);
gui.add(conf, 'velocityLimit', 0.1, 2);
gui.add(conf, 'shuffle');
gui.close();
onWindowResize();
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onMouseMove, false);
// document.addEventListener('mouseover', function () { mouseOver = true; }, false);
document.addEventListener('mouseout', function () { mouseOver = false; }, false);
animate();
};
function initScene() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
camera.position.z = 75;
bodyTexture = new THREE.TextureLoader().load('https://klevron.github.io/codepen/butterflies/b1.png');
wingTexture1 = new THREE.TextureLoader().load('https://klevron.github.io/codepen/butterflies/b1w.png');
wingTexture2 = new THREE.TextureLoader().load('https://klevron.github.io/codepen/butterflies/b2w.png');
wingTexture3 = new THREE.TextureLoader().load('https://klevron.github.io/codepen/butterflies/b3w.png');
bodyTexture4 = new THREE.TextureLoader().load('https://klevron.github.io/codepen/butterflies/b4.png');
wingTexture4 = new THREE.TextureLoader().load('https://klevron.github.io/codepen/butterflies/b4w.png');
butterflies = [];
for (var i = 0; i < nbButterflies; i++) {
var b = new Butterfly();
butterflies.push(b);
scene.add(b.o3d);
}
shuffle();
}
function animate() {
requestAnimationFrame(animate);
TWEEN.update();
cameraCtrl.update();
if (conf.move) {
for (var i = 0; i < butterflies.length; i++) {
butterflies[i].move();
}
}
renderer.render(scene, camera);
};
function shuffle() {
for (var i = 0; i < butterflies.length; i++) {
butterflies[i].shuffle();
}
}
function Butterfly() {
this.minWingRotation = -Math.PI / 6;
this.maxWingRotation = Math.PI / 2 - 0.1;
this.wingRotation = 0;
this.velocity = new THREE.Vector3(rnd(1, true), rnd(1, true), rnd(1, true));
this.destination = destination;
var confs = [
{ bodyTexture: bodyTexture, bodyW: 10, bodyH: 15, wingTexture: wingTexture1, wingW: 10, wingH: 15, wingX: 5.5 },
{ bodyTexture: bodyTexture, bodyW: 6, bodyH: 9, wingTexture: wingTexture2, wingW: 15, wingH: 20, wingX: 7.5 },
{ bodyTexture: bodyTexture, bodyW: 8, bodyH: 12, wingTexture: wingTexture3, wingW: 10, wingH: 15, wingX: 5.5 },
{ bodyTexture: bodyTexture4, bodyW: 6, bodyH: 10, bodyY: 2, wingTexture: wingTexture4, wingW: 15, wingH: 20, wingX: 8 },
];
this.init(confs[Math.floor(rnd(4))]);
}
Butterfly.prototype.init = function (bconf) {
var geometry = new THREE.PlaneGeometry(bconf.wingW, bconf.wingH);
var material = new THREE.MeshBasicMaterial({ transparent: true, map: bconf.wingTexture, side: THREE.DoubleSide, depthTest: false });
var lwmesh = new THREE.Mesh(geometry, material);
lwmesh.position.x = -bconf.wingX;
this.lwing = new THREE.Object3D();
this.lwing.add(lwmesh);
var rwmesh = new THREE.Mesh(geometry, material);
rwmesh.rotation.y = Math.PI;
rwmesh.position.x = bconf.wingX;
this.rwing = new THREE.Object3D();
this.rwing.add(rwmesh);
geometry = new THREE.PlaneGeometry(bconf.bodyW, bconf.bodyH);
material = new THREE.MeshBasicMaterial({ transparent: true, map: bconf.bodyTexture, side: THREE.DoubleSide, depthTest: false });
this.body = new THREE.Mesh(geometry, material);
if (bconf.bodyY) this.body.position.y = bconf.bodyY;
// this.body.position.z = -0.1;
this.group = new THREE.Object3D();
this.group.add(this.body);
this.group.add(this.lwing);
this.group.add(this.rwing);
this.group.rotation.x = Math.PI / 2;
this.group.rotation.y = Math.PI;
this.setWingRotation(this.wingRotation);
this.initTween();
this.o3d = new THREE.Object3D();
this.o3d.add(this.group);
};
Butterfly.prototype.initTween = function () {
var duration = limit(conf.velocityLimit - this.velocity.length(), 0.1, 1.5) * 1000;
this.wingRotation = this.minWingRotation;
this.tweenWingRotation = new TWEEN.Tween(this)
.to({ wingRotation: this.maxWingRotation }, duration)
.repeat(1)
.yoyo(true)
// .easing(TWEEN.Easing.Cubic.InOut)
.onComplete(function(object) {
object.initTween();
})
.start();
};
Butterfly.prototype.move = function () {
var destination;
if (mouseOver && conf.followMouse) {
destination = mousePosition;
} else {
destination = this.destination;
}
var dv = destination.clone().sub(this.o3d.position).normalize();
this.velocity.x += conf.attraction * dv.x;
this.velocity.y += conf.attraction * dv.y;
this.velocity.z += conf.attraction * dv.z;
this.limitVelocity();
// update position & rotation
this.setWingRotation(this.wingRotation);
this.o3d.lookAt(this.o3d.position.clone().add(this.velocity));
this.o3d.position.add(this.velocity);
};
Butterfly.prototype.limitVelocity = function (y) {
this.velocity.x = limit(this.velocity.x, -conf.velocityLimit, conf.velocityLimit);
this.velocity.y = limit(this.velocity.y, -conf.velocityLimit, conf.velocityLimit);
this.velocity.z = limit(this.velocity.z, -conf.velocityLimit, conf.velocityLimit);
};
Butterfly.prototype.setWingRotation = function (y) {
this.lwing.rotation.y = y;
this.rwing.rotation.y = -y;
};
Butterfly.prototype.shuffle = function () {
this.velocity = new THREE.Vector3(rnd(1, true), rnd(1, true), rnd(1, true));
var p = new THREE.Vector3(rnd(1, true), rnd(1, true), rnd(1, true)).normalize().multiplyScalar(100);
this.o3d.position.set(p.x, p.y, p.z);
var scale = rnd(0.4) + 0.1;
this.o3d.scale.set(scale, scale, scale);
}
function limit(number, min, max) {
return Math.min(Math.max(number, min), max);
}
function rnd(max, negative) {
return negative ? Math.random() * 2 * max - max : Math.random() * max;
}
function onWindowResize() {
whw = window.innerWidth / 2;
whh = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onMouseMove(event) {
// if (cameraCtrl.getState()!=-1) return;
var v = new THREE.Vector3();
camera.getWorldDirection(v);
v.normalize();
// console.log(v);
mousePlane.normal = v;
mouseOver = true;
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
raycaster.ray.intersectPlane(mousePlane, mousePosition);
}
init();
I've got a double click function to allow the user to double click on a car model and it displays which objects have been intersected; e.g. wipers, grille, tyres and so on, and this function displays them in a list with the number of items the double click intersected with.
However, I am now trying to get it so that when a certain part of the car is clicked, for example, the tyres, it will display a paragraph with information on them. I can see how this is just a case of checking the name of the intersecting object and then displaying the relevant text if it intersects it, but every time I go to do what I think is right, it just breaks the already existing function to the point where the whole thing won't run.
I'm not exactly a JavaScript or Three.js pro at all, but trying to progress my function further is proving to be rather difficult.
Any suggestions? I've included the entire double click function, however it's when it's checking if there has been intersections near the bottom that is where the alterations need to be.
// On Mouse double click event function
function onDoubleClick(event) {
// Set the mouse down flag to false
mouseDown = false;
// Canvas x (left) and y (top) position
var canvasLeft = 0;
var canvasTop = 0;
// "event.clientX" is the mouse x position. "event.clientY" is the mouse y position
var tempX = event.clientX - canvasLeft;
var tempY = event.clientY - canvasTop;
// Create a normalised vector in 2d space
var vector = new THREE.Vector3((tempX / window.innerWidth) * 2 - 1, - (tempY / innerHeight) * 2 + 1, 0.5);
// Unproject a 2D point into the 3D word
// Use the camera projection matrix to transform the vector to the 3D world space
vector.unproject(camera);
// Send a ray in the direction the user has clicked from the cameras position
var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
// Check if the ray has intersected with any objects and get intersections
var intersects = raycaster.intersectObjects(objects, true);
// Check if intersected with objects
if (intersects.length > 0) {
var tempStr = "Number of items: " + intersects.length + " ";
// List the items that were hit
for(var i=0; i < intersects.length; i++){
if(intersects[i].object.name != ""){
// The mesh name set above
tempStr += " | Name: " + intersects[i].object.name;
} else {
// The names inside the model
tempStr += " | Name: " + intersects[i].object.parent.name;
}
}
//Debug information
document.getElementById("debugInfo").innerHTML = tempStr + ".<br>";
//END
}
}
EDIT:
This is the entire code for the javascript file, as altering elements of the double click function seems to stop the page from loading.
window.onload = init;
// declare variables
var scene,camera,renderer, container;
var controls, guiControls, datGUI;
var grid, color;
var cube, cubeGeometry, cubeMaterial;
var plane, planeGeometry, planeMaterial;
var skyBoxMesh, texture_placeholder;
var spotLight;
var stats;
// Handles the mouse events.
var mouseOverCanvas;
var mouseDown;
// An array of objects that can be clicked on
var objects = [];
//DAE models
var showroom ,carOld, carNew;
var daeObject;
var animations;
var kfAnimations = [];
var kfAnimationsLength = 0;
var lastFrameCurrentTime = [];
var clock = new THREE.Clock();
var mouseOverCanvas, mouseDown;
var objectsClick=[];
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
//creates empty scene
scene = new THREE.Scene();
//camera
camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, .1, 500);
camera.position.x = 40;
camera.position.y = 40;
camera.position.z = 40;
camera.lookAt(scene.position);
//renderer
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setClearColor(0xe6f2ff);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMapSoft = true;
container.appendChild( renderer.domElement );
// Add an event to set if the mouse is over our canvas
renderer.domElement.onmouseover=function(e){ mouseOverCanvas = true; }
renderer.domElement.onmousemove=function(e){ mouseOverCanvas = true; }
renderer.domElement.onmouseout=function(e){ mouseOverCanvas = false; }
renderer.domElement.onmousedown=function(e){ mouseDown = true; }
renderer.domElement.onmouseup=function(e){ mouseDown = false; }
// Double Click Event. Set a function called "onDoubleClick"
renderer.domElement.ondblclick=onDoubleClick;
// stats
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
//adds controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.addEventListener('change', render);
var ambient = new THREE.AmbientLight( 0xadad85 );
scene.add( ambient );
//---------- creates grid ---------------
grid = new THREE.GridHelper(50,5);
color= new THREE.Color("rgb(255,0,0)");
grid.setColors( 0x000000);
scene.add(grid);
//----------- creates cube --------------
cubeGeometry = new THREE.BoxGeometry(5,5,5);
cubeMaterial = new THREE.MeshPhongMaterial({color: 0xff3300});
cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.x = 0;
cube.position.y = 6;
cube.position.z = 2.5;
cube.castShadow = true;
scene.add(cube);
//----------- creates plane ---------------
planeGeomenty= new THREE.PlaneGeometry(100,100,100);
planeMaterial = new THREE.MeshLambertMaterial({color: 0x00cc00});
plane = new THREE.Mesh(planeGeomenty, planeMaterial);
//position the add objects to the scene
plane.rotation.x = -.5*Math.PI;
plane.receiveShadow = true;
scene.add(plane);
//------------- skyBox --------------
texture_placeholder = document.createElement('canvas');
texture_placeholder.width = 128;
texture_placeholder.height = 128;
var context = texture_placeholder.getContext('2d');
context.fillStyle = 'rgb(200,200, 200)';
context.fillRect(0, 0,texture_placeholder.width, texture_placeholder.height);
var materials = [
loadTexture('images/skybox/posX.jpg'),
loadTexture('images/skybox/negX.jpg'),
loadTexture('images/skybox/posY.jpg'),
loadTexture('images/skybox/negY.jpg'),
loadTexture('images/skybox/posZ.jpg'),
loadTexture('images/skybox/negZ.jpg')
];
skyBoxMesh = new THREE.Mesh(new THREE.BoxGeometry(500,500,500,7,7,7),
new THREE.MeshFaceMaterial(materials));
skyBoxMesh.scale.x = -1;
scene.add(skyBoxMesh);
//---------- loads collada files -----------
loadCollada();
daeObject = cube;
// initialise datGUI controls values
guiControls = new function() {
this.rotationY = 0.0;
this.positionX = 0.0;
this.positionY = 0.0;
this.positionZ = -10;
this.lightX = 20;
this.lightY = 35;
this.lightZ = 40;
this.intensity = 1;
this.distance = 0;
this.angle = 1.570;
this.target = cube;
}
//add spotLight with starting parameters
spotLight = new THREE.SpotLight(0xffffff);
spotLight.castShadow = true;
spotLight.position.set(20,35,40);
spotLight.intensity = guiControls.intensity;
spotLight.distance = guiControls.distance;
spotLight.angle = guiControls.angle;
scene.add(spotLight);
//adds controls on the scene
datGUI = new dat.GUI();
// datGUI.add(guiControls, 'positionZ', 0, 1);
datGUI.add(guiControls, 'positionZ', -10, 25, 0.5). name("Move the car");
datGUI.add(guiControls, 'rotationY', 0, 1).name('Rotate the car');
datGUI.add(guiControls, 'lightX', -60, 180);
datGUI.add(guiControls, 'lightY', 0, 180);
datGUI.add(guiControls, 'lightZ', -60, 180);
datGUI.add(guiControls, 'target',[ 'cube','Modern Mini', 'Classic Mini']).onChange(function() {
if(guiControls.target == 'cube'){
spotLight.target = cube;
daeObject = cube;
}
else if(guiControls.target == 'Classic Mini'){
spotLight.target = carOld;
daeObject = carOld;
}
else if(guiControls.target = 'Modern Mini'){
spotLight.target = carNew;
daeObject = carNew;
}
});
datGUI.add(guiControls, 'intensity', 0.01, 5).onChange(function (value){
spotLight.intensity = value;
});
datGUI.add(guiControls, 'distance', 0, 1000).onChange(function (value){
spotLight.distance = value;
});
datGUI.add(guiControls, 'angle', 0.001, 1.570).onChange(function (value){
spotLight.angle = value;
});
datGUI.close();
container.appendChild(renderer.domElement);
window.addEventListener( 'resize', onWindowResize, false );
}
//------------------------- END INIT() ----------------------------
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function loadCollada() {
//--- Loads the Classic Mini ---
colladaLoader = new THREE.ColladaLoader();
colladaLoader.options.convertUpAxis = true;
colladaLoader.load( 'dae_files/ClassicMini.dae', function ( collada ) {
carOld = collada.scene; // stores dae file to a global variable
carOld.position.set( 14.5, 1.8, -10 );
carOld.scale.set( 0.04, 0.04, 0.04 );
carOld.traverse(function (child) {
child.castShadow = true;
child.receiveShadow = true;
});
carOld.updateMatrix();
carOld.name = "Classic";
scene.add( carOld );
objects.push( carOld );
} );
//--- loads Modern Mini ---
colladaLoader = new THREE.ColladaLoader();
colladaLoader.options.convertUpAxis = true;
colladaLoader.load( 'dae_files/ModernMini.dae', function ( collada ) {
carNew = collada.scene;
carNew.position.set( -14.5, 6.3, -10 );
carNew.scale.set( 0.06, 0.06, 0.06 );
// creates shadow
carNew.traverse(function (child) {
child.castShadow = true;
child.receiveShadow = true;
});
carNew.updateMatrix();
carNew.name = "Modern";
scene.add( carNew );
objects.push( carNew );
} );
//--- loads the Showroom ---
colladaLoader = new THREE.ColladaLoader();
colladaLoader.options.convertUpAxis = true;
colladaLoader.load( 'dae_files/roomAnim2.dae', function collada( collada ) {
showroom = collada.scene;
animations = collada.animations;
kfAnimationsLength = animations.length;
// Initialise last frame current time.
for ( var i = 0; i < kfAnimationsLength; i++ ) {
lastFrameCurrentTime[i] = 0;
}
// Get all the key frame animations.
for ( var i = 0; i < kfAnimationsLength; i++ ) {
var anim = animations[ i ];
var keyFrameAnim = new THREE.KeyFrameAnimation( anim );
keyFrameAnim.timeScale = 1;
keyFrameAnim.loop = false;
kfAnimations.push( keyFrameAnim );
anim = kfAnimations[i];
anim.play();
}
showroom.position.set(0, 0, -20);
showroom.scale.set(0.06, 0.06, 0.06);
showroom.traverse(function (child) {
child.castShadow = true;
child.receiveShadow = true;
});
showroom.updateMatrix();
scene.add( showroom );
animate();
} );
}
// On Mouse double click event function
function onDoubleClick(event) {
// Set the mouse down flag to false
mouseDown = false;
// Canvas x (left) and y (top) position
var canvasLeft = 0;
var canvasTop = 0;
// "event.clientX" is the mouse x position. "event.clientY" is the mouse y position
var tempX = event.clientX - canvasLeft;
var tempY = event.clientY - canvasTop;
// Create a normalised vector in 2d space
var vector = new THREE.Vector3((tempX / window.innerWidth) * 2 - 1, - (tempY / innerHeight) * 2 + 1, 0.5);
// Unproject a 2D point into the 3D word
// Use the camera projection matrix to transform the vector to the 3D world space
vector.unproject(camera);
// Send a ray in the direction the user has clicked from the cameras position
var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
// Check if the ray has intersected with any objects and get intersections
var intersects = raycaster.intersectObjects(objects, true);
// Check if intersected with objects
if (intersects.length > 0) {
var tempStr = "Number of items: " + intersects.length + " ";
// List the items that were hit
for(var i=0; i < intersects.length; i++){
if(intersects[i].object.name != ""){
// The mesh name set above
tempStr += " | Name: " + intersects[i].object.name;
} else {
// The names inside the model
tempStr += " | Name: " + intersects[i].object.parent.name;
}
}
//Debug information
document.getElementById("debugInfo").innerHTML = tempStr + ".<br>";
//END
}
}
function loopAnimations(){
// Loop through all animations
for ( var i = 0; i < kfAnimationsLength; i++ ) {
// Check if the animation is player and not paused.
if(kfAnimations[i].isPlaying && !kfAnimations[i].isPaused){
if(kfAnimations[i].currentTime == lastFrameCurrentTime[i]) {
kfAnimations[i].stop();
//kfAnimations[i].play();
lastFrameCurrentTime[i] = 0;
}
}
}
}
function play_pauseAnim() {
//checks is there animation and is it paused
if(kfAnimationsLength > 0) {
if(kfAnimations[0].isPlaying) {
for(i = 0; i < kfAnimationsLength; i++){
kfAnimations[i].stop();
}
}else {
for(i = 0; i < kfAnimationsLength; i++) {
lastFrameCurrentTime[i] = 0;
//kfAnimations[i].play(kfAnimations[i].currentTime);
kfAnimations[i].play(0);
}
}
}
}
function checkTime(){
if(kfAnimationsLength > 0) {
if(kfAnimations[0].isPlaying) {
if(kfAnimations[0].currentTime > 3){
play_pauseAnim();
}
}
}
}
// create a render loop to draw the scene 60 times per second
function render() {
//checkTime();
daeObject.rotation.y += guiControls.rotationY;
//if (daeObject.position.z < 25) {
daeObject.position.z = guiControls.positionZ;
//}
spotLight.rotation.x += guiControls.rotationX;
spotLight.rotation.y += guiControls.rotationY;
spotLight.rotation.z += guiControls.rotationZ;
stats.update();
}
function animate () {
var deltaTime = clock.getDelta();
for ( var i = 0; i < kfAnimationsLength; i++ ) {
// Get a key frame animation.
var anim = kfAnimations[i];
anim.update( deltaTime );
}
loopAnimations();
requestAnimationFrame(animate);
// Update last frame current time.
for ( var i = 0; i < kfAnimationsLength; i++ ) {
lastFrameCurrentTime[i] = kfAnimations[i].currentTime;
}
render();
renderer.render(scene, camera);
}
// Loads skybox texture
function loadTexture(path) {
var texture = new THREE.Texture(texture_placeholder);
var material = new THREE.MeshBasicMaterial({
map: texture,
overdraw: 0.5
});
var image = new Image();
image.onload = function() {
texture.image = this;
texture.needsUpdate = true;
};
image.src = path;
return material;
}
Macast,
Please, check if you haven't forgotten in your code:
var objets = [];
var raycaster = new THREE.Raycaster();
And for each part of the car this line :
objects.push( mesh );
Ex:
var geometry = new THREE.RingGeometry( 1, 5, 32 );
var material = new THREE.MeshBasicMaterial( { color: 0xff0000, side: THREE.DoubleSide } );
var simpleTire = new THREE.Mesh( geometry, material );
simpleTire.name = 'tire';
objects.push( simpleTire );
scene.add( simpleTire );
Then, it's simple :
if ( intersects.length > 0 ) {
switch(intersects[0].object.name){
case 'tire':
console.log('A pretty red tire');
break;
case 'motor':
console.log('An electric motor');
break;
}
}