How to draw a line with x length in the direction of the mouse position in unity3D? - math

My question seems rather simple but i cant figure it out myself.
I want to draw a line with a fixed length from my transform.position in the direction where the mouse cursor is.
The things i figured out:
var mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
lazer.setPosition(0, transform.position);
// here is where the failing starts. i need to calculate the end position.
lazer.setPosition(1, ?)
Thanks A.

I think what you are looking for is the variable normalized on either the Vector2 or Vector3 class. Something like this will give you a new vector with the same length (magnitude, actually) every time:
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector3 offsetPos = mousePos - transform.position;
Vector3 newVec = offsetPos.normalized * scale; // this is the important line
newVec += transform.position;

Related

Unity3D - How to get the angle between 2 points as a vector

I have run into problems while trying to get my unity code done (using Javascript/Unityscript), so the question is:
How can i get the angle between two points (as Vector3s) and the angle as another Vector3
my code is :
var Offset : Vector3 = (0,0,3);
var angle1 : Vector3;
angle1 = Vector3.Angle(Vector3(0,0,0), Offset);
The error that i got is :
BCE0022: Cannot convert 'float' to 'UnityEngine.Vector3'.
I looked around, but was only able to find what i already knew.
Thanks for any help in advance !
-Etaash
In addition to the syntax error letiagoalves mentioned, Vector3.Angle returns a float, not a Vector3. You don't need to pre-define the angle variable, you can do it one line. Your final code should look like this:
var Offset : Vector3 = Vector3(0,0,3);
var angle1 = Vector3.Angle(Vector3(0,0,0), Offset);

Rotation matrix by yaw

I want to set the yaw of a rotation matrix so an object points to a specific position using this code
Vector3 dist = transform().position() - mPlayerTarget;
transform().rotationZ(atan2(dist.x(), dist.y()));
This would produce the right results, except the rotation is inverse, so instead of following the target point it rotates away from it.
Vector3 dist = transform().position() - mPlayerTarget;
transform().rotationZ(-atan2(dist.x(), dist.y()));
(with -atan2) the object follows the target, but it's offset by a 90 degrees to the right. The rotationZ implementation looks like this:
float cz = cosf(rotation);
float sz = sinf(rotation);
matrix.mMatrix[0] = cz;
matrix.mMatrix[1] = sz;
matrix.mMatrix[2] = 0;
matrix.mMatrix[3] = -sz;
matrix.mMatrix[4] = cz;
matrix.mMatrix[5] = 0;
matrix.mMatrix[6] = 0;
matrix.mMatrix[7] = 0;
matrix.mMatrix[8] = 1;
I'm using iOS OpenGL ES 2.0. Something seems fundamentally wrong here, the first version should be the one producing the right results? All the other transformations seem to work properly. What could go wrong here? I don't know where to look for errors...
First thing is atan2 - it is usually defined as atan2(y, x), whereas you have it the other way around.
Another source of issues might be the direction of your dist vector - it goes from the target towards the transform position. Try reversing it.

How do I take a 2D point, and project it into a 3D Vector by a perspective camera

