Align actor to master's angle/pitch/roll with offset!

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
Post Reply
User avatar
Cherno
Posts: 1311
Joined: Tue Dec 06, 2016 11:25 am

Align actor to master's angle/pitch/roll with offset!

Post by Cherno »

Imagine a helicopter rotor: The helicopter itself is the rotor's master, and it can tilt in any direction (angle, pitch, roll). the rotor is offset from the master's pos so there is some math involved which goes completely over my head.

So, in effect: How to calculate an actors' position, angle, pitch and roll based on another actor's pos, angle etc., while having an offset in the xyz (forward/sideways/up) axis?

I got some help before when I had a similar problem with aligning a turret to a tank but that one had two shortcomings: It worked with the normal of the underlying sector's plane, and the equation only involved z offset.

This is the turret aligning code I used so far in my Hunter TC.

Code: Select all

const offsetX = 8.0;//not used :(
const offsetY = 0.0;//not used :(
const offsetZ = 16.0;

override void Tick()
{
     Super.Tick();
    //how to add the x and y offsets?
     double forward = offsetZ * sin(master.pitch) * cos(master.angle) * cos(master.roll) + offsetZ * sin(master.roll) * sin(master.angle);
		double sideways = offsetZ * sin(master.pitch) * sin(master.angle) * cos(master.roll) - offsetZ * sin(master.roll) * cos(master.angle);
		double upwards = offsetZ * cos(master.pitch) * cos(master.roll);
      
		SetOrigin((master.pos.X + forward, master.pos.Y + sideways, master.pos.Z + upwards), true);
		AlignToPlaneTurret(master,0,false);
}

void AlignToPlaneTurret(Actor a, double pitchAdjust = 0, bool ceiling = false)
	{
		if (!a) 
		{
			return;
		}
		double ceilingAdjust = 0;
		Vector3 fnormal;
		if (!ceiling)
		{
		 fnormal = a.CurSector.FloorPlane.Normal;
		}
		else
		{
		 fnormal = a.CurSector.CeilingPlane.Normal;
		 ceilingAdjust = 180.0;
		}
		Vector2 fnormalp1 = (fnormal.x != 0 || fnormal.y != 0) ? (fnormal.x, fnormal.y).Unit() : (0, 0);
		Vector2 fnormalp2 = ((fnormal.x, fnormal.y).Length(), fnormal.z);
		double dang = self.Angle;
		
		
		double fang = atan2(fnormalp1.y, fnormalp1.x);
		double fpitch = atan2(fnormalp2.x, fnormalp2.y);
		double ddiff1 = sin(fang - (dang - pitchAdjust));
		double ddiff2 = cos(fang - dang);
		
                //the values we want in the end
		double pitchTarget = (fpitch * ddiff2 - pitchAdjust) + ceilingAdjust;
		double rollTarget = -fpitch * ddiff1 + ceilingAdjust;
		double angleTarget = dang + ceilingAdjust;
User avatar
CBM
Posts: 373
Joined: Wed Oct 09, 2019 3:39 am
Graphics Processor: nVidia with Vulkan support
Location: The Shores of Hell

Re: Align actor to master's angle/pitch/roll with offset!

Post by CBM »

could this work?

I do not know if this helps, but they are talking about 3D offsets
here: https://stackoverflow.com/questions/274 ... fset-in-3d
and here: https://math.stackexchange.com/question ... eir-offset

by the way.. I am super hyped about your upcoming Hunter TC

actually... by looking at the last link..

x = x + offset_x * cos_ry * cos_rz - offset_x * sin_rx * sin_ry * sin_rz - offset_y * cos_rx * sin_rz + offset_z * sin_ry * cos_rz + offset_z * sin_rx * cos_ry * sin_rz;

y = y + offset_x * cos_ry * sin_rz + offset_x * sin_rx * sin_ry * cos_rz + offset_y * cos_rx * cos_rz + offset_z * sin_ry * sin_rz - offset_z * sin_rx * cos_ry * cos_rz;

z = z - offset_x * cos_rx * sin_ry + offset_y * sin_rx + offset_z * cos_rx * cos_ry;

it might be something like this

Code: Select all


const offsetX = 8.0;
const offsetY = 0.0;
const offsetZ = 16.0;

override void Tick()
{
     Super.Tick();

double MasterX = master.pos.X;
double MasterY = master.pos.Y;
double MasterZ = master.pos.Z;

// not to sure about these but from what I understand about pitch, angle and roll, I would expect them to map like this...
double MasterAngleX = master.roll;
double MasterAngleY = master.pitch;  
double MasterAngleZ = master.angle;


double NewX = MasterX + offsetx * cos(MasterAngleY) * cos(MasterAngleZ) - offsetx * sin(MasterAngleX) * sin(MasterAngleY) * sin(MasterAngleZ) - offsety * cos(MasterAngleX) * sin(MasterAngleZ) + offsetz * sin(MasterAngleY) * cos(MasterAngleZ) + offsetz * sin(MasterAngleX ) * cos(MasterAngleY) * sin(MasterAngleZ);

double NewY = MasterY + offsetx * cos(MasterAngleY) * sin(MasterAngleZ) + offsetx * sin(MasterAngleX) * sin(MasterAngleY) * cos(MasterAngleZ) + offsety * cos(MasterAngleX) * cos(MasterAngleZ) + offsetz * sin(MasterAngleY) * sin(MasterAngleZ) - offsetz * sin(MasterAngleX) * cos(MasterAngleY) * cos(MasterAngleZ);

double NewZ = MasterZ - offsetx * cos(MasterAngleX) * sin(MasterAngleY) + offsety * sin(MasterAngleX) + offsetz * cos(MasterAngleX) * cos(MasterAngleZ);

      SetOrigin((NewX, NewY, NewZ), true);
      AlignToPlaneTurret(master,0,false);

}

void AlignToPlaneTurret(Actor a, double pitchAdjust = 0, bool ceiling = false)
   {
      if (!a)
      {
         return;
      }
      double ceilingAdjust = 0;
      Vector3 fnormal;
      if (!ceiling)
      {
       fnormal = a.CurSector.FloorPlane.Normal;
      }
      else
      {
       fnormal = a.CurSector.CeilingPlane.Normal;
       ceilingAdjust = 180.0;
      }
      Vector2 fnormalp1 = (fnormal.x != 0 || fnormal.y != 0) ? (fnormal.x, fnormal.y).Unit() : (0, 0);
      Vector2 fnormalp2 = ((fnormal.x, fnormal.y).Length(), fnormal.z);
      double dang = self.Angle;
      
      
      double fang = atan2(fnormalp1.y, fnormalp1.x);
      double fpitch = atan2(fnormalp2.x, fnormalp2.y);
      double ddiff1 = sin(fang - (dang - pitchAdjust));
      double ddiff2 = cos(fang - dang);
      
                //the values we want in the end
      double pitchTarget = (fpitch * ddiff2 - pitchAdjust) + ceilingAdjust;
      double rollTarget = -fpitch * ddiff1 + ceilingAdjust;
      double angleTarget = dang + ceilingAdjust;

Hope this helps! Best of luck with your project! :D

EDIT

found this aviation link

https://aviation.stackexchange.com/ques ... itch-angle

and it showed me the difference between pitch, yaw(angle?) and roll :)
Post Reply

Return to “Scripting”