Page 1 of 1

rotation around point

Posted: Tue Jul 27, 2010 8:59 am
by serengeor
I'm not very good at vector maths so I'm asking you guys to help me figure out on how to achieve this kind of rotation (don't know if thats the right word to use )

This is a picture illustrating what I want this to make:
Image

So the object is black circle and it moves in the direction of yellow arrow
my other object has to go behind the black circle in a circular motion (have constant distance from black circle)

I need to make this work with angular velocity.

Posted: Tue Jul 27, 2010 9:26 am
by DarkDepths
Perhaps I'm misunderstanding the question, so I'd ask that you please clarify.

It sounds to me like you want the point of Origin for th rotation to be the blackCircleObject.

I'm afraid I'm not well enough acquainted with Irrlicht to tell you how this can be achieved specifically. There may be a function which will allow you to set the Node's rotation origin. I don't know about that, but if there is not one, then I think I might do something like:

1) Create an empty SceneNode at (0,0,0).
2) Create the blackCircle object.
3) Create the Rotating object at (radius, 0, 0).
4) Attach the Rotating object as a child of the empty SceneNode.
5) Every frame, move the empty SceneNode to the same position as the blackCircle object.
6) Rotate the empty SceneNode.


I think that would achieve what you want.... I think :D

Posted: Tue Jul 27, 2010 11:38 am
by serengeor
thanks for this idea :wink:, but I would like to do this the maths way( I mean I want to learn how this can be done the 'maths' way with sines and cosines)


So any ideas how this could be done ? :roll:

Posted: Tue Jul 27, 2010 12:19 pm
by DarkDepths
This is just off the top of my head, and it is also 4:45 AM, so please excuse me if the following makes absolutely no sense!

To start, I'll be working on only a 2D, xz plane.

First of all, you said that the rotating object will have a constant radius, and thus it will travel in a circular motion around the "black circle" (which, from now onwards I will simply call the "origin"). So, if we look at this system as a simple circle, the problem really comes down to trying to find the x,z coordinates at a certain point on the circle, so that if you wish to rotate the object around the origin, you can predict it's next position, given that you know it's "orbiting speed."

Fortunately, it shouldn't be too difficult. If we look at as a circle, then, no matter which point we pick on the circumference, if we draw a line from that point to the origin (tracing the radius to that point), we can also draw a vertical line from the point on the circumference such that it's secondary 'z-value' is equal to the 'z-value' of the origin, and a horizontal line from the origin to the secondary end-point of the vertical line. This gives us a right angle triangle.

Before I go any further, I need to state two things. First, I assume that your method will take an angle for the xz plane. Secondly, I assume this angle is between 0 - 360.

OK, now, the angle you pass in will be interpreted as the internal angle, ie the angle between the hypotenuse and the horizontal line. To get this angle, you will need to know which quadrant the point is in, I suppose, so you would have to do something like:

float[] getPositionOnCircle(float angle, float radius, float originX, float originY)

Code: Select all


int quad;
float tZ, tX, newX, newZ, tAngle;

if ( angle >= 0 && angle < 180 )
{
if (angle < 90)
{
quad = 1;
tAngle = angle;
}
else
{
quad = 2;
tAngle = 180 - angle;
}
}
else
{
if (angle <= 270)
{
quad = 3;
tAngle = abs(180-angle);
}
else
{
quad = 4;
tAngle = 360 - angle;
}
}

// Now to get the Z-Offset
tZ = radius*sin(tAngle);

// And with a little help from our friend Pythagoras...
tX = sqrt((radius^2) - (tZ^2));

// These are only Offsets though, so we need to find the actual location:

switch (quad)
{
case 1:
newX = originX+tX;
newZ = originY-tZ;
break;

case 2:
newX = originX - tX;
newZ = originY - tZ;
break;

case 3:
newX = originX - tX;
newZ = originY + tZ;
break;

case 4:
newX = originX + tX;
newZ = originY + tZ;
break;

default:
break; 
}

// Now you can just put newX and newY into an array of floats and return it.

If you want to add a third dimension and also retrieve the Y value, you should be able to repeat the process nearly as it is. You will be working on a circle still, but it will be on a different plane. So you will also need to add a dimension for the angle, my suggestion would be a second parameter indicating the "y-angle." This would simply describe the angle between the origin and the point on the y axis.

Again, sorry if none of this makes sense, or if it doesn't work at all, it is way to late/early for me to be trying to do this stuff :D
[/code]

Posted: Tue Jul 27, 2010 12:44 pm
by BlindSide
Check out core::vector3df rotateXYBy, rotateXZBy and rotateYZBy ;) (They take a "Center" parameter)

Posted: Tue Jul 27, 2010 12:54 pm
by serengeor
I need my second object to orient in the opposite direction of the circle's velocity, what angle do i have to get?
Angle between second object and circles linear velocity? :oops:

Code: Select all

float radius = 200.0f;
float angle = this->player->getLinearVelocity().angle(irrVecToBt(cam->getAbsolutePosition()));
int quad; 	
float tZ, tX, newX, newZ, tAngle; 

