From 04e237cf439d08aa64fdc0df4976e2c91f333e78 Mon Sep 17 00:00:00 2001 From: mattatz Date: Mon, 3 Sep 2018 17:25:12 +0900 Subject: [PATCH] Update unity version to 2018. --- .gitignore | 1 + Assets/Packages/MeshSmoothing/Demo/Demo.unity | Bin 17240 -> 15159 bytes .../Demo/Materials/defaultMat.mat | Bin 4896 -> 1895 bytes .../MeshSmoothing/Demo/sphere.obj.meta | 31 +- .../Packages/Triangulation2D/Demo/Demo.unity | Bin 13372 -> 8301 bytes .../Demo/Materials/CanvasLine.mat | Bin 4896 -> 1896 bytes .../Demo/Materials/DemoMesh.mat | Bin 4892 -> 1894 bytes .../Demo/Materials/DemoMeshLine.mat | Bin 4896 -> 1898 bytes .../Demo/Prefabs/DemoMesh.prefab | Bin 7412 -> 3056 bytes .../Triangulation2D/Demo/Scenes/Demo.unity | Bin 11768 -> 6757 bytes .../Demo/Shaders/DemoLine.shader | 6 +- .../Demo/Shaders/DemoMesh.shader | 6 +- Assets/Teddy/Materials/DebugChordLine.mat | Bin 4956 -> 1980 bytes Assets/Teddy/Materials/DebugNormal.mat | Bin 4952 -> 1977 bytes Assets/Teddy/Materials/Puppet.mat | Bin 5104 -> 2305 bytes Assets/Teddy/Materials/Teddy.mat | Bin 4928 -> 1928 bytes Assets/Teddy/Materials/TeddyDebug.mat | Bin 4932 -> 1933 bytes Assets/Teddy/Prefabs/Puppet.prefab | Bin 8548 -> 3727 bytes Assets/Teddy/Scenes/Demo.unity | Bin 16560 -> 9580 bytes Assets/Teddy/Scenes/Drawer.unity | Bin 37108 -> 21004 bytes Assets/Teddy/Scripts/Teddy/Teddy.cs | 1261 +++++++++-------- Assets/Teddy/Shaders/DebugChordLine.shader | 6 +- Assets/Teddy/Shaders/DebugNormal.shader | 6 +- Assets/Teddy/Shaders/Puppet.shader | 6 +- Assets/Teddy/Shaders/Teddy.shader | 6 +- Assets/Teddy/Shaders/TeddyDebug.shader | 6 +- Packages/manifest.json | 12 + README.md | 4 + 28 files changed, 709 insertions(+), 642 deletions(-) create mode 100644 Packages/manifest.json diff --git a/.gitignore b/.gitignore index b6a986e..f7bdeb4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ [Bb]uild/ [Pp]rojectSettings/ Papers/ +.vs/ # Autogenerated VS/MD solution and project files *.csproj diff --git a/Assets/Packages/MeshSmoothing/Demo/Demo.unity b/Assets/Packages/MeshSmoothing/Demo/Demo.unity index 315348b39f0dbb6fe7b8ea60571aed1346133b1b..9581229f18f4b62de81e8e0fddb918017e9bf64e 100644 GIT binary patch literal 15159 zcmeHNS#R4&5`NdO;5$p8aKeb!xHRrA+>4X-XO=fLUwdOJL`eyM)3N;W^NvbcQjMF*is_gvd?4mmr^XT3u{u#?M8wr{<0J7b=KzBctQ z7sEi_cq-;fQ0YDXITDEgyMN$+`=GmL(H#Aq>c1ey`P1yX5)s7UnV-izE1*4EX*+W8 zGR`>5aqOgId5MYD(UT04^0cIe=``k9IeGVfg$CDgH5IPg({#Aq!JgGnqIaJBuVSUh zS9Uv&uXj7H;llB}ExXThQDxD}X4}VwQUJD(Em8!whhsLbzQ{_$yJB3Eqy(fbp_-OC z3(NR{PZlf^k1KcihD*QK*H;C^Z*vs{GZjx)td#cLvI)obY~r$tA^jB z*{)LJIZMQ(%y~917o<0`XV^i)a^4IpmgL|mi}+;8Iq6LBrY4!JZP+cq)EDl|qUw8wq3cvvQ^m>?5@ zbKCXx^5HdUS8W|$U$Lj-xG2d08u^Swx*T4gJS{~A_M7FaF9JV5}nGWX6`i3SaQZnXs{unHFz2)6uF3=EnCJ6 zQNJSIT9RozZskTJ=d1XMN1H^_$Pp4U5@SQi&E0sy(j`HL=6(z+naL@x3GmGMW{;WZ z%0xvX!b}}KTB{X{w}`JBs<<0Blg2+*sB5O%_JE6Oxvg3|W;8-r;iq1G#;T&AP*N3! z7$f%fp{->NSqjuhHn*Ke1a5E*!46BL(Beh_10dv1;(5x<)he-Q(bZ>e+0YR2!W)Pf z!`NgY9vjEIe&Bh+fJSIq8$YNdKs7814pUpT{q!EeS7qju74Jwp8hSc|zvbHQac+M#w7`@1$Ng^oG z`%0T~Xq3dML@_G%Bs`k)<6JDwZXJf$(?2Q%oG=#!jK>5cJsD?XK8JpXIR`e;T4Gs+ z=*^QvMK`rHY?eZlKr=!zu^fxk-SnDexPQiTJdd6XaJ> zvjz6kd#$D2xEW=HWB1xByxm11YZiL6H(=%*|lLpH#rc>ln_LY zaJX(_Tg-(xr5lg{Wo*aKeJiYgHWw(O`x1OVyFw$oOZMJGViHOUQ&8Rr-Lb@yxj^21 z%Ye>RV1ApS1e^0nj$ed?o7R0qi+AO8fcr8IRq9;P#YHicc$a+8_>$c>3h3Jk#e5mr zr}r&wH*6VOP;gjb2;>cl8C$faFeEvp2`ep7N1&G6a?lO>!0x8p=z9a#>8?Qe4TL#n z*_@6f$3e{q*gVYUgsD6=qCm8P4r-CCA!Ol8dlXG3Xf{#s(AqcQ(ZJXS6xUO$Sf9>2 ziW$|<2ewHDzlj`0u^BetQ0toj(7DZ7R?MJ| zZ^&^j1!{n?pg$`#7Rf3i$8ZZGfp%djndV6b?E-_lVk~e6LjTXqcs45PvfB#2H_*8?`_0TpJqP)&! zw?{(;V(O$ycrMjZoX3=c=$ft~W#7YJ;-%@zKu z&3hsDUB>%<;JH!AqHYxQ?Ql7MD9sPSm1(%js1@=&Vr96v$Yw&pgISzIEY+0M59@$f02$Oz zUE=HPD`BhLOrd`hibzI>S-6lL@mbS?uK|Qyafc=&>IjsZIbI$%kCEx=A~Pt&2oxb1 z2=jrzy@Ti#MHll-8qCnbN}xC5&{fJ zH-=&g+ttyUC$&;%wF{l_k(l~+?L4u-woNW-6DI?QI`413Gg$S$j){RV0S_v2dFPK6!xTd zn=KFV4t3CizIl!JY;@#p^Gxpd{H{H~FIfu6sb1fgwPbp~%msZC0+b5?n#WJgdlo$@e%a>OC|f5QJU5^%B#QMLg3bzmCu<1)NeK#{&6k-c{gD!8ZAwNz5N_fL?&b zO9e@{v=UXvinhW3b6NJ*%c*)d-d6|zD23LQ8FJAwOd(0i$my=D2F zmpi{6P}6vT0KZy1=yS?FC+}9k#Do=5H&O5OT4M7-WPhNX#TVSm<~g({fZFmHJ$Yn zp;Q~X>^qt;d1f0-DJb=+eK{p_dHB}8T$>h9V$u`Br61Tmd<-=3UlT^H)~>G(gttVE zmp>O7hMxmYX3cZJ$*g&K<=)qE zWW$Ol8?O?kb6V$oExLVYeU$YNoz@#E{|AncAcFt^ literal 17240 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 CD*fjG diff --git a/Assets/Packages/MeshSmoothing/Demo/Materials/defaultMat.mat b/Assets/Packages/MeshSmoothing/Demo/Materials/defaultMat.mat index 193793f2a61faee55d8cbab0e4f9c3ec2e6d3af4..e5e061179a9a3739bf12b7a3cb8cc8957cbb866c 100644 GIT binary patch literal 1895 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 Ky`h0+HveCYzy^8% diff --git a/Assets/Packages/Triangulation2D/Demo/Materials/CanvasLine.mat b/Assets/Packages/Triangulation2D/Demo/Materials/CanvasLine.mat index 63a93e5df8752b6893874fd1e33bd0c3f22ad6b0..3d9c334761b71e30446115398de3bfc916ca1551 100644 GIT binary patch literal 1896 zcmcgtO;g)25WVMDhyy((Ozc1lzCi+%DTcJBblOfQvzFFItt@3EnUZ$;-@B5Nkba!) zgC^O1+P5Fx=lzeT`87)plEMDn=_T81_n3z|Yqj*Ni8$b<8K&bT$p)j*D0tI^y-1UB zcm_Fmv=US{V9do|@&}50v`!kGv6p0S7PsYBl3c%h(n85>9Q)L4sdX|#~KE=+4V zcF2tVtfa!L86kf~=-grj<&`EfO=SQ0Z=k`9O+i0`yOtW`rQ!hu+8yxWaZGy1>Q;)3 zr3s$k5y$j|C;YIil4F5odVF$(lcW@{#zW>;OA0&ba_GXn!PR$T1r-rFu4Vn;8(6Lj zJBr404JDLeW?J$W)DLlawe3dhylLK{rkvll*b;FXI!t}_mV(?t zox_r<3E2qg0)^;unuBvl(LaBQ^aVVkm|L?%>m}LA_}}47qN7>d;nTT(T;oP;an?4= zKo#BLZiM*OQc8agCOCt;;Glx@DPzfyt>_F%b`OoesvP>xO-&_toGN3)HA4?lovIRr z>6bGH_pQegZ;Wj~^;P0|BVE|QzW8#GnqH$``kB)!qm<;A$~f0ofw!Eiw$F~v!BUm* z)JuWQ;zAi9fr?wZmVotACmY+e^`@$5c@Kih?QHM%)&Bd&%=t4#g4Rh~yb*^+0_}nr zJ_p*&bO)ImL6Q>mFJ9aZpzs!T?H@>FHoi@-LdbEtu@;uE*|)&=_XYBupr1Zi>4~KS sG>fTG#y)o;{w3X_ZwSd+9nUhJKxZd$)U3_2?Z8Rq2u>%#>FnUY0Tc2PPyhe` literal 4896 zcmeI0OKcle6o!xO*hy1fZ76MNOU?UH2$T|@Ax-mYOJkCfwjdUmsXeg=#-3p2-00f_}Vq`M|ZydseQzId}Ea-V3`+ zU|B2{aHKpVlE8jlO%jm|eqZDy`6eStA0Yi`&B!*4e+It^$E@PC&dTrbaS(Ib=Q{W> z{5*vDK)Ob2{@%|@@_p(j-(lbBhw*9ataSS6H#{RJ;QvebVf?&CCgC~R%wfbsC1=c; zaq^ssb05xOoP*>_b8;HCZ$UZVZg@uEL&l)YmrCi*_h!X3?~L;n!*!g;F=ssJ7Otf1 ztvK1jt>WB4uGEfmr{TI^uVK!-hM*MIj`gf#Ony5dg#0S_yBISb-XmMZbBEz}-FA~h zSkHs#BkM*#dk7QqKGl~`Q@+>myp`{r;5y%e)t7zbN()wB_8YGK52BB}?g4OpUEBX% zv>&H0+duEqt^5~Lp2g}17+-+W|J^vI^-*>ED&_YWp0o10*YG|oulvX$tWRg%?k7yh z^YS4^?Ycc+ctO?kTg(~HgNFB8*X47j^Bu6R`!KoE0jr*m7@n8!FlIej<3msi>-IJJ z`vbi4p*`^n-&WFL08^)^(b=QsQ)LC|`DfC==IpeNOH?T@`C2l_~vF*4WD^Izx}el$G;jjYQ7MMZnGBG zX`USA-v`~jHm72pf8&(To?CD$v=@9VU|tHUjDVtYY1c&~_16;rJ}I~RHpvZWx@Zom LZ?o2}oj(2tkf;#{ diff --git a/Assets/Packages/Triangulation2D/Demo/Materials/DemoMesh.mat b/Assets/Packages/Triangulation2D/Demo/Materials/DemoMesh.mat index 6be7cc06d1677bdbc5fee777e4e2f6917b7d1a35..56cf1c162950e64cec16cc85c163e888cdd2fb03 100644 GIT binary patch literal 1894 zcmcgtO>^2X5WVv<X%g42A@#Z%IhfOyh*sX*zAE!>pynsFfu~l9SL*|9e+55c+Yp z4?D2?v~NGG=fh8@*$qpMlFs4%=@mPu515BCt+n*)p*Z5E>JIuzl6HE%UWg77_G*yy z!_&#Yqm`i24r4Cs5 z*dSB(b0HO8PYL-eLT45iP+V&w(?s@9{1z%q*%T|2poQxPCHLPz#acMwUxo!D`di zNpxOlD5!YtJZMgxJpc_z`(4{pQ&T*rX^5-q-7IS7P4yl%)%>o;nurHszBE;DDak#Q z8LX(AP>ql-P>80c890ZO{ma)#pTi@HnKdi4UXq`j|6R>62CDfzK40j^4X(%LXLYp- zR52XRMu@L1mGtLYLNJ7L4k`qnQKehuTd-W%;=R-O7bgZoNKGWJI+L{q(-tFDJ+JB#zI)A1}&>D%0C*sniMi<2J zCDC@Ld&tZPl9Zr-@!)O&xwoiGza){_#|f rnx7kG?8_A5U(zl5hLEh4(H7AH*+$}MSli3C2Pc^$I9Y;|ZQ#EF_>B<# literal 4892 zcmeI0OK=ob6oyYvGLsM#MMOYA;tStV#NZ2)kQZPW6AYl`W^9t1OiRyn?Cyz)<)T+s zX|dFmY$z=^R#}!SHtyW$$|}opfsd61TecQO{QrA#me2B)S>VF?&;I#(cRo0 zk>0OFcI*?8yF~8BL1b{?@W9~0A-T1-w&r;NJE5Ony|(}6wcRV%-<`g3dC#R?Wv~Jk zOE^+q6v<$}rYD(*hrh48B>UcztQ(MijC!&Kp`>_FXM}0Dd0F zyfWA?e>w>iU>9O3C6Y&2H{4joA!^?P1!8?R_sN{^<8zJw~ zaqh)AjI)niYnPmc?R!wpw_5HAe8>=#`BEwE`QE9S;jM9Qv)sga9COBlZsAJW-iebf z+$_%Rut=L*A6I!wPQW27?a;i2qC`#{t?EEhxf>4@!V&*Ten^05Z3bm z`pCM`&u+quyj%C>i=6MVyy)b6Ke)-a`?7vAZH8~=UiBd@z3++5f7{{Zbr zc#i9z_vvQ-`*U8v>L(aqg3|wkIOg@yb^A8w4_V&jqy0CZ_h&RSy!HMcu)HLH!1u41^BH{>D$=k0Tt>cEG3$mtN8G~y#EhKJ zpy9^P->4W@y%_~*kb7Y}Zm z`uSpY=*VZw?_YpXM>-YgRG?FVP6av@=v3f;s{pshwRZ`Xe6%TO}WQ3pFzwjFx zvIR=pO4$$U*cFhiONN~y)rhtmZPb>y^>Ds}ZZ2$aueHG#t8OgX_e3p7HZ^x``PrYxUG|d;n6-*)+mhq4@VuIjHiY8Z zZ-=W&88r#RVD5MrCCP>pVBwy_*x8@TY&zL-{No(=P- zgZ5tAQ?bsUa4Kid&8j)t3qBMuFGur?fTDA0*2N(Gvl4$gsWkgG#?5EGXb-t>yVk6o GIsONRsSj%a diff --git a/Assets/Packages/Triangulation2D/Demo/Materials/DemoMeshLine.mat b/Assets/Packages/Triangulation2D/Demo/Materials/DemoMeshLine.mat index 897954c4f5aedb27aabf560d58d79589e480ea76..70f34a839cd049e8ba96f20e30f0cfdfaeadc32f 100644 GIT binary patch literal 1898 zcmcgtO>^2X5WVv<X#~2Aj|j-$+Q(OmRZ%lup~}FtW5ZYGsL$PMZ^$H^@@sZWTbWl}5QwnN@$y6VP*C`vlLUe9~uh`flS zfqyzFbzlUQNrw;{eu?kE7htT=Dj_e?TrD5+FTmU@!Qn>I(k5gO%vahNuxqWjP-UiT z!=Q;w$d5uuxSL|+&k#B{P|*BNA(%q2zx?;Kf`m+=(ka;0OehG)vK8fEj>6Bzq3kXx zYrzu|M{ofn2Jr=p*jZjgV-9&dz8JwU%K7=AOWbyiiHA)UO}f{x{iY2^8UbS_%9X3= zdPi*(jMs|hNI+Rf6+?ClicM1PKz*uf^k>)+etUQ5M{S+1-h#rK-_%eeaO``GoplD2 zJkm0yYh>fA;lg?d-qbXw)&ge#^f|z1^a=Rf=rtH8(2mA`j%OGg)$$QG*Xn5(*CWfz zx>|dv;Pz)jh^q~j^!sSM)4MZ9rFU);5_QQI-@eG^!3$6n7F^@TrlLE{l@P?5f}=uC zWDZ=ni5cqD90Xs_i@x2ia lQJR2id8MT`&s_+AQMd3Lg1S|PcOKsKAaU5N{j&Wp{1-)}69WJM literal 4896 zcmeI0OKcle6o!xOI7w4pZ76MNOU?UH2$T|@AxZOUOJkCfwjdUmseNM)j6KoJxFiyb zVS@xqBqSs%qzc3a2_aT&*s)=Ugb<7HSfO?Si*BK6`2RcO8(+t$D|SB7>D>F>GiT0Y zW_rgWgP(~E7ewS{ky~&O867z?GP-5}_rmTX zSQd-@I8vSxiDAE?C$UHdf1l?h{yHOZA0YiCnvrc7{{(&mj#H!E}w*{ChVm@pq}8e4Bl{AI6thXQkcGfZ-WA4*y@k598-GGBMA|W)34BDmi1$ zOp@nxocnMN;~XN_nv+woeFMt*cEd9QA2JSQzEnzQzBg)?@b)-wGCYa%80L%z-NKc$ zy%i^0*e%W-lMtI*D#dA+OeKBjLB~$gpgkWe;Z@Q!+WG#JhvHc*KIdB zg!Md#KC*7~vxhJy@6&zxIOTf{&s+K44xZ%OZ}nv#xz>KGFZ&Ho{12gzyzT+;of z$@B6)MyyETZ~1w`@T~6RWz1R6QSzAa+kJe}aJ!FqUux;>- zV9|+c7-+ktnp05$my?khoK$OX`9UQFn0KqSsP3%Hc}|t{>1G)D^_NrwXP#=RrjjrU z+(z}ZQ!P3xa;D)%Ym0%uqJn5`siss!r_Om*NujIg<+NIzZJZCK;nY=fPC}BUs2M1p zR(3oktFngi!t!#cea(5k6X`&F&ksTgq$=mcVL?O++Y3BsDddu^#xC4o8fc51pSYB{oExD; z_{sePzoQ}BpxjQEijLdB&VX!FV(b>FiD$U0NuYy(aftTa2-4$D)1D*4?nHxoyi&|1|ER6TXRAyV$mEIUe=S zsfxcP6x)6WT$PHbiRZcHW1b&|TTXz5eGX%1e@aV1dCJ2+5M$bCHWNmhOz=?#yXj`+ zFE7(5v1!#5VCd&h$F$9>F9&X~&Yy8gXU;CEGVKK)3z!%E3L~KCTv~NWkp5|jKcAFZeVgV6G+i`@ J)c1d^{R^8o4}t&y diff --git a/Assets/Packages/Triangulation2D/Demo/Prefabs/DemoMesh.prefab b/Assets/Packages/Triangulation2D/Demo/Prefabs/DemoMesh.prefab index f1ee578633a592919304196efc5b2b5fbf9f745e..6608f3eb2a52ef5825f652e9d6703d7c3de6bc07 100644 GIT binary patch literal 3056 zcmd5;O>g5i5WV|XXb+oH66n*heDm5#R%o0ARuZ5nihv?VGFyoZD9O9t#s2pWNlA8` zk6sEiL15VAaAr8~&EtIjeYU)Eyi;%V`EGXUd}=>A4JoFr;LSE*r&LzQzUz6@(aFh) z-u0X#&-0>*JGvwl++=?NZKfl~sUGe3ubja}Ns4;vxMq1Sm4f<73dTi|%2v_-l=Cy^ zB_s>9{AEmU733sKL<35Ya=P31To?cGPuta?I4SuLU=N^bF2&RtcabU#1H$BU;$Z6C z&z++%9>?)mdwG372%>T1zhmGB@mUnUV-STt`Uu|+;d!AS`>t_OJzkM5sJ>L!SkbAo zfJ!c*UYk4Jks@srR&MIt3k0SBX4Vs`?|oRnYqHTNpE*q%(r|jtcq7#_V3K-98@|Da zUJq{Q9N7wu?i3MqE>-mgwq959{}|iqagSBI>siKGl3Ynj%9Yf&G9~zq)jM{!=JSX7 z{DwE$v%Qryf5UdqDn+kYil6AtGw$#c-F1%UYhE%1Sn@yqG&jE>%~}I@h`>t9=0>p{ zrY7C3hrkbEHAWApCQ=O^u6VI-Zk5d7z9z+B zyMnw#L$rTwPuB|@#x%i_)PGMMY&fL#nIA_c)g?iJK?$jKO;2_Z`c`9(oucJt!Pd!p7yr`-h zxPKUAJ1K-zaE%Ipg}RVxz9yGU=DnhGPl(2q}!4VV=p z%WQpfOf;~_aKWp#GOOE1+D`ZaYuMT&zmP2EAZ()GF+PxU2S1)*pkv?3fTJr7RzRN#Cz3<+u z(TW$GWs+?_So*KL_P*r`sRx}{C>&Y3Rze=MB~jhdscUI+U&Ey$8ysqSyQKb&3#jzt zI4tSO<4Kl=k^S@{>P8V1?SaK}S(aSS9nZRAQUhXOz1cyK^*&`pA#6f38NXE^g&Uadt`8i zL}>a+a%6|icR+cYd6HqK)D9q+tbV?Rc?ktaPoM{4V_&%4F(i{2B=q_U=e-TEc|Wf9 fd)1?zmb*j`JmNWgDE@U?N@{z2R@Z=8d82;-m5;al literal 7412 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 diff --git a/Assets/Packages/Triangulation2D/Demo/Scenes/Demo.unity b/Assets/Packages/Triangulation2D/Demo/Scenes/Demo.unity index ed271c1a372f1a234aa3fdb8b3d31b17a4a2ae22..01d80286fa1852d3de66ad7cb1a1f493b87ab09a 100644 GIT binary patch literal 6757 zcmdT}TW{+&5`OouP#>D7B(N^N<;}5kTO>_j`jWgfSKmI(tyY>82zxCs6c;)?2{os{sbynq~d<~P+SZ2pT+xO2} zCnqPw4F=wk-@1?Ev?_$mM^&1Nd^P1|i9f|z%k#4N{o>y|F0VzxFH;7h*9N)ZO0ZP? z%9F2L(b6+7Fw$y8eAA6PAdpl9_6I)h`c*2J#7_)o=3sdiTT zeq>ksfwRI7!#7r6DOu&o&f<221GNL%5te8dv_oujaP&=HI@^umRwd&gn+esTR4gvV z6Q8bGBA<88iky{EuWyg)lD+j&aLhu!+_6&U^KMR1rd_jCPD{n}Rk_x|GGR%X;x*Z5 zhufj}B}@2p!#RaOi_!)&{!&&7L2YK7&f|?NM^ZkDCJ#y8_Ti#RV3Ymq=6i%=uYBFm ztug5{=1W$k<%BO&+*w@9rmqf|6JE%)A~ED&(AWCbOV1IynB%@1^J>OHTt-z<%B&W6 z!_W#x>|1}6Cqh9@_$#j9yk_W3ikO%+jSr_Wqsm5m64BXxUzMAx++z;Y1yAI; zlm%|KTQTF=MkujsJ4=hRGCDXY`F=ylhQ!L{s3GmNu(l(_E zvctHzj+4IVbS!$7X^W0`DRP!xu@VuiRcH_|MM_18^m${+grR^}WLv{C^^My((fRpK zyzt~uNur#ix1z_@iadOsOj)*}?q8n|qVbt#ajQV+_IGO>qoaEcxd@zX^=L>N6K5z` z2ch^nshRG6>}XfBoB4o)wtm~qc5rO7-?3*aeZ{Jxpi)v5P8sL+=B5p?S}lW5w3%=1 zM+zQT4aW{kbi?97qMf7UPQ@x??r5L^o8isF-&jy9@jFi-Wt?HtwS2BG-u)9-DFd(| zwoQI$N!Vyu6db9xoBP=u#n&|1j1`X*9g8CULDxI#w0>ewcR*^*;_yC9d<#^fG*lu@ znj3tly0R7SIwg~aaN2#EWP%FytWP!Zno~b;anYn{Dyefu#`BsqN=2ptiK#s)PgZ=a z6t9h z;xnMrrg*vi9CW(I+&HcjpvyxFm`sJ=-I#Pz)>Dk~McRR=lrpa4-81R)ga;eL+2kuPK_oq!Igi#tA^ zc=7gQeSp)tLs01ZBGJbp;m0Du$08Qh-?CR%^(g=u((aCl+#BIv#k7Gl1~_lZKd~B| zo0#y~{#~?T+}RoPKq+F=qIY6`Qw%jkrn_$MY~Qcr?6-zhBIGSn8FQ8T|Aac5HOGAa2<-TZE!KA}cB1NWfY?)4*GFS7YYNqP#Qv5MiYzSQ6kPZAha0gN?x{q}5r$1f%30|@95vqQZBMM5gPmgx5t!Ji+b!b}&JsPEyh3||dTTZx^9^ZnVt|H)Wp{)j!2XUsh?FRS!J}Xh4Z6Kx zV74=_Gw3uAK-1f8XH2bl`R=G~*yz@<*SaU08{)+)?6=eUcw%hH=EIc6zUgr20Fow* zUvrj;xJFS<{8FOnp{>cu%#rq=)!ar?^gb>}G6w(yhS7rzc@#;cIa9vD0Aj{+O;C|)v12${R+Pvdq^MG6iL>h;hk%tWlsWoJ@lS- zN~XJmw-ExZTF7oSS_3v>Fh28s`ImO&rJb|(yXHj7@?Pn;N8@q5`9+m-HOyCdoV*r< zq8eA!=v_Y$;=Obb`9Tk_sJ*`xJld+=e;>ANWdpNgh9N{&qxJfXV2{cf=`hdr%$^aGwdN?iXuQuAJQJ;Dc9*!^{?P%q9`dgjaelQ4^ z{SFVqUJ%90<-%WfyS;E3cKZEJ5AWUPJy_2sc+KHJDviwoYUs6vVVo>F-8c$^B<@CG aJiyQwEq&fg*m5~o;LW_Tn;9yBCH@O4Z5_b? literal 11768 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 diff --git a/Assets/Teddy/Materials/DebugNormal.mat b/Assets/Teddy/Materials/DebugNormal.mat index 4cf5ba1a91b5ad9d5ad3c7da8c78d0841b07a60b..536240fdb71553430adb30f6ff5259334bd79f4b 100644 GIT binary patch literal 1977 zcmcgtO>fgc5WVMDY!Bs>RJIeN;9J|YrJ`;FE=7P)wDykOh4pTQprtH;h`Z7(*dKS$iI;~({rBRZmbRN&f#BSD@ciI)vrF#RL?@BZ5B5+*s=H9k+ zz3nUw#xqGvtX~>SWrfY%QJj&qedi11&|ly{*u`Z(4ri=t-+{!M-#TzeocIyrV6Da^ zx3tOW8oTk;Fm5~r>uOq3V*s;%{u1a5`T%UH)f%+rXh-8ew=)fnc6AGnXYyf-n~>Fs zYuBDCxP5GZSf{b1KR4r@-d$8wc;{nA;xXCa+ZWkAxc|B~U^{md++nSRAlCvc<>FYB zz|^puIW^w~Y_U6+L$!F;a^tVyP<%P%5|7a!^UU$c2*Ilhp^O=-!JDcQZpeu)sm3np z;~)*Tt8<|!3RJkYTM5`+>Ud{6byn3i%GHrqxxL%lAML**7RH_k6tqs_LPS^^mtedY zJ|)`ibPt&;hLYm-F9h}rD69tA*n1S2oo_cQpE62z)8B5xTV&|~ z?dntsrJtq{exh#Se+bH2gMnjGhBxgc4u=(BQHMiBkHeVfxcLA1c9(aLem^aKcWHkE D9dRUx literal 4952 zcmeI0OKcle6o!xO*hy1frIfamQuBU?mNq;?-bq_plaw@}LP%y3PwauQCz=_TL}D>3 zB)VY7iXu^g*dQU)6&qHtVTXh&7Ui*Qx80(u;s5U)-}pL~x?<-OozA`AJ@?FcjNLmH z8TdwI_c;-{TjU;GM23fs4h^p!kz1Rao0$y29_Z&+uN}O3ZQuI!_vdb0+JA9x2`r1n z0w!6tr^*Y@fGkpaLp=C>#Y0@ABQlfeXflU!Ov5e z52S0f=HDk-Nq$NFA{0k1=LEd`7y(bHCws-S(10SkFV~ zBkM*#`v?>AKGl~mQoi5typ`_*;5y%e)t3Y0N()wB9yDD0A4DH{--F=#zPA5|Xg^M0 zwtqgS-TW6*p2g~?7+-|a|HHVZ^-*>EKIM-Xp0o0L)bKtlugAzCtWSI09w$u5^Kt>B zR^6U3yrAm&Bj$|fNyGcC`|@+9^Bu76`!u=I0jr+R7@n7(FlIej<7c51*6j!M_g9Sh z>_0~c$w=aim|u*_^RP{ zA73-v?&Is=-TF8}uGH@18;0kF^<*DeH-2wX_hLdStiwrYrj6fB z`I{a5R?1IxaNdl5PN%%&#BS(0zRb_Z;mAzIi-T}xJ$4(B7c@qtUY_-Q_vADN^G;mD zK-n$SoQfNAS&z)%l)Ld!5LP09(_Xa}*PXRl->Gsw)r{hx{3j zS(gor=T=uEk(!1?mM9uyCBJ!%2&nWHQXpt`v&oEnLXA=LS@IF8n$Y_5QlD~8rNu^jPd7# z&R(0XSm)0;<;A51cZK$Xmj%pAL4^@eR4%Q$Xe2yt^XHRtt8Y_0fToM)lKM7ltX)fz VFiTZ2@#WIq_a9or7xVxC diff --git a/Assets/Teddy/Materials/Puppet.mat b/Assets/Teddy/Materials/Puppet.mat index f94125a79df8dcd95e55b56f567fce14ca7b4123..e1fffccc64b977bbbe1028f1b94c9f767ef461d5 100644 GIT binary patch literal 2305 zcmcgtO>^2X5WVv&)I)j##x^Dx-;zMmOhZCrnois4FpDf3wYKDuMPB8PAOPwp0!Rk_=m_V^V;@42Jn9S>{V#WcIHKa_n62r(9+$DL< z)0j{QS7Sdt4!m(N4o6WK(NP4WVV2Qh07Kd(W>X>MpwVyW-m=YisZwmfX)Q)+6tsiMRU-aA@}DmPCS8omd=%|m@*vaaq`7&8Mr{XT(F0!xZmdW$nvx< zD=X!~7VA<>t+1e{TVjJYoKPri@F6CCmuzsfMK%v^e3ofuny}}>Za)b@tqC*0i<4r- zQh8X-8R%~ZZ1GyE5{g5$I4!xhckfVoGvES`(LvU8hDW9-IK3#O)`x2FhSH)wOwkAJht09=PfcRfbJE=gTS_n3A?9l-@|JX>=(fatHSg~dMq47E zJ}7QbwMi(KXR?s$ajD#2G++D-qBmRaE?Kz|aBO_q8Zp;Z0hE5uIzbM!O?>wqiARZbl5J!t}`Hxyp`NPqc-wN5%`eFE7 KU?HXW2h?v&&v>2y literal 5104 zcmeI0OKclO7{|YLo=tg`QrfhX1}Km62!%c<5aKki)-)zgleU16%+{XR3+r98yDo{; z!wMl#QLh|;TuLQ`1OkLO6eQFO96)eFsE6`6wg(RB6;%!2e`Y=PB(8Gc>ao7;%x}K= z=6mcqvnJ~Pj%fWN5#3638()a_^zZK9IlGIlEiEls7K05e?_a#M_3EWfbC+M8ymF>@ zVPlqAiYGhyiuM#y%=$}m5EEJa`J|2FuPut(8N!Ydi`H=ecjh9v7w(}5=yOTL+FU4Y@-;%iIUQ1CSf|73L?o4}WlvH1p?9 z&CR@R1m}i)ZsR&4Z?LloFa~dzb@?day_$Cz@or|W;_Wo*vISg9r%{)?G*|X}xQ^I& zD|5B4Y5#8M55bmcANOf9`+W&d@$4z?FR;M=J$y~_BlGq}!td3*&4}wh&D)K*wu5s+ zej4+3KVS^rLGN*|p0@`y@09sG$7A^Opypl1zIe`5yxqpWJHVxM8~J=#^A7r+`^YD9 z{0Ivg^7a+i_b2Y--hUL3n?+sHe*JlWOftnA@BeW6?H|w}pbF+^8 zeJR`WI_}f@W*wi_+^pj>nwxcemU*)}4uDHB>-e1J9fW+Mj>sFnx6tr?h3B0`#+wF= zSH?S}xf$<%aBj=v9R`fS&3H#NH{%`E+>CdOd9!%O!KIk-;(Ju_4m!#nAYOcT9%Lcv zCPcB|E3=lLk1I0sT@`8>bPr{FdnIekzYA1 zJYG3f6E#6$6gXaK#x7;;Djo5hXg(MCRS`t<(`6wd7`0D`VgeljD>Gtl%sUa1XIF$; zqllV{YJtGAg6#^Lqj~O6&d!F?*0}52k#xj&{UD@(N_3oTB!sAMZ67YOEw-tn#s4Z_wAFP9$R|l;~!ax+xDro$(P81=B=D4id!RjN2r7%k?LB1APD zvGSuLvK@E7dt4O#RrK*1o#{c=OwFZe;lc2}{D*OB~K#R+lbT18jJm$e;_ zPd)YB)z$Q29c*SfKG$^$2V6f4R~Tjua}8eo^OJ>wTWjjb3VrE!&JK7Fdv1k!(>Cgq zKWtY}6db4GZ}Gy0X6oT*2Gmj3P#xo>4t^%#6J+Gi&T@~^c+F4hp>wR&+2$HKA4bD2 zpEt3Bo2=nju_PvhSBlC^;K7~hadFvo6}Ho@5kryb4tEZ2YyyU_&E5_)V}nuzf7=xd>(bs i_oUvBp>Ac_`Y|8`TqdxWmW?K diff --git a/Assets/Teddy/Materials/Teddy.mat b/Assets/Teddy/Materials/Teddy.mat index ba0b73cd0e77c56b0833491abced09bce94afeff..a87f1b2d05e45aca02e3e0dde4e7eb9289217894 100644 GIT binary patch literal 1928 zcmcgtO>^2X5WVv<X%g42Fb&Z)qTDrg1`Rnois4Fl%dV)XEYg$!Tb(|Gg_22u*vo z4;t8gyKg_N=i^To$t{acqR#Q+;+h@RN6bMP*Gjm}ke}qb>JIu*6nA>Pp7#zS_G%FI z{nJUnp%EbC4r4a_5E$_2$n7cQEAnvq@f@ zMx!wn=fkt?bTr{(PO;-?lHvIXCg)w|Hfzc_Z0MVGZ*lWO8&35Hj$2W#Tm|cGPiMh6 zQ;<>R$~sUvweouMQPC=*yy zH@+G!tf$~jO>?joDf^eNfj)&t` zV*|w1hD!Q-C*JAZX%5mmpJEnu*@jMEWb@GGi^8I7-2LDV3uTPBrszP(3z;F;?Q$ky zzqi=poi-K7wpyH3!ureC7GDBF(QDMoJQI3lq!jtJ)Yi7u;C-IUy3L8s!BCg*)JlWZ z@=9tTfeN>FD*@X}9qnwFwbMmGa&_WW?%?+BU+tF>Q|n$!60}C*Ld1-hc#EoZD-wxa zny^Ws(0YY@&c0jpL3pA$>5Lb}kZr$})R~t_cLVe(`-5G?e5F-+K%JU=TjIW&4-YBk z2PB_A8sUhw0aVLNEwyOjSkX8cQ^6?PFhHCItfl^1OEg3 CmKm@B literal 4928 zcmeI0OKjX!6o$`Cl1ZBKDy1}~l!o^^P)c})B+aWW$&i$!1+f|2nVT7dXB^p{l93R2 zg#;2y*w9S{>IMlRRgDI!N+0DY2TCKBk=PW z<^$;(t@-y!UgBR;KYbbdtRKdgSm!0{r{D0LoPhst;fL|_8o8L~=2i?Mzw7nH4 zTewr4d&srgao%Zo(yzBMXI^`u6xNRQtYJ)k7a@fF8u*78GalX}JH>Oi;db5jlS5d~ z!{{UHMn6M@F?p}<%U3BsV0fRE?>*p2z6Gl<2g$V-tiIf9c;bH$edKiyfhX6s{ohCX zN&2$=^FH0l|8UClSp5{^^HBP~AIG#lx^Ca4`~kyzth^pHyw}R>A#w=oldapsgfV%a ze1=iGZjTsV(DnQgbH?+i;r-Ti`J5&B4p`THoLuXGRnI33?~|V~W<6QsC!rM9?R)h1 z62`pupCW|hq+k1QKkrX#mhkNTKVo=6{)F$}Fy}M+3{+%T`?-L8FJsmVeU>=GuV6;b zXE5Q3pT9AqpXZ1(_H92$J9yjA^M>bjA2%>(Jx9r7#&7rW1;gz=;`dTZXCGfO_I4j% zHr(#xD~8*Bd=-4BK8}%Vwfp#*;eEn-vX87Af43<7z2fr@)%i{k#@q9qG~CYj7&)Xf z-zmbF+|GB}a68`_!|i-$!FS4cj$EsqFMmf9-X~`e0rTZ==Lx9DFxCpX4*z1tI-G>& zGW>eVU+>^IQa<0oc`^D~NO{qTRNy+EEG`_BQuy+tq=U55&|r^)ml_{*5*8?%K3CNjQskWs(~|4HC0nd7zJ*l zy5dxe&YGNVxKV2<@YhrjwU%p2MRe+%Q@~U9+GdPZI~MJGw(f>In%lN~?N8$_I^p}6WyQA5 za8)XzCZ6Y(k9&R?ZaV=M_Bs4~!2Xn$gYuMzJs`%k(QGD+wwU0B40hAa$X{KhQDW1s zDZt<#Uyo^BuIaLDa}@@YN36h)X!4QZ&Ya%Pw>+d X>r-m?cA6Vhu4N@X&#blUn;icGxQ`fF diff --git a/Assets/Teddy/Materials/TeddyDebug.mat b/Assets/Teddy/Materials/TeddyDebug.mat index 4ce68625f0523e6fafbb3681213574416a49e9b7..634f600199a9693367338cbcb03079ee49ede709 100644 GIT binary patch literal 1933 zcmcgtO>^2X5WVv<X%g3^tG^z7Zg4rg1`Rnois4FtW8aYGsMhM+)uqzjq}Ap=rYOgdH{`^f5KF7XNp80Tc2=mm8~39q>GXO%?~Nn!DvtX8 z>7>+x=2RpdLQMF@e*$|1ZMc#NIY)E7e8|5+Vc&2D*Me3iA^l*UD6PS)m1JC2nR2>- z2APmwB^PizMda@Qoogs*ek+koBH2Iwds;(67Qonc3c0I7P`08B^bvS?5sL1T%5jzu zHnX4pjFxZ~Bz)^xpV zY!r+$Npmb;8cSt?y**MKk+g@#r^=x}!+Efq+ru=Rv8sL#5^H|vz#(z$CyaBo8j~z& zmC`kKM|<1ESyh%OS7%=3j&ASa)qWWdy}2BrBrk`*5{r1%{SkCkKNPk ziVS`!vb`iCcZ=MEi^%B6p^?$$gK~3yeZ5cs*a7+c%GJF$uI^gB_TKFEi@PuEEQ1v> z*^evR%OWZC*YzM3Dd6v`9!bA1NZJcXJ4On!1^vt5ci>vooZ3bC6E^l?O#Pl5AAy}G zFdoe2sLj7mijw}6+3Cya=k3rxqg|A|odL@Wasu|hh8_CPJqjt;6blF84~3jQ7sknZ zw4ZyhhJFr_Yw3|Q(0w1m@m9+V0vmD^!gwico$=nOnc;aq@3P$Zc^qTh(6pjB7iDjk#k!>*$l;M~Fs#9sDEo=@0Lb&HTCFayM@~$<;MOH>d1Zff}4F^`wvln zoVHy1yiYf?Kb-L*W*ybv}Q~Q7&%&J zyc2{exf}1K7<2tP5C3AsJe-6S za{NZd-{{~sGk&Urb2HkR$#~gIROEYs%*`dy;i;;hgwfP$qMETEHjhf9GVKTIWC@)) zFR7!W_2%ndRYjaOJ=-~@);iGgkGW@34<_-C6byfipPYA3~wFgMYmFqIcn^{4W@zCICAp4e=Z+5 zUHSOx{>8t?!*`+7ZQTrXGtkXIHv`=abTjb3Wnc)F7gV*nR#Jvm;!X(?#&ytP3Yv#u}N_Ef`SqHy7ivU{O`W z4X(KQ+hD3vMoxmjUpgLyalByxG~6}(guwb#=A)&F0OvsTsiRpbPHr*5OBwVgTS>UQ zOeLe!&MCmqZ({#i{Dgntk?10sj$Z8NT~Jrso_@6=aWb^Ye}8z z=@>sBbk^D~#XLXbRL-88S4-3vyewc`4y*KlO~=yCi$VGmOl7KCQ#0+2GCOniu!;Mb b`||S>^HXWpc9Mrw&gEOS&d#;-Yp(wR0#_Lz diff --git a/Assets/Teddy/Prefabs/Puppet.prefab b/Assets/Teddy/Prefabs/Puppet.prefab index 22f9fa9f8d44d6918e2e09112a0cc7b1231ad150..1331219274d5dad3333c6f22d11b906860fc7a9b 100644 GIT binary patch literal 3727 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 Wwy!?=&G}L`@)#M$dK>#=`~Luz_vEtx diff --git a/Assets/Teddy/Scenes/Demo.unity b/Assets/Teddy/Scenes/Demo.unity index 05a4d361cb681e926d69f1e20026d55c3096b47b..d888896e8f2658614ddac90f60a2809a3a95e0e5 100644 GIT binary patch literal 9580 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 a`{$PfG`OLs9xMm+RLSnx!zaD)Yv(teYl&t6 literal 16560 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 O^sjyoQt;|;d;bB_Xf5>s literal 37108 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

