THREE.js camera following a specific path - javascript

I'm trying to make a game with THREE.js. I have a path with a lot of curves combined with some straight paths.
I found an example on Internet and tried to implement TrackballControls.js to make the camera follow a line, but the camera doesn't lookAt the front, it moves weird.
Here is the code:
var controls = new THREE.TrackballControls(camera, render.domElement);
var numPoints = 50;
spline = new THREE.CatmullRomCurve3([
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(50, 0, 0),
new THREE.Vector3(0, 0, -100)
]);
var material = new THREE.LineBasicMaterial({
color: 0xff00f0,
});
var geometry = new THREE.Geometry();
var splinePoints = spline.getPoints(numPoints);
for (var i = 0; i < splinePoints.length; i++) {
geometry.vertices.push(splinePoints[i]);
}
line = new THREE.Line(geometry, material);
line.position.set(0, 0, 0);
scene.add(line);
var counter = 0;
if (counter <= 1) {
camera.position.copy( spline.getPointAt(counter) );
tangent = spline.getTangentAt(counter).normalize();
axis.crossVectors(up, tangent).normalize();
var radians = Math.acos(up.dot(tangent));
camera.quaternion.setFromAxisAngle(axis, radians);
counter += 0.005
} else {
counter = 0;
}
Thanks.

The following example shows how to create a camera that follows a spline curve. Just click on the button "Camera Spline Animation View" to see the effect. Maybe you can use the underlying code to solve your problem.

Related

Light rays from point light three.js

Is there a way to see the light rays from a point light in a Three js scene. I have tried fog but it makes the whole objects in the scene the color of fog.
var width = $('#g_pre_emo').width();
var scene = new THREE.Scene();
scene.fog = new THREE.Fog(0xffff00, 0, 10);
var camera = new THREE.PerspectiveCamera(50, width / 500, 0.1, 1000);
var renderer = new THREE.WebGLRenderer({antialias: false});
renderer.setSize(width, 500);
$('#g_pre_emo').append(renderer.domElement);
var intensity = 2.5;
var distance = 5;
var decay = 2.0;
var light = new THREE.AmbientLight(0x404040); // soft white light
scene.add(light);
renderer.shadowMap.Enabled = true;
renderer.setClearColor(0xffffff, 1);
var happyGroup = new THREE.Object3D();
var sadGroup = new THREE.Object3D();
var angryGroup = new THREE.Object3D();
var relaxedGroup = new THREE.Object3D();
scene.add(happyGroup);
scene.add(sadGroup);
scene.add(angryGroup);
scene.add(relaxedGroup);
var c1 = 0xffff00;
var sphere = new THREE.SphereGeometry(0.25, 16, 8);
light1 = new THREE.PointLight(c1, intensity, distance, decay);
light1.add(new THREE.Mesh(sphere, new THREE.MeshBasicMaterial({color: c1})));
scene.add(light1);
happyGroup.position.set(-3, 3, 0);
sadGroup.position.set(3, 3, 0);
angryGroup.position.set(-3, -3, 0);
relaxedGroup.position.set(3, -3, 0);
var happyGeometry = new THREE.SphereGeometry(1, 50, 50);
var happyMaterial = new THREE.MeshNormalMaterial();
var happySphere = new THREE.Mesh(happyGeometry, happyMaterial);
scene.add(happySphere);
happyGroup.add(happySphere);
var sadGeometry = new THREE.SphereGeometry(1, 50, 50);
var sadMaterial = new THREE.MeshNormalMaterial();
var sadSphere = new THREE.Mesh(sadGeometry, sadMaterial);
scene.add(sadSphere);
sadGroup.add(sadSphere);
var angryGeometry = new THREE.SphereGeometry(1, 50, 50);
var angryMaterial = new THREE.MeshNormalMaterial();
var angrySphere = new THREE.Mesh(angryGeometry, angryMaterial);
scene.add(angrySphere);
angryGroup.add(angrySphere);
var relaxedGeometry = new THREE.SphereGeometry(1, 50, 50);
var relaxedMaterial = new THREE.MeshNormalMaterial();
var relaxedSphere = new THREE.Mesh(relaxedGeometry, relaxedMaterial);
scene.add(relaxedSphere);
relaxedGroup.add(relaxedSphere);
renderer.gammaInput = true;
renderer.gammaOutput = true;
camera.position.z = 15;
function render() {
renderer.render(scene, camera);
}
;
render();
animate();
function animate() {
requestAnimationFrame(animate);
}
If i run the above code the i cant see any fog in the scene
the fiddle for above code is
https://jsfiddle.net/bqv5ynbo/1/
Possibly, you can use VolumetricSpotlightMaterial from Jerome Etienne.
For me it worked well for Three.js r71, though I haven't tried it with later revisions.
Example of usage
'Light Rays' aren't an automatically occurring thing.
Typically, light rays are created using advanced pixel shaders (stencil/shadow projection over lit region / volumetric fog) or in simple cases by creating simple alpha-blended polygons with 'ray' textures applied.
A point light is simply a light that does not apply directional calculations during it's shading phase. Instead, only distance based calculations are made.
Good Luck!

