Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
normalcone.h
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/***********************************************************************************************
20 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
21 ***********************************************************************************************
22 * *
23 * Project Name : G *
24 * *
25 * $Archive:: /G/WWMath/normalcone.h $*
26 * *
27 * $Author:: Eric_c $*
28 * *
29 * $Modtime:: 11/01/99 2:44p $*
30 * *
31 * $Revision:: 8 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36
37/*
38** The NormalCone is a class used to represent a cone of unit length. It can be used to
39** loosely represent a collection of other normals allowing backface culling to be
40** performed at a heirarchial level rather than at a triangle level.
41**
42** The term 'NormalCone' is a bit of a misnomer; it is really a circular portion of a sphere.
43** -ehc
44*/
45
46#ifndef NORMALCONE_H
47#define NORMALCONE_H
48
49#include "vector3.h"
50#include "matrix3.h"
51
52class NormalCone : public Vector3
53{
54 public:
55
57
58 NormalCone(const Vector3 & normal, float angle = 1.0f)
59 : Vector3(normal),
60 Angle(angle)
61 {}
62
63 void Set(const Vector3 & normal, float angle = 1.0f)
64 {
65 Vector3::Set(normal);
66 Angle = angle;
67 }
68
69 void Set(const NormalCone & src)
70 {
71 Set(src, src.Angle);
72 }
73
74 // return true if this object has degenerated into a sphere.
75 inline bool Complete_Sphere()
76 {
77 return (Angle - WWMATH_EPSILON) <= -1.0f;
78 }
79
80 // find the two vectors on the edge of the cone residing on the same plane as the input vector.
81 // Note: these two Get_Coplanar functions return floats in an attempt to reduce float/int CPU state changes...
82 inline float Get_Coplanar_Normals(const Vector3 & Input, Vector3 & Output1, Vector3 & Output2) const;
83
84 // find the two vectors on the edge of the cone residing on the same plane as the input vector and their dot products with the input.
85 inline float Get_Coplanar_Normals_And_Dots(const Vector3 & Input, Vector3 & Output1, Vector3 & Output2, float & dot1, float & dot2) const;
86
87 // evaluate the input vector, expanding the angle of the cone and recalculating the
88 // new center vector as needed.
89 inline void Merge(const Vector3 & Input);
90
91 // merge the input normal cone's coplanar normals with this object.
92 inline void Merge(const NormalCone & Input);
93
94 // this function returns the dot product between the input vector and the nearest coplanar normal
95 // contained by the cone.
96 // If the input vector is also contained by the cone, the result is always 1.0f.
97 // Note that in the case of a complete sphere, the nearest coplanar normal will be pointing in
98 // the opposite direction of the input vector.
99 inline float Smallest_Dot_Product(const Vector3 & Input);
100
101 // this value is the dot product of the edge of the cone and the center of the cone.
102 // A value of 1.0f indicates that it is a degenerate cone which is basically a cone with radius zero.
103 // A value of zero indicates the cone is actually hemisphere.
104 // A value of -1.0f indicates that it is a complete sphere.
105 float Angle;
106
107};
108
109
110// find the two vectors on the edge of the cone residing on the same plane as the input vector.
111inline float NormalCone::Get_Coplanar_Normals(const Vector3 & Input, Vector3 & Output1, Vector3 & Output2) const
112{
113 // get the cross product of the existing normal and the new one
114 Vector3 cross;
115 Vector3::Cross_Product(Input, *this, & cross);
116
117 float length = cross.Length2();
118 if(length < WWMATH_EPSILON)
119 return 0.0f;
120
121 length = sqrt(length);
122 cross /= length;
123
124 // Make a matrix3 which uses it as an axis of rotation and
125 // rotate this about that axis twice, once +Angle, once -Angle.
126 float radians = (1.0f - Angle) * WWMATH_PI * 0.5f;
127 Matrix3 m1(cross, radians);
128 Matrix3 m2(cross, -radians);
129
130 Matrix3::Rotate_Vector(m1, *this, & Output1);
131 Matrix3::Rotate_Vector(m2, *this, & Output2);
132
133 return length;
134}
135
136inline float NormalCone::Get_Coplanar_Normals_And_Dots(const Vector3 & Input, Vector3 & Output1, Vector3 & Output2, float & Dot1, float & Dot2) const
137{
138 float length = Get_Coplanar_Normals(Input, Output1, Output2);
139
140 if(length < WWMATH_EPSILON)
141 return 0.0f;
142
143 // get the dot products of the new normal with the two coplanar normals and the current average
144 Dot1 = Vector3::Dot_Product(Input, Output1);
145 Dot2 = Vector3::Dot_Product(Input, Output2);
146 return length;
147}
148
149// evaluate the input vector, expanding the angle of the cone and recalculating the
150// new center vector as needed.
151inline void NormalCone::Merge(const Vector3 & Input)
152{
153 // early exit if this normal cone has already turned into a complete sphere.
154 if(Complete_Sphere())
155 return;
156
157 // get the dot of the new vector with the current center vector
158 float dot0 = Vector3::Dot_Product(Input, * this) + WWMATH_EPSILON;
159
160 // if the dot value is greater than the existing cone angle, then the new vector fits
161 // within the cone, so return.
162 if(dot0 >= Angle)
163 return;
164
165 // get the two normals found in the cone which are coplanar to the one passed to this function.
166 Vector3 normal1, normal2;
167 float dot1, dot2;
168 if(Get_Coplanar_Normals_And_Dots(Input, normal1, normal2, dot1, dot2) <= WWMATH_EPSILON)
169 return;
170
171 // test the case where the current average has a lower dot than either of the coplanar normals.
172 // If true, this means that the object now represents a complete sphere with normals facing every
173 // direction.
174 if((dot0 < dot1) && (dot0 < dot2))
175 {
176 Angle = -1;
177 return;
178 }
179
180 // the smaller of the dot values we have is going to indicate which of the two coplanar normals to use
181 // for averaging into the new center normal.
182 if(dot1 < dot2)
183 Set(Input + normal1, dot1);
184 else
185 Set(Input + normal2, dot2);
186
187 // if the angle is < 0, reverse the direction of the averaged normal since we have constructed
188 // something more like a sphere with a cone shape taken out of it (a negative cone).
190 *this *= -1;
191
192 Normalize();
193}
194
195
196// merge the input normal cone's coplanar normals with this object.
197inline void NormalCone::Merge(const NormalCone & Input)
198{
199 Vector3 n1, n2;
200
201 if(Input.Get_Coplanar_Normals(*this, n1,n2) >= WWMATH_EPSILON)
202 {
203 Merge(n1);
204 Merge(n2);
205 }
206}
207
208// this function returns the dot product between the input vector and the nearest coplanar normal
209// contained by the cone.
210// If the input vector is also contained by the cone, the result is always 1.0f.
211// Note that in the case of a complete sphere, the nearest coplanar normal will be pointing in
212// the opposite direction of the input vector.
213inline float NormalCone::Smallest_Dot_Product(const Vector3 & Input)
214{
215 if(Complete_Sphere())
216 return -1.0f;
217
218 // get the dot of the new vector with the current center vector
219 float dot0 = Vector3::Dot_Product(Input, * this);
220
221 // if the negative dot value is greater than the existing cone angle, then the new vector is
222 // parallel to one of the vectors contained in the cone but in negative
223 // direction, so return -1.0f
224 if(-dot0 + WWMATH_EPSILON >= Angle)
225 return -1.0f;
226
227 // if the dot value is greater than the existing cone angle, then the new vector is
228 // parallel to one of the vectors contained in the cone, so return 1.0f
229 if(dot0 + WWMATH_EPSILON >= Angle)
230 return 1.0f;
231
232 // get the two normals found in the cone which are coplanar to the one passed to this function.
233 Vector3 normal1, normal2;
234 float dot1, dot2;
235 Get_Coplanar_Normals_And_Dots(Input, normal1, normal2, dot1, dot2);
236
237 // return the smaller of the two dot products
238 if(dot1 < dot2)
239 return dot1;
240 return dot2;
241}
242
243#endif
#define WWMATH_EPSILON
Definition wwmath.h:54
#define WWMATH_PI
Definition wwmath.h:56
static void Rotate_Vector(const Matrix3 &tm, const Vector3 &in, Vector3 *out)
Definition WWmatrix3.h:976
float Angle
Definition normalcone.h:105
float Get_Coplanar_Normals(const Vector3 &Input, Vector3 &Output1, Vector3 &Output2) const
Definition normalcone.h:111
NormalCone(const Vector3 &normal, float angle=1.0f)
Definition normalcone.h:58
float Get_Coplanar_Normals_And_Dots(const Vector3 &Input, Vector3 &Output1, Vector3 &Output2, float &dot1, float &dot2) const
Definition normalcone.h:136
void Set(const Vector3 &normal, float angle=1.0f)
Definition normalcone.h:63
bool Complete_Sphere()
Definition normalcone.h:75
void Set(const NormalCone &src)
Definition normalcone.h:69
float Smallest_Dot_Product(const Vector3 &Input)
Definition normalcone.h:213
void Merge(const Vector3 &Input)
Definition normalcone.h:151
static WWINLINE float Dot_Product(const Vector3 &a, const Vector3 &b)
Definition vector3.h:293
WWINLINE float Length2(void) const
Definition vector3.h:469
WWINLINE Vector3(void)
Definition vector3.h:96
void Normalize(void)
Definition vector3.h:417
static WWINLINE void Cross_Product(const Vector3 &a, const Vector3 &b, Vector3 *result)
Definition vector3.h:374
WWINLINE void Set(float x, float y, float z)
Definition vector3.h:103