00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00032 #include "common.h"
00033 #include "test/test.h"
00034 #include "../vector3.h"
00035
00036
00037
00038
00039
00040
00041
00042 static bool Check(bool r)
00043 {
00044 if(!r)
00045 {
00046 BREAKPOINT;
00047 }
00048 return r;
00049 }
00050
00051 static bool CheckEqual(int a,int b)
00052 {
00053 bool r = a==b;
00054 if(!r)
00055 {
00056 BREAKPOINT;
00057 }
00058 return r;
00059 }
00060
00061 static bool CheckEqual(const Vector3& a,const Vector3& b)
00062 {
00063 bool r = a==b;
00064 if(!r)
00065 {
00066 BREAKPOINT;
00067 }
00068 return r;
00069 }
00070
00071 static bool CheckNotEqual(const Vector3& a,const Vector3& b)
00072 {
00073 bool r = a!=b;
00074 if(!r)
00075 {
00076 BREAKPOINT;
00077 }
00078 return r;
00079 }
00080
00081 #define CHECK(c) (void)(Check(c)||TEST_FAILED)
00082 #define CHECK_EQ(a,b) (void)(CheckEqual((a),(b))||TEST_FAILED)
00083 #define CHECK_NE(a,b) (void)(CheckNotEqual((a),(b))||TEST_FAILED)
00084
00085
00086
00087
00088
00089
00090
00091 static void TestLengthSquared()
00092 {
00093 int n;
00094 ufix seed=0;
00095 for(n=0; n<(1<<20); n++)
00096 {
00097 fix x = Fix::Random(seed);
00098 fix y = Fix::Random(seed);
00099 fix z = Fix::Random(seed);
00100 ufix f;
00101 ufix i = Vector3(x,y,z).LengthSquared(f);
00102 uint64_t d1 = int64_t(x)*int64_t(x)+int64_t(y)*int64_t(y)+int64_t(z)*int64_t(z);
00103 uint64_t d2 = uint64_t(i)*uint64_t(65536)*uint64_t(65536)+uint64_t(f);
00104 int64_t d = d1-d2;
00105 if(d<0) d = -d;
00106 CHECK(d1==d2);
00107 }
00108 }
00109
00110
00111 static void TestLength()
00112 {
00113 int i;
00114 for(i=0; i<31; i++)
00115 {
00116 CHECK_EQ(Vector3(1<<i,0,0).Length(),1<<i);
00117 CHECK_EQ(Vector3(0,1<<i,0).Length(),1<<i);
00118 CHECK_EQ(Vector3(0,0,1<<i).Length(),1<<i);
00119 if(i<29)
00120 CHECK_EQ(Vector3(1<<i,4<<i,8<<i).Length(),9<<i);
00121 }
00122 for(i=0; i<(1<<24); i++)
00123 {
00124 CHECK_EQ(Vector3(i,0,0).Length(),i);
00125 CHECK_EQ(Vector3(0,-i,0).Length(),i);
00126 CHECK_EQ(Vector3(0,0,i<<1).Length(),i<<1);
00127 }
00128 ufix seed=0;
00129 for(i=0; i<(1<<20); i++)
00130 {
00131 fix r = Fix::Random(seed,1<<24);
00132 r <<= Fix::Random(seed,8);
00133 ufix a = r<0 ? -r : r;
00134 CHECK_EQ(Vector3(r,0,0).Length(),a);
00135 CHECK_EQ(Vector3(0,r,0).Length(),a);
00136 CHECK_EQ(Vector3(0,0,r).Length(),a);
00137 }
00138 }
00139
00140
00141 static void TestCompareLength()
00142 {
00143 int n;
00144 ufix seed=0;
00145 for(n=0; n<(1<<20); n++)
00146 {
00147 fix x = Fix::Random(seed);
00148 fix y = Fix::Random(seed);
00149 fix z = Fix::Random(seed);
00150 Vector3 v(x,y,z);
00151 ufix l = v.Length();
00152 if(l<0xffffff00u)
00153 CHECK_EQ(v.CompareLength(l+0x100),-1);
00154 if(l>=0x100)
00155 CHECK_EQ(v.CompareLength(l-0x100),1);
00156 }
00157 for(n=0; n<(1<<20); n++)
00158 {
00159 fix r = Fix::Random(seed,1<<24);
00160 r <<= Fix::Random(seed,8);
00161 ufix a = r<0 ? -r : r;
00162 Vector3 v(0,a,0);
00163 ufix l = v.Length();
00164 CHECK_EQ(v.CompareLength(l),0);
00165 if(l<0xffffffffu)
00166 CHECK_EQ(v.CompareLength(l+1),-1);
00167 if(l>=0x1)
00168 CHECK_EQ(v.CompareLength(l-1),1);
00169 }
00170 }
00171
00172
00173 static void TestUnitVector()
00174 {
00175 uint32_t seed = 0;
00176 for(int n=0; n<1<<20; n++)
00177 {
00178 fix x = Fix::Random(seed);
00179 fix y = Fix::Random(seed);
00180 fix z = Fix::Random(seed);
00181 Vector3 u(Vector3(x,y,z).UnitVector());
00182
00183 ufix l = u.Length();
00184 CHECK(l<=0x10000 && l>=0x0fffe);
00185
00186 ufix f;
00187 ufix i = u.LengthSquared(f);
00188 if(i)
00189 {
00190 CHECK(i==1);
00191 CHECK(f<0x00010000);
00192 }
00193 else
00194 CHECK(f>0xfffc0000);
00195 }
00196
00197 for(int t=0; t<5; t++)
00198 {
00199 fix in[5][3] =
00200 {
00201 {0x12345678, 0, 0},
00202 {4<<16, 3<<16, 0},
00203 {1<<16, 2<<16, 2<<16},
00204 {1<<16, 4<<16, 8<<16},
00205 {1, 4, 8}
00206 };
00207 fix out[5][3] =
00208 {
00209 {1<<16, 0, 0},
00210 {(4<<16)/5, (3<<16)/5, 0},
00211 {(1<<16)/3, (2<<16)/3, (2<<16)/3},
00212 {(1<<16)/9, (4<<16)/9, (8<<16)/9},
00213 {(1<<16)/9, (4<<16)/9, (8<<16)/9}
00214 };
00215 for(int i=0; i<3; i++)
00216 for(int j=0; j<3; j++)
00217 for(int k=0; k<3; k++)
00218 {
00219 if(i==j) continue;
00220 if(i==k) continue;
00221 if(j==k) continue;
00222 int a[3];
00223 int b[3];
00224 for(int s=0; s<8; s++)
00225 {
00226 a[0] = in[t][i];
00227 a[1] = in[t][j];
00228 a[2] = in[t][k];
00229 b[0] = out[t][i];
00230 b[1] = out[t][j];
00231 b[2] = out[t][k];
00232 if(s&1)
00233 {
00234 a[0] = -a[0];
00235 b[0] = -b[0];
00236 }
00237 if(s&2)
00238 {
00239 a[1] = -a[1];
00240 b[1] = -b[1];
00241 }
00242 if(s&4)
00243 {
00244 a[2] = -a[2];
00245 b[2] = -b[2];
00246 }
00247 CHECK_EQ(Vector3(a[0],a[1],a[2]).UnitVector(),Vector3(b[0],b[1],b[2]));
00248 }
00249 }
00250 }
00251 }
00252
00253
00254 static void TestNormal()
00255 {
00256 CHECK_EQ(Vector3(17<<8,0,0).Normal(Vector3(0,31<<16,0)),Vector3(0,0,1<<16));
00257 CHECK_EQ(Vector3(-17<<8,0,0).Normal(Vector3(0,31<<16,0)),Vector3(0,0,-1<<16));
00258 CHECK_EQ(Vector3(17<<8,0,0).Normal(Vector3(0,-31<<16,0)),Vector3(0,0,-1<<16));
00259 CHECK_EQ(Vector3(-17<<8,0,0).Normal(Vector3(0,-31<<16,0)),Vector3(0,0,1<<16));
00260 fix q = 119<<16;
00261 CHECK_EQ(Vector3(q,q,0).Normal(Vector3(-q,q,0)),Vector3(0,0,1<<16));
00262 CHECK_EQ(Vector3(-q,q,0).Normal(Vector3(q,q,0)),Vector3(0,0,-1<<16));
00263 CHECK_EQ(Vector3(q,0,q).Normal(Vector3(-q,0,q)),Vector3(0,-1<<16,0));
00264 CHECK_EQ(Vector3(-q,0,q).Normal(Vector3(q,0,q)),Vector3(0,1<<16,0));
00265 CHECK_EQ(Vector3(0,q,q).Normal(Vector3(0,-q,q)),Vector3(1<<16,0,0));
00266 CHECK_EQ(Vector3(0,-q,q).Normal(Vector3(0,q,q)),Vector3(-1<<16,0,0));
00267 q = 0x7fffffff;
00268 CHECK_EQ(Vector3(q,q,0).Normal(Vector3(-q,q,0)),Vector3(0,0,1<<16));
00269 CHECK_EQ(Vector3(-q,q,0).Normal(Vector3(q,q,0)),Vector3(0,0,-1<<16));
00270 CHECK_EQ(Vector3(q,0,q).Normal(Vector3(-q,0,q)),Vector3(0,-1<<16,0));
00271 CHECK_EQ(Vector3(-q,0,q).Normal(Vector3(q,0,q)),Vector3(0,1<<16,0));
00272 CHECK_EQ(Vector3(0,q,q).Normal(Vector3(0,-q,q)),Vector3(1<<16,0,0));
00273 CHECK_EQ(Vector3(0,-q,q).Normal(Vector3(0,q,q)),Vector3(-1<<16,0,0));
00274
00275 int i;
00276 for(i=0; i<31; i++)
00277 for(int j=0; j<31; j++)
00278 {
00279 CHECK_EQ(Vector3(1<<i,0,0).Normal(Vector3(0,1<<j,0)),Vector3(0,0,1<<16));
00280 CHECK_EQ(Vector3((1<<(i+1))-1,0,0).Normal(Vector3(0,(1<<(j+1))-1,0)),Vector3(0,0,1<<16));
00281 CHECK_EQ(Vector3(0,-1<<i,0).Normal(Vector3(0,0,1<<j)),Vector3(-1<<16,0,0));
00282 CHECK_EQ(Vector3(0,-1<<(i+1),0).Normal(Vector3(0,0,1<<j)),Vector3(-1<<16,0,0));
00283 CHECK_EQ(Vector3(0,-1<<(i+1),0).Normal(Vector3(0,0,(1<<(j+1))-1)),Vector3(-1<<16,0,0));
00284 }
00285
00286 uint32_t seed=0;
00287 for(i=0; i<1<<20; i++)
00288 {
00289 ufix a = Fix::Random(seed);
00290 ufix b = Fix::Random(seed);
00291 Vector3 n(Vector3(1|(a>>1),0,0).Normal(Vector3(0,1|(b>>1),0)));
00292 CHECK_EQ(n,Vector3(0,0,1<<16));
00293 }
00294
00295 for(i=0; i<1<<20; i++)
00296 {
00297 Vector3 a(Fix::Random(seed),Fix::Random(seed),Fix::Random(seed));
00298 Vector3 b(Fix::Random(seed),Fix::Random(seed),Fix::Random(seed));
00299 Vector3 n(a.Normal(b));
00300 fix l = n.Length();
00301 CHECK(l<=0x10000 && l>=0x0fffe);
00302 }
00303 }
00304
00305
00306 #define OFFSET_VECTOR(a,b,c) Vector3((a)+(1<<16),(b)+(2<<16),(c)+(3<<16))
00307
00308 static void TestPointNormal()
00309 {
00310 CHECK_EQ(OFFSET_VECTOR(0,0,0).Normal(OFFSET_VECTOR(17<<8,0,0),OFFSET_VECTOR(0,31<<16,0)),Vector3(0,0,1<<16));
00311 CHECK_EQ(OFFSET_VECTOR(0,0,0).Normal(OFFSET_VECTOR(-17<<8,0,0),OFFSET_VECTOR(0,31<<16,0)),Vector3(0,0,-1<<16));
00312 CHECK_EQ(OFFSET_VECTOR(0,0,0).Normal(OFFSET_VECTOR(17<<8,0,0),OFFSET_VECTOR(0,-31<<16,0)),Vector3(0,0,-1<<16));
00313 CHECK_EQ(OFFSET_VECTOR(0,0,0).Normal(OFFSET_VECTOR(-17<<8,0,0),OFFSET_VECTOR(0,-31<<16,0)),Vector3(0,0,1<<16));
00314 fix q = 119<<16;
00315 CHECK_EQ(OFFSET_VECTOR(0,0,0).Normal(OFFSET_VECTOR(q,q,0),OFFSET_VECTOR(-q,q,0)),Vector3(0,0,1<<16));
00316 CHECK_EQ(OFFSET_VECTOR(0,0,0).Normal(OFFSET_VECTOR(-q,q,0),OFFSET_VECTOR(q,q,0)),Vector3(0,0,-1<<16));
00317 CHECK_EQ(OFFSET_VECTOR(0,0,0).Normal(OFFSET_VECTOR(q,0,q),OFFSET_VECTOR(-q,0,q)),Vector3(0,-1<<16,0));
00318 CHECK_EQ(OFFSET_VECTOR(0,0,0).Normal(OFFSET_VECTOR(-q,0,q),OFFSET_VECTOR(q,0,q)),Vector3(0,1<<16,0));
00319 CHECK_EQ(OFFSET_VECTOR(0,0,0).Normal(OFFSET_VECTOR(0,q,q),OFFSET_VECTOR(0,-q,q)),Vector3(1<<16,0,0));
00320 CHECK_EQ(OFFSET_VECTOR(0,0,0).Normal(OFFSET_VECTOR(0,-q,q),OFFSET_VECTOR(0,q,q)),Vector3(-1<<16,0,0));
00321 }
00322
00323
00324 static void TestAngle()
00325 {
00326 CHECK_EQ(Vector3(1,0,0).Angle(Vector3(0,1,0)),0x4000);
00327 CHECK_EQ(Vector3(0,-1,0).Angle(Vector3(0,0,1)),0x4000);
00328 CHECK_EQ(Vector3(1,1,0).Angle(Vector3(-1,1,0)),0x4000);
00329
00330 CHECK_EQ(Vector3(1,0,0).Angle(Vector3(1,0,0)),0);
00331 CHECK(Vector3(1,1,0).Angle(Vector3(1,1,0))<0x80);
00332 CHECK_EQ(Vector3(0,1,0).Angle(Vector3(1,1,0)),0x2000);
00333
00334 CHECK_EQ(Vector3(1,0,0).Angle(Vector3(-1,0,0)),0x8000);
00335 CHECK(Vector3(1,1,0).Angle(Vector3(-1,-1,0))>0x7f80);
00336 CHECK(Vector3(0,-1,1).Angle(Vector3(0,1,-1))>0x7f80);
00337 }
00338
00339
00340 static void TestPointAngle()
00341 {
00342 CHECK_EQ(OFFSET_VECTOR(0,0,0).Angle(OFFSET_VECTOR(1,0,0),OFFSET_VECTOR(0,1,0)),0x4000);
00343 CHECK_EQ(OFFSET_VECTOR(0,0,0).Angle(OFFSET_VECTOR(0,-1,0),OFFSET_VECTOR(0,0,1)),0x4000);
00344 CHECK_EQ(OFFSET_VECTOR(0,0,0).Angle(OFFSET_VECTOR(1,1,0),OFFSET_VECTOR(-1,1,0)),0x4000);
00345
00346 CHECK_EQ(OFFSET_VECTOR(0,0,0).Angle(OFFSET_VECTOR(1,0,0),OFFSET_VECTOR(1,0,0)),0);
00347 CHECK(OFFSET_VECTOR(0,0,0).Angle(OFFSET_VECTOR(1,1,0),OFFSET_VECTOR(1,1,0))<0x80);
00348 CHECK_EQ(OFFSET_VECTOR(0,0,0).Angle(OFFSET_VECTOR(0,1,0),OFFSET_VECTOR(1,1,0)),0x2000);
00349
00350 CHECK_EQ(OFFSET_VECTOR(0,0,0).Angle(OFFSET_VECTOR(1,0,0),OFFSET_VECTOR(-1,0,0)),0x8000);
00351 CHECK(OFFSET_VECTOR(0,0,0).Angle(OFFSET_VECTOR(1,1,0),OFFSET_VECTOR(-1,-1,0))>0x7f80);
00352 CHECK(OFFSET_VECTOR(0,0,0).Angle(OFFSET_VECTOR(0,-1,1),OFFSET_VECTOR(0,1,-1))>0x7f80);
00353 }
00354
00355
00356 static void TestTranslate()
00357 {
00358 Vector3 in[3];
00359 in[0] = Vector3(10,20,30);
00360 in[1] = Vector3(100,200,300);
00361 in[2] = Vector3(1000,2000,3000);
00362 Vector3 out[3];
00363 out[0] = in[0];
00364 out[1] = in[1];
00365 out[2] = in[2];
00366 Vector3 offset(1,2,3);
00367
00368 Vector3::Translate(out,0,in,offset);
00369 CHECK_EQ(out[0],in[0]);
00370
00371 Vector3::Translate(out,2,in,offset);
00372 CHECK_EQ(out[0],Vector3(11,22,33));
00373 CHECK_EQ(out[1],Vector3(101,202,303));
00374 CHECK_EQ(out[2],in[2]);
00375 }
00376
00377
00378 static void TestScale()
00379 {
00380 Vector3 in[3];
00381 in[0] = Vector3(10,20,30);
00382 in[1] = Vector3(100,200,300);
00383 in[2] = Vector3(1000,2000,3000);
00384 Vector3 out[3];
00385 out[0] = in[0];
00386 out[1] = in[1];
00387 out[2] = in[2];
00388 Vector3::Scale(out,0,in,2<<16);
00389 CHECK_EQ(out[0],in[0]);
00390 Vector3::Scale(out,2,in,2<<16);
00391 CHECK_EQ(out[0],Vector3(20,40,60));
00392 CHECK_EQ(out[1],Vector3(200,400,600));
00393 CHECK_EQ(out[2],in[2]);
00394 }
00395
00396
00397 static void TestMatrix3()
00398 {
00399
00400 Vector3 r1(1,2,3);
00401 Vector3 r2(4,5,6);
00402 Vector3 r3(7,8,9);
00403 Matrix3 m(r1,r2,r3);
00404 CHECK(m.Row1==r1);
00405 CHECK(m.Row2==r2);
00406 CHECK(m.Row3==r3);
00407
00408
00409 Matrix3 tm(m.Transposition());
00410 CHECK(tm.Row1==Vector3(1,4,7));
00411 CHECK(tm.Row2==Vector3(2,5,8));
00412 CHECK(tm.Row3==Vector3(3,6,9));
00413
00414
00415 fix o = 1<<16;
00416 Vector3 a;
00417 a = Matrix3(Vector3(o,0,0),Vector3(0,o,0),Vector3(0,0,o))*r1;
00418 CHECK_EQ(a,Vector3(1,2,3));
00419 a = Matrix3(Vector3(0,o,0),Vector3(0,0,o),Vector3(o,0,0))*r1;
00420 CHECK_EQ(a,Vector3(2,3,1));
00421 a = Matrix3(Vector3(0,0,o),Vector3(o,0,0),Vector3(0,o,0))*r1;
00422 CHECK_EQ(a,Vector3(3,1,2));
00423 a = Matrix3(Vector3(o,-o,0),Vector3(0,0,0),Vector3(0,0,0))*r1;
00424 CHECK_EQ(a,Vector3(-1,0,0));
00425 a = Matrix3(Vector3(0,0,0),Vector3(o,0,-o),Vector3(0,0,0))*r1;
00426 CHECK_EQ(a,Vector3(0,-2,0));
00427 a = Matrix3(Vector3(0,0,0),Vector3(0,0,0),Vector3(0,-o,o))*r1;
00428 CHECK_EQ(a,Vector3(0,0,1));
00429 o = -o;
00430 a = Matrix3(Vector3(o,0,0),Vector3(0,o,0),Vector3(0,0,o))*r1;
00431 CHECK_EQ(a,Vector3(-1,-2,-3));
00432 a = Matrix3(Vector3(0,o,0),Vector3(0,0,o),Vector3(o,0,0))*r1;
00433 CHECK_EQ(a,Vector3(-2,-3,-1));
00434 a = Matrix3(Vector3(0,0,o),Vector3(o,0,0),Vector3(0,o,0))*r1;
00435 CHECK_EQ(a,Vector3(-3,-1,-2));
00436
00437
00438 Vector3 in[3];
00439 in[0] = Vector3(10,20,30);
00440 in[1] = Vector3(100,200,300);
00441 in[2] = Vector3(1000,2000,3000);
00442 Vector3 out[3];
00443 out[0] = in[0];
00444 out[1] = in[1];
00445 out[2] = in[2];
00446 Vector3 offset(1,2,3);
00447
00448 m = Matrix3(Vector3(2<<16,0,0),Vector3(0,-1<<16,0),Vector3(0,0,3<<16));
00449 m.Transform(out,0,in);
00450 CHECK_EQ(out[0],in[0]);
00451
00452 m.Transform(out,2,in);
00453 CHECK_EQ(out[0],Vector3(20,-20,90));
00454 CHECK_EQ(out[1],Vector3(200,-200,900));
00455 CHECK_EQ(out[2],in[2]);
00456 }
00457
00458
00459
00460
00461
00462
00463
00464 void TestVector3()
00465 {
00466 TestNormal();
00467
00468 Vector3 a(1,2,3);
00469 Vector3 b(110,-220,330);
00470 Vector3 c;
00471
00472
00473 CHECK_EQ(a,a);
00474 CHECK_EQ(a,Vector3(1,2,3));
00475
00476
00477 CHECK_NE(a,Vector3(2,2,3));
00478 CHECK_NE(a,Vector3(1,3,3));
00479 CHECK_NE(a,Vector3(1,2,2));
00480
00481
00482 CHECK_EQ(-a,Vector3(-1,-2,-3));
00483
00484
00485 CHECK_EQ(a+b,Vector3(111,-218,333));
00486 CHECK_EQ(b+a,Vector3(111,-218,333));
00487 c=a;
00488 CHECK_EQ((c+=b),Vector3(111,-218,333));
00489
00490
00491 CHECK_EQ(a-b,Vector3(-109,222,-327));
00492 CHECK_EQ(b-a,Vector3(109,-222,327));
00493 c=a;
00494 CHECK_EQ((c-=b),Vector3(-109,222,-327));
00495
00496
00497 CHECK_EQ(a*(-10<<16),Vector3(-10,-20,-30));
00498 CHECK_EQ(a*(10<<16),Vector3(10,20,30));
00499 c=a;
00500 CHECK_EQ((c*=(-10<<16)),Vector3(-10,-20,-30));
00501 c=a;
00502 CHECK_EQ((c*=(10<<16)),Vector3(10,20,30));
00503
00504
00505 CHECK_EQ(b/(10<<16),Vector3(11,-22,33));
00506 CHECK_EQ(b/(-10<<16),Vector3(-11,22,-33));
00507 c=b;
00508 CHECK_EQ((c/=(10<<16)),Vector3(11,-22,33));
00509 c=b;
00510 CHECK_EQ((c/=(-10<<16)),Vector3(-11,22,-33));
00511
00512 TestLengthSquared();
00513 TestLength();
00514
00515
00516 CHECK_EQ(a.CompareLengths(b),-1);
00517 CHECK_EQ(a.CompareLengths(a),0);
00518 CHECK_EQ(b.CompareLengths(a),1);
00519 c=b;
00520 c.X+=1<<16;
00521 CHECK_EQ(b.CompareLengths(c),-1);
00522 CHECK_EQ(b.CompareLengths(b),0);
00523 CHECK_EQ(c.CompareLengths(b),1);
00524
00525 TestCompareLength();
00526 TestUnitVector();
00527
00528
00529 a = Vector3(1<<16,2<<16,3<<16);
00530 b = Vector3(5<<16,7<<16,11<<16);
00531 CHECK_EQ(a.DotProduct(b),(1*5+2*7+3*11)<<16);
00532
00533
00534 CHECK_EQ(a.CrossProduct(b),Vector3((2*11- 3*7)<<16, (3*5 - 1*11)<<16, (1*7 - 2*5)<<16 ));
00535
00536 TestNormal();
00537 TestAngle();
00538 TestPointNormal();
00539 TestPointAngle();
00540 TestTranslate();
00541 TestScale();
00542 TestMatrix3();
00543 }