KPwnBu zp52VAcG@)6=Y5g<2~cmIQm|DidM`M~SQj(Km-F@CE{U^>LJE^NAi$vx8}I2PDX zT%0F6eY<19^ct6~yI6e<-F_cLa^8~5)t*U!3~-LoZ`WD5Y&`R7vZ2<4k3P~m&pi9a zp8FsY^QYVg7v%9%CE@Wa+K%U&8S=l1{B?yVf8tbQU(#85 zHB_0;e#Sl$e*I>2&f05xscq~qjp=mM^XN?fqfSU?x+3*Qy2(xlJWGRt>7WckO$(N0 zviY=I$=bt(U64tJxnzBZMMr??!T%N0SId~8EnA#?W$|_V-*El)kQo=XK!a-1I&5h~ z-2K#d=%R|c8{rv}Fx`00oO?Wa)hUx{d0EmS=RIiREN*x{cfPf&xz_)B?zRDkW=)EWn78`XX+*|*j{|F7j7dBXL&{ujwI zmQCebERSo~DMqb5Vr2Lo`%~#+{mI$x#$Rj<@hOf?9stBvqKv<{t1FSFtugREcI*@1 z`F-T$$$QpgN6zxIe&#b~=f=-Ah`!Lv#W3egk7XOAC!_@(kH1?UUM%<9`{TE-tz&R) zgU;4Gc#q|TK+l6fFUsW7Ir)`^cc`u1`U&f;b@$uU?$eDy@N0Npb!|;$D*4xvxwPSM z-J#9KXKb93_o*kvQ8-u5*Hho0H}RzYZ&d2G&VBX3)$`ZSy`k~l#kb~7{QJ)PW16Jh z+JrJcSc`J17U*G=2R80)y~oDAtqob&){*!)<*aNPb`IjF5&PbexnOHpR%Tvpy@q+x zQ4fs2JFDZuJ~_*AslN-a^A!83IBUVDq%W)H6Y<)vRyk}vsn!!LC*{kIoY76DWB>Wi z#!5Brr`d6S?9;985z{xGb75O&vwpQTISbqR9qYt4b^FrqNFTEZwsz?Ev#rH3p3dTQ z?kP6X-&*u+4KMi&*Ry24wBT?pygJp19zY!Z_S>CLROjc&xC`>I!Y3m}3>m#-f*qHG S=`AbMnSB~IuYGK!`~L*M9KP}Z diff --git a/Assets/Teddy/Scripts/Teddy/Teddy.cs b/Assets/Teddy/Scripts/Teddy/Teddy.cs index c76bd62..87325f7 100644 --- a/Assets/Teddy/Scripts/Teddy/Teddy.cs +++ b/Assets/Teddy/Scripts/Teddy/Teddy.cs @@ -11,579 +11,645 @@ namespace mattatz.TeddySystem { - public enum MeshSmoothingMethod { - None, - Laplacian, - HC - } - - public class Teddy { - - public List contourSegments; - - public Triangulation2D triangulation; - public List faces; - public Chord2D chord; - public List networks; - Dictionary heightTable = new Dictionary(); - - public Dictionary network; - - public Teddy (List points) { - var polygon = Polygon2D.Contour(points.ToArray()); - triangulation = new Triangulation2D(polygon, 0f); - Init(triangulation); - } - - void Init (Triangulation2D triangulation) { - contourSegments = BuildContourSegments(triangulation); - - var triangles = triangulation.Triangles.ToList(); - faces = Categorize(triangles); - - var terminal = faces.Find(f => f.Type == Face2DType.Terminal); - chord = GetChordalAxis(terminal, faces); - - var terminalChords = Traverse(chord, null, (Chord2D c) => { - return c.Face.Type == Face2DType.Terminal; - }); - - var convergence = new List(); - terminalChords.ForEach(c => { - Prune(c, convergence); - }); - - Subdivide(chord); - - // var spine = GetSpinePoints(chord); - var networkTable = BuildTable(triangulation); - networks = BuildNetworks(triangulation, networkTable); - Elevate(networks); - - heightTable = new Dictionary(); - foreach(Vertex2D v in networkTable.Keys) { - heightTable.Add(v, networkTable[v].Height); - } - - Sew(triangulation, chord, heightTable, 3); - } - - public Mesh Build (MeshSmoothingMethod method, int times = 5, float alpha = 0.2f, float beta = 0.5f) { - var mesh = triangulation.Build( - (Vertex2D v) => { - float z = 0f; - if(heightTable.ContainsKey(v)) { - z = heightTable[v]; - } - return new Vector3(v.Coordinate.x, v.Coordinate.y, -z); - } - ); - - mesh = Symmetrize(mesh); - - switch(method) { - case MeshSmoothingMethod.Laplacian: - mesh = MeshSmoothing.LaplacianFilter(mesh, times); - break; - case MeshSmoothingMethod.HC: - mesh = MeshSmoothing.HCFilter(mesh, times, alpha, beta); - break; - } - - network = VertexConnection.BuildNetwork(mesh.triangles); - return mesh; - } - - List Categorize (List triangles) { - return triangles.Select(t => { - return new Face2D(GetFaceType(t), t); - }).ToList(); - } - - Face2DType GetFaceType (Triangle2D t) { - int count = 0; - count += ExternalSegment(t.s0) ? 1 : 0; - count += ExternalSegment(t.s1) ? 1 : 0; - count += ExternalSegment(t.s2) ? 1 : 0; - - Face2DType type; - if(count == 0) { - type = Face2DType.Junction; - } else if(count == 1) { - type = Face2DType.Sleeve; - } else { - type = Face2DType.Terminal; - } - return type; - } - - bool ExternalSegment (Segment2D s) { - return ContainsSegment(contourSegments, s); - } - - bool ContainsSegment (List segments, Segment2D s) { - for(int i = 0, n = segments.Count; i < n; i++) { - var s2 = segments[i]; - // if(s2.HasPoint(s.a.Coordinate) && s2.HasPoint(s.b.Coordinate)) return true; - if(s2.On(s.a.Coordinate) && s2.On(s.b.Coordinate)) return true; - // if(Distance(s2, s.a) <= epsilon && Distance(s2, s.b) <= epsilon) return true; - // if(s2.Distance(s.a) <= epsilon && s2.Distance(s.b) <= epsilon) return true; - } - return false; - } - - bool ExternalPoint (Vertex2D p) { - // var segments = contour.Segments; - return ContainsPoint(contourSegments, p); - } - - const float epsilon = 0.0001f; - bool ContainsPoint(List segments, Vertex2D p) { - for(int i = 0, n = segments.Count; i < n; i++) { - var s = segments[i]; - if(s.HasPoint(p) || s.HasPoint(p) || s.On(p)) { - return true; - } - } - return false; - } - - // https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line - float Distance (Segment2D line, Vertex2D v) { - Vector2 a = line.a.Coordinate, b = line.b.Coordinate, p = v.Coordinate; - float dx = (b.x - a.x), dy = (b.y - a.y); - return Mathf.Abs((dy * p.x) - (dx * p.y) + (b.x * a.y) - (b.y * a.x)) / Mathf.Sqrt(dy * dy + dx * dx); - } - - /* + public enum MeshSmoothingMethod { + None, + Laplacian, + HC + } + + public class Teddy { + + public List contourSegments; + + public Triangulation2D triangulation; + public List faces; + public Chord2D chord; + public List networks; + Dictionary heightTable = new Dictionary(); + + public Dictionary network; + + public Teddy(List points) { + var polygon = Polygon2D.Contour(points.ToArray()); + triangulation = new Triangulation2D(polygon, 0f); + Init(triangulation); + } + + void Init(Triangulation2D triangulation) { + contourSegments = BuildContourSegments(triangulation); + + var triangles = triangulation.Triangles.ToList(); + faces = Categorize(triangles); + + var terminal = faces.Find(f => f.Type == Face2DType.Terminal); + chord = GetChordalAxis(terminal, faces); + + var terminalChords = Traverse(chord, null, (Chord2D c) => { + return c.Face.Type == Face2DType.Terminal; + }); + + var convergence = new List(); + terminalChords.ForEach(c => { + Prune(c, convergence); + }); + + Subdivide(chord); + + // var spine = GetSpinePoints(chord); + var networkTable = BuildTable(triangulation); + networks = BuildNetworks(triangulation, networkTable); + Elevate(networks); + + heightTable = new Dictionary(); + foreach (Vertex2D v in networkTable.Keys) { + heightTable.Add(v, networkTable[v].Height); + } + + Sew(triangulation, chord, heightTable, 3); + } + + public Mesh Build(MeshSmoothingMethod method, int times = 5, float alpha = 0.2f, float beta = 0.5f) { + var mesh = triangulation.Build( + (Vertex2D v) => { + float z = 0f; + if (heightTable.ContainsKey(v)) { + z = heightTable[v]; + } + return new Vector3(v.Coordinate.x, v.Coordinate.y, -z); + } + ); + + mesh = Symmetrize(mesh); + + switch (method) { + case MeshSmoothingMethod.Laplacian: + mesh = MeshSmoothing.LaplacianFilter(mesh, times); + break; + case MeshSmoothingMethod.HC: + mesh = MeshSmoothing.HCFilter(mesh, times, alpha, beta); + break; + } + + network = VertexConnection.BuildNetwork(mesh.triangles); + return mesh; + } + + protected List Categorize(List triangles) { + return triangles.Select(t => { + return new Face2D(GetFaceType(t), t); + }).ToList(); + } + + protected Face2DType GetFaceType(Triangle2D t) { + int count = 0; + count += ExternalSegment(t.s0) ? 1 : 0; + count += ExternalSegment(t.s1) ? 1 : 0; + count += ExternalSegment(t.s2) ? 1 : 0; + + Face2DType type; + if (count == 0) { + type = Face2DType.Junction; + } else if (count == 1) { + type = Face2DType.Sleeve; + } else { + type = Face2DType.Terminal; + } + return type; + } + + protected bool ExternalSegment(Segment2D s) { + return ContainsSegment(contourSegments, s); + } + + protected bool ContainsSegment(List segments, Segment2D s) { + for (int i = 0, n = segments.Count; i < n; i++) { + var s2 = segments[i]; + // if(s2.HasPoint(s.a.Coordinate) && s2.HasPoint(s.b.Coordinate)) return true; + if (s2.On(s.a.Coordinate) && s2.On(s.b.Coordinate)) return true; + // if(Distance(s2, s.a) <= epsilon && Distance(s2, s.b) <= epsilon) return true; + // if(s2.Distance(s.a) <= epsilon && s2.Distance(s.b) <= epsilon) return true; + } + return false; + } + + protected bool ExternalPoint(Vertex2D p) { + // var segments = contour.Segments; + return ContainsPoint(contourSegments, p); + } + + const float epsilon = 0.0001f; + protected bool ContainsPoint(List segments, Vertex2D p) { + for (int i = 0, n = segments.Count; i < n; i++) { + var s = segments[i]; + if (s.HasPoint(p) || s.HasPoint(p) || s.On(p)) { + return true; + } + } + return false; + } + + // https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line + protected float Distance(Segment2D line, Vertex2D v) { + Vector2 a = line.a.Coordinate, b = line.b.Coordinate, p = v.Coordinate; + float dx = (b.x - a.x), dy = (b.y - a.y); + return Mathf.Abs((dy * p.x) - (dx * p.y) + (b.x * a.y) - (b.y * a.x)) / Mathf.Sqrt(dy * dy + dx * dx); + } + + /* * The chordal axis is obtained by connecting the midpoints of the internal edges. */ - Chord2D GetChordalAxis (Face2D external, List faces) { - var t = external.Triangle; - - Vertex2D src, dst; - Segment2D dstEdge; - - bool e0 = ExternalSegment(t.s0); - bool e1 = ExternalSegment(t.s1); - bool e2 = ExternalSegment(t.s2); - if(e0 && e1) { - src = t.s0.HasPoint(t.s1.a) ? t.s1.a : t.s1.b; - dst = triangulation.CheckAndAddVertex(t.s2.Midpoint()); - dstEdge = t.s2; - } else if(e1 && e2) { - src = t.s1.HasPoint(t.s2.a) ? t.s2.a : t.s2.b; - dst = triangulation.CheckAndAddVertex(t.s0.Midpoint()); - dstEdge = t.s0; - } else { - src = t.s2.HasPoint(t.s0.a) ? t.s0.a : t.s0.b; - dst = triangulation.CheckAndAddVertex(t.s1.Midpoint()); - dstEdge = t.s1; - } - - var chord = new Chord2D(src, dst, external); - chord.SetDstEdge(dstEdge); - - var connection = new Connection2D(faces); - ChordalAxisRoutine(chord, connection); - - return chord; - } - - void ChordalAxisRoutine (Chord2D chord, Connection2D connection) { - var origin = chord.Face; - var neighbors = connection.GetNeighbors(origin); - connection.Remove(origin); // prevent overlaping to traverse - - neighbors.ForEach(neighbor => { - var face = neighbor.face; - var segment = neighbor.joint; - - Vertex2D destination; - Segment2D destinationEdge = null; - - switch(face.Type) { - case Face2DType.Junction: - destination = triangulation.CheckAndAddVertex(face.Centroid()); - break; - - case Face2DType.Sleeve: - var others = face.Triangle.ExcludeSegment(segment); - if(!ExternalSegment(others[0])) { - destination = triangulation.CheckAndAddVertex(others[0].Midpoint()); - destinationEdge = others[0]; - } else { - destination = triangulation.CheckAndAddVertex(others[1].Midpoint()); - destinationEdge = others[1]; - } - break; - - // case Face2DType.Terminal: - default: - destination = face.GetUncommonPoint(origin); - break; - } - - Chord2D nextChord; - if(origin.Type == Face2DType.Junction) { - var interval = new Chord2D(chord.Dst, triangulation.CheckAndAddVertex(segment.Midpoint()), origin); - interval.SetSrcEdge(chord.DstEdge); // maybe null - interval.SetDstEdge(segment); - - nextChord = new Chord2D(interval.Dst, destination, face); - nextChord.SetSrcEdge(segment); - nextChord.SetDstEdge(destinationEdge); // null or exist - - chord.Connect(interval); - interval.Connect(nextChord); - } else { - nextChord = new Chord2D(chord.Dst, destination, face); - nextChord.SetSrcEdge(chord.DstEdge); - nextChord.SetDstEdge(destinationEdge); // null or exist - - chord.Connect(nextChord); - } - - ChordalAxisRoutine(nextChord, connection); - }); - - } - - /* + protected Chord2D GetChordalAxis(Face2D external, List faces) { + var t = external.Triangle; + + Vertex2D src, dst; + Segment2D dstEdge; + + bool e0 = ExternalSegment(t.s0); + bool e1 = ExternalSegment(t.s1); + bool e2 = ExternalSegment(t.s2); + if (e0 && e1) { + src = t.s0.HasPoint(t.s1.a) ? t.s1.a : t.s1.b; + dst = triangulation.CheckAndAddVertex(t.s2.Midpoint()); + dstEdge = t.s2; + } else if (e1 && e2) { + src = t.s1.HasPoint(t.s2.a) ? t.s2.a : t.s2.b; + dst = triangulation.CheckAndAddVertex(t.s0.Midpoint()); + dstEdge = t.s0; + } else { + src = t.s2.HasPoint(t.s0.a) ? t.s0.a : t.s0.b; + dst = triangulation.CheckAndAddVertex(t.s1.Midpoint()); + dstEdge = t.s1; + } + + var chord = new Chord2D(src, dst, external); + chord.SetDstEdge(dstEdge); + + var connection = new Connection2D(faces); + ChordalAxisRoutine(chord, connection); + + return chord; + } + + protected void ChordalAxisRoutine(Chord2D chord, Connection2D connection) { + var origin = chord.Face; + var neighbors = connection.GetNeighbors(origin); + connection.Remove(origin); // prevent overlaping to traverse + + neighbors.ForEach(neighbor => { + var face = neighbor.face; + var segment = neighbor.joint; + + Vertex2D destination; + Segment2D destinationEdge = null; + + switch (face.Type) { + case Face2DType.Junction: + destination = triangulation.CheckAndAddVertex(face.Centroid()); + break; + + case Face2DType.Sleeve: + var others = face.Triangle.ExcludeSegment(segment); + if (!ExternalSegment(others[0])) { + destination = triangulation.CheckAndAddVertex(others[0].Midpoint()); + destinationEdge = others[0]; + } else { + destination = triangulation.CheckAndAddVertex(others[1].Midpoint()); + destinationEdge = others[1]; + } + break; + + // case Face2DType.Terminal: + default: + destination = face.GetUncommonPoint(origin); + break; + } + + Chord2D nextChord; + if (origin.Type == Face2DType.Junction) { + var interval = new Chord2D(chord.Dst, triangulation.CheckAndAddVertex(segment.Midpoint()), origin); + interval.SetSrcEdge(chord.DstEdge); // maybe null + interval.SetDstEdge(segment); + + nextChord = new Chord2D(interval.Dst, destination, face); + nextChord.SetSrcEdge(segment); + nextChord.SetDstEdge(destinationEdge); // null or exist + + chord.Connect(interval); + interval.Connect(nextChord); + } else { + nextChord = new Chord2D(chord.Dst, destination, face); + nextChord.SetSrcEdge(chord.DstEdge); + nextChord.SetDstEdge(destinationEdge); // null or exist + + chord.Connect(nextChord); + } + + ChordalAxisRoutine(nextChord, connection); + }); + + } + + /* * BUG * 既にPrune済みのJunctionを再度Pruneしてしまうバグ */ - void Prune (Chord2D chord, List convergence, Chord2D from = null, List past = null) { - - if(chord.Face.Type == Face2DType.Junction) { - past.Add(chord); - - var centroid = chord.Face.Centroid(); - - var points = new List(); - var ignores = new List(); - - for(int i = 0, n = past.Count - 1; i < n; i++) { - var c0 = past[i]; - var c1 = past[i + 1]; - points.Add(c0.Face.GetUncommonPoint(c1.Face)); - } - - var t = chord.Face.Triangle; - Vertex2D dividePoint = null; - - if(!chord.Face.Pruned) { - points.Add(t.a); points.Add(t.b); points.Add(t.c); - - var coord = chord.Src.Coordinate; - if(coord == (t.a.Coordinate + t.b.Coordinate) * 0.5f) { - dividePoint = t.c; - } else if(coord == (t.b.Coordinate + t.c.Coordinate) * 0.5f) { - dividePoint = t.a; - } else { - dividePoint = t.b; - } - - } else { - points.Add(t.a); points.Add(t.b); points.Add(t.c); - - var divides = chord.Face.Divides; - Triangle2D t0 = divides[0], t1 = divides[1]; - Vertex2D[] ps0 = t0.ExcludePoint(centroid), ps1 = t1.ExcludePoint(centroid); - if(chord.Dst.Coordinate == (ps0[0].Coordinate + ps0[1].Coordinate) * 0.5f) { - triangulation.RemoveTriangle(t0); - if(t.a != ps0[0] && t.a != ps0[1]) { - ignores.Add(t.a); - } else if(t.b != ps0[0] && t.b != ps0[1]) { - ignores.Add(t.b); - } else { - ignores.Add(t.c); - } - } else if(chord.Dst.Coordinate == (ps1[0].Coordinate + ps1[1].Coordinate) * 0.5f) { - triangulation.RemoveTriangle(t1); - if(t.a != ps1[0] && t.a != ps1[1]) { - ignores.Add(t.a); - } else if(t.b != ps1[0] && t.b != ps1[1]) { - ignores.Add(t.b); - } else { - ignores.Add(t.c); - } - } else { - // Debug.LogWarning("error!"); - return; - } - } - - var vertices = points.OrderBy(p => Angle(centroid, p.Coordinate)).ToList(); - var cv = triangulation.CheckAndAddVertex(centroid); - - var newTriangles = new List(); - for(int i = 0, n = vertices.Count; i < n; i++) { - Vertex2D a = cv, b = vertices[i], c = vertices[(i + 1) % n]; - if(ignores.Contains(b) || ignores.Contains(c)) continue; - var nt = triangulation.AddTriangle(a, b, c); - newTriangles.Add(nt); - } - - if(!chord.Face.Pruned && dividePoint != null) { - var divides = newTriangles.FindAll(nt => nt.HasPoint(dividePoint)); - chord.Face.SetDivides(divides.ToList()); - } - - // finish current loop - convergence.Add(cv); - Prune(past); - - return; - } - - Segment2D diameter; - if(chord.Face.Type == Face2DType.Terminal) { - var t = chord.Face.Triangle; - if(!ExternalSegment(t.s0)) { - diameter = t.s0; - } else if(!ExternalSegment(t.s1)) { - diameter = t.s1; - } else { - diameter = t.s2; - } - } else { - var segments = chord.Face.GetUncommonSegments(from.Face); - if(!ExternalSegment(segments[0])) { - diameter = segments[0]; - } else { - diameter = segments[1]; - } - } - - if(past == null) past = new List(); - past.Add(chord); - - Vector2 center = diameter.Midpoint(); - float radius = Vector2.Distance(center, diameter.a.Coordinate); - - var found = past.Find(ch => { - var t = ch.Face.Triangle; - Vector2 a = t.a.Coordinate, b = t.b.Coordinate, c = t.c.Coordinate; - return - (!diameter.HasPoint(a) && Vector2.Distance(a, center) - radius > float.Epsilon) || - (!diameter.HasPoint(b) && Vector2.Distance(b, center) - radius > float.Epsilon) || - (!diameter.HasPoint(c) && Vector2.Distance(c, center) - radius > float.Epsilon); - }); - - if(found != null) { - var points = new List(); - - for(int i = 0, n = past.Count - 1; i < n; i++) { - var c0 = past[i]; - var c1 = past[i + 1]; - points.Add(c0.Face.GetUncommonPoint(c1.Face)); - } - points.Add(chord.Face.GetUncommonPoint(diameter)); - - var basis = diameter.a.Coordinate; - var vertices = points.OrderBy(p => Angle(center, basis, p.Coordinate)).ToList(); - vertices.Insert(0, diameter.a); - vertices.Add(diameter.b); - - var cv = triangulation.CheckAndAddVertex(center); - for(int i = 0, n = vertices.Count - 1; i < n; i++) { - Vertex2D a = cv, b = vertices[i], c = vertices[i + 1]; - triangulation.AddTriangle(a, b, c); - } - - convergence.Add(cv); - Prune(past); - return; - } - - chord.Connection.ForEach(to => { - if(to != from) { - Prune(to, convergence, chord, past.ToList()); - } - }); - - } - - void Prune (List chords) { - chords.ForEach(ch => { - ch.Prune(); - triangulation.RemoveTriangle(ch.Face.Triangle); - }); - } - - // triangles are divided at the spine - void Subdivide (Chord2D root) { - - var rTriangles = new List(); - var rSegments = new List(); - - Action SubdivideRoutine; - SubdivideRoutine = (Chord2D chord, Chord2D from) => { - switch(chord.Face.Type) { - case Face2DType.Sleeve: - - if(!chord.Pruned) { - Vertex2D top, lb, rb; - Segment2D s0 = chord.SrcEdge, s1 = chord.DstEdge; - if(s0.a == s1.a || s0.a == s1.b) { - top = s0.a; - lb = s0.b; - } else { - top = s0.b; - lb = s0.a; - } - rb = (s1.a == top) ? s1.b : s1.a; - - Vertex2D tl = chord.Src, tr = chord.Dst, bottom = triangulation.CheckAndAddVertex((lb.Coordinate + rb.Coordinate) * 0.5f); - - // triangulation.RemoveTriangle(chord.Face.Triangle); - rTriangles.Add(chord.Face.Triangle); - triangulation.AddTriangle(top, tl, tr); - triangulation.AddTriangle(tl, lb, bottom); - triangulation.AddTriangle(tr, bottom, rb); - triangulation.AddTriangle(tl, bottom, tr); - } - - break; - - case Face2DType.Junction: - - if(!chord.Pruned) { - Vertex2D top, lb, rb, bottom; - if(chord.SrcEdge != null) { - top = chord.Dst; - lb = chord.SrcEdge.a; - rb = chord.SrcEdge.b; - bottom = chord.Src; - // triangulation.RemoveTriangle(chord.SrcEdge); - rSegments.Add(chord.SrcEdge); - } else { - top = chord.Src; - lb = chord.DstEdge.a; - rb = chord.DstEdge.b; - bottom = chord.Dst; - // triangulation.RemoveTriangle(chord.DstEdge); - rSegments.Add(chord.DstEdge); - } - // triangulation.RemoveTriangle(chord.Face.Triangle); - triangulation.AddTriangle(top, lb, bottom); - triangulation.AddTriangle(top, rb, bottom); - } - - break; - } - - chord.Connection.ForEach(to => { - if(to != from) { - SubdivideRoutine(to, chord); - } - }); - - }; - - SubdivideRoutine(root, null); - rTriangles.ForEach(t => triangulation.RemoveTriangle(t)); - rSegments.ForEach(s => triangulation.RemoveTriangle(s)); - } - - List GetSpinePoints (Chord2D chord) { - var points = new List(); - Action Recursion; - Recursion = (Chord2D current, Chord2D from) => { - if(!current.Pruned) { - points.Add(current.Src); - } - current.Connection.ForEach(to => { - if(to != from) { - Recursion(to, current); - } - }); - }; - Recursion(chord, null); - return points; - } - - Dictionary BuildTable (Triangulation2D tri) { - var table = new Dictionary(); - var triangles = tri.Triangles; - for(int i = 0, n = triangles.Length; i < n; i++) { - var t = triangles[i]; - Vertex2D a = t.a, b = t.b, c = t.c; - if(!table.ContainsKey(a)) table.Add(a, new VertexNetwork2D(a, ExternalPoint(a))); - if(!table.ContainsKey(b)) table.Add(b, new VertexNetwork2D(b, ExternalPoint(b))); - if(!table.ContainsKey(c)) table.Add(c, new VertexNetwork2D(c, ExternalPoint(c))); - } - // tri.Points.ForEach(p => { - // if(!table.ContainsKey(p)) table.Add(p, new VertexNetwork2D(p, ExternalPoint(p))); - // }); - return table; - } - - List BuildNetworks (Triangulation2D tri, Dictionary networkTable) { - var network = new Dictionary>(); - - var triangles = tri.Triangles; - for(int i = 0, n = triangles.Length; i < n; i++) { - var t = triangles[i]; - Segment2D s0 = t.s0, s1 = t.s1, s2 = t.s2; - if(!network.ContainsKey(t.a)) { - network.Add(t.a, new HashSet()); - } - if(!network.ContainsKey(t.b)) { - network.Add(t.b, new HashSet()); - } - if(!network.ContainsKey(t.c)) { - network.Add(t.c, new HashSet()); - } - network[s0.a].Add(s0.b); network[s0.b].Add(s0.a); - network[s1.a].Add(s1.b); network[s1.b].Add(s1.a); - network[s2.a].Add(s2.b); network[s2.b].Add(s2.a); - } - - return network.Keys.Select(v => { - var n = networkTable[v]; - foreach (Vertex2D to in network[v]) { - n.Connect(networkTable[to]); - } - return n; - }).ToList(); - } - - List BuildContourSegments (Triangulation2D triangulation) { - var triangles = triangulation.Triangles; - - var table = new Dictionary>(); - for(int i = 0, n = triangles.Length; i < n; i++) { - var t = triangles[i]; - if(!table.ContainsKey(t.s0)) table.Add(t.s0, new HashSet()); - if(!table.ContainsKey(t.s1)) table.Add(t.s1, new HashSet()); - if(!table.ContainsKey(t.s2)) table.Add(t.s2, new HashSet()); - - table[t.s0].Add(t); - table[t.s1].Add(t); - table[t.s2].Add(t); - } - - return table.Keys.ToList().FindAll(s => { - return table[s].Count == 1; - }).ToList(); - } - - /* + protected void Prune(Chord2D chord, List convergence, Chord2D from = null, List past = null) { + + if (chord.Face.Type == Face2DType.Junction) { + past.Add(chord); + + var centroid = chord.Face.Centroid(); + + var points = new List(); + var ignores = new List(); + + for (int i = 0, n = past.Count - 1; i < n; i++) { + var c0 = past[i]; + var c1 = past[i + 1]; + points.Add(c0.Face.GetUncommonPoint(c1.Face)); + } + + var t = chord.Face.Triangle; + Vertex2D dividePoint = null; + + if (!chord.Face.Pruned) { + points.Add(t.a); points.Add(t.b); points.Add(t.c); + + var coord = chord.Src.Coordinate; + if (coord == (t.a.Coordinate + t.b.Coordinate) * 0.5f) { + dividePoint = t.c; + } else if (coord == (t.b.Coordinate + t.c.Coordinate) * 0.5f) { + dividePoint = t.a; + } else { + dividePoint = t.b; + } + + } else { + points.Add(t.a); points.Add(t.b); points.Add(t.c); + + var divides = chord.Face.Divides; + Triangle2D t0 = divides[0], t1 = divides[1]; + Vertex2D[] ps0 = t0.ExcludePoint(centroid), ps1 = t1.ExcludePoint(centroid); + if (chord.Dst.Coordinate == (ps0[0].Coordinate + ps0[1].Coordinate) * 0.5f) { + triangulation.RemoveTriangle(t0); + if (t.a != ps0[0] && t.a != ps0[1]) { + ignores.Add(t.a); + } else if (t.b != ps0[0] && t.b != ps0[1]) { + ignores.Add(t.b); + } else { + ignores.Add(t.c); + } + } else if (chord.Dst.Coordinate == (ps1[0].Coordinate + ps1[1].Coordinate) * 0.5f) { + triangulation.RemoveTriangle(t1); + if (t.a != ps1[0] && t.a != ps1[1]) { + ignores.Add(t.a); + } else if (t.b != ps1[0] && t.b != ps1[1]) { + ignores.Add(t.b); + } else { + ignores.Add(t.c); + } + } else { + // Debug.LogWarning("error!"); + return; + } + } + + var vertices = points.OrderBy(p => Angle(centroid, p.Coordinate)).ToList(); + var cv = triangulation.CheckAndAddVertex(centroid); + + var newTriangles = new List(); + for (int i = 0, n = vertices.Count; i < n; i++) { + Vertex2D a = cv, b = vertices[i], c = vertices[(i + 1) % n]; + if (ignores.Contains(b) || ignores.Contains(c)) continue; + var nt = triangulation.AddTriangle(a, b, c); + newTriangles.Add(nt); + } + + if (!chord.Face.Pruned && dividePoint != null) { + var divides = newTriangles.FindAll(nt => nt.HasPoint(dividePoint)); + chord.Face.SetDivides(divides.ToList()); + } + + // finish current loop + convergence.Add(cv); + Prune(past); + + return; + } + + Segment2D diameter; + if (chord.Face.Type == Face2DType.Terminal) { + var t = chord.Face.Triangle; + if (!ExternalSegment(t.s0)) { + diameter = t.s0; + } else if (!ExternalSegment(t.s1)) { + diameter = t.s1; + } else { + diameter = t.s2; + } + } else { + var segments = chord.Face.GetUncommonSegments(from.Face); + if (!ExternalSegment(segments[0])) { + diameter = segments[0]; + } else { + diameter = segments[1]; + } + } + + if (past == null) past = new List(); + past.Add(chord); + + Vector2 center = diameter.Midpoint(); + float radius = Vector2.Distance(center, diameter.a.Coordinate); + + var found = past.Find(ch => { + var t = ch.Face.Triangle; + Vector2 a = t.a.Coordinate, b = t.b.Coordinate, c = t.c.Coordinate; + return + (!diameter.HasPoint(a) && Vector2.Distance(a, center) - radius > float.Epsilon) || + (!diameter.HasPoint(b) && Vector2.Distance(b, center) - radius > float.Epsilon) || + (!diameter.HasPoint(c) && Vector2.Distance(c, center) - radius > float.Epsilon); + }); + + if (found != null) { + var points = new List(); + + for (int i = 0, n = past.Count - 1; i < n; i++) { + var c0 = past[i]; + var c1 = past[i + 1]; + points.Add(c0.Face.GetUncommonPoint(c1.Face)); + } + points.Add(chord.Face.GetUncommonPoint(diameter)); + + var basis = diameter.a.Coordinate; + var vertices = points.OrderBy(p => Angle(center, basis, p.Coordinate)).ToList(); + vertices.Insert(0, diameter.a); + vertices.Add(diameter.b); + + var cv = triangulation.CheckAndAddVertex(center); + for (int i = 0, n = vertices.Count - 1; i < n; i++) { + Vertex2D a = cv, b = vertices[i], c = vertices[i + 1]; + triangulation.AddTriangle(a, b, c); + } + + convergence.Add(cv); + Prune(past); + return; + } + + chord.Connection.ForEach(to => { + if (to != from) { + Prune(to, convergence, chord, past.ToList()); + } + }); + + } + + protected void Prune(List chords) { + chords.ForEach(ch => { + ch.Prune(); + triangulation.RemoveTriangle(ch.Face.Triangle); + }); + } + + protected void SubdivideRoutine(List rTriangles, List rSegments, Chord2D chord, Chord2D from) + { + switch (chord.Face.Type) { + case Face2DType.Sleeve: + + if (!chord.Pruned) { + Vertex2D top, lb, rb; + Segment2D s0 = chord.SrcEdge, s1 = chord.DstEdge; + if (s0.a == s1.a || s0.a == s1.b) { + top = s0.a; + lb = s0.b; + } else { + top = s0.b; + lb = s0.a; + } + rb = (s1.a == top) ? s1.b : s1.a; + + Vertex2D tl = chord.Src, tr = chord.Dst, bottom = triangulation.CheckAndAddVertex((lb.Coordinate + rb.Coordinate) * 0.5f); + + // triangulation.RemoveTriangle(chord.Face.Triangle); + rTriangles.Add(chord.Face.Triangle); + triangulation.AddTriangle(top, tl, tr); + triangulation.AddTriangle(tl, lb, bottom); + triangulation.AddTriangle(tr, bottom, rb); + triangulation.AddTriangle(tl, bottom, tr); + } + + break; + + case Face2DType.Junction: + + if (!chord.Pruned) { + Vertex2D top, lb, rb, bottom; + if (chord.SrcEdge != null) { + top = chord.Dst; + lb = chord.SrcEdge.a; + rb = chord.SrcEdge.b; + bottom = chord.Src; + // triangulation.RemoveTriangle(chord.SrcEdge); + rSegments.Add(chord.SrcEdge); + } else { + top = chord.Src; + lb = chord.DstEdge.a; + rb = chord.DstEdge.b; + bottom = chord.Dst; + // triangulation.RemoveTriangle(chord.DstEdge); + rSegments.Add(chord.DstEdge); + } + // triangulation.RemoveTriangle(chord.Face.Triangle); + triangulation.AddTriangle(top, lb, bottom); + triangulation.AddTriangle(top, rb, bottom); + } + + break; + } + + chord.Connection.ForEach(to => { + if (to != from) { + SubdivideRoutine(rTriangles, rSegments, to, chord); + } + }); + } + + // triangles are divided at the spine + protected void Subdivide(Chord2D root) { + var rTriangles = new List(); + var rSegments = new List(); + + SubdivideRoutine(rTriangles, rSegments, root, null); + rTriangles.ForEach(t => triangulation.RemoveTriangle(t)); + rSegments.ForEach(s => triangulation.RemoveTriangle(s)); + } + + protected void GetSpinePointsRoutine(List points, Chord2D current, Chord2D from) + { + if (!current.Pruned) + { + points.Add(current.Src); + } + current.Connection.ForEach(to => + { + if (to != from) + { + GetSpinePointsRoutine(points, to, current); + } + }); + } + + protected List GetSpinePoints(Chord2D chord) { + var points = new List(); + GetSpinePointsRoutine(points, chord, null); + return points; + } + + protected Dictionary BuildTable(Triangulation2D tri) { + var table = new Dictionary(); + var triangles = tri.Triangles; + for (int i = 0, n = triangles.Length; i < n; i++) { + var t = triangles[i]; + Vertex2D a = t.a, b = t.b, c = t.c; + if (!table.ContainsKey(a)) table.Add(a, new VertexNetwork2D(a, ExternalPoint(a))); + if (!table.ContainsKey(b)) table.Add(b, new VertexNetwork2D(b, ExternalPoint(b))); + if (!table.ContainsKey(c)) table.Add(c, new VertexNetwork2D(c, ExternalPoint(c))); + } + // tri.Points.ForEach(p => { + // if(!table.ContainsKey(p)) table.Add(p, new VertexNetwork2D(p, ExternalPoint(p))); + // }); + return table; + } + + protected List BuildNetworks(Triangulation2D tri, Dictionary networkTable) { + var network = new Dictionary>(); + + var triangles = tri.Triangles; + for (int i = 0, n = triangles.Length; i < n; i++) { + var t = triangles[i]; + Segment2D s0 = t.s0, s1 = t.s1, s2 = t.s2; + if (!network.ContainsKey(t.a)) { + network.Add(t.a, new HashSet()); + } + if (!network.ContainsKey(t.b)) { + network.Add(t.b, new HashSet()); + } + if (!network.ContainsKey(t.c)) { + network.Add(t.c, new HashSet()); + } + network[s0.a].Add(s0.b); network[s0.b].Add(s0.a); + network[s1.a].Add(s1.b); network[s1.b].Add(s1.a); + network[s2.a].Add(s2.b); network[s2.b].Add(s2.a); + } + + return network.Keys.Select(v => { + var n = networkTable[v]; + foreach (Vertex2D to in network[v]) { + n.Connect(networkTable[to]); + } + return n; + }).ToList(); + } + + protected List BuildContourSegments(Triangulation2D triangulation) { + var triangles = triangulation.Triangles; + + var table = new Dictionary>(); + for (int i = 0, n = triangles.Length; i < n; i++) { + var t = triangles[i]; + if (!table.ContainsKey(t.s0)) table.Add(t.s0, new HashSet()); + if (!table.ContainsKey(t.s1)) table.Add(t.s1, new HashSet()); + if (!table.ContainsKey(t.s2)) table.Add(t.s2, new HashSet()); + + table[t.s0].Add(t); + table[t.s1].Add(t); + table[t.s2].Add(t); + } + + return table.Keys.ToList().FindAll(s => { + return table[s].Count == 1; + }).ToList(); + } + + /* * each vertex of the spine is elevated proportionally to the average distance * between the vertex and the external vertices * that are directly connected to the vertex */ - void Elevate (List networks) { - for(int i = 0; i < 3; i++) { - networks.ForEach(network => { - network.Elevate(); - }); - } - } - - void Sew (Triangulation2D triangulation, Chord2D chord, Dictionary heightTable, int division) { + protected void Elevate(List networks) { + for (int i = 0; i < 3; i++) { + networks.ForEach(network => { + network.Elevate(); + }); + } + } + + protected void SewTriangle(Dictionary flags, Dictionary> sews, Triangle2D t, Segment2D[] segments, int division) + { + triangulation.RemoveTriangle(t); + var sewTriangles = Sew(heightTable, triangulation, segments[0], segments[1], division); + sews.Add(t, sewTriangles); + flags[t] = true; + } + + protected void SewRoutine(List triangles, Dictionary flags, Dictionary> sews, Chord2D current, Chord2D from, int division) + { + if (!current.Pruned) + { + triangles.FindAll(t => + { + return (t.HasPoint(current.Src) && (t.HasPoint(current.Dst) || !sews.ContainsKey(t))); + }).ForEach(t => + { + Segment2D[] segments; + + if (sews.ContainsKey(t)) + { + foreach (Triangle2D st in sews[t]) + { + triangulation.RemoveTriangle(st); + } + sews.Remove(t); + } + + if (t.HasPoint(current.Dst)) + { + Segment2D s = t.CommonSegment(current.Src, current.Dst); + segments = t.ExcludeSegment(s); + } + else + { + segments = t.CommonSegments(current.Src); + } + + SewTriangle(flags, sews, t, segments, division); + }); + } + + var next = current.Connection.FindAll(con => con != from); + + // Prune後のSpineで末端にあたる頂点 + bool terminal = next.All(con => con.Pruned); + if (terminal && !current.Pruned) + { + triangles.FindAll(t => + { + return !sews.ContainsKey(t) && t.HasPoint(current.Dst); + }).ForEach(t => + { + var segments = t.CommonSegments(current.Dst); + SewTriangle(flags, sews, t, segments, division); + }); + } + + next.ForEach(to => + { + SewRoutine(triangles, flags, sews, to, current, division); + }); + } + + protected void Sew (Triangulation2D triangulation, Chord2D chord, Dictionary heightTable, int division) { var triangles = triangulation.Triangles.ToList(); Dictionary flags = new Dictionary(); @@ -595,63 +661,10 @@ void Sew (Triangulation2D triangulation, Chord2D chord, Dictionary flags.Add(t, false)); - Action SewTriangle = (Triangle2D t, Segment2D[] segments) => { - triangulation.RemoveTriangle(t); - var sewTriangles = Sew(heightTable, triangulation, segments[0], segments[1], division); - sews.Add(t, sewTriangles); - flags[t] = true; - }; - - Action SewRoutine; - SewRoutine = (Chord2D current, Chord2D from) => { - - if(!current.Pruned) { - - triangles.FindAll(t => { - return (t.HasPoint(current.Src) && (t.HasPoint(current.Dst) || !sews.ContainsKey(t))); - }).ForEach(t => { - Segment2D[] segments; - - if(sews.ContainsKey(t)) { - foreach(Triangle2D st in sews[t]) { - triangulation.RemoveTriangle(st); - } - sews.Remove(t); - } - - if(t.HasPoint(current.Dst)) { - Segment2D s = t.CommonSegment(current.Src, current.Dst); - segments = t.ExcludeSegment(s); - } else { - segments = t.CommonSegments(current.Src); - } - - SewTriangle(t, segments); - }); - } - - var next = current.Connection.FindAll(con => con != from); - - // Prune後のSpineで末端にあたる頂点 - bool terminal = next.All(con => con.Pruned); - if(terminal && !current.Pruned) { - triangles.FindAll(t => { - return !sews.ContainsKey(t) && t.HasPoint(current.Dst); - }).ForEach(t => { - var segments = t.CommonSegments(current.Dst); - SewTriangle(t, segments); - }); - } - - next.ForEach(to => { - SewRoutine(to, current); - }); - }; - - SewRoutine(chord, null); + SewRoutine(triangles, flags, sews, chord, null, division); } - List Sew (Dictionary heightTable, Triangulation2D tri, Segment2D left, Segment2D right, int division) { + protected List Sew (Dictionary heightTable, Triangulation2D tri, Segment2D left, Segment2D right, int division) { Vertex2D top, lb, rb; if(left.a == right.a) { @@ -705,14 +718,14 @@ List Sew (Dictionary heightTable, Triangulation2D t // http://www.mathopenref.com/coordparamellipse.html // r : 0.0 ~ 1.0 const float HalfPI = Mathf.PI * 0.5f; - float QuarterOval (float height, float distance, float r) { + protected float QuarterOval (float height, float distance, float r) { if(height >= 0f) { return height * Mathf.Sin(r * HalfPI); } return height * (1f - Mathf.Sin((1f - r) * HalfPI)); } - Mesh Symmetrize (Mesh src) { + protected Mesh Symmetrize (Mesh src) { var mesh = new Mesh(); var vertices = new List(); var triangles = new List(); @@ -764,7 +777,7 @@ Mesh Symmetrize (Mesh src) { return mesh; } - List Traverse (Chord2D cur, Chord2D from, Func check) { + protected List Traverse (Chord2D cur, Chord2D from, Func check) { var chords = new List(); if(check(cur)) { @@ -780,7 +793,7 @@ List Traverse (Chord2D cur, Chord2D from, Func check) { return chords; } - float Angle (Vector2 from, Vector2 to0, Vector2 to1) { + protected float Angle (Vector2 from, Vector2 to0, Vector2 to1) { var v0 = (to0 - from); var v1 = (to1 - from); @@ -789,7 +802,7 @@ float Angle (Vector2 from, Vector2 to0, Vector2 to1) { return acos; } - float Angle (Vector2 p0, Vector2 p1) { + protected float Angle (Vector2 p0, Vector2 p1) { return Mathf.Atan2(p1.y - p0.y, p1.x - p0.x); } diff --git a/Assets/Teddy/Shaders/DebugChordLine.shader b/Assets/Teddy/Shaders/DebugChordLine.shader index 3062a66..f38d001 100644 --- a/Assets/Teddy/Shaders/DebugChordLine.shader +++ b/Assets/Teddy/Shaders/DebugChordLine.shader @@ -1,4 +1,6 @@ -Shader "Teddy/DebugChordLine" { +// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' + +Shader "Teddy/DebugChordLine" { Properties { _Color0 ("From Color", Color) = (0, 0, 1, 1) @@ -29,7 +31,7 @@ v2f vert (appdata v) { v2f o; - o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); + o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } diff --git a/Assets/Teddy/Shaders/DebugNormal.shader b/Assets/Teddy/Shaders/DebugNormal.shader index 3d70341..bbfab71 100644 --- a/Assets/Teddy/Shaders/DebugNormal.shader +++ b/Assets/Teddy/Shaders/DebugNormal.shader @@ -1,4 +1,6 @@ -Shader "Teddy/DebugNormal" { +// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' + +Shader "Teddy/DebugNormal" { Properties { } @@ -27,7 +29,7 @@ v2f vert (appdata v) { v2f o; - o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); + o.vertex = UnityObjectToClipPos(v.vertex); o.normal = mul(unity_ObjectToWorld, float4(v.normal, 0.0)).xyz; o.uv = v.uv; return o; diff --git a/Assets/Teddy/Shaders/Puppet.shader b/Assets/Teddy/Shaders/Puppet.shader index 8207a2b..2d031b4 100644 --- a/Assets/Teddy/Shaders/Puppet.shader +++ b/Assets/Teddy/Shaders/Puppet.shader @@ -1,4 +1,6 @@ -Shader "Teddy/Demo/Puppet" { +// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' + +Shader "Teddy/Demo/Puppet" { Properties { _Color ("Color", Color) = (1, 1, 1, 1) @@ -40,7 +42,7 @@ v2f OUT; v.vertex.xyz += v.normal * snoise(v.vertex.xyz * _DisplacementParams.x + float3(0, _Time.y, 0) * _DisplacementParams.y) * _DisplacementParams.z; - OUT.vertex = mul(UNITY_MATRIX_MVP, v.vertex); + OUT.vertex = UnityObjectToClipPos(v.vertex); OUT.screenPos = ComputeScreenPos(OUT.vertex); OUT.uv = v.uv; diff --git a/Assets/Teddy/Shaders/Teddy.shader b/Assets/Teddy/Shaders/Teddy.shader index cc82b07..cb0b3b2 100644 --- a/Assets/Teddy/Shaders/Teddy.shader +++ b/Assets/Teddy/Shaders/Teddy.shader @@ -1,4 +1,6 @@ -Shader "Teddy/Demo/Mesh" { +// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' + +Shader "Teddy/Demo/Mesh" { Properties { } @@ -27,7 +29,7 @@ v2f vert (appdata v) { v2f o; - o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); + o.vertex = UnityObjectToClipPos(v.vertex); o.normal = mul(unity_ObjectToWorld, float4(v.normal, 0)).xyz; o.uv = v.uv; return o; diff --git a/Assets/Teddy/Shaders/TeddyDebug.shader b/Assets/Teddy/Shaders/TeddyDebug.shader index 4fe68b6..a405177 100644 --- a/Assets/Teddy/Shaders/TeddyDebug.shader +++ b/Assets/Teddy/Shaders/TeddyDebug.shader @@ -1,4 +1,6 @@ -Shader "Teddy/Demo/Debug" { +// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' + +Shader "Teddy/Demo/Debug" { Properties { } @@ -27,7 +29,7 @@ v2f vert (appdata v) { v2f o; - o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); + o.vertex = UnityObjectToClipPos(v.vertex); o.normal = mul(unity_ObjectToWorld, float4(v.normal, 0)).xyz; o.uv = v.uv; return o; diff --git a/Packages/manifest.json b/Packages/manifest.json new file mode 100644 index 0000000..8303129 --- /dev/null +++ b/Packages/manifest.json @@ -0,0 +1,12 @@ +{ + "dependencies": { + "com.unity.package-manager-ui": "1.9.11", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.physics2d": "1.0.0", + "com.unity.modules.screencapture": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.uielements": "1.0.0" + } +} diff --git a/README.md b/README.md index 0b58249..2057b66 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,10 @@ Mesh mesh = teddy.Build( [Demo](https://mattatz.github.io/unity/teddy) +## Compatibility + +tested on Unity 2018.2.6f, windows10 (GTX 1060). + ## Sources - Teddy: A Sketching Interface for 3D Freeform Design - http://www-ui.is.s.u-tokyo.ac.jp/~takeo/papers/siggraph99.pdf