[Solved] Dual-Actor rotation comparison math

Discussions about Coding and Scripting
User avatar
ANUBITEK
Adept
Posts: 261
Joined: Sun Dec 28, 2014 1:10 am
Location: Anubitek

[Solved] Dual-Actor rotation comparison math

Post by ANUBITEK »

EDIT:
tl;dr My math compiles, but am I doing it right?

I can grab an Actor's facing direction with GetAxes():

Code: Select all

struct AnimRegister
{
    var Actor Animated; // Actor in question
    [...]
}; 
var private array<AnimRegister> Anims;

Code: Select all

function X()
{
	local Vector X,Y,Z; // These are used as an output storage for GetAxes

	if ( Anims[iTransfer].Animation != none )
	{
		GetAxes( Anims[iTransfer].Animated.Rotation, X, Y, Z );
		// Input actor, output X/Y/Z respectively
		[...]
From there, I want to get the resulting angle provided by dot calculation. In this example, X is normalized which according to Wiki(s) brings it to a value between 1 and -1, which if I'm understanding this correctly will help in determining the angle I am trying to calculate. Then get the normal result of the subtraction of two actor locations which I believe provides me with a straight line between the actors, or at least the magnitude of the line that goes through them. So now I have two resulting numbers, both between 1 and -1 depending on inserted values.

Code: Select all

if ( Normal(X) dot Normal(LocalCam.location - Anims[iTransfer].Animated.location) >= 0.7 )
So the code above is supposed to figure out the angle provided, and if the value of the cosine is greater than or equal to 0.7, then something happens. Is this correct so far? The math itself compiles, I'll post links I used for research.

Also how the FRICK do I use Abs()? I can't seem to find any info on it and I am going to need it for a later part.
Spoiler
Image
"What Does GetAxes() Do"
https://forums.beyondunreal.com/threads ... do.102776/
"Weapon of Destruction"
http://www.oldunreal.com/wiki/index.php ... gine.Actor
"Cross Product And Dot Product: Visual Explanation"
https://www.youtube.com/watch?v=h0NJK4mEIJU
Last edited by ANUBITEK on Tue Nov 22, 2016 7:45 am, edited 1 time in total.
<<| http://uncodex.ut-files.com/ |>>

Code reference for UGold, UT99, Unreal2, UT2k3, UT3
Additional Beyond Unreal Wiki Links
wiki.beyondunreal.com/Legacy:Console_Bar
wiki.beyondunreal.com/Exec_commands#Load
wiki.beyondunreal.com/Legacy:Exec_Directive#Loading_Other_Packages
wiki.beyondunreal.com/Legacy:Config_Vars_And_.Ini_Files
wiki.beyondunreal.com/Legacy:INT_File
User avatar
ANUBITEK
Adept
Posts: 261
Joined: Sun Dec 28, 2014 1:10 am
Location: Anubitek

bump

Post by ANUBITEK »

I'm sorry for the double post, but it is to bump the topic with an updated OP. I have done some more research into Vector math and I think I have a better understanding of the math now. But I still need some help in understanding the math I have posted. The math itself compiles, I just need assistance in getting a better understanding of the code I modified to work in UEng1.
<<| http://uncodex.ut-files.com/ |>>

Code reference for UGold, UT99, Unreal2, UT2k3, UT3
Additional Beyond Unreal Wiki Links
wiki.beyondunreal.com/Legacy:Console_Bar
wiki.beyondunreal.com/Exec_commands#Load
wiki.beyondunreal.com/Legacy:Exec_Directive#Loading_Other_Packages
wiki.beyondunreal.com/Legacy:Config_Vars_And_.Ini_Files
wiki.beyondunreal.com/Legacy:INT_File
User avatar
Barbie
Godlike
Posts: 2792
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Vector/single rotation comparison math

Post by Barbie »

Maybe it the other way round is easier: describe what you want to achieve. And starting in 2 dimensions reduces complexity.
<EDIT>
Also how the FRICK do I use Abs()? I can't seem to find any info on it
See Wiki: Abs() expect exact one parameter of type float and returns the same value of type float with a positive sign.
But I doubt that that this is the matter you wanted to know... :omfg:
</EDIT>
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
User avatar
Wormbo
Adept
Posts: 258
Joined: Sat Aug 24, 2013 6:04 pm
Contact:

Re: Vector/single rotation comparison math

Post by Wormbo »

Barbie wrote:And starting in 2 dimensions reduces complexity.
That's actually a very good starting point for most applications. I found that many problems become quite simple by solving them in a plane first.

As for the dot product in combination with Normal(): Normal(v) changes a vector's length to 1 without changing its direction. (As a side effect, the vector's components will all be values between -1 and 1.)
The dot product of two normalized vectors happens to be the cosine of the angle between the two vectors. (At least that's one way to interpret the result.)
The value 0.7 happens to be close enough to the cosine of 45 degrees or Pi/4 radians. (cos(45°) actually is about 0.7071; 45° for camera-related angles is derived from the 90° FOV angle, which may or may not be sufficient for your problem)

BTW: GetAxes() already returns unit vectors, so you don't need to normalize them again.
User avatar
ANUBITEK
Adept
Posts: 261
Joined: Sun Dec 28, 2014 1:10 am
Location: Anubitek

Re: Vector/single rotation comparison math

Post by ANUBITEK »

Edit:
Deleted and reposted to bump, was going to try to elaborate more on what I've typed but man I cannot think of a better way to describe what I'm attempting. So I guess just a bump, probably the last one if I can't get an answer on this. Barbie, hopefully this post clears up what I'm trying to accomplish.

I need to determine the locations of two actors, get the rotation of one of them (which would almost always likely be a Pawn), then based on the other actor's location (a Camera), make the Pawn change its facing sprite. Like in Doom. So what I'm trying to do with the math is figure out what angle the Camera is from the Pawn, then tell the Pawn what sprite it should change to. I should also mention that this check is happening on tick(), so it has to be kept minimal because it is constantly being called for multiple actors for multiple sprites.

I am trying to make a Doom-like sprite system.
Doom Sprites, skip 5 seconds in
juBmjE3PAbI
The effect I am trying to achieve via code could be visually described with the following image:
Blueprint In MS Paint
Image
<<| http://uncodex.ut-files.com/ |>>

Code reference for UGold, UT99, Unreal2, UT2k3, UT3
Additional Beyond Unreal Wiki Links
wiki.beyondunreal.com/Legacy:Console_Bar
wiki.beyondunreal.com/Exec_commands#Load
wiki.beyondunreal.com/Legacy:Exec_Directive#Loading_Other_Packages
wiki.beyondunreal.com/Legacy:Config_Vars_And_.Ini_Files
wiki.beyondunreal.com/Legacy:INT_File
User avatar
Barbie
Godlike
Posts: 2792
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Vector/single rotation comparison math

Post by Barbie »

I'll try to describe the aim what I have understood:
The "sprite" is a polygon in 2 dimensions only, called "sheet" in UnrealEd terms (I've never played Doom).
You have several sheets and depending on the angle of view one of these sheets should be drawn.
To be more concrete to your case: putting the sheet in the origin of a two-dimensional Cartesian system, one of four sheets should be drawn depending on the quadrant the viewer (camera) is in (see en.wikipedia > Quadrant for details). Is this correct so far?

BTW: changing the sheet must of course be done on client side because it sheet selection depends on Player's position.
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
User avatar
ANUBITEK
Adept
Posts: 261
Joined: Sun Dec 28, 2014 1:10 am
Location: Anubitek

Re: Vector/single rotation comparison math

Post by ANUBITEK »

Barbie wrote:You have several sheets and depending on the angle of view one of these sheets should be drawn.
Short answer: correct.
- I have multiple sheets which will be stored in an array in a native object, that are swapped out depending on certain conditions. There is a manager that checks for multiple copies of this native in the level, cycles through the native's current stored sheets in the native's array, and sets the actor's (pawn) texture to whatever sheet occupies the current position in the array of textures.

- The native object temporarily stores multiple sheets, so they are constantly swapped out. The native object will also store a value that will be changed based on where the camera is in relation to the pawn, but first the math to determine where the camera is to the pawn (or vice versa) needs to be figured out.

- Think of a light actor in the editor, notice that when you spawn it the actor has its drawtype set to DT_Sprite, and it holds a texture. The texture is drawn as a flat sheet. So the idea is to make it so the actor's current sheet is constantly being swapped.
Barbie wrote:To be more concrete to your case: putting the sheet in the origin of a two-dimensional Cartesian system, one of four sheets should be drawn depending on the quadrant the viewer (camera) is in (see en.wikipedia > Quadrant for details). Is this correct so far?
Correct mostly, except instead of 4 sheets, it will be 8 sheets. 8 different directions that the actor can be viewed from (North, NorthEast, East, SouthEast, South, Southwest, West, Northwest). View the spoiler in my previous reply and the OP if you need a visual understanding of how this is intended to work.
Barbie wrote:BTW: changing the sheet must of course be done on client side because it sheet selection depends on Player's position
This is a good suggestion, I'll keep it in mind.
<<| http://uncodex.ut-files.com/ |>>

Code reference for UGold, UT99, Unreal2, UT2k3, UT3
Additional Beyond Unreal Wiki Links
wiki.beyondunreal.com/Legacy:Console_Bar
wiki.beyondunreal.com/Exec_commands#Load
wiki.beyondunreal.com/Legacy:Exec_Directive#Loading_Other_Packages
wiki.beyondunreal.com/Legacy:Config_Vars_And_.Ini_Files
wiki.beyondunreal.com/Legacy:INT_File
User avatar
Barbie
Godlike
Posts: 2792
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Vector/single rotation comparison math

Post by Barbie »

Let's see if that goes into the direction of what you want to realize: I've created a test map with a custom actor nearby the centre of the map that changes its texture depending on PlayerPawn's location. The 3rd dimension (z-axis) is completely ignored there so that any action depends on x-y-plane only. Also I have used 4 shapes only, but that is expandable without problems.

The underlying mathematics is easy: first move the coordinate system into the view target. That is simply done by subtracting viewer's and view target's location what results in vector V. Then determinate the angle of that vector to the the x-axis. First I messed around with trigonometric functions, but a Rotator conversion does that very easy and perfectly; only its yaw component is of interest here. As you can see in the draft, the yaw runs from 0 to -32k when the viewer moves from quadrant I to II; if he moves from IV to III, the yaw runs from 0 to 32k.
Math.jpg
The task now is to assign a texture depending on the range the yaw is in.
Sourcecode

Code: Select all

//=============================================================================
// TestSprites.
//=============================================================================
class TestSprites expands Actor;

var() Texture Sprites[8];
var() byte CurrentTextureIndex;


simulated event PostBeginPlay() {
	Super.PostBeginPlay();
	CurrentTextureIndex = 0;
	SetTimer(1, true);
}


event Timer() {
local PlayerPawn P;
local vector v;
local byte TextureIndex;
local rotator R;

	ForEach AllActors(class'PlayerPawn', P)
		break; // take first found player
	if (P == None)
		return;

	v = P.Location - self.location;
	r = rotator(v);
	if (r.yaw <= -16384) // quadrant II
		TextureIndex = 1;
	else if (r.yaw <= 0)  // quadrant I
		TextureIndex = 0;
	else if (r.yaw <= +16384) // quadrant IV
		TextureIndex = 3;
	else  // quadrant III
		TextureIndex = 2;

	if (TextureIndex != CurrentTextureIndex)
	{
		CurrentTextureIndex = TextureIndex;
		Texture = Sprites[CurrentTextureIndex];
	}
	BroadCastMessage("new TextureIndex=" $ TextureIndex $ ", yaw=" $ r.yaw);
}
A big BUT: the way I implemented that is the worst way - instead of executing in a timer or even worse in a tick function that code should only be called when the drawtarget is to be drawn. Maybe the functions RenderOverlays/RenderTexture will do that job - I'm not familiar with them.
Attachments
Map preview
Map preview
TestSprites.7z
Test map with source code and textures (UTech1.uxt is needed)
(133.07 KiB) Downloaded 61 times
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
User avatar
sektor2111
Godlike
Posts: 6403
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Vector/single rotation comparison math

Post by sektor2111 »

Due to my lack of understanding everything In some Path tester which I did I simply turned player into Nav.Node direction very easy without 3 pages of math, that code works for Pawns generally and I'm presuming it can be implemented even in a Camera and it's called ROTATOR else you can combine it with FastTrace and if this doesn't exist walk to a "node" around player - like I said, simple is more efficient, and default pathing is used in the most of old maps. Else... feel free to go break your head computing...
User avatar
Barbie
Godlike
Posts: 2792
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Vector/single rotation comparison math

Post by Barbie »

sektor2111 wrote:...
You surely have noticed that the core math is

Code: Select all

r = rotator(P.Location - self.location)
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
User avatar
ANUBITEK
Adept
Posts: 261
Joined: Sun Dec 28, 2014 1:10 am
Location: Anubitek

Re: Vector/single rotation comparison math

Post by ANUBITEK »

sektor2111 wrote:Due to my lack of understanding everything In some Path tester which I did I simply turned player into Nav.Node direction very easy without 3 pages of math, that code works for Pawns generally and I'm presuming it can be implemented even in a Camera and it's called ROTATOR else you can combine it with FastTrace and if this doesn't exist walk to a "node" around player - like I said, simple is more efficient, and default pathing is used in the most of old maps. Else... feel free to go break your head computing...
I'm still totally up for looking at some example code of trace if you can send me some. I ask for them because I'd need a bit of explanation, never used it before and if my coding in the camera is of any example, it proves I don't know much about how movement works with ScriptedPawns. I still like the idea of moving a pawn around with trace checks. I could grab positions and have my actor strafe to the locations, though I'm not sure why in your example you'd have the camera move to a "node" around the player, something missing in translation or I am misunderstanding. Trying to stay topical, so if you do get around to a reply when you can, mind posting it here:
viewtopic.php?f=15&t=11688

That being said, thank you @Barbie, I'll post a little later today or maybe tomorrow with a video to preview how this works.
//=============
EDIT:
I just had the thought that I could try something involving VisibleActors for choosing who should be updated. The camera is a ScriptedPawn, so we'll see what I can figure out with that.
//=============
Spoiler
The rotation math will be used in one project for sure, but I really want to port some of the assets I have set up in my UGold mod to UT for some sort of third person wave survival single player game with stock UT 3D models, due to some important functions that are being used in sprite animation being only available in UGold.
<<| http://uncodex.ut-files.com/ |>>

Code reference for UGold, UT99, Unreal2, UT2k3, UT3
Additional Beyond Unreal Wiki Links
wiki.beyondunreal.com/Legacy:Console_Bar
wiki.beyondunreal.com/Exec_commands#Load
wiki.beyondunreal.com/Legacy:Exec_Directive#Loading_Other_Packages
wiki.beyondunreal.com/Legacy:Config_Vars_And_.Ini_Files
wiki.beyondunreal.com/Legacy:INT_File
User avatar
ANUBITEK
Adept
Posts: 261
Joined: Sun Dec 28, 2014 1:10 am
Location: Anubitek

Re: Vector/single rotation comparison math

Post by ANUBITEK »

@Wormbo , can you take a look at a corrected version of the math I had provided above and explain it in a way that utilizes Barbie's graph? While Barbie's math will check for relative positions of actors, it isn't accounting for the forward facing direction of the pawn.
Spoiler

Code: Select all

struct AnimRegister
{
	var Actor Animated;
	[...]
}; 
var private array<AnimRegister> Anims;
[...]
var int iTransfer;
Spoiler

Code: Select all

	local RPG_Camera	LocalCam;
	local Vector V, X, Y, Z;
	local byte TextureIndex;
	local rotator R;
	[...]
	GetAxes( Anims[iTransfer].Animated.Rotation, X, Y, Z );
	v = LocalCam.location - Anims[iTransfer].Animated.location;
	r = rotator(v);
Spoiler

Code: Select all

	if ( X dot Normal(V) >= 0.7 )
	{
		log("1");
	}
	else if ( Abs(X dot Normal(V) ) < 0.7 && X dot Normal(V) < 0 )
	{
		log("2");
	}
	else if ( Abs(X dot Normal(V) ) < 0.7 && X dot Normal(V) > 0 )
	{
		log("3");
	}
	else if ( X dot Normal(V) < -0.7 )
	{
		log("4");
	}
<<| http://uncodex.ut-files.com/ |>>

Code reference for UGold, UT99, Unreal2, UT2k3, UT3
Additional Beyond Unreal Wiki Links
wiki.beyondunreal.com/Legacy:Console_Bar
wiki.beyondunreal.com/Exec_commands#Load
wiki.beyondunreal.com/Legacy:Exec_Directive#Loading_Other_Packages
wiki.beyondunreal.com/Legacy:Config_Vars_And_.Ini_Files
wiki.beyondunreal.com/Legacy:INT_File
User avatar
Gustavo6046
Godlike
Posts: 1462
Joined: Mon Jun 01, 2015 7:08 pm
Personal rank: Resident Wallaby
Location: Porto Alegre, Brazil
Contact:

Re: Vector/single rotation comparison math

Post by Gustavo6046 »

LannFyre wrote:
Spoiler

Code: Select all

	local RPG_Camera	LocalCam;
	local Vector V, X, Y, Z;
	local byte TextureIndex;
	local rotator R;
	[...]
	GetAxes( Anims[iTransfer].Animated.Rotation, X, Y, Z );
	v = LocalCam.location - Anims[iTransfer].Animated.location;
	r = rotator(v);
Spoiler

Code: Select all

	if ( X dot Normal(V) >= 0.7 )
	{
		log("1");
	}
	else if ( Abs(X dot Normal(V) ) < 0.7 && X dot Normal(V) < 0 )
	{
		log("2");
	}
	else if ( Abs(X dot Normal(V) ) < 0.7 && X dot Normal(V) > 0 )
	{
		log("3");
	}
	else if ( X dot Normal(V) < -0.7 )
	{
		log("4");
	}
While in normal conditions it should log something (a number from 1 to 4) ALL of the time, check if it doesn't logs anything as well, because the probability of some small error, bug, typo, etc slithering that chews on algorithms can be a bit bigger than you expect.

Unless you take your efforts and do an intensive and tedious scan of the whole code. It still won't be as effective as to dizimating these code snakes (or whatever they are, that should like chewing on that. Maybe goblin? Hm.. foxes! There is one that chews me all the time. But I'm not code so maybe not...). :P
"Everyone is an idea man. Everybody thinks they have a revolutionary new game concept that no one else has ever thought of. Having cool ideas will rarely get you anywhere in the games industry. You have to be able to implement your ideas or provide some useful skill. Never join a project whose idea man or leader has no obvious development skills. Never join a project that only has a web designer. You have your own ideas. Focus on them carefully and in small chunks and you will be able to develop cool projects."

Weapon of Destruction
User avatar
ANUBITEK
Adept
Posts: 261
Joined: Sun Dec 28, 2014 1:10 am
Location: Anubitek

Re: Vector/single rotation comparison math

Post by ANUBITEK »

Gustavo, I know what the log functions do. I mean the math, I was asking for a step-by-step on the math. For instance, I need a bit more of an explanation on the 0.7 and 0 comparisons in the math and what exactly would be happening with that. And I could also use a visual example of what any of the math examples are doing, drawn on Barbie's graph.

...also wat dafuq, foxes, sneks, goblins?
<<| http://uncodex.ut-files.com/ |>>

Code reference for UGold, UT99, Unreal2, UT2k3, UT3
Additional Beyond Unreal Wiki Links
wiki.beyondunreal.com/Legacy:Console_Bar
wiki.beyondunreal.com/Exec_commands#Load
wiki.beyondunreal.com/Legacy:Exec_Directive#Loading_Other_Packages
wiki.beyondunreal.com/Legacy:Config_Vars_And_.Ini_Files
wiki.beyondunreal.com/Legacy:INT_File
User avatar
Gustavo6046
Godlike
Posts: 1462
Joined: Mon Jun 01, 2015 7:08 pm
Personal rank: Resident Wallaby
Location: Porto Alegre, Brazil
Contact:

Re: Vector/single rotation comparison math

Post by Gustavo6046 »

LannFyre wrote:Gustavo, I know what the log functions do. I mean the math, I was asking for a step-by-step on the math. For instance, I need a bit more of an explanation on the 0.7 and 0 comparisons in the math and what exactly would be happening with that. And I could also use a visual example of what any of the math examples are doing, drawn on Barbie's graph.

...also wat dafuq, foxes, sneks, goblins?
Yes, it was just a side note.

About the math, the dot product also happens vertically, so if you are higher or lower than the enemy, the sprite may still change, resulting in WEIRDNESS. :P Try using:

Code: Select all

function int SpriteNum(Actor Other, int NumRotations)
{
    local Rotator R; // our comparison rotator

    R = Rotation - Rotator(Other.Location - Location)

    // Return the floored yaw in NumRotations pieces
    return (R.Yaw / (65536 / NumRotations)) - ((R.Yaw / (65536 / NumRotations)) % 1)
}

// Then, do a single check per tick to change the sprite. Is there a tick function
// called per client that inserts the player as argument?
I will test now.

By the way, the goblin is a reference to the UnrealEd goblin, just a random meme about UnrealEd crashing.
The fox is a reference to... one of my IRC friends.
The snek? Eh, I forgot :P
"Everyone is an idea man. Everybody thinks they have a revolutionary new game concept that no one else has ever thought of. Having cool ideas will rarely get you anywhere in the games industry. You have to be able to implement your ideas or provide some useful skill. Never join a project whose idea man or leader has no obvious development skills. Never join a project that only has a web designer. You have your own ideas. Focus on them carefully and in small chunks and you will be able to develop cool projects."

Weapon of Destruction
Post Reply