QD3D: New math features

This commit is contained in:
Iliyas Jorio 2021-02-20 17:22:22 +01:00
parent b2873430d1
commit 4b6df39318
3 changed files with 237 additions and 19 deletions

View File

@ -209,6 +209,7 @@ typedef struct TQ3ColorRGB
float b;
} TQ3ColorRGB;
// WARNING: this structure differs from QD3D
typedef struct TQ3Vertex3D
{
TQ3Point3D point;
@ -221,6 +222,14 @@ typedef struct TQ3BoundingBox
TQ3Boolean isEmpty;
} TQ3BoundingBox;
typedef struct TQ3BoundingSphere
{
TQ3Point3D origin;
float radius;
TQ3Boolean isEmpty;
} TQ3BoundingSphere;
typedef struct TQ3Matrix3x3
{
float value[3][3];

View File

@ -382,3 +382,79 @@ TQ3Matrix4x4* Q3Matrix4x4_Invert(
return(result);
}
//-----------------------------------------------------------------------------
#pragma mark Q3BoundingBox
TQ3BoundingBox* Q3BoundingBox_SetFromPoints3D(
TQ3BoundingBox *bBox,
const TQ3Point3D *points3D,
TQ3Uns32 numPoints,
TQ3Uns32 structSize)
{
if (structSize != sizeof(TQ3Point3D))
throw std::runtime_error("Q3BoundingBox_SetFromPoints3D: unsupported struct size");
if (numPoints == 0)
{
bBox->isEmpty = kQ3True;
}
else
{
TQ3Uns32 i = 0;
bBox->isEmpty = kQ3False;
bBox->min = points3D[0];
bBox->max = points3D[0];
// We have already accounted for the first point, so if the number of
// points is odd, we can handle the other points in pairs, and need not
// look at the first point again. But if the number of points is even,
// we will start at the first point just so we can work in pairs.
if ( (numPoints % 2) == 1 )
{
i = 1;
}
for (; i < numPoints; i += 2)
{
TQ3Point3D pt0 = points3D[i];
TQ3Point3D pt1 = points3D[i+1];
if (pt0.x < pt1.x)
{
if (pt0.x < bBox->min.x) bBox->min.x = pt0.x;
if (pt1.x > bBox->max.x) bBox->max.x = pt1.x;
}
else // pt1.x <= pt0.x
{
if (pt1.x < bBox->min.x) bBox->min.x = pt1.x;
if (pt0.x > bBox->max.x) bBox->max.x = pt0.x;
}
if (pt0.y < pt1.y)
{
if (pt0.y < bBox->min.y) bBox->min.y = pt0.y;
if (pt1.y > bBox->max.y) bBox->max.y = pt1.y;
}
else // pt1.y <= pt0.y
{
if (pt1.y < bBox->min.y) bBox->min.y = pt1.y;
if (pt0.y > bBox->max.y) bBox->max.y = pt0.y;
}
if (pt0.z < pt1.z)
{
if (pt0.z < bBox->min.z) bBox->min.z = pt0.z;
if (pt1.z > bBox->max.z) bBox->max.z = pt1.z;
}
else // pt1.z <= pt0.z
{
if (pt1.z < bBox->min.z) bBox->min.z = pt1.z;
if (pt0.z > bBox->max.z) bBox->max.z = pt0.z;
}
}
}
return(bBox);
}

View File

@ -40,6 +40,7 @@ extern "C" {
#include "QD3D.h"
#include <math.h>
#include <float.h>
#include <string.h>
#ifdef FLT_EPSILON
@ -137,25 +138,6 @@ static inline void Q3Point3D_CrossProductTri(
result->z = (v1_x * v2_y) - (v1_y * v2_x);
}
static inline TQ3Vector3D* Q3Vector3D_Transform(
const TQ3Vector3D *vector3D,
const TQ3Matrix4x4 *matrix4x4,
TQ3Vector3D *result)
{
// Save input to avoid problems when result is same as input
float x = vector3D->x;
float y = vector3D->y;
float z = vector3D->z;
#define M(x,y) matrix4x4->value[x][y]
result->x = x*M(0,0) + y*M(1,0) + z*M(2,0);
result->y = x*M(0,1) + y*M(1,1) + z*M(2,1);
result->z = x*M(0,2) + y*M(1,2) + z*M(2,2);
#undef M
return result;
}
static inline TQ3Point3D* Q3Point3D_Transform(
const TQ3Point3D *point3D,
const TQ3Matrix4x4 *matrix4x4,
@ -210,6 +192,7 @@ static inline TQ3Point3D* Q3Point3D_TransformAffine(
return(result);
}
// This function's signature differs from vanilla QD3D's.
void Q3Point3D_To3DTransformArray(
const TQ3Point3D *inPoints3D,
const TQ3Matrix4x4 *matrix4x4,
@ -272,6 +255,41 @@ static inline void Q3Vector2D_Normalize(
Q3Vector2D_Scale(v1, 1.0f / theLength, result);
}
static inline float Q3Vector2D_Cross(
const TQ3Vector2D* v1,
const TQ3Vector2D* v2)
{
return (v1->x * v2->y) - (v1->y * v2->x);
}
//=============================================================================
// E3Vector2D_Transform : Transform 2D vector by 3x3 matrix.
//-----------------------------------------------------------------------------
// Note : 'result' may be the same as 'vector2D'.
//
// Note that the translation and perspective components of the
// matrix is ignored (as if it were really a 2x2 matrix).
//
// Contrast with E3Point2D_Transform, which does the full 3x3
// transformation.
//-----------------------------------------------------------------------------
static inline TQ3Vector2D* Q3Vector2D_Transform(
const TQ3Vector2D *vector2D,
const TQ3Matrix3x3 *matrix3x3,
TQ3Vector2D *result)
{
// Save input to avoid problems when result is same as input
float x = vector2D->x;
float y = vector2D->y;
#define M(x,y) matrix3x3->value[x][y]
result->x = x*M(0,0) + y*M(1,0);
result->y = x*M(0,1) + y*M(1,1);
#undef M
return(result);
}
//-----------------------------------------------------------------------------
#pragma mark Q3Vector3D
@ -335,6 +353,25 @@ static inline void Q3Vector3D_Normalize(
Q3Vector3D_Scale(v1, 1.0f / theLength, result);
}
static inline TQ3Vector3D* Q3Vector3D_Transform(
const TQ3Vector3D *vector3D,
const TQ3Matrix4x4 *matrix4x4,
TQ3Vector3D *result)
{
// Save input to avoid problems when result is same as input
float x = vector3D->x;
float y = vector3D->y;
float z = vector3D->z;
#define M(x,y) matrix4x4->value[x][y]
result->x = x*M(0,0) + y*M(1,0) + z*M(2,0);
result->y = x*M(0,1) + y*M(1,1) + z*M(2,1);
result->z = x*M(0,2) + y*M(1,2) + z*M(2,2);
#undef M
return result;
}
//-----------------------------------------------------------------------------
#pragma mark Q3Matrix3x3
@ -372,6 +409,37 @@ static inline TQ3Matrix3x3* Q3Matrix3x3_SetTranslate(
return matrix3x3;
}
static inline TQ3Matrix3x3* Q3Matrix3x3_SetRotateAboutPoint(
TQ3Matrix3x3 *matrix3x3,
const TQ3Point2D *origin,
float angle)
{
float cosAngle = cosf(angle);
float sinAngle = sinf(angle);
#define M(x,y) matrix3x3->value[x][y]
#define Dx origin->x
#define Dy origin->y
M(0,0) = cosAngle;
M(0,1) = sinAngle;
M(0,2) = 0.0f;
M(1,0) = -sinAngle;
M(1,1) = cosAngle;
M(1,2) = 0.0f;
M(2,0) = Dx - Dx*cosAngle + Dy*sinAngle; // = Dx - Dx*M(0,0) - Dy*M(1,0)
M(2,1) = Dy - Dx*sinAngle - Dy*cosAngle; // = Dx - Dx*M(0,1) - Dy*M(1,1)
M(2,2) = 1.0f;
#undef M
#undef Dx
#undef Dy
return(matrix3x3);
}
//-----------------------------------------------------------------------------
#pragma mark Q3Matrix4x4
@ -602,6 +670,62 @@ static inline TQ3Matrix4x4* Q3Matrix4x4_SetRotate_XYZ(
return(matrix4x4);
}
//=============================================================================
// E3Matrix4x4_SetRotateAboutPoint : Set 4x4 matrix to rotate about axes through
// point and parallel to X, Y, Z axes
// (in that order -- which is rarely useful).
//-----------------------------------------------------------------------------
static inline TQ3Matrix4x4* Q3Matrix4x4_SetRotateAboutPoint(
TQ3Matrix4x4 *matrix4x4,
const TQ3Point3D *origin,
float xAngle,
float yAngle,
float zAngle)
{
float cosX = cosf(xAngle);
float sinX = sinf(xAngle);
float cosY = cosf(yAngle);
float sinY = sinf(yAngle);
float cosZ = cosf(zAngle);
float sinZ = sinf(zAngle);
float sinXsinY = sinX*sinY;
float cosXsinY = cosX*sinY;
#define M(x,y) matrix4x4->value[x][y]
#define Dx origin->x
#define Dy origin->y
#define Dz origin->z
M(0,0) = cosY*cosZ;
M(0,1) = cosY*sinZ;
M(0,2) = -sinY;
M(0,3) = 0.0f;
M(1,0) = sinXsinY*cosZ - cosX*sinZ;
M(1,1) = sinXsinY*sinZ + cosX*cosZ;
M(1,2) = sinX*cosY;
M(1,3) = 0.0f;
M(2,0) = cosXsinY*cosZ + sinX*sinZ;
M(2,1) = cosXsinY*sinZ - sinX*cosZ;
M(2,2) = cosX*cosY;
M(2,3) = 0.0f;
M(3,0) = Dx - Dx*M(0,0) - Dy*M(1,0) - Dz*M(2,0);
M(3,1) = Dy - Dx*M(0,1) - Dy*M(1,1) - Dz*M(2,1);
M(3,2) = Dz - Dx*M(0,2) - Dy*M(1,2) - Dz*M(2,2);
M(3,3) = 1.0f;
#undef M
#undef Dx
#undef Dy
#undef Dz
return(matrix4x4);
}
TQ3Matrix4x4* Q3Matrix4x4_Transpose(
const TQ3Matrix4x4 *matrix4x4,
TQ3Matrix4x4 *result);
@ -610,6 +734,15 @@ TQ3Matrix4x4* Q3Matrix4x4_Invert(
const TQ3Matrix4x4 *inMatrix,
TQ3Matrix4x4 *result);
//-----------------------------------------------------------------------------
#pragma mark Q3BoundingBox
TQ3BoundingBox* Q3BoundingBox_SetFromPoints3D(
TQ3BoundingBox *bBox,
const TQ3Point3D *points3D,
TQ3Uns32 numPoints,
TQ3Uns32 structSize);
#ifdef __cplusplus
}
#endif