1 /****************************************************************************************/
\r
5 /* Description: 3D Vector implementation */
\r
7 /* The contents of this file are subject to the Genesis3D Public License */
\r
8 /* Version 1.01 (the "License"); you may not use this file except in */
\r
9 /* compliance with the License. You may obtain a copy of the License at */
\r
10 /* http://www.genesis3d.com */
\r
12 /* Software distributed under the License is distributed on an "AS IS" */
\r
13 /* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See */
\r
14 /* the License for the specific language governing rights and limitations */
\r
15 /* under the License. */
\r
17 /* The Original Code is Genesis3D, released March 25, 1999. */
\r
18 /*Genesis3D Version 1.1 released November 15, 1999 */
\r
19 /* Copyright (C) 1999 WildTangent, Inc. All Rights Reserved */
\r
21 /****************************************************************************************/
\r
26 #define VCOMPARE_EPSILON (geFloat)0.0005
\r
30 #define ASM_NORMALIZE
\r
35 GENESISAPI geFloat GENESISCC geVec3d_GetElement(geVec3d *V, int Index)
\r
37 assert( V != NULL );
\r
38 assert( Index >= 0 );
\r
39 assert( Index < 3 );
\r
40 return (* ((&((V)->X)) + (Index) ));
\r
44 GENESISAPI geBoolean GENESISCC geVec3d_IsValid(const geVec3d *V)
\r
48 if ((V->X * V->X) < 0.0f)
\r
50 if ((V->Y * V->Y) < 0.0f)
\r
52 if ((V->Z * V->Z) < 0.0f)
\r
58 GENESISAPI void GENESISCC geVec3d_Set(geVec3d *V, geFloat X, geFloat Y, geFloat Z)
\r
60 assert ( V != NULL );
\r
64 assert( geVec3d_IsValid(V) != GE_FALSE );
\r
67 GENESISAPI void GENESISCC geVec3d_Get(const geVec3d *V, geFloat *X, geFloat *Y, geFloat *Z)
\r
69 assert ( V != NULL );
\r
70 assert ( X != NULL );
\r
71 assert ( Y != NULL );
\r
72 assert ( Z != NULL );
\r
73 assert( geVec3d_IsValid(V) != GE_FALSE );
\r
81 GENESISAPI geFloat GENESISCC geVec3d_DotProduct(const geVec3d *V1, const geVec3d *V2)
\r
83 assert ( V1 != NULL );
\r
84 assert ( V2 != NULL );
\r
85 assert( geVec3d_IsValid(V1) != GE_FALSE );
\r
86 assert( geVec3d_IsValid(V2) != GE_FALSE );
\r
88 return(V1->X*V2->X + V1->Y*V2->Y + V1->Z*V2->Z);
\r
91 GENESISAPI void GENESISCC geVec3d_CrossProduct(const geVec3d *V1, const geVec3d *V2, geVec3d *VResult)
\r
94 assert ( V1 != NULL );
\r
95 assert ( V2 != NULL );
\r
96 assert ( VResult != NULL );
\r
97 assert( geVec3d_IsValid(V1) != GE_FALSE );
\r
98 assert( geVec3d_IsValid(V2) != GE_FALSE );
\r
100 Result.X = V1->Y*V2->Z - V1->Z*V2->Y;
\r
101 Result.Y = V1->Z*V2->X - V1->X*V2->Z;
\r
102 Result.Z = V1->X*V2->Y - V1->Y*V2->X;
\r
107 GENESISAPI geBoolean GENESISCC geVec3d_Compare(const geVec3d *V1, const geVec3d *V2, geFloat Tolerance)
\r
109 assert ( V1 != NULL );
\r
110 assert ( V2 != NULL );
\r
111 assert ( Tolerance >= 0.0 );
\r
112 assert( geVec3d_IsValid(V1) != GE_FALSE );
\r
113 assert( geVec3d_IsValid(V2) != GE_FALSE );
\r
115 if (fabs(V2->X - V1->X) > Tolerance) //VCOMPARE_EPSILON)
\r
117 if (fabs(V2->Y - V1->Y) > Tolerance) //VCOMPARE_EPSILON)
\r
119 if (fabs(V2->Z - V1->Z) > Tolerance) //VCOMPARE_EPSILON)
\r
125 #ifdef ASM_NORMALIZE
\r
127 GENESISAPI geFloat GENESISCC geVec3d_Normalize(geVec3d *V1)
\r
130 geFloat Dist,OneOverDist;
\r
132 fPtr = (geFloat *)V1;
\r
133 Dist = (*fPtr) * (*fPtr); fPtr++;
\r
134 Dist += (*fPtr) * (*fPtr); fPtr++;
\r
135 Dist += (*fPtr) * (*fPtr);
\r
137 // Vtune shows the geFloat <-> double conversions
\r
138 // required for the clib sqrt() are taking a lot of time.
\r
139 // hence we use asm to access the geFloat fsqrt() directly
\r
148 if ( Dist == 0.0f )
\r
151 OneOverDist = 1.0f/Dist;
\r
153 fPtr = (geFloat *)V1;
\r
154 *fPtr *= OneOverDist; fPtr++;
\r
155 *fPtr *= OneOverDist; fPtr++;
\r
156 *fPtr *= OneOverDist;
\r
158 return (geFloat)Dist;
\r
161 GENESISAPI geFloat GENESISCC geVec3d_Normalize(geVec3d *V1)
\r
163 geFloat OneOverDist;
\r
166 assert( geVec3d_IsValid(V1) != GE_FALSE );
\r
168 Dist = (geFloat)sqrt(geVec3d_DotProduct(V1, V1));
\r
172 OneOverDist = 1.0f/Dist;
\r
174 V1->X *= OneOverDist;
\r
175 V1->Y *= OneOverDist;
\r
176 V1->Z *= OneOverDist;
\r
180 #endif // ASM_NORMALIZE
\r
182 GENESISAPI geBoolean GENESISCC geVec3d_IsNormalized(const geVec3d *V)
\r
186 assert( geVec3d_IsValid(V) != GE_FALSE );
\r
188 length = geVec3d_Length(V);
\r
189 if ((length >= 1.0f - VCOMPARE_EPSILON) && (length <= 1.0f + VCOMPARE_EPSILON))
\r
195 GENESISAPI void GENESISCC geVec3d_Scale(const geVec3d *VSrc, geFloat Scale, geVec3d *VDst)
\r
197 assert ( VDst != NULL );
\r
198 assert( geVec3d_IsValid(VSrc) != GE_FALSE );
\r
200 VDst->X = VSrc->X * Scale;
\r
201 VDst->Y = VSrc->Y * Scale;
\r
202 VDst->Z = VSrc->Z * Scale;
\r
203 assert( geVec3d_IsValid(VDst) != GE_FALSE );
\r
206 GENESISAPI geFloat GENESISCC geVec3d_LengthSquared(const geVec3d *V1)
\r
208 return geVec3d_DotProduct(V1, V1);
\r
211 GENESISAPI geFloat GENESISCC geVec3d_Length(const geVec3d *V1)
\r
213 assert( geVec3d_IsValid(V1) != GE_FALSE );
\r
215 return (geFloat)sqrt(geVec3d_DotProduct(V1, V1));
\r
218 GENESISAPI void GENESISCC geVec3d_Subtract(const geVec3d *V1, const geVec3d *V2, geVec3d *V1MinusV2)
\r
220 assert( geVec3d_IsValid(V1) != GE_FALSE );
\r
221 assert( geVec3d_IsValid(V2) != GE_FALSE );
\r
222 assert ( V1MinusV2 != NULL );
\r
224 V1MinusV2->X = V1->X - V2->X;
\r
225 V1MinusV2->Y = V1->Y - V2->Y;
\r
226 V1MinusV2->Z = V1->Z - V2->Z;
\r
229 GENESISAPI void GENESISCC geVec3d_Add(const geVec3d *V1, const geVec3d *V2, geVec3d *V1PlusV2)
\r
231 assert( geVec3d_IsValid(V1) != GE_FALSE );
\r
232 assert( geVec3d_IsValid(V2) != GE_FALSE );
\r
233 assert ( V1PlusV2 != NULL );
\r
235 V1PlusV2->X = V1->X + V2->X;
\r
236 V1PlusV2->Y = V1->Y + V2->Y;
\r
237 V1PlusV2->Z = V1->Z + V2->Z;
\r
240 GENESISAPI void GENESISCC geVec3d_MA(geVec3d *V1, geFloat Scale, const geVec3d *V2, geVec3d *V1PlusV2Scaled)
\r
242 assert( geVec3d_IsValid(V1) != GE_FALSE );
\r
243 assert( geVec3d_IsValid(V2) != GE_FALSE );
\r
244 assert ( V1PlusV2Scaled != NULL );
\r
246 V1PlusV2Scaled->X = V1->X + V2->X*Scale;
\r
247 V1PlusV2Scaled->Y = V1->Y + V2->Y*Scale;
\r
248 V1PlusV2Scaled->Z = V1->Z + V2->Z*Scale;
\r
251 GENESISAPI void GENESISCC geVec3d_AddScaled(const geVec3d *V1, const geVec3d *V2, geFloat Scale, geVec3d *V1PlusV2Scaled)
\r
253 assert( geVec3d_IsValid(V1) != GE_FALSE );
\r
254 assert( geVec3d_IsValid(V2) != GE_FALSE );
\r
255 assert ( V1PlusV2Scaled != NULL );
\r
257 V1PlusV2Scaled->X = V1->X + V2->X*Scale;
\r
258 V1PlusV2Scaled->Y = V1->Y + V2->Y*Scale;
\r
259 V1PlusV2Scaled->Z = V1->Z + V2->Z*Scale;
\r
262 GENESISAPI void GENESISCC geVec3d_Copy(const geVec3d *VSrc, geVec3d *VDst)
\r
264 assert ( VDst != NULL );
\r
265 assert( geVec3d_IsValid(VSrc) != GE_FALSE );
\r
270 GENESISAPI void GENESISCC geVec3d_Clear(geVec3d *V)
\r
272 assert ( V != NULL );
\r
279 GENESISAPI void GENESISCC geVec3d_Inverse(geVec3d *V)
\r
281 assert( geVec3d_IsValid(V) != GE_FALSE );
\r
288 GENESISAPI geFloat GENESISCC geVec3d_DistanceBetween(const geVec3d *V1, const geVec3d *V2) // returns length of V1-V2
\r
292 assert( geVec3d_IsValid(V1) != GE_FALSE );
\r
293 assert( geVec3d_IsValid(V2) != GE_FALSE );
\r
295 geVec3d_Subtract(V1,V2,&B);
\r
296 return geVec3d_Length(&B);
\r