I'm trying to make a spherical burst of rays for the purpose of checking collision, but having specific interactions happen based upon what or where each ray hit. Hence why I'm using rays rather then something simpler such as OverlapSphere.
The reason I'm looking for how to make a sphere is because I can use the same math for my rays, by having them go to the vertices of where the sphere would be. But every way I can find for making a sphere has the lines get closer the near to the poles, which makes sense, as its pretty easy to do. But as you can imagine, its not that useful for my current project.
TL;DR:
How do I make a sphere with equidistant vertices? If its not perfectly equidistant its fine, it just needs to pretty close. If this happens, it would be great if you could give how much the difference would be, and where, if applicable.
Extra notes:
I've looked at this and this, but the math is way over my head, so what I've been looking for might've just been staring me in the face this whole time.
You could use an icosphere. As the vertices are distributed on equilateral triangles, your vertices are guaranteed to be equidistant.
To construct the icosphere, first you make an icosahedron and then split the faces recursively in smaller triangles as explained in this article.
Are you aware that the sphere given to you by Unity is in fact designed
with this exact goal in mind?
ie, the entire raison d'etre of the sphere built-in to Unity is that the points are fairly smoothly space ...... roughly equidistant, as you phrase it.
To bring up such a sphere in Unity, just do this:
You can then instantly get access to the verts, as you know
Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] vv = mesh.vertices;
int kVerts=vv.Length
for (int i=0; i<kVerts; ++i)
Debug.Log ... vv[i]
Note you can easily check "which part of the sphere" they are on by (for example) checking how far they are from your "cities" (or whatever) or just check (for example) the z values to see which hemisphere they are in .. et cetera.
Furthermore...
Please note. Regarding your overall reason for wanting to do this:
but having specific interactions happen based upon what or where each ray hit
Note that it could not be easier to do this using PhysX. (The completely built-in game physics in Unity.) Indeed, I have never, ever, looked at a collision without doing something "specific" depending on "where it hit!"
You can for example get the point where the contact was with http://docs.unity3d.com/ScriptReference/RaycastHit-point.html
It's worth noting it is absolutely inconceivable one could write something approaching the performance of PhysX in casual programming.
I hope this makes things easier!
slice the sphere into N circles
compute perimeter of it
divide it by the same angle that create the slice
this gives you the number of vertexes
and also angle step inside circle
cast rays
This is how I coded it in C++ + OpenGL:
// draw unit sphere points (r=1 center=(0,0,0)) ... your rays directions
int ia,na,ib,nb;
double x,y,z,r;
double a,b,da,db;
na=16; // number of slices
da=M_PI/double(na-1); // latitude angle step
for (a=-0.5*M_PI,ia=0;ia<na;ia++,a+=da) // slice sphere to circles in xy planes
{
r=cos(a); // radius of actual circle in xy plane
z=sin(a); // height of actual circle in xy plane
nb=ceil(2.0*M_PI*r/da);
db=2.0*M_PI/double(nb); // longitude angle step
if ((ia==0)||(ia==na-1)) { nb=1; db=0.0; } // handle edge cases
for (b=0.0,ib=0;ib<nb;ib++,b+=db) // cut circle to vertexes
{
x=r*cos(b); // compute x,y of vertex
y=r*sin(b);
// this just draw the ray direction (x,y,z) as line in OpenGL
// so you can ignore this
// instead add the ray cast of yours
double w=1.2;
glBegin(GL_LINES);
glColor3f(1.0,1.0,1.0); glVertex3d(x,y,z);
glColor3f(0.0,0.0,0.0); glVertex3d(w*x,w*y,w*z);
glEnd();
}
}
This is how it looks like:
R,G,B lines are the sphere coordinate system axises X,Y,Z
White-ish lines are your Vertexes (White) + direction (Gray)
[Notes]
do not forget to include math.h
and replace the OpenGL stuff with yours
If you want 4, 6, 8, 12 or 20 vertices then you can have exactly equidistant vertices as the Platonic solid which all fit inside a sphere. The actual coordinates of these should be easy to get. For other numbers of vertices you can use other polyhedra and scale the verties so they lie on a sphere. If you need lots of points then a geodesic dome might be a good base. The C60 bucky-ball could be a good base with 60 points. For most of these you should be able to find 3D models from which you can extract coordinates.
I think the easiest way to control points on a sphere is by using spherical coordinates. Then you can control position of points around the sphere by using two angles (rho and phi) and the radius.
Example code for filling points uniformly around a rotating sphere (for fun):
var time = 1; // Increment this variable every frame to see the rotation
var count = 1000;
for (int i = 0; i < count; i++)
{
var rho = time + i;
var phi = 2 * Math.PI * i / count;
var x = (float)(radius * Math.Sin(phi) * Math.Cos(rho));
var z = (float)(radius * Math.Sin(phi) * Math.Sin(rho));
var y = (float)(radius * Math.Cos(phi));
Draw(x, y, z); // your drawing code for rendering the point
}
As some answers have already suggested, use an icosahedron based solution. The source for this is quite easy to come by (and I have written my own several times) but I find the excellent Primitives Pro plugin extremely handy under many other circumstances, and always use their sphere instead of the built-in Unity one.
Link to Primitives Pro component
Primitives Pro options
Related
I have a polyline composed of multiple line segments. The line is very complex and squiggles all over the place in 3D, so for simplicity's sake let's say it looks something like this
I want to render it in 3D. Currently, I do a very simple process where I just generate a cylinder for each segment:
This is decent, but looks bad where the line changes direction. It is also wasteful - each of the direction changes requires twices as many vertices as is strictly necessary. I would be much happier with an approach that generated shapes like this:
At first I didn't think it would be too hard, but the more I've worked on it the more I've found it to be surprisingly nontrivial. I'm working in C#, and if this were in 2D I would just use Clipper, but I can't find any libraries or resources for how to solve this problem in 3D. It's okay if the solution isn't always perfect or sometimes leads to self-intersections or things of that nature. Anyone have any guidance?
So in a mathematical sense, the intersection of two cylinders is an ellipse. If I give you where the semi-major axis point on the ellipse is and the semi-minor axis you could calculate any number (like numsides) nodes on the ellipse.
Take the node connecting two segments located at a point p and define the two vectors of the ellipse as follows. a is the semi-major axis and b is the semi-minor axis
Each joining line segment has unit directions vectors e_1 and e_2 and the cylinder has radius R.
Then the intersection ellipse would be defined from the vectors a and b:
Then find a point c around the ellipse use the following parameterization with t = 0..1
Here is some C# code that calculates numsides points around the ellipse
// Vectors p, a, b defined
for(int i=0; i<numsides; i++)
{
double t = (1.0*i)/numsides
Vector c = p + a*Math.Cos(2*Math.PI*t) + b*Math.Sin(2*Math.PI*t)
// use/store c as needed for the mesh generation
}
I found this site which had an elegant solution. Starting with some points around the first line segment making up your polyline, you compute the intersection of the line parallel to the current segment that passes through each point and the plane formed by the intersection of the two current line segments.
I'm working on a first person 3D game. The levels are entirely cube based, walls/floors/etc are all just tiled cubes (1x1x1).
I'm currently creating a ray using the camera position and the rotation of the camera to get the direction. I'm wanting to then ray cast out to the first cube that is not empty (or when the ray falls off the grid). Quite often, these are direction vectors such as 0,0,1 or 1,0,0.
I'm not having much luck in finding a Bresenham Line Drawing Algorithm that works with a direction vector rather than a start/end point. Especially considering the direction vector is not going to house integers only.
So, for a specific question, I guess I'm asking if anyone can explain if I'm even coming close to going about this the right way and if someone might go into detail about how it should be done regardless.
Bresenham won't help you here, I'm afraid...what you need are Ray/Line-Plane intersection algorithms:
Line-Plane intersection on Wikipedia
Line-Plane intersection on Wolfram
Ray-Plane intersection on SigGraph
In very rough mathy-pseudocode:
(caveat:It's been a long time since I've done 3d graphics)
// Ray == origin point + some distance in a direction
myRay = Porg + t*Dir;
// Plane == Some point on cube face * normal of cube face (facing out),
// at some distance from origin
myPlane = Pcube * Ncubeface - d;
// Straight shot: from ray origin to point on cube direction
straightTo = (Pcube - Porg);
With these two equations, you can infer some things:
If the dot product of 'straightTo' and the plane normal is zero (call this "angA"), your origin point is inside the face of the cube.
If the dot product of the ray direction and the plane normal is close to 0 (call this "angB"), the ray is running parallel to the face of the cube - that is, not intersecting (unless you count if the origin is in the cube face, above).
If (-angA / angB) < 0, your ray is pointing away from the cube face.
There's other stuff, too, but I'm already pressing the limits of my meager memory. :)
EDIT:
There might be a "shortcut", now that I think it though a bit...this is all assuming you're using a 3-d array-like structure for your "map".
Ok, so bear with me here, thinking and typing on my phone - what if you used the standard old Bresenham delta-error algorithm, but "fixed" it into 2D?
So let's say:
We are at position (5, 5, 5) in a (10x10x10) "box"
We are pointing (1 0 0) (i.e., +X axis)
A ray cast from the upper-left corner of our view frustrum is still just a line; the definitions for "x" and "y" change, is all
"X" in this case would be (mental visualization)...say along the axis parallel to the eye line, but level with the cast line; that is, if we were looking at a 2D image that was (640x480), "center" was (0,0) and the upper left corner was (-320,-240), this "X axis line" would be a line cast through the point (-320,0) into infinity.
"Y" would likewise be a projection of the normal "Y" axis, so...pretty much the same, unless we're tilting our heads.
Now, the math would get hairy as hell when trying to figure out what the next deltaX value would be, but once you'd figured out the formula, it'd be basically constant time calculations (and now that I think about it, the "X axis" is just going to be the vector <1 0 0> projected through whatever your camera projection is, right?
Sorry for the rambling, I'm on the train home. ;)
I thought I'd be able to find this with some searching on the internet but everything I find is just balls bouncing off walls for something like pong or another arbitrary question. I'm making a 2D dungeon crawler game and when I kill enemies and they drop loot I want the item to come flying out as if it had just been thrown in the air and land a random point on the tile the unit was on.
I've been trying to figure this out myself but I can't figure it out, this is probably asked a lot, I'd be really grateful if someone could help me out.
EDIT AS REQUESTED:
Ok well when a monster would be destroyed I would choose a random location within the tile it's in, let's call this location endLoc and the monster's location startLoc. I would then find the center x point between these two locations and decrease the y by 20 ( because that's how many pixels i want the item to go up by), so let's called this variable launchLoc:
launchLoc = new Vector2(startLoc.X + ((endLoc.X - startLoc.X) / 2), startLoc.Y - 20)
I think that produces the right Vector.
So now I would need to launch the item from startLoc, to launchLoc, then have it come back down to endLoc. This is where it gets confusing and I'm not sure how to make a realistic arc for this. The end result would have the item move like it moved along a gaussian, as if it was thrown into the air.
I tried to make it so during each interval, the velocity is increased by 120th, of the X difference, between the startLoc and launchLoc, by an incrementing multiple, but I couldn't get it to work very well. I'm not sure if this was the best way to do. I use 120th because the y value is 20, and the item moves up 1 pixel every interval, so 1 to 20 added up gives 120, this would make the x movement constantly increase, like it was thrown up.
This is in 2D btw, I hope that helps.
You start with an initial velocity vector at time t0 (v(t0)) and position (p(t0)). Gravity can be assumed to produces a constant acceleration (a(t0) = <0, -9.8 m/s2>, though your value may differ) until the object lands. So the general form of the motion for going from one timeslice to the next is:
p(t) = 0.5*a(0)*(t-t0)2 + v(0)*(t-t0) + p(0)
v(t) = a(0)*(t-t0) + v(0)
To figure out when to stop that motion, you need to figure out at what time the object's path will intersect the surface against which it bounces. You'll have to do this for all of the surfaces for which this can reasonably be expected to happen. So for a plane with line equation Ux + Vy + T = 0 you break the position vector into its components, as in:
p(t) = <px(t), py(t)> Then use the quadratic formula to find tc where p(tc) satisfies the line equation:
0.5*(Uax(t0)+Vay(t0))*tc2 + (Uvx(t0)+Vvy(t0))*tc + (Upx(t0)+Vpy(t0)+T) = 0Chose the branch such that tc > t0. From there it's simple to figure out where the object will collide with the surface. You can then update the velocity vector and position vector based on the behavior of the bounce. If the plane is axially aligned (ie, it's a horizontal plane with normal vector parallel to the Z axis), then just flip the sign of the Z component of the velocity vector and multiply the whole velocity vector by some damping factor d, where 0≤d<1 to damp out the velocity. Then repeat until some predetermined time has passed or the velocity reaches some minimal amount (your call on that).
It becomes a bit more difficult with arbitrarily oriented planes. You will need to calculate the angle of incidence of the collision and reflect the velocity vector about the plane normal. I won't go into the details here, as I suspect you're probably not interested in it.
I've been working on a simple program in C# in which a Ball [X,Y] cordinates are periodical incremented.
I've managed to implement a collision detection method, but I'm trying to determine how to reflect the ball at an angle oposed bouncing it back along the same linear path.
dx = -dx //This bounces the ball back along the same linear path
dy = -dy
Solution
Trigonometry
theta = range between 0<theta<=360 depending on where it bounced
x = cos(theta)*time
y= sin(theta)*time
The whole point of Newtonian physics is that it is not random, it is deterministic. If you throw the same ball against the same wall at the same angle and with the same velocity and the same spin, it goes to the same place every time.
This sort of program is a really great learning opportunity for both programming and physics. What I encourage you to do is to first write a program that simulates very simple bouncing. As you note, when an object is moving straight down and hits a horizontal surface, then you can model the bounce as simply reversing the vertical velocity component. Just get that right; no gravity, no nothing. That's a great start.
Then try adding bouncing off of horizontal walls, the same way.
Then try adding bouncing off of walls that are not aligned with horizontal or vertical directions. That's where you're going to have to learn how vectors and trigonometry work, because you'll have to work out what component of the ball's velocity is changed by striking the wall obliquely.
Then add gravity. Then add friction from the air. Then add the fact that the ball can be spinning. Add elasticity, so that you can model deformation of the ball.
Once you get to that point, if you want to introduce randomness you'll be able to figure out how to do it. For example, you might introduce randomness by saying "well, when the ball strikes the wall and deforms, I'll introduce a random element that changes its deformation by 0-10%". That will then change how the simulation bounces the ball. You can experiment with different kinds of randomness: add random air currents, for instance.
You will have to add in randomness yourself. To rephrase your question: "Deterministically, it bounces off at angle theta. How can I make it bounce back at angle theta + epsilon, where epsilon is some random value?"
To rotate a vector, see this. You will just specify theta.
pseudocode:
RotateVector(vec):
bounce_vec = [-vec.x vec.y]; //deterministic answer is negative x, normal y
bounce_angle = acos(dot(vec,bounce_vec) / (norm(vec)*norm(bounce_vec)));
modified_angle = bounce_angle + random_number();
ca = cos(modified_angle);
sa = sin(modified_angle);
rotation_matrix = [ca -sa; sa ca];
return rotation_matrix * vec;
Line 3 uses the law of cosines to figure out the angle. In line 4, that angle is modified randomly. The rest of the function rotates the original vector by your new angle.
As long as it's a perfect ball with a perfect surface it will not bounce back randomly. Neither vectors nor trigonometry will give you any randomness.
"randomly, though applying to the basic laws of physics" seems like an oxymoron. However...
If you want it to bounce in a random direction, while maintaining its current speed, you might do something like this (pseudocode):
first, bounce back the canonical way (dx = -dx or dy = -dy depending on the collision)
then convert the dx and dy to polar coordinates (theta and r)
jitter theta by a small amount (+ or - a few degrees, according to your taste)
make sure theta isn't heading into a wall that you just bounced off
convert theta and r back to dx and dy
That would be conserving scalar momentum.
I played around with it for a while, but I simply can't figure it out.
I made a tank that fires missiles, and when the missiles hit the walls, I want them to bounce off, but I want them to bounce off to the right angle.
Right now I haven't got any obstacles, the missiles just bounce off when they get outside the viewportRectangle I made.
Is the solution I'm looking for quite advanced?
Is there a relativly simple way to do it?
You might think that because your walls are aligned with the coordinate axes that it makes sense to write special case code (for a vertical wall, negate the x-coordinate of the velocity; for a horizontal wall, negate the y-coordinate of the velocity). However, once you've got the game working well with vertical and horizontal walls, probably the next thing you'll think is, "what about walls at arbitrary angles?" So it's worth thinking about the general case from the beginning.
In the general case, suppose your missile has velocity v and hits a wall with surface normal n.
Split v into components u perpendicular to the wall and w parallel to it.
Where:
u = (v · n / n · n) n
w = v − u
Here, v · n is the dot product of the vectors v and n. See the link for an explanation of how to compute it. The dot product n · n evaluates to the square of the length of the normal vector; if you always keep your normals in the form of unit vectors then n · n = 1 and you can omit the division.
After bouncing, the component of motion parallel to the wall is affected by friction f, and the component perpendicular to the wall is affected by elasticity, which can be given in the form of a coefficient of restitution r.
So the velocity after the collision is v′ = f w − r u. In a perfectly elastic, frictionless collision, v′ = w − u; that is, the motion is reflected about the normal at the point of collision, as in the diagram given in Bill's answer.
This approach works just the same in three dimensions too.
(Obviously this is a very simplified notion of bouncing; it takes no account of angular momentum or deformation. But for many kinds of video games this kind of simplification is perfectly adequate.)
I think an easier way to do this is to use the velocity of the missile instead of calculating angles. Say you have a missile that has xVelocity and yVelocity to represent its movement horizontally and vertically. Those velocities can be positive or negative to represent left, right, up, or down.
If a missile hits a top or bottom border reverse the sign of the yVelocity.
If a missile hits a left or right border reverse the sign of the xVelocity.
This will keep the movement in the opposite axis the same.
Borrowing the image from ChrisF's answer, let's say the missile starts out at position I.
With the xVelocity and yVelocity both being positive (in 2D graphics right and down are typically positive) the missile will travel in the direction indicated. Let's just assign values of
xVelocity = 3
yVelocity = 4
When the missile hits the wall at position C, its xVelocity shouldn't change, but its yVelocity should be reversed to -4 so that it travels back in the up direction, but keeps going to the right.
The benefit to this method is that you only need to keep track of a missile's xPosition, yPosition, xVelocity, and yVelocity. Using just these four components and your game's update rate, the missile will always get redrawn at the correct position. Once you get into more complicated obstacles that are not at straight angles or are moving, it will be a lot easier to work with X and Y velocities than with angles.
For perfect particles (& light) the angle of reflection is equal to the angle of incidence, as illustrated by this diagram (from commons.wikimedia.org).
The Wikipedia page on reflection is quite good at explaining how it works.
It's a little bit more complicated when you take into account the elasticity and materials of the object and the obstacles, but this is probably good enough for most applications.
I've had this problem, the only way I found was separating the axes of collision!
Try it:
x += velocity * Math.cos(angle * Math.PI /180);
y += velocity * Math.sin(angle * Math.PI /180);
if (x < 0 || x > canvas.width) {
angle = 180 - angle;
}
else if (y < 0 ||y > canvas.height) {
angle = 360 - angle;
}
I hope this helps you!
As an aside to the specific physics question you are asking, I would recommend the book "Beginning Math and Physics for Game Programmers" by Wendy Stahler. I found it quite useful for my game/physics programming projects.
The code that accompanies the book is C++ but if you know C#, it would be pretty easy to make the conversion.
Have a good one!
180-a will not work in all instances, unless you are merely working a bounce on a top surface when X is increasing.
One direction to head is the XNA forums or pick up XNA sample code. It is C# and it is for building games. I am not stating you want to build your games in XNA, but it is a great tool, and it is free.
Not complicated at all - pseudo-code:
angleObjectHitWall = a;
bounceAngle = 180-a;
Of course this is a very simple calculation, and is totally irrelevant once you start to take into account factors such as material, gravity, walls which aren't straight, etc...
This is really a physics question, so if you are not a physicist (and since you are asking this question, I'm going to take it that you are not) it will require a lot of reading and brainstorming to get it right.
I suggest reading this wikipedia entry to get the basic idea about the depth of your question.
If you only want to make it "look plausible" then I wouldn't worry about it too much and use Bill the Lizard's answer, however if you want to make it right you will have quite an adventure. Don't let this scare you tho! Good luck!
a = 2w - b
where:
a => resulting angle
w => wall or floor or ceiling angle
b => ball angle
This is what I come up after trying to find the simplest formula for computing just the resulting angle of ball bouncing the walls, ceiling and floor. The result could go beyond +360 or -360 degrees but they are still equivalent angle.For example if the ceiling angle is 270deg and the ball angle is 30deg, the resulting angle is 510deg which is equivalent to +150deg or -210 deg. If you'll use 90deg for the ceiling instead of 270deg, the result is still 150deg.
if(!Collide(Missle, Mainchar)){
(Velocity.x)*-1;
(Velocity.y)*-1;
}
It works and is simple, good luck.