Example: I have a circle which is split up into two halfs. One half goes from 0 to -179,99999999999 while the other goes from 0 to 179,99999999999. Typical example: transform.rotation.z of an CALayer. Instead of reaching from 0 to 360 it is slip up like that.
So when I want to develop a gauge for example (in theory), I want to read values from 0 to 360 rather than getting a -142 and thinking about what that might be on that 0-360 scale.
How to convert this mathematically correctly? Sine? Cosine? Is there anything useful for this?
Isn't the normalization achieved by something as simple as:
assert(value >= -180.0 && value <= +180.0);
if (value < 0)
value += 360.0;
I'd probably put even this into a function if I'm going to need it in more than one place. If the code needs to deal with numbers that might already be normalized, then you change the assertion. If it needs to deal with numbers outside the range -180..+360, then you have more work to do (adding or subtracting appropriate multiples of 360).
while (x < 0) {
x = x + 360;
}
while (x > 360) {
x = x - 360;
}
This will work on any value, positive or negative.
((value % 360) + 360) % 360
The first (value % 360) makes it to -359 to 359.
The + 360 removes any negative number: Value now 1 to 719
The last % 360 makes it to 0
to 359
Say x is the value with range (-180, 180), y is the value you want display,
y = x + 180;
That will change shift reading to range (0, 360).
If you don't mind spending a few extra CPU cycles on values that are already positive, this should work on any value -360 < x < 360:
x = (x + 360) % 360;
I provide code to return 0 - 360 degree angle values from the layer's transform property in this answer to your previous question.
Related
I need a curve editor to make balancing of endless game then I tried to use AnimationCurve.
I need to set a curve to a certain range ex. [0;1] and if I want a value over 1, the result of the Evaluation have to extrapolate the curve. I want to be able to compute Y from X and X from Y.
The problem is AnimationCurve have only 3 WrapMode (Clamp, PingPong, Loop).
How to extrapolate an AnimationCurve ?
Is there a better tool to make curve with extrapolation (post and pre curve) ?
For real extrapolation I think you'd have to implement your own system based on Bézier mathematics. Me at least am not aware of unity providing it out of the box.
A work around for it could be to just define values beyond the 0 to 1 range to cover the extents, animation curves do allow this, I don't think there are to many issues with that.
Another solution, to stay in 0 to 1 range still but achieve the same effect, would be to model the curve from 0 to 1 so that it would cover extreme values within that range and remap the time for curve evaluation given by the object to a 0 to 1 range.
E.g.:
// define range extents
float rangeMin = -5f, rangeMax = 5f;
var range = 10f;
// range could be calculated at runtime if necessary:
// [to] (higher value) - [from] (lower value) = [range]
// 5f - -5f = 10f
var timeRaw = 0; // variable provided value
var time01 = (timeRaw - rangeMin) / range;
// reult by timeRaw = 0: (0 - -5) / 10 = 0.5
// reult by timeRaw = 5: (5 - -5) / 10 = 1.0
// reult by timeRaw = -5: (-5 - -5) / 10 = 0.0
Combining both solutions allow you to cover even more extreme values.
I have the following method to multiply two 32 bit numbers in fixed point
19.13 format. But I think there is a problem with this method:
1.5f is rounded up to 2.0f, while -1.5f is rounded up to -1.0f.
It seems to me that -1.5 should be rounded down to -2.0f.
First, does the current rounding make sense, and if not, how can I change it
to be more consistent?
static OPJ_INT32 opj_int_fix_mul(OPJ_INT32 a, OPJ_INT32 b) {
OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ;
temp += 4096;
assert((temp >> 13) <= (OPJ_INT64)0x7FFFFFFF);
assert((temp >> 13) >= (-(OPJ_INT64)0x7FFFFFFF - (OPJ_INT64)1));
return (OPJ_INT32) (temp >> 13);
}
Since you are always adding 4096, code is doing rounding half-way cases toward positive infinity. It is kind of odd.
To round toward positive infinity, I'd expect
temp += 4096 + 4095;
To round in the usual fashion (to nearest), use instead add a bias away from 0.
temp += (temp < 0) ? -4096 : 4096;
To round to nearest and ties to even is more work. Not certain OP desires that.
I have a voxel based game in development right now and I generate my world by using Simplex Noise so far. Now I want to generate some other structures like rivers, cities and other stuff, which can't be easily generated because I split my world (which is practically infinite) into chunks of 64x128x64. I already generated trees (the leaves can grow into neighbouring chunks), by generating the trees for a chunk, plus the trees for the 8 chunks surrounding it, so leaves wouldn't be missing. But if I go into higher dimensions that can get difficult, when I have to calculate one chunk, considering chunks in an radius of 16 other chunks.
Is there a way to do this a better way?
Depending on the desired complexity of the generated structure, you may find it useful to first generate it in a separate array, perhaps even a map (a location-to-contents dictionary, useful in case of high sparseness), and then transfer the structure to the world?
As for natural land features, you may want to google how fractals are used in landscape generation.
I know this thread is old and I suck at explaining, but I'll share my approach.
So for example 5x5x5 trees. What you want is for your noise function to return the same value for an area of 5x5 blocks, so that even outside of the chunk, you can still check if you should generate a tree or not.
// Here the returned value is different for every block
float value = simplexNoise(x * frequency, z * frequency) * amplitude;
// Here it will return the same value for an area of blocks (you should use floorDiv instead of dividing, or you it will get negative coordinates wrong (-3 / 5 should be -1, not 0 like in normal division))
float value = simplexNoise(Math.floorDiv(x, 5) * frequency, Math.floorDiv(z, 5) * frequency) * amplitude;
And now we'll plant a tree. For this we need to check what x y z position this current block is relative to the tree's starting position, so we can know what part of the tree this block is.
if(value > 0.8) { // A certain threshold (checking if tree should be generated at this area)
int startX = Math.floorDiv(x, 5) * 5; // flooring the x value to every 5 units to get the start position
int startZ = Math.floorDiv(z, 5) * 5; // flooring the z value to every 5 units to get the start position
// Getting the starting height of the trunk (middle of the tree , that's why I'm adding 2 to the starting x and starting z), which is 1 block over the grass surface
int startY = height(startX + 2, startZ + 2) + 1;
int relx = x - startX; // block pos relative to starting position
int relz = z - startZ;
for(int j = startY; j < startY + 5; j++) {
int rely = j - startY;
byte tile = tree[relx][rely][relz]; // Get the needing block at this part of the tree
tiles[i][j][k] = tile;
}
}
The tree 3d array here is almost like a "prefab" of the tree, which you can use to know what block to set at the position relative to the starting point. (God I don't know how to explain this, and having english as my fifth language doesn't help me either ;-; feel free to improve my answer or create a new one). I've implemented this in my engine, and it's totally working. The structures can be as big as you want, with no chunk pre loading needed. The one problem with this method is that the trees or structures will we spawned almost within a grid, but this can easily be solved with multiple octaves with different offsets.
So recap
for (int i = 0; i < 64; i++) {
for (int k = 0; k < 64; k++) {
int x = chunkPosToWorldPosX(i); // Get world position
int z = chunkPosToWorldPosZ(k);
// Here the returned value is different for every block
// float value = simplexNoise(x * frequency, z * frequency) * amplitude;
// Here it will return the same value for an area of blocks (you should use floorDiv instead of dividing, or you it will get negative coordinates wrong (-3 / 5 should be -1, not 0 like in normal division))
float value = simplexNoise(Math.floorDiv(x, 5) * frequency, Math.floorDiv(z, 5) * frequency) * amplitude;
if(value > 0.8) { // A certain threshold (checking if tree should be generated at this area)
int startX = Math.floorDiv(x, 5) * 5; // flooring the x value to every 5 units to get the start position
int startZ = Math.floorDiv(z, 5) * 5; // flooring the z value to every 5 units to get the start position
// Getting the starting height of the trunk (middle of the tree , that's why I'm adding 2 to the starting x and starting z), which is 1 block over the grass surface
int startY = height(startX + 2, startZ + 2) + 1;
int relx = x - startX; // block pos relative to starting position
int relz = z - startZ;
for(int j = startY; j < startY + 5; j++) {
int rely = j - startY;
byte tile = tree[relx][rely][relz]; // Get the needing block at this part of the tree
tiles[i][j][k] = tile;
}
}
}
}
So 'i' and 'k' are looping withing the chunk, and 'j' is looping inside the structure. This is pretty much how it should work.
And about the rivers, I personally haven't done it yet, and I'm not sure why you need to set the blocks around the chunk when generating them ( you could just use perlin worms and it would solve problem), but it's pretty much the same idea, and for your cities too.
I read something about this on a book and what they did in these cases was to make a finer division of chunks depending on the application, i.e.: if you are going to grow very big objects, it may be useful to have another separated logic division of, for example, 128x128x128, just for this specific application.
In essence, the data resides is in the same place, you just use different logical divisions.
To be honest, never did any voxel, so don't take my answer too serious, just throwing ideas. By the way, the book is game engine gems 1, they have a gem on voxel engines there.
About rivers, can't you just set a level for water and let rivers autogenerate in mountain-side-mountain ladders? To avoid placing water inside mountain caveats, you could perform a raycast up to check if it's free N blocks up.
I have two (2-D) vectors with a common vertex ( I had made these 2 vectors out of 3 given points ) . I want to find the angle between them, from 0 to 2*pi, and I need it clockwise and positive. I currently use this:
v1=[x1 y1]-[X Y];
v2=[x2 y2]-[X Y];
ang = mod(atan2(v1(1)*v2(2)-v2(1)*v1(2),v1(1)*v2(1)+v1(2)*v2(2)),2*pi);
if ang==0
Angle=ang;
else
Angle=360 - (ang*180/pi); % change Radian to Degree
end
Although it works correctly, I was wondering if there is any better way to find the angle, maybe not using if/else??!
Thanks in advance
I assume you want to restrict the output to the half-open interval [0, 360). In that case, simply do the mod at the end, after your other conversions, no if required:
ang = atan2(v1(1)*v2(2)-v2(1)*v1(2),v1(1)*v2(1)+v1(2)*v2(2));
Angle = mod(-180/pi * ang, 360);
The clockwise angle is the exact opposite from what atan2 assumes, so you just have to negate it:
Angle = mod(-atan2(v1(1)*v2(2)-v1(2)*v2(1), v1*v2'), 2*pi) * 180/pi;
which is, in essence, identical to Bas' answer I see now :)
Using this as a [reference][1]: Find a tangent point on circle?
cx = 0;
cy = 0;
px = -3;
py = -8;
dx = cx - px;
dy = cy - py;
a = asin(5 / ((dx*dx + dy*dy)^0.5));
b = atan2(dy, dx);
t_1 = deg2rad(180) + b - a;
t_2 = deg2rad(180) + b + a;
For a point (7,6) the angles are 7.9572/73.4434 and for (-3, -8) are 213.6264/285.2615. So for the first quadrant, the angles do not make sense, but for third quadrant they do. What I am doing wrong?
Your formula for a is wrong. You should use
a = acos(5 / ((dx*dx + dy*dy)^0.5))
instead of
a = asin(5 / ((dx*dx + dy*dy)^0.5))
i.e. use acos(...) instead of asin(...). The reason is shown in the image below. The formula for angle a is a=acos(r/H), where r is the radius of the circle and H is the length of the hypotenuse of the right angle triangle. So this has nothing to do with the fact that asin(...) has no way to know which of the two possible quadrants the value that is passed in lies. the argument of the asin is always positive, and you always want the answer in the range 0 to 90 degrees.
So the answer for the two angles that you want are b+a and b-a. Using acos instead of asin in your two cases produces 97.7592 & -16.5566 (or equivalently 343.4434) for your first quadrant example, and -164.7385 & -56.3736 (or equivalently 195.2615 and 303.6264) for your third quadrant example. (NB: instead of adding 180 degrees in the formula for t_1 and t-2, you could just switch the signs of dx and dy)
First -- I spent like 10 minutes figuring out what the heck you're trying to do (which in the end, I got from a comment in one of the answers), while solving your problem took 2 minutes. So, for future reference, please give a description of your problem as clear as you can first.
Now, I think you just have your signs messed up. Try the following:
%// difference vector
%// NOTE: these go the other way around for the atan2 to come out right
dx = px - cx;
dy = py - cy;
%// tip angle of the right triangle
a = asin( 5 / sqrt(dx*dx + dy*dy) );
%// angle between the (local) X-axis and the line of interest
b = atan2(dy, dx);
%// the third angle in the right triangle
%// NOTE: minus a here instead of plus b
g = pi/2 - a;
%// Angles of interest
%// NOTE1: signs are flipped; this automatically takes care of overshoots
%// NOTE2: don't forget to mod 360
t_1 = mod( rad2deg(b - g), 360)
t_2 = mod( rad2deg(b + g), 360)
Alternatively, you could skip computing the intermediate angle a by using acos instead of asin:
%// difference vector
dx = px - cx;
dy = py - cy;
%// Directly compute the third angle of the right triangle
%// (that is, the angle "at the origin")
g = acos( 5 / sqrt(dx*dx + dy*dy) );
%// angle between the (local) X-axis and the line of interest
b = atan2(dy, dx);
%// Angles of interest
t_1 = mod( rad2deg(b - g), 360)
t_2 = mod( rad2deg(b + g), 360)
Just another wayto re-discover the trigonometric identity acos(x) = pi/2 - asin(x) :)
This MathWorld entry is what you want: http://mathworld.wolfram.com/CircleTangentLine.html.
Alright, it looks like you are not accounting for the fact that asin, atan, ( any a-trig function ) has no way to know which of the two possible quadrants the value you passed in lies. To make up for that, a-trig function will assume that your point is in the first or fourth quadrant ( northeast / southeast ). Therefore, if you call atan function and your original point was in the second or third quadrant, you need to add 180 degrees / pi radians onto whatever value it returns.
See the documentation here stating that asin returns a value from [-pi/2, pi/2] :
http://www.mathworks.com/help/matlab/ref/asin.html
Hope that helps :)
EDIT
I misunderstood the situation originally
Here is what I think you have calculated :
t_1 and t_2 represent the angles you would travel at if you started on the circle from the tangent point and wanted to travel to your original starting point.
Viewed with this perspective your angles are correct.
For the point (7,6)
If you started on the circle at approx. (0,5) and traveled at 7 degrees, you would hit the point.
If you started on the circle at approx. (5,0) and traveled at 70 degrees, you would hit the point.
Now, what is going to be more useful and less confusing than angles, will be to know the slope of the line. To get this from the angle, do the following with angle in degrees:
angle = (angle + 90 + 360) % 180 - 90 // this gives us the angle as it would be in quad 1 or 4
slope = tan( deg2rad( angle ) )