How to determine the distance from an obstacle without knowing its location - java

I am writing a code where I have a world filled with various obstacles (of rectangular shapes). My robot which is a circle, originates randomly at any place inside the world. I assume that it has a range sensor on its head and want to get the distance between the nearest obstacle/boundary wall which is in its straight line of view.
I am using a random orientation between 0 and 360 degrees to orient the robot and use sin and cos of orientation to move the robot in the same orientation. But how can I get the distance between any obstacle or the boundary wall along this orientation? It should be able to tell me the distance of the first object it encounters in its vision which would be an angle from 0 to 360.
Please provide me a hint of logic how to encounter this issue?
Thanks

Assuming you know the angle, the robot's position and the position of all the obstacles, you could have a function like this:
if the angle if less than 90 or greater than 270 you increment the x coordinate by 1, otherwise you decrement by 1
you make a for loop from the current x coordinate until the edge of the world (I don't know how you have the world implemented), scanning for any obstacles at position (x, x*tan(angle)), incrementing or decrementing in accordance with the step above
the first obstacle you run across, return sqrt(x^2 + (x*tan(angle))^2) - that's just the pythagorean theorem

Here's what i think you could do.
In real game development, they uses a lot of optimization tricks, often giving approximates for better performances.
Also note that there's a lot of libraries out there for game development, that probably could get you what you want a lot simplified.
But anyway, here's what i'ld do.
identify object you'd pass through if you go straight forward.
identify the nearest one, in the list of objects you just made.
1:
A)
make a formula for your position/angle in the form y = mx + b
[y = tan(angle)x + (positionY - (tan(angle)*x))]
B)
for each object, divide the object in multiple lines segments (2 points).
check if the segment crosses the line made by the formula in point A
(if a point is smaller and the other is greater than the same X value in the formula, it's crossing)
do the same thing for your world boundaries
2: This part is more tricky (to do in programmation).
Next, you have to find the position where your robot orientation formula intersect
with all the lines you previously identified.
For each line, you must again turn the line into a y=mx+b
Let say we have:
y=3x+5 and
y=5x+1
3x+5 = 5x+1
3x-5x = 1-5
-2x = -4
x = 2
Then you replace x with 2 in either formula, you'll get the intersection point:
y = 3(2)+5 = 11
y = 5(2)+1 = 11
So these two lines intersect on point (2, 11)
Next you have to see if that point is in the domain of you're robot path formula.
Since your robot is looking at a single direction, and the formula we made in point 1.A is infinite in both directions, you must ensure the line intersection you found is not in the back of your robot (unless he moves backward...)
I guess you can make it simple, look at cos(angle) signs, then look at the position of the intersection point, if it's to the left of your robot, and cos(angle) is negative it's fine.
Finally,
Once you found ALL the intersect point, you can find the nearest one by using the Pythagorean theorem sqrt((x1-x2)^2 + (y1-y2)^2)
Also, note that it won't work for 90 and 270 angles, since tan(90) doesn't exists.
In that case, just look if both points of the segments are at both side of your robot, and the intersect point is in the right direction, it means you pass through it.
Again, there's a lot of place for optimization.

Related

Checking depth/z when rendering triangular faces in 3d space

My question can be simplified to the following: If a 3d triangle is being projected and rendered to a 2d viewing plane, how can the z value of each pixel being rendered be calculated in order to be stored to a buffer?
I currently have a working Java program that is capable of rendering 3d triangles to the 2d view as a solid color, and the camera can be moved, rotated, etc. with no problem, working exactly how one would expect it to, but if I try to render two triangles over each other, the one closer to the camera being expected to obscure the farther one, this isn't always the case. A Z buffer seems like the best idea as to how to remedy this issue, storing the z value of each pixel I render to the screen, and then if there's another pixel trying to be rendered to the same coordinate, I compare it to the z value of the current pixel when deciding which one to render. The issue I'm now facing is as follows:
How do I determine the z value of each pixel I render? I've thought about it, and there seem to be a few possibilities. One option involves finding the equation of the plane(ax + by + cz + d = 0) on which the face lies, then some sort of interpolation of each pixel in the triangle being rendered(e.g. halfway x-wise on the 2d rendered triangle -> halfway x-wise through the 3d triangle, same for the y, then solve for z using the plane's equation), though I'm not certain this would work. The other option I thought of is iterating through each point, with a given quantum, of the 3d triangle, then render each point individually, using the z of that point(which I'd also probably have to find through the plane's equation).
Again, I'm currently mainly considering using interpolation, so the pseudo-code would look like(if I have the plane's equation as "ax + by + cz + d = 0"):
xrange = (pixel.x - 2dtriangle.minX)/(2dtriangle.maxX - 2dtriangle.minX)
yrange = (pixel.y - 2dtriangle.minY)/(2dtriangle.maxY - 2dtriangle.minY)
x3d = (3dtriangle.maxX - 3dtriangle.minX) * xrange + 3dtriangle.minX
y3d = (3dtriangle.maxY - 3dtriangle.minY) * yrange + 3dtriangel.minY
z = (-d - a*x3d - b*y3d)/c
Where pixel.x is the x value of the pixel being rendered, 2dtraingle.minX and 2dtriangle.maxX are the minimum and maximum x values of the triangle being rendered(i.e. of its bounding box) after having been projected onto the 2d view, and it's min/max Y variables are the same, but for its Y. 3dtriangle.minX and 3dtriangle.maxX are the minimum and maximum x values of the 3d triangle before having been projected onto the 2d view, a, b, c, and d are the coefficients of the equation of the plane on which the 3d triangle lies, and z is the corresponding z value of the pixel being rendered.
Will that method work? If there's any ambiguity please let me know in the comments before closing the question! Thank you.
The best solution would be calculating the depth for each vertex of the triangle. Then we are able to get the depth of each pixel the same way we do for the colors when rendering a triangle with Gouraud shading. Doing that simultaneously with rendering allows to check the depth easily.
If we have a situation like this:
And we start to draw lines from the top to the bottom. We calculate the slopes from the point one to the others, and add the correct amount of depth every time we move to the next line... And so on.
You did't provide your rendering method, so can't say anything specific to it, but you should take a look at some tutorials related to Gouraud shading. Do some simple modifications to them and you should be able to use it with depth values.
Well, hopefully this helps!

