129 lines
4.9 KiB
C++
129 lines
4.9 KiB
C++
#pragma once
|
|
|
|
#include "idlib/math/vector.h"
|
|
|
|
#include <cassert>
|
|
#include <cmath>
|
|
#include <cstring>
|
|
|
|
class idPluecker {
|
|
public:
|
|
float p[6];
|
|
|
|
idPluecker() = default;
|
|
explicit idPluecker(const float* values) {
|
|
std::memcpy(p, values, sizeof(p));
|
|
}
|
|
idPluecker(const float p0, const float p1, const float p2,
|
|
const float p3, const float p4, const float p5) {
|
|
Set(p0, p1, p2, p3, p4, p5);
|
|
}
|
|
idPluecker(const idVec3& start, const idVec3& end) { FromLine(start, end); }
|
|
|
|
float operator[](const int index) const { assert(index >= 0 && index < 6); return p[index]; }
|
|
float& operator[](const int index) { assert(index >= 0 && index < 6); return p[index]; }
|
|
|
|
idPluecker operator-() const {
|
|
return idPluecker(-p[0], -p[1], -p[2], -p[3], -p[4], -p[5]);
|
|
}
|
|
idPluecker operator*(const float scale) const {
|
|
return idPluecker(p[0] * scale, p[1] * scale, p[2] * scale,
|
|
p[3] * scale, p[4] * scale, p[5] * scale);
|
|
}
|
|
idPluecker operator/(const float scale) const {
|
|
assert(scale != 0.0f); return *this * (1.0f / scale);
|
|
}
|
|
float operator*(const idPluecker& other) const {
|
|
return PermutedInnerProduct(other);
|
|
}
|
|
idPluecker operator+(const idPluecker& other) const {
|
|
return idPluecker(p[0] + other.p[0], p[1] + other.p[1],
|
|
p[2] + other.p[2], p[3] + other.p[3],
|
|
p[4] + other.p[4], p[5] + other.p[5]);
|
|
}
|
|
idPluecker operator-(const idPluecker& other) const { return *this + -other; }
|
|
idPluecker& operator*=(const float scale) {
|
|
for (float& value : p) value *= scale; return *this;
|
|
}
|
|
idPluecker& operator/=(const float scale) {
|
|
assert(scale != 0.0f); return *this *= 1.0f / scale;
|
|
}
|
|
idPluecker& operator+=(const idPluecker& other) {
|
|
for (int index = 0; index < 6; ++index) p[index] += other.p[index];
|
|
return *this;
|
|
}
|
|
idPluecker& operator-=(const idPluecker& other) {
|
|
for (int index = 0; index < 6; ++index) p[index] -= other.p[index];
|
|
return *this;
|
|
}
|
|
|
|
bool Compare(const idPluecker& other) const {
|
|
for (int index = 0; index < 6; ++index) if (p[index] != other.p[index]) return false;
|
|
return true;
|
|
}
|
|
bool Compare(const idPluecker& other, const float epsilon) const {
|
|
for (int index = 0; index < 6; ++index)
|
|
if (std::fabs(p[index] - other.p[index]) > epsilon) return false;
|
|
return true;
|
|
}
|
|
bool operator==(const idPluecker& other) const { return Compare(other); }
|
|
bool operator!=(const idPluecker& other) const { return !Compare(other); }
|
|
|
|
void Set(const float p0, const float p1, const float p2,
|
|
const float p3, const float p4, const float p5) {
|
|
p[0] = p0; p[1] = p1; p[2] = p2;
|
|
p[3] = p3; p[4] = p4; p[5] = p5;
|
|
}
|
|
void Zero() { for (float& value : p) value = 0.0f; }
|
|
void FromLine(const idVec3& start, const idVec3& end) {
|
|
p[0] = start.x * end.y - end.x * start.y;
|
|
p[1] = start.x * end.z - end.x * start.z;
|
|
p[2] = start.x - end.x;
|
|
p[3] = start.y * end.z - end.y * start.z;
|
|
p[4] = start.z - end.z;
|
|
p[5] = end.y - start.y;
|
|
}
|
|
void FromRay(const idVec3& start, const idVec3& direction) {
|
|
p[0] = start.x * direction.y - direction.x * start.y;
|
|
p[1] = start.x * direction.z - direction.x * start.z;
|
|
p[2] = -direction.x;
|
|
p[3] = start.y * direction.z - direction.y * start.z;
|
|
p[4] = -direction.z;
|
|
p[5] = direction.y;
|
|
}
|
|
bool ToRay(idVec3& start, idVec3& direction) const {
|
|
const idVec3 moment(p[3], -p[1], p[0]);
|
|
direction.Set(-p[2], p[5], -p[4]);
|
|
const float lengthSqr = direction.LengthSqr();
|
|
if (lengthSqr == 0.0f) return false;
|
|
start = direction.Cross(moment) * (1.0f / lengthSqr);
|
|
return true;
|
|
}
|
|
bool ToLine(idVec3& start, idVec3& end) const {
|
|
idVec3 direction;
|
|
if (!ToRay(start, direction)) return false;
|
|
end = start + direction;
|
|
return true;
|
|
}
|
|
void ToDir(idVec3& direction) const { direction.Set(-p[2], p[5], -p[4]); }
|
|
float PermutedInnerProduct(const idPluecker& other) const {
|
|
return p[0] * other.p[4] + p[1] * other.p[5]
|
|
+ p[2] * other.p[3] + p[4] * other.p[0]
|
|
+ p[5] * other.p[1] + p[3] * other.p[2];
|
|
}
|
|
float LengthSqr() const { return p[2] * p[2] + p[4] * p[4] + p[5] * p[5]; }
|
|
float Length() const { return std::sqrt(LengthSqr()); }
|
|
float NormalizeSelf() {
|
|
const float length = Length();
|
|
if (length != 0.0f) *this /= length;
|
|
return length;
|
|
}
|
|
idPluecker Normalize() const { idPluecker result(*this); result.NormalizeSelf(); return result; }
|
|
int GetDimension() const { return 6; }
|
|
const float* ToFloatPtr() const { return p; }
|
|
float* ToFloatPtr() { return p; }
|
|
};
|
|
|
|
static_assert(sizeof(idPluecker) == 24, "Recovered idPluecker ABI changed");
|
|
|