I have a 2D Point (x,y) and I want to project it to a Vector, so that I can perform a ray-trace to check if the user clicked on a 3D Object, I have written all the other code, Except when I got back to my function to get the Vector from the xy cords of the mouse, I was not accounting for Field-Of-View, and I don't want to guess what the factor would be, as 'voodoo' fixes are not a good idea for a library. any math-magicians wanna help? :-).
Heres my current code, that needs FOV of the camera applied:
sf::Vector3<float> Camera::Get3DVector(int Posx, int Posy, sf::Vector2<int> ScreenSize){
//not using a "wide lens", and will maintain the aspect ratio of the viewport
int window_x = Posx - ScreenSize.x/2;
int window_y = (ScreenSize.y - Posy) - ScreenSize.y/2;
float Ray_x = float(window_x)/float(ScreenSize.x/2);
float Ray_y = float(window_y)/float(ScreenSize.y/2);
sf::Vector3<float> Vector(Ray_x,Ray_y, -_zNear);
// to global cords
return MultiplyByMatrix((Vector/LengthOfVector(Vector)), _XMatrix, _YMatrix, _ZMatrix);
}
You're not too fart off, one thing is to make sure your mouse is in -1 to 1 space (not 0 to 1)
Then you create 2 vectors:
Vector3 orig = Vector3(mouse.X,mouse.Y,0.0f);
Vector3 far = Vector3(mouse.X,mouse.Y,1.0f);
You also need to use the inverse of your perspective tranform (or viewprojection if you want world space)
Matrix ivp = Matrix::Invert(Projection)
Then you do:
Vector3 rayorigin = Vector3::TransformCoordinate(orig,ivp);
Vector3 rayfar = Vector3::TransformCoordinate(far,ivp);
If you want a ray, you also need direction, which is simply:
Vector3 raydir = Normalize(rayfar-rayorigin);

Moving character with vectors

Whenever I have a character and I want him to move to an object I always have to convert it to an angle, ex:
int adjacent = myPosition.X - thatPosition.X;
int opposite = myPosition.Y - thatPosition.Y;
double angle = Math.atan2(adjacent, opposite);
myPosition.X += Math.cos(angle);
myPosition.Y += Math.sin(angle);
Is there an easier way to move an object to another by just using vectors and not converting to an angle and back, if so I would appreciate if you showed how and/or pointed me to a site that could show me.
p.s. I am coding in XNA
Yes, you can minimize the trig & take a more linear algebra approach. That would look something like this:
//class scope fields
Vector2 myPosition, velocity, myDestination;
float speed;
//in the initialize method
myPosition = new Vector2(?, ?);
myDestination = new Vector2(?, ?);
speed = ?f;//usually refers to "units (or pixels) per second"
//in the update method to change the direction traveled by changing the destination
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
myDestination = new Vector2(?', ?');//change direction by changing destination
Velocity = Vector2.Normalize(myDestination - myPosition);
velocity *= speed;
myPosition += velocity * elapsed;
//or instead of changing destination to change velocity direction, you can simply rotate the velocity vector
velocity = Vector2.Transform(velocity, Matrix.CreateRotationZ(someAngle);
velocity.Normalize();
velocity *= speed;
myPosition += velocity * elapsed;
The only angles/trig used here is the trig that is embedded in the CreateRotationZ() method and it is happening behind the scenes by the xna framework.

Cocos2D/Math - clean angle conversion

Mornin' SO!
I'm just trying to hone my math-fu, and I have some questions regarding Cocos2D in particular. Since Cocos2D wants to 'simplify' things, all sprites have a rotation property, ranging from 0-360 (359?) CW. This forces you to do some rather (for me) mind-humping conversions when dealing with functions like atan.
So f.ex. this method:
- (void)rotateTowardsPoint:(CGPoint)point
{
// vector from me to the point
CGPoint v = ccpSub(self.position, point);
// ccpToAngle is just a cute wrapper for atan2f
// the macro is self explanatory and the - is to flip the direction I guess
float angle = -CC_RADIANS_TO_DEGREES(ccpToAngle(v));
// just to get it all in the range of 0-360
if(angle < 0.f)
angle += 360.0f;
// but since '0' means east in Cocos..
angle += 180.0f;
// get us in the range of 0-360 again
if(angle > 360.0f)
angle -= 360.0f;
self.rotation = angle;
}
works as intended. But to me it looks kind of brute forced. Is there a cleaner way to achieve the same effect?
It is enough to do
float angle = -CC_RADIANS_TO_DEGREES(ccpToAngle(v));
self.rotation = angle + 180.0f;
for equivalent transformations
// vector from me to the point
CGPoint v = ccpSub(self.position, point);
actually, that's vector from point to you.
// just to get it all in the range of 0-360
you don't need to do that.

Resources