I am trying to implement a circular wave in OpenGL using Gerstner wave function:
It works fine but all my ground is deformed with more waves and all I want is a single wave propagating from the center to the exterior. I tried to modify the z position for the points where sqrt(x*x + y*y) is between two circles to limit the boundaries of a wave. The two circles the first circle has the radius of wavelength * time and the second has the radius of wavelength * (time + 1), but this still isn't good enough because the circles are expanding slower than the speed of the wave.
When you calculate the boundaries by wavelength * time, you're assuming the wavefront is moving with a speed equal to the wavelength; after 1 unit time, the wavefront will have traveled wavelength units in your calculation.
Try using the wave speed that you used to calculate $\varphi$ instead of wavelength there.
Related
I'm writing my own Inverse Kinematics and working on joint constraints currently. It's mostly fine but I want to remove all discontinuities from the resulting animation, and constraints are the biggest problem.
For example let's say you're looking at a ball rotating around your head. It rotates right and you look right, up to your neck twisting limit. The ball still moves and when it passes your back then your head will suddenly be clipped against opposite limit, looking left. This is what we get with typical clamping and it gives me frame-to-frame discontinuity.
What I need is that your head will get from right to left during few frames. My first idea is to reflect the source direction with my X axis (between shoulders) and if the reflected direction meets constraint limits - return it. If it doesn't meet the limits - clip the reflected direction instead of the source one.
This should give me the nice and continuous movement and it's not a rocket science but there're a lot of details to take care of. My limits may be like min < max but also max < min, they may pass through switching angle value (like 360->0, or 180->-180) or not. Besides, when my allowed range is bigger than 180deg then the logic should be slightly different.
The amount of different cases build up very fast so I'm wondering if I could find it already done somewhere?
BTW: I'm using Unreal engine if it makes any diffference.
EDIT:
I'm sorry if I've misguided you with my head example - it was just an analogy to visualize my needs. I'm not going to use this code to orient a head bone (nor any other) in a final animation. I'm planning to use it as a very basic operation in solving IK. It's going to be used in every iteration in every IK chain, for every bone, many times. So it need to be as fast as possible. All the higher level concepts, like movement planning, dynamics, etc. will be added on another layer, if needed.
For now I'm just asking for a function like:
float clampAngle( float angle, float min, float max )
that would return a continuous value for changing inputs.
I'm working on different issues currently, but I'll post my code when I get back to this one.
If you think of this as a simulation it will be a lot clearer. You won't need any planning, as in your comment, because the next frame is calculated using only information available on the current frame.
Set up one joint for the neck as described in your first two paragraphs. It will flip from left to right in one frame as the ball comes around.
Then set up a second identical joint and write an angular spring that will rotate it towards the first joint over time. By adjusting spring coefficients - strength, damping etc - you will have control over the way the head rotates.
How to write an angular spring?
This may not the best way, but the code is pretty short and easy, so here goes...
Lets call the 2 joints master and a slave. You need to store rotation phi and angular velocity omega on the slave joint.
phi and omega are axis-angle vectors - a 3d vector whose magnitude is the number of radians to rotate around the axis defined by the vector. It makes simulating rotations pretty easy. Whether your joint rotations are stored as euler angles or matrices or quaternions, you'll probably have some classes un UE API to help extract axis/angle vectors.
When master joint changes, convert its rotation to axis-angle. Lets call this phi_m.
On the start frame, the Slave rotation phi should be set to the same value as master. phi = phi_m. It has no angular velocity, so omega is set to the zero vector (0,0,0).
Then you move forward one frame. A frame's length dt is maybe 1/60 sec or whatever.
While simulating you first work out a new value for phi_m. Then the difference between master and slave ( the vector phi_m - phi) represents the torque acting on the slave joint. The bigger the angle the stronger the torque. Assume mass is 1.0 then using F=ma, angular acceleration alpha is equal to the torque. That means the change in angular velocity for the slave joint over that frame is alpha*dt. Now we can work out new angular velocity: omega = omega + (alpha*dt). Similarly, the new rotation is the old rotation plus change in rotation over time (angular velocity). phi = phi + (omega * dt)
Putting it all together and adding in a coefficient for spring strength and damping, a simulation step can go something like this:
damping = 0.01 // between 0 and 1
strength = 0.2 // ..experiment
dt = currentTime-lastTimeEvaluated
phi_m = eulerToAxisAngle(master.rotate)
if (currentTime <= startTime || dt < 0) {
slave.phi = phi_m
slave.omega = (0,0,0)
} else {
alpha = (phi_m - slave.phi)*strength
slave.omega = (slave.omega * (1.0 - damping)) + (alpha*dt)
slave.phi = slave.phi + slave.omega*dt
}
slave.rotate = axisAngleToEuler(slave.phi)
lastTimeEvaluated = currentTime
Notice that damping just kills off a little of the stored velocity. If damping is very low, the joint will overshoot and oscillate into place - boing!!
one approach:
define the region where the constraint cannot be satisfied (cone behind the head)
measure of how far into this region your target is (angle between target and center of cone divided by half cone angle)
us this scalar value to smoothly mix your constrained object back to some pre-defined neutral position (ie turn head back to center/rest position smoothly as target moves behind the head)
I'm working on an OpenCV program to find the distance from the camera to a rectangle with a known aspect ratio. Finding the distance to a rectangle as seen from a forward-facing view works just fine:
The actual distance is very close to the distance calculated by this:
wtarget · pimage
d = c ——————————————————————————
2 · ptarget · tan(θfov / 2)
Where wtarget is the actual width (in inches) of the target, pimage is the pixel width of the overall image, ptarget is the length of the largest width (in pixels) of the detected quadrilateral, and θfov is the FOV of our webcam. This is then multiplied by some constant c.
The issue occurs when the target rectangle is viewed from a perspective that isn't forward-facing:
The difference in actual distance between these two orientations is small, but the detected distance differs by almost 2 feet.
What I'd like to know is how to calculate the distance consistently, accounting for different perspective angles. I've experimented with getPerspectiveTransform, but that requires me to know the resulting scale of the target - I only know the aspect ratio.
Here's what you know:
The distance between the top left and top right corners in inches (w_target)
The distance between those corners in pixels on a 2D plane (p_target)
So the trouble is that you're not accounting for the shrinking distance of p_target when the rectangle is at an angle. For example, when the rectangle is turned 45 degrees, you'll lose about half of your pixels in p_target, but your formula assumes w_target is constant, so you overestimate distance.
To account for this, you should estimate the angle the box is turned. I'm not sure of an easy way to extract that information out of getPerspectiveTransform, but it may be possible. You could set up a constrained optimization where the decision variables are distance and skew angle and enforce a metric distance between the left and right points on the box.
Finally, no matter what you are doing, you should make sure your camera is calibrated. Depending on your application, you might be able to use AprilTags to just solve your problem.
I currently have several ellipses. These are defined by a centre point, and then two vectors, one point to the minimum axis and other to the maximum axis.
However, for the program I'm creating I need to be able to deal with these shapes as a polyline. I'm fairly sure there must be formula for generating a set of points from the available data that I have, but I'm unsure how to go about doing it.
Does anyone have any ideas of how to go about this?
Thanks.
(Under assumption that both vectors that represent ellipse axes are parllel to coordinate axes)
If you have a radial ray emanating from the centre of ellipsis at angle angle, then that ray intersects the ellipse at point
x = x_half_axis * cos(angle);
y = y_half_axis * sin(angle);
where x_half_axis and y_half_axis age just the lengths (magnitudes) of your half-axis vectors.
So, just choose some sufficiently small angle step delta. Sweep around your centre point through the entire [0...2*Pi] range with that step, beginning with 0 angle, then delta angle, then 2 * delta angle and so on. For each angle value the coordinates of the ellipse point will be given by the above formulas. That way you will generate your polygonal representation of the ellipse.
If your delta is relatively large (few points on the ellipse) then it should be chosen carefully to make sure your "elliptical polygon" closes nicely: 2*Pi should split into a whole number of delta steps. Albeit for small delta values it does not matter as much.
If your minimum-maximum axis vectors are not parallel to coordinate axes, your can still use the above approach and then transform the resultant points to the proper final position by applying the corresponding rotation transformation.
Fixed-delta angle stepping has some disadvantages though. It generates a denser sequence of polygonal points near the miminum axis of the ellipse (where the curvature is smaller) and a sparser sequence of points near the maximum axis (where the curvature is greater). This is actually the opposite of the desirable behavior: it is better to have higher point density in the regions of higher curvature.
If that is an issue for you, then you can update the algorithm to make it use variadic stepping. The angle delta should gradually decrease as we approach the maximum axis and increase as we approach the minimum axis.
Assuming the center at (Xc,Yc) and the axis vectors (Xm,Ym), (XM,YM) (these two should be orthogonal), the formula is
X = XM cos(t) + Xm sin(t) + Xc
Y = YM cos(t) + Ym sin(t) + Yc
with t in [0,2Pi].
To get a efficient distribution of the endpoints on the outline, I recommend to use the maximum deviation criterion applied recursively: to draw the arc corresponding to the range [t0,t2], try the midpoint value t1=(t0+t2)/2. If the corresponding points are such that the distance of P1 to the line P0P2 is below a constant threshold (such as one pixel), you can approximate the arc by the segment P0P1. Otherwise, repeat the operation for the arcs [t0,t1] and [t1,t2].
Preorder recursion allows you to emit the polyline vertexes in sequence.
I have a program in which I am querying all points included in a sphere S of radius R. The points are 3D points actually aligned on the vertices of a 3D regular grid, but I don't think this detail is relevant to the question. The center of the lookup volume (the sphere) can be anywhere in 3D pace.
The points hold some data (say a real). My question, is how can I interpolate/filter the data held by the points which are included in the sphere using a 3D filter (such as gaussian filter for instance). My understanding is that you need to do something like this (pseudo code):
interp_data = 0;
for (each point contained in the lookup sphere S of radius R)
// compute square distance from point location to sphere centre
dist2 = distance2(sphere_center, curr_point_loc);
// compute gaussian weight
w = exp(-100 * dist2);
sumWeight += w;
interp_data += curr_point_data * w;
interp_data /= sumWeight;
Is it correct. I have seen some code using a similar technique. I understand the value 100 on the exp function relates somehow to what seems to be called the standard normal deviation. The value 100 was hard coded in the source code that I have seen, but I assume this should somehow relate to the radius of the sphere? As the weight of the gaussian filter is supposed to drop to 0 when dist2 = R^2.
If someone could shed some light on this it would be great.
Also is it actually the best way of filtering 3D data? Is there a better/faster/more reliable method?
Thanks a lot for your help.
Your proposal is mostly reasonable, though probably not efficient. (Also, why distance squared and not just distance?)
You can perform a 3D Gaussian more efficiently by doing the following things:
1) Separate out the kernel into 3 1-dimensional passes with a 1D Gaussian kernel. This is explained on the Gaussian blur wikipedia page
2) You can approximate a Gaussian kernel by doing a box-blur several times in a row, and which you can implement by using summed area tables
3) You could also use a fast fourier transform and do the convolution by multiplying the image by the kernel in frequency space instead.
Ok i know this is quite off-topic for programmers but still I need this for app, so here it is:
Ballistic curve (without wind or any other conditions) is specified by these 2 lines:
So, there is a problem that you got 3 unknown values: x,y and time t, but only 2 equations.
You can't really compute all 3 with just these values, I got:
velocity v
angle Alpha
origin coordinates
Thus, you have to decide which one to specify.
Now you have 2D tanks game, or anything like that, you know you have tank and using ballistic you have to shoot opponent down with setting angle and power.
I need to know when the bullet hit the ground, it can be on-air as it fly, or precomputed.
There comes up my problem. Which way to use? Pre-compute or check for hitting the ground in each step.
If I would like to pre-compute, I would need to know height of terrain, which, logically would have to be constant as I don't know in which x coord. If I would know the X, it would mean that just in front of my turret is wall. So only way to get to result, when I hit the ground, would be with checking in intervals of time for hitting the ground. This is also good because the terrain doesn't have top be static yay! But isn't that too great overhead which could be made much simpler? Have you encountered with such problem/solution?
Thanks in advance, btw the terrain can be flat, using lines or NURBS so I please for general solution, not specific as in which height you shoot in that will be impact.
You can compute the path of the projectile y(x) by solving one equation for t and substituting into the other. You get
Then finding the landing point is a matter of computing the intersections between that function and the function that defines the height of the terrain. One intersection will be the launch point and the other will be the landing point. (If your terrain is very steep and hilly, there could be more than 2 intersections, in which case you take the first one with x greater than the launch point.) You can use any of various root-finding algorithms to actually compute the intersection; check the documentation of whatever mathematical or game-physical libraries you have to see if they provide a method to do this.
David Zaslavsky did a good job of answering your question about solving for the equation, but if your ultimate goal is simple ballistics simluation, I suggest you instead use vector decomposition.
By utilizing vector decomposition, you can derive the x- and y-compenent vectors of your projectile. You can then apply acceleration to each component to account for gravity, wind, etc. Then you can update the projectile's (x,y) position each interval as a function of time.
For example:
double Speed = 100.0; // Speed rather than velocity, as it is only the magnitude
double Angle = 30.0; // Initial angle of 30º
doulbe Position[2] = {0.0,0.0}; // Set the origin to (0,0)
double xvelocity = Speed * Cos(Angle);
double yvelocity = Speed * Sin(Angle);
Then if you can impliment a simple Update function as follows:
void Update(double Time)
{
yvelocity = -9.8 * Time; // Apply gravity
Position[0] *= (xvelocity * Time); // update x position
Position[1] *= (yvelocity * time); // update y position
CheckCollisions(); // check for collisions
}
Of course this is a very basic example, but you can build on it from here.
Fortunately, this is pretty simple kinematics.
Those equations are parametric: For any given time t, they give you the x and y coordinates for that time. All you need to do is plug in the starting velocity v and angle a.
If you're working on level ground, the time for your projectile to come back down is simply 2sin(a)v/g, i.e. the vertical component of your velocity divided by the downward acceleration due to gravity. The 2 is because it takes that amount of time for the speed to drop to 0, then the same time again for it to accelerate back down. Once you know the time you can solve for x.
If your terrain is not flat, you have some additional fun. Something you could try is work out the time for hitting the ground at the same height, and then correct for the extra vertical distance. This will also change your horizontal distance which might again affect your height... but two or three adjustments and the error will be too small for humans to notice :)
I'm not sure you're going about this is right way. The main equation you want is s = si + vi*dt + .5*adtdt. This is a simple equation of one dimension, but it generalizes to vectors cleanly.
Effectively, si is your initial position and vi is your initial velocity and a is acceleration due to gravity.
To make this work, build a vector for perfect horizontal muzzle velocity and project it on the launch angle. That's your vi. Si will be the tip of the barrel. From there it's vector summing and scaling.
Continuous functions do not work well for computers, because computers are implicitly discrete: the floating/double numbers are discrete, the timer is discrete, the game grid is discrete (even if it uses 'doubles').
So just discretize the equation the way Justin Holdsclaw suggested. Have velocity and accelerations vectors in each direction (in your case X and Y; you could also add Z). Update all vectors, and the object's position in space, at every tick.
Note that the result won't be 'exact'. The smaller your 'delta' values (grid coarseness), the closer you'll be to the 'exact' curve. To know precisely how close - if you're interested, find a book on numerical analysis and read the first few chapters. For practical purposes you can just experiment a bit.