[Resource] Rotate ObjectReference around another ObjectRefer

Post » Mon Nov 19, 2012 6:24 pm

You may be in a situation where you need to be able to precisely rotate one ObjectReference around another ObjectReference. This proved to be somewhat challenging if you are not familiar with rotation matricies (like me).

This function takes in an akOrigin (the ObjectReference to act as the center) and an akObject (the ObjectReference you want to be rotated). Note that this function returns a float[3] array; it does not perform the actual rotation. It returns a new set of X, Y, Z worldspace coordinates in the [0], [1], and [2] elements of the array that correspond to the coordinates your reference should be located at, once it's been rotated by the degrees you specified in the function call. You will need to create a new array to accept the return of this function. Once you have the coordinates returned by this function, you can call whatever movement function you like at that point (most likely SplineTranslateTo) using whatever parameters you choose.

Enjoy. I've tested it and it works.

float[] function GetPosXYZRotateAroundRef(ObjectReference akOrigin, ObjectReference akObject, float fAngleX, float fAngleY, float fAngleZ)

Rotates a point (coordinates of akObject) offset from the center of rotation (akOrigin) by the supplied degrees fAngleX, fAngleY, fAngleZ, and returns the new desired position of the point.
Spoiler
float[] function GetPosXYZRotateAroundRef(ObjectReference akOrigin, ObjectReference akObject, float fAngleX, float fAngleY, float fAngleZ);-----------\;Description \  Author: Chesko;----------------------------------------------------------------;Rotates a point (coordinates of akObject) offset from the center of;rotation (akOrigin) by the supplied degrees fAngleX, fAngleY,;fAngleZ, and returns the new desired position of the point.;-------------\;Return Values \;----------------------------------------------------------------; fNewPos[0] =  The new X position of the point; fNewPos[1] =  The new Y position of the point; fNewPos[2] =  The new Z position of the point; |1 0 0 |;Rx(t) =  |0 cos(t) -sin(t) |; |0 sin(t) cos(t) |;; |cos(t) 0 sin(t) |;Ry(t) = |0 1 0 |; |-sin(t) 0 cos(t) |;; |cos(t) -sin(t) 0 |;Rz(t) =  |sin(t) cos(t) 0 |; |0 0 1 |;R * v = Rv, where R = rotation matrix, v = column vector of point [ x y z ], Rv = column vector of point after rotationfAngleZ = -(fAngleZ)  ;Invert Z angle to account for the game's interpretation of Z rotationfloat myOriginPosX = akOrigin.GetPositionX()float myOriginPosY = akOrigin.GetPositionY()float myOriginPosZ = akOrigin.GetPositionZ()float fInitialX = akObject.GetPositionX() - myOriginPosXfloat fInitialY = akObject.GetPositionY() - myOriginPosYfloat fInitialZ = akObject.GetPositionZ() - myOriginPosZfloat fNewXfloat fNewYfloat fNewZ;Objects in Skyrim are rotated in order of Z, Y, X, so we will do that here as well.;Z-axis rotation matrixfloat fVectorX = fInitialXfloat fVectorY = fInitialYfloat fVectorZ = fInitialZfNewX = (fVectorX * cos(fAngleZ)) + (fVectorY * sin(-fAngleZ)) + (fVectorZ * 0)fNewY = (fVectorX * sin(fAngleZ)) + (fVectorY * cos(fAngleZ)) + (fVectorZ * 0)fNewZ = (fVectorX * 0) + (fVectorY * 0) + (fVectorZ * 1);Y-axis rotation matrixfVectorX = fNewXfVectorY = fNewYfVectorZ = fNewZfNewX = (fVectorX * cos(fAngleY)) + (fVectorY * 0) + (fVectorZ * sin(fAngleY))fNewY = (fVectorX * 0) + (fVectorY * 1) + (fVectorZ * 0)fNewZ = (fVectorX * sin(-fAngleY)) + (fVectorY * 0) + (fVectorZ * cos(fAngleY));X-axis rotation matrixfVectorX = fNewXfVectorY = fNewYfVectorZ = fNewZfNewX = (fVectorX * 1) + (fVectorY * 0) + (fVectorZ * 0)fNewY = (fVectorX * 0) + (fVectorY * cos(fAngleX)) + (fVectorZ * sin(-fAngleX))fNewZ = (fVectorX * 0) + (fVectorY * sin(fAngleX)) + (fVectorZ * cos(fAngleX));Return resultfloat[] fNewPos = new float[3]fNewPos[0] = fNewX + myOriginPosXfNewPos[1] = fNewY + myOriginPosYfNewPos[2] = fNewZ + myOriginPosZreturn fNewPosendFunction

