Three.js Enemy Moves towards player - javascript

In three.js I have a space ship at xyz, And id like it to fly towards a mesh object of a planet at xyz.
I cannot for the life of me figure this out.
Needs to travel in a straight line, at a speed constant towards the planet.

updateFcts.push(function(delta, now){
if (shipArr[0]===undefined){
}else{
//create two vector objects
var xd = new THREE.Vector3(marsMesh.position.x,marsMesh.position.y,marsMesh.position.z);
var yd = new THREE.Vector3(shipArr[0].position.x,shipArr[0].position.y,shipArr[0].position.z);
//find the distance / hypotnuse to the xyz location
var dicks = shipArr[0].position.distanceTo(marsMesh.position);
var subvec = new THREE.Vector3();
subvec = subvec.subVectors(xd,yd);
//sub subtrac the 3 vectors.
var hypotenuse = dicks;
console.log(hypotenuse);
//1.5 stops it at 1.5 distance from the target planet
if(hypotenuse > 1.5){
//console.log(hypotenuse);
shipArr[0].position.y += .0001*200*(subvec.y/hypotenuse);
shipArr[0].position.x += .0001*200*(subvec.x/hypotenuse);
shipArr[0].position.z += .0001*200*(subvec.z/hypotenuse);
}else{
//within fire range
alert ("FIIIIIRE");
}
}
})
I tried tween.js and was unhappy so i coded a function myself.

You could use https://github.com/sole/tween.js which is focused on that.
A very basic example http://jsfiddle.net/qASPe (square will fly towards sphere after 5s) with mainly this code:
new TWEEN.Tween(ship.position)
.to(planet.position, 700) // destination, duration
.start();
Later, you might want to use a THREE.Curve, or other Path mechanism, as a "flying" path like here http://jsfiddle.net/aevdJ/12
// create a path
var path = new THREE.SplineCurve3([
ship.position,
// some other points maybe? representing your landing/takeoff trajectory
planet.position
]);
new TWEEN.Tween({ distance:0 })
.to({ distance:1 }, 3000) // destination, duration
.onUpdate(function(){
var pathPosition = path.getPointAt(this.distance);
ship.position.set(pathPosition.x, pathPosition.y, pathPosition.z);
})
.start();
In all cases, do not forget to add this line in your update function
TWEEN.update();

Related

Openlayers map jitters on dynamic centering of feature movement animation

I want to make "camera follow" effect on feature while its moves along path.
The feature is moved using requestAnimationFrame, here is the example code:
var lastFrame = +new Date;
var updateSlider = function () {
var now = +new Date, deltaTime = now - lastFrame;
trackValue += deltaTime;
self.move(trackValue);
lastFrame = now;
self.Timer = requestAnimationFrame(updateSlider);
};
updateSlider();
.move = function (timestamp) {
var point = LineString.getCoordinateAtM(timestamp);
if(point) Feature.setCoordinate(point);
this.followCamera();
};
I tried a few options of centering the view. And it works, but the problem is that the map jitters. Need help on getting rid of the jitter.
See this OL example - http://openlayers.org/en/latest/examples/geolocation-orientation.html, to see map jitters, press "Simulate"
.followCamera = function() {
var extent = Feature.getGeometry().getExtent();
A) view.set('center', ol.extent.getCenter(extent);
B) view.setCenter(ol.extent.getCenter(extent);
C) view.animate({center: ol.extent.getCenter(extent)});
D) view.fit(extent) <- Not usable in my case, because i want to zoom in/out manually
};
Also you can try this example (taken from ol examples) - https://jsfiddle.net/32z45kLo/5/ - try with and without setCenter part at moveFeature function (line 152)
Here is the video - https://youtu.be/L96HgWZi6Lo
I think the problem is that you are creating and drawing a new feature to vectorContext at each frame animation.
Instead you should create a feature and add it into a vectorLayer once, and then modify its geometry at each frame animation.
//here you define the pinpoint feature and add it to the vectorLayer
var feature = new ol.Feature();
feature.setStyle(styles.geoMarker);
vectorLayer.getSource().addFeature(feature);
var moveFeature = function(event) {
var vectorContext = event.vectorContext;
var frameState = event.frameState;
if (animating) {
var elapsedTime = frameState.time - now;
// here the trick to increase speed is to jump some indexes
// on lineString coordinates
var index = Math.round(speed * elapsedTime / 1000);
if (index >= routeLength) {
stopAnimation(true);
return;
}
var currentPoint = new ol.geom.Point(routeCoords[index]);
//here you modify the feature geometry instead of creating a new feature
feature.setGeometry(currentPoint);
map.getView().setCenter(routeCoords[index]);
}
// tell OpenLayers to continue the postcompose animation
map.render();
};
working demo without jitter:
https://jsfiddle.net/32z45kLo/80/
The problem is that points on the lines are not equidistant thus the position jump from one to another but nothing inbeetween.
Look at this example to calculate points on the line: http://viglino.github.io/ol-ext/examples/animation/map.featureanimation.path.html
Using a ol.featureAnimation.Path, if you have to move the map on position change, just listen to the change event on the animated feature to get its current position:
geoMarker.on('change', function() {
map.getView().setCenter(geoMarker.getGeometry().getCoordinates());
});
You can see a working example with your code here: https://jsfiddle.net/Viglino/nhrwynzs/

