Thread: Vector rotation

  1. #1
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607

    Vector rotation

    After some research and the right google searches I found this information regarding vector rotation.

    #local AngleX = degrees(atn((T.z-L.z)/vlength(<T.x,T.y,0>-<L.x,L.y,0>));
    #if (T.y>L.y)
    #local AngleZ = degrees(atn((L.x-T.x)/(T.y-L.y)));
    #end

    #if (T.y<L.y)
    #local AngleZ = degrees(atn((L.x-T.x)/(T.y-L.y)))+180;
    #end

    #if (T.y=L.y)
    #if (T.x>L.x)
    #local AngleZ=-90;
    #else
    #local AngleZ=90;
    #end
    #end

    object { Gun rotate <AngleX,0,AngleZ> translate L }

    or you can do this instead:
    #local NY=vnormalize(T-L);
    #local NX=vnormalize(vcross(NY,z)); // z is down in this example
    #local NZ=vcross(NX,NY);
    object { Gun matrix < NX.x,NX.y,NX.z, NY.x,NY.y,NY.z, NZ.x,NZ.y,NZ.z, L.x,L.y,L.z > }
    Now this is for the POV ray tracer program. But, I think I can convert it to Direct3D.

    So to rotate a point that is at L to face T.
    Code:
    void MatrixRotateObjectOntoVector(D3DXVECTOR3 Target,D3DXVECTOR3 Location,D3DXMATRIX &RotMatrix)
    {
      D3DXVECTOR3 NX,NY,NZ,;
    
      NY=Target-Location;
      D3DXVec3Normalize(&NY,&NY);
    
      D3DXVec3Cross(&NX,&NY,&(-Camera.UpVector));
      D3DXVec3Normalize(&NX,&NX);
    
      D3DXVec3Cross(&NZ,&NX,&NY);
    
      //Setup rotation and translation
      RotMatrix._11=NX.x;
      RotMatrix._12=NX.y;
      RotMatrix._13=NX.z;
      RotMatrix._14=0.0f;
    
      RotMatrix._21=NY.x;
      RotMatrix._22=NY.y;
      RotMatrix._23=NY.z;
      RotMatrix._24=0.0f;
    
      RotMatrix._31=NZ.x;
      RotMatrix._32=NZ.y;
      RotMatrix._33=NZ.z;
      RotMatrix._34=0.0f;
    
      RotMatrix._41=Location.x;
      RotMatrix._42=Location.y;
      RotMatrix._43=Location.z;
      RotMatrix._44=1.0f;
    }
    Last edited by VirtualAce; 04-09-2005 at 06:44 PM.

  2. #2
    Registered User
    Join Date
    Mar 2003
    Posts
    580
    Hey man, what are you doing? What does it mean 'to rotate a point S to face T' ?

    You come up with a ton of interesting stuff but, like, did you ever intend for, you know, other humans to participate? You either are getting laid constantly which boosts your self esteem, or are snorting millions of dollars worth of coke, before visiting this site each day.
    See you in 13

  3. #3
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    >> What does it mean 'to rotate a point S to face T' ?

    yeah, there's something amiss here. Points have no orientation in space, just position. Rotating a point doesnt really make sense unless your talking about rotating a point around another point. Do you mean rotate a vector to face a point?

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    It should be rotate a vector at L to face a point in space T, not rotate a point.



    Rotating a vector to face a point is extremely extremely helpful. For instance if you want to rotate a vector to face a point in 3D space or point towards it you could use that. So if you know where the object B is and you want to make object A rotate to face object B then you can use what I posted.

    Take a model and set a velocity vector for it. Now how do you rotate the model from model space to world space and orient it such that it is always facing forward along it's velocity vector? Since the model is created in model/local space, it's orientation can be anything and just transforming it into world space is not going to work in all cases. You will have a spaceship that flies along a velocity vector but might face a totally different direction.

    Since vectors are infinite in space you can use this equation to pick any point in 3D space and rotate any vector to face that point, hence this will give you the correct x y and z amounts to cause the object to rotate and move towards the point.

    The stuff you gave me Darkness simply does not work with certain angles. This info I came across allows you to perform the same operation but does not use any inverse trig functions and therefore does not suffer from any angle aliasing issues.

    This is also useful for doing flyby camera's for objects and a host of other things. I cannot help that you do not see the usefulness of such an algorithm. I'm sure by now that Perspective has a clear understanding of what I'm getting at.

    And Darkness....chill dude.
    Last edited by VirtualAce; 04-11-2005 at 07:08 AM.

  5. #5
    Registered User
    Join Date
    Mar 2003
    Posts
    580
    I'm chill!!! I was trying to be funny (most males take the 'you must get laid all the time' thing as a compliment!)

    Anywho thanks for clearing that up (and I meant it when I said you post a lot of interesting stuff).

    edit:
    The stuff you gave me Darkness simply does not work with certain angles. This info I came across allows you to perform the same operation but does not use any inverse trig functions and therefore does not suffer from any angle aliasing issues.
    Yes it does, my code only uses inverse sine and cosine, not tan! The only 'problem' that exists is assuring the angle is positive or negative. If you look at the graph of asin and acos, the range (inputs) range from -1 to 1. If you look at my code, I normalize the vectors and then only take one of the components (i.e when calculating pitch, I take the y component and pass that into arcsine). The components I pass in are therefore guaranteed to fall in the range -1 to 1, therefore my code does in fact work for all angles. Also, I've implemented a little space shooter thingy since you posted that code, and the vehicles point guns and shoot in the direction towards the player. I did have to change some of the code but it only had to do with which component I set to zero before normalizing.
    Last edited by Darkness; 04-11-2005 at 09:07 AM.
    See you in 13

  6. #6
    Registered User
    Join Date
    Mar 2003
    Posts
    580
    I'm not letting you get off of the hook that easily. I want to know what you were talking about, either try to substantiate it or we can discuss the differences between my method and yours. But, as far as I can tell, mine is perfect. If you want, I can post a little demo of a 'bad guy' firing 'bullets' towards you in 3d space, using my euler angle calculation code.
    See you in 13

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Well it's not my method. I googled it and found it on the internet in relation to the POV ray tracer. I just converted the code from POV to Direct3D. But it does not help my problem because I'm rendering from the inverse view matrix which nullifies the effect. For my problem I will just go back to ray-picking to compute the coordinates.

  8. #8
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    This all sounds like a whole lot of fancy speak for "Billboarding"

  9. #9
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Actually it's an axis aligned billboard. The lasers are really long skinny textured quads. My biggest issue was getting the quad to point in the direction you were firing. It really doesn't look cool to fire a sideways facing laser out into space.

    So I thought this code might help, but it doesn't because when I use the inverse view matrix, +Z is always into the world. Essentially it 'undoes' the camera space transform and makes the math a lot easier.

    But I'm still faced with the problem of getting the lasers to fire through the cursor at some point in space in front of the ship.
    Freelancer does this quite well and it makes for a very satisfying space sim because you are not limited to firing straight ahead.

    I also need some type of convergence value so that I can set the convergence of the lasers at the correct values so they all arrive in the same spot at the same time, regardless of distance. I'm sure I will have to create a laser gun class and simply change the orientation of the laser gun as you move the mouse. Then when you fire, no extra computaton is needed. Just fire in the direction the gun is facing, and render it from the camera's perspective and all should be well.

    I'll try it but this requires me to add to the spaceship class so that I can incorporate laser guns and/or hardpoints into the class, which in turn would be controlled by another class. Hard-coding it would be easy but making your game engine extensible is probably the hardest thing to develop.

    But from this example you can probably see that this code will be used at some point. You have laser gun at position P and the mouse cursor is then translated to a point in 3D space. You want the laser gun to rotate to face point T so that when you send the fire message to the gun, the laser fires at that point in 3D space.
    And since I'm not going to render from the gun's perspective, I cannot just use an inverse view matrix to get the laser beam's orientation correct. It must be rotated to face along the same axis as the gun.

    So if this is my laser in model space.

    -1.0f,0.0f,10.0f
    1.0f,0.0f,10.0f
    -1.0f,0.0f,-10.0f
    1.0f,0.0f,-10.0f

    I want this rotated so that the largest axis or the z axis always points into the direction of fire. If I rotate the gun to face the point and this works, then it will also work to rotate the laser quad to face the point since the laser faces down the z axis in model space..
    Last edited by VirtualAce; 04-13-2005 at 02:33 PM.

  10. #10
    vae victus! skorman00's Avatar
    Join Date
    Nov 2003
    Posts
    594
    You just implimented the often used "LookAt" algorithm. D3DX has functions that perform that for you. Those would also help you out with your laser problem.

  11. #11
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Ya know I never even thought of using that obvious function. I'm gonna slap myself in the face for being stupid. It never occured to me to use the function to produce a matrix for something other than a view matrix. But you are right I could use the matrix from that function in the chain of concatenations to form the world matrix and it would work. Doh.

    Oh well, at least I did find the algo.

    Thanks a million for opening my blinded eyes.

    I want to show you just how stupid I was on this: The answer was sitting right inside the SDK. Damn it. No excuses on this one folks...I just dropped the ball.

    The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixLookAtLH function can be used as a parameter for another function.

    This function uses the following formula to compute the returned matrix.


    zaxis = normal(At - Eye)
    xaxis = normal(cross(Up, zaxis))
    yaxis = cross(zaxis, xaxis)

    xaxis.x yaxis.x zaxis.x 0
    xaxis.y yaxis.y zaxis.y 0
    xaxis.z yaxis.z zaxis.z 0
    -dot(xaxis, eye) -dot(yaxis, eye) -dot(zaxis, eye) 1
    Sometimes I guess Google is not your friend.

    Argh......I can't believe this info was right there and I never even though to look at it.

    Some days......some days.......I just tell ya.

    <...walks out the room muttering and shaking his head......>

    EDIT:

    BTW Darkness this is your answer. Just convert this matrix to be compatible with OpenGL right handedness and wallah - you have your rotation matrix. And do the math my friend it does make sense, I'm just baffled that you and I could not derive this thing. Note to self - stay away from sin(), cos(), and tan(). Especially when working with vectors. There always seems to be a way around these trig functions when working with vectors. The dot product, cross product, and normalization are some extremely powerful tools.
    Last edited by VirtualAce; 04-14-2005 at 07:21 AM.

  12. #12
    Registered User
    Join Date
    Mar 2003
    Posts
    580
    What are you talking about? I've had this working on my own for a long time. The only problem was that for my pitch code, you don't set the x component to zero.

    Here's some code of a bad guy that fires bullets ever x number of seconds in the direction of the player. It decomposes the vector connecting their positions into euler angles, rotates it out, and its direction is the same as the direction vector PlayerPos - EnemyPos

    Code:
    void	Physics_Bert::Update()
    {
    //	Vector3D	to = Export.mpPlayer->mPosition - mPosition;
    
    //	to.Normalize();
    //	if(DotProduct(&to,&mLinearVelocity)<0 && mLinearVelocity.BasicLength() > 50)
    //	{
    		mLinearVelocity	*=	1-(2*gpPhysics->mFrameTime);
    //	}
    //	else	
    //		mLinearVelocity	+=	to *METER(5)*gpPhysics->mFrameTime;
    
    	
    //	gpPhysics->UpdateNormalizedLinearVel(this);
    	
    //	Vector3D	toplayer(Export.mpPlayer->mPosition.x-mPosition.x,Export.mpPlayer->mPosition.y,Export.mpPlayer->mPosition.z-mPosition.z);
    //	toplayer.y = 0;
    	
    	Vector3D	toplayer	=	Export.mpPlayer->mPosition	-	mPosition;
    
    	Vector3D	Pitch;
    	Vector3D	Yaw;
    
    	Pitch	=	toplayer;
    	Yaw		=	toplayer;
    
    	Yaw.y	=	0;
    	Yaw.Normalize();
    	mYaw	=	RAD2DEG(acosf(-Yaw.z));
    
    	Pitch.Normalize();
    
    	mPitch	=	RAD2DEG(asinf(Pitch.y));
    
    	if(Export.mpPlayer->mPosition.x > mPosition.x)
    		mYaw = -mYaw;
    
    	static	int	curmis = 0;	//current missile
    	FireTimer.Update();
    
    	Vector3	FireVector(0,0,-1);
    	Matrix3x3	RotationVector;
    	
    	RotationVector.InitFromAngles(mPitch,mYaw,0);
    
    	RotationVector.TransformDir(&FireVector);
    
    	toplayer.Normalize();
    
    	char	message[1024];
    	char	message1[1024];
    
    	memset(message,0,sizeof(char)*1024);
    	memset(message1,0,sizeof(char)*1024);
    
    	sprintf(message,"ToPlayerVector: %f, %f, %f",toplayer.x,toplayer.y,toplayer.z);
    	sprintf(message1,"FireVector: %f, %f, %f", FireVector.x,FireVector.y,FireVector.z);
    
    	gpTextManager->ClearScreenText();
    	gpTextManager->PushLineOfText(message,-1024);
    	gpTextManager->PushLineOfText(message1,-1024);
    	
    
    	if(FireTimer.mTimeBuffer	>	60)	//If x seconds has passed fire a bullet towards the player, this does not correct for the player's velocity (just fires towards player)
    	{
    		++curmis;
    		if(curmis	>	10)	//which missile we are firing
    			curmis	=	0;
    		
    	//	Vector3D	toplayer	=	Export.mvPhysicsObjects[0]->mPosition	-	mPosition;
    		double		distance	=	toplayer.GetLength();
    		if(distance	>	mRadius	+	Export.mvPhysicsObjects[0]->mRadius	+	mMissile[curmis].mRadius	+	METER(1))
    		{
    			toplayer	*=	(1/distance);	//normalize
    			mMissile[curmis].mPosition	=	mPosition	+	(toplayer	*	(mMissile[curmis].mRadius+mRadius));
    			mMissile[curmis].mLinearVelocity	=	Vector3ToVector3D(FireVector)*METER(50);//toplayer*METER(50);
    			gpPhysics->UpdateNormalizedLinearVel(&mMissile[curmis]);
    		}
    		FireTimer.ResetTimeBuffer();
    	}
    
    	return;
    }
    Last edited by Darkness; 04-14-2005 at 07:59 AM.
    See you in 13

  13. #13
    vae victus! skorman00's Avatar
    Join Date
    Nov 2003
    Posts
    594
    No prob Bubba. To pay for my services, I ask that you answer a question for me: what is the purpose of the dot product calculation with the axes and the eye? The eye is a position, so I don't see what relavence the calculation would have.

  14. #14
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I'm talking about the fact that you don't need to use asinf or acosf.

    The dot product between the eye and the axis would return the arccos of the angle between them, which is exactly what Darkness is using, however, asinf and acosf are significantly slower than just using the dot product.

    Dot product will never return asinf so I'm not sure how both methods work perfectly.

  15. #15
    Registered User
    Join Date
    Mar 2003
    Posts
    580
    I don't see where any of the 'angle' macros are to be used, but they each involve an arc trig function. Dotproduct doesn't return arc cos, but a scalar proportional to cos, and besides, using the macros NX NY and NZ you incur a couple of normalizations, then a couple more, then a crossproduct or two...point being, you aint going to get this for cheap regardless. My method is pretty intuitive though:

    -Project the vector onto the XZ plane (Y = 0) then get the deviation from the negative Z axis, then correct for positive or negative angle (you could use tan instead, but you'd have to check for singularity)

    -For pitch, you do not project onto any plane, rather you are measuring the angle from the XZ plane to some point. My mistake in my first implementation was setting the X component to zero, effectively projecting onto the YZ plane, but this was not correct. No angle correction or singularity checking is required in the case of pitch.

    Normalizations aren't required, but you do need to compute length anyway (to get the ratio of some value over length), and normalizing is just easier
    See you in 13

Popular pages Recent additions subscribe to a feed