Three JS: How to add images on each vertices of icosahedron - three.js

I'm new to Three js, i was trying to create a rotating icosahedron with small icon kind of images on each vertex using three js, i could create the icosahedron and make it rotate but I'm not able to attach images on each vertex of it. Can anyone help me do this?
Please check the js fiddle link of what i could acheive so far:
<div id="container"></div>
var $container = $('#container');
var renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
var camera = new THREE.PerspectiveCamera(80, 1, 0.1, 10000);
var scene = new THREE.Scene();
var Ico;
scene.add(camera);
renderer.setSize(576, 576);
// Making the canvas responsive
function onWindowResize() {
var screenWidth = $(window).width();
if (screenWidth <= 479) {
renderer.setSize(300, 300);
} else if (screenWidth <= 767) {
renderer.setSize(400, 400);
} else if (screenWidth <= 991) {
renderer.setSize(500, 500);
} else if (screenWidth <= 1200) {
renderer.setSize(450, 450);
} else if (screenWidth <= 1366) {
renderer.setSize(550, 550);
}
camera.updateProjectionMatrix();
}
onWindowResize();
window.addEventListener('resize', onWindowResize, false);
$container.append(renderer.domElement);
// Camera
camera.position.z = 200;
// Material
var greyMat = new THREE.MeshPhongMaterial({
color: new THREE.Color("rgb(125,127,129)"),
emissive: new THREE.Color("rgb(125,127,129)"),
specular: new THREE.Color("rgb(125,127,129)"),
shininess: "100000000",
shading: THREE.FlatShading,
transparent: 1,
opacity: 1
});
var L2 = new THREE.PointLight();
L2.position.z = 1900;
L2.position.y = 1850;
L2.position.x = 1000;
scene.add(L2);
camera.add(L2);
var Ico = new THREE.Mesh(new THREE.IcosahedronGeometry(125, 1), greyMat);
Ico.rotation.z = 0.5;
scene.add(Ico);
var trackballControl = new THREE.TrackballControls(camera, renderer.domElement);
trackballControl.rotateSpeed = 1.0;
trackballControl.noZoom = true;
function update() {
Ico.rotation.x += 2 / 500;
Ico.rotation.y += 2 / 500;
}
// Render
function render() {
trackballControl.update();
requestAnimationFrame(render);
renderer.render(scene, camera);
update();
}
render();
https://jsfiddle.net/arunvenugopal11/uoxtmtnr/
Thanks in advance :)

You can use THREE.Sprite(), like this:
var txtLoader = new THREE.TextureLoader();
txtLoader.setCrossOrigin(""); // you don't need it, if you get images from your web site
var textures = [ // you can have a full set of 42 images, I used just 2
"https://threejs.org/examples/textures/UV_Grid_Sm.jpg",
"https://threejs.org/examples/textures/colors.png"
];
var direction = new THREE.Vector3(); // we'll re-use it in the loop
Ico.geometry.vertices.forEach(function(vertex, index){
var texture = txtLoader.load(textures[index % 2]); // when you have a full set of images, you don't need that operation with modulus '%'
var spriteMaterial = new THREE.SpriteMaterial({map: texture});
var sprite = new THREE.Sprite(spriteMaterial);
sprite.scale.setScalar(10); // the size is up to you
direction.copy(vertex).normalize(); // direction is just a normalized vertex
sprite.position.copy(vertex).addScaledVector(direction, 10); // add scaled direction to the position of a sprite
Ico.add(sprite);
});
jsfiddle example. r85

Related

Threejs & PhysiJs physics engine not updated when Mesh rotate