Three JS Raycasting - Find point closest to cursor

Three.js r85
When raycasting with Three JS, a series of points is returned, and I'd like to find the point that is closest to the cursor. The first point returned seems to be the point that is closest to the camera.
Is there a way to find the distance between the cursor position and a point?
Here's the code I'm using to debug this right now:
var raygun = new THREE.Raycaster();
raygun.setFromCamera(mouse, camera);
var hits = raygun.intersectObjects([plotpoints]);
if (hits.length > 0) {
scope.remove(dotPlot);
scope.remove(dotPlot2);
// All points except the first one - Grey
dotGeo = new THREE.Geometry();
for (var i=1; i < hits.length; i++) {
dotGeo.vertices.push(plotpoints.geometry.vertices[hits[i].index]);
}
dotPlot = new THREE.Points(dotGeo, dotMat);
scope.add(dotPlot);
// First point - Orange
var geo2 = new THREE.Geometry();
geo2.vertices.push(plotpoints.geometry.vertices[hits[0].index]);
dotPlot2 = new THREE.Points(geo2, dotMat2);
scope.add(dotPlot2);
scope.render();
}
And here's what I'm seeing:
Ah, figured it out with math!
First thing to note is that hits[].points returns a point directly under the cursor, but it doesn't "snap" to points.
In order to get the actual position of the point, we need to use hits[].index first to get the index number of the point/vertex we hit. We can then access that vertex directly by using GEOMETRY.vertices[] which returns a THREE.Vector3 of the vertex point we hit with our raycast.
So by feeding in the index, we can get the exact position of each vertex hit by our raycast:
GEOMETRY.vertices[hits[i].index]
This provides rudimentary "snapping" to vertices.
Note: When using THREE.LineSegments, the result will always be the starting point, and not the ending point. To get the ending point, you can just add 1 to the index value:
GEOMETRY.vertices[hits[i+1].index]
To snap directly to the vertex closest to the cursor, we need to find the vertex that has the shortest perpendicular distance from the raycaster's ray. To do this we use a cross product of 2 vectors. This is more of a math concept than a programming concept though, so if you want to understand the why behind this, look up something like: perpendicular distance from a point to a line
I just took the code from this question and translated it: http://answers.unity3d.com/questions/568773/shortest-distance-from-a-point-to-a-vector.html
And the end result:
// Variables to record and compare
var smallestDist = 99;
var smallestPointIndex = 0;
// Declare variables outside of loop to save memory
var m_ray = raycaster.ray;
var raydir = m_ray.direction;
var origin = m_ray.origin;
var hitray = new THREE.Vector3(0,0,0);
var dist = 1;
// Loop over all points to find the closest
for (var i=0; i<hits.length; i++){
// Math is magic
hitray.subVectors(plotpoints.geometry.vertices[hits[i].index], origin);
dist = new THREE.Vector3().crossVectors(raydir, hitray).lengthSq();
// Record the closest point
if (dist < smallestDist) {
smallestDist = dist;
smallestPointIndex = i;
}
}
// Now we can use that single point
Here's the result :)

Three js tween js performance lag with many simultaneous tweens