Create torus graph using three js

I'm trying to create a torus graph where there are different coloured segments of different widths (depending on the data size), basically a pie graph that looks nicer.
Is it possible to do this using torus geometry or would it be best to create the segments as shapes and use exctrudegeometry?
In wither case, what's the best way of doing this?
Edit
I have implemented this via torus geometry like:
var prevAngle = 0;
for(var i = 0; i < data.length; i++){
var mat = new THREE.MeshPhongmaterial({materialOptions});
var angle = 2* Math.PI * data[i].size //size is decimal
var geo = new THREE.TorusGeometry(500, 200, 8, 6, angle);
var mesh = new THREE.Mesh(geo, mat);
mesh.rotation.z = prevAngle;
scene.add(mesh);
prevAngle = angle;
}
But when I render this (with 4 objects in data with size 0.25) I only get the top half of the torus (semi-torus?).
is the rotation correct?
You can look at the example at https://github.com/josdirksen/learning-threejs/blob/master/chapter-05/07-basic-3d-geometries-torus.html
As you can see, the last argument to the TorusGeometry is the arc which you can use to directly map the segments of your pie graph to segments of a torus geometry.
Working solution
var prevAngle = 0;
var material = new THREE.MeshPhongmaterial({materialOptions});
var graphContainer = new THREE.Object3D();
graphContainer.castShadow = false;
for(var i = 0; i < data.length; i++){
var mat = material.clone();
mat.color = new THREE.Color(this.coloursArray[i]); //colorsArray = ['#46adad', ...]
var angle = 2* Math.PI * data[i].size //size is decimal
var geo = new THREE.TorusGeometry(500, 200, 8, 6, angle);
var mesh = new THREE.Mesh(geo, mat);
mesh.rotation.z = prevAngle;
graphContainer.add(mesh);
prevAngle += angle;
}
this.scene.add(graphContainer);

Can't color the vertices but if use faces the three.js works

I am trying to put some color on vertices but the colors do not appear. I am using Three.js library.
This is the function example I am using:
function parserExpose(arr) {
var geometry = new THREE.PlaneGeometry(60, 60, arr.x - 1, arr.y - 1);
for (var i = 0, l = geometry.vertices.length; i < l; i++) {
geometry.vertices[i].z = (arr.topo[i].topoValues / 65535 * 2470);
geometry.vertices[i].color = new THREE.Color(Math.random() * 0x00ffff);
}
geometry.colorsNeedUpdate = true;
geometry.needsUpdate = true;
geometry.__dirtyVertices = true;
geometry.__dirtyNormals = true;
geometry.computeBoundingSphere();
//vertexColors: THREE.VertexColors
//THREE.FaceColors
var plane = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({vertexColors: THREE.VertexColors, wireframe: true, wireframeLinewidth: 3}));
scene.add(plane);
}
If I use geometry.faces[] I can change the color but I only want to change on vertices not the faces.
Thx in advance. :)

Draw arc within polyline THREE.JS

I have points like this:
"POLYLINE":[[
{"x":"-6094.1665707632401","y":"3074.764386330728","r":""},
{"x":"-699.22595358468595","y":"1099.941236568309","r":""},
{"x":"-4940.397089330264","y":"576.87996358328382","r":""},
{"x":"-1329.5259580814709","y":"3149.4874087018579","r":"0.5163456475719181"},
{"x":"-6094.1665707632401","y":"3074.764386330728","r":""}
]]
where x y are vertices of a polyline and r is the radius if it is an arc.
i can manage drawing the are if this isnt possible but i would need to jump past the arc in the script
function DRAWpline(vert){
vert = JSON.parse(vert);
var material = new THREE.LineBasicMaterial({
color: 0x0000ff
});
var geometry = new THREE.Geometry();
for (var i = 0; i < vert.length; i++) {
if(vert[i]['r'] != ""){
geometry.vertices.push(new THREE.Vector3(vert[i]['x'], vert[i]['y'], 0));
} else {
}
}
var line = new THREE.Line(geometry, material);
scene.add(line);
}
Something like this, could do the job:
var p0 = new THREE.Vector3(vert[i]['x'], 0, 0);
var p1 = new THREE.Vector3(vert[i]['x'], vert[i]['y'], 0);
var p2 = new THREE.Vector3(vert[i+1]['x'], vert[i+1]['y'], 0);
var startAngle = Math.acos(p0.dot(p1)/(p0.length()*p1.length()));
var angle = Math.acos(p1.dot(p2)/(p1.length()*p2.length()));
geometry = new THREE.CircleGeometry(radius, nbSegments, startAngle, angle);
// remove center vertex
geometry.vertices.splice(0,1);
Add a check on vert[i+1] is exiting before compute p2