I am a beginner of Threejs.
I created a Box Mesh and a Sphere Mesh and applied physics using physiJs.
What I want to do is to hit the ball when the Box Mesh rotates and passing through the ball.
However, when the box mesh rotates, it passes without hitting the ball.
I think the box mesh loses physicality when it starts spinning.
function createBall () {
var ball = null;
var ballGeo = new THREE.SphereGeometry(1.5, 30, 30);
var ballMat = Physijs.createMaterial(
new THREE.MeshBasicMaterial({specular: 0x111111})
, 0.3, 0.1
);
ball = new Physijs.SphereMesh(
ballGeo,
ballMat,
5
);
ball.position.set(30, 10, 0);
scene.add(ball);
}
function createBox () {
var material = Physijs.createMaterial(
new THREE.MeshLambertMaterial(
{
color: 0x8041D9,
}), 5, 0.3);
var boxMesh = new THREE.BoxGeometry(5, 5, 25);
box = new Physijs.BoxMesh(
boxMesh,
material,
5
);
box.position.z = 20;
scene.add(box);
}
function createHeightMap() {
var initColor = new THREE.Color( 0x00ff00 );
initColor.setHSL( 0.25, 0.85, 0.5 );
var ground_material = Physijs.createMaterial(
new THREE.MeshPhongMaterial(
{ color: 0x47C83E}
),
.5,
.5
);
var ground_geometry = new THREE.PlaneGeometry(800, 800, 100, 100);
ground = new Physijs.HeightfieldMesh(
ground_geometry,
ground_material,
0, // 질량
100, // PlaneGeometry 의 분할 세그먼트랑 똑같은 값으로 줘야 한다.
100 // PlaneGeometry 의 분할 세그먼트랑 똑같은 값으로 줘야 한다.
);
ground.position.y = -10;
ground.rotation.x = Math.PI / -2;
ground.receiveShadow = true;
var meshes = [];
var controls = new function () {
this.startRotate = false;
this.addBall = function () {
createBall();
};
this.addBox = function () {
createBox();
};
this.clearMeshes = function () {
meshes.forEach(function (e) {
scene.remove(e);
});
meshes = [];
}
};
var gui = new dat.GUI();
gui.add(controls, 'addBall');
gui.add(controls, 'addBox');
gui.add(controls, 'clearMeshes');
gui.add(controls, 'startRotate').onChange(function (e) {
isStartRoate = e;
});
return ground;
}
render = function () {
stats.update();
if (isStartRoate === true) {
var rotateMatrix = new THREE.Matrix4();
rotateMatrix.identity();
rotateMatrix.makeRotationY(0.05);
box.applyMatrix(rotateMatrix);
}
requestAnimationFrame(render);
renderer.render(scene, camera);
var axes = new THREE.AxesHelper(30);
scene.add(axes);
scene.simulate(undefined, 2);
};
function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
// Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
window.onload = initScene;
below is codepen link
codepen
It seems like physicality not updated.
please give me any idea
When using Physijs, you should use setLinearVelocity() or setAngularVelocity() in order to update the position and rotation of your objects in a physical correct way. The updated codepen shows this approach:
https://codepen.io/anon/pen/YJmajN
Besides, the way you create AxesHelper in the render loop is no good approach. Create the helper once during the setup up of your scene.

Three.js, moving a partical along an EllipseCurve