if ( angle >= 0 && angle < 180 ) 
{ 
if (angle < 90) 
{ 
quad = 1; 
tAngle = angle; 
} 
else 
{ 
quad = 2; 
tAngle = 180 - angle; 
} 
} 
else 
{ 
if (angle <= 270) 
{ 
quad = 3; 
tAngle = abs(180-angle); 
} 
else 
{ 
quad = 4; 
tAngle = 360 - angle; 
} 
} 

// Now to get the Z-Offset 
tZ = radius*sin(tAngle); 

// And with a little help from our friend Pythagoras... 
tX = sqrt((radius*radius) - (tZ*tZ)); 

// These are only Offsets though, so we need to find the actual location: 

switch (quad) 
{ 
	case 1: 
	newX = this->player->getWorldTransform().getOrigin().getX() +tX; 
	newZ = this->player->getWorldTransform().getOrigin().getZ() -tZ; 
	break; 
	
	case 2: 
	newX = this->player->getWorldTransform().getOrigin().getX() - tX; 
	newZ = this->player->getWorldTransform().getOrigin().getZ() - tZ; 
	break; 
	
	case 3: 
	newX = this->player->getWorldTransform().getOrigin().getX() - tX; 
	newZ = this->player->getWorldTransform().getOrigin().getZ() + tZ; 
	break; 
	
	case 4: 
	newX = this->player->getWorldTransform().getOrigin().getX() + tX; 
	newZ = this->player->getWorldTransform().getOrigin().getZ() + tZ; 
	break; 
	
	default: 
	break; 
} 

	vec.X = newX ;
	vec.Z =	newZ;
	vec.Y = this->player->getWorldTransform().getOrigin().getY()+150;
	this->cam->setPosition(vec);
	this->cam->setTarget(irr::core::vector3df(this->player->getWorldTransform().getOrigin().getX(),this->player->getWorldTransform().getOrigin().getY(),this->player->getWorldTransform().getOrigin().getZ()));
	cam->updateAbsolutePosition();
doesn't seem to work :cry:

Posted: Tue Jul 27, 2010 1:46 pm
by DarkDepths
Hey, if you are trying to use my code, then I think that 0 degrees would lie on the x-axis (positive), and 180 would lie on the x-axis (negative). So, you just need to know what direction the origin Object is moving in in this angle system. This should be fairly simple to get. Once you have that, the angle you want is simply abs(originObjectsAngle - 180);

Also, WHY AM I STILL AWAKE!!!! :P

Posted: Tue Jul 27, 2010 2:25 pm
by DarkDepths
Well, now that Blindside has made us aware of these functions, it seems a waste not to use them, or at least try to. It would make for much more elegant, and readable code, in any case.

So, I think the function you want is rotateXZBy(degrees, center);

Now just to fill in the blanks.

First, the center is easy: player->getAbsolutePosition();

Degrees might be a bit more tricky, there may be a nice function for that too, but it's now 7:04 AM and I am too tired to search for it :) So instead, I will try and show a simple way of figuring it out.

You will need to store the x,y,z coordinates of the player from the previous frame.

So you can do something like:

Code: Select all

float prevX, prevZ;

// Whenever you move the player do something like:
prevX = player->getAbsolutePosition().X;
prevZ = player->getAbsolutePosition().Z;

// -- moving code --
To find the angle in which the player traveled, then, you just do simple math:

Code: Select all

float deltaX = player->getAbsolutePosition().X - prevX;
float deltaZ = player->getAbsolutePosition().Z - prevZ;

float tempAngle = atan(deltaz/deltax) - 180;

//But, I think that rotateXZBy does rotates by a specified amount, not to a specific angle, so we need to get the current rotation of the object, and subtract.

float angle = yourObject->getRotation().Y - tempAngle;

// Then, rotate!

yourObject->rotateXZBy(angle, player->getAbsolutePosition());

Again, I'm not going to garuntee that this will work, and you might need to alter the code (I've been dealing in Java as of late :P), but I think this should do the sort of thing you are after.

Oh, and by the way, atan is in "cmath.h" I think.

Good luck, again :P

Posted: Tue Jul 27, 2010 3:47 pm
by serengeor
I would like it to rotate according to LinearVelocity (Bullet physics vector)
and not by objects rotation because my object rotates on all axis since its a physics object ( sphere )

Posted: Tue Jul 27, 2010 9:22 pm
by Iyad
You could take a look at the FlyCircle animator, there is already the algorithm written, all you have to do is to tweak it a bit.

Posted: Wed Jul 28, 2010 6:23 am
by serengeor
Iyad wrote:You could take a look at the FlyCircle animator, there is already the algorithm written, all you have to do is to tweak it a bit.
You should trust people more, I have tried at least 6~ algorithms so far and all of them gave me a messed up result. like camera, the best one so far was the one I had 'invented' :lol: It followed the sphere pretty good but the radius that I gave would only be the max radius for some reason, Tough now I wish I hadn't deleted the code.
I'll try to make this thing myself, still waiting for your suggestions tough
:wink:

Posted: Wed Jul 28, 2010 11:12 pm
by kaliber
maybe you can use third person camera algorithm

change the camera with the object you want to rotate