Use loops to create a pyramid in Java

I am trying to create a hollow pyramid of sorts using a loop. The way I would like to approach this is to start at a certain Y, and decrease it by 1, while expanding the X and the Z out by one while covering the perimeter.
*
* *
* *
* *
* *
Granted this would be 3D, using XYZ.
So my main question is, if I have 3 points, X=50 Y=50 Z=50, how would I go down each level of Y while getting the points around the center?
So far
for (int y = 1; y<15; y++) {
l.setY(l.getY() - 1);
l.setX(l.getX() + 1);
l.setZ(l.getZ() + 1);
l.getBlock().setType(Material.GLASS);
}
will only generate a staircase of sorts going 15 blocks down from the starting position
Please imagine the graph of the 3 axis, if you are not practice with it just take a look at this graph.
We will use z as height, by rotating the axis in order to have a clear picture of what is happening. You may as well use z as the depth parameter but it will be harder for you to understand what is going on.
You obtain a wrong plot because you are not moving towards the space in the right way..
What you are looking for is starting by a point, say S=(x,y,z) = (5,5,5) and you want to go down each level by printing your edges for the piramid.
the starting point is plotted as shown in the following figure
By moving down decrementing z you want to draw 4 points (you may want to draw some more, I just draw the edges in this case).
so in the next cycle you have z = z-1;
thus you have to move in the 4 directions allowed by the graph.
The point in the middle keeps the center of the pyramid, while the others are respectively
(5,4,4) (5,6,4) --> moving along y axis
(4,5,4) (6,5,4) --> moving along x axis
while you cycle you keep moving this, by using as metrics the difference between the center, the level(height) and the axis while drawing the pyramid..
HOW? see the last following picture, I added some color to help you keeping track of what is happening. Further I added axis and main points coordinates.
Red points keep the center of the pyramid, by starting at S = (5,5,5) (which is the top) you go down to S1 =(5,5,4) and S2 = (5,5,3).. so imagine this are 2 cicles of your while loop.
Green points keep track of the first cycle, when z = 4,
the center of the pyramid is S1 this time. You want to expand in the space by moving on the y and x axis.
By the center you move -1 and -+1 on y.. so obtaining (5,4,4) and (5,6,4). So far you obtain 2 edges. Let's move on the x axis keeping the center as is, the same this time you move by 1 unit toward such plane so that you have (6,5,4) and (4,5,4)..
The same happens with the second cycle. The distance you move is obtained by
starting height - actual level height
in the case of z = 3 you have to from the center by 5 - 3 = 2 unit (by previous statement)
so on and so forth for the rest of the cycle up to the point you end up.
You may want to stop at 0 unit of shift from center (when starting height == actual level height) by obtaining a nice and well drawn pyramid, other wise you can keep cycling but you have to find another way to stop, the previous subtraction in fact works also with negative height, you can notice that if you reach z = -1 the previous will tell you to shift of 6 units, in this case you have to find another way to stop and break your cycle.
This said you have to adjust your cycle to draw the 4 points, instead of those that you actually draw =)
You go the staircase at only one side down. On the other side, x and z grow in the other direction.

