rayPlaneIntersection (like) exemple or similar function - math

I'm working with bots in Call Of Duty and their vision is calculated with a bulletTracePassed  function, there's no other way to calculate that, since there's not really bot functions, so this will return true if a bullet can pass from point A to point B returning true/false, which works great MOST of the times, but causes a chaos in those 2 cases mainly:
When the mapper didn't put any kind iDFLAGS_PENETRATION on the walls (means the wall have no resistance to bullets, so there's not contact/hit, and the bullets pass through like was nothing.
When we have Trees, Plants, etc in the middle
In those 2 cases the bots will see the other players when shoudn't, and in jungle like maps it's a complete hell to play.
Ok, the right way to do these fixes are just fix the maps, adding the right penetration in those walls and dense vegetation, but is not possible do that because are SEVERAL maps by SEVERAL modders, and even official releases with the same problems, and of course, we don't have their sources to apply these fixes.
So the only way to do that is via script, and I'm thinking in doing something like this:
I have the position of the eye of the attacker bot in 3D like (x,y,z) for exemple (1000,500,22), and also the position which hit the other players like (2000,1200,60), which is returned by the function bulletTracePassed.
But for exemple, in a wall I have part of it without any collision, so the bots can see through them, so would like to set the middle of the wall with position (1600,800,50) and angles (10,-40,-90) and a square radius of the size to of the square/plane, for exemple, 500.
So I want to test if the ray passed through this square/plane, then returning false/true to let me use it to make the bots decide to aim to shoot or not this player behind the "bad" wall.
Looking around I found the function rayPlaneIntersection, which by the name seams what I want, but didn't get right yet how it works in my solution, since I can't see any kind of angles of even a square radius to determine their size... or are doing to a single point only?
rayPlaneIntersectionrayPlaneIntersection(ray0: vec3, ray1: vec3, origin?: vec3 | number[], normal?: vec3 | number[]): vec3 | undefined
Defined in raymath.ts:130
Computes the intersection point of a given ray and a given plane (rooted at [ 0, 0, 0 ]). t = -(dot(plane.xyz, origin) + plane.w) / dot(plane.xyz, ray); The ray intersects when (t > 0.0) && (t < tm) is true.
Parameters
ray0: vec3 Start point of a ray.
ray1: vec3Far point of a ray, used to derive the ray direction.
Default value origin: vec3 | number[] = [0.0, 0.0, 0.0]
Point on a plane with origin [ 0, 0, 0 ].
Default value normal: vec3 | number[] = [0.0, 1.0, 0.0]
Normal of the plane with origin [ 0, 0, 0 ].
Returns vec3 | undefined
If ray intersects, the intersection point on the plane if the plane was hit.
Anyone could point an exemple of this use in my exemple? Or any other function that might give me the same (or even similar) result to let me at least start to fix this problem?
I know it's not an easy task, that's why I'm posting here, after many lost hours trying to do it alone without success yet.
thank you very much.

Related

Given error of distance, and the error of angle, How would I set a percentage of motion attributed to angular motion, and the net speed

So I have a robot with a mecanum drive, meaning it can move in any direction. I am trying to program it to move to a point and reach that point at a given angle, all while moving in a straight line. So far I've gotten the robot to reach that point, I've gotten it to stay on the straight line, but I cant get it to reach the correct angle(without having it turn and then move). To simplify the movement, I have a function that I creatively called Move, Move takes in three floats:
The first is what angle the robot moves to relative to the robots angle, but ignore this one as I got it working
the second(angle%) determines the percentage of motion that is given to the angular motion, so when it is given 1, the robot will only be turning, and when it is given 0, it won't turn at all. At 0.5 it will be turning a bit, and moving towards the destination at the same time.
The last one is the speed the robot moves at ranging from 0-127. For this I will probably use two PID loops, one for the angle error, and one for the distance error, then add both up.
So my problem is finding an algorithm to find what I should set angle% to, in order to arrive at a point facing the right way. There are a few 'properties that angle% must have: if distance = 0, and angle error > 0, angle% should = 1. And if distance > 0 and angle error = 0. Also when the angle err is 180deg, angle % should = 1.
I know the solution is going to be really simple but I can't wrap my head around this one.

DirectX negative W