I know questions related to my problem have been asked and answered before but three.js changed a lot in the last couple years and I'm having trouble finding what I need in the currently available examples.
I have an elliptical curve that I'd like to run particles along. My code runs without error but it doesn't actually move the particle anywhere. What am I missing?
var t = 0;
var curve = new THREE.EllipseCurve( .37, .15, .35, .25, 150, 450, false, 0 );
var points = curve.getPoints( 50 );
var curveGeometry = new THREE.BufferGeometry().setFromPoints( points );
var particleGeometry = new THREE.Geometry();
var particleMap = new THREE.TextureLoader().load( "/img/spark.png" );
var vertex = new THREE.Vector3();
vertex.x = points[0].x;
vertex.y = points[0].y;
vertex.z = 0;
particleGeometry.vertices.push(vertex);
particleMaterial = new THREE.PointsMaterial({
size: .05,
map: particleMap,
blending: THREE.AdditiveBlending,
depthTest: false,
transparent : true
});
particles = new THREE.Points( particleGeometry, particleMaterial );
scene.add(particles);
animate();
function animate() {
if (t <= 1) {
particles.position = curveGeometry.getPointAt(t)
t += 0.005
} else {
t = 0;
}
requestAnimationFrame( animate );
render();
}
function render() {
renderer.render( scene, camera );
}
Just a rough concept of how you can do it, using THREE.Geometry():
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 50);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor(0x404040);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var grid = new THREE.GridHelper(40, 40, "white", "gray");
grid.rotation.x = Math.PI * -0.5;
scene.add(grid);
var curve = new THREE.EllipseCurve(0, 0, 20, 20, 0, Math.PI * 2, false, 0);
// using of .getPoints(division) will give you a set of points of division + 1
// so, let's get the points manually :)
var count = 10;
var inc = 1 / count;
var pointAt = 0;
var points = [];
for (let i = 0; i < count; i++) {
let point = curve.getPoint(pointAt); // get a point of THREE.Vector2()
point.z = 0; // geometry needs points of x, y, z; so add z
point.pointAt = pointAt; // save position along the curve in a custom property
points.push(point);
pointAt += inc; // increment position along the curve for next point
}
var pointsGeom = new THREE.Geometry();
pointsGeom.vertices = points;
console.log(points);
var pointsObj = new THREE.Points(pointsGeom, new THREE.PointsMaterial({
size: 1,
color: "aqua"
}));
scene.add(pointsObj);
var clock = new THREE.Clock();
var time = 0;
render();
function render() {
requestAnimationFrame(render);
time = clock.getDelta();
points.forEach(p => {
p.pointAt = (p.pointAt + time * 0.1) % 1; // it always will be from 0 to 1
curve.getPoint(p.pointAt, p); //re-using of the current point
});
pointsGeom.verticesNeedUpdate = true;
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Adding a different colour to each side of this obj

I've recreated a bag model for my application and exported it into ThreeJs as an .obj:
I've assigned a different colour to every face found in the models geometry like this:
var geometry = new THREE.Geometry().fromBufferGeometry( bagMesh.children[0].geometry );
for (var i = 0; i < geometry.faces.length; i ++ ) {
var face = geometry.faces[i];
// 7 & 8 = front side
// can we flip its normal?
if(i === 7 || i === 8) {
face.color.setHex( 0xff0000 );
} else {
face.color.setHex( Math.random() * 0xffffff );
}
}
geometry.translate( 0, -1, 0.75);
mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial({ vertexColors: THREE.FaceColors, side: THREE.DoubleSide }) );
scene.add(mesh);
I've identified the faces of the front-side at indices 7 and 8 of the faces array and turned them red.
The problem is that this colour can be seen when I look inside of the bag too:
I realize that this is because I've set the object to THREE.DoubleSide but if I change it to THREE.FrontSide then the sides only partially visible.
So my question is how do I assign a different unique colour to each side (all 11 of them, counting the inside too) without that colour appearing on that sides respective opposite?
I'm trying to keep things simple here by only using colours as opposed to mapping images onto it, which is what I'll want to eventually get to.
Note - My previous model solved this problem by treating each side as a seperate mesh but this caused other issues like z-hiding and flickering problems.
Thanks
EDIT
#WestLangley I've setup a fiddle to demonstrate what you added in your comment. Assuming that I got it right it didn't have the desired affect:
(function onLoad() {
var canvasElement;
var width, height;
var scene, camera;
var renderer;
var controls;
var pivot;
var bagMesh;
var planeMesh;
const objLoader = new THREE.OBJLoader2();
const fileLoader = new THREE.FileLoader();
init();
function init() {
container = document.getElementById('container');
initScene();
addGridHelper();
addCamera();
addLighting();
addRenderer();
addOrbitControls();
loadPlaneObj();
// Logic
var update = function() {};
// Draw scene
var render = function() {
renderer.render(scene, camera);
};
// Run game logic (update, render, repeat)
var gameLoop = function() {
requestAnimationFrame(gameLoop);
update();
render();
};
gameLoop();
}
/**** Basic Scene Setup ****/
function initScene() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0xd3d3d3);
var axis = new THREE.AxesHelper();
scene.add(axis);
}
function addCamera() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(3,3,3);
scene.add(camera);
}
function addGridHelper() {
var planeGeometry = new THREE.PlaneGeometry(2000, 2000);
planeGeometry.rotateX(-Math.PI / 2);
var planeMaterial = new THREE.ShadowMaterial({
opacity: 0.2
});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.position.y = -200;
plane.receiveShadow = true;
scene.add(plane);
var helper = new THREE.GridHelper(2000, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper();
scene.add(axis);
}
// *********** Lighting settings **********************
function addLighting() {
var light = new THREE.HemisphereLight(0xffffff, 0xffffff, 1);
scene.add(light);
}
// ************** Material settings **************
function setMaterial(materialName) {
// get the object from the scene
var bagMesh = scene.getObjectByName('bag');
var material;
if (!materialName) {
materialName = materials.material;
}
if (bagMesh) {
var colour = parseInt(materials.colour);
switch (materialName) {
case 'MeshBasicMaterial':
material = new THREE.MeshBasicMaterial({
color: colour
});
break;
case 'MeshDepthMaterial':
material = new THREE.MeshDepthMaterial();
break;
case 'MeshLambertMaterial':
material = new THREE.MeshLambertMaterial({
color: colour
});
break;
case 'MeshNormalMaterial':
material = new THREE.MeshNormalMaterial();
break;
case 'MeshPhongMaterial':
material = new THREE.MeshPhongMaterial({
color: colour
});
break;
case 'MeshPhysicalMaterial':
material = new THREE.MeshPhysicalMaterial({
color: colour
});
break;
case 'MeshStandardMaterial':
material = new THREE.MeshStandardMaterial({
color: colour
});
break;
case 'MeshToonMaterial':
material = new THREE.MeshToonMaterial({
color: colour
});
break;
}
bagMesh.children.forEach(function(c) {
c.material = material;
});
}
}
function setMaterialColour(colour) {
materials.colour = colour;
setMaterial(null);
}
// ************** End of materials ***************
function addRenderer() {
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
}
function addOrbitControls() {
var controls = new THREE.OrbitControls(camera, renderer.domElement);
}
function addPivot() {
var cubeGeo = new THREE.BoxBufferGeometry(5, 5, 5);
var cubeMat = new THREE.MeshBasicMaterial();
pivot = new THREE.Mesh(cubeGeo, cubeMat);
bagMesh.position.x -= 15;
bagMesh.position.z -= 55;
pivot.add(bagMesh);
pivot.add(handle);
scene.add(pivot);
}
function loadPlaneObj() {
loadObj('Plane', 'https://rawgit.com/Katana24/threejs-experimentation/master/models/Plane.obj', 'https://rawgit.com/Katana24/threejs-experimentation/master/models/Plane.mtl', addPlaneToSceneSOAnswer);
}
function loadObj(objName, objUrl, mtlUrl, onLoadFunc) {
var onLoadMtl = function(materials) {
objLoader.setModelName(objName);
objLoader.setMaterials(materials);
fileLoader.setPath('');
fileLoader.setResponseType('arraybuffer');
fileLoader.load(objUrl,
function(onLoadContent) {
var mesh = objLoader.parse(onLoadContent);
onLoadFunc(mesh);
},
function(inProgress) {},
function(error) {
throw new Error('Couldnt load the model: ', error);
});
};
objLoader.loadMtl(mtlUrl, objName+'.mtl', onLoadMtl);
}
function addPlaneToSceneSOAnswer(mesh) {
var frontMaterial = new THREE.MeshBasicMaterial( { color : 0xff0000, side: THREE.FrontSide } );
var backMaterial = new THREE.MeshBasicMaterial( { color : 0x00ff00, side: THREE.BackSide } );
var geometry = new THREE.Geometry().fromBufferGeometry( mesh.children[0].geometry );
var length = geometry.faces.length;
geometry.faces.splice(14, 1);
for (var i = 0; i < geometry.faces.length; i ++ ) {
var face = geometry.faces[i];
face.color.setHex(Math.random() * 0xffffff);
}
mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial({ vertexColors: THREE.FaceColors, side: THREE.DoubleSide }) );
mesh.material.side = THREE.FrontSide;
var mesh2 = new THREE.Mesh( geometry, mesh.material.clone() );
mesh2.material.side = THREE.BackSide;
// mesh2.material.vertexColors = THREE.NoColors;
mesh2.material.vertexColors = [new THREE.Color(0xff0000), new THREE.Color(0x00ff00), new THREE.Color(0x0000ff)];
mesh.add( mesh2 );
scene.add(mesh);
}
})();
body {
background: transparent;
padding: 0;
margin: 0;
font-family: sans-serif;
}
#canvas {
margin: 10px auto;
width: 800px;
height: 350px;
margin-top: -44px;
}
<body>
<div id="container"></div>
<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/libs/dat.gui.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/loaders/MTLLoader.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/loaders/LoaderSupport.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/loaders/OBJLoader2.js"></script>
</body>
What am I missing here?
I followed along with Don's suggestion about the different materials but didn't know entirely what he meant.
I examined this question which details setting the materialIndex. I investigated what this means and what it means is that when you pass a geometry and an array of materials to a mesh like this:
mesh = new THREE.Mesh( geometry, [frontMaterial, backMaterial, otherMaterial] );
then that face will get the material (frontMaterial because it's at position 0) assigned to it.
Coming back to my original question, I decided to simplify (for the moment) and see if I could apply what I want to just a Plane mesh exported from Blender.
The Plane has two Faces when added into 3JS. I found I could flip each face or assign a different material to each but I needed to duplicate the faces in order to achieve this:
function addMeshTwoToScene() {
var frontMaterial = new THREE.MeshBasicMaterial( { color : 0xff0000, side: THREE.FrontSide } );
var backMaterial = new THREE.MeshBasicMaterial( { color : 0x00ff00, side: THREE.BackSide } );
var geometry = new THREE.Geometry().fromBufferGeometry( planeMesh.children[0].geometry );
// Duplicates the face
var length = geometry.faces.length;
for (var i = 0; i < length; i++ ) {
var face = geometry.faces[i];
var newFace = Object.assign({}, face);
geometry.faces.push(newFace);
}
for (var i = 0; i < geometry.faces.length; i ++ ) {
var face = geometry.faces[i];
if(i === 0 || i === 3) {
face.materialIndex = 0;
} else {
face.materialIndex = 1;
}
}
var mesh = new THREE.Mesh( geometry, [frontMaterial, backMaterial] );
scene.add(mesh);
}
This results in the following:
I'm not going to mark this as the accepted answer yet as I still need to apply it to the more complex model in the question plus I think there could still be a better way to do this, like flipping a particular vertex to some other value.
One solution would be to use a ShaderMaterial and define the colors based on whether the face is front or back facing.
Let me walk you through this simple example
Hold left click to rotate the mesh. If you're not familiar with ShaderFrog, click "Edit Source" on the right and scroll down the bottom of the fragment shader.
if (!gl_FrontFacing) gl_FragColor = vec4(vec3(0.0, 0.0, 1.0) * brightness, 1.0);
gl_FrontFacing is a boolean. Quite self explanatory, it'll return true if a face is front, and false otherwise.
The line reads "if the face is not front facing, render it blue at with alpha = 1.0.
Hoping that helps.

Three Js - How to fix the blurry images on the vertices of an icosahedron

I was trying to make a rotating icosahedorn with images on each vertex using three js, but the images look blurred. Can anyone please help me? js fiddle link here: https://jsfiddle.net/prisoner849/b2tncLh8/
<div id="container"></div>
var $container = $('#container');
var renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
var camera = new THREE.PerspectiveCamera(80, 1, 0.1, 10000);
var scene = new THREE.Scene();
var Ico;
scene.add(camera);
renderer.setSize(576, 576);
// Making the canvas responsive
function onWindowResize() {
var screenWidth = $(window).width();
if (screenWidth <= 479) {
renderer.setSize(300, 300);
} else if (screenWidth <= 767) {
renderer.setSize(400, 400);
} else if (screenWidth <= 991) {
renderer.setSize(500, 500);
} else if (screenWidth <= 1200) {
renderer.setSize(450, 450);
} else if (screenWidth <= 1366) {
renderer.setSize(550, 550);
}
camera.updateProjectionMatrix();
}
onWindowResize();
window.addEventListener('resize', onWindowResize, false);
$container.append(renderer.domElement);
// Camera
camera.position.z = 200;
// Material
var greyMat = new THREE.MeshPhongMaterial({
color: new THREE.Color("rgb(125,127,129)"),
emissive: new THREE.Color("rgb(125,127,129)"),
specular: new THREE.Color("rgb(125,127,129)"),
shininess: "100000000",
shading: THREE.FlatShading,
transparent: 1,
opacity: 1
});
var L2 = new THREE.PointLight();
L2.position.z = 1900;
L2.position.y = 1850;
L2.position.x = 1000;
scene.add(L2);
camera.add(L2);
var Ico = new THREE.Mesh(new THREE.IcosahedronGeometry(125, 1), greyMat);
Ico.rotation.z = 0.5;
scene.add(Ico);
var trackballControl = new THREE.TrackballControls(camera, renderer.domElement);
trackballControl.rotateSpeed = 1.0;
trackballControl.noZoom = true;
// sprites
var txtLoader = new THREE.TextureLoader();
txtLoader.setCrossOrigin("");
var textures = [
"https://threejs.org/examples/textures/UV_Grid_Sm.jpg",
"https://threejs.org/examples/textures/colors.png",
"https://threejs.org/examples/textures/metal.jpg"
];
var direction = new THREE.Vector3();
console.log(Ico.geometry.vertices.length);
Ico.geometry.vertices.forEach(function(vertex, index){
var texture = txtLoader.load(textures[index % 3]);
var spriteMaterial = new THREE.SpriteMaterial({map: texture});
var sprite = new THREE.Sprite(spriteMaterial);
sprite.scale.setScalar(10);
direction.copy(vertex).normalize();
sprite.position.copy(vertex).addScaledVector(direction, 10);
Ico.add(sprite);
});
function update() {
Ico.rotation.x += 2 / 500;
Ico.rotation.y += 2 / 500;
}
// Render
function render() {
trackballControl.update();
requestAnimationFrame(render);
renderer.render(scene, camera);
update();
}
render();
so i'm guessing because you scale the textures a lot, you're wondering how to get it more blocky and less blurry? If that's the case, with each loaded texture you should set texture.magFilter = THREE.NearestFilter.
magFilter specifies the behavior when a portion of a texture occupies more pixels than the texture's native resolution.
NearestFilter basically returns colors for the UV coordinates for pixel at Math.floor(UV.x*width). So if you have a resolution of 64 pixels, it'll color in 64 blocks across and 64 down. Nice and pixelated.
With the default, linearfilter - it will lerp in between pixel perfect values, giving you the blurring effect. The documentation for THREE.Texture can give you more info on things to try if you get stuck.
See in action.

Three.js mouseover mesh with ray intersection, no reaction

I'm trying to set up a website that runs in a single WebGL element. I'm trying to get it to tell when the mouse is over an object. I'm using a couple of planes with a with transparent textures on them as links, but it won't pick up on any intersections at all. It does absolutely nothing. I've even added a cube and used the same code as the interactive cubes example (http://mrdoob.github.com/three.js/examples/webgl_interactive_cubes.html) and it does absolutely nothing. No changing the color, absolutely nothing.
I've gone through and tried about 8 different examples online having to do with this and not a single one has worked for me.
Here is my code:
<meta charset="utf-8">
<style type="text/css">
body {
margin: 0px;
overflow: hidden;
background: #000000;
}
div {
margin: 0px;
}
</style>
</head>
<div>
<script src="http://www.html5canvastutorials.com/libraries/Three.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
//Variable Declarations
var camera, scene, renderer, aspect, projector;
var INTERSECTED;
var mouseX = 0, mouseY = 0;
init();
//Method Declarations
function init() {
aspect = window.innerWidth / window.innerHeight;
//aspect = 1.25;
//Sets the camera variable to a new Perspective Camera with a field of view of 45 degrees, an aspect ratio
//of the window width divided by the window height, the near culling distance of 1 and the far culling distance of 2000
camera = new THREE.PerspectiveCamera(45, aspect, 1, 2000);
//Sets the height of the camera to 400
camera.position.z = 700;
//Sets a variable "lookat" to a new 3d vector with a position of 0, 0, 0,
//or the center of the scene/center of the menu plane
var lookat = new THREE.Vector3(0, 0, 0);
//Uses a function built in to every camera object to make it look at a given coordinate
camera.lookAt(lookat);
//Makes a new scene object to add everything to
scene = new THREE.Scene();
//Adds the camera object to the scene
scene.add(camera);
//Sets the renderer varialbe to a new WebGL renderer object
//Change "WebGLRenderer" to "CanvasRenderer" to use canvas renderer instead
renderer = new THREE.WebGLRenderer({antialias:true});
//renderer.sortObjects = false;
//Sets the size of the renderer object to the size of the browser's window
//renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setSize(window.innerWidth, window.innerHeight);
//Adds an event listener to the webpage that "listens" for mouse movements and when the mouse does move, it runs the
//"onMouseMove" function
document.addEventListener('mousemove', onMouseMove, false);
//Force canvas to stay proportional to window size
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousedown', onDocumentMouseDown, false);
//Sets the update frequency of the webpage in milliseconds
setInterval(update, 1000/60);
//Makes a variable "texture" and sets it to the returned value of the method "loadTexture"
//supplied by the THREE.js library
var texture = THREE.ImageUtils.loadTexture('imgs/backgrounds.png');
//Makes a variable "geometry" and sets it to a "PlaneGeometry" object with a width of 645 and a height of 300
var geometry = new THREE.PlaneGeometry(645, 300);
//Makes a variable "material" and sets it to a "MeshBasicMaterial" object with it's map set to
//the "texture" object, it also makes it transparent
var material = new THREE.MeshBasicMaterial({map: texture, transparent: true});
//Makes a variable "plane" and sets it to a "Mesh" object with its geometry set to the "geometry" object
//and it's material set to the "material" object
var plane = new THREE.Mesh(geometry, material);
//Background Texture
var backgroundTexture = THREE.ImageUtils.loadTexture('imgs/gears.png');
var backgroundGeo = new THREE.PlaneGeometry(3500, 2500);
var backgroundMat = new THREE.MeshBasicMaterial({map: backgroundTexture});
var backgroundPlane = new THREE.Mesh(backgroundGeo, backgroundMat);
backgroundPlane.position.z = -1000;
backgroundPlane.overdraw = true;
//Home Button
//Makes a "homeTexture" variable and sets it to the returned value of the makeTextTexture function when
//the text passed in is set to "Home", the width is set to 300, height of 150, font set to 80pt Arial,
//fillStyle set to white, textAlign set to center, textBaseLine set to middle, and the color of the
//background set to red = 0, green = 0, blue = 0 and alpha = 0
var homeTexture = makeTextTexture("Home", 300, 150, '80pt Arial', 'white', "center", "middle", "rgba(0,0,0,0)");
var homeGeom = new THREE.PlaneGeometry(50, 25);
var homeMaterial = new THREE.MeshBasicMaterial({map: homeTexture, transparent: true});
var homeTest = new THREE.Mesh(homeGeom, homeMaterial);
homeTest.position.x -= 270;
homeTest.position.y += 120;
homeTest.position.z = 40;
homeTest.castShadow = true;
//Gallery Button
var galleryTexture = makeTextTexture("Gallery", 340, 150, '80pt Arial', 'white', "center", "middle", "rgba(0,0,0,0)");
var galleryGeom = new THREE.PlaneGeometry(50, 25);
var galleryMaterial = new THREE.MeshBasicMaterial({map: galleryTexture, transparent: true});
var galleryTest = new THREE.Mesh(galleryGeom, galleryMaterial);
galleryTest.position.x -= 270;
galleryTest.position.y += 90;
galleryTest.position.z = 40;
galleryTest.castShadow = true;
//The Team Button
var theTeamTexture = makeTextTexture("Company", 510, 150, '80pt Arial', 'white', "center", "middle", "rgba(0,0,0,0)");
var theTeamGeom = new THREE.PlaneGeometry(80, 25);
var theTeamMaterial = new THREE.MeshBasicMaterial({map: theTeamTexture, transparent: true});
var theTeamTest = new THREE.Mesh(theTeamGeom, theTeamMaterial);
theTeamTest.position.x -= 260;
theTeamTest.position.y += 60;
theTeamTest.position.z = 40;
theTeamTest.castShadow = true;
projector = new THREE.Projector();
var cubeGeom = new THREE.CubeGeometry(20, 20, 20);
var cubeMat = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
var cubeMesh = new THREE.Mesh(cubeGeom, cubeMat);
cubeMesh.position.z = 15;
//scene.add(cubeMesh);
//Adds all of the previously created objects to the scene
scene.add(plane);
scene.add(backgroundPlane);
scene.add(homeTest);
scene.add(theTeamTest);
scene.add(galleryTest);
//Adds the renderer to the webpage
document.body.appendChild(renderer.domElement);
}
function update() {
camera.position.x = (mouseX - (window.innerWidth / 2)) * 0.1;
camera.position.y = -((mouseY - (window.innerHeight / 2)) * 0.15);
camera.lookAt(new THREE.Vector3(0, 0, 0));
render();
}
function render() {
renderer.render(scene, camera);
}
function onMouseMove(event) {
mouseX = event.clientX;
mouseY = event.clientY;
}
function onDocumentMouseDown(event) {
event.preventDefault();
var vector = new THREE.Vector3(
( event.clientX / window.innerWidth ) * 2 - 1,
- ( event.clientY / window.innerHeight ) * 2 + 1,
0.5
);
projector.unprojectVector( vector, camera );
var ray = new THREE.Ray( camera.position,
vector.subSelf( camera.position ).normalize() );
var intersects = ray.intersectObjects( objects );
if ( intersects.length > 0 ) {
intersects[ 0 ].object.materials[ 0 ].color.setHex( Math.random() * 0xffffff );
}
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function makeTextTexture(text, width, height, font, fillStyle, textAlign, textBaseline, backgroundColor)
{
//Makes a new canvas element
var bitmap = document.createElement('canvas');
//Gets its 2d css element
var g = bitmap.getContext('2d');
//Sets it's width and height
bitmap.width = width;
bitmap.height = height;
//Takes "g", it's 2d css context and set's all of the following
g.font = font;
g.fillStyle = backgroundColor;
g.fillRect(0, 0, width, height);
g.textAlign = "center";
g.textBaseline = "middle";
g.fillStyle = fillStyle;
g.fillText(text, width / 2, height / 2);
//Rendered the contents of the canvas to a texture and then returns it
var texture = new THREE.Texture(bitmap);
texture.needsUpdate = true;
return texture;
}
</script>
</div>
</html>
Thanks to anyone that can help out. I wish I could figure out what's going on myself, it seems like I'm using StackOverflow to answer my questions way too much.
You have not declared the variable objects. Do this:
var objects = [];
Then populate it:
objects.push( plane );
objects.push( backgroundPlane );
Now, this line will work:
var intersects = ray.intersectObjects( objects );

Resources