[Solved] Apply impulse or force in the correct direction

Topics: User Forum
Jul 16, 2012 at 5:46 PM
Edited Jul 16, 2012 at 5:48 PM

Hi everyone! I would like to apply impulse or force on a body, so that it moves exactly in the direction of it's rotation. For that I would need to convert the degrees to a vector2, I guess. How does one do that? Is there a better alternative?

Regards,

Haris

Jul 16, 2012 at 10:33 PM
Edited Jul 16, 2012 at 10:33 PM

Recall the conversion from polar coordinates to cartesian coordinates.

(x,y)=(rCos(angle),rsin(angle)).  In your case r will be the magnitude of the force and (Cos(angle),Sin(angle)) will give you a unit vector in the direction you want.

Another way is to do Body.GetWorldVector(ref local_vector_facing_the_forward_direction e.g. (1,0) if body is created pointing to the right)

Jul 17, 2012 at 9:34 AM

Hi Jerry, thank you for the Math class!

Jul 17, 2012 at 3:28 PM
Edited Jul 17, 2012 at 3:50 PM

Jerry, I read one of your other contributions (http://farseerphysics.codeplex.com/discussions/355794) on the same topic. I'm a bit perplexed, because there is no Body.GetWorldVector command, but there is Body.GetWorldPosition. Is that what you meant? Here is what I tried, but the body doesn't seem to travel in the correct direction:

 

var ld = _ship.Body.Position;  
var wd = _ship.Body.GetWorldPosition(ld); 
wd.Normalize();
wd *= 10;
_ship.Body.ApplyForce(wd);

 

 

 

 

 

 

 

Jul 17, 2012 at 7:38 PM

I do have GetWorldVector() in my version (3.3.1 also in latest svn) - it's the next method after GetWorldPoint(). But anyways the difference is that the former doesn't take into consideration the position whereas GetWorldPoint() does. So you'd need to to subtract Body.Position from GetWorldPoint() to get what you need and then normalize. For reference here's the code from Body.cs on my install:

        public Vector2 GetWorldVector(ref Vector2 localVector)
        {
            return new Vector2(Xf.R.Col1.X * localVector.X + Xf.R.Col2.X * localVector.Y,
                               Xf.R.Col1.Y * localVector.X + Xf.R.Col2.Y * localVector.Y);
        }


       public Vector2 GetWorldPoint(ref Vector2 localPoint)
       {
           return new Vector2(Xf.Position.X + Xf.R.Col1.X * localPoint.X + Xf.R.Col2.X * localPoint.Y,
                              Xf.Position.Y + Xf.R.Col1.Y * localPoint.X + Xf.R.Col2.Y * localPoint.Y);
       }

Xf is the body transform. The R is the rotation matrix. Note the code is different in latest svn because the transform has been refactored.

HTH

P.S: Regarding the thread you mentioned - there is a method to approximate Sin and Cos using just algebra. My maths is not so advanced but the OP basically reinvented it I believe. Don't know if its correct or not - if it is, it's anyways a remarkable result to come up with something like this from scratch just... unnecessary :)

Jul 17, 2012 at 11:34 PM

You are right, I have an older version 2.1.3. I must've taken this Farseer project from a solution with samples that accompany the book "3D Game Development with Microsoft Silverlight 3". That is the book I'm learning from, and it's evidently outdated. In this new version there is no PhysicsSimulator class, and there is no Geometry class. Everything is changed!

Jul 18, 2012 at 2:51 PM

I switched to 3.3.1. Class World has replaced the PhysicsSimulator. Fixture has replaced the Geom object. I'm actually using Balder and it's Game class for my 3D game, and using Farseer only additionaly for the physics simulation. Now I see that Farseer also has it's own Game class. In Balder, on each update, I used this to update the physics simulator:

_physicsSimulator.Update((

float)_elapsedTime.TotalSeconds);

, but now World class doesn't have the Update command. How to update the World?

Jul 18, 2012 at 3:15 PM
Edited Jul 18, 2012 at 3:17 PM

I'd suggest you use the new 3.x Farseer over the 2.x series - it's just very good and is based on the Box2D C++ engine with some additions.While you're at it look at the TestBedXNA project and the Samples which are full of examples for many tasks.

But you could also add the missing method to the old one I suppose - see what you need to change in the source.

Anyways in the new Farseer you should call World.Step() or beter to run at 60Hz:

 float timeStep = Math.Min((float)gameTime.ElapsedGameTime.TotalMilliseconds * 0.001f, (1f / 60f));

World.Step(timeStep)

Jul 18, 2012 at 5:28 PM

I finally got everything working. I managed to move the object after I added this:

Body.BodyType =

BodyType.Dynamic;

 And I finally solved the original problem. The ship travels now in the correct direction:

var ld = new Vector2(0,-1);
var wd = _ship.Body.GetWorldVector(ld);
wd.Normalize();
wd *= 200;
_ship.Body.ApplyForce(wd);

The ship is pointing downwards at the start, so that's why (0,-1).

I also had to reverse the rotation angle of the body and the mesh. Jerry, you deserve a medal for endurance and patience for this! One more thing, I'm looking for a job to work from home, for a trifle. Anything to do with software. If you've got any ideas, please e-mail me at: harisomeragic@hotmail.com.

 

Coordinator
Aug 7, 2012 at 2:55 AM

I had no idea that Farseer Physics was featured in 3D Game Development with Microsoft Silverlight 3. Thanks for making me aware of this.

Aug 7, 2012 at 8:28 AM

Glad to help. But Farseer was not built for 3D, just for 2D, though you can combine three coordinate systems (three instances of PhysycsSimulator class, or World class i the newer release) to cover XY, XZ and YZ planes.

Feb 2, 2013 at 4:10 PM
I just want to say thank you stardust1611 you dont know how long i have been trying to do somthing like this also. I just started using farseer so yeah i dont know everything about it yet but i sure love it.