Three JS check if position is behind object - javascript

I have a 3D character along with several predefined positions on the floor. Is there a way to check if a position is behind the 3D character and not in front or sideways?
I’ve included a rough sketch of what I’m trying to achieve (sorry for the poor drawing). Essentially I would like to return all of the positions of the red circles within the red lines and exclude all other circles outside of these two lines.
Is this possible? If so, is there any suggestion on how I can achieve this? I’m sorry but I don’t actually know which functions to use from Three JS for something like this or if it is possible.
Thank you!

Yes, it's possible.
You start out by first checking if a point/circle is behind the player. You do this by getting the dot product between the direction player is facing (a unit vector) and the direction vector to the circle (normalize it so that it's also a unit vector). If the values dotProduct <= 0 then the circle is behind your player.
(unit vector means that your vector has a magnitude of one. Which is a fancy way of saying your x/y/z will never go beyond 1)
Code example
// Let's assume that the following code is in some sort of loop, yes
// Get the direction vector to the circle
const directionVect = circle.position.clone().sub(player.position).normalize();
// If your player is a camera you can get the direction like so
const playerFacing = player.getWorldDirection(new THREE.Vector3());
// Orientation
if (playerFacing.dot(directionVect) <= 0) {
// Circle is behind the player
// ...to be continued...
} else {
return;
}
Now that you know which circles are behind your player, you can get the circles within the cone. This is done by getting the angle between the player's position and the circle's position. Then check that the angle fits some criteria (e.g. the angle can't be more than 45deg from back of player).
// ...
// Orientation
if (playerFacing.dot(directionVect) <= 0) {
// Circle is behind the player
const angle = player.position.angleTo(circle.position);
if (angle < Math.PI * 0.25) {
// Do something with circle
}
} else {
return;
}

Related

struggling to create a smooth-moving snake in p5 js - tail catching up to head

I'm putting together a p5 sketch with little wiggling snakes that move randomly across the screen.
Unfortunately, the tail keeps catching up to the head every time it does a sharpish turn.
Here is the function I'm using to calculate the move, I've tried with a few different ways of calculating the speed, fixed numbers, relative to the snake's length.
It's supposed to work by moving the snakes head (points[3]) in a semi-random direction and then having each body point move towards the one before it by the same amount. This isn't working, and I feel there's something wrong with my algorithm itself. I'm not familiar with these kinds of intermediate random-walks, so I've just been going by guesswork for the most part.
this["moveCurve"] = function() {
let newDir = this["oldDir"] + (random() - 1/2)*PI/6;
let velocity = createVector(1,0);
velocity.setMag(5);
velocity.setHeading(newDir);
this["points"][3].add(velocity);
for (let i = 2; i >= 0; i--) {
this["points"][i].add(p5.Vector.sub(this["points"][i + 1],this["points"][i]).setMag(5));
}
this["oldDir"] = newDir;
}
If you have any idea what I could do to make this work properly, I'd love to hear your advice. Thanks!
This does look like an algorithmic issue / not a bug with how you implemented it.
Here's my go at explaining why the gap between two points must decrease in this algorithm:
Let's consider just a two point snake, with two points Hi (head) and Ti (tail) at an initial locations Hi: (20, 0), and Ti: (0, 0). So, the heading here is 0 radians.
What happens when moveCurve is called? A new heading is chosen (let's use PI/2, a right angle to make it easy to imagine) and using a fixed velocity of 5 we calculate a new position for the head of (20, 5), let's call it Hf. T also moves, but it also moves toward Hf at the same 5 unit velocity, ending up at about (4.85, 1.21). The distance between these two final positions is now 15.62657, which is smaller than the initial distance.
To visualize this, think of the triangle formed between Ti, Hi, and Hf. Ti, and Hi, form the base of this triangle. Ti will move along the hypotenuse to get to Tf, while Hi will move along the other side. The directions they are moving in form an angle which is smaller than PI radians and both points are moving at the same speed so intuitively the points must be getting closer together.
So how to solve this? Well if we consider our tiny snake's movement, the tail moved in a decent direction but too far. One solution might be to scale the velocity vector in order to maintain a fixed distance between points instead of using a fixed velocity. For example instead of stepping 5 units along the hypotenuse from Ti toward Hf in the example, you could step 20 units along the hypotenuse from Hf toward Ti. I'm not sure how this would work out for your snake, just an idea!
Keep slithering!
Fortunately, it turns out p5's documentation itself had the answer for me. By adapting the code from here to use p5 Vectors, I was able to get it all working.
The segLengths property is defined when the object is made, just takes the distances between all the points.
this["moveCurve"] = function() {
let newDir = this["oldDir"] + (random() - 1/2)*PI/6;
let velocity = p5.Vector.fromAngle(newDir).setMag(5);
this["points"][3].add(velocity);
for (let i = 2; i >= 0; i--) {
this["points"][i].set(p5.Vector.sub(this["points"][i+1], p5.Vector.fromAngle(p5.Vector.sub(this["points"][i+1],this["points"][i]).heading()).setMag(this["segLengths"][i])));
}
this["oldDir"] = newDir;
}
I might spend a little time trying to clean up the code a bit, it's a jot messy for my tastes at the moment. But it works.

Circle-Line Sliding Collision (js)

I'm doing a video-game in pure javascript with the Html-Canvas.
I need to find new save x and y coordinates of a circle colliding with a line.
I already find out a easy way to tell if a circle is intersecting with a line , but then i cant figure out how to find the new circle position according to the direction of the circle and the friction of the line.
screenshot example
So the collision detection is done and its working now the problem is the future position of the ball.
I am not looking for a bouncing physic , i am looking for a inelastic collision.
What i thinked was :
Ratio of angleOfStart + angleOfImpact (lets say the angle of the impact is 90° , that means I'm colliding at the line in a perpendicular way , and the angle of start is 0° that means i'm moving right , so x shouldnt be able to grow , but y can go up and down... I thought that by applying this report we could find a formula valid for all collision angles.
Following the direction of the segment collided with ( when i collide with a line i know bot point a and point b , then i can calculate the angle of this line , then i can force my circle to moove only in that direction , multiplying the initial speed - some friction).
Both of those idea in my mind works , but once implemented them in javascript seems works only sometimes...
Lets say i have an object segment collided :
segment = {
a : {
x : // some value,
y : // some value
},
b : {
x : // some value,
y : // some value
}
}
circle = {
x: // value,
y: // value,
ray: // value
}
future_circle = {
x: // x where user wants to go,
y: // y where user wants to go,
ray : // value
}
I know that circle is not colliding with segment.
But if i let the circle move becoming "future circle" then they will collide.
I need to change future circle values so my circle doesnt stops and doesnt go trought the line ... i need my circle mooves in line with the segment, taking care about friction.
I decided to open my mind to other solutions , that surely will work better than mines.
Any help is appreciated.
Sorry for my bad english.

p5.js - collision detection while using translate

I'm having a problem I can't seem to solve when using the p5 javascript library. Essentially I want to create a random "snake" of circles in p5.js.
My code looks like this.
function setup() {
createCanvas(400, 400)
background(220)
noFill()
noLoop()
}
function draw() {
translate(200,200)
strokeWeight(1)
for(j=0;j<5;j++) {
snake()
}
}
function snake() {
rad = 10
ellipse(0,0,rad,rad)
push()
for(i=0;i<100;i++) {
a = random(0,360)
translate(rad*sin(a),rad*cos(a))
ellipse(0,0,rad,rad)
}
pop()
}
What I do is create a circle in the centre, then select a random point 360 degrees around that circle at a certain radius from it, and create a new circle there. Then I translate the centre point (the 0,0) to the centre of that new circle and start the process again.
That delivers a snake, but the problem is the circles inevitably start overlapping.
What I want to do is have my code check whether a randomly created new circle will overlap with any of the previous ones, and if it does, select a new location for that circle.
All the approaches to overlap detection in p5.js I encountered so far, however, use distance to calculate whether circles overlap. Which of course the use of translate messes up.
So if anyone has a solution for my problem, feel free to let me know.
You need to store the positions and sizes of the circles in some kind of data structure, like an array. Then check against those circles before you create a new one.
You might be able to do this using the translate() function, but if I were you I would instead do the translation myself. Instead of using the translate() function, keep track of the circle X and circle Y, and move that point as you draw new circles.
This will allow you to work in screen coordinates, which will make it easier to do collision detection.

Function to get X/Y coordinates for move on triangle with soft edges

i want to make an animation in javascript where an object moves on a path.
For this i need a function that returns me X/Y coordinates on the path for a given time.
The path should be a triangle with soft edges.
At the beginning of the animation it should soft move into the triangle path - but this i could solve maybe in a different function .. more important to me is the function which can return me the X/Y coordinates for the move on the triangle.
The animation should then loop endless on the triangle path.
Are there (online) tools to create coordinates for such a animation?
Can someone help me with the function?
I'd recommend something like sqrt(x²+y²)=2.5+sin(atan2(y,x)*3)/5 - polar: ρ(θ)=2.5+sin(3θ)/5. It's a simple polar coordinate system, and adding a compressed sine wave (3 periods per turn) on a circle:
θ(t) = t // angle
ρ(t) = 2.5 + 0.2 * sin (t * 3) // radius
// of course, you can play with the parameters :-)
You can easily convert those polar coordinates into cartesion ones.
The animation at the beginning, moving from the center into the path, would need an extra function of course. Yet, it could be done with the same mechanic - leaving out the circle part: ρ(θ)=2.5*sin(3θ)

Javascript physics engine and simulated infinite curve

I'm trying to do a Tiny Wings like in javascript.
I first saw a technique using Box2D, I'm using the closure-web version (because of the memory leaks fix).
In short, I explode the curve into polygons so it looks like that:
I also tried with Chipmunk-js and I use the segment shape to simulate my ground like that:
In both cases, I'm experiencing some "crashes" or "bumps" at the common points between polygons or segments when a circle is rolling.
I asked about it for Chipmunk and the author said he implemented a radius property for the segment to reduce this behavior. I tried and it indeed did the trick but it's not perfect. I still have some bumps(I had to set to 30px of radius to get a positive effect).
The "bumps" append at the shared points between two polygons :
Using, as illandril suggested to me, the edging technique (he only tested with polygon-polygon contact) to avoid the circle to crash on an edge:
Also tried to add the bullet option as Luc suggested and nothing seems to change.
Here the demo of the issue.
You can try to change the value to check :
bullet option
edge size
iterations count
the physics
(only tested on latest dev Chrome)
Be patient (or change the horizontal gravity) and you'll see what I mean.
Here the repo for the interested.
The best solution is edge shapes with ghost vertices, but if that's not available in the version/port you're using, the next best thing is like the diagram in your question called 'edging', but extend the polygons further underground with a very shallow slope, like in this thread: http://www.box2d.org/forum/viewtopic.php?f=8&t=7917
I first thought the problem could come from the change of slope between two adjacent segments, but since on a flat surface of polygons you still have bumps I think the problem is rather hitting the corner of a polygon.
I don't know if you can set two sets of polygons, overlapping each other ? Just use the same interpolation calculations and generate a second set of polygons just like in the diagram hereafter : you have the red set of polygons built and add the green set by setting the left vertices of a green polygon in the middle of a red polygon, and its right vertices in the middle of the next red polygon.
![diagram][1]
This should work on concave curves and... well you should be flying over the convex ones anyway.
If this doesn't work try setting a big number of polygons to build the slope. Use a tenth of the circle's radius for the polygon's width, maybe even less. That should reduce your slope discontinuities.
-- Edit
In Box2D.js line 5082 (in this repo at least) you have the PreSolve(contact, manifold) function that you can override to check if the manifolds (directions in which the snowball are impulsed when colliding the polygons) are correct.
To do so, you would need to recover the manifold vector and compare it to the normal of the curve. It should look like that (maybe not exactly) :
Box2D.Dynamics.b2ContactListener.prototype.PreSolve = function (contact, oldManifold) {
// contact instanceof Box2D.Dynamics.Contacts.b2Contact == true
var localManifold, worldManifold, xA, xB, man_vect, curve_vect, normal_vect, angle;
localManifold = contact.GetManifold();
if(localManifold.m_pointCount == 0)
return; // or raise an exception
worldManifold = new Box2D.Collision.b2WorldManifold();
contact.GetWorldManifold( worldManifold );
// deduce the impulse direction from the manifold points
man_vect = worldManifold.m_normal.Copy();
// we need two points close to & surrounding the collision to compute the normal vector
// not sure this is the right order of magnitude
xA = worldManifold.m_points[0].x - 0.1;
xB = worldManifold.m_points[0].x + 0.1;
man_vect.Normalize();
// now we have the abscissas let's get the ordinate of these points on the curve
// the subtraction of these two points will give us a vector parallel to the curve
var SmoothConfig;
SmoothConfig = {
params: {
method: 'cubic',
clip: 'mirror',
cubicTension: 0,
deepValidation: false
},
options: {
averageLineLength: .5
}
}
// get the points, smooth and smooth config stuff here
smooth = Smooth(global_points,SmoothConfig);
curve_vect = new Box2D.Common.Math.b2Vec2(xB, smooth(xB)[1]);
curve_vect.Subtract(new Box2D.Common.Math.b2Vec2(xA, smooth(xA)[1]));
// now turn it to have a normal vector, turned upwards
normal_vect = new Box2D.Common.Math.b2Vec2(-curve_vect.y, curve_vect.x);
if(normal_vect.y > 0)
normal_vect.NegativeSelf();
normal_vect.Normalize();
worldManifold.m_normal = normal_vect.Copy();
// and finally compute the angle between the two vectors
angle = Box2D.Common.Math.b2Math.Dot(man_vect, normal_vect);
$('#angle').text("" + Math.round(Math.acos(angle)*36000/Math.PI)/100 + "°");
// here try to raise an exception if the angle is too big (maybe after a few ms)
// with different thresholds on the angle value to see if the bumps correspond
// to a manifold that's not normal enough to your curve
};
I'd say the problem has been tackled in Box2D 2.2.0 , see its manual, section 4.5 "Edge Shapes"
The thing is it's a feature of the 2.2.0 version, along with the chainshape thing, and the box2dweb is actually ported from 2.2.1a - don't know about box2dweb-closure.
Anything I've tried by modifying Box2D.Collision.b2Collision.CollidePolygonAndCircle has resulted in erratic behaviour. At least a part of the time (e.g. ball bumping in random directions, but only when it rolls slowly).

Categories

Resources