Example:

float[] myNewPos = new float[3]myNewPos = GetPosXYZRotateAroundRef(PlayerRef, myCabbage, 25.0, 0.0, 0.0)   ;Find out where myCabbage would be if rotated 25.0 degrees on the X axis around the Player.myCabbage.SplineTranslateTo(myNewPos[0], myNewPos[1], myNewPos[2], 0.0, 0.0, 0.0, 1.0, 200.0)  ;Move the cabbage to the new rotated position
User avatar
Da Missz
 
Posts: 3438
Joined: Fri Mar 30, 2007 4:42 pm

Post » Mon Nov 19, 2012 5:24 pm

And as usual, the forums jacked up my formatting.

If you'd like to see a more properly formatted version, http://pastebin.com/WFgjRt3y.
User avatar
Wanda Maximoff
 
Posts: 3493
Joined: Mon Jun 12, 2006 7:05 am

Post » Mon Nov 19, 2012 7:36 pm

Thank you so much, I'm going to need to do this soon. The fact that you set this up will probably save a lot of time!
User avatar
scorpion972
 
Posts: 3515
Joined: Fri Mar 16, 2007 11:20 am

Post » Mon Nov 19, 2012 9:10 pm

No problem. :drag:
User avatar
lexy
 
Posts: 3439
Joined: Tue Jul 11, 2006 6:37 pm

Post » Mon Nov 19, 2012 5:34 pm

Minor update. Made a change that inverts the Z angle before computation, to account for the game's interpretation of z-rotation (it's backwards). I can't edit the pastebin post, so make sure you get your code from the post up top. If you want to add the change yourself, just change:


;R * v = Rv, where R = rotation matrix, v = column vector of point [ x y z ], Rv = column vector of point after rotation

to

;R * v = Rv, where R = rotation matrix, v = column vector of point [ x y z ], Rv = column vector of point after rotationfAngleZ = -(fAngleZ)

User avatar
Chris BEvan
 
Posts: 3359
Joined: Mon Jul 02, 2007 4:40 pm

Post » Mon Nov 19, 2012 3:39 pm

Would not...
fNewX = (fVectorX * cos(fAngleZ)) + (fVectorY * sin(-fAngleZ))
...work just as well as...
fNewX = (fVectorX * cos(fAngleZ)) + (fVectorY * sin(-fAngleZ)) + (fVectorZ * 0)
...since '(fVectorZ * 0)' will always equal 0 regardless of fVectorZ's value (and other such instances)?

