From 7b727de312cd7e1507f24f0680b7d7b023548832 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Thu, 25 Mar 2021 18:55:24 +0100 Subject: [PATCH] [DEV] updates --- .checkstyle | 2 +- .classpath | 15 +- etk.iml | 22 + lib/spotbugs-annotations-4.2.2.jar | Bin 0 -> 15119 bytes src/module-info.java | 1 + src/org/atriasoft/etk/Color.java | 112 ++- src/org/atriasoft/etk/ThreadAbstract.java | 67 +- src/org/atriasoft/etk/Uri.java | 210 +++-- src/org/atriasoft/etk/math/FMath.java | 30 +- src/org/atriasoft/etk/math/Matrix3f.java | 551 ++++--------- src/org/atriasoft/etk/math/Matrix4f.java | 745 +++++++++--------- src/org/atriasoft/etk/math/Quaternion.java | 596 ++++---------- src/org/atriasoft/etk/math/Transform3D.java | 177 ++--- src/org/atriasoft/etk/math/Vector2b.java | 153 +--- src/org/atriasoft/etk/math/Vector2f.java | 482 ++++------- src/org/atriasoft/etk/math/Vector2i.java | 373 +++------ src/org/atriasoft/etk/math/Vector3f.java | 671 ++++++---------- src/org/atriasoft/etk/math/Vector3i.java | 407 ++++------ src/org/atriasoft/etk/theme/Theme.java | 108 +-- test/src/test/atriasoft/etk/TestBasicLog.java | 3 +- 20 files changed, 1743 insertions(+), 2982 deletions(-) create mode 100644 etk.iml create mode 100644 lib/spotbugs-annotations-4.2.2.jar diff --git a/.checkstyle b/.checkstyle index 34ed486..428926e 100644 --- a/.checkstyle +++ b/.checkstyle @@ -1,7 +1,7 @@ - + diff --git a/.classpath b/.classpath index d43dd0c..451e195 100644 --- a/.classpath +++ b/.classpath @@ -11,20 +11,25 @@ + + + + + + + + + + - - - - - diff --git a/etk.iml b/etk.iml new file mode 100644 index 0000000..a56a2fc --- /dev/null +++ b/etk.iml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/spotbugs-annotations-4.2.2.jar b/lib/spotbugs-annotations-4.2.2.jar new file mode 100644 index 0000000000000000000000000000000000000000..7d2a657911f5ce5bb0e8ccae70cc70dc177acfc9 GIT binary patch literal 15119 zcmbVTbzD{3)W34&ZYs@wGnsbf~kcWasgn)pDhk$?(1zivjkiUIHKp=pAD@v-1GRrDSu|h!r zej4~`Vdks?G~mf22ng&y4^$LYl9iHFQ)f|>3Jn)U>|#TgyzpPj#2d(vao=F;F~@8_=$vb2RTn(Q9?J<*e9`bKg(i4P00p_{Twto zEc+?@E-|sWz{AV6VN&zpXCeqDY18YmfdwveDbB)z**NHSozOgdRjg>YC;P`Vwj$c$ z<{QpMI|r~d;n>B7YIU_q-R!F)o`%8cSz4I0$}h4B>!RWa&&QkHqELn8+lV%1v3|b8 z@2l{~Qb2?LHZgYo%PRbN%=ZQSKE~O`_`i-r`qMZg$NxI?`@;TV5;WA*!q(W(+3dg1 zA^Q(=3~X)foD7^S>}>x!znSU*$_GSbHt2rYe__73xrvdLl%0c;v$Zvgk+p%Nqrb|K z644WE!GMSuGjY-uj2IY3{ioJNWdUp$kpa*&81R)MqZ^pWBxoN(CQq!GE?@hoPg}hu zQ_b&+IuzepFuJ+CNbjeGxOrBpU+DJ*Q4>0EuJCb>x>geOrWH5#^7N$Wq-CosW1y-& zZxxLeLTaIcGuKsLPUEnKB|FeAbKUJlQX8$_qeHe(8!?*vB{blfp^`M}bqt5llbE@a zS?%5yk?81MfrV(w&qShbbO0e#K51qa8s*!8Et+@Gn_ZeCXyv1~1*@cQfgPrm#uB`Y z4!wT!hX5tj(lt0&2jZM09 z>*&+rijMikhj%=*N~Ke~FFs}zuJKc1nT?>Hm6%1R;h8PfvbUCfHKXiKq=Mf+X_SY|*jQ7SRv6;8`G)4qC^j0c_r;HY0AKg(&N0NhEaDAaSq^H?akVqf)6q z30HpUL*vz{#dP#6ab9wT^=HQoGkYhU4`S003IgKkud=CX;^gdLt7%~EZ1OKgV^xQg z=0>qa)xl(UxNBuwRfv!>_W;IQv@{X(FNoqa>HntS7Urgiw0Ic9uJTMBA3m)D?fL zf)iwDA>ewD;&@1{)kvV8(0e~#96^IPHe(AQqzhtGrwe^wlBaPA{guGZL^j} zw2{V1Q#-LcwXrmaePk6w?A$chI0PPEJv;-xwQV|3UikJyhDP=h&OE@w0bo4b7O(Hq1>l zGe>F&*x*yt6Pgr0YNftXmA~gL9AbGMpU9EOGsh|eNlF?y^iDT|ft$)vZ*k68fvWn^ z^R{vw96!i(n)NVDhMcTqj73+$>rV&`$nD=KLz?n^rgjjm6*e8Z6inVHYAcHADo_uU*ZCf6;3-q&7Q`tiEl z16@F7T0ES^k6Ss58QxMp#LsPx%4nu)HpaAmT`r@sVxko>~^Vvx%)j1-Yv-8^W8CTN8#a={N{ZnqLBs z6EJDVOTRYEf%wYkbVZrA$Y}J^ezrC9W%>0w>|XNQr*#!NxpwGpAMg7>{k*)^eZIA3 zpk0**3jx9QE6ZzVYieO^Vr%rro>EtIoL9#d9E)O})rg*wCEo7=$j!|usd44{Pvp>$ zJ7cNPCKkRB4~V5;l#+~NuZ!UtK9bk(43OM|{5qaF$>saDy`$(=dDbADG3jAH{^8MXNc{#*F#~qWgS4_7J6GMV#MT|I!tAl#Ux6%Fa2)el9%vSF?o z*gQ|w73dpi$;yeW_8_&Al=vsIZMExfuFLl7U9*(*>b->FOUF@e+u8^(n{DThZOl~2 zsy{YZ3Cy8KBx$FsSeDq>3Yx=*%mwN&54|UTWB^ZBT^hTY9YD|a&>P`+PLRu*p;aVK z607y*=?JM!Q(HBGvunzdxK)34Fs701S41YQr0`O2`3t7@>|}$nGyeC}t9cvAKpS`F z;w^SJcG2_FvTn}@F+84m`z}goTvKFT)frBM@-0|s(}1|U>44gJ@&iWV7Ya2fIwhLQh#vZ|DM^Rdm6+Py zv=Jt;=x)hXNZ42LL?X9-Q&uv{bXab*2OF&vXX*XTvJWUZYnCjmpLNOZ2-z?4l}`0C zH2Al>JQH#gdL>_Gu}ED87$zB>!LW}sYPsfkxNq{uY<~D`H>)#} z(WNYbN$ETj{}AH#x>p%V;(3;i(3z0B!;Puf*S%+aM_2L#^H(WU!u^S6<7@jRDPh%- zJVc6SYt~Goqb5^4YO%|7v9ROAHtw%69Qg%15*ky<-;9`{E2Ax60|%)M1r%w7FK@``}3wXMb^0|1jWOpUyX?lCI(I>j(?4bit?bC7_b~#_wiGB5t$ph za0H1Cv|U2&O9P@KqUg(k-T^MG#9?dZ3-7z%tp>9XedS!Y7}U!h#Y~QG z4~V%P`+(0^eAs0yR%pOe=v*;p6c6ll1VzZ>inb6GPMx+_ zM)`=%%RetS3m_@J47AkIpg8#}k01#XQv+vfC((Z&Pk%ptMBB*|iK6$Vhsr9cSz#4h zl=>RJe^<9gek$3i3NOoGnA0hdd1>j$jldY+`l_Dsa{9UpZ6%N)wYn4OliPNnhW6($ug~unffGKFx~=hEueiGv63q={A2O_r6h+TX3ZO+3!z`KAw-b1{NL<^^CC@4- zONq1ZKSX@BgNczjJ?N9=yILAklJD4=A~HL}O0zMO)`?in*jRvZF(XT51L!(P`Aan~ zeMKZ5*&P?QL8r_2yxm@o=)cH*x-NHs2*2Sre0<0jzqJO?FCNfDMVxbQDDoctDXw-T{i!Guv1|kV9jy zChKOXY6LqJ6v1*)JVLOqt)%^!HNscr8tGQ6d-~`afMZ0s`m#Z;vgUmFfcs&1zs&dH z>I$ht+S+60=x9k?Bg2WZmJ&GKdRKg2+Y;FpXS)5lRv`)t=wC)iXrVJaV2^ro)jbu$ zNmDgZG;mo9_iY1dXgJ&mr}x7WBJsi3dU~feB7dKVODL1BHX<6e&Y_e5a;$HT7O9wr$k(MH@tk!eUg|K z5@_u1&F|Y!@k`aimaqKT8a-4CBwR-R`=?{8^`4V_&gbbIvp-j^#RV&u-ulVaj;K@<5S9^U7%A0cqxg*)=;!`f7tuFEo#2W@oS0|enmf}~&UkuQ za=?QQjAfb|>x6+>;Fx!ubCMRx=r98MM*3642VrWP)FB?t==NY9YRs@;#2v$jM+zys z#SnNQveo!$q$y{bft=!2%HS*PZ3p7s?V^5xTNo&u=;oCxw#dc9mmhDE{_GSJKv}s4 zkW-X`oI>J%bP9lhgMp2SlZnIM#EMKfb9&|)Y!7rlTu`ha14d*~scXEkjI2@Zo$gDM zc%R~2vn07T?eP(ATU;YV{H>z_M#aBl#lzjhH@pr!Yj;qr_|%;z@1_`}OYeo6mU22X0Y{V^lpXUlyp`1fva`v=l!1&WY`VDMjbvCm^|6Npm_kTRBp zbcUB4`L!1#$BwB`wDc73*9M$f2OkmIl|A~|GiK0}L=8ZmF#{?{as85KI9fQEDA{Ql zIM`a)n*ILRP*Ic@6U7!>cRkNFiNl$a%S;tKS`lI6yGkd-G)2O z&bkrv!UQ%Ztd6cOIF1Q^yE?mnw1QFpT)nDcbWMt^RaHp_GWSI*w-zJyV-r&cY`3}L zG-wBT<>oZhC1}E7GX9v=uDCeX{JELvSDW%CAw&ft&3*B2xRUwbm!d3X79ysKtQe32 zjmw2`2VBi}B6A_DU>Lf`p*=*)=RRWvt|7FExDWX(bo03najDrvSGtXC3dfn-T`nxn zgr{+?`W?P#P2MQzoRqfRetue#O1FV}HJ6R&S|ZT>h?{Z<@b1L zjrJXcjTbwAggOO$tVb^uC1XbR+#F7{8|5WUw>yM5c(t>(AUWCVFJe(DCJ%Y$VpgMW zMJ;ZEJ0WjmgL?sKBFygiIO6#EqzMX)=9~uEoy2G@f~iZSjEO=_k-9WZkgXNhJ@HT>Na(ghrxF0rDWB&`E|LW0{7f}dbxwiEIgo~C3Z zOB(jR)-^oQkOPW18Y&iPo#tQ(BGK0;z;iz38#t^8-3xuQP@DpgqY-Dau!$6q$~@P5 z{%kkgBaQY|bLl%h6=;U5+hc24p?LSRt!Ve0xYr^;EzQ{VSCMp2&}V={`z+PeT_hhA zzOJt%GoacJ^n9eTAEsnLMk>e(*ymr>_~M=Vkk8}*&EAdRlQIk z+)5^TJZcO%X56Uj$;FM+*3I?(B{W-)%G)>at?+@6i~S74j!mBepu>#5o^W%q4pJw6 z%spwU!c(gSlqmY0c}R`T?F^5{*2e1XD6Q<5ndYd}#q4TD*vAGEJXh|`?XckBARmL) z3aP>S08L_agmw)eNM)TxS4=yYoIjRX$(fD%x$GoOC^A$1``0%J=?sq*_L)}2_6FdyDN>IP zUMQCjr8?)*=63}ItZw=;pS)R3$V5lF6N@)3PS1ze@S9^%9T>>Qo1KXdXP^p?4g8#Y zI`XV13A1KWCTDxlgvr~$xC21?+-6Els8~W#Eb+Mlz9kXIz)}Rr`^7e6!*e3}B&jT{ zBLyTgPnKo2o!}mi88s|E1$jTd-1CQ3VXvTZ%8(8YYt3MC*1fu%1s zkI4Y%lpLQQ5u|hJd;;j_>cC7WZ@f&_H^mE5?~^E$b2i4DUEaQOF0D^QHZQYIKwP-9 zleFhdL*%JsFZZ%=4Uh~2n3?Z0ywMNWH8x5oaULLHRQ{;m8?fkF%_H!5Tw9?{jvn1y zsYLcHSl21bjQq+*DZvw#4GR&t> zpo^{!ev3zL-?k10-FH!*SDB5zO0G%o;Jwl{FsVCH^y z!*E}wFDjW0Hz6#^ll|J8V!i1W!yi)b1GN#uvq(nV1+PGd7=qM=>*x!LSxbbHTcQSc zS<`kVP@Cz)8EF-yRXHy`4g-%#%ySKb)DIk=UU*m4*}_q8+O}t|mGZcJ*mhLB3s7Py zm22hJo^l4tH;YEWZOysxm&Lc^kG{$G#Yyn?ajbR}l_fuFoC?^wu||YPJ|+p!>n?aj z+y!5h;@VhjPh#S=kH_%VUg45$r#l91GU1ra0N3%dYeRqsY zEDbPm#**1H=_%`m3}Ok@rx=E8EDgFPl#oIB=S2(HkcX80$F-bLdP|S)mD1)y6lCw1 zf!xz6WyGij#$H}jwO<^C)xU`;DiwJ;%Z9bgBW6Da_KD6cS~*S#AV8aSsm7wv%(mXeq{|b*78swfobur0)rIP3yikzgPe3S7B2a$CS;PxFbeKnXKWV)8ot`fXYjx) zZhVYIobhRoSH-4JZ=z9}<3mZ`v8GU?e>Kj{r=r%RR!In3a})*>#_!mNkVE48%^@k% zEH4M^WcG+H+1`XR@9hok?472_H^zloq$ldzbqjmCYAbZf2Wnkxhr8eCe57r=Mcg@H zONW$<*wA?%7@N{(;bU-VT36o+_`H$JJEW*6dMy(68S?=$5^tc}P($AY!w_LcK*0huQ+(RB=z~Ss`R%ms$b*R$TW+&{*MR&a5A7P)KjLw_B?k**k zhn?E?k*FLlWUat@9$oyFCH76EokG&k%Ul{P9>m9;lM~2-S9UAY6Eif%3HP!q8Tga2 z+2mgY^zh|v+#@e~8@~7El@11hd!b|{2r;aF2V1y!?`?!n8WAXfu@%k-fuG}jrjEwC zL{=)Ev1g^=G#Ym9`jUNBFLql~5<z}GmQ@qwqafkZ8 z;f6N{61jb$pf%0pYdyYq=noMElbAJd(B1lui4W+Hkq+5V#H3bmM2Jct`V?P0VfjVYQdvMN? z&t|8l+!n(v`3{@tWAK{r4rjN#1h!JlmhaAP=9M8FWvC;izH~i7wl5DMYiHk~4oDTVU-D@o^keNnSQU_Sg zTvT}j3c0m*?K^mrkSA5X$oY54wJNlFvNvVgyr|9k|f z{2mz!FC|N=J}|M2*wDq z;!_p+@HLH*SCT^bpM8;5mxA|Z@4DUIl7{w129ACq5XiM$%+Tmk$+gL|wpV6MtU2&% zUSia!omF`0#Lf4-kj3GntLlk-^{LU>1SvlkI;2!ir_*?ukM_c}<3Rgz>t|wb7Rjv0C=r@RC2+(PVy94c_`Cdtq zxAoR-2nu}2_EiF#LEe6stLbZlb%toR^GFSsS{c!J<=u+!)ugN~H}IEcw$0uJnh`$= z_H&S=+ZG$%3NEJjY%=x=lxwo@0xVrZ|0e-4R!8QXG%Bx$QPbjD&=immV#wP>HaL2zNYr z(~j#OjcnHa(J=0P?TY_60h&#&lgrR}y1C8^1C2sbV}_Ro1Wk<`nz;=30R&2c**2;`*vCg<&8E^=$%#*+^w3ZgG<&um6X z**;`QPUkIXle~dTZ+g5thxGb2M6>YgP7-^5F031#jC%R(CV?PvV(`k%hJ!p$JZOmv zK~DcGTCP8q8ElbNb?heDumzXqOi1^mZP@f*pR?Jp4w1MepX*N`(?AwRRUn)_YAn=l zlv`w|qy1Wb+<`U|p41@ar&)j*=jC*G+<4LR+1>5-7^{Q71@(x%qZlF(d4ykucd)|M zVNNz+P3djy_#3wR+KD$v0XAi4Gl<1~P1HAC8gT~R+aVg>8uxhwF3L(?zq|Hq+ zT16+gjmZj@7Q>|lT(ZN7tQ0Epn2ICD;j3hhb48IYDpJmjyw2RnfgCJrhoaBkd5|#^ zkcs#{D$NH)H#&SHHpw_MCUOVGooR;fxwf(G>*L0%HW{W{7#wX6W_(*lQipXSo{{&l{;(*>iXYmT(o>Ny6QCT{n%UBx@b=L(xMpG8t_n7%s5pJf-cuWlE z_UIP!=N)AX<%RbKM0GKU>R+jOYuH-Z+PVIg7u$k1*6;C5MMoJMq{H+#kp^6$10IET zK-rDs>4hjmA=|I>yst(QxD;usj?W$6Nl4v+^bLjcfe;RMlYfW)*eH4_JjGFYesaEf zj|hUa5_84obuPpZq*`hh3dbBMsNtgSH!`zWuZ2{q$7!2c=0L}(nlYwMX0kYs0nBYw z3gz(Xu%EpblqNKRQ@w-Tu#Id?v6j3WgFM{h)!`xr^j`MJ5cKz#fBr@RN|8O!q6OT` zaeA8}N9=JL|zFr-RuMZAfbA!hi6ro=7 zudksx*maHd^_RLJNfPn7k7v5raBJ-+@GI$dwu5OcLM+;2q%?2xY0{oh)z@7tcn8c@ z6-X;hmGJAX5X)$kONMr=%GHXIe27C#aSas1AsC)ea`wF$p?RaivZLgfr^?X2=tQu& zbb%Dbx9LL#86eg+?iyYBu?Q(3vP#{M*7B2tXZmNarYA-Y;|2dbie%U+mkv=2g30Dp7iq#kTIdsd0)`2VaF6tOZxj`y)CB21coyzMKUJgv`B- z8Q7EXnEuv0!s_Y4tugiTYxp4{M#X~W)OkgT` zBy1FCEK9^Y_pzh*X<4CG9?^X^FUoNO5`FMz2UZ(H`5UZ^ptGO$)eIWO7+h9~&GC)d z(XR=lv7VyOls-marP5(+J#_5e5(TvEHtR|;m$81-M4MzaDB0qKdVTxsvso=^>Qs{x z40}Tu0^34{c~XmzCfq&;>}cer1V*=FRUuD&_BAn0^VtyoJG;`7Cl4@#j`&SJE2?+Q zRp;pp3ac(D`C8(dluYEJX!@h93aRAIC(1X*%FRKZNqh(WT$3{Eq6*Kty~xO~W7;|k zOhGO%RJsWfl!hH=YkUoOMhWgK{e~_PoKIjl%MZf?4_d5XK)4<;W_&)giCkIFm`u_K{ zKfMtEZsGfA(B}B<^Ic>AuMaxJohTA05`LGy|F;?6756`8u>L;dyZ-*a&HApt|1nGJ zPqRQ0`~NoayBhz;M8BUW{#%>>-z<>*VF0wYccS0*5Pzrc|Fcpb+#0x2{||#T!1G_Q z_E+6LxP5T#_z(L%peFr4{kOl_|I@kqUx5r916-v11EU?33jZU<-%FOkLBOTDKR`&} zegOnbxC?F_TvPbN`Xp#q{o^hCy}}S21YAk?14In@pF#d2s``5}z_nUGKqOKB2M{pj z7WgfJ%Yc5MJwyNB(0&pHfy03dOn$)GVE%7#;BpgiL~!B455z!F`1mKskTCfh83Q;3 zc%S_T1V8StLj2Tt1P1``7XJYFg!c;o|FL%rjsxB^{eibx7S<2rX2ic@{7(%naMR$Ol^>=VNq)ifPkk0}+u*hSAGXg(|Jn9`s{Dha zfS0d-pu8jhXOzDdv%&3y*G_-fx1#(7`#)7u!EJ-rnSR(#ruk>ve|q};=c*GpBzQ69 z2P8e+KSTbJ^MjXGz)`?!2|rLGK NAMED_COLORS = Map.ofEntries( - //@formatter:off + private static final Map NAMED_COLORS = Map.ofEntries( + //@formatter:off Map.entry("none", NONE), Map.entry("aliceblue", ALICE_BLUE), Map.entry("antiquewhite", ANTIQUE_WHITE), @@ -177,7 +184,7 @@ public class Color { Map.entry("coral", CORAL), Map.entry("cornflowerblue", CORNFLOWER_BLUE), Map.entry("cornsilk", CORNSILK), - Map.entry("crimson", CRIMSON), + Map.entry("crimson", CRIMSON), Map.entry("cyan", CYAN), Map.entry("darkblue", DARK_BLUE), Map.entry("darkcyan", DARK_CYAN), @@ -186,11 +193,11 @@ public class Color { Map.entry("darkgrey", DARK_GREY), Map.entry("darkgreen", DARK_GREEN), Map.entry("darkkhaki", DARK_KHAKI), - Map.entry("darkmagenta", DARK_MAGENTA), + Map.entry("darkmagenta", DARK_MAGENTA), Map.entry("darkolivegreen", DARK_OLIVEGREEN), Map.entry("darkorange", DARK_ORANGE), Map.entry("darkorchid", DARK_ORCHID), - Map.entry("darkred", DARK_RED), + Map.entry("darkred", DARK_RED), Map.entry("darksalmon", DARK_SALMON), Map.entry("darkseagreen", DARK_SEAGREEN), Map.entry("darkslateblue", DARK_SLATE_BLUE), @@ -199,14 +206,14 @@ public class Color { Map.entry("darkturquoise", DARK_TURQUOISE), Map.entry("darkviolet", DARK_VIOLET), Map.entry("deeppink", DEEP_PINK), - Map.entry("deepskyblue", DEEP_SKY_BLUE), - Map.entry("dimgray", DIM_GRAY), - Map.entry("dimgrey", DIM_GREY), + Map.entry("deepskyblue", DEEP_SKY_BLUE), + Map.entry("dimgray", DIM_GRAY), + Map.entry("dimgrey", DIM_GREY), Map.entry("dodgerblue", DODGER_BLUE), Map.entry("firebrick", FIRE_BRICK), - Map.entry("floralwhite", FLORAL_WHITE), - Map.entry("forestgreen", FOREST_GREEN), - Map.entry("fuchsia", FUCHSIA), + Map.entry("floralwhite", FLORAL_WHITE), + Map.entry("forestgreen", FOREST_GREEN), + Map.entry("fuchsia", FUCHSIA), Map.entry("gainsboro", GAINSBORO), Map.entry("ghostwhite", GHOST_WHITE), Map.entry("gold", GOLD), @@ -214,9 +221,9 @@ public class Color { Map.entry("gray", GRAY), Map.entry("grey", GREY), Map.entry("green", GREEN), - Map.entry("greenyellow", GREEN_YELLOW), + Map.entry("greenyellow", GREEN_YELLOW), Map.entry("honeydew", HONEY_DEW), - Map.entry("hotpink", HOT_PINK), + Map.entry("hotpink", HOT_PINK), Map.entry("indianred", INDIAN_RED), Map.entry("indigo", INDIGO), Map.entry("ivory", IVORY), @@ -233,34 +240,34 @@ public class Color { Map.entry("lightgrey", LIGHT_GREY), Map.entry("lightgreen", LIGHT_GREEN), Map.entry("lightpink", LIGHT_PINK), - Map.entry("lightsalmon", LIGHT_SALMON), + Map.entry("lightsalmon", LIGHT_SALMON), Map.entry("lightseagreen", LIGHT_SEA_GREEN), Map.entry("lightskyblue", LIGHT_SKY_BLUE), Map.entry("lightslategray", LIGHT_SLATE_GRAY), Map.entry("lightslategrey", LIGHT_SLATE_GREY), Map.entry("lightsteelblue", LIGHT_STEEL_BLUE), - Map.entry("lightyellow", LIGHT_YELLOW), + Map.entry("lightyellow", LIGHT_YELLOW), Map.entry("lime", LIME), Map.entry("limegreen", LIME_GREEN), Map.entry("linen", LINEN), - Map.entry("magenta", MAGENTA), + Map.entry("magenta", MAGENTA), Map.entry("maroon", MAROON), Map.entry("mediumaquamarine", MEDIUM_AQUA_MARINE), Map.entry("mediumblue", MEDIUM_BLUE), Map.entry("mediumorchid", MEDIUM_ORCHID), Map.entry("mediumpurple", MEDIUM_PURPLE), Map.entry("mediumseagreen", MEDIUM_SEA_GREEN), - Map.entry("mediumslateblue", MEDIUM_SLATE_BLUE), + Map.entry("mediumslateblue", MEDIUM_SLATE_BLUE), Map.entry("mediumspringgreen", MEDIUM_SPRING_GREEN), - Map.entry("mediumturquoise", MEDIUM_TURQUOISE), - Map.entry("mediumvioletred", MEDIUM_VIOLET_RED), + Map.entry("mediumturquoise", MEDIUM_TURQUOISE), + Map.entry("mediumvioletred", MEDIUM_VIOLET_RED), Map.entry("midnightblue", MIDNIGHT_BLUE), Map.entry("mintcream", MINT_CREAM), Map.entry("mistyrose", MISTY_ROSE), Map.entry("moccasin", MOCCASIN), - Map.entry("navajowhite", NAVAJO_WHITE), + Map.entry("navajowhite", NAVAJO_WHITE), Map.entry("navy", NAVY), - Map.entry("oldlace", OLDLACE), + Map.entry("oldlace", OLDLACE), Map.entry("olive", OLIVE), Map.entry("olivedrab", OLIVE_DRAB), Map.entry("orange", ORANGE), @@ -277,26 +284,26 @@ public class Color { Map.entry("plum", PLUM), Map.entry("powderblue", POWDER_BLUE), Map.entry("purple", PURPLE), - Map.entry("red", RED), + Map.entry("red", RED), Map.entry("rosybrown", ROSY_BROWN), Map.entry("royalblue", ROYAL_BLUE), - Map.entry("saddlebrown", SADDLE_BROWN), + Map.entry("saddlebrown", SADDLE_BROWN), Map.entry("salmon", SALMON), Map.entry("sandybrown", SANDY_BROWN), Map.entry("seagreen", SEA_GREEN), Map.entry("seashell", SEA_SHELL), Map.entry("sienna", SIENNA), Map.entry("silver", SILVER), - Map.entry("skyblue", SKY_BLUE), + Map.entry("skyblue", SKY_BLUE), Map.entry("slateblue", SLATE_BLUE), Map.entry("slategray", SLATE_GRAY), Map.entry("slategrey", SLATE_GREY), Map.entry("snow", SNOW), - Map.entry("springgreen", SPRING_GREEN), + Map.entry("springgreen", SPRING_GREEN), Map.entry("steelblue", STEEL_BLUE), - Map.entry("tan", TAN), + Map.entry("tan", TAN), Map.entry("teal", TEAL), - Map.entry("thistle", THISTLE), + Map.entry("thistle", THISTLE), Map.entry("tomato", TOMATO), Map.entry("turquoise", TURQUOISE), Map.entry("violet", VIOLET), @@ -304,7 +311,7 @@ public class Color { Map.entry("white", WHITE), Map.entry("whitesmoke", WHITE_SMOKE), Map.entry("yellow", YELLOW), - Map.entry("yellowgreen", YELLOW_GREEN) + Map.entry("yellowgreen", YELLOW_GREEN) //@formatter:on ); @@ -315,46 +322,45 @@ public class Color { public static Color valueOf(final String colorBase) throws Exception { // remove all white space... String color = colorBase.replace(" \r\n\t\\(\\)", ""); - if (color.isEmpty() == true) { + if (color.isEmpty()) { return new Color(0, 0, 0, 1.0f); } final Color named = get(colorBase); if (named != null) { - return named.clone(); + return named; } else if (color.charAt(0) == '#') { // MODEL: #RGB // #RGBA // #RRGGBB // #RRGGBBAA switch (color.length()) { - case 4: { + case 4 -> { final float r = Integer.parseInt(color.substring(1, 2), 16) * 255.0f * 16.0f; final float g = Integer.parseInt(color.substring(2, 3), 16) * 255.0f * 16.0f; final float b = Integer.parseInt(color.substring(3, 4), 16) * 255.0f * 16.0f; return new Color(r, g, b); } - case 5: { + case 5 -> { final float r = Integer.parseInt(color.substring(1, 2), 16) * 255.0f * 16.0f; final float g = Integer.parseInt(color.substring(2, 3), 16) * 255.0f * 16.0f; final float b = Integer.parseInt(color.substring(3, 4), 16) * 255.0f * 16.0f; final float a = Integer.parseInt(color.substring(4, 5), 16) * 255.0f * 16.0f; return new Color(r, g, b, a); } - case 7: { + case 7 -> { final float r = Integer.parseInt(color.substring(1, 3), 16) * 255.0f; final float g = Integer.parseInt(color.substring(3, 5), 16) * 255.0f; final float b = Integer.parseInt(color.substring(5, 7), 16) * 255.0f; return new Color(r, g, b); } - case 9: { + case 9 -> { final float r = Integer.parseInt(color.substring(1, 3), 16) * 255.0f; final float g = Integer.parseInt(color.substring(3, 5), 16) * 255.0f; final float b = Integer.parseInt(color.substring(5, 7), 16) * 255.0f; final float a = Integer.parseInt(color.substring(7, 9), 16) * 255.0f; return new Color(r, g, b, a); } - default: - throw new Exception("Can not parse color ... '" + colorBase + "'"); + default -> throw new Exception("Can not parse color ... '" + colorBase + "'"); } } else { // Model: r.r,g.g,b.b @@ -364,7 +370,7 @@ public class Color { // rgb(r.r,g.g,b.b) // rgba(r.r,g.g,b.b,a.a) // argb(a.a,r.r,g.g,b.b) - if (color.startsWith("argb") == true) { + if (color.startsWith("argb")) { color = color.replace("argb", ""); final String[] vals = color.split(","); if (vals.length == 4) { @@ -397,17 +403,8 @@ public class Color { } } - public float r; - public float g; - public float b; - public float a; - public Color(final float r, final float g, final float b) { - super(); - this.r = r; - this.g = g; - this.b = b; - this.a = 1.0f; + this(r, g, b, 1.0f); } public Color(final float r, final float g, final float b, final float a) { @@ -417,23 +414,6 @@ public class Color { this.a = a; } - @Override - public Color clone() { - return new Color(this.r, this.g, this.b, this.a); - } - - @Override - public boolean equals(final Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof Color)) { - return false; - } - final Color other = (Color) obj; - return other.r == this.r && other.g == this.g && other.b == this.b && other.a == this.a; - } - @Override public String toString() { return "rgba(" + this.r + ", " + this.g + ", " + this.b + ", " + this.a + ")"; diff --git a/src/org/atriasoft/etk/ThreadAbstract.java b/src/org/atriasoft/etk/ThreadAbstract.java index adba966..248f0ec 100644 --- a/src/org/atriasoft/etk/ThreadAbstract.java +++ b/src/org/atriasoft/etk/ThreadAbstract.java @@ -5,57 +5,62 @@ public abstract class ThreadAbstract { private boolean threadStopRequested = false; private Thread threadInstance = null; private final String threadName; - public ThreadAbstract(String name) { + + public ThreadAbstract(final String name) { this.threadName = name; } - + + protected abstract void birth(); + + protected abstract void death(); + + protected abstract void runPeriodic(); + + private void threadRun() { + System.out.println("INFO: Thread Start: " + this.threadName); + birth(); + while (!this.threadStopRequested) { + try { + runPeriodic(); + } catch (Exception eee) { + eee.printStackTrace(); + } + } + death(); + System.out.println("INFO: Thread Stop: " + this.threadName); + } + public void threadStart() { System.out.println("INFO: Start the thread : " + this.threadName); - if (threadInstance != null) { + if (this.threadInstance != null) { threadStop(); } - threadStopRequested = false; - threadInstance = new Thread() { + this.threadStopRequested = false; + this.threadInstance = new Thread() { + @Override public void run() { threadRun(); } }; - threadInstance.setName(threadName); - threadInstance.start(); + this.threadInstance.setName(this.threadName); + this.threadInstance.start(); } - private void threadRun() { - System.out.println("INFO: Thread Start: " + threadName); - birth(); - while (threadStopRequested == false) { - try { - runPeriodic(); - } catch (Exception eee) { - eee.printStackTrace(); - } - } - death(); - System.out.println("INFO: Thread Stop: " + threadName); - } - protected abstract void birth(); - protected abstract void runPeriodic(); - protected abstract void death(); - public void threadStop() { - if (threadStopRequested == true) { + if (this.threadStopRequested) { return; } - threadStopRequested = true; - if (threadInstance == null) { + this.threadStopRequested = true; + if (this.threadInstance == null) { return; } - threadInstance.interrupt(); + this.threadInstance.interrupt(); try { - threadInstance.join(); + this.threadInstance.join(); } catch (InterruptedException eee) { // nothing to do } - threadInstance = null; + this.threadInstance = null; } - + } diff --git a/src/org/atriasoft/etk/Uri.java b/src/org/atriasoft/etk/Uri.java index b5cd497..fdaae88 100644 --- a/src/org/atriasoft/etk/Uri.java +++ b/src/org/atriasoft/etk/Uri.java @@ -2,6 +2,7 @@ package org.atriasoft.etk; import java.io.IOException; import java.io.InputStream; +import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -10,17 +11,32 @@ import java.util.Map; import org.atriasoft.etk.internal.Log; public class Uri { + private record LibraryElement( + Class klass, + String basePath) {}; + private static Map genericMap = new HashMap<>(); - private static Map> libraries = new HashMap<>(); + private static Map libraries = new HashMap<>(); private static Class applicationClass = null; + private static String applicationBasePath = ""; static { - genericMap.put("DATA", ""); + genericMap.put("DATA", "data/"); genericMap.put("THEME_GUI", "theme/"); } - public static void addLibrary(final String libName, final Class classHandle) { - libraries.put(libName.toLowerCase(), classHandle); + public static void addLibrary(final String libName, final Class classHandle, String basePath) { + Log.info("Add library reference: lib=" + libName + " ==> " + classHandle.getCanonicalName() + " base path=" + basePath); + if (basePath == null || basePath.isEmpty()) { + basePath = "/"; + } + if (basePath.charAt(basePath.length() - 1) != '/') { + basePath += "/"; + } + if (basePath.charAt(0) != '/') { + basePath = "/" + basePath; + } + libraries.put(libName.toLowerCase(), new LibraryElement(classHandle, basePath)); } public static byte[] getAllData(final Uri resourceName) { @@ -39,67 +55,73 @@ public class Uri { } /* - public static Stream getResources(final URL element) { - try { - final URI uri = element.toURI(); - FileSystem fs; - Path path; - if (uri.getScheme().contentEquals("jar")) { - try { - fs = FileSystems.getFileSystem(uri); - } catch (final FileSystemNotFoundException e) { - fs = FileSystems.newFileSystem(uri, Collections. emptyMap()); - } - String pathInJar = "/"; - final String tmpPath = element.getPath(); - final int idSeparate = tmpPath.indexOf('!'); - if (idSeparate != -1) { - pathInJar = tmpPath.substring(idSeparate + 1); - while (pathInJar.startsWith("/")) { - pathInJar = pathInJar.substring(1); - } - } - path = fs.getPath(pathInJar); - } else { - fs = FileSystems.getDefault(); - path = Paths.get(uri); - } - return Files.walk(path, 1); - } catch (URISyntaxException | IOException e) { - e.printStackTrace(); - return Stream.of(); - } - } - */ - public static InputStream getStream(final Uri resourceName) { - Log.verbose("Load resource: " + resourceName); - String offset = ""; - if (resourceName.group != null) { - final String ret = genericMap.get(resourceName.group); + * public static Stream getResources(final URL element) { try { final URI + * uri = element.toURI(); FileSystem fs; Path path; if + * (uri.getScheme().contentEquals("jar")) { try { fs = + * FileSystems.getFileSystem(uri); } catch (final FileSystemNotFoundException e) + * { fs = FileSystems.newFileSystem(uri, Collections. + * emptyMap()); } String pathInJar = "/"; final String tmpPath = + * element.getPath(); final int idSeparate = tmpPath.indexOf('!'); if + * (idSeparate != -1) { pathInJar = tmpPath.substring(idSeparate + 1); while + * (pathInJar.startsWith("/")) { pathInJar = pathInJar.substring(1); } } path = + * fs.getPath(pathInJar); } else { fs = FileSystems.getDefault(); path = + * Paths.get(uri); } return Files.walk(path, 1); } catch (URISyntaxException | + * IOException e) { e.printStackTrace(); return Stream.of(); } } + */ + public static InputStream getStream(final Uri uri) { + Log.warning("Load resource: " + uri); + String offsetGroup = ""; + if (uri.group != null) { + Log.warning(" find group: " + uri.group); + final String ret = genericMap.get(uri.group); if (ret != null) { - offset = ret; + Log.warning(" ==> " + ret); + offsetGroup = ret; } } InputStream out = null; if (applicationClass == null) { - Log.warning("Application data class is not defined ..."); + Log.warning(" !! Application data class is not defined ..."); } else { - out = applicationClass.getResourceAsStream("/data/" + offset + resourceName.path); - } - if (out != null) { - // search in the libraries ... - if (resourceName.lib == null) { - return null; - } else { - final Class libClass = libraries.get(resourceName.lib); - if (libClass == null) { - return null; - } - out = libClass.getResourceAsStream("/data/" + offset + resourceName.path); + String tmpPath = applicationBasePath + offsetGroup + uri.path; + Log.info("(appl) Try to load '" + tmpPath + "' in " + applicationClass.getCanonicalName()); + URL realFileName = applicationClass.getClassLoader().getResource(tmpPath); + if (realFileName != null) { + Log.info("(appl) >>> " + realFileName.getFile()); + } + out = applicationClass.getResourceAsStream(tmpPath); + + if (out == null) { + Log.info("(appl) ==> element does not exist ..."); } } if (out == null) { - Log.error("Can not load resource: '" + resourceName + "'"); + // search in the libraries ... + if (uri.lib == null) { + Log.warning(" !! No library specified"); + return null; + } else { + LibraryElement libraryElement = libraries.get(uri.lib); + if (libraryElement == null) { + Log.warning(" Can not get element in library"); + return null; + } + String tmpPath = libraryElement.basePath + offsetGroup + uri.path; + Log.info("(lib) Try to load '" + tmpPath + "' in " + libraryElement.klass.getCanonicalName()); + URL realFileName = libraryElement.klass.getClassLoader().getResource(tmpPath); + if (realFileName != null) { + Log.info("(lib) >>> " + realFileName.getFile()); + } + out = libraryElement.klass.getResourceAsStream(tmpPath); + if (out == null) { + Log.info("(lib) ==> element does not exist ..."); + } + } + } + if (out == null) { + Log.error("Can not load resource: '" + uri + "'"); + } else { + Log.warning(" =====> DATA LOADED <====== "); } return out; } @@ -109,40 +131,59 @@ public class Uri { return out; } - public static void setApplication(final Class classHandle) { + public static void setApplication(final Class classHandle, String basePath) { + Log.info("Set application reference : " + classHandle.getCanonicalName() + " base path=" + basePath); applicationClass = classHandle; + if (basePath == null || basePath.isEmpty()) { + basePath = "/"; + } + if (basePath.charAt(basePath.length() - 1) != '/') { + basePath += "/"; + } + if (basePath.charAt(0) != '/') { + basePath = "/" + basePath; + } + applicationBasePath = basePath; } - public static void setGroup(final String groupName, final String basePath) { + public static void setGroup(final String groupName, String basePath) { + Log.info("Set Group : " + groupName + " base path=" + basePath); + if (basePath == null || basePath.isEmpty()) { + basePath = "/"; + } + if (basePath.charAt(basePath.length() - 1) != '/') { + basePath += "/"; + } genericMap.put(groupName.toUpperCase(), basePath); } + public static Uri valueOf(String value) { + String group = null; + String path = null; + String lib = null; + if (value.contains(":")) { + final String[] ret = value.split(":", 2); + group = ret[0].toUpperCase(); + value = ret[1]; + } else { + group = "DATA"; + } + if (value.contains("?lib=")) { + final String[] ret = value.split("\\?lib=", 2); + path = ret[0]; + lib = ret[1].toLowerCase(); + } else { + path = value; + } + return new Uri(group, path, lib); + } + private final String group; private final String path; private final String lib; - // Format : DATA:jlfqkjsdflkjqs/sqldkhjflqksdjf/lll.png?lib=ewol - public Uri(String value) { - if (value.contains(":") == true) { - final String[] ret = value.split(":", 2); - this.group = ret[0].toUpperCase(); - ; - value = ret[1]; - } else { - this.group = "DATA"; - } - if (value.contains("?lib=") == true) { - final String[] ret = value.split("?lib=", 2); - this.path = ret[0]; - this.lib = ret[1].toLowerCase(); - } else { - this.path = value; - this.lib = null; - } - } - public Uri(final String group, final String path) { this(group, path, null); } @@ -194,4 +235,17 @@ public class Uri { } return out; } + + // Format : DATA:jlfqkjsdflkjqs/sqldkhjflqksdjf/lll.png?lib=ewol + public Uri withGroup(final String group) { + return new Uri(group, this.path, this.lib); + } + + public Uri withLib(final String lib) { + return new Uri(this.group, this.path, lib); + } + + public Uri withPath(final String path) { + return new Uri(this.group, path, this.lib); + } } diff --git a/src/org/atriasoft/etk/math/FMath.java b/src/org/atriasoft/etk/math/FMath.java index 580a1a3..30c0faf 100644 --- a/src/org/atriasoft/etk/math/FMath.java +++ b/src/org/atriasoft/etk/math/FMath.java @@ -3,6 +3,8 @@ package org.atriasoft.etk.math; import java.text.DecimalFormat; public class FMath { + public static final float PI = (float) Math.PI; + public static float abs(final float a) { if (a < 0.0f) { return -a; @@ -12,6 +14,7 @@ public class FMath { /** * Test if the value id in the correct range + * * @param a fist value * @param b second value (a-b) * @return true if it is in the range @@ -22,8 +25,9 @@ public class FMath { /** * Test if the value id in the correct range - * @param a fist value - * @param b second value (a-b) + * + * @param a fist value + * @param b second value (a-b) * @param epsilon delta to check * @return true if it is in the range */ @@ -32,6 +36,10 @@ public class FMath { return (abs(difference) < epsilon); } + public static float atan(final float value) { + return (float) Math.atan(value); + } + public static float atan2(final float sinHalfAngleAbs, final float cosHalfAngle) { return (float) Math.atan2(sinHalfAngleAbs, cosHalfAngle); } @@ -59,6 +67,10 @@ public class FMath { return FMath.min(FMath.max(value, lowerLimit), upperLimit); } + public static float cos(final float value) { + return (float) Math.cos(value); + } + public static String floatToString(final float value) { return new DecimalFormat("#0.0000000000").format(value); } @@ -89,7 +101,7 @@ public class FMath { } public static Vector3f max(final Vector3f a, final Vector3f b) { - return new Vector3f(Math.max(a.x, b.x), Math.max(a.y, b.y), Math.max(a.z, b.z)); + return new Vector3f(Math.max(a.x(), b.x()), Math.max(a.y(), b.y()), Math.max(a.z(), b.z())); } public static float min(final float a, final float b) { @@ -113,7 +125,7 @@ public class FMath { } public static Vector3f min(final Vector3f a, final Vector3f b) { - return new Vector3f(Math.min(a.x, b.x), Math.min(a.y, b.y), Math.min(a.z, b.z)); + return new Vector3f(Math.min(a.x(), b.x()), Math.min(a.y(), b.y()), Math.min(a.z(), b.z())); } public static float mod(final float value, final float modulo) { @@ -131,7 +143,17 @@ public class FMath { return a * b >= 0.0f; } + public static float sin(final float value) { + return (float) Math.sin(value); + } + public static float sqrt(final float value) { return (float) Math.sqrt(value); } + + public static float tan(final float value) { + return (float) Math.tan(value); + } + + private FMath() {} } diff --git a/src/org/atriasoft/etk/math/Matrix3f.java b/src/org/atriasoft/etk/math/Matrix3f.java index b207830..f829c4e 100644 --- a/src/org/atriasoft/etk/math/Matrix3f.java +++ b/src/org/atriasoft/etk/math/Matrix3f.java @@ -1,92 +1,75 @@ package org.atriasoft.etk.math; -public class Matrix3f { +import edu.umd.cs.findbugs.annotations.CheckReturnValue; + +@SuppressWarnings("preview") +public record Matrix3f( + float a1, + float a2, + float a3, + float b1, + float b2, + float b3, + float c1, + float c2, + float c3) { + /** - * @brief create a skew-symmetric matrix using a given vector that can be used to compute cross product with another vector using matrix multiplication + * create a skew-symmetric matrix using a given vector that can be used to compute cross product with another vector using matrix multiplication * @param vector Vector to comute * @return Matrix to compute */ public static Matrix3f computeSkewSymmetricMatrixForCrossProduct(final Vector3f vector) { - return new Matrix3f(0.0f, -vector.z, vector.y, vector.z, 0.0f, -vector.x, -vector.y, vector.x, 0.0f); + return new Matrix3f(0.0f, -vector.z(), vector.y(), vector.z(), 0.0f, -vector.x(), -vector.y(), vector.x(), 0.0f); } /** - * @brief Create a matrix 3D with a simple rotation + * Create a matrix 3D with a simple rotation * @param normal vector aroud witch apply the rotation * @param angleRad Radian angle to set at the matrix * @return New matrix of the transformation requested */ public static Matrix3f createMatrixRotate(final Vector3f normal, final float angleRad) { - final Matrix3f tmp = new Matrix3f(); final float cosVal = (float) Math.cos(angleRad); final float sinVal = (float) Math.sin(angleRad); final float invVal = 1.0f - cosVal; // set rotation : - tmp.mat[0] = normal.x * normal.x * invVal + cosVal; - tmp.mat[1] = normal.x * normal.y * invVal - normal.z * sinVal; - tmp.mat[2] = normal.x * normal.z * invVal + normal.y * sinVal; + float a1 = normal.x() * normal.x() * invVal + cosVal; + float a2 = normal.x() * normal.y() * invVal - normal.z() * sinVal; + float a3 = normal.x() * normal.z() * invVal + normal.y() * sinVal; - tmp.mat[3] = normal.y * normal.x * invVal + normal.z * sinVal; - tmp.mat[4] = normal.y * normal.y * invVal + cosVal; - tmp.mat[5] = normal.y * normal.z * invVal - normal.x * sinVal; + float b1 = normal.y() * normal.x() * invVal + normal.z() * sinVal; + float b2 = normal.y() * normal.y() * invVal + cosVal; + float b3 = normal.y() * normal.z() * invVal - normal.x() * sinVal; - tmp.mat[6] = normal.z * normal.x * invVal - normal.y * sinVal; - tmp.mat[7] = normal.z * normal.y * invVal + normal.x * sinVal; - tmp.mat[8] = normal.z * normal.z * invVal + cosVal; - return tmp; + float c1 = normal.z() * normal.x() * invVal - normal.y() * sinVal; + float c2 = normal.z() * normal.y() * invVal + normal.x() * sinVal; + float c3 = normal.z() * normal.z() * invVal + cosVal; + return new Matrix3f(a1, a2, a3, b1, b2, b3, c1, c2, c3); } /** - * @brief create a Identity matrix + * create a Identity matrix * @return created new matrix */ - public static Matrix3f identity() { - return new Matrix3f(1, 0, 0, 0, 1, 0, 0, 0, 1); - } + public static final Matrix3f IDENTITY = new Matrix3f(1, 0, 0, 0, 1, 0, 0, 0, 1); /** - * @brief create a ZERO matrix + * create a ZERO matrix * @return created new matrix */ - public static Matrix3f zero() { - return new Matrix3f(0, 0, 0, 0, 0, 0, 0, 0, 0); - } - - public float[] mat = new float[3 * 3]; //!< matrix data + public static final Matrix3f ZERO = new Matrix3f(0, 0, 0, 0, 0, 0, 0, 0, 0); /** - * @brief Constructor that load zero matrix - */ - public Matrix3f() { - this.mat[0] = 0.0f; - this.mat[1] = 0.0f; - this.mat[2] = 0.0f; - this.mat[3] = 0.0f; - this.mat[4] = 0.0f; - this.mat[5] = 0.0f; - this.mat[6] = 0.0f; - this.mat[7] = 0.0f; - this.mat[8] = 0.0f; - } - - /** - * @brief Configuration constructorwith single value. + * Configuration constructorwith single value. * @param value single value */ public Matrix3f(final float value) { - this.mat[0] = value; - this.mat[1] = value; - this.mat[2] = value; - this.mat[3] = value; - this.mat[4] = value; - this.mat[5] = value; - this.mat[6] = value; - this.mat[7] = value; - this.mat[8] = value; + this(value, value, value, value, value, value, value, value, value); } /** - * @brief Configuration constructor. + * Configuration constructor. * @param a1 element 0x0 * @param a2 element 0x1 * @param a3 element 0x2 @@ -98,488 +81,236 @@ public class Matrix3f { * @param c3 element 2x2 */ public Matrix3f(final float a1, final float a2, final float a3, final float b1, final float b2, final float b3, final float c1, final float c2, final float c3) { - this.mat[0] = a1; - this.mat[1] = a2; - this.mat[2] = a3; - this.mat[3] = b1; - this.mat[4] = b2; - this.mat[5] = b3; - this.mat[6] = c1; - this.mat[7] = c2; - this.mat[8] = c3; + this.a1 = a1; + this.a2 = a2; + this.a3 = a3; + this.b1 = b1; + this.b2 = b2; + this.b3 = b3; + this.c1 = c1; + this.c2 = c2; + this.c3 = c3; } /** - * @brief Copy constructor. - * @param obj Matrix object to copy - */ - public Matrix3f(final Matrix3f obj) { - this.mat[0] = obj.mat[0]; - this.mat[1] = obj.mat[1]; - this.mat[2] = obj.mat[2]; - this.mat[3] = obj.mat[3]; - this.mat[4] = obj.mat[4]; - this.mat[5] = obj.mat[5]; - this.mat[6] = obj.mat[6]; - this.mat[7] = obj.mat[7]; - this.mat[8] = obj.mat[8]; - } - - /** - * @brief absolutise the matrix + * absolutise the matrix */ + @CheckReturnValue public Matrix3f abs() { - this.mat[0] = Math.abs(this.mat[0]); - this.mat[1] = Math.abs(this.mat[1]); - this.mat[2] = Math.abs(this.mat[2]); - this.mat[3] = Math.abs(this.mat[3]); - this.mat[4] = Math.abs(this.mat[4]); - this.mat[5] = Math.abs(this.mat[5]); - this.mat[6] = Math.abs(this.mat[6]); - this.mat[7] = Math.abs(this.mat[7]); - this.mat[8] = Math.abs(this.mat[8]); - return this; - } - - @Deprecated - public void absolute() { - this.mat[0] = Math.abs(this.mat[0]); - this.mat[1] = Math.abs(this.mat[1]); - this.mat[2] = Math.abs(this.mat[2]); - this.mat[3] = Math.abs(this.mat[3]); - this.mat[4] = Math.abs(this.mat[4]); - this.mat[5] = Math.abs(this.mat[5]); - this.mat[6] = Math.abs(this.mat[6]); - this.mat[7] = Math.abs(this.mat[7]); - this.mat[8] = Math.abs(this.mat[8]); + return new Matrix3f(Math.abs(this.a1), Math.abs(this.a2), Math.abs(this.a3), Math.abs(this.b1), Math.abs(this.b2), Math.abs(this.b3), Math.abs(this.c1), Math.abs(this.c2), Math.abs(this.c3)); } /** - * @brief Operator+= Addition an other matrix with this one + * Operator+= Addition an other matrix with this one * @param obj Reference on the external object * @return Local reference of the vector additionned */ + @CheckReturnValue public Matrix3f add(final Matrix3f obj) { - for (int iii = 0; iii < 3 * 3; ++iii) { - this.mat[iii] += obj.mat[iii]; - } - return this; - } - - /** - * @brief Operator+ Addition an other matrix with this one - * @param obj Reference on the external object - * @return New vector containing the value - */ - public Matrix3f addNew(final Matrix3f obj) { - final Matrix3f tmp = new Matrix3f(this); - tmp.add(obj); - return tmp; + return new Matrix3f(this.a1 + obj.a1, this.a2 + obj.a2, this.a3 + obj.a3, this.b1 + obj.b1, this.b2 + obj.b2, this.b3 + obj.b3, this.c1 + obj.c1, this.c2 + obj.c2, this.c3 + obj.c3); } // Return a skew-symmetric matrix using a given vector that can be used // to compute cross product with another vector using matrix multiplication + @CheckReturnValue public Matrix3f computeSkewSymmetricMatrixForCrossProductNew(final Vector3f vector) { - return new Matrix3f(0.0f, -vector.z, vector.y, vector.z, 0, -vector.x, -vector.y, vector.x, 0.0f); + return new Matrix3f(0.0f, -vector.z(), vector.y(), vector.z(), 0, -vector.x(), -vector.y(), vector.x(), 0.0f); } /** - * @brief Computes the determinant of the matrix. + * Computes the determinant of the matrix. * @return The determinent Value. */ + @CheckReturnValue public float determinant() { - return this.mat[0] * (this.mat[4] * this.mat[8] - this.mat[7] * this.mat[5]) - this.mat[1] * (this.mat[3] * this.mat[8] - this.mat[6] * this.mat[5]) - + this.mat[2] * (this.mat[3] * this.mat[7] - this.mat[6] * this.mat[4]); + return this.a1 * (this.b2 * this.c3 - this.c2 * this.b3) - this.a2 * (this.b1 * this.c3 - this.c1 * this.b3) + this.a3 * (this.b1 * this.c2 - this.c1 * this.b2); } /** - * @brief devide a value + * devide a value * @param value value to devide all the matrix */ - public Matrix3f devide(final float value) { - this.mat[0] /= value; - this.mat[1] /= value; - this.mat[2] /= value; - this.mat[3] /= value; - this.mat[4] /= value; - this.mat[5] /= value; - this.mat[6] /= value; - this.mat[7] /= value; - this.mat[8] /= value; - return this; - } - - @Override - public boolean equals(final Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Matrix3f other = (Matrix3f) obj; - for (int iii = 0; iii < 3 * 3; ++iii) { - if (Float.floatToIntBits(this.mat[iii]) != Float.floatToIntBits(other.mat[iii])) { - return false; - } - } - return true; + @CheckReturnValue + public Matrix3f divide(final float value) { + return new Matrix3f(this.a1 / value, this.a2 / value, this.a3 / value, this.b1 / value, this.b2 / value, this.b3 / value, this.c1 / value, this.c2 / value, this.c3 / value); } + @CheckReturnValue public float get(final int iii) { - return this.mat[iii]; + switch (iii) { + case 0: + return this.a1; + case 1: + return this.a2; + case 2: + return this.a3; + case 3: + return this.b1; + case 4: + return this.b2; + case 5: + return this.b3; + case 6: + return this.c1; + case 7: + return this.c2; + case 8: + return this.c3; + default: + return 0; + } } /** - * @brief get the matrix with the absolute value - * @return matix in absolute - */ - public Matrix3f getAbsolute() { - return new Matrix3f(Math.abs(this.mat[0]), Math.abs(this.mat[1]), Math.abs(this.mat[2]), Math.abs(this.mat[3]), Math.abs(this.mat[4]), Math.abs(this.mat[5]), Math.abs(this.mat[6]), - Math.abs(this.mat[7]), Math.abs(this.mat[8])); - } - - /** - * @brief get the colom id values + * get the colom id values * @param iii Id of the colomn * @return Vector 3D vith the values */ + @CheckReturnValue public Vector3f getColumn(final int iii) { if (iii == 0) { - return new Vector3f(this.mat[0], this.mat[3], this.mat[6]); + return new Vector3f(this.a1, this.b1, this.c1); } else if (iii == 1) { - return new Vector3f(this.mat[1], this.mat[4], this.mat[7]); + return new Vector3f(this.a2, this.b2, this.c2); } - return new Vector3f(this.mat[2], this.mat[5], this.mat[8]); + return new Vector3f(this.a3, this.b3, this.c3); } /** - * @brief get the row id values + * get the row id values * @param iii Id of the row * @return Vector 3D vith the values */ + @CheckReturnValue public Vector3f getRow(final int iii) { if (iii == 0) { - return new Vector3f(this.mat[0], this.mat[1], this.mat[2]); + return new Vector3f(this.a1, this.a2, this.a3); } else if (iii == 1) { - return new Vector3f(this.mat[3], this.mat[4], this.mat[5]); + return new Vector3f(this.b1, this.b2, this.b3); } - return new Vector3f(this.mat[6], this.mat[7], this.mat[8]); + return new Vector3f(this.c1, this.c2, this.c3); } /** - * @brief Calculate the trace of the matrix + * Calculate the trace of the matrix * @return value of addition of all element in the diagonal */ + @CheckReturnValue public float getTrace() { - return (this.mat[0] + this.mat[4] + this.mat[8]); - } - - @Override - public int hashCode() { - int hash = 1542; - hash += Float.floatToIntBits(this.mat[0]); - hash += Float.floatToIntBits(this.mat[1]); - hash += Float.floatToIntBits(this.mat[2]); - hash += Float.floatToIntBits(this.mat[3]); - hash += Float.floatToIntBits(this.mat[4]); - hash += Float.floatToIntBits(this.mat[5]); - hash += Float.floatToIntBits(this.mat[6]); - hash += Float.floatToIntBits(this.mat[7]); - hash += Float.floatToIntBits(this.mat[8]); - return hash; + return (this.a1 + this.b2 + this.c3); } /** - * @brief Inverts the current matrix. + * Inverts the current matrix. * @note The determinant must be != 0, otherwithe the matrix can't be inverted. */ + @CheckReturnValue public Matrix3f inverse() { final float det = determinant(); //assert(Math.abs(det) > MACHINEEPSILON); - this.set((this.mat[4] * this.mat[8] - this.mat[7] * this.mat[5]), -(this.mat[1] * this.mat[8] - this.mat[7] * this.mat[2]), (this.mat[1] * this.mat[5] - this.mat[2] * this.mat[4]), - -(this.mat[3] * this.mat[8] - this.mat[6] * this.mat[5]), (this.mat[0] * this.mat[8] - this.mat[6] * this.mat[2]), -(this.mat[0] * this.mat[5] - this.mat[3] * this.mat[2]), - (this.mat[3] * this.mat[7] - this.mat[6] * this.mat[4]), -(this.mat[0] * this.mat[7] - this.mat[6] * this.mat[1]), (this.mat[0] * this.mat[4] - this.mat[1] * this.mat[3])); - devide(det); - return this; - } - - /** - * @brief Inverse the matrix. - * @note The determinant must be != 0, otherwithe the matrix can't be inverted. - * @return The inverted matrix. - */ - public Matrix3f inverseNew() { - final Matrix3f tmp = new Matrix3f(this); - tmp.inverse(); - return tmp; + return new Matrix3f((this.b2 * this.c3 - this.c2 * this.b3) / det, -(this.a2 * this.c3 - this.c2 * this.a3) / det, (this.a2 * this.b3 - this.a3 * this.b2) / det, + -(this.b1 * this.c3 - this.c1 * this.b3) / det, (this.a1 * this.c3 - this.c1 * this.a3) / det, -(this.a1 * this.b3 - this.b1 * this.a3) / det, + (this.b1 * this.c2 - this.c1 * this.b2) / det, -(this.a1 * this.c2 - this.c1 * this.a2) / det, (this.a1 * this.b2 - this.a2 * this.b1) / det); } // Overloaded operator for the negative of the matrix + @CheckReturnValue public Matrix3f invert() { - this.mat[0] = -this.mat[0]; - this.mat[1] = -this.mat[1]; - this.mat[2] = -this.mat[2]; - this.mat[3] = -this.mat[3]; - this.mat[4] = -this.mat[4]; - this.mat[5] = -this.mat[5]; - this.mat[6] = -this.mat[6]; - this.mat[7] = -this.mat[7]; - this.mat[8] = -this.mat[8]; - return this; + return new Matrix3f(-this.a1, -this.a2, -this.a3, -this.b1, -this.b2, -this.b3, -this.c1, -this.c2, -this.c3); } /** - * @brief In-Equality compare operator with an other object. + * In-Equality compare operator with an other object. * @param obj Reference on the comparing object * @return true The Objects are NOT identical * @return false The Objects are identical */ + @CheckReturnValue public boolean isDifferent(final Matrix3f obj) { - for (int iii = 0; iii < 3 * 3; ++iii) { - if (this.mat[iii] != obj.mat[iii]) { - return true; - } + if (this.a1 != obj.a1 || this.a2 != obj.a2 || this.a3 != obj.a3 || this.b1 != obj.b1 || this.b2 != obj.b2 || this.b3 != obj.b3 || this.c1 != obj.c1 || this.c2 != obj.c2 || this.c3 != obj.c3) { + return true; } return false; } /** - * @brief Equality compare operator with an other object. + * Equality compare operator with an other object. * @param obj Reference on the comparing object * @return true The Objects are identical * @return false The Objects are NOT identical */ + @CheckReturnValue boolean isEqual(final Matrix3f obj) { - for (int iii = 0; iii < 3 * 3; ++iii) { - if (this.mat[iii] != obj.mat[iii]) { - return false; - } + if (this.a1 != obj.a1 || this.a2 != obj.a2 || this.a3 != obj.a3 || this.b1 != obj.b1 || this.b2 != obj.b2 || this.b3 != obj.b3 || this.c1 != obj.c1 || this.c2 != obj.c2 || this.c3 != obj.c3) { + return false; } return true; } /** - * @brief Operator-= Decrement an other matrix with this one + * Operator-= Decrement an other matrix with this one * @param obj Reference on the external object * @return Local reference of the vector decremented */ + @CheckReturnValue public Matrix3f less(final Matrix3f obj) { - for (int iii = 0; iii < 3 * 3; ++iii) { - this.mat[iii] -= obj.mat[iii]; - } - return this; + return new Matrix3f(this.a1 - obj.a1, this.a2 - obj.a2, this.a3 - obj.a3, this.b1 - obj.b1, this.b2 - obj.b2, this.b3 - obj.b3, this.c1 - obj.c1, this.c2 - obj.c2, this.c3 - obj.c3); } /** - * @brief Operator- Decrement an other matrix with this one - * @param obj Reference on the external object - * @return New vector containing the value - */ - public Matrix3f lessNew(final Matrix3f obj) { - final Matrix3f tmp = new Matrix3f(this); - tmp.less(obj); - return tmp; - } - - /** - * @brief Operator*= Multiplication a value + * Operator*= Multiplication a value * @param value value to multiply all the matrix * @return Local reference of the vector multiplicated */ + @CheckReturnValue public Matrix3f multiply(final float value) { - this.mat[0] *= value; - this.mat[1] *= value; - this.mat[2] *= value; - this.mat[3] *= value; - this.mat[4] *= value; - this.mat[5] *= value; - this.mat[6] *= value; - this.mat[7] *= value; - this.mat[8] *= value; - return this; + return new Matrix3f(this.a1 * value, this.a2 * value, this.a3 * value, this.b1 * value, this.b2 * value, this.b3 * value, this.c1 * value, this.c2 * value, this.c3 * value); } /** - * @brief Operator*= Multiplication an other matrix with this one + * Operator*= Multiplication an other matrix with this one * @param obj Reference on the external object - * @return Local reference of the vector multiplicated + * @return Local reference of the vector multiplied */ + @CheckReturnValue public Matrix3f multiply(final Matrix3f obj) { - final float a1 = this.mat[0] * obj.mat[0] + this.mat[1] * obj.mat[3] + this.mat[2] * obj.mat[6]; - final float b1 = this.mat[3] * obj.mat[0] + this.mat[4] * obj.mat[3] + this.mat[5] * obj.mat[6]; - final float c1 = this.mat[6] * obj.mat[0] + this.mat[7] * obj.mat[3] + this.mat[8] * obj.mat[6]; - final float a2 = this.mat[0] * obj.mat[1] + this.mat[1] * obj.mat[4] + this.mat[2] * obj.mat[7]; - final float b2 = this.mat[3] * obj.mat[1] + this.mat[4] * obj.mat[4] + this.mat[5] * obj.mat[7]; - final float c2 = this.mat[6] * obj.mat[1] + this.mat[7] * obj.mat[4] + this.mat[8] * obj.mat[7]; - this.mat[2] = this.mat[0] * obj.mat[2] + this.mat[1] * obj.mat[5] + this.mat[2] * obj.mat[8]; - this.mat[5] = this.mat[3] * obj.mat[2] + this.mat[4] * obj.mat[5] + this.mat[5] * obj.mat[8]; - this.mat[8] = this.mat[6] * obj.mat[2] + this.mat[7] * obj.mat[5] + this.mat[8] * obj.mat[8]; - this.mat[0] = a1; - this.mat[3] = b1; - this.mat[6] = c1; - this.mat[1] = a2; - this.mat[4] = b2; - this.mat[7] = c2; - return this; + final float a1 = this.a1 * obj.a1 + this.a2 * obj.b1 + this.a3 * obj.c1; + final float b1 = this.b1 * obj.a1 + this.b2 * obj.b1 + this.b3 * obj.c1; + final float c1 = this.c1 * obj.a1 + this.c2 * obj.b1 + this.c3 * obj.c1; + final float a2 = this.a1 * obj.a2 + this.a2 * obj.b2 + this.a3 * obj.c2; + final float b2 = this.b1 * obj.a2 + this.b2 * obj.b2 + this.b3 * obj.c2; + final float c2 = this.c1 * obj.a2 + this.c2 * obj.b2 + this.c3 * obj.c2; + float tmpA3 = this.a1 * obj.a3 + this.a2 * obj.b3 + this.a3 * obj.c3; + float tmpB3 = this.b1 * obj.a3 + this.b2 * obj.b3 + this.b3 * obj.c3; + float tmpC3 = this.c1 * obj.a3 + this.c2 * obj.b3 + this.c3 * obj.c3; + return new Matrix3f(a1, a2, tmpA3, b1, b2, tmpB3, c1, c2, tmpC3); } /** - * @brief Operator*= Multiplication a value - * @param value value to multiply all the matrix - * @return Local reference of the vector multiplicated - */ - public Matrix3f multiplyNew(final float value) { - final Matrix3f tmp = new Matrix3f(this); - tmp.multiply(value); - return tmp; - } - - /** - * @brief Operator* Multiplication an other matrix with this one - * @param obj Reference on the external object - * @return New vector containing the value - */ - public Matrix3f multiplyNew(final Matrix3f obj) { - final Matrix3f tmp = new Matrix3f(this); - tmp.multiply(obj); - return tmp; - } - - /** - * @brief Operator* apply matrix on a vector + * Operator* apply matrix on a vector * @param point Point value to apply the matrix * @return New vector containing the value */ - public Vector3f multiplyNew(final Vector3f point) { - return new Vector3f((float) ((double) point.x * (double) this.mat[0] + (double) point.y * (double) this.mat[1] + (double) point.z * (double) this.mat[2]), - (float) ((double) point.x * (double) this.mat[3] + (double) point.y * (double) this.mat[4] + (double) point.z * (double) this.mat[5]), - (float) ((double) point.x * (double) this.mat[6] + (double) point.y * (double) this.mat[7] + (double) point.z * (double) this.mat[8])); - /* - return new Vector3f(point.x * this.mat[0] + point.y * this.mat[1] + point.z * this.mat[2], point.x * this.mat[3] + point.y * this.mat[4] + point.z * this.mat[5], - point.x * this.mat[6] + point.y * this.mat[7] + point.z * this.mat[8]); - */ - } - - /** - * @brief Operator*= Multiplication an other matrix with this one - * @param obj Reference on the external object - * @return Local reference of the vector multiplicated - */ - public void multiplyTo(final Matrix3f obj, final Matrix3f out) { - out.mat[2] = this.mat[0] * obj.mat[2] + this.mat[1] * obj.mat[5] + this.mat[2] * obj.mat[8]; - out.mat[5] = this.mat[3] * obj.mat[2] + this.mat[4] * obj.mat[5] + this.mat[5] * obj.mat[8]; - out.mat[8] = this.mat[6] * obj.mat[2] + this.mat[7] * obj.mat[5] + this.mat[8] * obj.mat[8]; - out.mat[0] = this.mat[0] * obj.mat[0] + this.mat[1] * obj.mat[3] + this.mat[2] * obj.mat[6]; - out.mat[3] = this.mat[3] * obj.mat[0] + this.mat[4] * obj.mat[3] + this.mat[5] * obj.mat[6]; - out.mat[6] = this.mat[6] * obj.mat[0] + this.mat[7] * obj.mat[3] + this.mat[8] * obj.mat[6]; - out.mat[1] = this.mat[0] * obj.mat[1] + this.mat[1] * obj.mat[4] + this.mat[2] * obj.mat[7]; - out.mat[4] = this.mat[3] * obj.mat[1] + this.mat[4] * obj.mat[4] + this.mat[5] * obj.mat[7]; - out.mat[7] = this.mat[6] * obj.mat[1] + this.mat[7] * obj.mat[4] + this.mat[8] * obj.mat[7]; - } - - public void multiplyTo(final Vector3f point, final Vector3f out) { - out.set(point.x * this.mat[0] + point.y * this.mat[1] + point.z * this.mat[2], point.x * this.mat[3] + point.y * this.mat[4] + point.z * this.mat[5], - point.x * this.mat[6] + point.y * this.mat[7] + point.z * this.mat[8]); - } - - /** - * @brief Set Value on the matrix - * @param a1 element 0x0 - * @param a2 element 0x1 - * @param a3 element 0x2 - * @param b1 element 1x0 - * @param b2 element 1x1 - * @param b3 element 1x2 - * @param c1 element 2x0 - * @param c2 element 2x1 - * @param c3 element 2x2 - */ - public Matrix3f set(final float a1, final float a2, final float a3, final float b1, final float b2, final float b3, final float c1, final float c2, final float c3) { - this.mat[0] = a1; - this.mat[1] = a2; - this.mat[2] = a3; - this.mat[3] = b1; - this.mat[4] = b2; - this.mat[5] = b3; - this.mat[6] = c1; - this.mat[7] = c2; - this.mat[8] = c3; - return this; - } - - /** - * @brief Operator= Asign the current object with an other object - * @param obj Reference on the external object - * @return Local reference of the vector asigned - */ - public Matrix3f set(final Matrix3f obj) { - for (int iii = 0; iii < 3 * 3; ++iii) { - this.mat[iii] = obj.mat[iii]; - } - return this; - } - - /** - * @brief Load Identity matrix - */ - public Matrix3f setIdentity() { - this.mat[0] = 1.0f; - this.mat[1] = 0.0f; - this.mat[2] = 0.0f; - this.mat[3] = 0.0f; - this.mat[4] = 1.0f; - this.mat[5] = 0.0f; - this.mat[6] = 0.0f; - this.mat[7] = 0.0f; - this.mat[8] = 1.0f; - return this; - } - - /** - * @brief Load Zero matrix - */ - public Matrix3f setZero() { - this.mat[0] = 0.0f; - this.mat[1] = 0.0f; - this.mat[2] = 0.0f; - this.mat[3] = 0.0f; - this.mat[4] = 0.0f; - this.mat[5] = 0.0f; - this.mat[6] = 0.0f; - this.mat[7] = 0.0f; - this.mat[8] = 0.0f; - return this; + @CheckReturnValue + public Vector3f multiply(final Vector3f point) { + return new Vector3f((float) (point.x() * (double) this.a1 + point.y() * (double) this.a2 + point.z() * (double) this.a3), + (float) (point.x() * (double) this.b1 + point.y() * (double) this.b2 + point.z() * (double) this.b3), + (float) (point.x() * (double) this.c1 + point.y() * (double) this.c2 + point.z() * (double) this.c3)); } @Override public String toString() { - return "Matrix3f(" + FMath.floatToString(this.mat[0]) + "," + FMath.floatToString(this.mat[1]) + "," + FMath.floatToString(this.mat[2]) + "," + FMath.floatToString(this.mat[3]) + "," - + FMath.floatToString(this.mat[4]) + "," + FMath.floatToString(this.mat[5]) + "," + FMath.floatToString(this.mat[6]) + "," + FMath.floatToString(this.mat[7]) + "," - + FMath.floatToString(this.mat[8]) + ")"; + return "Matrix3f(" + FMath.floatToString(this.a1) + "," + FMath.floatToString(this.a2) + "," + FMath.floatToString(this.a3) + "," + FMath.floatToString(this.b1) + "," + + FMath.floatToString(this.b2) + "," + FMath.floatToString(this.b3) + "," + FMath.floatToString(this.c1) + "," + FMath.floatToString(this.c2) + "," + FMath.floatToString(this.c3) + + ")"; } /** - * @brief Transpose the current matrix. - */ - public Matrix3f transpose() { - float tmp = this.mat[1]; - this.mat[1] = this.mat[3]; - this.mat[3] = tmp; - tmp = this.mat[2]; - this.mat[2] = this.mat[6]; - this.mat[6] = tmp; - tmp = this.mat[5]; - this.mat[5] = this.mat[7]; - this.mat[7] = tmp; - return this; - } - - /** - * @brief get a transpose matrix of this one. + * get a transpose matrix of this one. * @return the transpose matrix */ - public Matrix3f transposeNew() { - return new Matrix3f(this.mat[0], this.mat[3], this.mat[6], this.mat[1], this.mat[4], this.mat[7], this.mat[2], this.mat[5], this.mat[8]); + @CheckReturnValue + public Matrix3f transpose() { + return new Matrix3f(this.a1, this.b1, this.c1, this.a2, this.b2, this.c2, this.a3, this.b3, this.c3); } } diff --git a/src/org/atriasoft/etk/math/Matrix4f.java b/src/org/atriasoft/etk/math/Matrix4f.java index ffa08db..fbca9fd 100644 --- a/src/org/atriasoft/etk/math/Matrix4f.java +++ b/src/org/atriasoft/etk/math/Matrix4f.java @@ -1,8 +1,26 @@ package org.atriasoft.etk.math; -public class Matrix4f { +import edu.umd.cs.findbugs.annotations.CheckReturnValue; + +public record Matrix4f( + float a1, + float b1, + float c1, + float d1, + float a2, + float b2, + float c2, + float d2, + float a3, + float b3, + float c3, + float d3, + float a4, + float b4, + float c4, + float d4) { /** - * @brief Create projection matrix with the box parameter (camera view in -z axis) + * Create projection matrix with the box parameter (camera view in -z axis) * @param xmin X minimum size of the frustum * @param xmax X maximum size of the frustum * @param ymin Y minimum size of the frustum @@ -12,66 +30,74 @@ public class Matrix4f { * @return New matrix of the transformation requested */ public static Matrix4f createMatrixFrustum(final float xmin, final float xmax, final float ymin, final float ymax, final float zNear, final float zFar) { - final Matrix4f tmp = new Matrix4f(); - for (int iii = 0; iii < 4 * 4; iii++) { - tmp.mat[iii] = 0; - } + float a1 = 0; + float b1 = 0; + float c1 = 0; + float d1 = 0; + float a2 = 0; + float b2 = 0; + float c2 = 0; + float d2 = 0; + float a3 = 0; + float b3 = 0; + float c3 = 0; + float d3 = 0; + float a4 = 0; + float b4 = 0; + float c4 = 0; + float d4 = 0; // 0 1 2 3 // 4 5 6 7 // 8 9 10 11 // 12 13 14 15 - tmp.mat[0] = (2.0f * zNear) / (xmax - xmin); - tmp.mat[5] = (2.0f * zNear) / (ymax - ymin); - tmp.mat[10] = -(zFar + zNear) / (zFar - zNear); - tmp.mat[2] = (xmax + xmin) / (xmax - xmin); - tmp.mat[6] = (ymax + ymin) / (ymax - ymin); - tmp.mat[14] = -1.0f; - tmp.mat[11] = -(2.0f * zFar * zNear) / (zFar - zNear); - return tmp; + a1 = (2.0f * zNear) / (xmax - xmin); + b2 = (2.0f * zNear) / (ymax - ymin); + c3 = -(zFar + zNear) / (zFar - zNear); + c1 = (xmax + xmin) / (xmax - xmin); + c2 = (ymax + ymin) / (ymax - ymin); + c4 = -1.0f; + d3 = -(2.0f * zFar * zNear) / (zFar - zNear); + return new Matrix4f(a1, b1, c1, d1, a2, b2, c2, d2, a3, b3, c3, d3, a4, b4, c4, d4); } /** - * @brief Create projection matrix with camera property (camera view in -z axis) + * Create projection matrix with camera property (camera view in -z axis) * @param eye Optical center of the camera * @param target Point of where the camera is showing * @param up Up vector of the camera * @return New matrix of the transformation requested */ public static Matrix4f createMatrixLookAt(final Vector3f eye, final Vector3f target, final Vector3f up) { - final Matrix4f tmp = new Matrix4f(); - - final Vector3f forward = eye; - forward.less(target); - forward.safeNormalize(); - final Vector3f xaxis = target.cross(up.normalizeNew()); - xaxis.safeNormalize(); + final Vector3f forward = eye.less(target).safeNormalize(); + Vector3f xaxis = target.cross(up.normalize()); + xaxis = xaxis.safeNormalize(); final Vector3f up2 = xaxis.cross(forward); - xaxis.safeNormalize(); + xaxis = xaxis.safeNormalize(); // TODO ?????? - tmp.mat[0] = xaxis.x; - tmp.mat[1] = up2.x; - tmp.mat[2] = forward.x; - tmp.mat[3] = eye.x; + float a1 = xaxis.x(); + float b1 = up2.x(); + float c1 = forward.x(); + float d1 = eye.x(); - tmp.mat[4] = xaxis.y; - tmp.mat[5] = up2.y; - tmp.mat[6] = forward.y; - tmp.mat[7] = eye.y; + float a2 = xaxis.y(); + float b2 = up2.y(); + float c2 = forward.y(); + float d2 = eye.y(); - tmp.mat[8] = xaxis.z; - tmp.mat[9] = up2.z; - tmp.mat[10] = forward.z; - tmp.mat[11] = eye.z; + float a3 = xaxis.z(); + float b3 = up2.z(); + float c3 = forward.z(); + float d3 = eye.z(); - tmp.mat[12] = 0.0f; - tmp.mat[13] = 0.0f; - tmp.mat[14] = 0.0f; - tmp.mat[15] = 1.0f; - return tmp; + float a4 = 0.0f; + float b4 = 0.0f; + float c4 = 0.0f; + float d4 = 1.0f; + return new Matrix4f(a1, b1, c1, d1, a2, b2, c2, d2, a3, b3, c3, d3, a4, b4, c4, d4); } /** - * @brief Create orthogonal projection matrix with the box parameter (camera view in -z axis) + * Create orthogonal projection matrix with the box parameter (camera view in -z axis) * @param left left size of the camera * @param right Right size of the camera * @param bottom Buttom size of the camera @@ -81,22 +107,34 @@ public class Matrix4f { * @return New matrix of the transformation requested */ public static Matrix4f createMatrixOrtho(final float left, final float right, final float bottom, final float top, final float nearVal, final float farVal) { - final Matrix4f tmp = new Matrix4f(); - for (int iii = 0; iii < 4 * 4; iii++) { - tmp.mat[iii] = 0; - } - tmp.mat[0] = 2.0f / (right - left); - tmp.mat[5] = 2.0f / (top - bottom); - tmp.mat[10] = -2.0f / (farVal - nearVal); - tmp.mat[3] = -1 * (right + left) / (right - left); - tmp.mat[7] = -1 * (top + bottom) / (top - bottom); - tmp.mat[11] = -1 * (farVal + nearVal) / (farVal - nearVal); - tmp.mat[15] = 1; - return tmp; + float a1 = 1.0f; + float b1 = 0; + float c1 = 0; + float d1 = 0; + float a2 = 0; + float b2 = 1.0f; + float c2 = 0; + float d2 = 0; + float a3 = 0; + float b3 = 0; + float c3 = 1.0f; + float d3 = 0; + float a4 = 0; + float b4 = 0; + float c4 = 0; + float d4 = 1.0f; + a1 = 2.0f / (right - left); + b2 = 2.0f / (top - bottom); + c3 = -2.0f / (farVal - nearVal); + d1 = -1 * (right + left) / (right - left); + d2 = -1 * (top + bottom) / (top - bottom); + d3 = -1 * (farVal + nearVal) / (farVal - nearVal); + return new Matrix4f(a1, b1, c1, d1, a2, b2, c2, d2, a3, b3, c3, d3, a4, b4, c4, d4); + } /** - * @brief Create projection matrix with human repensentation view (camera view in -z axis) + * Create projection matrix with human repensentation view (camera view in -z axis) * @param foxy Focal in radian of the camera * @param aspect aspect ratio of the camera * @param zNear Z near size of the camera @@ -115,29 +153,45 @@ public class Matrix4f { } /** - * @brief Create a matrix 3D with a simple rotation + * Create a matrix 3D with a simple rotation * @param normal vector aroud witch apply the rotation * @param angleRad Radian angle to set at the matrix * @return New matrix of the transformation requested */ public static Matrix4f createMatrixRotate(final Vector3f normal, final float angleRad) { - final Matrix4f tmp = new Matrix4f(); + float a1 = 1.0f; + float b1 = 0; + float c1 = 0; + float d1 = 0; + float a2 = 0; + float b2 = 1.0f; + float c2 = 0; + float d2 = 0; + float a3 = 0; + float b3 = 0; + float c3 = 1.0f; + float d3 = 0; + float a4 = 0; + float b4 = 0; + float c4 = 0; + float d4 = 1.0f; + final float cosVal = (float) Math.cos(angleRad); final float sinVal = (float) Math.sin(angleRad); final float invVal = 1.0f - cosVal; // set rotation : - tmp.mat[0] = normal.x * normal.x * invVal + cosVal; - tmp.mat[1] = normal.x * normal.y * invVal - normal.z * sinVal; - tmp.mat[2] = normal.x * normal.z * invVal + normal.y * sinVal; + a1 = normal.x() * normal.x() * invVal + cosVal; + b1 = normal.x() * normal.y() * invVal - normal.z() * sinVal; + c1 = normal.x() * normal.z() * invVal + normal.y() * sinVal; - tmp.mat[4] = normal.y * normal.x * invVal + normal.z * sinVal; - tmp.mat[5] = normal.y * normal.y * invVal + cosVal; - tmp.mat[6] = normal.y * normal.z * invVal - normal.x * sinVal; + a2 = normal.y() * normal.x() * invVal + normal.z() * sinVal; + b2 = normal.y() * normal.y() * invVal + cosVal; + c2 = normal.y() * normal.z() * invVal - normal.x() * sinVal; - tmp.mat[8] = normal.z * normal.x * invVal - normal.y * sinVal; - tmp.mat[9] = normal.z * normal.y * invVal + normal.x * sinVal; - tmp.mat[10] = normal.z * normal.z * invVal + cosVal; - return tmp; + a3 = normal.z() * normal.x() * invVal - normal.y() * sinVal; + b3 = normal.z() * normal.y() * invVal + normal.x() * sinVal; + c3 = normal.z() * normal.z() * invVal + cosVal; + return new Matrix4f(a1, b1, c1, d1, a2, b2, c2, d2, a3, b3, c3, d3, a4, b4, c4, d4); } //! @notindoc @@ -146,47 +200,45 @@ public class Matrix4f { } /** - * @brief Create a matrix 3D with a simple scale - * @param scale 3 dimention scale + * Create a matrix 3D with a simple scale + * @param scale 3 dimension scale * @return New matrix of the transformation requested */ public static Matrix4f createMatrixScale(final Vector3f scale) { - final Matrix4f tmp = new Matrix4f(); - tmp.scale(scale); - return tmp; + return new Matrix4f(scale.x(), 0, 0, 0, 0, scale.y(), 0, 0, 0, 0, scale.z(), 0, 0, 0, 0, 1); + } + + public static Matrix4f createMatrixScale(final float xxx, final float yyy, final float zzz) { + return new Matrix4f(xxx, 0, 0, 0, 0, yyy, 0, 0, 0, 0, zzz, 0, 0, 0, 0, 1); } /** - * @brief Create a matrix 3D with a simple translation + * Create a matrix 3D with a simple translation * @param translate 3 dimention translation * @return New matrix of the transformation requested */ public static Matrix4f createMatrixTranslate(final Vector3f translate) { - final Matrix4f tmp = new Matrix4f(); - // set translation : - tmp.mat[3] = translate.x; - tmp.mat[7] = translate.y; - tmp.mat[11] = translate.z; - return tmp; - } - - public static Matrix4f identity() { - final Matrix4f tmp = new Matrix4f(); - tmp.setIdentity(); - return tmp; - } - - public float[] mat = new float[4 * 4]; //!< matrix data - - /** - * @brief Constructor that load identity - */ - public Matrix4f() { - setIdentity(); + float a1 = 1.0f; + float b1 = 0; + float c1 = 0; + float d1 = translate.x(); + float a2 = 0; + float b2 = 1.0f; + float c2 = 0; + float d2 = translate.y(); + float a3 = 0; + float b3 = 0; + float c3 = 1.0f; + float d3 = translate.z(); + float a4 = 0; + float b4 = 0; + float c4 = 0; + float d4 = 1.0f; + return new Matrix4f(a1, b1, c1, d1, a2, b2, c2, d2, a3, b3, c3, d3, a4, b4, c4, d4); } /** - * @brief Configuration constructor. + * Configuration constructor. * @param a1 1st colomn, 1 line value * @param b1 2nd colomn, 1 line value * @param c1 3rd colomn, 1 line value @@ -206,366 +258,345 @@ public class Matrix4f { */ public Matrix4f(final float a1, final float b1, final float c1, final float d1, final float a2, final float b2, final float c2, final float d2, final float a3, final float b3, final float c3, final float d3, final float a4, final float b4, final float c4, final float d4) { - this.mat[0] = a1; - this.mat[1] = b1; - this.mat[2] = c1; - this.mat[3] = d1; - this.mat[4] = a2; - this.mat[5] = b2; - this.mat[6] = c2; - this.mat[7] = d2; - this.mat[8] = a3; - this.mat[9] = b3; - this.mat[10] = c3; - this.mat[11] = d3; - this.mat[12] = a4; - this.mat[13] = b4; - this.mat[14] = c4; - this.mat[15] = d4; + this.a1 = a1; + this.b1 = b1; + this.c1 = c1; + this.d1 = d1; + this.a2 = a2; + this.b2 = b2; + this.c2 = c2; + this.d2 = d2; + this.a3 = a3; + this.b3 = b3; + this.c3 = c3; + this.d3 = d3; + this.a4 = a4; + this.b4 = b4; + this.c4 = c4; + this.d4 = d4; } /** - * @brief Configuration constructor. + * Configuration constructor. * @param values vector of values */ public Matrix4f(final float[] values) { - if (values == null) { - setIdentity(); - return; - } - for (int iii = 0; iii < 16; ++iii) { - this.mat[iii] = values[iii]; - } + this(values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9], values[10], values[11], values[12], values[13], values[14], values[15]); } public Matrix4f(final Matrix3f matrix) { - this.mat[0] = matrix.mat[0]; - this.mat[1] = matrix.mat[1]; - this.mat[2] = matrix.mat[2]; - this.mat[3] = 0; - this.mat[4] = matrix.mat[3]; - this.mat[5] = matrix.mat[4]; - this.mat[6] = matrix.mat[5]; - this.mat[7] = 0; - this.mat[8] = matrix.mat[6]; - this.mat[9] = matrix.mat[7]; - this.mat[10] = matrix.mat[8]; - this.mat[11] = 0; - this.mat[12] = 0; - this.mat[13] = 0; - this.mat[14] = 0; - this.mat[15] = 1; - // this.mat[0] = matrix.mat[0]; - // this.mat[1] = matrix.mat[3]; - // this.mat[2] = matrix.mat[6]; - // this.mat[3] = 0; - // this.mat[4] = matrix.mat[1]; - // this.mat[5] = matrix.mat[4]; - // this.mat[6] = matrix.mat[7]; - // this.mat[7] = 0; - // this.mat[8] = matrix.mat[2]; - // this.mat[9] = matrix.mat[5]; - // this.mat[10] = matrix.mat[8]; - // this.mat[11] = 0; - // this.mat[12] = 0; - // this.mat[13] = 0; - // this.mat[14] = 0; - // this.mat[15] = 1; - } - - // copy contructor: - public Matrix4f(final Matrix4f matrix) { - for (int iii = 0; iii < 16; ++iii) { - this.mat[iii] = matrix.mat[iii]; - } + this(matrix.a1(), matrix.a2(), matrix.a3(), 0, matrix.b1(), matrix.b2(), matrix.b3(), 0, matrix.c1(), matrix.c2(), matrix.c3(), 0, 0, 0, 0, 1); } /** - * @brief Operator+= Addition an other matrix with this one + * Operator+= Addition an other matrix with this one * @param obj Reference on the external object */ - public void add(final Matrix4f obj) { - for (int iii = 0; iii < 4 * 4; ++iii) { - this.mat[iii] += obj.mat[iii]; - } + @CheckReturnValue + public Matrix4f add(final Matrix4f obj) { + return new Matrix4f(this.a1 + obj.a1, this.b1 + obj.b1, this.c1 + obj.c1, this.d1 + obj.d1, this.a2 + obj.a2, this.b2 + obj.b2, this.c2 + obj.c2, this.d2 + obj.d2, this.a3 + obj.a3, + this.b3 + obj.b3, this.c3 + obj.c3, this.d3 + obj.d3, this.a4 + obj.a4, this.b4 + obj.b4, this.c4 + obj.c4, this.d4 + obj.d4); } /** - * @brief Operator= Asign the current object with an other object + * Operator-= Decrement an other matrix with this one * @param obj Reference on the external object */ - @Override - public Matrix4f clone() { - return new Matrix4f(this); + @CheckReturnValue + public Matrix4f decrement(final Matrix4f obj) { + return new Matrix4f(this.a1 - obj.a1, this.b1 - obj.b1, this.c1 - obj.c1, this.d1 - obj.d1, this.a2 - obj.a2, this.b2 - obj.b2, this.c2 - obj.c2, this.d2 - obj.d2, this.a3 - obj.a3, + this.b3 - obj.b3, this.c3 - obj.c3, this.d3 - obj.d3, this.a4 - obj.a4, this.b4 - obj.b4, this.c4 - obj.c4, this.d4 - obj.d4); + } + + private float coFactorRaw0Col0() { + return this.b2 * this.c3 * this.d4 - this.b2 * this.d3 * this.c4 - this.c2 * this.b3 * this.d4 + this.c2 * this.d3 * this.b4 + this.d2 * this.b3 * this.c4 - this.d2 * this.c3 * this.b4; + } + + private float coFactorRaw0Col1() { + return this.a2 * this.c3 * this.d4 - this.a2 * this.d3 * this.c4 - this.c2 * this.a3 * this.d4 + this.c2 * this.d3 * this.a4 + this.d2 * this.a3 * this.c4 - this.d2 * this.c3 * this.a4; + } + + private float coFactorRaw0Col2() { + return this.a2 * this.b3 * this.d4 - this.a2 * this.d3 * this.b4 - this.b2 * this.a3 * this.d4 + this.b2 * this.d3 * this.a4 + this.d2 * this.a3 * this.b4 - this.d2 * this.b3 * this.a4; + } + + private float coFactorRaw0Col3() { + return this.a2 * this.b3 * this.c4 - this.a2 * this.c3 * this.b4 - this.b2 * this.a3 * this.c4 + this.b2 * this.c3 * this.a4 + this.c2 * this.a3 * this.b4 - this.c2 * this.b3 * this.a4; + } + + private float coFactorRaw1Col0() { + return this.b1 * this.c3 * this.d4 - this.b1 * this.d3 * this.c4 - this.c1 * this.b3 * this.d4 + this.c1 * this.d3 * this.b4 + this.d1 * this.b3 * this.c4 - this.d1 * this.c3 * this.b4; + } + + private float coFactorRaw1Col1() { + return this.a1 * this.c3 * this.d4 - this.a1 * this.d3 * this.c4 - this.c1 * this.a3 * this.d4 + this.c1 * this.d3 * this.a4 + this.d1 * this.a3 * this.c4 - this.d1 * this.c3 * this.a4; + } + + private float coFactorRaw1Col2() { + return this.a1 * this.b3 * this.d4 - this.a1 * this.d3 * this.b4 - this.b1 * this.a3 * this.d4 + this.b1 * this.d3 * this.a4 + this.d1 * this.a3 * this.b4 - this.d1 * this.b3 * this.a4; + } + + private float coFactorRaw1Col3() { + return this.a1 * this.b3 * this.c4 - this.a1 * this.c3 * this.b4 - this.b1 * this.a3 * this.c4 + this.b1 * this.c3 * this.a4 + this.c1 * this.a3 * this.b4 - this.c1 * this.b3 * this.a4; + } + + private float coFactorRaw2Col0() { + return this.b1 * this.c2 * this.d4 - this.b1 * this.d2 * this.c4 - this.c1 * this.b2 * this.d4 + this.c1 * this.d2 * this.b4 + this.d1 * this.b2 * this.c4 - this.d1 * this.c2 * this.b4; + } + + private float coFactorRaw2Col1() { + return this.a1 * this.c2 * this.d4 - this.a1 * this.d2 * this.c4 - this.c1 * this.a2 * this.d4 + this.c1 * this.d2 * this.a4 + this.d1 * this.a2 * this.c4 - this.d1 * this.c2 * this.a4; + } + + private float coFactorRaw2Col2() { + return this.a1 * this.b2 * this.d4 - this.a1 * this.d2 * this.b4 - this.b1 * this.a2 * this.d4 + this.b1 * this.d2 * this.a4 + this.d1 * this.a2 * this.b4 - this.d1 * this.b2 * this.a4; + } + + private float coFactorRaw2Col3() { + return this.a1 * this.b2 * this.c4 - this.a1 * this.c2 * this.b4 - this.b1 * this.a2 * this.c4 + this.b1 * this.c2 * this.a4 + this.c1 * this.a2 * this.b4 - this.c1 * this.b2 * this.a4; + } + + private float coFactorRaw3Col0() { + return this.b1 * this.c2 * this.d3 - this.b1 * this.d2 * this.c3 - this.c1 * this.b2 * this.d3 + this.c1 * this.d2 * this.b3 + this.d1 * this.b2 * this.c3 - this.d1 * this.c2 * this.b3; + } + + private float coFactorRaw3Col1() { + return this.a1 * this.c2 * this.d3 - this.a1 * this.d2 * this.c3 - this.c1 * this.a2 * this.d3 + this.c1 * this.d2 * this.a3 + this.d1 * this.a2 * this.c3 - this.d1 * this.c2 * this.a3; + } + + private float coFactorRaw3Col2() { + return this.a1 * this.b2 * this.d3 - this.a1 * this.d2 * this.b3 - this.b1 * this.a2 * this.d3 + this.b1 * this.d2 * this.a3 + this.d1 * this.a2 * this.b3 - this.d1 * this.b2 * this.a3; + } + + private float coFactorRaw3Col3() { + return this.a1 * this.b2 * this.c3 - this.a1 * this.c2 * this.b3 - this.b1 * this.a2 * this.c3 + this.b1 * this.c2 * this.a3 + this.c1 * this.a2 * this.b3 - this.c1 * this.b2 * this.a3; } /** - * @brief Computes a cofactor. Used for matrix inversion. - * @param row Id of raw. - * @param col Id of colomn. - * @return the coFactorValue. - */ - public float coFactor(final int row, final int col) { - return ((this.mat[((row + 1) & 3) * 4 + ((col + 1) & 3)] * this.mat[((row + 2) & 3) * 4 + ((col + 2) & 3)] * this.mat[((row + 3) & 3) * 4 + ((col + 3) & 3)] - + this.mat[((row + 1) & 3) * 4 + ((col + 2) & 3)] * this.mat[((row + 2) & 3) * 4 + ((col + 3) & 3)] * this.mat[((row + 3) & 3) * 4 + ((col + 1) & 3)] - + this.mat[((row + 1) & 3) * 4 + ((col + 3) & 3)] * this.mat[((row + 2) & 3) * 4 + ((col + 1) & 3)] * this.mat[((row + 3) & 3) * 4 + ((col + 2) & 3)]) - - (this.mat[((row + 3) & 3) * 4 + ((col + 1) & 3)] * this.mat[((row + 2) & 3) * 4 + ((col + 2) & 3)] * this.mat[((row + 1) & 3) * 4 + ((col + 3) & 3)] - + this.mat[((row + 3) & 3) * 4 + ((col + 2) & 3)] * this.mat[((row + 2) & 3) * 4 + ((col + 3) & 3)] * this.mat[((row + 1) & 3) * 4 + ((col + 1) & 3)] - + this.mat[((row + 3) & 3) * 4 + ((col + 3) & 3)] * this.mat[((row + 2) & 3) * 4 + ((col + 1) & 3)] * this.mat[((row + 1) & 3) * 4 + ((col + 2) & 3)])) - * (((row + col) & 1) == 1 ? -1.0f : +1.0f); - } - - /** - * @brief Operator-= Decrement an other matrix with this one - * @param obj Reference on the external object - */ - public void decrement(final Matrix4f obj) { - for (int iii = 0; iii < 4 * 4; ++iii) { - this.mat[iii] -= obj.mat[iii]; - } - } - - /** - * @brief Computes the determinant of the matrix. + * Computes the determinant of the matrix. * @return The determinent Value. */ + // https://www.dcode.fr/determinant-matrice + + @CheckReturnValue public float determinant() { - return this.mat[0] * coFactor(0, 0) + this.mat[1] * coFactor(0, 1) + this.mat[2] * coFactor(0, 2) + this.mat[3] * coFactor(0, 3); + return this.a1 * coFactorRaw0Col0() - this.b1 * coFactorRaw0Col1() + this.c1 * coFactorRaw0Col2() - this.d1 * coFactorRaw0Col3(); + /* + return a *(f *k *p −f *l *o −g *j *p +g *l *n +h *j *o −h *k *n )−b *(e *k *p −e *l *o −g *i *p +g *l *m +h *i *o −h *k *m )+c *(e *j *p −e *l *n −f *i *p +f *l *m +h *i *n −h *j *m )−d *(e *j *o −e *k *n −f *i *o +f *k *m +g *i *n −g *j *m ); + a b c d + e f g h + i j k l + m n o p + */ } + @CheckReturnValue + @Deprecated public float[] getTable() { - return this.mat; + float[] mat = new float[16]; + mat[0] = this.a1; + mat[1] = this.b1; + mat[2] = this.c1; + mat[3] = this.d1; + mat[4] = this.a2; + mat[5] = this.b2; + mat[6] = this.c2; + mat[7] = this.d2; + mat[8] = this.a3; + mat[9] = this.b3; + mat[10] = this.c3; + mat[11] = this.d3; + mat[12] = this.a4; + mat[13] = this.b4; + mat[14] = this.c4; + mat[15] = this.d4; + return mat; + } + + @CheckReturnValue + public float[] asArray() { + float[] mat = new float[16]; + mat[0] = this.a1; + mat[1] = this.b1; + mat[2] = this.c1; + mat[3] = this.d1; + mat[4] = this.a2; + mat[5] = this.b2; + mat[6] = this.c2; + mat[7] = this.d2; + mat[8] = this.a3; + mat[9] = this.b3; + mat[10] = this.c3; + mat[11] = this.d3; + mat[12] = this.a4; + mat[13] = this.b4; + mat[14] = this.c4; + mat[15] = this.d4; + return mat; + } + + @CheckReturnValue + public float[] asArrayTransposed() { + float[] mat = new float[16]; + mat[0] = this.a1; + mat[1] = this.a2; + mat[2] = this.a3; + mat[3] = this.a4; + mat[4] = this.b1; + mat[5] = this.b2; + mat[6] = this.b3; + mat[7] = this.b4; + mat[8] = this.c1; + mat[9] = this.c2; + mat[10] = this.c3; + mat[11] = this.c4; + mat[12] = this.d1; + mat[13] = this.d2; + mat[14] = this.d3; + mat[15] = this.d4; + return mat; } /** - * @brief Inverts the matrix. + * Inverts the matrix. * @note The determinant must be != 0, otherwithe the matrix can't be inverted. * @return The inverted matrix. */ - public Matrix4f invertNew() { + @CheckReturnValue + public Matrix4f invert() { final float det = determinant(); if (Math.abs(det) < (1.0e-7f)) { // The matrix is not invertible! Singular case! - return clone(); + return this; } - final Matrix4f temp = new Matrix4f(); - temp.mat[0] = coFactor(0, 0) / det; - temp.mat[1] = coFactor(0, 1) / det; - temp.mat[2] = coFactor(0, 2) / det; - temp.mat[3] = coFactor(0, 3) / det; - temp.mat[4] = coFactor(1, 0) / det; - temp.mat[5] = coFactor(1, 1) / det; - temp.mat[6] = coFactor(1, 2) / det; - temp.mat[7] = coFactor(1, 3) / det; - temp.mat[8] = coFactor(2, 0) / det; - temp.mat[9] = coFactor(2, 1) / det; - temp.mat[10] = coFactor(2, 2) / det; - temp.mat[11] = coFactor(2, 3) / det; - temp.mat[12] = coFactor(3, 0) / det; - temp.mat[13] = coFactor(3, 1) / det; - temp.mat[14] = coFactor(3, 2) / det; - temp.mat[15] = coFactor(3, 3) / det; - return temp; + float a1 = coFactorRaw0Col0() / det; + float b1 = coFactorRaw0Col1() / det; + float c1 = coFactorRaw0Col2() / det; + float d1 = coFactorRaw0Col3() / det; + float a2 = coFactorRaw1Col0() / det; + float b2 = coFactorRaw1Col1() / det; + float c2 = coFactorRaw1Col2() / det; + float d2 = coFactorRaw1Col3() / det; + float a3 = coFactorRaw2Col0() / det; + float b3 = coFactorRaw2Col1() / det; + float c3 = coFactorRaw2Col2() / det; + float d3 = coFactorRaw2Col3() / det; + float a4 = coFactorRaw3Col0() / det; + float b4 = coFactorRaw3Col1() / det; + float c4 = coFactorRaw3Col2() / det; + float d4 = coFactorRaw3Col3() / det; + return new Matrix4f(a1, b1, c1, d1, a2, b2, c2, d2, a3, b3, c3, d3, a4, b4, c4, d4); } /** - * @brief In-Equality compare operator with an other object. - * @param obj Reference on the comparing object - * @return true The Objects are NOT identical - * @return false The Objects are identical - */ - public boolean isDifferent(final Matrix4f obj) { - for (int iii = 0; iii < 4 * 4; ++iii) { - if (this.mat[iii] != obj.mat[iii]) { - return true; - } - } - return false; - } - - /** - * @brief Equality compare operator with an other object. - * @param obj Reference on the comparing object - * @return true The Objects are identical - * @return false The Objects are NOT identical - */ - public boolean isEqual(final Matrix4f obj) { - for (int iii = 0; iii < 4 * 4; ++iii) { - if (this.mat[iii] != obj.mat[iii]) { - return false; - } - } - return true; - } - - /** - * @brief Operator*= Multiplication an other matrix with this one + * Operator*= Multiplication an other matrix with this one * @param obj Reference on the external object */ + @CheckReturnValue public Matrix4f multiply(final Matrix4f obj) { - // output Matrix - final float[] matrixOut = new float[16]; - for (int xxx = 0; xxx < 4; xxx++) { - for (int yyy = 0; yyy < 4; yyy++) { - float value = 0; - for (int kkk = 0; kkk < 4; kkk++) { - value += this.mat[yyy * 4 + kkk] * obj.mat[kkk * 4 + xxx]; - } - matrixOut[yyy * 4 + xxx] = value; - } - } - // set it at the output - for (int iii = 0; iii < 4 * 4; iii++) { - this.mat[iii] = matrixOut[iii]; - } - return this; + float a1 = this.a1 * obj.a1 + this.a2 * obj.b1 + this.a3 * obj.c1 + this.a3 * obj.d1; + float b1 = this.b1 * obj.a1 + this.b2 * obj.b1 + this.b3 * obj.c1 + this.b3 * obj.d1; + float c1 = this.c1 * obj.a1 + this.c2 * obj.b1 + this.c3 * obj.c1 + this.c3 * obj.d1; + float d1 = this.d1 * obj.a1 + this.d2 * obj.b1 + this.d3 * obj.c1 + this.d3 * obj.d1; + + float a2 = this.a1 * obj.a2 + this.a2 * obj.b2 + this.a3 * obj.c2 + this.a3 * obj.d2; + float b2 = this.b1 * obj.a2 + this.b2 * obj.b2 + this.b3 * obj.c2 + this.b3 * obj.d2; + float c2 = this.c1 * obj.a2 + this.c2 * obj.b2 + this.c3 * obj.c2 + this.c3 * obj.d2; + float d2 = this.d1 * obj.a2 + this.d2 * obj.b2 + this.d3 * obj.c2 + this.d3 * obj.d2; + + float a3 = this.a1 * obj.a3 + this.a2 * obj.b3 + this.a3 * obj.c3 + this.a3 * obj.d3; + float b3 = this.b1 * obj.a3 + this.b2 * obj.b3 + this.b3 * obj.c3 + this.b3 * obj.d3; + float c3 = this.c1 * obj.a3 + this.c2 * obj.b3 + this.c3 * obj.c3 + this.c3 * obj.d3; + float d3 = this.d1 * obj.a3 + this.d2 * obj.b3 + this.d3 * obj.c3 + this.d3 * obj.d3; + + float a4 = this.a1 * obj.a4 + this.a2 * obj.b4 + this.a3 * obj.c4 + this.a3 * obj.d4; + float b4 = this.b1 * obj.a4 + this.b2 * obj.b4 + this.b3 * obj.c4 + this.b3 * obj.d4; + float c4 = this.c1 * obj.a4 + this.c2 * obj.b4 + this.c3 * obj.c4 + this.c3 * obj.d4; + float d4 = this.d1 * obj.a4 + this.d2 * obj.b4 + this.d3 * obj.c4 + this.d3 * obj.d4; + return new Matrix4f(a1, b1, c1, d1, a2, b2, c2, d2, a3, b3, c3, d3, a4, b4, c4, d4); } /** - * @brief Operator* apply matrix on a vector + * Operator* apply matrix on a vector * @param point Point value to apply the matrix * @return New vector containing the value */ + @CheckReturnValue public Vector3f multiply(final Vector3f point) { - return new Vector3f(this.mat[0] * point.x + this.mat[1] * point.y + this.mat[2] * point.z + this.mat[3], this.mat[4] * point.x + this.mat[5] * point.y + this.mat[6] * point.z + this.mat[7], - this.mat[8] * point.x + this.mat[9] * point.y + this.mat[10] * point.z + this.mat[11]); - } - - public Matrix4f multiplyNew(final Matrix4f obj) { - return clone().multiply(obj); + return new Vector3f(this.a1 * point.x() + this.b1 * point.y() + this.c1 * point.z() + this.d1, this.a2 * point.x() + this.b2 * point.y() + this.c2 * point.z() + this.d2, + this.a3 * point.x() + this.b3 * point.y() + this.c3 * point.z() + this.d3); } /** - * @brief Makes a rotation matrix about an arbitrary axis. + * Makes a rotation matrix about an arbitrary axis. * @param vect vector to apply the angle. * @param angleRad angle to apply. */ + @CheckReturnValue public Matrix4f rotate(final Vector3f vect, final float angleRad) { final Matrix4f tmpMat = createMatrixRotate(vect, angleRad); return this.multiply(tmpMat); } - public Matrix4f rotateNew(final Vector3f vect, final float angleRad) { - final Matrix4f tmpMat = createMatrixRotate(vect, angleRad); - return multiplyNew(tmpMat); - } - /** - * @brief Scale the current Matrix in all direction with 1 value. + * Scale the current Matrix in all direction with 1 value. * @param scale Scale XYZ value to apply. */ + @CheckReturnValue public Matrix4f scale(final float scale) { return scale(scale, scale, scale); } /** - * @brief Scale the current Matrix. + * Scale the current Matrix. * @param sx Scale X value to apply. * @param sy Scale Y value to apply. * @param sz Scale Z value to apply. */ + @CheckReturnValue public Matrix4f scale(final float sx, final float sy, final float sz) { - this.mat[0] *= sx; - this.mat[1] *= sy; - this.mat[2] *= sz; - this.mat[4] *= sx; - this.mat[5] *= sy; - this.mat[6] *= sz; - this.mat[8] *= sx; - this.mat[9] *= sy; - this.mat[10] *= sz; - return this; + float a1 = this.a1 * sx; + float b1 = this.b1 * sy; + float c1 = this.c1 * sz; + float a2 = this.a2 * sx; + float b2 = this.b2 * sy; + float c2 = this.c2 * sz; + float a3 = this.a3 * sx; + float b3 = this.b3 * sy; + float c3 = this.c3 * sz; + return new Matrix4f(a1, b1, c1, this.d1, a2, b2, c2, this.d2, a3, b3, c3, this.d3, this.a4, this.b4, this.c4, this.d4); } /** - * @brief Scale the current Matrix. + * Scale the current Matrix. * @param vect Scale vector to apply. */ + @CheckReturnValue public Matrix4f scale(final Vector3f vect) { - return scale(vect.x, vect.y, vect.z); - } - - public Matrix4f scaleNew(final float scale) { - return clone().scale(scale, scale, scale); - } - - public Matrix4f scaleNew(final float sx, final float sy, final float sz) { - return clone().scale(sx, sy, sz); - } - - public Matrix4f scaleNew(final Vector3f vect) { - return clone().scale(vect.x, vect.y, vect.z); + return scale(vect.x(), vect.y(), vect.z()); } /** - * @brief Operator= Asign the current object with an other object - * @param obj Reference on the external object + * configure identity of the matrix */ - public void set(final Matrix4f obj) { - for (int iii = 0; iii < 16; iii++) { - this.mat[iii] = obj.mat[iii]; - } - } + public static final Matrix4f IDENTITY = new Matrix4f(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); /** - * @brief configure identity of the matrix - */ - public void setIdentity() { - for (int iii = 0; iii < 4 * 4; iii++) { - this.mat[iii] = 0; - } - this.mat[0] = 1.0f; - this.mat[5] = 1.0f; - this.mat[10] = 1.0f; - this.mat[15] = 1.0f; - } - - /** - * @brief Makes a translation of the matrix + * Makes a translation of the matrix * @param vect Translation to apply. */ + @CheckReturnValue public Matrix4f translate(final Vector3f vect) { final Matrix4f tmpMat = createMatrixTranslate(vect); return this.multiply(tmpMat); } - public Matrix4f translateNew(final Vector3f vect) { - final Matrix4f tmpMat = createMatrixTranslate(vect); - return multiplyNew(tmpMat); - } - /** - * @brief Transpose the current matix (usefull for OpenGL display) + * Transpose the current matix (usefull for OpenGL display) */ + @CheckReturnValue public Matrix4f transpose() { - float tmpVal = this.mat[1]; - this.mat[1] = this.mat[4]; - this.mat[4] = tmpVal; - - tmpVal = this.mat[2]; - this.mat[2] = this.mat[8]; - this.mat[8] = tmpVal; - - tmpVal = this.mat[6]; - this.mat[6] = this.mat[9]; - this.mat[9] = tmpVal; - - tmpVal = this.mat[3]; - this.mat[3] = this.mat[12]; - this.mat[12] = tmpVal; - - tmpVal = this.mat[7]; - this.mat[7] = this.mat[13]; - this.mat[13] = tmpVal; - - tmpVal = this.mat[11]; - this.mat[11] = this.mat[14]; - this.mat[14] = tmpVal; - return this; - } - - public Matrix4f transposeNew() { - return clone().transpose(); + return new Matrix4f(this.a1, this.a2, this.a3, this.a4, this.b1, this.b2, this.b3, this.b4, this.c1, this.c2, this.c3, this.c4, this.d1, this.d2, this.d3, this.d4); } } diff --git a/src/org/atriasoft/etk/math/Quaternion.java b/src/org/atriasoft/etk/math/Quaternion.java index c5c80e8..f41f27f 100644 --- a/src/org/atriasoft/etk/math/Quaternion.java +++ b/src/org/atriasoft/etk/math/Quaternion.java @@ -1,247 +1,144 @@ package org.atriasoft.etk.math; -public class Quaternion { +import edu.umd.cs.findbugs.annotations.CheckReturnValue; + +@SuppressWarnings("preview") +public record Quaternion( + float x, + float y, + float z, + float w) { // a * diff = b public static Quaternion diff(final Quaternion a, final Quaternion b) { // Log.info("diff " + a + " " + b); - final Quaternion inv = a.inverseNew(); + final Quaternion inv = a.inverse(); return inv.multiply(b); } - /** @brief get an identity quaternion - * @return an identity quaternion */ - public static Quaternion identity() { - return new Quaternion(0, 0, 0, 1); - } - - /** @brief get a 0 value on all a quaternion - * @return a (float)Math. quaternion */ - public static Quaternion zero() { - return new Quaternion(0, 0, 0, 0); - } - - public float x; - - public float y; - - public float z; - - public float w; - - /** @brief No initialization constructor (faster ...) */ - public Quaternion() { - this.x = 0.0f; - this.y = 0.0f; - this.z = 0.0f; - this.w = 1.0f; - } - /* void checkValues() { if ( isinf(this.x) == true || isnan(this.x) == true || isinf(this.y) == true || isnan(this.y) == true || isinf(this.z) == true || isnan(this.z) == true || isinf(this.w) == * true || isnan(this.w) == true) { TKCRITICAL(" set transform: (" << this.x << "," << this.y << "," << this.z << "," << this.w << ")"); } } */ /** - * @brief Constructor from scalars. + * Constructor from scalars. * @param xxx X value * @param yyy Y value * @param zzz Z value * @param www W value */ - public Quaternion(final float xxx, final float yyy, final float zzz, final float www) { - this.x = xxx; - this.y = yyy; - this.z = zzz; - this.w = www; + public Quaternion(final float x, final float y, final float z, final float w) { + this.x = x; + this.y = y; + this.z = z; + this.w = w; } /** - * @brief Constructor with the component w and a vector 3D. + * Constructor with the component w and a vector 3D. * @param www W value * @param vec 3D vector value */ public Quaternion(final float www, final Vector3f vec) { - this.x = vec.x; - this.y = vec.y; - this.z = vec.z; - this.w = www; + this(vec.x(), vec.y(), vec.z(), www); } - /** @brief Create a unit quaternion from a rotation matrix + /** Create a unit quaternion from a rotation matrix * @param matrix generic matrix */ - public Quaternion(final Matrix3f matrix) { + public static Quaternion createFromMatrix(final Matrix3f matrix) { final float trace = matrix.getTrace(); + float x, y, z, w; if (trace < 0.0f) { - if (matrix.mat[4] > matrix.mat[0]) { - if (matrix.mat[8] > matrix.mat[4]) { - final float rrr = (float) Math.sqrt(matrix.mat[8] - matrix.mat[0] - matrix.mat[4] + 1.0f); + if (matrix.b2() > matrix.a1()) { + if (matrix.c3() > matrix.b2()) { + final float rrr = (float) Math.sqrt(matrix.c3() - matrix.a1() - matrix.b2() + 1.0f); final float sss = 0.5f / rrr; - this.x = (matrix.mat[6] + matrix.mat[2]) * sss; - this.y = (matrix.mat[5] + matrix.mat[7]) * sss; - this.z = 0.5f * rrr; - this.w = (matrix.mat[3] - matrix.mat[1]) * sss; + x = (matrix.c1() + matrix.a3()) * sss; + y = (matrix.b3() + matrix.c2()) * sss; + z = 0.5f * rrr; + w = (matrix.b1() - matrix.a2()) * sss; } else { - final float rrr = (float) Math.sqrt(matrix.mat[4] - matrix.mat[8] - matrix.mat[0] + 1.0f); + final float rrr = (float) Math.sqrt(matrix.b2() - matrix.c3() - matrix.a1() + 1.0f); final float sss = 0.5f / rrr; - this.x = (matrix.mat[1] + matrix.mat[3]) * sss; - this.y = 0.5f * rrr; - this.z = (matrix.mat[5] + matrix.mat[7]) * sss; - this.w = (matrix.mat[2] - matrix.mat[6]) * sss; + x = (matrix.a2() + matrix.b1()) * sss; + y = 0.5f * rrr; + z = (matrix.b3() + matrix.c2()) * sss; + w = (matrix.a3() - matrix.c1()) * sss; } - } else if (matrix.mat[8] > matrix.mat[0]) { - final float rrr = (float) Math.sqrt(matrix.mat[8] - matrix.mat[0] - matrix.mat[4] + 1.0f); + } else if (matrix.c3() > matrix.a1()) { + final float rrr = (float) Math.sqrt(matrix.c3() - matrix.a1() - matrix.b2() + 1.0f); final float sss = 0.5f / rrr; - this.x = (matrix.mat[6] + matrix.mat[2]) * sss; - this.y = (matrix.mat[5] + matrix.mat[7]) * sss; - this.z = 0.5f * rrr; - this.w = (matrix.mat[3] - matrix.mat[1]) * sss; + x = (matrix.c1() + matrix.a3()) * sss; + y = (matrix.b3() + matrix.c2()) * sss; + z = 0.5f * rrr; + w = (matrix.b1() - matrix.a2()) * sss; } else { - final float rrr = (float) Math.sqrt(matrix.mat[0] - matrix.mat[4] - matrix.mat[8] + 1.0f); + final float rrr = (float) Math.sqrt(matrix.a1() - matrix.b2() - matrix.c3() + 1.0f); final float sss = 0.5f / rrr; - this.x = 0.5f * rrr; - this.y = (matrix.mat[1] + matrix.mat[3]) * sss; - this.z = (matrix.mat[6] - matrix.mat[2]) * sss; - this.w = (matrix.mat[7] - matrix.mat[5]) * sss; + x = 0.5f * rrr; + y = (matrix.a2() + matrix.b1()) * sss; + z = (matrix.c1() - matrix.a3()) * sss; + w = (matrix.c2() - matrix.b3()) * sss; } } else { final float rrr = (float) Math.sqrt(trace + 1.0f); final float sss = 0.5f / rrr; - this.x = (matrix.mat[7] - matrix.mat[5]) * sss; - this.y = (matrix.mat[2] - matrix.mat[6]) * sss; - this.z = (matrix.mat[3] - matrix.mat[1]) * sss; - this.w = 0.5f * rrr; + x = (matrix.c2() - matrix.b3()) * sss; + y = (matrix.a3() - matrix.c1()) * sss; + z = (matrix.b1() - matrix.a2()) * sss; + w = 0.5f * rrr; } + return new Quaternion(x, y, z, w); } - public Quaternion(final Quaternion obj) { - this.x = obj.x; - this.y = obj.y; - this.z = obj.z; - this.w = obj.w; - } - - /** @brief Constructor with Euler angles (in radians) to a quaternion - * @param eulerAngles list of all euler angle */ - public Quaternion(final Vector3f eulerAngles) { - setEulerAngles(eulerAngles); - } - - /** @brief Set the absolute values of each element */ + /** Set the absolute values of each element */ + @CheckReturnValue public Quaternion absolute() { - this.x = Math.abs(this.x); - this.y = Math.abs(this.y); - this.z = Math.abs(this.z); - this.w = Math.abs(this.w); - return this; - } - - /** @brief Return a quaternion will the absolute values of each element - * @return New quaternion with the absolute value */ - public Quaternion absoluteNew() { return new Quaternion(Math.abs(this.x), Math.abs(this.y), Math.abs(this.z), Math.abs(this.w)); } - /** @brief Add a vector to this one. - * @param obj The vector to add to this one - * @return Local reference of the vector */ - public Quaternion add(final Quaternion obj) { - this.x += obj.x; - this.y += obj.y; - this.z += obj.z; - this.w += obj.w; - return this; - } - - /** @brief Add a vector to this one. + /** Add a vector to this one. * @param obj The vector to add to this one * @return New vector containing the value */ - public Quaternion addNew(final Quaternion obj) { + @CheckReturnValue + public Quaternion add(final Quaternion obj) { return new Quaternion(this.x + obj.x, this.y + obj.y, this.z + obj.z, this.w + obj.w); } - /** @brief Clone the current Quaternion. - * @return New Quaternion containing the value */ - @Override - public Quaternion clone() { - return new Quaternion(this); - } - - /** @brief Conjugate the quaternion */ + /** Conjugate the quaternion */ + @CheckReturnValue public Quaternion conjugate() { - this.x *= -1.0f; - this.y *= -1.0f; - this.z *= -1.0f; - return this; + return new Quaternion(this.x * -1.0f, this.y * -1.0f, this.z * -1.0f, this.w); } - /** @brief Return the conjugate of the quaternion - * @return Conjugate quaternion */ - public Quaternion conjugateNew() { - final Quaternion tmp = new Quaternion(this); - tmp.conjugate(); - return tmp; - } - - /** @brief Inversely scale the quaternion - * @param val Scale factor to divide by. - * @return Local reference of the quaternion */ - public Quaternion devide(final float val) { - if (val != 0) { - this.x /= val; - this.y /= val; - this.z /= val; - this.w /= val; - } - return this; - } - - /** @brief Inversely scale the quaternion + /** Inversely scale the quaternion * @param val Scale factor to divide by. * @return New quaternion containing the value */ - public Quaternion devideNew(final float val) { + public Quaternion devide(final float val) { if (val != 0) { return new Quaternion(this.x / val, this.y / val, this.z / val, this.w / val); } - return clone(); + return this; } - /** @brief Return the dot product + /** Return the dot product * @param obj The other quaternion in the dot product * @return Dot result value */ + @CheckReturnValue public float dot(final Quaternion obj) { return this.x * obj.x + this.y * obj.y + this.z * obj.z + this.w * obj.w; } - @Override - public boolean equals(final Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Quaternion other = (Quaternion) obj; - if (Float.floatToIntBits(this.x) != Float.floatToIntBits(other.x)) { - return false; - } - if (Float.floatToIntBits(this.y) != Float.floatToIntBits(other.y)) { - return false; - } - if (Float.floatToIntBits(this.z) != Float.floatToIntBits(other.z)) { - return false; - } - return Float.floatToIntBits(this.w) == Float.floatToIntBits(other.w); - } - - /** @brief Compute the rotation angle (in radians) and the rotation axis + /** Compute the rotation angle (in radians) and the rotation axis * @param angle Angle of the quaternion - * @param axis Axis of the quaternion */ - public void getAngleAxis(float angle, final Vector3f axis) { + * @return Axis of the quaternion */ + @CheckReturnValue + public Vector3f getAngleAxis(float angle) { final Quaternion quaternion = getUnit(); angle = (float) Math.acos(quaternion.w) * 2.0f; - Vector3f rotationAxis = new Vector3f(quaternion.x, quaternion.y, quaternion.z); - rotationAxis = rotationAxis.normalizeNew(); - axis.setValue(rotationAxis.x, rotationAxis.y, rotationAxis.z); + Vector3f rotationAxis = quaternion.getVectorV(); + return rotationAxis.normalize(); } - /** @brief Get the orientation matrix corresponding to this quaternion + /** Get the orientation matrix corresponding to this quaternion * @return the 3x3 transformation matrix */ + @CheckReturnValue public Matrix3f getMatrix() { final float nQ = this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; float sss = 0.0f; @@ -263,8 +160,8 @@ public class Quaternion { return new Matrix3f(1.0f - yys - zzs, xys - wzs, xzs + wys, xys + wzs, 1.0f - xxs - zzs, yzs - wxs, xzs - wys, yzs + wxs, 1.0f - xxs - yys); } + @CheckReturnValue public Matrix4f getMatrix4() { - final float nQ = this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; float sss = 0.0f; if (nQ > 0.0f) { @@ -285,365 +182,178 @@ public class Quaternion { return new Matrix4f(1.0f - yys - zzs, xys - wzs, xzs + wys, 0, xys + wzs, 1.0f - xxs - zzs, yzs - wxs, 0, xzs - wys, yzs + wxs, 1.0f - xxs - yys, 0, 0, 0, 0, 1); } - public void getMatrixTo(final Matrix3f out) { - final float nQ = this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; - float sss = 0.0f; - if (nQ > 0.0f) { - sss = 2.0f / nQ; - } - final float xs = this.x * sss; - final float ys = this.y * sss; - final float zs = this.z * sss; - final float wxs = this.w * xs; - final float wys = this.w * ys; - final float wzs = this.w * zs; - final float xxs = this.x * xs; - final float xys = this.x * ys; - final float xzs = this.x * zs; - final float yys = this.y * ys; - final float yzs = this.y * zs; - final float zzs = this.z * zs; - out.set(1.0f - yys - zzs, xys - wzs, xzs + wys, xys + wzs, 1.0f - xxs - zzs, yzs - wxs, xzs - wys, yzs + wxs, 1.0f - xxs - yys); - } - - /** @brief Return the unit quaternion + /** Return the unit quaternion * @return Quaternion unitarised */ + @CheckReturnValue public Quaternion getUnit() { - return normalizeNew(); + return normalize(); } - /** @brief get x, y, z in a Vector3f */ + /** get x, y, z in a Vector3f */ + @CheckReturnValue public Vector3f getVectorV() { return new Vector3f(this.x, this.y, this.z); } - /** @brief Get W value - * @return the w value */ - public float getW() { - return this.w; - } - - /** @brief Get X value - * @return the x value */ - public float getX() { - return this.x; - }; - - /** @brief Get Y value - * @return the y value */ - public float getY() { - return this.y; - }; - - /** @brief Get Z value - * @return the z value */ - public float getZ() { - return this.z; - }; - - @Override - public int hashCode() { - int hash = 7564; - hash += Float.floatToIntBits(this.x); - hash += Float.floatToIntBits(this.y); - hash += Float.floatToIntBits(this.z); - hash += Float.floatToIntBits(this.w); - return hash; - } - - /** @brief Inverse the quaternion */ + /** Inverse the quaternion */ + @CheckReturnValue public Quaternion inverse() { final float invLengthSquare = 1.0f / length2(); - this.x *= -invLengthSquare; - this.y *= -invLengthSquare; - this.z *= -invLengthSquare; - this.w *= invLengthSquare; - return this; + return new Quaternion(this.x * -invLengthSquare, this.y * -invLengthSquare, this.z * -invLengthSquare, this.w * invLengthSquare); } - /** @brief Return the inverse of the quaternion - * @return inverted quaternion */ - public Quaternion inverseNew() { - final Quaternion tmp = new Quaternion(this); - tmp.inverse(); - return tmp; - } - - /** @brief In-Equality compare operator with an other object. + /** In-Equality compare operator with an other object. * @param obj Reference on the comparing object * @return true The Objects are NOT identical * @return false The Objects are identical */ + @CheckReturnValue public boolean isDifferent(final Quaternion obj) { return ((this.w != obj.w) || (this.z != obj.z) || (this.y != obj.y) || (this.x != obj.x)); } - /** @brief Equality compare operator with an other object. + /** Equality compare operator with an other object. * @param obj Reference on the comparing object * @return true The Objects are identical * @return false The Objects are NOT identical */ + @CheckReturnValue public boolean isEqual(final Quaternion obj) { return ((this.w == obj.w) && (this.z == obj.z) && (this.y == obj.y) && (this.x == obj.x)); } - /** @brief Check if the quaternion is equal to (0,0,0,0) + /** Check if the quaternion is equal to (0,0,0,0) * @return true The value is equal to (0,0,0,0) * @return false The value is NOT equal to (0,0,0,0) */ + @CheckReturnValue public boolean isZero() { return this.x == 0 && this.y == 0 && this.z == 0 && this.w == 0; } - /** @brief Return the length of the quaternion + /** Return the length of the quaternion * @return Length value */ + @CheckReturnValue public float length() { return (float) Math.sqrt(length2()); } - /** @brief Return the squared length of the quaternion. + /** Return the squared length of the quaternion. * @return Squared length value. */ + @CheckReturnValue public float length2() { return dot(this); } - /** @brief Subtract a vector from this one - * @param obj The vector to subtract - * @return Local reference of the vector */ - public Quaternion less(final Quaternion obj) { - this.x -= obj.x; - this.y -= obj.y; - this.z -= obj.z; - this.w -= obj.w; - return this; - } - - /** @brief Subtract a vector from this one + /** Subtract a vector from this one * @param obj The vector to subtract * @return New quaternion containing the value */ - public Quaternion lessNew(final Quaternion obj) { + @CheckReturnValue + public Quaternion less(final Quaternion obj) { return new Quaternion(this.x - obj.x, this.y - obj.y, this.z - obj.z, this.w - obj.w); } - /** @brief Scale the quaternion - * @param val Scale factor - * @return Local reference of the quaternion */ - public Quaternion multiply(final float val) { - this.x *= val; - this.y *= val; - this.z *= val; - this.w *= val; - return this; - } - + @CheckReturnValue public Vector3f multiply(final float xxx, final float yyy, final float zzz) { final Vector3f point = new Vector3f(xxx, yyy, zzz); final Vector3f qvec = getVectorV(); - final Vector3f uv = qvec.cross(point); - final Vector3f uuv = qvec.cross(uv); - uv.multiply(2.0f * this.w); - uuv.multiply(2.0f); + Vector3f uv = qvec.cross(point); + Vector3f uuv = qvec.cross(uv); + uv = uv.multiply(2.0f * this.w); + uuv = uuv.multiply(2.0f); return uv.add(point).add(uuv); } - /** @brief Multiply this quaternion by the other. + /** Multiply this quaternion by the other. * @param obj The other quaternion * @return Local reference of the quaternion */ + @CheckReturnValue public Quaternion multiply(final Quaternion obj) { final Vector3f base = getVectorV(); final Vector3f crossValue = base.cross(obj.getVectorV()); - this.x = this.w * obj.x + obj.w * this.x + crossValue.x; - this.y = this.w * obj.y + obj.w * this.y + crossValue.y; - this.z = this.w * obj.z + obj.w * this.z + crossValue.z; - this.w = this.w * obj.w - base.dot(obj.getVectorV()); - safeNormalize(); - return this; + float x = this.w * obj.x + obj.w * this.x + crossValue.x(); + float y = this.w * obj.y + obj.w * this.y + crossValue.y(); + float z = this.w * obj.z + obj.w * this.z + crossValue.z(); + float w = this.w * obj.w - base.dot(obj.getVectorV()); + return (new Quaternion(x, y, z, w)).safeNormalize(); } - /** @brief Operator* with a vector. This methods rotates a point given the rotation of a quaternion + /** Operator* with a vector. This methods rotates a point given the rotation of a quaternion * @param point Point to move * @return Point with the updated position */ + @CheckReturnValue public Vector3f multiply(final Vector3f point) { final Vector3f qvec = getVectorV(); - final Vector3f uv = qvec.cross(point); - final Vector3f uuv = qvec.cross(uv); - uv.multiply(2.0f * this.w); - uuv.multiply(2.0f); + Vector3f uv = qvec.cross(point); + Vector3f uuv = qvec.cross(uv); + uv = uv.multiply(2.0f * this.w); + uuv = uuv.multiply(2.0f); return uv.add(point).add(uuv); } - /** @brief Scale the quaternion + /** Scale the quaternion * @param val Scale factor * @return New quaternion containing the value */ - public Quaternion multiplyNew(final float val) { + @CheckReturnValue + public Quaternion multiply(final float val) { return new Quaternion(this.x * val, this.y * val, this.z * val, this.w * val); } - /** @brief Multiply this quaternion by the other. - * @param obj The other quaternion - * @return New quaternion containing the value */ - public Quaternion multiplyNew(final Quaternion obj) { - final Quaternion tmp = new Quaternion(this); - tmp.multiply(obj); - return tmp; - } - - /** @brief Normalize this quaternion x^2 + y^2 + z^2 + w^2 = 1 + /** Normalize this quaternion x^2 + y^2 + z^2 + w^2 = 1 * @return Local reference of the quaternion normalized */ + @CheckReturnValue public Quaternion normalize() { final float invLength = 1.0f / length(); - this.x *= invLength; - this.y *= invLength; - this.z *= invLength; - this.w *= invLength; - return this; + return new Quaternion(this.x * invLength, this.y * invLength, this.z * invLength, this.w * invLength); } - /** @brief Return a normalized version of this quaternion - * @return New quaternion containing the value */ - public Quaternion normalizeNew() { - final Quaternion tmp = new Quaternion(this); - tmp.normalize(); - return tmp; - } - - /** @brief Normalize this quaternion x^2 + y^2 + z^2 + w^2 = 1 + /** Normalize this quaternion x^2 + y^2 + z^2 + w^2 = 1 * @return Local reference of the quaternion normalized */ + @CheckReturnValue public Quaternion safeNormalize() { final float lengthTmp = length(); if (lengthTmp == 0.0f) { - this.x = 0.0f; - this.y = 0.0f; - this.z = 0.0f; - this.w = 1.0f; - return this; + return IDENTITY; } - - final double invLength = 1.0 / lengthTmp; - this.x = (float) (this.x * invLength); - this.y = (float) (this.y * invLength); - this.z = (float) (this.z * invLength); - this.w = (float) (this.w * invLength); - - /* - this.x /= lengthTmp; - this.y /= lengthTmp; - this.z /= lengthTmp; - this.w /= lengthTmp; - */ - return this; + return normalize(); } - /** @brief Return a normalized version of this quaternion - * @return New quaternion containing the value */ - public Quaternion safeNormalizeNew() { - final Quaternion tmp = new Quaternion(this); - tmp.safeNormalize(); - return tmp; - } - - /** - * @brief Constructor from scalars. - * @param xxx X value - * @param yyy Y value - * @param zzz Z value - * @param www W value */ - public Quaternion set(final float xxx, final float yyy, final float zzz, final float www) { - this.x = xxx; - this.y = yyy; - this.z = zzz; - this.w = www; - return this; - } - - /** - * @brief Constructor with the component w and a vector 3D. - * @param www W value - * @param vec 3D vector value - */ - public Quaternion set(final float www, final Vector3f obj) { - this.x = obj.x; - this.y = obj.y; - this.z = obj.z; - this.w = www; - return this; - } - - public Quaternion set(final Quaternion obj) { - this.x = obj.x; - this.y = obj.y; - this.z = obj.z; - this.w = obj.w; - return this; - } - - /** @brief Configure the quaternion with euler angles. + /** Configure the quaternion with euler angles. * @param angles Eular angle of the quaternion. */ - public void setEulerAngles(final Vector3f angles) { - float angle = angles.x * 0.5f; + @CheckReturnValue + public static Quaternion fromEulerAngles(final Vector3f angles) { + float angle = angles.x() * 0.5f; final float sinX = (float) Math.sin(angle); final float cosX = (float) Math.cos(angle); - angle = angles.y * 0.5f; + angle = angles.y() * 0.5f; final float sinY = (float) Math.sin(angle); final float cosY = (float) Math.cos(angle); - angle = angles.z * 0.5f; + angle = angles.z() * 0.5f; final float sinZ = (float) Math.sin(angle); final float cosZ = (float) Math.cos(angle); final float cosYcosZ = cosY * cosZ; final float sinYcosZ = sinY * cosZ; final float cosYsinZ = cosY * sinZ; final float sinYsinZ = sinY * sinZ; - this.x = sinX * cosYcosZ - cosX * sinYsinZ; - this.y = cosX * sinYcosZ + sinX * cosYsinZ; - this.z = cosX * cosYsinZ - sinX * sinYcosZ; - this.w = cosX * cosYcosZ + sinX * sinYsinZ; - normalize(); + float x = sinX * cosYcosZ - cosX * sinYsinZ; + float y = cosX * sinYcosZ + sinX * cosYsinZ; + float z = cosX * cosYsinZ - sinX * sinYcosZ; + float w = cosX * cosYcosZ + sinX * sinYsinZ; + return (new Quaternion(x, y, z, w)).normalize(); } - /** @brief Set identity value at the quaternion */ - public void setIdentity() { - setValue(0, 0, 0, 1); - } + /** Set identity value at the quaternion */ + public static final Quaternion IDENTITY = new Quaternion(0, 0, 0, 1); - /** @brief Set each element to the max of the current values and the values of another Vector + /** Set each element to the max of the current values and the values of another Vector * @param obj The other Vector to compare with */ - public void setMax(final Quaternion obj) { - this.x = Math.max(this.x, obj.x); - this.y = Math.max(this.y, obj.y); - this.z = Math.max(this.z, obj.z); - this.w = Math.max(this.w, obj.w); + @CheckReturnValue + public Quaternion max(final Quaternion obj) { + return new Quaternion(Math.max(this.x, obj.x), Math.max(this.y, obj.y), Math.max(this.z, obj.z), Math.max(this.w, obj.w)); } - /** @brief Set each element to the min of the current values and the values of another Vector + /** Set each element to the min of the current values and the values of another Vector * @param obj The other Vector to compare with */ - public void setMin(final Quaternion obj) { - this.x = Math.min(this.x, obj.x); - this.y = Math.min(this.y, obj.y); - this.z = Math.min(this.z, obj.z); - this.w = Math.min(this.w, obj.w); - } - - /** @brief Set Value on the quaternion - * @param xxx X value. - * @param yyy Y value. - * @param zzz Z value. - * @param www W value. */ - public void setValue(final float xxx, final float yyy, final float zzz, final float www) { - this.x = xxx; - this.y = yyy; - this.z = zzz; - this.w = www; - } - - /** @brief Set the w value - * @param w New value */ - public Quaternion setW(final float w) { - this.w = w; - return this; - } - - /** @brief Set the x value - * @param x New value */ - public Quaternion setX(final float x) { - this.x = x; - return this; + @CheckReturnValue + public Quaternion min(final Quaternion obj) { + return new Quaternion(Math.min(this.x, obj.x), Math.min(this.y, obj.y), Math.min(this.z, obj.z), Math.min(this.w, obj.w)); } // Compute the rotation angle (in radians) and the rotation axis @@ -670,29 +380,13 @@ public class Quaternion { } */ - /** @brief Set the y value - * @param y New value */ - public Quaternion setY(final float y) { - this.y = y; - return this; - } + public static final Quaternion ZERO = new Quaternion(0, 0, 0, 0); - /** @brief Set the z value - * @param z New value */ - public Quaternion setZ(final float z) { - this.z = z; - return this; - } - - /** @brief Set 0 value on all the quaternion */ - public void setZero() { - setValue(0, 0, 0, 0); - } - - /** @brief Compute the spherical linear interpolation between two quaternions. + /** Compute the spherical linear interpolation between two quaternions. * @param obj1 First quaternion * @param obj2 Second quaternion * @param ttt linar coefficient interpolation to be such that [0..1] */ + @CheckReturnValue public Quaternion slerp(final Quaternion obj2, final float ttt) { // TKASSERT(ttt >= 0.0f ttt <= 1.0f, "wrong intermolation"); float invert = 1.0f; @@ -702,13 +396,13 @@ public class Quaternion { invert = -1.0f; } if (1 - cosineTheta < 0.00001f) { - return this.multiplyNew(1.0f - ttt).add(obj2.multiplyNew(ttt * invert)); + return this.multiply(1.0f - ttt).add(obj2.multiply(ttt * invert)); } final float theta = (float) Math.acos(cosineTheta); final float sineTheta = (float) Math.sin(theta); final float coeff1 = (float) Math.sin((1.0f - ttt) * theta) / sineTheta; final float coeff2 = (float) Math.sin(ttt * theta) / sineTheta * invert; - return this.multiplyNew(coeff1).add(obj2.multiplyNew(coeff2)); + return this.multiply(coeff1).add(obj2.multiply(coeff2)); } @Override diff --git a/src/org/atriasoft/etk/math/Transform3D.java b/src/org/atriasoft/etk/math/Transform3D.java index cabf555..e81a46b 100644 --- a/src/org/atriasoft/etk/math/Transform3D.java +++ b/src/org/atriasoft/etk/math/Transform3D.java @@ -1,206 +1,127 @@ package org.atriasoft.etk.math; -public class Transform3D { +import edu.umd.cs.findbugs.annotations.CheckReturnValue; + +@SuppressWarnings("preview") +public record Transform3D( + // Position + Vector3f position, + // Orientation + Quaternion orientation) { /** - * @brief Get the identity of the transformation + * Get the identity of the transformation */ - public static Transform3D identity() { - return new Transform3D(Vector3f.zero(), Quaternion.identity()); - } - - // Position - protected Vector3f position; - // Orientation - protected Quaternion orientation; - - public Transform3D() { - this.position = Vector3f.zero(); - this.orientation = Quaternion.identity(); - } - - public Transform3D(final Transform3D transform3d) { - this.position = transform3d.position.clone(); - this.orientation = transform3d.orientation.clone(); - } + public static final Transform3D IDENTITY = new Transform3D(Vector3f.ZERO, Quaternion.IDENTITY); public Transform3D(final Vector3f position) { - this.position = position.clone(); - this.orientation = Quaternion.identity(); + this(position, Quaternion.IDENTITY); } public Transform3D(final Vector3f position, final Matrix3f orientation) { - this.position = position.clone(); - this.orientation = new Quaternion(orientation); + this(position, Quaternion.createFromMatrix(orientation)); } public Transform3D(final Vector3f position, final Quaternion orientation) { - this.position = position.clone(); - this.orientation = orientation.clone(); + this.position = position; + this.orientation = orientation; } - public void applyRotation(final Quaternion rotation) { - this.orientation = this.orientation.multiply(rotation); + @CheckReturnValue + public Transform3D rotate(final Quaternion rotation) { + return new Transform3D(this.position, this.orientation.multiply(rotation)); } - /** - * @brief Clone the current Transform3D. - * @return New Transform3D containing the value - */ - @Override - public Transform3D clone() { - return new Transform3D(this); + @CheckReturnValue + public Transform3D withOrientation(final Quaternion orientation) { + return new Transform3D(this.position, orientation); } - @Override - public boolean equals(final Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Transform3D other = (Transform3D) obj; - if (!this.position.equals(this.position)) { - return false; - } - return this.orientation.equals(other.orientation); + @CheckReturnValue + public Transform3D withPosition(final Vector3f position) { + return new Transform3D(position, this.orientation); } /// Get the OpenGL matrix of the transform + @CheckReturnValue public Matrix4f getOpenGLMatrix() { - final Matrix4f out = new Matrix4f(); final Matrix3f tmpMatrix = this.orientation.getMatrix(); - out.mat[0] = tmpMatrix.mat[0]; - out.mat[1] = tmpMatrix.mat[1]; - out.mat[2] = tmpMatrix.mat[2]; - out.mat[3] = this.position.x; - out.mat[4] = tmpMatrix.mat[3]; - out.mat[5] = tmpMatrix.mat[4]; - out.mat[6] = tmpMatrix.mat[5]; - out.mat[7] = this.position.y; - out.mat[8] = tmpMatrix.mat[6]; - out.mat[9] = tmpMatrix.mat[7]; - out.mat[10] = tmpMatrix.mat[8]; - out.mat[11] = this.position.z; - out.mat[12] = 0.0f; - out.mat[13] = 0.0f; - out.mat[14] = 0.0f; - out.mat[15] = 1.0f; - return out; + return new Matrix4f(tmpMatrix.a1(), tmpMatrix.a2(), tmpMatrix.a3(), this.position.x(), tmpMatrix.b1(), tmpMatrix.b2(), tmpMatrix.b3(), this.position.y(), tmpMatrix.c1(), tmpMatrix.c2(), + tmpMatrix.c3(), this.position.z(), 0.0f, 0.0f, 0.0f, 1.0f); } /// Get the OpenGL matrix of the transform + @CheckReturnValue public Matrix4f getOpenGLMatrixTransposed() { - final Matrix4f out = new Matrix4f(); final Matrix3f tmpMatrix = this.orientation.getMatrix(); - // version transposer... - out.mat[0] = tmpMatrix.mat[0]; - out.mat[1] = tmpMatrix.mat[3]; - out.mat[2] = tmpMatrix.mat[6]; - out.mat[3] = 0.0f; - out.mat[4] = tmpMatrix.mat[1]; - out.mat[5] = tmpMatrix.mat[4]; - out.mat[6] = tmpMatrix.mat[7]; - out.mat[7] = 0.0f; - out.mat[8] = tmpMatrix.mat[2]; - out.mat[9] = tmpMatrix.mat[5]; - out.mat[10] = tmpMatrix.mat[8]; - out.mat[11] = 0.0f; - out.mat[12] = this.position.x; - out.mat[13] = this.position.y; - out.mat[14] = this.position.z; - out.mat[15] = 1.0f; - return out; + return new Matrix4f(tmpMatrix.a1(), tmpMatrix.b1(), tmpMatrix.c1(), 0.0f, tmpMatrix.a2(), tmpMatrix.b2(), tmpMatrix.c2(), 0.0f, tmpMatrix.a3(), tmpMatrix.b3(), tmpMatrix.c3(), 0.0f, + this.position.x(), this.position.y(), this.position.z(), 1.0f); } + @CheckReturnValue public Quaternion getOrientation() { return this.orientation; } + @CheckReturnValue public Vector3f getPosition() { return this.position; } - @Override - public int hashCode() { - int hash = 38542; - hash += this.position.hashCode(); - hash += this.orientation.hashCode(); - return hash; - } - /// Return an interpolated transform + @CheckReturnValue public Transform3D interpolateTransforms(final Transform3D newOne, final float interpolationFactor) { - final Vector3f interPosition = this.position.multiplyNew(1.0f - interpolationFactor).add(newOne.position.multiplyNew(interpolationFactor)); + final Vector3f interPosition = this.position.multiply(1.0f - interpolationFactor).add(newOne.position.multiply(interpolationFactor)); final Quaternion interOrientation = this.orientation.slerp(newOne.orientation, interpolationFactor); return new Transform3D(interPosition, interOrientation); } /// Return the inverse of the transform + @CheckReturnValue public Transform3D inverseNew() { - final Quaternion invQuaternion = this.orientation.inverseNew(); + final Quaternion invQuaternion = this.orientation.inverse(); final Matrix3f invMatrix = invQuaternion.getMatrix(); - return new Transform3D(invMatrix.multiplyNew(this.position.multiplyNew(-1)), invQuaternion); + return new Transform3D(invMatrix.multiply(this.position.multiply(-1)), invQuaternion); } /// Return true if the two transforms are different + @CheckReturnValue public boolean isDifferent(final Transform3D transform2) { return this.position.isDifferent(transform2.position) || this.orientation.isDifferent(transform2.orientation); } /// Return true if the two transforms are equal + @CheckReturnValue public boolean isEqual(final Transform3D transform2) { return this.position.isEqual(transform2.position) && this.orientation.isEqual(transform2.orientation); } /// Return the transformed vector + @CheckReturnValue public Vector3f multiply(final Vector3f vector) { - return this.orientation.getMatrix().multiplyNew(vector).add(this.position); + return this.orientation.getMatrix().multiply(vector).add(this.position); } /// Operator of multiplication of a transform with another one /* + @CheckReturnValue public Transform3D multiply(Transform3D transform2) { this.position = this.orientation.getMatrix().multiply(transform2.position).add(this.position); this.orientation.multiply(transform2.orientation); } */ /// Operator of multiplication of a transform with another one - public Transform3D multiplyNew(final Transform3D transform2) { - return new Transform3D(this.orientation.getMatrix().multiplyNew(transform2.position).add(this.position), this.orientation.multiplyNew(transform2.orientation)); - } - - /// Return the transformed vector - public Vector3f multiplyNew(final Vector3f vector) { - return new Matrix3f(this.orientation.getMatrix()).multiplyNew(vector).add(this.position); - } - - /// Assignment operator - public Transform3D set(final Transform3D transform) { - this.position = transform.position.clone(); - this.orientation = transform.orientation.clone(); - return this; + @CheckReturnValue + public Transform3D multiply(final Transform3D transform2) { + return new Transform3D(this.orientation.getMatrix().multiply(transform2.position).add(this.position), this.orientation.multiply(transform2.orientation)); } /// Set the transform from an OpenGL transform matrix - public void setFromOpenGL(final float[] matrix) { + @CheckReturnValue + public Transform3D createFromOpenGL(final float[] matrix) { final Matrix3f tmpMatrix = new Matrix3f(matrix[0], matrix[4], matrix[8], matrix[1], matrix[5], matrix[9], matrix[2], matrix[6], matrix[10]); - this.orientation = new Quaternion(tmpMatrix); - this.position.setValue(matrix[12], matrix[13], matrix[14]); - } - - /// Set the Transform3D to the identity transform - public void setIdentity() { - this.position = Vector3f.zero(); - this.orientation = Quaternion.identity(); - } - - public void setOrientation(final Quaternion orientation) { - this.orientation = orientation; - } - - public void setPosition(final Vector3f position) { - this.position = position; + Quaternion orientation = Quaternion.createFromMatrix(tmpMatrix); + Vector3f position = new Vector3f(matrix[12], matrix[13], matrix[14]); + return new Transform3D(position, orientation); } @Override diff --git a/src/org/atriasoft/etk/math/Vector2b.java b/src/org/atriasoft/etk/math/Vector2b.java index 36a7515..14def5d 100644 --- a/src/org/atriasoft/etk/math/Vector2b.java +++ b/src/org/atriasoft/etk/math/Vector2b.java @@ -1,8 +1,10 @@ package org.atriasoft.etk.math; +import edu.umd.cs.findbugs.annotations.CheckReturnValue; import org.atriasoft.etk.internal.Log; -public class Vector2b { +@SuppressWarnings("preview") +public record Vector2b(boolean x, boolean y) { public static Vector2b valueOf(String value) { boolean val1 = false; boolean val2 = false; @@ -28,147 +30,56 @@ public class Vector2b { } return new Vector2b(val1, val2); } - - public boolean x = false; - public boolean y = false; - - /* **************************************************** - * Constructor + + /* + * **************************************************** Constructor *****************************************************/ public Vector2b() { - this.x = false; - this.y = false; + this(false, false); } - + + public Vector2b(final boolean x, final boolean y) { + this.x = x; + this.y = y; + } + /** - * @brief Constructor from scalars - * @param xxx X value - * @param yyy Y value - */ - public Vector2b(final boolean xxx, final boolean yyy) { - this.x = xxx; - this.y = yyy; - } - - /** - * @brief Constructor with external vector - * @param obj The vector to add to this one - */ - public Vector2b(final Vector2b obj) { - this.x = obj.x; - this.y = obj.y; - } - - @Override - public Vector2b clone() { - return new Vector2b(this.x, this.y); - } - - /** - * @brief Get X value - * @return the x value - */ - public boolean getX() { - return this.x; - } - - /** - * @brief Get Y value - * @return the y value - */ - public boolean getY() { - return this.y; - } - - /** - * @brief In-Equality compare operator with an other object. + * In-Equality compare operator with an other object. * @param obj Reference on the comparing object * @return true The Objects are NOT identical * @return false The Objects are identical */ + @CheckReturnValue public boolean isDifferent(final Vector2b obj) { return (obj.x != this.x || obj.y != this.y); } - + /** - * @brief Equality compare operator with an other object. + * Equality compare operator with an other object. * @param obj Reference on the comparing object * @return true The Objects are identical * @return false The Objects are NOT identical */ + @CheckReturnValue public boolean isEqual(final Vector2b obj) { return (obj.x == this.x && obj.y == this.y); } - - /** - * @brief Operator= Asign the current object with a value - * @param val Value to assign on the object - */ - public void set(final boolean val) { - this.x = val; - this.y = val; - }; - - /** - * @brief Operator= Asign the current object with a value - * @param xxx X value - * @param yyy Y value - */ - public void set(final boolean xxx, final boolean yyy) { - this.x = xxx; - this.y = yyy; - } - - /** - * @brief Operator= Asign the current object with an other object - * @param obj Reference on the external object - */ - public void set(final Vector2b obj) { - this.x = obj.x; - this.y = obj.y; - } - - public void setFalse() { - this.x = false; - this.y = false; - } - - /** - * @brief Set 0 value on all the vector - */ - public void setTrue() { - this.x = true; - this.y = true; - } - - /** - * @brief Set Value on the vector - * @param xxx X value. - * @param yyy Y value. - */ - public void setValue(final boolean xxx, final boolean yyy) { - this.x = xxx; - this.y = yyy; - } - - /** - * @brief Set the x value - * @param xxx New value - */ - public void setX(final boolean xxx) { - this.x = xxx; - } - - /** - * @brief Set the y value - * @param yyy New value - */ - public void setY(final boolean yyy) { - this.y = yyy; - } - + + public static final Vector2b FALSE = new Vector2b(false, false); + public static final Vector2b TRUE = new Vector2b(true, true); + @Override public String toString() { return "(" + this.x + "," + this.y + ")"; } + + @CheckReturnValue + public Vector2b withX(final boolean xxx) { + return new Vector2b(xxx, this.y); + } + + @CheckReturnValue + public Vector2b withY(final boolean yyy) { + return new Vector2b(this.x, yyy); + } } diff --git a/src/org/atriasoft/etk/math/Vector2f.java b/src/org/atriasoft/etk/math/Vector2f.java index aab6d66..56124c6 100644 --- a/src/org/atriasoft/etk/math/Vector2f.java +++ b/src/org/atriasoft/etk/math/Vector2f.java @@ -1,8 +1,10 @@ package org.atriasoft.etk.math; +import edu.umd.cs.findbugs.annotations.CheckReturnValue; import org.atriasoft.etk.internal.Log; -public class Vector2f { +@SuppressWarnings("preview") +public record Vector2f(float x, float y) { public static Vector2f valueOf(String value) { float val1 = 0; float val2 = 0; @@ -28,205 +30,145 @@ public class Vector2f { } return new Vector2f(val1, val2); } - - public static Vector2f zero() { - return new Vector2f(0, 0); - } - - public float x = 0; - - public float y = 0; - - /* **************************************************** - * Constructor + + /* + * **************************************************** Constructor *****************************************************/ - public Vector2f() { - this.x = 0; - this.y = 0; + + public Vector2f(final float x, final float y) { + this.x = x; + this.y = y; } - /** - * @brief Constructor from scalars - * @param xxx X value - * @param yyy Y value - */ - public Vector2f(final float xxx, final float yyy) { - this.x = xxx; - this.y = yyy; - } - /** - * @brief Constructor with external vector - * @param obj The vector to add to this one - */ - public Vector2f(final Vector2f obj) { - this.x = obj.x; - this.y = obj.y; - } + @CheckReturnValue + public static Vector2f clipInt(final Vector2f obj1) { + return new Vector2f((int)obj1.x, (int)obj1.y); + } + + + public static Vector2f max(final Vector2f obj1, final Vector2f obj2) { + return new Vector2f(Math.max(obj1.x, obj2.x), Math.max(obj1.y, obj2.y)); + } + + public static Vector2f min(final Vector2f obj1, final Vector2f obj2) { + return new Vector2f(Math.min(obj1.x, obj2.x), Math.min(obj1.y, obj2.y)); + } + /** - * @brief Return a vector will the absolute values of each element + * Return a vector will the absolute values of each element * @return New vector containing the value */ + @CheckReturnValue public Vector2f abs() { - this.x = Math.abs(this.x); - this.y = Math.abs(this.y); - return this; - } - - public Vector2f absolute() { return new Vector2f(Math.abs(this.x), Math.abs(this.y)); } - /** - * @brief Operator+= Addition an other vertor with this one - * @param val Value to addition at x/y - */ + @CheckReturnValue public Vector2f add(final float val) { - this.x += val; - this.y += val; - return this; - } - - /** - * @brief Operator+= Addition an other vertor with this one - * @param obj Reference on the external object - */ - public Vector2f add(final Vector2f obj) { - this.x += obj.x; - this.y += obj.y; - return this; - } - - public Vector2f addNew(final float val) { return new Vector2f(this.x + val, this.y + val); } - public Vector2f addNew(final Vector2f obj) { + @CheckReturnValue + public Vector2f add(final Vector2f obj) { return new Vector2f(this.x + obj.x, this.y + obj.y); } - - @Override - public Vector2f clone() { - return new Vector2f(this); + @CheckReturnValue + public Vector2f add(final Vector2i obj) { + return new Vector2f(this.x + obj.x(), this.y + obj.y()); } - + @CheckReturnValue + public Vector2f add(final float xxx, final float yyy) { + return new Vector2f(this.x + xxx, this.y + yyy); + } + /** - * @brief Return the axis with the largest ABSOLUTE value + * Return the axis with the largest ABSOLUTE value * @return values 0,1 for x or y */ + @CheckReturnValue public int closestAxis() { - return absolute().maxAxis(); + return abs().maxAxis(); } - + /** - * @brief Return the cross product / determinant + * Return the cross product / determinant * @param obj The other vector in the cross product * @return cross product value */ + @CheckReturnValue public float cross(final Vector2f obj) { return this.x * obj.y - this.y * obj.x; } - + /** - * @brief Decrementation of this vector (-1 of 2 elements) + * Decrementation of this vector (-1 of 2 elements) */ + @CheckReturnValue public Vector2f decrement() { - this.x--; - this.y--; - return this; + return new Vector2f(this.x - 1, this.y - 1); } - /** - * @brief Operator/ Dividing an other vertor with this one - * @param val Value to addition at x/y - */ + @CheckReturnValue public Vector2f devide(final float val) { - this.x /= val; - this.y /= val; - return this; - } - - /** - * @brief Operator/ Dividing an other vertor with this one - * @param obj Reference on the external object - */ - public Vector2f devide(final Vector2f obj) { - this.x /= obj.x; - this.y /= obj.y; - return this; - } - - public Vector2f devideNew(final float val) { return new Vector2f(this.x / val, this.y / val); } - public Vector2f devideNew(final Vector2f obj) { + @CheckReturnValue + public Vector2f devide(final Vector2f obj) { return new Vector2f(this.x / obj.x, this.y / obj.y); } - + /** - * @brief Return the distance between the ends of this and another vector - * This is semantically treating the vector like a point + * Return the distance between the ends of this and another vector This + * is semantically treating the vector like a point * @param obj The other vector to compare distance * @return the distance of the 2 points */ + @CheckReturnValue public float distance(final Vector2f obj) { return (float) Math.sqrt(distance2(obj)); } - + /** - * @brief Return the distance squared between the ends of this and another vector - * This is semantically treating the vector like a point + * Return the distance squared between the ends of this and another + * vector This is semantically treating the vector like a point * @param obj The other vector to compare distance * @return the square distance of the 2 points */ + @CheckReturnValue public float distance2(final Vector2f obj) { final float deltaX = obj.x - this.x; final float deltaY = obj.y - this.y; return deltaX * deltaX + deltaY * deltaY; } - + /** - * @brief Return the dot product + * Return the dot product * @param obj The other vector in the dot product * @return Dot product value */ + @CheckReturnValue public float dot(final Vector2f obj) { return this.x * obj.x + this.y * obj.y; } - - @Override - public boolean equals(final Object obj) { - if (obj == null) { - return false; - } - // check type - if (getClass() != obj.getClass()) { - return false; - } - // cast object - final Vector2f other = (Vector2f) obj; - // checks values - if (this.x != other.x) { - return false; - } - return this.y == other.y; - } - + /** - * @brief Return the axis with the smallest ABSOLUTE value + * Return the axis with the smallest ABSOLUTE value * @return values 0,1 for x, or z */ + @CheckReturnValue public int furthestAxis() { - return absolute().minAxis(); + return abs().minAxis(); } - + /** - * @brief get the value with his index + * get the value with his index * @param index Index of the value (0: x, 1: y) * @return The value associated */ + @CheckReturnValue public float get(final int index) { if (index == 0) { return this.x; @@ -235,318 +177,214 @@ public class Vector2f { } throw new IllegalArgumentException("Unknown index: " + index); } - + /** - * @brief Get X value - * @return the x value - */ - public float getX() { - return this.x; - } - - /** - * @brief Get Y value - * @return the y value - */ - public float getY() { - return this.y; - } - - @Override - public int hashCode() { - int hash = 38521; - hash += hash + Float.floatToIntBits(this.x); - hash += hash + Float.floatToIntBits(this.y); - return hash; - } - - /** - * @brief Incrementation of this vector (+1 of 2 elements) + * Incrementation of this vector (+1 of 2 elements) */ + @CheckReturnValue public Vector2f increment() { - this.x++; - this.y++; - return this; + return new Vector2f(this.x + 1, this.y + 1); } - + // Overloaded operator for the negative of a vector + @CheckReturnValue public Vector2f invert() { - this.x = -this.x; - this.y = -this.y; - return this; + return new Vector2f(-this.x, -this.y); } - + /** - * @brief In-Equality compare operator with an other object. + * In-Equality compare operator with an other object. * @param obj Reference on the comparing object * @return true The Objects are NOT identical * @return false The Objects are identical */ + @CheckReturnValue public boolean isDifferent(final Vector2f obj) { return (obj.x != this.x || obj.y != this.y); } - + /** - * @brief Equality compare operator with an other object. + * Equality compare operator with an other object. * @param obj Reference on the comparing object * @return true The Objects are identical * @return false The Objects are NOT identical */ + @CheckReturnValue public boolean isEqual(final Vector2f obj) { return (obj.x == this.x && obj.y == this.y); } + @CheckReturnValue public boolean isGreater(final Vector2f obj) { return (this.x > obj.x && this.y > obj.y); } + @CheckReturnValue public boolean isGreaterOrEqual(final Vector2f obj) { return (this.x >= obj.x && this.y >= obj.y); } + @CheckReturnValue public boolean isLower(final Vector2f obj) { return (this.x < obj.x && this.y < obj.y); } + @CheckReturnValue public boolean isLowerOrEqual(final Vector2f obj) { return (this.x <= obj.x && this.y <= obj.y); } - + /** - * @brief Check if the vector is unitary (langth = 10f=) + * Check if the vector is unitary (langth = 10f=) * @return true if unit , false otherwise */ + @CheckReturnValue public boolean isUnit() { return FMath.approxEqual(length2(), 1.0f, Constant.MACHINE_EPSILON); } - + /** - * @brief Check if the vector is equal to (0,0) + * Check if the vector is equal to (0,0) * @return true The value is equal to (0,0) * @return false The value is NOT equal to (0,0) */ + @CheckReturnValue public boolean isZero() { return FMath.approxEqual(length2(), 0.0f, Constant.MACHINE_EPSILON); } - + /** - * @brief Get the length of the vector + * Get the length of the vector * @return Length value */ + @CheckReturnValue public float length() { return (float) Math.sqrt(length2()); } - + /** - * @brief Get the length of the vector squared + * Get the length of the vector squared * @return Squared length value. */ + @CheckReturnValue public float length2() { return dot(this); } - /** - * @brief Operator-= Decrement an other vertor with this one - * @param val Value to addition at x/y - */ + @CheckReturnValue public Vector2f less(final float val) { - this.x -= val; - this.y -= val; - return this; - } - - /** - * @brief Operator-= Decrement an other vertor with this one - * @param obj Reference on the external object - */ - public Vector2f less(final Vector2f obj) { - this.x -= obj.x; - this.y -= obj.y; - return this; - } - - public Vector2f lessNew(final float val) { return new Vector2f(this.x - val, this.y - val); } - - public Vector2f lessNew(final Vector2f obj) { - return new Vector2f(this.x - obj.x, this.y - obj.y); + @CheckReturnValue + public Vector2f less(final float xxx, final float yyy) { + return new Vector2f(this.x - xxx, this.y - yyy); } + @CheckReturnValue + public Vector2f less(final Vector2f obj) { + return new Vector2f(this.x - obj.x, this.y - obj.y); + } + @CheckReturnValue + public Vector2f less(final Vector2i obj) { + return new Vector2f(this.x - obj.x(), this.y - obj.y()); + } + /** - * @brief Return the axis with the largest value + * Return the axis with the largest value * @return values are 0,1 for x or y */ + @CheckReturnValue public int maxAxis() { return this.x < this.y ? 1 : 0; } - + /** - * @brief Return the axis with the smallest value + * Return the axis with the smallest value * @return values are 0,1 for x or y */ + @CheckReturnValue public int minAxis() { return this.x < this.y ? 0 : 1; } - /** - * @brief Operator*= Multiplication an other vertor with this one - * @param val Value to addition at x/y - */ + @CheckReturnValue public Vector2f multiply(final float val) { - this.x *= val; - this.y *= val; - return this; - } - - /** - * @brief Operator*= Multiplication an other vertor with this one - * @param obj Reference on the external object - */ - public Vector2f multiply(final Vector2f obj) { - this.x *= obj.x; - this.y *= obj.y; - return this; - }; - - public Vector2f multiplyNew(final float val) { return new Vector2f(this.x * val, this.y * val); }; - public Vector2f multiplyNew(final Vector2f obj) { + @CheckReturnValue + public Vector2f multiply(final Vector2f obj) { return new Vector2f(this.x * obj.x, this.y * obj.y); }; - + /** - * @brief Normalize this vector x^2 + y^2 = 1 + * Normalize this vector x^2 + y^2 = 1 */ + @CheckReturnValue public Vector2f normalize() { - this.devide(length()); - return this; + return this.devide(length()); } - + /** - * @brief Return a normalized version of this vector - * @return New vector containing the value - */ - public Vector2f normalized() { - final Vector2f tmp = clone(); - tmp.normalize(); - return tmp; - } - - /** - * @brief Normalize this vector x^2 + y^2 = 1 (check if not deviding by 0, if it is the case ==> return (1,0)) + * Normalize this vector x^2 + y^2 = 1 (check if not deviding by 0, if it + * is the case ==> return (1,0)) * @return Local reference of the vector normalized */ + @CheckReturnValue public Vector2f safeNormalize() { final float tmp = length(); if (tmp != 0) { - this.devide(length()); - return this; + return this.devide(length()); } - setValue(1, 0); - return this; + return new Vector2f(1, 0); } - + /** - * @brief Operator= Asign the current object with a value - * @param val Value to assign on the object - */ - public Vector2f set(final float val) { - this.x = val; - this.y = val; - return this; - } - - /** - * @brief Operator= Asign the current object with a value - * @param xxx X value - * @param yyy Y value - */ - public Vector2f set(final float xxx, final float yyy) { - this.x = xxx; - this.y = yyy; - return this; - } - - /** - * @brief Operator= Asign the current object with an other object - * @param obj Reference on the external object - */ - public Vector2f set(final Vector2f obj) { - this.x = obj.x; - this.y = obj.y; - return this; - } - - /** - * @brief Set each element to the max of the current values and the values of another vector + * Set each element to the max of the current values and the values of + * another vector * @param other The other vector to compare with */ - public Vector2f setMax(final Vector2f other) { - this.x = Math.max(this.x, other.x); - this.y = Math.max(this.y, other.y); - return this; + @CheckReturnValue + public Vector2f max(final Vector2f other) { + return new Vector2f(Math.max(this.x, other.x), Math.max(this.y, other.y)); } - + /** - * @brief Set each element to the min of the current values and the values of another vector + * Set each element to the min of the current values and the values of + * another vector * @param other The other vector to compare with */ - public Vector2f setMin(final Vector2f other) { - this.x = Math.min(this.x, other.x); - this.y = Math.min(this.y, other.y); - return this; + @CheckReturnValue + public Vector2f min(final Vector2f other) { + return new Vector2f(Math.min(this.x, other.x), Math.min(this.y, other.y)); } - + // Return one unit orthogonal vector of the current vector - public Vector2f setUnitOrthogonal() { - this.y = -this.y; - return safeNormalize(); + @CheckReturnValue + public Vector2f unitOrthogonal() { + return (new Vector2f(this.x, -this.y)).safeNormalize(); } - + /** - * @brief Set Value on the vector - * @param xxx X value. - * @param yyy Y value. + * Set 0 value on all the vector */ - public Vector2f setValue(final float xxx, final float yyy) { - this.x = xxx; - this.y = yyy; - return this; - } - - /** - * @brief Set the x value - * @param xxx New value - */ - public Vector2f setX(final float xxx) { - this.x = xxx; - return this; - } - - /** - * @brief Set the y value - * @param yyy New value - */ - public Vector2f setY(final float yyy) { - this.y = yyy; - return this; - } - - /** - * @brief Set 0 value on all the vector - */ - public Vector2f setZero() { - this.x = 0; - this.y = 0; - return this; - } - + public static final Vector2f MAX_VALUE = new Vector2f(Float.MAX_VALUE, Float.MAX_VALUE); + public static final Vector2f MIN_VALUE = new Vector2f(Float.MIN_VALUE, Float.MIN_VALUE); + public static final Vector2f ZERO = new Vector2f(0, 0); + public static final Vector2f ONE = new Vector2f(1, 1); + @Override public String toString() { return "(" + this.x + "," + this.y + ")"; } + @CheckReturnValue + public Vector2f withX(final float xxx) { + return new Vector2f(xxx, this.y); + } + + @CheckReturnValue + public Vector2f withY(final float yyy) { + return new Vector2f(this.x, yyy); + } } diff --git a/src/org/atriasoft/etk/math/Vector2i.java b/src/org/atriasoft/etk/math/Vector2i.java index 5ef3d01..bbfd6a3 100644 --- a/src/org/atriasoft/etk/math/Vector2i.java +++ b/src/org/atriasoft/etk/math/Vector2i.java @@ -2,8 +2,14 @@ package org.atriasoft.etk.math; import org.atriasoft.etk.internal.Log; -public class Vector2i { - public static Vector2i valueOf(String value) { +import edu.umd.cs.findbugs.annotations.CheckReturnValue; + +@SuppressWarnings("preview") +public record Vector2i( + int x, + int y) { + + public static Vector2i valueOf(String value) throws NumberFormatException { int val1 = 0; int val2 = 0; // copy to permit to modify it : @@ -29,144 +35,105 @@ public class Vector2i { return new Vector2i(val1, val2); } - public int x = 0; - public int y = 0; - - /* **************************************************** - * Constructor + /* + * **************************************************** Constructor *****************************************************/ public Vector2i() { - this.x = 0; - this.y = 0; + this(0, 0); + } + + public Vector2i(final int x, final int y) { + this.x = x; + this.y = y; + } + + public static Vector2i max(final Vector2i obj1, final Vector2i obj2) { + return new Vector2i(Math.max(obj1.x, obj2.x), Math.max(obj1.y, obj2.y)); + } + + public static Vector2i min(final Vector2i obj1, final Vector2i obj2) { + return new Vector2i(Math.min(obj1.x, obj2.x), Math.min(obj1.y, obj2.y)); } /** - * @brief Constructor from scalars - * @param xxx X value - * @param yyy Y value - */ - public Vector2i(final int xxx, final int yyy) { - this.x = xxx; - this.y = yyy; - } - - /** - * @brief Constructor with external vector - * @param obj The vector to add to this one - */ - public Vector2i(final Vector2i obj) { - this.x = obj.x; - this.y = obj.y; - } - - /** - * @brief Return a vector will the absolute values of each element + * Return a vector will the absolute values of each element * @return New vector containing the value */ + @CheckReturnValue public Vector2i absolute() { return new Vector2i(Math.abs(this.x), Math.abs(this.y)); } - /** - * @brief Operator+= Addition an other vertor with this one - * @param val Value to addition at x/y - */ + @CheckReturnValue public Vector2i add(final int val) { - this.x += val; - this.y += val; - return this; - } - - /** - * @brief Operator+= Addition an other vertor with this one - * @param obj Reference on the external object - */ - public Vector2i add(final Vector2i obj) { - this.x += obj.x; - this.y += obj.y; - return this; - } - - public Vector2i addNew(final int val) { return new Vector2i(this.x + val, this.y + val); } - public Vector2i addNew(final Vector2i obj) { + @CheckReturnValue + public Vector2i add(final Vector2i obj) { return new Vector2i(this.x + obj.x, this.y + obj.y); } - @Override - public Vector2i clone() { - return new Vector2i(this); + @CheckReturnValue + public Vector2i add(final int xxx, final int yyy) { + return new Vector2i(this.x + xxx, this.y + yyy); } /** - * @brief Return the axis with the largest ABSOLUTE value + * Return the axis with the largest ABSOLUTE value * @return values 0,1 for x or y */ + @CheckReturnValue public int closestAxis() { return absolute().maxAxis(); } /** - * @brief Return the cross product / determinant + * Return the cross product / determinant * @param obj The other vector in the cross product * @return cross product value */ + @CheckReturnValue public int cross(final Vector2i obj) { return this.x * obj.y - this.y * obj.x; } /** - * @brief Decrementation of this vector (-1 of 2 elements) + * Decrementation of this vector (-1 of 2 elements) */ - public void decrement() { - this.x--; - this.y--; + @CheckReturnValue + public Vector2i decrement() { + return new Vector2i(this.x - 1, this.y - 1); } - /** - * @brief Operator/ Dividing an other vertor with this one - * @param val Value to addition at x/y - */ - public void devide(final int val) { - this.x /= val; - this.y /= val; - } - - /** - * @brief Operator/ Dividing an other vertor with this one - * @param obj Reference on the external object - */ - public void devide(final Vector2i obj) { - this.x /= obj.x; - this.y /= obj.y; - } - - public Vector2i devideNew(final int val) { + @CheckReturnValue + public Vector2i devide(final int val) { return new Vector2i(this.x / val, this.y / val); } - public Vector2i devideNew(final Vector2i obj) { + @CheckReturnValue + public Vector2i devide(final Vector2i obj) { return new Vector2i(this.x / obj.x, this.y / obj.y); } /** - * @brief Return the distance between the ends of this and another vector - * This is symantically treating the vector like a point + * Return the distance between the ends of this and another vector This + * is symantically treating the vector like a point * @param obj The other vector to compare distance * @return the distance of the 2 points */ + @CheckReturnValue public int distance(final Vector2i obj) { return (int) Math.sqrt(distance2(obj)); } /** - * @brief Return the distance squared between the ends of this and another vector - * This is symantically treating the vector like a point + * Return the distance squared between the ends of this and another + * vector This is symantically treating the vector like a point * @param obj The other vector to compare distance * @return the square distance of the 2 points */ + @CheckReturnValue public int distance2(final Vector2i obj) { final int deltaX = obj.x - this.x; final int deltaY = obj.y - this.y; @@ -174,298 +141,196 @@ public class Vector2i { } /** - * @brief Return the dot product + * Return the dot product * @param obj The other vector in the dot product * @return Dot product value */ + @CheckReturnValue public int dot(final Vector2i obj) { return this.x * obj.x + this.y * obj.y; } /** - * @brief Return the axis with the smallest ABSOLUTE value + * Return the axis with the smallest ABSOLUTE value * @return values 0,1 for x, or z */ + @CheckReturnValue public int furthestAxis() { return absolute().minAxis(); } /** - * @brief Get X value - * @return the x value + * Incrementation of this vector (+1 of 2 elements) */ - public int getX() { - return this.x; + @CheckReturnValue + public Vector2i increment() { + return new Vector2i(this.x + 1, this.y + 1); } /** - * @brief Get Y value - * @return the y value - */ - public int getY() { - return this.y; - } - - /** - * @brief Incrementation of this vector (+1 of 2 elements) - */ - public void increment() { - this.x++; - this.y++; - } - - /** - * @brief In-Equality compare operator with an other object. + * In-Equality compare operator with an other object. * @param obj Reference on the comparing object * @return true The Objects are NOT identical * @return false The Objects are identical */ + @CheckReturnValue public boolean isDifferent(final Vector2i obj) { return (obj.x != this.x || obj.y != this.y); } /** - * @brief Equality compare operator with an other object. + * Equality compare operator with an other object. * @param obj Reference on the comparing object * @return true The Objects are identical * @return false The Objects are NOT identical */ + @CheckReturnValue public boolean isEqual(final Vector2i obj) { return (obj.x == this.x && obj.y == this.y); } + @CheckReturnValue public boolean isGreater(final Vector2i obj) { return (this.x > obj.x && this.y > obj.y); } + @CheckReturnValue public boolean isGreaterOrEqual(final Vector2i obj) { return (this.x >= obj.x && this.y >= obj.y); } + @CheckReturnValue public boolean isLower(final Vector2i obj) { return (this.x < obj.x && this.y < obj.y); } + @CheckReturnValue public boolean isLowerOrEqual(final Vector2i obj) { return (this.x <= obj.x && this.y <= obj.y); } /** - * @brief Check if the vector is equal to (0,0) + * Check if the vector is equal to (0,0) * @return true The value is equal to (0,0) * @return false The value is NOT equal to (0,0) */ + @CheckReturnValue public boolean isZero() { return this.x == 0 && this.y == 0; } /** - * @brief Get the length of the vector + * Get the length of the vector * @return Length value */ + @CheckReturnValue public int length() { return (int) Math.sqrt(length2()); } /** - * @brief Get the length of the vector squared + * Get the length of the vector squared * @return Squared length value. */ + @CheckReturnValue public int length2() { return dot(this); } - /** - * @brief Operator-= Decrement an other vertor with this one - * @param val Value to addition at x/y - */ - public void less(final int val) { - this.x -= val; - this.y -= val; - } - - /** - * @brief Operator-= Decrement an other vertor with this one - * @param obj Reference on the external object - */ - public void less(final Vector2i obj) { - this.x -= obj.x; - this.y -= obj.y; - } - - public Vector2i lessNew(final int val) { + @CheckReturnValue + public Vector2i less(final int val) { return new Vector2i(this.x - val, this.y - val); } - public Vector2i lessNew(final Vector2i obj) { + @CheckReturnValue + public Vector2i less(final int xxx, final int yyy) { + return new Vector2i(this.x - xxx, this.y - yyy); + } + + @CheckReturnValue + public Vector2i less(final Vector2i obj) { return new Vector2i(this.x - obj.x, this.y - obj.y); } /** - * @brief Return the axis with the largest value + * Return the axis with the largest value * @return values are 0,1 for x or y */ + @CheckReturnValue public int maxAxis() { return this.x < this.y ? 1 : 0; } /** - * @brief Return the axis with the smallest value + * Return the axis with the smallest value * @return values are 0,1 for x or y */ + @CheckReturnValue public int minAxis() { return this.x < this.y ? 0 : 1; } - /** - * @brief Operator*= Multiplication an other vertor with this one - * @param val Value to addition at x/y - */ - public void multiply(final int val) { - this.x *= val; - this.y *= val; - } - - /** - * @brief Operator*= Multiplication an other vertor with this one - * @param obj Reference on the external object - */ - public void multiply(final Vector2i obj) { - this.x *= obj.x; - this.y *= obj.y; - } - - public Vector2i multiplyNew(final int val) { + @CheckReturnValue + public Vector2i multiply(final int val) { return new Vector2i(this.x * val, this.y * val); } - public Vector2i multiplyNew(final Vector2i obj) { + @CheckReturnValue + public Vector2i multiply(final Vector2i obj) { return new Vector2i(this.x * obj.x, this.y * obj.y); } /** - * @brief Normalize this vector x^2 + y^2 = 1 - */ - public void normalize() { - this.devide(length()); - } - - /** - * @brief Return a normalized version of this vector + * Normalize this vector x^2 + y^2 = 1 * @return New vector containing the value */ - public Vector2i normalized() { - final Vector2i tmp = clone(); - tmp.normalize(); - return tmp; + @CheckReturnValue + public Vector2i normalize() { + return this.devide(length()); } /** - * @brief Normalize this vector x^2 + y^2 = 1 (check if not deviding by 0, if it is the case ==> return (1,0)) + * Normalize this vector x^2 + y^2 = 1 (check if not deviding by 0, if it + * is the case ==> return (1,0)) * @return Local reference of the vector normalized */ - public void safeNormalize() { + @CheckReturnValue + public Vector2i safeNormalize() { final int tmp = length(); if (tmp != 0) { - this.devide(length()); - return; + return this.devide(length()); } - setValue(1, 0); - return; + return new Vector2i(1, 0); }; - /** - * @brief Operator= Asign the current object with a value - * @param val Value to assign on the object - */ - public void set(final int val) { - this.x = val; - this.y = val; - }; + @CheckReturnValue + public Vector2i max(final int xxx, final int yyy) { + return new Vector2i(Math.max(this.x, xxx), Math.max(this.y, yyy)); + } - /** - * @brief Operator= Asign the current object with a value - * @param xxx X value - * @param yyy Y value - */ - public void set(final int xxx, final int yyy) { - this.x = xxx; - this.y = yyy; + @CheckReturnValue + public Vector2i min(final int xxx, final int yyy) { + return new Vector2i(Math.min(this.x, xxx), Math.min(this.y, yyy)); } /** - * @brief Operator= Asign the current object with an other object - * @param obj Reference on the external object + * Set 0 value on all the vector */ - public void set(final Vector2i obj) { - this.x = obj.x; - this.y = obj.y; - } - - public void setMax(final int xxx, final int yyy) { - this.x = Math.max(this.x, xxx); - this.y = Math.max(this.y, yyy); - } - - /** - * @brief Set each element to the max of the current values and the values of another vector - * @param other The other vector to compare with - */ - public void setMax(final Vector2i other) { - this.x = Math.max(this.x, other.x); - this.y = Math.max(this.y, other.y); - } - - public void setMin(final int xxx, final int yyy) { - this.x = Math.min(this.x, xxx); - this.y = Math.min(this.y, yyy); - } - - /** - * @brief Set each element to the min of the current values and the values of another vector - * @param other The other vector to compare with - */ - public void setMin(final Vector2i other) { - this.x = Math.min(this.x, other.x); - this.y = Math.min(this.y, other.y); - } - - /** - * @brief Set Value on the vector - * @param xxx X value. - * @param yyy Y value. - */ - public void setValue(final int xxx, final int yyy) { - this.x = xxx; - this.y = yyy; - } - - /** - * @brief Set the x value - * @param xxx New value - */ - public void setX(final int xxx) { - this.x = xxx; - } - - /** - * @brief Set the y value - * @param yyy New value - */ - public void setY(final int yyy) { - this.y = yyy; - } - - /** - * @brief Set 0 value on all the vector - */ - public void setZero() { - this.x = 0; - this.y = 0; - } + public static final Vector2i ZERO = new Vector2i(0, 0); + public static final Vector2i ONE = new Vector2i(1, 1); @Override public String toString() { return "Vector2i(" + this.x + "," + this.y + ")"; } + + @CheckReturnValue + public Vector2i withX(final int xxx) { + return new Vector2i(xxx, this.y); + } + + @CheckReturnValue + public Vector2i withY(final int yyy) { + return new Vector2i(this.x, yyy); + } } diff --git a/src/org/atriasoft/etk/math/Vector3f.java b/src/org/atriasoft/etk/math/Vector3f.java index b8af618..a6a4c8a 100644 --- a/src/org/atriasoft/etk/math/Vector3f.java +++ b/src/org/atriasoft/etk/math/Vector3f.java @@ -1,12 +1,13 @@ package org.atriasoft.etk.math; +import edu.umd.cs.findbugs.annotations.CheckReturnValue; import org.atriasoft.etk.internal.Log; -public class Vector3f { +public record Vector3f(float x, float y, float z) { /** - * @brief Get the length square between the 2 vectors + * Get the length square between the 2 vectors * @param start First vector - * @param stop second vector + * @param stop second vector * @return Length value */ public static float length2(final Vector3f start, final Vector3f stop) { @@ -15,7 +16,7 @@ public class Vector3f { final float z = stop.z - start.z; return x * x + y * y + z * z; } - + public static Vector3f valueOf(String value) { float val1 = 0; float val2 = 0; @@ -37,7 +38,7 @@ public class Vector3f { val1 = Float.valueOf(values[0]); val2 = val1; val3 = val1; - } else if (values.length == 1) { + } else if (values.length == 2) { // no coma ... // in every case, we parse the first element : val1 = Float.valueOf(values[0]); @@ -50,119 +51,58 @@ public class Vector3f { } return new Vector3f(val1, val2, val3); } - - public static Vector3f zero() { - return new Vector3f(0, 0, 0); - } - - public float x; - public float y; - - public float z; - + /** - * @brief Default contructor - */ - public Vector3f() { - this.x = 0; - this.y = 0; - this.z = 0; - } - - /** - * @brief Constructor from scalars + * Constructor from scalars * @param value unique value for X,Y and Z value */ public Vector3f(final float value) { - this.x = value; - this.y = value; - this.z = value; + this(value, value, value); } - - /** - * @brief Constructor from scalars - * @param xxx X value - * @param yyy Y value - * @param zzz Z value - */ - public Vector3f(final float xxx, final float yyy, final float zzz) { - this.x = xxx; - this.y = yyy; - this.z = zzz; + + public Vector3f(final float x, final float y, final float z) { + this.x = x; + this.y = y; + this.z = z; } - + /** - * @brief Constructor from other vector (copy) - * @param obj The vector to add to this one - */ - public Vector3f(final Vector3f obj) { - this.x = obj.x; - this.y = obj.y; - this.z = obj.z; - } - - /** - * @brief Return a vector will the absolute values of each element + * Return a vector will the absolute values of each element * @return the curent reference */ + @CheckReturnValue public Vector3f abs() { - this.x = Math.abs(this.x); - this.y = Math.abs(this.y); - this.z = Math.abs(this.z); - return this; - } - - @Deprecated - public Vector3f absolute() { - this.x = Math.abs(this.x); - this.y = Math.abs(this.y); - this.z = Math.abs(this.z); - return this; - } - - /** - * @brief Return a vector will the absolute values of each element - * @return New vector containing the value - */ - public Vector3f absoluteNew() { return new Vector3f(Math.abs(this.x), Math.abs(this.y), Math.abs(this.z)); } + @CheckReturnValue public Vector3f add(final float value) { - this.x += value; - this.y += value; - this.z += value; - return this; - } - - /** - * @brief Add a vector to this one - * @param obj The vector to add to this one - */ - public Vector3f add(final Vector3f obj) { - this.x += obj.x; - this.y += obj.y; - this.z += obj.z; - return this; - } - - public Vector3f addNew(final float value) { return new Vector3f(this.x + value, this.y + value, this.z + value); } - + @CheckReturnValue + public Vector3f add(final float xxx, final float yyy, final float zzz) { + return new Vector3f(this.x + xxx, this.y + yyy, this.z + zzz); + } + @CheckReturnValue + public Vector3f clipInteger() { + return new Vector3f((int)x, (int)y, (int)z); + } + /** - * @brief Add a vector to this one + * Add a vector to this one * @param obj The vector to add to this one */ - public Vector3f addNew(final Vector3f obj) { + @CheckReturnValue + public Vector3f add(final Vector3f obj) { return new Vector3f(this.x + obj.x, this.y + obj.y, this.z + obj.z); } - + /** - * @brief Calculate the angle between this and another vector + * Calculate the angle between this and another vector * @param obj The other vector * @return Angle in radian */ + @CheckReturnValue public float angle(final Vector3f obj) { final float s = (float) Math.sqrt(length2() * obj.length2()); if (0 != s) { @@ -171,146 +111,105 @@ public class Vector3f { return 0; } - public Vector3f clampNew(final float maxLength) { + @CheckReturnValue + public Vector3f clamp(final float maxLength) { if (length2() > maxLength * maxLength) { - return safeNormalizeNew().multiply(maxLength); + return safeNormalize().multiply(maxLength); } - return clone(); + return this; } - + /** - * @brief Clone the current vector. - * @return New vector containing the value - */ - @Override - public Vector3f clone() { - return new Vector3f(this); - } - - /** - * @brief Return the axis with the largest ABSOLUTE value + * Return the axis with the largest ABSOLUTE value * @return values 0,1,2 for x, y, or z */ + @CheckReturnValue public int closestAxis() { - return absoluteNew().maxAxis(); + return abs().maxAxis(); } - + /** - * @brief Return the cross product between this and another vector + * Return the cross product between this and another vector * @param obj The other vector * @return Vector with the result of the cross product */ + @CheckReturnValue public Vector3f cross(final Vector3f obj) { - return new Vector3f(this.y * obj.z - this.z * obj.y, this.z * obj.x - this.x * obj.z, this.x * obj.y - this.y * obj.x); + return new Vector3f(this.y * obj.z - this.z * obj.y, this.z * obj.x - this.x * obj.z, + this.x * obj.y - this.y * obj.x); } - + /** - * @brief Return the distance between the ends of this and another vector - * This is symantically treating the vector like a point + * Return the distance between the ends of this and another vector This + * is symantically treating the vector like a point * @param obj The other vector to compare distance * @return the distance of the 2 points */ + @CheckReturnValue public float distance(final Vector3f obj) { return (float) Math.sqrt(distance2(obj)); } - + /** - * @brief Return the distance squared between the ends of this and another vector - * This is symantically treating the vector like a point + * Return the distance squared between the ends of this and another + * vector This is symantically treating the vector like a point * @param obj The other vector to compare distance * @return the square distance of the 2 points */ + @CheckReturnValue public float distance2(final Vector3f obj) { final float deltaX = obj.x - this.x; final float deltaY = obj.y - this.y; final float deltaZ = obj.z - this.z; return deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ; } - + /** - * @brief Inversely scale the vector + * Inversely scale the vector * @param val Scale factor to divide by */ + @CheckReturnValue public Vector3f divide(final float val) { - if (val != 0.0f) { - this.x /= val; - this.y /= val; - this.z /= val; - return this; - } - throw new IllegalArgumentException("divice by 0 (vector3f)"); - } - - /** - * @brief Inversely scale the vector - * @param val Scale factor to divide by - */ - public Vector3f divide(final Vector3f val) { - this.x /= val.x; - this.y /= val.y; - this.z /= val.z; - return this; - } - - /** - * @brief Inversely scale the vector - * @param val Scale factor to divide by - */ - public Vector3f divideNew(final float val) { if (val != 0.0f) { return new Vector3f(this.x / val, this.y / val, this.z / val); } throw new IllegalArgumentException("divice by 0 (vector3f)"); } - + /** - * @brief Inversely scale the vector + * Inversely scale the vector * @param val Scale factor to divide by */ - public Vector3f divideNew(final Vector3f val) { + @CheckReturnValue + public Vector3f divide(final Vector3f val) { return new Vector3f(this.x / val.x, this.y / val.y, this.z / val.z); } - + /** - * @brief Return the dot product + * Return the dot product * @param obj The other vector in the dot product * @return Dot product value */ + @CheckReturnValue public float dot(final Vector3f obj) { return this.x * obj.x + this.y * obj.y + this.z * obj.z; } - - @Override - public boolean equals(final Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Vector3f other = (Vector3f) obj; - if (Float.floatToIntBits(this.x) != Float.floatToIntBits(other.x)) { - return false; - } - if (Float.floatToIntBits(this.y) != Float.floatToIntBits(other.y)) { - return false; - } - return Float.floatToIntBits(this.z) == Float.floatToIntBits(other.z); - } - + /** - * @brief Return the axis with the smallest ABSOLUTE value + * Return the axis with the smallest ABSOLUTE value * @return values 0,1,2 for x, y, or z */ + @CheckReturnValue public int furthestAxis() { - return absoluteNew().minAxis(); + return abs().minAxis(); } - + /** - * @brief get the value with his index + * get the value with his index * @param index Index of the value (0: x, 1: y, 2: z) * @return The value associated */ + @CheckReturnValue public float get(final int index) { if (index == 0) { return this.x; @@ -321,43 +220,48 @@ public class Vector3f { } throw new IllegalArgumentException("Unknown index: " + index); } - + /** - * @brief Get the maximum value of the vector (x, y, z) + * Get the maximum value of the vector (x, y, z) * @return The max value */ + @CheckReturnValue public float getMax() { return Math.max(Math.max(this.x, this.y), this.z); } - + /** - * @brief Get the Axis id with the maximum value + * Get the Axis id with the maximum value * @return Axis ID 0,1,2 */ + @CheckReturnValue public int getMaxAxis() { return (this.x < this.y ? (this.y < this.z ? 2 : 1) : (this.x < this.z ? 2 : 0)); } - + /** - * @brief Get the minimum value of the vector (x, y, z) + * Get the minimum value of the vector (x, y, z) * @return The min value */ + @CheckReturnValue public float getMin() { return Math.min(Math.min(this.x, this.y), this.z); } - + /** - * @brief Get the Axis id with the minimum value + * Get the Axis id with the minimum value * @return Axis ID 0,1,2 */ + @CheckReturnValue public int getMinAxis() { return (this.x < this.y ? (this.x < this.z ? 0 : 2) : (this.y < this.z ? 1 : 2)); } - + /** * @breif Get the orthogonal vector of the current vector * @return The ortho vector */ + @CheckReturnValue public Vector3f getOrthoVector() { final Vector3f vectorAbs = new Vector3f(Math.abs(this.x), Math.abs(this.y), Math.abs(this.z)); final int minElement = vectorAbs.getMinAxis(); @@ -371,408 +275,299 @@ public class Vector3f { final float devider = (float) Math.sqrt(this.x * this.x + this.y * this.y); return new Vector3f(-this.y / devider, this.x / devider, 0.0f); } - - /** - * @brief Create a skew matrix of the object - * @param obj0 Vector matric first line - * @param obj1 Vector matric second line - * @param obj2 Vector matric third line + + /* + * public void getSkewSymmetricMatrix(final Vector3f obj0, final Vector3f obj1, + * final Vector3f obj2) { obj0.setValue(0, -this.z, this.y); + * obj1.setValue(this.z, 0, -this.x); obj2.setValue(-this.y, this.x, 0); } */ - public void getSkewSymmetricMatrix(final Vector3f obj0, final Vector3f obj1, final Vector3f obj2) { - obj0.setValue(0, -this.z, this.y); - obj1.setValue(this.z, 0, -this.x); - obj2.setValue(-this.y, this.x, 0); + @CheckReturnValue + public Vector3f getSkewSymmetricMatrix0() { + return new Vector3f(0, -this.z, this.y); } - /** - * @brief Get X value - * @return the x value - */ - public float getX() { - return this.x; + @CheckReturnValue + public Vector3f getSkewSymmetricMatrix1() { + return new Vector3f(this.z, 0, -this.x); } - /** - * @brief Get Y value - * @return the y value - */ - public float getY() { - return this.y; + @CheckReturnValue + public Vector3f getSkewSymmetricMatrix2() { + return new Vector3f(-this.y, this.x, 0); } - - /** - * @brief Get Z value - * @return the z value - */ - public float getZ() { - return this.z; - } - - @Override - public int hashCode() { - int hash = 5; - hash += Float.floatToIntBits(this.x); - hash += Float.floatToIntBits(this.y); - hash += Float.floatToIntBits(this.z); - return hash; - } - + // Overloaded operator for the negative of a vector + @CheckReturnValue public Vector3f invert() { - this.x = -this.x; - this.y = -this.y; - this.z = -this.z; - return this; + return new Vector3f(-this.x, -this.y, -this.z); } - + /** - * @brief In-Equality compare operator with an other object. + * In-Equality compare operator with an other object. * @param obj Reference on the comparing object * @return true The Objects are NOT identical * @return false The Objects are identical */ + @CheckReturnValue public boolean isDifferent(final Vector3f obj) { return ((this.z != obj.z) || (this.y != obj.y) || (this.x != obj.x)); } - + /** - * @brief Equality compare operator with an other object. + * Equality compare operator with an other object. * @param obj Reference on the comparing object * @return true The Objects are identical * @return false The Objects are NOT identical */ + @CheckReturnValue public boolean isEqual(final Vector3f obj) { return ((this.z == obj.z) && (this.y == obj.y) && (this.x == obj.x)); } - + /** - * @brief Check if the vector is unitary (langth = 10f=) + * Check if the vector is unitary (langth = 10f=) * @return true if unit , false otherwise */ + @CheckReturnValue public boolean isUnit() { return FMath.approxEqual(length2(), 1.0f, Constant.MACHINE_EPSILON); } - + /** - * @brief Check if the vector is equal to (0,0,0) + * Check if the vector is equal to (0,0,0) * @return true The value is equal to (0,0,0) * @return false The value is NOT equal to (0,0,0) */ + @CheckReturnValue public boolean isZero() { return FMath.approxEqual(length2(), 0.0f, Constant.MACHINE_EPSILON); } - + /** - * @brief Get the length of the vector + * Get the length of the vector * @return Length value */ + @CheckReturnValue public float length() { return (float) Math.sqrt(length2()); } - + /** - * @brief Get the length between the 2 vectors + * Get the length between the 2 vectors * @param start First vector - * @param stop second vector + * @param stop second vector * @return Length value */ + @CheckReturnValue public float length(final Vector3f start, final Vector3f stop) { return (float) Math.sqrt(length2(start, stop)); } - + /** - * @brief Get the length of the vector squared + * Get the length of the vector squared * @return Squared length value. */ + @CheckReturnValue public float length2() { return dot(this); } - + /** - * @brief Return the linear interpolation between this and another vector - * @param obj The other vector - * @param ratio The ratio of this to obj (ratio = 0 => return copy of this, ratio=1 => return other) + * Return the linear interpolation between this and another vector + * @param obj The other vector + * @param ratio The ratio of this to obj (ratio = 0 => return copy of this, + * ratio=1 => return other) * @return New vector containing the value */ + @CheckReturnValue public Vector3f lerp(final Vector3f obj, final float ratio) { - return new Vector3f(this.x + (obj.x - this.x) * ratio, this.y + (obj.y - this.y) * ratio, this.z + (obj.z - this.z) * ratio); + return new Vector3f(this.x + (obj.x - this.x) * ratio, this.y + (obj.y - this.y) * ratio, + this.z + (obj.z - this.z) * ratio); } + @CheckReturnValue public Vector3f less(final float value) { - this.x -= value; - this.y -= value; - this.z -= value; - return this; - } - - /** - * @brief Subtract a vector from this one - * @param obj The vector to subtract - */ - public Vector3f less(final Vector3f obj) { - this.x -= obj.x; - this.y -= obj.y; - this.z -= obj.z; - return this; - } - - public Vector3f lessNew(final float value) { return new Vector3f(this.x - value, this.y - value, this.z - value); } - + @CheckReturnValue + public Vector3f less(final float xxx, final float yyy, final float zzz) { + return new Vector3f(this.x - xxx, this.y - yyy, this.z - zzz); + } + /** - * @brief Subtract a vector from this one + * Subtract a vector from this one * @param obj The vector to subtract * @return A new vector with the data */ - public Vector3f lessNew(final Vector3f obj) { + @CheckReturnValue + public Vector3f less(final Vector3f obj) { return new Vector3f(this.x - obj.x, this.y - obj.y, this.z - obj.z); } - + /** - * @brief Return the axis with the largest value + * Return the axis with the largest value * @return values 0,1,2 for x, y, or z */ + @CheckReturnValue public int maxAxis() { if (this.x < this.y) { return this.y < this.z ? 2 : 1; } return this.x < this.z ? 2 : 0; } - + /** - * @brief Return the axis with the smallest value + * Return the axis with the smallest value * @return values 0,1,2 for x, y, or z */ + @CheckReturnValue public int minAxis() { if (this.x < this.y) { return this.x < this.z ? 0 : 2; } return this.y < this.z ? 1 : 2; } - + /** - * @brief Scale the vector - * @param val Scale factor - */ - public Vector3f multiply(final float val) { - this.x *= val; - this.y *= val; - this.z *= val; - return this; - } - - /** - * @brief Elementwise multiply this vector by the other - * @param obj The other vector - * @return the current reference - */ - public Vector3f multiply(final Vector3f obj) { - this.x *= obj.x; - this.y *= obj.y; - this.z *= obj.z; - return this; - } - - /** - * @brief Scale the vector + * Scale the vector * @param val Scale factor * @return A new vector with the data */ - public Vector3f multiplyNew(final float val) { + @CheckReturnValue + public Vector3f multiply(final float val) { return new Vector3f(this.x * val, this.y * val, this.z * val); } - + /** - * @brief Elementwise multiply this vector by the other + * Elementwise multiply this vector by the other * @param obj The other vector */ - public Vector3f multiplyNew(final Vector3f obj) { + @CheckReturnValue + public Vector3f multiply(final Vector3f obj) { return new Vector3f(this.x * obj.x, this.y * obj.y, this.z * obj.z); } - - public void multiplyTo(final Vector3f obj, final Vector3f out) { - out.set(this.x * obj.x, this.y * obj.y, this.z * obj.z); - } - + /** - * @brief Normalize this vector x^2 + y^2 + z^2 = 1 + * Normalize this vector x^2 + y^2 + z^2 = 1 * @return the current vector */ + @CheckReturnValue public Vector3f normalize() { - this.divide(this.length()); - return this; + return this.divide(this.length()); } - + /** - * @brief Return a normalized version of this vector - * @return New vector containing the value - */ - public Vector3f normalizeNew() { - return clone().normalize(); - } - - /** - * @brief Return a rotated version of this vector + * Return a rotated version of this vector * @param wAxis The axis to rotate about * @param angle The angle to rotate by * @return New vector containing the value */ + @CheckReturnValue public Vector3f rotateNew(final Vector3f wAxis, final float angle) { - final Vector3f out = wAxis.clone(); - out.multiply(wAxis.dot(this)); - final Vector3f x = clone(); - x.less(out); - final Vector3f y = wAxis.cross(this); - x.multiply((float) Math.cos(angle)); - y.multiply((float) Math.sin(angle)); - out.add(x); - out.add(y); + Vector3f out = wAxis.multiply(wAxis.dot(this)); + Vector3f x = this.less(out); + Vector3f y = wAxis.cross(this); + x = x.multiply((float) Math.cos(angle)); + y = y.multiply((float) Math.sin(angle)); + out = out.add(x); + out = out.add(y); return out; } - + /** - * @brief Normalize this vector x^2 + y^2 + z^2 = 1 (check if not deviding by 0, if it is the case ==> return (1,0,0)) + * Normalize this vector x^2 + y^2 + z^2 = 1 (check if not deviding by 0, + * if it is the case ==> return (1,0,0)) * @return the current vector */ + @CheckReturnValue public Vector3f safeNormalize() { final float length = length(); if (length != 0.0f) { - this.divide(length); - return this; + return this.divide(length); } - setValue(1, 0, 0); - return this; + return new Vector3f(1, 0, 0); } - + /** - * @brief Return a normalized version of this vector (check if not deviding by 0, if it is the case ==> return (1,0,0)) - * @return New vector containing the value - */ - public Vector3f safeNormalizeNew() { - final Vector3f out = new Vector3f(this); - out.safeNormalize(); - return out; - } - - /** - * @brief Set scalar values - * @param xxx X value - * @param yyy Y value - * @param zzz Z value - */ - public Vector3f set(final float xxx, final float yyy, final float zzz) { - this.x = xxx; - this.y = yyy; - this.z = zzz; - return this; - } - - /** - * @brief Copy an other object - * @param obj The vector to add to this one - */ - public Vector3f set(final Vector3f obj) { - this.x = obj.x; - this.y = obj.y; - this.z = obj.z; - return this; - } - - /** - * @brief Interpolate the vector with a ration between 2 others - * @param obj0 First vector - * @param obj1 Second vector + * Interpolate the vector with a ration between 2 others + * @param obj0 First vector + * @param obj1 Second vector * @param ratio Ratio between obj0 and obj1 */ - public void setInterpolate3(final Vector3f obj0, final Vector3f obj1, final float ratio) { + @CheckReturnValue + public Vector3f setInterpolate3(final Vector3f obj0, final Vector3f obj1, final float ratio) { final float inverse = 1.0f - ratio; - this.x = inverse * obj0.x + ratio * obj1.x; - this.y = inverse * obj0.y + ratio * obj1.y; - this.z = inverse * obj0.z + ratio * obj1.z; - // this.co[3] = s * v0[3] + rt * v1[3]; + return new Vector3f(inverse * obj0.x + ratio * obj1.x, inverse * obj0.y + ratio * obj1.y, + inverse * obj0.z + ratio * obj1.z); + // this.co[3] = s * v0[3] + rt * v1[3]; } - + /** - * @brief Set each element to the max of the current values and the values of another Vector3f - * @param obj The other Vector3f to compare with + * Set each element to the max of the current values and the values of + * another Vector3f + * @param obj The other Vector3f to compare with */ - public void setMax(final Vector3f obj) { - this.x = Math.max(this.x, obj.x); - this.y = Math.max(this.y, obj.y); - this.z = Math.max(this.z, obj.z); + @CheckReturnValue + public Vector3f max(final Vector3f obj) { + return new Vector3f(Math.max(this.x, obj.x), Math.max(this.y, obj.y), Math.max(this.z, obj.z)); } + @CheckReturnValue + public static Vector3f max(final Vector3f obj1, final Vector3f obj2) { + return new Vector3f(Math.max(obj1.x, obj2.x), Math.max(obj1.y, obj2.y), Math.max(obj1.z, obj2.z)); + } + + @CheckReturnValue + public static Vector3f min(final Vector3f obj1, final Vector3f obj2) { + return new Vector3f(Math.min(obj1.x, obj2.x), Math.min(obj1.y, obj2.y), Math.min(obj1.z, obj2.z)); + } + /** - * @brief Set each element to the min of the current values and the values of another Vector3f - * @param obj The other Vector3f to compare with + * Set each element to the min of the current values and the values of + * another Vector3f + * @param obj The other Vector3f to compare with */ - public void setMin(final Vector3f obj) { - this.x = Math.min(this.x, obj.x); - this.y = Math.min(this.y, obj.y); - this.z = Math.min(this.z, obj.z); + @CheckReturnValue + public Vector3f min(final Vector3f obj) { + return new Vector3f(Math.min(this.x, obj.x), Math.min(this.y, obj.y), Math.min(this.z, obj.z)); } + @CheckReturnValue + public Vector3f withX(final float xxx) { + return new Vector3f(xxx, this.y, this.z); + } + + @CheckReturnValue + public Vector3f withY(final float yyy) { + return new Vector3f(this.x, yyy, this.z); + } + + @CheckReturnValue + public Vector3f withZ(final float zzz) { + return new Vector3f(this.x, this.y, zzz); + } + /** - * @brief Set Value on the vector - * @param xxx X value. - * @param yyy Y value. - * @param zzz Z value. + * Set 0 value on all the vector */ - public void setValue(final float xxx, final float yyy, final float zzz) { - this.x = xxx; - this.y = yyy; - this.z = zzz; - } - - /** - * @brief Set the x value - * @param x New value - */ - public void setX(final float x) { - this.x = x; - } - - /** - * @brief Set the y value - * @param y New value - */ - public void setY(final float y) { - this.y = y; - } - - /** - * @brief Set the z value - * @param z New value - */ - public void setZ(final float z) { - this.z = z; - } - - /** - * @brief Set 0 value on all the vector - */ - public void setZero() { - setValue(0, 0, 0); - } - - public void to(final Vector3f out) { - out.set(this.x, this.y, this.z); - } - + public static final Vector3f ZERO = new Vector3f(0, 0, 0); + public static final Vector3f ONE = new Vector3f(1, 1, 1); + @Override public String toString() { - return "Vector3f(" + FMath.floatToString(this.x) + "," + FMath.floatToString(this.y) + "," + FMath.floatToString(this.z) + ")"; + return "Vector3f(" + FMath.floatToString(this.x) + "," + FMath.floatToString(this.y) + "," + + FMath.floatToString(this.z) + ")"; } - + /** - * @brief Return the triple product between this and another vector and another + * Return the triple product between this and another vector and another * @param obj1 The other vector 1 * @param obj2 The other vector 2 * @return Value with the result of the triple product */ + @CheckReturnValue public float triple(final Vector3f obj1, final Vector3f obj2) { - return this.x * (obj1.y * obj2.z - obj1.z * obj2.y) + this.y * (obj1.z * obj2.x - obj1.x * obj2.z) + this.z * (obj1.x * obj2.y - obj1.y * obj2.x); + return this.x * (obj1.y * obj2.z - obj1.z * obj2.y) + this.y * (obj1.z * obj2.x - obj1.x * obj2.z) + + this.z * (obj1.x * obj2.y - obj1.y * obj2.x); } - } diff --git a/src/org/atriasoft/etk/math/Vector3i.java b/src/org/atriasoft/etk/math/Vector3i.java index f86c824..b39d678 100644 --- a/src/org/atriasoft/etk/math/Vector3i.java +++ b/src/org/atriasoft/etk/math/Vector3i.java @@ -1,8 +1,12 @@ package org.atriasoft.etk.math; +import edu.umd.cs.findbugs.annotations.CheckReturnValue; import org.atriasoft.etk.internal.Log; -public class Vector3i { +public record Vector3i( + int x, + int y, + int z) { public static Vector3i valueOf(String value) { int val1 = 0; int val2 = 0; @@ -24,7 +28,7 @@ public class Vector3i { val1 = Integer.valueOf(values[0]); val2 = val1; val3 = val1; - } else if (values.length == 1) { + } else if (values.length == 2) { // no coma ... // in every case, we parse the first element : val1 = Integer.valueOf(values[0]); @@ -42,90 +46,67 @@ public class Vector3i { return new Vector3i(0, 0, 0); } - public int x = 0; - public int y = 0; - public int z = 0; - /** - * @brief Default constructor + * Default constructor */ - public Vector3i() {} + public Vector3i() { + this(0, 0, 0); + } + public Vector3i(final int x, final int y, final int z) { + this.x = x; + this.y = y; + this.z = z; + } + + public static Vector3i max(final Vector3i obj1, final Vector3i obj2) { + return new Vector3i(Math.max(obj1.x, obj2.x), Math.max(obj1.y, obj2.y), Math.max(obj1.z, obj2.z)); + } + + public static Vector3i min(final Vector3i obj1, final Vector3i obj2) { + return new Vector3i(Math.min(obj1.x, obj2.x), Math.min(obj1.y, obj2.y), Math.min(obj1.z, obj2.z)); + } + /** - * @brief Constructor from scalars + * Constructor from scalars * @param value unique value for X,Y and Z value */ public Vector3i(final int value) { - this.x = value; - this.y = value; - this.z = value; + this(value, value, value); } /** - * @brief Constructor from scalars - * @param xxx X value - * @param yyy Y value - * @param zzz Z value - */ - public Vector3i(final int xxx, final int yyy, final int zzz) { - this.x = xxx; - this.y = yyy; - this.z = zzz; - } - - /** - * @brief Constructor from other vector (copy) - * @param obj The vector to add to this one - */ - public Vector3i(final Vector3i obj) { - this.x += obj.x; - this.y += obj.y; - this.z += obj.z; - } - - /** - * @brief Return a vector will the absolute values of each element + * Return a vector will the absolute values of each element * @return the curent reference */ - public Vector3i absolute() { - this.x = Math.abs(this.x); - this.y = Math.abs(this.y); - this.z = Math.abs(this.z); - return this; - } - - /** - * @brief Return a vector will the absolute values of each element - * @return New vector containing the value - */ - public Vector3i absoluteNew() { + @CheckReturnValue + public Vector3i abs() { return new Vector3i(Math.abs(this.x), Math.abs(this.y), Math.abs(this.z)); } /** - * @brief Add a vector to this one + * Add a vector to this one * @param obj The vector to add to this one */ + @CheckReturnValue public Vector3i add(final Vector3i obj) { - this.x += obj.x; - this.y += obj.y; - this.z += obj.z; - return this; - } - - /** - * @brief Add a vector to this one - * @param obj The vector to add to this one - */ - public Vector3i addNew(final Vector3i obj) { return new Vector3i(this.x + obj.x, this.y + obj.y, this.z + obj.z); } + @CheckReturnValue + public Vector3i add(final int value) { + return new Vector3i(this.x + value, this.y + value, this.z + value); + } + @CheckReturnValue + public Vector3i add(final int xxx, final int yyy, final int zzz) { + return new Vector3i(this.x + xxx, this.y + yyy, this.z + zzz); + } /** - * @brief Calculate the angle between this and another vector + * Calculate the angle between this and another vector * @param obj The other vector * @return Angle in radian */ + @CheckReturnValue public int angle(final Vector3i obj) { final int s = (int) Math.sqrt(length2() * obj.length2()); if (0 != s) { @@ -135,60 +116,54 @@ public class Vector3i { } /** - * @brief Clone the current vector. - * @return New vector containing the value - */ - @Override - public Vector3i clone() { - return new Vector3i(this); - } - - /** - * @brief Return the axis with the largest ABSOLUTE value + * Return the axis with the largest ABSOLUTE value * @return values 0,1,2 for x, y, or z */ + @CheckReturnValue public int closestAxis() { - return absoluteNew().maxAxis(); + return abs().maxAxis(); } /** - * @brief Return the cross product between this and another vector + * Return the cross product between this and another vector * @param obj The other vector * @return Vector with the result of the cross product */ + @CheckReturnValue public Vector3i cross(final Vector3i obj) { return new Vector3i(this.y * obj.z - this.z * obj.y, this.z * obj.x - this.x * obj.z, this.x * obj.y - this.y * obj.x); } /** - * @brief Inversely scale the vector + * Inversely scale the vector * @param val Scale factor to divide by */ - public void devide(final int val) { + @CheckReturnValue + public Vector3i devide(final int val) { if (val != 0.0f) { - this.x /= val; - this.y /= val; - this.z /= val; + return new Vector3i(this.x / val, this.y / val, this.z / val); } - // TODO maybe throw ... + throw new ArithmeticException("Vector3i devide by 0"); } /** - * @brief Return the distance between the ends of this and another vector + * Return the distance between the ends of this and another vector * This is symantically treating the vector like a point * @param obj The other vector to compare distance * @return the distance of the 2 points */ + @CheckReturnValue public int distance(final Vector3i obj) { return (int) Math.sqrt(distance2(obj)); } /** - * @brief Return the distance squared between the ends of this and another vector + * Return the distance squared between the ends of this and another vector * This is symantically treating the vector like a point * @param obj The other vector to compare distance * @return the square distance of the 2 points */ + @CheckReturnValue public int distance2(final Vector3i obj) { final int deltaX = obj.x - this.x; final int deltaY = obj.y - this.y; @@ -197,160 +172,157 @@ public class Vector3i { } /** - * @brief Return the dot product + * Return the dot product * @param obj The other vector in the dot product * @return Dot product value */ + @CheckReturnValue public int dot(final Vector3i obj) { return this.x * obj.x + this.y * obj.y + this.z * obj.z; } /** - * @brief Return the axis with the smallest ABSOLUTE value + * Return the axis with the smallest ABSOLUTE value * @return values 0,1,2 for x, y, or z */ + @CheckReturnValue public int furthestAxis() { - return absoluteNew().minAxis(); + return abs().minAxis(); } /** - * @brief Get the maximum value of the vector (x, y, z) + * Get the maximum value of the vector (x, y, z) * @return The max value */ + @CheckReturnValue public int getMax() { return Math.max(Math.max(this.x, this.y), this.z); } /** - * @brief Get the Axis id with the maximum value + * Get the Axis id with the maximum value * @return Axis ID 0,1,2 */ + @CheckReturnValue public int getMaxAxis() { return (this.x < this.y ? (this.y < this.z ? 2 : 1) : (this.x < this.z ? 2 : 0)); } /** - * @brief Get the minimum value of the vector (x, y, z) + * Get the minimum value of the vector (x, y, z) * @return The min value */ + @CheckReturnValue public int getMin() { return Math.min(Math.min(this.x, this.y), this.z); } /** - * @brief Get the Axis id with the minimum value + * Get the Axis id with the minimum value * @return Axis ID 0,1,2 */ + @CheckReturnValue public int getMinAxis() { return (this.x < this.y ? (this.x < this.z ? 0 : 2) : (this.y < this.z ? 1 : 2)); } + @CheckReturnValue + public Vector3i getSkewSymmetricMatrix0() { + return new Vector3i(0, -this.z, this.y); + } - /** - * @brief Create a skew matrix of the object - * @param obj0 Vector matric first line - * @param obj1 Vector matric second line - * @param obj2 Vector matric third line - */ - public void getSkewSymmetricMatrix(final Vector3i obj0, final Vector3i obj1, final Vector3i obj2) { - obj0.setValue(0, -this.z, this.y); - obj1.setValue(this.z, 0, -this.x); - obj2.setValue(-this.y, this.x, 0); + @CheckReturnValue + public Vector3i getSkewSymmetricMatrix1() { + return new Vector3i(this.z, 0, -this.x); + } + + @CheckReturnValue + public Vector3i getSkewSymmetricMatrix2() { + return new Vector3i(-this.y, this.x, 0); } /** - * @brief Get X value - * @return the x value - */ - public int getX() { - return this.x; - } - - /** - * @brief Get Y value - * @return the y value - */ - public int getY() { - return this.y; - } - - /** - * @brief Get Z value - * @return the z value - */ - public int getZ() { - return this.z; - } - - /** - * @brief In-Equality compare operator with an other object. + * In-Equality compare operator with an other object. * @param obj Reference on the comparing object * @return true The Objects are NOT identical * @return false The Objects are identical */ + @CheckReturnValue public boolean isDifferent(final Vector3i obj) { return ((this.z != obj.z) || (this.y != obj.y) || (this.x != obj.x)); } /** - * @brief Equality compare operator with an other object. + * Equality compare operator with an other object. * @param obj Reference on the comparing object * @return true The Objects are identical * @return false The Objects are NOT identical */ + @CheckReturnValue public boolean isEqual(final Vector3i obj) { return ((this.z == obj.z) && (this.y == obj.y) && (this.x == obj.x)); } /** - * @brief Check if the vector is equal to (0,0,0) + * Check if the vector is equal to (0,0,0) * @return true The value is equal to (0,0,0) * @return false The value is NOT equal to (0,0,0) */ + @CheckReturnValue public boolean isZero() { return this.x == 0 && this.y == 0 && this.z == 0; } /** - * @brief Get the length of the vector + * Get the length of the vector * @return Length value */ + @CheckReturnValue public int length() { return (int) Math.sqrt(length2()); } /** - * @brief Get the length of the vector squared + * Get the length of the vector squared * @return Squared length value. */ + @CheckReturnValue public int length2() { return dot(this); } /** - * @brief Return the linear interpolation between this and another vector + * Return the linear interpolation between this and another vector * @param obj The other vector * @param ratio The ratio of this to obj (ratio = 0 => return copy of this, ratio=1 => return other) * @return New vector containing the value */ + @CheckReturnValue public Vector3i lerp(final Vector3i obj, final int ratio) { return new Vector3i(this.x + (obj.x - this.x) * ratio, this.y + (obj.y - this.y) * ratio, this.z + (obj.z - this.z) * ratio); } /** - * @brief Subtract a vector from this one + * Subtract a vector from this one * @param obj The vector to subtract */ + @CheckReturnValue public Vector3i less(final Vector3i obj) { - this.x -= obj.x; - this.y -= obj.y; - this.z -= obj.z; - return this; + return new Vector3i(this.x - obj.x, this.y - obj.y, this.z - obj.z); + } + @CheckReturnValue + public Vector3i less(final int value) { + return new Vector3i(this.x - value, this.y - value, this.z - value); + } + @CheckReturnValue + public Vector3i less(final int xxx, final int yyy, final int zzz) { + return new Vector3i(this.x - xxx, this.y - yyy, this.z - zzz); } /** - * @brief Return the axis with the largest value + * Return the axis with the largest value * @return values 0,1,2 for x, y, or z */ + @CheckReturnValue public int maxAxis() { if (this.x < this.y) { return this.y < this.z ? 2 : 1; @@ -359,9 +331,10 @@ public class Vector3i { } /** - * @brief Return the axis with the smallest value + * Return the axis with the smallest value * @return values 0,1,2 for x, y, or z */ + @CheckReturnValue public int minAxis() { if (this.x < this.y) { return this.x < this.z ? 0 : 2; @@ -370,166 +343,77 @@ public class Vector3i { } /** - * @brief Scale the vector + * Scale the vector * @param val Scale factor */ + @CheckReturnValue public Vector3i multiply(final int val) { - this.x *= val; - this.y *= val; - this.z *= val; - return this; - } - - /** - * @brief Elementwise multiply this vector by the other - * @param obj The other vector - * @return the current reference - */ - public Vector3i multiply(final Vector3i obj) { - this.x *= obj.x; - this.y *= obj.y; - this.z *= obj.z; - return this; - } - - /** - * @brief Scale the vector - * @param val Scale factor - */ - public Vector3i multiplyNew(final int val) { return new Vector3i(this.x * val, this.y * val, this.z * val); } /** - * @brief Elementwise multiply this vector by the other - * @param obj The other vector - */ - public Vector3i multiplyNew(final Vector3i obj) { - this.x *= obj.x; - this.y *= obj.y; - this.z *= obj.z; - return this; - } - - /** - * @brief Normalize this vector x^2 + y^2 + z^2 = 1 - */ - public void normalize() { - devide(length()); - } - - /** - * @brief Return a normalized version of this vector + * Normalize this vector x^2 + y^2 + z^2 = 1 * @return New vector containing the value */ - public Vector3i normalizeNew() { - final Vector3i out = new Vector3i(this); - out.normalize(); - return out; + @CheckReturnValue + public Vector3i normalize() { + return devide(length()); } /** - * @brief Return a rotated version of this vector + * Return a rotated version of this vector * @param wAxis The axis to rotate about * @param angle The angle to rotate by * @return New vector containing the value */ - public Vector3i rotateNew(final Vector3i wAxis, final int angle) { - final Vector3i out = wAxis.clone(); - out.multiply(wAxis.dot(this)); - final Vector3i x = clone(); - x.less(out); - final Vector3i y = wAxis.cross(this); - x.multiply((int) Math.cos(angle)); - y.multiply((int) Math.sin(angle)); - out.add(x); - out.add(y); + @CheckReturnValue + public Vector3i rotate(final Vector3i wAxis, final int angle) { + Vector3i out = wAxis.multiply(wAxis.dot(this)); + Vector3i x = less(out); + Vector3i y = wAxis.cross(this); + x = x.multiply((int) Math.cos(angle)); + y = y.multiply((int) Math.sin(angle)); + out = out.add(x); + out = out.add(y); return out; } /** - * @brief Normalize this vector x^2 + y^2 + z^2 = 1 (check if not deviding by 0, if it is the case ==> return (1,0,0)) - */ - public void safeNormalize() { - final int length = length(); - if (length != 0.0f) { - devide(length); - } - setValue(1, 0, 0); - } - - /** - * @brief Return a normalized version of this vector (check if not deviding by 0, if it is the case ==> return (1,0,0)) + * Normalize this vector x^2 + y^2 + z^2 = 1 (check if not dividing by 0, if it is the case ==> return (1,0,0)) * @return New vector containing the value */ - public Vector3i safeNormalizeNew() { - final Vector3i out = new Vector3i(this); - out.safeNormalize(); - return out; + @CheckReturnValue + public Vector3i safeNormalize() { + final int length = length(); + if (length != 0.0f) { + return devide(length); + } + return new Vector3i(1, 0, 0); } /** - * @brief Set each element to the max of the current values and the values of another Vector3f - * @param obj The other Vector3f to compare with + * Set each element to the max of the current values and the values of another Vector3i + * @param obj The other Vector3i to compare with */ - public void setMax(final Vector3i obj) { - this.x = Math.max(this.x, obj.x); - this.y = Math.max(this.y, obj.y); - this.z = Math.max(this.z, obj.z); + @CheckReturnValue + public Vector3i max(final Vector3i obj) { + return new Vector3i(Math.max(this.x, obj.x), Math.max(this.y, obj.y), Math.max(this.z, obj.z)); } /** - * @brief Set each element to the min of the current values and the values of another Vector3f - * @param obj The other Vector3f to compare with + * Set each element to the min of the current values and the values of another Vector3i + * @param obj The other Vector3i to compare with */ - public void setMin(final Vector3i obj) { - this.x = Math.min(this.x, obj.x); - this.y = Math.min(this.y, obj.y); - this.z = Math.min(this.z, obj.z); + @CheckReturnValue + public Vector3i min(final Vector3i obj) { + return new Vector3i(Math.min(this.x, obj.x), Math.min(this.y, obj.y), Math.min(this.z, obj.z)); } /** - * @brief Set Value on the vector - * @param xxx X value. - * @param yyy Y value. - * @param zzz Z value. + * Set 0 value on all the vector */ - public void setValue(final int xxx, final int yyy, final int zzz) { - this.x = xxx; - this.y = yyy; - this.z = zzz; - } - - /** - * @brief Set the x value - * @param x New value - */ - public void setX(final int x) { - this.x = x; - } - - /** - * @brief Set the y value - * @param y New value - */ - public void setY(final int y) { - this.y = y; - } - - /** - * @brief Set the z value - * @param z New value - */ - public void setZ(final int z) { - this.z = z; - } - - /** - * @brief Set 0 value on all the vector - */ - public void setZero() { - setValue(0, 0, 0); - } + public static final Vector3i ZERO = new Vector3i(0, 0, 0); + public static final Vector3i ONE = new Vector3i(1, 1, 1); @Override public String toString() { @@ -537,11 +421,12 @@ public class Vector3i { } /** - * @brief Return the triple product between this and another vector and another + * Return the triple product between this and another vector and another * @param obj1 The other vector 1 * @param obj2 The other vector 2 * @return Value with the result of the triple product */ + @CheckReturnValue public int triple(final Vector3i obj1, final Vector3i obj2) { return this.x * (obj1.y * obj2.z - obj1.z * obj2.y) + this.y * (obj1.z * obj2.x - obj1.x * obj2.z) + this.z * (obj1.x * obj2.y - obj1.y * obj2.x); } diff --git a/src/org/atriasoft/etk/theme/Theme.java b/src/org/atriasoft/etk/theme/Theme.java index eb0497e..c7fa8d4 100644 --- a/src/org/atriasoft/etk/theme/Theme.java +++ b/src/org/atriasoft/etk/theme/Theme.java @@ -8,79 +8,81 @@ import java.util.Set; import org.atriasoft.etk.internal.Log; public class Theme { - private static Map g_listTheme = new HashMap<>(); - private static Map g_listThemeDefault = new HashMap<>(); + private static Map globalListTheme = new HashMap<>(); + private static Map globalListThemeDefault = new HashMap<>(); /** - * @brief get the folder from a Reference theme - * @param[in] _refName Theme cathegorie ex : "GUI" "SHADER" "DEFAULT" + * get the folder from a Reference theme + * @param refName Theme cathegorie ex : "GUI" "SHADER" "DEFAULT" * @return the path of the theme */ - public static Path getName(final String _refName) { - return g_listTheme.get(_refName); + public static Path getName(final String refName) { + return globalListTheme.get(refName); } /** - * @brief get the default folder from a Reference theme - * @param[in] _refName Theme cathegorie ex : "GUI" "SHADER" "DEFAULT" + * get the default folder from a Reference theme + * @param refName Theme cathegorie ex : "GUI" "SHADER" "DEFAULT" * @return the path of the theme */ - public static Path getNameDefault(final String _refName) { - return g_listThemeDefault.get(_refName); - }; + public static Path getNameDefault(final String refName) { + return globalListThemeDefault.get(refName); + } /** - * @brief initialize the theme system + * initialize the theme system */ public static void init() { }; /** - * @brief Get the list of all the theme folder availlable in the user Home/appl + * Get the list of all the theme folder availlable in the user Home/appl * @return The list of elements */ public static Set list() { - return g_listTheme.keySet(); - } - - /** - * @brief Set the Folder of a subset of a theme ... - * @param[in] _refName Theme cathegorie ex : "GUI" "SHADER" "DEFAULT" - * @param[in] _folderName The associated folder of the Theme (like "myTheme/folder/folder2/") - */ - public static void setName(final String _refName, final Path _folderName) { - Log.warning("Change theme : '" + _refName + "' : '" + _folderName + "'"); - g_listTheme.put(_refName, _folderName); - updateProvider(_refName); - } - - /** - * @brief Set the default folder of a subset of a theme ... - * @param[in] _refName Theme cathegorie ex : "GUI" "SHADER" "DEFAULT" - * @param[in] _folderName The associated default folder of the Theme (like "myTheme/color/default/") - */ - public static void setNameDefault(final String _refName, final Path _folderName) { - g_listThemeDefault.put(_refName, _folderName); - updateProvider(_refName); - } - - /** - * @brief un-initialize the theme system - */ - public static void unInit() { - g_listTheme.clear(); - g_listThemeDefault.clear(); - } - - public static void updateProvider(final String _refName) { - final Path base = getName(_refName); - final Path baseDefault = getNameDefault(_refName); - if (base == null) { - //etk::uri::provider::add("THEME_" + _refName, new ProviderTheme(new Path("theme") / baseDefault, Path("theme") / base)); - } else { - //etk::uri::provider::add("THEME_" + _refName, new ProviderTheme(Path("theme") / base, Path("theme") / baseDefault)); - } + return globalListTheme.keySet(); }; + /** + * Set the Folder of a subset of a theme ... + * @param refName Theme cathegorie ex : "GUI" "SHADER" "DEFAULT" + * @param folderName The associated folder of the Theme (like "myTheme/folder/folder2/") + */ + public static void setName(final String refName, final Path folderName) { + Log.warning("Change theme : '" + refName + "' : '" + folderName + "'"); + globalListTheme.put(refName, folderName); + updateProvider(refName); + } + + /** + * Set the default folder of a subset of a theme ... + * @param _refName Theme cathegorie ex : "GUI" "SHADER" "DEFAULT" + * @param _folderName The associated default folder of the Theme (like "myTheme/color/default/") + */ + public static void setNameDefault(final String refName, final Path folderName) { + globalListThemeDefault.put(refName, folderName); + updateProvider(refName); + } + + /** + * un-initialize the theme system + */ + public static void unInit() { + globalListTheme.clear(); + globalListThemeDefault.clear(); + } + + public static void updateProvider(final String refName) { + final Path base = getName(refName); + final Path baseDefault = getNameDefault(refName); + if (base == null) { + //etk::uri::provider::add("THEME_" + refName, new ProviderTheme(new Path("theme") / baseDefault, Path("theme") / base)); + } else { + //etk::uri::provider::add("THEME_" + refName, new ProviderTheme(Path("theme") / base, Path("theme") / baseDefault)); + } + } + + private Theme() {}; + } diff --git a/test/src/test/atriasoft/etk/TestBasicLog.java b/test/src/test/atriasoft/etk/TestBasicLog.java index 6106c2c..22f6b89 100644 --- a/test/src/test/atriasoft/etk/TestBasicLog.java +++ b/test/src/test/atriasoft/etk/TestBasicLog.java @@ -13,10 +13,9 @@ import java.util.List; import io.scenarium.logger.Logger; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; import org.junit.jupiter.api.Order; -//import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; @TestMethodOrder(OrderAnnotation.class)