ecere/gfx3D/Plane: Added sphere intersection function
[sdk] / ecere / src / gfx / 3D / Plane.ec
1 namespace gfx3D;
2
3 import "Display"
4
5 public struct Line
6 {
7    Vector3D p0;
8    Vector3D delta;
9
10    bool IntersectSphere(double radius, double * t)
11    {
12       double a = delta.DotProduct(delta);
13       double b = 2 * delta.DotProduct(p0);
14       double c = p0.DotProduct(p0) - radius * radius;
15       double disc = b * b - 4 * a * c;
16       if(disc >= 0)
17       {
18          double distSqrt = sqrt(disc);
19          double q = ((b < 0) ? (-b - distSqrt) : (-b + distSqrt)) /2;
20          double t0 = q / a, t1 = c / q;
21          if (t0 > t1)
22          {
23             double temp = t0;
24             t0 = t1;
25             t1 = temp;
26          }
27          if (t1 >= 0)
28          {
29             if(t)
30               *t = (t0 >= 0) ? t0 : t1;
31             return true;
32          }
33       }
34       return false;
35    }
36 };
37
38 public struct Plane
39 {
40    union
41    {
42       struct { double a, b, c; };
43       Vector3D normal;
44    };
45    double d;
46
47    void FromPoints(Vector3D v1, Vector3D v2, Vector3D v3)
48    {
49       Vector3D a, b;
50
51       a.Subtract(v3, v1);
52       b.Subtract(v2, v1);
53       normal.CrossProduct(a, b);
54       normal.Normalize(normal);
55
56       d = -normal.DotProduct(v1);
57    }
58
59    void FromPointsf(Vector3Df v1, Vector3Df v2, Vector3Df v3)
60    {
61       Vector3D v1d { (double)v1.x, (double)v1.y, (double)v1.z };
62       Vector3D v2d { (double)v2.x, (double)v2.y, (double)v2.z };
63       Vector3D v3d { (double)v3.x, (double)v3.y, (double)v3.z };
64       Vector3D a, b;
65
66       a.Subtract(v3d, v1d);
67       b.Subtract(v2d, v1d);
68       normal.CrossProduct(a, b);
69       normal.Normalize(normal);
70
71       d = -normal.DotProduct(v1d);
72    }
73
74    void MultMatrix(Plane source, Matrix inverseTranspose)
75    {
76       a = source.a * inverseTranspose.m[0][0] +
77           source.b * inverseTranspose.m[1][0] +
78           source.c * inverseTranspose.m[2][0] +
79           source.d * inverseTranspose.m[3][0];
80       b = source.a * inverseTranspose.m[0][1] +
81           source.b * inverseTranspose.m[1][1] +
82           source.c * inverseTranspose.m[2][1] +
83           source.d * inverseTranspose.m[3][1];
84       c = source.a * inverseTranspose.m[0][2] +
85           source.b * inverseTranspose.m[1][2] +
86           source.c * inverseTranspose.m[2][2] +
87           source.d * inverseTranspose.m[3][2];
88       d = source.a * inverseTranspose.m[0][3] +
89           source.b * inverseTranspose.m[1][3] +
90           source.c * inverseTranspose.m[2][3] +
91           source.d * inverseTranspose.m[3][3];
92    }
93
94    void IntersectLine(Line line, Vector3D result)
95    {
96       double divisor = a * line.delta.x + b * line.delta.y + c * line.delta.z;
97
98       result.x = (b * line.delta.y * line.p0.x - b * line.delta.x * line.p0.y +
99                   c * line.delta.z * line.p0.x - c * line.delta.x * line.p0.z -
100                   d * line.delta.x ) / divisor;
101
102       result.y = (a * line.delta.x * line.p0.y - a * line.delta.y * line.p0.x +
103                   c * line.delta.z * line.p0.y - c * line.delta.y * line.p0.z -
104                   d * line.delta.y ) / divisor;
105
106       result.z = (a * line.delta.x * line.p0.z - a * line.delta.z * line.p0.x +
107                   b * line.delta.y * line.p0.z - b * line.delta.z * line.p0.y -
108                   d * line.delta.z ) / divisor;
109    }
110
111    void IntersectLinef(Line line, Vector3Df result)
112    {
113       double divisor = a * line.delta.x + b * line.delta.y + c * line.delta.z;
114
115       result.x = (float)((b * line.delta.y * line.p0.x - b * line.delta.x * line.p0.y +
116                   c * line.delta.z * line.p0.x - c * line.delta.x * line.p0.z -
117                   d * line.delta.x ) / divisor);
118
119       result.y = (float)((a * line.delta.x * line.p0.y - a * line.delta.y * line.p0.x +
120                   c * line.delta.z * line.p0.y - c * line.delta.y * line.p0.z -
121                   d * line.delta.y ) / divisor);
122
123       result.z = (float)((a * line.delta.x * line.p0.z - a * line.delta.z * line.p0.x +
124                   b * line.delta.y * line.p0.z - b * line.delta.z * line.p0.y -
125                   d * line.delta.z ) / divisor);
126    }
127
128    void FromPointNormal(Vector3D normal, Vector3D point)
129    {
130       this.normal = normal;
131       d = -(normal.x * point.x + normal.y * point.y + normal.z * point.z);
132    }
133 };