Long time first time and all that - I'm new to Three.js and Tween.js and was hoping to see if it's possible to simultaneously tween 200k Three.js vertices from one position to another. Please excuse my interchangeable use of the words pixels and vertices.
I would like to display 200k pixels in a grid. A user can decide to sort these 200k pixels in a number of ways causing them to rearrange in the grid. I would like all pixels to simultaneously tween between their initial position and final position. Currently, I have the vertices simultaneously moving with tweens but I'm having severe performance issues once the animation nears completion. I hope someone can help!
For each of the 200k vertices I have a tween object associated with them living in this list that I create after drawing vertices in the scene,
var scPartVerts = scene.children[0].geometry.vertices;
var dataSetLen = 200000;
tweenList = []
for (i=0; i<dataSetLen; i ++){
tweenList.push(new TWEEN.Tween(scPartVerts[i]))
}
Using D3 (just what I was familiar with for handling click events), I provide each tween with a new XY position to move to
d3.select("#key").on("click", function() {
for (i = 0; i < dataSetLen; i ++){
var newX = desiredXPostionList[i]; //grab the new X from presorted list
var newY = desiredYPositionList[i]; //grab the new Y from presorted list
tweenList[i].to( {
x: newX,
y: newY
}, 2500)
.start();
}
I then update the tweens while rendering,
function render() {
scene.children[0].geometry.verticesNeedUpdate = true;
TWEEN.update();
renderer.render( scene, camera );
}
The animation appears to run fine for ~75% of the tween and then it comes to a grinding, stuttering, 0 FPS, screeching halt for around 30 seconds once the vertices are close to their final positions. I tried to look at the animation timeline and it appears that all of that time is being dumped into updating the tweens.
Am I somehow supplying redundant tween updates using my d3.select method? (Does javascript register one click as 10 and try to update the tween 10x?) Or can tween.js not smoothly tween 200k positions simultaneously? Thank you so much for any help!
My approach from scratch is to use loops for vertices. The solution is not the ultimate truth, of course.
The plan: set duration and current time of animation,
var duration = 10; // seconds
var currentTime = 10;
var clock = new THREE.Clock();
remember the end position of a vertex, set a random start position for it, find the vector between those positions (direction),
fieldGeom = new THREE.PlaneGeometry(500, 500, 500, 500);
fieldGeom.vertices.forEach(function(vertex){
vertex.startPosition = new THREE.Vector3(THREE.Math.randInt(-500,500),THREE.Math.randInt(-500,500),THREE.Math.randInt(-500,500));
vertex.endPosition = vertex.clone();
vertex.direction = vertex.startPosition.clone().sub(vertex.endPosition);
vertex.copy(vertex.startPosition);
});
then in animation loop add the result vector, multiplied with proportion of currentTime / duration
var delta = clock.getDelta();
currentTime -= delta;
if (currentTime < 0) currentTime = 0;
fieldGeom.vertices.forEach(function(vertex){
vertex.addVectors(vertex.endPosition,vertex.direction.clone().multiplyScalar(currentTime / duration));
});
fieldGeom.verticesNeedUpdate = true;
jsfiddle example with 250K points.

how I can erase from memory the scene and meshes? Three.js

I am adding "n" number of circles on the scene.
var radius = 1;
var segments = 32;
var circleGeometry = new THREE.CircleGeometry( radius, segments);
function generateCircles(){
//scene.remove(circle);
var count=0;
while (1000> count) {
circle = new THREE.Mesh (circleGeometry, material);
scene.add (circle);
count ++;
}
}
It is effective to do it this way ?.
in my code I call this function. and every time you call it, it all goes back slower, I guess it's because there are more objects in the scene. what can I do?
Each time the function is called I need erased completely from the memory stage and the circles that were generated.
with "slower", I mean that I want my application to run faster. every time I run the function add more and more circles. so I want to be removed earlier. to add new ones. if there are many circles in the scene it slows execution.
http://jsfiddle.net/v8oxsxtc/
You can remove the old circles from the scene by calling the scene.remove method on each of the circles you previously added. Here is a simple example using your code:
var lastCircles = null;
function generateCircles(){
var count=0;
if(lastCircles) { // remove old circles if they exist
lastCircles.forEach(function(c) {
scene.remove(c);
});
}
lastCircles = []; // clear cache
while (1000 > count) {
circle = new THREE.Mesh (circleGeometry, material);
lastCircles.push(circle); // add each circle to cache
scene.add (circle);
circle.position.set(count,count,count)
count ++;
}
}

Animating Paper.js path segments & handle info

I'm trying to animate between two complex paths using Paper.js and Tween.js. I've gotten pretty close, I can move all of the points in the path to the correct final positions, but I'm having problems with the handleIn and handleOut for each segment. It doesn't seem to be updating them.
Here's my code: http://codepen.io/anon/pen/rVBaZV?editors=101
var endPathData = 'M740,342.9c-32,...etc...';
var endPath = new Path(endPathData);
endPath.fillColor = '#4CC7A4';
beginPathData = 'M762.8,262.8c-48,...etc...';
var beginPath = new Path(beginPathData);
beginPath.fillColor = '#FFC1D1';
var numberOfSegments = beginPath.segments.length;
for (var i = 0; i < numberOfSegments; i++) {
var tween = new TWEEN.Tween(beginPath.segments[i].point)
.to({
x: endPath.segments[i].point.x,
y: endPath.segments[i].point.y
}, 3000)
.easing(TWEEN.Easing.Linear.None)
.start();
}
view.draw();
view.onFrame = function (event) {
TWEEN.update();
};
I'd like the pink path to end up exactly like the green one, but now I'm stuck. Is there anyway to achieve this?
You need to tween the handles too.
Each segment has two handles: segment.handleIn and segment.handleOut
in your example code you tween the segment.point (the segments position) resulting in the right location of the segments.
I don't know your Tween library, so it is up to you to implement it.
But It looks like you can add to more new tween one for the
beginPath.segments[i].handleIn
and one for the
beginPath.segments[i].handleOut
You can easily check that your code is right by letting paperjs smooth your path and taking care of the handles. By updating the onFrame function like this:
view.onFrame = function (event) {
TWEEN.update();
beginPath.smooth();
endPath.smooth();
};
and this results in the same shaped path.

Categories