[286] | 1 | // This file is a part of Framsticks SDK. http://www.framsticks.com/ |
---|
[1020] | 2 | // Copyright (C) 1999-2020 Maciej Komosinski and Szymon Ulatowski. |
---|
[286] | 3 | // See LICENSE.txt for details. |
---|
[109] | 4 | |
---|
| 5 | #ifndef _3D_H_ |
---|
| 6 | #define _3D_H_ |
---|
| 7 | |
---|
[225] | 8 | #if defined SHP || defined __ANDROID__ |
---|
[109] | 9 | #include <string.h> //memcpy |
---|
| 10 | #else |
---|
| 11 | #include <memory.h> //memcpy |
---|
| 12 | #endif |
---|
| 13 | |
---|
| 14 | /********************************** |
---|
| 15 | \file 3d.h 3d.cpp |
---|
| 16 | |
---|
[255] | 17 | basic 3D classes and operators |
---|
[109] | 18 | *********************************/ |
---|
| 19 | |
---|
[255] | 20 | /// point in 3D space |
---|
[109] | 21 | class Pt3D |
---|
| 22 | { |
---|
[255] | 23 | public: |
---|
| 24 | double x, y, z; |
---|
| 25 | static bool report_errors; |
---|
[109] | 26 | |
---|
[255] | 27 | Pt3D(double _x, double _y, double _z) :x(_x), y(_y), z(_z) {} ///< constructor initializing all coords |
---|
| 28 | Pt3D(double xyz) :x(xyz), y(xyz), z(xyz) {} ///< all coords equal |
---|
| 29 | Pt3D() {} ///< coords will be not initialized! |
---|
| 30 | Pt3D(const Pt3D &p) :x(p.x), y(p.y), z(p.z) {} ///< copy from another point |
---|
[1020] | 31 | bool operator==(const Pt3D& p) { return (x == p.x) && (y == p.y) && (z == p.z); } |
---|
| 32 | void operator+=(const Pt3D& p) { x += p.x; y += p.y; z += p.z; } |
---|
| 33 | void operator-=(const Pt3D& p) { x -= p.x; y -= p.y; z -= p.z; } |
---|
| 34 | void operator*=(double d) { x *= d; y *= d; z *= d; } |
---|
| 35 | Pt3D operator*(const Pt3D &p) const { return Pt3D(y * p.z - z * p.y, z * p.x - x * p.z, x * p.y - y * p.x); } |
---|
| 36 | void operator/=(double d) { x /= d; y /= d; z /= d; } |
---|
[255] | 37 | //Pt3D operator+(const Pt3D& p) const {return Pt3D(x+p.x,y+p.y,z+p.z);} |
---|
| 38 | //Pt3D operator-(const Pt3D& p) const {return Pt3D(x-p.x,y-p.y,z-p.z);} |
---|
| 39 | Pt3D operator-() const { return Pt3D(-x, -y, -z); } |
---|
[1020] | 40 | Pt3D operator*(double d) const { return Pt3D(x * d, y * d, z * d); } |
---|
[255] | 41 | Pt3D operator/(double d) const { return Pt3D(x / d, y / d, z / d); } |
---|
[1020] | 42 | bool allCoordsLowerThan(const Pt3D& p) const { return (x < p.x) && (y < p.y) && (z < p.z); } |
---|
| 43 | bool allCoordsHigherThan(const Pt3D& p) const { return (x > p.x) && (y > p.y) && (z > p.z); } |
---|
[255] | 44 | void getMin(const Pt3D& p); |
---|
| 45 | void getMax(const Pt3D& p); |
---|
[1022] | 46 | double minComponentValue() const; |
---|
| 47 | double maxComponentValue() const; |
---|
[255] | 48 | /** vector length = \f$\sqrt{x^2+y^2+z^2}\f$ */ |
---|
| 49 | double operator()() const; |
---|
| 50 | /** vector length = \f$\sqrt{x^2+y^2+z^2}\f$ */ |
---|
| 51 | double length() const { return operator()(); } |
---|
[1020] | 52 | double length2() const { return x * x + y * y + z * z; } |
---|
[255] | 53 | double distanceTo(const Pt3D& p) const; |
---|
| 54 | double manhattanDistanceTo(const Pt3D& p) const; |
---|
| 55 | /** calculate angle between (0,0)-(dx,dy), @return 1=ok, 0=can't calculate */ |
---|
[305] | 56 | static double getAngle(double dx, double dy); |
---|
[255] | 57 | /** calculate 3 rotation angles translating (1,0,0) into 'X' and (0,0,1) into 'dir' */ |
---|
| 58 | void getAngles(const Pt3D& X, const Pt3D& dir); |
---|
| 59 | void vectorProduct(const Pt3D& a, const Pt3D& b); |
---|
[1020] | 60 | Pt3D vectorProduct(const Pt3D& p) const { return (*this) * p; } |
---|
| 61 | Pt3D entrywiseProduct(const Pt3D &p) const { return Pt3D(x * p.x, y * p.y, z * p.z); } ///< also known as Hadamard product or Schur product |
---|
| 62 | double dotProduct(const Pt3D& p) const { return x * p.x + y * p.y + z * p.z; } |
---|
[255] | 63 | bool normalize(); |
---|
[109] | 64 | }; |
---|
| 65 | |
---|
[255] | 66 | Pt3D operator+(const Pt3D &p1, const Pt3D &p2); |
---|
| 67 | Pt3D operator-(const Pt3D &p1, const Pt3D &p2); |
---|
| 68 | |
---|
[109] | 69 | class Pt3D_DontReportErrors |
---|
| 70 | { |
---|
[255] | 71 | bool state; |
---|
[109] | 72 | public: |
---|
[255] | 73 | Pt3D_DontReportErrors() { state = Pt3D::report_errors; Pt3D::report_errors = false; } |
---|
| 74 | ~Pt3D_DontReportErrors() { Pt3D::report_errors = state; } |
---|
[109] | 75 | }; |
---|
| 76 | |
---|
[255] | 77 | /// orientation in 3D space = rotation matrix |
---|
[109] | 78 | class Matrix44; |
---|
| 79 | |
---|
| 80 | class Orient |
---|
| 81 | { |
---|
[255] | 82 | public: |
---|
| 83 | Pt3D x, y, z; ///< 3 vectors (= 3x3 matrix) |
---|
[109] | 84 | |
---|
| 85 | Orient() {} |
---|
[255] | 86 | Orient(const Orient& src) { x = src.x; y = src.y; z = src.z; } |
---|
| 87 | Orient(const Pt3D& a, const Pt3D& b, const Pt3D& c) :x(a), y(b), z(c) {} |
---|
| 88 | // Orient(const Pt3D& rot) {*this=rot;} |
---|
[109] | 89 | Orient(const Matrix44& m); |
---|
| 90 | void operator=(const Pt3D &rot); |
---|
| 91 | void rotate(const Pt3D &); ///< rotate matrix around 3 axes |
---|
| 92 | |
---|
[255] | 93 | void transform(Pt3D &target, const Pt3D &src) const; ///< transform a vector |
---|
| 94 | void revTransform(Pt3D &target, const Pt3D &src) const; ///< reverse transform |
---|
| 95 | Pt3D transform(const Pt3D &src) const { Pt3D t; transform(t, src); return t; } |
---|
| 96 | Pt3D revTransform(const Pt3D &src) const { Pt3D t; revTransform(t, src); return t; } |
---|
[109] | 97 | |
---|
[255] | 98 | void transform(Orient& target, const Orient& src) const; ///< transform other orient |
---|
| 99 | void revTransform(Orient& target, const Orient& src) const; ///< reverse transform other orient |
---|
| 100 | Orient transform(const Orient& src) const { Orient o; transform(o, src); return o; } ///< transform other orient |
---|
| 101 | Orient revTransform(const Orient& src) const { Orient o; revTransform(o, src); return o; } ///< reverse transform other orient |
---|
[109] | 102 | |
---|
[255] | 103 | void transformSelf(const Orient &rot) { Orient tmp; rot.transform(tmp, *this); *this = tmp; } |
---|
| 104 | void revTransformSelf(const Orient &rot) { Orient tmp; rot.revTransform(tmp, *this); *this = tmp; } |
---|
[109] | 105 | |
---|
| 106 | void getAngles(Pt3D &) const; ///< calculate rotation from current matrix |
---|
[255] | 107 | Pt3D getAngles() const { Pt3D ret; getAngles(ret); return ret; }; ///< calculate rotation from current matrix |
---|
| 108 | void lookAt(const Pt3D &X, const Pt3D &dir); ///< calculate orientation matrix from 2 vectors: X becomes (normalized) Orient.x, dir is the preferred "up" direction (Orient.z). Use lookAt(Pt3D) if only X is relevant. |
---|
| 109 | void lookAt(const Pt3D &X); ///< calculate orientation matrix from 1 vector, X becomes (normalized) Orient.x, the other coordinates are deterministic but not continuous. Use lookAt(Pt3D,Pt3D) if you need more control. |
---|
[109] | 110 | |
---|
| 111 | bool normalize(); |
---|
| 112 | }; |
---|
| 113 | |
---|
| 114 | class Matrix44 |
---|
| 115 | { |
---|
| 116 | public: |
---|
[255] | 117 | double m[16]; |
---|
| 118 | Matrix44() {} |
---|
| 119 | Matrix44(const Matrix44& src) { memcpy(m, src.m, sizeof(m)); } |
---|
| 120 | Matrix44(double *srcm) { memcpy(m, srcm, sizeof(m)); } |
---|
| 121 | Matrix44(const Orient &rot); |
---|
[109] | 122 | |
---|
[255] | 123 | const double& operator()(int i, int j) const { return m[i + 16 * j]; } |
---|
| 124 | const double& operator[](int i) const { return m[i]; } |
---|
| 125 | double& operator()(int i, int j) { return m[i + 16 * j]; } |
---|
| 126 | double& operator[](int i) { return m[i]; } |
---|
[109] | 127 | |
---|
[255] | 128 | void operator+=(const Pt3D &); ///< translate matrix |
---|
| 129 | void operator*=(const Pt3D &); ///< scale matrix |
---|
| 130 | void operator*=(double sc); ///< scale matrix |
---|
[109] | 131 | }; |
---|
| 132 | |
---|
| 133 | extern Pt3D Pt3D_0; ///< zero vector |
---|
| 134 | extern Orient Orient_1; ///< standard unit matrix: 100 010 001 |
---|
| 135 | extern Matrix44 Matrix44_1; ///< standard unit matrix: 1000 0100 0010 0001 |
---|
| 136 | |
---|
[255] | 137 | void rotate2D(double, double &, double &); ///< rotate 2d vector, given angle |
---|
| 138 | void rotate2D(double, double, double &, double &); ///< rotate 2d vector, given sin and cos |
---|
| 139 | double d2(double, double); ///< distance in 2D |
---|
[109] | 140 | |
---|
| 141 | #endif |
---|