Projectiles don't inherit pitch?

Discuss all aspects related to modding Zandronum here.
scroton
 
Posts: 63
Joined: Mon Aug 26, 2013 3:33 am

RE: Projectiles don't inherit pitch?

#21

Post by scroton » Wed Apr 02, 2014 6:31 am

Glad I could be of help.

I had a little bit more time so using an online graphing calculator I went back so see if I could get a better approximation using my earlier idea:
scroton wrote:I suppose you could have jumps in decorate to have it use different pitch formulas depending upon what it's momz is, and that might be most accurate of all.
For instance, using the approximation I listed above for a projectile with a speed of 15

Image Image

You can see that the approximation (4x) follows the actual pitch (arcsin(x/15)) pretty closely for ~2/3 of the range, then diverges a bit at the far ends.

However, using just one more simple linear function you can approximate that portion where it starts to diverge pretty closely.

Image

Here it is at both ends:

Image

And truncated with range restrictions for easier viewing. Next to it is the original approximation again for comparison:

Image Image

And here is the decorate code for a projectile with speed 15 to use that approximation method instead of the original one:

Code: Select all

  Spawn:
    TNT1 A 0
    TNT1 A 0
	TNT1 A 0 A_JumpIf(MomZ > 10, "Spawn2")
	TNT1 A 0 A_JumpIf(MomZ < -10, "Spawn3")
	TNT1 A 0 A_SetPitch(MomZ*4)
	Goto Spawn4
  Spawn2:
    TNT1 A 0 A_SetPitch(MomZ*9 - 52)
	Goto Spawn4
  Spawn3:
    TNT1 A 0 A_SetPitch(MomZ*9 + 52)
	Goto Spawn4
  Spawn4:
    TNT1 A 1
	Loop
You would have to figure out the additional linear function(s) for each projectile speed that you wanted to approximate the pitch for, but this could be done entirely in decorate. It's also worth noting that you could easily use more than three linear functions to approximate the pitch.

Of course, after finishing the above, I realized that the same thing can be done in ACS, so I wrote the following script that sets the pitch of the calling actor to the appropriate pitch. This should be accurate rather than an approximation:

Code: Select all

//Not my function, from
//http://zdoom.org/wiki/Sqrt
//Not needed in zdoom

function int sqrt(int number)
{
    if(number <= 3) { return number > 0; }

    int oldAns = number >> 1,                     // initial guess
        newAns = (oldAns + number / oldAns) >> 1; // first iteration

    // main iterative method
    while(newAns < oldAns)
    {
    	oldAns = newAns;
    	newAns = (oldAns + number / oldAns) >> 1;
    }

    return oldAns;
}

//My script

script 1 (void)
{
    int finfgfzzgngXa = FixedMul([PROJECTILE_SPEED_x_65536],[PROJECTILE_SPEED_x_65536])-FixedMul(GetActorVelZ(0),GetActorVelZ(0)); //Put fixed-point projectile speed here
    int finfgfzzgngX = sqrt(finfgfzzgngXa);
    int finfgfzzgngZ = GetActorVelZ(0);
    int finfgfzzgngA = VectorAngle (finfgfzzgngX, finfgfzzgngZ);
    SetActorPitch(0, finfgfzzgngA);
    Terminate;
}
Very Late Edit:

A while back I went and tried to solve this even better with a matrix but while it spits out a solution that matches the actual pitch pretty closely it still isn't as accurate as the 3 linear equations at approximating the pitch. Might be worth it if you didn't want to use jump states I suppose, since even though it's inaccurate compared to the linear equations it's still a single expression and that might be desired in certain situations.
Last edited by scroton on Mon Jun 09, 2014 2:41 am, edited 1 time in total.

User avatar
Torr Samaho
Lead Developer
Posts: 1543
Joined: Fri May 25, 2012 6:03 pm
Location: Germany

RE: Projectiles don't inherit pitch?

#22

Post by Torr Samaho » Wed Apr 02, 2014 5:39 pm

scroton wrote: While it isn't actually linear, the function of pitch where Pitch = arcsin(momz/projectile_speed)
Are you sure that it's not arctan instead of arcsin (assuming you mean sqrt(momx^2+momy^2) by projectile_speed)? When I implemented the PITCHFROMMOMENTUM flag I used a similar approach:

Code: Select all

	// [BB] Workaround for the missing pitch information.
	if ( (smf->flags & MDL_PITCHFROMMOMENTUM) )
	{
		const double x = static_cast<double>(spr->actor->velx);
		const double y = static_cast<double>(spr->actor->vely);
		const double z = static_cast<double>(spr->actor->velz);
		// [BB] Calculate the pitch using spherical coordinates.
		
		pitch = float(atan( z/sqrt(x*x+y*y) ) / M_PI * 180);
	}

scroton
 
Posts: 63
Joined: Mon Aug 26, 2013 3:33 am

RE: Projectiles don't inherit pitch?

#23

Post by scroton » Thu Apr 03, 2014 1:40 am

No, I'm using the Speed projectile property as projectile_speed, since it skips a step of having to figure out sqrt(momx^2+momy^2) since where I'm using it the total projectile speed is already known. Arcsin is not actually used in the in-game decorate calculations, since those are just linear approximations and arc functions are not available in decorate.

Pitch = arcsin(momz/projectile_speed)

and

Pitch = arctan(momz/sqrt(momx^2+momy^2))

will both give the same result though, since they're just different methods of doing the same thing. Mine skips a step, but requires you to know the total projectile speed beforehand, so you couldn't use it for something meant for any projectile speed like PITCHFROMMOMENTUM, which requires the arctan you used. I used arctan in the ACS I posted for the same reason you did (and also becasue arctan2 is the only arc function available in ACS, but I would have used arctan2 regardless.)
Oh, and I forgot the other reason I used arcsin: it reduces the function to a single variable so it can be easily graphed.
Last edited by scroton on Thu Apr 03, 2014 1:46 am, edited 1 time in total.

scroton
 
Posts: 63
Joined: Mon Aug 26, 2013 3:33 am

RE: Projectiles don't inherit pitch?

#24

Post by scroton » Thu Apr 03, 2014 8:59 pm

I realized the ACS I posted above, while it would work, would require the script to include the projectile's speed, which is dumb since it means there would need to be separate scripts for every projectile speed. I was working backwards from the projectile speed to get the speed in the horizontal plane rather than using sqrt(momx^2+momy^2), which accommodates any projectile speed.

This

Code: Select all

script 1 (void)
{
    int finfgfzzgngXa = FixedMul(GetActorVelX(0),GetActorVelX(0))+FixedMul(GetActorVelY(0),GetActorVelY(0));
    int finfgfzzgngX = sqrt(finfgfzzgngXa);
    int finfgfzzgngZ = GetActorVelZ(0);
    int finfgfzzgngA = VectorAngle (finfgfzzgngX, finfgfzzgngZ);
    SetActorPitch(0, finfgfzzgngA);
    Terminate;
}

//or in one step, dunno that much about ACS so I dunno if this would cause issue

script 2 (void)
{
    SetActorPitch(0, VectorAngle (GetActorVelZ(0), sqrt(FixedMul(GetActorVelX(0),GetActorVelX(0))+FixedMul(GetActorVelY(0),GetActorVelY(0)))));
    Terminate;
}


Post Reply