.GetVectorForAngles \ In the following commentary I am talking about the \ vector from the player's eyes to the sights, as that \ makes it easier to describe the various points, but \ this routine can convert any vector into angles using \ the same process \ We start by converting the pitch angle of the vector \ from the player's eyes to the sights into a cartesian \ y-coordinate in the global 3D coordinate system, where \ the y-axis is the up-down axis \ \ We store the resulting y-coordinate in the 16-bit \ variable yVector(Lo Bot) \ \ We calculate yVector by considering a triangle with \ the sights vector as the hypotenuse, and we drop the \ end point down onto the y = 0 plane (i.e. onto the \ ground) \ \ Consider the case where the player is looking up at an \ angle of vectorPitchAngle, so the vector from the \ player's eye to the sights is from the bottom-left to \ the top-right in the following triangle: \ \ sights \ _.-+ ^ \ _.-´ | | \ vector _.-´ | y-axis (up) \ _.-´ | \ _.-´ | y \ _.-´ | \ .-´ vectorPitchAngle | \ eye +--------------------------+ \ p \ \ To make the calculations easier, let's say the length \ of the vector is 1 \ \ Trigonometry gives us the following: \ \ sin(vectorPitchAngle) = opposite / hypotenuse \ = y / 1 \ \ So the y-coordinate is given by: \ \ y = sin(vectorPitchAngle) \ \ which is what we calculate now \ \ Incidentally, the adjacent side p, which is the length \ of the vector projected down onto the y = 0 plane, is \ calculated in a similar way: \ \ cos(vectorPitchAngle) = adjacent / hypotenuse \ = p / 1 \ \ So p = cos(vectorPitchAngle), which we will use to \ calculate the x- and z-coordinates of the vector later JSR GetRotationMatrix \ This routine is taken from Revs, where it calculates a \ rotation matrix from an angle \ \ We don't need a full rotation matrix here, but the \ Revs routine calculates the values that we do need \ here, specifically: \ \ cosVectorPitchAngle = cos(vectorPitchAngle) \ \ sinVectorPitchAngle = sin(vectorPitchAngle) \ \ These calculations return 16-bit sign-magnitude \ numbers with the sign in bit 0, which the DivideBy16 \ routine converts into normal 16-bit signed numbers \ \ Note that because GetRotationMatrix is copied from \ Revs, where we only ever rotate through the yaw angle, \ the matrix values are actually returned in the various \ yawAngle variables, but for simplicity let's pretend \ they are returned as above LDY #1 \ Set (A X) = cosVectorPitchAngle / 16 JSR DivideBy16 STA cosVectorPitchHi \ Set cosVectorPitch(Hi Lo) = cosVectorPitchAngle / 16 STX cosVectorPitchLo LDY #0 \ Set (A X) = sinVectorPitchAngle / 16 JSR DivideBy16 STA yVectorLo \ Set yVector(Lo Bot) = sinVectorPitchAngle / 16 STX yVectorBot \ \ So we now have the y-coordinate of the sights vector \ as follows: \ \ y = sin(vectorPitchAngle) \ Now we convert the yaw angle of the sights vector \ into cartesian x- and z-coordinates, where the x-axis \ is the left-right axis and the z-axis goes into the \ screen \ \ We store the resulting x-coordinate in the 16-bit \ variable xVector(Lo Bot) and the z-coordinate in \ zVector(Lo Bot) \ \ We calculate xVector and zVector by considering a \ triangle on the y = 0 plane, so that's a triangle on \ the ground \ \ The hypotenuse of this triangle is side p from the \ first calculation, which is the sights vector \ projected down onto the ground - the shadow from a \ light source directly above, if you like \ \ The opposite and adjacent sides of this tringle will \ give us the x- and z-coordinates of the vector \ \ To see this, consider the same vector as before, with \ p as the vector projected down onto the ground, and \ where the player is looking sideways at a yaw angle of \ vectorYawAngle \ \ This gives us a triangle like this, when viewed from \ above, so it's as if we are the light source directly \ above the sights vector, projecting the vector down \ onto p, and with the vector going from the top-left to \ the bottom-right, and the sights end of the vector \ higher than the eye end: \ \ z \ eye +--------------------------+ z-axis --> \ `-._ vectorYawAngle | into screen \ `-._ | \ `-._ | x \ p `-._ | \ `-._ | x-axis left \ `-._ | to right \ `-+ | \ sights v \ \ Again, simple trigonometry gives us the following: \ \ sin(vectorYawAngle) = opposite / hypotenuse \ = x / p \ \ So: \ \ x = p * sin(vectorYawAngle) \ \ And: \ \ cos(vectorYawAngle) = adjacent / hypotenuse \ = z / p \ \ So: \ \ z = p * cos(vectorYawAngle) \ \ We calculated above that: \ \ p = cos(vectorPitchAngle) \ \ So substituting that into our result gives us: \ \ x = p * sin(vectorYawAngle) \ = cos(vectorPitchAngle) * sin(vectorYawAngle) \ \ z = p * cos(vectorYawAngle) \ = cos(vectorPitchAngle) * cos(vectorYawAngle) \ \ which is what we calculate now LDA vectorYawAngleLo \ Set (A T) = vectorYawAngle(Hi Lo) STA T LDA vectorYawAngleHi JSR GetRotationMatrix \ Calculate the following: \ \ cosVectorYawAngle = cos(vectorYawAngle) \ \ sinVectorYawAngle = sin(vectorYawAngle) \ \ Again these are returned as 16-bit sign-magnitude \ numbers with the sign in bit 0, which the \ MultiplyCoords converts into normal 16-bit signed \ numbers LDY #1 \ Call MultiplyCoords with Y = 1 and X = 2 to calculate LDX #2 \ the following: JSR MultiplyCoords \ \ zVector(Lo Bot) \ = cosVectorPitchAngle * cosVectorYawAngle / 16 LDY #0 \ Zero X and Y and fall through into MultiplyCoords to LDX #0 \ calculate the following: \ \ xVector(Lo Bot) \ = cosVectorPitchAngle * sinVectorYawAngle / 16 \ \ and return from the subroutine using a tail callName: GetVectorForAngles [Show more] Type: Subroutine Category: Maths (Geometry) Summary: Convert a vector from pitch and yaw angles into a 3D cartesian vectorContext: See this subroutine in context in the source code References: This subroutine is called as follows: * CheckEnemyGaze (Part 2 of 2) calls GetVectorForAngles
This routine uses the rotation matrix routine from Revs to convert a vector from a pair of pitch and yaw angles into a cartesian [x y z] vector. The pitch and yaw angles are 16-bit numbers as follows: vectorPitchAngle(Hi Lo) vectorYawAngle(Hi Lo) The same vector, but expressed as a cartesian vector, is calculated as follows: [ xVector(Lo Bot) ] [ yVector(Lo Bot) ] [ zVector(Lo Bot) ] The calculation is this: yVector = sinVectorPitchAngle / 16 zVector = cosVectorPitchAngle * cosVectorYawAngle / 16 xVector = cosVectorPitchAngle * sinVectorYawAngle / 16
[X]
Subroutine DivideBy16 (category: Maths (Arithmetic))
Divide a 16-bit sign-magnitude number by 16
[X]
Subroutine GetRotationMatrix (Part 1 of 5) (category: Maths (Geometry))
Calculate the rotation matrix for rotating the pitch or yaw angle for the sights into the global 3D coordinate system
[X]
Subroutine MultiplyCoords (category: Maths (Arithmetic))
Multiply a 16-bit signed number and a 16-bit sign-magnitude value
[X]
Variable cosVectorPitchHi in workspace Zero page
The high byte of cos(vectorPitchAngle) when converting pitch and yaw angles to cartesian vectors
[X]
Variable cosVectorPitchLo in workspace Zero page
The low byte of cos(vectorPitchAngle) when converting pitch and yaw angles to cartesian vectors
[X]
Variable vectorYawAngleHi in workspace Zero page
The yaw angle of a vector (high byte)
[X]
Variable vectorYawAngleLo in workspace Zero page
The yaw angle of a vector (low byte)
[X]
Variable yVectorBot in workspace Zero page
The y-coordinate of a vector (bottom byte)