When I am working on 3D games I find it useful to have a set of 3D math functions available for testing things.
I decided to convert all of the DirectX math functions. I considered adding these to the API which would of course provide better performance, but I decided it would be more fun to use my language and to make them open-source. They may later be added as API functions.
I often see people looking for code for a certain matrix/vector function (for example D3DXVec3Hermite) because they wish to make their own math libraries instead of linking to DirectX and making their projects rely heavily on linking to a large bulky library that works only on one platform.
So here are all of the purely D3DXVECTOR3 (VECTOR3 here) functions in DirectX. By “pure” I mean functions that relate entirely to vectors, not matrices/planes/etc.
This file can be used as-is in C, C++, and L. Spiro Script.
The names are all the same as in DirectX with the “D3DX” removed.
Vector3.h:
- Code: Select all
#pragma once
#ifdef _WIN32
#define MemCpy CopyMemory
#define Sqrt sqrtf
#endif
typedef struct VECTOR3 {
FLOAT x;
FLOAT y;
FLOAT z;
} * LPVECTOR3;
typedef struct VECTOR3 VECTOR3;
// Adds two 3D vectors.
VECTOR3 * Vec3Add( VECTOR3 * pvOut, const VECTOR3 * pvV1, const VECTOR3 * pvV2 ) {
pvOut->x = pvV1->x + pvV2->x;
pvOut->y = pvV1->y + pvV2->y;
pvOut->z = pvV1->z + pvV2->z;
return pvOut;
}
// Subtracts two 3D vectors.
VECTOR3 * Vec3Subtract( VECTOR3 * pvOut, const VECTOR3 * pvV1, const VECTOR3 * pvV2 ) {
pvOut->x = pvV1->x - pvV2->x;
pvOut->y = pvV1->y - pvV2->y;
pvOut->z = pvV1->z - pvV2->z;
return pvOut;
}
// Returns the square of the length of a 3D vector
FLOAT Vec3LengthSq( const VECTOR3 * pvV ) {
return pvV->x * pvV->x + pvV->y * pvV->y + pvV->z * pvV->z;
}
// Returns the length of a 3D vector
FLOAT Vec3Length( const VECTOR3 * pvV ) {
return Sqrt( pvV->x * pvV->x + pvV->y * pvV->y + pvV->z * pvV->z );
}
// Determines the cross-product of two 3D vectors.
VECTOR3 * Vec3Cross( VECTOR3 * pvOut, const VECTOR3 * pvV1, const VECTOR3 * pvV2 ) {
VECTOR3 vRet;
vRet.x = pvV1->y * pvV2->z - pvV1->z * pvV2->y;
vRet.y = pvV1->z * pvV2->x - pvV1->x * pvV2->z;
vRet.z = pvV1->x * pvV2->y - pvV1->y * pvV2->x;
MemCpy( pvOut, &vRet, sizeof( VECTOR3 ) );
return pvOut;
}
// Determines the dot product of two 3D vectors.
FLOAT Vec3Dot( const VECTOR3 * pvV1, const VECTOR3 * pvV2 ) {
return pvV1->x * pvV2->x + pvV1->y * pvV2->y + pvV1->z * pvV2->z;
}
// Scales a 3D vector.
VECTOR3 * Vec3Scale( VECTOR3 * pvOut, const VECTOR3 * pvV, FLOAT fS ) {
pvOut->x = pvV->x * fS;
pvOut->y = pvV->y * fS;
pvOut->z = pvV->z * fS;
return pvOut;
}
// Returns the normalized version of a 3D vector.
VECTOR3 * Vec3Normalize( VECTOR3 * pvOut, const VECTOR3 * pvV ) {
FLOAT fLen = Vec3LengthSq( pvV );
if ( fLen > 0.0000001f ) {
Vec3Scale( pvOut, pvV, 1.0f / Sqrt( fLen ) );
return pvOut;
}
return pvOut;
}
// Returns a 3D vector that is made up of the largest components of two 3D vectors.
VECTOR3 * Vec3Maximize( VECTOR3 * pvOut, const VECTOR3 * pvV1, const VECTOR3 * pvV2 ) {
pvOut->x = pvV1->x > pvV2->x ? pvV1->x : pvV2->x;
pvOut->y = pvV1->y > pvV2->y ? pvV1->y : pvV2->y;
pvOut->z = pvV1->z > pvV2->z ? pvV1->z : pvV2->z;
return pvOut;
}
// Returns a 3D vector that is made up of the smallest components of two 3D vectors
VECTOR3 * Vec3Minimize( VECTOR3 * pvOut, const VECTOR3 * pvV1, const VECTOR3 * pvV2 ) {
pvOut->x = pvV1->x < pvV2->x ? pvV1->x : pvV2->x;
pvOut->y = pvV1->y < pvV2->y ? pvV1->y : pvV2->y;
pvOut->z = pvV1->z < pvV2->z ? pvV1->z : pvV2->z;
return pvOut;
}
// Performs a linear interpolation between two 3D vectors.
VECTOR3 * Vec3Lerp( VECTOR3 * pvOut, const VECTOR3 * pvV1, const VECTOR3 * pvV2, FLOAT fS ) {
return Vec3Add( pvOut, Vec3Scale( pvOut, Vec3Subtract( pvOut, pvV2, pvV1 ), fS ), pvV1 );
}
// Performs a Hermite spline interpolation using the specified 3D vectors.
VECTOR3 * Vec3Hermite( VECTOR3 * pvOut, const VECTOR3 * pvV1, const VECTOR3 * pvT1, const VECTOR3 * pvV2, const VECTOR3 * pvT2, FLOAT fS ) {
FLOAT fS2 = fS * fS;
FLOAT fS3 = fS2 * fS;
FLOAT f2s2 = 2.0f * fS2;
FLOAT f2s3 = 2.0f * fS3;
FLOAT f3s2 = 3.0f * fS2;
VECTOR3 vTemp1;
VECTOR3 vTemp2;
VECTOR3 vTemp3;
VECTOR3 vTemp4;
VECTOR3 vTemp5;
VECTOR3 vTemp6;
Vec3Scale( &vTemp1, pvV1, f2s3 - f3s2 + 1.0f );
Vec3Scale( &vTemp3, pvV2, -f2s3 + f3s2 );
Vec3Scale( &vTemp5, pvT1, fS3 - f2s2 + fS );
Vec3Scale( &vTemp6, pvT2, fS3 - fS2 );
return Vec3Add( pvOut, &vTemp1,
Vec3Add( &vTemp2, &vTemp3,
Vec3Add( &vTemp4, &vTemp5,
&vTemp6 ) ) );
}
// Performs a Catmull-Rom interpolation using the specified 3D vectors.
VECTOR3 * Vec3CatmullRom( VECTOR3 * pvOut, const VECTOR3 * pvV1, const VECTOR3 * pvV2, const VECTOR3 * pvV3, const VECTOR3 * pvV4, FLOAT fS ) {
VECTOR3 vT1;
VECTOR3 vT2;
Vec3Subtract( &vT1, pvV3, pvV1 );
Vec3Scale( &vT1, &vT1, 0.5f );
Vec3Subtract( &vT2, pvV4, pvV2 );
Vec3Scale( &vT2, &vT2, 0.5f );
return Vec3Hermite( pvOut, pvV2, &vT1, pvV3, &vT2, fS );
}
// Returns a point in Barycentric coordinates, using the specified 3D vectors.
VECTOR3 * Vec3BaryCentric( VECTOR3 * pvOut, const VECTOR3 * pvV1, const VECTOR3 * pvV2, const VECTOR3 * pvV3, FLOAT fF, FLOAT fG ) {
VECTOR3 vP1;
VECTOR3 vP2;
Vec3Subtract( &vP1, pvV2, pvV1 );
Vec3Scale( &vP1, &vP1, fF );
Vec3Subtract( &vP2, pvV3, pvV1 );
Vec3Scale( &vP2, &vP2, fG );
VECTOR3 vP3;
return Vec3Add( pvOut, pvV1, Vec3Add( &vP3, &vP1, &vP2 ) );
}
Matrix functions will come later. I have already rewritten most of them.
L. Spiro