How can I wrap a value around arbitrary boundaries? I want to avoid if checks, so I have come up with this that works for a low boundary using step:
float check = step(-1, val)*2.0-1.0;
val *= check;
This will output whatever value the vector val has when it is greater than -1, and wrap around, and jump to 1 when it exceeds it.
My goal is that when a value exceeds a certain threshold, it "wraps" up and starts back from the opposite side of the screen. So, if a moving dot for example exceeds 1, then it will re-appear in the screen in the -1 position, and keep on moving from there on.
On the other hand if is below -1, it will appear in position 1 and keep moving from there.
float check = step(-1, val)*2.0-1.0;
This will effectively output whatever value the vector val has in its components whenever that value is greater than -1, and wrap around and jump to 1 when it exceeds it.
No. The result of the function step() is eiterh 0.0 or 1.0, in any case. So the result of step(-1, val)*2.0-1.0 is either -1.0 or 1.0.
My goal is that when a value exceeds a certain threshold, it "wraps" up and starts back from the opposite side of the screen. So, if a moving dot for example exceeds 1, then it will re-appear in the screen in the -1 position,
What you want to do can be achieved by the function mod(x, y)https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/mod.xhtml, which returns the rest of the division of x by y:
y = mod(x+1.0, 2.0)-1.0
Independent on the value of x has, the result of the function is always in the range [-1, 1]. If the upper limit 1 is reached the immediately following result is -1:
Note, the function uses mod()https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/mod.xhtml support genType. This means x and y can even be of type vec2, vec3 or vec4. Of course x and y have to be of the same type.
Related
I am trying to compute integer array bounds that will include floating point limits divided by a scale. For example, if my origin is 0, my floating point maximum is 10 then my integer array bounds need to be 2. The obvious formula is to divide my bounds by the scale, giving the incorrect result of 1.
I need to divide the inclusive maximum values by the scale and add one if the division is an exact multiple.
I am running into a mismatch between the normal way to define and use integer array indexes and my desired way to use real value coordinates. I am trying to map inclusive real value coordinates into integer array indexes, using a scaling term.
(I am actually working with two dimensional maps, but the problem can be expressed more simply in one dimension.)
This is wrong:
int get_array_size(double, scale, double maximum)
{
return std::ceil(maximum / scale); // Fails on exact multiples
}
This is wasteful:
int get_array_size(double, scale, double maximum)
{
return 1 + std::ceil(maximum / scale); // Allocates extra array memory
}
This is ugly and I am not sure if it is correct:
int get_array_size(double, scale, double maximum)
{
if (maximum % scale == 0) // I am not sure if this is correct
return 1 + std::ceil(maximum / scale);
else
return std::ceil(maximum / scale); // Maybe I can eliminate the call to std::ceil?
}
I am trying to get the value maximum / scale on every open ended interval ending at multiples of scale and 1 + maximum / scale on every interval from >= multiple of scale ending at < multiple of scale + 1. I am not sure how to correctly express this in mathematical terms or how to implement it in c++. I would be grateful if someone can clarify my understand and point me in the right direction.
Mathematically I think I am trying to define f(x, s) = y s.t. if s * n <= x and x < s * (n + 1) then y = n + 1. I want to implement this efficiently and respect the difference between <= and < comparison.
The way I interpret this question, I think maximum and scale don't actually matter - what you are really asking about is how to correctly map from floats to ints with specific boundary conditions. For example [0.0, 1.0) to 0, [1.0, 2.0) to 1, etc. So the question becomes a bit simpler if we just consider maximum / scale to be a single quantity; I'll call it t.
I believe you actually want to use std::floor instead of std::ceil:
int scaled_coord_to_index(float t) {
return std::floor(t);
}
And the size of your array should always be the maximum scaled coordinate + 1 (with negative values normalized to start at 0).
int array_size(float min_t, float max_t) {
// NOTE: This will "anchor" your coords based on the most negative value.
// e.g. if that value is 1.6, then your bins will be [1.6, 2.6), [2.6, 3.6), etc.
// To change that behavior you could use std::floor(min_t) instead.
return scaled_coord_to_index(max_t - min_t) + 1;
}
Given that analog stick outputs values
float xaxisval = controller->left_stick_x_axis(); //-1 is left, 1 is right
float yaxisval = controller->left_stick_y_axis(); //-1 is up, 1 is down
Values go from 0 to 1 with which can be used for sensitivity.
I'm moving the character in the direction of the joystick in a 3D environment the same way you would in a game like Diablo. I'm adding and retracting these values from X and Z position to move him. But the character is always facing the same dierection.
How can I use these values and convert them into degrees?
xaxisval += controller->left_stick_x_axis() /100;
yaxisval += controller->left_stick_y_axis() /100;
distAdjust.SetTranslation(Vector4(xaxisval, 0, yaxisval));
rotateAdjust.RotationX(rotateDegrees);
player_->set_transform(player_transform *distAdjust *rotateAdjust)
Problem I have is the movement only works with fixed rotation, if I rotate the object then it moves into a different direction.
I don't know what your function "rotateAdjust.RotationX(rotateDegrees);" really do.
But, you should for every game cycle take the value from 0 to 1 from your joystick, then multiply it by a constant angle depending of your rotation speed.
const float Angle = 1.0f; // Or whatever you want. Set more to increase rotation speed.
...
// Game loop
while ( true )
{
...
float xSensitivity = controller->left_stick_x_axis(); // example 0.33f for that cycle
myGuy.xRotate(Angle * xSensitivity);
...
}
"Angle" is a constant and can be expressed in degree or radian depending of your rotation function.
I want to find a best way because all coordinates are integer values and polygons consist of horizontal and vertical lines only. I think there may be a simple and fast method to do this.
From an asymptotic complexity point of view, a rectilinear polygon is not really simpler to process than a general one: O(N) without preprocessing, and O(Log N) after O(N Log N) preprocessing (but using a complicated procedure).
For the case of no preprocessing, the procedure is simple: consider every vertical side in turn and count those that cross the horizontal half-line from the given point (+1 upward, -1 downward). The point is inside if the final count is nonzero.
The status of points on the outline is application-dependent.
For rectilinear poygons with not too large integer coordinates, you can anyway do a little better, by "compressing" them. By two independent sorts on X and Y, you can obtain a mapping from X (or Y) to integer indexes in range [0,N). This gives the shrunk polygon below, of size NxN.
Now you can embed the polygon in an image and preprocess to label the pixels as inside/outside (by seed-filling). After filling two lookup-tables for coordinate conversion, you can obtain the status of any point in constant time O(1).
This will take O(N²+M) preprocessing time and storage, where M is the range of X and Y values.
Consider any polygon, not necessary convex, formed only with horizontal and vetical lines:
Take a point (I've drawn A,B,C,D) and draw horizontal and vertical lines passing through the point.
Let's take point A. You see the horizontal line through it crosses four (vertical) segments. Note one segment is at left and the others are at right.
For point B its horizontal line crosses also four segments, but two at left and two at right.
The conditions that a point must fulfill to be inside a polygon are:
At least one segment is horizontaly crossed at left of the point.
At least one segment is horizontaly crossed at right of the point.
Both numbers of crosses left, right must be odd.
Same three conditions for vertical lines.
So, in pseudocode it goes like this:
let nL = 0, nR = 0 //left/right counters
let nA = 0, nU = 0 //above/under counters
for each segment s(sx1,sy1, sx2, sy2) in polygon
if point is on segment
return true //or false, your choice
else if segment is vertical and pointY is inside of (sy1,sy2)
if pointX > min(sx1,sx2)
nL = nL + 1
else
nR = nR + 1
else if segment is horizontal and pointX is inside of (sx1,sx2)
if pointY > min(sy1,sy2)
nU = nU + 1
else
nA = nA + 1
//Check conditions
if nL > 0 and nR > 0 and nL is odd and nR is odd
return true
if nA > 0 and nU > 0 and nA is odd and nU is odd
return true
return false
I have an NxN grid with 2 points, the source and destination. I need to move step by step from the source to the destination (which is also moving). How do I determine what the next point is to move to?
One way is to assess all 8 points and see which yields the lowest distance using an Euclidian distance. However, I was hoping there is a cool (mathematical) trick which will yield more elegant results.
Your question statement allows moving diagonally, which is faster (since it's moving both horizontally and vertically in a single step): this solution will always do that unless it has the same x or y coordinate as the target.
using Position = pair<int,int>;
Position move(Position const ¤t, Position const &target) {
// horizontal and vertical distances
const int dx = target.first - current.first;
const int dy = target.second - current.second;
// horizontal and vertical steps [-1,+1]
const int sx = dx ? dx/abs(dx) : 0;
const int sy = dy ? dy/abs(dy) : 0;
return { current.first + sx, current.second + sy };
}
I'm not sure if this counts as a cool mathematical trick though, it just depends on knowing that:
dx = target.x-current.x is positive if you should move in the positive x-direction, negative if you should go in the negative direction, and zero if you should go straight up/down
dx/abs(dx) keeps the sign and removes the magnitude, so it's always one of -1,0,+1 (avoiding however division by zero)
I suppose that answer to your question is Bresenham's line algorithm. It allows to build sequence of integer points between start and end points in your grid. Anyway you can adapt ideas from it to your problem
For more information see https://www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html
I would simply use some vector math, take dest minus source as a vector, and then calculate the angle between that vector and some reference vector, e.g. <1, 0>, with standard methods.
Then you can simply divide the circle in 8 (or 4 if your prefer) sections and determine in which section your vector lies from the angle you obtained.
See euclidean space for how to calculate the angle between two vectors.
I have an array that represents a grid
For the sake of this example we will start the array at 1 rather that 0 because I realized after doing the picture, and can't be bothered to edit it
In this example blue would have an index of 5, green an index of 23 and red 38
Each color represents an object and the array index represents where the object is. I have implemented very simple gravity, whereby if the grid underneath is empty x + (WIDTH * (y + 1)) then the grid below is occupied by this object, and the grid that the object was in becomes empty.
This all works well in its current form, but what I want to do is make it so that red is the gravity point, so that in this example, blue will move to array index 16 and then 27.
This is not too bad, but how would the object be able to work out dynamically where to move, as in the example of the green grid? How can I get it to move to the correct index?
Also, what would be the best way to iterate through the array to 'find' the location of red? I should also note that red won't always be at 38
Any questions please ask, also thank you for your help.
This sounds very similar to line rasterization. Just imagine the grid to be a grid of pixels. Now when you draw a line from the green point to the red point, the pixels/cells that the line will pass are the cells that the green point should travel along, which should indeed be the shortest path from the green point to the red point along the discrete grid cells. You then just stop once you encounter a non-empty grid cell.
Look for Bresenham's algorithm as THE school book algorithm for line rasterization.
And for searching the red point, just iterate over the array linearly until you have it and then keep track of its grid position, like William already suggested in his answer.
x = x position
y = y position
cols = number of columns across in your grid
(y * cols) + x = index in array absolute value for any x, y
you could generalize this in a function:
int get_index(int x, int y, int gridcols)
{
return (gridcols * y) + x;
}
It should be noted that this works for ZERO BASED INDICES.
This is assuming I am understanding what you're talking about at all...
As for the second question, for any colored element you have, you should keep a value in memory (possibly stored in a structure) that keeps track of its position so you don't have to search for it at all.
struct _THING {
int xpos;
int ypos;
};
Using the get_index() function, you could find the index of the grid cell below it by calling like this:
index_below = get_index(thing.x, thing.y + 1, gridcols);
thing.y++; // increment the thing's y now since it has moved down
simple...
IF YOU WANT TO DO IT IN REVERSE, as in finding the x,y position by the array index, you can use the modulus operator and division.
ypos = array_index / total_cols; // division without remainder
xpos = array_index % total_cols; // gives the remainder
You could generalize this in a function like this:
// x and y parameters are references, and return values using these references
void get_positions_from_index(int array_index, int total_columns, int& x, int& y)
{
y = array_index / total_columns;
x = array_index % total_columns;
}
Whenever you're referring to an array index, it must be zero-based. However, when you are referring to the number of columns, that value will be 1-based for the calculations. x and y positions will also be zero based.
Probably easiest would be to work entirely in a system of (x,y) coordinates to calculate gravity and switch to the array coordinates when you finally need to lookup and store objects.
In your example, consider (2, 4) (red) to be the center of gravity; (5, 1) (blue) needs to move in the direction (2-5, 4-1) == (-3, 3) by the distance _n_. You get decide how simple you want n to be -- it could be that you move your objects to an adjoining element, including diagonals, so move (blue) to (5-1, 1+1) == (4, 2). Or perhaps you could move objects by some scalar multiple of the unit vector that describes the direction you need to move. (Say, heavier objects move further because the attraction of gravity is stronger. Or, lighter objects move further because they have less inertia to overcome. Or objects move further the closer they are to the gravity well, because gravity is an inverse square law).
Once you've sorted out the virtual coordinates of your universe, then convert your numbers (4, 2) via some simple linear formulas: 4*columns + 2 -- or just use multidimensional arrays and truncate your floating-point results to get your array indexes.