Forum formatting: You can retain formatting, but you have to turn off the WYSIWYG editor with the light switch looking thingy in the upper left when posting/editing.
Spoiler
float[] function GetPosXYZRotateAroundRef(ObjectReference akOrigin, ObjectReference akObject, float fAngleX, float fAngleY, float fAngleZ)	;-----------\	;Description \  Author: Chesko	;----------------------------------------------------------------	;Rotates a point (coordinates of akObject) offset from the center of	;rotation (akOrigin) by the supplied degrees fAngleX, fAngleY,	;fAngleZ, and returns the new desired position of the point.		;-------------\	;Return Values \	;----------------------------------------------------------------	;		fNewPos[0]	= 	The new X position of the point	;		fNewPos[1]	= 	The new Y position of the point	;		fNewPos[2]	= 	The new Z position of the point	;				|1		0		0	|	;Rx(t) = 			|0		cos(t)		-sin(t)	|	;				|0		sin(t)		cos(t)	|	;	;				|cos(t)		0		sin(t)	|	;Ry(t) =			|0		1		0	|	;				|-sin(t)	0		cos(t)	|	;	;				|cos(t)		-sin(t)		0	|	;Rz(t) = 			|sin(t)		cos(t)		0	|	;				|0		0		1	|		;R * v = Rv, where R = rotation matrix, v = column vector of point [ x y z ], Rv = column vector of point after rotation	fAngleZ = -(fAngleZ)  ;Invert Z angle to account for the game's interpretation of Z rotation'	float myOriginPosX = akOrigin.GetPositionX()	float myOriginPosY = akOrigin.GetPositionY()	float myOriginPosZ = akOrigin.GetPositionZ()		float fInitialX = akObject.GetPositionX() - myOriginPosX	float fInitialY = akObject.GetPositionY() - myOriginPosY	float fInitialZ = akObject.GetPositionZ() - myOriginPosZ		float fNewX	float fNewY	float fNewZ		;Objects in Skyrim are rotated in order of Z, Y, X, so we will do that here as well.		;Z-axis rotation matrix	float fVectorX = fInitialX	float fVectorY = fInitialY	float fVectorZ = fInitialZ	fNewX = (fVectorX * cos(fAngleZ)) + (fVectorY * sin(-fAngleZ))	fNewY = (fVectorX * sin(fAngleZ)) + (fVectorY * cos(fAngleZ))	fNewZ = fVectorZ		;Y-axis rotation matrix	fVectorX = fNewX	fVectorY = fNewY	fVectorZ = fNewZ	fNewX = (fVectorX * cos(fAngleY)) + (fVectorZ * sin(fAngleY))	fNewY = fVectorY	fNewZ = (fVectorX * sin(-fAngleY)) + (fVectorZ * cos(fAngleY))		;X-axis rotation matrix	fVectorX = fNewX	fVectorY = fNewY	fVectorZ = fNewZ		fNewX = fVectorX	fNewY = (fVectorY * cos(fAngleX)) + (fVectorZ * sin(-fAngleX))	fNewZ = (fVectorY * sin(fAngleX)) + (fVectorZ * cos(fAngleX))		;Return result	float[] fNewPos = new float[3]	fNewPos[0] = fNewX + myOriginPosX	fNewPos[1] = fNewY + myOriginPosY	fNewPos[2] = fNewZ + myOriginPosZ	return fNewPos	endFunction
Code will lose its indentation if it's copied out of a post, but not if you quote to view it with that switch toggled to off. Also, if you want to kill the pink, find the '/" that starts a string and close it with another '/".

Very cool function! Thanks for sharing, Chesko :)
User avatar
celebrity
 
Posts: 3522
Joined: Mon Jul 02, 2007 12:53 pm

Post » Mon Nov 19, 2012 8:38 pm

Another comment (not meant to be a "pun" but okay...) about the code tags... they recognize // as a comment, not ;.

So you can kind of fake the comment highlighting if you do this:

;// I am a comment

Hopefully they fix that eventually. I don't get why they didn't just use // as the comments for papyrus though. I guess they wanted to be different.
User avatar
brian adkins
 
Posts: 3452
Joined: Mon Oct 01, 2007 8:51 am

Post » Mon Nov 19, 2012 10:48 pm

JustinOther - yes, there are several parts of the matrix multiplication that could be condensed. I left it verbose such that I could debug it in case something came up, and for algebraic clarity. And I don't think the additional time cost means very much in this case. And thanks for reposting the well-formatted version. (Make sure to add the line that inverses the z-angle!)

seventyfour - Thanks.
User avatar
Anna S
 
Posts: 3408
Joined: Thu Apr 19, 2007 2:13 am

Post » Mon Nov 19, 2012 5:57 pm

Small note - you shouldn't have to allocate the array before calling the function, since the function allocates a new one anyway and returns it (the one you allocate before calling the function gets garbage collected).
User avatar
James Rhead
 
Posts: 3474
Joined: Sat Jul 14, 2007 7:32 am

Post » Mon Nov 19, 2012 7:44 am

Thanks again, as always, Viper :biggrin: I'll make the change soon.
User avatar
Sheila Esmailka
 
Posts: 3404
Joined: Wed Aug 22, 2007 2:31 am


Return to V - Skyrim