Search Unity

Possible to restrict Vector3 to a diamond shape?

Discussion in 'Scripting' started by Warrior1424, Jul 2, 2015.

  1. Warrior1424

    Warrior1424

    Joined:
    Sep 30, 2010
    Posts:
    984
    Imagine I have the following Vector3:
    Code (JavaScript):
    1. var hor = Input.GetAxis("Horizontal");
    2. var ver = Input.GetAxis("Vertical");
    3.  
    4. var myVector = Vector3(hor, 0, ver);
    Now, if I held right arrow and up arrow, myVector would look like this:
    Code (JavaScript):
    1. Vector3(1.0, 0, 1.0);
    Which means all of the possible places for values to be would make a square shape.

    If I normalized it, it would look something like this:
    Code (JavaScript):
    1. Vector3(0.7, 0, 0.7);
    Which means all of the possible places for values to be would make a circle shape.

    What I need is this:
    Code (JavaScript):
    1. Vector3(0.5, 0, 0.5);
    Which would mean all of the possible places for values to be would have to make a diamond shape:


    But how would I go about restricting a Vector3 to make this shape? Is it even possible?

    EDIT:
    Well it's certain that |X| + |Y| = 1, but I'm not sure how to translate that it into modifying/limiting a Vector3. It could possibly be quite easy, I don't really know. My brain is pretty fried from a long night of coding.
     
    Last edited: Jul 2, 2015
  2. arty155

    arty155

    Joined:
    Apr 17, 2015
    Posts:
    22
    Other than creating a diamond, what is your desired outcome. I am not viewing this the same way you are, so I'm not seeing how any of the vectors create anything but a single point. I mean you could create a plane that has 4 points, and then texture the plane. You could create a diamond shape with lines between each point as a sort of boundary. Why do you need the diamond? That will help us with a better answer.

    Your picture kind of illustrates how you can hard code the 4 points of the diamond based on a variable 5th point, that being the center.

    center = myVector
    point1 = Vector3 (hor + 0.5, 0, ver + 0.5)
    point2 = Vector3 (hor + 0.5, 0, ver - 0.5)
    point3 = Vector3 (hor - 0.5, 0, ver + 0.5)
    point4 = Vector3 (hor - 0.5, 0, ver - 0.5)

    So wherever you retriever your center point through a mouse click, or keyboard movement, you will end up calculating 4 points as a diamond shape around the center point.

    I still don't see how you are coming up with a circle based on a Vector3(0.7, 0, 0.7) by normalizing the vector. That is still only 1 point, nothing that has to do with a radius calc for a circle.

    It's been a long day for me, lol, so maybe I'm probably missing something critical. Sorry if my answer doesn't help.
     
  3. Pavlon

    Pavlon

    Joined:
    Apr 15, 2015
    Posts:
    191
    I am not sure if there is a easy math solution but with this one it should also work
    Code (CSharp):
    1.  
    2.  
    3. tmp_x = x;
    4. tmp_y = y;
    5.  
    6. if( x < 0) tmp_x = x * -1;
    7. if( y < 0) tmp_y = y * -1;
    8.  
    9. if(tmp_x+tmp_y > 1) // you are over the red border
    10.  
    11.  
    12.  
     
    Last edited: Jul 3, 2015
  4. Shinyclef

    Shinyclef

    Joined:
    Nov 20, 2013
    Posts:
    505
    Your x + y idea is a good one. I assume you want to snap positions to the nearest point.

    First find something we can multiply by to get to 1.
    Multiplier = 1 / (x+y)

    Now extend each component by that.
    VectorX *= multiplier.
    VectorY *= multiplier.

    I think that will snap?

    Or just check multiplier = 1 if you want to reject bad values?

    Thinking about this on the train so hopefully it works. Not sure if that's what you wanted...

    Edit. Posted way after writing it. Maybe the other answers are a better fit for you. Hope my answer is useful anyway.
     
  5. Warrior1424

    Warrior1424

    Joined:
    Sep 30, 2010
    Posts:
    984
    Sorry for not explaining more.

    Here's a better example in pseudo code:
    Code (JavaScript):
    1. //Bound to left/right arrow
    2. var hor = Input.GetAxis("Horizontal");
    3. //Bound to up/down arrow
    4. var ver = Input.GetAxis("Vertical");
    5. var myVector = Vector3(hor, 0, ver);
    6.  
    7. //The value below should be 1.0 when holding down right arrow
    8. myVector.x
    9.  
    10. //The value below should be 0.5 when holding both right and up arrow
    11. myVector.x
    12.  
    13. //The value below should be zero when holding up arrow only
    14. myVector.x
    Hopefully that explains better.
    Thank you all for helping!
     
  6. Nikussan

    Nikussan

    Joined:
    Jan 23, 2014
    Posts:
    5
    Basically, normalizing is dividing a vector by its length.
    You'll get diamond-shaped constraints if you use "manhattan length" instead of true vector length.
    Code (CSharp):
    1. manhattanLength = Mathf.abs(rawInputVector.x) +Mathf.abs(rawInputVector.y) + Mathf.abs(rawInputVector.z);
    2. constrainedVector = rawInputVector / manhattanLength;
     
  7. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    I think you have to do this with line intersections, I've drawn an image for you, hope you can understand my handwriting.

    diamond.png
    You'd do this piecewise for each quadrant, I've only done the first here. To get the angle (alpha) you'll use cos/sin on the original input.

    Also, if you only want the point on the diamond, you can skip the new length step, that's only for interpolating the length.
     
  8. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    TIL. That's much simpler, just disregard my post above. :)
     
  9. Warrior1424

    Warrior1424

    Joined:
    Sep 30, 2010
    Posts:
    984
    @Nikussan That's exactly what I needed, thank you so much!

    And thank you to everyone else for your responses as well.
    Especially @steego , for taking the time to draw an image.