I really was trying to find an answer on this very basic (at first sight) question.
For simplicity depth test is disabled during further discussion (it doesn’t have a big deal).
For example, we have triangle (after transformation) with next float4 coordinates.
top CenterPoint: (0.0f, +0.6f, 0.6f, 1f)
basic point1: (+0.4f, -0.4f, 0.4f, 1f),
basic point2: (-0.4f, -0.4f, 0.4f, 1f),
I’m sending float4 for input and use straight VertexShader (without transforms), so I’m sure about input. And we have result is reasonable:
But what we will get if we'll start to move CenterPoint to point of camera position. In our case we don’t have camera so will move this point to minus infinity.
I'm getting quite reasonable results as long as w (with z) is positive.
For example, (0.0f, +0.006f, 0.006f, .01f) – look the same.
But what if I'll use next coordinates (0.0f, -0.6f, -1f, -1f).
(Note: we have to switch points or change rasterizer for culling preventing).
According to huge amount of resource I'll have test like: -w < z < w, so GPU should cut of that point. And yes, in principle, I don’t see point. But triangle still visible! OK, according to huge amount of other resource (and my personal understanding) we'll have division like (x/w, y/w, z/w) so result should be (0, 0.6, 1). But I'm getting
And even if that result have some sense (one point is somewhere far away behind as), how really DirectX (I think it is rather GPU) works in such cases (in case of infinite points and negative W)?
It seems that I don't know something very basic, but it seems that nobody know that.
[Added]: I want to note that point w < 0 - is not a real input.
In real life such points are result of transformation by matrices and according to the math (math that are used in standard Direct sdk and other places) corresponds to the point that appears behind the camera position.
And yes, that point is clipped, but questions is rather about strange triangle that contains such point.
[Brief answer]: Clipping is essentially not just z/w checking and division (see details below).
Theoretically, NDC depth is divided into two distinct areas. The following diagram shows these areas for znear = 1, zfar = 3. The horizontal axis shows view-space z and the vertical axis shows the resulting NDC depth for a standard projective transform:
We can see that the part between view-space z of 1 and 3 (znear, zmax) gets mapped to NDC depth 0 to 1. This is the part that we are actually interested in.
However, the part where view-space z is negative also produces positive NDC depth. However, those are parts that result from fold-overs. I.e., if you take a corner of your triangle and slowly decrease z (along with w), starting in the area between znear and zfar, you would observe the following:
we start between znear and zfar, everything is good
as soon as we pass znear, the point gets clipped because NDC depth < 0.
when we are at view-space z = 0, the point also has w = 0 and no valid projection.
as we decrease view-space z further, the point gets a valid projection again (starting at infinity) and comes back in with positive NDC depth.
However, this last part is the area behind the camera. So, homogeneous clipping is made, such that this part is also clipped away by znear clipping.
Check the old D3D9 documentation for the formulas and some more illustrative explanations here.

GKObstacleGraph How to Find Closest Valid point?

In a scenario where user wants to navigate via mouse or touch to some are of the map that is not passable. When sending the point to GKObstacleGRpah FindPath it just returns an empty array.
I want the unit to go to closest (or close enough) passable point.
What would be an appropriate way to find a closest valid point in GKObstacleGraph.
I understand that I can get the GKObstacle so I can enumerate it's vertices, and I know my unit's position...
But well... what is the next step ?
NOTE: I am not using GKAgengts.
Here was my thinking as I worked through this problem. There may be an easier answer, but I haven’t found it.
1. Figure out if a point is valid or not.
To do this, I actually have a CGPath representation of each obstacle. I export paths from PhysicsEditor and then load them in through a custom script that converts them to CGPath. I always store that CGPath along with the GKObstacle I created from the path. Finally, I can call CGPathContainsPoint to determine the the obstacle contains the point. If true, I know the point is invalid.
2. Once the point is invalid, find out which obstacle was clicked.
With my approach in #1, I already have a handle on the CGPath and obstacle it belongs to.
3. Find closest vertex
Now that I know the obstacle, find the vertex closest to the unit that is moving. I wouldn’t find the closet vertex to the point clicked because that could be around a corner. Instead, figure out the vector between the desired position and the unit. Then, draw an invisible line from the desired position through the vertex. I used this equation to find out where the lines would cross.
// http://stackoverflow.com/questions/1811549/perpendicular-on-a-line-from-a-given-point
let k = ((end.y - start.y) * (hitPoint.x - start.x) - (end.x - start.x) * (hitPoint.y - start.y)) / ((end.y - start.y) * (end.y - start.y) + (end.x - start.x) * (end.x - start.x))
let x4 = hitPoint.x - k * (end.y - start.y)
let y4 = hitPoint.y + k * (end.x - start.x)
let ret = float2(x: x4, y: y4)
4. Offset intersection by unit size towards moving unit
Knowing where the paths intersect along with the vector towards the unit, we can just move to intersection point + (the vector * unit size).
5. Edge cases
This gets tricky when you have two obstacles touching each other, or if you have very large obstacles. The user may think they are moving to the far side of the map, but this script will follow back to the closet valid point which could be nearby. Because of that, I scrapped all of the code and I just don’t allow you to move to invalid positions. A red X and a buzz sound happens prompting the user to select a new, valid position on the map.
6. DemoBots
I could be wrong, but I vaguely recall DemoBots from Apple having similar logic — they may be a good reference too.
7. Debug Layer
This took forever for me to get a proof of concept together. I’d highly recommend drawing lines on a debug layer to verify your logic.

