I'm looking to draw a laser beam which can possibly bounce around a box. Basically the laser beam is of variable length and when it bounces off a surface it will reflect at the angle that it collides.
I can handle the collision stuff myself (probably, haven't tried it yet though), but I'm confused about how the actual drawing would work here. It's not like I'm drawing a straight line, I need to sometimes duplicate the line so there are two lines at angles to each other, but when the laser beam stops, the game needs to work out where the end of the beam is so that it can stop drawing the first line after the entire beam has bounced off the surface.
Sorry for the poor explanation.
My math and trig are a little rusty but here's my attempt.
The correct position and length of your beam depends on four variables,
v, the velocity of the beam, since presumably this is not a true laser beam and thus it's velocity is much slower than c. For convenience, we can store v as distance covered in the forward direction from the beam's perspective, per unit of time.
theta, the angle of incidence, that is, the angle at which the beam has struck a wall or barrier.
l, the length of the beam.
t, the time of the incident (let T be the current time).
Basically, a beam traveling at velocity v strikes a wall at angle theta. How long will the collision occur? (How long will it be from the time that the collision occurs until the time that the beam has completely traveled past the incidence point?)
First, because the beam is traveling at an angle relative to an orthogonal coordinate set, we should get the x and y components of velocity and length.
v.x = cos(theta) * v
v.y = sin(theta) * v
l.x = cos(theta) * l
l.y = sin(theta) * l
If the walls off which the beam can reflect are themselves at angles, you will have to project onto them by using the wall's angle as a frame of reference (use the difference between the two angles).
Now the time it takes for the beam to strike from the left side and leave out the right side is given by:
d = l.x/v.x
Suppose that the incident begins at time t, and the current time is T. Then, the proportion of the beam which is drawn on the left and right sides of the incidence point is,
r = (T - t)/d
left = l * r
right = l * (1 - r)
This example has been simplified to show only how one might compute the beam position if it strike from the left to the right. I think it should be a fairly simple process to apply these principles to a beam striking a vertical barrier from the top or the bottom. Also, consider the case that the head of the beam strikes a second barrier while still in collision with the first.
In that case, we need another variable in place of l to represent not the entire length of the beam, but the length of the segment of the beam available for collision (Euclidean distance between the two incident locations).
It sounds like you're not really talking about a laser beam but instead about a gun shooting a bright projectile that reflects off the surface, and you then want to watch it bounce around the box. (Well, at least that's the problem I'm answering!) There are more complicated, efficient, general, accurate, etc, methods, but there's an easy solution to the problem, especially when the box has perpendicular walls (i.e. a normal box):
Using the direction that the gun is fired, find the three velocity components, (vx, vy, vz), and at each timestep while you're drawing the bullet, update it's position x+=dtvx, y+=dtvy, z+=dt*vz, and keep doing this until you hit a wall. When you hit a wall, just reverse the appropriate component of the velocity vector, e.g. if you hit the wall parallel to the y-z plane, take vx to -vx. And just keep going the same way until you hit another wall, and then reverse the appropriate component again...
Here's an example in 2D, just so I can show a plot, but 3D is exactly the same with this simple method. I show both the full path in black, and highlight some sections of it in red. Also, the example's in python, but the only import key lines (x+=dt*vx,...) probably won't require much in translation:
from pylab import *
from collections import deque
dt = .01
x, y = .5, .5
vx, vy = .233, .61
data = deque(maxlen=100)
all_data = []
for i in range(6000):
x += dt*vx
y += dt*vy
if x<0 or x>1:
vx = -vx
if y<0 or y>1:
vy = -vy
# store data and plot
data.append((x, y))
all_data.append((x, y))
if i%400==0:
plot(*zip(*data), color='r', linewidth=4)
plot(*zip(*all_data), color='k')
show()
Like I said, not so efficient, but very easy.
I think you'll want to look into OpenGL. Here's an often-linked resource on OpenGL on the iPhone: OpenGL ES from the Ground Up.
Since OpenGL is used on many platforms, there are all sorts of resources out there that you can use. A quick google search for "bouncing laser opengl" produces some promising results. If you throw "gaming" into your search, you'll probably find things more like the example you gave (actually seeing the ends of a laser beam bouncing around).
Related
I've got a 3d sphere which I've been able to plot a point on using longitude and latitude thanks to some work of another developer I've found online. I think I understand what its doing.
What I need to do now is rotate my planet so the point is always at the top most point (ie the north pole) but I'm not sure how to do this. I'm probably missing some important fundamentals here so I'm hoping the answer can assist in my future learning.
Here's an image showing what I have - The blue line is a line coming from the longitude and latitude I have plotted and I need to rotate the planet so that line is basically pointing directly upwards.
https://ibb.co/2y24FxS
If anyone is able to advise it'd be very much appreciated.
If I'm not mistaken, Unity uses a coordinate system where the y-axis points up.
If the point on your sphere was in the xy-plane, you'd just have to determine the angle between the radius-vector (starts in the center of the sphere, ends on the point in question) and the y-axis, and than rotate by that amount around the z-axis, so that the radius vector becomes vertical. But your point is at an arbitrary location in 3D space - see the image below. So one way to go about it is to first bring the point to the xy-plane, then continue from there.
Calculate the radius vector, which is just r = x-sphereCenter. Make a copy of it, set y to zero, so that you have (x, 0, z) - which is just the projection of the vector r on the horizontal xz-plane - let's call the copy rXZ.
Determine the signed angle between the x-axis and rXZ (use Vector3.SignedAngle(xAxis, rXZ, yAxis), see docs), and create a rotation matrix M1 that rotates the sphere in the opposite direction around the vertical (negate the angle). This should place your point in the xy-plane.
Now determine the angle between r and the y-axis (Vector3.SignedAngle(r, yAxis, zAxis)), and create a new rotation matrix M2 that rotates by that angle around the zAxis. (I think for this second one, the simpler Vector3.Angle will work as well.)
So, what you want now is to combine the two matrices (by multiplying them) into a single transform (I'm assuming this is a transformation in the local coordinate system of the sphere, where (0, 0, 0) is the sphere's center). If I'm not mistaken, Unity uses column-major matrices, so the multiplication order should be M = M2 * M1 (the rightmost matrix is applied first).
Reorient your globe using M as a local transform, and it should bring your point to the top. You can also create M3 = M1.inverse, and then do M = M3 * M2 * M1, to preserve the original angular offset from the xy-plane.
Check for edge cases, such as r already being vertical (pointing straight up, or straight down).
I'm trying to make a character jump between two points. The two points are varying distances apart, and at different heights.
I have the character moving from point to point using Vector3.MoveTowards in a IEnumerator. But how can I make modify the Y axis so that the character moves in a curved path to appear as if jumping?
The character needs to land exactly at each point, so I cannot use physics.
Thanks! :-)
Image Example
Extra bonus points if you can adjust where you want the peak of the jump to occur (so the curve isn't perfectly circular, but more like an arc) E.g. so that the peak of the jump is closer to destination.
Looking at your given image, I would suggest using a projectile motion's equation to calculate the path between the source and destination in a given time with a given start velocity(Vo) and given angle (theta).
In case you are not familiar with projectile equation, have a look at here:
https://en.wikipedia.org/wiki/Projectile_motion
In the Displacement section you'll find 2 equations like this:
x = Vo * T * cos(theta)
y = Vo * T * sin(theta) - 0.5 * g * pow(T,2)
So, in Update function don't move the object directly towards the target, rather take temporary targets along the projectile motion, which you can calculate using the above two equations. You can then use,
Vector3.MoveTowards(curPosition,new Vector3(x,y,0),step);
Considering, the z value is 0.
What I have:
A projectile in Unity 5 2D, affected by gravity, that I want to move from point A to point B with initial impulse on a parabolic path
What I know:
The 2D coordinates of a random starting position (A)
The 2D coordinates of a random target position (B)
The time (X) I want the body to reach the target position after
What I want to know:
The initial impulse (as in unity applyforce with forcemode impulse) that I have to apply to the body onetime in order for it to reach the desired position B after X time.
Notes:
It is a 2D world using Unity 2D physics
The two positions A and B are totally random and may or may NOT be at equal heights (y coordinates)
I want to apply the impulse one time only when spawning the projectile
The projectile does NOT have any other forces affecting him other than GRAVITY (for the current problem lets assume that it always with magnitude 9.8 pointed down)
Here is a (bad) drawing of what I want :D
Thanks upfront guys!
Let's solve a few simpler problems. Our goal is to find an initial velocity for the particle, instead of an "impulse", because we'll achieve better control this way.
First, consider how we would solve this without Unity physics. A particle's position as a function of time depends on its initial position, velocity and acceleration. The same equations apply regardless of how many dimensions you have. This equation is:
current_position = 1/2 * acceleration * time^2 + velocity * time + starting_position
Let current_position be our desired destination, time be the duration of travel you choose, and the starting_position to be the starting position of the particle.
In the x-dimension, there is no acceleration. Let X_0 be our starting X position, X_1 be our destination, and T be the duration of time we want to spend getting to that destination. We want to find v_x, or the velocity in the x-dimension. For ease of interpretation, I've marked all the constants in uppercase and the variable in lowercase.
X_1 = v_x*T + X_0
v_x = (X_1-X_0)/T
In the y-dimension, we have gravity of some kind. So let's incorporate that as our acceleration:
Y_1 = 0.5*G*T*T + v_y*T + Y_0
v_y = (Y_1 - Y_0 - 0.5*G*T*T)/T
Now that you have v_x and v_y, just set the velocity:
rigidbody2d.velocity = new Vector2(v_x, v_y);
Since different objects have different mass, you don't want to try to calculate an impulse. Just set the velocity to what you want in the frame when the object is spawned.
This runs contrary to advice you might find elsewhere on the Internet, but try it first before doing something more complicated.
Some important notes:
Physics processing in Unity isn't stable: you might get different results on different platforms, especially between different mobile devices. If there is performance pressure, there may be fewer physics evaluations and therefore incorrect results. This is generally not a problem with 2D physics.
You may experience an issue with the scale of gravity, depending on your version and what other settings you have.
The formulas of position of a projectile influenced only by gravity are these:
x = x0 + v_x0*t
y = y0 + v_y0*t + 0.5*g*t^2
so, to know the starting velocity, with some basic calculations:
v_x0 = (x-x0)/t
v_y0 = (y-y0)/t + 0.5*g*t^2/t = (y-y0)/t - 4.9*t
Now, in order to add this startin velocity by using AddForce, we could have used ForceMode.VelocityChange, but this mode is only available for 3D rigidbodies, so we need to use the ForceMode.Impulse and multiplying the force by the mass of the object:
RigidBody2D rigid = GetComponent<RigidBody2D>();
rigid.AddForce(new Vector2 (v_x0, v_y0) * rigid.mass, ForceMode2D.Impulse);
and that's it.
Of course you can just set the velocity of the rigid body directly instead of using AddForce.
I want to use the iPhones's accelerometer to detect motions while driving. I'm a bit confused what the accelerometer actually measures, especially when driving a curve.
As you can see in the picture, a car driving a curve causes two forces. One is the centripetal force and one is the velocity. Imagine the iPhone is placed on the dashboard with +y-axis is pointing to the front, +x-axis to the right and +z-axis to the top.
My Question is now what acceleration will be measured when the car drives this curve. Will it measure g-force on the -x-axis or will the g-force appear on the +y axis?
Thanks for helping!
UPDATE!
For thoses interested, as one of the answers suggested it measures both. The accelerometer is effected by centrifugal force and velocity resulting in an acceleration vector that is a combination of these two.
I think it will measure both. But don't forget that the sensor will measure gravity as well. So when your car is not moving, you will still get accelerometer readings. A nice talk on sensors in smartphones http://www.youtube.com/watch?v=C7JQ7Rpwn2k&feature=results_main&playnext=1&list=PL29AD66D8C4372129 (it's on android, but the same type of sensors are used in iphone).
Accelerometer measures acceleration of resultant force applied to it (velocity is not a force by the way). In this case force is F = g + w + c i.e. vector sum of gravity, centrifugal force (reaction to steering centripetal force, points from the center of the turn) and car acceleration force (a force changing absolute value of instantaneous velocity, points along the velocity vector). Providing Z axis of accelerometer always points along the gravity vector (which is rare case for actual car) values of g, w and c accelerations can be accessed in Z, X and Y coordinates respectively.
Unless you are in free fall the g-force (gravity) is always measured. If I understand your setup correctly, the g-force will appear on the z axis, the axis that is vertical in the Earth frame of reference. I cannot tell whether it will be +z or -z, it is partly convention so you will have to check it for yourself.
UPDATE: If the car is also going up/downhill then you have to take the rotation into account. In other words, there are two frames of reference: the iPhone's frame of reference and the Earth frame of reference. If you would like to deal with this situation, then please ask a new question.
Let's consider a disk with mass m and radius R on a surface where friction u also involved. When we give this disk a starting velocity v in a direction, the disk will go towards that direction and slow down and stop.
In case the disk has a rotation (or spin with the rotational line perpendicular on the surface) w beside the speed then the disk won't move on a line, instead bend. Both the linear and angular velocity would be 0 at the end.
How can this banding/curving/dragging be calculated? Is it possible to give analytical solution for the X(v,w,t) function, where X would give the position of the disk according to it's initial v w at a given t?
Any simulation hint would be also fine.
I imagine, depending on w and m and u there would be an additional velocity which is perpendicular to the linear velocity and so the disk's path would bend from the linear path.
If you're going to simulate this, I'd probably recommend something like dividing up the contact surface between the disk and the table into a radial grid. Compute the relative velocity and the force at each point on the grid at each time step, then sum up the forces and torques (r cross F) to get the net force F and the net torque T on the disk as a whole. Then you can apply the equations F=(m)(dv/dt) and T=(I)(dw/dt) to determine the differential changes in v and w for the next time step.
For what it's worth, I don't think a flat disk would curve under the influence of either a frictional force (velocity-independent) or a drag force (linearly proportional to velocity).
A ball will move in a large arc with spin, but a [uniform] disk on a 2D surface will not.
For the disk it's center of spin is the same as it's center of gravity, so there is no torque applied. (As mentioned by duffymo, a nonuniform disk will have a torque applied.)
For a uniform ball, if the axis of the spin is not perpendicular to the table, this causes the ball to experience a rotational torque which causes it to move in a slight arc. The arc has a large radius, and the torque is slight, so usually friction makes the ball stop quickly.
If there was a sideways velocity, the ball would move along a parabola, like a falling object. The torque component (and the radius of the arc) can be computed in the same way you do for a precessing top. It's just that the ball sits at the tip of the top (err....) and the bottom is "imaginary".
Top equation: http://hyperphysics.phy-astr.gsu.edu/HBASE/top.html
omega_p = mgr/I/omega
where
omega_p = rotational velocity...dependent on how quickly you want friction to slow the ball
m = ball mass
g = 9.8 m/s^2 (constant)
r = distance from c.g. (center of ball) to center, depends on angle of spin axis (solve for this)
omega = spin rate of ball
I = rotational inertia of a sphere
My 2 cents.
Numerical integration of Newton's laws of motion would be what I'd recommend. Draw the free body diagram of the disk, give the initial conditions for the system, and numerically integrate the equations for acceleration and velocity forward in time. You have three degrees of freedom: x, y translation in the plane and the rotation perpendicular to the plane. So you'll have six simultaneous ODEs to solve: rates of change of linear and angular velocities, rates of change for two positions, and the rate of change of angular rotation.
Be warned: friction and contact make that boundary condition between the disk and the table non-linear. It's not a trivial problem.
There could be some simplifications by treating the disk as a point mass. I'd recommend looking at Kane's Dynamics for a good understanding of the physics and how to best formulate the problem.
I'm wondering if the bending of the path that you're imagining would occur with a perfectly balanced disk. I haven't worked it out, so I'm not certain. But if you took a perfectly balanced disk and spun it about its center there'd be no translation without an imbalance, because there's no net force to cause it to translate. Adding in an initial velocity in a given direction wouldn't change that.
But it's easy to see a force that would cause the disk to deviate from the straight path if there was an imbalance in the disk. If I'm correct, you'll have to add an imbalance to your disk to see bending from a straight line. Perhaps someone who's a better physicist than me could weigh in.
When you say friction u, I'm not sure what you mean. Usually there is a coefficient of friction C, such that the friction F of a sliding object = C * contact force.
The disk is modeled as a single object consisting of some number of points arranged in circles about the center.
For simplicity, you might model the disk as a hexagon evenly filled with points, to make sure every point represents equal area.
The weight w of each point is the weight of the portion of the disk that it represents.
It's velocity vector is easily computed from the velocity and rotation rate of the disk.
The drag force at that point is minus its weight times the coefficient of friction, times a unit vector in the direction of its velocity.
If the velocity of a point becomes zero, its drag vector is also zero.
You will probably need to use a tolerance about zero, else it might keep jiggling.
To get the total deceleration force on the disk, sum those drag vectors.
To get the angular deceleration moment, convert each drag vector to an angular moment about the center of the disk, and sum those.
Factor in the mass of the disk and angular inertia, then that should give linear and angular acclerations.
For integrating the equations of motion, make sure your solver can handle abrupt transitions, like when the disk stops.
A simple Euler solver with really fine stepsize might be good enough.