Given two vectors $A$ and $B$ on the unit cube, I am trying to get the flipped vector $C$ that lies on the opposite side of $B$ from $A$.
The following are the conditions of the "reflected" operator:
- assume that B's components are either 0, 1, or -1. aka B is either a corner vector or a center-face/center-edge vector
- we are dealing with MANHATTAN space. operators such as dot and cross don't have the same result in this space, so I don't recommend using them.
- distance(v1-v2) = distance(v2-v3) = 2 * distance(v1-reflected(v1,v2)) <- aka maintain manhattan distances
- cmax(abs(v3)) == cmax(abs(v1))
- reflected(v1,v2) == reflected(reflected(v1,v2), v2) //the reflection of a reflection is the original vector
- reflected(v1,v2) only has 1 solution, for all v1,v2
- the function maps for every vector in the unit square (aka continuous)
- reflected(v1,v2) = reflected(v1,-v2)
- reflected(v1,v1) = reflected(-v1,v1) = v1
The following are a few examples of inputs v1 and v2, and the reflection v3:
- v1=(1,0), v2=(1,1), reflected(v1,v2)=(0,1).
- v1=(1,y), v2=(1,0), reflected(v1,v2)=(1,-y)
- v1=(x, 1), v2=(0,1), reflected(v1,v2)=(-x,1)
- v1=(x,y), v2=(1,1), reflected(v1,v2) = (y,x) (remember that this only applies for cmax(abs(v1))==1)
- v1=(x,y), v2=(-1,1), reflected(v1,v2) = (-y, -x)
- v1=(1,y), v2=(0,1), reflected(v1,v2) = (-1, y)
- v1=(x,1), v2=(1,0), reflected(v1,v2) = (x, -1)
The 3D case changes things slightly. In a nutshell, we want the reflection to be on the same plane as v1 and v2, during this operation. In other words:
- v1=(0,0,1), v2=(1,1,1), reflected(v1,v2)=(0.5,0.5,0)
- v1=(0.1,0.5,1), v2=(0,0,1), reflected(v1,v2)=(-0.1,-0.5,1)
I have it working in 2D (with the above assumption on B), but need it in 3D. Here is a working script for the 2D case (with all vectors on the unit square):
public Vector2 Reflected_2general(Vector2 v1, Vector2 v2)
{
//Looks like it works, make sure to test it!!
// Translate the coordinates by subtracting v2 from v1
Vector2 v1_t = new Vector2(v1.x - v2.x, v1.y - v2.y);
// Perform a 45-degree rotation (either clockwise or counterclockwise)
// This is equivalent to swapping the x and y coordinates
Vector2 v1_r = new Vector2(v1_t.y, v1_t.x);
// Reflect across the x-axis
// This is equivalent to negating the y coordinate
Vector2 v1_rf = new Vector2(v1_r.x, -v1_r.y);
// Translate the coordinates back by adding v2
Vector2 v3 = new Vector2(v1_rf.x + v2.x, v1_rf.y + v2.y);
v3.x = Bouncey(v3.x, -1, 1);
v3.y = Bouncey(v3.y, -1, 1);
return v3;
}
public float Bouncey(float number, float min, float max)
{
float startingPosition = 0;
float cycle = 2 * (max - min);
float full_cycles = math.trunc(number / cycle);
float modified_value = number-cycle*full_cycles;
float position = startingPosition+modified_value;
if (position < min) {
position = min+(min-position);
if (max < position) {
return max - (position - max);
}
return position;
}
else if(min<= position && max >= position) {
return position;
}
else {
position = max - (position - max);
if (position < min) {
return min + (min - position);
}
return position;
}
// If the number is already within the range, return it
}
I tried doing a naive extension to 3D, but since the resulting vector has to stay on the same plane, I'm not sure how to implement this. There are solutions using cross products, but those don't work in manhattan space.