How to calculate a point on a circle knowing the radius and center point

I have a complicated problem and it involves an understanding of Maths I'm not confident with.
Some slight context may help. I'm building a 3D train simulator for children and it will run in the browser using WebGL. I'm trying to create a network of points to place the track assets (see image) and provide reference for the train to move along.
To help explain my problem I have created a visual representation as I am a designer who can script and not really a programmer or a mathematician:
Basically, I have 3 shapes (Figs. A, B & C) and although they have width, can be represented as a straight line for A and curves (B & C). Curves B & C are derived (bend modified) from A so are all the same length (l) which is 112. The curves (B & C) each have a radius (r) of 285.5 and the (a) angle they were bent at was 22.5°.
Each shape (A, B & C) has a registration point (start point) illustrated by the centre of the green boxes attached to each of them.
What I am trying to do is create a network of "track" starting at 0, 0 (using standard Cartesian coordinates).
My problem is where to place the next element after a curve. If it were straight track then there is no problem as I can use the length as a constant offset along the y axis but that would be boring so I need to add curves.
Fig. D. demonstrates an example of a possible track layout but please understand that I am not looking for a static answer (based on where everything is positioned in the image), I need a formula that can be applied no matter how I configure the track.
Using Fig. D. I tried to work out where to place the second curved element after the first one. I used the formula for plotting a point of the circumference of a circle given its centre coordinates and radius (Fig. E.).
I had point 1 as that was simply a case of setting the length (y position) of the straight line. I could easily work out the centre of the circle because that's just the offset y position, the offset of the radius (r) (x position) and the angle (a) which is always 22.5° (which, incidentally, was converted to Radians as per formula requirements).
After passing the values through the formula I didn't get the correct result because the formula assumed I was working anti-clockwise starting at 3 o'clock so I had to deduct 180 from (a) and convert that to Radians to get the expected result.
That did work and if I wanted to create a 180° track curve I could use the same centre point and simply deducted 22.5° from the angle each time. Great. But I want a more dynamic track layout like in Figs. D & E.
So, how would I go about working point 5 in Fig. E. because that represents the centre point for that curve segment? I simply have no idea.
Also, as a bonus question, is this the correct way to be doing this or am I over-complicating things?
This problem is the only issue stopping me from building my game and, as you can appreciate, it is a bit of a biggie so I thank anyone for their contribution in advance.
As you build up the track, the position of the next piece of track to be placed needs to be relative to location and direction of the current end of the track.
I would store an (x,y) position and an angle a to indicate the current point (with x,y starting at 0, and a starting at pi/2 radians, which corresponds to straight up in the "anticlockwise from 3-o'clock" system).
Then construct
fx = cos(a);
fy = sin(a);
lx = -sin(a);
ly = cos(a);
which correspond to the x and y components of 'forward' and 'left' vectors relative to the direction we are currently facing. If we wanted to move our position one unit forward, we would increment (x,y) by (fx, fy).
In your case, the rule for placing a straight section of track is then:
x=x+112*fx
y=y+112*fy
The rule for placing a curve is slightly more complex. For a curve turning right, we need to move forward 112*sin(22.5°), then side-step right 112*(1-cos(22.5°), then turn clockwise by 22.5°. In code,
x=x+285.206*sin(22.5*pi/180)*fx // Move forward
y=y+285.206*sin(22.5*pi/180)*fy
x=x+285.206*(1-cos(22.5*pi/180))*(-lx) // Side-step right
y=y+285.206*(1-cos(22.5*pi/180))*(-ly)
a=a-22.5*pi/180 // Turn to face new direction
Turning left is just like turning right, but with a negative angle.
To place the subsequent pieces, just run this procedure again, calculating fx,fy, lx and ly with the now-updated value of a, and then incrementing x and y depending on what type of track piece is next.
There is one other point that you might consider; in my experience, building tracks which form closed loops with these sort of pieces usually works if you stick to making 90° turns or rather symmetric layouts. However, it's quite easy to make tracks which don't quite join up, and it's not obvious to see how they should be modified to allow them to join. Something to bear in mind perhaps if your program allows children to design their own layouts.
Point 5 is equidistant from 3 as 2, but in the opposite direction.

Ray-Sphere intersection: the discriminant is WRONG

Alright, so I'm working on a ray tracer using phong shading. So far, everything is good. I've cast rays that have hit the spheres in my scene, applied phong shading to them, and it looks normal.
Now, I'm calculating shadow rays, which is shooting a ray from the point of intersection from the primary ray to the light source, and seeing if it hits any objects on the way. If it does, then it's in a shadow.
However, when computing whether the shadow ray hits any spheres, there seems to be an error with my discriminant that is calculated, which is odd since it's been correct so far for primary rays.
Here's the setup:
// Origin of ray (x,y,z)
origin: -1.9865333, 1.0925934, -9.8653316
// Direction of ray (x,y,z), already normalized
ray: -0.99069530, -0.13507602, -0.016648887
// Center of sphere (x,y,z)
cCenter: 1.0, 1.0, -10.0
// Radius of the sphere (x,y,z)
cRadius: 1.0
, and here's the code for finding the discriminant:
// A = d DOT d
float a = dotProd(ray, ray);
// B = 2 * (o - c) DOT d
Point temp (2.0*(origin.getX() - cCenter.getX()), 2.0*(origin.getY() - cCenter.getY()), 2.0*(origin.getZ() - cCenter.getZ()));
float b = dotProd(temp, ray);
// C = (o - c) DOT (o - c) - r^2
temp.setAll(origin.getX() - cCenter.getX(), origin.getY() - cCenter.getY(), origin.getZ() - cCenter.getZ());
float c = dotProd(temp, temp);
c -= (cRadius * cRadius);
// Find the discriminant (B^2 - 4AC)
float discrim = (b*b) - 4*a*c;
Clearly, the ray is pointing away from the sphere, yet the discriminant here is positive (2.88) indicating that the ray is hitting the sphere. And this code works fine for primary rays as their discriminants must be correct, yet not for these secondary shadow rays.
Am I missing something here?
So short answer for my problem, in case someone finds this and has the same problem:
The discriminant tells you whether a hit exists for a line (and not for a ray, like I thought). If it's positive, then it has detected a hit somewhere on the line.
So, when calculating the t-value(s) for the ray, check to see if they're negative. If they are, then it's a hit BEHIND the point of origin of the ray (ie. the opposite direction of the ray), so discard it. Only keep the positive values, as they're hits in the direction of the ray.
Even shorter answer: discard negative t-values.
Credit goes to woodchips for making me realize this.
The issue is, the trick to finding the intersection of a line and a sphere requires the solution of a quadratic equation. Such an equation has one of three possibilities as a solution - there are 0, 1, or 2 real solutions to that equation. The sign of the discriminant tells us how many real solutions there are (as well as helping us to solve for those solutions.)
If a unique solution exists, then the line just kisses the surface of the sphere. This happens when the discriminant is exactly zero.
If two solutions exist, then the line passes through the sphere, hitting the surface in TWO distinct points.
If no real solution exists (the case where the discriminant is negative) then the line lies too far away from the sphere to touch it at all.
Having discovered if the line ever goes near the sphere or not, only then do we worry if the ray hits it. For this, we can look at how we define the ray. A ray is a half line, extending to infinity in only one direction. So we look to see where on the line the intersection points happen. Only if the intersection happens on the half of the line that we care about is there a RAY-sphere intersection.
The point is, computation of the discriminant (and simply testing its sign) tells you ONLY about what the line does, not about where an intersection occurs along that line.
Of course, a careful reading of the link you yourself provided would have told you all of this.
Pretty sure "o-c" should be "c-o"
You're shooting a ray off in the wrong direction and finding the intersection on the other side of the sphere.

Resources