Trying to aim the particles to camera while rotating and alert message on intersecting in three js?

I'm trying to create event handler on the particles, with alert message on a sphere, aiming always on the camera.
Something similar to this demo ( and making it to work on IE 9+ )
here is my code..
http://jsfiddle.net/praveenv29/cVnKV/11/
var renderer, projector;
var mouseX, mouseY, stats, container;
var objects = [];
var INTERSECTED;
var camera, scene, renderer, material, mesh, cont;
var w1 = 960;
var h1 = 700;
var halfWidth = w1 / 2;
var halfHeigth = h1 / 2;
function init() {
cont = document.createElement('div');
cont.id = "cont";
document.body.appendChild(cont);
camera = new THREE.PerspectiveCamera(75, w1 / h1, 1, 10000);
camera.position.set(90, 90, -200);
scene = new THREE.Scene();
scene.add(camera);
controls = new THREE.OrbitControls(camera);
controls = new THREE.TrackballControls(camera, cont);
controls.rotateSpeed = 0.8;
controls.zoomSpeed = 1.2;
controls.panSpeed = 2.5;
controls.noZoom = true;
controls.noPan = true;
controls.staticMoving = false;
controls.target.set(0, 0, 0);
controls.keys = [95, 90, 84];
renderer = new THREE.CanvasRenderer();
material = new THREE.MeshBasicMaterial({
color: 0x000000,
wireframe: true
});
renderer.setSize(w1, h1);
cont.appendChild(renderer.domElement);
generateGeometry();
var light = new THREE.PointLight(0xffffff);
light.position.set(10, 0, 0);
scene.add(light);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
controls.update();
renderer.render(scene, camera);
}
function generateGeometry() {
var axis = new THREE.AxisHelper();
scene.add(axis);
for (var i = 0; i < 20; i++) {
var gloom = new THREE.ImageUtils.loadTexture('map_pin.png');
materialr = new THREE.MeshBasicMaterial({
map: gloom,
overdraw: true,
side: THREE.DoubleSide
});
var geometry = new THREE.PlaneGeometry(15, 15, 2, 2);
var cube = new THREE.Mesh(geometry, materialr);
cube.position.x = Math.random() * 2 - 1;
cube.position.y = Math.random() * 2 - 1;
cube.position.z = Math.random() * 2 - 1;
cube.position.normalize();
cube.position.multiplyScalar(125);
cube.rotation.x = cube.position.x / Math.PI; //57.38
cube.rotation.y = 360 / Math.PI * 2;
objects.push(cube);
scene.add(cube);
}
//earth
var texture = THREE.ImageUtils.loadTexture('world.jpg');
var materials = new THREE.MeshBasicMaterial({
map: texture,
overdraw: true
});
var cone = new THREE.SphereGeometry(120, 35, 35);
var coneMesh = new THREE.Mesh(cone, material);
coneMesh.position.y = 0;
coneMesh.rotation.set(0, 0, 0);
scene.add(coneMesh);
}
init();
animate();
It is pretty unclear what you are looking for; your demo link seems unrelated...
Are you trying to make cubes appear camera normal (always facing the camera)? If so, you'll need logic to re-orient them to re-face the camera anytime the user moves the camera view, as I see you are also setting up the TrackballControls, which actually move the camera, not the scene. This means a user can change the camera view of your scene, and items you want facing the camera need to be re-orientated. That re-orientation logic needs to be placed inside your render() function.
BTW, to get an object to always face the camera:
Define it such that when not rotated, it is facing the direction you
want;
Place the object into your scene via any method you want,
including whatever hierarchical rotations or translations you want to use to get them positioned where you want; (Note, they may not be facing
where you want at this point, but that is okay at this step);
Request from three.js that it calculate the local to world space
transformations for your scene. After that, each object's world
transformation matrix contains the concatenated rotations, and
translations that transform each object from local space to world
space.
Go into each object's local-to-world transform matrix and
replace the rotation 3x3 matrix components with the identity
transformation { [1 0 0] [0 1 0] [0 0 1] }. This effectively wipes
out the rotations in world space, making all the objects you do this
to always face the camera.

Categories