add length to a line that passes through 2 points and get the new end point

i have been working with lwjgl and also j3d for the geometry part. i am still working on the collision. what i have so far witht he collision is working decently but there are 2 problems. to sum up my current way of colliding, it tests if the previous coordinate and current coordinate go through a triangle(what things are rendered as) and then it finds the point on the triangle that it just intersected that is closest to your current coordinate and makes you go there. it also makes your y coordinate go up by .001.
this workd descent but going up .001 is bad becuase if you go to a triangle that is at a 90* angle going updards you can go left to rigth but you cant back up out of it, almost as if you are stuck in it.
here is a drawing of how it works on imgur
http://i.imgur.com/1gMhRut.png
from here i want to add say .001 to the length between the current coordinate and the closest point (i already know these points) and get the new current point.
btw prev is where the person was at before they moved to the cur point and then it tests to see if those 2 points intersect a triangle and then i get the closest point to the prev if it does which is defined as closest in the picture. i can already calculate for all of those points
If I understand you correctly you want to add .001 to move away from the triangle. If that is the case then you need a vector of length 0.001 perpendicular to the triangle. In case of a triangle this is usually called the "normal". If you already have a normal for the triangle, then multiply that by .001 and add that. If you don't have a normal yet you can calculate it using cross product (you can Google the details of what a cross product is), something like this, from the vertices of the triangle:
Vector3 perpendicular = crossProduct(vertex3.pos - vertex1.pos, vertex2.pos - vertex1.pos);
Vector3 normal = perpendicular / length(normal);
Vector3 offset = normal * 0.001f;

Calculating block/face camera/cursor has focus on in 3d block world

Been teaching myself 3d programming with a minecraft-clone game. I have an infinite map, loaded in chunks of 16x16x64 blocks.
As the player (the camera) walks around, the center of the camera (the game cursor) points at a block. I'm trying to figure out how to determine which block the user is pointing at.
I have a camera with a 3d coordinate, yaw, pitch, so I know where the user is looking.
I've tried finding coordinates that would be on a "line" drawn from that origin point but that doesn't account for when the camera points at the edges/corners of a block, the system won't know.
I've tried looking for examples online but I'm not finding anything useful, a few examples but they're extremely buggy and poorly documented.
How can I properly convert where the center of the camera is looking into which block/face it's looking at?
"I've tried finding coordinates that would be on a "line" drawn from that origin point but that doesn't account for when the camera points at the edges/corners of a block, the system won't know." .. "How can I properly convert where the center of the camera is looking into which block/face it's looking at?"
The two common ways that OpenGL programs do mouse picking is either colour picking or ray casting. It sounds like you are trying to iterate through your block grid to get the position which is a bit unusual, or want to do something like ray casting.
Ray casting is done from the camera -> through the mouse -> onto a plane on the screen -> map screen space to world space -> collide with scene
"I've tried looking for examples online but I'm not finding anything useful, a few examples but they're extremely buggy and poorly documented."
Here are some links to some ray casting tutorials one with maths and diagrams, one with some code examples, and another.
Note that if you find any older OpenGL tutorials, they might mention "selection mode" or the "name stack" which is really old, don't use it - OpenGL wiki.
There is a Minecraft type clone called CraftMania that is open source at https://github.com/mcourteaux/CraftMania
There might be some documented information about 3D picking.
First, a note on the camera height question: be sure to keep camera position and pointing in the ModelView matrix and not in the Projection matrix. The Projection matrix should only be used to compensate for your human eye relative to your real screen (frustum). "Zooming" is a trickier subject.
The previous answer's links show how to get the line of sight vector from the camera, looking into the model space (center of screen or cross hairs).
Call this line of sight vector l. It should be a unit column vector, expressed in the same coordinate frame as your blocks.
In terms of yaw(h for heading) and pitch(p), if +y is up, and 0 yaw has -z forward and x right, then the (x,y,z) components of l are: l = (cp*sh, sp, -cp*ch), where cp is cos(pitch), sh is sin(yaw=heading), etc.
We want the nearest cube in front of the camera that has any face(s) pierced by a ray from the camera in the direction of l.
At every step, you want to rule out cubes to consider, to save throughput. OpenGL has a way to tell if a primitive (e.g. triangle) writes to the depth buffer (is visible). If you want to, you could render twice, and note the cubes that write to the depth buffer under a *-or-equal rule on the second pass, and only consider those cubes. If not, you can skip that and just consider all cubes.
If you don't have a limited number of your 16x16x64 chunks already selected, you could consider large cubic block chunks (e.g. 16^3) to reject as a whole first, using the coarse method below for single blocks, with the acceptance threshold scaled up by e.g. 16.
Assume a cube is 2x2x2 units (corners at center +/- 1 in x,y,z).
The camera "eye" is at position e.
For every cube, with center at c, compute displacement from the eye: d = c - e.
Compute distance in the direction of l: u = d dot l. (i.e. u = dx*lx + dy*ly + dz*lz.)
Discard this cube if u < -1.5 (cube is entirely behind the camera).
Compute the perpendicular displacement vector of the cube center from the ray: p = d - u*l.
Coarse check:
Discard the cube if the sum of the absolute values of the components of p is > 3.
This is a fast check that will eliminate all but cubes which are very close to the line of sight ray.
Sort all remaining cubes by smallest to greatest u.
The first of these to pass the following detailed check wins.
Detailed check:
You first have to do some preparation based on your l vector, before processing any cubes:
Designate the 8 corner vertex numbers and position vectors universal to all cubes as follows:
no x y z
1 1 1 1
2 1 -1 1
3 1 -1 -1
4 1 1 -1
5 -1 1 1
6 -1 -1 1
7 -1 -1 -1
8 -1 1 -1
Next, choose the 4 or 6 vertices forming the 2-D convex hull of precise collision, as seen by the eye, based on the signs of the x,y,z components of l:
xyz Vertices (cyclic)
+++ 234856
--- 658432 (reverse order of +++)
++- 123785 (6->1, 4->7) of +++
--+ 587321 reverse order of ++-
+-+ 156734
-+- 437651 reverse of +-+
-++ 148762
+-- 267841 reverse of -++
Degenerate cases, when any 2 of l's x,y,or z components are zero:
+00 1234
-00 4321
0+0 1485
0-0 5841
00+ 1562
00- 2651
Select one of the above 14 hulls, once, based on your line of sight l vector. Then do the following detailed test for each of the remaining range-sorted cubes.
Now, for the ray to be within this hull, meaning at least one face of the cube is pierced (or at least grazed), the ray must be to the left of each line segment specified by subsequent pairs of the vertices of the hull (6 or 4 checks) as we go around the hull counter-clockwise. This is the same as requiring the the cross product of the hull segment with the displacement from either end of that segment to the ray has negative or zero projection into the line of sight vector l:
Taking the hull vertices in pairs from left to right, and wrapping around from the last to the first, the leftmost vertex designated "a" and the right one "b",
((b - a) cross (p - a)) dot l <= 0. (same "p" as above, p = d - u*l. p may be stored from above, or recomputed here.)
The first cube, taken in order from nearest to farthest, to have all 4 or 6 line segments of the hull pass this test is the cube in front of the player. The four or six (b - a) vectors may be pre-computed (once).
You can also come up with sets of 4 vertices for the degenerate cases where only one of the components of l is zero, but that is optional, unlike the cases where two components of l are zero, where you must only use 4 vertices.
This is all on paper, not coded or tested.

Building a radar

I want to try and build a radar in Java OpenGL. Basically in the method, you pass in the player's current location, angle the player is facing and the enemies location. If the enemy is straight ahead, the red dot(symbolizes the enemy) should be at the top of the circle(radar), which one could say is 0 degrees. If directly to the right, the red dot would be 90 degrees, etc. Basically, I'm try to find the angle between a vector that is shooting out directly in front of the player and a vector from the player to the enemy. How exactly would I go about doing that? I've looked around and found suggestions of atan2(), but haven't been really sure how to use it. If there is a quicker, more efficient way of doing things, please let me know as well.
Edit: I used the method of plotting the points instead of dot product and cos, etc. and I am using the player's position as the origin. But if the distance is greater than lets say a chosen number 70 using the distance formula, how I would make the enemy dot appear on edge of the radar? Anything less than 70 would be within the radar, but any enemy beyond 70, I would want the enemy to be just circling around the edge of the radar, rather than having the enemy dot disappear.
Assuming that your players and enemies are represented in some 2D space (or even 3D space, but they move on a 2D plane such as a level ground) with coordinates, I think the simpler way would be to just directly map in the positions of the player/enemy entities onto the radar, and then apply a rotate transform on the radar with the player as the origin, based on what angle the player is currently facing with respect to the true north.
If you are using vectors, you can use the property that the dot product of two vectors is equal to the product of their magnitudes and the cosine of the angle between them:
u . v = |u| |v| cos(theta)
Where u is the direction of your player and v is the vector from your player to the enemy.
You're looking for theta, so you just need to use:
theta = acos((v . u) / (|v| |u|))
Note that this will only give you the angle, not whether it is to the left or to the right. To find that, we can take the cross product and see if it is positive or negative:
is_left = |u X v| < 0

Categories