openscenegraph-3.2.3/0000755000175000017500000000000012674261210014363 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/0000755000175000017500000000000012674261223017230 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/CTestConfig.cmake0000644000175000017500000000105411553272246022404 0ustar albertoalberto## This file should be placed in the root directory of your project. ## Then modify the CMakeLists.txt file in the root directory of your ## project to incorporate the testing dashboard. ## # The following are required to uses Dart and the Cdash dashboard ## ENABLE_TESTING() ## INCLUDE(Dart) set(CTEST_PROJECT_NAME "OpenSceneGraph") set(CTEST_NIGHTLY_START_TIME "00:00:00 CET") set(CTEST_DROP_METHOD "http") set(CTEST_DROP_SITE "cdash.openscenegraph.org") set(CTEST_DROP_LOCATION "/submit.php?project=OpenSceneGraph") set(CTEST_DROP_SITE_CDASH TRUE) openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/0000755000175000017500000000000012674261223022645 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/0000755000175000017500000000000012674261223024277 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/icons/0000755000175000017500000000000012674261223025412 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/icons/src/0000755000175000017500000000000012674261223026201 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/icons/src/osg32.xcf0000644000175000017500000000745310005712307027637 0ustar albertoalbertogimp xcf file BB0/ gimp-commentCreated with The GIMP   Pasted Layer     O c s   Ԟ[CtY=% )L60  >AGG(  c025v}V)  l{5Ok  M4?0  C:uc(  \ȴ?:S2+M@  ?XZeMJu>:B 7<:7+   )<5kj?L;;,,2=<0  G=FNB@75 .103G[Y  KO9=B?6k UDK\c/  0eYX5DJ6U +{M]P  GO37U78B sOG  V4B37T76c Na3  *%438_=67 V  z:37Lf@7=A  O3?Z|I9Cc JR5InX;JtZ@iCWdHkqF`Ut|N~^f Q5/A7+ '=;W5" .DyA, %8CD2!$KyW( -H> B).; "6E K1!-ԟ\CvI!)<;S@*0u[?% &5]J&1HGRJC%  JU[DŽVl]7  \+59b7  yµ`qrg  ss|:!  yxc4  _xx17aP   Rkgwhgvxw DVSO5  4UQgvzMKJNVJ5  UMDwxy5 6KMPX[Z  OR;wwv{j TTY_^2  +`VYry{ "pYbR  ;yIsrzzA fXR  Dk1zsrz{ Ia:  $ssqz{zQ  zvss~zz|?  sxzc  Kr}y幙nt }z{y zu|{y~z|Ή G'!6*11M' 9p4*86$=owJ=4 4y.(9 @#|էyj</.H3!lU09SFBA8*:>#>;G*hehė+e8ECDDBw5=DCDDAW}59:=CDDBJ@Yhxkkhԛ-]>3&&1?DD:,070BLB/,=DD>9<- ='NA& #9ADD57 `C2 %5>DD9#7rD?;*/2CDDE5*Yߗ(0CDCH,1:DDNR:5 jD>O"&6CDDRSJ6 @HCH45ADDCDDC?ǘD F>D=DDB癙I JSACDDE𢙚k% IGDDCFo𣘜7Ū裗 Mڜ V.cɖ<II%L4YEנ #U<g  S m  ml0&***"~dba``6yeu*>~  ; b /U Ur!7 white     -   black     '    Background     e y  Selection Mask  'openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/icons/src/osg32-32.png0000644000175000017500000000437610005712307030066 0ustar albertoalbertoPNG  IHDR szzbKGDn ]] pHYs  ~tIME =iIDATx{pT?}H!!CP0ѪPTEEg@at,ZDB;Dkh#j<I Iv}޽?Bb9~wL5Ꮆ[D ]Ruj- 4N-%\fF}7N^uɦK.%y#\]s Odz]аe#z |f!x`ӾlGB 0@-=v׊qezo[帺7;]uф^8&MA'kW AgZ[tDH_7VBS$"yZ쨖&BrEϪgZS%HK E^(zn$yi"ƾluF519We)i I t>76z;7zrQIBpĘ3#~dbeOc0p 5r??*iNPN4V{iri"&SώMB 'F[ g-[Y ߨyVvI9X,uO Mwk1 ܷE`X̍\i|{`7fU|Uy ":Hn=ܰ Į=w]7b6$55]E+ Mg8) vDmK;I!ivIK:2GOl% L!?U w@3Bߥ&ff8/LHH4O'} ~| 7Ϗ0p&;ȽZכMs]:DFyIQI+D'LA%d@ҵY})gOD8", (p`TE <\sȊډ =nGhB-q`Ii8@1uP$\45'&EL 3=L݁"!6Ln̸$1`AF( P4%n@BocAH79mLt,: 5f<;rd{\'=ɱb,+sF8PȲ 1RSnHLWLwWRC$料&tI&W `r IHv7sf̘BQQ!u"fdHgҬAS>7ϣ'ˊ>TKIڹ!ylI# q !NKMSeىS% n~7,LS5#&rFPZ-?J\lF _̊hxR$Xްmpo䴬w+ǔ/JgP:iU lQVԩi-i 3n_~~Y38˸gMMm7Lfswaz/'OqIsS8fneu}AG74sʸusѯ⥛yUh$o]̅>|~?~tq,վ ş}Rtn@M-nij4M- b9o|Blq0ڤQY7,ѕoF joq9\o Ky<WY.V7M^(}bZ~de&# K'|$~҇־&=.Z{Étܛ$xnӓ+_~ekY>veYym#k,\OgCIENDB`openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/icons/src/osg16.xcf0000644000175000017500000000353310005712307027634 0ustar albertoalbertogimp xcf fileBB0/ gimp-commentCreated with The GIMP Pasted Layer     K_ore._' 3;*  Ї4k] D;2 3FX]=20G*  0CD:P)V[  Zg8?e\'  I~5F85  8DJ@sIRoĿCRkBEfFJUP7+(=y5$#/CC)<ȘE(8S3?se.eøQ.H6 5DҴ5  rƤrc ʲLE !=Ze{FMU,  5HzzO%]\  Pet|Z+  =rzŘ2  u{}sHQn{}{~}~*1p'!85.Ð8*H%1yYjD>(;DD:+α5BDDCoؘJi=BDDCkJ&;DD:7!(M ;DD+'v@'-=DDFXAC;5DDJ" HADDޙ'ِovޜMΛ!pÜ4ՙ"]s2`    Mx>CX white     ,vblack     'L`p Background     ';Kopenscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/icons/src/osg32-8.png0000644000175000017500000000304710005712307030003 0ustar albertoalbertoPNG  IHDR DPLTEƢ>~6z &GZ."3N.J  Fx*6*xn>zB B>zRjBz$.F:J~nf62Jfv2zrJj~fZ^z:vvB"FrVJBBjJ>jf>®ƖࢦZF2rRR2^^JB>R֜*$B6\\(LjVN’~V2jζ0 bBGJN"Bv>zzڶ6vv2Jʖ8*vX>R.LhFΞ2*6Xd22Bldf>N&ҪN*:rr26::BllʺzjR<.2*F2$>>>2N^:rv:N&F:Nb^FڟNJ:zj">J"zrjdb6:VRFN򢚂bz$>. FB44`Nb&>zH~":RNJJҾ¾>zLRFFV2"Zj2΢>JJn:vNZ >J.ƪ&&R檢Ž.226JR.::6BV+60:ZZ6FR&ZZXBz&:rfNVV:6F.6r֞"bbjLNRB4R 3:7O:z ZV*b^.^b.ֲ:>BR&VFRFF6|*:vF^:>V:z>Fz򚔪6(>v*66.tRNS@fbKGDH pHYs  ~tIME+p:PIDATxc`@g1oY/V}ҥng  ce6W!oYx}`_WP ]*R-.j,ޞ"TroҿU%Wz/SbOФG8f,S4X~I|BB%@ҋn'Y@ >8t:{fǁtU zu9[(]"Ԝz1Vw9Pt XWQKJJD< .l`c_1]Q _(pj2#!!urj*lbs٧$-n>#EqL}%w/;nPгBr;bæu^2B"7q$ƫR q    M:4DCC<    8166)59653." N.,5532-! )   Y2#05221,$ ̷U?'"1782.-   WI87378+   aJB?9;7'   gQGC@;6   oZHD><5    Ht_LE?@=  B~эmLHCA3  @f YBBF/   >> ϘoG149  =8L)$ ("   >66=/66=1EC-     ?65:m"?5-    ?649A+ /D?    >779@ 95  .&   ?669=  '& >RW4$-"  ?667;jo  *#%@IGPUY_F(  @6679ho  $7KGKPTVWG9    ?669io  .IMPVLAC<;;%$   ?6579Uo  1RTUO=::AK@336)  ?667>  =QMC=85:JQA5789! A5667=  +PI@:3326;>;776;L&   @7665<  TK?62-++,220044   l:766=  c?;50,(++-,.399:;DB5  =966966:PQ  K8/-*+--*++.02477?DEBEMQD)  * I-*F,*:o3f.'#"%*.H("  .m/(#!/?*#)].'# *7)!  *R1'#  )H*# )j-'#  $A*"  #l.&# "p=*# !V,'#   т2'!  "$%%&(*))(G,&"   ""'-004fppo]Ն0'" "%'*-DLOB+%" "(09oj2&  !%(+0|H,&! &1`{p7&! "$*1K T,&"  !'1V ΂3'!  !%*.^턿C,%"  &1`܏d2Q?)&I& % j6% "#()7wM#:9)" du#  M-'! #+C|e%:OE?    w5&! #&)1?zT?"7HGH?  O+%" #)2^FBCB4BDA@=9) ˁ3(#$&(,Dq\ACHGEC=0-)4#  E,'%'-9ZhD8HNLKH?% +$ <3/5:maQ=9HRSKB<% Пd[LMKNN>   i\XWQPI7    oa^_[SG#  rh^`\UJ    i ug`_ZYP'  m ȇr[]\XF$  qbVXY;  ssɎkQCFH  tuwp5&9  tw~ B.7!  txt^u /I,  tzxej;1P2  t{yq Pc1@C   t{{s >T4/!5"(  s{{t4ER8I <*  s{{v:WX@      t{{v.QH=    s{zxo, EI<@CB@<@:uX/ ,5-:*5@B@==>@BEDB@o)$3qy3(%,/$*4,5BDDBBCDDB D&U"($ $)/5BD D{(8f8..6BDDCDDEDD< /Qm? #%3=>;D D4'"(.cg1!  #)746856>D Dƙn/!"((#146=@>>BD D p6!)/,%1<@BDD n>"#5,-7>BBCD DEjC+)$0=DDCDDE0I+ 4)0>BDD%d g<$*&.=DD}G|U)+/'2=BDDCDD{sH.1'6>EDD{Bgd1)!";2=BDBBDDE D{0{zG'44?JG@BDBBDDE D{ Kl47;:G_R@BDD{ Mc^6*9;CHeS@@ADD{ R]#;;QNN;CA@BDDEDE D~>I8A474E;JG@BDEDEEDDE Du:@7A/7==7=\PEECEDDBn$?=7-6BE=776=?CECDDEBR06*9*27CB@>>@@BBEBDDED$J;7'5;@3?>;87;=>>CADD2=>7,??2=4.?7./27?BDDCD D 5>DB6:9..AHK6-8659?DD M9@DD;5@;15.#*06>51+:CDDE I;BDD>5=:<0 "!*(&26;@D DEJ;BEDB>8-6+"% **+:BCDDEDEDD 4ݒ>BDCDD;*61 ! "030;@EDDEDEEDD @BDD9&9, !**0=D D9DDB56B!   @/.9>BDDCDD 9DEDFB@6O.   *+'5>BBDCCDDM v7DDEFB>7V   16../39>BDD 95BDDCA>0E  $)*0716=ADEDD4w@BDDB@:?     *3@@  Zu{5"(#3-Ezs \   -SbW:AOPUA, (%MzA -i|62Z9 #xO&('[=4 ?޷To}AOW:4 S @94 *ү w:63 q A643 (~ĸ >433 n꩓ ;366 ߔm:6; [ÅB96? ,>76= 3in;66> GШik946> +pzuioͺԻrn_646> P`\VZeryyih_D>436= @ROSVdmrt}ywy}vpb[`quh[U=336>  =PLPW^]^qnpnpusa\WOFIQSS}=336> =GLT^ZXX_d]do[LHJB:>?FLTzp;336=  7HOUPLE8*>hdLGE?><88@M\}W;336> $ ;3GJH;=>53:NtU:427@   >LF47:5.5Jw}L9339I   8IC2578-.Efc>7339] 8EC9442/=G|D=643:_    7@NC710.37Pd&I:633:`  'JRK?434;UmR|7433:` CRNK;9@C`o;@5433:`4/8,$/W,!$)50 ".X, $(0v,#*;*#(2_(!)Q& "(.R"(3  "%.C" 'D}    "',; '%$$"!  "&/^62/+'$  !!%*A QNA,)&$"!! &3e Ӣa7-'#  "%)0p1,($!  #,>ԥZ.&! $)5HЅ5+#  "&*; DA5059iw8+'#  &6g  */#-7(3FOq|B*# "&+M  :=8*$@;4PVUl|:,)&#! "%.W  1)@ZP뾤R;=E[ *KTXcK- 3F7D[a)5 #[uxu9!%6:CVD7DC  Vnxt/!)'70Ex|m}  'GSG(0?EL;)(#Izsyo Satų- (q  dB %$Nĸpr  1ĝEev:D }pr  @߼ oqr  !sЮ prs  eϿ䀚 nrrs !f orss gؑ~ pqrr ʴ|prp  Q۩nnqrp !goqrn )˼äZprro F÷ʰ`qrro /wuzxqerro "\mpkosz|~soX:orsrn %Nfikkty|~}|xqqvpdypssro Lihhnsst~}|~wupjadjlocuossro 'O_dmtpnnpuowrede_\aafidopssrn D[cfa_TA3Lzycbb\]_^^bhgmzpqrro )0"!#HD^ddW\_XXZd{t~{prqqo  L`^ORYTNS^{yhxqssqu     CZXKNRSJHUkSprssq CUVNJMOLGNNu:prtsp   >M^VLJJFHCTa Gqrssp  ,Q]YRJLJJYjMrrssp I\YYMMRN`j6osrssp4/,3"N0*y."O-$l1 &T  G "H&'~   9#    9v .  "V)'" 5񲰬GC5'\͚X-"$w߃d$ 4ΞP"/e!י@ O ?" Lù J"  0 58>5;8mq1&xZO@DC@4+:(4}+. =@@B>:.&?0"Sl-*^ @B@9<6%%*.-$!Gu7B B8D=A5 #- !?s0$ODB;H2@R0)-!#6ώW)&DB>5)'),:'$<z;"&ADB>84/<@( %-?пS6$ 8sD=5$$("++(%%);湜H/3dYcωDA;+EN]0)4563%0DB>;fpK5,DA)H͏DB>9Jn@cl22 DBA9,F򞥵ž ӍDBA@@uƾr DB=4sXy D73LяD7n²ukDC5}` DB1OOB4'MEHBD41yqEEGBD3BvcXHS]insuy}}l?{DBBD40VI7+.>OUT^fptp|{mwl[bw}lAETDE94N?) (17;FFBMTORUGB>4=X^F.9E8ݍD>2.51")/35<83?2&70$!"5351133$!F␙EDD=305-&+3/-04,=?>DA??>.5R> "9gD@6./."#''--'>"( 8B_DA@;524557>;5*2%  >IMDBDBDB9&5& 5Z<΋D:'5$ $X.ЍDCDDCDDCDDCDD;.7!  1P UӐDCDDED D>32/! &GJ D?;,/'*J<%s 663310 . 2+ +((%%#|   !v#$&() + , . /22222222.2222211111111111111111>966:No  ^<0+''+,)+*-*/06?ILLIPX_id5  >9669@p  3D2.+**,++)*-/04GRSRRWcdf`@  >9669=o  M<3..100/*-0315CSYYS]kngY+  >9667:{  3J762635;.19?5=DR]^Xdjh]:  >9667@  OG95376<99=A7AJU]g^ba_B  >86676>  2gWL966=x  YvqP>?6;HPTZ[^_bidb]L  >966<  RtXDFEDJO\`defif\UO  >966:b  DeQMB@N\ccdfgdWXL  ?96659A\   zYQGFMZaaccVS7  W:65566=}    UhVPINX_^`]\YRO$  _<655679a9     lljh[[YPC _;66W  +|olaSRJ' _;667667:M  fxg^YO? a:566=  7mn]Y= |@:7665669@  RkgI!  K<765667:Y  1jsV  x=9667<[  `pX  >97667<_ ,sC   R<97667A9  XV  X@9669>U @V1  @:7656779> '@$    a<765667;Cy    mF976679D=     D:7667:>B  ;%  n=97669>&"v* y@9669AyjwD#-CL:96670@:7679>d=9868>})zJ:779;L%H=977:O,s>967:J,|@:779>t/T:669=u2Q>977=v)@:79=n&\=:9=t2iD99t.k=<>n4K<>v4N>@u1y>A/DF,YPq-dl-|sx{{w}n  gMLKGGIJIKJKINOTY_]XUZ]aie9  sx{{xqo  7QJLIHHJIIJNPOR^c][X[aaedE  sxz{xtn  TMKKNMMLHKORNPX_^ZS\dhj`1  sxz{yvz  7UHKLPNPUKNTZOST\`\T^cdbC  sx{{zyq QMFILPOURORUKSU\]dW\[]H  sw{{|{s  /eYUKUWMQ[Z[X\\]\`^`\Q#  sx{{tx  SnlRISLP[^]a`a_^c]^]O  sx{{u  EtlWMVUTUXabdcbc_ZWS  sx{{v   8aVYRNYaccbcc`U[Q  px{{zxp\   bVYUV[_ddfaaW=  v{||{xt  A\VYX\adfh`^[UR(  u{||{zx8  +bVYZX^gd_\XC1(    u{{zt  z_TTRVW\[QF*    u{{v.  ajUUXVVRVM=   u{{xt   R|mY\YUUYYO;  u{{zvb  /tl^Y_[^a[P1 u{{zys cudgjbba[K  t{{u\  8tcjhc`cQ, u{{xsV  *yfc`ZZS, t{{|{{zw|  em]\^VG v{zz{{xt  5deYYB&  qxyz{{z{{xq Mc`C  vuyz{{yw /fhL txzz{{zu ]gN  rwy{zz{{yu *lA   uxyz{{yx9 U{V  ux{{zxrU @Y3   rvyzz{|zxr +D&     Čuy{|{{zxuy    {xzz{{zxv=     svy{{zwsB  :$  ښtxy{{zxr & "u) qxz{zzxwzkvD#-C}vxzzyt Ȫvjlfsrtxzzyvruyz{zu~uy|{yu|xxzzwr6qvzzxsϒtxzzws/|wyzxt{1wvxzyw~/ܜsxzyw|/rvyzxs~vzzxt}wxyyt3qvyxt)tyxt0xxs8tuws+ђtvs*}us9zsr9rp5mo,t3}ƃ3/=BDDBEDD=BDDB463     (*/AI1>EDD  =BEDD9*L# !$!&045?=5@DD  s9BFDD>4B7    ))$./5:2/;BDD 4>DEDDB=2F)   &)1),'6<)5@DD.=DDB6:V2   $%*(002)/'0=DD;DDCDD=6][F# !$+*,+.3//)0+7@DDj9ADDCD@;4LdH'+00231*&82=BDDGD@BEDDB@;1Fnc1+1//030%.;3>DEDD ~=BDDEDDB>-^rV#  )//1.01/631@DEDD: a7@DDEDDB2Jh,$"(,-/+-38G35CDDC @Z=CDD8=r5&$"+((-40.53=DDC ;DDED94{r6#! !("(37=BDDBDC>T@BDD;0irC% ""-"5BDDCDDBBDDD8@DDB=4`kI,($"$*4*9DDCDDE F;BDDBB>7GgK4(+%(-)372=D DD F@BDDCDB>3^[?:8,,.3<6;@D DEEQ{9@DDB39^B@8-,8BDD9/aW9355<-<@D DBG  i9>DD=0BUF6?<66@BED Dh  A>BDD@93IND5.3=BD Dߜ.  8=>DDB@4:]TB0;@DED D\  A5>BDD;1dXE-9@DD t   B;=BD@9BbN1=DBBDDED 4  ];?B@5`|`-9CEBDDEDED< q7=@=5ZhH6@J@BBDDCDDCDD  A9=>8H_M?@BBDENDDE   4;>:<@@BDDEDDCDDEDDHDR#  !a=;>?CDBABA@BEDDEGD#  ^=;@B@DdN;@DEDDO  L87DK7=>@@?=;`  !z^E<:<;;O_ڟ, @ Ͷ.  ;q  8:  +r!C  t/"  q(G c$c' +! ' -+X 'y+d ].6 X.2 ]/z  Q2= Z1Q#X+#[,QQ4f(\3/[4\"+l))*=74SБ6艿74 4 4 4444444 5 5 5 5 5 5 5 5 5 5 5 5 3 2 //.7+**('&$#   Q"#%&')*+-./A 1 2 4 5 689: 3OJQGJOGZb+>3443:_ #ILOMQRKZ\#=3343:` !KNPPOMYS <33:`  !NMOQNOOMM";339`   ,SPQONPRIJ/b:33:`   !XYVVZQSVMAfA8334;`  Ii`abg]YWP3 =733:a  wyzrone^[G 9e:6233; "wsjdP&'ib84332= wna51C332= tlS !?=33> weC3O:33> %{hU#(>7322332= 4zc)?w94322332= 3sD*>533> (vI{:33>    +svK/A73343>    1^Z>m:623343> mH6433433>  dI94332332> ;r:64332334S #>434337;w  P9332336;X  L943343469>| W;4336;V   v>73343347?g  g>643443349B  -@733467;_    ?74332349F P>733247;_  ]=743347@t 6Z@73347;L[˄>743346=tS;63346:@ N;64336=VF963369>xH95434:Fz=64348=gl=74347@E:4348;G G96337A~'|H7346;K(d=7446= a;646:@ a;636=\(B:679B'@966:E)@769=h*@86:K)>99=M*>9:B~)C:;T.B;@e.a@F-bDd0Nz333  :XS[QUXLY_)psrrsp (QSTRVWNY[%pssrsp %RTUSSRPYT"ossp %SPRQNRROP#psso -TRQONPTLN0pssrp VWUTXOQXODfopssq Cc[]^`WVVT7 oqssq npoife]ZYJ"8prrssp qxrjga_N&'grrssp gzq~rvd]30rqssp ew~scO <psso q~yi]A2upsso {i]N&oqssp "ziY$ =qrssp $}}nd= (osso sqd= qsso   fre@ .nrssrso   ,TP4 prrssrrso   nwrrsstsso   erorssrssro  ;qrtssrssr  #orstssqsp   ~qssrssqrp~   xqrsstsrrqo  Vprssrrssrp    uprsstrssrr  hoqrsrrssrqp  -oqssqrrp   pqrssrsrqu   Qprssrqp  ]nrrsrrqo  4YoqssrqpxYqqrssrrpÿ{prssrrpozprrssro~!rqrssrqo+yqsrsrqp,prrsrsp,Ԗprrsrro,oqssrsps-vqrssrn,uqsrrpw,pqrrp)prrpo.prsrp+nprsqt'oqrrqm/qrrqp/qsrpy/pqqpw0pqpn+rqp0ppq1or-n4r5qDB@-*+!#@6+DC2!,#=4.DE4$3$%51.ÎDE3$5#50BDCDB0%2#"7,NDB=7G0'#''(3(D>3QK10/2'#(3(*萖D;2sSB>;:/+37@DC;3thMI@=895&3rD;,j_HVIL@@'BݎD;-ljNXVIDC"-MΏD;+wmWYQFHD'DD9/{kj\EAD63>ʍD78nlUKM+15SDE77yrWLOE.7OD7,mpTP=.55EDDC5.^^UH-79M񋔙D9B\O<17=5B DED>B<43;=8ߕB DEDB>?@@B;DEDBBA>aDEDEB=I덗DEDB>@񘔙DEDB@;= D@7u DEDB>7Ë DEDDCB>7ō DB@>9SDCDEEDDE@;2󼎖DB@>=;BpċDB@>;8;w Č988<@=ABFYyo锏,!,-,⮏,އ-۔#"  .Ή*΋/ď+Ώ0ϋ0ʋ+Ž1ي2-56q1111111000000000000000/. , + *('%$#! F<"\"%&(( ) , f, 7-023467q==zzwhite     ,ilzziizziiii $ $ $ $==zzblack     'jzzjk zzjjjj&<  $ $ $ $==zz Background     kzzkl4zzklll$ $ $ $ $==zzSelection Masklzzllzzllll $==openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/icons/src/osg32-4.png0000644000175000017500000000101510005712307027770 0ustar albertoalbertoPNG  IHDR Tg0PLTEz~#Ew`5&_aB;-BRHF8Gڧ/73xnO*btRNS@fbKGDH pHYs  ~tIME 6K/VIDATxU1K@3hߡ8RApJppp9ŖDťsRP]K,]ACid]"IDb7MxywUH) q˂pVfw0 h01ܽ9_ 8_X"\;$lwbL(_&M*Gʶ_!Oj"7.c(j'dC3C)!!7('D&MCްkjφnSӊi~Ңqעfb_M;ZH~e0R /$R7X(f%KTLޡSIDZ-Nfci#0ZBЖIENDB`openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/icons/src/osg48-8.png0000644000175000017500000000410410005712307030005 0ustar albertoalbertoPNG  IHDR00` PLTEΤ6~6z(6Z . 1O 6*.J J F~v*8-Ez  BNwo".fFB6ښ>v\$*1^r*^R$4.">26*ʦ:~Z_^Rnz.ƶzڮfjfNNqv?>ekaC2rv檎sgv7ZV""2FLA2(Bz<^Z*""N/AsHyTJξ򢚪nz6.NN*LO-!B FƓªM[ڲ@2zvvvVB>:AP/Oj* >򪦺"6Rڶ®~z0@-B@vjRfnb>N%'޺Pf&6bVV&ҮX\2ΎR@6>B6^=ƶB¦">€lV澒4$U\(FR:bv"fBޒ?2ބ򲮊F;B3"[SK>z11WrnNʎ~~63AfZR^>bb6*6. 7r¦>8,ھ~:G"ʝQ-Lb"@U:6JzR FFEg%.7tV=?C¿anbZ~.2.4JӜ"FFHnfn8y D[62Fba2Zb*xvnn:8QzJZ.nh@..;Y8BVVlg^FG329+¢ԢBV"::avhܣ.*:LTR^Jl>087b^tRNS@fbKGDH pHYs  ~tIME 'xIDATxS}TSeaRHLaG@?ZEcV'ԥHDfPaj';sc)L^t-ġ| %BncCsϹЂI>LO5"ܙ}"^3S,$3,RI@5=spSiU\mw-+oS_ò9^#2' _$̃e"e<ٲSr5vz/#k/6l|Xqc |o̅7B P(2Wx_J(CL3 U5] +Գ~sEdJ* *Xu:: dQm-=x4;veeuVT0n}g}{A  ۞ط1vAOXlx.x߼`,uCKjZ^>ax0i$BŸH39&]`OKVf¶ĕ1mzhA '۷o艁>HbC@E@ɷz}q -ĒЯ2';H j \lCq֝KBC?[XȜa+eUc56i`WVU+dPXaMހvÃvSxtJ> _2%נ 2LalX)hS%D`˳ӑ}x onłıV+zNG&uc#D#vx8PB.- 8=$W7sфKs '{QEqe:pa;e:fS0j82mZ?ޑVU= sɜHQ;?J.6bכ-E0EYVq hw<2U >D7.få $[^kYm%ʺ‚oһ*ھ$IȔNQ+g wlDǴyp,Rn{YΐLipA %<MaIw#~;"v!~%э;ÚN[[T"7iiiXsn+e$}$BڛM]F<ޖиBqϺٲF',b=مE\7%(rO9#J4t,"cM1O+.;2  $").O<41!"  &IDEKI1.  3U21?6dG "CNI!  3N_fmq`OOS6D>6V9 OI??,  %/( CH<7M5D?6F 6@34:5< C63Bmy4Hn9= @2-,.6:@/$  CA4JBc3Ko:9= :.*++/3KO:6e HR=@MUacC  S\XLV73LQ:6F ^lIObe^9 &{h7z43KYC58D /UM[VC  %^3L33<_F66c VJJ/ 3~.n623<_F66faM>< F7Cz^D9r;>T~pF9[~8DiQ>Yc:N _DZc@`h"kR\cGc%NetX([ŏ]:4K(?Q1! 'Dr%7&"2O"jO-!&Aaf>&!.MyK1! &?CX:$ ")=Ww^I-" !.Oe[D*! *Qf5"%7G\=$ *f܉6! /@Vށ?/ ,kÄTaI#!4H ]3$ $StD->? ;\C" )6g SK-".\n(B5  -+6AeK(#/BF<*9zNHC-+  .YZ\`vC/sywy= DKIJJNW\Y`?  9UTV-sywzN !MLONRT^Za,  2RQR/vsyw{ FXQTZ]_^D  OYUNWrs{w{~ QhUYcc\=  una6rs|{|yC  $X[c\E  {zW1~ssp|{{ qYVW8  &k(mrssp|{{M Rc`[) #n3 ssp|{{ 2f^>   ssp~y{{y UJ {yssvx{{ 3R   nssv}yz{0D! rrs zz|   Lrrt zzމ8I8 !01@srrw}wzӦrs{z{ مru{z|sw|xuw{ysw}yr} {t"w%z(}թR-(?(4F":j%-*%D"`E 6W[2 Bp?"28N-/LmvS<!C\P8Eߥ['*<Q/\ـ(!3Ly2!aȕt݌=(DDB82/ zm7"1i&$/:=BDD>43*-*-`Ѭ)+7ADDEDD??J6A8:JP=)9CDDBjxBHS;~w*-9CDDCBn86G9PCCDDAn˗(g*=DEBDEDEDD? 6/8>AADDE?[yu o8898?DDA@5/DR\c]L`Ce왜ClC:7-+//;BDDC:0#*074#Xޖ1cD@3#"2ADDC;63424 NǗHD@9 &/>CDDCA@AB/" EN KD>1  !)5=DD8) !;PgDA5  2B?DD>*&93 vrDC; &(46ADDA-$>阙.DBD?D)&-.-:DD>=*#+bז1 EDC=O8 /1-3ADD@ZD9.< jDDAc$*-38CDD?cRD?C CBDC;b((8BDCDDCnN8֗E rCC?P9+/6AD D=^>EF @ODCAG04YBCCDEDDCH 2$ /CBBCCEEDCBBo *'ak\A@CMXYf`* #ض򨗗M!  ⣗D,w ћ@SØV"9216 C8󩔥"Q0<%/I[(D۹%2([%N"c% a x "zt5%~ nJ 2 {b  "/&?'?'?%?'?&6u&.u&.u&.u&$u&H& &&&&&u&u&u&u%e"j? , iP((>G+ [} % Eh"-%u(100white     ,f00z00    00black     '<00P00`    00 Background     00+00;    00Selection Mask0000 openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/icons/src/osg16-4.png0000644000175000017500000000047210005712307030000 0ustar albertoalbertoPNG  IHDRR0PLTEθB/OvsY^I6(=J5396G htRNS@fbKGDH pHYs  ~tIME<xa\m=x{3,/ځ*[dznKpf6y VGToDj3 %B 'hhsël\Q\rBJp 'ە`Ԅ Qce2sF6w:|=ob\OAK CL͸@f/$?Ȫ4qR:'&ѫ"&v;,(ф kDγTo_?EGH$lH \ c7F/*7ޛ8f/Z-դ}EK,sv۸{d ''U+HZ-jotԬ8T^Wc?p^IgdEU/66 vXuq( UvTMqU5|K;:|x1E3#tMo[O(#AWIENDB`openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/icons/src/osg48-4.png0000644000175000017500000000140710005712307030004 0ustar albertoalbertoPNG  IHDR00,0PLTEyz Fw\9,\a4:-ER(9-DD4))R Fᰢ{"tRNS@fbKGDH pHYs  ~tIMEkPIDATxuk`ƅmopH*PR%.;  e pcO;+zb@]acŽ%by7XfV>ŢmnnG+&MiY`YibNj[o4w6FjR{^@?Zi HczNN@CDLȳl8`ҿ>sl krOZ%t8N]IПnt8Yx:%+;A?Xצ ^] FπA a4S-;Hz*YrrH%{tmUZzZ E 2O˘u9xDW]IgK&kK;K#C7tٹksdji&dGn|~&z&i,q !:pL u`WA ѸZ_()K>X Rko$ uQl{(ʻ-z^į2uN S%b"[ӋATs;Hq=憝e'K6B >w ŀa@IENDB`openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/icons/src/osg48-32.png0000644000175000017500000001023610005712307030065 0ustar albertoalbertoPNG  IHDR00WbKGDn ]] pHYs  ~tIME'o댠+IDATxyUŕǿuA7tliHBDA h !~b1hDq .h1c4D'HEEĸYdWuo_5 9nUթ:u >! ]ٖlΟ3zęٹA_dLHIWV?uDΤ3Jy.|]ɤ ʲF8PϨp[_s׃nXB!D'?4M 6g͍qE<Ig?@;LˤC;y{6/_7۷5z5{2 `RM5.aXH9%M5v:B `/k~k8݁UAu4WxhHe/l}PsCr2rU9иuV19@eiiqo.K34w#ݒv*y{g8@!͖#gHLiSG˔  v#6-x)^~ GA+@r_ {v .Odp@~BJ:F[6ᦫ5ȤzZ"Ҩߝ="Gy(ݙ"7)N4 aWhI8&KMQSRJow7ecˑ@@i@$ c$qj>L A*j%ɚ fjݸKb  !U`e4nDm& Q3CAg0(s$d2hAJ*B&G Mqz$)Z[;**m &2)6-3`QhaƣMh4t8c ~fML!Hd%Vή& Rh}AOϜ6gj2I:E( b򦉦Rds!sEb9=7J>VGQmzԆ̬2vܺa(8,{8]aFSH)V@@^HC SU=>"UI D"1dLEU:TWY0u: HJ6m#'c>ܚN(lr ,Ig(F }cO(#*)(:%#3 4䌜ddH8:QIi3ĩlvJJŽhkٮ O9l&*xnӰ3m$w 1+P5mE Ov fc,Kcۖ fSh(R94%IflH>QFЫ0{J%J+xVYxyR 搩Rh/CMA I4b[H$fMc@ٹ;ʴxT"ɐc0cc] L%ٜ=>I7F.Ȣ_@2ͮA`<{B6Վ*TXJu1e #}_8K8"BI 9|3SS95Jn;vYp%Lx=mƳ# 1e?zא,E\p0@"pp+HšLpjw2,ɘY:#[n.f ^L N0!PX)K՛%GTVu@`ZmUX::.H~ϯ]p6; UeX졹;:# ASW\udʚMc,3gNW oPB,䦹^4WR8"J_X{_͵^zyb}T/$.7LWTtz<* ),;SYZC)LREՄ ^})PƖhlJaYFm dŊ/p=ף*D;\HfxyTiՔzc~Pz\nO]T.Q5Os9{39{5ӎH9RUE w/[4)E+kW3Β5{v9h"?dZ[;Xu^x~pxĦ.~7B|~/sԲ+ 9:%lY㫼ЉDE{W=mDU+>< Ϊ G1], }! GG"}D2CQGՄ2~7n׋i>@k(==aTc=k*JnTQ]7>xZ=ODeps? C2ȓv΃nP**~_S'RȖ }VHL >uV}03Bɤwv/«k'.zO٦}Gv.ꌶ.a V7R~V]O"ɪ _N{]˿0wy`s[˕>1k 홶fMKUƑCcEDĺqO_z_+R589k%wmC?Ou>ho=AU+-.4\Vl(70!!1# /"/0nWl&_%""$-"NqVl&b:6""# 2-!!6tVi'f, 2:2 %:?DEEC669uV\'^ DETY\( %OЙi\(SԪp\c*SպV vYD- ѐOp=" FO H湿: #5$0Sǽy}$   2.-:Ӊy}z|Q $ ;ŀyz{x{UF,,%H{xy}xx|ןM]{xz{xx|}zzz|}xxxyƅ}zzxy{xxzzy}|zzzzz}xxxxzxxxxxxxxxyyxxxxxxxxxxzxxxxxxxx|yxxxxzzz}?????( @= =><6;7:-%6$=,:%!+5)43,4532<1:<34:9C EBHAKAMF%@$%K!"B%,T$%W((Z0/A-2\/0O9;`34 J, N1K4S9S='I9z6 z9y:JMR*RU&ZS#ZX*_\3VQfK.`O-fS,a\-o^5`_-^a9^e8deDJO_IMNCTDKP@QU\^^iCBvWV|WXI`^LcmRrcCmtSeyAvthomhgddprn|y{~r5r3u:__|E}Hmnssyw|}@C$K+P+P=^EgKhHiSr[uWv[xa{LMSS_abijoySwmyjx  # /&40>4ABNJVQ]ZdYdeojsktt}Jqfhhuxs|_il}y~}ıȶǸͽ˻˯̳̺ӽĩʱѻp|qmygrf_{ih`v_fea# ]t\n-f$v[_k,,Ic\[_-,jFB[[.dNP94HSGu[-lR3@</~7[},`522;C"D8KZw-%'''1:<42\t.+'''*+ 005ste+*'( ))Dzrh# 64 +>>A==T_oVO_qtY Xv> W? I5̋( 506͍U5  QЈ۪MLbЊ·Ϣ????( ;;=<9 4+&;,*'5&+5/55*9536<3D B D AD CJL@%(Y..G25 M0F1D2+C:&L:IoUx}ael{T O}vjDin,.*_kEfHBgpuhCFA??@IG??(0` %D}[1ʵ/zNIeu[tXQk0R<\cwGΠc-C_E{D8Zct@`hh2}Q1Q}y>6Ycr:}Nư%Vp+"{Fy99[~s8wD⬓i[@^G|Dx9Srñu;w>T~Da,M{>zMk(!{F z8{@Sr5u>f`y*}KPw= z7#HѶar5s8Ps(*Mz<z6'La89kIJ\89A@ CM!"X01Y12f@@stpr5r4wC嬔ni2S,$I z7z6/S||CBB C C E E E D D D C B BoLLvr5r3t;]}Zs,}Ljy=z6{6%KY01>YDDB! CC D E D D D D D D D D C Hqr5r4s5M槐f?ƶ.vK1Sx8{6{6DӽGA G35QRY<D D D D D D D D D D D D D D Cno^s4s3s3v?^ZWn*~K y7{6{6 y8òHC :IU[;JM9C D D D D D D D D D D D D D D A {|yCs4s3s3s7\eF_ |F{6{6{6@bO !D C A24Gfn0^Z4>8<D D D D D C C D D D E D D A?#@§s8s3s3s3p3=E "\s3s3s3p=OS*Y\#UX+NLbWVǪr7s3{L3Tw: z7vrNOD C ;! M= L3 O4 N2R8TA&^Z(Z^4ac6,'A D D D D D D D D D A -2/ROQO$RO>/.v>s3yKPo w:y9̴g==D A5D: K. I* J+ J+ N/W<\MYP2`_B? *93ULTK&VU9-.Is3yKNnH x9z=KD >1N@ N2 K- J, J. Q6T:!T@)Bcs3yKs?uz6FHD @ 9A6W@ P3 N4R:O5&L C D D D D D D C A @ A B /"TC N6 O3TBEcmys4yHڶt>u{61Vc89D @ 3$#bO_IU?U?"?,2 A D D D D D D D C ; 6/%3uz6CdlFGC :7,"-TC+aN/XI/+!; B D D D D D D D C :0B3#fN*s_0xf7zm4q#v`iOiOkSXӾr6zDț.t=u z7oz{8 8;.899 8? D D D D D D D D D A @@95ug/ymDR\c]L`Cew}u;zDț.t=u y8˱ú65,/B08>AAD D D D D D D D D E? [blyuNzEț.(Ly:gjf*%=D0 EB D E D E D D D D D D ? r{Dܽ68Y6ZG=?9 P7"C C D D D D D D D D D D A ndm˼r5s4?;[~w*:3-6)9 C D D D D D D D D D D C Bnsu?r4?Ph=qkZD):*9C D D D D D D D D D D B B'1jxB-5H7;SZgsr6?)gVZ@+8(7A D D D D D D E D D ? ?;@J_i6*4A5:8++:.,JWY[?ً&ZIH1$C./&:= B D D D D D D > 4433ZU*:2-<1*M?-F<`mg?=F 0<*,9pzý$N<H4C1-!1+"> D D D D D B 82.&/YIZD\E `Kzmv7C"/1<ݵiq/HS@K{-".P\Wnh$($*B>/52;B B C C B ? <-$1+"(6)A.1eO@K(#!/8Bb S]2&3$ $GSttuIDCL--a>=g?AHHA 86;3I\Q6C" ))6^gy 2?n!/  ,aktTTa`=I#!(4&! .BMa`jEOc-! &6AWa-7*7&"%2DON4?FQ["1! ':DjrR]%-:(4?K2??????( @ )L7?μ`TBX)$ 1uMPd}xRi# */QTrxPoO.3mJ:{CRq|HЄoM^-&g@f!HhȶJUaT>)"C/%~I{?ʱ{D~IpX;?^Ty>+P˯nn`uLcm&ZS'KA6C C D D D D D D NCTSey_IMSs2q9-Na {8HiLC D&.CmtYN,a\0RQ:C D D D D D D JMRr3s<%}Hb y7smnC @9JKWIWJ*_\-^a30.A D D D D D D A-29^e*RU\^^ѻr5xC.Qe x8Ҽ`34B .7-K2 M0 O3WF#ZX5QP>D D D D D D 9"HDRN4:9w C D D D D D C F%jxddpmyıdL#*-fS)4%7A B D D D D =@QU424563>C@qeV*EJyAQ[ZdJ6=,,#;D D D C 71KAP>"VD[ev|璇 $f,5r .%4gphom?JH=#"T&'V&'DA 8' 2<1RrcCO(,95;-8 GO2#2$2@}˻vWViCBywQ]')?Kk4948Cd*!%3oy3A %'2̘-4"3 '}<+9!!)8LYu~}U`1?$ #1CNe 0 15k-7n#2 )"-_ ?H-,9#  "05=E +(2P /! )7As2%,6-;%3$~D6?(  @,7.!H,Cjn[=X c9};tH,(   GěɮssoHIuQRnnӾ}GJ>+>$X9Lz9ĨG25AD D D D Ҿu8wMx#IAdC;Z\4+&C C D D I:='/`1>훡ysreeY..ie^¿DP.9Њ4 M+ղ-<7E#1e1 &/\&#'sG!.׭(նM"??openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/icons/osg_icon.rc0000644000175000017500000000004510571027442027534 0ustar albertoalbertoOSG_ICON ICON DISCARDABLE "osg.ico" openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/OpenSceneGraphVersionInfo.rc.in0000644000175000017500000000224411553272246032261 0ustar albertoalberto1 VERSIONINFO FILEVERSION ${OPENSCENEGRAPH_MAJOR_VERSION}, ${OPENSCENEGRAPH_MINOR_VERSION}, ${OPENSCENEGRAPH_PATCH_VERSION}, ${OPENSCENEGRAPH_SOVERSION} PRODUCTVERSION ${OPENSCENEGRAPH_MAJOR_VERSION}, ${OPENSCENEGRAPH_MINOR_VERSION}, ${OPENSCENEGRAPH_PATCH_VERSION}, ${OPENSCENEGRAPH_SOVERSION} FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x4L FILETYPE 0x0L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "OpenSceneGraph Binary" VALUE "FileVersion", "${OPENSCENEGRAPH_MAJOR_VERSION}, ${OPENSCENEGRAPH_MINOR_VERSION}, ${OPENSCENEGRAPH_PATCH_VERSION}, ${OPENSCENEGRAPH_SOVERSION}" VALUE "InternalName", "OSG" VALUE "LegalCopyright", "Copyright (C) 2009" VALUE "OriginalFilename", "" VALUE "ProductName", "OpenSceneGraph" VALUE "ProductVersion", "${OPENSCENEGRAPH_MAJOR_VERSION}, ${OPENSCENEGRAPH_MINOR_VERSION}, ${OPENSCENEGRAPH_PATCH_VERSION}, ${OPENSCENEGRAPH_SOVERSION}" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/collect_mangled_names.js0000644000175000017500000000330310745100675031133 0ustar albertoalberto/* collect_mangled_names - Copyright (C) 2006 Joran Jessurun * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. * * Made by Joran Jessurun (A.J.Jessurun@tue.nl) */ var dumpbin="dumpbin"; var fso=WScript.createObject("Scripting.FileSystemObject"); var ForReading=1; var ForWriting=2; var shell=WScript.createObject("WScript.Shell"); function process(file) { WScript.echo("Processing: "+file); var txt=""; var exec=shell.exec(dumpbin+' /linkermember:1 "'+file+'"'); while(!exec.stdOut.atEndOfStream) { var line=exec.stdOut.readLine(); if(/3V\?\$RegisterReaderWriterProxy/.test(line) || /3VRegisterDotOsgWrapperProxy/.test(line)) { txt+=line.substr(10)+"\n"; } } while(exec.status!=1) WScript.sleep(100); if(txt!="") { file=file.replace(/\.lib$/m,".sym"); var f=fso.openTextFile(file,ForWriting,true); f.write(txt); f.close(); WScript.echo("Created: "+file); } } WScript.echo("Collecting mangled names"); var files=new Enumerator(fso.getFolder("..\\lib\\win32").Files); for(;!files.atEnd();files.moveNext()) { if(/_s\.lib$/.test(files.item())) { process(""+files.item()); } } openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/VisualStudio_Syntax_Highlighting.txt0000644000175000017500000000222011553272246033524 0ustar albertoalbertoMapping extensionless header files to C++ in Visual Studio ============================================================================= Previous versions of the OSG included registry files which enabled syntax highlighting for OSG's extensionless headers in Visual Studio. These are not needed anymore, because starting with Visual Studio 2002 (7.0), there is a setting that will map extensionless files to a certain language in the options. This also works for the Express Editions. 1. Go to Tools-Options. 2. Open the Text Editor section, and click on File Extension. 3. At the bottom of the window, check the Map Extensionless Files To checkbox, and select Microsoft Visual C++ in the list to the right. Note that if you use this feature for other languages, you will have to change it when needed. If that is too cumbersome you may want to generate the registry files and do it that way instead. Please see the .reg files in previous versions of OSG in the VisualStudio directory for a guide on how to do that (hint: check the location of the registry key to make sure the added values end up in the right place for your version of Visual Studio). openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/collect_mangled_names.bat0000644000175000017500000000030010745100675031257 0ustar albertoalberto@echo off rem Insert below the path to the installed visual studio vcvars32.bat call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" cscript collect_mangled_names.js openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/osgShell.bat0000644000175000017500000000117411143042624026542 0ustar albertoalberto@echo off REM This script provides a commandline shell properly configured to run OSG REM executables directly from the OpenThreads/OpenSceneGraph source REM trees. REM mew 2004-07-16 cd ..\.. set PATH=%CD%\OpenThreads\bin\win32;%CD%\bin;%CD%\3rdParty\bin;%PATH% set OSG_FILE_PATH=%CD%\OpenSceneGraph-Data;%OSG_FILE_PATH% REM uncomment one of these for your desired notify level... rem set OSG_NOTIFY_LEVEL=ALWAYS rem set OSG_NOTIFY_LEVEL=FATAL rem set OSG_NOTIFY_LEVEL=WARN rem set OSG_NOTIFY_LEVEL=NOTICE rem set OSG_NOTIFY_LEVEL=DEBUG rem set OSG_NOTIFY_LEVEL=DEBUG_FP rem set OSG_NOTIFY_LEVEL=INFO TITLE osgShell %COMSPEC% /K openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Windows/OpenThreadsVersionInfo.rc.in0000644000175000017500000000215611553272246031636 0ustar albertoalberto1 VERSIONINFO FILEVERSION ${OPENTHREADS_MAJOR_VERSION}, ${OPENTHREADS_MINOR_VERSION}, ${OPENTHREADS_PATCH_VERSION}, ${OPENTHREADS_SOVERSION} PRODUCTVERSION ${OPENTHREADS_MAJOR_VERSION}, ${OPENTHREADS_MINOR_VERSION}, ${OPENTHREADS_PATCH_VERSION}, ${OPENTHREADS_SOVERSION} FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x4L FILETYPE 0x0L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "OPENTHREADS Binary" VALUE "FileVersion", "${OPENTHREADS_MAJOR_VERSION}, ${OPENTHREADS_MINOR_VERSION}, ${OPENTHREADS_PATCH_VERSION}, ${OPENTHREADS_SOVERSION}" VALUE "InternalName", "OSG" VALUE "LegalCopyright", "Copyright (C) 2009" VALUE "OriginalFilename", "" VALUE "ProductName", "OPENTHREADS" VALUE "ProductVersion", "${OPENTHREADS_MAJOR_VERSION}, ${OPENTHREADS_MINOR_VERSION}, ${OPENTHREADS_PATCH_VERSION}, ${OPENTHREADS_SOVERSION}" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Android/0000755000175000017500000000000012674261223024225 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Android/Application.mk.master.in0000644000175000017500000000064512444516150030722 0ustar albertoalberto#ANDROID APPLICATION MAKEFILE APP_BUILD_SCRIPT := $(call my-dir)/Android.mk APP_PROJECT_PATH := $(call my-dir) APP_OPTIM := ${ANDROID_RELEASE_OPTIM} APP_PLATFORM := android-${ANDROID_PLATFORM} APP_STL := ${ANDROID_STL} APP_CPPFLAGS := -fexceptions -frtti #APP_CPPFLAGS := -Os -mthumb-interwork -fno-short-enums #APP_CPPFLAGS := -Wl,--no-undefined APP_ABI := ${ANDROID_ABI} APP_MODULES := $ENV{AND_OSG_LIB_NAMES} openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Android/AndroidManifest.xml.master.in0000644000175000017500000000041312106734527031715 0ustar albertoalberto openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Android/Android.mk.src.in0000644000175000017500000000020611553272246027331 0ustar albertoalberto#ANDROID makefile in src SRC_ROOT := $(call my-dir) LOCAL_PATH := $(call my-dir) SRC_ROOT := $(LOCAL_PATH) $ENV{AND_OSG_LIB_PATHS} openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Android/Android.mk.serializers.in0000644000175000017500000000117511553272246031104 0ustar albertoalberto#ANDROID makefile in src SERIALIZER_ROOT := $(call my-dir) LOCAL_PATH := $(call my-dir) SERIALIZER_ROOT := $(LOCAL_PATH) #include $(call all-subdir-makefiles) include $(SERIALIZER_ROOT)/osg/Android.mk include $(SERIALIZER_ROOT)/osgAnimation/Android.mk include $(SERIALIZER_ROOT)/osgFX/Android.mk include $(SERIALIZER_ROOT)/osgManipulator/Android.mk include $(SERIALIZER_ROOT)/osgParticle/Android.mk include $(SERIALIZER_ROOT)/osgShadow/Android.mk include $(SERIALIZER_ROOT)/osgSim/Android.mk include $(SERIALIZER_ROOT)/osgTerrain/Android.mk include $(SERIALIZER_ROOT)/osgText/Android.mk include $(SERIALIZER_ROOT)/osgVolume/Android.mk openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Android/Android.mk.master.in0000644000175000017500000000033311553272246030036 0ustar albertoalberto#ANDROID ROOT MAKEFILE OSG_ROOT := $(call my-dir) LOCAL_PATH := $(call my-dir) OSG_ROOT := $(LOCAL_PATH) OSGInclude := $(OSG_ROOT)/include/OpenThreads \ $(OSG_ROOT)/include/osg include src/Android.mk openscenegraph-3.2.3/OpenSceneGraph/PlatformSpecifics/Android/Android.mk.modules.in0000644000175000017500000000134711743757722030231 0ustar albertoalberto#ANDROID makefile ${MODULE_NAME} LOCAL_PATH := ${MODULE_DIR} include $(CLEAR_VARS) ifeq (${ANDROID_OPTIM_NEON},true) ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) LOCAL_ARM_NEON := true endif endif ifeq (${ANDROID_OPTIM_ARM32},true) LOCAL_ARM_MODE := arm endif LOCAL_CPP_EXTENSION := ${CPP_EXTENSION} LOCAL_LDLIBS := ${MODULE_LIBS_FLAGS} LOCAL_MODULE := ${MODULE_NAME} LOCAL_SRC_FILES := ${MODULE_SOURCES} LOCAL_C_INCLUDES := ${MODULE_INCLUDES} LOCAL_CFLAGS := ${MODULE_FLAGS_C} LOCAL_CPPFLAGS := ${MODULE_FLAGS_CPP} LOCAL_SHARED_LIBRARIES := ${MODULE_LIBS_SHARED} LOCAL_STATIC_LIBRARIES := ${MODULE_LIBS_STATIC} include ${MODULE_BUILD_TYPE} openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/0000755000175000017500000000000012674261223021541 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/CMakeModules/Find3rdPartyDependencies.cmake0000644000175000017500000001570312173411731027364 0ustar albertoalberto################################################################################################ # this Macro find a generic dependency, handling debug suffix # all the paramenter are required, in case of lists, use "" in calling ################################################################################################ MACRO(FIND_DEPENDENCY DEPNAME INCLUDEFILE LIBRARY_NAMES_BASE SEARCHPATHLIST DEBUGSUFFIX EXSUFFIX) MESSAGE(STATUS "searching ${DEPNAME} -->${INCLUDEFILE}<-->${LIBRARY_NAMES_BASE}<-->${SEARCHPATHLIST}<--") SET(MY_PATH_INCLUDE ) SET(MY_PATH_LIB ) FOREACH( MYPATH ${SEARCHPATHLIST} ) SET(MY_PATH_INCLUDE ${MY_PATH_INCLUDE} ${MYPATH}/include) SET(MY_PATH_LIB ${MY_PATH_LIB} ${MYPATH}/lib) ENDFOREACH( MYPATH ${SEARCHPATHLIST} ) FIND_PATH("${DEPNAME}_INCLUDE_DIR" ${INCLUDEFILE} ${MY_PATH_INCLUDE} NO_DEFAULT_PATH ) MARK_AS_ADVANCED("${DEPNAME}_INCLUDE_DIR") #MESSAGE( " ${DEPNAME}_INCLUDE_DIR --> ${${DEPNAME}_INCLUDE_DIR}<--") SET(LIBRARY_NAMES "") FOREACH(LIBNAME ${LIBRARY_NAMES_BASE}) LIST(APPEND LIBRARY_NAMES "${LIBNAME}${EXSUFFIX}") ENDFOREACH(LIBNAME) FIND_LIBRARY("${DEPNAME}_LIBRARY" NAMES ${LIBRARY_NAMES} PATHS ${MY_PATH_LIB} NO_DEFAULT_PATH ) SET(LIBRARY_NAMES_DEBUG "") FOREACH(LIBNAME ${LIBRARY_NAMES_BASE}) LIST(APPEND LIBRARY_NAMES_DEBUG "${LIBNAME}${DEBUGSUFFIX}${EXSUFFIX}") ENDFOREACH(LIBNAME) FIND_LIBRARY("${DEPNAME}_LIBRARY_DEBUG" NAMES ${LIBRARY_NAMES_DEBUG} PATHS ${MY_PATH_LIB} NO_DEFAULT_PATH ) MARK_AS_ADVANCED("${DEPNAME}_LIBRARY") #MESSAGE( " ${DEPNAME}_LIBRARY --> ${${DEPNAME}_LIBRARY}<--") SET( ${DEPNAME}_FOUND "NO" ) IF(${DEPNAME}_INCLUDE_DIR AND ${DEPNAME}_LIBRARY) SET( ${DEPNAME}_FOUND "YES" ) IF(NOT ${DEPNAME}_LIBRARY_DEBUG) MESSAGE("-- Warning Debug ${DEPNAME} not found, using: ${${DEPNAME}_LIBRARY}") SET(${DEPNAME}_LIBRARY_DEBUG "${${DEPNAME}_LIBRARY}") ENDIF(NOT ${DEPNAME}_LIBRARY_DEBUG) ENDIF(${DEPNAME}_INCLUDE_DIR AND ${DEPNAME}_LIBRARY) ENDMACRO(FIND_DEPENDENCY DEPNAME INCLUDEFILE LIBRARY_NAMES_BASE SEARCHPATHLIST DEBUGSUFFIX) ################################################################################################ # this Macro is tailored to Mike and Torbens dependencies ################################################################################################ MACRO(SEARCH_3RDPARTY OSG_3RDPARTY_BIN) FIND_DEPENDENCY(TIFF tiff.h libtiff ${OSG_3RDPARTY_BIN} "D" "_i") FIND_DEPENDENCY(FREETYPE ft2build.h "freetype;freetype2311MT;freetype234;freetype234MT;freetype235;freetype237;freetype238;freetype244;freetype250;" ${OSG_3RDPARTY_BIN} "d" "") IF(FREETYPE_FOUND) #forcing subsequent FindFreeType stuff to not search for other variables.... kind of a hack SET(FREETYPE_INCLUDE_DIR_ft2build ${FREETYPE_INCLUDE_DIR} CACHE PATH "" FORCE) SET(FREETYPE_INCLUDE_DIR_freetype2 ${FREETYPE_INCLUDE_DIR} CACHE PATH "" FORCE) MARK_AS_ADVANCED(FREETYPE_INCLUDE_DIR_ft2build FREETYPE_INCLUDE_DIR_freetype2) SET(FREETYPE_INCLUDE_DIRS "${FREETYPE_INCLUDE_DIR_ft2build};${FREETYPE_INCLUDE_DIR_freetype2}") ENDIF(FREETYPE_FOUND) FIND_DEPENDENCY(CURL curl/curl.h "libcurl;curllib" ${OSG_3RDPARTY_BIN} "D" "") FIND_DEPENDENCY(JPEG jpeglib.h "libjpeg;jpeg" ${OSG_3RDPARTY_BIN} "D" "") FIND_DEPENDENCY(GDAL gdal.h "gdal;gdal16" ${OSG_3RDPARTY_BIN} "d" "_i") FIND_DEPENDENCY(GLUT GL/glut.h glut32 ${OSG_3RDPARTY_BIN} "D" "") IF(GLUT_FOUND) #forcing subsequent FindGlut stuff to not search for other variables.... kind of a hack SET(GLUT_glut_LIBRARY ${GLUT_LIBRARY} CACHE FILEPATH "") MARK_AS_ADVANCED(GLUT_glut_LIBRARY) ENDIF(GLUT_FOUND) FIND_DEPENDENCY(GIFLIB gif_lib.h "ungif;libungif;giflib" ${OSG_3RDPARTY_BIN} "D" "") FIND_DEPENDENCY(ZLIB zlib.h "z;zlib;zlib1" ${OSG_3RDPARTY_BIN} "D" "") IF(ZLIB_FOUND) FIND_DEPENDENCY(PNG png.h "libpng;libpng13;libpng15;libpng16" ${OSG_3RDPARTY_BIN} "D" "") IF(PNG_FOUND) #forcing subsequent FindPNG stuff to not search for other variables.... kind of a hack SET(PNG_PNG_INCLUDE_DIR ${PNG_INCLUDE_DIR} CACHE FILEPATH "") MARK_AS_ADVANCED(PNG_PNG_INCLUDE_DIR) ENDIF(PNG_FOUND) ENDIF(ZLIB_FOUND) FIND_DEPENDENCY(LIBXML2 libxml2 "libxml2" ${OSG_3RDPARTY_BIN} "D" "") IF(LIBXML2_FOUND) # The CMAKE find libxml module uses LIBXML2_LIBRARIES -> fill it.... kind of a hack SET(LIBXML2_LIBRARIES ${LIBXML2_LIBRARY} CACHE FILEPATH "" FORCE) SET(LIBXML2_XMLLINT_EXECUTABLE ${OSG_3RDPARTY_BIN}/bin/xmllint.exe CACHE FILEPATH "Path to xmllint executable" FORCE) ENDIF(LIBXML2_FOUND) #FIND_DEPENDENCY(DEPNAME INCLUDEFILE LIBRARY_NAMES_BASE SEARCHPATHLIST DEBUGSUFFIX EXSUFFIX) FIND_Package(NVTT) #luigi#INCLUDE(FindOSGDepends.cmake) ENDMACRO(SEARCH_3RDPARTY OSG_3RDPARTY_BIN) ################################################################################################ # this is code for handling optional 3RDPARTY usage ################################################################################################ OPTION(USE_3RDPARTY_BIN "Set to ON to use Mike prebuilt dependencies situated side of OpenSceneGraph source. Use OFF for avoiding." ON) IF(USE_3RDPARTY_BIN) # Check Architecture IF( CMAKE_SIZEOF_VOID_P EQUAL 4 ) MESSAGE( STATUS "32 bit architecture detected" ) SET(DESTINATION_ARCH "x86") ENDIF() IF( CMAKE_SIZEOF_VOID_P EQUAL 8 ) MESSAGE( STATUS "64 bit architecture detected" ) SET(DESTINATION_ARCH "x64") ENDIF() GET_FILENAME_COMPONENT(PARENT_DIR ${PROJECT_SOURCE_DIR} PATH) SET(TEST_3RDPARTY_DIR "${PARENT_DIR}/3rdparty") IF(NOT EXISTS ${TEST_3RDPARTY_DIR}) SET(3RDPARTY_DIR_BY_ENV $ENV{OSG_3RDPARTY_DIR}) IF(3RDPARTY_DIR_BY_ENV) MESSAGE( STATUS "3rdParty-Package ENV variable found:${3RDPARTY_DIR_BY_ENV}/${DESTINATION_ARCH}" ) SET(TEST_3RDPARTY_DIR "${3RDPARTY_DIR_BY_ENV}/${DESTINATION_ARCH}") ELSEIF(MSVC71) SET(TEST_3RDPARTY_DIR "${PARENT_DIR}/3rdParty_win32binaries_vs71") ELSEIF(MSVC80) SET(TEST_3RDPARTY_DIR "${PARENT_DIR}/3rdParty_win32binaries_vs80sp1") ELSEIF(MSVC90) SET(TEST_3RDPARTY_DIR "${PARENT_DIR}/3rdParty_win32binaries_vs90sp1") ENDIF() ENDIF(NOT EXISTS ${TEST_3RDPARTY_DIR}) SET(ACTUAL_3RDPARTY_DIR "${TEST_3RDPARTY_DIR}" CACHE PATH "Location of 3rdparty dependencies") SET(ACTUAL_3DPARTY_DIR "${ACTUAL_3RDPARTY_DIR}") # kept for backcompatibility IF(EXISTS ${ACTUAL_3RDPARTY_DIR}) SET (3rdPartyRoot ${ACTUAL_3RDPARTY_DIR}) SEARCH_3RDPARTY(${ACTUAL_3RDPARTY_DIR}) ENDIF(EXISTS ${ACTUAL_3RDPARTY_DIR}) ENDIF(USE_3RDPARTY_BIN) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindAVFoundation.cmake0000644000175000017500000000232512434646657025717 0ustar albertoalberto# Locate Apple AVFoundation (next-generation QTKit) # This module defines # AV_FOUNDATION_LIBRARY # AV_FOUNDATION_FOUND, if false, do not try to link to gdal # # $AV_FOUNDATION_DIR is an environment variable that would # correspond to the ./configure --prefix=$AV_FOUNDATION_DIR # # Created by Stephan Maximilian Huber IF(APPLE) FIND_LIBRARY(AV_FOUNDATION_LIBRARY AVFoundation) ENDIF() SET(AV_FOUNDATION_FOUND "NO") IF(AV_FOUNDATION_LIBRARY) SET(AV_FOUNDATION_FOUND "YES") ENDIF() IF(OSG_BUILD_PLATFORM_IPHONE OR OSG_BUILD_PLATFORM_IPHONE_SIMULATOR) # AVFoundation exists ON iOS, too -- good support for SDK 6.0 and greater IF(${IPHONE_SDKVER} LESS "6.0") SET(AV_FOUNDATION_FOUND "NO") ELSE() SET(AV_FOUNDATION_FOUND "YES") ENDIF() ELSE() IF(APPLE) # AVFoundation exists since 10.7, but only 10.8 has all features necessary for OSG # so check the SDK-setting IF(${OSG_OSX_SDK_NAME} STREQUAL "macosx10.8" OR ${OSG_OSX_SDK_NAME} STREQUAL "macosx10.9" OR ${OSG_OSX_SDK_NAME} STREQUAL "macosx10.10") # nothing special here ;-) ELSE() MESSAGE("AVFoundation disabled for SDK < 10.8") SET(AV_FOUNDATION_FOUND "NO") ENDIF() ENDIF() ENDIF() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindGIFLIB.cmake0000644000175000017500000000265711204232725024303 0ustar albertoalberto# This module defines # GIFLIB_LIBRARY # GIFLIB_FOUND, if false, do not try to link # GIFLIB_INCLUDE_DIR, where to find the headers # # $GIFLIB_DIR is an environment variable that would # correspond to the ./configure --prefix=$GIFLIB_DIR # # Created by Eric Wing. FIND_PATH(GIFLIB_INCLUDE_DIR gif_lib.h PATHS $ENV{GIFLIB_DIR} NO_DEFAULT_PATH PATH_SUFFIXES include ) FIND_PATH(GIFLIB_INCLUDE_DIR gif_lib.h PATHS ${CMAKE_PREFIX_PATH} # Unofficial: We are proposing this. NO_DEFAULT_PATH PATH_SUFFIXES include ) FIND_PATH(GIFLIB_INCLUDE_DIR gif_lib.h PATHS ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include ) FIND_LIBRARY(GIFLIB_LIBRARY NAMES gif ungif libgif libungif PATHS $ENV{GIFLIB_DIR} NO_DEFAULT_PATH PATH_SUFFIXES lib64 lib ) FIND_LIBRARY(GIFLIB_LIBRARY NAMES gif ungif libgif libungif PATHS ${CMAKE_PREFIX_PATH} # Unofficial: We are proposing this. NO_DEFAULT_PATH PATH_SUFFIXES lib64 lib ) FIND_LIBRARY(GIFLIB_LIBRARY NAMES gif ungif libgif libungif PATHS ~/Library/Frameworks /Library/Frameworks /usr/local /usr /sw /opt/local /opt/csw /opt /usr/freeware PATH_SUFFIXES lib64 lib ) SET(GIFLIB_FOUND "NO") IF(GIFLIB_LIBRARY AND GIFLIB_INCLUDE_DIR) SET(GIFLIB_FOUND "YES") ENDIF(GIFLIB_LIBRARY AND GIFLIB_INCLUDE_DIR) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindFBX.cmake0000644000175000017500000001061412500326371023757 0ustar albertoalberto# Locate FBX # This module defines: # FBX_INCLUDE_DIR, where to find the headers # # FBX_LIBRARY, FBX_LIBRARY_DEBUG # FBX_FOUND # # $FBX_DIR is an environment variable that would # correspond to the ./configure --prefix=$FBX_DIR IF(APPLE) SET(FBX_LIBDIR "gcc4/ub") ELSEIF(CMAKE_COMPILER_IS_GNUCXX) SET(FBX_LIBDIR "gcc4") ELSEIF(MSVC80) SET(FBX_LIBDIR "vs2005") ELSEIF(MSVC90) SET(FBX_LIBDIR "vs2008") ELSEIF(MSVC10) SET(FBX_LIBDIR "vs2010") ELSEIF(MSVC11) SET(FBX_LIBDIR "vs2012") ELSEIF(MSVC12 OR MSVC_VERSION>1800) SET(FBX_LIBDIR "vs2013") ENDIF() IF(APPLE) # do nothing ELSEIF(CMAKE_CL_64) SET(FBX_LIBDIR ${FBX_LIBDIR}/x64) ELSEIF(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_SIZEOF_VOID_P EQUAL 8) SET(FBX_LIBDIR ${FBX_LIBDIR}/x64) ELSE() SET(FBX_LIBDIR ${FBX_LIBDIR}/x86) ENDIF() #try to use 2015.1 or 2014.2 version IF(APPLE) SET(FBX_LIBNAME "libfbxsdk") ELSEIF(CMAKE_COMPILER_IS_GNUCXX) SET(FBX_LIBNAME "fbxsdk") ELSE() SET(FBX_LIBNAME "libfbxsdk-md") ENDIF() SET(FBX_LIBNAME_DEBUG ${FBX_LIBNAME}d) SET( FBX_SEARCH_PATHS $ENV{FBX_DIR} "$ENV{ProgramW6432}/Autodesk/FBX/FBX SDK/2015.1" "$ENV{PROGRAMFILES}/Autodesk/FBX/FBX SDK/2015.1" /Applications/Autodesk/FBXSDK20151 "$ENV{ProgramW6432}/Autodesk/FBX/FBX SDK/2014.2" "$ENV{PROGRAMFILES}/Autodesk/FBX/FBX SDK/2014.2" /Applications/Autodesk/FBXSDK20142 /Applications/Autodesk/FBXSDK20141 ) #I think the last line in the search path is an old typo, but let's search for 2014.1 anyway - LV # search for headers & debug/release libraries FIND_PATH(FBX_INCLUDE_DIR "fbxsdk.h" PATHS ${FBX_SEARCH_PATHS} PATH_SUFFIXES "include") FIND_LIBRARY( FBX_LIBRARY ${FBX_LIBNAME} PATHS ${FBX_SEARCH_PATHS} PATH_SUFFIXES "lib/${FBX_LIBDIR}/release" "lib/${FBX_LIBDIR}") #Once one of the calls succeeds the result variable will be set and stored in the cache so that no call will search again. #no debug d suffix, search in debug folder only FIND_LIBRARY( FBX_LIBRARY_DEBUG ${FBX_LIBNAME} PATHS ${FBX_SEARCH_PATHS} PATH_SUFFIXES "lib/${FBX_LIBDIR}/debug") FIND_LIBRARY( FBX_LIBRARY_DEBUG ${FBX_LIBNAME_DEBUG} PATHS ${FBX_SEARCH_PATHS} PATH_SUFFIXES "lib/${FBX_LIBDIR}") IF(FBX_LIBRARY AND FBX_LIBRARY_DEBUG AND FBX_INCLUDE_DIR) SET(FBX_FOUND "YES") ELSE() SET(FBX_FOUND "NO") ENDIF() IF(NOT FBX_FOUND) #try to use 2014.1 version IF(APPLE) SET(FBX_LIBNAME "fbxsdk-2014.1") ELSEIF(CMAKE_COMPILER_IS_GNUCXX) SET(FBX_LIBNAME "fbxsdk-2014.1") ELSE() SET(FBX_LIBNAME "fbxsdk-2014.1") ENDIF() SET(FBX_LIBNAME_DEBUG ${FBX_LIBNAME}d) SET( FBX_SEARCH_PATHS $ENV{FBX_DIR} $ENV{ProgramW6432}/Autodesk/FBX/FBX SDK/2014.1 $ENV{PROGRAMFILES}/Autodesk/FBX/FBX SDK/2014.1 /Applications/Autodesk/FBXSDK20141 ) # search for headers & debug/release libraries FIND_PATH(FBX_INCLUDE_DIR "fbxsdk.h" PATHS ${FBX_SEARCH_PATHS} PATH_SUFFIXES "include") FIND_LIBRARY( FBX_LIBRARY ${FBX_LIBNAME} PATHS ${FBX_SEARCH_PATHS} PATH_SUFFIXES "lib/${FBX_LIBDIR}") FIND_LIBRARY( FBX_LIBRARY_DEBUG ${FBX_LIBNAME_DEBUG} PATHS ${FBX_SEARCH_PATHS} PATH_SUFFIXES "lib/${FBX_LIBDIR}") IF(FBX_LIBRARY AND FBX_LIBRARY_DEBUG AND FBX_INCLUDE_DIR) SET(FBX_FOUND "YES") ELSE() SET(FBX_FOUND "NO") ENDIF() ENDIF() IF(NOT FBX_FOUND) #try to use 2013.3 version IF(APPLE) SET(FBX_LIBNAME "fbxsdk-2013.3-static") ELSEIF(CMAKE_COMPILER_IS_GNUCXX) SET(FBX_LIBNAME "fbxsdk-2013.3-static") ELSE() SET(FBX_LIBNAME "fbxsdk-2013.3-md") ENDIF() SET(FBX_LIBNAME_DEBUG ${FBX_LIBNAME}d) SET( FBX_SEARCH_PATHS $ENV{FBX_DIR} $ENV{ProgramW6432}/Autodesk/FBX/FBX SDK/2013.3 $ENV{PROGRAMFILES}/Autodesk/FBX/FBX SDK/2013.3 /Applications/Autodesk/FBXSDK20133 ) # search for headers & debug/release libraries FIND_PATH(FBX_INCLUDE_DIR "fbxsdk.h" PATHS ${FBX_SEARCH_PATHS} PATH_SUFFIXES "include") FIND_LIBRARY( FBX_LIBRARY ${FBX_LIBNAME} PATHS ${FBX_SEARCH_PATHS} PATH_SUFFIXES "lib/${FBX_LIBDIR}") FIND_LIBRARY( FBX_LIBRARY_DEBUG ${FBX_LIBNAME_DEBUG} PATHS ${FBX_SEARCH_PATHS} PATH_SUFFIXES "lib/${FBX_LIBDIR}") IF(FBX_LIBRARY AND FBX_LIBRARY_DEBUG AND FBX_INCLUDE_DIR) SET(FBX_FOUND "YES") ELSE() SET(FBX_FOUND "NO") ENDIF() ENDIF() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindAsio.cmake0000644000175000017500000000065712263027305024242 0ustar albertoalberto# Locate ASIO-headers (http://think-async.com/Asio) # This module defines # ASIO_FOUND, if false, do not try to link to gdal # ASIO_INCLUDE_DIR, where to find the headers # # Created by Stephan Maximilian Huber FIND_PATH(ASIO_INCLUDE_DIR NAMES asio.hpp PATHS /usr/include /usr/local/include ) SET(ASIO_FOUND "NO") FIND_PACKAGE( Boost 1.37 ) IF(Boost_FOUND AND ASIO_INCLUDE_DIR) SET(ASIO_FOUND "YES") ENDIF() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindOpenEXR.cmake0000644000175000017500000000427311553272246024634 0ustar albertoalberto# Locate OpenEXR # This module defines # OPENEXR_LIBRARY # OPENEXR_FOUND, if false, do not try to link to OpenEXR # OPENEXR_INCLUDE_DIR, where to find the headers # # $OPENEXR_DIR is an environment variable that would # correspond to the ./configure --prefix=$OPENEXR_DIR # # Created by Robert Osfield. FIND_PATH(OPENEXR_INCLUDE_DIR OpenEXR/ImfIO.h $ENV{OPENEXR_DIR}/include $ENV{OPENEXR_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include ) FIND_LIBRARY(OPENEXR_IlmIlf_LIBRARY NAMES IlmImf PATHS $ENV{OPENEXR_DIR}/lib $ENV{OPENEXR_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) FIND_LIBRARY(OPENEXR_IlmThread_LIBRARY NAMES IlmThread PATHS $ENV{OPENEXR_DIR}/lib $ENV{OPENEXR_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) FIND_LIBRARY(OPENEXR_Iex_LIBRARY NAMES Iex PATHS $ENV{OPENEXR_DIR}/lib $ENV{OPENEXR_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) FIND_LIBRARY(OPENEXR_Half_LIBRARY NAMES Half PATHS $ENV{OPENEXR_DIR}/lib $ENV{OPENEXR_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) SET(OPENEXR_FOUND "NO") IF(OPENEXR_INCLUDE_DIR AND OPENEXR_IlmIlf_LIBRARY AND OPENEXR_IlmThread_LIBRARY AND OPENEXR_Iex_LIBRARY AND OPENEXR_Half_LIBRARY) SET(OPENEXR_LIBRARIES ${OPENEXR_IlmIlf_LIBRARY} ${OPENEXR_IlmThread_LIBRARY} ${OPENEXR_Half_LIBRARY} ${OPENEXR_Iex_LIBRARY} ) SET(OPENEXR_FOUND "YES") ENDIF(OPENEXR_INCLUDE_DIR AND OPENEXR_IlmIlf_LIBRARY AND OPENEXR_IlmThread_LIBRARY AND OPENEXR_Iex_LIBRARY AND OPENEXR_Half_LIBRARY) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindAndroidNDK.cmake0000644000175000017500000000216711575722023025266 0ustar albertoalberto# Locate AndroidNDK # This module defines # ANDROID_NDK # ANDROID_FOUND, if false, do not try to use AndroidNDK # FIND_PATH(ANDROID_NDK ndk-build ${ANDROID_NDK} NO_DEFAULT_PATH ) IF(NOT ANDROID_NDK) FIND_PATH(ANDROID_NDK ndk-build $ENV{ANDROID_NDK} $ENV{ANDROID_ROOT} NO_DEFAULT_PATH ) ENDIF() IF(NOT ANDROID_NDK) FIND_PATH(ANDROID_NDK ndk-build # search for r5c ~/android-ndk-r5c ~/android_develop/android-ndk-r5c ~/ndk-r5c ~/android_develop/ndk-r5c # search for r5b ~/android-ndk-r5b ~/android_develop/android-ndk-r5b ~/ndk-r5b ~/android_develop/ndk-r5b # search for r5 ~/android-ndk-r5 ~/android_develop/android-ndk-r5 ~/ndk-r5 ~/android_develop/ndk-r5 # search for r4-crystax ~/android-ndk-r4-crystax ~/android_develop/android-ndk-r4-crystax ~/ndk-r4 ~/android_develop/ndk-r4 ) ENDIF() SET(ANDROID_FOUND "NO") IF(ANDROID_NDK) SET(ANDROID_FOUND "YES") MESSAGE(STATUS "Android NDK found in: ${ANDROID_NDK}") ENDIF(ANDROID_NDK) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/OsgCPack.cmake0000644000175000017500000001407611567665040024212 0ustar albertoalberto# This script sets up packaging targets for each "COMPONENT" as specified in INSTALL commands # # for each component a CPackConfig-.cmake is generated in the build tree # and a target is added to call cpack for it (e.g. package_openscenegaph # A target for generating a package with everything that gets INSTALLED is generated (package_openscenegraph-all) # A target for making all of the abaove packages is generated (package_ALL) # # package filenames are created on the form --[-]-[-static].tar.gz # ...where compiler optionally set using a cmake gui (OSG_CPACK_COMPILER). This script tries to guess compiler version for msvc generators # ...build_type matches CMAKE_BUILD_TYPE for all generators but the msvc ones # resolve architecture. The reason i "change" i686 to i386 is that debian packages # require i386 so this is for the future IF("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "i686") SET(SYSTEM_ARCH "i386") ELSE() SET(SYSTEM_ARCH ${CMAKE_SYSTEM_PROCESSOR}) ENDIF() # set a default system name - use CMake setting (Linux|Windows|...) SET(SYSTEM_NAME ${CMAKE_SYSTEM_NAME}) #message(STATUS "CMAKE_SYSTEM_NAME ${CMAKE_SYSTEM_NAME}") #message(STATUS "CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}") # for msvc the SYSTEM_NAME is set win32/64 instead of "Windows" IF(MSVC) IF(CMAKE_CL_64) SET(SYSTEM_NAME "win64") ELSE() SET(SYSTEM_NAME "win32") ENDIF() ENDIF() # Guess the compiler (is this desired for other platforms than windows?) IF(NOT DEFINED OSG_CPACK_COMPILER) INCLUDE(OsgDetermineCompiler) ENDIF() # expose the compiler setting to the user SET(OSG_CPACK_COMPILER "${OSG_COMPILER}" CACHE STRING "This ia short string (vc90, vc80sp1, gcc-4.3, ...) describing your compiler. The string is used for creating package filenames") IF(OSG_CPACK_COMPILER) SET(OSG_CPACK_SYSTEM_SPEC_STRING ${SYSTEM_NAME}-${SYSTEM_ARCH}-${OSG_CPACK_COMPILER}) ELSE() SET(OSG_CPACK_SYSTEM_SPEC_STRING ${SYSTEM_NAME}-${SYSTEM_ARCH}) ENDIF() ## variables that apply to all packages SET(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${OPENSCENEGRAPH_VERSION}") # these goes for all platforms. Setting these stops the CPack.cmake script from generating options about other package compression formats (.z .tz, etc.) IF(WIN32) SET(CPACK_GENERATOR "ZIP" CACHE STRING "CPack package generator type (i.e ZIP,NSIS,TGZ,DEB,RPM, -- see CPack for valid stypes") ELSE() SET(CPACK_GENERATOR "TGZ" CACHE STRING "CPack package generator type (i.e ZIP,NSIS,TGZ,DEB,RPM, -- see CPack for valid stypes") ENDIF() SET(CPACK_SOURCE_GENERATOR "TGZ") # for ms visual studio we use it's internally defined variable to get the configuration (debug,release, ...) IF(MSVC_IDE) SET(OSG_CPACK_CONFIGURATION "$(OutDir)") SET(PACKAGE_TARGET_PREFIX "Package ") ELSE() # on un*x an empty CMAKE_BUILD_TYPE means release IF(CMAKE_BUILD_TYPE) SET(OSG_CPACK_CONFIGURATION ${CMAKE_BUILD_TYPE}) ELSE() SET(OSG_CPACK_CONFIGURATION "Release") ENDIF() SET(PACKAGE_TARGET_PREFIX "package_") ENDIF() # Get all defined components GET_CMAKE_PROPERTY(CPACK_COMPONENTS_ALL COMPONENTS) IF(NOT CPACK_COMPONENTS_ALL) # cmake 2.6.0 don't supply the COMPONENTS property. # I set it manually to be the packages that can always be packaged MESSAGE("When building packages please consider using cmake version 2.6.1 or above") SET(CPACK_COMPONENTS_ALL libopenscenegraph libopenthreads openscenegraph libopenscenegraph-dev libopenthreads-dev) ENDIF() # Create a target that will be used to generate all packages defined below SET(PACKAGE_ALL_TARGETNAME "${PACKAGE_TARGET_PREFIX}ALL") ADD_CUSTOM_TARGET(${PACKAGE_ALL_TARGETNAME}) MACRO(GENERATE_PACKAGING_TARGET package_name) SET(CPACK_PACKAGE_NAME ${package_name}) # the doc packages don't need a system-arch specification IF(${package} MATCHES -doc) SET(OSG_PACKAGE_FILE_NAME ${package_name}-${OPENSCENEGRAPH_VERSION}) ELSE() SET(OSG_PACKAGE_FILE_NAME ${package_name}-${OPENSCENEGRAPH_VERSION}-${OSG_CPACK_SYSTEM_SPEC_STRING}-${OSG_CPACK_CONFIGURATION}) IF(NOT DYNAMIC_OPENSCENEGRAPH) SET(OSG_PACKAGE_FILE_NAME ${OSG_PACKAGE_FILE_NAME}-static) ENDIF() ENDIF() CONFIGURE_FILE("${OpenSceneGraph_SOURCE_DIR}/CMakeModules/OsgCPackConfig.cmake.in" "${OpenSceneGraph_BINARY_DIR}/CPackConfig-${package_name}.cmake" IMMEDIATE) SET(PACKAGE_TARGETNAME "${PACKAGE_TARGET_PREFIX}${package_name}") # This is naive and will probably need fixing eventually IF(MSVC) SET(MOVE_COMMAND "move") ELSE() SET(MOVE_COMMAND "mv") ENDIF() # Set in and out archive filenames. Windows = zip, others = tar.gz IF(WIN32) SET(ARCHIVE_EXT "zip") ELSE() SET(ARCHIVE_EXT "tar.gz") ENDIF() # Create a target that creates the current package # and rename the package to give it proper filename ADD_CUSTOM_TARGET(${PACKAGE_TARGETNAME}) SET_TARGET_PROPERTIES(${PACKAGE_TARGETNAME} PROPERTIES FOLDER "Packaging") ADD_CUSTOM_COMMAND(TARGET ${PACKAGE_TARGETNAME} COMMAND ${CMAKE_CPACK_COMMAND} -C ${OSG_CPACK_CONFIGURATION} --config ${OpenSceneGraph_BINARY_DIR}/CPackConfig-${package_name}.cmake COMMENT "Run CPack packaging for ${package_name}..." ) # Add the exact same custom command to the all package generating target. # I can't use add_dependencies to do this because it would allow parallell building of packages so am going brute here ADD_CUSTOM_COMMAND(TARGET ${PACKAGE_ALL_TARGETNAME} COMMAND ${CMAKE_CPACK_COMMAND} -C ${OSG_CPACK_CONFIGURATION} --config ${OpenSceneGraph_BINARY_DIR}/CPackConfig-${package_name}.cmake ) SET_TARGET_PROPERTIES(${PACKAGE_ALL_TARGETNAME} PROPERTIES FOLDER "Packaging") ENDMACRO(GENERATE_PACKAGING_TARGET) # Create configs and targets for a package including all components SET(OSG_CPACK_COMPONENT ALL) GENERATE_PACKAGING_TARGET(openscenegraph-all) # Create configs and targets for each component FOREACH(package ${CPACK_COMPONENTS_ALL}) SET(OSG_CPACK_COMPONENT ${package}) GENERATE_PACKAGING_TARGET(${package}) ENDFOREACH() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindNVTT.cmake0000644000175000017500000000346612173411731024143 0ustar albertoalberto# Locate nvidia-texture-tools # This module defines # NVTT_LIBRARY # NVTT_FOUND, if false, do not try to link to nvtt # NVTT_INCLUDE_DIR, where to find the headers # FIND_PATH(NVTT_INCLUDE_DIR nvtt/nvtt.h PATHS /usr/local /usr $ENV{NVTT_DIR} ${3rdPartyRoot} PATH_SUFFIXES include ) # NVTT FIND_LIBRARY(NVTT_LIBRARY NAMES nvtt PATHS /usr/local /usr $ENV{NVTT_DIR} ${3rdPartyRoot} PATH_SUFFIXES lib64 lib lib/shared lib/static lib64/static ) FIND_LIBRARY(NVTT_LIBRARY_DEBUG NAMES nvtt_d PATHS /usr/local /usr $ENV{NVTT_DIR} ${3rdPartyRoot} PATH_SUFFIXES lib64 lib lib/shared lib/static lib64/static ) # NVIMAGE FIND_LIBRARY(NVIMAGE_LIBRARY NAMES nvimage PATHS /usr/local /usr $ENV{NVTT_DIR} ${3rdPartyRoot} PATH_SUFFIXES lib64 lib lib/shared lib/static lib64/static ) FIND_LIBRARY(NVIMAGE_LIBRARY_DEBUG NAMES nvimage_d PATHS /usr/local /usr $ENV{NVTT_DIR} ${3rdPartyRoot} PATH_SUFFIXES lib64 lib lib/shared lib/static lib64/static ) # NVMATH FIND_LIBRARY(NVMATH_LIBRARY NAMES nvmath PATHS /usr/local /usr $ENV{NVTT_DIR} ${3rdPartyRoot} PATH_SUFFIXES lib64 lib lib/shared lib/static lib64/static ) FIND_LIBRARY(NVMATH_LIBRARY_DEBUG NAMES nvmath_d PATHS /usr/local /usr $ENV{NVTT_DIR} ${3rdPartyRoot} PATH_SUFFIXES lib64 lib lib/shared lib/static lib64/static ) # NVCORE FIND_LIBRARY(NVCORE_LIBRARY NAMES nvcore PATHS /usr/local /usr $ENV{NVTT_DIR} ${3rdPartyRoot} PATH_SUFFIXES lib64 lib lib/shared lib/static lib64/static ) FIND_LIBRARY(NVCORE_LIBRARY_DEBUG NAMES nvcore_d PATHS /usr/local /usr $ENV{NVTT_DIR} ${3rdPartyRoot} PATH_SUFFIXES lib64 lib lib/shared lib/static lib64/static ) SET(NVTT_FOUND "NO") IF(NVTT_LIBRARY AND NVTT_INCLUDE_DIR) SET(NVTT_FOUND "YES") ENDIF(NVTT_LIBRARY AND NVTT_INCLUDE_DIR) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindOpenVRML.cmake0000644000175000017500000000262611206775500024752 0ustar albertoalberto# Locate openvml library # This module defines # OPENVRML_LIBRARY # OPENVRML_FOUND, if false, do not try to link to vrml # OPENVRML_INCLUDE_DIR, where to find the headers # # $OPENVRML_DIR is an environment variable that would # correspond to the ./configure --prefix=$OPENVRML_DIR # # Created by Robert Osfield. # Modified for the debug library by Jean-Sbastien Guay. FIND_PATH(OPENVRML_INCLUDE_DIR openvrml/openvrml-common.h $ENV{OPENVRML_DIR}/include $ENV{OPENVRML_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include ) FIND_LIBRARY(OPENVRML_LIBRARY NAMES openvrml PATHS $ENV{OPENVRML_DIR}/lib $ENV{OPENVRML_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) FIND_LIBRARY(OPENVRML_LIBRARY_DEBUG NAMES openvrmld PATHS $ENV{OPENVRML_DIR}/lib $ENV{OPENVRML_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) SET(OPENVRML_FOUND "NO") IF(OPENVRML_LIBRARY AND OPENVRML_INCLUDE_DIR) SET(OPENVRML_FOUND "YES") ENDIF(OPENVRML_LIBRARY AND OPENVRML_INCLUDE_DIR) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/clean_directories0000755000175000017500000000032111553272246025143 0ustar albertoalbertofind . -name Makefile | xargs rm -rf find . -name cmake_install.cmake | xargs rm -rf find . -name CMakeFiles | xargs rm -rf rm -rf CMakeCache.txt cmake_uninstall.cmake install_manifest.txt rm -rf lib bin openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindFreetype.cmake0000644000175000017500000000723012322532611025121 0ustar albertoalberto# - Locate FreeType library # This module defines # FREETYPE_LIBRARY, the library to link against # FREETYPE_FOUND, if false, do not try to link to FREETYPE # FREETYPE_INCLUDE_DIRS, where to find headers. # This is the concatenation of the paths: # FREETYPE_INCLUDE_DIR_ft2build # FREETYPE_INCLUDE_DIR_freetype2 # # $FREETYPE_DIR is an environment variable that would # correspond to the ./configure --prefix=$FREETYPE_DIR # used in building FREETYPE. # Created by Eric Wing. # Ugh, FreeType seems to use some #include trickery which # makes this harder than it should be. It looks like they # put ft2build.h in a common/easier-to-find location which # then contains a #include to a more specific header in a # more specific location (#include ). # Then from there, they need to set a bunch of #define's # so you can do something like: # #include FT_FREETYPE_H # Unfortunately, using CMake's mechanisms like INCLUDE_DIRECTORIES() # wants explicit full paths and this trickery doesn't work too well. # I'm going to attempt to cut out the middleman and hope # everything still works. FIND_PATH(FREETYPE_INCLUDE_DIR_ft2build ft2build.h PATHS $ENV{FREETYPE_DIR} NO_DEFAULT_PATH PATH_SUFFIXES include ) FIND_PATH(FREETYPE_INCLUDE_DIR_ft2build ft2build.h PATHS ${CMAKE_PREFIX_PATH} # Unofficial: We are proposing this. NO_DEFAULT_PATH PATH_SUFFIXES include ) FIND_PATH(FREETYPE_INCLUDE_DIR_ft2build ft2build.h PATHS /usr/local /usr /usr/local/X11R6 /usr/local/X11 /usr/X11R6 /usr/X11 /sw /opt/local /opt/csw /opt /usr/freeware PATH_SUFFIXES include include/freetype2 ) FIND_PATH(FREETYPE_INCLUDE_DIR_freetype2 freetype/config/ftheader.h $ENV{FREETYPE_DIR}/include/freetype2 NO_DEFAULT_PATH ) FIND_PATH(FREETYPE_INCLUDE_DIR_freetype2 freetype/config/ftheader.h PATHS ${CMAKE_PREFIX_PATH} # Unofficial: We are proposing this. NO_DEFAULT_PATH PATH_SUFFIXES include/freetype2 ) FIND_PATH(FREETYPE_INCLUDE_DIR_freetype2 freetype/config/ftheader.h /usr/local/include/freetype2 /usr/include/freetype2 /usr/local/X11R6/include/freetype2 /usr/local/X11/include/freetype2 /usr/X11R6/include/freetype2 /usr/X11/include/freetype2 /sw/include/freetype2 /opt/local/include/freetype2 /opt/csw/include/freetype2 /opt/include/freetype2 /usr/freeware/include/freetype2 ) FIND_PATH(FREETYPE_INCLUDE_DIR_freetype2 config/ftheader.h /usr/local/include/freetype2 /usr/include/freetype2 /usr/local/X11R6/include/freetype2 /usr/local/X11/include/freetype2 /usr/X11R6/include/freetype2 /usr/X11/include/freetype2 /sw/include/freetype2 /opt/local/include/freetype2 /opt/csw/include/freetype2 /opt/include/freetype2 /usr/freeware/include/freetype2 ) FIND_LIBRARY(FREETYPE_LIBRARY NAMES freetype libfreetype freetype219 PATHS $ENV{FREETYPE_DIR} NO_DEFAULT_PATH PATH_SUFFIXES lib64 lib ) FIND_LIBRARY(FREETYPE_LIBRARY NAMES freetype libfreetype freetype219 PATHS ${CMAKE_PREFIX_PATH} # Unofficial: We are proposing this. NO_DEFAULT_PATH PATH_SUFFIXES lib64 lib ) FIND_LIBRARY(FREETYPE_LIBRARY NAMES freetype libfreetype freetype219 PATHS /usr/local /usr /usr/local/X11R6 /usr/local/X11 /usr/X11R6 /usr/X11 /sw /opt/local /opt/csw /opt /usr/freeware PATH_SUFFIXES lib64 lib ) IF(FREETYPE_INCLUDE_DIR_ft2build AND FREETYPE_INCLUDE_DIR_freetype2) SET(FREETYPE_INCLUDE_DIRS "${FREETYPE_INCLUDE_DIR_ft2build};${FREETYPE_INCLUDE_DIR_freetype2}") ENDIF(FREETYPE_INCLUDE_DIR_ft2build AND FREETYPE_INCLUDE_DIR_freetype2) SET(FREETYPE_FOUND "NO") IF(FREETYPE_LIBRARY AND FREETYPE_INCLUDE_DIRS) SET(FREETYPE_FOUND "YES") ENDIF(FREETYPE_LIBRARY AND FREETYPE_INCLUDE_DIRS) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindCOLLADA.cmake0000644000175000017500000002165312270512254024405 0ustar albertoalberto# Locate Collada # This module defines: # COLLADA_INCLUDE_DIR, where to find the headers # # COLLADA_LIBRARY, COLLADA_LIBRARY_DEBUG # COLLADA_FOUND, if false, do not try to link to Collada dynamically # # COLLADA_LIBRARY_STATIC, COLLADA_LIBRARY_STATIC_DEBUG # COLLADA_STATIC_FOUND, if false, do not try to link to Collada statically # # $COLLADA_DIR is an environment variable that would # correspond to the ./configure --prefix=$COLLADA_DIR # # Created by Robert Osfield. # Check if COLLADA_DIR is set, otherwise use ACTUAL_3DPARTY_DIR: SET( COLLADA_ENV_VAR_AVAILABLE $ENV{COLLADA_DIR} ) IF ( COLLADA_ENV_VAR_AVAILABLE ) SET(COLLADA_DOM_ROOT "$ENV{COLLADA_DIR}/dom" CACHE PATH "Location of Collada DOM directory" FORCE) ELSE ( COLLADA_ENV_VAR_AVAILABLE ) SET(COLLADA_DOM_ROOT "${ACTUAL_3DPARTY_DIR}/include/1.4/dom" CACHE PATH "Location of Collada DOM directory" FORCE) ENDIF( COLLADA_ENV_VAR_AVAILABLE ) IF(APPLE) SET(COLLADA_BUILDNAME "mac") ELSEIF(MINGW) SET(COLLADA_BUILDNAME "mingw") ELSEIF(MSVC12) SET(COLLADA_BUILDNAME "vc12") ELSEIF(MSVC11) SET(COLLADA_BUILDNAME "vc11") ELSEIF(MSVC10) SET(COLLADA_BUILDNAME "vc10") ELSEIF(MSVC90) SET(COLLADA_BUILDNAME "vc9") ELSEIF(MSVC80) SET(COLLADA_BUILDNAME "vc8") ELSE(APPLE) SET(COLLADA_BUILDNAME "linux") ENDIF(APPLE) FIND_PATH(COLLADA_INCLUDE_DIR dae.h ${COLLADA_DOM_ROOT}/include $ENV{COLLADA_DIR}/include $ENV{COLLADA_DIR} ~/Library/Frameworks /Library/Frameworks /opt/local/Library/Frameworks #macports /usr/local/include /usr/local/include/colladadom /usr/local/include/collada-dom /opt/local/include/collada-dom /usr/include/ /usr/include/colladadom /usr/include/collada-dom /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include ${ACTUAL_3DPARTY_DIR}/include ) FIND_LIBRARY(COLLADA_DYNAMIC_LIBRARY NAMES collada_dom collada14dom Collada14Dom libcollada14dom21 libcollada14dom22 PATHS ${COLLADA_DOM_ROOT}/build/${COLLADA_BUILDNAME}-1.4 $ENV{COLLADA_DIR}/build/${COLLADA_BUILDNAME}-1.4 $ENV{COLLADA_DIR}/lib $ENV{COLLADA_DIR}/lib-dbg $ENV{COLLADA_DIR} ~/Library/Frameworks /Library/Frameworks /opt/local/Library/Frameworks #macports /usr/local/lib /usr/local/lib64 /usr/lib /usr/lib64 /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ${ACTUAL_3DPARTY_DIR}/lib ) FIND_LIBRARY(COLLADA_DYNAMIC_LIBRARY_DEBUG NAMES collada_dom-d collada14dom-d Collada14Dom-d libcollada14dom21-d libcollada14dom22-d PATHS ${COLLADA_DOM_ROOT}/build/${COLLADA_BUILDNAME}-1.4-d $ENV{COLLADA_DIR}/build/${COLLADA_BUILDNAME}-1.4-d $ENV{COLLADA_DIR}/lib $ENV{COLLADA_DIR}/lib-dbg $ENV{COLLADA_DIR} ~/Library/Frameworks /Library/Frameworks /opt/local/Library/Frameworks #macports /usr/local/lib /usr/local/lib64 /usr/lib /usr/lib64 /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ${ACTUAL_3DPARTY_DIR}/lib ) FIND_LIBRARY(COLLADA_STATIC_LIBRARY NAMES libcollada14dom21-s libcollada14dom22-s libcollada14dom.a PATHS ${COLLADA_DOM_ROOT}/build/${COLLADA_BUILDNAME}-1.4 $ENV{COLLADA_DIR}/build/${COLLADA_BUILDNAME}-1.4 $ENV{COLLADA_DIR}/lib $ENV{COLLADA_DIR}/lib-dbg $ENV{COLLADA_DIR} ~/Library/Frameworks /Library/Frameworks /opt/local/Library/Frameworks #macports /usr/local/lib /usr/local/lib64 /usr/lib /usr/lib64 /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ${ACTUAL_3DPARTY_DIR}/lib ) FIND_LIBRARY(COLLADA_STATIC_LIBRARY_DEBUG NAMES collada_dom-sd collada14dom-sd libcollada14dom21-sd libcollada14dom22-sd libcollada14dom-d.a PATHS ${COLLADA_DOM_ROOT}/build/${COLLADA_BUILDNAME}-1.4-d $ENV{COLLADA_DIR}/build/${COLLADA_BUILDNAME}-1.4-d $ENV{COLLADA_DIR}/lib $ENV{COLLADA_DIR}/lib-dbg $ENV{COLLADA_DIR} ~/Library/Frameworks /Library/Frameworks /opt/local/Library/Frameworks #macports /usr/local/lib /usr/local/lib64 /usr/lib /usr/lib64 /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ${ACTUAL_3DPARTY_DIR}/lib ) # find extra libraries that the static linking requires FIND_PACKAGE(LibXml2) IF (LIBXML2_FOUND) SET(COLLADA_LIBXML_LIBRARY "${LIBXML2_LIBRARIES}" CACHE FILEPATH "" FORCE) ELSE(LIBXML2_FOUND) IF(WIN32) FIND_LIBRARY(COLLADA_LIBXML_LIBRARY NAMES libxml2 PATHS ${COLLADA_DOM_ROOT}/external-libs/libxml2/win32/lib ${COLLADA_DOM_ROOT}/external-libs/libxml2/mingw/lib ${ACTUAL_3DPARTY_DIR}/lib ) ENDIF(WIN32) ENDIF(LIBXML2_FOUND) FIND_PACKAGE(ZLIB) IF (ZLIB_FOUND) SET(COLLADA_ZLIB_LIBRARY "${ZLIB_LIBRARY}" CACHE FILEPATH "" FORCE) ELSE(ZLIB_FOUND) IF(WIN32) FIND_LIBRARY(COLLADA_ZLIB_LIBRARY NAMES zlib PATHS ${COLLADA_DOM_ROOT}/external-libs/libxml2/win32/lib ${COLLADA_DOM_ROOT}/external-libs/libxml2/mingw/lib ${ACTUAL_3DPARTY_DIR}/lib ) ENDIF(WIN32) ENDIF(ZLIB_FOUND) FIND_LIBRARY(COLLADA_PCRECPP_LIBRARY NAMES pcrecpp PATHS ${COLLADA_DOM_ROOT}/external-libs/pcre/lib/${COLLADA_BUILDNAME} ${COLLADA_DOM_ROOT}/external-libs/pcre/lib/mac ${COLLADA_DOM_ROOT}/external-libs/pcre/lib/mingw ${ACTUAL_3DPARTY_DIR}/lib ) FIND_LIBRARY(COLLADA_PCRECPP_LIBRARY_DEBUG NAMES pcrecpp-d pcrecppd PATHS ${COLLADA_DOM_ROOT}/external-libs/pcre/lib/${COLLADA_BUILDNAME} ${COLLADA_DOM_ROOT}/external-libs/pcre/lib/mac ${COLLADA_DOM_ROOT}/external-libs/pcre/lib/mingw ${ACTUAL_3DPARTY_DIR}/lib ) FIND_LIBRARY(COLLADA_PCRE_LIBRARY NAMES pcre PATHS ${COLLADA_DOM_ROOT}/external-libs/pcre/lib/${COLLADA_BUILDNAME} ${COLLADA_DOM_ROOT}/external-libs/pcre/lib/mac ${COLLADA_DOM_ROOT}/external-libs/pcre/lib/mingw ${ACTUAL_3DPARTY_DIR}/lib ) FIND_LIBRARY(COLLADA_PCRE_LIBRARY_DEBUG NAMES pcre-d pcred PATHS ${COLLADA_DOM_ROOT}/external-libs/pcre/lib/${COLLADA_BUILDNAME} ${COLLADA_DOM_ROOT}/external-libs/pcre/lib/mac ${COLLADA_DOM_ROOT}/external-libs/pcre/lib/mingw ${ACTUAL_3DPARTY_DIR}/lib ) FIND_LIBRARY(COLLADA_MINIZIP_LIBRARY NAMES minizip PATHS ${COLLADA_DOM_ROOT}/external-libs/minizip/win32/lib ${COLLADA_DOM_ROOT}/external-libs/minizip/mac ${ACTUAL_3DPARTY_DIR}/lib ) FIND_LIBRARY(COLLADA_MINIZIP_LIBRARY_DEBUG NAMES minizip-d minizipD PATHS ${COLLADA_DOM_ROOT}/external-libs/minizip/win32/lib ${COLLADA_DOM_ROOT}/external-libs/minizip/mac ${ACTUAL_3DPARTY_DIR}/lib ) FIND_LIBRARY(COLLADA_BOOST_FILESYSTEM_LIBRARY NAMES libboost_filesystem boost_filesystem boost_filesystem-mt libboost_filesystem-${COLLADA_BUILDNAME}0-mt libboost_filesystem-${COLLADA_BUILDNAME}0-mt-1_54 libboost_filesystem-${COLLADA_BUILDNAME}0-mt-1_55 PATHS ${COLLADA_DOM_ROOT}/external-libs/boost/lib/${COLLADA_BUILDNAME} ${COLLADA_DOM_ROOT}/external-libs/boost/lib/mingw ${ACTUAL_3DPARTY_DIR}/lib ) FIND_LIBRARY(COLLADA_BOOST_FILESYSTEM_LIBRARY_DEBUG NAMES libboost_filesystem-d boost_filesystem-d boost_filesystem-mt-d libboost_filesystem-${COLLADA_BUILDNAME}0-mt-gd libboost_filesystem-${COLLADA_BUILDNAME}0-mt-gd-1_54 libboost_filesystem-${COLLADA_BUILDNAME}0-mt-gd-1_55 PATHS ${COLLADA_DOM_ROOT}/external-libs/boost/lib/${COLLADA_BUILDNAME} ${COLLADA_DOM_ROOT}/external-libs/boost/lib/mingw ${ACTUAL_3DPARTY_DIR}/lib ) FIND_LIBRARY(COLLADA_BOOST_SYSTEM_LIBRARY NAMES libboost_system boost_system boost_system-mt libboost_system-${COLLADA_BUILDNAME}0-mt libboost_system-${COLLADA_BUILDNAME}0-mt-1_54 libboost_system-${COLLADA_BUILDNAME}0-mt-1_55 PATHS ${COLLADA_DOM_ROOT}/external-libs/boost/lib/${COLLADA_BUILDNAME} ${COLLADA_DOM_ROOT}/external-libs/boost/lib/mingw ${ACTUAL_3DPARTY_DIR}/lib ) FIND_LIBRARY(COLLADA_BOOST_SYSTEM_LIBRARY_DEBUG NAMES libboost_system-d boost_system-d boost_system-mt-d libboost_system-${COLLADA_BUILDNAME}0-mt-gd libboost_system-${COLLADA_BUILDNAME}0-mt-gd-1_54 libboost_system-${COLLADA_BUILDNAME}0-mt-gd-1_55 PATHS ${COLLADA_DOM_ROOT}/external-libs/boost/lib/${COLLADA_BUILDNAME} ${COLLADA_DOM_ROOT}/external-libs/boost/lib/mingw ${ACTUAL_3DPARTY_DIR}/lib ) SET(COLLADA_FOUND "NO") IF(COLLADA_DYNAMIC_LIBRARY OR COLLADA_STATIC_LIBRARY) IF (COLLADA_INCLUDE_DIR) SET(COLLADA_FOUND "YES") ENDIF(COLLADA_INCLUDE_DIR) ENDIF(COLLADA_DYNAMIC_LIBRARY OR COLLADA_STATIC_LIBRARY) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindGTA.cmake0000644000175000017500000000217611717502075023765 0ustar albertoalberto# Locate libgta # This module defines # GTA_FOUND, if false, do not try to link to libgta # GTA_INCLUDE_DIRS, where to find the headers # GTA_LIBRARIES # # $GTA_DIR is an environment variable that would # correspond to the ./configure --prefix=$GTA_DIR # used in building libgta. INCLUDE(FindPkgConfig OPTIONAL) IF(PKG_CONFIG_FOUND) INCLUDE(FindPkgConfig) PKG_CHECK_MODULES(GTA gta) ELSE(PKG_CONFIG_FOUND) FIND_PATH(GTA_INCLUDE_DIRS gta/gta.hpp $ENV{GTA_DIR}/include $ENV{GTA_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include ) FIND_LIBRARY(GTA_LIBRARIES NAMES gta libgta PATHS $ENV{GTA_DIR}/lib $ENV{GTA_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) SET(GTA_FOUND "NO") IF(GTA_LIBRARIES AND GTA_INCLUDE_DIRS) SET(GTA_FOUND "YES") ENDIF(GTA_LIBRARIES AND GTA_INCLUDE_DIRS) ENDIF(PKG_CONFIG_FOUND) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindZLIB.cmake0000644000175000017500000000177111204232725024103 0ustar albertoalberto# Locate zlib # This module defines # ZLIB_LIBRARY # ZLIB_FOUND, if false, do not try to link to zlib # ZLIB_INCLUDE_DIR, where to find the headers # # $ZLIB_DIR is an environment variable that would # correspond to the ./configure --prefix=$ZLIB_DIR # used in building zlib. # # Created by Ulrich Hertlein. FIND_PATH(ZLIB_INCLUDE_DIR zlib.h $ENV{ZLIB_DIR}/include $ENV{ZLIB_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include ) FIND_LIBRARY(ZLIB_LIBRARY NAMES z libz zlib PATHS $ENV{ZLIB_DIR}/lib $ENV{ZLIB_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) SET(ZLIB_FOUND "NO") IF(ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR) SET(ZLIB_FOUND "YES") ENDIF(ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/OsgAndroidMacroUtils.cmake0000644000175000017500000001677711743757722026633 0ustar albertoalbertoMACRO(SETUP_ANDROID_LIBRARY LIB_NAME) #foreach(arg ${TARGET_LIBRARIES}) # set(MODULE_LIBS "${MODULE_LIBS} -l${arg}") #endforeach(arg ${TARGET_LIBRARIES}) foreach(arg ${TARGET_SRC}) string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" n_f ${arg}) IF ("${arg}" MATCHES ".*\\.c$" OR "${arg}" MATCHES ".*\\.cpp$") #We only include source files, not header files, this removes anoying warnings set(MODULE_SOURCES "${MODULE_SOURCES} ${n_f}") ENDIF() endforeach(arg ${TARGET_SRC}) #SET(MODULE_INCLUDES "${CMAKE_SOURCE_DIR}/include include") GET_DIRECTORY_PROPERTY(loc_includes INCLUDE_DIRECTORIES) foreach(arg ${loc_includes}) IF(NOT "${arg}" MATCHES "/usr/include" AND NOT "${arg}" MATCHES "/usr/local/include") set(MODULE_INCLUDES "${MODULE_INCLUDES} ${arg}") ENDIF() endforeach(arg ${loc_includes}) GET_DIRECTORY_PROPERTY(loc_definitions COMPILE_DEFINITIONS) foreach(arg ${loc_definitions}) set(DEFINITIONS "${DEFINITIONS} -D${arg}") endforeach(arg ${loc_definitions}) message(STATUS "##############Creating Android Makefile#################") message(STATUS "name: ${LIB_NAME}") set(MODULE_NAME ${LIB_NAME}) set(MODULE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(MODULE_FLAGS_C ${DEFINITIONS}) set(MODULE_FLAGS_CPP ${DEFINITIONS}) #TODO: determine if GLES2 or GLES IF(OSG_GLES1_AVAILABLE) SET(OPENGLES_LIBRARY -lGLESv1_CM) ELSEIF(OSG_GLES2_AVAILABLE) SET(OPENGLES_LIBRARY -lGLESv2) ENDIF() #${MODULE_LIBS} set(MODULE_LIBS_FLAGS "${OPENGLES_LIBRARY} -ldl") if(NOT CPP_EXTENSION) set(CPP_EXTENSION "cpp") endif() IF(NOT MODULE_USER_STATIC_OR_DYNAMIC) MESSAGE(FATAL_ERROR "Not defined MODULE_USER_STATIC_OR_DYNAMIC") ENDIF() IF("MODULE_USER_STATIC_OR_DYNAMIC" MATCHES "STATIC") SET(MODULE_BUILD_TYPE "\$\(BUILD_STATIC_LIBRARY\)") SET(MODULE_LIBS_SHARED " ") SET(MODULE_LIBS_STATIC ${TARGET_LIBRARIES}) ELSE() SET(MODULE_BUILD_TYPE "\$\(BUILD_SHARED_LIBRARY\)") SET(MODULE_LIBS_SHARED ${TARGET_LIBRARIES}) SET(MODULE_LIBS_STATIC " ") ENDIF() set(ENV{AND_OSG_LIB_NAMES} "$ENV{AND_OSG_LIB_NAMES} ${LIB_NAME}") set(ENV{AND_OSG_LIB_PATHS} "$ENV{AND_OSG_LIB_PATHS}include ${CMAKE_CURRENT_BINARY_DIR}/Android.mk \n") configure_file("${OSG_ANDROID_TEMPLATES}/Android.mk.modules.in" "${CMAKE_CURRENT_BINARY_DIR}/Android.mk") ENDMACRO() MACRO(ANDROID_3RD_PARTY) ################################################ #JPEG ################################################ FIND_PATH(JPEG_INCLUDE_DIR Android.mk ${CMAKE_SOURCE_DIR}/3rdparty/libjpeg ) #set(ENV{AND_OSG_LIB_NAMES} "$ENV{AND_OSG_LIB_NAMES} libjpeg") #set(ENV{AND_OSG_LIB_PATHS} "$ENV{AND_OSG_LIB_PATHS}include ${JPEG_INCLUDE_DIR}/Android.mk \n") if(JPEG_INCLUDE_DIR) message(STATUS "Jpeg found ${JPEG_INCLUDE_DIR}" ) set(JPEG_FOUND "Yes") install(DIRECTORY 3rdparty/build/libjpeg/ DESTINATION ./ ) else(JPEG_INCLUDE_DIR) message(STATUS "Jpeg missing" ) endif() ################################################ #PNG ################################################ FIND_PATH(PNG_INCLUDE_DIR Android.mk ${CMAKE_SOURCE_DIR}/3rdparty/libpng ) #set(ENV{AND_OSG_LIB_NAMES} "$ENV{AND_OSG_LIB_NAMES} libpng") #set(ENV{AND_OSG_LIB_PATHS} "$ENV{AND_OSG_LIB_PATHS}include ${PNG_INCLUDE_DIR}/Android.mk \n") if(PNG_INCLUDE_DIR) message(STATUS "PNG found ${PNG_INCLUDE_DIR}" ) set(PNG_FOUND "Yes") install(DIRECTORY 3rdparty/build/libpng/ DESTINATION ./ ) else(PNG_INCLUDE_DIR) message(STATUS "PNG missing" ) endif() ################################################ #GIF ################################################ FIND_PATH(GIFLIB_INCLUDE_DIR Android.mk ${CMAKE_SOURCE_DIR}/3rdparty/giflib ) #set(ENV{AND_OSG_LIB_NAMES} "$ENV{AND_OSG_LIB_NAMES} libgif") #set(ENV{AND_OSG_LIB_PATHS} "$ENV{AND_OSG_LIB_PATHS}include ${GIFLIB_INCLUDE_DIR}/Android.mk \n") if(GIFLIB_INCLUDE_DIR) message(STATUS "GIF found ${GIFLIB_INCLUDE_DIR}" ) set(GIFLIB_FOUND "Yes") install(DIRECTORY 3rdparty/build/giflib/ DESTINATION ./ ) else(GIFLIB_INCLUDE_DIR) message(STATUS "GIF missing" ) endif() ################################################ #TIF ################################################ FIND_PATH(TIFF_INCLUDE_DIR Android.mk ${CMAKE_SOURCE_DIR}/3rdparty/libtiff ) #set(ENV{AND_OSG_LIB_NAMES} "$ENV{AND_OSG_LIB_NAMES} libtiff") #set(ENV{AND_OSG_LIB_PATHS} "$ENV{AND_OSG_LIB_PATHS}include ${TIFF_INCLUDE_DIR}/Android.mk \n") if(TIFF_INCLUDE_DIR) message(STATUS "TIF found ${TIFF_INCLUDE_DIR}" ) set(TIFF_FOUND "Yes") install(DIRECTORY 3rdparty/build/libtiff/ DESTINATION ./ ) else(TIFF_INCLUDE_DIR) message(STATUS "TIF missing" ) endif() ################################################ #ZLIB ################################################ #FIND_PATH(ZLIB_INCLUDE_DIR Android.mk # ${CMAKE_SOURCE_DIR}/3rdparty/zlib #) #set(ENV{AND_OSG_LIB_NAMES} "$ENV{AND_OSG_LIB_NAMES} zlib") #set(ENV{AND_OSG_LIB_PATHS} "$ENV{AND_OSG_LIB_PATHS}include ${ZLIB_INCLUDE_DIR}/Android.mk \n") #if(ZLIB_INCLUDE_DIR) # message(STATUS "ZLIB found ${ZLIB_INCLUDE_DIR}" ) # set(ZLIB_FOUND "Yes") # install(DIRECTORY 3rdparty/build/libjpeg/ DESTINATION ./ ) #else(ZLIB_INCLUDE_DIR) # message(STATUS "ZLIB missing" ) #endif() ################################################ #CURL ################################################ FIND_PATH(CURL_DIR Android.mk ${CMAKE_SOURCE_DIR}/3rdparty/curl ) #set(ENV{AND_OSG_LIB_NAMES} "$ENV{AND_OSG_LIB_NAMES} libcurl") #set(ENV{AND_OSG_LIB_PATHS} "$ENV{AND_OSG_LIB_PATHS}include ${CURL_DIR}/Android.mk \n") set(CURL_INCLUDE_DIR ${CURL_DIR}/include) set(CURL_INCLUDE_DIRS ${CURL_DIR}/include) #Both are defined in FindCurl if(CURL_DIR) message(STATUS "Curl found ${CURL_DIR}" ) set(CURL_FOUND "Yes") install(DIRECTORY 3rdparty/build/curl/ DESTINATION ./ ) else(CURL_DIR) message(STATUS "Curl missing" ) endif() ################################################ #FREETYPE ################################################ FIND_PATH(FREETYPE_DIR Android.mk ${CMAKE_SOURCE_DIR}/3rdparty/freetype ) #set(ENV{AND_OSG_LIB_NAMES} "$ENV{AND_OSG_LIB_NAMES} libft2") #set(ENV{AND_OSG_LIB_PATHS} "$ENV{AND_OSG_LIB_PATHS}include ${FREETYPE_DIR}/Android.mk \n") set(FREETYPE_INCLUDE_DIRS "${FREETYPE_DIR}/include ${FREETYPE_DIR}/include/freetype/config") if(FREETYPE_DIR) message(STATUS "FREETYPE found ${FREETYPE_DIR}" ) set(FREETYPE_FOUND "Yes") install(DIRECTORY 3rdparty/build/freetype/ DESTINATION ./ ) else(FREETYPE_DIR) message(STATUS "FREETYPE missing" ) endif() ################################################ #GDAL ################################################ FIND_PATH(GDAL_DIR gdal.h ${CMAKE_SOURCE_DIR}/3rdparty/gdal/include ) set(GDAL_INCLUDE_DIR "${GDAL_DIR}") if(GDAL_DIR) message(STATUS "GDAL found ${GDAL_DIR}" ) set(GDAL_FOUND "Yes") install(DIRECTORY 3rdparty/build/gdal/ DESTINATION ./ ) else(GDAL_DIR) message(STATUS "GDAL missing" ) endif() ENDMACRO() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindDirectInput.cmake0000644000175000017500000000266411553272246025610 0ustar albertoalberto# Locate directinput # This module defines # DIRECTINPUT_LIBRARIES # DIRECTINPUT_FOUND, if false, do not try to link to directinput # DIRECTINPUT_INCLUDE_DIR, where to find the headers # # $DIRECTINPUT_DIR is an environment variable that would # point to the this path in the plateform devkit (Samples\Multimedia\DirectShow) # # Created by Cedric Pinson. # SET( DIRECTINPUT_FOUND FALSE ) IF( WIN32 ) FIND_PATH( DIRECTINPUT_ROOT_DIR Include/D3D10.h PATHS $ENV{PATH} $ENV{PROGRAMFILES} ) FIND_PATH( DIRECTINPUT_INCLUDE_DIR dinput.h PATHS ${DIRECTINPUT_ROOT_DIR}/Include ) FIND_LIBRARY( DIRECTINPUT_LIBRARY dinput7.lib dinput8.lib PATHS ${DIRECTINPUT_ROOT_DIR}/lib/x86 ) FIND_LIBRARY( DIRECTINPUT_GUID_LIBRARY dxguid.lib PATHS ${DIRECTINPUT_ROOT_DIR}/lib/x86 ) FIND_LIBRARY( DIRECTINPUT_ERR_LIBRARY dxerr.lib PATHS ${DIRECTINPUT_ROOT_DIR}/lib/x86 ) SET( DIRECTINPUT_LIBRARIES ${DIRECTINPUT_LIBRARY} ${DIRECTINPUT_GUID_LIBRARY} ${DIRECTINPUT_ERR_LIBRARY} ) IF ( DIRECTINPUT_INCLUDE_DIR AND DIRECTINPUT_LIBRARIES ) SET( DIRECTINPUT_FOUND TRUE ) ENDIF ( DIRECTINPUT_INCLUDE_DIR AND DIRECTINPUT_LIBRARIES ) ENDIF( WIN32 ) MARK_AS_ADVANCED( DIRECTINPUT_FOUND ) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindXine.cmake0000644000175000017500000000173011204232725024241 0ustar albertoalberto# Locate gdal # This module defines # XINE_LIBRARY # XINE_FOUND, if false, do not try to link to gdal # XINE_INCLUDE_DIR, where to find the headers # # $XINE_DIR is an environment variable that would # correspond to the ./configure --prefix=$XINE_DIR # # Created by Robert Osfield. FIND_PATH(XINE_INCLUDE_DIR xine.h $ENV{XINE_DIR}/include $ENV{XINE_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include ) FIND_LIBRARY(XINE_LIBRARY NAMES xine PATHS $ENV{XINE_DIR}/lib $ENV{XINE_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) SET(XINE_FOUND "NO") IF(XINE_LIBRARY AND XINE_INCLUDE_DIR) SET(XINE_FOUND "YES") ENDIF(XINE_LIBRARY AND XINE_INCLUDE_DIR) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/OsgDetermineCompiler.cmake0000644000175000017500000000510011553272246026621 0ustar albertoalberto# - If Visual Studio is being used, this script sets the variable OSG_COMPILER # The principal reason for this is due to MSVC 8.0 SP0 vs SP1 builds. # # Variable: # OSG_COMPILER # # Not currently used... #IF(CMAKE_COMPILER_IS_GNUCXX) # EXEC_PROGRAM( # ${CMAKE_CXX_COMPILER} # ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion # OUTPUT_VARIABLE gcc_compiler_version # ) # #MESSAGE("GCC Version: ${gcc_compiler_version}") IF(MSVC60) SET(OSG_COMPILER "vc60") ELSEIF(MSVC70) SET(OSG_COMPILER "vc70") ELSEIF(MSVC71) SET(OSG_COMPILER "vc71") ELSEIF(MSVC80) SET(OSG_COMPILER "vc80") ELSEIF(MSVC90) SET(OSG_COMPILER "vc90") ENDIF() IF(MSVC80) MESSAGE(STATUS "Checking if compiler has service pack 1 installed...") FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.cxx" "int main() {return 0;}\n") TRY_COMPILE(_TRY_RESULT ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.cxx CMAKE_FLAGS -D CMAKE_VERBOSE_MAKEFILE=ON OUTPUT_VARIABLE OUTPUT ) IF(_TRY_RESULT) # parse for exact compiler version STRING(REGEX MATCH "Compiler Version [0-9]+.[0-9]+.[0-9]+.[0-9]+" vc_compiler_version "${OUTPUT}") IF(vc_compiler_version) #MESSAGE("${vc_compiler_version}") STRING(REGEX MATCHALL "[0-9]+" CL_VERSION_LIST "${vc_compiler_version}") LIST(GET CL_VERSION_LIST 0 CL_MAJOR_VERSION) LIST(GET CL_VERSION_LIST 1 CL_MINOR_VERSION) LIST(GET CL_VERSION_LIST 2 CL_PATCH_VERSION) LIST(GET CL_VERSION_LIST 3 CL_EXTRA_VERSION) ENDIF(vc_compiler_version) # Standard vc80 is 14.00.50727.42, sp1 14.00.50727.762, sp2? # Standard vc90 is 9.0.30729.1, sp1 ? IF(CL_EXTRA_VERSION EQUAL 762) SET(OSG_COMPILER "vc80sp1") ELSE(CL_EXTRA_VERSION EQUAL 762) SET(OSG_COMPILER "vc80") ENDIF(CL_EXTRA_VERSION EQUAL 762) # parse for exact visual studio version #IF(MSVC_IDE) # string(REGEX MATCH "Visual Studio Version [0-9]+.[0-9]+.[0-9]+.[0-9]+" vs_version "${OUTPUT}") # IF(vs_version) # MESSAGE("${vs_version}") # string(REGEX MATCHALL "[0-9]+" VS_VERSION_LIST "${vs_version}") # list(GET VS_VERSION_LIST 0 VS_MAJOR_VERSION) # list(GET VS_VERSION_LIST 1 VS_MINOR_VERSION) # list(GET VS_VERSION_LIST 2 VS_PATCH_VERSION) # list(GET VS_VERSION_LIST 3 VS_EXTRA_VERSION) # ENDIF(vs_version) #ENDIF(MSVC_IDE) ENDIF(_TRY_RESULT) ENDIF(MSVC80) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindJasper.cmake0000644000175000017500000000301611526246655024577 0ustar albertoalberto# Locate gdal # This module defines # JASPER_LIBRARY # JASPER_FOUND, if false, do not try to link to gdal # JASPER_INCLUDE_DIR, where to find the headers # # $JASPER_DIR is an environment variable that would # correspond to the ./configure --prefix=$JASPER_DIR # # Created by Robert Osfield. FIND_PATH(JASPER_INCLUDE_DIR jasper/jasper.h $ENV{JASPER_DIR}/include $ENV{JASPER_DIR}/src/libjasper/include $ENV{JASPER_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include ) FIND_LIBRARY(JASPER_LIBRARY NAMES jasper libjasper PATHS $ENV{JASPER_DIR}/lib $ENV{JASPER_DIR}/src/libjasper/lib $ENV{JASPER_DIR}/src/msvc/Win32_Release $ENV{JASPER_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) FIND_LIBRARY(JASPER_LIBRARY_DEBUG NAMES jasper libjasper jasperd libjasperd PATHS $ENV{JASPER_DIR}/lib $ENV{JASPER_DIR}/src/libjasper/lib $ENV{JASPER_DIR}/src/msvc/Win32_Debug $ENV{JASPER_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) SET(JASPER_FOUND "NO") IF(JASPER_LIBRARY AND JASPER_INCLUDE_DIR) SET(JASPER_FOUND "YES") ENDIF(JASPER_LIBRARY AND JASPER_INCLUDE_DIR) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindLibVNCServer.cmake0000644000175000017500000000263511553272246025620 0ustar albertoalberto# Locate libvncserver # This module defines # LIBVNCSERVER_LIBRARY # LIBVNCSERVER_FOUND, if false, do not try to link to libvncserver # LIBVNCSERVER_INCLUDE_DIR, where to find the headers # # $LIBVNCSERVER_DIR is an environment variable that would # correspond to the ./configure --prefix=$LIBVNCSERVER_DIR # used in building libvncserver. FIND_PATH(LIBVNCSERVER_INCLUDE_DIR rfb/rfb.h $ENV{LIBVNCSERVER_DIR}/include $ENV{LIBVNCSERVER_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include ) FIND_LIBRARY(LIBVNCCLIENT_LIBRARY NAMES vncclient PATHS $ENV{LIBVNCSERVER_DIR}/lib $ENV{LIBVNCSERVER_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) FIND_LIBRARY(LIBVNCSERVER_LIBRARY NAMES vncserver PATHS $ENV{LIBVNCSERVER_DIR}/lib $ENV{LIBVNCSERVER_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) SET(LIBVNCSERVER_FOUND "NO") IF(LIBVNCSERVER_LIBRARY AND LIBVNCSERVER_INCLUDE_DIR) SET(LIBVNCSERVER_FOUND "YES") ENDIF(LIBVNCSERVER_LIBRARY AND LIBVNCSERVER_INCLUDE_DIR) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindQuickTime.cmake0000644000175000017500000000460312434646657025256 0ustar albertoalberto# Locate QuickTime # This module defines # QUICKTIME_LIBRARY # QUICKTIME_FOUND, if false, do not try to link to gdal # QUICKTIME_INCLUDE_DIR, where to find the headers # # $QUICKTIME_DIR is an environment variable that would # correspond to the ./configure --prefix=$QUICKTIME_DIR # # Created by Eric Wing. # QuickTime on OS X looks different than QuickTime for Windows, # so I am going to case the two. IF(APPLE) FIND_PATH(QUICKTIME_INCLUDE_DIR QuickTime/QuickTime.h) FIND_LIBRARY(QUICKTIME_LIBRARY QuickTime) ELSE() FIND_PATH(QUICKTIME_INCLUDE_DIR QuickTime.h $ENV{QUICKTIME_DIR}/include $ENV{QUICKTIME_DIR} NO_DEFAULT_PATH ) FIND_PATH(QUICKTIME_INCLUDE_DIR QuickTime.h PATHS ${CMAKE_PREFIX_PATH} # Unofficial: We are proposing this. NO_DEFAULT_PATH PATH_SUFFIXES include ) FIND_PATH(QUICKTIME_INCLUDE_DIR QuickTime.h) FIND_LIBRARY(QUICKTIME_LIBRARY QuickTime $ENV{QUICKTIME_DIR}/lib $ENV{QUICKTIME_DIR} NO_DEFAULT_PATH ) FIND_LIBRARY(QUICKTIME_LIBRARY QuickTime PATHS ${CMAKE_PREFIX_PATH} # Unofficial: We are proposing this. NO_DEFAULT_PATH PATH_SUFFIXES lib64 lib ) FIND_LIBRARY(QUICKTIME_LIBRARY QuickTime) ENDIF() SET(QUICKTIME_FOUND "NO") IF(QUICKTIME_LIBRARY AND QUICKTIME_INCLUDE_DIR) SET(QUICKTIME_FOUND "YES") ENDIF() IF(OSG_BUILD_PLATFORM_IPHONE OR OSG_BUILD_PLATFORM_IPHONE_SIMULATOR) SET(QUICKTIME_FOUND "NO") ELSE() IF(APPLE) #Quicktime is not supported under 64bit OSX build so we need to detect it and disable it. #First check to see if we are running with a native 64-bit compiler (10.6 default) and implicit arch IF(NOT CMAKE_OSX_ARCHITECTURES AND CMAKE_SIZEOF_VOID_P EQUAL 8) SET(QUICKTIME_FOUND "NO") ELSE() #Otherwise check to see if 64-bit is explicitly called for. LIST(FIND CMAKE_OSX_ARCHITECTURES "x86_64" has64Compile) IF(NOT has64Compile EQUAL -1) SET(QUICKTIME_FOUND "NO") ENDIF() ENDIF() # Disable quicktime for >= 10.7, as it's officially deprecated IF(${OSG_OSX_SDK_NAME} STREQUAL "macosx10.7" OR ${OSG_OSX_SDK_NAME} STREQUAL "macosx10.8" OR ${OSG_OSX_SDK_NAME} STREQUAL "macosx10.9" OR ${OSG_OSX_SDK_NAME} STREQUAL "macosx10.10") MESSAGE("disabling quicktime because it's not supported by the selected SDK ${OSG_OSX_SDK_NAME}") SET(QUICKTIME_FOUND "NO") ENDIF() ENDIF() ENDIF() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/OsgMacroUtils.cmake0000644000175000017500000006261712322532505025304 0ustar albertoalberto ####################################################################################################### # macro for linking libraries that come from Findxxxx commands, so there is a variable that contains the # full path of the library name. in order to differentiate release and debug, this macro get the # NAME of the variables, so the macro gets as arguments the target name and the following list of parameters # is intended as a list of variable names each one containing the path of the libraries to link to # The existance of a variable name with _DEBUG appended is tested and, in case it' s value is used # for linking to when in debug mode # the content of this library for linking when in debugging ####################################################################################################### # VALID_BUILDER_VERSION: used for replacing CMAKE_VERSION (available in v2.6.3 RC9) and VERSION_GREATER/VERSION_LESS (available in 2.6.2 RC4). # This can be replaced by "IF(${CMAKE_VERSION} VERSION_LESS "x.y.z")" from 2.6.4. SET(VALID_BUILDER_VERSION OFF) MACRO(BUILDER_VERSION_GREATER MAJOR_VER MINOR_VER PATCH_VER) SET(VALID_BUILDER_VERSION OFF) IF(CMAKE_MAJOR_VERSION GREATER ${MAJOR_VER}) SET(VALID_BUILDER_VERSION ON) ELSEIF(CMAKE_MAJOR_VERSION EQUAL ${MAJOR_VER}) IF(CMAKE_MINOR_VERSION GREATER ${MINOR_VER}) SET(VALID_BUILDER_VERSION ON) ELSEIF(CMAKE_MINOR_VERSION EQUAL ${MINOR_VER}) IF(CMAKE_PATCH_VERSION GREATER ${PATCH_VER}) SET(VALID_BUILDER_VERSION ON) ENDIF(CMAKE_PATCH_VERSION GREATER ${PATCH_VER}) ENDIF() ENDIF() ENDMACRO(BUILDER_VERSION_GREATER MAJOR_VER MINOR_VER PATCH_VER) # CMAKE24: if CMake version is <2.6.0. SET(CMAKE24 OFF) IF(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} LESS 5) SET(CMAKE24 ON) ENDIF(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} LESS 5) # CMAKE_VERSION_TEST: Define whether "IF(${CMAKE_VERSION} VERSION_LESS "x.y.z")" can be used or not. BUILDER_VERSION_GREATER(2 6 3) SET(CMAKE_VERSION_TEST ${VALID_BUILDER_VERSION}) # >= 2.6.4 SET(VALID_BUILDER_VERSION OFF) MACRO(LINK_WITH_VARIABLES TRGTNAME) FOREACH(varname ${ARGN}) IF(${varname}_DEBUG) TARGET_LINK_LIBRARIES(${TRGTNAME} optimized "${${varname}}" debug "${${varname}_DEBUG}") ELSE(${varname}_DEBUG) TARGET_LINK_LIBRARIES(${TRGTNAME} "${${varname}}" ) ENDIF(${varname}_DEBUG) ENDFOREACH(varname) ENDMACRO(LINK_WITH_VARIABLES TRGTNAME) MACRO(LINK_INTERNAL TRGTNAME) IF(NOT CMAKE24) TARGET_LINK_LIBRARIES(${TRGTNAME} ${ARGN}) ELSE(NOT CMAKE24) FOREACH(LINKLIB ${ARGN}) IF(MSVC AND OSG_MSVC_VERSIONED_DLL) #when using versioned names, the .dll name differ from .lib name, there is a problem with that: #CMake 2.4.7, at least seem to use PREFIX instead of IMPORT_PREFIX for computing linkage info to use into projects, # so we full path name to specify linkage, this prevent automatic inferencing of dependencies, so we add explicit depemdencies #to library targets used TARGET_LINK_LIBRARIES(${TRGTNAME} optimized "${OUTPUT_LIBDIR}/${LINKLIB}${CMAKE_RELEASE_POSTFIX}.lib" debug "${OUTPUT_LIBDIR}/${LINKLIB}${CMAKE_DEBUG_POSTFIX}.lib") ADD_DEPENDENCIES(${TRGTNAME} ${LINKLIB}) ELSE(MSVC AND OSG_MSVC_VERSIONED_DLL) TARGET_LINK_LIBRARIES(${TRGTNAME} optimized "${LINKLIB}${CMAKE_RELEASE_POSTFIX}" debug "${LINKLIB}${CMAKE_DEBUG_POSTFIX}") ENDIF(MSVC AND OSG_MSVC_VERSIONED_DLL) ENDFOREACH(LINKLIB) ENDIF(NOT CMAKE24) ENDMACRO(LINK_INTERNAL TRGTNAME) MACRO(LINK_EXTERNAL TRGTNAME) FOREACH(LINKLIB ${ARGN}) TARGET_LINK_LIBRARIES(${TRGTNAME} "${LINKLIB}" ) ENDFOREACH(LINKLIB) ENDMACRO(LINK_EXTERNAL TRGTNAME) ####################################################################################################### # macro for common setup of core libraries: it links OPENGL_LIBRARIES in undifferentiated mode ####################################################################################################### MACRO(LINK_CORELIB_DEFAULT CORELIB_NAME) #SET(ALL_GL_LIBRARIES ${OPENGL_LIBRARIES}) SET(ALL_GL_LIBRARIES ${OPENGL_gl_LIBRARY}) IF (OSG_GLES1_AVAILABLE OR OSG_GLES2_AVAILABLE) SET(ALL_GL_LIBRARIES ${ALL_GL_LIBRARIES} ${OPENGL_egl_LIBRARY}) ENDIF() LINK_EXTERNAL(${CORELIB_NAME} ${ALL_GL_LIBRARIES}) LINK_WITH_VARIABLES(${CORELIB_NAME} OPENTHREADS_LIBRARY) IF(OPENSCENEGRAPH_SONAMES) SET_TARGET_PROPERTIES(${CORELIB_NAME} PROPERTIES VERSION ${OPENSCENEGRAPH_VERSION} SOVERSION ${OPENSCENEGRAPH_SOVERSION}) ENDIF(OPENSCENEGRAPH_SONAMES) ENDMACRO(LINK_CORELIB_DEFAULT CORELIB_NAME) ####################################################################################################### # macro for common setup of plugins, examples and applications it expect some variables to be set: # either within the local CMakeLists or higher in hierarchy # TARGET_NAME is the name of the folder and of the actually .exe or .so or .dll # TARGET_TARGETNAME is the name of the target , this get buit out of a prefix, if present and TARGET_TARGETNAME # TARGET_SRC are the sources of the target # TARGET_H are the eventual headers of the target # TARGET_LIBRARIES are the libraries to link to that are internal to the project and have d suffix for debug # TARGET_EXTERNAL_LIBRARIES are external libraries and are not differentiated with d suffix # TARGET_LABEL is the label IDE should show up for targets ########################################################################################################## MACRO(SETUP_LINK_LIBRARIES) ###################################################################### # # This set up the libraries to link to, it assumes there are two variable: one common for a group of examples or plugins # kept in the variable TARGET_COMMON_LIBRARIES and an example or plugin specific kept in TARGET_ADDED_LIBRARIES # they are combined in a single list checked for unicity # the suffix ${CMAKE_DEBUG_POSTFIX} is used for differentiating optimized and debug # # a second variable TARGET_EXTERNAL_LIBRARIES hold the list of libraries not differentiated between debug and optimized ################################################################################## SET(TARGET_LIBRARIES ${TARGET_COMMON_LIBRARIES}) FOREACH(LINKLIB ${TARGET_ADDED_LIBRARIES}) SET(TO_INSERT TRUE) FOREACH (value ${TARGET_COMMON_LIBRARIES}) IF (${value} STREQUAL ${LINKLIB}) SET(TO_INSERT FALSE) ENDIF (${value} STREQUAL ${LINKLIB}) ENDFOREACH (value ${TARGET_COMMON_LIBRARIES}) IF(TO_INSERT) LIST(APPEND TARGET_LIBRARIES ${LINKLIB}) ENDIF(TO_INSERT) ENDFOREACH(LINKLIB) #SET(ALL_GL_LIBRARIES ${OPENGL_LIBRARIES}) SET(ALL_GL_LIBRARIES ${OPENGL_gl_LIBRARY}) IF (OSG_GLES1_AVAILABLE OR OSG_GLES2_AVAILABLE) SET(ALL_GL_LIBRARIES ${ALL_GL_LIBRARIES} ${OPENGL_egl_LIBRARY}) ENDIF() # FOREACH(LINKLIB ${TARGET_LIBRARIES}) # TARGET_LINK_LIBRARIES(${TARGET_TARGETNAME} optimized ${LINKLIB} debug "${LINKLIB}${CMAKE_DEBUG_POSTFIX}") # ENDFOREACH(LINKLIB) LINK_INTERNAL(${TARGET_TARGETNAME} ${TARGET_LIBRARIES}) # FOREACH(LINKLIB ${TARGET_EXTERNAL_LIBRARIES}) # TARGET_LINK_LIBRARIES(${TARGET_TARGETNAME} ${LINKLIB}) # ENDFOREACH(LINKLIB) TARGET_LINK_LIBRARIES(${TARGET_TARGETNAME} ${TARGET_EXTERNAL_LIBRARIES}) IF(TARGET_LIBRARIES_VARS) LINK_WITH_VARIABLES(${TARGET_TARGETNAME} ${TARGET_LIBRARIES_VARS}) ENDIF(TARGET_LIBRARIES_VARS) IF(MSVC AND OSG_MSVC_VERSIONED_DLL) #when using full path name to specify linkage, it seems that already linked libs must be specified LINK_EXTERNAL(${TARGET_TARGETNAME} ${ALL_GL_LIBRARIES}) ENDIF(MSVC AND OSG_MSVC_VERSIONED_DLL) ENDMACRO(SETUP_LINK_LIBRARIES) ############################################################################################ # this is the common set of command for all the plugins # # Sets the output directory property for CMake >= 2.6.0, giving an output path RELATIVE to default one MACRO(SET_OUTPUT_DIR_PROPERTY_260 TARGET_TARGETNAME RELATIVE_OUTDIR) BUILDER_VERSION_GREATER(2 8 0) IF(NOT VALID_BUILDER_VERSION) # If CMake <= 2.8.0 (Testing CMAKE_VERSION is possible in >= 2.6.4) IF(MSVC_IDE) # Using the "prefix" hack SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES PREFIX "../${RELATIVE_OUTDIR}/") ELSE(MSVC_IDE) SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES PREFIX "${RELATIVE_OUTDIR}/") ENDIF(MSVC_IDE) ELSE(NOT VALID_BUILDER_VERSION) # Using the output directory properties # Global properties (All generators but VS & Xcode) FILE(TO_CMAKE_PATH TMPVAR "CMAKE_ARCHIVE_OUTPUT_DIRECTORY/${RELATIVE_OUTDIR}") SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${TMPVAR}") FILE(TO_CMAKE_PATH TMPVAR "CMAKE_RUNTIME_OUTPUT_DIRECTORY/${RELATIVE_OUTDIR}") SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TMPVAR}") FILE(TO_CMAKE_PATH TMPVAR "CMAKE_LIBRARY_OUTPUT_DIRECTORY/${RELATIVE_OUTDIR}") SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${TMPVAR}") # Per-configuration property (VS, Xcode) FOREACH(CONF ${CMAKE_CONFIGURATION_TYPES}) # For each configuration (Debug, Release, MinSizeRel... and/or anything the user chooses) STRING(TOUPPER "${CONF}" CONF) # Go uppercase (DEBUG, RELEASE...) # We use "FILE(TO_CMAKE_PATH", to create nice looking paths FILE(TO_CMAKE_PATH "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CONF}}/${RELATIVE_OUTDIR}" TMPVAR) SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES "ARCHIVE_OUTPUT_DIRECTORY_${CONF}" "${TMPVAR}") FILE(TO_CMAKE_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONF}}/${RELATIVE_OUTDIR}" TMPVAR) SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES "RUNTIME_OUTPUT_DIRECTORY_${CONF}" "${TMPVAR}") FILE(TO_CMAKE_PATH "${CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CONF}}/${RELATIVE_OUTDIR}" TMPVAR) SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES "LIBRARY_OUTPUT_DIRECTORY_${CONF}" "${TMPVAR}") ENDFOREACH(CONF ${CMAKE_CONFIGURATION_TYPES}) ENDIF(NOT VALID_BUILDER_VERSION) ENDMACRO(SET_OUTPUT_DIR_PROPERTY_260 TARGET_TARGETNAME RELATIVE_OUTDIR) ####################################################################################################### # macro for common setup of libraries it expect some variables to be set: # either within the local CMakeLists or higher in hierarchy # LIB_NAME is the name of the target library # TARGET_SRC are the sources of the target # TARGET_H are the eventual headers of the target # TARGET_H_NO_MODULE_INSTALL are headers that belong to target but shouldn't get installed by the ModuleInstall script # TARGET_LIBRARIES are the libraries to link to that are internal to the project and have d suffix for debug # TARGET_EXTERNAL_LIBRARIES are external libraries and are not differentiated with d suffix # TARGET_LABEL is the label IDE should show up for targets ########################################################################################################## MACRO(SETUP_LIBRARY LIB_NAME) IF(ANDROID) SETUP_ANDROID_LIBRARY(${LIB_NAME}) ELSE() SET(TARGET_NAME ${LIB_NAME} ) SET(TARGET_TARGETNAME ${LIB_NAME} ) ADD_LIBRARY(${LIB_NAME} ${OPENSCENEGRAPH_USER_DEFINED_DYNAMIC_OR_STATIC} ${TARGET_H} ${TARGET_H_NO_MODULE_INSTALL} ${TARGET_SRC} ) SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES FOLDER "OSG Core") IF(APPLE) SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES XCODE_ATTRIBUTE_WARNING_CFLAGS "") ENDIF() IF(TARGET_LABEL) SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES PROJECT_LABEL "${TARGET_LABEL}") ENDIF(TARGET_LABEL) IF(TARGET_LIBRARIES) LINK_INTERNAL(${LIB_NAME} ${TARGET_LIBRARIES}) ENDIF() IF(TARGET_EXTERNAL_LIBRARIES) LINK_EXTERNAL(${LIB_NAME} ${TARGET_EXTERNAL_LIBRARIES}) ENDIF() IF(TARGET_LIBRARIES_VARS) LINK_WITH_VARIABLES(${LIB_NAME} ${TARGET_LIBRARIES_VARS}) ENDIF(TARGET_LIBRARIES_VARS) LINK_CORELIB_DEFAULT(${LIB_NAME}) ENDIF() INCLUDE(ModuleInstall OPTIONAL) ENDMACRO(SETUP_LIBRARY LIB_NAME) MACRO(SETUP_PLUGIN PLUGIN_NAME) IF(ANDROID) SETUP_ANDROID_LIBRARY(${TARGET_DEFAULT_PREFIX}${PLUGIN_NAME}) ELSE() SET(TARGET_NAME ${PLUGIN_NAME} ) #MESSAGE("in -->SETUP_PLUGIN<-- ${TARGET_NAME}-->${TARGET_SRC} <--> ${TARGET_H}<--") ## we have set up the target label and targetname by taking into account global prfix (osgdb_) IF(NOT TARGET_TARGETNAME) SET(TARGET_TARGETNAME "${TARGET_DEFAULT_PREFIX}${TARGET_NAME}") ENDIF(NOT TARGET_TARGETNAME) IF(NOT TARGET_LABEL) SET(TARGET_LABEL "${TARGET_DEFAULT_LABEL_PREFIX} ${TARGET_NAME}") ENDIF(NOT TARGET_LABEL) ## plugins gets put in libopenscenegraph by default IF(${ARGC} GREATER 1) SET(PACKAGE_COMPONENT libopenscenegraph-${ARGV1}) ELSE(${ARGC} GREATER 1) SET(PACKAGE_COMPONENT libopenscenegraph) ENDIF(${ARGC} GREATER 1) # Add the VisualStudio versioning info SET(TARGET_SRC ${TARGET_SRC} ${OPENSCENEGRAPH_VERSIONINFO_RC}) # here we use the command to generate the library IF (DYNAMIC_OPENSCENEGRAPH) ADD_LIBRARY(${TARGET_TARGETNAME} MODULE ${TARGET_SRC} ${TARGET_H}) ELSE (DYNAMIC_OPENSCENEGRAPH) ADD_LIBRARY(${TARGET_TARGETNAME} STATIC ${TARGET_SRC} ${TARGET_H}) ENDIF(DYNAMIC_OPENSCENEGRAPH) IF(MSVC) IF(NOT CMAKE24) SET_OUTPUT_DIR_PROPERTY_260(${TARGET_TARGETNAME} "${OSG_PLUGINS}") # Sets the ouput to be /osgPlugin-X.X.X ; also ensures the /Debug /Release are removed ELSE(NOT CMAKE24) IF(OSG_MSVC_VERSIONED_DLL) #this is a hack... the build place is set to lib/ by LIBARARY_OUTPUT_PATH equal to OUTPUT_LIBDIR #the .lib will be crated in ../ so going straight in lib by the IMPORT_PREFIX property #because we want dll placed in OUTPUT_BINDIR ie the bin folder sibling of lib, we can use ../../bin to go there, #it is hardcoded, we should compute OUTPUT_BINDIR position relative to OUTPUT_LIBDIR ... to be implemented #changing bin to something else breaks this hack #the dll are placed in bin/${OSG_PLUGINS} IF(NOT MSVC_IDE) SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES PREFIX "../bin/${OSG_PLUGINS}/") ELSE(NOT MSVC_IDE) SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES PREFIX "../../bin/${OSG_PLUGINS}/" IMPORT_PREFIX "../") ENDIF(NOT MSVC_IDE) ELSE(OSG_MSVC_VERSIONED_DLL) #in standard mode (unversioned) the .lib and .dll are placed in lib//${OSG_PLUGINS}. #here the PREFIX property has been used, the same result would be accomplidhe by prepending ${OSG_PLUGINS}/ to OUTPUT_NAME target property SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES PREFIX "${OSG_PLUGINS}/") ENDIF(OSG_MSVC_VERSIONED_DLL) ENDIF(NOT CMAKE24) ENDIF(MSVC) SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES PROJECT_LABEL "${TARGET_LABEL}") SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES FOLDER "Plugins") IF(APPLE) SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES XCODE_ATTRIBUTE_WARNING_CFLAGS "") ENDIF() SETUP_LINK_LIBRARIES() #the installation path are differentiated for win32 that install in bib versus other architecture that install in lib${LIB_POSTFIX}/${OSG_PLUGINS} IF(WIN32) INSTALL(TARGETS ${TARGET_TARGETNAME} RUNTIME DESTINATION bin COMPONENT ${PACKAGE_COMPONENT} ARCHIVE DESTINATION lib/${OSG_PLUGINS} COMPONENT libopenscenegraph-dev LIBRARY DESTINATION bin/${OSG_PLUGINS} COMPONENT ${PACKAGE_COMPONENT}) ELSE(WIN32) INSTALL(TARGETS ${TARGET_TARGETNAME} RUNTIME DESTINATION bin COMPONENT ${PACKAGE_COMPONENT} ARCHIVE DESTINATION lib${LIB_POSTFIX}/${OSG_PLUGINS} COMPONENT libopenscenegraph-dev LIBRARY DESTINATION lib${LIB_POSTFIX}/${OSG_PLUGINS} COMPONENT ${PACKAGE_COMPONENT}) ENDIF(WIN32) ENDIF() ENDMACRO(SETUP_PLUGIN) ################################################################################################################# # this is the macro for example and application setup ########################################################### MACRO(SETUP_EXE IS_COMMANDLINE_APP) #MESSAGE("in -->SETUP_EXE<-- ${TARGET_NAME}-->${TARGET_SRC} <--> ${TARGET_H}<--") IF(NOT TARGET_TARGETNAME) SET(TARGET_TARGETNAME "${TARGET_DEFAULT_PREFIX}${TARGET_NAME}") ENDIF(NOT TARGET_TARGETNAME) IF(NOT TARGET_LABEL) SET(TARGET_LABEL "${TARGET_DEFAULT_LABEL_PREFIX} ${TARGET_NAME}") ENDIF(NOT TARGET_LABEL) IF(${IS_COMMANDLINE_APP}) ADD_EXECUTABLE(${TARGET_TARGETNAME} ${TARGET_SRC} ${TARGET_H}) ELSE(${IS_COMMANDLINE_APP}) IF(APPLE) # SET(MACOSX_BUNDLE_LONG_VERSION_STRING "${OPENSCENEGRAPH_MAJOR_VERSION}.${OPENSCENEGRAPH_MINOR_VERSION}.${OPENSCENEGRAPH_PATCH_VERSION}") # Short Version is the "marketing version". It is the version # the user sees in an information panel. SET(MACOSX_BUNDLE_SHORT_VERSION_STRING "${OPENSCENEGRAPH_MAJOR_VERSION}.${OPENSCENEGRAPH_MINOR_VERSION}.${OPENSCENEGRAPH_PATCH_VERSION}") # Bundle version is the version the OS looks at. SET(MACOSX_BUNDLE_BUNDLE_VERSION "${OPENSCENEGRAPH_MAJOR_VERSION}.${OPENSCENEGRAPH_MINOR_VERSION}.${OPENSCENEGRAPH_PATCH_VERSION}") SET(MACOSX_BUNDLE_GUI_IDENTIFIER "org.openscenegraph.${TARGET_TARGETNAME}" ) # replace underscore by hyphen STRING(REGEX REPLACE "_" "-" MACOSX_BUNDLE_GUI_IDENTIFIER ${MACOSX_BUNDLE_GUI_IDENTIFIER}) SET(MACOSX_BUNDLE_BUNDLE_NAME "${TARGET_NAME}" ) # SET(MACOSX_BUNDLE_ICON_FILE "myicon.icns") # SET(MACOSX_BUNDLE_COPYRIGHT "") # SET(MACOSX_BUNDLE_INFO_STRING "Info string, localized?") ENDIF(APPLE) IF(WIN32) IF (REQUIRE_WINMAIN_FLAG) SET(PLATFORM_SPECIFIC_CONTROL WIN32) ENDIF(REQUIRE_WINMAIN_FLAG) ENDIF(WIN32) IF(APPLE) IF(OSG_BUILD_APPLICATION_BUNDLES) SET(PLATFORM_SPECIFIC_CONTROL MACOSX_BUNDLE) ENDIF(OSG_BUILD_APPLICATION_BUNDLES) ENDIF(APPLE) ADD_EXECUTABLE(${TARGET_TARGETNAME} ${PLATFORM_SPECIFIC_CONTROL} ${TARGET_SRC} ${TARGET_H}) ENDIF(${IS_COMMANDLINE_APP}) SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES PROJECT_LABEL "${TARGET_LABEL}") SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES OUTPUT_NAME ${TARGET_NAME}) SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES DEBUG_OUTPUT_NAME "${TARGET_NAME}${CMAKE_DEBUG_POSTFIX}") SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES RELEASE_OUTPUT_NAME "${TARGET_NAME}${CMAKE_RELEASE_POSTFIX}") SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES RELWITHDEBINFO_OUTPUT_NAME "${TARGET_NAME}${CMAKE_RELWITHDEBINFO_POSTFIX}") SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES MINSIZEREL_OUTPUT_NAME "${TARGET_NAME}${CMAKE_MINSIZEREL_POSTFIX}") IF(MSVC_IDE AND OSG_MSVC_VERSIONED_DLL) SET_OUTPUT_DIR_PROPERTY_260(${TARGET_TARGETNAME} "") # Ensure the /Debug /Release are removed ENDIF(MSVC_IDE AND OSG_MSVC_VERSIONED_DLL) IF(APPLE) SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES XCODE_ATTRIBUTE_WARNING_CFLAGS "") ENDIF() SETUP_LINK_LIBRARIES() ENDMACRO(SETUP_EXE) # Takes optional second argument (is_commandline_app?) in ARGV1 MACRO(SETUP_APPLICATION APPLICATION_NAME) SET(TARGET_NAME ${APPLICATION_NAME} ) IF(${ARGC} GREATER 1) SET(IS_COMMANDLINE_APP ${ARGV1}) ELSE(${ARGC} GREATER 1) SET(IS_COMMANDLINE_APP 0) ENDIF(${ARGC} GREATER 1) SETUP_EXE(${IS_COMMANDLINE_APP}) SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES FOLDER "Applications") IF(APPLE) INSTALL(TARGETS ${TARGET_TARGETNAME} RUNTIME DESTINATION bin BUNDLE DESTINATION bin) ELSE(APPLE) INSTALL(TARGETS ${TARGET_TARGETNAME} RUNTIME DESTINATION bin COMPONENT openscenegraph ) ENDIF(APPLE) ENDMACRO(SETUP_APPLICATION) MACRO(SETUP_COMMANDLINE_APPLICATION APPLICATION_NAME) SETUP_APPLICATION(${APPLICATION_NAME} 1) ENDMACRO(SETUP_COMMANDLINE_APPLICATION) # Takes optional second argument (is_commandline_app?) in ARGV1 MACRO(SETUP_EXAMPLE EXAMPLE_NAME) SET(TARGET_NAME ${EXAMPLE_NAME} ) IF(${ARGC} GREATER 1) SET(IS_COMMANDLINE_APP ${ARGV1}) ELSE(${ARGC} GREATER 1) SET(IS_COMMANDLINE_APP 0) ENDIF(${ARGC} GREATER 1) SETUP_EXE(${IS_COMMANDLINE_APP}) SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES FOLDER "Examples") IF(APPLE) INSTALL(TARGETS ${TARGET_TARGETNAME} RUNTIME DESTINATION share/OpenSceneGraph/bin BUNDLE DESTINATION share/OpenSceneGraph/bin ) ELSE(APPLE) INSTALL(TARGETS ${TARGET_TARGETNAME} RUNTIME DESTINATION share/OpenSceneGraph/bin COMPONENT openscenegraph-examples ) ENDIF(APPLE) ENDMACRO(SETUP_EXAMPLE) MACRO(SETUP_COMMANDLINE_EXAMPLE EXAMPLE_NAME) SETUP_EXAMPLE(${EXAMPLE_NAME} 1) ENDMACRO(SETUP_COMMANDLINE_EXAMPLE) # Takes two optional arguments -- osg prefix and osg version MACRO(HANDLE_MSVC_DLL) #this is a hack... the build place is set to lib/ by LIBARARY_OUTPUT_PATH equal to OUTPUT_LIBDIR #the .lib will be crated in ../ so going straight in lib by the IMPORT_PREFIX property #because we want dll placed in OUTPUT_BINDIR ie the bin folder sibling of lib, we can use ../../bin to go there, #it is hardcoded, we should compute OUTPUT_BINDIR position relative to OUTPUT_LIBDIR ... to be implemented #changing bin to something else breaks this hack #the dll are versioned by prefixing the name with osg${OPENSCENEGRAPH_SOVERSION}- # LIB_PREFIX: use "osg" by default, else whatever we've been given. IF(${ARGC} GREATER 0) SET(LIB_PREFIX ${ARGV0}) ELSE(${ARGC} GREATER 0) SET(LIB_PREFIX osg) ENDIF(${ARGC} GREATER 0) # LIB_SOVERSION: use OSG's soversion by default, else whatever we've been given IF(${ARGC} GREATER 1) SET(LIB_SOVERSION ${ARGV1}) ELSE(${ARGC} GREATER 1) SET(LIB_SOVERSION ${OPENSCENEGRAPH_SOVERSION}) ENDIF(${ARGC} GREATER 1) SET_OUTPUT_DIR_PROPERTY_260(${LIB_NAME} "") # Ensure the /Debug /Release are removed IF(NOT MSVC_IDE) IF (NOT CMAKE24) BUILDER_VERSION_GREATER(2 8 0) IF(NOT VALID_BUILDER_VERSION) # If CMake < 2.8.1 SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES PREFIX "../bin/${LIB_PREFIX}${LIB_SOVERSION}-" IMPORT_PREFIX "../") ELSE(NOT VALID_BUILDER_VERSION) SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES PREFIX "${LIB_PREFIX}${LIB_SOVERSION}-") ENDIF(NOT VALID_BUILDER_VERSION) ELSE (NOT CMAKE24) SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES PREFIX "../bin/${LIB_PREFIX}${LIB_SOVERSION}-" IMPORT_PREFIX "../") SET(NEW_LIB_NAME "${OUTPUT_BINDIR}/${LIB_PREFIX}${LIB_SOVERSION}-${LIB_NAME}") ADD_CUSTOM_COMMAND( TARGET ${LIB_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${NEW_LIB_NAME}.lib" "${OUTPUT_LIBDIR}/${LIB_NAME}.lib" COMMAND ${CMAKE_COMMAND} -E copy "${NEW_LIB_NAME}.exp" "${OUTPUT_LIBDIR}/${LIB_NAME}.exp" COMMAND ${CMAKE_COMMAND} -E remove "${NEW_LIB_NAME}.lib" COMMAND ${CMAKE_COMMAND} -E remove "${NEW_LIB_NAME}.exp" ) ENDIF (NOT CMAKE24) ELSE(NOT MSVC_IDE) IF (NOT CMAKE24) BUILDER_VERSION_GREATER(2 8 0) IF(NOT VALID_BUILDER_VERSION) # If CMake < 2.8.1 SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES PREFIX "../../bin/${LIB_PREFIX}${LIB_SOVERSION}-" IMPORT_PREFIX "../") ELSE(NOT VALID_BUILDER_VERSION) SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES PREFIX "${LIB_PREFIX}${LIB_SOVERSION}-") ENDIF(NOT VALID_BUILDER_VERSION) ELSE (NOT CMAKE24) SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES PREFIX "../../bin/${LIB_PREFIX}${LIB_SOVERSION}-" IMPORT_PREFIX "../") ENDIF (NOT CMAKE24) ENDIF(NOT MSVC_IDE) # SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES PREFIX "../../bin/osg${OPENSCENEGRAPH_SOVERSION}-") # SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES IMPORT_PREFIX "../") ENDMACRO(HANDLE_MSVC_DLL) MACRO(REMOVE_CXX_FLAG flag) STRING(REPLACE "${flag}" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") ENDMACRO() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindPoppler-glib.cmake0000644000175000017500000000156211553272246025706 0ustar albertoalberto#use pkg-config to find various modues INCLUDE(FindPkgConfig OPTIONAL) IF(PKG_CONFIG_FOUND) INCLUDE(FindPkgConfig) PKG_CHECK_MODULES(CAIRO cairo) PKG_CHECK_MODULES(POPPLER poppler-glib) IF (POPPLER_FOUND) INCLUDE(CheckCXXSourceRuns) SET(CMAKE_REQUIRED_INCLUDES ${POPPLER_INCLUDE_DIRS}) # Do step by step checking, CHECK_CXX_SOURCE_RUNS(" #include #include int main() { #ifdef POPPLER_HAS_CAIRO return EXIT_SUCCESS; #else return EXIT_FAILURE #endif } " POPPLER_HAS_CAIRO) IF (NOT POPPLER_HAS_CAIRO) SET(POPPLER_FOUND FALSE) ENDIF() ENDIF() # IF (POPPLER_FOUND AND (NOT POPPLER_LIBRARIES OR NOT POPPLER_INCLUDE_DIRS) ) # SET(POPPLER_FOUND FALSE) # ENDIF() ENDIF() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/OsgCPackConfig.cmake.in0000644000175000017500000001021311553272246025727 0ustar albertoalberto# This file will be configured to contain variables for CPack. These variables # should be set in the CMake list file of the project before CPack module is # included. Example variables are: # CPACK_GENERATOR - Generator used to create package # CPACK_INSTALL_CMAKE_PROJECTS - For each project (path, name, component) # CPACK_CMAKE_GENERATOR - CMake Generator used for the projects # CPACK_INSTALL_COMMANDS - Extra commands to install components # CPACK_INSTALL_DIRECTORIES - Extra directories to install # CPACK_PACKAGE_DESCRIPTION_FILE - Description file for the package # CPACK_PACKAGE_DESCRIPTION_SUMMARY - Summary of the package # CPACK_PACKAGE_EXECUTABLES - List of pairs of executables and labels # CPACK_PACKAGE_FILE_NAME - Name of the package generated # CPACK_PACKAGE_ICON - Icon used for the package # CPACK_PACKAGE_INSTALL_DIRECTORY - Name of directory for the installer # CPACK_PACKAGE_NAME - Package project name # CPACK_PACKAGE_VENDOR - Package project vendor # CPACK_PACKAGE_VERSION - Package project version # CPACK_PACKAGE_VERSION_MAJOR - Package project version (major) # CPACK_PACKAGE_VERSION_MINOR - Package project version (minor) # CPACK_PACKAGE_VERSION_PATCH - Package project version (patch) # There are certain generator specific ones # NSIS Generator: # CPACK_PACKAGE_INSTALL_REGISTRY_KEY - Name of the registry key for the installer # CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS - Extra commands used during uninstall # CPACK_NSIS_EXTRA_INSTALL_COMMANDS - Extra commands used during install SET(CPACK_BINARY_BUNDLE "${CPACK_BINARY_BUNDLE}") SET(CPACK_BINARY_CYGWIN "${CPACK_BINARY_CYGWIN}") SET(CPACK_BINARY_DEB "${CPACK_BINARY_DEB}") SET(CPACK_BINARY_NSIS "${CPACK_BINARY_NSIS}") SET(CPACK_BINARY_OSXX11 "${CPACK_BINARY_OSXX11}") SET(CPACK_BINARY_PACKAGEMAKER "${CPACK_BINARY_PACKAGEMAKER}") SET(CPACK_BINARY_RPM "${CPACK_BINARY_RPM}") SET(CPACK_BINARY_STGZ "${CPACK_BINARY_STGZ}") SET(CPACK_BINARY_TBZ2 "${CPACK_BINARY_TBZ2}") SET(CPACK_BINARY_TGZ "${CPACK_BINARY_TGZ}") SET(CPACK_BINARY_TZ "${CPACK_BINARY_TZ}") SET(CPACK_BINARY_ZIP "${CPACK_BINARY_ZIP}") SET(CPACK_CMAKE_GENERATOR "${CMAKE_GENERATOR}") SET(CPACK_COMPONENTS_ALL "${CPACK_COMPONENTS_ALL}") SET(CPACK_COMPONENT_UNSPECIFIED_HIDDEN "TRUE") SET(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "TRUE") SET(CPACK_GENERATOR "${CPACK_GENERATOR}") SET(CPACK_INSTALL_CMAKE_PROJECTS "${OpenSceneGraph_BINARY_DIR};OpenSceneGraph;${OSG_CPACK_COMPONENT};/") SET(CPACK_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") SET(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") SET(CPACK_MODULE_PATH "${OpenSceneGraph_SOURCE_DIR}/CMakeModules;") SET(CPACK_NSIS_DISPLAY_NAME "${CMAKE_PROJECT_NAME} ${OPENSCENEGRAPH_VERSION}") SET(CPACK_NSIS_INSTALLER_ICON_CODE "") SET(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "") SET(CPACK_OUTPUT_CONFIG_FILE "${PROJECT_BINARY_DIR}/CPackConfig-${OSG_CPACK_COMPONENT}.cmake") SET(CPACK_PACKAGE_DEFAULT_LOCATION "/") SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenSceneGraph_SOURCE_DIR}/README.txt") SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The OpenSceneGraph is an open source high performance 3d graphics toolkit") SET(CPACK_PACKAGE_FILE_NAME "${OSG_PACKAGE_FILE_NAME}") SET(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_INSTALL_DIRECTORY}") SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${CMAKE_PROJECT_NAME}-${OPENSCENEGRAPH_VERSION}") SET(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME}") SET(CPACK_PACKAGE_RELOCATABLE "true") SET(CPACK_PACKAGE_VENDOR "The OpenSceneGraph developers and contributors lead by Robert Osfield") SET(CPACK_PACKAGE_VERSION "${OPENSCENEGRAPH_VERSION}") SET(CPACK_PACKAGE_VERSION_MAJOR "${OPENSCENEGRAPH_MAJOR_VERSION}") SET(CPACK_PACKAGE_VERSION_MINOR "${OPENSCENEGRAPH_MINOR_VERSION}") SET(CPACK_PACKAGE_VERSION_PATCH "${OPENSCENEGRAPH_PATCH_VERSION}") SET(CPACK_RESOURCE_FILE_LICENSE "${OpenSceneGraph_SOURCE_DIR}/LICENSE.txt") SET(CPACK_RESOURCE_FILE_README "${OpenSceneGraph_SOURCE_DIR}/README.txt") SET(CPACK_RESOURCE_FILE_WELCOME "${OpenSceneGraph_SOURCE_DIR}/NEWS.txt") SET(CPACK_STRIP_FILES "ON") openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/CheckAtomicOps.cmake0000644000175000017500000001124312433611070025370 0ustar albertoalberto# Check for availability of atomic operations # This module defines # OPENTHREADS_HAVE_ATOMIC_OPS OPTION(OPENTHREADS_ATOMIC_USE_MUTEX "Set to ON to force OpenThreads to use a mutex for Atmoic." OFF) IF (OPENTHREADS_ATOMIC_USE_MUTEX) SET(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS 0) SET(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS 0) SET(_OPENTHREADS_ATOMIC_USE_SUN 0) SET(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED 0) SET(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC 0) SET(_OPENTHREADS_ATOMIC_USE_MUTEX 1) ELSE() # as the test does not work for IOS hardcode the ATOMIC implementation IF(OSG_BUILD_PLATFORM_IPHONE_SIMULATOR OR OSG_BUILD_PLATFORM_IPHONE) SET(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS 0) SET(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS 0) SET(_OPENTHREADS_ATOMIC_USE_SUN 0) SET(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED 0) SET(_OPENTHREADS_ATOMIC_USE_MUTEX 0) SET(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC 1) ELSE() INCLUDE(CheckCXXSourceRuns) # Do step by step checking, CHECK_CXX_SOURCE_RUNS(" #include int main() { unsigned value = 0; void* ptr = &value; __sync_add_and_fetch(&value, 1); __sync_synchronize(); __sync_sub_and_fetch(&value, 1); if (!__sync_bool_compare_and_swap(&value, 0, 1)) return EXIT_FAILURE; if (!__sync_bool_compare_and_swap(&ptr, ptr, ptr)) return EXIT_FAILURE; return EXIT_SUCCESS; } " _OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) CHECK_CXX_SOURCE_RUNS(" #include int main(int, const char**) { unsigned value = 0; void* ptr = &value; __add_and_fetch(&value, 1); __synchronize(value); __sub_and_fetch(&value, 1); if (!__compare_and_swap(&value, 0, 1)) return EXIT_FAILURE; if (!__compare_and_swap((unsigned long*)&ptr, (unsigned long)ptr, (unsigned long)ptr)) return EXIT_FAILURE; return EXIT_SUCCESS; } " _OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS) CHECK_CXX_SOURCE_RUNS(" #include #include int main(int, const char**) { uint_t value = 0; void* ptr = &value; atomic_inc_uint_nv(&value); membar_consumer(); atomic_dec_uint_nv(&value); if (0 != atomic_cas_uint(&value, 0, 1)) return EXIT_FAILURE; if (ptr != atomic_cas_ptr(&ptr, ptr, ptr)) return EXIT_FAILURE; return EXIT_SUCCESS; } " _OPENTHREADS_ATOMIC_USE_SUN) CHECK_CXX_SOURCE_RUNS(" #include #include #include #pragma intrinsic(_InterlockedAnd) #pragma intrinsic(_InterlockedOr) #pragma intrinsic(_InterlockedXor) int main(int, const char**) { volatile long value = 0; long data = 0; long* volatile ptr = &data; InterlockedIncrement(&value); MemoryBarrier(); InterlockedDecrement(&value); if (0 != InterlockedCompareExchange(&value, 1, 0)) return EXIT_FAILURE; if (ptr != InterlockedCompareExchangePointer((PVOID volatile*)&ptr, (PVOID)ptr, (PVOID)ptr)) return EXIT_FAILURE; return EXIT_SUCCESS; } " _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) CHECK_CXX_SOURCE_RUNS(" #include int main() { volatile int32_t value = 0; long data = 0; long * volatile ptr = &data; OSAtomicIncrement32(&value); OSMemoryBarrier(); OSAtomicDecrement32(&value); OSAtomicCompareAndSwapInt(value, 1, &value); OSAtomicCompareAndSwapPtr(ptr, ptr, (void * volatile *)&ptr); } " _OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) IF(NOT _OPENTHREADS_ATOMIC_USE_GCC_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_SUN AND NOT _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED AND NOT _OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) SET(_OPENTHREADS_ATOMIC_USE_MUTEX 1) ENDIF() # MinGW can set both WIN32_INTERLOCKED and GCC_BUILTINS to true which results in compliation errors IF (_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS AND _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) # In this case we prefer the GCC_BUILTINS SET(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS 1) SET(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED 0) ENDIF() ENDIF() ENDIF() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindCoreVideo.cmake0000644000175000017500000000124311553272246025225 0ustar albertoalberto# Locate Apple CoreVideo (next-generation QuickTime) # This module defines # COREVIDEO_LIBRARY # COREVIDEO_FOUND, if false, do not try to link to gdal # COREVIDEO_INCLUDE_DIR, where to find the headers # # $COREVIDEO_DIR is an environment variable that would # correspond to the ./configure --prefix=$COREVIDEO_DIR # # Created by Eric Wing. # CoreVideo on OS X looks different than CoreVideo for Windows, # so I am going to case the two. IF(APPLE) FIND_PATH(COREVIDEO_INCLUDE_DIR CoreVideo/CoreVideo.h) FIND_LIBRARY(COREVIDEO_LIBRARY CoreVideo) ENDIF() SET(COREVIDEO_FOUND "NO") IF(COREVIDEO_LIBRARY AND COREVIDEO_INCLUDE_DIR) SET(COREVIDEO_FOUND "YES") ENDIF() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindCoreMedia.cmake0000644000175000017500000000106512032572420025166 0ustar albertoalberto# Locate Apple CoreMedia # This module defines # COREMEDIA_LIBRARY # COREMEDIA_FOUND, if false, do not try to link to gdal # COREMEDIA_INCLUDE_DIR, where to find the headers # # $COREMEDIA_DIR is an environment variable that would # correspond to the ./configure --prefix=$COREMEDIA_DIR # # Created by Stephan Maximilian Huber. IF(APPLE) FIND_PATH(COREMEDIA_INCLUDE_DIR CoreMedia/CoreMedia.h) FIND_LIBRARY(COREMEDIA_LIBRARY CoreMedia) ENDIF() SET(COREMEDIA_FOUND "NO") IF(COREMEDIA_LIBRARY AND COREMEDIA_INCLUDE_DIR) SET(COREMEDIA_FOUND "YES") ENDIF() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindQTKit.cmake0000644000175000017500000000307111575621602024341 0ustar albertoalberto# Locate Apple QTKit (next-generation QuickTime) # This module defines # QTKIT_LIBRARY # QTKIT_FOUND, if false, do not try to link to gdal # QTKIT_INCLUDE_DIR, where to find the headers # # $QTKIT_DIR is an environment variable that would # correspond to the ./configure --prefix=$QTKIT_DIR # # Created by Eric Wing. # QTKit on OS X looks different than QTKit for Windows, # so I am going to case the two. IF(APPLE) FIND_PATH(QTKIT_INCLUDE_DIR QTKit/QTKit.h) FIND_LIBRARY(QTKIT_LIBRARY QTKit) ENDIF() SET(QTKIT_FOUND "NO") IF(QTKIT_LIBRARY AND QTKIT_INCLUDE_DIR) SET(QTKIT_FOUND "YES") ENDIF() IF(OSG_BUILD_PLATFORM_IPHONE OR OSG_BUILD_PLATFORM_IPHONE_SIMULATOR) SET(QTKIT_FOUND "NO") ENDIF() IF(APPLE) # Technically QTKit is 64-bit capable, but the QTKit plug-in currently uses # a few 32-bit only APIs to bridge QTKit and Core Video. # As such, the plugin won't compile for 64-bit until Apple fixes this hole # in their API. # For simplicitly, I pretend QTKit is only 32-bit, but if/when Apple fixes # this, we need an OS version check. # Snow Leopard still lacks a 64-bit path for this. #First check to see if we are running with a native 64-bit compiler (10.6 default) and implicit arch IF(NOT CMAKE_OSX_ARCHITECTURES AND CMAKE_SIZEOF_VOID_P EQUAL 8) SET(QTKIT_FOUND "NO") ELSE() #Otherwise check to see if 64-bit is explicitly called for. LIST(FIND CMAKE_OSX_ARCHITECTURES "x86_64" has64Compile) IF(NOT has64Compile EQUAL -1) SET(QTKIT_FOUND "NO") ENDIF() ENDIF() ENDIF() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/cmake_uninstall.cmake.in0000644000175000017500000000212211536127114026312 0ustar albertoalbertoIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") ENDIF() FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) STRING(REGEX REPLACE "\n" ";" files "${files}") FOREACH(file ${files}) MESSAGE(STATUS "Uninstalling \"${file}\"") IF(EXISTS "${file}") EXEC_PROGRAM( "@CMAKE_COMMAND@" ARGS "-E remove \"${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) IF(NOT "${rm_retval}" STREQUAL 0) MESSAGE(FATAL_ERROR "Problem when removing \"${file}\"") ENDIF() ELSEIF(IS_SYMLINK "${file}") EXEC_PROGRAM( "@CMAKE_COMMAND@" ARGS "-E remove \"${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) IF(NOT "${rm_retval}" STREQUAL 0) MESSAGE(FATAL_ERROR "Problem when removing \"${file}\"") ENDIF() ELSE() MESSAGE(STATUS "File \"${file}\" does not exist.") ENDIF() ENDFOREACH() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindOpenThreads.cmake0000644000175000017500000001323210737510122025552 0ustar albertoalberto# OpenThreads is a C++ based threading library. Its largest userbase # seems to OpenSceneGraph so you might notice I accept OSGDIR as an # environment path. # I consider this part of the Findosg* suite used to find OpenSceneGraph # components. # Each component is separate and you must opt in to each module. # # Locate OpenThreads # This module defines # OPENTHREADS_LIBRARY # OPENTHREADS_FOUND, if false, do not try to link to OpenThreads # OPENTHREADS_INCLUDE_DIR, where to find the headers # # $OPENTHREADS_DIR is an environment variable that would # correspond to the ./configure --prefix=$OPENTHREADS_DIR # used in building osg. # # Created by Eric Wing. # Header files are presumed to be included like # #include # To make it easier for one-step automated configuration/builds, # we leverage environmental paths. This is preferable # to the -DVAR=value switches because it insulates the # users from changes we may make in this script. # It also offers a little more flexibility than setting # the CMAKE_*_PATH since we can target specific components. # However, the default CMake behavior will search system paths # before anything else. This is problematic in the cases # where you have an older (stable) version installed, but # are trying to build a newer version. # CMake doesn't offer a nice way to globally control this behavior # so we have to do a nasty "double FIND_" in this module. # The first FIND disables the CMAKE_ search paths and only checks # the environmental paths. # If nothing is found, then the second find will search the # standard install paths. # Explicit -DVAR=value arguments should still be able to override everything. # Note: We have added an additional check for ${CMAKE_PREFIX_PATH}. # This is not an official CMake variable, but one we are proposing be # added to CMake. Be warned that this may go away or the variable name # may change. FIND_PATH(OPENTHREADS_INCLUDE_DIR OpenThreads/Thread PATHS $ENV{OPENTHREADS_INCLUDE_DIR} $ENV{OPENTHREADS_DIR}/include $ENV{OPENTHREADS_DIR} $ENV{OSG_INCLUDE_DIR} $ENV{OSG_DIR}/include $ENV{OSG_DIR} $ENV{OSGDIR}/include $ENV{OSGDIR} NO_DEFAULT_PATH ) FIND_PATH(OPENTHREADS_INCLUDE_DIR OpenThreads/Thread PATHS ${CMAKE_PREFIX_PATH} # Unofficial: We are proposing this. NO_DEFAULT_PATH PATH_SUFFIXES include ) FIND_PATH(OPENTHREADS_INCLUDE_DIR OpenThreads/Thread ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OpenThreads_ROOT]/include [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OSG_ROOT]/include ) FIND_LIBRARY(OPENTHREADS_LIBRARY NAMES OpenThreads OpenThreadsWin32 PATHS $ENV{OPENTHREADS_LIBRARY_DIR} $ENV{OPENTHREADS_DIR}/lib64 $ENV{OPENTHREADS_DIR}/lib $ENV{OPENTHREADS_DIR} $ENV{OSG_LIBRARY_DIR} $ENV{OSG_DIR}/lib64 $ENV{OSG_DIR}/lib $ENV{OSG_DIR} $ENV{OSGDIR}/lib64 $ENV{OSGDIR}/lib $ENV{OSGDIR} NO_DEFAULT_PATH ) FIND_LIBRARY(OPENTHREADS_LIBRARY NAMES OpenThreads OpenThreadsWin32 PATHS ${CMAKE_PREFIX_PATH} # Unofficial: We are proposing this. NO_DEFAULT_PATH PATH_SUFFIXES lib64 lib ) FIND_LIBRARY(OPENTHREADS_LIBRARY NAMES OpenThreads OpenThreadsWin32 PATHS ~/Library/Frameworks /Library/Frameworks /usr/local/lib64 /usr/local/lib /usr/lib64 /usr/lib /sw/lib64 /sw/lib /opt/local/lib64 /opt/local/lib /opt/csw/lib64 /opt/csw/lib /opt/lib64 /opt/lib [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OpenThreads_ROOT]/lib [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OSG_ROOT]/lib ) FIND_LIBRARY(OPENTHREADS_LIBRARY_DEBUG NAMES OpenThreadsd OpenThreadsWin32d PATHS $ENV{OPENTHREADS_DEBUG_LIBRARY_DIR} $ENV{OPENTHREADS_LIBRARY_DIR} $ENV{OPENTHREADS_DIR}/lib64 $ENV{OPENTHREADS_DIR}/lib $ENV{OPENTHREADS_DIR} $ENV{OSG_LIBRARY_DIR} $ENV{OSG_DIR}/lib64 $ENV{OSG_DIR}/lib $ENV{OSG_DIR} $ENV{OSGDIR}/lib64 $ENV{OSGDIR}/lib $ENV{OSGDIR} NO_DEFAULT_PATH ) FIND_LIBRARY(OPENTHREADS_LIBRARY_DEBUG NAMES OpenThreadsd OpenThreadsWin32d PATHS ${CMAKE_PREFIX_PATH} # Unofficial: We are proposing this. NO_DEFAULT_PATH PATH_SUFFIXES lib64 lib ) FIND_LIBRARY(OPENTHREADS_LIBRARY_DEBUG NAMES OpenThreadsd OpenThreadsWin32d PATHS /usr/local/lib64 /usr/local/lib /usr/lib64 /usr/lib /sw/lib64 /sw/lib /opt/local/lib64 /opt/local/lib /opt/csw/lib64 /opt/csw/lib /opt/lib64 /opt/lib [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OpenThreads_ROOT]/lib [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OSG_ROOT]/lib ) IF(OPENTHREADS_LIBRARY) IF(NOT OPENTHREADS_LIBRARY_DEBUG) #MESSAGE("-- Warning Debug OpenThreads not found, using: ${OPENTHREADS_LIBRARY}") #SET(OPENTHREADS_LIBRARY_DEBUG "${OPENTHREADS_LIBRARY}") SET(OPENTHREADS_LIBRARY_DEBUG "${OPENTHREADS_LIBRARY}" CACHE FILEPATH "Debug version of OpenThreads Library (use regular version if not available)" FORCE) ENDIF(NOT OPENTHREADS_LIBRARY_DEBUG) ENDIF(OPENTHREADS_LIBRARY) SET(OPENTHREADS_FOUND "NO") IF(OPENTHREADS_INCLUDE_DIR AND OPENTHREADS_LIBRARY) SET(OPENTHREADS_FOUND "YES") # MESSAGE("-- Found OpenThreads: "${OPENTHREADS_LIBRARY}) ENDIF(OPENTHREADS_INCLUDE_DIR AND OPENTHREADS_LIBRARY) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindGtkGl.cmake0000644000175000017500000000046311553272246024361 0ustar albertoalberto#use pkg-config to find various modues INCLUDE(FindPkgConfig OPTIONAL) IF(PKG_CONFIG_FOUND) INCLUDE(FindPkgConfig) PKG_CHECK_MODULES(GTK gtk+-2.0) IF(WIN32) PKG_CHECK_MODULES(GTKGL gtkglext-win32-1.0) ELSE() PKG_CHECK_MODULES(GTKGL gtkglext-x11-1.0) ENDIF() ENDIF() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindFLTK.cmake0000644000175000017500000000233211467017442024105 0ustar albertoalberto# Locate FLTK # This module defines # FLTK_LIBRARY # FLTK_FOUND, if false, do not try to link to gdal # FLTK_INCLUDE_DIR, where to find the headers # # $FLTK_DIR is an environment variable that would # correspond to the ./configure --prefix=$FLTK_DIR # # Created by Robert Osfield. FIND_PATH(FLTK_INCLUDE_DIR Fl/Fl.H Fl/Fl.h $ENV{FLTK_DIR}/include $ENV{FLTK_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include ) MACRO(FIND_FLTK_LIBRARY MYLIBRARY MYLIBRARYNAME) FIND_LIBRARY(${MYLIBRARY} NAMES ${MYLIBRARYNAME} PATHS $ENV{FLTK_DIR}/lib $ENV{FLTK_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) ENDMACRO(FIND_FLTK_LIBRARY LIBRARY LIBRARYNAME) FIND_FLTK_LIBRARY(FLTK_LIBRARY fltk) FIND_FLTK_LIBRARY(FLTK_GL_LIBRARY fltk_gl) SET(FLTK_FOUND "NO") IF(FLTK_LIBRARY AND FLTK_INCLUDE_DIR) SET(FLTK_FOUND "YES") ENDIF(FLTK_LIBRARY AND FLTK_INCLUDE_DIR) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/ListHandle.cmake0000644000175000017500000000626410637677072024614 0ustar albertoalberto#miscellaneous macros ################### macros from http://www.cmake.org/Wiki/CMakeMacroListOperations MACRO(CAR var) SET(${var} ${ARGV1}) ENDMACRO(CAR) MACRO(CDR var junk) SET(${var} ${ARGN}) ENDMACRO(CDR) MACRO(LIST_INDEX var index) SET(list . ${ARGN}) FOREACH(i RANGE 1 ${index}) CDR(list ${list}) ENDFOREACH(i) CAR(${var} ${list}) ENDMACRO(LIST_INDEX) ######### LIST_CONTAINS usage #SET(MYLIST hello world foo bar) #LIST_CONTAINS(contains foo ${MYLIST}) #IF (contains) # MESSAGE("MYLIST contains foo") #ENDIF (contains) #LIST_CONTAINS(contains baz ${MYLIST}) #IF (NOT contains) # MESSAGE("MYLIST does not contain baz") #ENDIF (NOT contains) MACRO(LIST_CONTAINS var value) SET(${var}) FOREACH (value2 ${ARGN}) IF (${value} STREQUAL ${value2}) SET(${var} TRUE) ENDIF (${value} STREQUAL ${value2}) ENDFOREACH (value2) ENDMACRO(LIST_CONTAINS) ############################################################ ################### macros from http://www.cmake.org/Wiki/CMakeMacroParseArguments MACRO(PARSE_ARGUMENTS prefix arg_names option_names) #MESSAGE("!!!! ${prefix} args-->${arg_names}<-- opt-->${option_names}<--") SET(DEFAULT_ARGS) FOREACH(arg_name ${arg_names}) SET(${prefix}_${arg_name}) ENDFOREACH(arg_name) FOREACH(option ${option_names}) SET(${prefix}_${option} FALSE) ENDFOREACH(option) SET(current_arg_name DEFAULT_ARGS) SET(current_arg_list) FOREACH(arg ${ARGN}) #debug#MESSAGE("---->${arg}<------") LIST_CONTAINS(is_arg_name ${arg} ${arg_names}) IF (is_arg_name) SET(${prefix}_${current_arg_name} ${current_arg_list}) SET(current_arg_name ${arg}) SET(current_arg_list) ELSE (is_arg_name) LIST_CONTAINS(is_option ${arg} ${option_names}) IF (is_option) SET(${prefix}_${arg} TRUE) ELSE (is_option) SET(current_arg_list ${current_arg_list} ${arg}) ENDIF (is_option) ENDIF (is_arg_name) ENDFOREACH(arg) SET(${prefix}_${current_arg_name} ${current_arg_list}) ENDMACRO(PARSE_ARGUMENTS) ############################################################# #MACRO(SHOW_USAGE_OF_PARSE_ARGUMENTS) # PARSE_ARGUMENTS(PLUGIN # "EXPORTS;AUTOLOAD_SCRIPTS;LINK_LIBRARIES;DEPENDS" # "AUTO_INSTALL;NO_MODULE" # ${ARGN} # ) # CAR(PLUGIN_NAME ${PLUGIN_DEFAULT_ARGS}) # CDR(PLUGIN_SOURCES ${PLUGIN_DEFAULT_ARGS}) # # MESSAGE("*** Arguments for ${PLUGIN_NAME}") # MESSAGE("Sources: ${PLUGIN_SOURCES}") # MESSAGE("Exports: ${PLUGIN_EXPORTS}") # MESSAGE("Autoload scripts: ${PLUGIN_AUTOLOAD_SCRIPTS}") # MESSAGE("Link libraries: ${PLUGIN_LINK_LIBRARIES}") # MESSAGE("Depends: ${PLUGIN_DEPENDS}") # IF (PLUGIN_AUTO_INSTALL) # MESSAGE("Auto install") # ENDIF (PLUGIN_AUTO_INSTALL) # IF (PLUGIN_NO_MODULE) # MESSAGE("No module") # ENDIF (PLUGIN_NO_MODULE) #ENDMACRO(SHOW_USAGE_OF_PARSE_ARGUMENTS) #examples #SHOW_USAGE_OF_PARSE_ARGUMENTS(MyAppCore NO_MODULE CoreSource1.cxx CoreSource2.cxx EXPORTS RequiredObject1 RequredObject2 AUTOLOAD_SCRIPTS startup.py initialize.py) #SHOW_USAGE_OF_PARSE_ARGUMENTS(MyAppDefaultComponents # Component1.cxx Component2.cxx # EXPORTS Component1 Component2 # DEPENDS MyAppCore # AUTO_INSTALL # ) ######################################################## openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindFFmpeg.cmake0000644000175000017500000001166412104450213024503 0ustar albertoalberto# Locate ffmpeg # This module defines # FFMPEG_LIBRARIES # FFMPEG_FOUND, if false, do not try to link to ffmpeg # FFMPEG_INCLUDE_DIR, where to find the headers # # $FFMPEG_DIR is an environment variable that would # correspond to the ./configure --prefix=$FFMPEG_DIR # # Created by Robert Osfield. #In ffmpeg code, old version use "#include " and newer use "#include " #In OSG ffmpeg plugin, we used "#include " for compatibility with old version of ffmpeg #With the new version of FFmpeg, a file named "time.h" was added that breaks compatability with the old version of ffmpeg. #We have to search the path which contain the header.h (usefull for old version) #and search the path which contain the libname/header.h (usefull for new version) #Then we need to include ${FFMPEG_libname_INCLUDE_DIRS} (in old version case, use by ffmpeg header and osg plugin code) # (in new version case, use by ffmpeg header) #and ${FFMPEG_libname_INCLUDE_DIRS/libname} (in new version case, use by osg plugin code) # Macro to find header and lib directories # example: FFMPEG_FIND(AVFORMAT avformat avformat.h) MACRO(FFMPEG_FIND varname shortname headername) # old version of ffmpeg put header in $prefix/include/[ffmpeg] # so try to find header in include directory FIND_PATH(FFMPEG_${varname}_INCLUDE_DIRS lib${shortname}/${headername} PATHS ${FFMPEG_ROOT}/include $ENV{FFMPEG_DIR}/include ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include PATH_SUFFIXES ffmpeg DOC "Location of FFMPEG Headers" ) FIND_PATH(FFMPEG_${varname}_INCLUDE_DIRS ${headername} PATHS ${FFMPEG_ROOT}/include $ENV{FFMPEG_DIR}/include ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include PATH_SUFFIXES ffmpeg DOC "Location of FFMPEG Headers" ) FIND_LIBRARY(FFMPEG_${varname}_LIBRARIES NAMES ${shortname} PATHS ${FFMPEG_ROOT}/lib $ENV{FFMPEG_DIR}/lib ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/local/lib64 /usr/lib /usr/lib64 /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 DOC "Location of FFMPEG Libraries" ) IF (FFMPEG_${varname}_LIBRARIES AND FFMPEG_${varname}_INCLUDE_DIRS) SET(FFMPEG_${varname}_FOUND 1) ENDIF(FFMPEG_${varname}_LIBRARIES AND FFMPEG_${varname}_INCLUDE_DIRS) ENDMACRO(FFMPEG_FIND) SET(FFMPEG_ROOT "$ENV{FFMPEG_DIR}" CACHE PATH "Location of FFMPEG") # find stdint.h IF(WIN32) FIND_PATH(FFMPEG_STDINT_INCLUDE_DIR stdint.h PATHS ${FFMPEG_ROOT}/include $ENV{FFMPEG_DIR}/include ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include PATH_SUFFIXES ffmpeg DOC "Location of FFMPEG stdint.h Header" ) IF (FFMPEG_STDINT_INCLUDE_DIR) SET(STDINT_OK TRUE) ENDIF() ELSE() SET(STDINT_OK TRUE) ENDIF() FFMPEG_FIND(LIBAVFORMAT avformat avformat.h) FFMPEG_FIND(LIBAVDEVICE avdevice avdevice.h) FFMPEG_FIND(LIBAVCODEC avcodec avcodec.h) FFMPEG_FIND(LIBAVUTIL avutil avutil.h) FFMPEG_FIND(LIBSWSCALE swscale swscale.h) # not sure about the header to look for here. SET(FFMPEG_FOUND "NO") # Note we don't check FFMPEG_LIBSWSCALE_FOUND here, it's optional. IF (FFMPEG_LIBAVFORMAT_FOUND AND FFMPEG_LIBAVDEVICE_FOUND AND FFMPEG_LIBAVCODEC_FOUND AND FFMPEG_LIBAVUTIL_FOUND AND STDINT_OK) SET(FFMPEG_FOUND "YES") SET(FFMPEG_INCLUDE_DIRS ${FFMPEG_LIBAVFORMAT_INCLUDE_DIRS} ${FFMPEG_LIBAVDEVICE_INCLUDE_DIRS} ${FFMPEG_LIBAVCODEC_INCLUDE_DIRS} ${FFMPEG_LIBAVUTIL_INCLUDE_DIRS} ) # Using the new include style for FFmpeg prevents issues with #include IF (FFMPEG_STDINT_INCLUDE_DIR) SET(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} ${FFMPEG_STDINT_INCLUDE_DIR} ) ENDIF() SET(FFMPEG_LIBRARY_DIRS ${FFMPEG_LIBAVFORMAT_LIBRARY_DIRS}) # Note we don't add FFMPEG_LIBSWSCALE_LIBRARIES here, it will be added if found later. SET(FFMPEG_LIBRARIES ${FFMPEG_LIBAVFORMAT_LIBRARIES} ${FFMPEG_LIBAVDEVICE_LIBRARIES} ${FFMPEG_LIBAVCODEC_LIBRARIES} ${FFMPEG_LIBAVUTIL_LIBRARIES}) ELSE () # MESSAGE(STATUS "Could not find FFMPEG") ENDIF() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/ModuleInstall.cmake0000644000175000017500000000302711536374114025321 0ustar albertoalberto# INSTALL and SOURCE_GROUP commands for OSG/OT/Producer Modules # Required Vars: # ${LIB_NAME} # ${TARGET_H} SET(INSTALL_INCDIR include) SET(INSTALL_BINDIR bin) IF(WIN32) SET(INSTALL_LIBDIR bin) SET(INSTALL_ARCHIVEDIR lib) ELSE() SET(INSTALL_LIBDIR lib${LIB_POSTFIX}) SET(INSTALL_ARCHIVEDIR lib${LIB_POSTFIX}) ENDIF() SET(HEADERS_GROUP "Header Files") SOURCE_GROUP( ${HEADERS_GROUP} FILES ${TARGET_H} ) IF(MSVC AND OSG_MSVC_VERSIONED_DLL) HANDLE_MSVC_DLL() ENDIF() IF(ANDROID) INSTALL ( FILES ${TARGET_H} DESTINATION ${INSTALL_INCDIR}/${LIB_NAME} COMPONENT libopenscenegraph-dev ) ELSE(ANDROID) INSTALL( TARGETS ${LIB_NAME} RUNTIME DESTINATION ${INSTALL_BINDIR} COMPONENT libopenscenegraph LIBRARY DESTINATION ${INSTALL_LIBDIR} COMPONENT libopenscenegraph ARCHIVE DESTINATION ${INSTALL_ARCHIVEDIR} COMPONENT libopenscenegraph-dev ) IF(NOT OSG_COMPILE_FRAMEWORKS) INSTALL ( FILES ${TARGET_H} DESTINATION ${INSTALL_INCDIR}/${LIB_NAME} COMPONENT libopenscenegraph-dev ) ELSE() SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) SET(CMAKE_INSTALL_RPATH "${OSG_COMPILE_FRAMEWORKS_INSTALL_NAME_DIR}") SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES FRAMEWORK TRUE FRAMEWORK_VERSION ${OPENSCENEGRAPH_SOVERSION} PUBLIC_HEADER "${TARGET_H}" INSTALL_NAME_DIR "${OSG_COMPILE_FRAMEWORKS_INSTALL_NAME_DIR}" ) # MESSAGE("${OSG_COMPILE_FRAMEWORKS_INSTALL_NAME_DIR}") ENDIF() ENDIF(ANDROID) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindPerformer.cmake0000644000175000017500000000323411204232725025300 0ustar albertoalberto# Locate Performer # This module defines # PERFORMER_LIBRARY # PERFORMER_FOUND, if false, do not try to link to gdal # PERFORMER_INCLUDE_DIR, where to find the headers # # $PERFORMER_DIR is an environment variable that would # correspond to the ./configure --prefix=$PERFORMER_DIR # # Created by Robert Osfield. FIND_PATH(PERFORMER_INCLUDE_DIR Performer/pfdu.h $ENV{PFROOT}/include $ENV{PFROOT} $ENV{PERFORMER_DIR}/include $ENV{PERFORMER_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include ) IF(MSVC) FIND_LIBRARY(PERFORMER_LIBRARY NAMES libpf PATHS $ENV{PFROOT}/lib $ENV{PFROOT} $ENV{PERFORMER_DIR}/lib $ENV{PERFORMER_DIR} $ENV{OSGDIR}/lib $ENV{OSGDIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) ELSE(MSVC) FIND_LIBRARY(PERFORMER_LIBRARY NAMES pf PATHS $ENV{PFROOT}/lib $ENV{PFROOT} $ENV{PERFORMER_DIR}/lib $ENV{PERFORMER_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) ENDIF(MSVC) SET(PERFORMER_FOUND "NO") IF(PERFORMER_LIBRARY AND PERFORMER_INCLUDE_DIR) SET(PERFORMER_FOUND "YES") ENDIF(PERFORMER_LIBRARY AND PERFORMER_INCLUDE_DIR) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindOSG.cmake0000644000175000017500000000731712262502043023773 0ustar albertoalberto# Locate gdal # This module defines # OSG_LIBRARY # OSG_FOUND, if false, do not try to link to gdal # OSG_INCLUDE_DIR, where to find the headers # # $OSG_DIR is an environment variable that would # correspond to the ./configure --prefix=$OSG_DIR # # Created by Robert Osfield. FIND_PATH(OSG_INCLUDE_DIR osg/Node ${OSG_DIR}/include $ENV{OSG_DIR}/include $ENV{OSG_DIR} $ENV{OSGDIR}/include $ENV{OSGDIR} $ENV{OSG_ROOT}/include NO_DEFAULT_PATH ) FIND_PATH(OSG_INCLUDE_DIR osg/Node) MACRO(FIND_OSG_LIBRARY MYLIBRARY MYLIBRARYNAME) FIND_LIBRARY("${MYLIBRARY}_DEBUG" NAMES "${MYLIBRARYNAME}${CMAKE_DEBUG_POSTFIX}" PATHS ${OSG_DIR}/lib/Debug ${OSG_DIR}/lib64/Debug ${OSG_DIR}/lib ${OSG_DIR}/lib64 $ENV{OSG_DIR}/lib/debug $ENV{OSG_DIR}/lib64/debug $ENV{OSG_DIR}/lib $ENV{OSG_DIR}/lib64 $ENV{OSG_DIR} $ENV{OSGDIR}/lib $ENV{OSGDIR}/lib64 $ENV{OSGDIR} $ENV{OSG_ROOT}/lib $ENV{OSG_ROOT}/lib64 NO_DEFAULT_PATH ) FIND_LIBRARY("${MYLIBRARY}_DEBUG" NAMES "${MYLIBRARYNAME}${CMAKE_DEBUG_POSTFIX}" PATHS ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/local/lib64 /usr/lib /usr/lib64 /sw/lib /opt/local/lib /opt/csw/lib /opt/lib [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OSG_ROOT]/lib /usr/freeware/lib64 ) FIND_LIBRARY(${MYLIBRARY} NAMES "${MYLIBRARYNAME}${CMAKE_RELEASE_POSTFIX}" PATHS ${OSG_DIR}/lib/Release ${OSG_DIR}/lib64/Release ${OSG_DIR}/lib ${OSG_DIR}/lib64 $ENV{OSG_DIR}/lib/Release $ENV{OSG_DIR}/lib64/Release $ENV{OSG_DIR}/lib $ENV{OSG_DIR}/lib64 $ENV{OSG_DIR} $ENV{OSGDIR}/lib $ENV{OSGDIR}/lib64 $ENV{OSGDIR} $ENV{OSG_ROOT}/lib $ENV{OSG_ROOT}/lib64 NO_DEFAULT_PATH ) FIND_LIBRARY(${MYLIBRARY} NAMES "${MYLIBRARYNAME}${CMAKE_RELEASE_POSTFIX}" PATHS ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/local/lib64 /usr/lib /usr/lib64 /sw/lib /opt/local/lib /opt/csw/lib /opt/lib [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OSG_ROOT]/lib /usr/freeware/lib64 ) IF( NOT ${MYLIBRARY}_DEBUG) IF(MYLIBRARY) SET(${MYLIBRARY}_DEBUG ${MYLIBRARY}) ENDIF(MYLIBRARY) ELSE() IF( NOT MYLIBRARY ) SET(${MYLIBRARY} ${${MYLIBRARY}_DEBUG} ) ENDIF(NOT MYLIBRARY) ENDIF( NOT ${MYLIBRARY}_DEBUG ) ENDMACRO(FIND_OSG_LIBRARY LIBRARY LIBRARYNAME) FIND_OSG_LIBRARY(OSG_LIBRARY osg) FIND_OSG_LIBRARY(OSGGA_LIBRARY osgGA) FIND_OSG_LIBRARY(OSGUTIL_LIBRARY osgUtil) FIND_OSG_LIBRARY(OSGDB_LIBRARY osgDB) FIND_OSG_LIBRARY(OSGTEXT_LIBRARY osgText) FIND_OSG_LIBRARY(OSGWIDGET_LIBRARY osgWidget) FIND_OSG_LIBRARY(OSGQT_LIBRARY osgQt) FIND_OSG_LIBRARY(OSGTERRAIN_LIBRARY osgTerrain) FIND_OSG_LIBRARY(OSGFX_LIBRARY osgFX) FIND_OSG_LIBRARY(OSGVIEWER_LIBRARY osgViewer) FIND_OSG_LIBRARY(OSGVOLUME_LIBRARY osgVolume) FIND_OSG_LIBRARY(OSGMANIPULATOR_LIBRARY osgManipulator) FIND_OSG_LIBRARY(OSGANIMATION_LIBRARY osgAnimation) FIND_OSG_LIBRARY(OSGPARTICLE_LIBRARY osgParticle) FIND_OSG_LIBRARY(OSGSHADOW_LIBRARY osgShadow) FIND_OSG_LIBRARY(OSGPRESENTATION_LIBRARY osgPresentation) FIND_OSG_LIBRARY(OSGSIM_LIBRARY osgSim) FIND_OSG_LIBRARY(OPENTHREADS_LIBRARY OpenThreads) SET(OSG_FOUND "NO") IF(OSG_LIBRARY AND OSG_INCLUDE_DIR) SET(OSG_FOUND "YES") ENDIF(OSG_LIBRARY AND OSG_INCLUDE_DIR) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindRSVG.cmake0000644000175000017500000000055512354212044024122 0ustar albertoalberto#use pkg-config to find various modues INCLUDE(FindPkgConfig OPTIONAL) IF(PKG_CONFIG_FOUND) INCLUDE(FindPkgConfig) #Version 2.35 introduces the rsvg_cleanup function which is used PKG_CHECK_MODULES(RSVG librsvg-2.0>=2.35) PKG_CHECK_MODULES(CAIRO cairo) IF (RSVG_FOUND AND NOT CAIRO_FOUND) SET(RSVG_FOUND FALSE) ENDIF() ENDIF() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindQuartzCore.cmake0000644000175000017500000000111212032572420025426 0ustar albertoalberto# Locate Apple QuartzCore # This module defines # QUARTZCORE_LIBRARY # QUARTZCORE_FOUND, if false, do not try to link to QUARTZCORE # QUARTZCORE_INCLUDE_DIR, where to find the headers # # $QUARTZCORE_DIR is an environment variable that would # correspond to the ./configure --prefix=$QUARTZCORE_DIR # # Created by Stephan Maximilian Huber. IF(APPLE) FIND_PATH(QUARTZCORE_INCLUDE_DIR QuartzCore/QuartzCore.h) FIND_LIBRARY(QUARTZCORE_LIBRARY QuartzCore) ENDIF() SET(QUARTZCORE_FOUND "NO") IF(QUARTZCORE_LIBRARY AND QUARTZCORE_INCLUDE_DIR) SET(QUARTZCORE_FOUND "YES") ENDIF() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindFOX.cmake0000644000175000017500000000277011553272246024010 0ustar albertoalberto# Locate gdal # This module defines # FOX_LIBRARY # FOX_FOUND, if false, do not try to link to gdal # FOX_INCLUDE_DIR, where to find the headers # # $FOX_DIR is an environment variable that would # correspond to the ./configure --prefix=$FOX_DIR # # Created by Robert Osfield. FIND_PATH(FOX_INCLUDE_DIR fx.h $ENV{FOX_DIR}/include/fox-1.6 $ENV{FOX_DIR}/fox-1.6 ~/Library/Frameworks/fox-1.6 /Library/Frameworks/fox-1.6 /usr/local/include/fox-1.6 /usr/include/fox-1.6 /sw/include/fox-1.6 # Fink /opt/local/include/fox-1.6 # DarwinPorts /opt/csw/include/fox-1.6 # Blastwave /opt/include/fox-1.6 /usr/freeware/include/fox-1.6 $ENV{FOX_DIR}/include $ENV{FOX_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include ) MACRO(FIND_FOX_LIBRARY MYLIBRARY MYLIBRARYNAME) FIND_LIBRARY(${MYLIBRARY} NAMES ${MYLIBRARYNAME} PATHS $ENV{FOX_DIR}/lib $ENV{FOX_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) ENDMACRO(FIND_FOX_LIBRARY LIBRARY LIBRARYNAME) FIND_FOX_LIBRARY(FOX_LIBRARY FOX-1.6) SET(FOX_FOUND "NO") IF(FOX_LIBRARY AND FOX_INCLUDE_DIR) SET(FOX_FOUND "YES") ENDIF(FOX_LIBRARY AND FOX_INCLUDE_DIR) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/UtilityMacros.cmake0000644000175000017500000001613511167337241025361 0ustar albertoalberto INCLUDE(ListHandle) #--------------------------------------------------- # Macro: FILTER_OUT FILTERS INPUTS OUTPUT # # Mimicks Gnu Make's $(filter-out) which removes elements # from a list that match the pattern. # Arguments: # FILTERS - list of patterns that need to be removed # INPUTS - list of inputs that will be worked on # OUTPUT - the filtered list to be returned # # Example: # SET(MYLIST this that and the other) # SET(FILTS this that) # # FILTER_OUT("${FILTS}" "${MYLIST}" OUT) # MESSAGE("OUTPUT = ${OUT}") # # The output - # OUTPUT = and;the;other # #--------------------------------------------------- MACRO(FILTER_OUT FILTERS INPUTS OUTPUT) SET(FOUT "") FOREACH(INP ${INPUTS}) SET(FILTERED 0) FOREACH(FILT ${FILTERS}) IF(${FILTERED} EQUAL 0) IF("${FILT}" STREQUAL "${INP}") SET(FILTERED 1) ENDIF() ENDIF() ENDFOREACH() IF(${FILTERED} EQUAL 0) SET(FOUT ${FOUT} ${INP}) ENDIF() ENDFOREACH(INP ${INPUTS}) SET(${OUTPUT} ${FOUT}) ENDMACRO() #--------------------------------------------------- # Macro: GET_HEADERS_EXTENSIONLESS DIR GLOB_PATTERN OUTPUT # #--------------------------------------------------- MACRO(GET_HEADERS_EXTENSIONLESS DIR GLOB_PATTERN OUTPUT) FILE(GLOB TMP "${DIR}/${GLOB_PATTERN}" ) #FOREACH(F ${TMP}) # MESSAGE(STATUS "header-->${F}<--") #ENDFOREACH(F ${TMP}) FILTER_OUT("${DIR}/CVS" "${TMP}" TMP) FILTER_OUT("${DIR}/cvs" "${TMP}" ${OUTPUT}) FILTER_OUT("${DIR}/.svn" "${TMP}" ${OUTPUT}) ENDMACRO() #--------------------------------------------------- # Macro: ADD_DIRS_TO_ENV_VAR _VARNAME # #--------------------------------------------------- MACRO(ADD_DIRS_TO_ENV_VAR _VARNAME ) FOREACH(_ADD_PATH ${ARGN}) FILE(TO_NATIVE_PATH ${_ADD_PATH} _ADD_NATIVE) #SET(_CURR_ENV_PATH $ENV{PATH}) #LIST(SET _CURR_ENV_PATH ${_ADD_PATH}) #SET(ENV{PATH} ${_CURR_ENV_PATH})${_FILE} IF(WIN32) SET(ENV{${_VARNAME}} "$ENV{${_VARNAME}};${_ADD_NATIVE}") ELSE() SET(ENV{${_VARNAME}} "$ENV{${_VARNAME}}:${_ADD_NATIVE}") ENDIF() #MESSAGE(" env ${_VARNAME} --->$ENV{${_VARNAME}}<---") ENDFOREACH() ENDMACRO() #--------------------------------------------------- # Macro: CORRECT_PATH VAR PATH # # Corrects slashes in PATH to be cmake conformous ( / ) # and puts result in VAR #--------------------------------------------------- MACRO(CORRECT_PATH VAR PATH) SET(${VAR} ${PATH}) IF(WIN32) STRING(REGEX REPLACE "/" "\\\\" ${VAR} "${PATH}") ENDIF() ENDMACRO() #--------------------------------------------------- # Macro: TARGET_LOCATIONS_SET_FILE FILE # TODO: Ok, this seems a bit ridiculuous. #--------------------------------------------------- MACRO(TARGET_LOCATIONS_SET_FILE FILE) SET(ACCUM_FILE_TARGETS ${FILE}) FILE(WRITE ${ACCUM_FILE_TARGETS} "") ENDMACRO() #--------------------------------------------------- # Macro: TARGET_LOCATIONS_ACCUM TARGET_NAME # #--------------------------------------------------- MACRO(TARGET_LOCATIONS_ACCUM TARGET_NAME) IF(ACCUM_FILE_TARGETS) IF(EXISTS ${ACCUM_FILE_TARGETS}) GET_TARGET_PROPERTY(_FILE_LOCATION ${TARGET_NAME} LOCATION) FILE(APPEND ${ACCUM_FILE_TARGETS} "${_FILE_LOCATION};") #SET(_TARGETS_LIST ${_TARGETS_LIST} "${_FILE_LOCATION}" CACHE INTERNAL "lista dll") #MESSAGE("adding target -->${TARGET_NAME}<-- file -->${_FILE_LOCATION}<-- to list -->${_TARGETS_LIST}<--") #SET(ACCUM_FILE_TARGETS ${ACCUM_FILE_TARGETS} ${_FILE_LOCATION}) ENDIF() ENDIF() ENDMACRO() #--------------------------------------------------- # Macro: TARGET_LOCATIONS_GET_LIST _VAR # #--------------------------------------------------- MACRO(TARGET_LOCATIONS_GET_LIST _VAR) IF(ACCUM_FILE_TARGETS) IF(EXISTS ${ACCUM_FILE_TARGETS}) FILE(READ ${ACCUM_FILE_TARGETS} ${_VAR}) ENDIF(EXISTS ${ACCUM_FILE_TARGETS}) ENDIF() ENDMACRO() #--------------------------------------------------- # Macro: FIND_DEPENDENCY DEPNAME INCLUDEFILE LIBRARY SEARCHPATHLIST # #--------------------------------------------------- MACRO(FIND_DEPENDENCY DEPNAME INCLUDEFILE LIBRARY SEARCHPATHLIST) MESSAGE(STATUS "searching ${DEPNAME} -->${INCLUDEFILE}<-->${LIBRARY}<-->${SEARCHPATHLIST}<--") SET(MY_PATH_INCLUDE ) SET(MY_PATH_LIB ) SET(MY_PATH_BIN ) FOREACH( MYPATH ${SEARCHPATHLIST} ) SET(MY_PATH_INCLUDE ${MY_PATH_INCLUDE} ${MYPATH}/include) SET(MY_PATH_LIB ${MY_PATH_LIB} ${MYPATH}/lib) SET(MY_PATH_BIN ${MY_PATH_BIN} ${MYPATH}/bin) ENDFOREACH() SET(MYLIBRARY "${LIBRARY}") SEPARATE_ARGUMENTS(MYLIBRARY) #MESSAGE( " include paths: -->${MY_PATH_INCLUDE}<--") #MESSAGE( " ${DEPNAME}_INCLUDE_DIR --> ${${DEPNAME}_INCLUDE_DIR}<--") FIND_PATH("${DEPNAME}_INCLUDE_DIR" ${INCLUDEFILE} ${MY_PATH_INCLUDE} ) MARK_AS_ADVANCED("${DEPNAME}_INCLUDE_DIR") #MESSAGE( " ${DEPNAME}_INCLUDE_DIR --> ${${DEPNAME}_INCLUDE_DIR}<--") FIND_LIBRARY("${DEPNAME}_LIBRARY" NAMES ${MYLIBRARY} PATHS ${MY_PATH_LIB} ) IF(${DEPNAME}_LIBRARY) GET_FILENAME_COMPONENT(MYLIBNAME ${${DEPNAME}_LIBRARY} NAME_WE) GET_FILENAME_COMPONENT(MYBINPATH ${${DEPNAME}_LIBRARY} PATH) GET_FILENAME_COMPONENT(MYBINPATH ${MYBINPATH} PATH) SET(MYBINPATH "${MYBINPATH}/bin") IF(EXISTS ${MYBINPATH}) SET(MYFOUND 0) FOREACH(MYPATH ${MY_ACCUM_BINARY_DEP}) IF(MYPATH MATCHES ${MYBINPATH}) SET(MYFOUND 1) #MESSAGE("found -->${MYPATH}<-->${MYBINPATH}<--") ENDIF() ENDFOREACH() IF(MYFOUND EQUAL 0) SET(MY_ACCUM_BINARY_DEP ${MY_ACCUM_BINARY_DEP} ${MYBINPATH}) ENDIF() ENDIF() #MESSAGE("${DEPNAME}_BINDEP searching -->${MYLIBNAME}${CMAKE_SHARED_MODULE_SUFFIX}<--in-->${MY_PATH_BIN}<--") # FIND_FILE("${DEPNAME}_BINDEP" # ${MYLIBNAME}${CMAKE_SHARED_MODULE_SUFFIX} # PATHS ${MY_PATH_BIN} # ) # FIND_LIBRARY("${DEPNAME}_BINDEP" # NAMES ${MYLIBRARY} # PATHS ${MY_PATH_BIN} # ) ENDIF() MARK_AS_ADVANCED("${DEPNAME}_LIBRARY") #MESSAGE( " ${DEPNAME}_LIBRARY --> ${${DEPNAME}_LIBRARY}<--") IF(${DEPNAME}_INCLUDE_DIR) IF(${DEPNAME}_LIBRARY) SET( ${DEPNAME}_FOUND "YES" ) SET( ${DEPNAME}_LIBRARIES ${${DEPNAME}_LIBRARY} ) ENDIF() ENDIF() ENDMACRO() #--------------------------------------------------- # Macro: MACRO_MESSAGE MYTEXT # #--------------------------------------------------- #SET(MACRO_MESSAGE_DEBUG TRUE) MACRO(MACRO_MESSAGE MYTEXT) IF(MACRO_MESSAGE_DEBUG) MESSAGE("in file -->${CMAKE_CURRENT_LIST_FILE}<-- line -->${CMAKE_CURRENT_LIST_LINE}<-- message ${MYTEXT}") ELSE() MESSAGE(STATUS "in file -->${CMAKE_CURRENT_LIST_FILE}<-- line -->${CMAKE_CURRENT_LIST_LINE}<-- message ${MYTEXT}") ENDIF() ENDMACRO() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindZeroConf.cmake0000644000175000017500000000230312263027305025062 0ustar albertoalberto# Locate ZeroConf / Bonjour # This module defines # ZEROCONF_LIBRARY # ZEROCONF_FOUND, if false, do not try to link to gdal # ZEROCONF_INCLUDE_DIR, where to find the headers # # $ZEROCONF_DIR is an environment variable that would # correspond to the ./configure --prefix=$ZEROCONF_DIR # Created by Stephan Maximilian Huber SET(ZEROCONF_FOUND "NO") IF(APPLE) # bonjour is part of the system on os x / ios SET(ZEROCONF_FOUND "YES") ELSE() IF(WIN32) # find the Bonjour SDK FIND_PATH(ZEROCONF_INCLUDE_DIR dnssd.h $ENV{ZEROCONF_DIR}/include $ENV{ZEROCONF_DIR} NO_DEFAULT_PATH ) FIND_PATH(ZEROCONF_INCLUDE_DIR dnssd.h PATHS ${CMAKE_PREFIX_PATH} # Unofficial: We are proposing this. NO_DEFAULT_PATH PATH_SUFFIXES include ) FIND_PATH(ZEROCONF_INCLUDE_DIR dnssd.h) FIND_LIBRARY(ZEROCONF_LIBRARY dnssd PATHS ${CMAKE_PREFIX_PATH} # Unofficial: We are proposing this. NO_DEFAULT_PATH PATH_SUFFIXES lib64 lib ) FIND_LIBRARY(ZEROCONF_LIBRARY dnssd) SET(ZEROCONF_FOUND "NO") IF(ZEROCONF_LIBRARY AND ZEROCONF_INCLUDE_DIR) SET(ZEROCONF_FOUND "YES") ENDIF() ELSE() # TODO find AVAHI on linux ENDIF() ENDIF() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindInventor.cmake0000644000175000017500000001304711331345247025153 0ustar albertoalberto# # Find Open Inventor # # This module defines: # INVENTOR_FOUND, if false, do not try to link against Inventor. # INVENTOR_INCLUDE_DIR, where to find headers. # INVENTOR_LIBRARY, the library to link against. # INVENTOR_LIBRARY_DEBUG, the debug library to link against. # INVENTOR_SOWIN_LIBRARY, the SoWin library - window binding library for Inventor # INVENTOR_SOWIN_LIBRARY, the SoWin debug library # INVENTOR_SOXT_LIBRARY, the SoXt library - window binding library for Inventor # INVENTOR_SOXT_LIBRARY, the SoXt debug library # # # Inventor # # notes: # - Coin is honored over SGI Inventor # - Coin is detected by coin-config script, COINDIR environment variable, # and finally standard system locations are searched # - SGI Inventor is searched at standard system locations only # # coin-config tells much of Coin instalation (if present) execute_process (COMMAND coin-config --prefix OUTPUT_VARIABLE COIN_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) # try to find Inventor includes (priority paths) FIND_PATH(INVENTOR_INCLUDE_DIR Inventor/So.h ${COIN_PREFIX}/include $ENV{COINDIR}/include NO_DEFAULT_PATH ) # try to find Inventor includes (regular paths) FIND_PATH(INVENTOR_INCLUDE_DIR Inventor/So.h /usr/local/include /usr/include /sw/include /opt/local/include /opt/csw/include /opt/include ) # default Inventor lib search paths SET(INVENTOR_LIB_SEARCH_PATH /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib ) # try to find Coin release lib (priority paths) FIND_LIBRARY(INVENTOR_LIBRARY_RELEASE NAMES coin5 coin4 coin3 coin2 coin1 Coin PATHS ${COIN_PREFIX}/lib $ENV{COINDIR}/lib NO_DEFAULT_PATH ) # try to find Coin release lib (regular paths) FIND_LIBRARY(INVENTOR_LIBRARY_RELEASE NAMES coin5 coin4 coin3 coin2 coin1 Coin PATHS ${INVENTOR_LIB_SEARCH_PATH} ) # try to find SGI Inventor lib FIND_LIBRARY(INVENTOR_LIBRARY_RELEASE NAMES Inventor PATHS ${INVENTOR_LIB_SEARCH_PATH} ) # try to find Coin debug lib (priority paths) FIND_LIBRARY(INVENTOR_LIBRARY_DEBUG NAMES coin5d coin4d coin3d coin2d coin1d PATHS ${COIN_PREFIX}/lib $ENV{COINDIR}/lib NO_DEFAULT_PATH ) # try to find Coin debug lib (regular paths) FIND_LIBRARY(INVENTOR_LIBRARY_DEBUG NAMES coin5d coin4d coin3d coin2d coin1d PATHS ${INVENTOR_LIB_SEARCH_PATH} ) # set release to debug if only debug found IF(NOT INVENTOR_LIBRARY_RELEASE AND INVENTOR_LIBRARY_DEBUG) SET(INVENTOR_LIBRARY_RELEASE ${INVENTOR_LIBRARY_DEBUG}) ENDIF(NOT INVENTOR_LIBRARY_RELEASE AND INVENTOR_LIBRARY_DEBUG) # set debug to release (if only release found) IF(NOT INVENTOR_LIBRARY_DEBUG AND INVENTOR_LIBRARY_RELEASE) SET(INVENTOR_LIBRARY_DEBUG ${INVENTOR_LIBRARY_RELEASE}) ENDIF(NOT INVENTOR_LIBRARY_DEBUG AND INVENTOR_LIBRARY_RELEASE) # INVENTOR_LIBRARY IF (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) SET(INVENTOR_LIBRARY optimized ${INVENTOR_LIBRARY_RELEASE} debug ${INVENTOR_LIBRARY_DEBUG}) ELSE(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) SET(INVENTOR_LIBRARY ${INVENTOR_LIBRARY_RELEASE}) ENDIF(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) # set INVENTOR_FOUND appropriately SET(INVENTOR_FOUND "NO") IF(INVENTOR_INCLUDE_DIR AND INVENTOR_LIBRARY) SET(INVENTOR_FOUND "YES") ENDIF(INVENTOR_INCLUDE_DIR AND INVENTOR_LIBRARY) # # SoWin # # notes: SoWin is searched by COINDIR environment variable # (as expected to be located at Windows platform) # try to find SoWin lib (priority paths) FIND_LIBRARY(INVENTOR_SOWIN_LIBRARY NAMES sowin1 PATHS $ENV{COINDIR}/lib NO_DEFAULT_PATH ) # try to find SoWin lib (regular paths) FIND_LIBRARY(INVENTOR_SOWIN_LIBRARY NAMES sowin1 PATHS ${INVENTOR_LIB_SEARCH_PATH} ) # try to find SoWin debug lib (priority paths) FIND_LIBRARY(INVENTOR_SOWIN_LIBRARY_DEBUG NAMES sowin1d PATHS $ENV{COINDIR}/lib NO_DEFAULT_PATH ) # try to find SoWin debug lib (regular paths) FIND_LIBRARY(INVENTOR_SOWIN_LIBRARY_DEBUG NAMES sowin1d PATHS ${INVENTOR_LIB_SEARCH_PATH} ) # SoWin debug library defaults to non-debug lib IF(NOT INVENTOR_SOWIN_LIBRARY_DEBUG) IF(INVENTOR_SOWIN_LIBRARY) SET(INVENTOR_SOWIN_LIBRARY_DEBUG INVENTOR_SOWIN_LIBRARY) ENDIF(INVENTOR_SOWIN_LIBRARY) ENDIF(NOT INVENTOR_SOWIN_LIBRARY_DEBUG) # # SoXt # # notes: # - SoXt is detected by soxt-config script (as expected by # Coin's SoXt on Linux/Unix) and on standard system locations # - SGI's InventorXt support is missing now # # soxt-config tells much of SoXt instalation (if present) execute_process (COMMAND soxt-config --prefix OUTPUT_VARIABLE SOXT_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) # try to find SoXt lib (priority paths) FIND_LIBRARY(INVENTOR_SOXT_LIBRARY NAMES soxt1 SoXt PATHS ${SOXT_PREFIX}/lib $ENV{COINDIR}/lib NO_DEFAULT_PATH ) # try to find SoXt lib (regular paths) FIND_LIBRARY(INVENTOR_SOXT_LIBRARY NAMES soxt1 SoXt PATHS ${INVENTOR_LIB_SEARCH_PATH} ) # try to find SoXt debug lib (priority paths) FIND_LIBRARY(INVENTOR_SOXT_LIBRARY_DEBUG NAMES soxt1d PATHS ${SOXT_PREFIX}/lib $ENV{COINDIR}/lib NO_DEFAULT_PATH ) # try to find SoXt debug lib (regular paths) FIND_LIBRARY(INVENTOR_SOXT_LIBRARY_DEBUG NAMES soxt1d PATHS ${INVENTOR_LIB_SEARCH_PATH} ) # SoXt debug library defaults to non-debug lib IF(NOT INVENTOR_SOXT_LIBRARY_DEBUG) IF(INVENTOR_SOXT_LIBRARY) SET(INVENTOR_SOXT_LIBRARY_DEBUG INVENTOR_SOXT_LIBRARY) ENDIF(INVENTOR_SOXT_LIBRARY) ENDIF(NOT INVENTOR_SOXT_LIBRARY_DEBUG) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindDirectShow.cmake0000644000175000017500000000405711553272246025427 0ustar albertoalberto# Locate directshow # This module defines # DIRECTSHOW_LIBRARIES # DIRECTSHOW_FOUND, if false, do not try to link to directshow # DIRECTSHOW_INCLUDE_DIR, where to find the headers # # $DIRECTSHOW_DIR is an environment variable that would # point to the this path in the plateform devkit (Samples\Multimedia\DirectShow) # # Created by Cedric Pinson. # SET(DIRECTSHOW_FOUND "NO") SET(DIRECTSHOW_SAMPLE_ROOT "$ENV{DIRECTSHOW_DIR}" CACHE PATH "Location of DirectShow sample in devkit") IF(WIN32) FIND_PATH(DIRECTSHOW_STRMBASE_INCLUDE_DIRS renbase.h PATHS ${DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/ $ENV{DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/ DOC "Location of DirectShow Base include on the windows devkit" ) FIND_LIBRARY(DIRECTSHOW_STRMBASE_LIBRARY_RELEASE strmbase PATHS ${DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Release_MBCS/ # sdk 6.1 $ENV{DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Release_MBCS/ # sdk 6.1 ${DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Release/ # sdk 2003 $ENV{DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Release/ # sdk 2003 DOC "Location of DirectShow Base library on the windows devkit" ) FIND_LIBRARY(DIRECTSHOW_STRMBASE_LIBRARY_DEBUG strmbasd PATHS ${DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Debug_MBCS/ # sdk 6.1 $ENV{DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Debug_MBCS/ # sdk 6.1 ${DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Debug/ # sdk 2003 $ENV{DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Debug/ # sdk 2003 DOC "Location of DirectShow Base library on the windows devkit" ) IF (DIRECTSHOW_STRMBASE_INCLUDE_DIRS AND DIRECTSHOW_STRMBASE_LIBRARY_RELEASE) SET(WIN_LIBS winmm d3d9 d3dx9 kernel32 user32 gdi32 winspool shell32 ole32 oleaut32 uuid comdlg32 advapi32) SET(DIRECTSHOW_FOUND "YES") SET(DIRECTSHOW_LIBRARY_DEBUG ${DIRECTSHOW_STRMBASE_LIBRARY_DEBUG} ) SET(DIRECTSHOW_LIBRARY ${DIRECTSHOW_STRMBASE_LIBRARY_RELEASE} ) SET(DIRECTSHOW_INLUDE_DIRS ${DIRECTSHOW_STRMBASE_INCLUDE_DIRS} ) ENDIF() ENDIF() openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindGDAL.cmake0000644000175000017500000000463111553272246024061 0ustar albertoalberto# Locate gdal # This module defines # GDAL_LIBRARY # GDAL_FOUND, if false, do not try to link to gdal # GDAL_INCLUDE_DIR, where to find the headers # # $GDALDIR is an environment variable that would # correspond to the ./configure --prefix=$GDAL_DIR # used in building gdal. # # Created by Eric Wing. I'm not a gdal user, but OpenSceneGraph uses it # for osgTerrain so I whipped this module together for completeness. # I actually don't know the conventions or where files are typically # placed in distros. # Any real gdal users are encouraged to correct this (but please don't # break the OS X framework stuff when doing so which is what usually seems # to happen). # This makes the presumption that you are include gdal.h like # #include "gdal.h" FIND_PATH(GDAL_INCLUDE_DIR gdal.h PATHS $ENV{GDAL_DIR} NO_DEFAULT_PATH PATH_SUFFIXES include ) FIND_PATH(GDAL_INCLUDE_DIR gdal.h PATHS ${CMAKE_PREFIX_PATH} # Unofficial: We are proposing this. NO_DEFAULT_PATH PATH_SUFFIXES include ) FIND_PATH(GDAL_INCLUDE_DIR gdal.h PATHS ~/Library/Frameworks/gdal.framework/Headers /Library/Frameworks/gdal.framework/Headers /usr/local/include/gdal /usr/local/include/GDAL /usr/local/include /usr/include/gdal /usr/include/GDAL /usr/include /sw/include/gdal /sw/include/GDAL /sw/include # Fink /opt/local/include/gdal /opt/local/include/GDAL /opt/local/include # DarwinPorts /opt/csw/include/gdal /opt/csw/include/GDAL /opt/csw/include # Blastwave /opt/include/gdal /opt/include/GDAL /opt/include ) FIND_LIBRARY(GDAL_LIBRARY NAMES gdal gdal_i gdal1.7.0 gdal1.6.0 gdal1.5.0 gdal1.4.0 gdal1.3.2 GDAL PATHS $ENV{GDAL_DIR} NO_DEFAULT_PATH PATH_SUFFIXES lib64 lib ) FIND_LIBRARY(GDAL_LIBRARY NAMES gdal gdal_i gdal1.7.0 gdal1.6.0 gdal1.5.0 gdal1.4.0 gdal1.3.2 GDAL PATHS ${CMAKE_PREFIX_PATH} # Unofficial: We are proposing this. NO_DEFAULT_PATH PATH_SUFFIXES lib64 lib ) FIND_LIBRARY(GDAL_LIBRARY NAMES gdal gdal_i gdal1.7.0 gdal1.6.0 gdal1.5.0 gdal1.4.0 gdal1.3.2 GDAL PATHS ~/Library/Frameworks /Library/Frameworks /usr/local /usr /sw /opt/local /opt/csw /opt /usr/freeware [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;GDAL_ROOT]/lib PATH_SUFFIXES lib64 lib ) SET(GDAL_FOUND "NO") IF(GDAL_LIBRARY AND GDAL_INCLUDE_DIR) SET(GDAL_FOUND "YES") ENDIF(GDAL_LIBRARY AND GDAL_INCLUDE_DIR) openscenegraph-3.2.3/OpenSceneGraph/CMakeModules/FindOurDCMTK.cmake0000644000175000017500000001553611576341346024713 0ustar albertoalberto# - find DCMTK libraries # # DCMTK_INCLUDE_DIRS - Directories to include to use DCMTK # DCMTK_LIBRARIES - Files to link against to use DCMTK # DCMTK_FOUND - If false, don't try to use DCMTK # DCMTK_DIR - (optional) Source directory for DCMTK # # DCMTK_DIR can be used to make it simpler to find the various include # directories and compiled libraries if you've just compiled it in the # source tree. Just set it to the root of the tree where you extracted # the source. # # Written for VXL by Amitha Perera. # Modified by Robert Osfied to enable support for install placements of DCMTK 3.5.4 versions onwards FIND_PATH( DCMTK_ROOT_INCLUDE_DIR dcmtk/config/osconfig.h ${DCMTK_DIR}/config/include ${DCMTK_DIR}/include /usr/local/dicom/include /usr/local/include/ /usr/include/ /usr/local/dicom/include/ ) FIND_PATH( DCMTK_config_INCLUDE_DIR osconfig.h ${DCMTK_ROOT_INCLUDE_DIR}/dcmtk/config ${DCMTK_DIR}/config/include ${DCMTK_DIR}/include /usr/local/dicom/include /usr/local/include/dcmtk/config /usr/include/dcmtk/config /usr/local/dicom/include/dcmtk/config ) FIND_PATH( DCMTK_ofstd_INCLUDE_DIR ofstdinc.h ${DCMTK_ROOT_INCLUDE_DIR}/dcmtk/ofstd ${DCMTK_DIR}/ofstd/include ${DCMTK_DIR}/include/ofstd /usr/local/dicom/include/dcmtk/ofstd /usr/local/include/dcmtk/ofstd /usr/include/dcmtk/ofstd /usr/local/dicom/include/dcmtk/ofstd ) FIND_LIBRARY( DCMTK_ofstd_LIBRARY ofstd PATHS ${DCMTK_DIR}/ofstd/libsrc ${DCMTK_DIR}/ofstd/libsrc/Release ${DCMTK_DIR}/ofstd/libsrc/Debug ${DCMTK_DIR}/ofstd/Release ${DCMTK_DIR}/ofstd/Debug ${DCMTK_DIR}/lib /usr/local/dicom/lib /usr/local/lib64 /usr/lib64 /usr/local/lib /usr/lib /usr/local/dicom/lib PATH_SUFFIXES dcmtk ) FIND_PATH( DCMTK_dcmdata_INCLUDE_DIR dctypes.h ${DCMTK_ROOT_INCLUDE_DIR}/dcmtk/dcmdata ${DCMTK_DIR}/dcmdata/include ${DCMTK_DIR}/include/dcmdata /usr/local/dicom/include/dcmtk/dcmdata /usr/local/include/dcmtk/dcmdata /usr/include/dcmtk/dcmdata /usr/local/dicom/include/dcmtk/dcmdata ) FIND_LIBRARY( DCMTK_dcmdata_LIBRARY dcmdata PATHS ${DCMTK_DIR}/dcmdata/libsrc ${DCMTK_DIR}/dcmdata/libsrc/Release ${DCMTK_DIR}/dcmdata/libsrc/Debug ${DCMTK_DIR}/dcmdata/Release ${DCMTK_DIR}/dcmdata/Debug ${DCMTK_DIR}/lib /usr/local/dicom/lib /usr/local/lib64 /usr/lib64 /usr/local/lib /usr/lib /usr/local/dicom/lib PATH_SUFFIXES dcmtk ) FIND_PATH( DCMTK_dcmimgle_INCLUDE_DIR dcmimage.h ${DCMTK_ROOT_INCLUDE_DIR}/dcmtk/dcmimgle ${DCMTK_DIR}/dcmimgle/include ${DCMTK_DIR}/include/dcmimgle /usr/local/dicom/include/dcmtk/dcmimgle /usr/local/include/dcmtk/dcmimgle /usr/include/dcmtk/dcmimgle /usr/local/dicom/include/dcmtk/dcmimgle ) FIND_LIBRARY( DCMTK_dcmimgle_LIBRARY dcmimgle PATHS ${DCMTK_DIR}/dcmimgle/libsrc ${DCMTK_DIR}/dcmimgle/libsrc/Release ${DCMTK_DIR}/dcmimgle/libsrc/Debug ${DCMTK_DIR}/dcmimgle/Release ${DCMTK_DIR}/dcmimgle/Debug ${DCMTK_DIR}/lib /usr/local/dicom/lib /usr/local/lib64 /usr/lib64 /usr/local/lib /usr/lib /usr/local/dicom/lib PATH_SUFFIXES dcmtk ) FIND_PATH( DCMTK_dcmimage_INCLUDE_DIR diregist.h ${DCMTK_ROOT_INCLUDE_DIR}/dcmtk/dcmimage ${DCMTK_DIR}/dcmimage/include ${DCMTK_DIR}/include/dcmimage /usr/local/dicom/include/dcmtk/dcmimage /usr/local/include/dcmtk/dcmimage /usr/include/dcmtk/dcmimage /usr/local/dicom/include/dcmtk/dcmimage ) FIND_LIBRARY( DCMTK_dcmimage_LIBRARY dcmimage PATHS ${DCMTK_DIR}/dcmimage/libsrc ${DCMTK_DIR}/dcmimage/libsrc/Release ${DCMTK_DIR}/dcmimage/libsrc/Debug ${DCMTK_DIR}/dcmimage/Release ${DCMTK_DIR}/dcmimage/Debug ${DCMTK_DIR}/lib /usr/local/dicom/lib /usr/local/lib64 /usr/lib64 /usr/local/lib /usr/lib /usr/local/dicom/lib PATH_SUFFIXES dcmtk ) FIND_LIBRARY(DCMTK_imagedb_LIBRARY imagedb PATHS ${DCMTK_DIR}/imagectn/libsrc/Release ${DCMTK_DIR}/imagectn/libsrc/ ${DCMTK_DIR}/imagectn/libsrc/Debug ${DCMTK_DIR}/lib /usr/local/dicom/lib /usr/local/lib64 /usr/lib64 /usr/local/lib /usr/lib /usr/local/dicom/lib PATH_SUFFIXES dcmtk ) FIND_LIBRARY(DCMTK_dcmnet_LIBRARY dcmnet PATHS ${DCMTK_DIR}/dcmnet/libsrc/Release ${DCMTK_DIR}/dcmnet/libsrc/Debug ${DCMTK_DIR}/dcmnet/libsrc/ ${DCMTK_DIR}/lib /usr/local/dicom/lib /usr/local/lib64 /usr/lib64 /usr/local/lib /usr/lib /usr/local/dicom/lib PATH_SUFFIXES dcmtk ) FIND_LIBRARY(DCMTK_oflog_LIBRARY oflog PATHS ${DCMTK_DIR}/dcmnet/libsrc/Release ${DCMTK_DIR}/dcmnet/libsrc/Debug ${DCMTK_DIR}/dcmnet/libsrc/ ${DCMTK_DIR}/lib /usr/local/dicom/lib /usr/local/lib64 /usr/lib64 /usr/local/lib /usr/lib /usr/local/dicom/lib PATH_SUFFIXES dcmtk ) FIND_LIBRARY(DCMTK_ofstd_LIBRARY ofstd PATHS ${DCMTK_DIR}/dcmnet/libsrc/Release ${DCMTK_DIR}/dcmnet/libsrc/Debug ${DCMTK_DIR}/dcmnet/libsrc/ ${DCMTK_DIR}/lib /usr/local/dicom/lib /usr/local/lib64 /usr/lib64 /usr/local/lib /usr/lib /usr/local/dicom/lib PATH_SUFFIXES dcmtk ) IF( DCMTK_config_INCLUDE_DIR AND DCMTK_ofstd_INCLUDE_DIR AND DCMTK_ofstd_LIBRARY AND DCMTK_dcmdata_INCLUDE_DIR AND DCMTK_dcmdata_LIBRARY AND DCMTK_dcmimgle_INCLUDE_DIR AND DCMTK_dcmimgle_LIBRARY AND DCMTK_dcmimage_INCLUDE_DIR AND DCMTK_dcmimage_LIBRARY ) SET( DCMTK_FOUND "YES" ) SET( DCMTK_INCLUDE_DIRS ${DCMTK_config_INCLUDE_DIR} ${DCMTK_ofstd_INCLUDE_DIR} ${DCMTK_dcmdata_INCLUDE_DIR} ${DCMTK_dcmimgle_INCLUDE_DIR} ${DCMTK_dcmimage_INCLUDE_DIR} ) SET( DCMTK_LIBRARIES ${DCMTK_dcmimgle_LIBRARY} ${DCMTK_dcmimage_LIBRARY} ${DCMTK_dcmdata_LIBRARY} ${DCMTK_ofstd_LIBRARY} ${DCMTK_config_LIBRARY} ) IF(DCMTK_imagedb_LIBRARY) SET( DCMTK_LIBRARIES ${DCMTK_LIBRARIES} ${DCMTK_imagedb_LIBRARY} ) ENDIF() IF(DCMTK_dcmnet_LIBRARY) SET( DCMTK_LIBRARIES ${DCMTK_LIBRARIES} ${DCMTK_dcmnet_LIBRARY} ) ENDIF() IF(DCMTK_oflog_LIBRARY) SET( DCMTK_LIBRARIES ${DCMTK_LIBRARIES} ${DCMTK_oflog_LIBRARY} ) ENDIF() IF(DCMTK_ofstd_LIBRARY) SET( DCMTK_LIBRARIES ${DCMTK_LIBRARIES} ${DCMTK_ofstd_LIBRARY} ) ENDIF() IF( WIN32 ) SET( DCMTK_LIBRARIES ${DCMTK_LIBRARIES} netapi32 ) ENDIF() ENDIF() IF( NOT DCMTK_FOUND ) SET( DCMTK_DIR "" CACHE PATH "Root of DCMTK source tree (optional)." ) MARK_AS_ADVANCED( DCMTK_DIR ) ENDIF() openscenegraph-3.2.3/OpenSceneGraph/src/0000755000175000017500000000000012674261222020016 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/0000755000175000017500000000000012674261220023020 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/TabBoxDragger.cpp0000644000175000017500000000525111732410624026200 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include using namespace osgManipulator; TabBoxDragger::TabBoxDragger() { for (int i=0; i<6; ++i) { _planeDraggers.push_back(new TabPlaneDragger()); addChild(_planeDraggers[i].get()); addDragger(_planeDraggers[i].get()); } { _planeDraggers[0]->setMatrix(osg::Matrix::translate(osg::Vec3(0.0,0.5,0.0))); } { osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, -1.0f, 0.0f), osg::Vec3(0.0f, 1.0f, 0.0f)); _planeDraggers[1]->setMatrix(osg::Matrix(rotation)*osg::Matrix::translate(osg::Vec3(0.0,-0.5,0.0))); } { osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(0.0f, 1.0f, 0.0f)); _planeDraggers[2]->setMatrix(osg::Matrix(rotation)*osg::Matrix::translate(osg::Vec3(0.0,0.0,-0.5))); } { osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 1.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 1.0f)); _planeDraggers[3]->setMatrix(osg::Matrix(rotation)*osg::Matrix::translate(osg::Vec3(0.0,0.0,0.5))); } { osg::Quat rotation; rotation.makeRotate(osg::Vec3(1.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 1.0f, 0.0f)); _planeDraggers[4]->setMatrix(osg::Matrix(rotation)*osg::Matrix::translate(osg::Vec3(-0.5,0.0,0.0))); } { osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 1.0f, 0.0f), osg::Vec3(1.0f, 0.0f, 0.0f)); _planeDraggers[5]->setMatrix(osg::Matrix(rotation)*osg::Matrix::translate(osg::Vec3(0.5,0.0,0.0))); } setParentDragger(getParentDragger()); } TabBoxDragger::~TabBoxDragger() { } void TabBoxDragger::setupDefaultGeometry() { for (unsigned int i=0; i<_planeDraggers.size(); ++i) _planeDraggers[i]->setupDefaultGeometry(false); } void TabBoxDragger::setPlaneColor(const osg::Vec4& color) { for (unsigned int i=0; i<_planeDraggers.size(); ++i) _planeDraggers[i]->setPlaneColor(color); } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/TabPlaneTrackballDragger.cpp0000644000175000017500000000275511732410624030335 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include #include #include #include using namespace osgManipulator; TabPlaneTrackballDragger::TabPlaneTrackballDragger() { _trackballDragger = new TrackballDragger(true); addChild(_trackballDragger.get()); addDragger(_trackballDragger.get()); _tabPlaneDragger = new TabPlaneDragger(); addChild(_tabPlaneDragger.get()); addDragger(_tabPlaneDragger.get()); setParentDragger(getParentDragger()); } TabPlaneTrackballDragger::~TabPlaneTrackballDragger() { } void TabPlaneTrackballDragger::setupDefaultGeometry() { _trackballDragger->setupDefaultGeometry(); _tabPlaneDragger->setupDefaultGeometry(); } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/Constraint.cpp0000644000175000017500000001642211711744364025663 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include using namespace osgManipulator; namespace { double round_to_nearest_int(double x) { return floor(x+0.5); } osg::Vec3d snap_point_to_grid(const osg::Vec3d& point, const osg::Vec3d& origin, const osg::Vec3d& spacing) { osg::Vec3d scale; scale[0] = spacing[0] ? round_to_nearest_int((point[0] - origin[0]) / spacing[0]) : 1.0; scale[1] = spacing[1] ? round_to_nearest_int((point[1] - origin[1]) / spacing[1]) : 1.0; scale[2] = spacing[2] ? round_to_nearest_int((point[2] - origin[2]) / spacing[2]) : 1.0; osg::Vec3d snappedPoint = origin; snappedPoint += osg::Vec3(scale[0]*spacing[0],scale[1]*spacing[1],scale[2]*spacing[2]); return snappedPoint; } } void Constraint::computeLocalToWorldAndWorldToLocal() const { if (!_refNode) { _localToWorld.makeIdentity(); _worldToLocal.makeIdentity(); return; } osg::NodePath pathToRoot; computeNodePathToRoot(const_cast(getReferenceNode()),pathToRoot); _localToWorld = osg::computeLocalToWorld(pathToRoot); _worldToLocal = osg::computeWorldToLocal(pathToRoot); } GridConstraint::GridConstraint(osg::Node& refNode, const osg::Vec3d& origin, const osg::Vec3d& spacing) : Constraint(refNode), _origin(origin), _spacing(spacing) { } bool GridConstraint::constrain(TranslateInLineCommand& command) const { if (command.getStage() == osgManipulator::MotionCommand::START) computeLocalToWorldAndWorldToLocal(); else if (command.getStage() == osgManipulator::MotionCommand::FINISH) return true; osg::Vec3d translatedPoint = command.getLineStart() + command.getTranslation(); osg::Vec3d localTranslatedPoint = (osg::Vec3d(translatedPoint) * command.getLocalToWorld() * getWorldToLocal()); osg::Vec3d newLocalTranslatedPoint = snap_point_to_grid(localTranslatedPoint, _origin, _spacing); command.setTranslation(newLocalTranslatedPoint * getLocalToWorld() * command.getWorldToLocal() - command.getLineStart()); return true; } bool GridConstraint::constrain(TranslateInPlaneCommand& command) const { if (command.getStage() == osgManipulator::MotionCommand::START) computeLocalToWorldAndWorldToLocal(); else if (command.getStage() == osgManipulator::MotionCommand::FINISH) return true; osg::Matrix commandToConstraint = command.getLocalToWorld() * getWorldToLocal(); osg::Matrix constraintToCommand = getLocalToWorld() * command.getWorldToLocal(); // Snap the reference point to grid. osg::Vec3d localRefPoint = command.getReferencePoint() * commandToConstraint; osg::Vec3d snappedLocalRefPoint = snap_point_to_grid(localRefPoint, _origin, _spacing); osg::Vec3d snappedCmdRefPoint = snappedLocalRefPoint * constraintToCommand; // Snap the translated point to grid. osg::Vec3d translatedPoint = snappedCmdRefPoint + command.getTranslation(); osg::Vec3d localTranslatedPoint = osg::Vec3d(translatedPoint) * commandToConstraint; osg::Vec3d newLocalTranslatedPoint = snap_point_to_grid(localTranslatedPoint, _origin, _spacing); // Set the snapped translation. command.setTranslation(newLocalTranslatedPoint * constraintToCommand - snappedCmdRefPoint); return true; } bool GridConstraint::constrain(Scale1DCommand& command) const { if (command.getStage() == osgManipulator::MotionCommand::START) computeLocalToWorldAndWorldToLocal(); else if (command.getStage() == osgManipulator::MotionCommand::FINISH) return true; double scaledPoint = (command.getReferencePoint() - command.getScaleCenter()) * command.getScale() + command.getScaleCenter(); osg::Matrix constraintToCommand = getLocalToWorld() * command.getWorldToLocal(); osg::Vec3d commandOrigin = _origin * constraintToCommand; osg::Vec3d commandSpacing = (_origin + _spacing) * constraintToCommand - commandOrigin; double spacingFactor = commandSpacing[0] ? round_to_nearest_int((scaledPoint-commandOrigin[0])/commandSpacing[0]) : 1.0; double snappedScaledPoint = commandOrigin[0] + commandSpacing[0] * spacingFactor; double denom = (command.getReferencePoint() - command.getScaleCenter()); double snappedScale = (denom) ? (snappedScaledPoint - command.getScaleCenter()) / denom : 1.0; if (snappedScale < command.getMinScale()) snappedScale = command.getMinScale(); command.setScale(snappedScale); return true; } bool GridConstraint::constrain(Scale2DCommand& command) const { if (command.getStage() == osgManipulator::MotionCommand::START) computeLocalToWorldAndWorldToLocal(); else if (command.getStage() == osgManipulator::MotionCommand::FINISH) return true; osg::Vec2d scaledPoint = command.getReferencePoint() - command.getScaleCenter(); scaledPoint[0] *= command.getScale()[0]; scaledPoint[1] *= command.getScale()[1]; scaledPoint += command.getScaleCenter(); osg::Matrix constraintToCommand = getLocalToWorld() * command.getWorldToLocal(); osg::Vec3d commandOrigin = _origin * constraintToCommand; osg::Vec3d commandSpacing = (_origin + _spacing) * constraintToCommand - commandOrigin; osg::Vec2d spacingFactor; spacingFactor[0] = commandSpacing[0] ? round_to_nearest_int((scaledPoint[0] - commandOrigin[0])/commandSpacing[0]) : 1.0; spacingFactor[1] = commandSpacing[2] ? round_to_nearest_int((scaledPoint[1] - commandOrigin[2])/commandSpacing[2]) : 1.0; osg::Vec2d snappedScaledPoint = (osg::Vec2d(commandOrigin[0],commandOrigin[2]) + osg::Vec2d(commandSpacing[0]*spacingFactor[0], commandSpacing[2]*spacingFactor[1])); osg::Vec2d denom = command.getReferencePoint() - command.getScaleCenter(); osg::Vec2d snappedScale; snappedScale[0] = denom[0] ? (snappedScaledPoint[0] - command.getScaleCenter()[0]) / denom[0] : 1.0; snappedScale[1] = denom[1] ? (snappedScaledPoint[1] - command.getScaleCenter()[1]) / denom[1] : 1.0; if (snappedScale[0] < command.getMinScale()[0]) snappedScale[0] = command.getMinScale()[0]; if (snappedScale[1] < command.getMinScale()[1]) snappedScale[1] = command.getMinScale()[1]; command.setScale(snappedScale); return true; } bool GridConstraint::constrain(ScaleUniformCommand&) const { // Can you correctly snap a ScaleUniformCommand using a Grid constraint that has // different spacings in the three axis?? return false; } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/Version.cpp0000644000175000017500000000155211732410624025152 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include extern "C" { const char* osgManipulatorGetVersion() { return osgGetVersion(); } const char* osgManipulatorGetLibraryName() { return "OpenSceneGraph Manipulator Library"; } } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/Translate1DDragger.cpp0000644000175000017500000001602611732410624027145 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include #include using namespace osgManipulator; Translate1DDragger::Translate1DDragger() : Dragger(), _checkForNodeInNodePath(true) { _projector = new LineProjector; setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); } Translate1DDragger::Translate1DDragger(const osg::Vec3d& s, const osg::Vec3d& e) : Dragger(), _checkForNodeInNodePath(true) { _projector = new LineProjector(s,e); setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); } Translate1DDragger::~Translate1DDragger() { } bool Translate1DDragger::handle(const PointerInfo& pointer, const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { // Check if the dragger node is in the nodepath. if (_checkForNodeInNodePath) { if (!pointer.contains(this)) return false; } switch (ea.getEventType()) { // Pick start. case (osgGA::GUIEventAdapter::PUSH): { // Get the LocalToWorld matrix for this node and set it for the projector. osg::NodePath nodePathToRoot; computeNodePathToRoot(*this,nodePathToRoot); osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot); _projector->setLocalToWorld(localToWorld); if (_projector->project(pointer, _startProjectedPoint)) { // Generate the motion command. osg::ref_ptr cmd = new TranslateInLineCommand(_projector->getLineStart(), _projector->getLineEnd()); cmd->setStage(MotionCommand::START); cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); // Dispatch command. dispatch(*cmd); // Set color to pick color. setMaterialColor(_pickColor,*this); aa.requestRedraw(); } return true; } // Pick move. case (osgGA::GUIEventAdapter::DRAG): { osg::Vec3d projectedPoint; if (_projector->project(pointer, projectedPoint)) { // Generate the motion command. osg::ref_ptr cmd = new TranslateInLineCommand(_projector->getLineStart(), _projector->getLineEnd()); cmd->setStage(MotionCommand::MOVE); cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); cmd->setTranslation(projectedPoint - _startProjectedPoint); // Dispatch command. dispatch(*cmd); aa.requestRedraw(); } return true; } // Pick finish. case (osgGA::GUIEventAdapter::RELEASE): { osg::Vec3d projectedPoint; if (_projector->project(pointer, projectedPoint)) { osg::ref_ptr cmd = new TranslateInLineCommand(_projector->getLineStart(), _projector->getLineEnd()); cmd->setStage(MotionCommand::FINISH); cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); // Dispatch command. dispatch(*cmd); // Reset color. setMaterialColor(_color,*this); aa.requestRedraw(); } return true; } default: return false; } } void Translate1DDragger::setupDefaultGeometry() { // Get the line length and direction. osg::Vec3 lineDir = _projector->getLineEnd()-_projector->getLineStart(); float lineLength = lineDir.length(); lineDir.normalize(); osg::Geode* geode = new osg::Geode; // Create a left cone. { osg::Cone* cone = new osg::Cone (_projector->getLineStart(), 0.025f * lineLength, 0.10f * lineLength); osg::Quat rotation; rotation.makeRotate(lineDir, osg::Vec3(0.0f, 0.0f, 1.0f)); cone->setRotation(rotation); geode->addDrawable(new osg::ShapeDrawable(cone)); } // Create a right cone. { osg::Cone* cone = new osg::Cone (_projector->getLineEnd(), 0.025f * lineLength, 0.10f * lineLength); osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), lineDir); cone->setRotation(rotation); geode->addDrawable(new osg::ShapeDrawable(cone)); } // Create an invisible cylinder for picking the line. { osg::Cylinder* cylinder = new osg::Cylinder ((_projector->getLineStart()+_projector->getLineEnd())/2, 0.015f * lineLength, lineLength); osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), lineDir); cylinder->setRotation(rotation); osg::Drawable* cylinderGeom = new osg::ShapeDrawable(cylinder); setDrawableToAlwaysCull(*cylinderGeom); geode->addDrawable(cylinderGeom); } osg::Geode* lineGeode = new osg::Geode; // Create a line. { osg::Geometry* geometry = new osg::Geometry(); osg::Vec3Array* vertices = new osg::Vec3Array(2); (*vertices)[0] = _projector->getLineStart(); (*vertices)[1] = _projector->getLineEnd(); geometry->setVertexArray(vertices); geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2)); lineGeode->addDrawable(geometry); } // Turn of lighting for line and set line width. lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); osg::LineWidth* linewidth = new osg::LineWidth(); linewidth->setWidth(2.0f); lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON); // Add line and cones to the scene. addChild(lineGeode); addChild(geode); } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/TrackballDragger.cpp0000644000175000017500000001325112162611727026724 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include #include #include #include #include using namespace osgManipulator; namespace { osg::Geometry* createCircleGeometry(float radius, unsigned int numSegments) { const float angleDelta = 2.0f*osg::PI/(float)numSegments; const float r = radius; float angle = 0.0f; osg::Vec3Array* vertexArray = new osg::Vec3Array(numSegments); osg::Vec3Array* normalArray = new osg::Vec3Array(numSegments); for(unsigned int i = 0; i < numSegments; ++i,angle+=angleDelta) { float c = cosf(angle); float s = sinf(angle); (*vertexArray)[i].set(c*r,s*r,0.0f); (*normalArray)[i].set(c,s,0.0f); } osg::Geometry* geometry = new osg::Geometry(); geometry->setVertexArray(vertexArray); geometry->setNormalArray(normalArray, osg::Array::BIND_PER_VERTEX); geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,vertexArray->size())); return geometry; } } TrackballDragger::TrackballDragger(bool useAutoTransform) { if (useAutoTransform) { float pixelSize = 50.0f; osg::MatrixTransform* scaler = new osg::MatrixTransform; scaler->setMatrix(osg::Matrix::scale(pixelSize, pixelSize, pixelSize)); osg::AutoTransform *at = new osg::AutoTransform; at->setAutoScaleToScreen(true); at->addChild(scaler); AntiSquish* as = new AntiSquish; as->addChild(at); addChild(as); _xDragger = new RotateCylinderDragger(); scaler->addChild(_xDragger.get()); addDragger(_xDragger.get()); _yDragger = new RotateCylinderDragger(); scaler->addChild(_yDragger.get()); addDragger(_yDragger.get()); _zDragger = new RotateCylinderDragger(); scaler->addChild(_zDragger.get()); addDragger(_zDragger.get()); _xyzDragger = new RotateSphereDragger(); scaler->addChild(_xyzDragger.get()); addDragger(_xyzDragger.get()); } else { _xDragger = new RotateCylinderDragger(); addChild(_xDragger.get()); addDragger(_xDragger.get()); _yDragger = new RotateCylinderDragger(); addChild(_yDragger.get()); addDragger(_yDragger.get()); _zDragger = new RotateCylinderDragger(); addChild(_zDragger.get()); addDragger(_zDragger.get()); _xyzDragger = new RotateSphereDragger(); addChild(_xyzDragger.get()); addDragger(_xyzDragger.get()); } setParentDragger(getParentDragger()); } TrackballDragger::~TrackballDragger() { } void TrackballDragger::setupDefaultGeometry() { osg::Geode* geode = new osg::Geode; { osg::TessellationHints* hints = new osg::TessellationHints; hints->setCreateTop(false); hints->setCreateBottom(false); hints->setCreateBackFace(false); osg::Cylinder* cylinder = new osg::Cylinder; cylinder->setHeight(0.15f); osg::ShapeDrawable* cylinderDrawable = new osg::ShapeDrawable(cylinder,hints); geode->addDrawable(cylinderDrawable); setDrawableToAlwaysCull(*cylinderDrawable); geode->addDrawable(createCircleGeometry(1.0f, 100)); } // Draw in line mode. { osg::PolygonMode* polymode = new osg::PolygonMode; polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE); geode->getOrCreateStateSet()->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); geode->getOrCreateStateSet()->setAttributeAndModes(new osg::LineWidth(2.0f),osg::StateAttribute::ON); #if !defined(OSG_GLES2_AVAILABLE) geode->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON); #endif } // Add line to all the individual 1D draggers. _xDragger->addChild(geode); _yDragger->addChild(geode); _zDragger->addChild(geode); // Rotate X-axis dragger appropriately. { osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(1.0f, 0.0f, 0.0f)); _xDragger->setMatrix(osg::Matrix(rotation)); } // Rotate Y-axis dragger appropriately. { osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(0.0f, 1.0f, 0.0f)); _yDragger->setMatrix(osg::Matrix(rotation)); } // Send different colors for each dragger. _xDragger->setColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f)); _yDragger->setColor(osg::Vec4(0.0f,1.0f,0.0f,1.0f)); _zDragger->setColor(osg::Vec4(0.0f,0.0f,1.0f,1.0f)); // Add invisible sphere for pick the spherical dragger. { osg::Drawable* sphereDrawable = new osg::ShapeDrawable(new osg::Sphere()); setDrawableToAlwaysCull(*sphereDrawable); osg::Geode* sphereGeode = new osg::Geode; sphereGeode->addDrawable(sphereDrawable); _xyzDragger->addChild(sphereGeode); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/Scale1DDragger.cpp0000644000175000017500000001601511732410624026235 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include #include using namespace osgManipulator; namespace { double computeScale(const osg::Vec3d& startProjectedPoint, const osg::Vec3d& projectedPoint, double scaleCenter) { double denom = startProjectedPoint[0] - scaleCenter; double scale = denom ? (projectedPoint[0] - scaleCenter)/denom : 1.0; return scale; } } Scale1DDragger::Scale1DDragger(ScaleMode scaleMode) : Dragger(), _minScale(0.001), _scaleMode(scaleMode) { _projector = new LineProjector(osg::Vec3d(-0.5,0.0,0.0),osg::Vec3d(0.5,0.0,0.0)); setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); } Scale1DDragger::~Scale1DDragger() { } bool Scale1DDragger::handle(const PointerInfo& pointer, const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { // Check if the dragger node is in the nodepath. if (!pointer.contains(this)) return false; switch (ea.getEventType()) { // Pick start. case (osgGA::GUIEventAdapter::PUSH): { // Get the LocalToWorld matrix for this node and set it for the projector. osg::NodePath nodePathToRoot; computeNodePathToRoot(*this,nodePathToRoot); osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot); _projector->setLocalToWorld(localToWorld); if (_projector->project(pointer, _startProjectedPoint)) { _scaleCenter = 0.0; if (_scaleMode == SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT) { if ( pointer.contains(_leftHandleNode.get()) ) _scaleCenter = _projector->getLineEnd()[0]; else if ( pointer.contains( _rightHandleNode.get()) ) _scaleCenter = _projector->getLineStart()[0]; } // Generate the motion command. osg::ref_ptr cmd = new Scale1DCommand(); cmd->setStage(MotionCommand::START); cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); // Dispatch command. dispatch(*cmd); // Set color to pick color. setMaterialColor(_pickColor,*this); aa.requestRedraw(); } return true; } // Pick move. case (osgGA::GUIEventAdapter::DRAG): { osg::Vec3d projectedPoint; if (_projector->project(pointer, projectedPoint)) { // Generate the motion command. osg::ref_ptr cmd = new Scale1DCommand(); // Compute scale. double scale = computeScale(_startProjectedPoint,projectedPoint,_scaleCenter); if (scale < getMinScale()) scale = getMinScale(); // Snap the referencePoint to the line start or line end depending on which is closer. double referencePoint = _startProjectedPoint[0]; if (fabs(_projector->getLineStart()[0] - referencePoint) < fabs(_projector->getLineEnd()[0] - referencePoint)) referencePoint = _projector->getLineStart()[0]; else referencePoint = _projector->getLineEnd()[0]; cmd->setStage(MotionCommand::MOVE); cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); cmd->setScale(scale); cmd->setScaleCenter(_scaleCenter); cmd->setReferencePoint(referencePoint); cmd->setMinScale(getMinScale()); // Dispatch command. dispatch(*cmd); aa.requestRedraw(); } return true; } // Pick finish. case (osgGA::GUIEventAdapter::RELEASE): { osg::ref_ptr cmd = new Scale1DCommand(); cmd->setStage(MotionCommand::FINISH); cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); // Dispatch command. dispatch(*cmd); // Reset color. setMaterialColor(_color,*this); aa.requestRedraw(); return true; } default: return false; } } void Scale1DDragger::setupDefaultGeometry() { // Get the line length and direction. osg::Vec3 lineDir = _projector->getLineEnd()-_projector->getLineStart(); float lineLength = lineDir.length(); lineDir.normalize(); osg::Geode* lineGeode = new osg::Geode; // Create a line. { osg::Geometry* geometry = new osg::Geometry(); osg::Vec3Array* vertices = new osg::Vec3Array(2); (*vertices)[0] = _projector->getLineStart(); (*vertices)[1] = _projector->getLineEnd(); geometry->setVertexArray(vertices); geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2)); lineGeode->addDrawable(geometry); } // Turn of lighting for line and set line width. lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); osg::LineWidth* linewidth = new osg::LineWidth(); linewidth->setWidth(2.0f); lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON); // Add line and cones to the scene. addChild(lineGeode); // Create a left box. { osg::Geode* geode = new osg::Geode; geode->addDrawable(new osg::ShapeDrawable(new osg::Box(_projector->getLineStart(), 0.05 * lineLength))); addChild(geode); setLeftHandleNode(*geode); } // Create a right box. { osg::Geode* geode = new osg::Geode; geode->addDrawable(new osg::ShapeDrawable(new osg::Box(_projector->getLineEnd(), 0.05 * lineLength))); addChild(geode); setRightHandleNode(*geode); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/RotateCylinderDragger.cpp0000644000175000017500000001702612162611727027761 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include using namespace osgManipulator; namespace { //------------------------------------------------------------------------------ osg::Geometry* createDiskGeometry(float radius, float offset, float z, unsigned int numSegments ) { const float angleDelta = 2.0f*osg::PI/float(numSegments); const unsigned int numPoints = (numSegments+1) * 2; float angle = 0.0f; osg::Vec3Array* vertexArray = new osg::Vec3Array(numPoints); osg::Vec3Array* normalArray = new osg::Vec3Array(numPoints); unsigned int p = 0; for(unsigned int i = 0; i < numSegments; ++i,angle+=angleDelta) { float c = cosf(angle); float s = sinf(angle); // Outer point (*vertexArray)[p].set(radius*c, radius*s, z); (*normalArray)[p].set(0.0, 0.0, -1.0); ++p; // Inner point (*vertexArray)[p].set((radius-offset)*c, (radius-offset)*s, z); (*normalArray)[p].set(0.0, 0.0, -1.0); ++p; } // do last points by hand to ensure no round off errors. (*vertexArray)[p] = (*vertexArray)[0]; (*normalArray)[p] = (*normalArray)[0]; ++p; (*vertexArray)[p] = (*vertexArray)[1]; (*normalArray)[p] = (*normalArray)[1]; osg::Geometry* geometry = new osg::Geometry; geometry->setVertexArray(vertexArray); geometry->setNormalArray(normalArray, osg::Array::BIND_PER_VERTEX); geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP, 0, vertexArray->size())); return geometry; } } RotateCylinderDragger::RotateCylinderDragger() { _projector = new CylinderPlaneProjector(); setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); } RotateCylinderDragger::~RotateCylinderDragger() { } bool RotateCylinderDragger::handle(const PointerInfo& pointer, const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { // Check if the dragger node is in the nodepath. if (!pointer.contains(this)) return false; switch (ea.getEventType()) { // Pick start. case (osgGA::GUIEventAdapter::PUSH): { // Get the LocalToWorld matrix for this node and set it for the projector. osg::NodePath nodePathToRoot; computeNodePathToRoot(*this,nodePathToRoot); osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot); _projector->setLocalToWorld(localToWorld); _startLocalToWorld = _projector->getLocalToWorld(); _startWorldToLocal = _projector->getWorldToLocal(); if (_projector->isPointInFront(pointer, _startLocalToWorld)) _projector->setFront(true); else _projector->setFront(false); osg::Vec3d projectedPoint; if (_projector->project(pointer, projectedPoint)) { // Generate the motion command. osg::ref_ptr cmd = new Rotate3DCommand(); cmd->setStage(MotionCommand::START); cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal); // Dispatch command. dispatch(*cmd); // Set color to pick color. setMaterialColor(_pickColor,*this); _prevWorldProjPt = projectedPoint * _projector->getLocalToWorld(); _prevRotation = osg::Quat(); aa.requestRedraw(); } return true; } // Pick move. case (osgGA::GUIEventAdapter::DRAG): { // Get the LocalToWorld matrix for this node and set it for the projector. osg::Matrix localToWorld = osg::Matrix(_prevRotation) * _startLocalToWorld; _projector->setLocalToWorld(localToWorld); osg::Vec3d projectedPoint; if (_projector->project(pointer, projectedPoint)) { osg::Vec3d prevProjectedPoint = _prevWorldProjPt * _projector->getWorldToLocal(); osg::Quat deltaRotation = _projector->getRotation(prevProjectedPoint, projectedPoint); osg::Quat rotation = deltaRotation * _prevRotation; // Generate the motion command. osg::ref_ptr cmd = new Rotate3DCommand(); cmd->setStage(MotionCommand::MOVE); cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal); cmd->setRotation(rotation); // Dispatch command. dispatch(*cmd); _prevWorldProjPt = projectedPoint * _projector->getLocalToWorld(); _prevRotation = rotation; aa.requestRedraw(); } return true; } // Pick finish. case (osgGA::GUIEventAdapter::RELEASE): { osg::ref_ptr cmd = new Rotate3DCommand(); cmd->setStage(MotionCommand::FINISH); cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal); // Dispatch command. dispatch(*cmd); // Reset color. setMaterialColor(_color,*this); aa.requestRedraw(); return true; } default: return false; } } void RotateCylinderDragger::setupDefaultGeometry() { osg::Geode* geode = new osg::Geode; { osg::TessellationHints* hints = new osg::TessellationHints; hints->setCreateTop(false); hints->setCreateBottom(false); hints->setCreateBackFace(false); float radius = 1.0f; float height = 0.1f; float thickness = 0.1f; // outer cylinder osg::Cylinder* cylinder = new osg::Cylinder; cylinder->setHeight(height); cylinder->setRadius(radius); osg::ShapeDrawable* cylinderDrawable = new osg::ShapeDrawable(cylinder, hints); geode->addDrawable(cylinderDrawable); // inner cylinder osg::Cylinder* cylinder1 = const_cast(_projector->getCylinder()); cylinder1->setHeight(height); cylinder1->setRadius(radius-thickness); osg::ShapeDrawable* cylinderDrawable1 = new osg::ShapeDrawable(cylinder1, hints); geode->addDrawable(cylinderDrawable1); // top geode->addDrawable(createDiskGeometry(radius, thickness, height/2, 100)); // bottom geode->addDrawable(createDiskGeometry(radius, thickness, -height/2, 100)); } addChild(geode); } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/Translate2DDragger.cpp0000644000175000017500000001656511732410624027156 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include #include using namespace osgManipulator; Translate2DDragger::Translate2DDragger() { _projector = new PlaneProjector(osg::Plane(0.0,1.0,0.0,0.0)); _polygonOffset = new osg::PolygonOffset(-1.0f,-1.0f); setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); } Translate2DDragger::Translate2DDragger(const osg::Plane& plane) { _projector = new PlaneProjector(plane); _polygonOffset = new osg::PolygonOffset(-1.0f,-1.0f); setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); } Translate2DDragger::~Translate2DDragger() { } bool Translate2DDragger::handle(const PointerInfo& pointer, const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { // Check if the dragger node is in the nodepath. if (!pointer.contains(this)) return false; switch (ea.getEventType()) { // Pick start. case (osgGA::GUIEventAdapter::PUSH): { // Get the LocalToWorld matrix for this node and set it for the projector. osg::NodePath nodePathToRoot; computeNodePathToRoot(*this,nodePathToRoot); osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot); _projector->setLocalToWorld(localToWorld); if (_projector->project(pointer, _startProjectedPoint)) { // Generate the motion command. osg::ref_ptr cmd = new TranslateInPlaneCommand(_projector->getPlane()); cmd->setStage(MotionCommand::START); cmd->setReferencePoint(_startProjectedPoint); cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); // Dispatch command. dispatch(*cmd); // Set color to pick color. setMaterialColor(_pickColor,*this); getOrCreateStateSet()->setAttributeAndModes(_polygonOffset.get(), osg::StateAttribute::ON); aa.requestRedraw(); } return true; } // Pick move. case (osgGA::GUIEventAdapter::DRAG): { osg::Vec3d projectedPoint; if (_projector->project(pointer, projectedPoint)) { // Generate the motion command. osg::ref_ptr cmd = new TranslateInPlaneCommand(_projector->getPlane()); cmd->setStage(MotionCommand::MOVE); cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); cmd->setTranslation(projectedPoint - _startProjectedPoint); cmd->setReferencePoint(_startProjectedPoint); // Dispatch command. dispatch(*cmd); aa.requestRedraw(); } return true; } // Pick finish. case (osgGA::GUIEventAdapter::RELEASE): { osg::ref_ptr cmd = new TranslateInPlaneCommand(_projector->getPlane()); cmd->setStage(MotionCommand::FINISH); cmd->setReferencePoint(_startProjectedPoint); cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); // Dispatch command. dispatch(*cmd); // Reset color. setMaterialColor(_color,*this); getOrCreateStateSet()->removeAttribute(_polygonOffset.get()); aa.requestRedraw(); return true; } default: return false; } } void Translate2DDragger::setupDefaultGeometry() { // Create a line. osg::Geode* lineGeode = new osg::Geode; { osg::Geometry* geometry = new osg::Geometry(); osg::Vec3Array* vertices = new osg::Vec3Array(2); (*vertices)[0] = osg::Vec3(0.0f,0.0f,-0.5f); (*vertices)[1] = osg::Vec3(0.0f,0.0f,0.5f); geometry->setVertexArray(vertices); geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2)); lineGeode->addDrawable(geometry); } // Turn of lighting for line and set line width. osg::LineWidth* linewidth = new osg::LineWidth(); linewidth->setWidth(2.0f); lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON); lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); osg::Geode* geode = new osg::Geode; // Create left cone. { osg::Cone* cone = new osg::Cone (osg::Vec3(0.0f, 0.0f, -0.5f), 0.025f, 0.10f); osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f,0.0f,-1.0f), osg::Vec3(0.0f, 0.0f, 1.0f)); cone->setRotation(rotation); geode->addDrawable(new osg::ShapeDrawable(cone)); } // Create right cone. { osg::Cone* cone = new osg::Cone (osg::Vec3(0.0f, 0.0f, 0.5f), 0.025f, 0.10f); geode->addDrawable(new osg::ShapeDrawable(cone)); } // Create an invisible cylinder for picking the line. { osg::Cylinder* cylinder = new osg::Cylinder (osg::Vec3(0.0f,0.0f,0.0f), 0.015f, 1.0f); osg::Drawable* drawable = new osg::ShapeDrawable(cylinder); setDrawableToAlwaysCull(*drawable); geode->addDrawable(drawable); } // MatrixTransform to rotate the geometry according to the normal of the plane. osg::MatrixTransform* xform = new osg::MatrixTransform; // Create an arrow in the X axis. { osg::MatrixTransform* arrow = new osg::MatrixTransform; arrow->addChild(lineGeode); arrow->addChild(geode); // Rotate X-axis arrow appropriately. osg::Quat rotation; rotation.makeRotate(osg::Vec3(1.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 1.0f)); arrow->setMatrix(osg::Matrix(rotation)); xform->addChild(arrow); } // Create an arrow in the Z axis. { osg::Group* arrow = new osg::Group; arrow->addChild(lineGeode); arrow->addChild(geode); xform->addChild(arrow); } // Rotate the xform so that the geometry lies on the plane. { osg::Vec3 normal = _projector->getPlane().getNormal(); normal.normalize(); osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 1.0f, 0.0f), normal); xform->setMatrix(osg::Matrix(rotation)); } addChild(xform); } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/Command.cpp0000644000175000017500000000770511222666045025115 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include using namespace osgManipulator; /////////////////////////////////////////////////////////////////////////////// // // Motion Command base class. // MotionCommand::MotionCommand() : _stage(NONE) { } MotionCommand::~MotionCommand() { } /////////////////////////////////////////////////////////////////////////////// // // Translate in line command. // TranslateInLineCommand::TranslateInLineCommand() { _line = new osg::LineSegment; } TranslateInLineCommand::TranslateInLineCommand(const osg::LineSegment::vec_type& s, const osg::LineSegment::vec_type& e) { _line = new osg::LineSegment(s,e); } TranslateInLineCommand::~TranslateInLineCommand() { } MotionCommand* TranslateInLineCommand::createCommandInverse() { osg::ref_ptr inverse = new TranslateInLineCommand(); *inverse = *this; inverse->setTranslation(-_translation); return inverse.release(); } /////////////////////////////////////////////////////////////////////////////// // // Translate in plane command. // TranslateInPlaneCommand::TranslateInPlaneCommand() { } TranslateInPlaneCommand::TranslateInPlaneCommand(const osg::Plane& plane) : _plane(plane) { } TranslateInPlaneCommand::~TranslateInPlaneCommand() { } MotionCommand* TranslateInPlaneCommand::createCommandInverse() { osg::ref_ptr inverse = new TranslateInPlaneCommand(); *inverse = *this; inverse->setTranslation(-_translation); return inverse.release(); } /////////////////////////////////////////////////////////////////////////////// // // Scale 1D command. // Scale1DCommand::Scale1DCommand() : _scale(1.0) { } Scale1DCommand::~Scale1DCommand() { } MotionCommand* Scale1DCommand::createCommandInverse() { osg::ref_ptr inverse = new Scale1DCommand(); *inverse = *this; if (_scale) inverse->setScale(1.0/_scale); return inverse.release(); } /////////////////////////////////////////////////////////////////////////////// // // Scale 2D command. // Scale2DCommand::Scale2DCommand() : _scale(1.0,1.0) { } Scale2DCommand::~Scale2DCommand() { } MotionCommand* Scale2DCommand::createCommandInverse() { osg::ref_ptr inverse = new Scale2DCommand(); *inverse = *this; if (_scale[0] && _scale[1]) inverse->setScale(osg::Vec2(1.0/_scale[0],1.0/_scale[1])); return inverse.release(); } /////////////////////////////////////////////////////////////////////////////// // // Scale uniform command. // ScaleUniformCommand::ScaleUniformCommand() : _scale(1.0) { } ScaleUniformCommand::~ScaleUniformCommand() { } MotionCommand* ScaleUniformCommand::createCommandInverse() { osg::ref_ptr inverse = new ScaleUniformCommand(); *inverse = *this; if (_scale) inverse->setScale(1.0/_scale); return inverse.release(); } /////////////////////////////////////////////////////////////////////////////// // // Rotate 3D command. // Rotate3DCommand::Rotate3DCommand() { } Rotate3DCommand::~Rotate3DCommand() { } MotionCommand* Rotate3DCommand::createCommandInverse() { osg::ref_ptr inverse = new Rotate3DCommand(); *inverse = *this; inverse->setRotation(_rotation.inverse()); return inverse.release(); } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/Dragger.cpp0000644000175000017500000004425412146641340025107 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include #include using namespace osgManipulator; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // computeNodePathToRoot // void osgManipulator::computeNodePathToRoot(osg::Node& node, osg::NodePath& np) { np.clear(); osg::NodePathList nodePaths = node.getParentalNodePaths(); if (!nodePaths.empty()) { np = nodePaths.front(); if (nodePaths.size()>1) { OSG_NOTICE<<"osgManipulator::computeNodePathToRoot(,) taking first parent path, ignoring others."<getMatrix(); // Get the LocalToWorld and WorldToLocal matrix for this node. osg::NodePath nodePathToRoot; computeNodePathToRoot(*_transform,nodePathToRoot); _localToWorld = osg::computeLocalToWorld(nodePathToRoot); _worldToLocal = osg::Matrix::inverse(_localToWorld); return true; } case MotionCommand::MOVE: { //OSG_NOTICE<<"MotionCommand::MOVE "<setMatrix(localMotionMatrix * _startMotionMatrix); return true; } case MotionCommand::FINISH: { return true; } case MotionCommand::NONE: default: return false; } } bool DraggerTransformCallback::receive(const TranslateInLineCommand& command) { if ((_handleCommandMask&HANDLE_TRANSLATE_IN_LINE)!=0) return receive(static_cast(command)); return false; } bool DraggerTransformCallback::receive(const TranslateInPlaneCommand& command) { if ((_handleCommandMask&HANDLE_TRANSLATE_IN_PLANE)!=0) return receive(static_cast(command)); return false; } bool DraggerTransformCallback::receive(const Scale1DCommand& command) { if ((_handleCommandMask&HANDLE_SCALED_1D)!=0) return receive(static_cast(command)); return false; } bool DraggerTransformCallback::receive(const Scale2DCommand& command) { if ((_handleCommandMask&HANDLE_SCALED_2D)!=0) return receive(static_cast(command)); return false; } bool DraggerTransformCallback::receive(const ScaleUniformCommand& command) { if ((_handleCommandMask&HANDLE_SCALED_UNIFORM)!=0) return receive(static_cast(command)); return false; } bool DraggerTransformCallback::receive(const Rotate3DCommand& command) { if ((_handleCommandMask&HANDLE_ROTATE_3D)!=0) return receive(static_cast(command)); return false; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // PointerInfo // PointerInfo::PointerInfo(): _nearPoint(osg::Vec3d()), _farPoint(osg::Vec3d()), _eyeDir(osg::Vec3d(0,0,1)) { _hitIter = _hitList.begin(); } bool PointerInfo::contains(const osg::Node* node) const { if (node && _hitIter!=_hitList.end()) return std::find((*_hitIter).first.begin(), (*_hitIter).first.end(), node) != (*_hitIter).first.end(); else return false; } bool PointerInfo::projectWindowXYIntoObject(const osg::Vec2d& windowCoord, osg::Vec3d& nearPoint, osg::Vec3d& farPoint) const { nearPoint = osg::Vec3d(windowCoord.x(),windowCoord.y(),0.0)*_inverseMVPW; farPoint = osg::Vec3d(windowCoord.x(),windowCoord.y(),1.0)*_inverseMVPW; return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Dragger // Dragger::Dragger() : _handleEvents(false), _draggerActive(false), _activationModKeyMask(0), _activationMouseButtonMask(0), _activationKeyEvent(0), _activationPermittedByModKeyMask(false), _activationPermittedByMouseButtonMask(false), _activationPermittedByKeyEvent(false), _intersectionMask(0xffffffff) { _parentDragger = this; getOrCreateStateSet()->setDataVariance(osg::Object::DYNAMIC); _selfUpdater = new DraggerTransformCallback(this); } Dragger::Dragger(const Dragger& rhs, const osg::CopyOp& copyop): osg::MatrixTransform(rhs, copyop), _handleEvents(rhs._handleEvents), _draggerActive(false), _activationModKeyMask(rhs._activationModKeyMask), _activationMouseButtonMask(rhs._activationMouseButtonMask), _activationKeyEvent(rhs._activationKeyEvent), _activationPermittedByModKeyMask(false), _activationPermittedByMouseButtonMask(false), _activationPermittedByKeyEvent(false), _intersectionMask(0xffffffff) { } Dragger::~Dragger() { } void Dragger::setHandleEvents(bool flag) { if (_handleEvents == flag) return; _handleEvents = flag; // update the number of children that require an event traversal to make sure this dragger recieves events. if (_handleEvents) setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()+1); else if (getNumChildrenRequiringEventTraversal()>=1) setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1); } void Dragger::addConstraint(Constraint* constraint) { // check to make sure constaint hasn't already been attached. for(Constraints::iterator itr = _constraints.begin(); itr != _constraints.end(); ++itr) { if (*itr == constraint) return; } _constraints.push_back(constraint); } void Dragger::removeConstraint(Constraint* constraint) { for(Constraints::iterator itr = _constraints.begin(); itr != _constraints.end(); ) { if (*itr == constraint) { _constraints.erase(itr); return; } else { ++itr; } } } void Dragger::addTransformUpdating(osg::MatrixTransform* transform, int handleCommandMask) { addDraggerCallback(new DraggerTransformCallback(transform, handleCommandMask)); } void Dragger::removeTransformUpdating(osg::MatrixTransform* transform) { for(Dragger::DraggerCallbacks::iterator itr = _draggerCallbacks.begin(); itr != _draggerCallbacks.end(); ) { DraggerCallback* dc = itr->get(); DraggerTransformCallback* dtc = dynamic_cast(dc); if (dtc && dtc->getTransform()==transform) { itr = _draggerCallbacks.erase(itr); } else { ++itr; } } } void Dragger::addDraggerCallback(DraggerCallback* dc) { for(DraggerCallbacks::iterator itr = _draggerCallbacks.begin(); itr != _draggerCallbacks.end(); ++itr) { if (*itr == dc) return; } _draggerCallbacks.push_back(dc); } void Dragger::removeDraggerCallback(DraggerCallback* dc) { for(Dragger::DraggerCallbacks::iterator itr = _draggerCallbacks.begin(); itr != _draggerCallbacks.end(); ) { if (dc==itr->get()) { itr = _draggerCallbacks.erase(itr); } else { ++itr; } } } void Dragger::traverse(osg::NodeVisitor& nv) { if (_handleEvents && nv.getVisitorType()==osg::NodeVisitor::EVENT_VISITOR) { osgGA::EventVisitor* ev = dynamic_cast(&nv); if (ev) { for(osgGA::EventQueue::Events::iterator itr = ev->getEvents().begin(); itr != ev->getEvents().end(); ++itr) { osgGA::GUIEventAdapter* ea = itr->get(); if (handle(*ea, *(ev->getActionAdapter()))) ea->setHandled(true); } } return; } MatrixTransform::traverse(nv); } bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { if (ea.getHandled()) return false; osgViewer::View* view = dynamic_cast(&aa); if (!view) return false; bool handled = false; bool activationPermitted = true; if (_activationModKeyMask!=0 || _activationMouseButtonMask!=0 || _activationKeyEvent!=0) { _activationPermittedByModKeyMask = (_activationModKeyMask!=0) ? ((ea.getModKeyMask() & _activationModKeyMask)!=0) : false; _activationPermittedByMouseButtonMask = (_activationMouseButtonMask!=0) ? ((ea.getButtonMask() & _activationMouseButtonMask)!=0) : false; if (_activationKeyEvent!=0) { switch (ea.getEventType()) { case osgGA::GUIEventAdapter::KEYDOWN: { if (ea.getKey()==_activationKeyEvent) _activationPermittedByKeyEvent = true; break; } case osgGA::GUIEventAdapter::KEYUP: { if (ea.getKey()==_activationKeyEvent) _activationPermittedByKeyEvent = false; break; } default: break; } } activationPermitted = _activationPermittedByModKeyMask || _activationPermittedByMouseButtonMask || _activationPermittedByKeyEvent; } if (activationPermitted || _draggerActive) { switch (ea.getEventType()) { case osgGA::GUIEventAdapter::PUSH: { osgUtil::LineSegmentIntersector::Intersections intersections; _pointer.reset(); if (view->computeIntersections(ea ,intersections, _intersectionMask)) { for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin(); hitr != intersections.end(); ++hitr) { _pointer.addIntersection(hitr->nodePath, hitr->getLocalIntersectPoint()); } for (osg::NodePath::iterator itr = _pointer._hitList.front().first.begin(); itr != _pointer._hitList.front().first.end(); ++itr) { osgManipulator::Dragger* dragger = dynamic_cast(*itr); if (dragger) { if (dragger==this) { osg::Camera *rootCamera = view->getCamera(); osg::NodePath nodePath = _pointer._hitList.front().first; osg::NodePath::reverse_iterator ritr; for(ritr = nodePath.rbegin(); ritr != nodePath.rend(); ++ritr) { osg::Camera* camera = dynamic_cast(*ritr); if (camera && (camera->getReferenceFrame()!=osg::Transform::RELATIVE_RF || camera->getParents().empty())) { rootCamera = camera; break; } } _pointer.setCamera(rootCamera); _pointer.setMousePosition(ea.getX(), ea.getY()); if(dragger->handle(_pointer, ea, aa)) { dragger->setDraggerActive(true); handled = true; } } } } } break; } case osgGA::GUIEventAdapter::DRAG: case osgGA::GUIEventAdapter::RELEASE: { if (_draggerActive) { _pointer._hitIter = _pointer._hitList.begin(); // _pointer.setCamera(view->getCamera()); _pointer.setMousePosition(ea.getX(), ea.getY()); if(handle(_pointer, ea, aa)) { handled = true; } } break; } default: break; } if (_draggerActive && ea.getEventType() == osgGA::GUIEventAdapter::RELEASE) { setDraggerActive(false); _pointer.reset(); } } return handled; } bool Dragger::receive(const MotionCommand& command) { if (_selfUpdater.valid()) return _selfUpdater->receive(command); else return false; } void Dragger::dispatch(MotionCommand& command) { // apply any constraints for(Constraints::iterator itr = _constraints.begin(); itr != _constraints.end(); ++itr) { command.accept(*(*itr)); } // apply any constraints of parent dragger. if (getParentDragger()!=this) { for(Constraints::iterator itr = getParentDragger()->getConstraints().begin(); itr != getParentDragger()->getConstraints().end(); ++itr) { command.accept(*(*itr)); } } // move self getParentDragger()->receive(command); // pass on movement to any dragger callbacks for(DraggerCallbacks::iterator itr = getParentDragger()->getDraggerCallbacks().begin(); itr != getParentDragger()->getDraggerCallbacks().end(); ++itr) { command.accept(*(*itr)); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // CompositeDragger // CompositeDragger::CompositeDragger(const CompositeDragger& rhs, const osg::CopyOp& copyop): Dragger(rhs, copyop) { OSG_NOTICE<<"CompositeDragger::CompositeDragger(const CompositeDragger& rhs, const osg::CopyOp& copyop) not Implemented yet."<handle(pi, ea, aa)) return true; } return false; } bool CompositeDragger::containsDragger( const Dragger* dragger ) const { for (DraggerList::const_iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr) { if (itr->get() == dragger) return true; } return false; } CompositeDragger::DraggerList::iterator CompositeDragger::findDragger( const Dragger* dragger ) { for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr) { if (itr->get() == dragger) return itr; } return _draggerList.end(); } bool CompositeDragger::addDragger(Dragger *dragger) { if (dragger && !containsDragger(dragger)) { _draggerList.push_back(dragger); return true; } else return false; } bool CompositeDragger::removeDragger(Dragger *dragger) { DraggerList::iterator itr = findDragger(dragger); if (itr != _draggerList.end()) { _draggerList.erase(itr); return true; } else return false; } void CompositeDragger::setParentDragger(Dragger* dragger) { for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr) { (*itr)->setParentDragger(dragger); } Dragger::setParentDragger(dragger); } void CompositeDragger::setIntersectionMask(osg::Node::NodeMask intersectionMask) { Dragger::setIntersectionMask(intersectionMask); for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr) { (*itr)->setIntersectionMask(intersectionMask); } } class ForceCullCallback : public osg::Drawable::CullCallback { public: virtual bool cull(osg::NodeVisitor*, osg::Drawable*, osg::State*) const { return true; } }; void osgManipulator::setDrawableToAlwaysCull(osg::Drawable& drawable) { ForceCullCallback* cullCB = new ForceCullCallback; drawable.setCullCallback (cullCB); } void osgManipulator::setMaterialColor(const osg::Vec4& color, osg::Node& node) { osg::Material* mat = dynamic_cast(node.getOrCreateStateSet()->getAttribute(osg::StateAttribute::MATERIAL)); if (! mat) { mat = new osg::Material; mat->setDataVariance(osg::Object::DYNAMIC); node.getOrCreateStateSet()->setAttribute(mat); } mat->setDiffuse(osg::Material::FRONT_AND_BACK, color); } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/TabBoxTrackballDragger.cpp0000644000175000017500000000272711732410624030025 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include #include #include #include using namespace osgManipulator; TabBoxTrackballDragger::TabBoxTrackballDragger() { _trackballDragger = new TrackballDragger(true); addChild(_trackballDragger.get()); addDragger(_trackballDragger.get()); _tabBoxDragger = new TabBoxDragger(); addChild(_tabBoxDragger.get()); addDragger(_tabBoxDragger.get()); setParentDragger(getParentDragger()); } TabBoxTrackballDragger::~TabBoxTrackballDragger() { } void TabBoxTrackballDragger::setupDefaultGeometry() { _trackballDragger->setupDefaultGeometry(); _tabBoxDragger->setupDefaultGeometry(); } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/TranslatePlaneDragger.cpp0000644000175000017500000000701312162611727027741 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include #include #include #include using namespace osgManipulator; TranslatePlaneDragger::TranslatePlaneDragger() : _usingTranslate1DDragger(false) { _translate2DDragger = new Translate2DDragger(); _translate2DDragger->setColor(osg::Vec4(0.7f, 0.7f, 0.7f, 1.0f)); addChild(_translate2DDragger.get()); addDragger(_translate2DDragger.get()); _translate1DDragger = new Translate1DDragger(osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(0.0f,1.0f,0.0f)); _translate1DDragger->setCheckForNodeInNodePath(false); addChild(_translate1DDragger.get()); addDragger(_translate1DDragger.get()); setParentDragger(getParentDragger()); } TranslatePlaneDragger::~TranslatePlaneDragger() { } bool TranslatePlaneDragger::handle(const PointerInfo& pointer, const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { // Check if the dragger node is in the nodepath. if (!pointer.contains(this)) return false; if ((ea.getButtonMask() & osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) && ea.getEventType() == osgGA::GUIEventAdapter::PUSH) _usingTranslate1DDragger = true; bool handled = false; if (_usingTranslate1DDragger) { if (_translate1DDragger->handle(pointer, ea, aa)) handled = true; } else { if (_translate2DDragger->handle(pointer, ea, aa)) handled = true; } if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE) _usingTranslate1DDragger = false; return handled; } void TranslatePlaneDragger::setupDefaultGeometry() { // Create a polygon. { osg::Geode* geode = new osg::Geode; osg::Geometry* geometry = new osg::Geometry(); osg::Vec3Array* vertices = new osg::Vec3Array(4); (*vertices)[0] = osg::Vec3(-0.5,0.0,0.5); (*vertices)[1] = osg::Vec3(-0.5,0.0,-0.5); (*vertices)[2] = osg::Vec3(0.5,0.0,-0.5); (*vertices)[3] = osg::Vec3(0.5,0.0,0.5); geometry->setVertexArray(vertices); geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,vertices->size())); osg::Vec3Array* normals = new osg::Vec3Array; normals->push_back(osg::Vec3(0.0,1.0,0.0)); geometry->setNormalArray(normals, osg::Array::BIND_OVERALL); geode->addDrawable(geometry); osg::PolygonMode* polymode = new osg::PolygonMode; polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE); geode->getOrCreateStateSet()->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); geode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); _translate2DDragger->addChild(geode); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/ScaleAxisDragger.cpp0000644000175000017500000000636611732410624026705 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include using namespace osgManipulator; ScaleAxisDragger::ScaleAxisDragger() { _xDragger = new osgManipulator::Scale1DDragger(); addChild(_xDragger.get()); addDragger(_xDragger.get()); _yDragger = new osgManipulator::Scale1DDragger(); addChild(_yDragger.get()); addDragger(_yDragger.get()); _zDragger = new osgManipulator::Scale1DDragger(); addChild(_zDragger.get()); addDragger(_zDragger.get()); setParentDragger(getParentDragger()); } ScaleAxisDragger::~ScaleAxisDragger() { } void ScaleAxisDragger::setupDefaultGeometry() { // Create a line. osg::Geode* lineGeode = new osg::Geode; { osg::Geometry* geometry = new osg::Geometry(); osg::Vec3Array* vertices = new osg::Vec3Array(2); (*vertices)[0] = osg::Vec3(0.0f,0.0f,0.0f); (*vertices)[1] = osg::Vec3(1.0f,0.0f,0.0f); geometry->setVertexArray(vertices); geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2)); lineGeode->addDrawable(geometry); } // Turn of lighting for line and set line width. { osg::LineWidth* linewidth = new osg::LineWidth(); linewidth->setWidth(2.0f); lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON); lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); } // Add line to all the individual 1D draggers. _xDragger->addChild(lineGeode); _yDragger->addChild(lineGeode); _zDragger->addChild(lineGeode); osg::Geode* geode = new osg::Geode; // Create a box. geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(1.0f,0.0f,0.0f), 0.05))); // Add geode to all 1D draggers. _xDragger->addChild(geode); _yDragger->addChild(geode); _zDragger->addChild(geode); // Rotate Z-axis dragger appropriately. { osg::Quat rotation; rotation.makeRotate(osg::Vec3(1.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 1.0f)); _zDragger->setMatrix(osg::Matrix(rotation)); } // Rotate Y-axis dragger appropriately. { osg::Quat rotation; rotation.makeRotate(osg::Vec3(1.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 1.0f, 0.0f)); _yDragger->setMatrix(osg::Matrix(rotation)); } // Send different colors for each dragger. _xDragger->setColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f)); _yDragger->setColor(osg::Vec4(0.0f,1.0f,0.0f,1.0f)); _zDragger->setColor(osg::Vec4(0.0f,0.0f,1.0f,1.0f)); } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/CMakeLists.txt0000644000175000017500000000330411535432121025553 0ustar albertoalberto IF(DYNAMIC_OPENSCENEGRAPH) ADD_DEFINITIONS(-DOSGMANIPULATOR_LIBRARY) ELSE() ADD_DEFINITIONS(-DOSG_LIBRARY_STATIC) ENDIF() SET(LIB_NAME osgManipulator) SET(HEADER_PATH ${OpenSceneGraph_SOURCE_DIR}/include/${LIB_NAME}) SET(TARGET_H ${HEADER_PATH}/AntiSquish ${HEADER_PATH}/Command ${HEADER_PATH}/CommandManager ${HEADER_PATH}/Constraint ${HEADER_PATH}/Dragger ${HEADER_PATH}/Export ${HEADER_PATH}/Projector ${HEADER_PATH}/RotateCylinderDragger ${HEADER_PATH}/RotateSphereDragger ${HEADER_PATH}/Scale1DDragger ${HEADER_PATH}/Scale2DDragger ${HEADER_PATH}/ScaleAxisDragger ${HEADER_PATH}/Selection ${HEADER_PATH}/TabBoxDragger ${HEADER_PATH}/TabBoxTrackballDragger ${HEADER_PATH}/TabPlaneDragger ${HEADER_PATH}/TabPlaneTrackballDragger ${HEADER_PATH}/TrackballDragger ${HEADER_PATH}/Translate1DDragger ${HEADER_PATH}/Translate2DDragger ${HEADER_PATH}/TranslateAxisDragger ${HEADER_PATH}/TranslatePlaneDragger ${HEADER_PATH}/Version ) # FIXME: For OS X, need flag for Framework or dylib SET(TARGET_SRC AntiSquish.cpp Command.cpp Constraint.cpp Dragger.cpp Projector.cpp RotateCylinderDragger.cpp RotateSphereDragger.cpp Scale1DDragger.cpp Scale2DDragger.cpp ScaleAxisDragger.cpp TabBoxDragger.cpp TabBoxTrackballDragger.cpp TabPlaneDragger.cpp TabPlaneTrackballDragger.cpp TrackballDragger.cpp Translate1DDragger.cpp Translate2DDragger.cpp TranslateAxisDragger.cpp TranslatePlaneDragger.cpp Version.cpp ${OPENSCENEGRAPH_VERSIONINFO_RC} ) SET(TARGET_LIBRARIES osgViewer osgGA osgUtil osg OpenThreads ) SETUP_LIBRARY(${LIB_NAME}) openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/RotateSphereDragger.cpp0000644000175000017500000001255311732410624027431 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include #include using namespace osgManipulator; RotateSphereDragger::RotateSphereDragger() : _prevPtOnSphere(true) { _projector = new SpherePlaneProjector(); setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); } RotateSphereDragger::~RotateSphereDragger() { } bool RotateSphereDragger::handle(const PointerInfo& pointer, const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { // Check if the dragger node is in the nodepath. if (!pointer.contains(this)) return false; switch (ea.getEventType()) { // Pick start. case (osgGA::GUIEventAdapter::PUSH): { // Get the LocalToWorld matrix for this node and set it for the projector. osg::NodePath nodePathToRoot; computeNodePathToRoot(*this,nodePathToRoot); osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot); _projector->setLocalToWorld(localToWorld); _startLocalToWorld = _projector->getLocalToWorld(); _startWorldToLocal = _projector->getWorldToLocal(); if (_projector->isPointInFront(pointer, _startLocalToWorld)) _projector->setFront(true); else _projector->setFront(false); osg::Vec3d projectedPoint; if (_projector->project(pointer, projectedPoint)) { // Generate the motion command. osg::ref_ptr cmd = new Rotate3DCommand(); cmd->setStage(MotionCommand::START); cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal); // Dispatch command. dispatch(*cmd); // Set color to pick color. setMaterialColor(_pickColor,*this); _prevRotation = osg::Quat(); _prevWorldProjPt = projectedPoint * _projector->getLocalToWorld(); _prevPtOnSphere = _projector->isProjectionOnSphere(); aa.requestRedraw(); } return true; } // Pick move. case (osgGA::GUIEventAdapter::DRAG): { // Get the LocalToWorld matrix for this node and set it for the projector. osg::Matrix localToWorld = osg::Matrix(_prevRotation) * _startLocalToWorld; _projector->setLocalToWorld(localToWorld); osg::Vec3d projectedPoint; if (_projector->project(pointer, projectedPoint)) { osg::Vec3d prevProjectedPoint = _prevWorldProjPt * _projector->getWorldToLocal(); osg::Quat deltaRotation = _projector->getRotation(prevProjectedPoint, _prevPtOnSphere, projectedPoint, _projector->isProjectionOnSphere(),1.0f); osg::Quat rotation = deltaRotation * _prevRotation; // Generate the motion command. osg::ref_ptr cmd = new Rotate3DCommand(); cmd->setStage(MotionCommand::MOVE); cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal); cmd->setRotation(rotation); // Dispatch command. dispatch(*cmd); _prevWorldProjPt = projectedPoint * _projector->getLocalToWorld(); _prevRotation = rotation; _prevPtOnSphere = _projector->isProjectionOnSphere(); aa.requestRedraw(); } return true; } // Pick finish. case (osgGA::GUIEventAdapter::RELEASE): { osg::ref_ptr cmd = new Rotate3DCommand(); cmd->setStage(MotionCommand::FINISH); cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal); // Dispatch command. dispatch(*cmd); // Reset color. setMaterialColor(_color,*this); aa.requestRedraw(); return true; } default: return false; } } void RotateSphereDragger::setupDefaultGeometry() { osg::Geode* geode = new osg::Geode; geode->addDrawable(new osg::ShapeDrawable(const_cast(_projector->getSphere()))); addChild(geode); } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/Projector.cpp0000644000175000017500000005206611732410624025502 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include using namespace osgManipulator; // When the squared magnitude (length2) of the cross product of 2 // angles is less than this tolerance, they are considered parallel. // osg::Vec3 a, b; (a ^ b).length2() #define CROSS_PRODUCT_ANGLE_TOLERANCE 1.0e-1 namespace { bool computeClosestPoints(const osg::LineSegment& l1, const osg::LineSegment& l2, osg::Vec3d& p1, osg::Vec3d& p2) { // Computes the closest points (p1 and p2 on line l1 and l2 respectively) between the two lines // An explanation of the algorithm can be found at // http://www.geometryalgorithms.com/Archive/algorithm_0106/algorithm_0106.htm osg::LineSegment::vec_type u = l1.end() - l1.start(); u.normalize(); osg::LineSegment::vec_type v = l2.end() - l2.start(); v.normalize(); osg::LineSegment::vec_type w0 = l1.start() - l2.start(); double a = u * u; double b = u * v; double c = v * v; double d = u * w0; double e = v * w0; double denominator = a*c - b*b; // Test if lines are parallel if (denominator == 0.0) return false; double sc = (b*e - c*d)/denominator; double tc = (a*e - b*d)/denominator; p1 = l1.start() + u * sc; p2 = l2.start() + v * tc; return true; } bool computeClosestPointOnLine(const osg::Vec3d& lineStart, const osg::Vec3d& lineEnd, const osg::Vec3d& fromPoint, osg::Vec3d& closestPoint) { osg::Vec3d v = lineEnd - lineStart; osg::Vec3d w = fromPoint - lineStart; double c1 = w * v; double c2 = v * v; double almostZero = 0.000001; if (c2 < almostZero) return false; double b = c1 / c2; closestPoint = lineStart + v * b; return true; } bool getPlaneLineIntersection(const osg::Vec4d& plane, const osg::Vec3d& lineStart, const osg::Vec3d& lineEnd, osg::Vec3d& isect) { const double deltaX = lineEnd.x() - lineStart.x(); const double deltaY = lineEnd.y() - lineStart.y(); const double deltaZ = lineEnd.z() - lineStart.z(); const double denominator = (plane[0]*deltaX + plane[1]*deltaY + plane[2]*deltaZ); if (! denominator) return false; const double C = (plane[0]*lineStart.x() + plane[1]*lineStart.y() + plane[2]*lineStart.z() + plane[3]) / denominator; isect.x() = lineStart.x() - deltaX * C; isect.y() = lineStart.y() - deltaY * C; isect.z() = lineStart.z() - deltaZ * C; return true; } bool getSphereLineIntersection(const osg::Sphere& sphere, const osg::Vec3d& lineStart, const osg::Vec3d& lineEnd, osg::Vec3d& frontISect, osg::Vec3d& backISect) { osg::Vec3d lineDirection = lineEnd - lineStart; lineDirection.normalize(); osg::Vec3d v = lineStart - sphere.getCenter(); double B = 2.0f * (lineDirection * v); double C = v * v - sphere.getRadius() * sphere.getRadius(); double discriminant = B * B - 4.0f * C; if (discriminant < 0.0f) // Line and sphere don't intersect. return false; double discriminantSqroot = sqrtf(discriminant); double t0 = (-B - discriminantSqroot) * 0.5f; frontISect = lineStart + lineDirection * t0; double t1 = (-B + discriminantSqroot) * 0.5f; backISect = lineStart + lineDirection * t1; return true; } bool getUnitCylinderLineIntersection(const osg::Vec3d& lineStart, const osg::Vec3d& lineEnd, osg::Vec3d& isectFront, osg::Vec3d& isectBack) { osg::Vec3d dir = lineEnd - lineStart; dir.normalize(); double a = dir[0] * dir[0] + dir[1] * dir[1]; double b = 2.0f * (lineStart[0] * dir[0] + lineStart[1] * dir[1]); double c = lineStart[0] * lineStart[0] + lineStart[1] * lineStart[1] - 1; double d = b*b - 4*a*c; if (d < 0.0f) return false; double dSqroot = sqrtf(d); double t0, t1; if (b > 0.0f) { t0 = -(2.0f * c) / (dSqroot + b); t1 = -(dSqroot + b) / (2.0 * a); } else { t0 = (2.0f * c) / (dSqroot - b); t1 = (dSqroot - b) / (2.0 * a); } isectFront = lineStart + dir * t0; isectBack = lineStart + dir * t1; return true; } bool getCylinderLineIntersection(const osg::Cylinder& cylinder, const osg::Vec3d& lineStart, const osg::Vec3d& lineEnd, osg::Vec3d& isectFront, osg::Vec3d& isectBack) { // Compute matrix transformation that takes the cylinder to a unit cylinder with Z-axis as it's axis and // (0,0,0) as it's center. double oneOverRadius = 1.0f / cylinder.getRadius(); osg::Matrix toUnitCylInZ = osg::Matrix::translate(-cylinder.getCenter()) * osg::Matrix::scale(oneOverRadius, oneOverRadius, oneOverRadius) * osg::Matrix(cylinder.getRotation().inverse()); // Transform the lineStart and lineEnd into the unit cylinder space. osg::Vec3d unitCylLineStart = lineStart * toUnitCylInZ; osg::Vec3d unitCylLineEnd = lineEnd * toUnitCylInZ; // Intersect line with unit cylinder. osg::Vec3d unitCylIsectFront, unitCylIsectBack; if (! getUnitCylinderLineIntersection(unitCylLineStart, unitCylLineEnd, unitCylIsectFront, unitCylIsectBack)) return false; // Transform back from unit cylinder space. osg::Matrix invToUnitCylInZ(osg::Matrix::inverse(toUnitCylInZ)); isectFront = unitCylIsectFront * invToUnitCylInZ; isectBack = unitCylIsectBack * invToUnitCylInZ; return true; } osg::Vec3d getLocalEyeDirection(const osg::Vec3d& eyeDir, const osg::Matrix& localToWorld) { // To take a normal from world to local you need to transform it by the transpose of the inverse of the // world to local matrix. Pre-multiplying is equivalent to doing a post-multiplication of the transpose. osg::Vec3d localEyeDir = localToWorld * eyeDir; localEyeDir.normalize(); return localEyeDir; } osg::Plane computePlaneThruPointAndOrientedToEye(const osg::Vec3d& eyeDir, const osg::Matrix& localToWorld, const osg::Vec3d& point, bool front) { osg::Vec3d planeNormal = getLocalEyeDirection(eyeDir, localToWorld); if (! front) planeNormal = -planeNormal; osg::Plane plane; plane.set(planeNormal, point); return plane; } // Computes a plane to be used as a basis for determining a displacement. When eyeDir is close // to the cylinder axis, then the plane will be set to be perpendicular to the cylinder axis. // Otherwise it will be set to be parallel to the cylinder axis and oriented towards eyeDir. osg::Plane computeIntersectionPlane(const osg::Vec3d& eyeDir, const osg::Matrix& localToWorld, const osg::Vec3d& axisDir, const osg::Cylinder& cylinder, osg::Vec3d& planeLineStart, osg::Vec3d& planeLineEnd, bool& parallelPlane, bool front) { osg::Plane plane; osg::Vec3d unitAxisDir = axisDir; unitAxisDir.normalize(); osg::Vec3d perpDir = unitAxisDir ^ getLocalEyeDirection(eyeDir, localToWorld); // Check to make sure eye and cylinder axis are not too close if(perpDir.length2() < CROSS_PRODUCT_ANGLE_TOLERANCE) { // Too close, so instead return plane perpendicular to cylinder axis. plane.set(unitAxisDir, cylinder.getCenter()); parallelPlane = false; return plane; } // Otherwise compute plane along axisDir oriented towards eye osg::Vec3d planeDir = perpDir ^ axisDir; planeDir.normalize(); if (! front) planeDir = -planeDir; osg::Vec3d planePoint = planeDir * cylinder.getRadius() + axisDir; plane.set(planeDir, planePoint); planeLineStart = planePoint; planeLineEnd = planePoint + axisDir; parallelPlane = true; return plane; } } // namespace Projector::Projector() : _worldToLocalDirty(false) { } Projector::~Projector() { } LineProjector::LineProjector() { _line = new osg::LineSegment(osg::LineSegment::vec_type(0.0,0.0,0.0), osg::LineSegment::vec_type(1.0,0.0,0.0)); } LineProjector::LineProjector(const osg::LineSegment::vec_type& s, const osg::LineSegment::vec_type& e) { _line = new osg::LineSegment(s,e); } LineProjector::~LineProjector() { } bool LineProjector::project(const PointerInfo& pi, osg::Vec3d& projectedPoint) const { if (!_line->valid()) { OSG_WARN << "Warning: Invalid line set. LineProjector::project() failed."< objectLine = new osg::LineSegment; objectLine->mult(*_line, getLocalToWorld()); // Get the near and far points for the mouse point. osg::Vec3d nearPoint, farPoint; pi.getNearFarPoints(nearPoint,farPoint); osg::ref_ptr pointerLine = new osg::LineSegment(nearPoint,farPoint); osg::Vec3d closestPtLine, closestPtProjWorkingLine; if (! computeClosestPoints(*objectLine, *pointerLine, closestPtLine, closestPtProjWorkingLine)) return false; osg::Vec3d localClosestPtLine = closestPtLine * getWorldToLocal(); projectedPoint = localClosestPtLine; return true; } PlaneProjector::PlaneProjector() { } PlaneProjector::PlaneProjector(const osg::Plane& plane) { _plane = plane; } PlaneProjector::~PlaneProjector() { } bool PlaneProjector::project(const PointerInfo& pi, osg::Vec3d& projectedPoint) const { if (!_plane.valid()) { OSG_WARN << "Warning: Invalid plane set. PlaneProjector::project() failed."<< std::endl; return false; } // Get the near and far points for the mouse point. osg::Vec3d nearPoint, farPoint; pi.getNearFarPoints(nearPoint,farPoint); // Transform these points into local coordinates. osg::Vec3d objectNearPoint, objectFarPoint; objectNearPoint = nearPoint * getWorldToLocal(); objectFarPoint = farPoint * getWorldToLocal(); // Find the intersection of the plane with the line (formed by the near and far points in local coordinates). return getPlaneLineIntersection(_plane.asVec4(), objectNearPoint, objectFarPoint, projectedPoint); } SphereProjector::SphereProjector() : _sphere(new osg::Sphere), _front(true) { } SphereProjector::SphereProjector(osg::Sphere* sphere) : _sphere(sphere), _front(true) { } SphereProjector::~SphereProjector() { } bool SphereProjector::project(const PointerInfo& pi, osg::Vec3d& projectedPoint) const { if (!_sphere->valid()) { OSG_WARN << "Warning: Invalid sphere. SphereProjector::project() failed." << std::endl; return false; } // Get the near and far points for the mouse point. osg::Vec3d nearPoint, farPoint; pi.getNearFarPoints(nearPoint,farPoint); // Transform these points into local coordinates. osg::Vec3d objectNearPoint, objectFarPoint; objectNearPoint = nearPoint * getWorldToLocal(); objectFarPoint = farPoint * getWorldToLocal(); // Find the intersection of the sphere with the line. osg::Vec3d dontCare; if (_front) return getSphereLineIntersection(*_sphere, objectNearPoint, objectFarPoint, projectedPoint, dontCare); return getSphereLineIntersection(*_sphere, objectNearPoint, objectFarPoint, dontCare, projectedPoint); } bool SphereProjector::isPointInFront(const PointerInfo& pi, const osg::Matrix& localToWorld) const { osg::Vec3d centerToPoint = getSphere()->getCenter() - pi.getLocalIntersectPoint(); if (centerToPoint * getLocalEyeDirection(pi.getEyeDir(), localToWorld) < 0.0) return false; return true; } SpherePlaneProjector::SpherePlaneProjector() { } SpherePlaneProjector::SpherePlaneProjector(osg::Sphere* sphere) : SphereProjector(sphere) { } SpherePlaneProjector::~SpherePlaneProjector() { } osg::Quat SpherePlaneProjector::getRotation(const osg::Vec3d& p1, bool p1OnSphere, const osg::Vec3d& p2, bool p2OnSphere, float radialFactor) const { if (p1OnSphere && p2OnSphere) { osg::Quat rotation; if (_front) rotation.makeRotate(p1 - getSphere()->getCenter(), p2 - getSphere()->getCenter()); else rotation.makeRotate(p2 - getSphere()->getCenter(), p1 - getSphere()->getCenter()); return rotation; } else if (!p1OnSphere && !p2OnSphere) { osg::Quat rotation; rotation.makeRotate(p1 - getSphere()->getCenter(), p2 - getSphere()->getCenter()); osg::Vec3d axis; double angle; rotation.getRotate(angle, axis); osg::Vec3d realAxis; if (axis * _plane.getNormal() > 0.0f) realAxis = _plane.getNormal(); else realAxis = - _plane.getNormal(); osg::Quat rollRotation(angle, realAxis); osg::Vec3d diff1 = p1 - getSphere()->getCenter(); osg::Vec3d diff2 = p2 - getSphere()->getCenter(); double d = diff2.length() - diff1.length(); double theta = d / getSphere()->getRadius(); if (fabs(theta) < 0.000001 || fabs(theta) > 1.0) return rollRotation; diff1.normalize(); osg::Vec3d pullAxis = diff1 ^ _plane.getNormal(); pullAxis.normalize(); osg::Quat pullRotation(radialFactor * theta, pullAxis); osg::Quat totalRotation = pullRotation * rollRotation; return totalRotation; } else { const osg::Vec3d& planePoint = getSphere()->getCenter(); osg::Vec3d intersection, dontCare; if (p1OnSphere) getSphereLineIntersection(*getSphere(), p2, planePoint, intersection, dontCare); else getSphereLineIntersection(*getSphere(), p1, planePoint, intersection, dontCare); osg::Quat rotation; if (p1OnSphere) rotation.makeRotate(p1 - getSphere()->getCenter(), intersection - getSphere()->getCenter()); else rotation.makeRotate(intersection - getSphere()->getCenter(), p2 - getSphere()->getCenter()); return rotation; } } bool SpherePlaneProjector::project(const PointerInfo& pi, osg::Vec3d& projectedPoint) const { if (!_sphere->valid()) { OSG_WARN << "Warning: Invalid sphere. SpherePlaneProjector::project() failed." << std::endl; return false; } // Get the near and far points for the mouse point. osg::Vec3d nearPoint, farPoint; pi.getNearFarPoints(nearPoint,farPoint); // Transform these points into local coordinates. osg::Vec3d objectNearPoint, objectFarPoint; objectNearPoint = nearPoint * getWorldToLocal(); objectFarPoint = farPoint * getWorldToLocal(); // Find the intersection of the sphere with the line. osg::Vec3d sphereIntersection, dontCare; bool hitSphere = false; if (_front) hitSphere = getSphereLineIntersection(*_sphere, objectNearPoint, objectFarPoint, sphereIntersection, dontCare); else hitSphere = getSphereLineIntersection(*_sphere, objectNearPoint, objectFarPoint, dontCare, sphereIntersection); // Compute plane oriented to the eye. _plane = computePlaneThruPointAndOrientedToEye(pi.getEyeDir(), getLocalToWorld(), getSphere()->getCenter(), _front); // Find the intersection on the plane. osg::Vec3d planeIntersection; if (hitSphere) { if (! getPlaneLineIntersection(_plane.asVec4(), sphereIntersection, sphereIntersection + _plane.getNormal(), planeIntersection)) return false; } else { if (! getPlaneLineIntersection(_plane.asVec4(), objectNearPoint, objectFarPoint, planeIntersection)) return false; } // Distance from the plane intersection point to the center of the sphere. double dist = (planeIntersection - getSphere()->getCenter()).length(); // If the distance is less that the sphere radius choose the sphere intersection else choose // the plane intersection. if (dist < getSphere()->getRadius()) { if (! hitSphere) return false; projectedPoint = sphereIntersection; _onSphere = true; } else { projectedPoint = planeIntersection; _onSphere = false; } return true; } CylinderProjector::CylinderProjector() : _cylinder(new osg::Cylinder()), _cylinderAxis(0.0,0.0,1.0), _front(true) { } CylinderProjector::CylinderProjector(osg::Cylinder* cylinder) : _front(true) { setCylinder(cylinder); } CylinderProjector::~CylinderProjector() { } bool CylinderProjector::project(const PointerInfo& pi, osg::Vec3d& projectedPoint) const { if (!_cylinder.valid()) { OSG_WARN << "Warning: Invalid cylinder. CylinderProjector::project() failed." << std::endl; return false; } // Get the near and far points for the mouse point. osg::Vec3d nearPoint, farPoint; pi.getNearFarPoints(nearPoint,farPoint); // Transform these points into local coordinates. osg::Vec3d objectNearPoint, objectFarPoint; objectNearPoint = nearPoint * getWorldToLocal(); objectFarPoint = farPoint * getWorldToLocal(); // Find the intersection of the sphere with the line. osg::Vec3d dontCare; return getCylinderLineIntersection(*_cylinder, objectNearPoint, objectFarPoint, projectedPoint, dontCare); } bool CylinderProjector::isPointInFront(const PointerInfo& pi, const osg::Matrix& localToWorld) const { osg::Vec3d closestPointOnAxis; computeClosestPointOnLine(getCylinder()->getCenter(), getCylinder()->getCenter() + _cylinderAxis, pi.getLocalIntersectPoint(), closestPointOnAxis); osg::Vec3d perpPoint = pi.getLocalIntersectPoint() - closestPointOnAxis; if (perpPoint * getLocalEyeDirection(pi.getEyeDir(), localToWorld) < 0.0) return false; return true; } CylinderPlaneProjector::CylinderPlaneProjector() { } CylinderPlaneProjector::CylinderPlaneProjector(osg::Cylinder* cylinder) : CylinderProjector(cylinder), _parallelPlane(false) { } CylinderPlaneProjector::~CylinderPlaneProjector() { } bool CylinderPlaneProjector::project(const PointerInfo& pi, osg::Vec3d& projectedPoint) const { if (!_cylinder.valid()) { OSG_WARN << "Warning: Invalid cylinder. CylinderProjector::project() failed." << std::endl; return false; } // Get the near and far points for the mouse point. osg::Vec3d nearPoint, farPoint; pi.getNearFarPoints(nearPoint,farPoint); // Transform these points into local coordinates. osg::Vec3d objectNearPoint, objectFarPoint; objectNearPoint = nearPoint * getWorldToLocal(); objectFarPoint = farPoint * getWorldToLocal(); // Computes either a plane parallel to cylinder axis oriented to the eye or the plane // perpendicular to the cylinder axis if the eye-cylinder angle is close. _plane = computeIntersectionPlane(pi.getEyeDir(), getLocalToWorld(), _cylinderAxis, *_cylinder, _planeLineStart, _planeLineEnd, _parallelPlane, _front); // Now find the point of intersection on our newly-calculated plane. getPlaneLineIntersection(_plane.asVec4(), objectNearPoint, objectFarPoint, projectedPoint); return true; } osg::Quat CylinderPlaneProjector::getRotation(const osg::Vec3d& p1, const osg::Vec3d& p2) const { if(_parallelPlane) { osg::Vec3d closestPointToPlaneLine1, closestPointToPlaneLine2; computeClosestPointOnLine(_planeLineStart, _planeLineEnd, p1, closestPointToPlaneLine1); computeClosestPointOnLine(_planeLineStart, _planeLineEnd, p2, closestPointToPlaneLine2); osg::Vec3d v1 = p1 - closestPointToPlaneLine1; osg::Vec3d v2 = p2 - closestPointToPlaneLine2; osg::Vec3d diff = v2 - v1; double d = diff.length(); // The amount of rotation is inversely proportional to the size of the cylinder double angle = (getCylinder()->getRadius() == 0.0) ? 0.0 : (d / getCylinder()->getRadius()); osg::Vec3d rotAxis = _plane.getNormal() ^ v1; if (v2.length() > v1.length()) return osg::Quat(angle, rotAxis); else return osg::Quat(-angle, rotAxis); } else { osg::Vec3d v1 = p1 - getCylinder()->getCenter(); osg::Vec3d v2 = p2 - getCylinder()->getCenter(); double cosAngle = v1 * v2 / (v1.length() * v2.length()); if (cosAngle > 1.0 || cosAngle < -1.0) return osg::Quat(); double angle = acosf(cosAngle); osg::Vec3d rotAxis = v1 ^ v2; return osg::Quat(angle, rotAxis); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/AntiSquish.cpp0000644000175000017500000001172311732410624025616 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include using namespace osgManipulator; namespace { class AntiSquishCallback: public osg::NodeCallback { public: AntiSquishCallback(AntiSquish* asq) : osg::NodeCallback(), _antiSquish(asq) {} virtual ~AntiSquishCallback() {}; virtual void operator() (osg::Node* node, osg::NodeVisitor* nv) { // Get the node path. osg::NodePath np = nv->getNodePath(); // Remove the last node which is the anti squish node itself. np.pop_back(); // Get the accumulated modeling matrix. osg::Matrix localToWorld = osg::computeLocalToWorld(np); // compute the unsquished matrix. bool flag = false; osg::Matrix _unsquishedMatrix = _antiSquish->computeUnSquishedMatrix(localToWorld, flag); if (flag) _antiSquish->setMatrix(_unsquishedMatrix); traverse(node,nv); } protected: AntiSquish* _antiSquish; }; } AntiSquish::AntiSquish() : _usePivot(true), _usePosition(false) { _asqCallback = new AntiSquishCallback(this); setUpdateCallback(_asqCallback); } AntiSquish::AntiSquish(const osg::Vec3d& pivot) : _pivot(pivot), _usePivot(true), _usePosition(false) { _asqCallback = new AntiSquishCallback(this); setUpdateCallback(_asqCallback); } AntiSquish::AntiSquish(const osg::Vec3d& pivot, const osg::Vec3d& pos) : _pivot(pivot), _usePivot(true), _position(pos), _usePosition(true) { _asqCallback = new AntiSquishCallback(this); setUpdateCallback(_asqCallback); } AntiSquish::AntiSquish(const AntiSquish& pat,const osg::CopyOp& copyop) : MatrixTransform(pat,copyop), _asqCallback(pat._asqCallback), _pivot(pat._pivot), _usePivot(pat._usePivot), _position(pat._position), _usePosition(pat._usePosition), _cachedLocalToWorld(pat._cachedLocalToWorld) { } AntiSquish::~AntiSquish() { } osg::Matrix AntiSquish::computeUnSquishedMatrix(const osg::Matrix& LTW, bool& flag) { osg::Vec3d t, s; osg::Quat r, so; if (LTW == _cachedLocalToWorld && _dirty == false) { flag = false; return osg::Matrix::identity(); } _cachedLocalToWorld = LTW; LTW.decompose(t, r, s, so); // Let's take an average of the scale. double av = (s[0] + s[1] + s[2])/3.0; s[0] = av; s[1] = av; s[2]=av; if (av == 0) { flag = false; return osg::Matrix::identity(); } osg::Matrix unsquished; // // Final Matrix: [-Pivot][SO]^[S][SO][R][T][Pivot][LOCALTOWORLD]^[position] // OR [SO]^[S][SO][R][T][LOCALTOWORLD]^ // if (_usePivot) { unsquished.postMultTranslate(-_pivot); osg::Matrix tmps, invtmps; so.get(tmps); if (!invtmps.invert(tmps)) { flag = false; return osg::Matrix::identity(); } //SO^ unsquished.postMult(invtmps); //S unsquished.postMultScale(s); //SO unsquished.postMult(tmps); //R unsquished.postMultRotate(r); //T unsquished.postMultTranslate(t); osg::Matrix invltw; if (!invltw.invert(LTW)) { flag = false; return osg::Matrix::identity(); } // LTW^ unsquished.postMult( invltw ); // Position if (_usePosition) unsquished.postMultTranslate(_position); else unsquished.postMultTranslate(_pivot); } else { osg::Matrix tmps, invtmps; so.get(tmps); if (!invtmps.invert(tmps)) { flag = false; return osg::Matrix::identity(); } unsquished.postMult(invtmps); unsquished.postMultScale(s); unsquished.postMult(tmps); unsquished.postMultRotate(r); unsquished.postMultTranslate(t); osg::Matrix invltw; if (!invltw.invert(LTW)) { flag = false; return osg::Matrix::identity(); } unsquished.postMult( invltw ); } if (unsquished.isNaN()) { flag = false; return osg::Matrix::identity(); } flag = true; _dirty = false; return unsquished; } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/TabPlaneDragger.cpp0000644000175000017500000002626512162611727026524 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include #include #include #include #include using namespace osgManipulator; namespace { osg::Node* createHandleNode(Scale2DDragger* cornerScaleDragger, float handleScaleFactor, bool twosided) { osg::Vec3Array* vertices = new osg::Vec3Array(4); (*vertices)[0] = osg::Vec3(cornerScaleDragger->getTopLeftHandlePosition()[0],0.0,cornerScaleDragger->getTopLeftHandlePosition()[1]) * handleScaleFactor; (*vertices)[1] = osg::Vec3(cornerScaleDragger->getBottomLeftHandlePosition()[0],0.0,cornerScaleDragger->getBottomLeftHandlePosition()[1]) * handleScaleFactor; (*vertices)[2] = osg::Vec3(cornerScaleDragger->getBottomRightHandlePosition()[0],0.0,cornerScaleDragger->getBottomRightHandlePosition()[1]) * handleScaleFactor; (*vertices)[3] = osg::Vec3(cornerScaleDragger->getTopRightHandlePosition()[0],0.0,cornerScaleDragger->getTopRightHandlePosition()[1]) * handleScaleFactor; osg::Geometry* geometry = new osg::Geometry(); geometry->setVertexArray(vertices); geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,vertices->size())); osg::Vec3Array* normals = new osg::Vec3Array; normals->push_back(osg::Vec3(0.0,1.0,0.0)); geometry->setNormalArray(normals, osg::Array::BIND_OVERALL); osg::Geode* geode = new osg::Geode; geode->setName("Dragger Handle"); geode->addDrawable(geometry); if (!twosided) { osg::CullFace* cullface = new osg::CullFace; cullface->setMode(osg::CullFace::FRONT); geode->getOrCreateStateSet()->setAttribute(cullface, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); geode->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); } geode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); return geode; } osg::Node* createHandleScene(const osg::Vec3& pos, osg::Node* handleNode, float handleScaleFactor) { osg::AutoTransform *at = new osg::AutoTransform; at->setPosition(pos); at->setPivotPoint(pos * handleScaleFactor); at->setAutoScaleToScreen(true); at->addChild(handleNode); AntiSquish* as = new AntiSquish; as->setPivot(pos); as->addChild(at); return as; } void createCornerScaleDraggerGeometry(Scale2DDragger* cornerScaleDragger, osg::Node* handleNode, float handleScaleFactor) { // Create a top left box. { osg::Node* handleScene = createHandleScene(osg::Vec3(cornerScaleDragger->getTopLeftHandlePosition()[0], 0.0,cornerScaleDragger->getTopLeftHandlePosition()[1]), handleNode, handleScaleFactor); cornerScaleDragger->addChild(handleScene); cornerScaleDragger->setTopLeftHandleNode(*handleScene); } // Create a bottom left box. { osg::Node* handleScene = createHandleScene(osg::Vec3(cornerScaleDragger->getBottomLeftHandlePosition()[0], 0.0,cornerScaleDragger->getBottomLeftHandlePosition()[1]), handleNode, handleScaleFactor); cornerScaleDragger->addChild(handleScene); cornerScaleDragger->setBottomLeftHandleNode(*handleScene); } // Create a bottom right box. { osg::Node* handleScene = createHandleScene(osg::Vec3(cornerScaleDragger->getBottomRightHandlePosition()[0], 0.0,cornerScaleDragger->getBottomRightHandlePosition()[1]), handleNode, handleScaleFactor); cornerScaleDragger->addChild(handleScene); cornerScaleDragger->setBottomRightHandleNode(*handleScene); } // Create a top right box. { osg::Node* handleScene = createHandleScene(osg::Vec3(cornerScaleDragger->getTopRightHandlePosition()[0], 0.0,cornerScaleDragger->getTopRightHandlePosition()[1]), handleNode, handleScaleFactor); cornerScaleDragger->addChild(handleScene); cornerScaleDragger->setTopRightHandleNode(*handleScene); } } void createEdgeScaleDraggerGeometry(Scale1DDragger* horzEdgeScaleDragger, Scale1DDragger* vertEdgeScaleDragger, osg::Node* handleNode, float handleScaleFactor) { // Create a left box. { osg::Node* handleScene = createHandleScene(osg::Vec3(horzEdgeScaleDragger->getLeftHandlePosition(),0.0,0.0), handleNode, handleScaleFactor); horzEdgeScaleDragger->addChild(handleScene); horzEdgeScaleDragger->setLeftHandleNode(*handleScene); } // Create a right box. { osg::Node* handleScene = createHandleScene(osg::Vec3(horzEdgeScaleDragger->getRightHandlePosition(),0.0,0.0), handleNode, handleScaleFactor); horzEdgeScaleDragger->addChild(handleScene); horzEdgeScaleDragger->setRightHandleNode(*handleScene); } // Create a top box. { osg::Node* handleScene = createHandleScene(osg::Vec3(vertEdgeScaleDragger->getLeftHandlePosition(),0.0,0.0), handleNode, handleScaleFactor); vertEdgeScaleDragger->addChild(handleScene); vertEdgeScaleDragger->setLeftHandleNode(*handleScene); } // Create a bottom box. { osg::Node* handleScene = createHandleScene(osg::Vec3(vertEdgeScaleDragger->getRightHandlePosition(),0.0,0.0), handleNode, handleScaleFactor); vertEdgeScaleDragger->addChild(handleScene); vertEdgeScaleDragger->setRightHandleNode(*handleScene); } osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(1.0f, 0.0f, 0.0f)); vertEdgeScaleDragger->setMatrix(osg::Matrix(rotation)); } void createTranslateDraggerGeometry(Scale2DDragger* cornerScaleDragger, TranslatePlaneDragger* translateDragger) { // Create a polygon. { osg::Geode* geode = new osg::Geode; osg::Geometry* geometry = new osg::Geometry(); osg::Vec3Array* vertices = new osg::Vec3Array(4); (*vertices)[0] = osg::Vec3(cornerScaleDragger->getTopLeftHandlePosition()[0],0.0,cornerScaleDragger->getTopLeftHandlePosition()[1]); (*vertices)[1] = osg::Vec3(cornerScaleDragger->getBottomLeftHandlePosition()[0],0.0,cornerScaleDragger->getBottomLeftHandlePosition()[1]); (*vertices)[2] = osg::Vec3(cornerScaleDragger->getBottomRightHandlePosition()[0],0.0,cornerScaleDragger->getBottomRightHandlePosition()[1]); (*vertices)[3] = osg::Vec3(cornerScaleDragger->getTopRightHandlePosition()[0],0.0,cornerScaleDragger->getTopRightHandlePosition()[1]); geometry->setVertexArray(vertices); geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,vertices->size())); osg::Vec3Array* normals = new osg::Vec3Array; normals->push_back(osg::Vec3(0.0,1.0,0.0)); geometry->setNormalArray(normals, osg::Array::BIND_OVERALL); geode->addDrawable(geometry); osg::PolygonMode* polymode = new osg::PolygonMode; polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE); geode->getOrCreateStateSet()->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); geode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); translateDragger->getTranslate2DDragger()->addChild(geode); } } } TabPlaneDragger::TabPlaneDragger( float handleScaleFactor ) :_handleScaleFactor( handleScaleFactor ) { _cornerScaleDragger = new Scale2DDragger(Scale2DDragger::SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT); addChild(_cornerScaleDragger.get()); addDragger(_cornerScaleDragger.get()); _horzEdgeScaleDragger = new Scale1DDragger(Scale1DDragger::SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT); addChild(_horzEdgeScaleDragger.get()); addDragger(_horzEdgeScaleDragger.get()); _vertEdgeScaleDragger = new Scale1DDragger(Scale1DDragger::SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT); addChild(_vertEdgeScaleDragger.get()); addDragger(_vertEdgeScaleDragger.get()); _translateDragger = new TranslatePlaneDragger(); _translateDragger->setColor(osg::Vec4(0.7f, 0.7f, 0.7f, 1.0f)); addChild(_translateDragger.get()); addDragger(_translateDragger.get()); setParentDragger(getParentDragger()); } TabPlaneDragger::~TabPlaneDragger() { } bool TabPlaneDragger::handle(const PointerInfo& pointer, const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { if (ea.getButtonMask() & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) return false; // Check if the dragger node is in the nodepath. if (!pointer.contains(this)) return false; // Since the translate plane and the handleNode lie on the same plane the hit could've been on either one. But we // need to handle the scaling draggers before the translation. Check if the node path has the scaling nodes else // check for the scaling nodes in next hit. if (_cornerScaleDragger->handle(pointer, ea, aa)) return true; if (_horzEdgeScaleDragger->handle(pointer, ea, aa)) return true; if (_vertEdgeScaleDragger->handle(pointer, ea, aa)) return true; PointerInfo nextPointer(pointer); nextPointer.next(); while (!nextPointer.completed()) { if (_cornerScaleDragger->handle(nextPointer, ea, aa)) return true; if (_horzEdgeScaleDragger->handle(nextPointer, ea, aa)) return true; if (_vertEdgeScaleDragger->handle(nextPointer, ea, aa)) return true; nextPointer.next(); } if (_translateDragger->handle(pointer, ea, aa)) return true; return false; } void TabPlaneDragger::setupDefaultGeometry(bool twoSidedHandle) { osg::ref_ptr handleNode = createHandleNode(_cornerScaleDragger.get(), _handleScaleFactor, twoSidedHandle); createCornerScaleDraggerGeometry(_cornerScaleDragger.get(), handleNode.get(), _handleScaleFactor); createEdgeScaleDraggerGeometry(_horzEdgeScaleDragger.get(),_vertEdgeScaleDragger.get(),handleNode.get(),_handleScaleFactor); createTranslateDraggerGeometry(_cornerScaleDragger.get(), _translateDragger.get()); } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/TranslateAxisDragger.cpp0000644000175000017500000000735611732410624027613 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include using namespace osgManipulator; TranslateAxisDragger::TranslateAxisDragger() { _xDragger = new Translate1DDragger(osg::Vec3(0.0,0.0,0.0), osg::Vec3(0.0,0.0,1.0)); addChild(_xDragger.get()); addDragger(_xDragger.get()); _yDragger = new Translate1DDragger(osg::Vec3(0.0,0.0,0.0), osg::Vec3(0.0,0.0,1.0)); addChild(_yDragger.get()); addDragger(_yDragger.get()); _zDragger = new Translate1DDragger(osg::Vec3(0.0,0.0,0.0), osg::Vec3(0.0,0.0,1.0)); addChild(_zDragger.get()); addDragger(_zDragger.get()); setParentDragger(getParentDragger()); } TranslateAxisDragger::~TranslateAxisDragger() { } void TranslateAxisDragger::setupDefaultGeometry() { // Create a line. osg::Geode* lineGeode = new osg::Geode; { osg::Geometry* geometry = new osg::Geometry(); osg::Vec3Array* vertices = new osg::Vec3Array(2); (*vertices)[0] = osg::Vec3(0.0f,0.0f,0.0f); (*vertices)[1] = osg::Vec3(0.0f,0.0f,1.0f); geometry->setVertexArray(vertices); geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2)); lineGeode->addDrawable(geometry); } // Turn of lighting for line and set line width. { osg::LineWidth* linewidth = new osg::LineWidth(); linewidth->setWidth(2.0f); lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON); lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); } // Add line to all the individual 1D draggers. _xDragger->addChild(lineGeode); _yDragger->addChild(lineGeode); _zDragger->addChild(lineGeode); osg::Geode* geode = new osg::Geode; // Create a cone. { osg::Cone* cone = new osg::Cone (osg::Vec3(0.0f, 0.0f, 1.0f), 0.025f, 0.10f); geode->addDrawable(new osg::ShapeDrawable(cone)); } // Create an invisible cylinder for picking the line. { osg::Cylinder* cylinder = new osg::Cylinder (osg::Vec3(0.0f,0.0f,0.5f), 0.015f, 1.0f); osg::Drawable* geometry = new osg::ShapeDrawable(cylinder); setDrawableToAlwaysCull(*geometry); geode->addDrawable(geometry); } // Add geode to all 1D draggers. _xDragger->addChild(geode); _yDragger->addChild(geode); _zDragger->addChild(geode); // Rotate X-axis dragger appropriately. { osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(1.0f, 0.0f, 0.0f)); _xDragger->setMatrix(osg::Matrix(rotation)); } // Rotate Y-axis dragger appropriately. { osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(0.0f, 1.0f, 0.0f)); _yDragger->setMatrix(osg::Matrix(rotation)); } // Send different colors for each dragger. _xDragger->setColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f)); _yDragger->setColor(osg::Vec4(0.0f,1.0f,0.0f,1.0f)); _zDragger->setColor(osg::Vec4(0.0f,0.0f,1.0f,1.0f)); } openscenegraph-3.2.3/OpenSceneGraph/src/osgManipulator/Scale2DDragger.cpp0000644000175000017500000002213411732410624026235 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #include #include #include #include #include #include using namespace osgManipulator; namespace { osg::Vec2d computeScale(const osg::Vec3d& startProjectedPoint, const osg::Vec3d& projectedPoint, const osg::Vec2d& scaleCenter) { osg::Vec2d scale(1.0,1.0); if ((startProjectedPoint[0] - scaleCenter[0]) != 0.0) scale[0] = (projectedPoint[0] - scaleCenter[0])/(startProjectedPoint[0] - scaleCenter[0]); if ((startProjectedPoint[2] - scaleCenter[1]) != 0.0) scale[1] = (projectedPoint[2] - scaleCenter[1])/(startProjectedPoint[2] - scaleCenter[1]); return scale; } } Scale2DDragger::Scale2DDragger(ScaleMode scaleMode) : Dragger(), _minScale(0.001,0.001), _scaleMode(scaleMode) { _projector = new PlaneProjector(osg::Plane(0.0,1.0,0.0,0.0)); setColor(osg::Vec4(0.0, 1.0, 0.0, 1.0)); setPickColor(osg::Vec4(1.0, 1.0, 0.0, 1.0)); _topLeftHandlePosition.set (-0.5,0.5); _bottomLeftHandlePosition.set (-0.5,-0.5); _bottomRightHandlePosition.set(0.5,-0.5); _topRightHandlePosition.set (0.5,0.5); } Scale2DDragger::~Scale2DDragger() { } bool Scale2DDragger::handle(const PointerInfo& pointer, const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { // Check if the dragger node is in the nodepath. if (!pointer.contains(this)) return false; switch (ea.getEventType()) { // Pick start. case (osgGA::GUIEventAdapter::PUSH): { // Get the LocalToWorld matrix for this node and set it for the projector. osg::NodePath nodePathToRoot; computeNodePathToRoot(*this,nodePathToRoot); osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot); _projector->setLocalToWorld(localToWorld); if (_projector->project(pointer, _startProjectedPoint)) { _scaleCenter.set(0.0,0.0); if (pointer.contains(_topLeftHandleNode.get())) { _referencePoint = _topLeftHandlePosition; if (_scaleMode == SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT) _scaleCenter = _bottomRightHandlePosition; } else if (pointer.contains(_bottomLeftHandleNode.get())) { _referencePoint = _bottomLeftHandlePosition; if (_scaleMode == SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT) _scaleCenter = _topRightHandlePosition; } else if (pointer.contains(_bottomRightHandleNode.get())) { _referencePoint = _bottomRightHandlePosition; if (_scaleMode == SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT) _scaleCenter = _topLeftHandlePosition; } else if (pointer.contains(_topRightHandleNode.get())) { _referencePoint = _topRightHandlePosition; if (_scaleMode == SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT) _scaleCenter = _bottomLeftHandlePosition; } // Generate the motion command. osg::ref_ptr cmd = new Scale2DCommand(); cmd->setStage(MotionCommand::START); cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); cmd->setReferencePoint(_referencePoint); // Dispatch command. dispatch(*cmd); // Set color to pick color. setMaterialColor(_pickColor,*this); aa.requestRedraw(); } return true; } // Pick move. case (osgGA::GUIEventAdapter::DRAG): { osg::Vec3d projectedPoint; if (_projector->project(pointer, projectedPoint)) { // Compute scale. osg::Vec2d scale = computeScale(_startProjectedPoint,projectedPoint,_scaleCenter); if (scale[0] < getMinScale()[0]) scale[0] = getMinScale()[0]; if (scale[1] < getMinScale()[1]) scale[1] = getMinScale()[1]; // Generate the motion command. osg::ref_ptr cmd = new Scale2DCommand(); cmd->setStage(MotionCommand::MOVE); cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); cmd->setScale(scale); cmd->setScaleCenter(_scaleCenter); cmd->setReferencePoint(_referencePoint); cmd->setMinScale(getMinScale()); // Dispatch command. dispatch(*cmd); aa.requestRedraw(); } return true; } // Pick finish. case (osgGA::GUIEventAdapter::RELEASE): { osg::ref_ptr cmd = new Scale2DCommand(); cmd->setStage(MotionCommand::FINISH); cmd->setReferencePoint(_referencePoint); cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); // Dispatch command. dispatch(*cmd); // Reset color. setMaterialColor(_color,*this); aa.requestRedraw(); return true; } default: return false; } } void Scale2DDragger::setupDefaultGeometry() { osg::Geode* lineGeode = new osg::Geode; // Create a line. { osg::Geometry* geometry = new osg::Geometry(); osg::Vec3Array* vertices = new osg::Vec3Array(4); (*vertices)[0].set(_topLeftHandlePosition[0],0.0,_topLeftHandlePosition[1]); (*vertices)[1].set(_bottomLeftHandlePosition[0],0.0,_bottomLeftHandlePosition[1]); (*vertices)[2].set(_bottomRightHandlePosition[0],0.0,_bottomRightHandlePosition[1]); (*vertices)[3].set(_topRightHandlePosition[0],0.0,_topRightHandlePosition[1]); geometry->setVertexArray(vertices); geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,vertices->size())); lineGeode->addDrawable(geometry); } // Turn of lighting for line and set line width. lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); osg::LineWidth* linewidth = new osg::LineWidth(); linewidth->setWidth(2.0); lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON); // Add line and cones to the scene. addChild(lineGeode); // Create a top left box. { osg::Geode* geode = new osg::Geode; geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(_topLeftHandlePosition[0], 0.0,_topLeftHandlePosition[1]), 0.05))); addChild(geode); setTopLeftHandleNode(*geode); } // Create a bottom left box. { osg::Geode* geode = new osg::Geode; geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(_bottomLeftHandlePosition[0], 0.0,_bottomLeftHandlePosition[1]), 0.05))); addChild(geode); setBottomLeftHandleNode(*geode); } // Create a bottom right box. { osg::Geode* geode = new osg::Geode; geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(_bottomRightHandlePosition[0], 0.0,_bottomRightHandlePosition[1]), 0.05))); addChild(geode); setBottomRightHandleNode(*geode); } // Create a top right box. { osg::Geode* geode = new osg::Geode; geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(_topRightHandlePosition[0], 0.0,_topRightHandlePosition[1]), 0.05))); addChild(geode); setTopRightHandleNode(*geode); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/0000755000175000017500000000000012674261220021012 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/src/osgDB/Version.cpp0000644000175000017500000000152111732410624023140 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include extern "C" { const char* osgDBGetVersion() { return osgGetVersion(); } const char* osgDBGetLibraryName() { return "OpenSceneGraph DB (Data Base) Library"; } } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/FileNameUtils.cpp0000644000175000017500000004023611732410624024222 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #ifdef WIN32 #define _WIN32_WINNT 0x0500 #include #endif #if defined(__sgi) #include #elif defined(__GNUC__) || !defined(WIN32) || defined(__MWERKS__) #include using std::tolower; #endif using namespace std; static const char * const PATH_SEPARATORS = "/\\"; static unsigned int PATH_SEPARATORS_LEN = 2; std::string osgDB::getFilePath(const std::string& fileName) { std::string::size_type slash = fileName.find_last_of(PATH_SEPARATORS); if (slash==std::string::npos) return std::string(); else return std::string(fileName, 0, slash); } std::string osgDB::getSimpleFileName(const std::string& fileName) { std::string::size_type slash = fileName.find_last_of(PATH_SEPARATORS); if (slash==std::string::npos) return fileName; else return std::string(fileName.begin()+slash+1,fileName.end()); } std::string osgDB::getFileExtension(const std::string& fileName) { std::string::size_type dot = fileName.find_last_of('.'); std::string::size_type slash = fileName.find_last_of(PATH_SEPARATORS); if (dot==std::string::npos || (slash!=std::string::npos && dotisProtocolRegistered(proto); } std::string osgDB::getServerProtocol(const std::string& filename) { std::string::size_type pos(filename.find("://")); if (pos != std::string::npos) return filename.substr(0,pos); return ""; } std::string osgDB::getServerAddress(const std::string& filename) { std::string::size_type pos(filename.find("://")); if (pos != std::string::npos) { std::string::size_type pos_slash = filename.find_first_of('/',pos+3); if (pos_slash!=std::string::npos) { return filename.substr(pos+3,pos_slash-pos-3); } else { return filename.substr(pos+3,std::string::npos); } } return ""; } std::string osgDB::getServerFileName(const std::string& filename) { std::string::size_type pos(filename.find("://")); if (pos != std::string::npos) { std::string::size_type pos_slash = filename.find_first_of('/',pos+3); if (pos_slash!=std::string::npos) { return filename.substr(pos_slash+1,std::string::npos); } else { return ""; } } return filename; } std::string osgDB::concatPaths(const std::string& left, const std::string& right) { #if defined(WIN32) && !defined(__CYGWIN__) const char delimiterNative = WINDOWS_PATH_SEPARATOR; const char delimiterForeign = UNIX_PATH_SEPARATOR; #else const char delimiterNative = UNIX_PATH_SEPARATOR; const char delimiterForeign = WINDOWS_PATH_SEPARATOR; #endif if(left.empty()) { return(right); } char lastChar = left[left.size() - 1]; if(lastChar == delimiterNative) { return left + right; } else if(lastChar == delimiterForeign) { return left.substr(0, left.size() - 1) + delimiterNative + right; } else // lastChar != a delimiter { return left + delimiterNative + right; } } std::string osgDB::getRealPath(const std::string& path) { #if defined(WIN32) && !defined(__CYGWIN__) #ifdef OSG_USE_UTF8_FILENAME std::wstring wpath = convertUTF8toUTF16(path); wchar_t retbuf[MAX_PATH + 1]; wchar_t tempbuf1[MAX_PATH + 1]; if (GetFullPathNameW(wpath.c_str(), _countof(retbuf), retbuf, NULL)==0) { return path; } // Force drive letter to upper case if ((retbuf[1] == ':') && iswlower(retbuf[0])) retbuf[0] = towupper(retbuf[0]); if (fileExists(convertUTF16toUTF8(retbuf))) { // Canonicalise the full path GetShortPathNameW(retbuf, tempbuf1, _countof(tempbuf1)); GetLongPathNameW(tempbuf1, retbuf, _countof(retbuf)); return convertUTF16toUTF8(retbuf); } else { std::string retbuf8 = convertUTF16toUTF8(retbuf); // Canonicalise the directories std::string FilePath = getFilePath(retbuf8); wchar_t tempbuf2[MAX_PATH + 1]; if (0 == GetShortPathNameW(convertUTF8toUTF16(FilePath).c_str(), tempbuf1, _countof(tempbuf1))) return retbuf8; if (0 == GetLongPathNameW(tempbuf1, tempbuf2, _countof(tempbuf2))) return retbuf8; FilePath = convertUTF16toUTF8(tempbuf2); FilePath += WINDOWS_PATH_SEPARATOR; FilePath.append(getSimpleFileName(retbuf8)); return FilePath; } #else // Not unicode compatible should give an error if UNICODE defined char retbuf[MAX_PATH + 1]; char tempbuf1[MAX_PATH + 1]; GetFullPathName(path.c_str(), sizeof(retbuf), retbuf, NULL); // Force drive letter to upper case if ((retbuf[1] == ':') && islower(retbuf[0])) retbuf[0] = _toupper(retbuf[0]); if (fileExists(std::string(retbuf))) { // Canonicalise the full path GetShortPathName(retbuf, tempbuf1, sizeof(tempbuf1)); GetLongPathName(tempbuf1, retbuf, sizeof(retbuf)); return std::string(retbuf); } else { // Canonicalise the directories std::string FilePath = getFilePath(retbuf); char tempbuf2[MAX_PATH + 1]; if (0 == GetShortPathName(FilePath.c_str(), tempbuf1, sizeof(tempbuf1))) return std::string(retbuf); if (0 == GetLongPathName(tempbuf1, tempbuf2, sizeof(tempbuf2))) return std::string(retbuf); FilePath = std::string(tempbuf2); FilePath += WINDOWS_PATH_SEPARATOR; FilePath.append(getSimpleFileName(std::string(retbuf))); return FilePath; } #endif #else char resolved_path[PATH_MAX]; char* result = realpath(path.c_str(), resolved_path); if (result) return std::string(resolved_path); else return path; #endif } namespace osgDB { /** Helper to iterate over elements of a path (including Windows' root, if any). **/ class PathIterator { public: PathIterator(const std::string & v); bool valid() const { return start!=end; } PathIterator & operator++(); std::string operator*(); protected: std::string::const_iterator end; ///< End of path string std::string::const_iterator start; ///< Points to the first char of an element, or ==end() if no more std::string::const_iterator stop; ///< Points to the separator after 'start', or ==end() /// Iterate until 'it' points to something different from a separator std::string::const_iterator skipSeparators(std::string::const_iterator it); std::string::const_iterator next(std::string::const_iterator it); }; } osgDB::PathIterator::PathIterator(const std::string & v) : end(v.end()), start(v.begin()), stop(v.begin()) { operator++(); } osgDB::PathIterator & osgDB::PathIterator::operator++() { if (!valid()) return *this; start = skipSeparators(stop); if (start != end) stop = next(start); return *this; } std::string osgDB::PathIterator::operator*() { if (!valid()) return std::string(); return std::string(start, stop); } std::string::const_iterator osgDB::PathIterator::skipSeparators(std::string::const_iterator it) { for (; it!=end && std::find_first_of(it, it+1, PATH_SEPARATORS, PATH_SEPARATORS+PATH_SEPARATORS_LEN) != it+1; ++it) {} return it; } std::string::const_iterator osgDB::PathIterator::next(std::string::const_iterator it) { return std::find_first_of(it, end, PATH_SEPARATORS, PATH_SEPARATORS+PATH_SEPARATORS_LEN); } void osgDB::getPathElements(const std::string& path, std::vector & out_elements) { out_elements.clear(); for(osgDB::PathIterator it(path); it.valid(); ++it) out_elements.push_back(*it); } std::string osgDB::getPathRoot(const std::string& path) { // Test for unix root if (path.empty()) return ""; if (path[0] == '/') return "/"; // Now test for Windows root if (path.length()<2) return ""; if (path[1] == ':') return path.substr(0, 2); // We should check that path[0] is a letter, but as ':' is invalid in paths in other cases, that's not a problem. return ""; } bool osgDB::isAbsolutePath(const std::string& path) { // Test for unix root if (path.empty()) return false; if (path[0] == '/') return true; // Now test for Windows root if (path.length()<2) return false; return path[1] == ':'; // We should check that path[0] is a letter, but as ':' is invalid in paths in other cases, that's not a problem. } std::string osgDB::getPathRelative(const std::string& from, const std::string& to) { // This implementation is not 100% robust, and should be replaced with C++0x "std::path" as soon as possible. // Definition: an "element" is a part between slashes. Ex: "/a/b" has two elements ("a" and "b"). // Algorithm: // 1. If paths are neither both absolute nor both relative, then we cannot do anything (we need to make them absolute, but need additionnal info on how to make it). Return. // 2. If both paths are absolute and root isn't the same (for Windows only, as roots are of the type "C:", "D:"), then the operation is impossible. Return. // 3. Iterate over two paths elements until elements are equal // 4. For each remaining element in "from", add ".." to result // 5. For each remaining element in "to", add this element to result // 1 & 2 const std::string root = getPathRoot(from); if (root != getPathRoot(to)) { OSG_INFO << "Cannot relativise paths. From=" << from << ", To=" << to << ". Returning 'to' unchanged." << std::endl; //return to; return osgDB::getSimpleFileName(to); } // 3 PathIterator itFrom(from), itTo(to); // Iterators may point to Windows roots. As we tested they are equal, there is no need to ++itFrom and ++itTo. // However, if we got an Unix root, we must add it to the result. std::string res(root == "/" ? "/" : ""); for(; itFrom.valid() && itTo.valid() && *itFrom==*itTo; ++itFrom, ++itTo) {} // 4 for(; itFrom.valid(); ++itFrom) res += "../"; // 5 for(; itTo.valid(); ++itTo) res += *itTo + "/"; // Remove trailing slash before returning if (!res.empty() && std::find_first_of(res.rbegin(), res.rbegin()+1, PATH_SEPARATORS, PATH_SEPARATORS+PATH_SEPARATORS_LEN) != res.rbegin()+1) { return res.substr(0, res.length()-1); } return res; } //using namespace osgDB; //std::string testA = getPathRelative("C:\\a\\b", "C:\\a/b/d/f"); // d/f //std::string testB = getPathRelative("C:\\a\\d", "C:\\a/b/d/f"); // ../b/d/f //std::string testC = getPathRelative("C:\\ab", "C:\\a/b/d/f"); // ../a/b/d/f //std::string testD = getPathRelative("a/d", "a/d"); // "" //std::string testE = getPathRelative("a", "a/d"); // ../d //std::string testF = getPathRelative("C:/a/b", "a/d"); // Precondition fail. Returns d. //std::string testG = getPathRelative("/a/b", "a/d"); // Precondition fail. Returns d. //std::string testH = getPathRelative("a/b", "/a/d"); // Precondition fail. Returns d. openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/PluginQuery.cpp0000644000175000017500000001427611732410624024012 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield * * This application is open source and may be redistributed and/or modified * freely and without restriction, both in commercial and non commercial applications, * as long as this copyright notice is maintained. * * This application is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include using namespace osgDB; FileNameList osgDB::listAllAvailablePlugins() { FileNameList pluginFiles; std::string validExtension = ADDQUOTES(OSG_PLUGIN_EXTENSION); std::string pluginDirectoryName = std::string("osgPlugins-")+std::string(osgGetVersion()); std::string fullPath = osgDB::findLibraryFile(pluginDirectoryName); if (!fullPath.empty()) { osgDB::DirectoryContents contents = getDirectoryContents(fullPath); for(DirectoryContents::iterator itr = contents.begin(); itr != contents.end(); ++itr) { std::string::size_type pos = itr->find("osgdb_"); if (pos==std::string::npos) { continue; } std::string ext = getFileExtensionIncludingDot(*itr); if (ext != validExtension) { continue; } pluginFiles.push_back(fullPath + std::string("/")+*itr); } } return pluginFiles; } bool osgDB::queryPlugin(const std::string& fileName, ReaderWriterInfoList& infoList) { typedef std::set ReaderWriterSet; ReaderWriterSet previouslyLoadedReaderWriters; const Registry::ReaderWriterList& rwList = osgDB::Registry::instance()->getReaderWriterList(); for(Registry::ReaderWriterList::const_iterator itr = rwList.begin(); itr != rwList.end(); ++itr) { const ReaderWriter* rw = itr->get(); previouslyLoadedReaderWriters.insert(rw); } if (osgDB::Registry::instance()->loadLibrary(fileName)) { const Registry::ReaderWriterList& rwList = osgDB::Registry::instance()->getReaderWriterList(); for(Registry::ReaderWriterList::const_iterator itr = rwList.begin(); itr != rwList.end(); ++itr) { const ReaderWriter* rw = itr->get(); if (previouslyLoadedReaderWriters.count(rw)==0) { osg::ref_ptr rwi = new ReaderWriterInfo; rwi->plugin = fileName; rwi->description = rw->className(); rwi->protocols = rw->supportedProtocols(); rwi->extensions = rw->supportedExtensions(); rwi->options = rw->supportedOptions(); rwi->features = rw->supportedFeatures(); infoList.push_back(rwi.get()); } } osgDB::Registry::instance()->closeLibrary(fileName); return true; } else { return false; } } static std::string padwithspaces(const std::string& str, unsigned int padLength) { std::string newStr(str); while(newStr.length()first.length()>longestOptionLength) longestOptionLength = fdm_itr->first.length(); } for(fdm_itr = info.extensions.begin(); fdm_itr != info.extensions.end(); ++fdm_itr) { if (fdm_itr->first.length()>longestOptionLength) longestOptionLength = fdm_itr->first.length(); } for(fdm_itr = info.options.begin(); fdm_itr != info.options.end(); ++fdm_itr) { if (fdm_itr->first.length()>longestOptionLength) longestOptionLength = fdm_itr->first.length(); } unsigned int padLength = longestOptionLength+4; for(fdm_itr = info.protocols.begin(); fdm_itr != info.protocols.end(); ++fdm_itr) { out<<" protocol : "<first, padLength)<second<first, padLength-1)<second<first, padLength)<second< #include #include #include #include using namespace osgDB; osg::Object* ReaderWriter::ReadResult::getObject() { return _object.get(); } osg::Image* ReaderWriter::ReadResult::getImage() { return dynamic_cast(_object.get()); } osg::HeightField* ReaderWriter::ReadResult::getHeightField() { return dynamic_cast(_object.get()); } osg::Node* ReaderWriter::ReadResult::getNode() { return dynamic_cast(_object.get()); } osgDB::Archive* ReaderWriter::ReadResult::getArchive() { return dynamic_cast(_object.get()); } osg::Shader* ReaderWriter::ReadResult::getShader() { return dynamic_cast(_object.get()); } osg::Object* ReaderWriter::ReadResult::takeObject() { osg::Object* obj = _object.get(); if (obj) { obj->ref(); _object=NULL; obj->unref_nodelete(); } return obj; } osg::Image* ReaderWriter::ReadResult::takeImage() { osg::Image* image=dynamic_cast(_object.get()); if (image) { image->ref(); _object=NULL; image->unref_nodelete(); } return image; } osg::HeightField* ReaderWriter::ReadResult::takeHeightField() { osg::HeightField* hf=dynamic_cast(_object.get()); if (hf) { hf->ref(); _object=NULL; hf->unref_nodelete(); } return hf; } osg::Node* ReaderWriter::ReadResult::takeNode() { osg::Node* node=dynamic_cast(_object.get()); if (node) { node->ref(); _object=NULL; node->unref_nodelete(); } return node; } osgDB::Archive* ReaderWriter::ReadResult::takeArchive() { osgDB::Archive* archive=dynamic_cast(_object.get()); if (archive) { archive->ref(); _object=NULL; archive->unref_nodelete(); } return archive; } osg::Shader* ReaderWriter::ReadResult::takeShader() { osg::Shader* shader=dynamic_cast(_object.get()); if (shader) { shader->ref(); _object=NULL; shader->unref_nodelete(); } return shader; } ReaderWriter::~ReaderWriter() { } bool ReaderWriter::acceptsExtension(const std::string& extension) const { // check for an exact match std::string lowercase_ext = convertToLowerCase(extension); return (_supportedExtensions.count(lowercase_ext)!=0); } bool ReaderWriter::acceptsProtocol(const std::string& protocol) const { std::string lowercase_protocol = convertToLowerCase(protocol); return (_supportedProtocols.count(lowercase_protocol)!=0); } void ReaderWriter::supportsProtocol(const std::string& fmt, const std::string& description) { Registry::instance()->registerProtocol(fmt); _supportedProtocols[convertToLowerCase(fmt)] = description; } void ReaderWriter::supportsExtension(const std::string& fmt, const std::string& description) { _supportedExtensions[convertToLowerCase(fmt)] = description; } void ReaderWriter::supportsOption(const std::string& fmt, const std::string& description) { _supportedOptions[fmt] = description; } ReaderWriter::Features ReaderWriter::supportedFeatures() const { int features = FEATURE_NONE; std::string dummyFilename; if (readObject(dummyFilename,0).status()!=ReadResult::NOT_IMPLEMENTED) features |= FEATURE_READ_OBJECT; if (readImage(dummyFilename,0).status()!=ReadResult::NOT_IMPLEMENTED) features |= FEATURE_READ_IMAGE; if (readHeightField(dummyFilename,0).status()!=ReadResult::NOT_IMPLEMENTED) features |= FEATURE_READ_HEIGHT_FIELD; if (readShader(dummyFilename,0).status()!=ReadResult::NOT_IMPLEMENTED) features |= FEATURE_READ_SHADER; if (readNode(dummyFilename,0).status()!=ReadResult::NOT_IMPLEMENTED) features |= FEATURE_READ_NODE; osg::ref_ptr image = new osg::Image; osg::ref_ptr hf = new osg::HeightField; osg::ref_ptr shader = new osg::Shader; osg::ref_ptr node = new osg::Node; if (writeObject(*image, dummyFilename,0).status()!=WriteResult::NOT_IMPLEMENTED) features |= FEATURE_WRITE_OBJECT; if (writeImage(*image,dummyFilename,0).status()!=WriteResult::NOT_IMPLEMENTED) features |= FEATURE_WRITE_IMAGE; if (writeHeightField(*hf,dummyFilename,0).status()!=WriteResult::NOT_IMPLEMENTED) features |= FEATURE_WRITE_HEIGHT_FIELD; if (writeShader(*shader,dummyFilename,0).status()!=WriteResult::NOT_IMPLEMENTED) features |= FEATURE_WRITE_SHADER; if (writeNode(*node, dummyFilename,0).status()!=WriteResult::NOT_IMPLEMENTED) features |= FEATURE_WRITE_NODE; return Features(features); } ReaderWriter::FeatureList ReaderWriter::featureAsString(ReaderWriter::Features feature) { typedef struct { ReaderWriter::Features feature; const char *s; } FeatureStringList; FeatureStringList list[] = { { FEATURE_READ_OBJECT, "readObject" }, { FEATURE_READ_IMAGE, "readImage" }, { FEATURE_READ_HEIGHT_FIELD, "readHeightField" }, { FEATURE_READ_NODE, "readNode" }, { FEATURE_READ_SHADER, "readShader" }, { FEATURE_WRITE_OBJECT, "writeObject" }, { FEATURE_WRITE_IMAGE, "writeImage" }, { FEATURE_WRITE_HEIGHT_FIELD, "writeHeightField" }, { FEATURE_WRITE_NODE, "writeNode" }, { FEATURE_WRITE_SHADER, "writeShader" }, { FEATURE_NONE,0 } }; FeatureList result; for(FeatureStringList *p=list; p->feature != 0; p++) { if ((feature & p->feature) != 0) result.push_back(p->s); } return result; } bool ReaderWriter::fileExists(const std::string& filename, const Options* /*options*/) const { return ::osgDB::fileExists(filename); } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/DynamicLibrary.cpp0000644000175000017500000001341511406400373024427 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ //The dlopen calls were not adding to OS X until 10.3 #ifdef __APPLE__ #include #if !defined(MAC_OS_X_VERSION_10_3) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3) #define APPLE_PRE_10_3 #endif #endif #if defined(WIN32) && !defined(__CYGWIN__) #include #include #include #elif defined(__APPLE__) && defined(APPLE_PRE_10_3) #include #else // all other unix #include #ifdef __hpux // Although HP-UX has dlopen() it is broken! We therefore need to stick // to shl_load()/shl_unload()/shl_findsym() #include #include #else #include #endif #endif #include #include #include #include #include #include using namespace osgDB; DynamicLibrary::DynamicLibrary(const std::string& name, HANDLE handle) { _name = name; _handle = handle; OSG_INFO<<"Opened DynamicLibrary "<<_name<(_handle), FALSE); #elif defined(__hpux) // fortunately, shl_t is a pointer shl_unload (static_cast(_handle)); #else // other unix dlclose(_handle); #endif } } DynamicLibrary* DynamicLibrary::loadLibrary(const std::string& libraryName) { HANDLE handle = NULL; std::string fullLibraryName = osgDB::findLibraryFile(libraryName); if (!fullLibraryName.empty()) handle = getLibraryHandle( fullLibraryName ); // try the lib we have found else handle = getLibraryHandle( libraryName ); // havn't found a lib ourselves, see if the OS can find it simply from the library name. if (handle) return new DynamicLibrary(libraryName,handle); // else no lib found so report errors. OSG_INFO << "DynamicLibrary::failed loading \""<( GetProcAddress( (HMODULE)_handle, procName.c_str() ) ); #elif defined(__APPLE__) && defined(APPLE_PRE_10_3) std::string temp("_"); NSSymbol symbol; temp += procName; // Mac OS X prepends an underscore on function names symbol = NSLookupSymbolInModule(static_cast(_handle), temp.c_str()); return NSAddressOfSymbol(symbol); #elif defined(__hpux) void* result = NULL; if (shl_findsym (reinterpret_cast(&_handle), procName.c_str(), TYPE_PROCEDURE, result) == 0) { return result; } else { OSG_WARN << "DynamicLibrary::failed looking up " << procName << std::endl; OSG_WARN << "DynamicLibrary::error " << strerror(errno) << std::endl; return NULL; } #else // other unix void* sym = dlsym( _handle, procName.c_str() ); if (!sym) { OSG_WARN << "DynamicLibrary::failed looking up " << procName << std::endl; OSG_WARN << "DynamicLibrary::error " << dlerror() << std::endl; } return sym; #endif } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/DatabasePager.cpp0000644000175000017500000016722312163275353024221 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WIN32 #include #else #include #endif using namespace osgDB; using namespace OpenThreads; static osg::ApplicationUsageProxy DatabasePager_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_DO_PRE_COMPILE ","Switch on or off the pre compile of OpenGL object database pager."); static osg::ApplicationUsageProxy DatabasePager_e3(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_DATABASE_PAGER_DRAWABLE ","Set the drawable policy for setting of loaded drawable to specified type. mode can be one of DoNotModify, DisplayList, VBO or VertexArrays>."); static osg::ApplicationUsageProxy DatabasePager_e4(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_DATABASE_PAGER_PRIORITY ", "Set the thread priority to DEFAULT, MIN, LOW, NOMINAL, HIGH or MAX."); static osg::ApplicationUsageProxy DatabasePager_e11(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MAX_PAGEDLOD ","Set the target maximum number of PagedLOD to maintain."); static osg::ApplicationUsageProxy DatabasePager_e12(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_ASSIGN_PBO_TO_IMAGES ","Set whether PixelBufferObjects should be assigned to Images to aid download to the GPU."); // Convert function objects that take pointer args into functions that a // reference to an osg::ref_ptr. This is quite useful for doing STL // operations on lists of ref_ptr. This code assumes that a function // with an argument const Foo* should be composed into a function of // argument type ref_ptr&, not ref_ptr&. Some support // for that should be added to make this more general. namespace { template struct PointerTraits { typedef class NullType {} PointeeType; }; template struct PointerTraits { typedef U PointeeType; }; template struct PointerTraits { typedef U PointeeType; }; template class RefPtrAdapter : public std::unary_function::PointeeType>, typename FuncObj::result_type> { public: typedef typename PointerTraits::PointeeType PointeeType; typedef osg::ref_ptr RefPtrType; explicit RefPtrAdapter(const FuncObj& funcObj) : _func(funcObj) {} typename FuncObj::result_type operator()(const RefPtrType& refPtr) const { return _func(refPtr.get()); } protected: FuncObj _func; }; template RefPtrAdapter refPtrAdapt(const FuncObj& func) { return RefPtrAdapter(func); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // CountPagedLODList // struct DatabasePager::DatabasePagerCompileCompletedCallback : public osgUtil::IncrementalCompileOperation::CompileCompletedCallback { DatabasePagerCompileCompletedCallback(osgDB::DatabasePager* pager, osgDB::DatabasePager::DatabaseRequest* databaseRequest): _pager(pager), _databaseRequest(databaseRequest) {} virtual bool compileCompleted(osgUtil::IncrementalCompileOperation::CompileSet* /*compileSet*/) { _pager->compileCompleted(_databaseRequest.get()); return true; } osgDB::DatabasePager* _pager; osg::ref_ptr _databaseRequest; }; void DatabasePager::compileCompleted(DatabaseRequest* databaseRequest) { //OSG_NOTICE<<"DatabasePager::compileCompleted("<remove(databaseRequest); _dataToMergeList->add(databaseRequest); } // This class is a helper for the management of SetBasedPagedLODList. class DatabasePager::ExpirePagedLODsVisitor : public osg::NodeVisitor { public: ExpirePagedLODsVisitor(): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { } META_NodeVisitor("osgDB","ExpirePagedLODsVisitor") virtual void apply(osg::PagedLOD& plod) { _childPagedLODs.insert(&plod); markRequestsExpired(&plod); traverse(plod); } // Remove expired children from a PagedLOD. On return // removedChildren contains the nodes removed by the call to // PagedLOD::removeExpiredChildren, and the _childPagedLODs member // contains all the PagedLOD objects found in those children's // subgraphs. bool removeExpiredChildrenAndFindPagedLODs(osg::PagedLOD* plod, double expiryTime, unsigned int expiryFrame, osg::NodeList& removedChildren) { size_t sizeBefore = removedChildren.size(); plod->removeExpiredChildren(expiryTime, expiryFrame, removedChildren); for(size_t i = sizeBefore; iaccept(*this); } return sizeBefore!=removedChildren.size(); } typedef std::set > PagedLODset; PagedLODset _childPagedLODs; private: void markRequestsExpired(osg::PagedLOD* plod) { unsigned numFiles = plod->getNumFileNames(); for (unsigned i = 0; i < numFiles; ++i) { DatabasePager::DatabaseRequest* request = dynamic_cast(plod->getDatabaseRequest(i).get()); if (request) request->_groupExpired = true; } } }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // SetBasedPagedLODList // class SetBasedPagedLODList : public DatabasePager::PagedLODList { public: typedef std::set< osg::observer_ptr > PagedLODs; PagedLODs _pagedLODs; virtual PagedLODList* clone() { return new SetBasedPagedLODList(); } virtual void clear() { _pagedLODs.clear(); } virtual unsigned int size() { return _pagedLODs.size(); } virtual void removeExpiredChildren( int numberChildrenToRemove, double expiryTime, unsigned int expiryFrame, DatabasePager::ObjectList& childrenRemoved, bool visitActive) { int leftToRemove = numberChildrenToRemove; for(PagedLODs::iterator itr = _pagedLODs.begin(); itr!=_pagedLODs.end() && leftToRemove > 0; ) { osg::ref_ptr plod; if (itr->lock(plod)) { bool plodActive = expiryFrame < plod->getFrameNumberOfLastTraversal(); if (visitActive==plodActive) // true if (visitActive && plodActive) OR (!visitActive &&!plodActive) { DatabasePager::ExpirePagedLODsVisitor expirePagedLODsVisitor; osg::NodeList expiredChildren; // expired PagedLODs expirePagedLODsVisitor.removeExpiredChildrenAndFindPagedLODs( plod.get(), expiryTime, expiryFrame, expiredChildren); // Clear any expired PagedLODs out of the set for (DatabasePager::ExpirePagedLODsVisitor::PagedLODset::iterator citr = expirePagedLODsVisitor._childPagedLODs.begin(), end = expirePagedLODsVisitor._childPagedLODs.end(); citr != end; ++citr) { osg::observer_ptr clod(*citr); // This child PagedLOD cannot be equal to the // PagedLOD pointed to by itr because it must be // in itr's subgraph. Therefore erasing it doesn't // invalidate itr. if (_pagedLODs.erase(clod) > 0) leftToRemove--; } std::copy(expiredChildren.begin(), expiredChildren.end(), std::back_inserter(childrenRemoved)); } // advance the iterator to the next element ++itr; } else { _pagedLODs.erase(itr++); // numberChildrenToRemove includes possibly expired // observer pointers. leftToRemove--; OSG_INFO<<"DatabasePager::removeExpiredSubgraphs() _inactivePagedLOD has been invalidated, but ignored"<(itr->get()); osg::observer_ptr obs_ptr(plod); PagedLODs::iterator plod_itr = _pagedLODs.find(obs_ptr); if (plod_itr != _pagedLODs.end()) { OSG_INFO<<"Removing node from PagedLOD list"<& plod) { if (_pagedLODs.count(plod)!=0) { OSG_NOTICE<<"Warning: SetBasedPagedLODList::insertPagedLOD("<& plod) const { return (_pagedLODs.count(plod)!=0); } }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // FindCompileableGLObjectsVisitor // class DatabasePager::FindCompileableGLObjectsVisitor : public osgUtil::StateToCompile { public: FindCompileableGLObjectsVisitor(const DatabasePager* pager): osgUtil::StateToCompile(osgUtil::GLObjectsVisitor::COMPILE_DISPLAY_LISTS|osgUtil::GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES), _pager(pager), _changeAutoUnRef(false), _valueAutoUnRef(false), _changeAnisotropy(false), _valueAnisotropy(1.0) { _assignPBOToImages = _pager->_assignPBOToImages; _changeAutoUnRef = _pager->_changeAutoUnRef; _valueAutoUnRef = _pager->_valueAutoUnRef; _changeAnisotropy = _pager->_changeAnisotropy; _valueAnisotropy = _pager->_valueAnisotropy; switch(_pager->_drawablePolicy) { case DatabasePager::DO_NOT_MODIFY_DRAWABLE_SETTINGS: // do nothing, leave settings as they came in from loaded database. // OSG_NOTICE<<"DO_NOT_MODIFY_DRAWABLE_SETTINGS"<getBuildKdTreesHint()==osgDB::Options::BUILD_KDTREES && osgDB::Registry::instance()->getKdTreeBuilder()) { _kdTreeBuilder = osgDB::Registry::instance()->getKdTreeBuilder()->clone(); } } META_NodeVisitor("osgDB","FindCompileableGLObjectsVisitor") bool requiresCompilation() const { return !empty(); } virtual void apply(osg::Geode& geode) { StateToCompile::apply(geode); if (_kdTreeBuilder.valid()) { geode.accept(*_kdTreeBuilder); } } void apply(osg::Texture& texture) { StateToCompile::apply(texture); if (_changeAutoUnRef) { texture.setUnRefImageDataAfterApply(_valueAutoUnRef); } if ((_changeAnisotropy && texture.getMaxAnisotropy() != _valueAnisotropy)) { texture.setMaxAnisotropy(_valueAnisotropy); } } const DatabasePager* _pager; bool _changeAutoUnRef; bool _valueAutoUnRef; bool _changeAnisotropy; float _valueAnisotropy; osg::ref_ptr _kdTreeBuilder; protected: FindCompileableGLObjectsVisitor& operator = (const FindCompileableGLObjectsVisitor&) { return *this; } }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // SortFileRequestFunctor // struct DatabasePager::SortFileRequestFunctor { bool operator() (const osg::ref_ptr& lhs,const osg::ref_ptr& rhs) const { if (lhs->_timestampLastRequest>rhs->_timestampLastRequest) return true; else if (lhs->_timestampLastRequest_timestampLastRequest) return false; else return (lhs->_priorityLastRequest>rhs->_priorityLastRequest); } }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // DatabaseRequest // void DatabasePager::DatabaseRequest::invalidate() { OSG_INFO<<" DatabasePager::DatabaseRequest::invalidate()."<get()); } } void DatabasePager::RequestQueue::invalidate(DatabaseRequest* dr) { // OSG_NOTICE<<"DatabasePager::RequestQueue::invalidate(DatabaseRequest* dr) dr->_compileSet="<_compileSet.get()< compileSet; if (dr->_compileSet.lock(compileSet) && _pager->getIncrementalCompileOperation()) { _pager->getIncrementalCompileOperation()->remove(compileSet.get()); } dr->invalidate(); } bool DatabasePager::RequestQueue::pruneOldRequestsAndCheckIfEmpty() { OpenThreads::ScopedLock lock(_requestMutex); unsigned int frameNumber = _pager->_frameNumber; if (_frameNumberLastPruned != frameNumber) { for(RequestQueue::RequestList::iterator citr = _requestList.begin(); citr != _requestList.end(); ) { OpenThreads::ScopedLock drLock(_pager->_dr_mutex); if ((*citr)->isRequestCurrent(frameNumber)) { ++citr; } else { invalidate(citr->get()); OSG_INFO<<"DatabasePager::RequestQueue::pruneOldRequestsAndCheckIfEmpty(): Pruning "<<(*citr)< lock(_requestMutex); return _requestList.empty(); } unsigned int DatabasePager::RequestQueue::size() { OpenThreads::ScopedLock lock(_requestMutex); return _requestList.size(); } void DatabasePager::RequestQueue::clear() { OpenThreads::ScopedLock lock(_requestMutex); for(RequestList::iterator citr = _requestList.begin(); citr != _requestList.end(); ++citr) { OpenThreads::ScopedLock drLock(_pager->_dr_mutex); invalidate(citr->get()); } _requestList.clear(); _frameNumberLastPruned = _pager->_frameNumber; updateBlock(); } void DatabasePager::RequestQueue::add(DatabasePager::DatabaseRequest* databaseRequest) { OpenThreads::ScopedLock lock(_requestMutex); addNoLock(databaseRequest); } void DatabasePager::RequestQueue::remove(DatabasePager::DatabaseRequest* databaseRequest) { // OSG_NOTICE<<"DatabasePager::RequestQueue::remove(DatabaseRequest* databaseRequest)"< lock(_requestMutex); for(RequestList::iterator citr = _requestList.begin(); citr != _requestList.end(); ++citr) { if (citr->get()==databaseRequest) { // OSG_NOTICE<<" done remove(DatabaseRequest* databaseRequest)"< lock(_requestMutex); _requestList.swap(requestList); } void DatabasePager::RequestQueue::takeFirst(osg::ref_ptr& databaseRequest) { OpenThreads::ScopedLock lock(_requestMutex); if (!_requestList.empty()) { DatabasePager::SortFileRequestFunctor highPriority; RequestQueue::RequestList::iterator selected_itr = _requestList.end(); int frameNumber = _pager->_frameNumber; for(RequestQueue::RequestList::iterator citr = _requestList.begin(); citr != _requestList.end(); ) { OpenThreads::ScopedLock drLock(_pager->_dr_mutex); if ((*citr)->isRequestCurrent(frameNumber)) { if (selected_itr==_requestList.end() || highPriority(*citr, *selected_itr)) { selected_itr = citr; } ++citr; } else { invalidate(citr->get()); OSG_INFO<<"DatabasePager::RequestQueue::takeFirst(): Pruning "<<(*citr)< read_queue; osg::ref_ptr out_queue; switch(_mode) { case(HANDLE_ALL_REQUESTS): read_queue = _pager->_fileRequestQueue; break; case(HANDLE_NON_HTTP): read_queue = _pager->_fileRequestQueue; out_queue = _pager->_httpRequestQueue; break; case(HANDLE_ONLY_HTTP): read_queue = _pager->_httpRequestQueue; break; } do { _active = false; read_queue->block(); if (_done) { break; } _active = true; OSG_INFO<<_name<<": _pager->size()= "<size()<<" to delete = "<_childrenToDeleteList.size()<_deleteRemovedSubgraphsInDatabaseThread/* && !(read_queue->_childrenToDeleteList.empty())*/) { ObjectList deleteList; { // Don't hold lock during destruction of deleteList OpenThreads::ScopedLock lock(read_queue->_requestMutex); if (!read_queue->_childrenToDeleteList.empty()) { deleteList.swap(read_queue->_childrenToDeleteList); read_queue->updateBlock(); } } } // // load any subgraphs that are required. // osg::ref_ptr databaseRequest; read_queue->takeFirst(databaseRequest); bool readFromFileCache = false; osg::ref_ptr fileCache = osgDB::Registry::instance()->getFileCache(); osg::ref_ptr fileLocationCallback = osgDB::Registry::instance()->getFileLocationCallback(); osg::ref_ptr dr_loadOptions; std::string fileName; int frameNumberLastRequest = 0; if (databaseRequest.valid()) { { OpenThreads::ScopedLock drLock(_pager->_dr_mutex); dr_loadOptions = databaseRequest->_loadOptions; fileName = databaseRequest->_fileName; frameNumberLastRequest = databaseRequest->_frameNumberLastRequest; } if (dr_loadOptions.valid()) { if (dr_loadOptions->getFileCache()) fileCache = dr_loadOptions->getFileCache(); if (dr_loadOptions->getFileLocationCallback()) fileLocationCallback = dr_loadOptions->getFileLocationCallback(); dr_loadOptions = dr_loadOptions->cloneOptions(); } else { dr_loadOptions = new osgDB::Options; } dr_loadOptions->setTerrain(databaseRequest->_terrain); // disable the FileCache if the fileLocationCallback tells us that it isn't required for this request. if (fileLocationCallback.valid() && !fileLocationCallback->useFileCache()) fileCache = 0; // check if databaseRequest is still relevant if ((_pager->_frameNumber-frameNumberLastRequest)<=1) { // now check to see if this request is appropriate for this thread switch(_mode) { case(HANDLE_ALL_REQUESTS): { // do nothing as this thread can handle the load if (fileCache.valid() && fileCache->isFileAppropriateForFileCache(fileName)) { if (fileCache->existsInCache(fileName)) { readFromFileCache = true; } } break; } case(HANDLE_NON_HTTP): { // check the cache first bool isHighLatencyFileRequest = false; if (fileLocationCallback.valid()) { isHighLatencyFileRequest = fileLocationCallback->fileLocation(fileName, dr_loadOptions.get()) == FileLocationCallback::REMOTE_FILE; } else if (fileCache.valid() && fileCache->isFileAppropriateForFileCache(fileName)) { isHighLatencyFileRequest = true; } if (isHighLatencyFileRequest) { if (fileCache.valid() && fileCache->existsInCache(fileName)) { readFromFileCache = true; } else { OSG_INFO<<_name<<": Passing http requests over "<add(databaseRequest.get()); databaseRequest = 0; } } break; } case(HANDLE_ONLY_HTTP): { // accept all requests, as we'll assume only high latency requests will have got here. break; } } } else { databaseRequest = 0; } } if (databaseRequest.valid()) { // load the data, note safe to write to the databaseRequest since once // it is created this thread is the only one to write to the _loadedModel pointer. //OSG_NOTICE<<"In DatabasePager thread readNodeFile("<_fileName<<")"<tick(); // assume that readNode is thread safe... ReaderWriter::ReadResult rr = readFromFileCache ? fileCache->readNode(fileName, dr_loadOptions.get(), false) : Registry::instance()->readNode(fileName, dr_loadOptions.get(), false); osg::ref_ptr loadedModel; if (rr.validNode()) loadedModel = rr.getNode(); if (rr.error()) OSG_WARN<<"Error in reading file "<isFileAppropriateForFileCache(fileName) && !readFromFileCache) { fileCache->writeNode(*(loadedModel), fileName, dr_loadOptions.get()); } { OpenThreads::ScopedLock drLock(_pager->_dr_mutex); if ((_pager->_frameNumber-databaseRequest->_frameNumberLastRequest)>1) { OSG_INFO<<_name<<": Warning DatabaseRquest no longer required."<delta_m(before,osg::Timer::instance()->tick())<<" ms"<getBound(); // find all the compileable rendering objects DatabasePager::FindCompileableGLObjectsVisitor stateToCompile(_pager); loadedModel->accept(stateToCompile); bool loadedObjectsNeedToBeCompiled = _pager->_doPreCompile && _pager->_incrementalCompileOperation.valid() && _pager->_incrementalCompileOperation->requiresCompile(stateToCompile); // move the databaseRequest from the front of the fileRequest to the end of // dataToCompile or dataToMerge lists. osg::ref_ptr compileSet = 0; if (loadedObjectsNeedToBeCompiled) { // OSG_NOTICE<<"Using IncrementalCompileOperation"<buildCompileMap(_pager->_incrementalCompileOperation->getContextSet(), stateToCompile); compileSet->_compileCompletedCallback = new DatabasePagerCompileCompletedCallback(_pager, databaseRequest.get()); _pager->_incrementalCompileOperation->add(compileSet.get(), false); } { OpenThreads::ScopedLock drLock(_pager->_dr_mutex); databaseRequest->_loadedModel = loadedModel; databaseRequest->_compileSet = compileSet; } // Dereference the databaseRequest while the queue is // locked. This prevents the request from being // deleted at an unpredictable time within // addLoadedDataToSceneGraph. if (loadedObjectsNeedToBeCompiled) { OpenThreads::ScopedLock listLock( _pager->_dataToCompileList->_requestMutex); _pager->_dataToCompileList->addNoLock(databaseRequest.get()); databaseRequest = 0; } else { OpenThreads::ScopedLock listLock( _pager->_dataToMergeList->_requestMutex); _pager->_dataToMergeList->addNoLock(databaseRequest.get()); databaseRequest = 0; } } // _pager->_dataToCompileList->pruneOldRequestsAndCheckIfEmpty(); } else { OpenThreads::Thread::YieldCurrentThread(); } // go to sleep till our the next time our thread gets scheduled. if (firstTime) { // do a yield to get round a peculiar thread hang when testCancel() is called // in certain circumstances - of which there is no particular pattern. YieldCurrentThread(); firstTime = false; } } while (!testCancel() && !_done); } DatabasePager::DatabasePager() { //OSG_INFO<<"Constructing DatabasePager()"<getNumOfDatabaseThreadsHint(), osg::DisplaySettings::instance()->getNumOfHttpDatabaseThreadsHint()); str = getenv("OSG_DATABASE_PAGER_PRIORITY"); if (str) { if (strcmp(str,"DEFAULT")==0) { setSchedulePriority(OpenThreads::Thread::THREAD_PRIORITY_DEFAULT); } else if (strcmp(str,"MIN")==0) { setSchedulePriority(OpenThreads::Thread::THREAD_PRIORITY_MIN); } else if (strcmp(str,"LOW")==0) { setSchedulePriority(OpenThreads::Thread::THREAD_PRIORITY_LOW); } else if (strcmp(str,"NOMINAL")==0) { setSchedulePriority(OpenThreads::Thread::THREAD_PRIORITY_NOMINAL); } else if (strcmp(str,"HIGH")==0) { setSchedulePriority(OpenThreads::Thread::THREAD_PRIORITY_HIGH); } else if (strcmp(str,"MAX")==0) { setSchedulePriority(OpenThreads::Thread::THREAD_PRIORITY_MAX); } } _activePagedLODList = new SetBasedPagedLODList; } DatabasePager::DatabasePager(const DatabasePager& rhs) { //OSG_INFO<<"Constructing DatabasePager(const DatabasePager& )"<clone(); #if 1 // need to set the display list manager to be able to reuse display lists osg::Drawable::setMinimumNumberOfDisplayListsToRetainInCache(100); #else // need to set the display list manager to be able to reuse display lists osg::Drawable::setMinimumNumberOfDisplayListsToRetainInCache(0); #endif // initialize the stats variables resetStats(); } void DatabasePager::setIncrementalCompileOperation(osgUtil::IncrementalCompileOperation* ico) { _incrementalCompileOperation = ico; } DatabasePager::~DatabasePager() { // cancel the threads cancel(); // destruct all the threads _databaseThreads.clear(); // destruct all the queues _fileRequestQueue = 0; _httpRequestQueue = 0; _dataToCompileList = 0; _dataToMergeList = 0; // remove reference to the ICO _incrementalCompileOperation = 0; //_activePagedLODList; //_inactivePagedLODList; } osg::ref_ptr& DatabasePager::prototype() { static osg::ref_ptr s_DatabasePager = new DatabasePager; return s_DatabasePager; } DatabasePager* DatabasePager::create() { return DatabasePager::prototype().valid() ? DatabasePager::prototype()->clone() : new DatabasePager; } void DatabasePager::setUpThreads(unsigned int totalNumThreads, unsigned int numHttpThreads) { _databaseThreads.clear(); unsigned int numGeneralThreads = numHttpThreads < totalNumThreads ? totalNumThreads - numHttpThreads : 1; if (numHttpThreads==0) { for(unsigned int i=0; istartThread(); } return pos; } int DatabasePager::setSchedulePriority(OpenThreads::Thread::ThreadPriority priority) { int result = 0; for(DatabaseThreadList::iterator dt_itr = _databaseThreads.begin(); dt_itr != _databaseThreads.end(); ++dt_itr) { result = (*dt_itr)->setSchedulePriority(priority); } return result; } bool DatabasePager::isRunning() const { for(DatabaseThreadList::const_iterator dt_itr = _databaseThreads.begin(); dt_itr != _databaseThreads.end(); ++dt_itr) { if ((*dt_itr)->isRunning()) return true; } return false; } int DatabasePager::cancel() { int result = 0; for(DatabaseThreadList::iterator dt_itr = _databaseThreads.begin(); dt_itr != _databaseThreads.end(); ++dt_itr) { (*dt_itr)->setDone(true); } // release the queue blocks in case they are holding up thread cancellation. _fileRequestQueue->release(); _httpRequestQueue->release(); for(DatabaseThreadList::iterator dt_itr = _databaseThreads.begin(); dt_itr != _databaseThreads.end(); ++dt_itr) { (*dt_itr)->cancel(); } _done = true; _startThreadCalled = false; return result; } void DatabasePager::clear() { _fileRequestQueue->clear(); _httpRequestQueue->clear(); _dataToCompileList->clear(); _dataToMergeList->clear(); // note, no need to use a mutex as the list is only accessed from the update thread. _activePagedLODList->clear(); // ?? // _activeGraphicsContexts } void DatabasePager::resetStats() { // initialize the stats variables _minimumTimeToMergeTile = DBL_MAX; _maximumTimeToMergeTile = -DBL_MAX; _totalTimeToMergeTiles = 0.0; _numTilesMerges = 0; } bool DatabasePager::getRequestsInProgress() const { if (getFileRequestListSize()>0) return true; if (getDataToCompileListSize()>0) { return true; } if (getDataToMergeListSize()>0) return true; for(DatabaseThreadList::const_iterator itr = _databaseThreads.begin(); itr != _databaseThreads.end(); ++itr) { if ((*itr)->getActive()) return true; } return false; } void DatabasePager::requestNodeFile(const std::string& fileName, osg::NodePath& nodePath, float priority, const osg::FrameStamp* framestamp, osg::ref_ptr& databaseRequestRef, const osg::Referenced* options) { osgDB::Options* loadOptions = dynamic_cast(const_cast(options)); if (!loadOptions) { loadOptions = Registry::instance()->getOptions(); // OSG_NOTICE<<"Using options from Registry "<asGroup(); if (!group) { OSG_NOTICE<<"Warning: DatabasePager::requestNodeFile(..) passed NodePath without group as last node in path, so nowhere to attach new subgraph to."<asTerrain()) terrain = *itr; } double timestamp = framestamp?framestamp->getReferenceTime():0.0; unsigned int frameNumber = framestamp?framestamp->getFrameNumber():static_cast(_frameNumber); // #define WITH_REQUESTNODEFILE_TIMING #ifdef WITH_REQUESTNODEFILE_TIMING osg::Timer_t start_tick = osg::Timer::instance()->tick(); static int previousFrame = -1; static double totalTime = 0.0; if (previousFrame!=frameNumber) { OSG_NOTICE<<"requestNodeFiles for "<_valid = true; databaseRequest->_frameNumberLastRequest = frameNumber; databaseRequest->_timestampLastRequest = timestamp; databaseRequest->_priorityLastRequest = priority; ++(databaseRequest->_numOfRequests); foundEntry = true; if (databaseRequestRef->referenceCount()==1) { OSG_INFO<<"DatabasePager::requestNodeFile("<_frameNumberLastRequest = frameNumber; databaseRequest->_timestampLastRequest = timestamp; databaseRequest->_priorityLastRequest = priority; databaseRequest->_group = group; databaseRequest->_terrain = terrain; databaseRequest->_loadOptions = loadOptions; requeue = true; } } } if (requeue) _fileRequestQueue->add(databaseRequest); } if (!foundEntry) { OSG_INFO<<"In DatabasePager::requestNodeFile("< lock(_fileRequestQueue->_requestMutex); if (!databaseRequestRef.valid() || databaseRequestRef->referenceCount()==1) { osg::ref_ptr databaseRequest = new DatabaseRequest; databaseRequestRef = databaseRequest.get(); databaseRequest->_valid = true; databaseRequest->_fileName = fileName; databaseRequest->_frameNumberFirstRequest = frameNumber; databaseRequest->_timestampFirstRequest = timestamp; databaseRequest->_priorityFirstRequest = priority; databaseRequest->_frameNumberLastRequest = frameNumber; databaseRequest->_timestampLastRequest = timestamp; databaseRequest->_priorityLastRequest = priority; databaseRequest->_group = group; databaseRequest->_terrain = terrain; databaseRequest->_loadOptions = loadOptions; _fileRequestQueue->addNoLock(databaseRequest.get()); } } if (!_startThreadCalled) { OpenThreads::ScopedLock lock(_run_mutex); if (!_startThreadCalled) { _startThreadCalled = true; _done = false; OSG_INFO<<"DatabasePager::startThread()"<getNumOfDatabaseThreadsHint(), osg::DisplaySettings::instance()->getNumOfHttpDatabaseThreadsHint()); } for(DatabaseThreadList::const_iterator dt_itr = _databaseThreads.begin(); dt_itr != _databaseThreads.end(); ++dt_itr) { (*dt_itr)->startThread(); } } } #ifdef WITH_REQUESTNODEFILE_TIMING totalTime += osg::Timer::instance()->delta_m(start_tick, osg::Timer::instance()->tick()); #endif } void DatabasePager::signalBeginFrame(const osg::FrameStamp* framestamp) { #if 0 OSG_NOTICE<<"DatabasePager : _fileRequestQueue->size()="<<_fileRequestQueue->size() <<", _httpRequestQueue->size()= "<<_httpRequestQueue->size() <<", _dataToCompileList->size()= "<<_dataToCompileList->size() <<", _dataToMergeList->size()= "<<_dataToMergeList->size()<pruneOldRequestsAndCheckIfEmpty(); //OSG_INFO << "signalBeginFrame "<getFrameNumber()<<">>>>>>>>>>>>>>>>"<getFrameNumber()); } //else OSG_INFO << "signalBeginFrame >>>>>>>>>>>>>>>>"< lock(_fileRequestQueue->_requestMutex); _fileRequestQueue->updateBlock(); } { OpenThreads::ScopedLock lock(_httpRequestQueue->_requestMutex); _httpRequestQueue->updateBlock(); } } bool DatabasePager::requiresUpdateSceneGraph() const { return !(_dataToMergeList->empty()); } void DatabasePager::updateSceneGraph(const osg::FrameStamp& frameStamp) { #define UPDATE_TIMING 0 #if UPDATE_TIMING osg::ElapsedTime timer; double timeFor_removeExpiredSubgraphs, timeFor_addLoadedDataToSceneGraph; #endif { removeExpiredSubgraphs(frameStamp); #if UPDATE_TIMING timeFor_removeExpiredSubgraphs = timer.elapsedTime_m(); #endif addLoadedDataToSceneGraph(frameStamp); #if UPDATE_TIMING timeFor_addLoadedDataToSceneGraph = timer.elapsedTime_m() - timeFor_removeExpiredSubgraphs; #endif } #if UPDATE_TIMING double elapsedTime = timer.elapsedTime_m(); if (elapsedTime>0.4) { OSG_NOTICE<<"DatabasePager::updateSceneGraph() total time = "<_fileName<<" after "<_numOfRequests<<" requests and time="<<(timeStamp-databaseRequest->_timestampFirstRequest)*1000.0<_timestampFirstRequest; if (timeToMerge<_minimumTimeToMergeTile) _minimumTimeToMergeTile = timeToMerge; if (timeToMerge>_maximumTimeToMergeTile) _maximumTimeToMergeTile = timeToMerge; _totalTimeToMergeTiles += timeToMerge; ++_numTilesMerges; } else { OSG_INFO<<"DatabasePager::addLoadedDataToSceneGraph() node in parental chain deleted, discarding subgaph."<_loadedModel = 0; // OSG_NOTICE<<"curr = "<delta_m(before,mid)<<"ms,\t"<< osg::Timer::instance()->delta_m(mid,last)<<"ms"<< " objects"<tick(); // numPagedLODs >= actual number of PagedLODs. There can be // invalid observer pointers in _activePagedLODList. unsigned int numPagedLODs = _activePagedLODList->size(); osg::Timer_t end_a_Tick = osg::Timer::instance()->tick(); double time_a = osg::Timer::instance()->delta_m(startTick,end_a_Tick); s_total_iter_stage_a += 1.0; s_total_time_stage_a += time_a; if (s_total_max_stage_a0) _activePagedLODList->removeExpiredChildren( numToPrune, expiryTime, expiryFrame, childrenRemoved, false); numToPrune = _activePagedLODList->size() - _targetMaximumNumberOfPageLOD; if (numToPrune>0) _activePagedLODList->removeExpiredChildren( numToPrune, expiryTime, expiryFrame, childrenRemoved, true); osg::Timer_t end_b_Tick = osg::Timer::instance()->tick(); double time_b = osg::Timer::instance()->delta_m(end_a_Tick,end_b_Tick); s_total_iter_stage_b += 1.0; s_total_time_stage_b += time_b; if (s_total_max_stage_b obs_ptr(&plod); _activePagedLODList.insertPagedLOD(obs_ptr); traverse(plod); } DatabasePager::PagedLODList& _activePagedLODList; unsigned int _frameNumber; protected: FindPagedLODsVisitor& operator = (const FindPagedLODsVisitor&) { return *this; } }; void DatabasePager::registerPagedLODs(osg::Node* subgraph, unsigned int frameNumber) { if (!subgraph) return; FindPagedLODsVisitor fplv(*_activePagedLODList, frameNumber); subgraph->accept(fplv); } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/ImageOptions.cpp0000644000175000017500000000064411732410624024116 0ustar albertoalberto#include using namespace osgDB; ImageOptions::ImageOptions() { init(); } ImageOptions::ImageOptions(const std::string& str) { init(); _str = str; } void ImageOptions::init() { _sourceImageSamplingMode = NEAREST; _sourceImageWindowMode = ALL_IMAGE; _destinationImageWindowMode = ALL_IMAGE; _destinationDataType = GL_NONE; _destinationPixelFormat = GL_NONE; } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/Registry.cpp0000644000175000017500000016447112352777752023362 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__sgi) #include #elif defined(__GNUC__) || !defined(WIN32) || defined(__MWERKS__) #include using std::tolower; #endif #ifdef OSG_LIBRARY_POSTFIX #define OSG_LIBRARY_POSTFIX_WITH_QUOTES ADDQUOTES(OSG_LIBRARY_POSTFIX) #else #define OSG_LIBRARY_POSTFIX_WITH_QUOTES "" #endif using namespace osg; using namespace osgDB; #if !defined(WIN32) || defined(__CYGWIN__) static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH [:path]..","Paths for locating datafiles"); static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH [:path]..","Paths for locating libraries/ plugins"); #else static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH [;path]..","Paths for locating datafiles"); static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH [;path]..","Paths for locating libraries/ plugins"); #endif static osg::ApplicationUsageProxy Registry_e2(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_BUILD_KDTREES on/off","Enable/disable the automatic building of KdTrees for each loaded Geometry."); // from MimeTypes.cpp extern const char* builtinMimeTypeExtMappings[]; class Registry::AvailableReaderWriterIterator { public: AvailableReaderWriterIterator(Registry::ReaderWriterList& rwList, OpenThreads::ReentrantMutex& pluginMutex): _rwList(rwList), _pluginMutex(pluginMutex) {} ReaderWriter& operator * () { return *get(); } ReaderWriter* operator -> () { return get(); } bool valid() { return get()!=0; } void operator ++() { _rwUsed.insert(get()); } protected: AvailableReaderWriterIterator& operator = (const AvailableReaderWriterIterator&) { return *this; } Registry::ReaderWriterList& _rwList; OpenThreads::ReentrantMutex& _pluginMutex; std::set _rwUsed; ReaderWriter* get() { OpenThreads::ScopedLock lock(_pluginMutex); Registry::ReaderWriterList::iterator itr=_rwList.begin(); for(;itr!=_rwList.end();++itr) { if (_rwUsed.find(itr->get())==_rwUsed.end()) { return itr->get(); } } return 0; } }; class Registry::AvailableArchiveIterator { public: AvailableArchiveIterator(Registry::ArchiveCache& archives, OpenThreads::ReentrantMutex& mutex): _archives(archives), _mutex(mutex) {} Archive& operator * () { return *get(); } Archive* operator -> () { return get(); } bool valid() { return get()!=0; } void operator ++() { _archivesUsed.insert(get()); } protected: AvailableArchiveIterator& operator = (const AvailableArchiveIterator&) { return *this; } Registry::ArchiveCache& _archives; OpenThreads::ReentrantMutex& _mutex; std::set _archivesUsed; Archive* get() { OpenThreads::ScopedLock lock(_mutex); Registry::ArchiveCache::iterator itr=_archives.begin(); for(;itr!=_archives.end();++itr) { if (_archivesUsed.find(itr->second.get())==_archivesUsed.end()) { return itr->second.get(); } } return 0; } }; #if 0 // temporary test of autoregistering, not compiled by default. enum Methods { SET_1, SET_2, END }; typedef std::pair MethodPair; class Proxy { public: Proxy(MethodPair* methods) { std::cout<<"methods "< s_registry = new Registry; if (erase) { s_registry->destruct(); s_registry = 0; } return s_registry.get(); // will return NULL on erase } // definition of the Registry Registry::Registry() { // comment out because it was causing problems under OSX - causing it to crash osgconv when constructing ostream in osg::notify(). // OSG_INFO << "Constructing osg::Registry"< void Registry::initDataFilePathList() { FilePathList filepath; // // set up data file paths // char *ptr; if( (ptr = getenv( "OSG_FILE_PATH" )) ) { //OSG_NOTIFY(DEBUG_INFO) << "OSG_FILE_PATH("<addCommandLineOption("-l ","Load the plugin"); arguments.getApplicationUsage()->addCommandLineOption("-e ","Load the plugin associated with handling files with specified extension"); arguments.getApplicationUsage()->addCommandLineOption("-O ","Provide an option string to reader/writers used to load databases"); } std::string value; while(arguments.read("-l",value)) { loadLibrary(value); } while(arguments.read("-e",value)) { std::string libName = createLibraryNameForExtension(value); loadLibrary(libName); } while(arguments.read("-O",value)) { setOptions(new Options(value)); } } void Registry::addReaderWriter(ReaderWriter* rw) { if (rw==0L) return; // OSG_NOTIFY(INFO) << "osg::Registry::addReaderWriter("<className()<<")"<< std::endl; OpenThreads::ScopedLock lock(_pluginMutex); _rwList.push_back(rw); } void Registry::removeReaderWriter(ReaderWriter* rw) { if (rw==0L) return; // OSG_NOTIFY(INFO) << "osg::Registry::removeReaderWriter();"<< std::endl; OpenThreads::ScopedLock lock(_pluginMutex); ReaderWriterList::iterator rwitr = std::find(_rwList.begin(),_rwList.end(),rw); if (rwitr!=_rwList.end()) { _rwList.erase(rwitr); } } ImageProcessor* Registry::getImageProcessor() { { OpenThreads::ScopedLock lock(_pluginMutex); if (!_ipList.empty()) { return _ipList.front().get(); } } return getImageProcessorForExtension("nvtt"); } ImageProcessor* Registry::getImageProcessorForExtension(const std::string& ext) { { OpenThreads::ScopedLock lock(_pluginMutex); if (!_ipList.empty()) { return _ipList.front().get(); } } std::string libraryName = createLibraryNameForExtension(ext); OSG_NOTICE << "Now checking for plug-in "< lock(_pluginMutex); if (!_ipList.empty()) { OSG_NOTICE << "Loaded plug-in "<className()<<")"<< std::endl; OpenThreads::ScopedLock lock(_pluginMutex); _ipList.push_back(ip); } void Registry::removeImageProcessor(ImageProcessor* ip) { if (ip==0L) return; OSG_NOTIFY(NOTICE) << "osg::Registry::removeImageProcessor();"<< std::endl; OpenThreads::ScopedLock lock(_pluginMutex); ImageProcessorList::iterator ipitr = std::find(_ipList.begin(),_ipList.end(),ip); if (ipitr!=_ipList.end()) { _ipList.erase(ipitr); } } void Registry::addFileExtensionAlias(const std::string mapExt, const std::string toExt) { _extAliasMap[mapExt] = toExt; } void Registry::addMimeTypeExtensionMapping(const std::string fromMimeType, const std::string toExt) { _mimeTypeExtMap[fromMimeType] = toExt; } bool Registry::readPluginAliasConfigurationFile( const std::string& file ) { std::string fileName = osgDB::findDataFile( file ); if (fileName.empty()) { OSG_NOTIFY( osg::WARN) << "Can't find plugin alias config file \"" << file << "\"." << std::endl; return false; } osgDB::ifstream ifs; ifs.open( fileName.c_str() ); if (!ifs.good()) { OSG_NOTIFY( osg::WARN) << "Can't open plugin alias config file \"" << fileName << "\"." << std::endl; return false; } int lineNum( 0 ); while (ifs.good()) { std::string raw; ++lineNum; std::getline( ifs, raw ); std::string ln = trim( raw ); if (ln.empty()) continue; if (ln[0] == '#') continue; std::string::size_type spIdx = ln.find_first_of( " \t" ); if (spIdx == ln.npos) { // mapExt and toExt must be on the same line, separated by a space. OSG_NOTIFY( osg::WARN) << file << ", line " << lineNum << ": Syntax error: missing space in \"" << raw << "\"." << std::endl; continue; } const std::string mapExt = trim( ln.substr( 0, spIdx ) ); const std::string toExt = trim( ln.substr( spIdx+1 ) ); addFileExtensionAlias( mapExt, toExt ); } return true; } std::string Registry::trim( const std::string& str ) { if (!str.size()) return str; std::string::size_type first = str.find_first_not_of( " \t" ); std::string::size_type last = str.find_last_not_of( " \t\r\n" ); if ((first==str.npos) || (last==str.npos)) return std::string( "" ); return str.substr( first, last-first+1 ); } std::string Registry::createLibraryNameForFile(const std::string& fileName) { return createLibraryNameForExtension(getFileExtension(fileName)); } std::string Registry::createLibraryNameForExtension(const std::string& ext) { std::string lowercase_ext; for(std::string::const_iterator sitr=ext.begin(); sitr!=ext.end(); ++sitr) { lowercase_ext.push_back(tolower(*sitr)); } ExtensionAliasMap::iterator itr=_extAliasMap.find(lowercase_ext); if (itr!=_extAliasMap.end() && ext != itr->second) return createLibraryNameForExtension(itr->second); std::string prepend = std::string("osgPlugins-")+std::string(osgGetVersion())+std::string("/"); #if defined(__CYGWIN__) return prepend+"cygwin_"+"osgdb_"+lowercase_ext+OSG_LIBRARY_POSTFIX_WITH_QUOTES+".dll"; #elif defined(__MINGW32__) return prepend+"mingw_"+"osgdb_"+lowercase_ext+OSG_LIBRARY_POSTFIX_WITH_QUOTES+".dll"; #elif defined(WIN32) return prepend+"osgdb_"+lowercase_ext+OSG_LIBRARY_POSTFIX_WITH_QUOTES+".dll"; #elif macintosh return prepend+"osgdb_"+lowercase_ext+OSG_LIBRARY_POSTFIX_WITH_QUOTES; #else return prepend+"osgdb_"+lowercase_ext+OSG_LIBRARY_POSTFIX_WITH_QUOTES+ADDQUOTES(OSG_PLUGIN_EXTENSION); #endif } std::string Registry::createLibraryNameForNodeKit(const std::string& name) { #if defined(__CYGWIN__) return "cyg"+name+OSG_LIBRARY_POSTFIX_WITH_QUOTES+".dll"; #elif defined(__MINGW32__) return "lib"+name+OSG_LIBRARY_POSTFIX_WITH_QUOTES+".dll"; #elif defined(WIN32) return name+OSG_LIBRARY_POSTFIX_WITH_QUOTES+".dll"; #elif macintosh return name+OSG_LIBRARY_POSTFIX_WITH_QUOTES; #else return "lib"+name+OSG_LIBRARY_POSTFIX_WITH_QUOTES + ADDQUOTES(OSG_PLUGIN_EXTENSION); #endif } Registry::LoadStatus Registry::loadLibrary(const std::string& fileName) { OpenThreads::ScopedLock lock(_pluginMutex); DynamicLibraryList::iterator ditr = getLibraryItr(fileName); if (ditr!=_dlList.end()) return PREVIOUSLY_LOADED; _openingLibrary=true; DynamicLibrary* dl = DynamicLibrary::loadLibrary(fileName); _openingLibrary=false; if (dl) { _dlList.push_back(dl); return LOADED; } return NOT_LOADED; } bool Registry::closeLibrary(const std::string& fileName) { OpenThreads::ScopedLock lock(_pluginMutex); DynamicLibraryList::iterator ditr = getLibraryItr(fileName); if (ditr!=_dlList.end()) { _dlList.erase(ditr); return true; } return false; } void Registry::closeAllLibraries() { // OSG_NOTICE<<"Registry::closeAllLibraries()"< lock(_pluginMutex); _dlList.clear(); } Registry::DynamicLibraryList::iterator Registry::getLibraryItr(const std::string& fileName) { DynamicLibraryList::iterator ditr = _dlList.begin(); for(;ditr!=_dlList.end();++ditr) { if ((*ditr)->getName()==fileName) return ditr; } return _dlList.end(); } DynamicLibrary* Registry::getLibrary(const std::string& fileName) { OpenThreads::ScopedLock lock(_pluginMutex); DynamicLibraryList::iterator ditr = getLibraryItr(fileName); if (ditr!=_dlList.end()) return ditr->get(); else return NULL; } ReaderWriter* Registry::getReaderWriterForExtension(const std::string& ext) { // record the existing reader writer. std::set rwOriginal; OpenThreads::ScopedLock lock(_pluginMutex); // first attemt one of the installed loaders for(ReaderWriterList::iterator itr=_rwList.begin(); itr!=_rwList.end(); ++itr) { rwOriginal.insert(itr->get()); if((*itr)->acceptsExtension(ext)) return (*itr).get(); } // now look for a plug-in to load the file. std::string libraryName = createLibraryNameForExtension(ext); OSG_NOTIFY(INFO) << "Now checking for plug-in "<get())==rwOriginal.end()) { if((*itr)->acceptsExtension(ext)) return (*itr).get(); } } } return NULL; } ReaderWriter* Registry::getReaderWriterForMimeType(const std::string& mimeType) { MimeTypeExtensionMap::const_iterator i = _mimeTypeExtMap.find( mimeType ); return i != _mimeTypeExtMap.end()? getReaderWriterForExtension( i->second ) : NULL; } #if 0 struct concrete_wrapper: basic_type_wrapper { virtual ~concrete_wrapper() {} concrete_wrapper(const osg::Object *myobj) : myobj_(myobj) {} bool matches(const osg::Object *proto) const { return myobj_->isSameKindAs(proto); } const osg::Object *myobj_; }; #endif struct Registry::ReadObjectFunctor : public Registry::ReadFunctor { ReadObjectFunctor(const std::string& filename, const Options* options):ReadFunctor(filename,options) {} virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.readObject(_filename, _options); } virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validObject(); } virtual bool isValid(osg::Object* object) const { return object!=0; } virtual ReadFunctor* cloneType(const std::string& filename, const Options* options) const { return new ReadObjectFunctor(filename, options); } }; struct Registry::ReadImageFunctor : public Registry::ReadFunctor { ReadImageFunctor(const std::string& filename, const Options* options):ReadFunctor(filename,options) {} virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw)const { return rw.readImage(_filename, _options); } virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validImage(); } virtual bool isValid(osg::Object* object) const { return dynamic_cast(object)!=0; } virtual ReadFunctor* cloneType(const std::string& filename, const Options* options) const { return new ReadImageFunctor(filename, options); } }; struct Registry::ReadHeightFieldFunctor : public Registry::ReadFunctor { ReadHeightFieldFunctor(const std::string& filename, const Options* options):ReadFunctor(filename,options) {} virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.readHeightField(_filename, _options); } virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validHeightField(); } virtual bool isValid(osg::Object* object) const { return dynamic_cast(object)!=0; } virtual ReadFunctor* cloneType(const std::string& filename, const Options* options) const { return new ReadHeightFieldFunctor(filename, options); } }; struct Registry::ReadNodeFunctor : public Registry::ReadFunctor { ReadNodeFunctor(const std::string& filename, const Options* options):ReadFunctor(filename,options) {} virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.readNode(_filename, _options); } virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validNode(); } virtual bool isValid(osg::Object* object) const { return dynamic_cast(object)!=0; } virtual ReadFunctor* cloneType(const std::string& filename, const Options* options) const { return new ReadNodeFunctor(filename, options); } }; struct Registry::ReadArchiveFunctor : public Registry::ReadFunctor { ReadArchiveFunctor(const std::string& filename, ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint, const Options* options): ReadFunctor(filename,options), _status(status), _indexBlockSizeHint(indexBlockSizeHint) {} ReaderWriter::ArchiveStatus _status; unsigned int _indexBlockSizeHint; virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.openArchive(_filename, _status, _indexBlockSizeHint, _options); } virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validArchive(); } virtual bool isValid(osg::Object* object) const { return dynamic_cast(object)!=0; } virtual ReadFunctor* cloneType(const std::string& filename, const Options* options) const { return new ReadArchiveFunctor(filename, _status, _indexBlockSizeHint, options); } }; struct Registry::ReadShaderFunctor : public Registry::ReadFunctor { ReadShaderFunctor(const std::string& filename, const Options* options):ReadFunctor(filename,options) {} virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw)const { return rw.readShader(_filename, _options); } virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validShader(); } virtual bool isValid(osg::Object* object) const { return dynamic_cast(object)!=0; } virtual ReadFunctor* cloneType(const std::string& filename, const Options* options) const { return new ReadShaderFunctor(filename, options); } }; void Registry::addArchiveExtension(const std::string ext) { for(ArchiveExtensionList::iterator aitr=_archiveExtList.begin(); aitr!=_archiveExtList.end(); ++aitr) { if ( (*aitr) == ext) // extension already in archive extension list return; } _archiveExtList.push_back(ext); } std::string Registry::findDataFileImplementation(const std::string& filename, const Options* options, CaseSensitivity caseSensitivity) { if (filename.empty()) return filename; // if data file contains a server address then we can't find it in local directories so return empty string. if (containsServerAddress(filename)) return std::string(); bool absolutePath = osgDB::isAbsolutePath(filename); if (absolutePath && fileExists(filename)) { OSG_DEBUG << "FindFileInPath(" << filename << "): returning " << filename << std::endl; return filename; } std::string fileFound; bool pathsContainsCurrentWorkingDirectory = false; if (options && !options->getDatabasePathList().empty()) { fileFound = findFileInPath(filename, options->getDatabasePathList(), caseSensitivity); if (!fileFound.empty()) return fileFound; if (osgDB::containsCurrentWorkingDirectoryReference(options->getDatabasePathList())) { pathsContainsCurrentWorkingDirectory = true; } } const FilePathList& filepaths = Registry::instance()->getDataFilePathList(); if (!filepaths.empty()) { fileFound = findFileInPath(filename, filepaths, caseSensitivity); if (!fileFound.empty()) return fileFound; if (!pathsContainsCurrentWorkingDirectory && osgDB::containsCurrentWorkingDirectoryReference(filepaths)) { pathsContainsCurrentWorkingDirectory = true; } } if (!absolutePath && !pathsContainsCurrentWorkingDirectory) { // check current working directory if (fileExists(filename)) { return filename; } } // if a directory is included in the filename, get just the (simple) filename itself and try that std::string simpleFileName = getSimpleFileName(filename); if (simpleFileName!=filename) { if(fileExists(simpleFileName)) { OSG_DEBUG << "FindFileInPath(" << filename << "): returning " << simpleFileName << std::endl; return simpleFileName; } if (options && !options->getDatabasePathList().empty()) { fileFound = findFileInPath(simpleFileName, options->getDatabasePathList(), caseSensitivity); if (!fileFound.empty()) return fileFound; } if (!filepaths.empty()) { fileFound = findFileInPath(simpleFileName, filepaths,caseSensitivity); if (!fileFound.empty()) return fileFound; } } // return empty string. return std::string(); } std::string Registry::findLibraryFileImplementation(const std::string& filename, const Options* /*options*/, CaseSensitivity caseSensitivity) { if (filename.empty()) return filename; const FilePathList& filepath = Registry::instance()->getLibraryFilePathList(); std::string fileFound = findFileInPath(filename, filepath,caseSensitivity); if (!fileFound.empty()) return fileFound; if(fileExists(filename)) { OSG_DEBUG << "FindFileInPath(" << filename << "): returning " << filename << std::endl; return filename; } // if a directory is included in the filename, get just the (simple) filename itself and try that std::string simpleFileName = getSimpleFileName(filename); if (simpleFileName!=filename) { std::string fileFound = findFileInPath(simpleFileName, filepath,caseSensitivity); if (!fileFound.empty()) return fileFound; } // failed return empty string. return std::string(); } ReaderWriter::ReadResult Registry::read(const ReadFunctor& readFunctor) { for(ArchiveExtensionList::iterator aitr=_archiveExtList.begin(); aitr!=_archiveExtList.end(); ++aitr) { std::string archiveExtension = "." + (*aitr); std::string::size_type positionArchive = readFunctor._filename.find(archiveExtension+'/'); if (positionArchive==std::string::npos) positionArchive = readFunctor._filename.find(archiveExtension+'\\'); if (positionArchive!=std::string::npos) { std::string::size_type endArchive = positionArchive + archiveExtension.length(); std::string archiveName( readFunctor._filename.substr(0,endArchive)); std::string fileName(readFunctor._filename.substr(endArchive+1,std::string::npos)); OSG_INFO<<"Contains archive : "< options = readFunctor._options ? readFunctor._options->cloneOptions() : new osgDB::ReaderWriter::Options; options->setDatabasePath(archiveName); std::auto_ptr rf(readFunctor.cloneType(fileName, options.get())); result = rf->doRead(*archive); if (rf->isValid(result)) { OSG_INFO<<"Read object from archive"< Results; Results results; // first attempt to load the file from existing ReaderWriter's AvailableReaderWriterIterator itr(_rwList, _pluginMutex); for(;itr.valid();++itr) { ReaderWriter::ReadResult rr = readFunctor.doRead(*itr); if (readFunctor.isValid(rr)) return rr; else results.push_back(rr); } // check loaded archives. AvailableArchiveIterator aaitr(_archiveCache, _archiveCacheMutex); for(;aaitr.valid();++aaitr) { ReaderWriter::ReadResult rr = readFunctor.doRead(*aaitr); if (readFunctor.isValid(rr)) return rr; else { // don't pass on FILE_NOT_FOUND results as we don't want to prevent non archive plugins that haven't been // loaded yet from getting a chance to test for the presence of the file. if (rr.status()!=ReaderWriter::ReadResult::FILE_NOT_FOUND) results.push_back(rr); } } // now look for a plug-in to load the file. std::string libraryName = createLibraryNameForFile(readFunctor._filename); if (loadLibrary(libraryName)!=NOT_LOADED) { for(;itr.valid();++itr) { ReaderWriter::ReadResult rr = readFunctor.doRead(*itr); if (readFunctor.isValid(rr)) return rr; else results.push_back(rr); } } //If the filename contains a server address and wasn't loaded by any of the plugins, try to find a plugin which supports the server //protocol and supports wildcards. If not successfully use curl as a last fallback if (containsServerAddress(readFunctor._filename)) { ReaderWriter* rw = getReaderWriterForProtocolAndExtension( osgDB::getServerProtocol(readFunctor._filename), osgDB::getFileExtension(readFunctor._filename) ); if (rw) { return readFunctor.doRead(*rw); } else { return ReaderWriter::ReadResult("Warning: Could not find the .curl plugin to read from server."); } } if (results.empty()) { return ReaderWriter::ReadResult("Warning: Could not find plugin to read objects from file \""+readFunctor._filename+"\"."); } // sort the results so the most relevant (i.e. ERROR_IN_READING_FILE is more relevant than FILE_NOT_FOUND) results get placed at the end of the results list. std::sort(results.begin(), results.end()); ReaderWriter::ReadResult result = results.back(); if (result.message().empty()) { switch(result.status()) { case(ReaderWriter::ReadResult::FILE_NOT_HANDLED): result.message() = "Warning: reading \""+readFunctor._filename+"\" not supported."; break; case(ReaderWriter::ReadResult::FILE_NOT_FOUND): result.message() = "Warning: could not find file \""+readFunctor._filename+"\"."; break; case(ReaderWriter::ReadResult::ERROR_IN_READING_FILE): result.message() = "Warning: Error in reading to \""+readFunctor._filename+"\"."; break; default: break; } } return result; } ReaderWriter::ReadResult Registry::readImplementation(const ReadFunctor& readFunctor,Options::CacheHintOptions cacheHint) { std::string file(readFunctor._filename); bool useObjectCache=false; //Note CACHE_ARCHIVES has a different object that it caches to so it will never be used here if (cacheHint!=Options::CACHE_ARCHIVES) { const Options* options=readFunctor._options; useObjectCache=options ? (options->getObjectCacheHint()&cacheHint)!=0: false; } if (useObjectCache) { // search for entry in the object cache. { OpenThreads::ScopedLock lock(_objectCacheMutex); ObjectCache::iterator oitr=_objectCache.find(file); if (oitr!=_objectCache.end()) { OSG_INFO<<"returning cached instanced of "<second.first.get())) return ReaderWriter::ReadResult(oitr->second.first.get(), ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE); else return ReaderWriter::ReadResult("Error file does not contain an osg::Object"); } } ReaderWriter::ReadResult rr = read(readFunctor); if (rr.validObject()) { // search AGAIN for entry in the object cache. { OpenThreads::ScopedLock lock(_objectCacheMutex); ObjectCache::iterator oitr = _objectCache.find(file); if (oitr != _objectCache.end()) { OSG_INFO << "returning cached instanced of " << file << std::endl; if (readFunctor.isValid(oitr->second.first.get())) return ReaderWriter::ReadResult(oitr->second.first.get(), ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE); else return ReaderWriter::ReadResult("Error file does not contain an osg::Object"); } // update cache with new entry. OSG_INFO<<"Adding to object cache "< archive = getRefFromArchiveCache(fileName); if (archive.valid()) return archive.get(); ReaderWriter::ReadResult result = readImplementation(ReadArchiveFunctor(fileName, status, indexBlockSizeHint, options),Options::CACHE_ARCHIVES); // default to using caching archive if no options structure provided, but if options are provided use archives // only if supplied. if (result.validArchive() && (!options || (options->getObjectCacheHint() & Options::CACHE_ARCHIVES)) ) { addToArchiveCache(fileName,result.getArchive()); } return result; } ReaderWriter::ReadResult Registry::readObjectImplementation(const std::string& fileName,const Options* options) { return readImplementation(ReadObjectFunctor(fileName, options),Options::CACHE_OBJECTS); } ReaderWriter::WriteResult Registry::writeObjectImplementation(const Object& obj,const std::string& fileName,const Options* options) { // record the errors reported by readerwriters. typedef std::vector Results; Results results; // first attempt to load the file from existing ReaderWriter's AvailableReaderWriterIterator itr(_rwList, _pluginMutex); for(;itr.valid();++itr) { ReaderWriter::WriteResult rr = itr->writeObject(obj,fileName,options); if (rr.success()) return rr; else results.push_back(rr); } // now look for a plug-in to save the file. std::string libraryName = createLibraryNameForFile(fileName); if (loadLibrary(libraryName)==LOADED) { for(;itr.valid();++itr) { ReaderWriter::WriteResult rr = itr->writeObject(obj,fileName,options); if (rr.success()) return rr; else results.push_back(rr); } } if (results.empty()) { return ReaderWriter::WriteResult("Warning: Could not find plugin to write objects to file \""+fileName+"\"."); } // sort the results so the most relevant (i.e. ERROR_IN_WRITING_FILE is more relevant than FILE_NOT_FOUND) results get placed at the end of the results list. std::sort(results.begin(), results.end()); ReaderWriter::WriteResult result = results.back(); if (result.message().empty()) { switch(result.status()) { case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): result.message() = "Warning: Write to \""+fileName+"\" not supported."; break; case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): result.message() = "Warning: Error in writing to \""+fileName+"\"."; break; default: break; } } return result; } ReaderWriter::ReadResult Registry::readImageImplementation(const std::string& fileName,const Options* options) { return readImplementation(ReadImageFunctor(fileName, options),Options::CACHE_IMAGES); } ReaderWriter::WriteResult Registry::writeImageImplementation(const Image& image,const std::string& fileName,const Options* options) { // record the errors reported by readerwriters. typedef std::vector Results; Results results; // first attempt to load the file from existing ReaderWriter's AvailableReaderWriterIterator itr(_rwList, _pluginMutex); for(;itr.valid();++itr) { ReaderWriter::WriteResult rr = itr->writeImage(image,fileName,options); if (rr.success()) return rr; else results.push_back(rr); } // now look for a plug-in to save the file. std::string libraryName = createLibraryNameForFile(fileName); if (loadLibrary(libraryName)==LOADED) { for(;itr.valid();++itr) { ReaderWriter::WriteResult rr = itr->writeImage(image,fileName,options); if (rr.success()) return rr; else results.push_back(rr); } } if (results.empty()) { return ReaderWriter::WriteResult("Warning: Could not find plugin to write image to file \""+fileName+"\"."); } // sort the results so the most relevant (i.e. ERROR_IN_WRITING_FILE is more relevant than FILE_NOT_FOUND) results get placed at the end of the results list. std::sort(results.begin(), results.end()); ReaderWriter::WriteResult result = results.back(); if (result.message().empty()) { switch(result.status()) { case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): result.message() = "Warning: Write to \""+fileName+"\" not supported."; break; case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): result.message() = "Warning: Error in writing to \""+fileName+"\"."; break; default: break; } } return result; } ReaderWriter::ReadResult Registry::readHeightFieldImplementation(const std::string& fileName,const Options* options) { return readImplementation(ReadHeightFieldFunctor(fileName, options),Options::CACHE_HEIGHTFIELDS); } ReaderWriter::WriteResult Registry::writeHeightFieldImplementation(const HeightField& HeightField,const std::string& fileName,const Options* options) { // record the errors reported by readerwriters. typedef std::vector Results; Results results; // first attempt to load the file from existing ReaderWriter's AvailableReaderWriterIterator itr(_rwList, _pluginMutex); for(;itr.valid();++itr) { ReaderWriter::WriteResult rr = itr->writeHeightField(HeightField,fileName,options); if (rr.success()) return rr; else results.push_back(rr); } // now look for a plug-in to save the file. std::string libraryName = createLibraryNameForFile(fileName); if (loadLibrary(libraryName)==LOADED) { for(;itr.valid();++itr) { ReaderWriter::WriteResult rr = itr->writeHeightField(HeightField,fileName,options); if (rr.success()) return rr; else results.push_back(rr); } } if (results.empty()) { return ReaderWriter::WriteResult("Warning: Could not find plugin to write HeightField to file \""+fileName+"\"."); } // sort the results so the most relevant (i.e. ERROR_IN_WRITING_FILE is more relevant than FILE_NOT_FOUND) results get placed at the end of the results list. std::sort(results.begin(), results.end()); ReaderWriter::WriteResult result = results.back(); if (result.message().empty()) { switch(result.status()) { case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): result.message() = "Warning: Write to \""+fileName+"\" not supported."; break; case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): result.message() = "Warning: Error in writing to \""+fileName+"\"."; break; default: break; } } return result; } ReaderWriter::ReadResult Registry::readNodeImplementation(const std::string& fileName,const Options* options) { #if 0 osg::Timer_t startTick = osg::Timer::instance()->tick(); ReaderWriter::ReadResult result = readImplementation(ReadNodeFunctor(fileName, options),Options::CACHE_NODES); osg::Timer_t endTick = osg::Timer::instance()->tick(); OSG_NOTICE<<"time to load "<delta_m(startTick, endTick)<<"ms"< Results; Results results; // first attempt to write the file from existing ReaderWriter's AvailableReaderWriterIterator itr(_rwList, _pluginMutex); for(;itr.valid();++itr) { ReaderWriter::WriteResult rr = itr->writeNode(node,fileName,options); if (rr.success()) return rr; else results.push_back(rr); } // now look for a plug-in to save the file. std::string libraryName = createLibraryNameForFile(fileName); if (loadLibrary(libraryName)==LOADED) { for(;itr.valid();++itr) { ReaderWriter::WriteResult rr = itr->writeNode(node,fileName,options); if (rr.success()) return rr; else results.push_back(rr); } } if (results.empty()) { return ReaderWriter::WriteResult("Warning: Could not find plugin to write nodes to file \""+fileName+"\"."); } // sort the results so the most relevant (i.e. ERROR_IN_WRITING_FILE is more relevant than FILE_NOT_FOUND) results get placed at the end of the results list. std::sort(results.begin(), results.end()); ReaderWriter::WriteResult result = results.back(); if (result.message().empty()) { switch(result.status()) { case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): result.message() = "Warning: Write to \""+fileName+"\" not supported."; break; case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): result.message() = "Warning: Error in writing to \""+fileName+"\"."; break; default: break; } } return result; } ReaderWriter::ReadResult Registry::readShaderImplementation(const std::string& fileName,const Options* options) { return readImplementation(ReadShaderFunctor(fileName, options),Options::CACHE_SHADERS); } ReaderWriter::WriteResult Registry::writeShaderImplementation(const Shader& shader,const std::string& fileName,const Options* options) { // record the errors reported by readerwriters. typedef std::vector Results; Results results; // first attempt to load the file from existing ReaderWriter's AvailableReaderWriterIterator itr(_rwList, _pluginMutex); for(;itr.valid();++itr) { ReaderWriter::WriteResult rr = itr->writeShader(shader,fileName,options); if (rr.success()) return rr; else results.push_back(rr); } results.clear(); // now look for a plug-in to save the file. std::string libraryName = createLibraryNameForFile(fileName); if (loadLibrary(libraryName)==LOADED) { for(;itr.valid();++itr) { ReaderWriter::WriteResult rr = itr->writeShader(shader,fileName,options); if (rr.success()) return rr; else results.push_back(rr); } } if (results.empty()) { return ReaderWriter::WriteResult("Warning: Could not find plugin to write shader to file \""+fileName+"\"."); } // sort the results so the most relevant (i.e. ERROR_IN_WRITING_FILE is more relevant than FILE_NOT_FOUND) results get placed at the end of the results list. std::sort(results.begin(), results.end()); ReaderWriter::WriteResult result = results.back(); if (result.message().empty()) { switch(result.status()) { case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): result.message() = "Warning: Write to \""+fileName+"\" not supported."; break; case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): result.message() = "Warning: Error in writing to \""+fileName+"\"."; break; default: break; } } return result; } void Registry::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp) { OpenThreads::ScopedLock lock(_objectCacheMutex); _objectCache[filename]=ObjectTimeStampPair(object,timestamp); } osg::Object* Registry::getFromObjectCache(const std::string& fileName) { OpenThreads::ScopedLock lock(_objectCacheMutex); ObjectCache::iterator itr = _objectCache.find(fileName); if (itr!=_objectCache.end()) return itr->second.first.get(); else return 0; } osg::ref_ptr Registry::getRefFromObjectCache(const std::string& fileName) { OpenThreads::ScopedLock lock(_objectCacheMutex); ObjectCache::iterator itr = _objectCache.find(fileName); if (itr!=_objectCache.end()) return itr->second.first; else return 0; } void Registry::updateTimeStampOfObjectsInCacheWithExternalReferences(const osg::FrameStamp& frameStamp) { OpenThreads::ScopedLock lock(_objectCacheMutex); // look for objects with external references and update their time stamp. for(ObjectCache::iterator itr=_objectCache.begin(); itr!=_objectCache.end(); ++itr) { // if ref count is greater the 1 the object has an external reference. if (itr->second.first->referenceCount()>1) { // so update it time stamp. itr->second.second = frameStamp.getReferenceTime(); } } } void Registry::removeExpiredObjectsInCache(const osg::FrameStamp& frameStamp) { double expiryTime = frameStamp.getReferenceTime() - _expiryDelay; OpenThreads::ScopedLock lock(_objectCacheMutex); // Remove expired entries from object cache ObjectCache::iterator oitr = _objectCache.begin(); while(oitr != _objectCache.end()) { if (oitr->second.second<=expiryTime) { _objectCache.erase(oitr++); } else { ++oitr; } } } void Registry::removeFromObjectCache(const std::string& fileName) { OpenThreads::ScopedLock lock(_objectCacheMutex); ObjectCache::iterator itr = _objectCache.find(fileName); if (itr!=_objectCache.end()) _objectCache.erase(itr); } void Registry::clearObjectCache() { OpenThreads::ScopedLock lock(_objectCacheMutex); _objectCache.clear(); } void Registry::addToArchiveCache(const std::string& fileName, osgDB::Archive* archive) { OpenThreads::ScopedLock lock(_archiveCacheMutex); _archiveCache[fileName] = archive; } /** Remove archive from cache.*/ void Registry::removeFromArchiveCache(const std::string& fileName) { OpenThreads::ScopedLock lock(_archiveCacheMutex); ArchiveCache::iterator itr = _archiveCache.find(fileName); if (itr!=_archiveCache.end()) { _archiveCache.erase(itr); } } osgDB::Archive* Registry::getFromArchiveCache(const std::string& fileName) { OpenThreads::ScopedLock lock(_archiveCacheMutex); ArchiveCache::iterator itr = _archiveCache.find(fileName); if (itr!=_archiveCache.end()) return itr->second.get(); else return 0; } osg::ref_ptr Registry::getRefFromArchiveCache(const std::string& fileName) { OpenThreads::ScopedLock lock(_archiveCacheMutex); ArchiveCache::iterator itr = _archiveCache.find(fileName); if (itr!=_archiveCache.end()) return itr->second; else return 0; } void Registry::clearArchiveCache() { OpenThreads::ScopedLock lock(_archiveCacheMutex); _archiveCache.clear(); } void Registry::releaseGLObjects(osg::State* state) { OpenThreads::ScopedLock lock(_objectCacheMutex); for(ObjectCache::iterator itr = _objectCache.begin(); itr != _objectCache.end(); ++itr) { osg::Object* object = itr->second.first.get(); object->releaseGLObjects(state); } if (_sharedStateManager.valid()) { _sharedStateManager->releaseGLObjects( state ); } } SharedStateManager* Registry::getOrCreateSharedStateManager() { if (!_sharedStateManager) _sharedStateManager = new SharedStateManager; return _sharedStateManager.get(); } void Registry::registerProtocol(const std::string& protocol) { _registeredProtocols.insert( convertToLowerCase(protocol) ); } bool Registry::isProtocolRegistered(const std::string& protocol) { return (_registeredProtocols.find( convertToLowerCase(protocol) ) != _registeredProtocols.end()); } void Registry::getReaderWriterListForProtocol(const std::string& protocol, ReaderWriterList& results) const { for(ReaderWriterList::const_iterator i = _rwList.begin(); i != _rwList.end(); ++i) { if ((*i)->acceptsProtocol(protocol)) results.push_back(*i); } } ReaderWriter* Registry::getReaderWriterForProtocolAndExtension(const std::string& protocol, const std::string& extension) { // try first the registered ReaderWriter ReaderWriter* result = getReaderWriterForExtension(extension); if (result && result->acceptsProtocol(protocol)) return result; result = NULL; ReaderWriterList results; getReaderWriterListForProtocol(protocol, results); for(ReaderWriterList::const_iterator i = results.begin(); i != results.end(); ++i) { // if we have a readerwriter which supports wildcards, save it as a fallback if ((*i)->acceptsExtension("*")) result = i->get(); else if ((*i)->acceptsExtension(extension)) return i->get(); } return result ? result : getReaderWriterForExtension("curl"); } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/DatabaseRevisions.cpp0000644000175000017500000001156112163275353025135 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include using namespace osgDB; //////////////////////////////////////////////////////////////////////////////////////////// // // FilelList // FileList::FileList() { } FileList::FileList(const FileList& fileList, const osg::CopyOp & copyop): osg::Object(fileList, copyop), _files(fileList._files) { } FileList::~FileList() { } bool FileList::removeFile(const std::string& filename) { FileNames::iterator itr = _files.find(filename); if (itr==_files.end()) return false; _files.erase(itr); return true; } void FileList::append(FileList* fileList) { for(FileNames::iterator itr = fileList->_files.begin(); itr != fileList->_files.end(); ++itr) { _files.insert(*itr); } } //////////////////////////////////////////////////////////////////////////////////////////// // // DatabaseRevision // DatabaseRevision::DatabaseRevision() { } DatabaseRevision::DatabaseRevision(const DatabaseRevision& revision, const osg::CopyOp & copyop): osg::Object(revision, copyop), _databasePath(revision._databasePath), _filesAdded(revision._filesAdded), _filesRemoved(revision._filesRemoved), _filesModified(revision._filesModified) { } DatabaseRevision::~DatabaseRevision() { } bool DatabaseRevision::isFileBlackListed(const std::string& filename) const { OSG_INFO<<"DatabaseRevision("<=filename.length()) return false; if (filename.compare(0,_databasePath.length(), _databasePath)!=0) return false; std::string localPath(filename, _databasePath.empty() ? 0 : _databasePath.length()+1, std::string::npos); return (_filesRemoved.valid() && _filesRemoved->containsFile(localPath)) || (_filesModified.valid() && _filesModified->containsFile(localPath)); } bool DatabaseRevision::removeFile(const std::string& filename) { bool removed = false; if (_filesAdded.valid()) removed = _filesAdded->removeFile(filename) | removed; if (_filesRemoved.valid()) removed = _filesRemoved->removeFile(filename) | removed; if (_filesModified.valid()) removed = _filesModified->removeFile(filename) | removed; return removed; } //////////////////////////////////////////////////////////////////////////////////////////// // // DatabaseRevisions // DatabaseRevisions::DatabaseRevisions() { } DatabaseRevisions::DatabaseRevisions(const DatabaseRevisions& revisions, const osg::CopyOp & copyop): osg::Object(revisions, copyop), _databasePath(revisions._databasePath), _revisionList(revisions._revisionList) { } DatabaseRevisions::~DatabaseRevisions() { } void DatabaseRevisions::addRevision(DatabaseRevision* revision) { if (!revision) return; for(DatabaseRevisionList::iterator itr = _revisionList.begin(); itr != _revisionList.end(); ++itr) { if (*itr == revision) return; if ((*itr)->getName()==revision->getName()) { (*itr) = revision; return; } } _revisionList.push_back(revision); } void DatabaseRevisions::removeRevision(DatabaseRevision* revision) { for(DatabaseRevisionList::iterator itr = _revisionList.begin(); itr != _revisionList.end(); ++itr) { if (*itr == revision) { _revisionList.erase(itr); return; } } } bool DatabaseRevisions::isFileBlackListed(const std::string& filename) const { for(DatabaseRevisionList::const_iterator itr = _revisionList.begin(); itr != _revisionList.end(); ++itr) { if ((*itr)->isFileBlackListed(filename)) { OSG_INFO<<"File is black listed "<removeFile(filename) | removed; } return removed; } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/FileUtils.cpp0000644000175000017500000012361212433716615023431 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ // handle TCHAR type on various platforms // #ifndef is inspired by https://svn.apache.org/repos/asf/logging/log4cxx/tags/v0_9_4/include/log4cxx/helpers/tchar.h // defining type as plain char is from unzip.h, line 64 #ifndef TCHAR typedef char TCHAR; #endif // currently this impl is for _all_ platforms, except as defined. // the mac version will change soon to reflect the path scheme under osx, but // for now, the above include is commented out, and the below code takes precedence. #if defined(WIN32) && !defined(__CYGWIN__) #include #define WINBASE_DECLARE_GET_MODULE_HANDLE_EX #include #include #include #include #include // for _mkdir #define mkdir(x,y) _mkdir((x)) #define stat64 _stati64 // set up for windows so acts just like unix access(). #ifndef F_OK #define F_OK 4 #endif #else // unix #if defined( __APPLE__ ) // I'm not sure how we would handle this in raw Darwin // without the AvailablilityMacros. #include //>OSG_IOS //IOS includes #include "TargetConditionals.h" #if (TARGET_OS_IPHONE) #include // workaround a bug which appears when compiling for SDK < 4.0 and for the simulator #if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) #define stat64 stat #else #if !TARGET_IPHONE_SIMULATOR #define stat64 stat #endif #endif #endif // #include #include #include #endif // set up _S_ISDIR() #if !defined(S_ISDIR) # if defined( _S_IFDIR) && !defined( __S_IFDIR) # define __S_IFDIR _S_IFDIR # endif # define S_ISDIR(mode) (mode&__S_IFDIR) #endif #include #include #include #include #include #include #include #include #include namespace osgDB { #ifdef OSG_USE_UTF8_FILENAME #define OSGDB_STRING_TO_FILENAME(s) osgDB::convertUTF8toUTF16(s) #define OSGDB_FILENAME_TO_STRING(s) osgDB::convertUTF16toUTF8(s) #define OSGDB_FILENAME_TEXT(x) L ## x #define OSGDB_WINDOWS_FUNCT(x) x ## W #define OSGDB_WINDOWS_FUNCT_STRING(x) #x "W" typedef wchar_t filenamechar; typedef std::wstring filenamestring; #else #define OSGDB_STRING_TO_FILENAME(s) s #define OSGDB_FILENAME_TO_STRING(s) s #define OSGDB_FILENAME_TEXT(x) x #define OSGDB_WINDOWS_FUNCT(x) x ## A #define OSGDB_WINDOWS_FUNCT_STRING(x) #x "A" typedef char filenamechar; typedef std::string filenamestring; #endif } FILE* osgDB::fopen(const char* filename, const char* mode) { #ifdef OSG_USE_UTF8_FILENAME return ::_wfopen(convertUTF8toUTF16(filename).c_str(), convertUTF8toUTF16(mode).c_str()); #else return ::fopen(filename, mode); #endif } bool osgDB::makeDirectory( const std::string &path ) { if (path.empty()) { OSG_DEBUG << "osgDB::makeDirectory(): cannot create an empty directory" << std::endl; return false; } struct stat64 stbuf; #ifdef OSG_USE_UTF8_FILENAME if( _wstat64( OSGDB_STRING_TO_FILENAME(path).c_str(), &stbuf ) == 0 ) #else if( stat64( path.c_str(), &stbuf ) == 0 ) #endif { if( S_ISDIR(stbuf.st_mode)) return true; else { OSG_DEBUG << "osgDB::makeDirectory(): " << path << " already exists and is not a directory!" << std::endl; return false; } } std::string dir = path; std::stack paths; while( true ) { if( dir.empty() ) break; #ifdef OSG_USE_UTF8_FILENAME if( _wstat64( OSGDB_STRING_TO_FILENAME(dir).c_str(), &stbuf ) < 0 ) #else if( stat64( dir.c_str(), &stbuf ) < 0 ) #endif { switch( errno ) { case ENOENT: case ENOTDIR: paths.push( dir ); break; default: OSG_DEBUG << "osgDB::makeDirectory(): " << strerror(errno) << std::endl; return false; } } dir = getFilePath(std::string(dir)); } while( !paths.empty() ) { std::string dir = paths.top(); #if defined(WIN32) //catch drive name if (dir.size() == 2 && dir.c_str()[1] == ':') { paths.pop(); continue; } #endif #ifdef OSG_USE_UTF8_FILENAME if ( _wmkdir(OSGDB_STRING_TO_FILENAME(dir).c_str())< 0 ) #else if( mkdir( dir.c_str(), 0755 )< 0 ) #endif { // Only return an error if the directory actually doesn't exist. It's possible that the directory was created // by another thread or process if (!osgDB::fileExists(dir)) { OSG_DEBUG << "osgDB::makeDirectory(): " << strerror(errno) << std::endl; return false; } } paths.pop(); } return true; } bool osgDB::makeDirectoryForFile( const std::string &path ) { return makeDirectory( getFilePath( path )); } std::string osgDB::getCurrentWorkingDirectory( void ) { // MAX_PATH/cwd inspired by unzip.cpp #ifndef MAX_PATH #define MAX_PATH 1024 #endif TCHAR rootdir[MAX_PATH]; if(getcwd(rootdir,MAX_PATH-1)) { return(rootdir); } return(""); }// osgDB::getCurrentWorkingDirectory bool osgDB::setCurrentWorkingDirectory( const std::string &newCurrentWorkingDirectory ) { if (newCurrentWorkingDirectory.empty()) { OSG_DEBUG << "osgDB::setCurrentWorkingDirectory(): called with empty string." << std::endl; return false; } #ifdef OSG_USE_UTF8_FILENAME return _wchdir( OSGDB_STRING_TO_FILENAME(newCurrentWorkingDirectory).c_str()) == 0; #else return chdir( newCurrentWorkingDirectory.c_str()) == 0; #endif return true; } // osgDB::setCurrentWorkingDirectory void osgDB::convertStringPathIntoFilePathList(const std::string& paths,FilePathList& filepath) { #if defined(WIN32) && !defined(__CYGWIN__) char delimitor = ';'; #else char delimitor = ':'; #endif if (!paths.empty()) { std::string::size_type start = 0; std::string::size_type end; while ((end = paths.find_first_of(delimitor,start))!=std::string::npos) { filepath.push_back(std::string(paths,start,end-start)); start = end+1; } std::string lastPath(paths,start,std::string::npos); if (!lastPath.empty()) filepath.push_back(lastPath); } } bool osgDB::fileExists(const std::string& filename) { #ifdef OSG_USE_UTF8_FILENAME return _waccess( OSGDB_STRING_TO_FILENAME(filename).c_str(), F_OK ) == 0; #else return access( filename.c_str(), F_OK ) == 0; #endif } osgDB::FileType osgDB::fileType(const std::string& filename) { struct stat64 fileStat; #ifdef OSG_USE_UTF8_FILENAME if ( _wstat64(OSGDB_STRING_TO_FILENAME(filename).c_str(), &fileStat) != 0 ) #else if ( stat64(filename.c_str(), &fileStat) != 0 ) #endif { return FILE_NOT_FOUND; } // end if if ( fileStat.st_mode & S_IFDIR ) return DIRECTORY; else if ( fileStat.st_mode & S_IFREG ) return REGULAR_FILE; return FILE_NOT_FOUND; } std::string osgDB::findFileInPath(const std::string& filename, const FilePathList& filepath,CaseSensitivity caseSensitivity) { if (filename.empty()) return filename; if (!isFileNameNativeStyle(filename)) return findFileInPath(convertFileNameToNativeStyle(filename), filepath, caseSensitivity); for(FilePathList::const_iterator itr=filepath.begin(); itr!=filepath.end(); ++itr) { OSG_DEBUG << "itr='" <<*itr<< "'\n"; std::string path = itr->empty() ? filename : concatPaths(*itr, filename); path = getRealPath(path); OSG_DEBUG << "FindFileInPath() : trying " << path << " ...\n"; if(fileExists(path)) { OSG_DEBUG << "FindFileInPath() : USING " << path << "\n"; return path; } #ifndef WIN32 // windows already case insensitive so no need to retry.. else if (caseSensitivity==CASE_INSENSITIVE) { std::string foundfile = findFileInDirectory(filename,*itr,CASE_INSENSITIVE); if (!foundfile.empty()) return foundfile; } #endif } return std::string(); } std::string osgDB::findDataFile(const std::string& filename,CaseSensitivity caseSensitivity) { return findDataFile(filename,static_cast(0),caseSensitivity); } OSGDB_EXPORT std::string osgDB::findDataFile(const std::string& filename,const Options* options, CaseSensitivity caseSensitivity) { return Registry::instance()->findDataFile(filename, options, caseSensitivity); } std::string osgDB::findLibraryFile(const std::string& filename,CaseSensitivity caseSensitivity) { return Registry::instance()->findLibraryFile(filename, osgDB::Registry::instance()->getOptions(), caseSensitivity); } std::string osgDB::findFileInDirectory(const std::string& fileName,const std::string& dirName,CaseSensitivity caseSensitivity) { bool needFollowingBackslash = false; bool needDirectoryName = true; osgDB::DirectoryContents dc; std::string realDirName = dirName; std::string realFileName = fileName; // Skip case-insensitive recursion if on Windows #ifdef WIN32 bool win32 = true; #else bool win32 = false; #endif // If the fileName contains extra path information, make that part of the // directory name instead if (fileName != getSimpleFileName(fileName)) { // See if we need to add a slash between the directory and file if (realDirName.empty()) { realDirName = getFilePath(fileName); } else if (realDirName=="." || realDirName=="./" || realDirName==".\\") { realDirName = "./" + getFilePath(fileName); } else { char lastChar = dirName[dirName.size()-1]; if ((lastChar == '/') || (lastChar == '\\')) realDirName = dirName + getFilePath(fileName); else realDirName = dirName + "/" + getFilePath(fileName); } // Simplify the file name realFileName = getSimpleFileName(fileName); } OSG_DEBUG << "findFileInDirectory() : looking for " << realFileName << " in " << realDirName << "...\n"; if (realDirName.empty()) { dc = osgDB::getDirectoryContents("."); needFollowingBackslash = false; needDirectoryName = false; } else if (realDirName=="." || realDirName=="./" || realDirName==".\\") { dc = osgDB::getDirectoryContents("."); needFollowingBackslash = false; needDirectoryName = false; } else if (realDirName=="/") { dc = osgDB::getDirectoryContents("/"); needFollowingBackslash = false; needDirectoryName = true; } else { // See if we're working in case insensitive mode, and that we're not // using Windows (the recursive search is not needed in these // cases) if ((caseSensitivity == CASE_INSENSITIVE) && (!win32)) { // Split the last path element from the directory name std::string parentPath = getFilePath(realDirName); std::string lastElement = getSimpleFileName(realDirName); // See if we're already at the top level of the filesystem if ((parentPath.empty()) && (!lastElement.empty())) { std::string directoryStringToUse = (realDirName[0]=='/' || realDirName[0]=='\\') ? std::string("/") : std::string("."); // Search for the first path element (ignoring case) in // the top-level directory realDirName = findFileInDirectory(lastElement, directoryStringToUse, CASE_INSENSITIVE); dc = osgDB::getDirectoryContents(realDirName); needFollowingBackslash = true; needDirectoryName = true; } else { // Recursively search for the last path element (ignoring case) // in the parent path realDirName = findFileInDirectory(lastElement, parentPath, CASE_INSENSITIVE); dc = osgDB::getDirectoryContents(realDirName); char lastChar = realDirName[realDirName.size()-1]; if (lastChar=='/') needFollowingBackslash = false; else if (lastChar=='\\') needFollowingBackslash = false; else needFollowingBackslash = true; needDirectoryName = true; } } else { // No need for recursive search if we're doing an exact comparison dc = osgDB::getDirectoryContents(realDirName); char lastChar = realDirName[realDirName.size()-1]; if (lastChar=='/') needFollowingBackslash = false; else if (lastChar=='\\') needFollowingBackslash = false; else needFollowingBackslash = true; needDirectoryName = true; } } for(osgDB::DirectoryContents::iterator itr=dc.begin(); itr!=dc.end(); ++itr) { if ((caseSensitivity==CASE_INSENSITIVE && osgDB::equalCaseInsensitive(realFileName,*itr)) || (realFileName==*itr)) { if (!needDirectoryName) return *itr; else if (needFollowingBackslash) return realDirName+'/'+*itr; else return realDirName+*itr; } } return ""; } static void appendInstallationLibraryFilePaths(osgDB::FilePathList& filepath) { #ifdef OSG_DEFAULT_LIBRARY_PATH // Append the install prefix path to the library search path if configured filepath.push_back(OSG_DEFAULT_LIBRARY_PATH); #endif } #if defined(WIN32) && !defined(__CYGWIN__) #include #include osgDB::DirectoryContents osgDB::getDirectoryContents(const std::string& dirName) { osgDB::DirectoryContents contents; OSGDB_WINDOWS_FUNCT(WIN32_FIND_DATA) data; HANDLE handle = OSGDB_WINDOWS_FUNCT(FindFirstFile)((OSGDB_STRING_TO_FILENAME(dirName) + OSGDB_FILENAME_TEXT("\\*")).c_str(), &data); if (handle != INVALID_HANDLE_VALUE) { do { contents.push_back(OSGDB_FILENAME_TO_STRING(data.cFileName)); } while (OSGDB_WINDOWS_FUNCT(FindNextFile)(handle, &data) != 0); FindClose(handle); } return contents; } #else #include osgDB::DirectoryContents osgDB::getDirectoryContents(const std::string& dirName) { osgDB::DirectoryContents contents; DIR *handle = opendir(dirName.c_str()); if (handle) { dirent *rc; while((rc = readdir(handle))!=NULL) { contents.push_back(rc->d_name); } closedir(handle); } return contents; } #endif // unix getDirectoryContexts osgDB::DirectoryContents osgDB::getSortedDirectoryContents(const std::string& dirName) { osgDB::DirectoryContents filenames = osgDB::getDirectoryContents(dirName); std::sort(filenames.begin(), filenames.end(), osgDB::FileNameComparator()); return filenames; } osgDB::DirectoryContents osgDB::expandWildcardsInFilename(const std::string& filename) { osgDB::DirectoryContents contents; std::string dir = osgDB::getFilePath(filename); std::string filenameOnly = dir.empty() ? filename : filename.substr(dir.length()+1, std::string::npos); std::string left = filenameOnly.substr(0, filenameOnly.find('*')); std::string right = filenameOnly.substr(filenameOnly.find('*')+1, std::string::npos); if (dir.empty()) dir = osgDB::getCurrentWorkingDirectory(); osgDB::DirectoryContents dirContents = osgDB::getDirectoryContents(dir); for (unsigned int i = 0; i < dirContents.size(); ++i) { std::string filenameInDir = dirContents[i]; if (filenameInDir == "." || filenameInDir == "..") { continue; } if ((filenameInDir.find(left) == 0 || left.empty()) && (filenameInDir.find(right) == filenameInDir.length() - right.length() || right.empty())) { contents.push_back( dir + osgDB::getNativePathSeparator() + filenameInDir ); } } return contents; } osgDB::FileOpResult::Value osgDB::copyFile(const std::string & source, const std::string & destination) { if (source.empty() || destination.empty()) { OSG_INFO << "copyFile(): Empty file name." << std::endl; return FileOpResult::BAD_ARGUMENT; } // Check if source and destination are the same if (source == destination || osgDB::getRealPath(source) == osgDB::getRealPath(destination)) { OSG_INFO << "copyFile(): Source and destination point to the same file: source=" << source << ", destination=" << destination << std::endl; return FileOpResult::SOURCE_EQUALS_DESTINATION; } // Check if source file exists if (!osgDB::fileExists(source)) { OSG_INFO << "copyFile(): Source file does not exist: " << source << std::endl; return FileOpResult::SOURCE_MISSING; } // Open source file osgDB::ifstream fin(source.c_str(), std::ios::in | std::ios::binary); if (!fin) { OSG_NOTICE << "copyFile(): Can't read source file: " << source << std::endl; return FileOpResult::SOURCE_NOT_OPENED; // Return success since it's not an output error. } // Ensure the directory exists or else the FBX SDK will fail if (!osgDB::makeDirectoryForFile(destination)) { OSG_INFO << "Can't create directory for file '" << destination << "'. Copy may fail creating the file." << std::endl; } // Open destination file osgDB::ofstream fout(destination.c_str(), std::ios::out | std::ios::binary | std::ios::trunc); if (!fout) { OSG_NOTICE << "copyFile(): Can't write destination file: " << destination << std::endl; return FileOpResult::DESTINATION_NOT_OPENED; } // Copy file const unsigned int BUFFER_SIZE = 10240; osgDB::ifstream::char_type buffer[BUFFER_SIZE]; for(; fin.good() && fout.good() && !fin.eof(); ) { fin.read(buffer, BUFFER_SIZE); fout.write(buffer, fin.gcount()); } if (!fout.good()) { OSG_NOTICE << "copyFile(): Error writing destination file: " << destination << std::endl; return FileOpResult::WRITE_ERROR; } if (!fin.eof()) { OSG_NOTICE << "copyFile(): Error reading source file: " << source << std::endl; return FileOpResult::READ_ERROR; } return FileOpResult::OK; } bool osgDB::containsCurrentWorkingDirectoryReference(const FilePathList& paths) { const std::string cwd("."); for(FilePathList::const_iterator itr = paths.begin(); itr != paths.end(); ++itr) { if (itr->empty()) return true; if (*itr==cwd) return true; } return false; } ///////////////////////////////////////////////////////////////////////////////////////////////// // // Implementation of appendPlatformSpecificLibraryFilePaths(..) // #ifdef __sgi void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath) { convertStringPathIntoFilePathList("/usr/lib32/:/usr/local/lib32/",filepath); // bloody mess see rld(1) man page char* ptr; #if (_MIPS_SIM == _MIPS_SIM_ABI32) if( (ptr = getenv( "LD_LIBRARY_PATH" ))) { convertStringPathIntoFilePathList(ptr,filepath); } #elif (_MIPS_SIM == _MIPS_SIM_NABI32) if( !(ptr = getenv( "LD_LIBRARYN32_PATH" ))) ptr = getenv( "LD_LIBRARY_PATH" ); if( ptr ) { convertStringPathIntoFilePathList(ptr,filepath); } #elif (_MIPS_SIM == _MIPS_SIM_ABI64) if( !(ptr = getenv( "LD_LIBRARY64_PATH" ))) ptr = getenv( "LD_LIBRARY_PATH" ); if( ptr ) { convertStringPathIntoFilePathList(ptr,filepath); } #endif appendInstallationLibraryFilePaths(filepath); } #elif defined(__CYGWIN__) void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath) { char* ptr; if ((ptr = getenv( "PATH" ))) { convertStringPathIntoFilePathList(ptr,filepath); } appendInstallationLibraryFilePaths(filepath); convertStringPathIntoFilePathList("/usr/bin/:/usr/local/bin/",filepath); } #elif defined(WIN32) void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath) { // See http://msdn2.microsoft.com/en-us/library/ms682586.aspx // Safe DLL search mode changes the DLL search order to search for // DLLs in the current directory after the system directories, instead // of right after the application's directory. According to the article // linked above, on Windows XP and Windows 2000, Safe DLL search mode // is disabled by default. However, it is a good idea to enable it. We // will search as if it was enabled. // So if SafeDllSearchMode is enabled, the search order is as follows: // 1. The directory from which the application loaded. DWORD retval = 0; const DWORD size = MAX_PATH; filenamechar path[size]; retval = OSGDB_WINDOWS_FUNCT(GetModuleFileName)(NULL, path, size); if (retval != 0 && retval < size) { filenamestring pathstr(path); filenamestring executableDir(pathstr, 0, pathstr.find_last_of(OSGDB_FILENAME_TEXT("\\/"))); convertStringPathIntoFilePathList(OSGDB_FILENAME_TO_STRING(executableDir), filepath); } else { OSG_WARN << "Could not get application directory " "using Win32 API. It will not be searched." << std::endl; } // 2. The directory that the dll that contains this function is in. // For static builds, this will be the executable directory. #if defined(_MSC_VER) // Requires use of the GetModuleHandleEx() function which is available only on Windows XP or higher. // In order to allow execution on older versions, we load the function dynamically from the library and // use it only if it's available. OSGDB_WINDOWS_FUNCT(PGET_MODULE_HANDLE_EX) pGetModuleHandleEx = reinterpret_cast (GetProcAddress( GetModuleHandleA("kernel32.dll"), OSGDB_WINDOWS_FUNCT_STRING(GetModuleHandleEx))); if( pGetModuleHandleEx ) { HMODULE thisModule = 0; static filenamechar static_variable = 0; // Variable that is located in DLL address space. if( pGetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, &static_variable, &thisModule) ) { retval = OSGDB_WINDOWS_FUNCT(GetModuleFileName)(thisModule, path, size); if (retval != 0 && retval < size) { filenamestring pathstr(path); filenamestring dllDir(pathstr, 0, pathstr.find_last_of(OSGDB_FILENAME_TEXT("\\/"))); convertStringPathIntoFilePathList(OSGDB_FILENAME_TO_STRING(dllDir), filepath); } else { OSG_WARN << "Could not get dll directory " "using Win32 API. It will not be searched." << std::endl; } FreeLibrary(thisModule); } else { OSG_WARN << "Could not get dll module handle " "using Win32 API. Dll directory will not be searched." << std::endl; } } #endif // 3. The system directory. Use the GetSystemDirectory function to // get the path of this directory. filenamechar systemDir[(UINT)size]; retval = OSGDB_WINDOWS_FUNCT(GetSystemDirectory)(systemDir, (UINT)size); if (retval != 0 && retval < size) { convertStringPathIntoFilePathList(OSGDB_FILENAME_TO_STRING(systemDir), filepath); } else { OSG_WARN << "Could not get system directory using " "Win32 API, using default directory." << std::endl; convertStringPathIntoFilePathList("C:\\Windows\\System32", filepath); } // 4. The 16-bit system directory. There is no function that obtains // the path of this directory, but it is searched. // 5. The Windows directory. Use the GetWindowsDirectory function to // get the path of this directory. filenamechar windowsDir[(UINT)size]; retval = OSGDB_WINDOWS_FUNCT(GetWindowsDirectory)(windowsDir, (UINT)size); if (retval != 0 && retval < size) { convertStringPathIntoFilePathList(std::string(OSGDB_FILENAME_TO_STRING(windowsDir)) + "\\System", filepath); convertStringPathIntoFilePathList(OSGDB_FILENAME_TO_STRING(windowsDir), filepath); } else { OSG_WARN << "Could not get Windows directory using " "Win32 API, using default directory." << std::endl; convertStringPathIntoFilePathList("C:\\Windows", filepath); convertStringPathIntoFilePathList("C:\\Windows\\System", filepath); } // 6. The current directory. convertStringPathIntoFilePathList(".", filepath); // 7. The directories that are listed in the PATH environment // variable. Note that this does not include the per-application // path specified by the App Paths registry key. filenamechar* ptr; #ifdef OSG_USE_UTF8_FILENAME if ((ptr = _wgetenv(OSGDB_FILENAME_TEXT("PATH")))) #else if ((ptr = getenv("PATH"))) #endif { // Note that on any sane Windows system, some of the paths above // will also be on the PATH (the values gotten in systemDir and // windowsDir), but the DLL search goes sequentially and stops // when a DLL is found, so I see no point in removing duplicates. convertStringPathIntoFilePathList(OSGDB_FILENAME_TO_STRING(ptr), filepath); } appendInstallationLibraryFilePaths(filepath); } #elif defined(__APPLE__) #if (TARGET_OS_IPHONE) #define COMPILE_COCOA_VERSION #else #define COMPILE_CARBON_VERSION #endif // WARNING: Cocoa version is currently untested. #ifdef COMPILE_COCOA_VERSION #include #endif #ifdef COMPILE_CARBON_VERSION #include #include #include #endif #include // These functions are local to FileUtils.cpp and not exposed to the API // returns the path string except for numToShorten directories stripped off the end std::string GetShortenedPath(std::string path, int numToShorten) { unsigned int i = path.length() - 1; if(path[i] == '/') i--; while(i > 1 && numToShorten) { if(path[i] == '/') numToShorten--; i--; } return path.substr(0,i + 1); } // returns an absolute (POSIX on MacOS X) path from a CFURLRef std::string GetPathFromCFURLRef(CFURLRef urlRef) { char buffer[1024]; std::string path; if(CFURLGetFileSystemRepresentation(urlRef, true, (UInt8*)buffer, 1024)) path = std::string(buffer); return path; } // returns the absolute path to the main bundle std::string GetApplicationBundlePath(CFBundleRef mainBundle) { std::string path; CFURLRef urlRef = CFBundleCopyBundleURL(mainBundle); if(urlRef) { path = GetPathFromCFURLRef(urlRef); CFRelease(urlRef); // docs say we are responsible for releasing CFURLRef } return path; } std::string GetApplicationParentPath(CFBundleRef mainBundle) { return GetShortenedPath(GetApplicationBundlePath(mainBundle), 1); } std::string GetApplicationPluginsPath(CFBundleRef mainBundle) { std::string path; CFURLRef urlRef = CFBundleCopyBuiltInPlugInsURL(mainBundle); if(urlRef) { path = GetPathFromCFURLRef(urlRef); CFRelease(urlRef); } return path; } std::string GetApplicationResourcesPath(CFBundleRef mainBundle) { std::string path; CFURLRef urlRef = CFBundleCopyResourcesDirectoryURL(mainBundle); if(urlRef) { path = GetPathFromCFURLRef(urlRef); CFRelease(urlRef); } return path; } // The Cocoa version is about 10 lines of code. // The Carbon version is noticably longer. // Unfortunately, the Cocoa version requires -lobjc to be // linked in when creating an executable. // Rumor is that this will be done autmatically in gcc 3.5/Tiger, // but for now, this will cause a lot of headaches for people // who aren't familiar with this concept, so the Carbon version // is preferable. // But for the curious, both implementations are here. // Note that if the Cocoa version is used, the file should be // renamed to use the .mm extension to denote Objective-C++. // And of course, you will need to link against Cocoa // Update: There is a bug in the Cocoa version. Advanced users can remap // their systems so these paths go somewhere else. The Carbon calls // will catch this, but the hardcoded Cocoa code below will not. #ifdef COMPILE_COCOA_VERSION // OS X has preferred locations for where PlugIns should be located. // This function will set this as the order to search: // YourProgram.app/Contents/PlugIns // ~/Library/Application Support/OpenSceneGraph/PlugIns // /Library/Application Support/OpenSceneGraph/PlugIns // /Network/Library/Application Support/OpenSceneGraph/PlugIns // // As a side effect of this function, if the application is not a // bundle, the first place searched becomes // YourProgram/PlugIns // // In principle, these other directories should be searched: // ~/Library/Application Support/YourProgram/PlugIns // /Library/Application Support/YourProgram/PlugIns // /Network/Library/Application Support/TheProgram/PlugIns // But I'm not going to worry about it for now because the // bundle's PlugIns directory is supposed to be the preferred // place for this anyway. // // Another directory that might be worth considering is // the directory the program resides in, // but I'm worried about multiplatform distribution. // Because .so is used by other platforms like Linux, we // could end up loading the wrong binary. // I'm not sure how robust the current code is for this case. // Assuming the program doesn't crash, will OSG move on to the // next search directory, or just give up? void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath) { char* ptr; if ((ptr = getenv( "DYLD_LIBRARY_PATH" )) ) { convertStringPathIntoFilePathList(ptr, filepath); } appendInstallationLibraryFilePaths(filepath); // Since this is currently the only Objective-C code in the // library, we need an autoreleasepool for obj-c memory management. // If more Obj-C is added, we might move this pool to another // location so it can be shared. Pools seem to be stackable, // so I don't think there will be a problem if multiple pools // exist at a time. NSAutoreleasePool* mypool = [[NSAutoreleasePool alloc] init]; NSString* myBundlePlugInPath; NSString* userSupportDir; // This will grab the "official" bundle plug in path. // It will be YourProgram.app/Contents/PlugIns (for App bundles) // or YourProgram/PlugIns (for Unix executables) myBundlePlugInPath = [[NSBundle mainBundle] builtInPlugInsPath]; // Now setup the other search paths // Cocoa has a nice method for tilde expansion. // There's probably a better way of getting this directory, but I // can't find the call. userSupportDir = [@"~/Library/Application Support/OpenSceneGraph/PlugIns" stringByExpandingTildeInPath]; // Can setup the remaining directories directly in C++ // Since Obj-C and C++ objects don't understand each other, // the Obj-C strings must be converted down to C strings so // C++ can make them into C++ strings. filepath.push_back( [myBundlePlugInPath UTF8String] ); filepath.push_back( [userSupportDir UTF8String] ); filepath.push_back( "/Library/Application Support/OpenSceneGraph/PlugIns" ); filepath.push_back( "/Network/Library/Application Support/OpenSceneGraph/PlugIns" ); // Clean up the autorelease pool [mypool release]; } #elif defined(COMPILE_CARBON_VERSION) // OS X has preferred locations for where PlugIns should be located. // This function will set this as the order to search: // YourProgram.app/Contents/PlugIns // ~/Library/Application Support/OpenSceneGraph/PlugIns // /Library/Application Support/OpenSceneGraph/PlugIns // /Network/Library/Application Support/OpenSceneGraph/PlugIns // // In principle, these other directories should be searched: // ~/Library/Application Support/YourProgram/PlugIns // /Library/Application Support/YourProgram/PlugIns // /Network/Library/Application Support/TheProgram/PlugIns // But I'm not going to worry about it for now because the // bundle's PlugIns directory is supposed to be the preferred // place for this anyway. // // Another directory that might be worth considering is // the directory the program resides in, // but I'm worried about multiplatform distribution. // Because .so is used by other platforms like Linux, we // could end up loading the wrong binary. // I'm not sure how robust the current code is for this case. // Assuming the program doesn't crash, will OSG move on to the // next search directory, or just give up? void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath) { char* ptr; if ((ptr = getenv( "DYLD_LIBRARY_PATH" )) ) { convertStringPathIntoFilePathList(ptr, filepath); } appendInstallationLibraryFilePaths(filepath); const std::string OSG_PLUGIN_PATH("/OpenSceneGraph/PlugIns"); CFURLRef url; CFBundleRef myBundle; FSRef f; OSErr errCode; // Start with the the Bundle PlugIns directory. // Get the main bundle first. No need to retain or release it since // we are not keeping a reference myBundle = CFBundleGetMainBundle(); if(myBundle != NULL) { // CFBundleGetMainBundle will return a bundle ref even if // the application isn't part of a bundle, so we need to check // if the path to the bundle ends in ".app" to see if it is a // proper application bundle. If it is, the plugins path is added std::string bundlePath = GetApplicationBundlePath(myBundle); if( bundlePath.substr(bundlePath.length() - 4, 4) == std::string(".app") ) filepath.push_back(GetApplicationPluginsPath(myBundle)); } else { OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't find the Application Bundle" << std::endl; } // Next, check the User's Application Support folder errCode = FSFindFolder( kUserDomain, kApplicationSupportFolderType, kDontCreateFolder, &f ); if(noErr == errCode) { // Get the URL url = CFURLCreateFromFSRef( 0, &f ); if(url) { filepath.push_back(GetPathFromCFURLRef(url) + OSG_PLUGIN_PATH); CFRelease( url ); } else OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't create CFURLRef for User's application support Path" << std::endl; url = NULL; } else { OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't find the User's Application Support Path" << std::endl; } // Next, check the Local System's Application Support Folder errCode = FSFindFolder( kLocalDomain, kApplicationSupportFolderType, kDontCreateFolder, &f ); if(noErr == errCode) { // Get the URL url = CFURLCreateFromFSRef( 0, &f ); if(url) { filepath.push_back(GetPathFromCFURLRef(url) + OSG_PLUGIN_PATH); CFRelease( url ); } else OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't create CFURLRef for local System's ApplicationSupport Path" << std::endl; url = NULL; } else { OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't find the Local System's Application Support Path" << std::endl; } // Finally, check the Network Application Support Folder // This one has a likely chance of not existing so an error // may be returned. Don't panic. errCode = FSFindFolder( kNetworkDomain, kApplicationSupportFolderType, kDontCreateFolder, &f ); if(noErr == errCode) { // Get the URL url = CFURLCreateFromFSRef( 0, &f ); if(url) { filepath.push_back(GetPathFromCFURLRef(url) + OSG_PLUGIN_PATH); CFRelease( url ); } else OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't create CFURLRef for network Application Support Path" << std::endl; url = NULL; } else { // had to comment out as it segfauls the OSX app otherwise // OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't find the Network Application Support Path" << std::endl; } } #else void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath) { char* ptr; if ((ptr = getenv( "DYLD_LIBRARY_PATH" )) ) { convertStringPathIntoFilePathList(ptr, filepath); } appendInstallationLibraryFilePaths(filepath); } #endif #else void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath) { char* ptr; if( (ptr = getenv( "LD_LIBRARY_PATH" )) ) { convertStringPathIntoFilePathList(ptr,filepath); } appendInstallationLibraryFilePaths(filepath); #if defined(__ia64__) || defined(__x86_64__) convertStringPathIntoFilePathList("/usr/lib/:/usr/lib64/:/usr/local/lib/:/usr/local/lib64/",filepath); #else convertStringPathIntoFilePathList("/usr/lib/:/usr/local/lib/",filepath); #endif } #endif #ifdef __APPLE__ void osgDB::appendPlatformSpecificResourceFilePaths(FilePathList& filepath) { // Get the main application bundle CFBundleRef mainBundle = CFBundleGetMainBundle(); if (mainBundle != NULL) { // Get the parent directory and the resources directory std::string bundlePath = GetApplicationBundlePath(mainBundle); std::string resourcesPath = GetApplicationResourcesPath(mainBundle); // check if application is really part of a .app bundle if(bundlePath.substr(bundlePath.length() - 4, 4) == std::string(".app")) { if(resourcesPath != std::string("")) filepath.push_back( resourcesPath ); std::string parentPath = GetShortenedPath(bundlePath, 1); if(parentPath != std::string("")) filepath.push_back( parentPath ); } } else { OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't find the Application Bundle." << std::endl; } } #else void osgDB::appendPlatformSpecificResourceFilePaths(FilePathList& /*filepath*/) { } #endif openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/Archive.cpp0000644000175000017500000000663011732410624023102 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include using namespace osgDB; osgDB::Archive* osgDB::openArchive(const std::string& filename, ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint) { return openArchive(filename, status, indexBlockSizeHint, Registry::instance()->getOptions()); } osgDB::Archive* osgDB::openArchive(const std::string& filename, ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint,Options* options) { // ensure archive extension is in the registry list std::string::size_type dot = filename.find_last_of('.'); if (dot != std::string::npos) { std::string ext = filename.substr(dot+1); Registry::instance()->addArchiveExtension(ext); } ReaderWriter::ReadResult result = osgDB::Registry::instance()->openArchive(filename, status, indexBlockSizeHint, options); return result.takeArchive(); } Archive::Archive() { OSG_INFO<<"Archive::Archive() open"< searchPath.size()) { size_t endSubElement = currentFile.find(searchPath); //we match the whole string in the beginning of the path if(endSubElement == 0) { std::string remainingFile = currentFile.substr(searchPath.size() + 1, std::string::npos); size_t endFileToken = remainingFile.find_first_of('/'); if(endFileToken == std::string::npos) { dirContents.push_back(remainingFile); } } } } return dirContents; } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/Output.cpp0000644000175000017500000001362511732410624023023 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include using namespace std; using namespace osgDB; static osg::ApplicationUsageProxy Output_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_WRITE_OUT_DEFAULT_VALUES", "ON | OFF"); Output::Output() { init(); } Output::Output(const char* name) : osgDB::ofstream(name) { init(); _filename = name; } Output::~Output() { } void Output::init() { _indent = 0; _indentStep = 2; _numIndicesPerLine = 10; _pathNameHint = AS_IS; _outputTextureFiles = false; _textureFileNameNumber = 0; _outputShaderFiles = false; _shaderFileNameNumber = 0; _writeOutDefaultValues = false; const char* env = getenv("OSG_WRITE_OUT_DEFAULT_VALUES"); if (env) { _writeOutDefaultValues = strcmp(env,"ON")==0; } } void Output::setOptions(const Options* options) { _options = options; } void Output::open(const char *name) { init(); osgDB::ofstream::open(name); _filename = name; } // Comment out to avoid compile errors under new compilers, the int mode // is now a replaced by a class to wrap the mode. // This method is not used right now to hopefully nobody will miss it... // Jan 2002. // void Output::open(const char *name,int mode) // { // init(); // ofstream::open(name,mode); // _filename = name; // } Output& Output::indent() { for(int i=0;i<_indent;++i) *this<<' '; return *this; } void Output::moveIn() { _indent += _indentStep; } void Output::moveOut() { _indent -= _indentStep; if (_indent<0) _indent=0; } std::string Output::wrapString(const char* str) { if (!str) return std::string("\"\""); return wrapString(std::string(str)); } std::string Output::wrapString(const std::string& str) { std::string newstring; newstring += '"'; for(unsigned int i=0;igetDeprecatedDotOsgObjectWrapperManager()->writeObject(obj,*this); } void Output::writeBeginObject(const std::string& name) { indent() << name << " {" << std::endl; } void Output::writeEndObject() { indent() << "}" << std::endl; } void Output::writeUseID(const std::string& id) { indent() << "Use " << id << std::endl; } void Output::writeUniqueID(const std::string& id) { indent() << "UniqueID " << id << std::endl; } bool Output::getUniqueIDForObject(const osg::Object* obj,std::string& uniqueID) { UniqueIDToLabelMapping::iterator fitr = _objectToUniqueIDMap.find(obj); if (fitr != _objectToUniqueIDMap.end()) { uniqueID = (*fitr).second; return true; } else return false; } bool Output::createUniqueIDForObject(const osg::Object* obj,std::string& uniqueID) { char str[256]; sprintf(str,"%s_%i",obj->className(),(unsigned int)_objectToUniqueIDMap.size()); uniqueID = str; return true; } bool Output::registerUniqueIDForObject(const osg::Object* obj,std::string& uniqueID) { _objectToUniqueIDMap[obj] = uniqueID; return true; } std::string Output::getFileNameForOutput(const std::string& filename) const { switch(_pathNameHint) { case(FULL_PATH): { // need to think about how best to implement this first... OSG_WARN<<"Warning: Output::getFileNameForOutput() does not support FULL_PATH yet."<< std::endl; return filename; } case(RELATIVE_PATH): { // need to think about how best to implement this as well... OSG_WARN<<"Warning: Output::getFileNameForOutput() does not support RELATIVE_PATH yet."<< std::endl; return filename; } case(FILENAME_ONLY): // this one is straight forward. return getSimpleFileName(filename); case(AS_IS): default: // and this one is even more trivial. return filename; } } std::string Output::getTextureFileNameForOutput() { std::string fileName = osgDB::getNameLessExtension(_filename); if (_textureFileNameNumber>0) { std::ostringstream o; o << '_' << _textureFileNameNumber; fileName += o.str(); } fileName += ".dds"; ++_textureFileNameNumber; return fileName; } std::string Output::getShaderFileNameForOutput() { std::string fileName = osgDB::getNameLessExtension(_filename); if (_shaderFileNameNumber>0) { std::ostringstream o; o << '_' << _shaderFileNameNumber; fileName += o.str(); } fileName += ".glsl"; ++_shaderFileNameNumber; return fileName; } void Output::setExternalFileWritten(const std::string& filename, bool hasBeenWritten) { _externalFileWritten[filename] = hasBeenWritten; } bool Output::getExternalFileWritten(const std::string& filename) const { ExternalFileWrittenMap::const_iterator itr = _externalFileWritten.find(filename); if (itr != _externalFileWritten.end()) return itr->second; return false; } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/ImagePager.cpp0000644000175000017500000003001712163275353023525 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include using namespace osgDB; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // SortFileRequestFunctor // struct ImagePager::SortFileRequestFunctor { bool operator() (const osg::ref_ptr& lhs,const osg::ref_ptr& rhs) const { return (lhs->_timeToMergeBy < rhs->_timeToMergeBy); } }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // RequestQueue // void ImagePager::RequestQueue::sort() { std::sort(_requestList.begin(),_requestList.end(),SortFileRequestFunctor()); } unsigned int ImagePager::RequestQueue::size() const { OpenThreads::ScopedLock lock(_requestMutex); return _requestList.size(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // ReadQueue // ImagePager::ReadQueue::ReadQueue(ImagePager* pager, const std::string& name): _pager(pager), _name(name) { _block = new osg::RefBlock; } void ImagePager::ReadQueue::clear() { OpenThreads::ScopedLock lock(_requestMutex); for(RequestList::iterator citr = _requestList.begin(); citr != _requestList.end(); ++citr) { (*citr)->_attachmentPoint = 0; (*citr)->_requestQueue = 0; } _requestList.clear(); updateBlock(); } void ImagePager::ReadQueue::add(ImagePager::ImageRequest* imageRequest) { OpenThreads::ScopedLock lock(_requestMutex); _requestList.push_back(imageRequest); imageRequest->_requestQueue = this; OSG_INFO<<"ImagePager::ReadQueue::add("<_fileName<<"), size()="<<_requestList.size()<& databaseRequest) { OpenThreads::ScopedLock lock(_requestMutex); if (!_requestList.empty()) { sort(); OSG_INFO<<"ImagePager::ReadQueue::takeFirst(..), size()="<<_requestList.size()<_requestQueue = 0; _requestList.erase(_requestList.begin()); updateBlock(); } } ////////////////////////////////////////////////////////////////////////////////////// // // ImageThread // ImagePager::ImageThread::ImageThread(ImagePager* pager, Mode mode, const std::string& name): _done(false), _mode(mode), _pager(pager), _name(name) { } ImagePager::ImageThread::ImageThread(const ImageThread& dt, ImagePager* pager): _done(false), _mode(dt._mode), _pager(pager), _name(dt._name) { } ImagePager::ImageThread::~ImageThread() { } int ImagePager::ImageThread::cancel() { int result = 0; if( isRunning() ) { _done = true; switch(_mode) { case(HANDLE_ALL_REQUESTS): _pager->_readQueue->release(); break; case(HANDLE_NON_HTTP): _pager->_readQueue->release(); break; case(HANDLE_ONLY_HTTP): _pager->_readQueue->release(); break; } // release the frameBlock and _databasePagerThreadBlock in case its holding up thread cancellation. // _databasePagerThreadBlock->release(); // then wait for the the thread to stop running. while(isRunning()) { // commenting out debug info as it was cashing crash on exit, presumable // due to osg::notify or std::cout destructing earlier than this destructor. // OSG_DEBUG<<"Waiting for DatabasePager to cancel"<getFrameNumber()<<">>>>>>>>>>>>>>>>"<getFrameNumber()); } //else OSG_INFO << "signalBeginFrame >>>>>>>>>>>>>>>>"< read_queue; switch(_mode) { case(HANDLE_ALL_REQUESTS): read_queue = _pager->_readQueue; break; case(HANDLE_NON_HTTP): read_queue = _pager->_readQueue; break; case(HANDLE_ONLY_HTTP): read_queue = _pager->_readQueue; break; } do { read_queue->block(); osg::ref_ptr imageRequest; read_queue->takeFirst(imageRequest); if (imageRequest.valid()) { // OSG_NOTICE<<"doing readImageFile("<_fileName<<") index to assign = "<_attachmentIndex< image = osgDB::readImageFile(imageRequest->_fileName, imageRequest->_readOptions.get()); if (image.valid()) { // OSG_NOTICE<<" successful readImageFile("<_fileName<<") index to assign = "<_attachmentIndex<(imageRequest->_attachmentPoint.get()); if (is) { if (imageRequest->_attachmentIndex >= 0) { is->setImage(imageRequest->_attachmentIndex, image.get()); } else { is->addImage(image.get()); } } else { imageRequest->_loadedImage = image; OpenThreads::ScopedLock lock(_pager->_completedQueue->_requestMutex); _pager->_completedQueue->_requestList.push_back(imageRequest); } } } else { OpenThreads::Thread::YieldCurrentThread(); } // go to sleep till our the next time our thread gets scheduled. if (firstTime) { // do a yield to get round a peculiar thread hang when testCancel() is called // in certain circumstances - of which there is no particular pattern. YieldCurrentThread(); firstTime = false; } } while (!testCancel() && !_done); OSG_INFO<<"ImagePager::ImageThread::done()"<setDone(true); } // release the frameBlock and _databasePagerThreadBlock in case its holding up thread cancellation. _readQueue->release(); for(ImageThreads::iterator itr = _imageThreads.begin(); itr != _imageThreads.end(); ++itr) { (*itr)->cancel(); } _done = true; _startThreadCalled = false; //std::cout<<"DatabasePager::~DatabasePager() stopped running"<(const_cast(options)); return osgDB::readImageFile(fileName, readOptions); } void ImagePager::requestImageFile(const std::string& fileName, osg::Object* attachmentPoint, int attachmentIndex, double timeToMergeBy, const osg::FrameStamp* /*framestamp*/, osg::ref_ptr& imageRequest, const osg::Referenced* options) { osgDB::Options* readOptions = dynamic_cast(const_cast(options)); if (!readOptions) { readOptions = Registry::instance()->getOptions(); } bool alreadyAssigned = dynamic_cast(imageRequest.get()) && (imageRequest->referenceCount()>1); if (alreadyAssigned) { // OSG_NOTICE<<"ImagePager::requestImageFile("< request = new ImageRequest; request->_timeToMergeBy = timeToMergeBy; request->_fileName = fileName; request->_attachmentPoint = attachmentPoint; request->_attachmentIndex = attachmentIndex; request->_requestQueue = _readQueue.get(); request->_readOptions = readOptions; imageRequest = request; // OSG_NOTICE<<"ImagePager::requestImageFile("<add(request.get()); if (!_startThreadCalled) { OpenThreads::ScopedLock lock(_run_mutex); if (!_startThreadCalled) { _startThreadCalled = true; _done = false; for(ImageThreads::iterator itr = _imageThreads.begin(); itr != _imageThreads.end(); ++itr) { (*itr)->startThread(); } } } } bool ImagePager::requiresUpdateSceneGraph() const { //OSG_NOTICE<<"ImagePager::requiresUpdateSceneGraph()"<_requestList.empty()); } void ImagePager::updateSceneGraph(const osg::FrameStamp&) { OpenThreads::ScopedLock lock(_completedQueue->_requestMutex); for(RequestQueue::RequestList::iterator itr = _completedQueue->_requestList.begin(); itr != _completedQueue->_requestList.end(); ++itr) { ImageRequest* imageRequest = itr->get(); osg::Texture* texture = dynamic_cast(imageRequest->_attachmentPoint.get()); if (texture) { int attachmentIndex = imageRequest->_attachmentIndex > 0 ? imageRequest->_attachmentIndex : 0; texture->setImage(attachmentIndex, imageRequest->_loadedImage.get()); } else { OSG_NOTICE<<"ImagePager::updateSceneGraph() : error, image request attachment type not handled yet."<_requestList.clear(); } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/SharedStateManager.cpp0000644000175000017500000002527112162023637025227 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include using namespace osgDB; SharedStateManager::SharedStateManager(unsigned int mode): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { setShareMode(mode); _mutex=0; } void SharedStateManager::setShareMode(unsigned int mode) { _shareMode = mode; _shareTexture[osg::Object::DYNAMIC] = (_shareMode & SHARE_DYNAMIC_TEXTURES)!=0; _shareTexture[osg::Object::STATIC] = (_shareMode & SHARE_STATIC_TEXTURES)!=0; _shareTexture[osg::Object::UNSPECIFIED] = (_shareMode & SHARE_UNSPECIFIED_TEXTURES)!=0; _shareStateSet[osg::Object::DYNAMIC] = (_shareMode & SHARE_DYNAMIC_STATESETS)!=0; _shareStateSet[osg::Object::STATIC] = (_shareMode & SHARE_STATIC_STATESETS)!=0; _shareStateSet[osg::Object::UNSPECIFIED] = (_shareMode & SHARE_UNSPECIFIED_STATESETS)!=0; } //---------------------------------------------------------------- // SharedStateManager::prune //---------------------------------------------------------------- void SharedStateManager::prune() { StateSetSet::iterator sitr; OpenThreads::ScopedLock lock(_listMutex); for(sitr=_sharedStateSetList.begin(); sitr!=_sharedStateSetList.end();) { if ((*sitr)->referenceCount()<=1) _sharedStateSetList.erase(sitr++); else ++sitr; } TextureSet::iterator titr; for(titr=_sharedTextureList.begin(); titr!=_sharedTextureList.end();) { if ((*titr)->referenceCount()<=1) _sharedTextureList.erase(titr++); else ++titr; } } //---------------------------------------------------------------- // SharedStateManager::share //---------------------------------------------------------------- void SharedStateManager::share(osg::Node *node, OpenThreads::Mutex *mt) { // const osg::Timer& timer = *osg::Timer::instance(); // osg::Timer_t start_tick = timer.tick(); _mutex = mt; node->accept(*this); tmpSharedTextureList.clear(); tmpSharedStateSetList.clear(); _mutex = 0; // osg::Timer_t end_tick = timer.tick(); // std::cout << "SHARING TIME = "< #include #include namespace osgDB { #ifdef OSG_USE_UTF8_FILENAME #define OSGDB_CONVERT_UTF8_FILENAME(s) convertUTF8toUTF16(s).c_str() #else #define OSGDB_CONVERT_UTF8_FILENAME(s) s #endif void open(std::fstream &fs, const char* filename,std::ios_base::openmode mode) { fs.open(OSGDB_CONVERT_UTF8_FILENAME(filename), mode); } ifstream::ifstream(){} ifstream::ifstream(const char* filename, std::ios_base::openmode mode) : std::ifstream(OSGDB_CONVERT_UTF8_FILENAME(filename), mode) {} ifstream::~ifstream(){} void ifstream::open(const char* filename, std::ios_base::openmode mode) { std::ifstream::open(OSGDB_CONVERT_UTF8_FILENAME(filename), mode); } ofstream::ofstream(){} ofstream::ofstream(const char* filename, std::ios_base::openmode mode) : std::ofstream(OSGDB_CONVERT_UTF8_FILENAME(filename), mode) {} ofstream::~ofstream(){} void ofstream::open(const char* filename, std::ios_base::openmode mode) { std::ofstream::open(OSGDB_CONVERT_UTF8_FILENAME(filename), mode); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/FileCache.cpp0000644000175000017500000004460012021334765023326 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include using namespace osgDB; //////////////////////////////////////////////////////////////////////////////////////////// // // FileCache // FileCache::FileCache(const std::string& path): osg::Referenced(true), _fileCachePath(path) { OSG_INFO<<"Constructed FileCache : "<readObject(cacheFileName, options); } else { return 0; } } ReaderWriter::WriteResult FileCache::writeObject(const osg::Object& object, const std::string& originalFileName, const osgDB::Options* options) const { std::string cacheFileName = createCacheFileName(originalFileName); if (!cacheFileName.empty()) { std::string path = osgDB::getFilePath(cacheFileName); if (!osgDB::fileExists(path) && !osgDB::makeDirectory(path)) { OSG_NOTICE<<"Could not create cache directory: "<writeObject(object, cacheFileName, options); if (result.success()) { removeFileFromBlackListed(originalFileName); } return result; } return ReaderWriter::WriteResult::FILE_NOT_HANDLED; } ReaderWriter::ReadResult FileCache::readImage(const std::string& originalFileName, const osgDB::Options* options) const { std::string cacheFileName = createCacheFileName(originalFileName); if (!cacheFileName.empty() && osgDB::fileExists(cacheFileName)) { OSG_INFO<<"FileCache::readImageFromCache("<readImage(cacheFileName, options); } else { return 0; } } ReaderWriter::WriteResult FileCache::writeImage(const osg::Image& image, const std::string& originalFileName, const osgDB::Options* options) const { std::string cacheFileName = createCacheFileName(originalFileName); if (!cacheFileName.empty()) { std::string path = osgDB::getFilePath(cacheFileName); if (!osgDB::fileExists(path) && !osgDB::makeDirectory(path)) { OSG_NOTICE<<"Could not create cache directory: "<writeImage(image, cacheFileName, options); if (result.success()) { removeFileFromBlackListed(originalFileName); } return result; } return ReaderWriter::WriteResult::FILE_NOT_HANDLED; } ReaderWriter::ReadResult FileCache::readHeightField(const std::string& originalFileName, const osgDB::Options* options) const { std::string cacheFileName = createCacheFileName(originalFileName); if (!cacheFileName.empty() && osgDB::fileExists(cacheFileName)) { OSG_INFO<<"FileCache::readHeightFieldFromCache("<readHeightField(cacheFileName, options); } else { return 0; } } ReaderWriter::WriteResult FileCache::writeHeightField(const osg::HeightField& hf, const std::string& originalFileName, const osgDB::Options* options) const { std::string cacheFileName = createCacheFileName(originalFileName); if (!cacheFileName.empty()) { std::string path = osgDB::getFilePath(cacheFileName); if (!osgDB::fileExists(path) && !osgDB::makeDirectory(path)) { OSG_NOTICE<<"Could not create cache directory: "<writeHeightField(hf, cacheFileName, options); if (result.success()) { removeFileFromBlackListed(originalFileName); } return result; } return ReaderWriter::WriteResult::FILE_NOT_HANDLED; } ReaderWriter::ReadResult FileCache::readNode(const std::string& originalFileName, const osgDB::Options* options, bool buildKdTreeIfRequired) const { std::string cacheFileName = createCacheFileName(originalFileName); if (!cacheFileName.empty() && osgDB::fileExists(cacheFileName)) { OSG_INFO<<"FileCache::readNodeFromCache("<readNode(cacheFileName, options, buildKdTreeIfRequired); } else { return 0; } } ReaderWriter::WriteResult FileCache::writeNode(const osg::Node& node, const std::string& originalFileName, const osgDB::Options* options) const { std::string cacheFileName = createCacheFileName(originalFileName); if (!cacheFileName.empty()) { std::string path = osgDB::getFilePath(cacheFileName); if (!osgDB::fileExists(path) && !osgDB::makeDirectory(path)) { OSG_NOTICE<<"Could not create cache directory: "<writeNode(node, cacheFileName, options); if (result.success()) { removeFileFromBlackListed(originalFileName); } return result; } return ReaderWriter::WriteResult::FILE_NOT_HANDLED; } ReaderWriter::ReadResult FileCache::readShader(const std::string& originalFileName, const osgDB::Options* options) const { std::string cacheFileName = createCacheFileName(originalFileName); if (!cacheFileName.empty() && osgDB::fileExists(cacheFileName)) { OSG_INFO<<"FileCache::readShaderFromCache("<readShader(cacheFileName, options); } else { return 0; } } ReaderWriter::WriteResult FileCache::writeShader(const osg::Shader& shader, const std::string& originalFileName, const osgDB::Options* options) const { std::string cacheFileName = createCacheFileName(originalFileName); if (!cacheFileName.empty()) { std::string path = osgDB::getFilePath(cacheFileName); if (!osgDB::fileExists(path) && !osgDB::makeDirectory(path)) { OSG_NOTICE<<"Could not create cache directory: "<writeShader(shader, cacheFileName, options); if (result.success()) { removeFileFromBlackListed(originalFileName); } return result; } return ReaderWriter::WriteResult::FILE_NOT_HANDLED; } bool FileCache::isCachedFileBlackListed(const std::string& originalFileName) const { for(DatabaseRevisionsList::const_iterator itr = _databaseRevisionsList.begin(); itr != _databaseRevisionsList.end(); ++itr) { if ((*itr)->isFileBlackListed(originalFileName)) return true; } return false; } bool FileCache::removeFileFromBlackListed(const std::string& originalFileName) const { for(DatabaseRevisionsList::const_iterator dr_itr = _databaseRevisionsList.begin(); dr_itr != _databaseRevisionsList.end(); ++dr_itr) { DatabaseRevisions* dr = dr_itr->get(); if (dr->getDatabasePath().length()>=originalFileName.length()) continue; if (originalFileName.compare(0,dr->getDatabasePath().length(), dr->getDatabasePath())!=0) continue; std::string localPath(originalFileName, dr->getDatabasePath().empty() ? 0 : dr->getDatabasePath().length()+1, std::string::npos); for(DatabaseRevisions::DatabaseRevisionList::const_iterator itr = dr->getDatabaseRevisionList().begin(); itr != dr->getDatabaseRevisionList().end(); ++itr) { DatabaseRevision* revision = const_cast(itr->get()); if (revision->getFilesAdded() && revision->getFilesAdded()->removeFile(localPath)) { std::string cacheFileName = revision->getFilesAdded()->getName(); if (containsServerAddress(cacheFileName)) cacheFileName = createCacheFileName(cacheFileName); if (!cacheFileName.empty()) writeObjectFile(*(revision->getFilesAdded()), cacheFileName); } if (revision->getFilesRemoved() && revision->getFilesRemoved()->removeFile(localPath)) { std::string cacheFileName = revision->getFilesRemoved()->getName(); if (containsServerAddress(cacheFileName)) cacheFileName = createCacheFileName(cacheFileName); if (!cacheFileName.empty()) writeObjectFile(*(revision->getFilesRemoved()), cacheFileName); } if (revision->getFilesModified() && revision->getFilesModified()->removeFile(localPath)) { std::string cacheFileName = revision->getFilesModified()->getName(); if (containsServerAddress(cacheFileName)) cacheFileName = createCacheFileName(cacheFileName); if (!cacheFileName.empty()) writeObjectFile(*(revision->getFilesModified()), cacheFileName); } } } return false; } bool FileCache::loadDatabaseRevisionsForFile(const std::string& originalFileName) { OSG_INFO<<"FileCache::loadDatabaseRevisionsForFile("< dr_local; std::string cacheFileName = createCacheFileName(revisionsFileName); // check to see if revion file is already loaded. DatabaseRevisionsList::iterator ritr = _databaseRevisionsList.begin(); for(; ritr != _databaseRevisionsList.end() && !dr_local; ++ritr) { OSG_INFO<<" comparing "<<(*ritr)->getName()<<" to "<getName()==revisionsFileName) { OSG_INFO<<"Already loaded"< object = osgDB::readObjectFile(cacheFileName); dr_local = dynamic_cast(object.get()); if (dr_local) { OSG_INFO<<" loaded local revisions File("< object = osgDB::readObjectFile(revisionsFileName+".curl"); osg::ref_ptr dr_remote = dynamic_cast(object.get()); if (dr_remote.valid()) { bool needToWriteRevisionsFileToDisk = true; if (dr_local.valid()) { if (dr_local->getDatabaseRevisionList().size()==dr_remote->getDatabaseRevisionList().size()) { unsigned int i; for(i=0; igetDatabaseRevisionList().size(); ++i) { DatabaseRevision* revision_local = dr_local->getDatabaseRevision(i); DatabaseRevision* revision_remote = dr_remote->getDatabaseRevision(i); OSG_INFO<<" Comparing local "<getName()<<" to remote "<getName()<getName()!=revision_remote->getName()) break; } needToWriteRevisionsFileToDisk = (i!=dr_local->getDatabaseRevisionList().size()); OSG_INFO<<"Local and remote revisions are different "< dr = dr_remote.valid() ? dr_remote : dr_local; if (dr.valid()) { OSG_INFO<<" loaded remote revisions File("<getName()<getDatabaseRevisionList().begin(); itr != dr->getDatabaseRevisionList().end(); ++itr) { DatabaseRevision* revision = itr->get(); OSG_INFO<<" now loaded DatabaseRevisions "<getName()<<" FileList contents"<getFilesAdded()) { FileList* fileList = readFileList(osgDB::concatPaths(revision->getDatabasePath(), revision->getFilesAdded()->getName())); if (fileList) { revision->setFilesAdded(fileList); } } if (revision->getFilesRemoved()) { FileList* fileList = readFileList(osgDB::concatPaths(revision->getDatabasePath(), revision->getFilesRemoved()->getName())); if (fileList) { revision->setFilesRemoved(fileList); } } if (revision->getFilesModified()) { FileList* fileList = readFileList(osgDB::concatPaths(revision->getDatabasePath(), revision->getFilesModified()->getName())); if (fileList) { revision->setFilesModified(fileList); } } } return true; } else { OSG_NOTICE<<" failed to read revisions File, object.get()="< fileList; std::string cacheFileListName = createCacheFileName(originalFileName); if (!cacheFileListName.empty() && osgDB::fileExists(cacheFileListName)) { osg::ref_ptr object = osgDB::readObjectFile(cacheFileListName); fileList = dynamic_cast(object.get()); if (fileList) OSG_INFO<<" loadeded FileList from local cache "<getName()<(object.get()); if (fileList) { OSG_INFO<<" loadeded FileList from remote system "<getName()<getName()< #include #include #include #include namespace osgDB { /// Counts the number of directories the given relative path goes "up" the current dir, or 0 if not. /// This returns 0 for absolute paths. /// Examples: /// - "../a" goes 1 level up /// - "../../a/b/c/d/e" goes 2 /// - "../a/../b/../.." goes 2 /// - "a/b/../c" goes 0 static unsigned int countNbDirsUp(const std::string & path) { // Algorithm: // - For each path component, count +1 for "..", 0 for ".", and -1 for anything else // - Ignore everything after the last ".." of the path. if (isAbsolutePath(path)) return 0; int result(0), tempResult(0); std::vector pathElems; getPathElements(path, pathElems); for(std::vector::const_iterator it(pathElems.begin()), itEnd(pathElems.end()); it!=itEnd; ++it) { if (*it == "..") { // Count +1, and "validates" temporary result ++tempResult; result = tempResult; } else if (*it != ".") --tempResult; } return result<=0 ? 0 : static_cast(result); } /// Local hash function for a path. /// Does not canonize the given path, but is not confused with mixed separators. static unsigned int pathHash(const std::string & s) { // This is based on the DJB hash algorithm // Note: SDBM Hash initializes at 0 and is // hash = c + (hash << 6) + (hash << 16) - hash; unsigned int hash = 5381; for(std::string::const_iterator it=s.begin(), itEnd=s.end(); it!=itEnd; ++it) { std::string::value_type c = *it; if (c == '\\') c = '/'; // We're processing a path and don't want to be affected by differences in separators hash = ((hash << 5) + hash) + c; } return hash; } //virtual ReaderWriter::WriteResult writeObject(const osg::Object& obj, const std::string& fileName,const Options* options); //virtual ReaderWriter::WriteResult writeImage(const osg::Image& obj, const std::string& fileName,const Options* options); //virtual ReaderWriter::WriteResult writeHeightField(const osg::HeightField& obj, const std::string& fileName,const Options* options); //virtual ReaderWriter::WriteResult writeNode(const osg::Node& obj, const std::string& fileName,const Options* options); //virtual ReaderWriter::WriteResult writeShader(const osg::Shader& obj, const std::string& fileName,const Options* options); enum WriteType { WRITE_TYPE_OBJECT, WRITE_TYPE_IMAGE, WRITE_TYPE_HEIGHT_FIELD, WRITE_TYPE_NODE, WRITE_TYPE_SHADER, MAX_WRITE_TYPE }; /// Default prefixes for unnamed objects. static const char * const FILE_PREFIX[/*MAX_WRITE_TYPE*/] = { "Object_", "Image_", "HF_", "Node_", "Shader_" }; /// Default prefixes for unnamed objects. static const char * const FILE_EXTENSION[/*MAX_WRITE_TYPE*/] = { ".osgb", ".tga", ".osgb", ".osgb", ".glsl" }; //.frag //.vert inline WriteType getType(const osg::Object & obj) { // Is there something faster than a dynamic_cast<>? if (dynamic_cast(&obj)) return WRITE_TYPE_IMAGE; if (dynamic_cast(&obj)) return WRITE_TYPE_HEIGHT_FIELD; if (dynamic_cast(&obj)) return WRITE_TYPE_NODE; if (dynamic_cast(&obj)) return WRITE_TYPE_SHADER; return WRITE_TYPE_OBJECT; } /// Returns the object filename if available, or its name otherwise. inline const std::string & getFileName(const osg::Object & obj, WriteType type) { switch(type) { case WRITE_TYPE_IMAGE: return static_cast(obj).getFileName(); case WRITE_TYPE_SHADER: return static_cast(obj).getFileName(); default: // WRITE_TYPE_OBJECT, WRITE_TYPE_NODE, WRITE_TYPE_HEIGHT_FIELD return obj.getName(); } } inline bool doWrite(const osg::Object & obj, WriteType type, const std::string& fileName, const Options * options) { switch(type) { case WRITE_TYPE_IMAGE: return writeImageFile (static_cast(obj), fileName, options); case WRITE_TYPE_HEIGHT_FIELD: return writeHeightFieldFile(static_cast(obj), fileName, options); case WRITE_TYPE_NODE: return writeNodeFile (static_cast(obj), fileName, options); case WRITE_TYPE_SHADER: return writeShaderFile (static_cast(obj), fileName, options); // WRITE_TYPE_OBJECT default: return writeObjectFile(obj, fileName, options); } } // -------------------------------------------------------------------------------- ExternalFileWriter::ExternalFileWriter(const std::string & srcDirectory, const std::string & destDirectory, bool keepRelativePaths, unsigned int allowUpDirs) : _lastGeneratedObjectIndex(0), _srcDirectory(srcDirectory), _destDirectory(destDirectory), _keepRelativePaths(keepRelativePaths), _allowUpDirs(allowUpDirs) {} ExternalFileWriter::ExternalFileWriter(const std::string & destDirectory) : _lastGeneratedObjectIndex(0), _destDirectory(destDirectory), _keepRelativePaths(false), _allowUpDirs(0) {} bool ExternalFileWriter::write(const osg::Object & obj, const Options * options, std::string * out_absolutePath, std::string * out_relativePath) { ObjectsSet::iterator it( _objects.find(&obj) ); if (it != _objects.end()) { // Object has already been passed to this method if (out_absolutePath) *out_absolutePath = it->second.absolutePath; if (out_relativePath) *out_relativePath = it->second.relativePath; return it->second.written; } // Object is a new entry // Get absolute source path WriteType type( getType(obj) ); std::string originalFileName( getFileName(obj, type) ); std::string absoluteSourcePath; if (_keepRelativePaths && !originalFileName.empty()) // if keepRelativePaths is false, absoluteSourcePath is not used, then we can skip this part { if (isAbsolutePath(originalFileName)) absoluteSourcePath = originalFileName; else absoluteSourcePath = concatPaths(_srcDirectory, originalFileName); absoluteSourcePath = getRealPath(convertFileNameToNativeStyle(absoluteSourcePath)); // getRealPath() here is only used to canonize the path, not to add current directory in front of relative paths, hence the "concatPaths(_srcDirectory, ...)" just above } // Compute destination paths from the source path std::string relativeDestinationPath; std::string absoluteDestinationPath; if (absoluteSourcePath.empty()) { // We have no name. Generate one. generateObjectName(relativeDestinationPath, absoluteDestinationPath, type); } else { // We have a name. if (_keepRelativePaths) { // We'll try to keep images relative path. relativeDestinationPath = getPathRelative(_srcDirectory, absoluteSourcePath); unsigned int nbDirsUp = countNbDirsUp(relativeDestinationPath); // TODO if nbDirsUp>nb dirs in _destDirectory, then issue a warning, and use simple file name if (nbDirsUp > _allowUpDirs) relativeDestinationPath = getSimpleFileName(absoluteSourcePath); } else { // We keep only the simple file name. relativeDestinationPath = getSimpleFileName(absoluteSourcePath); } absoluteDestinationPath = getRealPath(convertFileNameToNativeStyle( concatPaths(_destDirectory, relativeDestinationPath) )); // TODO Check for absolute paths collisions between multiple objects } // Write object bool written(false); if (!makeDirectoryForFile(absoluteDestinationPath)) { OSG_NOTICE << "Can't create directory for file '" << absoluteDestinationPath << "'. May fail creating the image file." << std::endl; } if (!doWrite(obj, type, absoluteDestinationPath, options)) { OSG_WARN << "Can't write file '" << absoluteDestinationPath << "'." << std::endl; } else written = true; // Add entry _objects.insert(ObjectsSet::value_type(&obj, ObjectData(absoluteDestinationPath, relativeDestinationPath, written))); _searchMap.insert(SearchMap::value_type(pathHash(absoluteDestinationPath), &obj)); // Fill output strings if (out_absolutePath) *out_absolutePath = absoluteDestinationPath; if (out_relativePath) *out_relativePath = relativeDestinationPath; return written; } bool ExternalFileWriter::absoluteObjectPathExists(const std::string & path) { // For all paths in the search map having the same hash as 'path', check if paths correspond std::pair bounds( _searchMap.equal_range(pathHash(path)) ); for(SearchMap::iterator it=bounds.first; it!=bounds.second; ++it) { const osg::Object * img( it->second ); if (_objects[img].absolutePath == path) return true; } return false; } void ExternalFileWriter::generateObjectName(std::string & out_relativePath, std::string & out_absolutePath, int type) { static const ObjectIndex MAX_NUMBER = UINT_MAX-1; // -1 to allow doing +1 without an overflow for (ObjectIndex number=_lastGeneratedObjectIndex+1; number #include #include #include #include using namespace osgDB; // Example compressor copying data to/from stream directly class NullCompressor : public BaseCompressor { public: NullCompressor() {} virtual bool compress( std::ostream& fout, const std::string& src ) { int size = src.size(); fout.write( (char*)&size, INT_SIZE ); fout.write( src.c_str(), src.size() ); return true; } virtual bool decompress( std::istream& fin, std::string& target ) { int size = 0; fin.read( (char*)&size, INT_SIZE ); if ( size ) { target.resize( size ); fin.read( (char*)target.c_str(), size ); } return true; } }; REGISTER_COMPRESSOR( "null", NullCompressor ) #ifdef USE_ZLIB #include #define CHUNK 32768 // ZLib compressor class ZLibCompressor : public BaseCompressor { public: ZLibCompressor() {} virtual bool compress( std::ostream& fout, const std::string& src ) { int ret, flush = Z_FINISH; unsigned have; z_stream strm; unsigned char out[CHUNK]; int level = 6; int stategy = Z_DEFAULT_STRATEGY; /* allocate deflate state */ strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; ret = deflateInit2( &strm, level, Z_DEFLATED, 15+16, // +16 to use gzip encoding 8, // default stategy ); if ( ret != Z_OK ) return false; strm.avail_in = src.size(); strm.next_in = (Bytef*)( &(*src.begin()) ); /* run deflate() on input until output buffer not full, finish compression if all of source has been read in */ do { strm.avail_out = CHUNK; strm.next_out = out; ret = deflate(&strm, flush); /* no bad return value */ if ( ret == Z_STREAM_ERROR ) { OSG_NOTICE << "Z_STREAM_ERROR" << std::endl; return false; } have = CHUNK - strm.avail_out; if ( have>0 ) fout.write( (const char*)out, have ); if ( fout.fail() ) { (void)deflateEnd( &strm ); return false; } } while ( strm.avail_out==0 ); /* clean up and return */ (void)deflateEnd( &strm ); return true; } virtual bool decompress( std::istream& fin, std::string& target ) { int ret; unsigned have; z_stream strm; unsigned char in[CHUNK]; unsigned char out[CHUNK]; /* allocate inflate state */ strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = 0; strm.next_in = Z_NULL; ret = inflateInit2( &strm, 15 + 32 ); // autodected zlib or gzip header if ( ret!=Z_OK ) { OSG_INFO << "failed to init" << std::endl; return ret!=0; } /* decompress until deflate stream ends or end of file */ do { fin.read( (char *)in, CHUNK ); strm.avail_in = fin.gcount(); if (strm.avail_in==0 ) break; /* run inflate() on input until output buffer not full */ strm.next_in = in; do { strm.avail_out = CHUNK; strm.next_out = out; ret = inflate( &strm, Z_NO_FLUSH ); switch (ret) { case Z_NEED_DICT: case Z_DATA_ERROR: case Z_MEM_ERROR: (void)inflateEnd( &strm ); return false; } have = CHUNK - strm.avail_out; target.append( (char*)out, have ); } while ( strm.avail_out==0 ); /* done when inflate() says it's done */ } while ( ret!=Z_STREAM_END ); /* clean up and return */ (void)inflateEnd( &strm ); return ret==Z_STREAM_END ? true : false; } }; REGISTER_COMPRESSOR( "zlib", ZLibCompressor ) #endif openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/OutputStream.cpp0000644000175000017500000007110012212055634024167 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ // Written by Wang Rui, (C) 2010 #include #include #include #include #include #include #include #include using namespace osgDB; OutputStream::OutputStream( const osgDB::Options* options ) : _writeImageHint(WRITE_USE_IMAGE_HINT), _useSchemaData(false), _useRobustBinaryFormat(true) { BEGIN_BRACKET.set( "{", +INDENT_VALUE ); END_BRACKET.set( "}", -INDENT_VALUE ); if ( !options ) return; _options = options; if ( options->getPluginStringData("RobustBinaryFormat")=="false" ) _useRobustBinaryFormat = false; if ( options->getPluginStringData("SchemaData")=="true" ) _useSchemaData = true; if ( !options->getPluginStringData("SchemaFile").empty() ) _schemaName = options->getPluginStringData("SchemaFile"); if ( !options->getPluginStringData("Compressor").empty() ) _compressorName = options->getPluginStringData("Compressor"); if ( !options->getPluginStringData("WriteImageHint").empty() ) { std::string hintString = options->getPluginStringData("WriteImageHint"); if ( hintString=="IncludeData" ) _writeImageHint = WRITE_INLINE_DATA; else if ( hintString=="IncludeFile" ) _writeImageHint = WRITE_INLINE_FILE; else if ( hintString=="UseExternal" ) _writeImageHint = WRITE_USE_EXTERNAL; else if ( hintString=="WriteOut" ) _writeImageHint = WRITE_EXTERNAL_FILE; } if ( !options->getPluginStringData("CustomDomains").empty() ) { StringList domains, keyAndValue; split( options->getPluginStringData("CustomDomains"), domains, ';' ); for ( unsigned int i=0; i1 ) _domainVersionMap[keyAndValue.front()] = atoi(keyAndValue.back().c_str()); } } } OutputStream::~OutputStream() { } int OutputStream::getFileVersion( const std::string& d ) const { if ( d.empty() ) return OPENSCENEGRAPH_SOVERSION; VersionMap::const_iterator itr = _domainVersionMap.find(d); return itr==_domainVersionMap.end() ? 0 : itr->second; } OutputStream& OutputStream::operator<<( const osg::Vec2b& v ) { *this << v.x() << v.y(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec3b& v ) { *this << v.x() << v.y() << v.z(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec4b& v ) { *this << v.x() << v.y() << v.z() << v.w(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec2ub& v ) { *this << v.x() << v.y(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec3ub& v ) { *this << v.x() << v.y() << v.z(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec4ub& v ) { *this << v.r() << v.g() << v.b() << v.a(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec2s& v ) { *this << v.x() << v.y(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec3s& v ) { *this << v.x() << v.y() << v.z(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec4s& v ) { *this << v.x() << v.y() << v.z() << v.w(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec2us& v ) { *this << v.x() << v.y(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec3us& v ) { *this << v.x() << v.y() << v.z(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec4us& v ) { *this << v.x() << v.y() << v.z() << v.w(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec2f& v ) { *this << v.x() << v.y(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec3f& v ) { *this << v.x() << v.y() << v.z(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec4f& v ) { *this << v.x() << v.y() << v.z() << v.w(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec2d& v ) { *this << v.x() << v.y(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec3d& v ) { *this << v.x() << v.y() << v.z(); return *this; } OutputStream& OutputStream::operator<<( const osg::Vec4d& v ) { *this << v.x() << v.y() << v.z() << v.w(); return *this; } OutputStream& OutputStream::operator<<( const osg::Quat& q ) { *this << q.x() << q.y() << q.z() << q.w(); return *this; } OutputStream& OutputStream::operator<<( const osg::Plane& p ) { *this << (double)p[0] << (double)p[1] << (double)p[2] << (double)p[3]; return *this; } #if 0 OutputStream& OutputStream::operator<<( const osg::Matrixf& mat ) { *this << PROPERTY("Matrixf")<getType() ) { case osg::Array::ByteArrayType: *this << MAPPEE(ArrayType, ID_BYTE_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements(), 4 ); break; case osg::Array::UByteArrayType: *this << MAPPEE(ArrayType, ID_UBYTE_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements(), 4 ); break; case osg::Array::ShortArrayType: *this << MAPPEE(ArrayType, ID_SHORT_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements(), 4 ); break; case osg::Array::UShortArrayType: *this << MAPPEE(ArrayType, ID_USHORT_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements(), 4 ); break; case osg::Array::IntArrayType: *this << MAPPEE(ArrayType, ID_INT_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements(), 4 ); break; case osg::Array::UIntArrayType: *this << MAPPEE(ArrayType, ID_UINT_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements(), 4 ); break; case osg::Array::FloatArrayType: *this << MAPPEE(ArrayType, ID_FLOAT_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements(), 4 ); break; case osg::Array::DoubleArrayType: *this << MAPPEE(ArrayType, ID_DOUBLE_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements(), 4 ); break; case osg::Array::Vec2bArrayType: *this << MAPPEE(ArrayType, ID_VEC2B_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec3bArrayType: *this << MAPPEE(ArrayType, ID_VEC3B_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec4bArrayType: *this << MAPPEE(ArrayType, ID_VEC4B_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec2ubArrayType: *this << MAPPEE(ArrayType, ID_VEC2UB_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec3ubArrayType: *this << MAPPEE(ArrayType, ID_VEC3UB_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec4ubArrayType: *this << MAPPEE(ArrayType, ID_VEC4UB_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec2sArrayType: *this << MAPPEE(ArrayType, ID_VEC2S_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec3sArrayType: *this << MAPPEE(ArrayType, ID_VEC3S_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec4sArrayType: *this << MAPPEE(ArrayType, ID_VEC4S_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec2usArrayType: *this << MAPPEE(ArrayType, ID_VEC2US_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec3usArrayType: *this << MAPPEE(ArrayType, ID_VEC3US_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec4usArrayType: *this << MAPPEE(ArrayType, ID_VEC4US_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec2ArrayType: *this << MAPPEE(ArrayType, ID_VEC2_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec3ArrayType: *this << MAPPEE(ArrayType, ID_VEC3_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec4ArrayType: *this << MAPPEE(ArrayType, ID_VEC4_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec2dArrayType: *this << MAPPEE(ArrayType, ID_VEC2D_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec3dArrayType: *this << MAPPEE(ArrayType, ID_VEC3D_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; case osg::Array::Vec4dArrayType: *this << MAPPEE(ArrayType, ID_VEC4D_ARRAY); writeArrayImplementation( static_cast(a), a->getNumElements() ); break; default: throwException( "OutputStream::writeArray(): Unsupported array type." ); } } void OutputStream::writePrimitiveSet( const osg::PrimitiveSet* p ) { if ( !p ) return; switch ( p->getType() ) { case osg::PrimitiveSet::DrawArraysPrimitiveType: *this << MAPPEE(PrimitiveType, ID_DRAWARRAYS); { const osg::DrawArrays* da = static_cast(p); *this << MAPPEE(PrimitiveType, da->getMode()) << da->getNumInstances() << da->getFirst() << da->getCount() << std::endl; } break; case osg::PrimitiveSet::DrawArrayLengthsPrimitiveType: *this << MAPPEE(PrimitiveType, ID_DRAWARRAY_LENGTH); { const osg::DrawArrayLengths* dl = static_cast(p); *this << MAPPEE(PrimitiveType, dl->getMode()) << dl->getNumInstances() << dl->getFirst(); writeArrayImplementation( dl, dl->size(), 4 ); } break; case osg::PrimitiveSet::DrawElementsUBytePrimitiveType: *this << MAPPEE(PrimitiveType, ID_DRAWELEMENTS_UBYTE); { const osg::DrawElementsUByte* de = static_cast(p); *this << MAPPEE(PrimitiveType, de->getMode()) << de->getNumInstances(); writeArrayImplementation( de, de->size(), 4 ); } break; case osg::PrimitiveSet::DrawElementsUShortPrimitiveType: *this << MAPPEE(PrimitiveType, ID_DRAWELEMENTS_USHORT); { const osg::DrawElementsUShort* de = static_cast(p); *this << MAPPEE(PrimitiveType, de->getMode()) << de->getNumInstances(); writeArrayImplementation( de, de->size(), 4 ); } break; case osg::PrimitiveSet::DrawElementsUIntPrimitiveType: *this << MAPPEE(PrimitiveType, ID_DRAWELEMENTS_UINT); { const osg::DrawElementsUInt* de = static_cast(p); *this << MAPPEE(PrimitiveType, de->getMode()) << de->getNumInstances(); writeArrayImplementation( de, de->size(), 4 ); } break; default: throwException( "OutputStream::writePrimitiveSet(): Unsupported primitive type." ); } } void OutputStream::writeImage( const osg::Image* img ) { if ( !img ) return; std::string name = img->libraryName(); name += std::string("::") + img->className(); bool newID = false; unsigned int id = findOrCreateObjectID( img, newID ); *this << PROPERTY("ClassName") << name << std::endl; // Write object name *this << PROPERTY("UniqueID") << id << std::endl; // Write image ID if ( getException() ) return; if (newID) { int decision = IMAGE_EXTERNAL; switch ( _writeImageHint ) { case OutputStream::WRITE_INLINE_DATA: decision = IMAGE_INLINE_DATA; break; case OutputStream::WRITE_INLINE_FILE: decision = IMAGE_INLINE_FILE; break; case OutputStream::WRITE_EXTERNAL_FILE: decision = IMAGE_WRITE_OUT; break; case OutputStream::WRITE_USE_EXTERNAL: decision = IMAGE_EXTERNAL; break; default: if ( img->getWriteHint()==osg::Image::EXTERNAL_FILE ) decision = IMAGE_EXTERNAL; else if ( isBinary() ) decision = IMAGE_INLINE_DATA; break; } std::string imageFileName = img->getFileName(); if ( decision==IMAGE_WRITE_OUT || _writeImageHint==WRITE_EXTERNAL_FILE ) { if (imageFileName.empty()) { OSG_NOTICE<<"Empty Image::FileName resetting to image.dds"<getFileName() << std::endl; } } *this << PROPERTY("FileName"); writeWrappedString(imageFileName); *this << std::endl; *this << PROPERTY("WriteHint") << (int)img->getWriteHint(); if ( getException() ) return; *this << decision << std::endl; switch ( decision ) { case IMAGE_INLINE_DATA: if ( isBinary() ) { *this << img->getOrigin(); // _origin *this << img->s() << img->t() << img->r(); // _s & _t & _r *this << img->getInternalTextureFormat(); // _internalTextureFormat *this << img->getPixelFormat(); // _pixelFormat *this << img->getDataType(); // _dataType *this << img->getPacking(); // _packing *this << img->getAllocationMode(); // _allocationMode // _data unsigned int size = img->getTotalSizeInBytesIncludingMipmaps(); writeSize(size); for(osg::Image::DataIterator img_itr(img); img_itr.valid(); ++img_itr) { writeCharArray( (char*)img_itr.data(), img_itr.size() ); } // _mipmapData unsigned int numMipmaps = img->getNumMipmapLevels()-1; writeSize(numMipmaps); int s = img->s(); int t = img->t(); int r = img->r(); unsigned int offset = 0; for (unsigned int i=0; igetPixelFormat(),img->getDataType(),img->getPacking()); offset += size; *this << offset; s >>= 1; t >>= 1; r >>= 1; if (s<1) s=1; if (t<1) t=1; if (r<1) r=1; } } break; case IMAGE_INLINE_FILE: if ( isBinary() ) { std::string fullPath = osgDB::findDataFile( img->getFileName() ); std::ifstream infile( fullPath.c_str(), std::ios::in|std::ios::binary ); if ( infile ) { infile.seekg( 0, std::ios::end ); unsigned int size = infile.tellg(); writeSize(size); if ( size>0 ) { char* data = new char[size]; if ( !data ) { throwException( "OutputStream::writeImage(): Out of memory." ); if ( getException() ) return; } infile.seekg( 0, std::ios::beg ); infile.read( data, size ); writeCharArray( data, size ); delete[] data; } infile.close(); } else { OSG_WARN << "OutputStream::writeImage(): Failed to open image file " << img->getFileName() << std::endl; *this << (unsigned int)0; } } break; case IMAGE_EXTERNAL: break; default: break; } writeObjectFields( img ); } // *this << END_BRACKET << std::endl; } void OutputStream::writeObject( const osg::Object* obj ) { if ( !obj ) return; std::string name = obj->libraryName(); name += std::string("::") + obj->className(); bool newID = false; unsigned int id = findOrCreateObjectID( obj, newID ); *this << name << BEGIN_BRACKET << std::endl; // Write object name *this << PROPERTY("UniqueID") << id << std::endl; // Write object ID if ( getException() ) return; if (newID) { writeObjectFields(obj); } *this << END_BRACKET << std::endl; } void OutputStream::writeObjectFields( const osg::Object* obj ) { std::string name = obj->libraryName(); name += std::string("::") + obj->className(); ObjectWrapper* wrapper = Registry::instance()->getObjectWrapperManager()->findWrapper( name ); if ( !wrapper ) { OSG_WARN << "OutputStream::writeObject(): Unsupported wrapper class " << name << std::endl; return; } const StringList& associates = wrapper->getAssociates(); for ( StringList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr ) { const std::string& assocName = *itr; ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName); if ( !assocWrapper ) { OSG_WARN << "OutputStream::writeObject(): Unsupported associated class " << assocName << std::endl; continue; } else if ( _useSchemaData ) { if ( _inbuiltSchemaMap.find(assocName)==_inbuiltSchemaMap.end() ) { StringList properties; std::vector types; assocWrapper->writeSchema( properties, types ); unsigned int size = osg::minimum( properties.size(), types.size() ); if ( size>0 ) { std::stringstream propertiesStream; for ( unsigned int i=0; igetName() ); assocWrapper->write( *this, *obj ); if ( getException() ) return; _fields.pop_back(); } } void OutputStream::start( OutputIterator* outIterator, OutputStream::WriteType type ) { _fields.clear(); _fields.push_back( "Start" ); _out = outIterator; if ( !_out ) throwException( "OutputStream: Null stream specified." ); if ( getException() ) return; if ( isBinary() ) { *this << (unsigned int)type << (unsigned int)OPENSCENEGRAPH_SOVERSION; bool useCompressSource = false; unsigned int attributes = 0; // From SOVERSION 98, start to support custom wrapper domains, enabling the attribute bit if ( _domainVersionMap.size()>0 ) attributes |= 0x1; if ( _useSchemaData ) { attributes |= 0x2; // Record if we use inbuilt schema data or not useCompressSource = true; } // From SOVERSION 98, start to support binary begin/end brackets so we can easily ignore // errors and unsupport classes, enabling the attribute bit if ( _useRobustBinaryFormat ) { outIterator->setSupportBinaryBrackets( true ); attributes |= 0x4; } *this << attributes; // Record all custom versions if ( _domainVersionMap.size()>0 ) { unsigned int numDomains = _domainVersionMap.size(); *this << numDomains; for ( VersionMap::iterator itr=_domainVersionMap.begin(); itr!=_domainVersionMap.end(); ++itr ) { *this << itr->first << itr->second; } } if ( !_compressorName.empty() ) { BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(_compressorName); if ( !compressor ) { OSG_WARN << "OutputStream::start(): No such compressor " << _compressorName << std::endl; _compressorName.clear(); } else { useCompressSource = true; } } if ( !_compressorName.empty() ) *this << _compressorName; else *this << std::string("0"); // No compressor // Compressors and inbuilt schema use a new stream, which will be merged with the original one at the end. if ( useCompressSource ) { _out->flush(); _out->setStream( &_compressSource ); } } else { std::string typeString("Unknown"); switch ( type ) { case WRITE_SCENE: typeString = "Scene"; break; case WRITE_IMAGE: typeString = "Image"; break; case WRITE_OBJECT: typeString = "Object"; break; default: break; } *this << typeString << std::endl; *this << PROPERTY("#Version") << (unsigned int)OPENSCENEGRAPH_SOVERSION << std::endl; *this << PROPERTY("#Generator") << std::string("OpenSceneGraph") << std::string(osgGetVersion()) << std::endl; if ( _domainVersionMap.size()>0 ) { for ( VersionMap::iterator itr=_domainVersionMap.begin(); itr!=_domainVersionMap.end(); ++itr ) { *this << PROPERTY("#CustomDomain") << itr->first << itr->second << std::endl; } } *this << std::endl; } _fields.pop_back(); } void OutputStream::compress( std::ostream* ostream ) { _fields.clear(); if ( !isBinary() ) return; std::stringstream schemaSource; if ( _useSchemaData ) { _fields.push_back( "SchemaData" ); std::string schemaData; for ( SchemaMap::iterator itr=_inbuiltSchemaMap.begin(); itr!=_inbuiltSchemaMap.end(); ++itr ) { schemaData += itr->first + '='; schemaData += itr->second; schemaData += '\n'; } int size = schemaData.size(); schemaSource.write( (char*)&size, INT_SIZE ); schemaSource.write( schemaData.c_str(), size ); _inbuiltSchemaMap.clear(); _fields.pop_back(); } if ( !_compressorName.empty() ) { _fields.push_back( "Compression" ); BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(_compressorName); if ( !compressor || !ostream ) { _fields.pop_back(); return; } if ( !compressor->compress(*ostream, schemaSource.str() + _compressSource.str()) ) throwException( "OutputStream: Failed to compress stream." ); if ( getException() ) return; _fields.pop_back(); } else if ( _useSchemaData ) { std::string str = schemaSource.str() + _compressSource.str(); ostream->write( str.c_str(), str.size() ); } } void OutputStream::writeSchema( std::ostream& fout ) { // Write to external ascii stream const ObjectWrapperManager::WrapperMap& wrappers = Registry::instance()->getObjectWrapperManager()->getWrapperMap(); for ( ObjectWrapperManager::WrapperMap::const_iterator itr=wrappers.begin(); itr!=wrappers.end(); ++itr ) { ObjectWrapper* wrapper = itr->second.get(); fout << itr->first << " ="; StringList properties; std::vector types; wrapper->writeSchema( properties, types ); std::string propertiesString; unsigned int size = osg::minimum( properties.size(), types.size() ); for ( unsigned int i=0; i void OutputStream::writeArrayImplementation( const T* a, int write_size, unsigned int numInRow ) { *this << write_size << BEGIN_BRACKET; if ( numInRow>1 ) { for ( int i=0; isecond; } unsigned int OutputStream::findOrCreateObjectID( const osg::Object* obj, bool& newID ) { ObjectMap::iterator itr = _objectMap.find( obj ); if ( itr==_objectMap.end() ) { unsigned int id = _objectMap.size()+1; _objectMap[obj] = id; newID = true; return id; } newID = false; return itr->second; } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/FieldReaderIterator.cpp0000644000175000017500000003447011732410624025404 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include using namespace osgDB; FieldReaderIterator::FieldReaderIterator() { _init(); } FieldReaderIterator::FieldReaderIterator(const FieldReaderIterator& ic) { _copy(ic); } FieldReaderIterator::~FieldReaderIterator() { _free(); } FieldReaderIterator& FieldReaderIterator::operator = (const FieldReaderIterator& ic) { if (this==&ic) return *this; _free(); _copy(ic); return *this; } void FieldReaderIterator::_free() { // free all data if (_previousField) { delete _previousField; } if (_fieldQueue) { for(int i=0;i<_fieldQueueCapacity;++i) { if (_fieldQueue[i]) delete _fieldQueue[i]; _fieldQueue[i] = NULL; } delete [] _fieldQueue; } _init(); } void FieldReaderIterator::_init() { _previousField = NULL; _fieldQueue = NULL; _fieldQueueSize = 0; _fieldQueueCapacity = 0; } void FieldReaderIterator::_copy(const FieldReaderIterator& ic) { _reader = ic._reader; if (ic._previousField) { _previousField = new Field(*ic._previousField); } if (ic._fieldQueue && ic._fieldQueueCapacity>0) { _fieldQueue = new Field* [ic._fieldQueueCapacity]; for(int i=0;i_fieldQueueSize) pos=_fieldQueueSize; int i; // need to reallocate the stack if (_fieldQueueSize>=_fieldQueueCapacity) { int newCapacity = _fieldQueueCapacity*2; if (newCapacity=newCapacity) newCapacity*=2; Field** newFieldStack = new Field* [newCapacity]; for(i=0;i<_fieldQueueCapacity;++i) { newFieldStack[i] = _fieldQueue[i]; } for(;i=pos;++i) { _fieldQueue[i+1]=_fieldQueue[i]; } _fieldQueue[pos] = field; ++_fieldQueueSize; } void FieldReaderIterator::insert(int pos,const char* str) { if (str) { Field* field = new Field; while(*str!=0) { field->addChar(*str); ++str; } insert(pos,field); } } Field& FieldReaderIterator::operator [] (int pos) { return field(pos); } Field& FieldReaderIterator::field (int pos) { if (pos<0) { _blank.setNoNestedBrackets(_reader.getNoNestedBrackets()); return _blank; } // can directly access field else if (pos<_fieldQueueSize) { return *_fieldQueue[pos]; } // need to read the new fields. else { // need to reallocate the stack if (pos>=_fieldQueueCapacity) { int newCapacity = _fieldQueueCapacity*2; if (newCapacity=newCapacity) newCapacity*=2; Field** newFieldStack = new Field* [newCapacity]; int i; for(i=0;i<_fieldQueueCapacity;++i) { newFieldStack[i] = _fieldQueue[i]; } for(;i=_fieldQueueSize) { if (_fieldQueue[_fieldQueueSize]==NULL) _fieldQueue[_fieldQueueSize] = new Field; if (_reader.readField(*_fieldQueue[_fieldQueueSize])) { ++_fieldQueueSize; } } if (pos<_fieldQueueSize) { return *_fieldQueue[pos]; } else { _blank.setNoNestedBrackets(_reader.getNoNestedBrackets()); return _blank; } } } FieldReaderIterator& FieldReaderIterator::operator ++ () { return (*this)+=1; } FieldReaderIterator& FieldReaderIterator::operator += (int no) { if (no>_fieldQueueSize) { while (!_reader.eof() && no>_fieldQueueSize) { _reader.ignoreField(); --no; } _fieldQueueSize=0; } else if (no>0) { Field** tmpFields = new Field* [no]; int i; for(i=0;i=entry) { ++(*this); } } void FieldReaderIterator::advanceToEndOfBlock(int noNestedBrackets) { while(!eof() && field(0).getNoNestedBrackets()>=noNestedBrackets) { ++(*this); } } bool FieldReaderIterator::matchSequence(const char* str) { if (str==NULL) return false; if (*str==0) return false; int fieldCount = 0; const char* end = str; while((*end)!=0 && (*end)==' ') ++end; const char* start = end; while((*start)!=0) { if (*end!=' ' && *end!=0) { ++end; } else { if (start!=end) { if (end-start>1 && *start=='%') { const char type = *(start+1); switch(type) { // expecting an integer case('i') : { if (!field(fieldCount).isInt()) return false; break; } // expecting an floating point number case('f') : { if (!field(fieldCount).isFloat()) return false; break; } // expecting an quoted string case('s') : { if (!field(fieldCount).isQuotedString()) return false; break; } case('w') : default :// expecting an word { if (!field(fieldCount).isWord()) return false; break; } } } else { if (*start=='{') { if (!field(fieldCount).isOpenBracket()) return false; } else if (*start=='}') { if (!field(fieldCount).isCloseBracket()) return false; } else { if (!field(fieldCount).matchWord(start,end-start)) return false; } } fieldCount++; } while((*end)==' ') ++end; start = end; } } return true; } bool FieldReaderIterator::readSequence(const char* keyword,std::string& value) { if ((*this)[0].matchWord(keyword) && (*this)[1].isString()) { value = (*this)[1].getStr(); (*this)+=2; return true; } return false; } bool FieldReaderIterator::readSequence(const char* keyword,unsigned int& value) { if ((*this)[0].matchWord(keyword) && (*this)[1].getUInt(value)) { (*this)+=2; return true; } return false; } bool FieldReaderIterator::readSequence(const char* keyword,int& value) { if ((*this)[0].matchWord(keyword) && (*this)[1].getInt(value)) { (*this)+=2; return true; } return false; } bool FieldReaderIterator::readSequence(const char* keyword,float& value) { if ((*this)[0].matchWord(keyword) && (*this)[1].getFloat(value)) { (*this)+=2; return true; } return false; } bool FieldReaderIterator::readSequence(const char* keyword,osg::Vec2f& value) { if ((*this)[0].matchWord(keyword) && (*this)[1].getFloat(value[0]) && (*this)[2].getFloat(value[1])) { (*this)+=3; return true; } return false; } bool FieldReaderIterator::readSequence(const char* keyword,osg::Vec3f& value) { if ((*this)[0].matchWord(keyword) && (*this)[1].getFloat(value[0]) && (*this)[2].getFloat(value[1]) && (*this)[3].getFloat(value[2])) { (*this)+=4; return true; } return false; } bool FieldReaderIterator::readSequence(const char* keyword,osg::Vec4f& value) { if ((*this)[0].matchWord(keyword) && (*this)[1].getFloat(value[0]) && (*this)[2].getFloat(value[1]) && (*this)[3].getFloat(value[2]) && (*this)[4].getFloat(value[3])) { (*this)+=5; return true; } return false; } bool FieldReaderIterator::readSequence(const char* keyword,osg::Vec2d& value) { if ((*this)[0].matchWord(keyword) && (*this)[1].getFloat(value[0]) && (*this)[2].getFloat(value[1])) { (*this)+=3; return true; } return false; } bool FieldReaderIterator::readSequence(const char* keyword,osg::Vec3d& value) { if ((*this)[0].matchWord(keyword) && (*this)[1].getFloat(value[0]) && (*this)[2].getFloat(value[1]) && (*this)[3].getFloat(value[2])) { (*this)+=4; return true; } return false; } bool FieldReaderIterator::readSequence(const char* keyword,osg::Vec4d& value) { if ((*this)[0].matchWord(keyword) && (*this)[1].getFloat(value[0]) && (*this)[2].getFloat(value[1]) && (*this)[3].getFloat(value[2]) && (*this)[4].getFloat(value[3])) { (*this)+=5; return true; } return false; } bool FieldReaderIterator::readSequence(std::string& value) { if ((*this)[0].isString()) { value = (*this)[0].getStr(); (*this)+=1; return true; } return false; } bool FieldReaderIterator::readSequence(unsigned int& value) { if ((*this)[0].getUInt(value)) { (*this)+=1; return true; } return false; } bool FieldReaderIterator::readSequence(int& value) { if ((*this)[0].getInt(value)) { (*this)+=1; return true; } return false; } bool FieldReaderIterator::readSequence(float& value) { if ((*this)[0].getFloat(value)) { (*this)+=1; return true; } return false; } bool FieldReaderIterator::readSequence(osg::Vec2f& value) { if ((*this)[0].getFloat(value[0]) && (*this)[1].getFloat(value[1])) { (*this)+=2; return true; } return false; } bool FieldReaderIterator::readSequence(osg::Vec3f& value) { if ((*this)[0].getFloat(value[0]) && (*this)[1].getFloat(value[1]) && (*this)[2].getFloat(value[2])) { (*this)+=3; return true; } return false; } bool FieldReaderIterator::readSequence(osg::Vec4f& value) { if ((*this)[0].getFloat(value[0]) && (*this)[1].getFloat(value[1]) && (*this)[2].getFloat(value[2]) && (*this)[3].getFloat(value[3])) { (*this)+=4; return true; } return false; } bool FieldReaderIterator::readSequence(osg::Vec2d& value) { if ((*this)[0].getFloat(value[0]) && (*this)[1].getFloat(value[1])) { (*this)+=2; return true; } return false; } bool FieldReaderIterator::readSequence(osg::Vec3d& value) { if ((*this)[0].getFloat(value[0]) && (*this)[1].getFloat(value[1]) && (*this)[2].getFloat(value[2])) { (*this)+=3; return true; } return false; } bool FieldReaderIterator::readSequence(osg::Vec4d& value) { if ((*this)[0].getFloat(value[0]) && (*this)[1].getFloat(value[1]) && (*this)[2].getFloat(value[2]) && (*this)[3].getFloat(value[3])) { (*this)+=4; return true; } return false; } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/Field.cpp0000644000175000017500000002152511732410624022544 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include using namespace osgDB; using namespace std; Field::Field() { _init(); } Field::Field(const Field& ic) { _copy(ic); } Field::~Field() { _free(); } Field& Field::operator = (const Field& ic) { if (this==&ic) return *this; _free(); _copy(ic); return *this; } void Field::_free() { // free all data if (_fieldCache) delete [] _fieldCache; _init(); } void Field::_init() { _fieldCacheCapacity = 256; _fieldCacheSize = 0; _fieldCache = NULL; _fieldType = UNINITIALISED; _withinQuotes = false; _noNestedBrackets = 0; } void Field::_copy(const Field& ic) { // copy string cache. if (ic._fieldCache) { _fieldCacheCapacity = ic._fieldCacheCapacity; _fieldCacheSize = ic._fieldCacheSize; _fieldCache = new char [_fieldCacheCapacity]; strncpy(_fieldCache,ic._fieldCache,_fieldCacheCapacity); } else { _fieldCacheCapacity = 0; _fieldCacheSize = 0; _fieldCache = NULL; } _fieldType = ic._fieldType; _withinQuotes = ic._withinQuotes; _noNestedBrackets = ic._noNestedBrackets; } void Field::setWithinQuotes(bool withinQuotes) { _withinQuotes=withinQuotes; _fieldType = UNINITIALISED; } bool Field::getWithinQuotes() { return _withinQuotes; } void Field::setNoNestedBrackets(int no) { _noNestedBrackets=no; } int Field::getNoNestedBrackets() { return _noNestedBrackets; } const char* Field::getStr() const { if (_fieldCacheSize!=0) return _fieldCache; else return NULL; } char* Field::takeStr() { char* field = _fieldCache; _fieldCache = NULL; _fieldCacheSize = 0; _fieldType = UNINITIALISED; _withinQuotes = false; return field; } void Field::reset() { _fieldCacheSize = 0; if (_fieldCache) { _fieldCache[_fieldCacheSize] = 0; } _withinQuotes = false; _noNestedBrackets = 0; } void Field::addChar(char c) { if (_fieldCache==NULL) { if (_fieldCacheCapacity=_fieldCacheCapacity-1) { if (_fieldCacheCapacity=_fieldCacheCapacity-1) _fieldCacheCapacity *= 2; char* tmp_str = _fieldCache; _fieldCache = new char[_fieldCacheCapacity]; memset(_fieldCache,0,_fieldCacheCapacity); strncpy(_fieldCache,tmp_str,_fieldCacheSize); delete [] tmp_str; } _fieldCache[_fieldCacheSize++] = c; _fieldCache[_fieldCacheSize] = 0; _fieldType = UNINITIALISED; } Field::FieldType Field::getFieldType() const { if (_fieldType==UNINITIALISED && _fieldCache) { _fieldType = calculateFieldType(_fieldCache,_withinQuotes); } return _fieldType; } bool Field::isValid() const { if (_fieldCacheSize>0 && !_withinQuotes) return true; else return false; } bool Field::isOpenBracket() const { if (_fieldCacheSize==1) return _fieldCache[0]=='{'; else return false; } bool Field::isCloseBracket() const { if (_fieldCacheSize==1) return _fieldCache[0]=='}'; else return false; } bool Field::isWord() const { getFieldType(); return (_fieldType==WORD); } bool Field::matchWord(const char* str) const { getFieldType(); return _fieldType==WORD && strcmp(_fieldCache,str)==0; } bool Field::matchWord(const char* str,int noCharacters) const { getFieldType(); return _fieldType==WORD && strncmp(_fieldCache,str,noCharacters)==0; } bool Field::isString() const { return getNoCharacters()!=0; } bool Field::matchString(const char* str) const { return strcmp(_fieldCache,str)==0; } bool Field::matchString(const char* str,int noCharacters) const { return strncmp(_fieldCache,str,noCharacters)==0; } bool Field::isQuotedString() const { return _withinQuotes; } bool Field::isInt() const { getFieldType(); return _fieldType==INTEGER; } bool Field::matchInt(int i) const { getFieldType(); if (_fieldType==INTEGER) { return strtol(_fieldCache,NULL,0)==i; } else { return false; } } bool Field::getInt(int& i) const { getFieldType(); if (_fieldType==INTEGER) { i = strtol(_fieldCache,NULL,0); return true; } else { return false; } } bool Field::isUInt() const { getFieldType(); return _fieldType==INTEGER; } bool Field::matchUInt(unsigned int i) const { getFieldType(); if (_fieldType==INTEGER) { return (unsigned int) strtoul(_fieldCache,NULL,0)==i; } else { return false; } } bool Field::getUInt(unsigned int& i) const { getFieldType(); if (_fieldType==INTEGER) { i = strtoul(_fieldCache,NULL,0); return true; } else { return false; } } bool Field::isFloat() const { getFieldType(); return _fieldType==REAL || _fieldType==INTEGER; } bool Field::matchFloat(float f) const { getFieldType(); if (_fieldType==REAL || _fieldType==INTEGER) { return osg::asciiToFloat(_fieldCache)==f; } else { return false; } } bool Field::getFloat(float& f) const { getFieldType(); if (_fieldType==REAL || _fieldType==INTEGER) { f = osg::asciiToFloat(_fieldCache); return true; } else { return false; } } bool Field::getFloat(double& f) const { getFieldType(); if (_fieldType==REAL || _fieldType==INTEGER) { f = osg::asciiToDouble(_fieldCache); return true; } else { return false; } } Field::FieldType Field::calculateFieldType(const char* str,bool withinQuotes) { if (str==NULL) return BLANK; if (*str==0) return BLANK; if (withinQuotes) return STRING; bool hadPlusMinus = false; bool hadDecimalPlace = false; bool hadExponent = false; bool couldBeInt = true; bool couldBeFloat = true; int noZeroToNine = 0; const char* ptr = str; // check if could be a hex number. if (strncmp(ptr,"0x",2)==0) { // skip over leading 0x, and then go through rest of string // checking to make sure all values are 0...9 or a..f. ptr+=2; while ( *ptr!=0 && ((*ptr>='0' && *ptr<='9') || (*ptr>='a' && *ptr<='f') || (*ptr>='A' && *ptr<='F')) ) { ++ptr; } // got to end of string without failure, therefore must be a hex integer. if (*ptr==0) return INTEGER; } ptr = str; // check if a float or an int. while (*ptr!=0 && couldBeFloat) { if (*ptr=='+' || *ptr=='-') { if (hadPlusMinus) { couldBeInt = false; couldBeFloat = false; } else hadPlusMinus = true; } else if (*ptr>='0' && *ptr<='9') { noZeroToNine++; } else if (*ptr=='.') { if (hadDecimalPlace) { couldBeInt = false; couldBeFloat = false; } else { hadDecimalPlace = true; couldBeInt = false; } } else if (*ptr=='e' || *ptr=='E') { if (hadExponent || noZeroToNine==0) { couldBeInt = false; couldBeFloat = false; } else { hadExponent = true; couldBeInt = false; hadDecimalPlace = false; hadPlusMinus = false; noZeroToNine=0; } } else { couldBeInt = false; couldBeFloat = false; } ++ptr; } if (couldBeInt && noZeroToNine>0) return INTEGER; if (couldBeFloat && noZeroToNine>0) return REAL; if (str[0]=='{') return OPEN_BRACKET; if (str[0]=='}') return CLOSE_BRACKET; return WORD; } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/CMakeLists.txt0000644000175000017500000001131512433716615023561 0ustar albertoalberto IF (DYNAMIC_OPENSCENEGRAPH) OPTION(OSG_PLUGIN_SEARCH_INSTALL_DIR_FOR_PLUGINS "Set to ON to have OpenSceneGraph search the configured install directory for plugins." ON) ADD_DEFINITIONS(-DOSGDB_LIBRARY) IF(OSG_PLUGIN_SEARCH_INSTALL_DIR_FOR_PLUGINS) # Add a default plugin search path component ADD_DEFINITIONS(-DOSG_DEFAULT_LIBRARY_PATH=\"${CMAKE_INSTALL_PREFIX}/lib${LIB_POSTFIX}/${OSG_PLUGINS}\") ENDIF() # Set the library extension according to what configuration is being built. # If the string is empty, don't set the define. IF(CMAKE_DEBUG_POSTFIX) SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DOSG_LIBRARY_POSTFIX=${CMAKE_DEBUG_POSTFIX}") ENDIF() IF(CMAKE_RELEASE_POSTFIX) SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DOSG_LIBRARY_POSTFIX=${CMAKE_RELEASE_POSTFIX}") ENDIF() IF(CMAKE_RELWITHDEBINFO_POSTFIX) SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DOSG_LIBRARY_POSTFIX=${CMAKE_RELWITHDEBINFO_POSTFIX}") ENDIF() IF(CMAKE_MINSIZEREL_POSTFIX) SET(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -DOSG_LIBRARY_POSTFIX=${CMAKE_MINSIZEREL_POSTFIX}") ENDIF() ELSE () ADD_DEFINITIONS(-DOSG_LIBRARY_STATIC) ENDIF() IF(APPLE AND NOT ANDROID) IF(OSG_BUILD_PLATFORM_IPHONE OR OSG_BUILD_PLATFORM_IPHONE_SIMULATOR) # compile FileUtils.cpp as objective-c++ SET_SOURCE_FILES_PROPERTIES(FileUtils.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++" ) ENDIF() ENDIF() SET(LIB_NAME osgDB) SET(HEADER_PATH ${OpenSceneGraph_SOURCE_DIR}/include/${LIB_NAME}) SET(TARGET_H ${HEADER_PATH}/DataTypes ${HEADER_PATH}/StreamOperator ${HEADER_PATH}/Serializer ${HEADER_PATH}/ObjectWrapper ${HEADER_PATH}/InputStream ${HEADER_PATH}/OutputStream ${HEADER_PATH}/Archive ${HEADER_PATH}/AuthenticationMap ${HEADER_PATH}/Callbacks ${HEADER_PATH}/ConvertUTF ${HEADER_PATH}/DatabasePager ${HEADER_PATH}/DatabaseRevisions ${HEADER_PATH}/DotOsgWrapper ${HEADER_PATH}/DynamicLibrary ${HEADER_PATH}/Export ${HEADER_PATH}/ExternalFileWriter ${HEADER_PATH}/FileCache ${HEADER_PATH}/FileNameUtils ${HEADER_PATH}/FileUtils ${HEADER_PATH}/fstream ${HEADER_PATH}/ImageOptions ${HEADER_PATH}/ImagePager ${HEADER_PATH}/ImageProcessor ${HEADER_PATH}/Input ${HEADER_PATH}/Output ${HEADER_PATH}/Options ${HEADER_PATH}/ParameterOutput ${HEADER_PATH}/PluginQuery ${HEADER_PATH}/ReaderWriter ${HEADER_PATH}/ReadFile ${HEADER_PATH}/Registry ${HEADER_PATH}/SharedStateManager ${HEADER_PATH}/Version ${HEADER_PATH}/WriteFile ${HEADER_PATH}/XmlParser ) SET(TARGET_SRC ObjectWrapper.cpp InputStream.cpp OutputStream.cpp Compressors.cpp Archive.cpp AuthenticationMap.cpp Callbacks.cpp ConvertUTF.cpp DatabasePager.cpp DatabaseRevisions.cpp DotOsgWrapper.cpp DynamicLibrary.cpp ExternalFileWriter.cpp Field.cpp FieldReader.cpp FieldReaderIterator.cpp FileCache.cpp FileNameUtils.cpp FileUtils.cpp fstream.cpp ImageOptions.cpp ImagePager.cpp Input.cpp MimeTypes.cpp Output.cpp Options.cpp PluginQuery.cpp ReaderWriter.cpp ReadFile.cpp Registry.cpp SharedStateManager.cpp StreamOperator.cpp Version.cpp WriteFile.cpp XmlParser.cpp ${OPENSCENEGRAPH_VERSIONINFO_RC} ) IF(APPLE AND NOT ANDROID) IF(NOT OSG_BUILD_PLATFORM_IPHONE AND NOT OSG_BUILD_PLATFORM_IPHONE_SIMULATOR) # Needs CoreFoundation calls and a Carbon function SET(OSGDB_PLATFORM_SPECIFIC_LIBRARIES ${CARBON_LIBRARY} ${COCOA_LIBRARY}) ENDIF() IF(OSG_DEFAULT_IMAGE_PLUGIN_FOR_OSX STREQUAL "quicktime") ADD_DEFINITIONS(-DDARWIN_QUICKTIME) ELSE() ADD_DEFINITIONS(-DDARWIN_IMAGEIO) ENDIF() ENDIF() IF(QTKIT_FOUND) ADD_DEFINITIONS(-DUSE_QTKIT) ENDIF() IF(QUICKTIME_FOUND) ADD_DEFINITIONS(-DUSE_QUICKTIME) ENDIF() IF(AV_FOUNDATION_FOUND) ADD_DEFINITIONS(-DUSE_AV_FOUNDATION) ENDIF() IF(XINE_FOUND) ADD_DEFINITIONS(-DUSE_XINE) ENDIF() IF(INVENTOR_FOUND) ADD_DEFINITIONS(-DUSE_INVENTOR) ENDIF() IF(OPENVRML_FOUND) ADD_DEFINITIONS(-DUSE_VRML) ENDIF() IF( ZLIB_FOUND ) ADD_DEFINITIONS( -DUSE_ZLIB ) INCLUDE_DIRECTORIES( ${ZLIB_INCLUDE_DIR} ) SET(COMPRESSION_LIBRARIES ZLIB_LIBRARY) ENDIF() ADD_DEFINITIONS(-DOSG_PLUGIN_EXTENSION=${CMAKE_SHARED_MODULE_SUFFIX}) SET(TARGET_LIBRARIES osg osgUtil OpenThreads ) SET(TARGET_EXTERNAL_LIBRARIES ${OSGDB_PLATFORM_SPECIFIC_LIBRARIES} ${DL_LIBRARY}) SET(TARGET_LIBRARIES_VARS ${COMPRESSION_LIBRARIES}) SETUP_LIBRARY(${LIB_NAME}) openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/AuthenticationMap.cpp0000644000175000017500000000303111732410624025126 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include using namespace osgDB; void AuthenticationMap::addAuthenticationDetails(const std::string& path, AuthenticationDetails* details) { _authenticationMap[path] = details; } const AuthenticationDetails* AuthenticationMap::getAuthenticationDetails(const std::string& path) const { // see if the full filename has its own authentication details AuthenticationDetailsMap::const_iterator itr = _authenticationMap.find(path); if (itr != _authenticationMap.end()) return itr->second.get(); // now look to see if the paths to the file have their own authentication details std::string basePath = osgDB::getFilePath(path); while(!basePath.empty()) { itr = _authenticationMap.find(basePath); if (itr != _authenticationMap.end()) return itr->second.get(); basePath = osgDB::getFilePath(basePath); } return 0; } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/MimeTypes.cpp0000644000175000017500000000742611732410624023441 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ const char* builtinMimeTypeExtMappings[] = { "application/dxf","dxf", "application/gnutar","tgz", "application/pdf","pdf", "application/plain","text", "application/postscript","ps", "application/x-bzip","bz", "application/x-bzip2","bz2", "application/x-compressed","zip", "application/x-gzip","gz", "application/x-inventor","iv", "application/x-javascript","js", "application/xml","xml", "application/x-tar","tar", "application/x-vrml","wrl", "application/x-world","wrl", "application/x-zip-compressed","zip", "application/zip","zip", "drawing/x-dwf(old)","dwf", "image/bmp","bmp", "image/cmu-raster","ras", "image/fif","fif", "image/florian","flo", "image/g3fax","g3", "image/gif","gif", "image/ief","ief", "image/jpeg","jpg", "image/jutvision","jut", "image/naplps","nap", "image/naplps","naplps", "image/pict","pic", "image/pjpeg","jpg", "image/png","png", "image/tiff","tif", "image/vasa","mcf", "image/vnd.dwg","dxf", "image/vnd.fpx","fpx", "image/vnd.net-fpx","fpx", "image/vnd.rn-realflash","rf", "image/vnd.rn-realpix","rp", "image/vnd.wap.wbmp","wbmp", "image/vnd.xiff","xif", "image/xbm","xbm", "image/x-cmu-raster","ras", "image/x-dwg","dxf", "image/x-icon","ico", "image/x-jg","art", "image/x-jps","jps", "image/x-niff","nif", "image/x-pcx","pcx", "image/x-pict","pct", "image/xpm","xpm", "image/x-portable-anymap","pnm", "image/x-portable-bitmap","pbm", "image/x-portable-graymap","pgm", "image/x-portable-greymap","pgm", "image/x-portable-pixmap","ppm", "image/x-quicktime","qif", "image/x-rgb","rgb", "image/x-tiff","tif", "image/x-windows-bmp","bmp", "image/x-xbitmap","xbm", "image/x-xbm","xbm", "image/x-xpixmap","xpm", "image/x-xwd","xwd", "image/x-xwindowdump","xwd", "i-world/i-vrml","ivr", "model/iges","igs", "model/vnd.dwf","dwf", "model/vrml","wrl", "model/x-pov","pov", "multipart/x-gzip","gzip", "multipart/x-ustar","ustar", "multipart/x-zip","zip", "video/animaflex","afl", "video/avi","avi", "video/avs-video","avs", "video/dl","dl", "video/fli","fli", "video/gl","gl", "video/mpeg","mpg", "video/msvideo","avi", "video/quicktime","qt", "video/vdo","vdo", "video/vivo","viv", "video/vnd.rn-realvideo","rv", "video/vnd.vivo","viv", "video/vosaic","vos", "video/x-amt-demorun","xdr", "video/x-amt-showrun","xsr", "video/x-atomic3d-feature","fmf", "video/x-dl","dl", "video/x-dv","dv", "video/x-fli","fli", "video/x-gl","gl", "video/x-isvideo","isu", "video/x-motion-jpeg","mjpg", "video/x-mpeg","mp3", "video/x-mpeq2a","mp2", "video/x-ms-asf","asf", "video/x-ms-asf-plugin","asx", "video/x-msvideo","avi", "video/x-qtc","qtc", "video/x-scm","scm", "video/x-sgi-movie","movie", "windows/metafile","wmf", "xgl/drawing","xgz", "xgl/movie","xmz", "x-world/x-3dmf","3dm", "x-world/x-svr","svr", "x-world/x-vrml","wrl", "x-world/x-vrt","vrt", "" // end of list }; openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/Input.cpp0000644000175000017500000003130612163040026022610 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include using namespace osgDB; Input::Input() { } Input::~Input() { } osg::Object* Input::getObjectForUniqueID(const std::string& uniqueID) { UniqueIDToObjectMapping::iterator fitr = _uniqueIDToObjectMap.find(uniqueID); if (fitr != _uniqueIDToObjectMap.end()) return (*fitr).second.get(); else return NULL; } void Input::registerUniqueIDForObject(const std::string& uniqueID,osg::Object* obj) { _uniqueIDToObjectMap[uniqueID] = obj; } osg::Object* Input::readObjectOfType(const osg::Object& compObj) { return Registry::instance()->getDeprecatedDotOsgObjectWrapperManager()->readObjectOfType(compObj,*this); } osg::Object* Input::readObjectOfType(const basic_type_wrapper &btw) { return Registry::instance()->getDeprecatedDotOsgObjectWrapperManager()->readObjectOfType(btw,*this); } osg::Object* Input::readObject() { return Registry::instance()->getDeprecatedDotOsgObjectWrapperManager()->readObject(*this); } osg::Image* Input::readImage() { return Registry::instance()->getDeprecatedDotOsgObjectWrapperManager()->readImage(*this); } osg::Drawable* Input::readDrawable() { osg::Drawable* drawable = Registry::instance()->getDeprecatedDotOsgObjectWrapperManager()->readDrawable(*this); osg::Geometry* geometry = drawable ? drawable->asGeometry() : 0; if (geometry && geometry->containsDeprecatedData()) geometry->fixDeprecatedData(); return drawable; } osg::StateAttribute* Input::readStateAttribute() { return Registry::instance()->getDeprecatedDotOsgObjectWrapperManager()->readStateAttribute(*this); } osg::Uniform* Input::readUniform() { return Registry::instance()->getDeprecatedDotOsgObjectWrapperManager()->readUniform(*this); } osg::Node* Input::readNode() { return Registry::instance()->getDeprecatedDotOsgObjectWrapperManager()->readNode(*this); } osg::Object* Input::readObject(const std::string& fileName) { return readObjectFile(fileName,_options.get()); } osg::Shader* Input::readShader() { return Registry::instance()->getDeprecatedDotOsgObjectWrapperManager()->readShader(*this); } osg::Image* Input::readImage(const std::string& fileName) { return readImageFile(fileName,_options.get()); } osg::Node* Input::readNode(const std::string& fileName) { return readNodeFile(fileName,_options.get()); } osg::Shader* Input::readShader(const std::string& fileName) { return readShaderFile(fileName,_options.get()); } bool Input::read(Parameter value1) { if (value1.valid((*this)[0].getStr())) { value1.assign((*this)[0].getStr()); (*this) += 1; return true; } else return false; } bool Input::read(Parameter value1, Parameter value2) { if (value1.valid((*this)[0].getStr()) && value2.valid((*this)[1].getStr())) { value1.assign((*this)[0].getStr()); value2.assign((*this)[1].getStr()); (*this) += 2; return true; } else return false; } bool Input::read(Parameter value1, Parameter value2, Parameter value3) { if (value1.valid((*this)[0].getStr()) && value2.valid((*this)[1].getStr()) && value3.valid((*this)[2].getStr())) { value1.assign((*this)[0].getStr()); value2.assign((*this)[1].getStr()); value3.assign((*this)[2].getStr()); (*this) += 3; return true; } else return false; } bool Input::read(Parameter value1, Parameter value2, Parameter value3, Parameter value4) { if (value1.valid((*this)[0].getStr()) && value2.valid((*this)[1].getStr()) && value3.valid((*this)[2].getStr()) && value4.valid((*this)[3].getStr())) { value1.assign((*this)[0].getStr()); value2.assign((*this)[1].getStr()); value3.assign((*this)[2].getStr()); value4.assign((*this)[3].getStr()); (*this) += 4; return true; } else return false; } bool Input::read(Parameter value1, Parameter value2, Parameter value3, Parameter value4, Parameter value5) { if (value1.valid((*this)[0].getStr()) && value2.valid((*this)[1].getStr()) && value3.valid((*this)[2].getStr()) && value4.valid((*this)[3].getStr()) && value5.valid((*this)[4].getStr())) { value1.assign((*this)[0].getStr()); value2.assign((*this)[1].getStr()); value3.assign((*this)[2].getStr()); value4.assign((*this)[3].getStr()); value5.assign((*this)[4].getStr()); (*this) += 5; return true; } else return false; } bool Input::read(Parameter value1, Parameter value2, Parameter value3, Parameter value4, Parameter value5, Parameter value6) { if (value1.valid((*this)[0].getStr()) && value2.valid((*this)[1].getStr()) && value3.valid((*this)[2].getStr()) && value4.valid((*this)[3].getStr()) && value5.valid((*this)[4].getStr()) && value6.valid((*this)[5].getStr())) { value1.assign((*this)[0].getStr()); value2.assign((*this)[1].getStr()); value3.assign((*this)[2].getStr()); value4.assign((*this)[3].getStr()); value5.assign((*this)[4].getStr()); value6.assign((*this)[5].getStr()); (*this) += 6; return true; } else return false; } bool Input::read(Parameter value1, Parameter value2, Parameter value3, Parameter value4, Parameter value5, Parameter value6, Parameter value7) { if (value1.valid((*this)[0].getStr()) && value2.valid((*this)[1].getStr()) && value3.valid((*this)[2].getStr()) && value4.valid((*this)[3].getStr()) && value5.valid((*this)[4].getStr()) && value6.valid((*this)[5].getStr()) && value7.valid((*this)[6].getStr())) { value1.assign((*this)[0].getStr()); value2.assign((*this)[1].getStr()); value3.assign((*this)[2].getStr()); value4.assign((*this)[3].getStr()); value5.assign((*this)[4].getStr()); value6.assign((*this)[5].getStr()); value7.assign((*this)[6].getStr()); (*this) += 7; return true; } else return false; } bool Input::read(Parameter value1, Parameter value2, Parameter value3, Parameter value4, Parameter value5, Parameter value6, Parameter value7, Parameter value8) { if (value1.valid((*this)[0].getStr()) && value2.valid((*this)[1].getStr()) && value3.valid((*this)[2].getStr()) && value4.valid((*this)[3].getStr()) && value5.valid((*this)[4].getStr()) && value6.valid((*this)[5].getStr()) && value7.valid((*this)[6].getStr()) && value8.valid((*this)[7].getStr())) { value1.assign((*this)[0].getStr()); value2.assign((*this)[1].getStr()); value3.assign((*this)[2].getStr()); value4.assign((*this)[3].getStr()); value5.assign((*this)[4].getStr()); value6.assign((*this)[5].getStr()); value7.assign((*this)[6].getStr()); value8.assign((*this)[7].getStr()); (*this) += 8; return true; } else return false; } bool Input::read(const char* str) { if ((*this)[0].matchWord(str)) { (*this) += 1; return true; } else return false; } bool Input::read(const char* str, Parameter value1) { if ((*this)[0].matchWord(str) && value1.valid((*this)[1].getStr())) { value1.assign((*this)[1].getStr()); (*this) += 2; return true; } else return false; } bool Input::read(const char* str, Parameter value1, Parameter value2) { if ((*this)[0].matchWord(str) && value1.valid((*this)[1].getStr()) && value2.valid((*this)[2].getStr())) { value1.assign((*this)[1].getStr()); value2.assign((*this)[2].getStr()); (*this) += 3; return true; } else return false; } bool Input::read(const char* str, Parameter value1, Parameter value2, Parameter value3) { if ((*this)[0].matchWord(str) && value1.valid((*this)[1].getStr()) && value2.valid((*this)[2].getStr()) && value3.valid((*this)[3].getStr())) { value1.assign((*this)[1].getStr()); value2.assign((*this)[2].getStr()); value3.assign((*this)[3].getStr()); (*this) += 4; return true; } else return false; } bool Input::read(const char* str, Parameter value1, Parameter value2, Parameter value3, Parameter value4) { if ((*this)[0].matchWord(str) && value1.valid((*this)[1].getStr()) && value2.valid((*this)[2].getStr()) && value3.valid((*this)[3].getStr()) && value4.valid((*this)[4].getStr())) { value1.assign((*this)[1].getStr()); value2.assign((*this)[2].getStr()); value3.assign((*this)[3].getStr()); value4.assign((*this)[4].getStr()); (*this) += 5; return true; } else return false; } bool Input::read(const char* str, Parameter value1, Parameter value2, Parameter value3, Parameter value4, Parameter value5) { if ((*this)[0].matchWord(str) && value1.valid((*this)[1].getStr()) && value2.valid((*this)[2].getStr()) && value3.valid((*this)[3].getStr()) && value4.valid((*this)[4].getStr()) && value5.valid((*this)[5].getStr())) { value1.assign((*this)[1].getStr()); value2.assign((*this)[2].getStr()); value3.assign((*this)[3].getStr()); value4.assign((*this)[4].getStr()); value5.assign((*this)[5].getStr()); (*this) += 6; return true; } else return false; } bool Input::read(const char* str, Parameter value1, Parameter value2, Parameter value3, Parameter value4, Parameter value5, Parameter value6) { if ((*this)[0].matchWord(str) && value1.valid((*this)[1].getStr()) && value2.valid((*this)[2].getStr()) && value3.valid((*this)[3].getStr()) && value4.valid((*this)[4].getStr()) && value5.valid((*this)[5].getStr()) && value6.valid((*this)[6].getStr())) { value1.assign((*this)[1].getStr()); value2.assign((*this)[2].getStr()); value3.assign((*this)[3].getStr()); value4.assign((*this)[4].getStr()); value5.assign((*this)[5].getStr()); value6.assign((*this)[6].getStr()); (*this) += 7; return true; } else return false; } bool Input::read(const char* str, Parameter value1, Parameter value2, Parameter value3, Parameter value4, Parameter value5, Parameter value6, Parameter value7) { if ((*this)[0].matchWord(str) && value1.valid((*this)[1].getStr()) && value2.valid((*this)[2].getStr()) && value3.valid((*this)[3].getStr()) && value4.valid((*this)[4].getStr()) && value5.valid((*this)[5].getStr()) && value6.valid((*this)[6].getStr()) && value7.valid((*this)[7].getStr())) { value1.assign((*this)[1].getStr()); value2.assign((*this)[2].getStr()); value3.assign((*this)[3].getStr()); value4.assign((*this)[4].getStr()); value5.assign((*this)[5].getStr()); value6.assign((*this)[6].getStr()); value7.assign((*this)[7].getStr()); (*this) += 8; return true; } else return false; } bool Input::read(const char* str, Parameter value1, Parameter value2, Parameter value3, Parameter value4, Parameter value5, Parameter value6, Parameter value7, Parameter value8) { if ((*this)[0].matchWord(str) && value1.valid((*this)[1].getStr()) && value2.valid((*this)[2].getStr()) && value3.valid((*this)[3].getStr()) && value4.valid((*this)[4].getStr()) && value5.valid((*this)[5].getStr()) && value6.valid((*this)[6].getStr()) && value7.valid((*this)[7].getStr()) && value8.valid((*this)[8].getStr())) { value1.assign((*this)[1].getStr()); value2.assign((*this)[2].getStr()); value3.assign((*this)[3].getStr()); value4.assign((*this)[4].getStr()); value5.assign((*this)[5].getStr()); value6.assign((*this)[6].getStr()); value7.assign((*this)[7].getStr()); value8.assign((*this)[8].getStr()); (*this) += 9; return true; } else return false; } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/ReadFile.cpp0000644000175000017500000002273012021065211023161 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace osg; using namespace osgDB; Object* osgDB::readObjectFile(const std::string& filename,const Options* options) { ReaderWriter::ReadResult rr = Registry::instance()->readObject(filename,options); if (rr.validObject()) return rr.takeObject(); if (rr.error()) OSG_WARN << rr.message() << std::endl; return NULL; } Image* osgDB::readImageFile(const std::string& filename,const Options* options) { ReaderWriter::ReadResult rr = Registry::instance()->readImage(filename,options); if (rr.validImage()) return rr.takeImage(); if (rr.error()) OSG_WARN << rr.message() << std::endl; return NULL; } Shader* osgDB::readShaderFile(const std::string& filename,const Options* options) { ReaderWriter::ReadResult rr = Registry::instance()->readShader(filename,options); if (rr.validShader()) return rr.takeShader(); if (rr.error()) OSG_WARN << rr.message() << std::endl; return NULL; } HeightField* osgDB::readHeightFieldFile(const std::string& filename,const Options* options) { ReaderWriter::ReadResult rr = Registry::instance()->readHeightField(filename,options); if (rr.validHeightField()) return rr.takeHeightField(); if (rr.error()) OSG_WARN << rr.message() << std::endl; return NULL; } Node* osgDB::readNodeFile(const std::string& filename,const Options* options) { ReaderWriter::ReadResult rr = Registry::instance()->readNode(filename,options); if (rr.validNode()) return rr.takeNode(); if (rr.error()) OSG_WARN << rr.message() << std::endl; if (rr.notEnoughMemory()) OSG_INFO << "Not enought memory to load file "<& fileList,const Options* options) { typedef std::vector NodeList; NodeList nodeList; for(std::vector::iterator itr=fileList.begin(); itr!=fileList.end(); ++itr) { osg::Node *node = osgDB::readNodeFile( *itr , options ); if( node != (osg::Node *)0L ) { if (node->getName().empty()) node->setName( *itr ); nodeList.push_back(node); } } if (nodeList.empty()) { return NULL; } if (nodeList.size()==1) { return nodeList.front(); } else // size >1 { osg::Group* group = new osg::Group; for(NodeList::iterator itr=nodeList.begin(); itr!=nodeList.end(); ++itr) { group->addChild(*itr); } return group; } } Node* osgDB::readNodeFiles(osg::ArgumentParser& arguments,const Options* options) { typedef std::vector< osg::ref_ptr > NodeList; NodeList nodeList; std::string filename; while (arguments.read("--file-cache",filename)) { osgDB::Registry::instance()->setFileCache(new osgDB::FileCache(filename)); } while (arguments.read("--image",filename)) { osg::ref_ptr image = readImageFile(filename.c_str(), options); if (image.valid()) { osg::Geode* geode = osg::createGeodeForImage(image.get()); if (image->isImageTranslucent()) { OSG_INFO<<"Image "<getFileName()<<" is translucent; setting up blending."<getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); geode->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); } nodeList.push_back(geode); } } while (arguments.read("--movie",filename)) { osg::ref_ptr image = readImageFile(filename.c_str(), options); osg::ref_ptr imageStream = dynamic_cast(image.get()); if (imageStream.valid()) { bool flip = image->getOrigin()==osg::Image::TOP_LEFT; // start the stream playing. imageStream->play(); osg::ref_ptr pictureQuad = 0; bool useTextureRectangle = true; if (useTextureRectangle) { pictureQuad = osg::createTexturedQuadGeometry(osg::Vec3(0.0f,0.0f,0.0f), osg::Vec3(image->s(),0.0f,0.0f), osg::Vec3(0.0f,0.0f,image->t()), 0.0f, flip ? image->t() : 0.0, image->s(), flip ? 0.0 : image->t()); pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0, new osg::TextureRectangle(image.get()), osg::StateAttribute::ON); } else { pictureQuad = osg::createTexturedQuadGeometry(osg::Vec3(0.0f,0.0f,0.0f), osg::Vec3(image->s(),0.0f,0.0f), osg::Vec3(0.0f,0.0f,image->t()), 0.0f, flip ? 1.0f : 0.0f , 1.0f, flip ? 0.0f : 1.0f); pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0, new osg::Texture2D(image.get()), osg::StateAttribute::ON); } if (pictureQuad.valid()) { osg::ref_ptr geode = new osg::Geode; geode->addDrawable(pictureQuad.get()); nodeList.push_back(geode.get()); } } else if (image.valid()) { nodeList.push_back(osg::createGeodeForImage(image.get())); } } while (arguments.read("--dem",filename)) { osg::HeightField* hf = readHeightFieldFile(filename.c_str(), options); if (hf) { osg::Geode* geode = new osg::Geode; geode->addDrawable(new osg::ShapeDrawable(hf)); nodeList.push_back(geode); } } // note currently doesn't delete the loaded file entries from the command line yet... for(int pos=1;posgetName().empty()) node->setName( arguments[pos] ); nodeList.push_back(node); } } } if (nodeList.empty()) { return NULL; } if (nodeList.size()==1) { return nodeList.front().release(); } else // size >1 { osg::Group* group = new osg::Group; for(NodeList::iterator itr=nodeList.begin(); itr!=nodeList.end(); ++itr) { group->addChild((*itr).get()); } return group; } } osg::ref_ptr osgDB::readRefObjectFile(const std::string& filename,const Options* options) { ReaderWriter::ReadResult rr = Registry::instance()->readObject(filename,options); if (rr.validObject()) return osg::ref_ptr(rr.getObject()); if (rr.error()) OSG_WARN << rr.message() << std::endl; return NULL; } osg::ref_ptr osgDB::readRefImageFile(const std::string& filename,const Options* options) { ReaderWriter::ReadResult rr = Registry::instance()->readImage(filename,options); if (rr.validImage()) return osg::ref_ptr(rr.getImage()); if (rr.error()) OSG_WARN << rr.message() << std::endl; return NULL; } osg::ref_ptr osgDB::readRefShaderFile(const std::string& filename,const Options* options) { ReaderWriter::ReadResult rr = Registry::instance()->readShader(filename,options); if (rr.validShader()) return osg::ref_ptr(rr.getShader()); if (rr.error()) OSG_WARN << rr.message() << std::endl; return NULL; } osg::ref_ptr osgDB::readRefHeightFieldFile(const std::string& filename,const Options* options) { ReaderWriter::ReadResult rr = Registry::instance()->readHeightField(filename,options); if (rr.validHeightField()) return osg::ref_ptr(rr.getHeightField()); if (rr.error()) OSG_WARN << rr.message() << std::endl; return NULL; } osg::ref_ptr osgDB::readRefNodeFile(const std::string& filename,const Options* options) { ReaderWriter::ReadResult rr = Registry::instance()->readNode(filename,options); if (rr.validNode()) return osg::ref_ptr(rr.getNode()); if (rr.error()) OSG_WARN << rr.message() << std::endl; return NULL; } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/StreamOperator.cpp0000644000175000017500000000305611723376200024470 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2011 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include using namespace osgDB; void InputIterator::readComponentArray( char* s, unsigned int numElements, unsigned int numComponentsPerElements, unsigned int componentSizeInBytes) { unsigned int size = numElements * numComponentsPerElements * componentSizeInBytes; if ( size>0 ) { readCharArray( s, size); if (_byteSwap && componentSizeInBytes>1) { char* ptr = s; for(unsigned int i=0; ithrowException(msg); else OSG_WARN << msg << std::endl; } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/Options.cpp0000644000175000017500000000406111732410624023150 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include using namespace osgDB; Options::Options(const Options& options,const osg::CopyOp& copyop): osg::Object(options,copyop), _str(options._str), _databasePaths(options._databasePaths), _objectCacheHint(options._objectCacheHint), _precisionHint(options._precisionHint), _buildKdTreesHint(options._buildKdTreesHint), _pluginData(options._pluginData), _pluginStringData(options._pluginStringData), _findFileCallback(options._findFileCallback), _readFileCallback(options._readFileCallback), _writeFileCallback(options._writeFileCallback), _fileLocationCallback(options._fileLocationCallback), _fileCache(options._fileCache), _terrain(options._terrain) {} void Options::parsePluginStringData(const std::string& str, char separator1, char separator2) { StringList valueList; split(str, valueList, separator1); if (valueList.size() > 0) { StringList keyAndValue; for (StringList::iterator itr=valueList.begin(); itr!=valueList.end(); ++itr) { split(*itr, keyAndValue, separator2); if (keyAndValue.size() > 1) { setPluginStringData(keyAndValue.front(), keyAndValue.back()); } else if (keyAndValue.size() > 0) { setPluginStringData(keyAndValue.front(), "true"); } keyAndValue.clear(); } } } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/ObjectWrapper.cpp0000644000175000017500000006302112352354071024267 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ // Written by Wang Rui, (C) 2010 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // pull in OSG headers to just introduce their GL defines for GL3/GLES compatibility #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef GL_PERSPECTIVE_CORRECTION_HINT #define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 #endif #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) #define GL_POLYGON_SMOOTH_HINT 0x0C53 #define GL_LINE_SMOOTH_HINT 0x0C52 #define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B #endif using namespace osgDB; void osgDB::split( const std::string& src, StringList& list, char separator ) { std::string::size_type start = src.find_first_not_of(separator); while ( start!=std::string::npos ) { std::string::size_type end = src.find_first_of(separator, start); if ( end!=std::string::npos ) { list.push_back( std::string(src, start, end-start) ); start = src.find_first_not_of(separator, end); } else { list.push_back( std::string(src, start, src.size()-start) ); start = end; } } } //////////////////////////////////////////////////////////////////////////////////////////////////////// // // ObjectWrapper // ObjectWrapper::ObjectWrapper( osg::Object* proto, const std::string& name, const std::string& associates ) : osg::Referenced(), _proto(proto), _name(name), _version(0) { split( associates, _associates ); } ObjectWrapper::ObjectWrapper( osg::Object* proto, const std::string& domain, const std::string& name, const std::string& associates ) : osg::Referenced(), _proto(proto), _domain(domain), _name(name), _version(0) { split( associates, _associates ); } void ObjectWrapper::addSerializer( BaseSerializer* s, BaseSerializer::Type t ) { s->_firstVersion = _version; _serializers.push_back(s); _typeList.push_back(static_cast(t)); } void ObjectWrapper::markSerializerAsRemoved( const std::string& name ) { for ( SerializerList::iterator itr=_serializers.begin(); itr!=_serializers.end(); ++itr ) { // When a serializer is marked as 'removed', it means that this serializer won't be used any more // from specified OSG version (by macro UPDATE_TO_VERSION). The read() functions of higher versions // will thus ignore it according to the sign and value of the _version variable. if ( (*itr)->getName()==name ) (*itr)->_lastVersion = _version-1; } } BaseSerializer* ObjectWrapper::getSerializer( const std::string& name ) { for ( SerializerList::iterator itr=_serializers.begin(); itr!=_serializers.end(); ++itr ) { if ( (*itr)->getName()==name ) return itr->get(); } for ( StringList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr ) { const std::string& assocName = *itr; ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName); if ( !assocWrapper ) { osg::notify(osg::WARN) << "ObjectWrapper::getSerializer(): Unsupported associated class " << assocName << std::endl; continue; } for ( SerializerList::iterator aitr=assocWrapper->_serializers.begin(); aitr!=assocWrapper->_serializers.end(); ++aitr ) { if ( (*aitr)->getName()==name ) return aitr->get(); } } return NULL; } bool ObjectWrapper::read( InputStream& is, osg::Object& obj ) { bool readOK = true; int inputVersion = is.getFileVersion(_domain); for ( SerializerList::iterator itr=_serializers.begin(); itr!=_serializers.end(); ++itr ) { BaseSerializer* serializer = itr->get(); if ( serializer->_firstVersion <= inputVersion && inputVersion <= serializer->_lastVersion ) { if ( !serializer->read(is, obj) ) { OSG_WARN << "ObjectWrapper::read(): Error reading property " << _name << "::" << (*itr)->getName() << std::endl; readOK = false; } } else { // OSG_NOTICE<<"Ignoring serializer due to version mismatch"<objectRead(is, obj); } return readOK; } bool ObjectWrapper::write( OutputStream& os, const osg::Object& obj ) { bool writeOK = true; int outputVersion = os.getFileVersion(_domain); for ( SerializerList::iterator itr=_serializers.begin(); itr!=_serializers.end(); ++itr ) { BaseSerializer* serializer = itr->get(); if ( serializer->_firstVersion <= outputVersion && outputVersion <= serializer->_lastVersion ) { if ( !serializer->write(os, obj) ) { OSG_WARN << "ObjectWrapper::write(): Error writing property " << _name << "::" << (*itr)->getName() << std::endl; writeOK = false; } } else { // OSG_NOTICE<<"Ignoring serializer due to version mismatch"<& ) { // FIXME: At present, I didn't do anything to determine serializers from their types... if ( !_backupSerializers.size() ) _backupSerializers = _serializers; _serializers.clear(); unsigned int size = properties.size(); unsigned int serializersSize = _backupSerializers.size(); for ( unsigned int i=0; igetName() ) { _serializers.push_back( _backupSerializers[i] ); } else { bool hasSerializer = false; for ( SerializerList::iterator itr=_backupSerializers.begin(); itr!=_backupSerializers.end(); ++itr ) { if ( prop!=(*itr)->getName() ) continue; _serializers.push_back( *itr ); hasSerializer = true; } if ( !hasSerializer ) { OSG_WARN << "ObjectWrapper::readSchema(): Wrapper " << _name << ": Unknown property " << prop << std::endl; } } } return size==_serializers.size(); } void ObjectWrapper::writeSchema( StringList& properties, std::vector& types ) { for ( SerializerList::iterator itr=_serializers.begin(); itr!=_serializers.end(); ++itr ) { properties.push_back( (*itr)->getName() ); } for ( std::vector::iterator itr=_typeList.begin(); itr!=_typeList.end(); ++itr ) { types.push_back( (*itr) ); } } //////////////////////////////////////////////////////////////////////////////////////////////////////// // // RegisterWrapperProxy // RegisterWrapperProxy::RegisterWrapperProxy( osg::Object* proto, const std::string& name, const std::string& associates, AddPropFunc func ) { _wrapper = new ObjectWrapper( proto, name, associates ); if ( func ) (*func)( _wrapper.get() ); if (Registry::instance()) { Registry::instance()->getObjectWrapperManager()->addWrapper( _wrapper.get() ); } } RegisterWrapperProxy::~RegisterWrapperProxy() { if (Registry::instance()) { Registry::instance()->getObjectWrapperManager()->removeWrapper( _wrapper.get() ); } } //////////////////////////////////////////////////////////////////////////////////////////////////////// // // RegisterCustomWrapperProxy // RegisterCustomWrapperProxy::RegisterCustomWrapperProxy( osg::Object* proto, const std::string& domain, const std::string& name, const std::string& associates, AddPropFunc func ) { _wrapper = new ObjectWrapper( proto, domain, name, associates ); if ( func ) (*func)( domain.c_str(), _wrapper.get() ); if (Registry::instance()) { Registry::instance()->getObjectWrapperManager()->addWrapper( _wrapper.get() ); } } RegisterCustomWrapperProxy::~RegisterCustomWrapperProxy() { if (Registry::instance()) { Registry::instance()->getObjectWrapperManager()->removeWrapper( _wrapper.get() ); } } //////////////////////////////////////////////////////////////////////////////////////////////////////// // // ObjectWrapperManager // //////////////////////////////////////////////////////////////////////////////////////////////////////// // // GlobalLookupTable // ObjectWrapperManager::ObjectWrapperManager() { IntLookup& glTable = _globalMap["GL"]; // Modes glTable.add( "GL_ALPHA_TEST", GL_ALPHA_TEST ); glTable.add( "GL_BLEND", GL_BLEND ); glTable.add( "GL_COLOR_LOGIC_OP", GL_COLOR_LOGIC_OP ); glTable.add( "GL_COLOR_MATERIAL", GL_COLOR_MATERIAL ); glTable.add( "GL_CULL_FACE", GL_CULL_FACE ); glTable.add( "GL_DEPTH_TEST", GL_DEPTH_TEST ); glTable.add( "GL_FOG", GL_FOG ); glTable.add( "GL_FRAGMENT_PROGRAM_ARB", GL_FRAGMENT_PROGRAM_ARB ); glTable.add( "GL_LINE_STIPPLE", GL_LINE_STIPPLE ); glTable.add( "GL_POINT_SMOOTH", GL_POINT_SMOOTH ); glTable.add( "GL_POINT_SPRITE_ARB", GL_POINT_SPRITE_ARB ); glTable.add( "GL_POLYGON_OFFSET_FILL", GL_POLYGON_OFFSET_FILL ); glTable.add( "GL_POLYGON_OFFSET_LINE", GL_POLYGON_OFFSET_LINE ); glTable.add( "GL_POLYGON_OFFSET_POINT", GL_POLYGON_OFFSET_POINT ); glTable.add( "GL_POLYGON_STIPPLE", GL_POLYGON_STIPPLE ); glTable.add( "GL_SCISSOR_TEST", GL_SCISSOR_TEST); glTable.add( "GL_STENCIL_TEST", GL_STENCIL_TEST ); glTable.add( "GL_STENCIL_TEST_TWO_SIDE", GL_STENCIL_TEST_TWO_SIDE ); glTable.add( "GL_VERTEX_PROGRAM_ARB", GL_VERTEX_PROGRAM_ARB ); glTable.add( "GL_COLOR_SUM", GL_COLOR_SUM ); glTable.add( "GL_LIGHTING", GL_LIGHTING ); glTable.add( "GL_NORMALIZE", GL_NORMALIZE ); glTable.add( "GL_RESCALE_NORMAL", GL_RESCALE_NORMAL ); glTable.add( "GL_TEXTURE_1D", GL_TEXTURE_1D ); glTable.add( "GL_TEXTURE_2D", GL_TEXTURE_2D ); glTable.add( "GL_TEXTURE_3D", GL_TEXTURE_3D ); glTable.add( "GL_TEXTURE_CUBE_MAP", GL_TEXTURE_CUBE_MAP ); glTable.add( "GL_TEXTURE_RECTANGLE", GL_TEXTURE_RECTANGLE ); glTable.add( "GL_TEXTURE_GEN_Q", GL_TEXTURE_GEN_Q ); glTable.add( "GL_TEXTURE_GEN_R", GL_TEXTURE_GEN_R ); glTable.add( "GL_TEXTURE_GEN_S", GL_TEXTURE_GEN_S ); glTable.add( "GL_TEXTURE_GEN_T", GL_TEXTURE_GEN_T ); glTable.add( "GL_CLIP_PLANE0", GL_CLIP_PLANE0 ); glTable.add( "GL_CLIP_PLANE1", GL_CLIP_PLANE1 ); glTable.add( "GL_CLIP_PLANE2", GL_CLIP_PLANE2 ); glTable.add( "GL_CLIP_PLANE3", GL_CLIP_PLANE3 ); glTable.add( "GL_CLIP_PLANE4", GL_CLIP_PLANE4 ); glTable.add( "GL_CLIP_PLANE5", GL_CLIP_PLANE5 ); glTable.add( "GL_LIGHT0", GL_LIGHT0 ); glTable.add( "GL_LIGHT1", GL_LIGHT1 ); glTable.add( "GL_LIGHT2", GL_LIGHT2 ); glTable.add( "GL_LIGHT3", GL_LIGHT3 ); glTable.add( "GL_LIGHT4", GL_LIGHT4 ); glTable.add( "GL_LIGHT5", GL_LIGHT5 ); glTable.add( "GL_LIGHT6", GL_LIGHT6 ); glTable.add( "GL_LIGHT7", GL_LIGHT7 ); glTable.add("GL_VERTEX_PROGRAM_POINT_SIZE", GL_VERTEX_PROGRAM_POINT_SIZE); glTable.add("GL_VERTEX_PROGRAM_TWO_SIDE", GL_VERTEX_PROGRAM_TWO_SIDE); // Functions glTable.add( "NEVER", GL_NEVER ); glTable.add( "LESS", GL_LESS ); glTable.add( "EQUAL", GL_EQUAL ); glTable.add( "LEQUAL", GL_LEQUAL ); glTable.add( "GREATER", GL_GREATER ); glTable.add( "NOTEQUAL", GL_NOTEQUAL ); glTable.add( "GEQUAL", GL_GEQUAL ); glTable.add( "ALWAYS", GL_ALWAYS ); // Texture environment states glTable.add( "REPLACE", GL_REPLACE ); glTable.add( "MODULATE", GL_MODULATE ); glTable.add( "ADD", GL_ADD ); glTable.add( "ADD_SIGNED", GL_ADD_SIGNED_ARB ); glTable.add( "INTERPOLATE", GL_INTERPOLATE_ARB ); glTable.add( "SUBTRACT", GL_SUBTRACT_ARB ); glTable.add( "DOT3_RGB", GL_DOT3_RGB_ARB ); glTable.add( "DOT3_RGBA", GL_DOT3_RGBA_ARB ); glTable.add( "CONSTANT", GL_CONSTANT_ARB ); glTable.add( "PRIMARY_COLOR", GL_PRIMARY_COLOR_ARB ); glTable.add( "PREVIOUS", GL_PREVIOUS_ARB ); glTable.add( "TEXTURE", GL_TEXTURE ); glTable.add( "TEXTURE0", GL_TEXTURE0 ); glTable.add( "TEXTURE1", GL_TEXTURE0+1 ); glTable.add( "TEXTURE2", GL_TEXTURE0+2 ); glTable.add( "TEXTURE3", GL_TEXTURE0+3 ); glTable.add( "TEXTURE4", GL_TEXTURE0+4 ); glTable.add( "TEXTURE5", GL_TEXTURE0+5 ); glTable.add( "TEXTURE6", GL_TEXTURE0+6 ); glTable.add( "TEXTURE7", GL_TEXTURE0+7 ); // Texture clamp modes glTable.add( "CLAMP", GL_CLAMP ); glTable.add( "CLAMP_TO_EDGE", GL_CLAMP_TO_EDGE ); glTable.add( "CLAMP_TO_BORDER", GL_CLAMP_TO_BORDER_ARB ); glTable.add( "REPEAT", GL_REPEAT ); glTable.add( "MIRROR", GL_MIRRORED_REPEAT_IBM ); // Texture filter modes glTable.add( "LINEAR", GL_LINEAR ); glTable.add( "LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR ); glTable.add( "LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST ); glTable.add( "NEAREST", GL_NEAREST ); glTable.add( "NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR ); glTable.add( "NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST ); // Texture formats glTable.add( "GL_INTENSITY", GL_INTENSITY ); glTable.add( "GL_LUMINANCE", GL_LUMINANCE ); glTable.add( "GL_ALPHA", GL_ALPHA ); glTable.add( "GL_LUMINANCE_ALPHA", GL_LUMINANCE_ALPHA ); glTable.add( "GL_RGB", GL_RGB ); glTable.add( "GL_RGBA", GL_RGBA ); glTable.add( "GL_COMPRESSED_ALPHA_ARB", GL_COMPRESSED_ALPHA_ARB ); glTable.add( "GL_COMPRESSED_LUMINANCE_ARB", GL_COMPRESSED_LUMINANCE_ARB ); glTable.add( "GL_COMPRESSED_INTENSITY_ARB", GL_COMPRESSED_INTENSITY_ARB ); glTable.add( "GL_COMPRESSED_LUMINANCE_ALPHA_ARB", GL_COMPRESSED_LUMINANCE_ALPHA_ARB ); glTable.add( "GL_COMPRESSED_RGB_ARB", GL_COMPRESSED_RGB_ARB ); glTable.add( "GL_COMPRESSED_RGBA_ARB", GL_COMPRESSED_RGBA_ARB ); glTable.add( "GL_COMPRESSED_RGB_S3TC_DXT1_EXT", GL_COMPRESSED_RGB_S3TC_DXT1_EXT ); glTable.add( "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT", GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ); glTable.add( "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT", GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ); glTable.add( "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT", GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ); glTable.add( "GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG",GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG ); glTable.add( "GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG",GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG ); glTable.add( "GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG",GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG ); glTable.add( "GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG",GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG ); glTable.add( "GL_ETC1_RGB8_OES",GL_ETC1_RGB8_OES ); // Texture source types glTable.add( "GL_BYTE", GL_BYTE ); glTable.add( "GL_SHORT", GL_SHORT ); glTable.add( "GL_INT", GL_INT ); glTable.add( "GL_FLOAT", GL_FLOAT ); glTable.add( "GL_DOUBLE", GL_DOUBLE ); glTable.add( "GL_UNSIGNED_BYTE", GL_UNSIGNED_BYTE ); glTable.add( "GL_UNSIGNED_SHORT", GL_UNSIGNED_SHORT ); glTable.add( "GL_UNSIGNED_INT", GL_UNSIGNED_INT ); // Blend values glTable.add( "DST_ALPHA", GL_DST_ALPHA ); glTable.add( "DST_COLOR", GL_DST_COLOR ); glTable.add( "ONE", GL_ONE ); glTable.add( "ONE_MINUS_DST_ALPHA", GL_ONE_MINUS_DST_ALPHA ); glTable.add( "ONE_MINUS_DST_COLOR", GL_ONE_MINUS_DST_COLOR ); glTable.add( "ONE_MINUS_SRC_ALPHA", GL_ONE_MINUS_SRC_ALPHA ); glTable.add( "ONE_MINUS_SRC_COLOR", GL_ONE_MINUS_SRC_COLOR ); glTable.add( "SRC_ALPHA", GL_SRC_ALPHA ); glTable.add( "SRC_ALPHA_SATURATE", GL_SRC_ALPHA_SATURATE ); glTable.add( "SRC_COLOR", GL_SRC_COLOR ); glTable.add( "CONSTANT_COLOR", GL_CONSTANT_COLOR ); glTable.add( "ONE_MINUS_CONSTANT_COLOR", GL_ONE_MINUS_CONSTANT_COLOR ); glTable.add( "CONSTANT_ALPHA", GL_CONSTANT_ALPHA ); glTable.add( "ONE_MINUS_CONSTANT_ALPHA", GL_ONE_MINUS_CONSTANT_ALPHA ); glTable.add( "ZERO", GL_ZERO ); // Fog coordinate sources glTable.add( "COORDINATE", GL_FOG_COORDINATE ); glTable.add( "DEPTH", GL_FRAGMENT_DEPTH ); // Hint targets glTable.add( "FOG_HINT", GL_FOG_HINT ); glTable.add( "GENERATE_MIPMAP_HINT", GL_GENERATE_MIPMAP_HINT_SGIS ); glTable.add( "LINE_SMOOTH_HINT", GL_LINE_SMOOTH_HINT ); glTable.add( "PERSPECTIVE_CORRECTION_HINT", GL_PERSPECTIVE_CORRECTION_HINT ); glTable.add( "POINT_SMOOTH_HINT", GL_POINT_SMOOTH_HINT ); glTable.add( "POLYGON_SMOOTH_HINT", GL_POLYGON_SMOOTH_HINT ); glTable.add( "TEXTURE_COMPRESSION_HINT", GL_TEXTURE_COMPRESSION_HINT_ARB ); glTable.add( "FRAGMENT_SHADER_DERIVATIVE_HINT", GL_FRAGMENT_SHADER_DERIVATIVE_HINT ); // Polygon modes glTable.add( "POINT", GL_POINT ); glTable.add( "LINE", GL_LINE ); glTable.add( "FILL", GL_FILL ); // Misc glTable.add( "BACK", GL_BACK ); glTable.add( "FRONT", GL_FRONT ); glTable.add( "FRONT_AND_BACK", GL_FRONT_AND_BACK ); glTable.add( "FIXED_ONLY", GL_FIXED_ONLY ); glTable.add( "FASTEST", GL_FASTEST ); glTable.add( "NICEST", GL_NICEST ); glTable.add( "DONT_CARE", GL_DONT_CARE ); IntLookup& arrayTable = _globalMap["ArrayType"]; arrayTable.add( "ByteArray", ID_BYTE_ARRAY ); arrayTable.add( "UByteArray", ID_UBYTE_ARRAY ); arrayTable.add( "ShortArray", ID_SHORT_ARRAY ); arrayTable.add( "UShortArray", ID_USHORT_ARRAY ); arrayTable.add( "IntArray", ID_INT_ARRAY ); arrayTable.add( "UIntArray", ID_UINT_ARRAY ); arrayTable.add( "FloatArray", ID_FLOAT_ARRAY ); arrayTable.add( "DoubleArray", ID_DOUBLE_ARRAY ); arrayTable.add( "Vec2bArray", ID_VEC2B_ARRAY ); arrayTable.add( "Vec3bArray", ID_VEC3B_ARRAY ); arrayTable.add( "Vec4bArray", ID_VEC4B_ARRAY ); arrayTable.add( "Vec2ubArray", ID_VEC2UB_ARRAY ); arrayTable.add( "Vec3ubArray", ID_VEC3UB_ARRAY ); arrayTable.add( "Vec4ubArray", ID_VEC4UB_ARRAY ); arrayTable.add( "Vec2sArray", ID_VEC2S_ARRAY ); arrayTable.add( "Vec3sArray", ID_VEC3S_ARRAY ); arrayTable.add( "Vec4sArray", ID_VEC4S_ARRAY ); arrayTable.add( "Vec2usArray", ID_VEC2US_ARRAY ); arrayTable.add( "Vec3usArray", ID_VEC3US_ARRAY ); arrayTable.add( "Vec4usArray", ID_VEC4US_ARRAY ); arrayTable.add( "Vec2fArray", ID_VEC2_ARRAY ); arrayTable.add( "Vec3fArray", ID_VEC3_ARRAY ); arrayTable.add( "Vec4fArray", ID_VEC4_ARRAY ); arrayTable.add( "Vec2dArray", ID_VEC2D_ARRAY ); arrayTable.add( "Vec3dArray", ID_VEC3D_ARRAY ); arrayTable.add( "Vec4dArray", ID_VEC4D_ARRAY ); IntLookup& primitiveTable = _globalMap["PrimitiveType"]; primitiveTable.add( "DrawArrays", ID_DRAWARRAYS ); primitiveTable.add( "DrawArraysLength", ID_DRAWARRAY_LENGTH ); primitiveTable.add( "DrawElementsUByte", ID_DRAWELEMENTS_UBYTE ); primitiveTable.add( "DrawElementsUShort", ID_DRAWELEMENTS_USHORT ); primitiveTable.add( "DrawElementsUInt", ID_DRAWELEMENTS_UINT ); primitiveTable.add( "GL_POINTS", GL_POINTS ); primitiveTable.add( "GL_LINES", GL_LINES ); primitiveTable.add( "GL_LINE_STRIP", GL_LINE_STRIP ); primitiveTable.add( "GL_LINE_LOOP", GL_LINE_LOOP ); primitiveTable.add( "GL_TRIANGLES", GL_TRIANGLES ); primitiveTable.add( "GL_TRIANGLE_STRIP", GL_TRIANGLE_STRIP ); primitiveTable.add( "GL_TRIANGLE_FAN", GL_TRIANGLE_FAN ); primitiveTable.add( "GL_QUADS", GL_QUADS ); primitiveTable.add( "GL_QUAD_STRIP", GL_QUAD_STRIP ); primitiveTable.add( "GL_POLYGON", GL_POLYGON ); primitiveTable.add( "GL_LINES_ADJACENCY_EXT", GL_LINES_ADJACENCY_EXT ); primitiveTable.add( "GL_LINE_STRIP_ADJACENCY_EXT", GL_LINE_STRIP_ADJACENCY_EXT ); primitiveTable.add( "GL_TRIANGLES_ADJACENCY_EXT", GL_TRIANGLES_ADJACENCY_EXT ); primitiveTable.add( "GL_TRIANGLE_STRIP_ADJACENCY_EXT", GL_TRIANGLE_STRIP_ADJACENCY_EXT ); primitiveTable.add( "GL_PATCHES", GL_PATCHES ); } ObjectWrapperManager::~ObjectWrapperManager() { } void ObjectWrapperManager::addWrapper( ObjectWrapper* wrapper ) { if ( !wrapper ) return; WrapperMap::iterator itr = _wrappers.find( wrapper->getName() ); if ( itr!=_wrappers.end() ) { OSG_WARN << "ObjectWrapperManager::addWrapper(): '" << wrapper->getName() << "' already exists." << std::endl; } _wrappers[wrapper->getName()] = wrapper; } void ObjectWrapperManager::removeWrapper( ObjectWrapper* wrapper ) { if ( !wrapper ) return; WrapperMap::iterator itr = _wrappers.find( wrapper->getName() ); if ( itr!=_wrappers.end() ) _wrappers.erase( itr ); } ObjectWrapper* ObjectWrapperManager::findWrapper( const std::string& name ) { WrapperMap::iterator itr = _wrappers.find( name ); if ( itr!=_wrappers.end() ) return itr->second.get(); // Load external libraries std::string::size_type posDoubleColon = name.rfind("::"); if ( posDoubleColon!=std::string::npos ) { std::string libName = std::string( name, 0, posDoubleColon ); std::string nodeKitLib = osgDB::Registry::instance()->createLibraryNameForNodeKit(libName); if ( osgDB::Registry::instance()->loadLibrary(nodeKitLib)==osgDB::Registry::LOADED ) return findWrapper(name); std::string pluginLib = osgDB::Registry::instance()->createLibraryNameForExtension(std::string("serializers_")+libName); if ( osgDB::Registry::instance()->loadLibrary(pluginLib)==osgDB::Registry::LOADED ) return findWrapper(name); pluginLib = osgDB::Registry::instance()->createLibraryNameForExtension(libName); if ( osgDB::Registry::instance()->loadLibrary(pluginLib)==osgDB::Registry::LOADED ) return findWrapper(name); } return NULL; } void ObjectWrapperManager::addCompressor( BaseCompressor* compressor ) { if ( !compressor ) return; CompressorMap::iterator itr = _compressors.find( compressor->getName() ); if ( itr!=_compressors.end() ) { OSG_WARN << "ObjectWrapperManager::addCompressor(): '" << compressor->getName() << "' already exists." << std::endl; } _compressors[compressor->getName()] = compressor; } void ObjectWrapperManager::removeCompressor( BaseCompressor* compressor ) { if ( !compressor ) return; CompressorMap::iterator itr = _compressors.find( compressor->getName() ); if ( itr!=_compressors.end() ) _compressors.erase( itr ); } BaseCompressor* ObjectWrapperManager::findCompressor( const std::string& name ) { CompressorMap::iterator itr = _compressors.find( name ); if ( itr!=_compressors.end() ) return itr->second.get(); // Load external libraries std::string nodeKitLib = osgDB::Registry::instance()->createLibraryNameForNodeKit(name); if ( osgDB::Registry::instance()->loadLibrary(nodeKitLib)==osgDB::Registry::LOADED ) return findCompressor(name); std::string pluginLib = osgDB::Registry::instance()->createLibraryNameForExtension(std::string("compressor_")+name); if ( osgDB::Registry::instance()->loadLibrary(pluginLib)==osgDB::Registry::LOADED ) return findCompressor(name); pluginLib = osgDB::Registry::instance()->createLibraryNameForExtension(name); if ( osgDB::Registry::instance()->loadLibrary(pluginLib)==osgDB::Registry::LOADED ) return findCompressor(name); return NULL; } //////////////////////////////////////////////////////////////////////////////////////////////////////// // // RegisytrCompressorProxy // RegisterCompressorProxy::RegisterCompressorProxy( const std::string& name, BaseCompressor* compressor ): _compressor(compressor) { _compressor->setName( name ); if (Registry::instance()) { Registry::instance()->getObjectWrapperManager()->addCompressor( _compressor.get() ); } } RegisterCompressorProxy::~RegisterCompressorProxy() { if (Registry::instance()) { Registry::instance()->getObjectWrapperManager()->removeCompressor( _compressor.get() ); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/Callbacks.cpp0000644000175000017500000001004311732410624023371 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include using namespace osgDB; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // FindFileCallback default implementation // std::string FindFileCallback::findDataFile(const std::string& filename, const Options* options, CaseSensitivity caseSensitivity) { return osgDB::Registry::instance()->findDataFileImplementation(filename, options, caseSensitivity); } std::string FindFileCallback::findLibraryFile(const std::string& filename, const Options* options, CaseSensitivity caseSensitivity) { return osgDB::Registry::instance()->findLibraryFileImplementation(filename, options, caseSensitivity); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // ReadFileCallback default implementation // ReaderWriter::ReadResult ReadFileCallback::openArchive(const std::string& filename,ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint, const Options* useObjectCache) { return osgDB::Registry::instance()->openArchiveImplementation(filename, status, indexBlockSizeHint, useObjectCache); } ReaderWriter::ReadResult ReadFileCallback::readObject(const std::string& filename, const Options* options) { return osgDB::Registry::instance()->readObjectImplementation(filename,options); } ReaderWriter::ReadResult ReadFileCallback::readImage(const std::string& filename, const Options* options) { return osgDB::Registry::instance()->readImageImplementation(filename,options); } ReaderWriter::ReadResult ReadFileCallback::readHeightField(const std::string& filename, const Options* options) { return osgDB::Registry::instance()->readHeightFieldImplementation(filename,options); } ReaderWriter::ReadResult ReadFileCallback::readNode(const std::string& filename, const Options* options) { return osgDB::Registry::instance()->readNodeImplementation(filename,options); } ReaderWriter::ReadResult ReadFileCallback::readShader(const std::string& filename, const Options* options) { return osgDB::Registry::instance()->readShaderImplementation(filename,options); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // WriteFileCallback default implementation // ReaderWriter::WriteResult WriteFileCallback::writeObject(const osg::Object& obj, const std::string& fileName,const Options* options) { return osgDB::Registry::instance()->writeObjectImplementation(obj,fileName,options); } ReaderWriter::WriteResult WriteFileCallback::writeImage(const osg::Image& obj, const std::string& fileName,const Options* options) { return osgDB::Registry::instance()->writeImageImplementation(obj,fileName,options); } ReaderWriter::WriteResult WriteFileCallback::writeHeightField(const osg::HeightField& obj, const std::string& fileName,const Options* options) { return osgDB::Registry::instance()->writeHeightFieldImplementation(obj,fileName,options); } ReaderWriter::WriteResult WriteFileCallback::writeNode(const osg::Node& obj, const std::string& fileName,const Options* options) { return osgDB::Registry::instance()->writeNodeImplementation(obj,fileName,options); } ReaderWriter::WriteResult WriteFileCallback::writeShader(const osg::Shader& obj, const std::string& fileName,const Options* options) { return osgDB::Registry::instance()->writeShaderImplementation(obj,fileName,options); } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/WriteFile.cpp0000644000175000017500000000476511732410624023422 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include using namespace osg; using namespace osgDB; bool osgDB::writeObjectFile(const Object& object,const std::string& filename, const Options* options ) { ReaderWriter::WriteResult wr = Registry::instance()->writeObject( object, filename, options ); if (wr.error()) OSG_WARN << "Error writing file " << filename << ": " << wr.message() << std::endl; return wr.success(); } bool osgDB::writeImageFile(const Image& image,const std::string& filename, const Options* options ) { ReaderWriter::WriteResult wr = Registry::instance()->writeImage( image, filename, options ); if (wr.error()) OSG_WARN << "Error writing file " << filename << ": " << wr.message() << std::endl; return wr.success(); } bool osgDB::writeHeightFieldFile(const HeightField& HeightField,const std::string& filename, const Options* options ) { ReaderWriter::WriteResult wr = Registry::instance()->writeHeightField( HeightField, filename, options ); if (wr.error()) OSG_WARN << "Error writing file " << filename << ": " << wr.message() << std::endl; return wr.success(); } bool osgDB::writeNodeFile(const Node& node,const std::string& filename, const Options* options ) { ReaderWriter::WriteResult wr = Registry::instance()->writeNode( node, filename, options ); if (wr.error()) OSG_WARN << "Error writing file " << filename << ": " << wr.message() << std::endl; return wr.success(); } bool osgDB::writeShaderFile(const Shader& shader,const std::string& filename, const Options* options ) { ReaderWriter::WriteResult wr = Registry::instance()->writeShader( shader, filename, options ); if (wr.error()) OSG_WARN << "Error writing file " << filename << ": " << wr.message() << std::endl; return wr.success(); } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/FieldReader.cpp0000644000175000017500000002036211732410624023665 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include using namespace osgDB; FieldReader::FieldReader() { _init(); } FieldReader::FieldReader(const FieldReader& ic) { _copy(ic); } FieldReader::~FieldReader() { _free(); } FieldReader& FieldReader::operator = (const FieldReader& ic) { if (this==&ic) return *this; _free(); _copy(ic); return *this; } void FieldReader::_free() { // free all data _init(); } void FieldReader::_init() { _fin = NULL; _eof = true; _noNestedBrackets = 0; int i; for(i=0;i<256;++i) _delimiterEatLookUp[i]=false; _delimiterEatLookUp[int(' ')] = true; _delimiterEatLookUp[int('\t')] = true; _delimiterEatLookUp[int('\n')] = true; _delimiterEatLookUp[int('\r')] = true; for(i=0;i<256;++i) _delimiterKeepLookUp[i]=false; _delimiterKeepLookUp[int('{')] = true; _delimiterKeepLookUp[int('}')] = true; _delimiterKeepLookUp[int('"')] = true; _delimiterKeepLookUp[int('\'')] = true; } void FieldReader::_copy(const FieldReader& ic) { _fin = ic._fin; _eof = ic._eof; _noNestedBrackets = ic._noNestedBrackets; int i; for(i=0;i<256;++i) _delimiterEatLookUp[i]=ic._delimiterEatLookUp[i]; for(i=0;i<256;++i) _delimiterKeepLookUp[i]=ic._delimiterKeepLookUp[i]; } void FieldReader::attach(std::istream* input) { _fin = input; if (_fin) { _eof = _fin->eof()!=0; } else { _eof = true; } } void FieldReader::detach() { _fin = NULL; _eof = true; } bool FieldReader::eof() const { return _eof; } bool FieldReader::findStartOfNextField() { int ch = 0; while (true) { ch = _fin->peek(); if (ch==EOF) { _eof = true; return false; } else if (_delimiterEatLookUp[ch]) { _fin->ignore(1); } else { return true; } } } bool FieldReader::readField(Field& fieldPtr) { return _readField(&fieldPtr); } void FieldReader::ignoreField() { _readField(NULL); } bool FieldReader::_readField(Field* fieldPtr) { if (fieldPtr) fieldPtr->reset(); if (!eof() && findStartOfNextField()) { int ch = _fin->peek(); if (ch==EOF) { _eof = true; if (fieldPtr) fieldPtr->setNoNestedBrackets(getNoNestedBrackets()); return fieldPtr && fieldPtr->getNoCharacters()!=0; } else if (ch=='"') { if (fieldPtr) { fieldPtr->setWithinQuotes(true); fieldPtr->setNoNestedBrackets(getNoNestedBrackets()); } _fin->ignore(1); char c; bool escape = false; // use the escape character sequence \" to allow " to included in strings. while (true) { ch = _fin->peek(); if (ch==EOF) { _eof = true; return fieldPtr && fieldPtr->getNoCharacters()!=0; } c = ch; if (ch=='\\') { if (escape) { escape = false; _fin->get(c); if (fieldPtr) fieldPtr->addChar(c); } else { escape = true; _fin->ignore(1); } } else if (ch=='"') { if (escape) { escape = false; _fin->get(c); if (fieldPtr) fieldPtr->addChar(c); } else { _fin->ignore(1); //return fieldPtr && fieldPtr->getNoCharacters()!=0; return fieldPtr!=NULL; } } else { if (escape) { escape = false; if (fieldPtr) fieldPtr->addChar('\\'); } _fin->get(c); if (fieldPtr) fieldPtr->addChar(c); } } } else if (ch=='\'') { if (fieldPtr) { fieldPtr->setWithinQuotes(true); fieldPtr->setNoNestedBrackets(getNoNestedBrackets()); } _fin->ignore(1); char c; bool escape = false; // use the escape character sequence \' to allow ' to included in strings. while (true) { ch = _fin->peek(); if (ch==EOF) { _eof = true; return fieldPtr && fieldPtr->getNoCharacters()!=0; } c = ch; if (ch=='\\' && !escape) { if (escape) { escape = false; _fin->get(c); if (fieldPtr) fieldPtr->addChar(c); } else { escape = true; _fin->ignore(1); } } else if (ch=='\'') { if (escape) { escape = false; _fin->get(c); if (fieldPtr) fieldPtr->addChar(c); } else { _fin->ignore(1); //return fieldPtr && fieldPtr->getNoCharacters()!=0; return fieldPtr!=NULL; } } else { if (escape) { escape = false; if (fieldPtr) fieldPtr->addChar('\\'); } _fin->get(c); if (fieldPtr) fieldPtr->addChar(c); } } } else if (_delimiterKeepLookUp[ch]) { char c; _fin->get(c); if (fieldPtr) fieldPtr->addChar(c); if (c=='{') ++_noNestedBrackets; else if (c=='}') --_noNestedBrackets; if (fieldPtr) fieldPtr->setNoNestedBrackets(getNoNestedBrackets()); return fieldPtr && fieldPtr->getNoCharacters()!=0; } else { if (fieldPtr) fieldPtr->setNoNestedBrackets(getNoNestedBrackets()); char c; while (true) { ch = _fin->peek(); if (ch==EOF) { _eof = true; return fieldPtr && fieldPtr->getNoCharacters()!=0; } c = ch; if (_delimiterEatLookUp[int(c)]) { _fin->ignore(1); return fieldPtr && fieldPtr->getNoCharacters()!=0; } if (_delimiterKeepLookUp[int(c)]) { return fieldPtr && fieldPtr->getNoCharacters()!=0; } else { _fin->get(c); if (fieldPtr) fieldPtr->addChar(c); } } } } else { return false; } } int FieldReader::getNoNestedBrackets() const { return _noNestedBrackets; } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/DotOsgWrapper.cpp0000644000175000017500000006113311732410624024260 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include using namespace osgDB; DotOsgWrapper::DotOsgWrapper(osg::Object* proto, const std::string& name, const std::string& associates, ReadFunc readFunc, WriteFunc writeFunc, ReadWriteMode readWriteMode) { _prototype = proto; _name = name; // copy the names in the space delimited associates input into // a vector of separated names. std::string::size_type start_of_name = associates.find_first_not_of(' '); while (start_of_name!=std::string::npos) { std::string::size_type end_of_name = associates.find_first_of(' ',start_of_name); if (end_of_name!=std::string::npos) { _associates.push_back(std::string(associates,start_of_name,end_of_name-start_of_name)); start_of_name = associates.find_first_not_of(' ',end_of_name); } else { _associates.push_back(std::string(associates,start_of_name,associates.size()-start_of_name)); start_of_name = end_of_name; } } _readFunc = readFunc; _writeFunc = writeFunc; _readWriteMode = readWriteMode; } RegisterDotOsgWrapperProxy::RegisterDotOsgWrapperProxy(osg::Object* proto, const std::string& name, const std::string& associates, DotOsgWrapper::ReadFunc readFunc, DotOsgWrapper::WriteFunc writeFunc, DotOsgWrapper::ReadWriteMode readWriteMode) { if (Registry::instance()) { _wrapper = new DotOsgWrapper(proto,name,associates,readFunc,writeFunc,readWriteMode); Registry::instance()->getDeprecatedDotOsgObjectWrapperManager()->addDotOsgWrapper(_wrapper.get()); } } RegisterDotOsgWrapperProxy::~RegisterDotOsgWrapperProxy() { if (Registry::instance()) { Registry::instance()->getDeprecatedDotOsgObjectWrapperManager()->removeDotOsgWrapper(_wrapper.get()); } } void DeprecatedDotOsgWrapperManager::addDotOsgWrapper(DotOsgWrapper* wrapper) { if (wrapper==0L) return; //OSG_INFO << "osg::Registry::addDotOsgWrapper("<getName()<<")"<< std::endl; const DotOsgWrapper::Associates& assoc = wrapper->getAssociates(); for(DotOsgWrapper::Associates::const_iterator itr=assoc.begin(); itr!=assoc.end(); ++itr) { //OSG_INFO << " ("<<*itr<<")"<< std::endl; } const std::string& name = wrapper->getName(); const osg::Object* proto = wrapper->getPrototype(); _objectWrapperMap[name] = wrapper; if (wrapper->getReadWriteMode()==DotOsgWrapper::READ_AND_WRITE) _classNameWrapperMap[name] = wrapper; if (proto) { std::string libraryName = proto->libraryName(); std::string compositeName = libraryName + "::" + name; _objectWrapperMap[compositeName] = wrapper; if (wrapper->getReadWriteMode()==DotOsgWrapper::READ_AND_WRITE) _classNameWrapperMap[compositeName] = wrapper; if (dynamic_cast(proto)) { _imageWrapperMap[name] = wrapper; _imageWrapperMap[compositeName] = wrapper; } if (dynamic_cast(proto)) { _drawableWrapperMap[name] = wrapper; _drawableWrapperMap[compositeName] = wrapper; } if (dynamic_cast(proto)) { _stateAttrWrapperMap[name] = wrapper; _stateAttrWrapperMap[compositeName] = wrapper; } if (dynamic_cast(proto)) { _uniformWrapperMap[name] = wrapper; _uniformWrapperMap[compositeName] = wrapper; } if (dynamic_cast(proto)) { _nodeWrapperMap[name] = wrapper; _nodeWrapperMap[compositeName] = wrapper; } if (dynamic_cast(proto)) { _shaderWrapperMap[name] = wrapper; _shaderWrapperMap[compositeName] = wrapper; } } } // need to change to delete all instances of wrapper, since we // now can have a wrapper entered twice with the addition of the // library::class composite name. void DeprecatedDotOsgWrapperManager::eraseWrapper(DotOsgWrapperMap& wrappermap,DotOsgWrapper* wrapper) { typedef std::vector EraseList; EraseList eraseList; for(DotOsgWrapperMap::iterator witr=wrappermap.begin(); witr!=wrappermap.end(); ++witr) { if (witr->second==wrapper) eraseList.push_back(witr); } for(EraseList::iterator eitr=eraseList.begin(); eitr!=eraseList.end(); ++eitr) { wrappermap.erase(*eitr); } } void DeprecatedDotOsgWrapperManager::removeDotOsgWrapper(DotOsgWrapper* wrapper) { if (wrapper==0L) return; eraseWrapper(_objectWrapperMap,wrapper); eraseWrapper(_classNameWrapperMap,wrapper); eraseWrapper(_imageWrapperMap,wrapper); eraseWrapper(_drawableWrapperMap,wrapper); eraseWrapper(_uniformWrapperMap,wrapper); eraseWrapper(_stateAttrWrapperMap,wrapper); eraseWrapper(_nodeWrapperMap,wrapper); eraseWrapper(_shaderWrapperMap,wrapper); } struct concrete_wrapper: basic_type_wrapper { virtual ~concrete_wrapper() {} concrete_wrapper(const osg::Object *myobj) : myobj_(myobj) {} bool matches(const osg::Object *proto) const { return myobj_->isSameKindAs(proto); } const osg::Object *myobj_; }; osg::Object* DeprecatedDotOsgWrapperManager::readObjectOfType(const osg::Object& compObj,Input& fr) { return readObjectOfType(concrete_wrapper(&compObj), fr); } bool DeprecatedDotOsgWrapperManager::getLibraryFileNamesToTry(const std::string& name, FileNames& fileNames) { FileNames::size_type sizeBefore = fileNames.size(); std::string libraryName = osgDB::Registry::instance()->createLibraryNameForNodeKit(name); if (!libraryName.empty()) fileNames.push_back(libraryName); libraryName = osgDB::Registry::instance()->createLibraryNameForExtension(std::string("deprecated_")+name); if (!libraryName.empty()) fileNames.push_back(libraryName); libraryName = osgDB::Registry::instance()->createLibraryNameForExtension(name); if (!libraryName.empty()) fileNames.push_back(libraryName); return fileNames.size() != sizeBefore; } osg::Object* DeprecatedDotOsgWrapperManager::readObjectOfType(const basic_type_wrapper &btw,Input& fr) { const char *str = fr[0].getStr(); if (str==NULL) return NULL; if (fr[0].matchWord("Use")) { if (fr[1].isString()) { osg::Object* obj = fr.getObjectForUniqueID(fr[1].getStr()); if (obj && btw.matches(obj)) { fr+=2; return obj; } } else return NULL; } std::string name = str; DotOsgWrapperMap::iterator itr = _objectWrapperMap.find(name); if (itr==_objectWrapperMap.end()) { // not found so check if a library::class composite name. std::string token = fr[0].getStr(); std::string::size_type posDoubleColon = token.rfind("::"); if (posDoubleColon != std::string::npos) { // we have a composite name so now strip off the library name // are try to load it, and then retry the readObject to see // if we can recognize the objects. std::string libraryName = std::string(token,0,posDoubleColon); FileNames fileNames; if (getLibraryFileNamesToTry(libraryName, fileNames)) { for(FileNames::iterator itr = fileNames.begin(); itr != fileNames.end(); ++itr) { if (osgDB::Registry::instance()->loadLibrary(*itr)==osgDB::Registry::LOADED) return readObjectOfType(btw,fr); } } } } else if (fr[1].isOpenBracket()) { DotOsgWrapper* wrapper = itr->second.get(); const osg::Object* proto = wrapper->getPrototype(); if (proto==NULL) { OSG_WARN<<"Token "<getAssociates(); osg::Object* obj = proto->cloneType(); while(!fr.eof() && fr[0].getNoNestedBrackets()>entry) { bool iteratorAdvanced = false; if (fr[0].matchWord("UniqueID") && fr[1].isString()) { fr.registerUniqueIDForObject(fr[1].getStr(),obj); fr += 2; iteratorAdvanced = true; } // read the local data by iterating through the associate // list, mapping the associate names to DotOsgWrapper's which // in turn have the appropriate functions. for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin(); aitr!=assoc.end(); ++aitr) { DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr); if (mitr==_objectWrapperMap.end()) { // not found so check if a library::class composite name. std::string token = *aitr; std::string::size_type posDoubleColon = token.rfind("::"); if (posDoubleColon != std::string::npos) { // we have a composite name so now strip off the library name // and try to load it, and then retry the find to see // if we can recognize the objects. std::string libraryName = std::string(token,0,posDoubleColon); FileNames fileNames; if (getLibraryFileNamesToTry(libraryName, fileNames)) { for(FileNames::iterator itr = fileNames.begin(); itr != fileNames.end() && mitr==_objectWrapperMap.end(); ++itr) { if (osgDB::Registry::instance()->loadLibrary(*itr)==osgDB::Registry::LOADED) { mitr = _objectWrapperMap.find(*aitr); } } } } } if (mitr!=_objectWrapperMap.end()) { // get the function to read the data... DotOsgWrapper::ReadFunc rf = mitr->second->getReadFunc(); if (rf && (*rf)(*obj,fr)) iteratorAdvanced = true; } } if (!iteratorAdvanced) fr.advanceOverCurrentFieldOrBlock(); } ++fr; // step over trailing '}' return obj; } return 0L; } // // read object from input iterator. // osg::Object* DeprecatedDotOsgWrapperManager::readObject(DotOsgWrapperMap& dowMap,Input& fr) { const char *str = fr[0].getStr(); if (str==NULL) return NULL; std::string name = str; DotOsgWrapperMap::iterator itr = dowMap.find(name); if (itr==dowMap.end()) { // not found so check if a library::class composite name. std::string token = fr[0].getStr(); std::string::size_type posDoubleColon = token.rfind("::"); if (posDoubleColon != std::string::npos) { // we have a composite name so now strip off the library name // are try to load it, and then retry the readObject to see // if we can recognize the objects. std::string libraryName = std::string(token,0,posDoubleColon); FileNames fileNames; if (getLibraryFileNamesToTry(libraryName, fileNames)) { for(FileNames::iterator itr = fileNames.begin(); itr != fileNames.end(); ++itr) { if (osgDB::Registry::instance()->loadLibrary(*itr)==osgDB::Registry::LOADED) return readObject(dowMap,fr); } } } } else if (fr[1].isOpenBracket()) { DotOsgWrapper* wrapper = itr->second.get(); const osg::Object* proto = wrapper->getPrototype(); if (proto==NULL) { OSG_WARN<<"Token "<getAssociates(); osg::Object* obj = proto->cloneType(); while(!fr.eof() && fr[0].getNoNestedBrackets()>entry) { bool iteratorAdvanced = false; if (fr[0].matchWord("UniqueID") && fr[1].isString()) { fr.registerUniqueIDForObject(fr[1].getStr(),obj); fr += 2; iteratorAdvanced = true; } // read the local data by iterating through the associate // list, mapping the associate names to DotOsgWrapper's which // in turn have the appropriate functions. for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin(); aitr!=assoc.end(); ++aitr) { DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr); if (mitr==_objectWrapperMap.end()) { // not found so check if a library::class composite name. std::string token = *aitr; std::string::size_type posDoubleColon = token.rfind("::"); if (posDoubleColon != std::string::npos) { // we have a composite name so now strip off the library name // are try to load it, and then retry the find to see // if we can recognize the objects. std::string libraryName = std::string(token,0,posDoubleColon); FileNames fileNames; if (getLibraryFileNamesToTry(libraryName, fileNames)) { for(FileNames::iterator itr = fileNames.begin(); itr != fileNames.end() && mitr==_objectWrapperMap.end(); ++itr) { if (osgDB::Registry::instance()->loadLibrary(*itr)==osgDB::Registry::LOADED) { mitr = _objectWrapperMap.find(*aitr); } } } } } if (mitr!=_objectWrapperMap.end()) { // get the function to read the data... DotOsgWrapper::ReadFunc rf = mitr->second->getReadFunc(); if (rf && (*rf)(*obj,fr)) iteratorAdvanced = true; } } if (!iteratorAdvanced) fr.advanceOverCurrentFieldOrBlock(); } ++fr; // step over trailing '}' return obj; } return 0L; } // // read object from input iterator. // osg::Object* DeprecatedDotOsgWrapperManager::readObject(Input& fr) { if (fr[0].matchWord("Use")) { if (fr[1].isString()) { osg::Object* obj = fr.getObjectForUniqueID(fr[1].getStr()); if (obj) fr+=2; return obj; } else return NULL; } return readObject(_objectWrapperMap,fr); } // // read image from input iterator. // osg::Image* DeprecatedDotOsgWrapperManager::readImage(Input& fr) { if (fr[0].matchWord("Use")) { if (fr[1].isString()) { osg::Image* image = dynamic_cast(fr.getObjectForUniqueID(fr[1].getStr())); if (image) fr+=2; return image; } else return NULL; } osg::Object* obj = readObject(_imageWrapperMap,fr); osg::Image* image = dynamic_cast(obj); if (image) return image; else if (obj) obj->unref(); return NULL; } // // read drawable from input iterator. // osg::Drawable* DeprecatedDotOsgWrapperManager::readDrawable(Input& fr) { if (fr[0].matchWord("Use")) { if (fr[1].isString()) { osg::Drawable* drawable = dynamic_cast(fr.getObjectForUniqueID(fr[1].getStr())); if (drawable) fr+=2; return drawable; } else return NULL; } osg::Object* obj = readObject(_drawableWrapperMap,fr); osg::Drawable* drawable = dynamic_cast(obj); if (drawable) return drawable; else if (obj) obj->unref(); return NULL; } // // read drawable from input iterator. // osg::StateAttribute* DeprecatedDotOsgWrapperManager::readStateAttribute(Input& fr) { if (fr[0].matchWord("Use")) { if (fr[1].isString()) { osg::StateAttribute* attribute = dynamic_cast(fr.getObjectForUniqueID(fr[1].getStr())); if (attribute) fr+=2; return attribute; } else return NULL; } return dynamic_cast(readObject(_stateAttrWrapperMap,fr)); } // // read drawable from input iterator. // osg::Uniform* DeprecatedDotOsgWrapperManager::readUniform(Input& fr) { if (fr[0].matchWord("Use")) { if (fr[1].isString()) { osg::Uniform* attribute = dynamic_cast(fr.getObjectForUniqueID(fr[1].getStr())); if (attribute) fr+=2; return attribute; } else return NULL; } return dynamic_cast(readObject(_uniformWrapperMap,fr)); } // // read node from input iterator. // osg::Node* DeprecatedDotOsgWrapperManager::readNode(Input& fr) { if (fr[0].matchWord("Use")) { if (fr[1].isString()) { osg::Node* node = dynamic_cast(fr.getObjectForUniqueID(fr[1].getStr())); if (node) fr+=2; return node; } else return NULL; } osg::Object* obj = readObject(_nodeWrapperMap,fr); osg::Node* node = dynamic_cast(obj); if (node) return node; else if (obj) obj->unref(); return NULL; } // // read image from input iterator. // osg::Shader* DeprecatedDotOsgWrapperManager::readShader(Input& fr) { if (fr[0].matchWord("Use")) { if (fr[1].isString()) { osg::Shader* shader = dynamic_cast(fr.getObjectForUniqueID(fr[1].getStr())); if (shader) fr+=2; return shader; } else return NULL; } osg::Object* obj = readObject(_shaderWrapperMap,fr); osg::Shader* shader = dynamic_cast(obj); if (shader) return shader; else if (obj) obj->unref(); return NULL; } // // Write object to output // bool DeprecatedDotOsgWrapperManager::writeObject(const osg::Object& obj,Output& fw) { if (obj.referenceCount()>1) { std::string uniqueID; if (fw.getUniqueIDForObject(&obj,uniqueID)) { fw.writeUseID( uniqueID ); return true; } } const std::string classname( obj.className() ); const std::string libraryName( obj.libraryName() ); const std::string compositeName( libraryName + "::" + classname ); // try composite name first DotOsgWrapperMap::iterator itr = _classNameWrapperMap.find(compositeName); if (itr==_classNameWrapperMap.end()) { FileNames fileNames; if (getLibraryFileNamesToTry(libraryName, fileNames)) { for(FileNames::iterator itr = fileNames.begin(); itr != fileNames.end(); ++itr) { if (osgDB::Registry::instance()->loadLibrary(*itr)==osgDB::Registry::LOADED) return writeObject(obj,fw); } } // otherwise try simple class name if (itr == _classNameWrapperMap.end()) itr = _classNameWrapperMap.find(classname); } if (itr!=_classNameWrapperMap.end()) { DotOsgWrapper* wrapper = itr->second.get(); const DotOsgWrapper::Associates& assoc = wrapper->getAssociates(); if (libraryName=="osg") { // member of the core osg, so no need to have composite library::class name. fw.writeBeginObject( wrapper->getName() ); } else { // member of the node kit so must use composite library::class name. std::string::size_type posDoubleColon = wrapper->getName().find("::"); if (posDoubleColon != std::string::npos) { fw.writeBeginObject( wrapper->getName() ); } else { fw.writeBeginObject( libraryName + "::" + wrapper->getName() ); } } fw.moveIn(); // write out the unique ID if required. if (obj.referenceCount()>1) { std::string uniqueID; fw.createUniqueIDForObject(&obj,uniqueID); fw.registerUniqueIDForObject(&obj,uniqueID); fw.writeUniqueID( uniqueID ); } // read the local data by iterating through the associate // list, mapping the associate names to DotOsgWrapper's which // in turn have the appropriate functions. for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin(); aitr!=assoc.end(); ++aitr) { DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr); if (mitr==_objectWrapperMap.end()) { // not found so check if a library::class composite name. std::string token = *aitr; std::string::size_type posDoubleColon = token.rfind("::"); if (posDoubleColon != std::string::npos) { // we have a composite name so now strip off the library name // are try to load it, and then retry the find to see // if we can recognize the objects. std::string libraryName = std::string(token,0,posDoubleColon); FileNames fileNames; if (getLibraryFileNamesToTry(libraryName, fileNames)) { for(FileNames::iterator itr = fileNames.begin(); itr != fileNames.end() && mitr==_objectWrapperMap.end(); ++itr) { if (osgDB::Registry::instance()->loadLibrary(*itr)==osgDB::Registry::LOADED) { mitr = _objectWrapperMap.find(*aitr); } } } } } if (mitr!=_objectWrapperMap.end()) { // get the function to read the data... DotOsgWrapper::WriteFunc wf = mitr->second->getWriteFunc(); if (wf) (*wf)(obj,fw); } } fw.moveOut(); fw.writeEndObject(); return true; } return false; } openscenegraph-3.2.3/OpenSceneGraph/src/osgDB/XmlParser.cpp0000644000175000017500000003673012274415477023457 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include using namespace osgDB; XmlNode* osgDB::readXmlFile(const std::string& filename,const Options* options) { std::string foundFile = osgDB::findDataFile(filename, options); if (!foundFile.empty()) { XmlNode::Input input; input.open(foundFile); input.readAllDataIntoBuffer(); if (!input) { OSG_NOTICE<<"Could not open XML file: "< root = new XmlNode; root->read(input); return root.release(); } else { OSG_NOTICE<<"Could not find XML file: "< root = new XmlNode; root->read(input); return root.release(); } XmlNode::ControlMap::ControlMap() { setUpControlMappings(); } void XmlNode::ControlMap::addControlToCharacter(const std::string& control, int c) { _controlToCharacterMap[control] = c; _characterToControlMap[c] = control; } void XmlNode::ControlMap::setUpControlMappings() { addControlToCharacter("&",'&'); addControlToCharacter("<",'<'); addControlToCharacter(">",'>'); addControlToCharacter(""",'"'); addControlToCharacter("'",'\''); } XmlNode::Input::Input(): _currentPos(0) { } XmlNode::Input::Input(const Input&): ControlMap(), _currentPos(0) { } XmlNode::Input::~Input() { } void XmlNode::Input::open(const std::string& filename) { _fin.open(filename.c_str()); } void XmlNode::Input::attach(std::istream& fin) { std::ios &fios = _fin; fios.rdbuf(fin.rdbuf()); } void XmlNode::Input::readAllDataIntoBuffer() { while(_fin) { int c = _fin.get(); if (c>=0 && c<=255) { _buffer.push_back(c); } } } void XmlNode::Input::skipWhiteSpace() { while(_currentPos<_buffer.size() && (_buffer[_currentPos]==' ' || _buffer[_currentPos]=='\t' || _buffer[_currentPos]=='\n' || _buffer[_currentPos]=='\r')) { //OSG_NOTICE<<"_currentPos="<<_currentPos<<"_buffer.size()="<<_buffer.size()<<" v="<type = XmlNode::COMMENT; children.push_back(commentNode); input += 4; XmlNode::Input::size_type end = input.find("-->"); commentNode->contents = input.substr(0, end); if (end!=std::string::npos) { OSG_INFO<<"Valid Comment record ["<contents<<"]"<contents<<"]"<"); std::string comment = input.substr(0, end); if (end!=std::string::npos) { OSG_INFO<<"Valid end tag ["<type = XmlNode::INFORMATION; children.push_back(commentNode); ++input; XmlNode::Input::size_type end = input.find(">"); commentNode->contents = input.substr(0, end); if (end!=std::string::npos) { OSG_INFO<<"Valid infomation record ["<contents<<"]"<contents<<"]"<type = XmlNode::INFORMATION; children.push_back(commentNode); input += 9; XmlNode::Input::size_type end = input.find("]]>"); commentNode->contents = input.substr(0, end); if (end!=std::string::npos) { OSG_INFO<<"Valid infomation record ["<contents<<"]"<contents<<"]"<type = XmlNode::INFORMATION; children.push_back(commentNode); input += 2; XmlNode::Input::size_type end = input.find("?>"); commentNode->contents = input.substr(0, end); if (end!=std::string::npos) { OSG_INFO<<"Valid infomation record ["<contents<<"]"<contents<<"]"<type = XmlNode::NODE; children.push_back(childNode); input += 1; input.skipWhiteSpace(); int c = 0; while ((c=input[0])>=0 && c!=' ' && c!='\n' && c!='\r' && c!='>' && c!='/') { childNode->name.push_back(c); ++input; } while ((c=input[0])>=0 && c!='>' && c!='/') { Input::size_type prev_pos = input.currentPosition(); input.skipWhiteSpace(); std::string option; std::string value; if (input[0]=='"') { option.push_back(input[0]); ++input; while((c=input[0])>=0 && c!='"') { if (c=='&') readAndReplaceControl(option, input); else { option.push_back(c); ++input; } } option.push_back(input[0]); ++input; } else { while((c=input[0])>=0 && c!='>' && c!='/' && c!='"' && c!='\'' && c!='=' && c!=' ' && c!='\n' && c!='\r') { option.push_back(c); ++input; } } input.skipWhiteSpace(); if (input[0]=='=') { ++input; input.skipWhiteSpace(); if (input[0]=='"') { ++input; while((c=input[0])>=0 && c!='"') { if (c=='&') readAndReplaceControl(value, input); else { value.push_back(c); ++input; } } ++input; } else if (input[0]=='\'') { ++input; while((c=input[0])>=0 && c!='\'') { if (c=='&') readAndReplaceControl(value, input); else { value.push_back(c); ++input; } } ++input; } else { ++input; while((c=input[0])>=0 && c!=' ' && c!='\n' && c!='\r' && c!='"' && c!='\'' && c!='>') { value.push_back(c); ++input; } } } if (prev_pos == input.currentPosition()) { OSG_NOTICE<<"Error, parser iterator not advanced, position: "<properties[option] = value; } } if ((c=input[0])>=0 && (c=='>' || c=='/')) { ++input; OSG_INFO<<"Valid tag ["<name<<"]"<=0 && c=='>') { ++input; OSG_INFO<<"tag is closed correctly"<type = ATOM; } else OSG_NOTICE<<"Error: tag is not closed correctly"<read(input); if (!result) return false; } if (type==NODE && !children.empty()) type = GROUP; } else { OSG_NOTICE<<"Unclosed tag ["<name<<"]"<"<"; writeString(controlMap, fout, contents); fout<<""<"<"<"<"<second; else fout.put(c); } return true; } bool XmlNode::writeChildren(const ControlMap& /*controlMap*/, std::ostream& fout, const std::string& indent) const { for(Children::const_iterator citr = children.begin(); citr != children.end(); ++citr) { if (!(*citr)->write(fout, indent)) return false; } return true; } bool XmlNode::writeProperties(const ControlMap& controlMap, std::ostream& fout) const { for(Properties::const_iterator oitr = properties.begin(); oitr != properties.end(); ++oitr) { fout<<" "<first<<"=\""; if (!writeString(controlMap,fout,oitr->second)) return false; fout<<"\""; } return true; } bool XmlNode::readAndReplaceControl(std::string& contents, XmlNode::Input& input) { int c = 0; std::string value; while(input && (c=input.get())!=';') { value.push_back(c); } value.push_back(c); if (input._controlToCharacterMap.count(value)!=0) { c = input._controlToCharacterMap[value]; OSG_INFO<<"Read control character "< #include #include #include #include #include using namespace osgDB; static std::string s_lastSchema; InputStream::InputStream( const osgDB::Options* options ) : _fileVersion(0), _useSchemaData(false), _forceReadingImage(false), _dataDecompress(0) { BEGIN_BRACKET.set( "{", +INDENT_VALUE ); END_BRACKET.set( "}", -INDENT_VALUE ); if ( !options ) return; _options = options; if ( options->getPluginStringData("ForceReadingImage")=="true" ) _forceReadingImage = true; if ( !options->getPluginStringData("CustomDomains").empty() ) { StringList domains, keyAndValue; split( options->getPluginStringData("CustomDomains"), domains, ';' ); for ( unsigned int i=0; i1 ) _domainVersionMap[keyAndValue.front()] = atoi(keyAndValue.back().c_str()); } } std::string schema; if ( !options->getPluginStringData("SchemaFile").empty() ) { schema = options->getPluginStringData("SchemaFile"); if ( s_lastSchema!=schema ) { osgDB::ifstream schemaStream( schema.c_str(), std::ios::in ); if ( !schemaStream.fail() ) readSchema( schemaStream ); schemaStream.close(); s_lastSchema = schema; } } if ( schema.empty() ) { resetSchema(); s_lastSchema.clear(); } } InputStream::~InputStream() { if (_dataDecompress) delete _dataDecompress; } int InputStream::getFileVersion( const std::string& d ) const { if ( d.empty() ) return _fileVersion; VersionMap::const_iterator itr = _domainVersionMap.find(d); return itr==_domainVersionMap.end() ? 0 : itr->second; } InputStream& InputStream::operator>>( osg::Vec2b& v ) { char x, y; *this >> x >> y; v.set( x, y ); return *this; } InputStream& InputStream::operator>>( osg::Vec3b& v ) { char x, y, z; *this >> x >> y >> z; v.set( x, y, z ); return *this; } InputStream& InputStream::operator>>( osg::Vec4b& v ) { char x, y, z, w; *this >> x >> y >> z >> w; v.set( x, y, z, w ); return *this; } InputStream& InputStream::operator>>( osg::Vec2ub& v ) { unsigned char x, y; *this >> x >> y; v.set( x, y ); return *this; } InputStream& InputStream::operator>>( osg::Vec3ub& v ) { unsigned char x, y, z; *this >> x >> y >> z; v.set( x, y, z ); return *this; } InputStream& InputStream::operator>>( osg::Vec4ub& v ) { unsigned char r, g, b, a; *this >> r >> g >> b >> a; v.set( r, g, b, a ); return *this; } InputStream& InputStream::operator>>( osg::Vec2s& v ) { *this >> v.x() >> v.y(); return *this; } InputStream& InputStream::operator>>( osg::Vec3s& v ) { *this >> v.x() >> v.y() >> v.z(); return *this; } InputStream& InputStream::operator>>( osg::Vec4s& v ) { *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; } InputStream& InputStream::operator>>( osg::Vec2us& v ) { *this >> v.x() >> v.y(); return *this; } InputStream& InputStream::operator>>( osg::Vec3us& v ) { *this >> v.x() >> v.y() >> v.z(); return *this; } InputStream& InputStream::operator>>( osg::Vec4us& v ) { *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; } InputStream& InputStream::operator>>( osg::Vec2i& v ) { *this >> v.x() >> v.y(); return *this; } InputStream& InputStream::operator>>( osg::Vec3i& v ) { *this >> v.x() >> v.y() >> v.z(); return *this; } InputStream& InputStream::operator>>( osg::Vec4i& v ) { *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; } InputStream& InputStream::operator>>( osg::Vec2ui& v ) { *this >> v.x() >> v.y(); return *this; } InputStream& InputStream::operator>>( osg::Vec3ui& v ) { *this >> v.x() >> v.y() >> v.z(); return *this; } InputStream& InputStream::operator>>( osg::Vec4ui& v ) { *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; } InputStream& InputStream::operator>>( osg::Vec2f& v ) { *this >> v.x() >> v.y(); return *this; } InputStream& InputStream::operator>>( osg::Vec3f& v ) { *this >> v.x() >> v.y() >> v.z(); return *this; } InputStream& InputStream::operator>>( osg::Vec4f& v ) { *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; } InputStream& InputStream::operator>>( osg::Vec2d& v ) { *this >> v.x() >> v.y(); return *this; } InputStream& InputStream::operator>>( osg::Vec3d& v ) { *this >> v.x() >> v.y() >> v.z(); return *this; } InputStream& InputStream::operator>>( osg::Vec4d& v ) { *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; } InputStream& InputStream::operator>>( osg::Quat& q ) { *this >> q.x() >> q.y() >> q.z() >> q.w(); return *this; } InputStream& InputStream::operator>>( osg::Plane& p ) { double p0, p1, p2, p3; *this >> p0 >> p1 >> p2 >> p3; p.set( p0, p1, p2, p3 ); return *this; } #if 0 InputStream& InputStream::operator>>( osg::Matrixf& mat ) { ObjectProperty property(""); *this >> property >> BEGIN_BRACKET; if (property._name == "Matrixf") { // stream has same type as what we want to read so read directly for ( int r=0; r<4; ++r ) { *this >> mat(r, 0) >> mat(r, 1) >> mat(r, 2) >> mat(r, 3); } } else if (property._name == "Matrixd") { // stream has different type than what we want to read so read stream into // a temporary and then copy across to the final matrix double value; for ( int r=0; r<4; ++r ) { for ( int c=0; c<4; ++c) { *this >> value; mat(r,c) = static_cast(value); } } } *this >> END_BRACKET; return *this; } InputStream& InputStream::operator>>( osg::Matrixd& mat ) { ObjectProperty property(""); *this >> property >> BEGIN_BRACKET; if (property._name == "Matrixf") { // stream has different type than what we want to read so read stream into // a temporary and then copy across to the final matrix float value; for ( int r=0; r<4; ++r ) { for ( int c=0; c<4; ++c) { *this >> value; mat(r,c) = static_cast(value); } } } else if (property._name == "Matrixd") { // stream has same type as what we want to read so read directly for ( int r=0; r<4; ++r ) { *this >> mat(r, 0) >> mat(r, 1) >> mat(r, 2) >> mat(r, 3); } } *this >> END_BRACKET; return *this; } #else InputStream& InputStream::operator>>( osg::Matrixf& mat ) { *this >> BEGIN_BRACKET; // stream has different type than what we want to read so read stream into // a temporary and then copy across to the final matrix double value; for ( int r=0; r<4; ++r ) { for ( int c=0; c<4; ++c) { *this >> value; mat(r,c) = static_cast(value); } } *this >> END_BRACKET; return *this; } InputStream& InputStream::operator>>( osg::Matrixd& mat ) { *this >> BEGIN_BRACKET; for ( int r=0; r<4; ++r ) { *this >> mat(r, 0) >> mat(r, 1) >> mat(r, 2) >> mat(r, 3); } *this >> END_BRACKET; return *this; } #endif osg::Array* InputStream::readArray() { osg::ref_ptr array = NULL; unsigned int id = 0; *this >> PROPERTY("ArrayID") >> id; ArrayMap::iterator itr = _arrayMap.find( id ); if ( itr!=_arrayMap.end() ) { return itr->second.get(); } DEF_MAPPEE(ArrayType, type); *this >> type; switch ( type.get() ) { case ID_BYTE_ARRAY: { osg::ByteArray* ba = new osg::ByteArray; readArrayImplementation( ba, 1, CHAR_SIZE); array = ba; } break; case ID_UBYTE_ARRAY: { osg::UByteArray* uba = new osg::UByteArray; readArrayImplementation( uba, 1, CHAR_SIZE ); array = uba; } break; case ID_SHORT_ARRAY: { osg::ShortArray* sa = new osg::ShortArray; readArrayImplementation( sa, 1, SHORT_SIZE ); array = sa; } break; case ID_USHORT_ARRAY: { osg::UShortArray* usa = new osg::UShortArray; readArrayImplementation( usa, 1, SHORT_SIZE ); array = usa; } break; case ID_INT_ARRAY: { osg::IntArray* ia = new osg::IntArray; readArrayImplementation( ia, 1, INT_SIZE ); array = ia; } break; case ID_UINT_ARRAY: { osg::UIntArray* uia = new osg::UIntArray; readArrayImplementation( uia, 1, INT_SIZE ); array = uia; } break; case ID_FLOAT_ARRAY: { osg::FloatArray* fa = new osg::FloatArray; readArrayImplementation( fa, 1, FLOAT_SIZE ); array = fa; } break; case ID_DOUBLE_ARRAY: { osg::DoubleArray* da = new osg::DoubleArray; readArrayImplementation( da, 1, DOUBLE_SIZE ); array = da; } break; case ID_VEC2B_ARRAY: { osg::Vec2bArray* va = new osg::Vec2bArray; readArrayImplementation( va, 2, CHAR_SIZE ); array = va; } break; case ID_VEC3B_ARRAY: { osg::Vec3bArray* va = new osg::Vec3bArray; readArrayImplementation( va, 3, CHAR_SIZE ); array = va; } break; case ID_VEC4B_ARRAY: { osg::Vec4bArray* va = new osg::Vec4bArray; readArrayImplementation( va, 4, CHAR_SIZE ); array = va; } break; case ID_VEC2UB_ARRAY: { osg::Vec2ubArray* va = new osg::Vec2ubArray; readArrayImplementation( va, 2, CHAR_SIZE ); array = va; } break; case ID_VEC3UB_ARRAY: { osg::Vec3ubArray* va = new osg::Vec3ubArray; readArrayImplementation( va, 3, CHAR_SIZE ); array = va; } break; case ID_VEC4UB_ARRAY: { osg::Vec4ubArray* va = new osg::Vec4ubArray; readArrayImplementation( va, 4, CHAR_SIZE ); array = va; } break; case ID_VEC2S_ARRAY: { osg::Vec2sArray* va = new osg::Vec2sArray; readArrayImplementation( va, 2, SHORT_SIZE ); array = va; } break; case ID_VEC3S_ARRAY: { osg::Vec3sArray* va = new osg::Vec3sArray; readArrayImplementation( va, 3, SHORT_SIZE ); array = va; } break; case ID_VEC4S_ARRAY: { osg::Vec4sArray* va = new osg::Vec4sArray; readArrayImplementation( va, 4, SHORT_SIZE ); array = va; } break; case ID_VEC2US_ARRAY: { osg::Vec2usArray* va = new osg::Vec2usArray; readArrayImplementation( va, 2, SHORT_SIZE ); array = va; } break; case ID_VEC3US_ARRAY: { osg::Vec3usArray* va = new osg::Vec3usArray; readArrayImplementation( va, 3, SHORT_SIZE ); array = va; } break; case ID_VEC4US_ARRAY: { osg::Vec4usArray* va = new osg::Vec4usArray; readArrayImplementation( va, 4, SHORT_SIZE ); array = va; } break; case ID_VEC2_ARRAY: { osg::Vec2Array* va = new osg::Vec2Array; readArrayImplementation( va, 2, FLOAT_SIZE ); array = va; } break; case ID_VEC3_ARRAY: { osg::Vec3Array* va = new osg::Vec3Array; readArrayImplementation( va, 3, FLOAT_SIZE ); array = va; } break; case ID_VEC4_ARRAY: { osg::Vec4Array* va = new osg::Vec4Array; readArrayImplementation( va, 4, FLOAT_SIZE ); array = va; } break; case ID_VEC2D_ARRAY: { osg::Vec2dArray* va = new osg::Vec2dArray; readArrayImplementation( va, 2, DOUBLE_SIZE ); array = va; } break; case ID_VEC3D_ARRAY: { osg::Vec3dArray* va = new osg::Vec3dArray; readArrayImplementation( va, 3, DOUBLE_SIZE ); array = va; } break; case ID_VEC4D_ARRAY: { osg::Vec4dArray* va = new osg::Vec4dArray; readArrayImplementation( va, 4, DOUBLE_SIZE ); array = va; } break; default: throwException( "InputStream::readArray(): Unsupported array type." ); } if ( getException() ) return NULL; _arrayMap[id] = array; return array.release(); } osg::PrimitiveSet* InputStream::readPrimitiveSet() { osg::ref_ptr primitive = NULL; DEF_MAPPEE(PrimitiveType, type); DEF_MAPPEE(PrimitiveType, mode); unsigned int numInstances = 0u; *this >> type >> mode; if ( _fileVersion>96 ) { *this >> numInstances; } switch ( type.get() ) { case ID_DRAWARRAYS: { int first = 0, count = 0; *this >> first >> count; osg::DrawArrays* da = new osg::DrawArrays( mode.get(), first, count ); primitive = da; primitive->setNumInstances( numInstances ); } break; case ID_DRAWARRAY_LENGTH: { int first = 0, value = 0; unsigned int size = 0; *this >> first >> size >> BEGIN_BRACKET; osg::DrawArrayLengths* dl = new osg::DrawArrayLengths( mode.get(), first ); for ( unsigned int i=0; i> value; dl->push_back( value ); } *this >> END_BRACKET; primitive = dl; primitive->setNumInstances( numInstances ); } break; case ID_DRAWELEMENTS_UBYTE: { osg::DrawElementsUByte* de = new osg::DrawElementsUByte( mode.get() ); unsigned int size = 0; unsigned char value = 0; *this >> size >> BEGIN_BRACKET; for ( unsigned int i=0; i> value; de->push_back( value ); } *this >> END_BRACKET; primitive = de; primitive->setNumInstances( numInstances ); } break; case ID_DRAWELEMENTS_USHORT: { osg::DrawElementsUShort* de = new osg::DrawElementsUShort( mode.get() ); unsigned int size = 0; unsigned short value = 0; *this >> size >> BEGIN_BRACKET; for ( unsigned int i=0; i> value; de->push_back( value ); } *this >> END_BRACKET; primitive = de; primitive->setNumInstances( numInstances ); } break; case ID_DRAWELEMENTS_UINT: { osg::DrawElementsUInt* de = new osg::DrawElementsUInt( mode.get() ); unsigned int size = 0, value = 0; *this >> size >> BEGIN_BRACKET; for ( unsigned int i=0; i> value; de->push_back( value ); } *this >> END_BRACKET; primitive = de; primitive->setNumInstances( numInstances ); } break; default: throwException( "InputStream::readPrimitiveSet(): Unsupported array type." ); } if ( getException() ) return NULL; return primitive.release(); } osg::Image* InputStream::readImage(bool readFromExternal) { std::string className = "osg::Image"; if ( _fileVersion>94 ) // ClassName property is only supported in 3.1.4 and higher *this >> PROPERTY("ClassName") >> className; unsigned int id = 0; *this >> PROPERTY("UniqueID") >> id; if ( getException() ) return NULL; IdentifierMap::iterator itr = _identifierMap.find( id ); if ( itr!=_identifierMap.end() ) { return static_cast( itr->second.get() ); } std::string name; int writeHint, decision = IMAGE_EXTERNAL; *this >> PROPERTY("FileName"); readWrappedString(name); *this >> PROPERTY("WriteHint") >> writeHint >> decision; if ( getException() ) return NULL; osg::ref_ptr image = NULL; switch ( decision ) { case IMAGE_INLINE_DATA: if ( isBinary() ) { // _origin, _s & _t & _r, _internalTextureFormat int origin, s, t, r, internalFormat; *this >> origin >> s >> t >> r >> internalFormat; // _pixelFormat, _dataType, _packing, _allocationMode int pixelFormat, dataType, packing, mode; *this >> pixelFormat >> dataType >> packing >> mode; // _data unsigned int size = 0; *this >> size; if ( size ) { char* data = new char[size]; if ( !data ) throwException( "InputStream::readImage() Out of memory." ); if ( getException() ) return NULL; readCharArray( data, size ); image = new osg::Image; image->setOrigin( (osg::Image::Origin)origin ); image->setImage( s, t, r, internalFormat, pixelFormat, dataType, (unsigned char*)data, osg::Image::USE_NEW_DELETE, packing ); } // _mipmapData unsigned int levelSize = readSize(); osg::Image::MipmapDataType levels(levelSize); for ( unsigned int i=0; i> levels[i]; } if ( image && levelSize>0 ) image->setMipmapLevels( levels ); readFromExternal = false; } break; case IMAGE_INLINE_FILE: if ( isBinary() ) { unsigned int size = readSize(); if ( size>0 ) { char* data = new char[size]; if ( !data ) { throwException( "InputStream::readImage(): Out of memory." ); if ( getException() ) return NULL; } readCharArray( data, size ); std::string ext = osgDB::getFileExtension( name ); osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension( ext ); if ( reader ) { std::stringstream inputStream; inputStream.write( data, size ); osgDB::ReaderWriter::ReadResult rr = reader->readImage( inputStream ); if ( rr.validImage() ) image = rr.takeImage(); else { OSG_WARN << "InputStream::readImage(): " << rr.message() << std::endl; } } else { OSG_WARN << "InputStream::readImage(): Unable to find a plugin for " << ext << std::endl; } delete[] data; } readFromExternal = false; } break; case IMAGE_EXTERNAL: case IMAGE_WRITE_OUT: break; default: break; } if ( readFromExternal && !name.empty() ) { image = osgDB::readImageFile( name, getOptions() ); if ( !image && _forceReadingImage ) image = new osg::Image; } image = static_cast( readObjectFields(className, id, image.get()) ); if ( image.valid() ) { image->setFileName( name ); image->setWriteHint( (osg::Image::WriteHint)writeHint ); } return image.release(); } osg::Object* InputStream::readObject( osg::Object* existingObj ) { std::string className; unsigned int id = 0; *this >> className >> BEGIN_BRACKET >> PROPERTY("UniqueID") >> id; if ( getException() ) return NULL; IdentifierMap::iterator itr = _identifierMap.find( id ); if ( itr!=_identifierMap.end() ) { advanceToCurrentEndBracket(); return itr->second.get(); } osg::ref_ptr obj = readObjectFields( className, id, existingObj ); advanceToCurrentEndBracket(); return obj.release(); } osg::Object* InputStream::readObjectFields( const std::string& className, unsigned int id, osg::Object* existingObj ) { ObjectWrapper* wrapper = Registry::instance()->getObjectWrapperManager()->findWrapper( className ); if ( !wrapper ) { OSG_WARN << "InputStream::readObject(): Unsupported wrapper class " << className << std::endl; return NULL; } osg::ref_ptr obj = existingObj ? existingObj : wrapper->getProto()->cloneType(); _identifierMap[id] = obj; if ( obj.valid() ) { const StringList& associates = wrapper->getAssociates(); for ( StringList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr ) { ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(*itr); if ( !assocWrapper ) { OSG_WARN << "InputStream::readObject(): Unsupported associated class " << *itr << std::endl; continue; } _fields.push_back( assocWrapper->getName() ); assocWrapper->read( *this, *obj ); if ( getException() ) return NULL; _fields.pop_back(); } } return obj.release(); } void InputStream::readSchema( std::istream& fin ) { // Read from external ascii stream std::string line; while ( std::getline(fin, line) ) { if ( line[0]=='#' ) continue; // Comment StringList keyAndValue; split( line, keyAndValue, '=' ); if ( keyAndValue.size()<2 ) continue; setWrapperSchema( osgDB::trimEnclosingSpaces(keyAndValue[0]), osgDB::trimEnclosingSpaces(keyAndValue[1]) ); } } InputStream::ReadType InputStream::start( InputIterator* inIterator ) { _fields.clear(); _fields.push_back( "Start" ); ReadType type = READ_UNKNOWN; _in = inIterator; if ( !_in ) throwException( "InputStream: Null stream specified." ); if ( getException() ) return type; _in->setInputStream(this); // Check OSG header information unsigned int version = 0; if ( isBinary() ) { unsigned int typeValue; *this >> typeValue >> version; type = static_cast(typeValue); unsigned int attributes; *this >> attributes; if ( attributes&0x4 ) inIterator->setSupportBinaryBrackets( true ); if ( attributes&0x2 ) _useSchemaData = true; // Record custom domains if ( attributes&0x1 ) { unsigned int numDomains; *this >> numDomains; for ( unsigned int i=0; i> domainName; int domainVersion; *this >> domainVersion; _domainVersionMap[domainName] = domainVersion; } } } if ( !isBinary() ) { std::string typeString; *this >> typeString; if ( typeString=="Scene" ) type = READ_SCENE; else if ( typeString=="Image" ) type = READ_IMAGE; else if ( typeString=="Object" ) type = READ_OBJECT; std::string osgName, osgVersion; *this >> PROPERTY("#Version") >> version; *this >> PROPERTY("#Generator") >> osgName >> osgVersion; while ( matchString("#CustomDomain") ) { std::string domainName; *this >> domainName; int domainVersion; *this >> domainVersion; _domainVersionMap[domainName] = domainVersion; } } // Record file version for back-compatibility checking of wrappers _fileVersion = version; _fields.pop_back(); return type; } void InputStream::decompress() { if ( !isBinary() ) return; _fields.clear(); std::string compressorName; *this >> compressorName; if ( compressorName!="0" ) { std::string data; _fields.push_back( "Decompression" ); BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(compressorName); if ( !compressor ) { OSG_WARN << "InputStream::decompress(): No such compressor " << compressorName << std::endl; } if ( !compressor->decompress(*(_in->getStream()), data) ) throwException( "InputStream: Failed to decompress stream." ); if ( getException() ) return; _dataDecompress = new std::stringstream(data); _in->setStream( _dataDecompress ); _fields.pop_back(); } if ( _useSchemaData ) { _fields.push_back( "SchemaData" ); std::string schemaSource; *this >> schemaSource; std::istringstream iss( schemaSource ); readSchema( iss ); _fields.pop_back(); } } // PROTECTED METHODS void InputStream::setWrapperSchema( const std::string& name, const std::string& properties ) { ObjectWrapper* wrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(name); if ( !wrapper ) { OSG_WARN << "InputStream::setSchema(): Unsupported wrapper class " << name << std::endl; return; } StringList schema, methods, keyAndValue; std::vector types; split( properties, schema ); for ( StringList::iterator itr=schema.begin(); itr!=schema.end(); ++itr ) { split( *itr, keyAndValue, ':' ); if ( keyAndValue.size()>1 ) { methods.push_back( keyAndValue.front() ); types.push_back( atoi(keyAndValue.back().c_str()) ); } else { methods.push_back( *itr ); types.push_back( 0 ); } keyAndValue.clear(); } wrapper->readSchema( methods, types ); } void InputStream::resetSchema() { const ObjectWrapperManager::WrapperMap& wrappers = Registry::instance()->getObjectWrapperManager()->getWrapperMap(); for ( ObjectWrapperManager::WrapperMap::const_iterator itr=wrappers.begin(); itr!=wrappers.end(); ++itr ) { ObjectWrapper* wrapper = itr->second.get(); wrapper->resetSchema(); } } template void InputStream::readArrayImplementation( T* a, unsigned int numComponentsPerElements, unsigned int componentSizeInBytes ) { int size = 0; *this >> size >> BEGIN_BRACKET; if ( size ) { a->resize( size ); if ( isBinary() ) { readComponentArray( (char*)&((*a)[0]), size, numComponentsPerElements, componentSizeInBytes ); checkStream(); } else { for ( int i=0; i> (*a)[i]; } } *this >> END_BRACKET; } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/0000755000175000017500000000000012674261220021766 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/Version.cpp0000644000175000017500000000152511732410624024120 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include extern "C" { const char* osgViewerGetVersion() { return osgGetVersion(); } const char* osgViewerGetLibraryName() { return "OpenSceneGraph Viewer Library"; } } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/PixelBufferX11.cpp0000644000175000017500000003412012163275353025204 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ /* Note, elements of PixelBufferX11 have used Prodcer/RenderSurface_X11.cpp as both * a guide to use of X11/GLX and copiying directly in the case of setBorder(). * These elements are license under OSGPL as above, with Copyright (C) 2001-2004 Don Burns. */ #include #include #include #include #include using namespace osgViewer; PixelBufferX11::PixelBufferX11(osg::GraphicsContext::Traits* traits) : _valid(false), _pbuffer(0), _visualInfo(0), _initialized(false), _realized(false), _useGLX1_3(false) { _traits = traits; init(); if (valid()) { setState( new osg::State ); getState()->setGraphicsContext(this); if (_traits.valid() && _traits->sharedContext.valid()) { getState()->setContextID( _traits->sharedContext->getState()->getContextID() ); incrementContextIDUsageCount( getState()->getContextID() ); } else { getState()->setContextID( osg::GraphicsContext::createNewContextID() ); } } } PixelBufferX11::~PixelBufferX11() { close(true); } #if defined(GLX_VERSION_1_3) || defined(GLX_SGIX_pbuffer) bool PixelBufferX11::createVisualInfo() { typedef std::vector Attributes; Attributes attributes; attributes.push_back(GLX_USE_GL); attributes.push_back(GLX_RGBA); if (_traits->doubleBuffer) attributes.push_back(GLX_DOUBLEBUFFER); attributes.push_back(GLX_RED_SIZE); attributes.push_back(_traits->red); attributes.push_back(GLX_GREEN_SIZE); attributes.push_back(_traits->green); attributes.push_back(GLX_BLUE_SIZE); attributes.push_back(_traits->blue); attributes.push_back(GLX_DEPTH_SIZE); attributes.push_back(_traits->depth); if (_traits->alpha) { attributes.push_back(GLX_ALPHA_SIZE); attributes.push_back(_traits->alpha); } if (_traits->stencil) { attributes.push_back(GLX_STENCIL_SIZE); attributes.push_back(_traits->stencil); } #if defined(GLX_SAMPLE_BUFFERS) && defined (GLX_SAMPLES) if (_traits->sampleBuffers) { attributes.push_back(GLX_SAMPLE_BUFFERS); attributes.push_back(_traits->sampleBuffers); } if (_traits->sampleBuffers) { attributes.push_back(GLX_SAMPLES); attributes.push_back(_traits->samples); } #endif // TODO // GLX_AUX_BUFFERS // GLX_ACCUM_RED_SIZE // GLX_ACCUM_GREEN_SIZE attributes.push_back(None); _visualInfo = glXChooseVisual( _display, _traits->screenNum, &(attributes.front()) ); return _visualInfo != 0; } void PixelBufferX11::init() { if (_initialized) return; if (!_traits) { _valid = false; return; } if (_traits->target != 0) { // we don't support Pbuffer render to texture under GLX. _valid = false; return; } _display = XOpenDisplay(_traits->displayName().c_str()); unsigned int screen = _traits->screenNum; if (!_display) { OSG_NOTICE<<"Error: Unable to open display \"" << XDisplayName(_traits->displayName().c_str()) << "\"."<displayName().c_str()) <<" has no GLX extension." << std::endl; XCloseDisplay( _display ); _display = 0; _valid = false; return; } // OSG_NOTICE<<"GLX extension, errorBase="<displayName().c_str()) << " can not query GLX version." << std::endl; XCloseDisplay( _display ); _display = 0; _valid = false; return; } // Just be paranoid, if we are older than 1.1, we cannot even call glxQueryExtensionString if (major < 1 || (1 == major && minor < 1)) { OSG_NOTICE << "Error: " << XDisplayName(_traits->displayName().c_str()) << " GLX version " << major << "." << minor << " is too old." << std::endl; XCloseDisplay( _display ); _display = 0; _valid = false; return; } bool haveGLX1_3 = false; bool haveSGIX_pbuffer = false; // We need to have at least GLX 1.3 to use getFBConfigFromVisual and glXCreatePbuffer if (1 < major || (1 == major && 3 <= minor)) { haveGLX1_3 = true; } #if defined(GLX_VERSION_1_1) // We need at least GLX 1.1 for glXQueryExtensionsString if (!haveGLX1_3 && 1 <= minor) { const char *extensions = glXQueryExtensionsString(_display, screen); haveSGIX_pbuffer = osg::isExtensionInExtensionString("GLX_SGIX_pbuffer", extensions) && osg::isExtensionInExtensionString("GLX_SGIX_fbconfig", extensions); } #endif if (!haveGLX1_3 && !haveSGIX_pbuffer) { OSG_NOTICE << "Error: " << XDisplayName(_traits->displayName().c_str()) << " no Pbuffer support in GLX available." << std::endl; XCloseDisplay( _display ); _display = 0; _valid = false; return; } if (!createVisualInfo()) { _traits->red /= 2; _traits->green /= 2; _traits->blue /= 2; _traits->alpha /= 2; _traits->depth /= 2; OSG_INFO<<"Relaxing traits"<(_traits->sharedContext.get()); Context sharedContext = graphicsHandleX11 ? graphicsHandleX11->getContext() : 0; _context = glXCreateContext( _display, _visualInfo, sharedContext, True ); if (!_context) { OSG_NOTICE<<"Error: Unable to create OpenGL graphics context."<visualid ) { typedef std::vector AttributeList; AttributeList attributes; attributes.push_back( GLX_PBUFFER_WIDTH ); attributes.push_back( _traits->width ); attributes.push_back( GLX_PBUFFER_HEIGHT ); attributes.push_back( _traits->height ); attributes.push_back( GLX_LARGEST_PBUFFER ); attributes.push_back( GL_TRUE ); attributes.push_back( 0L ); _pbuffer = glXCreatePbuffer(_display, fbconfigs[i], &attributes.front() ); _useGLX1_3 = true; } } } if (_pbuffer) { int iWidth = 0; int iHeight = 0; glXQueryDrawable(_display, _pbuffer, GLX_WIDTH , (unsigned int *)&iWidth); glXQueryDrawable(_display, _pbuffer, GLX_HEIGHT , (unsigned int *)&iHeight); if (_traits->width != iWidth || _traits->height != iHeight) { OSG_NOTICE << "PixelBufferX11::init(), pbuffer created with different size then requsted" << std::endl; OSG_NOTICE << "\tRequested size (" << _traits->width << "," << _traits->height << ")" << std::endl; OSG_NOTICE << "\tPbuffer size (" << iWidth << "," << iHeight << ")" << std::endl; _traits->width = iWidth; _traits->height = iHeight; } } XFree( fbconfigs ); } #endif #ifdef GLX_SGIX_pbuffer // If we still have no pbuffer but a capable display with the SGIX extension, try to use that if (!_pbuffer && haveSGIX_pbuffer) { GLXFBConfigSGIX fbconfig = glXGetFBConfigFromVisualSGIX( _display, _visualInfo ); typedef std::vector AttributeList; AttributeList attributes; attributes.push_back( GLX_LARGEST_PBUFFER_SGIX ); attributes.push_back( GL_TRUE ); attributes.push_back( 0L ); _pbuffer = glXCreateGLXPbufferSGIX(_display, fbconfig, _traits->width, _traits->height, &attributes.front() ); if (_pbuffer) { int iWidth = 0; int iHeight = 0; glXQueryGLXPbufferSGIX(_display, _pbuffer, GLX_WIDTH_SGIX , (unsigned int *)&iWidth); glXQueryGLXPbufferSGIX(_display, _pbuffer, GLX_HEIGHT_SGIX, (unsigned int *)&iHeight); if (_traits->width != iWidth || _traits->height != iHeight) { OSG_NOTICE << "PixelBufferX11::init(), SGIX_pbuffer created with different size then requsted" << std::endl; OSG_NOTICE << "\tRequested size (" << _traits->width << "," << _traits->height << ")" << std::endl; OSG_NOTICE << "\tPbuffer size (" << iWidth << "," << iHeight << ")" << std::endl; _traits->width = iWidth; _traits->height = iHeight; } } XFree( fbconfig ); } #endif if (!_pbuffer) { OSG_NOTICE<<"Error: Unable to create pbuffer."< #include #include #include #include #include #include #include #include #include /* For CARD16 */ #ifdef OSGVIEWER_USE_XRANDR #include #endif #include using namespace osgViewer; #ifdef OSG_USE_EGL bool checkEGLError(const char* str) { EGLint err = eglGetError(); if (err != EGL_SUCCESS) { OSG_WARN<<"Warning: "<second; itr = _standardKeymap.find(key); if (itr != _standardKeymap.end()) return itr->second; return key; } bool remapExtendedKey(int& key) { KeyMap::iterator itr = _extendedKeymap.find(key); if (itr != _extendedKeymap.end()) { key = itr->second; return true; } else return false; } protected: typedef std::map KeyMap; KeyMap _extendedKeymap; KeyMap _standardKeymap; }; static bool remapExtendedX11Key(int& key) { static X11KeyboardMap s_x11KeyboardMap; return s_x11KeyboardMap.remapExtendedKey(key); } // Functions to handle key maps of type char[32] as contained in // an XKeymapEvent or returned by XQueryKeymap(). static inline bool keyMapGetKey(const char* map, unsigned int key) { return (map[(key & 0xff) / 8] & (1 << (key & 7))) != 0; } static inline void keyMapSetKey(char* map, unsigned int key) { map[(key & 0xff) / 8] |= (1 << (key & 7)); } static inline void keyMapClearKey(char* map, unsigned int key) { map[(key & 0xff) / 8] &= ~(1 << (key & 7)); } GraphicsWindowX11::~GraphicsWindowX11() { close(true); } Display* GraphicsWindowX11::getDisplayToUse() const { if (_threadOfLastMakeCurrent==0) { return _display; } if (OpenThreads::Thread::CurrentThread()==_threadOfLastMakeCurrent) { return _display; } else { return _eventDisplay; } } bool GraphicsWindowX11::createVisualInfo() { if (_visualInfo) { #ifdef OSG_USE_EGL delete _visualInfo; #else XFree(_visualInfo); #endif _visualInfo = 0; } if( _window != 0 ) { XWindowAttributes watt; XGetWindowAttributes( _display, _window, &watt ); XVisualInfo temp; temp.visualid = XVisualIDFromVisual(watt.visual); int n; _visualInfo = XGetVisualInfo( _display, VisualIDMask, &temp, &n ); } else { #ifdef OSG_USE_EGL _visualInfo = new XVisualInfo; int depth = DefaultDepth( _display, _traits->screenNum ); if (XMatchVisualInfo( _display, _traits->screenNum, depth, TrueColor, _visualInfo )==0) { OSG_NOTICE<<"GraphicsWindowX11::createVisualInfo() failed."< Attributes; Attributes attributes; attributes.push_back(GLX_USE_GL); attributes.push_back(GLX_RGBA); if (_traits->doubleBuffer) attributes.push_back(GLX_DOUBLEBUFFER); if (_traits->quadBufferStereo) attributes.push_back(GLX_STEREO); attributes.push_back(GLX_RED_SIZE); attributes.push_back(_traits->red); attributes.push_back(GLX_GREEN_SIZE); attributes.push_back(_traits->green); attributes.push_back(GLX_BLUE_SIZE); attributes.push_back(_traits->blue); attributes.push_back(GLX_DEPTH_SIZE); attributes.push_back(_traits->depth); if (_traits->alpha) { attributes.push_back(GLX_ALPHA_SIZE); attributes.push_back(_traits->alpha); } if (_traits->stencil) { attributes.push_back(GLX_STENCIL_SIZE); attributes.push_back(_traits->stencil); } #if defined(GLX_SAMPLE_BUFFERS) && defined (GLX_SAMPLES) if (_traits->sampleBuffers) { attributes.push_back(GLX_SAMPLE_BUFFERS); attributes.push_back(_traits->sampleBuffers); } if (_traits->samples) { attributes.push_back(GLX_SAMPLES); attributes.push_back(_traits->samples); } #endif // TODO // GLX_AUX_BUFFERS // GLX_ACCUM_RED_SIZE // GLX_ACCUM_GREEN_SIZE attributes.push_back(None); _visualInfo = glXChooseVisual( _display, _traits->screenNum, &(attributes.front()) ); #endif } return _visualInfo != 0; } bool GraphicsWindowX11::checkAndSendEventFullScreenIfNeeded(Display* display, int x, int y, int width, int height, bool windowDecoration) { osg::GraphicsContext::WindowingSystemInterface *wsi = osg::GraphicsContext::getWindowingSystemInterface(); if (wsi == NULL) { OSG_NOTICE << "Error, no WindowSystemInterface available, cannot toggle window fullscreen." << std::endl; return false; } unsigned int screenWidth; unsigned int screenHeight; wsi->getScreenResolution(*_traits, screenWidth, screenHeight); bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight && !windowDecoration; if (isFullScreen) { resized(x, y, width, height); getEventQueue()->windowResize(x, y, width, height, getEventQueue()->getTime()); } Atom netWMStateAtom = XInternAtom(display, "_NET_WM_STATE", True); Atom netWMStateFullscreenAtom = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", True); if (netWMStateAtom != None && netWMStateFullscreenAtom != None) { XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.serial = 0; xev.xclient.send_event = True; xev.xclient.window = _window; xev.xclient.message_type = netWMStateAtom; xev.xclient.format = 32; xev.xclient.data.l[0] = isFullScreen ? 1 : 0; xev.xclient.data.l[1] = netWMStateFullscreenAtom; xev.xclient.data.l[2] = 0; XSendEvent(display, RootWindow(display, DefaultScreen(display)), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); return true; } return false; } #define MWM_HINTS_FUNCTIONS (1L << 0) #define MWM_HINTS_DECORATIONS (1L << 1) #define MWM_HINTS_INPUT_MODE (1L << 2) #define MWM_HINTS_STATUS (1L << 3) #define MWM_DECOR_ALL (1L<<0) #define MWM_DECOR_BORDER (1L<<1) #define MWM_DECOR_RESIZEH (1L<<2) #define MWM_DECOR_TITLE (1L<<3) #define MWM_DECOR_MENU (1L<<4) #define MWM_DECOR_MINIMIZE (1L<<5) #define MWM_DECOR_MAXIMIZE (1L<<6) #define MWM_FUNC_ALL (1L<<0) #define MWM_FUNC_RESIZE (1L<<1) #define MWM_FUNC_MOVE (1L<<2) #define MWM_FUNC_MINIMIZE (1L<<3) #define MWM_FUNC_MAXIMIZE (1L<<4) #define MWM_FUNC_CLOSE (1L<<5) bool GraphicsWindowX11::setWindowDecorationImplementation(bool flag) { Display* display = getDisplayToUse(); XMapWindow(display, _window ); checkAndSendEventFullScreenIfNeeded(display, _traits->x, _traits->y, _traits->width, _traits->height, flag); struct { unsigned long flags; unsigned long functions; unsigned long decorations; long inputMode; unsigned long status; } wmHints; Atom atom; bool result = false; if( (atom = XInternAtom( display, "_MOTIF_WM_HINTS", 0 )) != None ) { if (flag) { wmHints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS; wmHints.functions = MWM_FUNC_ALL; wmHints.decorations = MWM_DECOR_ALL; wmHints.inputMode = 0; wmHints.status = 0; // if traits says not resize we want to set the functions to exlude MWM_FUNC_RESIZE, // but this bitmask needs to be set if the MWM_FUNC_ALL bit is already set in order to toggle it off. if (_traits.valid() && !_traits->supportsResize) wmHints.functions = wmHints.functions | MWM_FUNC_RESIZE; } else { wmHints.flags = MWM_HINTS_DECORATIONS; wmHints.functions = 0; wmHints.decorations = 0; wmHints.inputMode = 0; wmHints.status = 0; } XChangeProperty( display, _window, atom, atom, 32, PropModeReplace, (unsigned char *)&wmHints, 5 ); result = true; } else { OSG_NOTICE<<"Error: GraphicsWindowX11::setWindowDecorationImplementation(" << flag << ") - couldn't change decorations." << std::endl; result = false; } XFlush(display); XSync(display,0); // add usleep here to give window manager a chance to handle the request, if // we don't add this sleep then any X11 calls right afterwards can produce // X11 errors. usleep(100000); return result; } bool GraphicsWindowX11::setWindowRectangleImplementation(int x, int y, int width, int height) { if (!_initialized) return false; Display* display = getDisplayToUse(); checkAndSendEventFullScreenIfNeeded(display, x, y, width, height, _traits->windowDecoration); XMoveResizeWindow(display, _window, x, y, width, height); XFlush(display); XSync(display, 0); // add usleep here to give window manager a chance to handle the request, if // we don't add this sleep then any X11 calls right afterwards can produce // X11 errors. usleep(100000); return true; } void GraphicsWindowX11::setWindowName(const std::string& name) { if( _window == 0) return; // char *slist[] = { name.c_str(), 0L }; // XTextProperty xtp; // XStringListToTextProperty( slist, 1, &xtp ); Display* display = getDisplayToUse(); if( !display ) return; // XSetWMName( display, _window, &xtp ); XStoreName( display, _window, name.c_str() ); XSetIconName( display, _window, name.c_str() ); XFlush(display); XSync(display,0); _traits->windowName = name; } void GraphicsWindowX11::setCursor(MouseCursor mouseCursor) { Cursor newCursor = getOrCreateCursor(mouseCursor); if (newCursor == _currentCursor) return; _currentCursor = newCursor; if (!_window) return; Display* display = getDisplayToUse(); if (!display) return; XDefineCursor( display, _window, _currentCursor ); XFlush(display); XSync(display, 0); _traits->useCursor = (_currentCursor != getOrCreateCursor(NoCursor)); } Cursor GraphicsWindowX11::getOrCreateCursor(MouseCursor mouseCursor) { std::map::iterator i = _mouseCursorMap.find(mouseCursor); if (i != _mouseCursorMap.end()) return i->second; Display* display = getDisplayToUse(); if (!display) return None; switch (mouseCursor) { case NoCursor: { // create an empty mouse cursor, note that it is safe to destroy the Pixmap just past cursor creation // since the resource in the x server is reference counted. char buff[2] = {0,0}; XColor ncol = {0,0,0,0,DoRed|DoGreen|DoBlue,0}; Pixmap pixmap = XCreateBitmapFromData( display, _parent, buff, 1, 1); _mouseCursorMap[mouseCursor] = XCreatePixmapCursor( display, pixmap, pixmap, &ncol, &ncol, 0, 0 ); XFreePixmap(display, pixmap); // Important to have the pixmap and the buffer still available when the request is sent to the server ... XFlush(display); XSync(display, 0); break; } case RightArrowCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_ptr ); break; case LeftArrowCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_arrow ); break; case InfoCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_hand1 ); break; case DestroyCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_pirate ); break; case HelpCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_question_arrow ); break; case CycleCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_exchange ); break; case SprayCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_spraycan ); break; case WaitCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_watch ); break; case TextCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_xterm ); break; case CrosshairCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_crosshair ); break; case UpDownCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_v_double_arrow ); break; case LeftRightCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_h_double_arrow ); break; case TopSideCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_side ); break; case BottomSideCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_side ); break; case LeftSideCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_side ); break; case RightSideCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_right_side ); break; case TopLeftCorner: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_corner ); break; case TopRightCorner: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_right_corner ); break; case BottomRightCorner: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_right_corner ); break; case BottomLeftCorner: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_left_corner ); break; case HandCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_hand1 ); break; case InheritCursor: default: _mouseCursorMap[mouseCursor] = None; break; }; return _mouseCursorMap[mouseCursor]; } void GraphicsWindowX11::init() { if (_initialized) return; if (!_traits) { _valid = false; return; } // getEventQueue()->setCurrentEventState(osgGA::GUIEventAdapter::getAccumulatedEventState().get()); WindowData* inheritedWindowData = dynamic_cast(_traits->inheritedWindowData.get()); Window windowHandle = inheritedWindowData ? inheritedWindowData->_window : 0; _ownsWindow = windowHandle == 0; _display = XOpenDisplay(_traits->displayName().c_str()); if (!_display) { OSG_NOTICE<<"Error: Unable to open display \"" << XDisplayName(_traits->displayName().c_str()) << "\"."<displayName().c_str()) <<" has no GLX extension." << std::endl; XCloseDisplay( _display ); _display = 0; _valid = false; return; } #endif // OSG_NOTICE<<"GLX extension, errorBase="<(_traits->sharedContext.get()); Context sharedContext = graphicsHandleX11 ? graphicsHandleX11->getContext() : 0; #ifdef OSG_USE_EGL _valid = _ownsWindow ? createWindow() : setWindow(windowHandle); if (!_valid) { XCloseDisplay( _display ); _display = 0; return; } OSG_NOTICE<<"GraphicsWindowX11::init() - window created ="<<_valid< Attributes; Attributes attributes; attributes.push_back(EGL_RED_SIZE); attributes.push_back(_traits->red); attributes.push_back(EGL_GREEN_SIZE); attributes.push_back(_traits->green); attributes.push_back(EGL_BLUE_SIZE); attributes.push_back(_traits->blue); attributes.push_back(EGL_DEPTH_SIZE); attributes.push_back(_traits->depth); if (_traits->alpha) { attributes.push_back(EGL_ALPHA_SIZE); attributes.push_back(_traits->alpha); } if (_traits->stencil) { attributes.push_back(EGL_STENCIL_SIZE); attributes.push_back(_traits->stencil); } if (_traits->sampleBuffers) { attributes.push_back(EGL_SAMPLE_BUFFERS); attributes.push_back(_traits->sampleBuffers); } if (_traits->samples) { attributes.push_back(EGL_SAMPLES); attributes.push_back(_traits->samples); } attributes.push_back(EGL_RENDERABLE_TYPE); attributes.push_back(OSG_EGL_OPENGL_TARGET_BIT); attributes.push_back(EGL_NONE); attributes.push_back(EGL_NONE); int numConfigs; if (!eglChooseConfig(_eglDisplay, &(attributes.front()), &eglConfig, 1, &numConfigs) || (numConfigs != 1)) { OSG_NOTICE<<"GraphicsWindowX11::init() - eglChooseConfig() failed."<syncWindowRectangleWithGraphcisContext(); } bool GraphicsWindowX11::createWindow() { unsigned int screen = _traits->screenNum; _eventDisplay = XOpenDisplay(_traits->displayName().c_str()); _parent = RootWindow( _display, screen ); XWindowAttributes watt; XGetWindowAttributes( _display, _parent, &watt ); // unsigned int parentWindowHeight = watt.height; XSetWindowAttributes swatt; swatt.colormap = XCreateColormap( _display, _parent, _visualInfo->visual, AllocNone); //swatt.colormap = DefaultColormap( _dpy, 10 ); swatt.background_pixel = 0; swatt.border_pixel = 0; swatt.event_mask = 0; unsigned long mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap; if (_traits->overrideRedirect) { swatt.override_redirect = true; mask |= CWOverrideRedirect; OSG_INFO<<"Setting override redirect"<x; int y = _traits->y; int width = _traits->width; int height = _traits->height; unsigned int screenWidth; unsigned int screenHeight; wsi->getScreenResolution(*_traits, screenWidth, screenHeight); bool doFullSceenWorkAround = false; bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight && !_traits->windowDecoration; if (isFullScreen && !_traits->overrideRedirect) { // follows is hack to get around problems with toggling off full screen with modern X11 window // managers that try to be too clever when toggling off full screen and ignore the window size // calls made by the OSG when the initial window size is full screen. Atom netWMStateAtom = XInternAtom(_display, "_NET_WM_STATE", True); Atom netWMStateFullscreenAtom = XInternAtom(_display, "_NET_WM_STATE_FULLSCREEN", True); // we have a modern X11 server so assume we need the do the full screen hack. if (netWMStateAtom != None && netWMStateFullscreenAtom != None) { // artifically reduce the initial window size so that the windowing // system has a size to go back to when toggling off full screen, // we don't have to worry about the window being initially smaller as the // setWindowDecoration(..) implementation with enable full screen for us x = width/4; y = height/4; width /= 2; height /= 2; doFullSceenWorkAround = true; } } _window = XCreateWindow( _display, _parent, x, y, width, height, 0, _visualInfo->depth, InputOutput, _visualInfo->visual, mask, &swatt ); if (!_window) { OSG_NOTICE<<"Error: Unable to create Window."<x; sh.y = _traits->y; sh.width = _traits->width; sh.height = _traits->height; XSetStandardProperties( _display, _window, _traits->windowName.c_str(), _traits->windowName.c_str(), None, 0, 0, &sh); setWindowDecoration(_traits->windowDecoration); useCursor(_traits->useCursor); _deleteWindow = XInternAtom (_display, "WM_DELETE_WINDOW", False); XSetWMProtocols(_display, _window, &_deleteWindow, 1); XFlush( _display ); XSync( _display, 0 ); // get window geometry relative to root window/screen Window child_return; int windowX, windowY; XGetWindowAttributes( _display, _window, &watt ); XTranslateCoordinates( _display, _window, watt.root, watt.x, watt.y, &windowX, &windowY, &child_return); if (_traits->x != windowX || _traits->y != windowY ||_traits->width != watt.width || _traits->height != watt.height) { if (doFullSceenWorkAround) { OSG_INFO<<"Full Screen failed, resizing manually"<x, _traits->y, _traits->width, _traits->height); XFlush(_display); XSync(_display, 0); XGetWindowAttributes( _display, _window, &watt ); XTranslateCoordinates( _display, _window, watt.root, watt.x, watt.y, &windowX, &windowY, &child_return); } resized( windowX, windowY, watt.width, watt.height ); } //OSG_NOTICE<<"After sync apply.x = "<x = watt.x; _traits->y = watt.y; _traits->width = watt.width; _traits->height = watt.height; _parent = DefaultRootWindow( _display ); //_traits->supportsResize = false; _traits->windowDecoration = false; if (_traits->windowName.size()) setWindowName(_traits->windowName); _eventDisplay = XOpenDisplay(_traits->displayName().c_str()); XFlush( _eventDisplay ); XSync( _eventDisplay, 0 ); return true; } bool GraphicsWindowX11::realizeImplementation() { if (_realized) { OSG_NOTICE<<"GraphicsWindowX11::realizeImplementation() Already realized"<syncWindowRectangleWithGraphcisContext(); // Window temp = _window; // XSetWMColormapWindows( _display, _window, &temp, 1); _realized = true; return true; } bool GraphicsWindowX11::makeCurrentImplementation() { if (!_realized) { OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<vsync) { unsigned int counter; glXGetVideoSyncSGI(&counter); glXWaitVideoSyncSGI(1, 0, &counter); } #endif glXSwapBuffers( _display, _window ); #endif while( XPending(_display) ) { XEvent ev; XNextEvent( _display, &ev ); switch( ev.type ) { case ClientMessage: { if (static_cast(ev.xclient.data.l[0]) == _deleteWindow) { OSG_INFO<<"DeleteWindow event received"<closeWindow(); } } } } } bool GraphicsWindowX11::checkEvents() { if (!_realized) return false; Display* display = _eventDisplay; double baseTime = _timeOfLastCheckEvents; double eventTime = baseTime; double resizeTime = eventTime; _timeOfLastCheckEvents = getEventQueue()->getTime(); if (baseTime>_timeOfLastCheckEvents) baseTime = _timeOfLastCheckEvents; // OSG_NOTICE<<"GraphicsWindowX11::checkEvents() : getEventQueue()->getCurrentEventState()->getGraphicsContext()="<getCurrentEventState()->getGraphicsContext()<x; int windowY = _traits->y; int windowWidth = _traits->width; int windowHeight = _traits->height; Time firstEventTime = 0; // OSG_NOTICE<<"Check events"<(ev.xclient.data.l[0]) == _deleteWindow) { OSG_INFO<<"DeleteWindow event received"<closeWindow(eventTime); } break; } case Expose : OSG_INFO<<"Expose x="<(relativeTime)*0.001; int wx, wy; Window win = 0L; if( ev.xmotion.same_screen ) { wx = ev.xmotion.x; wy = ev.xmotion.y; } else { // the mouse in on another screen so need to compute the // coordinates of the mouse position relative to an absolute position // then take away the position of the original window/screen to get // the coordinates relative to the original position. Window root; int rx, ry; unsigned int buttons; int screenOrigin_x = 0; int screenOrigin_y = 0; int i; for(i= 0; i < ScreenCount(display); i++ ) { if( XQueryPointer( display, RootWindow(display, i), &root, &win, &rx, &ry, &wx, &wy, &buttons) ) { break; } screenOrigin_x += DisplayWidth(display, i); } for(i= 0; i < static_cast(_traits->screenNum); i++ ) { screenOrigin_x -= DisplayWidth(display, i); } int dest_x_return, dest_y_return; Window child_return; XTranslateCoordinates(display, _window, _parent, 0, 0, &dest_x_return, &dest_y_return, &child_return); wx += (screenOrigin_x - dest_x_return); wy += (screenOrigin_y - dest_y_return); } float mx = wx; float my = wy; transformMouseXY(mx, my); getEventQueue()->mouseMotion(mx, my, eventTime); // OSG_NOTICE<<"MotionNotify wx="<x || windowY != _traits->y || windowWidth != _traits->width || windowHeight != _traits->height) { resized(windowX, windowY, windowWidth, windowHeight); getEventQueue()->windowResize(windowX, windowY, windowWidth, windowHeight, resizeTime); // request window repaint if window size was changed if (windowWidth != _traits->width || windowHeight != _traits->height) { requestRedraw(); } } return !(getEventQueue()->empty()); } void GraphicsWindowX11::grabFocus() { Display* display = getDisplayToUse(); XSetInputFocus( display, _window, RevertToNone, CurrentTime ); XFlush(display); XSync(display,0); } void GraphicsWindowX11::grabFocusIfPointerInWindow() { Window win, root; int wx, wy, rx, ry; unsigned int buttons; Display* display = getDisplayToUse(); if( XQueryPointer( display, _window, &root, &win, &rx, &ry, &wx, &wy, &buttons)) { #if 0 if (wx>=0 && wx<_traits->width && wy>=0 && wy<_traits->height) { grabFocus(); } #else grabFocus(); #endif } } void GraphicsWindowX11::transformMouseXY(float& x, float& y) { if (getEventQueue()->getUseFixedMouseInputRange()) { osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState(); x = eventState->getXmin() + (eventState->getXmax()-eventState->getXmin())*x/float(_traits->width); y = eventState->getYmin() + (eventState->getYmax()-eventState->getYmin())*y/float(_traits->height); } } void GraphicsWindowX11::adaptKey(XKeyEvent& keyevent, int& keySymbol, int& unmodifiedKeySymbol) { unsigned char buffer_return[32]; int bytes_buffer = 32; KeySym keysym_return; int numChars = XLookupString(&keyevent, reinterpret_cast(buffer_return), bytes_buffer, &keysym_return, NULL); keySymbol = keysym_return; if (!remapExtendedX11Key(keySymbol) && (numChars==1)) { keySymbol = buffer_return[0]; } unmodifiedKeySymbol = XkbKeycodeToKeysym(keyevent.display, keyevent.keycode, 0, 0); } // Function to inject artificial key presses/releases. void GraphicsWindowX11::forceKey(int key, double time, bool state) { if (!(state ^ keyMapGetKey(_keyMap, key))) return; // already pressed/released XKeyEvent event; event.serial = 0; event.send_event = True; event.display = _eventDisplay; event.window = _window; event.subwindow = 0; event.time = 0; event.x = 0; event.y = 0; event.x_root = 0; event.y_root = 0; event.state = getModifierMask() | (_modifierState & (LockMask | _numLockMask)); event.keycode = key; event.same_screen = True; int keySymbol = 0; int unmodifiedKeySymbol = 0; if (state) { event.type = KeyPress; adaptKey(event, keySymbol, unmodifiedKeySymbol); getEventQueue()->keyPress(keySymbol, time, unmodifiedKeySymbol); keyMapSetKey(_keyMap, key); } else { event.type = KeyRelease; adaptKey(event, keySymbol, unmodifiedKeySymbol); getEventQueue()->keyRelease(keySymbol, time, unmodifiedKeySymbol); keyMapClearKey(_keyMap, key); } } void GraphicsWindowX11::syncLocks() { unsigned int mask = getEventQueue()->getCurrentEventState()->getModKeyMask(); if (_modifierState & LockMask) mask |= osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK; else mask &= ~osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK; if (_modifierState & _numLockMask) mask |= osgGA::GUIEventAdapter::MODKEY_NUM_LOCK; else mask &= ~osgGA::GUIEventAdapter::MODKEY_NUM_LOCK; getEventQueue()->getCurrentEventState()->setModKeyMask(mask); } void GraphicsWindowX11::rescanModifierMapping() { XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay); KeyCode *m = mkm->modifiermap; KeyCode numlock = XKeysymToKeycode(_eventDisplay, XK_Num_Lock); _numLockMask = 0; for (int i = 0; i < mkm->max_keypermod * 8; i++, m++) { if (*m == numlock) { _numLockMask = 1 << (i / mkm->max_keypermod); break; } } XFree(mkm->modifiermap); XFree(mkm); } void GraphicsWindowX11::flushKeyEvents() { XEvent e; while (XCheckMaskEvent(_eventDisplay, KeyPressMask|KeyReleaseMask, &e)) continue; } // Returns char[32] keymap with bits for every modifier key set. void GraphicsWindowX11::getModifierMap(char* keymap) const { memset(keymap, 0, 32); XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay); KeyCode *m = mkm->modifiermap; for (int i = 0; i < mkm->max_keypermod * 8; i++, m++) { if (*m) keyMapSetKey(keymap, *m); } XFree(mkm->modifiermap); XFree(mkm); } int GraphicsWindowX11::getModifierMask() const { int mask = 0; XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay); for (int i = 0; i < mkm->max_keypermod * 8; i++) { unsigned int key = mkm->modifiermap[i]; if (key && keyMapGetKey(_keyMap, key)) { mask |= 1 << (i / mkm->max_keypermod); } } XFree(mkm->modifiermap); XFree(mkm); return mask; } void GraphicsWindowX11::requestWarpPointer(float x,float y) { if (!_realized) { OSG_INFO<<"GraphicsWindowX11::requestWarpPointer() - Window not realized; cannot warp pointer, screenNum="<< _traits->screenNum<(x), static_cast(y) ); XFlush(display); XSync(display, 0); getEventQueue()->mouseWarped(x,y); } extern "C" { typedef int (*X11ErrorHandler)(Display*, XErrorEvent*); int X11ErrorHandling(Display* display, XErrorEvent* event) { OSG_NOTICE<<"Got an X11ErrorHandling call display="<request_code << std::endl; OSG_NOTICE << "Minor opcode: " << (int)event->minor_code << std::endl; OSG_NOTICE << "Error code: " << (int)event->error_code << std::endl; OSG_NOTICE << "Request serial: " << event->serial << std::endl; OSG_NOTICE << "Current serial: " << NextRequest( display ) - 1 << std::endl; switch( event->error_code ) { case BadValue: OSG_NOTICE << " Value: " << event->resourceid << std::endl; break; case BadAtom: OSG_NOTICE << " AtomID: " << event->resourceid << std::endl; break; default: OSG_NOTICE << " ResourceID: " << event->resourceid << std::endl; break; } return 0; } } class X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface { #ifdef OSGVIEWER_USE_XRANDR // TODO: Investigate whether or not Robert thinks we should store/restore the original // resolution in the destructor; I'm not sure the other ones do this, and it may be the // responsibility of the user. bool _setScreen(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height, unsigned int colorDepth, double rate) { if (colorDepth>0) OSG_NOTICE << "X11WindowingSystemInterface::_setScreen() is not fully implemented (missing depth)."<(width) && ss[i].height == static_cast(height)) { short* rates = XRRConfigRates(sc, i, &numRates); bool rateFound = false; // Search for our rate in the list of acceptable rates given to us by Xrandr. // If it's not found, rateFound will still be false and the call will never // be made to XRRSetScreenConfigAndRate since the rate will be invalid. for(int r = 0; r < numRates; r++) { if(rates[r] == static_cast(rate)) { rateFound = true; break; } } if(rate > 0.0f && !rateFound) { OSG_NOTICE << "Unable to find valid refresh rate " << rate << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<(rate), CurrentTime) != RRSetConfigSuccess) { OSG_NOTICE << "Unable to set resolution to " << width << "x" << height << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<setNumFramesToRetainObjects(0); osg::Referenced::getDeleteHandler()->flushAll(); } //OSG_NOTICE<<"~X11WindowingSystemInterface()"< 1 || ( major == 1 && minor >= 2 ) ); } #endif return false; } virtual void getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution ) { Display* display = XOpenDisplay(si.displayName().c_str()); if(display) { resolution.width = DisplayWidth(display, si.screenNum); resolution.height = DisplayHeight(display, si.screenNum); resolution.colorDepth = DefaultDepth(display, si.screenNum); resolution.refreshRate = 0; // Missing call. Need a X11 expert. #ifdef OSGVIEWER_USE_XRANDR if (supportsRandr(display)) { XRRScreenConfiguration* screenConfig = XRRGetScreenInfo ( display, RootWindow(display, si.screenNum) ); resolution.refreshRate = XRRConfigCurrentRate ( screenConfig ); XRRFreeScreenConfigInfo( screenConfig ); } #endif XCloseDisplay(display); } else { OSG_NOTICE << "Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\"."<0) { for(int i=0; i0) { for(int j=0; jpbuffer) { #if 1 osg::ref_ptr pbuffer = new PixelBufferX11(traits); if (pbuffer->valid()) return pbuffer.release(); else return 0; #else osg::ref_ptr window = new GraphicsWindowX11(traits); if (window->valid()) return window.release(); else return 0; #endif } else { osg::ref_ptr window = new GraphicsWindowX11(traits); if (window->valid()) return window.release(); else return 0; } } }; struct RegisterWindowingSystemInterfaceProxy { RegisterWindowingSystemInterfaceProxy() { OSG_INFO<<"RegisterWindowingSystemInterfaceProxy()"<setNumFramesToRetainObjects(0); osg::Referenced::getDeleteHandler()->flushAll(); } osg::GraphicsContext::setWindowingSystemInterface(0); } }; RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy; // declare C entry point for static compilation. extern "C" void graphicswindow_X11(void) { osg::GraphicsContext::setWindowingSystemInterface(new X11WindowingSystemInterface); } void GraphicsWindowX11::raiseWindow() { Display* display = getDisplayToUse(); if(!display) return; // get handles to window props of interest Atom stateAbove = XInternAtom(display, "_NET_WM_STATE_ABOVE", True); Atom stateAtom = XInternAtom(display, "_NET_WM_STATE", True); // check that atoms are supported if(stateAbove != None && stateAtom != None) { // fill an XEvent struct to send XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.serial = 0; xev.xclient.send_event = True; xev.xclient.window = _window; xev.xclient.message_type = stateAtom; xev.xclient.format = 32; xev.xclient.data.l[0] = 1; xev.xclient.data.l[1] = stateAbove; xev.xclient.data.l[2] = 0; XSendEvent(display, RootWindow(display, DefaultScreen(display)), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); } else { // one or both of _NET_WM_STATE and _NET_WM_STATE_ABOVE aren't supported // try to use XRaiseWindow XWindowAttributes winAttrib; Window root_return, parent_return, *children; unsigned int nchildren, i=0; XTextProperty windowName; bool xraise = false; // get the window tree around our current window XQueryTree(display, _parent, &root_return, &parent_return, &children, &nchildren); while (!xraise && iwindowName.c_str(),(const char *)windowName.value) == 0)) xraise = true; } if (xraise) XRaiseWindow(display,_window); else { XGetWindowAttributes(display, _window, &winAttrib); XReparentWindow(display, _window, _parent, winAttrib.x, winAttrib.y); } XFree(children); } XFlush(display); XSync(display,0); } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/DarwinUtils.mm0000644000175000017500000003750311633431050024570 0ustar albertoalberto/* * DarwinUtils.cpp * OpenSceneGraph * * Created by Stephan Huber on 27.06.08. * Copyright 2008 Stephan Maximilian Huber, digital mind. All rights reserved. * */ #include #include #include "DarwinUtils.h" #include @interface MenubarToggler : NSObject { } -(void) show: (id) data; -(void) hide: (id) data; @end @implementation MenubarToggler -(void) hide:(id) data { OSErr error = SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar); if (error) { OSG_DEBUG << "MenubarToggler::hide failed with " << error << std::endl; } } -(void) show:(id) data { OSErr error = SetSystemUIMode(kUIModeNormal, 0); if (error) { OSG_DEBUG << "MenubarToggler::show failed with " << error << std::endl; } } @end namespace osgDarwin { // // Lion replacement for CGDisplayBitsPerPixel(CGDirectDisplayID displayId) // size_t displayBitsPerPixel( CGDirectDisplayID displayId ) { #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 return CGDisplayBitsPerPixel(displayId); #else CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId); if (!mode) { OSG_WARN << "CGDisplayCopyDisplayMode returned NULL" << std::endl; return 0; } CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(mode); if (!pixEnc) { OSG_WARN << "CGDisplayModeCopyPixelEncoding returned NULL" << std::endl; CGDisplayModeRelease(mode); return 0; } size_t depth = 0; if (CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { depth = 32; } else if (CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { depth = 16; } else if (CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { depth = 8; } else { OSG_WARN << "Unable to match pixel encoding '" << CFStringGetCStringPtr(pixEnc, kCFStringEncodingUTF8) << "'" << std::endl; } CGDisplayModeRelease(mode); CFRelease(pixEnc); return depth; #endif } static inline CGRect toCGRect(NSRect nsRect) { CGRect cgRect; cgRect.origin.x = nsRect.origin.x; cgRect.origin.y = nsRect.origin.y; cgRect.size.width = nsRect.size.width; cgRect.size.height = nsRect.size.height; return cgRect; } MenubarController::MenubarController() : osg::Referenced(), _list(), _menubarShown(false), _mutex() { // the following code will query the system for the available rect on the main-display (typically the displaying showing the menubar + the dock NSRect rect = [[[NSScreen screens] objectAtIndex: 0] visibleFrame]; _availRect = toCGRect(rect); // now we need the rect of the main-display including the menubar and the dock _mainScreenBounds = CGDisplayBounds( CGMainDisplayID() ); // NSRect 0/0 is bottom/left, _mainScreenBounds 0/0 is top/left _availRect.origin.y = _mainScreenBounds.size.height - _availRect.size.height - _availRect.origin.y; // hide the menubar initially SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar); } MenubarController* MenubarController::instance() { static osg::ref_ptr s_menubar_controller = new MenubarController(); return s_menubar_controller.get(); } void MenubarController::attachWindow(WindowAdapter* win) { OpenThreads::ScopedLock lock(_mutex); _list.push_back(win); update(); } void MenubarController::detachWindow(osgViewer::GraphicsWindow* win) { OpenThreads::ScopedLock lock(_mutex); for(WindowList::iterator i = _list.begin(); i != _list.end(); ) { if ((*i)->getWindow() == win) i = _list.erase(i); else ++i; } update(); } // iterate through all open windows and check, if they intersect the area occupied by the menubar/dock, and if so, hide the menubar/dock void MenubarController::update() { unsigned int windowsCoveringMenubarArea = 0; unsigned int windowsIntersectingMainScreen = 0; for(WindowList::iterator i = _list.begin(); i != _list.end(); ) { WindowAdapter* wi = (*i).get(); if (wi->valid()) { CGRect windowBounds; wi->getWindowBounds(windowBounds); if (CGRectIntersectsRect(_mainScreenBounds, windowBounds)) { ++windowsIntersectingMainScreen; // OSG_ALWAYS << "testing rect " << windowBounds.origin.x << "/" << windowBounds.origin.y << " " << windowBounds.size.width << "x" << windowBounds.size.height << std::endl; // OSG_ALWAYS << "against " << _availRect.origin.x << "/" << _availRect.origin.y << " " << _availRect.size.width << "x" << _availRect.size.height << std::endl; // the window intersects the main-screen, does it intersect with the menubar/dock? if (((_availRect.origin.y > _mainScreenBounds.origin.y) && (_availRect.origin.y > windowBounds.origin.y)) || ((_availRect.origin.x > _mainScreenBounds.origin.x) && (_availRect.origin.x > windowBounds.origin.x)) || ((_availRect.size.width < _mainScreenBounds.size.width) && (_availRect.origin.x + _availRect.size.width < windowBounds.origin.x + windowBounds.size.width)) || ((_availRect.size.height < _mainScreenBounds.size.height) && (_availRect.origin.y + _availRect.size.height < windowBounds.origin.y + windowBounds.size.height) )) { ++windowsCoveringMenubarArea; } } ++i; } else i = _list.erase(i); } // if we use the cocoa implementation then we have a NSRunLoop in place, and so we can use the deferred menubar-toggling which is thread safe #ifdef USE_DARWIN_COCOA_IMPLEMENTATION // SetSystemUIMode is not threadsafe, you'll get crashes if you call this method from other threads // so use a small NSObject to switch the menubar on the main thread via performSelectorOnMainThread NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (windowsCoveringMenubarArea && _menubarShown) { //error = SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar); MenubarToggler* toggler = [[MenubarToggler alloc] init]; [toggler performSelectorOnMainThread: @selector(hide:) withObject:NULL waitUntilDone: YES]; [toggler autorelease]; } if (!windowsCoveringMenubarArea && !_menubarShown) { //error = SetSystemUIMode(kUIModeNormal, 0); MenubarToggler* toggler = [[MenubarToggler alloc] init]; [toggler performSelectorOnMainThread: @selector(show:) withObject:NULL waitUntilDone: YES]; [toggler autorelease]; } [pool release]; #else OSErr error; // see http://developer.apple.com/technotes/tn2002/tn2062.html for hiding the dock+menubar if (windowsCoveringMenubarArea && _menubarShown) { error = SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar); } if (!windowsCoveringMenubarArea && !_menubarShown) { error = SetSystemUIMode(kUIModeNormal, 0); } #endif _menubarShown = !windowsCoveringMenubarArea; } /** Helper method to get a double value out of a CFDictionary */ static double getDictDouble (CFDictionaryRef refDict, CFStringRef key) { double value; CFNumberRef number_value = (CFNumberRef) CFDictionaryGetValue(refDict, key); if (!number_value) // if can't get a number for the dictionary return -1; // fail if (!CFNumberGetValue(number_value, kCFNumberDoubleType, &value)) // or if cant convert it return -1; // fail return value; // otherwise return the long value } /** Helper method to get a long value out of a CFDictionary */ static long getDictLong(CFDictionaryRef refDict, CFStringRef key) // const void* key? { long value = 0; CFNumberRef number_value = (CFNumberRef)CFDictionaryGetValue(refDict, key); if (!number_value) // if can't get a number for the dictionary return -1; // fail if (!CFNumberGetValue(number_value, kCFNumberLongType, &value)) // or if cant convert it return -1; // fail return value; } /** ctor, get a list of all attached displays */ DarwinWindowingSystemInterface::DarwinWindowingSystemInterface() : _initialized(false), _displayCount(0), _displayIds(NULL) { } /** dtor */ DarwinWindowingSystemInterface::~DarwinWindowingSystemInterface() { if (osg::Referenced::getDeleteHandler()) { osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); osg::Referenced::getDeleteHandler()->flushAll(); } if (_displayIds) delete[] _displayIds; _displayIds = NULL; } void DarwinWindowingSystemInterface::_init() { if (_initialized) return; ProcessSerialNumber sn = { 0, kCurrentProcess }; TransformProcessType(&sn,kProcessTransformToForegroundApplication); SetFrontProcess(&sn); if( CGGetActiveDisplayList( 0, NULL, &_displayCount ) != CGDisplayNoErr ) { OSG_WARN << "DarwinWindowingSystemInterface: could not get # of screens" << std::endl; _displayCount = 0; _initialized = true; return; } _displayIds = new CGDirectDisplayID[_displayCount]; if( CGGetActiveDisplayList( _displayCount, _displayIds, &_displayCount ) != CGDisplayNoErr ) { OSG_WARN << "DarwinWindowingSystemInterface: CGGetActiveDisplayList failed" << std::endl; } _initialized = true; } /** @return a CGDirectDisplayID for a ScreenIdentifier */ CGDirectDisplayID DarwinWindowingSystemInterface::getDisplayID(const osg::GraphicsContext::ScreenIdentifier& si) { _init(); if (_displayCount==0) { OSG_WARN << "DarwinWindowingSystemInterface::getDisplayID(..) no valid screens available returning 0 instead." << std::endl; return 0; } if (si.screenNum < static_cast(_displayCount)) { return _displayIds[si.screenNum]; } else { OSG_WARN << "DarwinWindowingSystemInterface::getDisplayID(..) invalid screen # " << si.screenNum << ", returning main-screen instead." << std::endl; return _displayIds[0]; } } /** @return count of attached screens */ unsigned int DarwinWindowingSystemInterface::getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si) { _init(); return _displayCount; } void DarwinWindowingSystemInterface::getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution) { _init(); if (_displayCount==0) { resolution.width = 0; resolution.height = 0; resolution.colorDepth = 0; resolution.refreshRate = 0; return; } CGDirectDisplayID id = getDisplayID(si); resolution.width = CGDisplayPixelsWide(id); resolution.height = CGDisplayPixelsHigh(id); resolution.colorDepth = displayBitsPerPixel(id); resolution.refreshRate = getDictDouble (CGDisplayCurrentMode(id), kCGDisplayRefreshRate); // Not tested if (resolution.refreshRate<0) resolution.refreshRate = 0; } void DarwinWindowingSystemInterface::enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, osg::GraphicsContext::ScreenSettingsList & resolutionList) { _init(); // Warning! This method has not been tested. resolutionList.clear(); if (_displayCount==0) { return; } CGDirectDisplayID displayid = getDisplayID(screenIdentifier); CFArrayRef availableModes = CGDisplayAvailableModes(displayid); unsigned int numberOfAvailableModes = CFArrayGetCount(availableModes); for (unsigned int i=0; i(bounds.origin.x); y = static_cast(bounds.origin.y); // OSG_DEBUG << "topleft of screen " << si.screenNum <<" " << bounds.origin.x << "/" << bounds.origin.y << std::endl; } bool DarwinWindowingSystemInterface::setScreenSettings(const osg::GraphicsContext::ScreenIdentifier &si, const osg::GraphicsContext::ScreenSettings & settings) { bool result = setScreenResolutionImpl(si, settings.width, settings.height); if (result) { setScreenRefreshRateImpl(si, settings.refreshRate); } return result; } /** implementation of setScreenResolution */ bool DarwinWindowingSystemInterface::setScreenResolutionImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, unsigned int width, unsigned int height) { _init(); if (_displayCount==0) { return false; } CGDirectDisplayID displayid = getDisplayID(screenIdentifier); // add next line and on following line replace hard coded depth and refresh rate CGRefreshRate refresh = getDictDouble (CGDisplayCurrentMode(displayid), kCGDisplayRefreshRate); CFDictionaryRef display_mode_values = CGDisplayBestModeForParametersAndRefreshRate( displayid, displayBitsPerPixel(displayid), width, height, refresh, NULL); CGDisplaySwitchToMode(displayid, display_mode_values); return true; } /** implementation of setScreenRefreshRate */ bool DarwinWindowingSystemInterface::setScreenRefreshRateImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, double refreshRate) { _init(); if (_displayCount==0) { return false; } boolean_t success(false); unsigned width, height; getScreenResolution(screenIdentifier, width, height); CGDirectDisplayID displayid = getDisplayID(screenIdentifier); // add next line and on following line replace hard coded depth and refresh rate CFDictionaryRef display_mode_values = CGDisplayBestModeForParametersAndRefreshRate( displayid, displayBitsPerPixel(displayid), width, height, refreshRate, &success); if (success) CGDisplaySwitchToMode(displayid, display_mode_values); return (success != 0); } unsigned int DarwinWindowingSystemInterface::getScreenContaining(int x, int y, int w, int h) { _init(); if (_displayCount==0) { return 0; } CGRect rect = CGRectMake(x,y,w,h); for(unsigned int i = 0; i < _displayCount; ++i) { CGRect bounds = CGDisplayBounds( getDisplayID(i) ); if (CGRectIntersectsRect(bounds, rect)) { return i; } } return 0; } } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/Scene.cpp0000644000175000017500000000717112147720211023530 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include using namespace osgViewer; namespace osgViewer { struct SceneSingleton { SceneSingleton() {} inline void add(Scene* scene) { OpenThreads::ScopedLock lock(_mutex); _cache.push_back(scene); } inline void remove(Scene* scene) { OpenThreads::ScopedLock lock(_mutex); for(SceneCache::iterator itr = _cache.begin(); itr != _cache.end(); ++itr) { if (scene==itr->get()) { _cache.erase(itr); break; } } } inline Scene* getScene(osg::Node* node) { OpenThreads::ScopedLock lock(_mutex); for(SceneCache::iterator itr = _cache.begin(); itr != _cache.end(); ++itr) { Scene* scene = itr->get(); if (scene && scene->getSceneData()==node) return scene; } return 0; } typedef std::vector< osg::observer_ptr > SceneCache; SceneCache _cache; OpenThreads::Mutex _mutex; }; static SceneSingleton& getSceneSingleton() { static SceneSingleton s_sceneSingleton; return s_sceneSingleton; } // Use a proxy to force the initialization of the SceneSingleton during static initialization OSG_INIT_SINGLETON_PROXY(SceneSingletonProxy, getSceneSingleton()) } Scene::Scene(): osg::Referenced(true) { setDatabasePager(osgDB::DatabasePager::create()); setImagePager(new osgDB::ImagePager); getSceneSingleton().add(this); } Scene::~Scene() { getSceneSingleton().remove(this); } void Scene::setSceneData(osg::Node* node) { _sceneData = node; } osg::Node* Scene::getSceneData() { return _sceneData.get(); } const osg::Node* Scene::getSceneData() const { return _sceneData.get(); } void Scene::setDatabasePager(osgDB::DatabasePager* dp) { _databasePager = dp; } void Scene::setImagePager(osgDB::ImagePager* ip) { _imagePager = ip; } void Scene::updateSceneGraph(osg::NodeVisitor& updateVisitor) { if (!_sceneData) return; if (getDatabasePager()) { // synchronize changes required by the DatabasePager thread to the scene graph getDatabasePager()->updateSceneGraph((*updateVisitor.getFrameStamp())); } if (getImagePager()) { // synchronize changes required by the DatabasePager thread to the scene graph getImagePager()->updateSceneGraph(*(updateVisitor.getFrameStamp())); } if (getSceneData()) { updateVisitor.setImageRequestHandler(getImagePager()); getSceneData()->accept(updateVisitor); } } Scene* Scene::getScene(osg::Node* node) { return getSceneSingleton().getScene(node); return 0; } Scene* Scene::getOrCreateScene(osg::Node* node) { if (!node) return 0; osgViewer::Scene* scene = getScene(node); if (!scene) { scene = new Scene; scene->setSceneData(node); } return scene; } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/HelpHandler.cpp0000644000175000017500000001421312057617137024670 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include using namespace osgViewer; HelpHandler::HelpHandler(osg::ApplicationUsage* au): _applicationUsage(au), _keyEventTogglesOnScreenHelp('h'), _helpEnabled(false), _initialized(false) { _camera = new osg::Camera; _camera->setRenderer(new Renderer(_camera.get())); _camera->setRenderOrder(osg::Camera::POST_RENDER, 11); } void HelpHandler::reset() { _initialized = false; _camera->setGraphicsContext(0); } bool HelpHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { osgViewer::View* view = dynamic_cast(&aa); if (!view) return false; osgViewer::ViewerBase* viewer = view->getViewerBase(); if (!viewer) return false; if (ea.getHandled()) return false; switch(ea.getEventType()) { case(osgGA::GUIEventAdapter::KEYDOWN): { if (ea.getKey()==_keyEventTogglesOnScreenHelp) { if (!_initialized) { setUpHUDCamera(viewer); setUpScene(viewer); } _helpEnabled = !_helpEnabled; if (_helpEnabled) { _camera->setNodeMask(0xffffffff); } else { _camera->setNodeMask(0); } return true; } } default: break; } return false; } void HelpHandler::setUpHUDCamera(osgViewer::ViewerBase* viewer) { osgViewer::GraphicsWindow* window = dynamic_cast(_camera->getGraphicsContext()); if (!window) { osgViewer::Viewer::Windows windows; viewer->getWindows(windows); if (windows.empty()) return; window = windows.front(); _camera->setGraphicsContext(window); } _camera->setGraphicsContext(window); _camera->setViewport(0, 0, window->getTraits()->width, window->getTraits()->height); _camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1280,0,1024)); _camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); _camera->setViewMatrix(osg::Matrix::identity()); // only clear the depth buffer _camera->setClearMask(0); _initialized = true; } void HelpHandler::setUpScene(osgViewer::ViewerBase* viewer) { _switch = new osg::Switch; _camera->addChild(_switch.get()); osg::StateSet* stateset = _switch->getOrCreateStateSet(); stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); stateset->setMode(GL_BLEND,osg::StateAttribute::ON); stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF); stateset->setAttribute(new osg::PolygonMode(), osg::StateAttribute::PROTECTED); std::string font("fonts/arial.ttf"); if (!_applicationUsage) setApplicationUsage(new osg::ApplicationUsage()); viewer->getUsage(*_applicationUsage); float leftPos = 10.0f; float startDescription = 200.0f; float characterSize = 20.0f; osg::Vec3 pos(leftPos,1000.0f,0.0f); osg::Vec4 color(1.0f,1.0f,1.0f,1.0f); osg::Geode* geode = new osg::Geode(); _switch->addChild(geode, true); // application description if (!_applicationUsage->getDescription().empty()) { osg::ref_ptr label = new osgText::Text; geode->addDrawable( label.get() ); label->setColor(color); label->setBackdropType(osgText::Text::OUTLINE); label->setFont(font); label->setCharacterSize(characterSize); label->setPosition(pos); label->setText(_applicationUsage->getDescription()); pos.x() = label->getBound().xMax(); pos.y() -= characterSize*2.5f; } const osg::ApplicationUsage::UsageMap& keyboardBinding = _applicationUsage->getKeyboardMouseBindings(); for(osg::ApplicationUsage::UsageMap::const_iterator itr = keyboardBinding.begin(); itr != keyboardBinding.end(); ++itr) { pos.x() = leftPos; osg::ref_ptr key = new osgText::Text; geode->addDrawable( key.get() ); key->setColor(color); key->setBackdropType(osgText::Text::OUTLINE); key->setFont(font); key->setCharacterSize(characterSize); key->setPosition(pos); key->setText(itr->first); pos.x() = startDescription; osg::ref_ptr description = new osgText::Text; geode->addDrawable( description.get() ); description->setColor(color); description->setBackdropType(osgText::Text::OUTLINE); description->setFont(font); description->setCharacterSize(characterSize); description->setPosition(pos); description->setText(itr->second); pos.y() -= characterSize*1.5f; } osg::BoundingBox bb = geode->getBoundingBox(); if (bb.valid()) { float width = bb.xMax() - bb.xMin(); float height = bb.yMax() - bb.yMin(); float ratio = 1.0; if (width > 1024.0f) ratio = 1024.0f/width; if (height*ratio > 800.0f) ratio = 800.0f/height; _camera->setViewMatrix(osg::Matrix::translate(-bb.center()) * osg::Matrix::scale(ratio,ratio,ratio) * osg::Matrix::translate(osg::Vec3(640.0f, 520.0f, 0.0f))); } } void HelpHandler::getUsage(osg::ApplicationUsage& usage) const { if (_keyEventTogglesOnScreenHelp) usage.addKeyboardMouseBinding(_keyEventTogglesOnScreenHelp,"Onscreen help."); } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/ScreenCaptureHandler.cpp0000644000175000017500000007113412163275353026546 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include namespace osgViewer { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // WindowCaptureCallback // // From osgscreencapture example /** Callback which will be added to a viewer's camera to do the actual screen capture. */ class WindowCaptureCallback : public osg::Camera::DrawCallback { public: enum Mode { READ_PIXELS, SINGLE_PBO, DOUBLE_PBO, TRIPLE_PBO }; enum FramePosition { START_FRAME, END_FRAME }; WindowCaptureCallback(int numFrames, Mode mode, FramePosition position, GLenum readBuffer); FramePosition getFramePosition() const { return _position; } void setCaptureOperation(ScreenCaptureHandler::CaptureOperation* operation); ScreenCaptureHandler::CaptureOperation* getCaptureOperation() { return _contextDataMap.begin()->second->_captureOperation.get(); } void setFramesToCapture(int numFrames) { _numFrames = numFrames; } int getFramesToCapture() const { return _numFrames; } virtual void operator () (osg::RenderInfo& renderInfo) const; struct OSGVIEWER_EXPORT ContextData : public osg::Referenced { ContextData(osg::GraphicsContext* gc, Mode mode, GLenum readBuffer); void getSize(osg::GraphicsContext* gc, int& width, int& height); void updateTimings(osg::Timer_t tick_start, osg::Timer_t tick_afterReadPixels, osg::Timer_t tick_afterMemCpy, osg::Timer_t tick_afterCaptureOperation, unsigned int dataSize); void read(); void readPixels(); void singlePBO(osg::GLBufferObject::Extensions* ext); void multiPBO(osg::GLBufferObject::Extensions* ext); typedef std::vector< osg::ref_ptr > ImageBuffer; typedef std::vector< GLuint > PBOBuffer; osg::GraphicsContext* _gc; unsigned int _index; Mode _mode; GLenum _readBuffer; GLenum _pixelFormat; GLenum _type; int _width; int _height; unsigned int _currentImageIndex; ImageBuffer _imageBuffer; unsigned int _currentPboIndex; PBOBuffer _pboBuffer; unsigned int _reportTimingFrequency; unsigned int _numTimeValuesRecorded; double _timeForReadPixels; double _timeForMemCpy; double _timeForCaptureOperation; double _timeForFullCopy; double _timeForFullCopyAndOperation; osg::Timer_t _previousFrameTick; osg::ref_ptr _captureOperation; }; typedef std::map > ContextDataMap; ContextData* createContextData(osg::GraphicsContext* gc) const; ContextData* getContextData(osg::GraphicsContext* gc) const; Mode _mode; FramePosition _position; GLenum _readBuffer; mutable OpenThreads::Mutex _mutex; mutable ContextDataMap _contextDataMap; mutable int _numFrames; osg::ref_ptr _defaultCaptureOperation; }; WindowCaptureCallback::ContextData::ContextData(osg::GraphicsContext* gc, Mode mode, GLenum readBuffer) : _gc(gc), _index(_gc->getState()->getContextID()), _mode(mode), _readBuffer(readBuffer), _pixelFormat(GL_RGBA), _type(GL_UNSIGNED_BYTE), _width(0), _height(0), _currentImageIndex(0), _currentPboIndex(0), _reportTimingFrequency(100), _numTimeValuesRecorded(0), _timeForReadPixels(0.0), _timeForMemCpy(0.0), _timeForCaptureOperation(0.0), _timeForFullCopy(0.0), _timeForFullCopyAndOperation(0.0), _previousFrameTick(0) { _previousFrameTick = osg::Timer::instance()->tick(); osg::NotifySeverity level = osg::INFO; if (gc->getTraits()) { if (gc->getTraits()->alpha) { OSG_NOTIFY(level)<<"ScreenCaptureHandler: Selected GL_RGBA read back format"<getTraits()) { width = gc->getTraits()->width; height = gc->getTraits()->height; } } void WindowCaptureCallback::ContextData::updateTimings(osg::Timer_t tick_start, osg::Timer_t tick_afterReadPixels, osg::Timer_t tick_afterMemCpy, osg::Timer_t tick_afterCaptureOperation, unsigned int /*dataSize*/) { _timeForReadPixels = osg::Timer::instance()->delta_s(tick_start, tick_afterReadPixels); _timeForMemCpy = osg::Timer::instance()->delta_s(tick_afterReadPixels, tick_afterMemCpy); _timeForCaptureOperation = osg::Timer::instance()->delta_s(tick_afterMemCpy, tick_afterCaptureOperation); _timeForFullCopy = osg::Timer::instance()->delta_s(tick_start, tick_afterMemCpy); _timeForFullCopyAndOperation = osg::Timer::instance()->delta_s(tick_start, tick_afterCaptureOperation); } void WindowCaptureCallback::ContextData::read() { osg::GLBufferObject::Extensions* ext = osg::GLBufferObject::getExtensions(_gc->getState()->getContextID(),true); if (ext->isPBOSupported() && !_pboBuffer.empty()) { if (_pboBuffer.size()==1) { singlePBO(ext); } else { multiPBO(ext); } } else { readPixels(); } } void WindowCaptureCallback::ContextData::readPixels() { unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size(); unsigned int nextPboIndex = _pboBuffer.empty() ? 0 : (_currentPboIndex+1)%_pboBuffer.size(); int width=0, height=0; getSize(_gc, width, height); if (width!=_width || _height!=height) { //OSG_NOTICE<<" Window resized "<tick(); #if 1 image->readPixels(0,0,_width,_height, _pixelFormat,_type); #endif osg::Timer_t tick_afterReadPixels = osg::Timer::instance()->tick(); if (_captureOperation.valid()) { (*_captureOperation)(*image, _index); } osg::Timer_t tick_afterCaptureOperation = osg::Timer::instance()->tick(); updateTimings(tick_start, tick_afterReadPixels, tick_afterReadPixels, tick_afterCaptureOperation, image->getTotalSizeInBytes()); _currentImageIndex = nextImageIndex; _currentPboIndex = nextPboIndex; } void WindowCaptureCallback::ContextData::singlePBO(osg::GLBufferObject::Extensions* ext) { unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size(); int width=0, height=0; getSize(_gc, width, height); if (width!=_width || _height!=height) { //OSG_NOTICE<<" Window resized "<s() != _width || image->t() != _height) { //OSG_NOTICE<<"ScreenCaptureHandler: Allocating image "<allocateImage(_width, _height, 1, _pixelFormat, _type); if (pbo!=0) { //OSG_NOTICE<<"ScreenCaptureHandler: deleting pbo "<glDeleteBuffers (1, &pbo); pbo = 0; } } if (pbo==0) { ext->glGenBuffers(1, &pbo); ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo); ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ); //OSG_NOTICE<<"ScreenCaptureHandler: Generating pbo "<glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo); } osg::Timer_t tick_start = osg::Timer::instance()->tick(); #if 1 glReadPixels(0, 0, _width, _height, _pixelFormat, _type, 0); #endif osg::Timer_t tick_afterReadPixels = osg::Timer::instance()->tick(); GLubyte* src = (GLubyte*)ext->glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB); if(src) { memcpy(image->data(), src, image->getTotalSizeInBytes()); ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB); } ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); osg::Timer_t tick_afterMemCpy = osg::Timer::instance()->tick(); if (_captureOperation.valid()) { (*_captureOperation)(*image, _index); } osg::Timer_t tick_afterCaptureOperation = osg::Timer::instance()->tick(); updateTimings(tick_start, tick_afterReadPixels, tick_afterMemCpy, tick_afterCaptureOperation, image->getTotalSizeInBytes()); _currentImageIndex = nextImageIndex; } void WindowCaptureCallback::ContextData::multiPBO(osg::GLBufferObject::Extensions* ext) { unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size(); unsigned int nextPboIndex = (_currentPboIndex+1)%_pboBuffer.size(); int width=0, height=0; getSize(_gc, width, height); if (width!=_width || _height!=height) { //OSG_NOTICE<<" Window resized "<s() != _width || image->t() != _height) { //OSG_NOTICE<<"ScreenCaptureHandler: Allocating image "<allocateImage(_width, _height, 1, _pixelFormat, _type); if (read_pbo!=0) { //OSG_NOTICE<<"ScreenCaptureHandler: deleting pbo "<glDeleteBuffers (1, &read_pbo); read_pbo = 0; } if (copy_pbo!=0) { //OSG_NOTICE<<"ScreenCaptureHandler: deleting pbo "<glDeleteBuffers (1, ©_pbo); copy_pbo = 0; } } bool doCopy = copy_pbo!=0; if (copy_pbo==0) { ext->glGenBuffers(1, ©_pbo); ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, copy_pbo); ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ); //OSG_NOTICE<<"ScreenCaptureHandler: Generating pbo "<glGenBuffers(1, &read_pbo); ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, read_pbo); ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ); //OSG_NOTICE<<"ScreenCaptureHandler: Generating pbo "<glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, read_pbo); } osg::Timer_t tick_start = osg::Timer::instance()->tick(); #if 1 glReadPixels(0, 0, _width, _height, _pixelFormat, _type, 0); #endif osg::Timer_t tick_afterReadPixels = osg::Timer::instance()->tick(); if (doCopy) { ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, copy_pbo); GLubyte* src = (GLubyte*)ext->glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB); if(src) { memcpy(image->data(), src, image->getTotalSizeInBytes()); ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB); } if (_captureOperation.valid()) { (*_captureOperation)(*image, _index); } } ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); osg::Timer_t tick_afterMemCpy = osg::Timer::instance()->tick(); updateTimings(tick_start, tick_afterReadPixels, tick_afterMemCpy, tick_afterMemCpy, image->getTotalSizeInBytes()); _currentImageIndex = nextImageIndex; _currentPboIndex = nextPboIndex; } WindowCaptureCallback::WindowCaptureCallback(int numFrames, Mode mode, FramePosition position, GLenum readBuffer) : _mode(mode), _position(position), _readBuffer(readBuffer), _numFrames(numFrames) { } WindowCaptureCallback::ContextData* WindowCaptureCallback::createContextData(osg::GraphicsContext* gc) const { WindowCaptureCallback::ContextData* cd = new WindowCaptureCallback::ContextData(gc, _mode, _readBuffer); cd->_captureOperation = _defaultCaptureOperation; return cd; } WindowCaptureCallback::ContextData* WindowCaptureCallback::getContextData(osg::GraphicsContext* gc) const { OpenThreads::ScopedLock lock(_mutex); osg::ref_ptr& data = _contextDataMap[gc]; if (!data) data = createContextData(gc); return data.get(); } void WindowCaptureCallback::setCaptureOperation(ScreenCaptureHandler::CaptureOperation* operation) { _defaultCaptureOperation = operation; // Set the capture operation for each ContextData. for (ContextDataMap::iterator it = _contextDataMap.begin(); it != _contextDataMap.end(); ++it) { it->second->_captureOperation = operation; } } void WindowCaptureCallback::operator () (osg::RenderInfo& renderInfo) const { #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) glReadBuffer(_readBuffer); #endif osg::GraphicsContext* gc = renderInfo.getState()->getGraphicsContext(); osg::ref_ptr cd = getContextData(gc); cd->read(); // If _numFrames is > 0 it means capture that number of frames. if (_numFrames > 0) { --_numFrames; if (_numFrames == 0) { // the callback must remove itself when it's done. if (_position == START_FRAME) renderInfo.getCurrentCamera()->setInitialDrawCallback(0); if (_position == END_FRAME) renderInfo.getCurrentCamera()->setFinalDrawCallback(0); } } int prec = osg::notify(osg::INFO).precision(5); OSG_INFO << "ScreenCaptureHandler: " << "copy=" << (cd->_timeForFullCopy*1000.0f) << "ms, " << "operation=" << (cd->_timeForCaptureOperation*1000.0f) << "ms, " << "total=" << (cd->_timeForFullCopyAndOperation*1000.0f) << std::endl; osg::notify(osg::INFO).precision(prec); cd->_timeForFullCopy = 0; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // ScreenCaptureHandler::WriteToFile // ScreenCaptureHandler::WriteToFile::WriteToFile(const std::string& filename, const std::string& extension, SavePolicy savePolicy) : _filename(filename), _extension(extension), _savePolicy(savePolicy) { } void ScreenCaptureHandler::WriteToFile::operator () (const osg::Image& image, const unsigned int context_id) { if (_savePolicy == SEQUENTIAL_NUMBER) { if (_contextSaveCounter.size() <= context_id) { unsigned int oldSize = _contextSaveCounter.size(); _contextSaveCounter.resize(context_id + 1); // Initialize all new values to 0 since context ids may not be consecutive. for (unsigned int i = oldSize; i <= context_id; i++) _contextSaveCounter[i] = 0; } } std::stringstream filename; filename << _filename << "_" << context_id; if (_savePolicy == SEQUENTIAL_NUMBER) filename << "_" << _contextSaveCounter[context_id]; filename << "." << _extension; osgDB::writeImageFile(image, filename.str()); OSG_INFO<<"ScreenCaptureHandler: Taking a screenshot, saved as '"<(_callback.get()); callback->setCaptureOperation(operation); } ScreenCaptureHandler::CaptureOperation* ScreenCaptureHandler::getCaptureOperation() const { WindowCaptureCallback* callback = static_cast(_callback.get()); return callback->getCaptureOperation(); } void ScreenCaptureHandler::addCallbackToViewer(osgViewer::ViewerBase& viewer) { osg::Camera* camera = findAppropriateCameraForCallback(viewer); if (!camera) return; WindowCaptureCallback* callback = static_cast(_callback.get()); if (callback && callback->getFramePosition() == WindowCaptureCallback::START_FRAME) { camera->setInitialDrawCallback(_callback.get()); } else { camera->setFinalDrawCallback(_callback.get()); } } void ScreenCaptureHandler::removeCallbackFromViewer(osgViewer::ViewerBase& viewer) { osg::Camera* camera = findAppropriateCameraForCallback(viewer); if (!camera) return; WindowCaptureCallback* callback = static_cast(_callback.get()); if (callback && callback->getFramePosition() == WindowCaptureCallback::START_FRAME) { camera->setInitialDrawCallback(0); } else { camera->setFinalDrawCallback(0); } } osg::Camera* ScreenCaptureHandler::findAppropriateCameraForCallback(osgViewer::ViewerBase& viewer) { // Select either the first or the last active camera, depending on the // frame position set in the callback. // One case where testing the node mask is important is when the stats // handler has been initialized, but stats are not displayed. In that // case, there is a post render camera on the viewer, but its node mask // is zero, so the callback added to that camera would never be called. WindowCaptureCallback* callback = static_cast(_callback.get()); if (callback->getFramePosition() == WindowCaptureCallback::START_FRAME) { osgViewer::ViewerBase::Contexts contexts; viewer.getContexts(contexts); for(osgViewer::ViewerBase::Contexts::iterator itr = contexts.begin(); itr != contexts.end(); ++itr) { osg::GraphicsContext* context = *itr; osg::GraphicsContext::Cameras& cameras = context->getCameras(); osg::Camera* firstCamera = 0; for(osg::GraphicsContext::Cameras::iterator cam_itr = cameras.begin(); cam_itr != cameras.end(); ++cam_itr) { if (firstCamera) { if ((*cam_itr)->getRenderOrder() < firstCamera->getRenderOrder()) { if ((*cam_itr)->getNodeMask() != 0x0) firstCamera = (*cam_itr); } if ((*cam_itr)->getRenderOrder() == firstCamera->getRenderOrder() && (*cam_itr)->getRenderOrderNum() < firstCamera->getRenderOrderNum()) { if ((*cam_itr)->getNodeMask() != 0x0) firstCamera = (*cam_itr); } } else { if ((*cam_itr)->getNodeMask() != 0x0) firstCamera = *cam_itr; } } if (firstCamera) { //OSG_NOTICE<<"ScreenCaptureHandler: First camera "<getCameras(); osg::Camera* lastCamera = 0; for(osg::GraphicsContext::Cameras::iterator cam_itr = cameras.begin(); cam_itr != cameras.end(); ++cam_itr) { if (lastCamera) { if ((*cam_itr)->getRenderOrder() > lastCamera->getRenderOrder()) { if ((*cam_itr)->getNodeMask() != 0x0) lastCamera = (*cam_itr); } if ((*cam_itr)->getRenderOrder() == lastCamera->getRenderOrder() && (*cam_itr)->getRenderOrderNum() >= lastCamera->getRenderOrderNum()) { if ((*cam_itr)->getNodeMask() != 0x0) lastCamera = (*cam_itr); } } else { if ((*cam_itr)->getNodeMask() != 0x0) lastCamera = *cam_itr; } } if (lastCamera) { //OSG_NOTICE<<"ScreenCaptureHandler: Last camera "<(&aa)->getViewerBase(); if (!viewer) return false; switch(ea.getEventType()) { case (osgGA::GUIEventAdapter::FRAME): { // Booleans aren't the best way of doing this, but I want to do // the actual adding here because I don't want to require // startCapture() take a viewer as argument, which could not be // the right one. if (_startCapture) { // Start capturing with the currently set number of frames. // If set to -1 it will capture continuously, if set to >0 // it will capture that number of frames. _startCapture = false; addCallbackToViewer(*viewer); } else if (_stopCapture) { _stopCapture = false; removeCallbackFromViewer(*viewer); } break; } case(osgGA::GUIEventAdapter::KEYUP): { if (ea.getKey() == _keyEventTakeScreenShot) { // Check that we will capture at least one frame. // Just check for ==0, because >0 is means we're already // capturing and <0 means it will capture all frames. WindowCaptureCallback* callback = static_cast(_callback.get()); if (callback->getFramesToCapture() == 0) { setFramesToCapture(1); } addCallbackToViewer(*viewer); return true; } if (ea.getKey() == _keyEventToggleContinuousCapture) { if (getFramesToCapture() < 0) { setFramesToCapture(0); removeCallbackFromViewer(*viewer); } else { setFramesToCapture(-1); addCallbackToViewer(*viewer); } return true; } break; } default: break; } return false; } /** Capture the given viewer's views on the next frame. */ void ScreenCaptureHandler::captureNextFrame(osgViewer::ViewerBase& viewer) { addCallbackToViewer(viewer); } /** Set the number of frames to capture. */ void ScreenCaptureHandler::setFramesToCapture(int numFrames) { WindowCaptureCallback* callback = static_cast(_callback.get()); callback->setFramesToCapture(numFrames); } /** Get the number of frames to capture. */ int ScreenCaptureHandler::getFramesToCapture() const { WindowCaptureCallback* callback = static_cast(_callback.get()); return callback->getFramesToCapture(); } /** Start capturing at the end of the next frame. */ void ScreenCaptureHandler::startCapture() { if (getFramesToCapture() != 0) _startCapture = true; } /** Stop capturing. */ void ScreenCaptureHandler::stopCapture() { _stopCapture = true; } /** Get the keyboard and mouse usage of this manipulator.*/ void ScreenCaptureHandler::getUsage(osg::ApplicationUsage& usage) const { usage.addKeyboardMouseBinding(_keyEventTakeScreenShot,"Take screenshot."); usage.addKeyboardMouseBinding(_keyEventToggleContinuousCapture,"Toggle continuous screen capture."); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/ViewerBase.cpp0000644000175000017500000007102712100020024024510 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include static osg::ApplicationUsageProxy ViewerBase_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_CONFIG_FILE ","Specify a viewer configuration file to load by default."); static osg::ApplicationUsageProxy ViewerBase_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_THREADING ","Set the threading model using by Viewer, can be SingleThreaded, CullDrawThreadPerContext, DrawThreadPerContext or CullThreadPerCameraDrawThreadPerContext."); static osg::ApplicationUsageProxy ViewerBase_e2(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN ","Set the default screen that windows should open up on."); static osg::ApplicationUsageProxy ViewerBase_e3(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_WINDOW x y width height","Set the default window dimensions that windows should open up on."); static osg::ApplicationUsageProxy ViewerBase_e4(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_RUN_FRAME_SCHEME","Frame rate manage scheme that viewer run should use, ON_DEMAND or CONTINUOUS (default)."); static osg::ApplicationUsageProxy ViewerBase_e5(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_RUN_MAX_FRAME_RATE","Set the maximum number of frame as second that viewer run. 0.0 is default and disables an frame rate capping."); using namespace osgViewer; ViewerBase::ViewerBase(): osg::Object(true) { viewerBaseInit(); } ViewerBase::ViewerBase(const ViewerBase&): osg::Object(true) { viewerBaseInit(); } void ViewerBase::viewerBaseInit() { _firstFrame = true; _done = false; _keyEventSetsDone = osgGA::GUIEventAdapter::KEY_Escape; _quitEventSetsDone = true; _releaseContextAtEndOfFrameHint = true; _threadingModel = AutomaticSelection; _threadsRunning = false; _endBarrierPosition = AfterSwapBuffers; _endBarrierOperation = osg::BarrierOperation::NO_OPERATION; _requestRedraw = true; _requestContinousUpdate = false; _runFrameScheme = CONTINUOUS; _runMaxFrameRate = 0.0f; const char* str = getenv("OSG_RUN_FRAME_SCHEME"); if (str) { if (strcmp(str, "ON_DEMAND")==0) _runFrameScheme = ON_DEMAND; else if (strcmp(str, "CONTINUOUS")==0) _runFrameScheme = CONTINUOUS; } str = getenv("OSG_RUN_MAX_FRAME_RATE"); if (str) { _runMaxFrameRate = osg::asciiToDouble(str); } } void ViewerBase::setThreadingModel(ThreadingModel threadingModel) { if (_threadingModel == threadingModel) return; if (_threadsRunning) stopThreading(); _threadingModel = threadingModel; if (isRealized() && _threadingModel!=SingleThreaded) startThreading(); } ViewerBase::ThreadingModel ViewerBase::suggestBestThreadingModel() { const char* str = getenv("OSG_THREADING"); if (str) { if (strcmp(str,"SingleThreaded")==0) return SingleThreaded; else if (strcmp(str,"CullDrawThreadPerContext")==0) return CullDrawThreadPerContext; else if (strcmp(str,"DrawThreadPerContext")==0) return DrawThreadPerContext; else if (strcmp(str,"CullThreadPerCameraDrawThreadPerContext")==0) return CullThreadPerCameraDrawThreadPerContext; } Contexts contexts; getContexts(contexts); if (contexts.empty()) return SingleThreaded; #if 0 // temporary hack to disable multi-threading under Windows till we find good solutions for // crashes that users are seeing. return SingleThreaded; #endif Cameras cameras; getCameras(cameras); if (cameras.empty()) return SingleThreaded; int numProcessors = OpenThreads::GetNumberOfProcessors(); if (contexts.size()==1) { if (numProcessors==1) return SingleThreaded; else return DrawThreadPerContext; } #if 1 if (numProcessors >= static_cast(cameras.size()+contexts.size())) { return CullThreadPerCameraDrawThreadPerContext; } #endif return DrawThreadPerContext; } void ViewerBase::setUpThreading() { Contexts contexts; getContexts(contexts); if (_threadingModel==SingleThreaded) { if (_threadsRunning) stopThreading(); else { // we'll set processor affinity here to help single threaded apps // with multiple processor cores, and using the database pager. int numProcessors = OpenThreads::GetNumberOfProcessors(); bool affinity = numProcessors>1; if (affinity) { OpenThreads::SetProcessorAffinityOfCurrentThread(0); Scenes scenes; getScenes(scenes); } } } else { if (!_threadsRunning) startThreading(); } } void ViewerBase::setEndBarrierPosition(BarrierPosition bp) { if (_endBarrierPosition == bp) return; if (_threadsRunning) stopThreading(); _endBarrierPosition = bp; if (_threadingModel!=SingleThreaded) startThreading(); } void ViewerBase::setEndBarrierOperation(osg::BarrierOperation::PreBlockOp op) { if (_endBarrierOperation == op) return; if (_threadsRunning) stopThreading(); _endBarrierOperation = op; if (_threadingModel!=SingleThreaded) startThreading(); } void ViewerBase::stopThreading() { if (!_threadsRunning) return; OSG_INFO<<"ViewerBase::stopThreading() - stopping threading"<(camera->getRenderer()); if (renderer) renderer->release(); } // delete all the graphics threads. for(gcitr = contexts.begin(); gcitr != contexts.end(); ++gcitr) { (*gcitr)->setGraphicsThread(0); } // delete all the camera threads. for(citr = cameras.begin(); citr != cameras.end(); ++citr) { (*citr)->setCameraThread(0); } for(Cameras::iterator camItr = cameras.begin(); camItr != cameras.end(); ++camItr) { osg::Camera* camera = *camItr; Renderer* renderer = dynamic_cast(camera->getRenderer()); if (renderer) { renderer->setGraphicsThreadDoesCull( true ); renderer->setDone(false); } } _threadsRunning = false; _startRenderingBarrier = 0; _endRenderingDispatchBarrier = 0; _endDynamicDrawBlock = 0; OSG_INFO<<"Viewer::stopThreading() - stopped threading."<getSceneData()) { OSG_INFO<<"Making scene thread safe"<getSceneData()->setThreadSafeRefUnref(true); // update the scene graph so that it has enough GL object buffer memory for the graphics contexts that will be using it. (*scitr)->getSceneData()->resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts()); } } int numProcessors = OpenThreads::GetNumberOfProcessors(); bool affinity = numProcessors>1; Contexts::iterator citr; unsigned int numViewerDoubleBufferedRenderingOperation = 0; bool graphicsThreadsDoesCull = _threadingModel == CullDrawThreadPerContext || _threadingModel==SingleThreaded; for(Cameras::iterator camItr = cameras.begin(); camItr != cameras.end(); ++camItr) { osg::Camera* camera = *camItr; Renderer* renderer = dynamic_cast(camera->getRenderer()); if (renderer) { renderer->setGraphicsThreadDoesCull(graphicsThreadsDoesCull); renderer->setDone(false); renderer->reset(); ++numViewerDoubleBufferedRenderingOperation; } } if (_threadingModel==CullDrawThreadPerContext) { _startRenderingBarrier = 0; _endRenderingDispatchBarrier = 0; _endDynamicDrawBlock = 0; } else if (_threadingModel==DrawThreadPerContext || _threadingModel==CullThreadPerCameraDrawThreadPerContext) { _startRenderingBarrier = 0; _endRenderingDispatchBarrier = 0; _endDynamicDrawBlock = new osg::EndOfDynamicDrawBlock(numViewerDoubleBufferedRenderingOperation); #ifndef OSGUTIL_RENDERBACKEND_USE_REF_PTR if (!osg::Referenced::getDeleteHandler()) osg::Referenced::setDeleteHandler(new osg::DeleteHandler(2)); else osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(2); #endif } if (numThreadsOnStartBarrier>1) { _startRenderingBarrier = new osg::BarrierOperation(numThreadsOnStartBarrier, osg::BarrierOperation::NO_OPERATION); } if (numThreadsOnEndBarrier>1) { _endRenderingDispatchBarrier = new osg::BarrierOperation(numThreadsOnEndBarrier, _endBarrierOperation); } osg::ref_ptr swapReadyBarrier = contexts.empty() ? 0 : new osg::BarrierOperation(contexts.size(), osg::BarrierOperation::NO_OPERATION); osg::ref_ptr swapOp = new osg::SwapBuffersOperation(); typedef std::map ThreadAffinityMap; ThreadAffinityMap threadAffinityMap; unsigned int processNum = 1; for(citr = contexts.begin(); citr != contexts.end(); ++citr, ++processNum) { osg::GraphicsContext* gc = (*citr); if (!gc->isRealized()) { OSG_INFO<<"ViewerBase::startThreading() : Realizng window "<realize(); } gc->getState()->setDynamicObjectRenderingCompletedCallback(_endDynamicDrawBlock.get()); // create the a graphics thread for this context gc->createGraphicsThread(); if (affinity) gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors); threadAffinityMap[gc->getGraphicsThread()] = processNum % numProcessors; // add the startRenderingBarrier if (_threadingModel==CullDrawThreadPerContext && _startRenderingBarrier.valid()) gc->getGraphicsThread()->add(_startRenderingBarrier.get()); // add the rendering operation itself. gc->getGraphicsThread()->add(new osg::RunOperations()); if (_threadingModel==CullDrawThreadPerContext && _endBarrierPosition==BeforeSwapBuffers && _endRenderingDispatchBarrier.valid()) { // add the endRenderingDispatchBarrier gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); } if (swapReadyBarrier.valid()) gc->getGraphicsThread()->add(swapReadyBarrier.get()); // add the swap buffers gc->getGraphicsThread()->add(swapOp.get()); if (_threadingModel==CullDrawThreadPerContext && _endBarrierPosition==AfterSwapBuffers && _endRenderingDispatchBarrier.valid()) { // add the endRenderingDispatchBarrier gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); } } if (_threadingModel==CullThreadPerCameraDrawThreadPerContext && numThreadsOnStartBarrier>1) { Cameras::iterator camItr; for(camItr = cameras.begin(); camItr != cameras.end(); ++camItr, ++processNum) { osg::Camera* camera = *camItr; camera->createCameraThread(); if (affinity) camera->getCameraThread()->setProcessorAffinity(processNum % numProcessors); threadAffinityMap[camera->getCameraThread()] = processNum % numProcessors; osg::GraphicsContext* gc = camera->getGraphicsContext(); // add the startRenderingBarrier if (_startRenderingBarrier.valid()) camera->getCameraThread()->add(_startRenderingBarrier.get()); Renderer* renderer = dynamic_cast(camera->getRenderer()); renderer->setGraphicsThreadDoesCull(false); camera->getCameraThread()->add(renderer); if (_endRenderingDispatchBarrier.valid()) { // add the endRenderingDispatchBarrier gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); } } for(camItr = cameras.begin(); camItr != cameras.end(); ++camItr) { osg::Camera* camera = *camItr; if (camera->getCameraThread() && !camera->getCameraThread()->isRunning()) { OSG_INFO<<" camera->getCameraThread()-> "<getCameraThread()<getCameraThread()->startThread(); } } } #if 0 if (affinity) { OpenThreads::SetProcessorAffinityOfCurrentThread(0); if (_scene.valid() && _scene->getDatabasePager()) { #if 0 _scene->getDatabasePager()->setProcessorAffinity(1); #else _scene->getDatabasePager()->setProcessorAffinity(0); #endif } } #endif #if 0 if (affinity) { for(ThreadAffinityMap::iterator titr = threadAffinityMap.begin(); titr != threadAffinityMap.end(); ++titr) { titr->first->setProcessorAffinity(titr->second); } } #endif for(citr = contexts.begin(); citr != contexts.end(); ++citr) { osg::GraphicsContext* gc = (*citr); if (gc->getGraphicsThread() && !gc->getGraphicsThread()->isRunning()) { OSG_INFO<<" gc->getGraphicsThread()->startThread() "<getGraphicsThread()<getGraphicsThread()->startThread(); // OpenThreads::Thread::YieldCurrentThread(); } } _threadsRunning = true; OSG_INFO<<"Set up threading"<(*itr); if (gw) windows.push_back(gw); } } void ViewerBase::checkWindowStatus() { Contexts contexts; getContexts(contexts); checkWindowStatus(contexts); } void ViewerBase::checkWindowStatus(const Contexts& contexts) { if (contexts.size()==0) { _done = true; if (areThreadsRunning()) stopThreading(); } } void ViewerBase::addUpdateOperation(osg::Operation* operation) { if (!operation) return; if (!_updateOperations) _updateOperations = new osg::OperationQueue; _updateOperations->add(operation); } void ViewerBase::removeUpdateOperation(osg::Operation* operation) { if (!operation) return; if (_updateOperations.valid()) { _updateOperations->remove(operation); } } void ViewerBase::setIncrementalCompileOperation(osgUtil::IncrementalCompileOperation* ico) { if (_incrementalCompileOperation == ico) return; Contexts contexts; getContexts(contexts, false); if (_incrementalCompileOperation.valid()) _incrementalCompileOperation->removeContexts(contexts); // assign new operation _incrementalCompileOperation = ico; Scenes scenes; getScenes(scenes,false); for(Scenes::iterator itr = scenes.begin(); itr != scenes.end(); ++itr) { osgDB::DatabasePager* dp = (*itr)->getDatabasePager(); dp->setIncrementalCompileOperation(ico); } if (_incrementalCompileOperation) _incrementalCompileOperation->assignContexts(contexts); } int ViewerBase::run() { if (!isRealized()) { realize(); } const char* run_frame_count_str = getenv("OSG_RUN_FRAME_COUNT"); unsigned int runTillFrameNumber = run_frame_count_str==0 ? osg::UNINITIALIZED_FRAME_NUMBER : atoi(run_frame_count_str); while(!done() && (run_frame_count_str==0 || getViewerFrameStamp()->getFrameNumber()0.0 ? 1.0/_runMaxFrameRate : 0.0; osg::Timer_t startFrameTick = osg::Timer::instance()->tick(); if (_runFrameScheme==ON_DEMAND) { if (checkNeedToDoFrame()) { frame(); } else { // we don't need to render a frame but we don't want to spin the run loop so make sure the minimum // loop time is 1/100th of second, if not otherwise set, so enabling the frame microSleep below to // avoid consume excessive CPU resources. if (minFrameTime==0.0) minFrameTime=0.01; } } else { frame(); } // work out if we need to force a sleep to hold back the frame rate osg::Timer_t endFrameTick = osg::Timer::instance()->tick(); double frameTime = osg::Timer::instance()->delta_s(startFrameTick, endFrameTick); if (frameTime < minFrameTime) OpenThreads::Thread::microSleep(static_cast(1000000.0*(minFrameTime-frameTime))); } return 0; } void ViewerBase::frame(double simulationTime) { if (_done) return; // OSG_NOTICE<getCamera()->getInverseViewMatrix(); OSG_NOTICE<<"View "<collectStats("scene")) { unsigned int frameNumber = frameStamp ? frameStamp->getFrameNumber() : 0; Views views; getViews(views); for(Views::iterator vitr = views.begin(); vitr != views.end(); ++vitr) { View* view = *vitr; osg::Stats* stats = view->getStats(); osg::Node* sceneRoot = view->getSceneData(); if (sceneRoot && stats) { osgUtil::StatsVisitor statsVisitor; sceneRoot->accept(statsVisitor); statsVisitor.totalUpStats(); unsigned int unique_primitives = 0; osgUtil::Statistics::PrimitiveCountMap::iterator pcmitr; for(pcmitr = statsVisitor._uniqueStats.GetPrimitivesBegin(); pcmitr != statsVisitor._uniqueStats.GetPrimitivesEnd(); ++pcmitr) { unique_primitives += pcmitr->second; } stats->setAttribute(frameNumber, "Number of unique StateSet", static_cast(statsVisitor._statesetSet.size())); stats->setAttribute(frameNumber, "Number of unique Group", static_cast(statsVisitor._groupSet.size())); stats->setAttribute(frameNumber, "Number of unique Transform", static_cast(statsVisitor._transformSet.size())); stats->setAttribute(frameNumber, "Number of unique LOD", static_cast(statsVisitor._lodSet.size())); stats->setAttribute(frameNumber, "Number of unique Switch", static_cast(statsVisitor._switchSet.size())); stats->setAttribute(frameNumber, "Number of unique Geode", static_cast(statsVisitor._geodeSet.size())); stats->setAttribute(frameNumber, "Number of unique Drawable", static_cast(statsVisitor._drawableSet.size())); stats->setAttribute(frameNumber, "Number of unique Geometry", static_cast(statsVisitor._geometrySet.size())); stats->setAttribute(frameNumber, "Number of unique Vertices", static_cast(statsVisitor._uniqueStats._vertexCount)); stats->setAttribute(frameNumber, "Number of unique Primitives", static_cast(unique_primitives)); unsigned int instanced_primitives = 0; for(pcmitr = statsVisitor._instancedStats.GetPrimitivesBegin(); pcmitr != statsVisitor._instancedStats.GetPrimitivesEnd(); ++pcmitr) { instanced_primitives += pcmitr->second; } stats->setAttribute(frameNumber, "Number of instanced Stateset", static_cast(statsVisitor._numInstancedStateSet)); stats->setAttribute(frameNumber, "Number of instanced Group", static_cast(statsVisitor._numInstancedGroup)); stats->setAttribute(frameNumber, "Number of instanced Transform", static_cast(statsVisitor._numInstancedTransform)); stats->setAttribute(frameNumber, "Number of instanced LOD", static_cast(statsVisitor._numInstancedLOD)); stats->setAttribute(frameNumber, "Number of instanced Switch", static_cast(statsVisitor._numInstancedSwitch)); stats->setAttribute(frameNumber, "Number of instanced Geode", static_cast(statsVisitor._numInstancedGeode)); stats->setAttribute(frameNumber, "Number of instanced Drawable", static_cast(statsVisitor._numInstancedDrawable)); stats->setAttribute(frameNumber, "Number of instanced Geometry", static_cast(statsVisitor._numInstancedGeometry)); stats->setAttribute(frameNumber, "Number of instanced Vertices", static_cast(statsVisitor._instancedStats._vertexCount)); stats->setAttribute(frameNumber, "Number of instanced Primitives", static_cast(instanced_primitives)); } } } Scenes scenes; getScenes(scenes); for(Scenes::iterator sitr = scenes.begin(); sitr != scenes.end(); ++sitr) { Scene* scene = *sitr; osgDB::DatabasePager* dp = scene ? scene->getDatabasePager() : 0; if (dp) dp->signalBeginFrame(frameStamp); osgDB::ImagePager* ip = scene ? scene->getImagePager() : 0; if (ip) ip->signalBeginFrame(frameStamp); if (scene->getSceneData()) { // fire off a build of the bounding volumes while we // are still running single threaded. scene->getSceneData()->getBound(); } } // OSG_NOTICE<reset(); } // dispatch the rendering threads if (_startRenderingBarrier.valid()) _startRenderingBarrier->block(); // reset any double buffer graphics objects for(Cameras::iterator camItr = cameras.begin(); camItr != cameras.end(); ++camItr) { osg::Camera* camera = *camItr; Renderer* renderer = dynamic_cast(camera->getRenderer()); if (renderer) { if (!renderer->getGraphicsThreadDoesCull() && !(camera->getCameraThread())) { renderer->cull(); } } } for(itr = contexts.begin(); itr != contexts.end() && !_done; ++itr) { if (!((*itr)->getGraphicsThread()) && (*itr)->valid()) { doneMakeCurrentInThisThread = true; makeCurrent(*itr); (*itr)->runOperations(); } } // OSG_NOTICE<<"Joing _endRenderingDispatchBarrier block "<<_endRenderingDispatchBarrier.get()<block(); for(itr = contexts.begin(); itr != contexts.end() && !_done; ++itr) { if (!((*itr)->getGraphicsThread()) && (*itr)->valid()) { doneMakeCurrentInThisThread = true; makeCurrent(*itr); (*itr)->swapBuffers(); } } for(Scenes::iterator sitr = scenes.begin(); sitr != scenes.end(); ++sitr) { Scene* scene = *sitr; osgDB::DatabasePager* dp = scene ? scene->getDatabasePager() : 0; if (dp) dp->signalEndFrame(); osgDB::ImagePager* ip = scene ? scene->getImagePager() : 0; if (ip) ip->signalEndFrame(); } // wait till the dynamic draw is complete. if (_endDynamicDrawBlock.valid()) { // osg::Timer_t startTick = osg::Timer::instance()->tick(); _endDynamicDrawBlock->block(); // OSG_NOTICE<<"Time waiting "<delta_m(startTick, osg::Timer::instance()->tick())<collectStats("update")) { double endRenderingTraversals = elapsedTime(); // update current frames stats getViewerStats()->setAttribute(frameStamp->getFrameNumber(), "Rendering traversals begin time ", beginRenderingTraversals); getViewerStats()->setAttribute(frameStamp->getFrameNumber(), "Rendering traversals end time ", endRenderingTraversals); getViewerStats()->setAttribute(frameStamp->getFrameNumber(), "Rendering traversals time taken", endRenderingTraversals-beginRenderingTraversals); } _requestRedraw = false; } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/IOSUtils.h0000644000175000017500000000713611575622736023635 0ustar albertoalberto/* * IOSUtils.h * OpenSceneGraph * * Created by Thomas Hogarth on 25.11.09. * * By default we create a full res buffer across all devices and if now viewContentScaleFator is given We use the screens ScaleFactor. * This means that for backward compatibility you need to set the windowData _viewContentScaleFactor to 1.0f and set the screen res to the * res that of the older gen device. * http://developer.apple.com/library/ios/documentation/IOS/Conceptual/IOSOSProgrammingGuide/SupportingResolutionIndependence/SupportingResolutionIndependence.html#//apple_ref/doc/uid/TP40007072-CH10-SW11 * */ #ifdef __APPLE__ #ifndef IOS_UTILS_HEADER_ #define IOS_UTILS_HEADER_ #ifdef __OBJC__ @class UIScreen; #else class UIScreen; #endif #include #include #include namespace osgIOS { struct IOSWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface { public: IOSWindowingSystemInterface(); /** dtor */ ~IOSWindowingSystemInterface(); /** @return count of attached screens */ virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si) ; virtual void getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution); virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, osg::GraphicsContext::ScreenSettingsList & resolutionList); virtual bool setScreenSettings (const osg::GraphicsContext::ScreenIdentifier & si, const osg::GraphicsContext::ScreenSettings & settings); /** returns screen-ndx containing rect x,y,w,h, NOT_TESTED@tom */ unsigned int getScreenContaining(int x, int y, int w, int h); //IOS specific // //return the UIScreen object asscoiated with the passed ScreenIdentifier //returns nil if si isn't found UIScreen* getUIScreen(const osg::GraphicsContext::ScreenIdentifier& si); // //Get the contents scale factor of the screen, this is the scale factor required //to convert points to pixels on this screen bool getScreenContentScaleFactor(const osg::GraphicsContext::ScreenIdentifier& si, float& scaleFactor); // //Get the screens size in points, docs state a point is roughly 1/160th of an inch bool getScreenSizeInPoints(const osg::GraphicsContext::ScreenIdentifier& si, osg::Vec2& pointSize); protected: /** implementation of setScreenResolution */ //IPad can have extenal screens which we can request a res for //the main screen screenNum 0 can not currently have its res changed //as it only has one mode (might change though and this should still handle it) bool setScreenResolutionImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, unsigned int width, unsigned int height); /** implementation of setScreenRefreshRate, currently can't set refresh rate of IOS*/ bool setScreenRefreshRateImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, double refreshRate); private: }; template struct RegisterWindowingSystemInterfaceProxy { RegisterWindowingSystemInterfaceProxy() { osg::GraphicsContext::setWindowingSystemInterface(new WSI); } ~RegisterWindowingSystemInterfaceProxy() { if (osg::Referenced::getDeleteHandler()) { osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); osg::Referenced::getDeleteHandler()->flushAll(); } osg::GraphicsContext::setWindowingSystemInterface(0); } }; } #endif #endif // __APPLE__ openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/View.cpp0000644000175000017500000024225012161022405023400 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // view configurations. #include #include #include #include #include #include #include using namespace osgViewer; osg::DisplaySettings* ViewConfig::getActiveDisplaySetting(osgViewer::View& view) const { return view.getDisplaySettings() ? view.getDisplaySettings() : osg::DisplaySettings::instance().get(); } class CollectedCoordinateSystemNodesVisitor : public osg::NodeVisitor { public: CollectedCoordinateSystemNodesVisitor(): NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) {} META_NodeVisitor("osgViewer","CollectedCoordinateSystemNodesVisitor") virtual void apply(osg::Node& node) { traverse(node); } virtual void apply(osg::CoordinateSystemNode& node) { if (_pathToCoordinateSystemNode.empty()) { OSG_DEBUG<<"Found CoordinateSystemNode node"<getCoordinateSystemNodePath(); if (!tmpPath.empty()) { osg::Matrixd coordinateFrame; osg::CoordinateSystemNode* csn = dynamic_cast(tmpPath.back()); if (csn) { osg::Vec3 local_position = position*osg::computeWorldToLocal(tmpPath); // get the coordinate frame in world coords. coordinateFrame = csn->computeLocalCoordinateFrame(local_position)* osg::computeLocalToWorld(tmpPath); // keep the position of the coordinate frame to reapply after rescale. osg::Vec3d pos = coordinateFrame.getTrans(); // compensate for any scaling, so that the coordinate frame is a unit size osg::Vec3d x(1.0,0.0,0.0); osg::Vec3d y(0.0,1.0,0.0); osg::Vec3d z(0.0,0.0,1.0); x = osg::Matrixd::transform3x3(x,coordinateFrame); y = osg::Matrixd::transform3x3(y,coordinateFrame); z = osg::Matrixd::transform3x3(z,coordinateFrame); coordinateFrame.preMultScale(osg::Vec3d(1.0/x.length(),1.0/y.length(),1.0/z.length())); // reapply the position. coordinateFrame.setTrans(pos); OSG_DEBUG<<"csn->computeLocalCoordinateFrame(position)* osg::computeLocalToWorld(tmpPath)"< _view; }; View::View(): _fusionDistanceMode(osgUtil::SceneView::PROPORTIONAL_TO_SCREEN_DISTANCE), _fusionDistanceValue(1.0f) { // OSG_NOTICE<<"Constructing osgViewer::View"<setFrameNumber(0); _frameStamp->setReferenceTime(0); _frameStamp->setSimulationTime(0); _scene = new Scene; // make sure View is safe to reference multi-threaded. setThreadSafeRefUnref(true); // need to attach a Renderer to the master camera which has been default constructed getCamera()->setRenderer(createRenderer(getCamera())); setEventQueue(new osgGA::EventQueue); setStats(new osg::Stats("View")); } View::View(const osgViewer::View& view, const osg::CopyOp& copyop): osg::Object(true), osg::View(view,copyop), osgGA::GUIActionAdapter(), _startTick(0), _fusionDistanceMode(view._fusionDistanceMode), _fusionDistanceValue(view._fusionDistanceValue) { _scene = new Scene; // need to attach a Renderer to the master camera which has been default constructed getCamera()->setRenderer(createRenderer(getCamera())); setEventQueue(new osgGA::EventQueue); setStats(new osg::Stats("View")); } View::~View() { OSG_INFO<<"Destructing osgViewer::View"<(&rhs); if (rhs_osgViewer) { // copy across rhs _startTick = rhs_osgViewer->_startTick; _frameStamp = rhs_osgViewer->_frameStamp; if (rhs_osgViewer->getSceneData()) { _scene = rhs_osgViewer->_scene; } if (rhs_osgViewer->_cameraManipulator.valid()) { _cameraManipulator = rhs_osgViewer->_cameraManipulator; } _eventHandlers.insert(_eventHandlers.end(), rhs_osgViewer->_eventHandlers.begin(), rhs_osgViewer->_eventHandlers.end()); _coordinateSystemNodePath = rhs_osgViewer->_coordinateSystemNodePath; _displaySettings = rhs_osgViewer->_displaySettings; _fusionDistanceMode = rhs_osgViewer->_fusionDistanceMode; _fusionDistanceValue = rhs_osgViewer->_fusionDistanceValue; // clear rhs rhs_osgViewer->_frameStamp = 0; rhs_osgViewer->_scene = 0; rhs_osgViewer->_cameraManipulator = 0; rhs_osgViewer->_eventHandlers.clear(); rhs_osgViewer->_coordinateSystemNodePath.clearNodePath(); rhs_osgViewer->_displaySettings = 0; } #endif computeActiveCoordinateSystemNodePath(); assignSceneDataToCameras(); } osg::GraphicsOperation* View::createRenderer(osg::Camera* camera) { Renderer* render = new Renderer(camera); camera->setStats(new osg::Stats("Camera")); return render; } void View::init() { OSG_INFO<<"View::init()"< initEvent = _eventQueue->createEvent(); initEvent->setEventType(osgGA::GUIEventAdapter::FRAME); if (_cameraManipulator.valid()) { _cameraManipulator->init(*initEvent, *this); } } void View::setStartTick(osg::Timer_t tick) { _startTick = tick; for(Devices::iterator eitr = _eventSources.begin(); eitr != _eventSources.end(); ++eitr) { (*eitr)->getEventQueue()->setStartTick(_startTick); } } void View::setSceneData(osg::Node* node) { if (node==_scene->getSceneData()) return; osg::ref_ptr scene = Scene::getScene(node); if (scene) { OSG_INFO<<"View::setSceneData() Sharing scene "<referenceCount()!=1) { // we are not the only reference to the Scene so we cannot reuse it. _scene = new Scene; OSG_INFO<<"View::setSceneData() Allocating new scene"<<_scene.get()<setSceneData(node); } if (getSceneData()) { #if defined(OSG_GLES2_AVAILABLE) osgUtil::ShaderGenVisitor sgv; getSceneData()->getOrCreateStateSet(); getSceneData()->accept(sgv); #endif // now make sure the scene graph is set up with the correct DataVariance to protect the dynamic elements of // the scene graph from being run in parallel. osgUtil::Optimizer::StaticObjectDetectionVisitor sodv; getSceneData()->accept(sodv); // make sure that existing scene graph objects are allocated with thread safe ref/unref if (getViewerBase() && getViewerBase()->getThreadingModel()!=ViewerBase::SingleThreaded) { getSceneData()->setThreadSafeRefUnref(true); } // update the scene graph so that it has enough GL object buffer memory for the graphics contexts that will be using it. getSceneData()->resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts()); } computeActiveCoordinateSystemNodePath(); assignSceneDataToCameras(); } void View::setDatabasePager(osgDB::DatabasePager* dp) { _scene->setDatabasePager(dp); } osgDB::DatabasePager* View::getDatabasePager() { return _scene->getDatabasePager(); } const osgDB::DatabasePager* View::getDatabasePager() const { return _scene->getDatabasePager(); } void View::setImagePager(osgDB::ImagePager* dp) { _scene->setImagePager(dp); } osgDB::ImagePager* View::getImagePager() { return _scene->getImagePager(); } const osgDB::ImagePager* View::getImagePager() const { return _scene->getImagePager(); } void View::setCameraManipulator(osgGA::CameraManipulator* manipulator, bool resetPosition) { _cameraManipulator = manipulator; if (_cameraManipulator.valid()) { _cameraManipulator->setCoordinateFrameCallback(new ViewerCoordinateFrameCallback(this)); if (getSceneData()) _cameraManipulator->setNode(getSceneData()); if (resetPosition) { osg::ref_ptr dummyEvent = _eventQueue->createEvent(); _cameraManipulator->home(*dummyEvent, *this); } } } void View::home() { if (_cameraManipulator.valid()) { osg::ref_ptr dummyEvent = _eventQueue->createEvent(); _cameraManipulator->home(*dummyEvent, *this); } } void View::addEventHandler(osgGA::GUIEventHandler* eventHandler) { EventHandlers::iterator itr = std::find(_eventHandlers.begin(), _eventHandlers.end(), eventHandler); if (itr == _eventHandlers.end()) { _eventHandlers.push_back(eventHandler); } } void View::removeEventHandler(osgGA::GUIEventHandler* eventHandler) { EventHandlers::iterator itr = std::find(_eventHandlers.begin(), _eventHandlers.end(), eventHandler); if (itr != _eventHandlers.end()) { _eventHandlers.erase(itr); } } void View::setCoordinateSystemNodePath(const osg::NodePath& nodePath) { _coordinateSystemNodePath.setNodePath(nodePath); } osg::NodePath View::getCoordinateSystemNodePath() const { osg::NodePath nodePath; _coordinateSystemNodePath.getNodePath(nodePath); return nodePath; } void View::computeActiveCoordinateSystemNodePath() { // now search for CoordinateSystemNode's for which we want to track. osg::Node* subgraph = getSceneData(); if (subgraph) { CollectedCoordinateSystemNodesVisitor ccsnv; subgraph->accept(ccsnv); if (!ccsnv._pathToCoordinateSystemNode.empty()) { setCoordinateSystemNodePath(ccsnv._pathToCoordinateSystemNode); return; } } // otherwise no node path found so reset to empty. setCoordinateSystemNodePath(osg::NodePath()); } void View::apply(ViewConfig* config) { if (config) { OSG_INFO<<"Applying osgViewer::ViewConfig : "<className()<configure(*this); } _lastAppliedViewConfig = config; } void View::setUpViewAcrossAllScreens() { apply(new osgViewer::AcrossAllScreens()); } void View::setUpViewInWindow(int x, int y, int width, int height, unsigned int screenNum) { apply(new osgViewer::SingleWindow(x, y, width, height, screenNum)); } void View::setUpViewOnSingleScreen(unsigned int screenNum) { apply(new osgViewer::SingleScreen(screenNum)); } void View::setUpViewFor3DSphericalDisplay(double radius, double collar, unsigned int screenNum, osg::Image* intensityMap, const osg::Matrixd& projectorMatrix) { apply(new osgViewer::SphericalDisplay(radius, collar, screenNum, intensityMap, projectorMatrix)); } void View::setUpViewForPanoramicSphericalDisplay(double radius, double collar, unsigned int screenNum, osg::Image* intensityMap, const osg::Matrixd& projectorMatrix) { apply(new osgViewer::PanoramicSphericalDisplay(radius, collar, screenNum, intensityMap, projectorMatrix)); } void View::setUpViewForWoWVxDisplay(unsigned int screenNum, unsigned char wow_content, unsigned char wow_factor, unsigned char wow_offset, float wow_disparity_Zd, float wow_disparity_vz, float wow_disparity_M, float wow_disparity_C) { apply(new osgViewer::WoWVxDisplay(screenNum, wow_content, wow_factor, wow_offset, wow_disparity_Zd,wow_disparity_vz, wow_disparity_M, wow_disparity_C)); } DepthPartitionSettings::DepthPartitionSettings(DepthMode mode): _mode(mode), _zNear(1.0), _zMid(5.0), _zFar(1000.0) {} bool DepthPartitionSettings::getDepthRange(osg::View& view, unsigned int partition, double& zNear, double& zFar) { switch(_mode) { case(FIXED_RANGE): { if (partition==0) { zNear = _zNear; zFar = _zMid; return true; } else if (partition==1) { zNear = _zMid; zFar = _zFar; return true; } return false; } case(BOUNDING_VOLUME): { osgViewer::View* view_withSceneData = dynamic_cast(&view); const osg::Node* node = view_withSceneData ? view_withSceneData->getSceneData() : 0; if (!node) return false; const osg::Camera* masterCamera = view.getCamera(); if (!masterCamera) return false; osg::BoundingSphere bs = node->getBound(); const osg::Matrixd& viewMatrix = masterCamera->getViewMatrix(); //osg::Matrixd& projectionMatrix = masterCamera->getProjectionMatrix(); osg::Vec3d lookVectorInWorldCoords = osg::Matrixd::transform3x3(viewMatrix,osg::Vec3d(0.0,0.0,-1.0)); lookVectorInWorldCoords.normalize(); osg::Vec3d nearPointInWorldCoords = bs.center() - lookVectorInWorldCoords*bs.radius(); osg::Vec3d farPointInWorldCoords = bs.center() + lookVectorInWorldCoords*bs.radius(); osg::Vec3d nearPointInEyeCoords = nearPointInWorldCoords * viewMatrix; osg::Vec3d farPointInEyeCoords = farPointInWorldCoords * viewMatrix; #if 0 OSG_NOTICE<setNodeMask(0x0); return; } else { camera->setNodeMask(0xffffff); } if (camera->getProjectionMatrix()(0,3)==0.0 && camera->getProjectionMatrix()(1,3)==0.0 && camera->getProjectionMatrix()(2,3)==0.0) { double left, right, bottom, top, zNear, zFar; camera->getProjectionMatrixAsOrtho(left, right, bottom, top, zNear, zFar); camera->setProjectionMatrixAsOrtho(left, right, bottom, top, computed_zNear, computed_zFar); } else { double left, right, bottom, top, zNear, zFar; camera->getProjectionMatrixAsFrustum(left, right, bottom, top, zNear, zFar); double nr = computed_zNear / zNear; camera->setProjectionMatrixAsFrustum(left * nr, right * nr, bottom * nr, top * nr, computed_zNear, computed_zFar); } } osg::ref_ptr _dps; unsigned int _partition; }; typedef std::list< osg::ref_ptr > Cameras; Cameras getActiveCameras(osg::View& view) { Cameras activeCameras; if (view.getCamera() && view.getCamera()->getGraphicsContext()) { activeCameras.push_back(view.getCamera()); } for(unsigned int i=0; igetGraphicsContext()) { activeCameras.push_back(slave._camera.get()); } } return activeCameras; } } bool View::setUpDepthPartitionForCamera(osg::Camera* cameraToPartition, DepthPartitionSettings* incomming_dps) { osg::ref_ptr context = cameraToPartition->getGraphicsContext(); if (!context) return false; osg::ref_ptr viewport = cameraToPartition->getViewport(); if (!viewport) return false; osg::ref_ptr dps = incomming_dps; if (!dps) dps = new DepthPartitionSettings; bool useMastersSceneData = true; osg::Matrixd projectionOffset; osg::Matrixd viewOffset; if (getCamera()==cameraToPartition) { // replace main camera with depth partition cameras OSG_INFO<<"View::setUpDepthPartitionForCamera(..) Replacing main Camera"<=getNumSlaves()) return false; osg::View::Slave& slave = getSlave(i); useMastersSceneData = slave._useMastersSceneData; projectionOffset = slave._projectionOffset; viewOffset = slave._viewOffset; OSG_NOTICE<<"View::setUpDepthPartitionForCamera(..) Replacing slave Camera"<setGraphicsContext(0); cameraToPartition->setViewport(0); // far camera { osg::ref_ptr camera = new osg::Camera; camera->setGraphicsContext(context.get()); camera->setViewport(viewport.get()); camera->setDrawBuffer(cameraToPartition->getDrawBuffer()); camera->setReadBuffer(cameraToPartition->getReadBuffer()); camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); camera->setCullingMode(osg::Camera::ENABLE_ALL_CULLING); addSlave(camera.get()); osg::View::Slave& slave = getSlave(getNumSlaves()-1); slave._useMastersSceneData = useMastersSceneData; slave._projectionOffset = projectionOffset; slave._viewOffset = viewOffset; slave._updateSlaveCallback = new osgDepthPartition::MyUpdateSlaveCallback(dps.get(), 1); } // near camera { osg::ref_ptr camera = new osg::Camera; camera->setGraphicsContext(context.get()); camera->setViewport(viewport.get()); camera->setDrawBuffer(cameraToPartition->getDrawBuffer()); camera->setReadBuffer(cameraToPartition->getReadBuffer()); camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); camera->setCullingMode(osg::Camera::ENABLE_ALL_CULLING); camera->setClearMask(GL_DEPTH_BUFFER_BIT); addSlave(camera.get()); osg::View::Slave& slave = getSlave(getNumSlaves()-1); slave._useMastersSceneData = useMastersSceneData; slave._projectionOffset = projectionOffset; slave._viewOffset = viewOffset; slave._updateSlaveCallback = new osgDepthPartition::MyUpdateSlaveCallback(dps.get(), 0); } return true; } bool View::setUpDepthPartition(DepthPartitionSettings* dsp) { osgDepthPartition::Cameras originalCameras = osgDepthPartition::getActiveCameras(*this); if (originalCameras.empty()) { OSG_INFO<<"osgView::View::setUpDepthPartition(,..), no windows assigned, doing view.setUpViewAcrossAllScreens()"<areThreadsRunning(); if (threadsWereRunning) getViewerBase()->stopThreading(); for(osgDepthPartition::Cameras::iterator itr = originalCameras.begin(); itr != originalCameras.end(); ++itr) { setUpDepthPartitionForCamera(itr->get(), dsp); } if (threadsWereRunning) getViewerBase()->startThreading(); return true; } void View::assignSceneDataToCameras() { // OSG_NOTICE<<"View::assignSceneDataToCameras()"<getDatabasePager() && getViewerBase()) { _scene->getDatabasePager()->setIncrementalCompileOperation(getViewerBase()->getIncrementalCompileOperation()); } osg::Node* sceneData = _scene.valid() ? _scene->getSceneData() : 0; if (_cameraManipulator.valid()) { _cameraManipulator->setNode(sceneData); osg::ref_ptr dummyEvent = _eventQueue->createEvent(); _cameraManipulator->home(*dummyEvent, *this); } if (_camera.valid()) { _camera->removeChildren(0,_camera->getNumChildren()); if (sceneData) _camera->addChild(sceneData); Renderer* renderer = dynamic_cast(_camera->getRenderer()); if (renderer) renderer->setCompileOnNextDraw(true); } for(unsigned i=0; iremoveChildren(0,slave._camera->getNumChildren()); if (sceneData) slave._camera->addChild(sceneData); Renderer* renderer = dynamic_cast(slave._camera->getRenderer()); if (renderer) renderer->setCompileOnNextDraw(true); } } } void View::requestRedraw() { if (getViewerBase()) { getViewerBase()->_requestRedraw = true; } else { OSG_INFO<<"View::requestRedraw(), No viewer base has been assigned yet."<_requestContinousUpdate = flag; } else { OSG_INFO<<"View::requestContinuousUpdate(), No viewer base has been assigned yet."<(camera->getGraphicsContext()); if (gw) { getEventQueue()->mouseWarped(x,y); if (gw->getEventQueue()->getCurrentEventState()->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS) { local_y = gw->getTraits()->height - local_y; } const_cast(gw)->getEventQueue()->mouseWarped(local_x,local_y); const_cast(gw)->requestWarpPointer(local_x, local_y); } } else { OSG_INFO<<"View::requestWarpPointer failed no camera containing pointer"<getCurrentEventState(); const osgViewer::GraphicsWindow* gw = dynamic_cast(eventState->getGraphicsContext()); bool view_invert_y = eventState->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS; // OSG_NOTICE<<"getCameraContainingPosition("<getViewport(); // rescale mouse x,y first to 0 to 1 range double new_x = (x-eventState->getXmin())/(eventState->getXmax()-eventState->getXmin()); double new_y = (y-eventState->getYmin())/(eventState->getYmax()-eventState->getYmin()); // flip y if required if (view_invert_y) new_y = 1.0f-new_y; // rescale mouse x, y to window dimensions so we can check against master Camera's viewport new_x *= static_cast(_camera->getGraphicsContext()->getTraits()->width); new_y *= static_cast(_camera->getGraphicsContext()->getTraits()->height); if (new_x >= (viewport->x()-epsilon) && new_y >= (viewport->y()-epsilon) && new_x < (viewport->x()+viewport->width()-1.0+epsilon) && new_y <= (viewport->y()+viewport->height()-1.0+epsilon) ) { local_x = new_x; local_y = new_y; //OSG_NOTICE<<"Returning master camera"<getViewMatrix() * getCamera()->getProjectionMatrix(); // convert to non dimensional x = (x - eventState->getXmin()) * 2.0 / (eventState->getXmax()-eventState->getXmin()) - 1.0; y = (y - eventState->getYmin())* 2.0 / (eventState->getYmax()-eventState->getYmin()) - 1.0; if (view_invert_y) y = - y; for(int i=getNumSlaves()-1; i>=0; --i) { const Slave& slave = getSlave(i); if (slave._camera.valid() && slave._camera->getAllowEventFocus() && slave._camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER) { OSG_INFO<<"Testing slave camera "<getName()<getViewport() : 0; osg::Matrix localCameraVPW = camera->getViewMatrix() * camera->getProjectionMatrix(); if (viewport) localCameraVPW *= viewport->computeWindowMatrix(); osg::Matrix matrix( osg::Matrix::inverse(masterCameraVPW) * localCameraVPW ); osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix; //OSG_NOTICE<<" x="<getXmin()="<getXmin()<<" eventState->getXmax()="<getXmax()<= (viewport->x()-epsilon) && new_coord.y() >= (viewport->y()-epsilon) && new_coord.x() < (viewport->x()+viewport->width()-1.0+epsilon) && new_coord.y() <= (viewport->y()+viewport->height()-1.0+epsilon) ) { // OSG_NOTICE<<" in viewport "<x()<<" "<<(viewport->x()+viewport->width())<setGraphicsContext(gc); camera->setViewport(new osg::Viewport(0,0,width, height)); camera->setDrawBuffer(GL_FRONT); camera->setReadBuffer(GL_FRONT); camera->setAllowEventFocus(false); camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. camera->attach(osg::Camera::COLOR_BUFFER, texture); addSlave(camera.get(), osg::Matrixd(), osg::Matrixd()); return camera.release(); } osg::Camera* View::assignKeystoneDistortionCamera(osg::DisplaySettings* ds, osg::GraphicsContext* gc, int x, int y, int width, int height, GLenum buffer, osg::Texture* texture, Keystone* keystone) { double screenDistance = ds->getScreenDistance(); double screenWidth = ds->getScreenWidth(); double screenHeight = ds->getScreenHeight(); double fovy = osg::RadiansToDegrees(2.0*atan2(screenHeight/2.0,screenDistance)); double aspectRatio = screenWidth/screenHeight; osg::Geode* geode = keystone->createKeystoneDistortionMesh(); // new we need to add the texture to the mesh, we do so by creating a // StateSet to contain the Texture StateAttribute. osg::StateSet* stateset = geode->getOrCreateStateSet(); stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON); stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); osg::TexMat* texmat = new osg::TexMat; texmat->setScaleByTextureRectangleSize(true); stateset->setTextureAttributeAndModes(0, texmat, osg::StateAttribute::ON); osg::ref_ptr camera = new osg::Camera; camera->setGraphicsContext(gc); camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ); camera->setClearColor( osg::Vec4(0.0,0.0,0.0,1.0) ); camera->setViewport(new osg::Viewport(x, y, width, height)); camera->setDrawBuffer(buffer); camera->setReadBuffer(buffer); camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE); //camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); camera->setViewMatrix(osg::Matrix::identity()); camera->setProjectionMatrixAsPerspective(fovy, aspectRatio, 0.1, 1000.0); // add subgraph to render camera->addChild(geode); camera->addChild(keystone->createGrid()); camera->setName("DistortionCorrectionCamera"); // camera->addEventCallback(new KeystoneHandler(keystone)); addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false); return camera.release(); } void View::StereoSlaveCallback::updateSlave(osg::View& view, osg::View::Slave& slave) { osg::Camera* camera = slave._camera.get(); osgViewer::View* viewer_view = dynamic_cast(&view); if (_ds.valid() && camera && viewer_view) { // inherit any settings applied to the master Camera. camera->inheritCullSettings(*(view.getCamera()), camera->getInheritanceMask()); if (_eyeScale<0.0) { camera->setCullMask(camera->getCullMaskLeft()); } else { camera->setCullMask(camera->getCullMaskRight()); } // set projection matrix if (_eyeScale<0.0) { camera->setProjectionMatrix(_ds->computeLeftEyeProjectionImplementation(view.getCamera()->getProjectionMatrix())); } else { camera->setProjectionMatrix(_ds->computeRightEyeProjectionImplementation(view.getCamera()->getProjectionMatrix())); } double sd = _ds->getScreenDistance(); double fusionDistance = sd; switch(viewer_view->getFusionDistanceMode()) { case(osgUtil::SceneView::USE_FUSION_DISTANCE_VALUE): fusionDistance = viewer_view->getFusionDistanceValue(); break; case(osgUtil::SceneView::PROPORTIONAL_TO_SCREEN_DISTANCE): fusionDistance *= viewer_view->getFusionDistanceValue(); break; } double eyeScale = osg::absolute(_eyeScale) * (fusionDistance/sd); if (_eyeScale<0.0) { camera->setViewMatrix(_ds->computeLeftEyeViewImplementation(view.getCamera()->getViewMatrix(), eyeScale)); } else { camera->setViewMatrix(_ds->computeRightEyeViewImplementation(view.getCamera()->getViewMatrix(), eyeScale)); } } else { slave.updateSlaveImplementation(view); } } osg::Camera* View::assignStereoCamera(osg::DisplaySettings* ds, osg::GraphicsContext* gc, int x, int y, int width, int height, GLenum buffer, double eyeScale) { osg::ref_ptr camera = new osg::Camera; camera->setGraphicsContext(gc); camera->setViewport(new osg::Viewport(x,y, width, height)); camera->setDrawBuffer(buffer); camera->setReadBuffer(buffer); // add this slave camera to the viewer, with a shift left of the projection matrix addSlave(camera.get(), osg::Matrixd::identity(), osg::Matrixd::identity()); // assign update callback to maintain the correct view and projection matrices osg::View::Slave& slave = getSlave(getNumSlaves()-1); slave._updateSlaveCallback = new StereoSlaveCallback(ds, eyeScale); return camera.release(); } static const GLubyte patternVertEven[] = { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}; static const GLubyte patternVertOdd[] = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}; static const GLubyte patternHorzEven[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; // 32 x 32 bit array every row is a horizontal line of pixels // and the (bitwise) columns a vertical line // The following is a checkerboard pattern static const GLubyte patternCheckerboard[] = { 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA}; void View::assignStereoOrKeystoneToCamera(osg::Camera* camera, osg::DisplaySettings* ds) { if (!camera || camera->getGraphicsContext()==0) return; if (!ds->getStereo() && !ds->getKeystoneHint()) return; ds->setUseSceneViewForStereoHint(false); typedef std::vector< osg::ref_ptr > Keystones; Keystones keystones; if (ds->getKeystoneHint() && !ds->getKeystones().empty()) { for(osg::DisplaySettings::Objects::iterator itr = ds->getKeystones().begin(); itr != ds->getKeystones().end(); ++itr) { Keystone* keystone = dynamic_cast(itr->get()); if (keystone) keystones.push_back(keystone); } } if (ds->getKeystoneHint()) { while(keystones.size()<2) keystones.push_back(new Keystone); } // set up view's main camera { double height = ds->getScreenHeight(); double width = ds->getScreenWidth(); double distance = ds->getScreenDistance(); double vfov = osg::RadiansToDegrees(atan2(height/2.0f,distance)*2.0); camera->setProjectionMatrixAsPerspective( vfov, width/height, 1.0f,10000.0f); } osg::ref_ptr gc = camera->getGraphicsContext(); osg::ref_ptr traits = const_cast(camera->getGraphicsContext()->getTraits()); if (!ds->getStereo()) { // load or create a Keystone object osg::ref_ptr keystone = 0; if (!(ds->getKeystones().empty())) keystone = dynamic_cast(ds->getKeystones().front().get()); if (!keystone) keystone = new osgViewer::Keystone; // create distortion texture osg::ref_ptr texture = createDistortionTexture(traits->width, traits->height); // create RTT Camera assignRenderToTextureCamera(gc.get(), traits->width, traits->height, texture.get()); // create Keystone distortion camera osg::ref_ptr distortion_camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, texture.get(), keystone.get()); // attach Keystone editing event handler. distortion_camera->addEventCallback(new KeystoneHandler(keystone.get())); camera->setGraphicsContext(0); return; } switch(ds->getStereoMode()) { case(osg::DisplaySettings::QUAD_BUFFER): { // disconect the camera from the graphics context. camera->setGraphicsContext(0); // left Camera left buffer osg::ref_ptr left_camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK_LEFT : GL_FRONT_LEFT, -1.0); left_camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); left_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); // right Camera right buffer osg::ref_ptr right_camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK_RIGHT : GL_FRONT_RIGHT, 1.0); right_camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); // for keystone: // left camera to render to left texture // right camera to render to right texture // left keystone camera to render to left buffer // left keystone camera to render to right buffer // one keystone and editing for the one window if (!keystones.empty()) { // for keystone: // left camera to render to left texture using whole viewport of left texture // right camera to render to right texture using whole viewport of right texture // left keystone camera to render to left viewport/window // right keystone camera to render to right viewport/window // two keystone, one for each of the left and right viewports/windows osg::ref_ptr keystone = keystones.front(); // create distortion texture osg::ref_ptr left_texture = createDistortionTexture(traits->width, traits->height); // convert to RTT Camera left_camera->setViewport(0, 0, traits->width, traits->height); left_camera->setDrawBuffer(GL_FRONT); left_camera->setReadBuffer(GL_FRONT); left_camera->setAllowEventFocus(true); left_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. left_camera->attach(osg::Camera::COLOR_BUFFER, left_texture.get()); // create distortion texture osg::ref_ptr right_texture = createDistortionTexture(traits->width, traits->height); // convert to RTT Camera right_camera->setViewport(0, 0, traits->width, traits->height); right_camera->setDrawBuffer(GL_FRONT); right_camera->setReadBuffer(GL_FRONT); right_camera->setAllowEventFocus(true); right_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. right_camera->attach(osg::Camera::COLOR_BUFFER, right_texture.get()); // create Keystone left distortion camera keystone->setGridColor(osg::Vec4(1.0f,0.0f,0.0,1.0)); osg::ref_ptr left_keystone_camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK_LEFT : GL_FRONT_LEFT, left_texture.get(), keystone.get()); left_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 2); // attach Keystone editing event handler. left_keystone_camera->addEventCallback(new KeystoneHandler(keystone.get())); // create Keystone right distortion camera osg::ref_ptr right_keystone_camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK_RIGHT : GL_FRONT_RIGHT, right_texture.get(), keystone.get()); right_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 3); right_keystone_camera->setAllowEventFocus(false); } break; } case(osg::DisplaySettings::ANAGLYPHIC): { // disconect the camera from the graphics context. camera->setGraphicsContext(0); // left Camera red osg::ref_ptr left_camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, -1.0); left_camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); left_camera->getOrCreateStateSet()->setAttribute(new osg::ColorMask(true, false, false, true)); left_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); // right Camera cyan osg::ref_ptr right_camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0); right_camera->setClearMask(GL_DEPTH_BUFFER_BIT); right_camera->getOrCreateStateSet()->setAttribute(new osg::ColorMask(false, true, true, true)); right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); if (!keystones.empty()) { // for keystone: // left camera to render to texture using red colour mask // right camera to render to same texture using cyan colour mask // keystone camera to render to whole screen without colour masks // one keystone and editing for the one window osg::ref_ptr keystone = keystones.front(); bool useTwoTexture = true; if (useTwoTexture) { // create left distortion texture osg::ref_ptr left_texture = createDistortionTexture(traits->width, traits->height); // convert to RTT Camera left_camera->setDrawBuffer(GL_FRONT); left_camera->setReadBuffer(GL_FRONT); left_camera->setAllowEventFocus(false); left_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); left_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); left_camera->getOrCreateStateSet()->removeAttribute(osg::StateAttribute::COLORMASK); left_camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // attach the texture and use it as the color buffer. left_camera->attach(osg::Camera::COLOR_BUFFER, left_texture.get()); // create left distortion texture osg::ref_ptr right_texture = createDistortionTexture(traits->width, traits->height); // convert to RTT Camera right_camera->setDrawBuffer(GL_FRONT); right_camera->setReadBuffer(GL_FRONT); right_camera->setAllowEventFocus(false); right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); right_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); right_camera->getOrCreateStateSet()->removeAttribute(osg::StateAttribute::COLORMASK); right_camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // attach the texture and use it as the color buffer. right_camera->attach(osg::Camera::COLOR_BUFFER, right_texture.get()); // create Keystone left distortion camera osg::ref_ptr left_keystone_camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, left_texture.get(), keystone.get()); left_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 2); left_keystone_camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); left_keystone_camera->getOrCreateStateSet()->setAttribute(new osg::ColorMask(true, false, false, true)); // create Keystone right distortion camera osg::ref_ptr right_keystone_camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, right_texture.get(), keystone.get()); right_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 3); right_keystone_camera->setClearMask(GL_DEPTH_BUFFER_BIT); right_keystone_camera->getOrCreateStateSet()->setAttribute(new osg::ColorMask(false, true, true, true)); // attach Keystone editing event handler. left_keystone_camera->addEventCallback(new KeystoneHandler(keystone.get())); camera->setAllowEventFocus(false); } else { // create distortion texture osg::ref_ptr texture = createDistortionTexture(traits->width, traits->height); // convert to RTT Camera left_camera->setDrawBuffer(GL_FRONT); left_camera->setReadBuffer(GL_FRONT); left_camera->setAllowEventFocus(false); left_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); left_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. left_camera->attach(osg::Camera::COLOR_BUFFER, texture.get()); // convert to RTT Camera right_camera->setDrawBuffer(GL_FRONT); right_camera->setReadBuffer(GL_FRONT); right_camera->setAllowEventFocus(false); right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); right_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. right_camera->attach(osg::Camera::COLOR_BUFFER, texture.get()); // create Keystone distortion camera osg::ref_ptr distortion_camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, texture.get(), keystone.get()); distortion_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 2); // attach Keystone editing event handler. distortion_camera->addEventCallback(new KeystoneHandler(keystone.get())); camera->setAllowEventFocus(false); } } break; } case(osg::DisplaySettings::HORIZONTAL_SPLIT): { // disconect the camera from the graphics context. camera->setGraphicsContext(0); bool left_eye_left_viewport = ds->getSplitStereoHorizontalEyeMapping()==osg::DisplaySettings::LEFT_EYE_LEFT_VIEWPORT; int left_start = (left_eye_left_viewport) ? 0 : traits->width/2; int right_start = (left_eye_left_viewport) ? traits->width/2 : 0; // left viewport Camera osg::ref_ptr left_camera = assignStereoCamera(ds, gc.get(), left_start, 0, traits->width/2, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, -1.0); // right viewport Camera osg::ref_ptr right_camera = assignStereoCamera(ds, gc.get(), right_start, 0, traits->width/2, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0); if (!keystones.empty()) { // for keystone: // left camera to render to left texture using whole viewport of left texture // right camera to render to right texture using whole viewport of right texture // left keystone camera to render to left viewport/window // right keystone camera to render to right viewport/window // two keystone, one for each of the left and right viewports/windows osg::ref_ptr left_keystone = keystones[0]; osg::ref_ptr right_keystone = keystones[1]; // create distortion texture osg::ref_ptr left_texture = createDistortionTexture(traits->width/2, traits->height); // convert to RTT Camera left_camera->setViewport(0, 0, traits->width/2, traits->height); left_camera->setDrawBuffer(GL_FRONT); left_camera->setReadBuffer(GL_FRONT); left_camera->setAllowEventFocus(true); left_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); left_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. left_camera->attach(osg::Camera::COLOR_BUFFER, left_texture.get()); // create distortion texture osg::ref_ptr right_texture = createDistortionTexture(traits->width/2, traits->height); // convert to RTT Camera right_camera->setViewport(0, 0, traits->width/2, traits->height); right_camera->setDrawBuffer(GL_FRONT); right_camera->setReadBuffer(GL_FRONT); right_camera->setAllowEventFocus(true); right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); right_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. right_camera->attach(osg::Camera::COLOR_BUFFER, right_texture.get()); // create Keystone left distortion camera left_keystone->setGridColor(osg::Vec4(1.0f,0.0f,0.0,1.0)); osg::ref_ptr left_keystone_camera = assignKeystoneDistortionCamera(ds, gc.get(), left_start, 0, traits->width/2, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, left_texture.get(), left_keystone.get()); left_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 2); // attach Keystone editing event handler. left_keystone_camera->addEventCallback(new KeystoneHandler(left_keystone.get())); // create Keystone right distortion camera right_keystone->setGridColor(osg::Vec4(0.0f,1.0f,0.0,1.0)); osg::ref_ptr right_keystone_camera = assignKeystoneDistortionCamera(ds, gc.get(), right_start, 0, traits->width/2, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, right_texture.get(), right_keystone.get()); right_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 3); // attach Keystone editing event handler. right_keystone_camera->addEventCallback(new KeystoneHandler(right_keystone.get())); camera->setAllowEventFocus(false); } break; } case(osg::DisplaySettings::VERTICAL_SPLIT): { // disconect the camera from the graphics context. camera->setGraphicsContext(0); bool left_eye_bottom_viewport = ds->getSplitStereoVerticalEyeMapping()==osg::DisplaySettings::LEFT_EYE_BOTTOM_VIEWPORT; int left_start = (left_eye_bottom_viewport) ? 0 : traits->height/2; int right_start = (left_eye_bottom_viewport) ? traits->height/2 : 0; // bottom viewport Camera osg::ref_ptr left_camera = assignStereoCamera(ds, gc.get(), 0, left_start, traits->width, traits->height/2, traits->doubleBuffer ? GL_BACK : GL_FRONT, -1.0); // top vieport camera osg::ref_ptr right_camera = assignStereoCamera(ds, gc.get(), 0, right_start, traits->width, traits->height/2, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0); // for keystone: // left camera to render to left texture using whole viewport of left texture // right camera to render to right texture using whole viewport of right texture // left keystone camera to render to left viewport/window // right keystone camera to render to right viewport/window // two keystone, one for each of the left and right viewports/windows if (!keystones.empty()) { // for keystone: // left camera to render to left texture using whole viewport of left texture // right camera to render to right texture using whole viewport of right texture // left keystone camera to render to left viewport/window // right keystone camera to render to right viewport/window // two keystone, one for each of the left and right viewports/windows osg::ref_ptr left_keystone = keystones[0]; osg::ref_ptr right_keystone = keystones[1]; // create distortion texture osg::ref_ptr left_texture = createDistortionTexture(traits->width, traits->height/2); // convert to RTT Camera left_camera->setViewport(0, 0, traits->width, traits->height/2); left_camera->setDrawBuffer(GL_FRONT); left_camera->setReadBuffer(GL_FRONT); left_camera->setAllowEventFocus(true); left_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); left_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. left_camera->attach(osg::Camera::COLOR_BUFFER, left_texture.get()); // create distortion texture osg::ref_ptr right_texture = createDistortionTexture(traits->width, traits->height/2); // convert to RTT Camera right_camera->setViewport(0, 0, traits->width, traits->height/2); right_camera->setDrawBuffer(GL_FRONT); right_camera->setReadBuffer(GL_FRONT); right_camera->setAllowEventFocus(true); right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); right_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. right_camera->attach(osg::Camera::COLOR_BUFFER, right_texture.get()); // create Keystone left distortion camera left_keystone->setGridColor(osg::Vec4(1.0f,0.0f,0.0,1.0)); osg::ref_ptr left_keystone_camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, left_start, traits->width, traits->height/2, traits->doubleBuffer ? GL_BACK : GL_FRONT, left_texture.get(), left_keystone.get()); left_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 2); // attach Keystone editing event handler. left_keystone_camera->addEventCallback(new KeystoneHandler(left_keystone.get())); // create Keystone right distortion camera right_keystone->setGridColor(osg::Vec4(0.0f,1.0f,0.0,1.0)); osg::ref_ptr right_keystone_camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, right_start, traits->width, traits->height/2, traits->doubleBuffer ? GL_BACK : GL_FRONT, right_texture.get(), right_keystone.get()); right_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 3); // attach Keystone editing event handler. right_keystone_camera->addEventCallback(new KeystoneHandler(right_keystone.get())); camera->setAllowEventFocus(false); } break; } case(osg::DisplaySettings::LEFT_EYE): { // disconect the camera from the graphics context. camera->setGraphicsContext(0); // single window, whole window, just left eye offsets osg::ref_ptr left_camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, -1.0); // for keystone: // treat as standard keystone correction. // left eye camera to render to texture // keystone camera then render to window // one keystone and editing for window if (!keystones.empty()) { // for keystone: // left camera to render to texture using red colour mask // right camera to render to same texture using cyan colour mask // keystone camera to render to whole screen without colour masks // one keystone and editing for the one window osg::ref_ptr keystone = keystones.front(); // create distortion texture osg::ref_ptr texture = createDistortionTexture(traits->width, traits->height); // convert to RTT Camera left_camera->setDrawBuffer(GL_FRONT); left_camera->setReadBuffer(GL_FRONT); left_camera->setAllowEventFocus(false); left_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); left_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. left_camera->attach(osg::Camera::COLOR_BUFFER, texture.get()); // create Keystone distortion camera osg::ref_ptr distortion_camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, texture.get(), keystone.get()); distortion_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 2); // attach Keystone editing event handler. distortion_camera->addEventCallback(new KeystoneHandler(keystone.get())); } break; } case(osg::DisplaySettings::RIGHT_EYE): { // disconect the camera from the graphics context. camera->setGraphicsContext(0); // single window, whole window, just right eye offsets osg::ref_ptr right_camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0); // for keystone: // treat as standard keystone correction. // left eye camera to render to texture // keystone camera then render to window // one keystone and editing for window if (!keystones.empty()) { // for keystone: // left camera to render to texture using red colour mask // right camera to render to same texture using cyan colour mask // keystone camera to render to whole screen without colour masks // one keystone and editing for the one window osg::ref_ptr keystone = keystones.front(); // create distortion texture osg::ref_ptr texture = createDistortionTexture(traits->width, traits->height); // convert to RTT Camera right_camera->setDrawBuffer(GL_FRONT); right_camera->setReadBuffer(GL_FRONT); right_camera->setAllowEventFocus(false); right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); right_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. right_camera->attach(osg::Camera::COLOR_BUFFER, texture.get()); // create Keystone distortion camera osg::ref_ptr distortion_camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, texture.get(), keystone.get()); distortion_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); // attach Keystone editing event handler. distortion_camera->addEventCallback(new KeystoneHandler(keystone.get())); } break; } case(osg::DisplaySettings::HORIZONTAL_INTERLACE): case(osg::DisplaySettings::VERTICAL_INTERLACE): case(osg::DisplaySettings::CHECKERBOARD): { // disconect the camera from the graphics context. camera->setGraphicsContext(0); // set up the stencil buffer { osg::ref_ptr camera = new osg::Camera; camera->setGraphicsContext(gc.get()); camera->setViewport(0, 0, traits->width, traits->height); camera->setDrawBuffer(traits->doubleBuffer ? GL_BACK : GL_FRONT); camera->setReadBuffer(camera->getDrawBuffer()); camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); camera->setClearStencil(0); camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); addSlave(camera.get(), false); osg::ref_ptr geometry = osg::createTexturedQuadGeometry(osg::Vec3(-1.0f,-1.0f,0.0f), osg::Vec3(2.0f,0.0f,0.0f), osg::Vec3(0.0f,2.0f,0.0f), 0.0f, 0.0f, 1.0f, 1.0f); osg::ref_ptr geode = new osg::Geode; geode->addDrawable(geometry.get()); camera->addChild(geode.get()); geode->setCullingActive(false); osg::ref_ptr stateset = geode->getOrCreateStateSet(); // set up stencil osg::ref_ptr stencil = new osg::Stencil; stencil->setFunction(osg::Stencil::ALWAYS, 1, ~0u); stencil->setOperation(osg::Stencil::REPLACE, osg::Stencil::REPLACE, osg::Stencil::REPLACE); stencil->setWriteMask(~0u); stateset->setAttributeAndModes(stencil.get(), osg::StateAttribute::ON); // set up polygon stipple if(ds->getStereoMode() == osg::DisplaySettings::VERTICAL_INTERLACE) { stateset->setAttributeAndModes(new osg::PolygonStipple(patternVertEven), osg::StateAttribute::ON); } else if(ds->getStereoMode() == osg::DisplaySettings::HORIZONTAL_INTERLACE) { stateset->setAttributeAndModes(new osg::PolygonStipple(patternHorzEven), osg::StateAttribute::ON); } else { stateset->setAttributeAndModes(new osg::PolygonStipple(patternCheckerboard), osg::StateAttribute::ON); } stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); } // left Camera { osg::ref_ptr left_camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, -1.0); left_camera->setClearMask(0); left_camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); left_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); osg::ref_ptr stencil = new osg::Stencil; stencil->setFunction(osg::Stencil::EQUAL, 0, ~0u); stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP); left_camera->getOrCreateStateSet()->setAttributeAndModes(stencil.get(), osg::StateAttribute::ON); } // right Camera { osg::ref_ptr right_camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0); right_camera->setClearMask(GL_DEPTH_BUFFER_BIT); right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 2); osg::ref_ptr stencil = new osg::Stencil; stencil->setFunction(osg::Stencil::NOTEQUAL, 0, ~0u); stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP); right_camera->getOrCreateStateSet()->setAttributeAndModes(stencil.get(), osg::StateAttribute::ON); } break; } } } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/IOSUtils.mm0000644000175000017500000002234011715251270023774 0ustar albertoalberto/* * DarwinUtils.cpp * OpenSceneGraph * * Created by Stephan Huber on 27.06.08. * Copyright 2008 Stephan Maximilian Huber, digital mind. All rights reserved. * */ #include #include #include #import #include "IOSUtils.h" namespace osgIOS { class AutoReleasePoolHelper { public: AutoReleasePoolHelper() { pool = [[NSAutoreleasePool alloc] init]; } ~AutoReleasePoolHelper() { [pool release]; } private: NSAutoreleasePool* pool; }; /** ctor, get a list of all attached displays */ IOSWindowingSystemInterface::IOSWindowingSystemInterface() : osg::GraphicsContext::WindowingSystemInterface() { } /** dtor */ IOSWindowingSystemInterface::~IOSWindowingSystemInterface() { if (osg::Referenced::getDeleteHandler()) { osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); osg::Referenced::getDeleteHandler()->flushAll(); } } /** @return count of attached screens */ unsigned int IOSWindowingSystemInterface::getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si) { AutoReleasePoolHelper auto_release_pool_helper; return [[UIScreen screens] count]; } void IOSWindowingSystemInterface::getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution) { AutoReleasePoolHelper auto_release_pool_helper; if(si.screenNum >= [[UIScreen screens] count]){return;} //get the screens array from the UIScreen class NSArray* screens = [UIScreen screens]; //iterate to the desired screen num UIScreen* screen = [screens objectAtIndex:si.screenNum]; if (si.screenNum == 0) { //internal display supports only one mode, UiScreenMode reports wrong sizes for internal display at least for iOS 3.2 float scale = 1.0f; #if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) scale = [screen scale]; #endif resolution.width = [screen bounds].size.width * scale; resolution.height = [screen bounds].size.height * scale; resolution.colorDepth = 24; resolution.refreshRate = 60; //i've read 60 is max, not sure if thats true } else { //get the screen mode NSArray* modesArray = [screen availableModes]; if(modesArray) { //for this method we copy the first mode (default) then return UIScreenMode* mode = [modesArray objectAtIndex:0]; CGSize size = [mode size]; resolution.width = size.width; resolution.height = size.height; resolution.colorDepth = 24; resolution.refreshRate = 60; //i've read 60 is max, not sure if thats true OSG_INFO << "new resolution for screen " << si.screenNum << ": " << size.width << "x" << size.height << std::endl; } } } // //Due to the weird void IOSWindowingSystemInterface::enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettingsList & resolutionList) { AutoReleasePoolHelper auto_release_pool_helper; if(si.screenNum >= [[UIScreen screens] count]){return;} //get the screens array from the UIScreen class NSArray* screens = [UIScreen screens]; //get the desired screen num UIScreen* screen = [screens objectAtIndex:si.screenNum]; if (si.screenNum == 0) { //internal display supports only one mode, UiScreenMode reports wrong sizes for internal screen at least for iOS 3.2 osg::GraphicsContext::ScreenSettings resolution; float scale = 1.0f; #if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) scale = [screen scale]; #endif resolution.width = [screen bounds].size.width * scale; resolution.height = [screen bounds].size.height * scale; resolution.colorDepth = 24; resolution.refreshRate = 60; //i've read 60 is max, not sure if thats true resolutionList.push_back(resolution); } else { // external display may support more resolutions: //get the screen mode NSArray* modesArray = [screen availableModes]; NSEnumerator* modesEnum = [modesArray objectEnumerator]; UIScreenMode* mode; //iterate over modes and get their size property while ( mode = [modesEnum nextObject] ) { osg::GraphicsContext::ScreenSettings resolution; CGSize size = [mode size]; resolution.width = size.width; resolution.height = size.height; resolution.colorDepth = 24; resolution.refreshRate = 60; //i've read 60 is max, not sure if thats true resolutionList.push_back(resolution); OSG_INFO << "new resolution: " << size.width << "x" << size.height << std::endl; } } } bool IOSWindowingSystemInterface::setScreenSettings(const osg::GraphicsContext::ScreenIdentifier &si, const osg::GraphicsContext::ScreenSettings & settings) { bool result = setScreenResolutionImpl(si, settings.width, settings.height); if (result) setScreenRefreshRateImpl(si, settings.refreshRate); return result; } /** implementation of setScreenResolution */ //IPad can have extenal screens which we can request a res for //the main screen screenNum 0 can not currently have its res changed //as it only has one mode (might change though and this should still handle it) // bool IOSWindowingSystemInterface::setScreenResolutionImpl(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height) { AutoReleasePoolHelper auto_release_pool_helper; if(si.screenNum >= [[UIScreen screens] count]){return false;} //get the screens array from the UIScreen class NSArray* screens = [UIScreen screens]; //iterate to the desired screen num UIScreen* screen = [screens objectAtIndex:si.screenNum]; //get the screen mode NSArray* modesArray = [screen availableModes]; NSEnumerator* modesEnum = [modesArray objectEnumerator]; UIScreenMode* mode; //iterate over modes and get their size property while ( mode = [modesEnum nextObject] ) { osg::GraphicsContext::ScreenSettings resolution; CGSize size = [mode size]; //if the modes size/resolution matches the passed width/height then assign this //mode as the screens current mode if(size.width == width && size.height == height) { screen.currentMode = mode; OSG_INFO << "IOSWindowingSystemInterface::setScreenResolutionImpl: Set resolution of screen '" << si.screenNum << "', to '" << width << ", " << height << "'." << std::endl; return true; } } OSG_WARN << "IOSWindowingSystemInterface::setScreenResolutionImpl: Failed to set resolution of screen '" << si.screenNum << "', to '" << width << ", " << height << "'." << std::endl; return false; } /** implementation of setScreenRefreshRate, don't think you can do this on IOS */ bool IOSWindowingSystemInterface::setScreenRefreshRateImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, double refreshRate) { return true; } unsigned int IOSWindowingSystemInterface::getScreenContaining(int x, int y, int w, int h) { return 1; } // //return the UIScreen object asscoiated with the passed ScreenIdentifier //returns nil if si isn't found // UIScreen* IOSWindowingSystemInterface::getUIScreen(const osg::GraphicsContext::ScreenIdentifier& si) { AutoReleasePoolHelper auto_release_pool_helper; if(si.screenNum >= [[UIScreen screens] count]){return nil;} UIScreen* screen = [[UIScreen screens] objectAtIndex:si.screenNum]; return screen; } // //Returns the contents scale factor of the screen, this is the scale factor required //to convert points to pixels on this screen // bool IOSWindowingSystemInterface::getScreenContentScaleFactor(const osg::GraphicsContext::ScreenIdentifier& si, float& scaleFactor) { AutoReleasePoolHelper auto_release_pool_helper; if(si.screenNum >= [[UIScreen screens] count]){return false;} UIScreen* screen = this->getUIScreen(si); if(screen != nil) { scaleFactor = 1.0f; #if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) CGFloat scale = [screen scale]; scaleFactor = scale; #endif return true; } return false; } // //Returns the screens size in points, docs state a point is roughly 1/160th of an inch // bool IOSWindowingSystemInterface::getScreenSizeInPoints(const osg::GraphicsContext::ScreenIdentifier& si, osg::Vec2& pointSize) { AutoReleasePoolHelper auto_release_pool_helper; if(si.screenNum >= [[UIScreen screens] count]){return false;} UIScreen* screen = this->getUIScreen(si); if(screen != nil) { CGRect bounds = [screen bounds]; pointSize.x() = bounds.size.width; pointSize.y() = bounds.size.height; return true; } return false; } } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/config/0000755000175000017500000000000012674261220023233 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/config/AcrossAllScreens.cpp0000644000175000017500000001166712146640772027167 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include using namespace osgViewer; void AcrossAllScreens::configure(osgViewer::View& view) const { osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); if (!wsi) { OSG_NOTICE<<"AcrossAllScreens::configure() : Error, no WindowSystemInterface available, cannot create windows."<getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar); osg::GraphicsContext::ScreenIdentifier si; si.readDISPLAY(); // displayNum has not been set so reset it to 0. if (si.displayNum<0) si.displayNum = 0; unsigned int numScreens = wsi->getNumScreens(si); if (numScreens==1) { osg::ref_ptr ss = new SingleScreen(0); ss->configure(view); } else { double translate_x = 0.0; for(unsigned int i=0; igetScreenResolution(si, width, height); translate_x += double(width) / (double(height) * aspectRatio); } bool stereoSplitScreens = numScreens==2 && ds->getStereoMode()==osg::DisplaySettings::HORIZONTAL_SPLIT && ds->getStereo(); for(unsigned int i=0; igetScreenResolution(si, width, height); osg::ref_ptr traits = new osg::GraphicsContext::Traits(ds); traits->hostName = si.hostName; traits->displayNum = si.displayNum; traits->screenNum = si.screenNum; traits->screenNum = i; traits->x = 0; traits->y = 0; traits->width = width; traits->height = height; traits->windowDecoration = false; traits->doubleBuffer = true; traits->sharedContext = 0; osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); osg::ref_ptr camera = new osg::Camera; camera->setGraphicsContext(gc.get()); osgViewer::GraphicsWindow* gw = dynamic_cast(gc.get()); if (gw) { OSG_INFO<<" GraphicsWindow has been created successfully."<getEventQueue()->getCurrentEventState()->setWindowRectangle(traits->x, traits->y, traits->width, traits->height ); } else { OSG_NOTICE<<" GraphicsWindow has not been created successfully."<setViewport(new osg::Viewport(0, 0, traits->width, traits->height)); GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT; camera->setDrawBuffer(buffer); camera->setReadBuffer(buffer); if (stereoSplitScreens) { unsigned int leftCameraNum = (ds->getSplitStereoHorizontalEyeMapping()==osg::DisplaySettings::LEFT_EYE_LEFT_VIEWPORT) ? 0 : 1; osg::ref_ptr ds_local = new osg::DisplaySettings(*ds); ds_local->setStereoMode(leftCameraNum==i ? osg::DisplaySettings::LEFT_EYE : osg::DisplaySettings::RIGHT_EYE); camera->setDisplaySettings(ds_local.get()); view.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd() ); } else { double newAspectRatio = double(traits->width) / double(traits->height); double aspectRatioChange = newAspectRatio / aspectRatio; view.addSlave(camera.get(), osg::Matrixd::translate( translate_x - aspectRatioChange, 0.0, 0.0) * osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0), osg::Matrixd() ); translate_x -= aspectRatioChange * 2.0; } } } view.assignSceneDataToCameras(); } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/config/WoWVxDisplay.cpp0000644000175000017500000017237612243626606026344 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include using namespace osgViewer; void WoWVxDisplay::configure(osgViewer::View& view) const { OSG_INFO<<"WoWVxDisplay::configure(...)"<getScreenResolution(si, width, height); osg::ref_ptr traits = new osg::GraphicsContext::Traits; traits->hostName = si.hostName; traits->displayNum = si.displayNum; traits->screenNum = si.screenNum; traits->x = 0; traits->y = 0; traits->width = width; traits->height = height; traits->windowDecoration = false; traits->doubleBuffer = true; traits->sharedContext = 0; osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); if (!gc) { OSG_NOTICE<<"GraphicsWindow has not been created successfully."<setTextureSize(tex_width, tex_height); texture->setInternalFormat(GL_RGB); texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); osg::Texture2D* textureD = new osg::Texture2D; textureD->setTextureSize(tex_width, tex_height); textureD->setInternalFormat(GL_DEPTH_COMPONENT); textureD->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); textureD->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); #if 0 osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::SEPERATE_WINDOW; GLenum buffer = GL_FRONT; #else osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::FRAME_BUFFER_OBJECT; GLenum buffer = GL_FRONT; #endif // front face { osg::ref_ptr camera = new osg::Camera; camera->setName("Front face camera"); camera->setGraphicsContext(gc.get()); camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height)); camera->setDrawBuffer(buffer); camera->setReadBuffer(buffer); camera->setAllowEventFocus(false); // tell the camera to use OpenGL frame buffer object where supported. camera->setRenderTargetImplementation(renderTargetImplementation); // attach the texture and use it as the color buffer. camera->attach(osg::Camera::COLOR_BUFFER, texture); camera->attach(osg::Camera::DEPTH_BUFFER, textureD); view.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd()); } // WoW display set up. { osg::Texture1D *textureHeader = new osg::Texture1D(); // Set up the header { unsigned char header[]= {0xF1,_wow_content,_wow_factor,_wow_offset,0x00,0x00,0x00,0x00,0x00,0x00}; // Calc the CRC32 { unsigned long _register = 0; for(int i = 0; i < 10; ++i) { unsigned char mask = 0x80; unsigned char byte = header[i]; for (int j = 0; j < 8; ++j) { bool topBit = (_register & 0x80000000) != 0; _register <<= 1; _register ^= ((byte & mask) != 0? 0x1: 0x0); if (topBit) { _register ^= 0x04c11db7; } mask >>= 1; } } unsigned char *p = (unsigned char*) &_register; for(size_t i = 0; i < 4; ++i) { header[i+6] = p[3-i]; } } osg::ref_ptr imageheader = new osg::Image(); imageheader->allocateImage(256,1,1,GL_LUMINANCE,GL_UNSIGNED_BYTE); { unsigned char *cheader = imageheader->data(); for (int x=0; x<256; ++x){ cheader[x] = 0; } for (int x=0; x<=9; ++x){ for (int y=7; y>=0; --y){ int i = 2*(7-y)+16*x; cheader[i] = (((1<<(y))&(header[x])) << (7-(y))); } } } textureHeader->setImage(imageheader.get()); } // Create the Screen Aligned Quad osg::Geode* geode = new osg::Geode(); { osg::Geometry* geom = new osg::Geometry; osg::Vec3Array* vertices = new osg::Vec3Array; vertices->push_back(osg::Vec3(0,height,0)); vertices->push_back(osg::Vec3(0,0,0)); vertices->push_back(osg::Vec3(width,0,0)); vertices->push_back(osg::Vec3(width,height,0)); geom->setVertexArray(vertices); osg::Vec2Array* tex = new osg::Vec2Array; tex->push_back(osg::Vec2(0,1)); tex->push_back(osg::Vec2(0,0)); tex->push_back(osg::Vec2(1,0)); tex->push_back(osg::Vec2(1,1)); geom->setTexCoordArray(0,tex); geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4)); geode->addDrawable(geom); // new we need to add the textures to the quad, and setting up the shader. osg::StateSet* stateset = geode->getOrCreateStateSet(); stateset->setTextureAttributeAndModes(0, textureHeader,osg::StateAttribute::ON); stateset->setTextureAttributeAndModes(1, texture,osg::StateAttribute::ON); stateset->setTextureAttributeAndModes(2, textureD,osg::StateAttribute::ON); stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); osg::ref_ptr programShader = new osg::Program(); stateset->setAttribute(programShader.get(), osg::StateAttribute::ON); stateset->addUniform( new osg::Uniform("wow_width", (int)width)); stateset->addUniform( new osg::Uniform("wow_height", (int)height)); stateset->addUniform( new osg::Uniform("wow_disparity_M", _wow_disparity_M)); stateset->addUniform( new osg::Uniform("wow_disparity_Zd", _wow_disparity_Zd)); stateset->addUniform( new osg::Uniform("wow_disparity_vz", _wow_disparity_vz)); stateset->addUniform( new osg::Uniform("wow_disparity_C", _wow_disparity_C)); stateset->addUniform(new osg::Uniform("wow_header", 0)); stateset->addUniform(new osg::Uniform("wow_tcolor", 1)); stateset->addUniform(new osg::Uniform("wow_tdepth", 2)); osg::Shader *frag = new osg::Shader(osg::Shader::FRAGMENT); frag->setShaderSource(" "\ " uniform sampler1D wow_header; " \ " uniform sampler2D wow_tcolor; " \ " uniform sampler2D wow_tdepth; " \ " " \ " uniform int wow_width; " \ " uniform int wow_height; " \ " uniform float wow_disparity_M; " \ " uniform float wow_disparity_Zd; " \ " uniform float wow_disparity_vz; " \ " uniform float wow_disparity_C; " \ " " \ " float disparity(float Z) " \ " { " \ " return (wow_disparity_M*(1.0-(wow_disparity_vz/(Z-wow_disparity_Zd+wow_disparity_vz))) " \ " + wow_disparity_C) / 255.0; " \ " } " \ " " \ " void main() " \ " { " \ " vec2 pos = (gl_FragCoord.xy / vec2(wow_width/2,wow_height) ); " \ " if (gl_FragCoord.x > float(wow_width/2)) " \ " { " \ " gl_FragColor = vec4(disparity(( texture2D(wow_tdepth, pos - vec2(1,0))).z)); " \ " } " \ " else{ " \ " gl_FragColor = texture2D(wow_tcolor, pos); " \ " } " \ " if ( (gl_FragCoord.y >= float(wow_height-1)) && (gl_FragCoord.x < 256.0) ) " \ " { " \ " float pos = gl_FragCoord.x/256.0; " \ " float blue = texture1D(wow_header, pos).b; " \ " if ( blue < 0.5) " \ " gl_FragColor.b = 0.0; " \ " else " \ " gl_FragColor.b = 1.0; " \ " } " \ " } " ); programShader->addShader(frag); } // Create the Camera { osg::ref_ptr camera = new osg::Camera; camera->setGraphicsContext(gc.get()); camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ); camera->setClearColor( osg::Vec4(0.0,0.0,0.0,1.0) ); camera->setViewport(new osg::Viewport(0, 0, width, height)); GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT; camera->setDrawBuffer(buffer); camera->setReadBuffer(buffer); camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); camera->setAllowEventFocus(false); camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE); //camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); camera->setProjectionMatrixAsOrtho2D(0,width,0,height); camera->setViewMatrix(osg::Matrix::identity()); // add subgraph to render camera->addChild(geode); camera->setName("WoWCamera"); view.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false); } } } #if 0 DepthPartitionSettings::DepthPartitionSettings(DepthMode mode): _mode(mode), _zNear(1.0), _zMid(5.0), _zFar(1000.0) {} bool DepthPartitionSettings::getDepthRange(osg::View& view, unsigned int partition, double& zNear, double& zFar) { switch(_mode) { case(FIXED_RANGE): { if (partition==0) { zNear = _zNear; zFar = _zMid; return true; } else if (partition==1) { zNear = _zMid; zFar = _zFar; return true; } return false; } case(BOUNDING_VOLUME): { osgViewer::View* view_withSceneData = dynamic_cast(&view); const osg::Node* node = view_withSceneData ? view_withSceneData->getSceneData() : 0; if (!node) return false; const osg::Camera* masterCamera = view.getCamera(); if (!masterCamera) return false; osg::BoundingSphere bs = node->getBound(); const osg::Matrixd& viewMatrix = masterCamera->getViewMatrix(); //osg::Matrixd& projectionMatrix = masterCamera->getProjectionMatrix(); osg::Vec3d lookVectorInWorldCoords = osg::Matrixd::transform3x3(viewMatrix,osg::Vec3d(0.0,0.0,-1.0)); lookVectorInWorldCoords.normalize(); osg::Vec3d nearPointInWorldCoords = bs.center() - lookVectorInWorldCoords*bs.radius(); osg::Vec3d farPointInWorldCoords = bs.center() + lookVectorInWorldCoords*bs.radius(); osg::Vec3d nearPointInEyeCoords = nearPointInWorldCoords * viewMatrix; osg::Vec3d farPointInEyeCoords = farPointInWorldCoords * viewMatrix; #if 0 OSG_NOTICE<setNodeMask(0x0); return; } else { camera->setNodeMask(0xffffff); } if (camera->getProjectionMatrix()(0,3)==0.0 && camera->getProjectionMatrix()(1,3)==0.0 && camera->getProjectionMatrix()(2,3)==0.0) { double left, right, bottom, top, zNear, zFar; camera->getProjectionMatrixAsOrtho(left, right, bottom, top, zNear, zFar); camera->setProjectionMatrixAsOrtho(left, right, bottom, top, computed_zNear, computed_zFar); } else { double left, right, bottom, top, zNear, zFar; camera->getProjectionMatrixAsFrustum(left, right, bottom, top, zNear, zFar); double nr = computed_zNear / zNear; camera->setProjectionMatrixAsFrustum(left * nr, right * nr, bottom * nr, top * nr, computed_zNear, computed_zFar); } } osg::ref_ptr _dps; unsigned int _partition; }; typedef std::list< osg::ref_ptr > Cameras; Cameras getActiveCameras(osg::View& view) { Cameras activeCameras; if (view.getCamera() && view.getCamera()->getGraphicsContext()) { activeCameras.push_back(view.getCamera()); } for(unsigned int i=0; igetGraphicsContext()) { activeCameras.push_back(slave._camera.get()); } } return activeCameras; } } bool View::setUpDepthPartitionForCamera(osg::Camera* cameraToPartition, DepthPartitionSettings* incomming_dps) { osg::ref_ptr context = cameraToPartition->getGraphicsContext(); if (!context) return false; osg::ref_ptr viewport = cameraToPartition->getViewport(); if (!viewport) return false; osg::ref_ptr dps = incomming_dps; if (!dps) dps = new DepthPartitionSettings; bool useMastersSceneData = true; osg::Matrixd projectionOffset; osg::Matrixd viewOffset; if (getCamera()==cameraToPartition) { // replace main camera with depth partition cameras OSG_INFO<<"View::setUpDepthPartitionForCamera(..) Replacing main Camera"<=getNumSlaves()) return false; osg::View::Slave& slave = getSlave(i); useMastersSceneData = slave._useMastersSceneData; projectionOffset = slave._projectionOffset; viewOffset = slave._viewOffset; OSG_NOTICE<<"View::setUpDepthPartitionForCamera(..) Replacing slave Camera"<setGraphicsContext(0); cameraToPartition->setViewport(0); // far camera { osg::ref_ptr camera = new osg::Camera; camera->setGraphicsContext(context.get()); camera->setViewport(viewport.get()); camera->setDrawBuffer(cameraToPartition->getDrawBuffer()); camera->setReadBuffer(cameraToPartition->getReadBuffer()); camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); camera->setCullingMode(osg::Camera::ENABLE_ALL_CULLING); addSlave(camera.get()); osg::View::Slave& slave = getSlave(getNumSlaves()-1); slave._useMastersSceneData = useMastersSceneData; slave._projectionOffset = projectionOffset; slave._viewOffset = viewOffset; slave._updateSlaveCallback = new osgDepthPartition::MyUpdateSlaveCallback(dps.get(), 1); } // near camera { osg::ref_ptr camera = new osg::Camera; camera->setGraphicsContext(context.get()); camera->setViewport(viewport.get()); camera->setDrawBuffer(cameraToPartition->getDrawBuffer()); camera->setReadBuffer(cameraToPartition->getReadBuffer()); camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); camera->setCullingMode(osg::Camera::ENABLE_ALL_CULLING); camera->setClearMask(GL_DEPTH_BUFFER_BIT); addSlave(camera.get()); osg::View::Slave& slave = getSlave(getNumSlaves()-1); slave._useMastersSceneData = useMastersSceneData; slave._projectionOffset = projectionOffset; slave._viewOffset = viewOffset; slave._updateSlaveCallback = new osgDepthPartition::MyUpdateSlaveCallback(dps.get(), 0); } return true; } bool View::setUpDepthPartition(DepthPartitionSettings* dsp) { osgDepthPartition::Cameras originalCameras = osgDepthPartition::getActiveCameras(*this); if (originalCameras.empty()) { OSG_INFO<<"osgView::View::setUpDepthPartition(,..), no windows assigned, doing view.setUpViewAcrossAllScreens()"<areThreadsRunning(); if (threadsWereRunning) getViewerBase()->stopThreading(); for(osgDepthPartition::Cameras::iterator itr = originalCameras.begin(); itr != originalCameras.end(); ++itr) { setUpDepthPartitionForCamera(itr->get(), dsp); } if (threadsWereRunning) getViewerBase()->startThreading(); return true; } void View::StereoSlaveCallback::updateSlave(osg::View& view, osg::View::Slave& slave) { osg::Camera* camera = slave._camera.get(); osgViewer::View* viewer_view = dynamic_cast(&view); if (_ds.valid() && camera && viewer_view) { // set projection matrix if (_eyeScale<0.0) { camera->setProjectionMatrix(_ds->computeLeftEyeProjectionImplementation(view.getCamera()->getProjectionMatrix())); } else { camera->setProjectionMatrix(_ds->computeRightEyeProjectionImplementation(view.getCamera()->getProjectionMatrix())); } double sd = _ds->getScreenDistance(); double fusionDistance = sd; switch(viewer_view->getFusionDistanceMode()) { case(osgUtil::SceneView::USE_FUSION_DISTANCE_VALUE): fusionDistance = viewer_view->getFusionDistanceValue(); break; case(osgUtil::SceneView::PROPORTIONAL_TO_SCREEN_DISTANCE): fusionDistance *= viewer_view->getFusionDistanceValue(); break; } double eyeScale = osg::absolute(_eyeScale) * (fusionDistance/sd); if (_eyeScale<0.0) { camera->setViewMatrix(_ds->computeLeftEyeViewImplementation(view.getCamera()->getViewMatrix(), eyeScale)); } else { camera->setViewMatrix(_ds->computeRightEyeViewImplementation(view.getCamera()->getViewMatrix(), eyeScale)); } } else { slave.updateSlaveImplementation(view); } } osg::Camera* View::assignStereoCamera(osg::DisplaySettings* ds, osg::GraphicsContext* gc, int x, int y, int width, int height, GLenum buffer, double eyeScale) { osg::ref_ptr camera = new osg::Camera; camera->setGraphicsContext(gc); camera->setViewport(new osg::Viewport(x,y, width, height)); camera->setDrawBuffer(buffer); camera->setReadBuffer(buffer); // add this slave camera to the viewer, with a shift left of the projection matrix addSlave(camera.get(), osg::Matrixd::identity(), osg::Matrixd::identity()); // assign update callback to maintain the correct view and projection matrices osg::View::Slave& slave = getSlave(getNumSlaves()-1); slave._updateSlaveCallback = new StereoSlaveCallback(ds, eyeScale); return camera.release(); } static const GLubyte patternVertEven[] = { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}; static const GLubyte patternVertOdd[] = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}; static const GLubyte patternHorzEven[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; // 32 x 32 bit array every row is a horizontal line of pixels // and the (bitwise) columns a vertical line // The following is a checkerboard pattern static const GLubyte patternCheckerboard[] = { 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA}; void View::setUpViewForStereo() { osg::DisplaySettings* ds = _displaySettings.valid() ? _displaySettings.get() : osg::DisplaySettings::instance().get(); if (!ds->getStereo()) return; ds->setUseSceneViewForStereoHint(false); typedef std::vector< osg::ref_ptr > Keystones; Keystones keystones; if (ds->getKeystoneHint() && !ds->getKeystones().empty()) { for(osg::DisplaySettings::Objects::iterator itr = ds->getKeystones().begin(); itr != ds->getKeystones().end(); ++itr) { Keystone* keystone = dynamic_cast(itr->get()); if (keystone) keystones.push_back(keystone); } } if (ds->getKeystoneHint()) { while(keystones.size()<2) keystones.push_back(new Keystone); } // set up view's main camera { double height = osg::DisplaySettings::instance()->getScreenHeight(); double width = osg::DisplaySettings::instance()->getScreenWidth(); double distance = osg::DisplaySettings::instance()->getScreenDistance(); double vfov = osg::RadiansToDegrees(atan2(height/2.0f,distance)*2.0); getCamera()->setProjectionMatrixAsPerspective( vfov, width/height, 1.0f,10000.0f); } int screenNum = 0; osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); if (!wsi) { OSG_NOTICE<<"Error, no WindowSystemInterface available, cannot create windows."<getNumScreens(si); osg::GraphicsContext::ScreenIdentifier si; si.readDISPLAY(); // displayNum has not been set so reset it to 0. if (si.displayNum<0) si.displayNum = 0; si.screenNum = screenNum; unsigned int width, height; wsi->getScreenResolution(si, width, height); // width/=2; height/=2; osg::ref_ptr traits = new osg::GraphicsContext::Traits(ds); traits->hostName = si.hostName; traits->displayNum = si.displayNum; traits->screenNum = si.screenNum; traits->x = 0; traits->y = 0; traits->width = width; traits->height = height; traits->windowDecoration = false; traits->doubleBuffer = true; traits->sharedContext = 0; OSG_NOTICE<<"traits->stencil="<stencil< gc = osg::GraphicsContext::createGraphicsContext(traits.get()); if (!gc) { OSG_NOTICE<<"GraphicsWindow has not been created successfully."<getStereoMode()) { case(osg::DisplaySettings::QUAD_BUFFER): { // left Camera left buffer osg::ref_ptr left_camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK_LEFT : GL_FRONT_LEFT, -1.0); left_camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); left_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); // right Camera right buffer osg::ref_ptr right_camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK_RIGHT : GL_FRONT_RIGHT, 1.0); right_camera->setClearMask(GL_DEPTH_BUFFER_BIT); right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); // for keystone: // left camera to render to left texture // right camera to render to right texture // left keystone camera to render to left buffer // left keystone camera to render to right buffer // one keystone and editing for the one window if (!keystones.empty()) { // for keystone: // left camera to render to left texture using whole viewport of left texture // right camera to render to right texture using whole viewport of right texture // left keystone camera to render to left viewport/window // right keystone camera to render to right viewport/window // two keystone, one for each of the left and right viewports/windows osg::ref_ptr keystone = keystones.front(); // create distortion texture osg::ref_ptr left_texture = createDistortionTexture(traits->width, traits->height); // convert to RTT Camera left_camera->setViewport(0, 0, traits->width, traits->height); left_camera->setDrawBuffer(GL_FRONT); left_camera->setReadBuffer(GL_FRONT); left_camera->setAllowEventFocus(true); left_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. left_camera->attach(osg::Camera::COLOR_BUFFER, left_texture.get()); // create distortion texture osg::ref_ptr right_texture = createDistortionTexture(traits->width, traits->height); // convert to RTT Camera right_camera->setViewport(0, 0, traits->width, traits->height); right_camera->setDrawBuffer(GL_FRONT); right_camera->setReadBuffer(GL_FRONT); right_camera->setAllowEventFocus(true); right_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. right_camera->attach(osg::Camera::COLOR_BUFFER, right_texture.get()); // create Keystone left distortion camera keystone->setGridColor(osg::Vec4(1.0f,0.0f,0.0,1.0)); osg::ref_ptr left_keystone_camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK_LEFT : GL_FRONT_LEFT, left_texture.get(), keystone.get()); left_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 2); // attach Keystone editing event handler. left_keystone_camera->addEventCallback(new KeystoneHandler(keystone.get())); // create Keystone right distortion camera osg::ref_ptr right_keystone_camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK_RIGHT : GL_FRONT_RIGHT, right_texture.get(), keystone.get()); right_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 3); right_keystone_camera->setAllowEventFocus(false); } break; } case(osg::DisplaySettings::ANAGLYPHIC): { // left Camera red osg::ref_ptr left_camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, -1.0); left_camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); left_camera->getOrCreateStateSet()->setAttribute(new osg::ColorMask(true, false, false, true)); left_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); // right Camera cyan osg::ref_ptr right_camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0); right_camera->setClearMask(GL_DEPTH_BUFFER_BIT); right_camera->getOrCreateStateSet()->setAttribute(new osg::ColorMask(false, true, true, true)); right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); if (!keystones.empty()) { // for keystone: // left camera to render to texture using red colour mask // right camera to render to same texture using cyan colour mask // keystone camera to render to whole screen without colour masks // one keystone and editing for the one window osg::ref_ptr keystone = keystones.front(); // create distortion texture osg::ref_ptr texture = createDistortionTexture(traits->width, traits->height); // convert to RTT Camera left_camera->setDrawBuffer(GL_FRONT); left_camera->setReadBuffer(GL_FRONT); left_camera->setAllowEventFocus(false); right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); left_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. left_camera->attach(osg::Camera::COLOR_BUFFER, texture.get()); // convert to RTT Camera right_camera->setDrawBuffer(GL_FRONT); right_camera->setReadBuffer(GL_FRONT); right_camera->setAllowEventFocus(false); right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); right_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. right_camera->attach(osg::Camera::COLOR_BUFFER, texture.get()); // create Keystone distortion camera osg::ref_ptr camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, texture.get(), keystone.get()); camera->setRenderOrder(osg::Camera::NESTED_RENDER, 2); // attach Keystone editing event handler. camera->addEventCallback(new KeystoneHandler(keystone.get())); } break; } case(osg::DisplaySettings::HORIZONTAL_SPLIT): { bool left_eye_left_viewport = ds->getSplitStereoHorizontalEyeMapping()==osg::DisplaySettings::LEFT_EYE_LEFT_VIEWPORT; int left_start = (left_eye_left_viewport) ? 0 : traits->width/2; int right_start = (left_eye_left_viewport) ? traits->width/2 : 0; // left viewport Camera osg::ref_ptr left_camera = assignStereoCamera(ds, gc.get(), left_start, 0, traits->width/2, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0); // right viewport Camera osg::ref_ptr right_camera = assignStereoCamera(ds, gc.get(), right_start, 0, traits->width/2, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0); if (!keystones.empty()) { // for keystone: // left camera to render to left texture using whole viewport of left texture // right camera to render to right texture using whole viewport of right texture // left keystone camera to render to left viewport/window // right keystone camera to render to right viewport/window // two keystone, one for each of the left and right viewports/windows osg::ref_ptr left_keystone = keystones[0]; osg::ref_ptr right_keystone = keystones[1]; // create distortion texture osg::ref_ptr left_texture = createDistortionTexture(traits->width/2, traits->height); // convert to RTT Camera left_camera->setViewport(0, 0, traits->width/2, traits->height); left_camera->setDrawBuffer(GL_FRONT); left_camera->setReadBuffer(GL_FRONT); left_camera->setAllowEventFocus(true); left_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); left_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. left_camera->attach(osg::Camera::COLOR_BUFFER, left_texture.get()); // create distortion texture osg::ref_ptr right_texture = createDistortionTexture(traits->width/2, traits->height); // convert to RTT Camera right_camera->setViewport(0, 0, traits->width/2, traits->height); right_camera->setDrawBuffer(GL_FRONT); right_camera->setReadBuffer(GL_FRONT); right_camera->setAllowEventFocus(true); right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); right_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. right_camera->attach(osg::Camera::COLOR_BUFFER, right_texture.get()); // create Keystone left distortion camera left_keystone->setGridColor(osg::Vec4(1.0f,0.0f,0.0,1.0)); osg::ref_ptr left_keystone_camera = assignKeystoneDistortionCamera(ds, gc.get(), left_start, 0, traits->width/2, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, left_texture.get(), left_keystone.get()); left_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 2); // attach Keystone editing event handler. left_keystone_camera->addEventCallback(new KeystoneHandler(left_keystone.get())); // create Keystone right distortion camera right_keystone->setGridColor(osg::Vec4(0.0f,1.0f,0.0,1.0)); osg::ref_ptr right_keystone_camera = assignKeystoneDistortionCamera(ds, gc.get(), right_start, 0, traits->width/2, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, right_texture.get(), right_keystone.get()); right_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 3); // attach Keystone editing event handler. right_keystone_camera->addEventCallback(new KeystoneHandler(right_keystone.get())); getCamera()->setAllowEventFocus(false); } break; } case(osg::DisplaySettings::VERTICAL_SPLIT): { bool left_eye_bottom_viewport = ds->getSplitStereoVerticalEyeMapping()==osg::DisplaySettings::LEFT_EYE_BOTTOM_VIEWPORT; int left_start = (left_eye_bottom_viewport) ? 0 : traits->height/2; int right_start = (left_eye_bottom_viewport) ? traits->height/2 : 0; // bottom viewport Camera osg::ref_ptr left_camera = assignStereoCamera(ds, gc.get(), 0, left_start, traits->width, traits->height/2, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0); // top vieport camera osg::ref_ptr right_camera = assignStereoCamera(ds, gc.get(), 0, right_start, traits->width, traits->height/2, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0); // for keystone: // left camera to render to left texture using whole viewport of left texture // right camera to render to right texture using whole viewport of right texture // left keystone camera to render to left viewport/window // right keystone camera to render to right viewport/window // two keystone, one for each of the left and right viewports/windows if (!keystones.empty()) { // for keystone: // left camera to render to left texture using whole viewport of left texture // right camera to render to right texture using whole viewport of right texture // left keystone camera to render to left viewport/window // right keystone camera to render to right viewport/window // two keystone, one for each of the left and right viewports/windows osg::ref_ptr left_keystone = keystones[0]; osg::ref_ptr right_keystone = keystones[1]; // create distortion texture osg::ref_ptr left_texture = createDistortionTexture(traits->width, traits->height/2); // convert to RTT Camera left_camera->setViewport(0, 0, traits->width, traits->height/2); left_camera->setDrawBuffer(GL_FRONT); left_camera->setReadBuffer(GL_FRONT); left_camera->setAllowEventFocus(true); left_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); left_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. left_camera->attach(osg::Camera::COLOR_BUFFER, left_texture.get()); // create distortion texture osg::ref_ptr right_texture = createDistortionTexture(traits->width, traits->height/2); // convert to RTT Camera right_camera->setViewport(0, 0, traits->width, traits->height/2); right_camera->setDrawBuffer(GL_FRONT); right_camera->setReadBuffer(GL_FRONT); right_camera->setAllowEventFocus(true); right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); right_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. right_camera->attach(osg::Camera::COLOR_BUFFER, right_texture.get()); // create Keystone left distortion camera left_keystone->setGridColor(osg::Vec4(1.0f,0.0f,0.0,1.0)); osg::ref_ptr left_keystone_camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, left_start, traits->width, traits->height/2, traits->doubleBuffer ? GL_BACK : GL_FRONT, left_texture.get(), left_keystone.get()); left_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 2); // attach Keystone editing event handler. left_keystone_camera->addEventCallback(new KeystoneHandler(left_keystone.get())); // create Keystone right distortion camera right_keystone->setGridColor(osg::Vec4(0.0f,1.0f,0.0,1.0)); osg::ref_ptr right_keystone_camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, right_start, traits->width, traits->height/2, traits->doubleBuffer ? GL_BACK : GL_FRONT, right_texture.get(), right_keystone.get()); right_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 3); // attach Keystone editing event handler. right_keystone_camera->addEventCallback(new KeystoneHandler(right_keystone.get())); getCamera()->setAllowEventFocus(false); } break; } case(osg::DisplaySettings::LEFT_EYE): { // single window, whole window, just left eye offsets osg::ref_ptr left_camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, -1.0); // for keystone: // treat as standard keystone correction. // left eye camera to render to texture // keystone camera then render to window // one keystone and editing for window if (!keystones.empty()) { // for keystone: // left camera to render to texture using red colour mask // right camera to render to same texture using cyan colour mask // keystone camera to render to whole screen without colour masks // one keystone and editing for the one window osg::ref_ptr keystone = keystones.front(); // create distortion texture osg::ref_ptr texture = createDistortionTexture(traits->width, traits->height); // convert to RTT Camera left_camera->setDrawBuffer(GL_FRONT); left_camera->setReadBuffer(GL_FRONT); left_camera->setAllowEventFocus(false); left_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); left_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. left_camera->attach(osg::Camera::COLOR_BUFFER, texture.get()); // create Keystone distortion camera osg::ref_ptr camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, texture.get(), keystone.get()); camera->setRenderOrder(osg::Camera::NESTED_RENDER, 2); // attach Keystone editing event handler. camera->addEventCallback(new KeystoneHandler(keystone.get())); } break; } case(osg::DisplaySettings::RIGHT_EYE): { // single window, whole window, just right eye offsets osg::ref_ptr right_camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0); // for keystone: // treat as standard keystone correction. // left eye camera to render to texture // keystone camera then render to window // one keystone and editing for window if (!keystones.empty()) { // for keystone: // left camera to render to texture using red colour mask // right camera to render to same texture using cyan colour mask // keystone camera to render to whole screen without colour masks // one keystone and editing for the one window osg::ref_ptr keystone = keystones.front(); // create distortion texture osg::ref_ptr texture = createDistortionTexture(traits->width, traits->height); // convert to RTT Camera right_camera->setDrawBuffer(GL_FRONT); right_camera->setReadBuffer(GL_FRONT); right_camera->setAllowEventFocus(false); right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); right_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // attach the texture and use it as the color buffer. right_camera->attach(osg::Camera::COLOR_BUFFER, texture.get()); // create Keystone distortion camera osg::ref_ptr camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, texture.get(), keystone.get()); camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); // attach Keystone editing event handler. camera->addEventCallback(new KeystoneHandler(keystone.get())); } break; } case(osg::DisplaySettings::HORIZONTAL_INTERLACE): case(osg::DisplaySettings::VERTICAL_INTERLACE): case(osg::DisplaySettings::CHECKERBOARD): { // set up the stencil buffer { osg::ref_ptr camera = new osg::Camera; camera->setGraphicsContext(gc.get()); camera->setViewport(0, 0, traits->width, traits->height); camera->setDrawBuffer(traits->doubleBuffer ? GL_BACK : GL_FRONT); camera->setReadBuffer(camera->getDrawBuffer()); camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); camera->setClearStencil(0); camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); addSlave(camera.get(), false); osg::ref_ptr geometry = osg::createTexturedQuadGeometry(osg::Vec3(-1.0f,-1.0f,0.0f), osg::Vec3(2.0f,0.0f,0.0f), osg::Vec3(0.0f,2.0f,0.0f), 0.0f, 0.0f, 1.0f, 1.0f); osg::ref_ptr geode = new osg::Geode; geode->addDrawable(geometry.get()); camera->addChild(geode.get()); geode->setCullingActive(false); osg::ref_ptr stateset = geode->getOrCreateStateSet(); // set up stencil osg::ref_ptr stencil = new osg::Stencil; stencil->setFunction(osg::Stencil::ALWAYS, 1, ~0u); stencil->setOperation(osg::Stencil::REPLACE, osg::Stencil::REPLACE, osg::Stencil::REPLACE); stencil->setWriteMask(~0u); stateset->setAttributeAndModes(stencil.get(), osg::StateAttribute::ON); // set up polygon stipple if(ds->getStereoMode() == osg::DisplaySettings::VERTICAL_INTERLACE) { stateset->setAttributeAndModes(new osg::PolygonStipple(patternVertEven), osg::StateAttribute::ON); } else if(ds->getStereoMode() == osg::DisplaySettings::HORIZONTAL_INTERLACE) { stateset->setAttributeAndModes(new osg::PolygonStipple(patternHorzEven), osg::StateAttribute::ON); } else { stateset->setAttributeAndModes(new osg::PolygonStipple(patternCheckerboard), osg::StateAttribute::ON); } stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); } // left Camera { osg::ref_ptr camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, -1.0); camera->setClearMask(0); camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); osg::ref_ptr stencil = new osg::Stencil; stencil->setFunction(osg::Stencil::EQUAL, 0, ~0u); stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP); camera->getOrCreateStateSet()->setAttributeAndModes(stencil.get(), osg::StateAttribute::ON); } // right Camera { osg::ref_ptr camera = assignStereoCamera(ds, gc.get(), 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0); camera->setClearMask(GL_DEPTH_BUFFER_BIT); camera->setRenderOrder(osg::Camera::NESTED_RENDER, 2); osg::ref_ptr stencil = new osg::Stencil; stencil->setFunction(osg::Stencil::NOTEQUAL, 0, ~0u); stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP); camera->getOrCreateStateSet()->setAttributeAndModes(stencil.get(), osg::StateAttribute::ON); } break; } } } void View::setUpViewForKeystone(Keystone* keystone) { int screenNum = 0; osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); if (!wsi) { OSG_NOTICE<<"Error, no WindowSystemInterface available, cannot create windows."<getScreenResolution(si, width, height); // width/=2; height/=2; osg::ref_ptr traits = new osg::GraphicsContext::Traits; traits->hostName = si.hostName; traits->displayNum = si.displayNum; traits->screenNum = si.screenNum; traits->x = 0; traits->y = 0; traits->width = width; traits->height = height; traits->windowDecoration = false; traits->doubleBuffer = true; traits->sharedContext = 0; osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); if (!gc) { OSG_NOTICE<<"GraphicsWindow has not been created successfully."< texture = createDistortionTexture(width, height); // create RTT Camera assignRenderToTextureCamera(gc.get(), width, height, texture.get()); // create Keystone distortion camera osg::ref_ptr camera = assignKeystoneDistortionCamera(ds, gc.get(), 0, 0, width, height, traits->doubleBuffer ? GL_BACK : GL_FRONT, texture.get(), keystone); // attach Keystone editing event handler. camera->addEventCallback(new KeystoneHandler(keystone)); } #endif openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/config/SingleScreen.cpp0000644000175000017500000000211312146474162026322 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include using namespace osgViewer; void SingleScreen::configure(osgViewer::View& view) const { osg::ref_ptr singleWindow = new SingleWindow(0,0,-1,-1,_screenNum); singleWindow->setWindowDecoration(false); singleWindow->configure(view); } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/config/PanoramicSphericalDisplay.cpp0000644000175000017500000002516312162625741031044 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include using namespace osgViewer; osg::Geometry* PanoramicSphericalDisplay::createParoramicSphericalDisplayDistortionMesh(const osg::Vec3& origin, const osg::Vec3& widthVector, const osg::Vec3& heightVector, double sphere_radius, double collar_radius, osg::Image* intensityMap, const osg::Matrix& projectorMatrix) const { osg::Vec3d center(0.0,0.0,0.0); osg::Vec3d eye(0.0,0.0,0.0); double distance = sqrt(sphere_radius*sphere_radius - collar_radius*collar_radius); bool flip = false; bool texcoord_flip = false; osg::Vec3d projector = eye - osg::Vec3d(0.0,0.0, distance); OSG_INFO<<"createParoramicSphericalDisplayDistortionMesh : Projector position = "<getScreenResolution(si, width, height); osg::ref_ptr traits = new osg::GraphicsContext::Traits; traits->hostName = si.hostName; traits->displayNum = si.displayNum; traits->screenNum = si.screenNum; traits->x = 0; traits->y = 0; traits->width = width; traits->height = height; traits->windowDecoration = false; traits->doubleBuffer = true; traits->sharedContext = 0; bool applyIntensityMapAsColours = true; osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); if (!gc) { OSG_NOTICE<<"GraphicsWindow has not been created successfully."<setTextureSize(tex_width, tex_height); texture->setInternalFormat(GL_RGB); texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR); texture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE); texture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE); #if 0 osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::SEPERATE_WINDOW; GLenum buffer = GL_FRONT; #else osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::FRAME_BUFFER_OBJECT; GLenum buffer = GL_FRONT; #endif // front face { osg::ref_ptr camera = new osg::Camera; camera->setName("Front face camera"); camera->setGraphicsContext(gc.get()); camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height)); camera->setDrawBuffer(buffer); camera->setReadBuffer(buffer); camera->setAllowEventFocus(false); // tell the camera to use OpenGL frame buffer object where supported. camera->setRenderTargetImplementation(renderTargetImplementation); // attach the texture and use it as the color buffer. camera->attach(osg::Camera::COLOR_BUFFER, texture); view.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd()); } // distortion correction set up. { osg::Geode* geode = new osg::Geode(); geode->addDrawable(createParoramicSphericalDisplayDistortionMesh(osg::Vec3(0.0f,0.0f,0.0f), osg::Vec3(width,0.0f,0.0f), osg::Vec3(0.0f,height,0.0f), _radius, _collar, applyIntensityMapAsColours ? _intensityMap.get() : 0, _projectorMatrix)); // new we need to add the texture to the mesh, we do so by creating a // StateSet to contain the Texture StateAttribute. osg::StateSet* stateset = geode->getOrCreateStateSet(); stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON); stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); osg::TexMat* texmat = new osg::TexMat; texmat->setScaleByTextureRectangleSize(true); stateset->setTextureAttributeAndModes(0, texmat, osg::StateAttribute::ON); if (!applyIntensityMapAsColours && _intensityMap.valid()) { stateset->setTextureAttributeAndModes(1, new osg::Texture2D(_intensityMap.get()), osg::StateAttribute::ON); } osg::ref_ptr camera = new osg::Camera; camera->setGraphicsContext(gc.get()); camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ); camera->setClearColor( osg::Vec4(0.0,0.0,0.0,1.0) ); camera->setViewport(new osg::Viewport(0, 0, width, height)); GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT; camera->setDrawBuffer(buffer); camera->setReadBuffer(buffer); camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); camera->setAllowEventFocus(false); camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE); //camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); camera->setProjectionMatrixAsOrtho2D(0,width,0,height); camera->setViewMatrix(osg::Matrix::identity()); // add subgraph to render camera->addChild(geode); camera->setName("DistortionCorrectionCamera"); view.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/config/SphericalDisplay.cpp0000644000175000017500000003731012162625741027207 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace osgViewer; osg::Geometry* SphericalDisplay::create3DSphericalDisplayDistortionMesh(const osg::Vec3& origin, const osg::Vec3& widthVector, const osg::Vec3& heightVector, double sphere_radius, double collar_radius,osg::Image* intensityMap, const osg::Matrix& projectorMatrix) const { osg::Vec3d center(0.0,0.0,0.0); osg::Vec3d eye(0.0,0.0,0.0); double distance = sqrt(sphere_radius*sphere_radius - collar_radius*collar_radius); bool centerProjection = false; osg::Vec3d projector = eye - osg::Vec3d(0.0,0.0, distance); OSG_INFO<<"create3DSphericalDisplayDistortionMesh : Projector position = "<getScreenResolution(si, width, height); osg::ref_ptr traits = new osg::GraphicsContext::Traits; traits->hostName = si.hostName; traits->displayNum = si.displayNum; traits->screenNum = si.screenNum; traits->x = 0; traits->y = 0; traits->width = width; traits->height = height; traits->windowDecoration = false; traits->doubleBuffer = true; traits->sharedContext = 0; osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); if (!gc) { OSG_NOTICE<<"GraphicsWindow has not been created successfully."<setTextureSize(tex_width, tex_height); texture->setInternalFormat(GL_RGB); texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR); texture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE); texture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE); texture->setWrap(osg::Texture::WRAP_R,osg::Texture::CLAMP_TO_EDGE); #if 0 osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::SEPERATE_WINDOW; GLenum buffer = GL_FRONT; #else osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::FRAME_BUFFER_OBJECT; GLenum buffer = GL_FRONT; #endif // front face { osg::ref_ptr camera = new osg::Camera; camera->setName("Front face camera"); camera->setGraphicsContext(gc.get()); camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height)); camera->setDrawBuffer(buffer); camera->setReadBuffer(buffer); camera->setAllowEventFocus(false); // tell the camera to use OpenGL frame buffer object where supported. camera->setRenderTargetImplementation(renderTargetImplementation); // attach the texture and use it as the color buffer. camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::POSITIVE_Y); view.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd()); } // top face { osg::ref_ptr camera = new osg::Camera; camera->setName("Top face camera"); camera->setGraphicsContext(gc.get()); camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height)); camera->setDrawBuffer(buffer); camera->setReadBuffer(buffer); camera->setAllowEventFocus(false); // tell the camera to use OpenGL frame buffer object where supported. camera->setRenderTargetImplementation(renderTargetImplementation); // attach the texture and use it as the color buffer. camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::POSITIVE_Z); view.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::inDegrees(-90.0f), 1.0,0.0,0.0)); } // left face { osg::ref_ptr camera = new osg::Camera; camera->setName("Left face camera"); camera->setGraphicsContext(gc.get()); camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height)); camera->setDrawBuffer(buffer); camera->setReadBuffer(buffer); camera->setAllowEventFocus(false); // tell the camera to use OpenGL frame buffer object where supported. camera->setRenderTargetImplementation(renderTargetImplementation); // attach the texture and use it as the color buffer. camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::NEGATIVE_X); view.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::inDegrees(-90.0f), 0.0,1.0,0.0) * osg::Matrixd::rotate(osg::inDegrees(-90.0f), 0.0,0.0,1.0)); } // right face { osg::ref_ptr camera = new osg::Camera; camera->setName("Right face camera"); camera->setGraphicsContext(gc.get()); camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height)); camera->setDrawBuffer(buffer); camera->setReadBuffer(buffer); camera->setAllowEventFocus(false); // tell the camera to use OpenGL frame buffer object where supported. camera->setRenderTargetImplementation(renderTargetImplementation); // attach the texture and use it as the color buffer. camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::POSITIVE_X); view.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::inDegrees(90.0f), 0.0,1.0,0.0 ) * osg::Matrixd::rotate(osg::inDegrees(90.0f), 0.0,0.0,1.0)); } // bottom face { osg::ref_ptr camera = new osg::Camera; camera->setGraphicsContext(gc.get()); camera->setName("Bottom face camera"); camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height)); camera->setDrawBuffer(buffer); camera->setReadBuffer(buffer); camera->setAllowEventFocus(false); // tell the camera to use OpenGL frame buffer object where supported. camera->setRenderTargetImplementation(renderTargetImplementation); // attach the texture and use it as the color buffer. camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::NEGATIVE_Z); view.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::inDegrees(90.0f), 1.0,0.0,0.0) * osg::Matrixd::rotate(osg::inDegrees(180.0f), 0.0,0.0,1.0)); } // back face { osg::ref_ptr camera = new osg::Camera; camera->setName("Back face camera"); camera->setGraphicsContext(gc.get()); camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height)); camera->setDrawBuffer(buffer); camera->setReadBuffer(buffer); camera->setAllowEventFocus(false); // tell the camera to use OpenGL frame buffer object where supported. camera->setRenderTargetImplementation(renderTargetImplementation); // attach the texture and use it as the color buffer. camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::NEGATIVE_Y); view.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::inDegrees(180.0f), 1.0,0.0,0.0)); } view.getCamera()->setProjectionMatrixAsPerspective(90.0f, 1.0, 1, 1000.0); // distortion correction set up. { osg::Geode* geode = new osg::Geode(); geode->addDrawable(create3DSphericalDisplayDistortionMesh(osg::Vec3(0.0f,0.0f,0.0f), osg::Vec3(width,0.0f,0.0f), osg::Vec3(0.0f,height,0.0f), _radius, _collar, applyIntensityMapAsColours ? _intensityMap.get() : 0, _projectorMatrix)); // new we need to add the texture to the mesh, we do so by creating a // StateSet to contain the Texture StateAttribute. osg::StateSet* stateset = geode->getOrCreateStateSet(); stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON); stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); if (!applyIntensityMapAsColours && _intensityMap.valid()) { stateset->setTextureAttributeAndModes(1, new osg::Texture2D(_intensityMap.get()), osg::StateAttribute::ON); } osg::ref_ptr camera = new osg::Camera; camera->setGraphicsContext(gc.get()); camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ); camera->setClearColor( osg::Vec4(0.0,0.0,0.0,1.0) ); camera->setViewport(new osg::Viewport(0, 0, width, height)); GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT; camera->setDrawBuffer(buffer); camera->setReadBuffer(buffer); camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); camera->setAllowEventFocus(true); camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE); //camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); camera->setProjectionMatrixAsOrtho2D(0,width,0,height); camera->setViewMatrix(osg::Matrix::identity()); // add subgraph to render camera->addChild(geode); camera->setName("DistortionCorrectionCamera"); view.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false); } view.getCamera()->setNearFarRatio(0.0001f); if (view.getLightingMode()==osg::View::HEADLIGHT) { // set a local light source for headlight to ensure that lighting is consistent across sides of cube. view.getLight()->setPosition(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/config/SingleWindow.cpp0000644000175000017500000001006712160630536026354 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include using namespace osgViewer; void SingleWindow::configure(osgViewer::View& view) const { osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); if (!wsi) { OSG_NOTICE<<"SingleWindow::configure() : Error, no WindowSystemInterface available, cannot create windows."< traits = new osg::GraphicsContext::Traits(ds); traits->readDISPLAY(); if (traits->displayNum<0) traits->displayNum = 0; traits->screenNum = _screenNum; traits->x = _x; traits->y = _y; traits->width = _width; traits->height = _height; traits->windowDecoration = _windowDecoration; traits->overrideRedirect = _overrideRedirect; traits->doubleBuffer = true; traits->sharedContext = 0; if (traits->width<=0 || traits->height<=0 ) { osg::GraphicsContext::ScreenIdentifier si; si.readDISPLAY(); // displayNum has not been set so reset it to 0. if (si.displayNum<0) si.displayNum = 0; si.screenNum = _screenNum; unsigned int width, height; wsi->getScreenResolution(si, width, height); if (traits->width<=0) traits->width = width; if (traits->height<=0) traits->height = height; } osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); view.getCamera()->setGraphicsContext(gc.get()); osgViewer::GraphicsWindow* gw = dynamic_cast(gc.get()); if (gw) { OSG_INFO<<"View::setUpViewOnSingleScreen - GraphicsWindow has been created successfully."<getEventQueue()->getCurrentEventState()->setWindowRectangle(traits->x, traits->y, traits->width, traits->height ); } else { OSG_NOTICE<<" GraphicsWindow has not been created successfully."<getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar); double newAspectRatio = double(traits->width) / double(traits->height); double aspectRatioChange = newAspectRatio / aspectRatio; if (aspectRatioChange != 1.0) { view.getCamera()->getProjectionMatrix() *= osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0); } view.getCamera()->setViewport(new osg::Viewport(0, 0, traits->width, traits->height)); GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT; view.getCamera()->setDrawBuffer(buffer); view.getCamera()->setReadBuffer(buffer); if (ds->getKeystoneHint()) { if (ds->getKeystoneHint() && !ds->getKeystoneFileNames().empty()) { osgViewer::Keystone::loadKeystoneFiles(ds); } if (ds->getKeystones().empty()) ds->getKeystones().push_back(new Keystone); view.assignStereoOrKeystoneToCamera(view.getCamera(), ds); } else if (ds->getStereo() && ds->getUseSceneViewForStereoHint()) { view.assignStereoOrKeystoneToCamera(view.getCamera(), ds); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/GraphicsWindowIOS.mm0000644000175000017500000012025412243412020025614 0ustar albertoalberto #include #include #import #import #if OSG_GLES1_FEATURES #import #else #import // in GLES2, the OES suffix if dropped from function names (from rti) #define glGenFramebuffersOES glGenFramebuffers #define glGenRenderbuffersOES glGenRenderbuffers #define glBindFramebufferOES glBindFramebuffer #define glBindRenderbufferOES glBindRenderbuffer #define glFramebufferRenderbufferOES glFramebufferRenderbuffer #define glGetRenderbufferParameterivOES glGetRenderbufferParameteriv #define glRenderbufferStorageOES glRenderbufferStorage #define glDeleteRenderbuffersOES glDeleteRenderbuffers #define glDeleteFramebuffersOES glDeleteFramebuffers #define glCheckFramebufferStatusOES glCheckFramebufferStatus #define GL_FRAMEBUFFER_OES GL_FRAMEBUFFER #define GL_RENDERBUFFER_OES GL_RENDERBUFFER #define GL_RENDERBUFFER_WIDTH_OES GL_RENDERBUFFER_WIDTH #define GL_RENDERBUFFER_HEIGHT_OES GL_RENDERBUFFER_HEIGHT #define GL_COLOR_ATTACHMENT0_OES GL_COLOR_ATTACHMENT0 #define GL_DEPTH_ATTACHMENT_OES GL_DEPTH_ATTACHMENT #define GL_DEPTH_COMPONENT16_OES GL_DEPTH_COMPONENT16 #define GL_STENCIL_INDEX8_OES GL_STENCIL_INDEX8 #define GL_FRAMEBUFFER_COMPLETE_OES GL_FRAMEBUFFER_COMPLETE #define GL_STENCIL_ATTACHMENT_OES GL_STENCIL_ATTACHMENT #define GL_RGB5_A1_OES GL_RGB5_A1 #endif #include "IOSUtils.h" #pragma mark GraphicsWindowIOSWindow // ---------------------------------------------------------------------------------------------------------- // GraphicsWindowIOSWindow, implements canBecomeKeyWindow + canBecomeMainWindow // ---------------------------------------------------------------------------------------------------------- @interface GraphicsWindowIOSWindow : UIWindow { } - (BOOL) canBecomeKeyWindow; - (BOOL) canBecomeMainWindow; @end @implementation GraphicsWindowIOSWindow // //Implement dealloc // - (void) dealloc { [super dealloc]; } - (BOOL) canBecomeKeyWindow { return YES; } - (BOOL) canBecomeMainWindow { return YES; } @end #pragma mark GraphicsWindowIOSGLView // ---------------------------------------------------------------------------------------------------------- // GraphicsWindowIOSGLView // custom UIView-class handling creation and display of frame/render buffers plus receives touch input // ---------------------------------------------------------------------------------------------------------- typedef std::map TouchPointsIdMapping; @interface GraphicsWindowIOSGLView : UIView { @private osgViewer::GraphicsWindowIOS* _win; EAGLContext* _context; /* The pixel dimensions of the backbuffer */ GLint _backingWidth; GLint _backingHeight; //the pixel buffers for the video /* OpenGL names for the renderbuffer and framebuffers used to render to this view */ GLuint _viewRenderbuffer, _viewFramebuffer; /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */ GLuint _depthRenderbuffer; /* OpenGL name for the stencil buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */ GLuint _stencilBuffer; // for multisampled antialiased rendering GLuint _msaaFramebuffer, _msaaRenderBuffer, _msaaDepthBuffer; TouchPointsIdMapping* _touchPointsIdMapping; unsigned int _lastTouchPointId; } - (void)setGraphicsWindow: (osgViewer::GraphicsWindowIOS*) win; - (osgViewer::GraphicsWindowIOS*) getGraphicsWindow; - (void)setOpenGLContext: (EAGLContext*) context; - (void)updateDimensions; - (BOOL)createFramebuffer; - (void)destroyFramebuffer; - (void)swapBuffers; - (void)bindFrameBuffer; - (BOOL)acceptsFirstResponder; - (BOOL)becomeFirstResponder; - (BOOL)resignFirstResponder; - (osgGA::GUIEventAdapter::TouchPhase) convertTouchPhase: (UITouchPhase) phase; - (osg::Vec2) convertPointToPixel: (osg::Vec2) point; - (void) dealloc; @end @implementation GraphicsWindowIOSGLView - (osgGA::GUIEventAdapter::TouchPhase) convertTouchPhase: (UITouchPhase) phase { switch(phase) { case UITouchPhaseBegan: return osgGA::GUIEventAdapter::TOUCH_BEGAN; break; case UITouchPhaseMoved: return osgGA::GUIEventAdapter::TOUCH_MOVED; break; case UITouchPhaseStationary: return osgGA::GUIEventAdapter::TOUCH_STATIONERY; break; case UITouchPhaseEnded: case UITouchPhaseCancelled: return osgGA::GUIEventAdapter::TOUCH_ENDED; break; } return osgGA::GUIEventAdapter::TOUCH_ENDED; } - (unsigned int)computeTouchId: (UITouch*) touch mayCleanup: (bool)may_cleanup { unsigned int result(0); if (!_touchPointsIdMapping) { _lastTouchPointId = 0; _touchPointsIdMapping = new TouchPointsIdMapping(); } switch([touch phase]) { case UITouchPhaseBegan: { TouchPointsIdMapping::iterator itr = _touchPointsIdMapping->find(touch); // std::cout << "new: " << touch << " num: " << _touchPointsIdMapping->size() << " found: " << (itr != _touchPointsIdMapping->end()) << std::endl; if (itr == _touchPointsIdMapping->end()) { (*_touchPointsIdMapping)[touch] = result = _lastTouchPointId; _lastTouchPointId++; break; } } // missing "break" by intention! case UITouchPhaseMoved: case UITouchPhaseStationary: { result = (*_touchPointsIdMapping)[touch]; } break; case UITouchPhaseEnded: case UITouchPhaseCancelled: { TouchPointsIdMapping::iterator itr = _touchPointsIdMapping->find(touch); // std::cout<< "remove: " << touch << " num: " << _touchPointsIdMapping->size() << " found: " << (itr != _touchPointsIdMapping->end()) << std::endl; if (itr != _touchPointsIdMapping->end()) { result = itr->second; if(may_cleanup) _touchPointsIdMapping->erase(itr); } if(_touchPointsIdMapping->size() == 0) { _lastTouchPointId = 0; } // std::cout<< "remove: " << touch << " num: " << _touchPointsIdMapping->size() << std::endl; } break; default: break; } return result; } - (osg::Vec2) convertPointToPixel: (osg::Vec2) point { //get the views contentscale factor and multiply the point by it float scale = 1.0f; #if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) scale = self.contentScaleFactor; #endif return osg::Vec2(point.x()*scale, point.y()*scale); } -(void) setGraphicsWindow: (osgViewer::GraphicsWindowIOS*) win { _win = win; _touchPointsIdMapping = new TouchPointsIdMapping(); _lastTouchPointId = 0; } - (osgViewer::GraphicsWindowIOS*) getGraphicsWindow { return _win; } -(void) setOpenGLContext: (EAGLContext*) context { _context = context; } // You must implement this method + (Class)layerClass { return [CAEAGLLayer class]; } // //Called when the view is created using a frame for dimensions // - (id)initWithFrame:(CGRect)frame : (osgViewer::GraphicsWindowIOS*)win{ _win = win; if ((self = [super initWithFrame:frame])) { // Get the layer CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; osgViewer::GraphicsWindowIOS::WindowData* win_data(NULL); if (_win->getTraits()->inheritedWindowData.valid()) win_data = dynamic_cast(_win->getTraits()->inheritedWindowData.get()); eaglLayer.opaque = win_data ? !win_data->getCreateTransparentView() : YES; bool retained_backing = win_data ? win_data->getUseRetainedBacking() : NO; if(_win->getTraits()->alpha > 0) { //create layer with alpha channel RGBA8 eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:retained_backing], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil]; }else{ //else no alpha, IOS uses RBG565 eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:retained_backing], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGB565, kEAGLDrawablePropertyColorFormat, nil]; } } self.multipleTouchEnabled = YES; return self; } // //Implement dealloc to destory our frame buffer // - (void) dealloc { OSG_INFO << "GraphicsWindowIOSGLView::dealloc" << std::endl; if(_touchPointsIdMapping) delete _touchPointsIdMapping; _touchPointsIdMapping = NULL; [super dealloc]; } - (void)layoutSubviews { [super layoutSubviews]; [self updateDimensions]; } - (void) setFrame:(CGRect)frame { [super setFrame:frame]; [self updateDimensions]; } - (void) updateDimensions { if (_win) { CGRect frame = self.bounds; osg::Vec2 pointOrigin = osg::Vec2(frame.origin.x,frame.origin.y); osg::Vec2 pointSize = osg::Vec2(frame.size.width,frame.size.height); osg::Vec2 pixelOrigin = [(GraphicsWindowIOSGLView*)(self) convertPointToPixel:pointOrigin]; osg::Vec2 pixelSize = [(GraphicsWindowIOSGLView*)(self) convertPointToPixel:pointSize]; OSG_INFO << "updateDimensions, resize to " << pixelOrigin.x() << " " << pixelOrigin.y() << " " << pixelSize.x() << " " << pixelSize.y() << std::endl; _win->resized(pixelOrigin.x(), pixelOrigin.y(), pixelSize.x(), pixelSize.y()); } } - (BOOL)createFramebuffer { _msaaFramebuffer = _msaaRenderBuffer = 0; glGenFramebuffersOES(1, &_viewFramebuffer); glGenRenderbuffersOES(1, &_viewRenderbuffer); // set the default id for osg to switch back after using fbos. _win->setDefaultFboId(_viewFramebuffer); glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); [_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer]; glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _viewRenderbuffer); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &_backingWidth); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &_backingHeight); osg::notify(osg::DEBUG_INFO) << "GraphicsWindowIOS::createFramebuffer INFO: Created GL RenderBuffer of size " << _backingWidth << ", " << _backingHeight << " ." << std::endl; #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000 //on ios 5 we have to use a packed depth stencil buffer if we want stencil if(_win->getTraits()->depth > 0) { //add stencil if requested if(_win->getTraits()->stencil > 0) { // Create a packed depth stencil buffer. glGenRenderbuffersOES(1, &_depthRenderbuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, _depthRenderbuffer); glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH24_STENCIL8_OES, _backingWidth, _backingHeight); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _depthRenderbuffer); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _depthRenderbuffer); }else{ //normal depth buffer glGenRenderbuffersOES(1, &_depthRenderbuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, _depthRenderbuffer); if(_win->getTraits()->depth == 16) { glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, _backingWidth, _backingHeight); }else if(_win->getTraits()->depth == 24){ glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT24_OES, _backingWidth, _backingHeight); } glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _depthRenderbuffer); } } #else //add depth if requested if(_win->getTraits()->depth > 0) { glGenRenderbuffersOES(1, &_depthRenderbuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, _depthRenderbuffer); if(_win->getTraits()->depth == 16) { glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, _backingWidth, _backingHeight); }else if(_win->getTraits()->depth == 24){ glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT24_OES, _backingWidth, _backingHeight); } #if defined(GL_DEPTH_COMPONENT32_OES) else if(_win->getTraits()->depth == 32){ glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT32_OES, _backingWidth, _backingHeight); } #endif glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _depthRenderbuffer); } //add stencil if requested if(_win->getTraits()->stencil > 0) { glGenRenderbuffersOES(1, &_stencilBuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, _stencilBuffer); glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_STENCIL_INDEX8_OES, _backingWidth, _backingHeight); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _stencilBuffer); } #endif //MSAA only available for >= 4.0 sdk #if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) if(_win->getTraits()->sampleBuffers > 0) { glGenFramebuffersOES(1, &_msaaFramebuffer); glGenRenderbuffersOES(1, &_msaaRenderBuffer); _win->setDefaultFboId(_msaaFramebuffer); glBindFramebufferOES(GL_FRAMEBUFFER_OES, _msaaFramebuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, _msaaRenderBuffer); // Samples is the amount of pixels the MSAA buffer uses to make one pixel on the render // buffer. Use a small number like 2 for the 3G and below and 4 or more for newer models glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, _win->getTraits()->samples, GL_RGB5_A1_OES, _backingWidth, _backingHeight); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _msaaRenderBuffer); glGenRenderbuffersOES(1, &_msaaDepthBuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, _msaaDepthBuffer); GLuint attachmentType = (_win->getTraits()->stencil > 0) ? GL_DEPTH24_STENCIL8_OES : ((_win->getTraits()->depth == 16) ? GL_DEPTH_COMPONENT16_OES : GL_DEPTH_COMPONENT24_OES); glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, _win->getTraits()->samples, attachmentType, _backingWidth , _backingHeight); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _msaaDepthBuffer); if (_win->getTraits()->stencil > 0) { glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _msaaDepthBuffer); } } #endif if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { OSG_FATAL << "GraphicsWindowIOS::createFramebuffer ERROR: Failed to create a GL RenderBuffer, glCheckFramebufferStatusOES returned '" << glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) << "'." << std::endl; return NO; } return YES; } - (void)destroyFramebuffer { if(_viewFramebuffer) { glDeleteFramebuffersOES(1, &_viewFramebuffer); _viewFramebuffer = 0; } if(_viewRenderbuffer) { glDeleteRenderbuffersOES(1, &_viewRenderbuffer); _viewRenderbuffer = 0; } if(_depthRenderbuffer) { glDeleteRenderbuffersOES(1, &_depthRenderbuffer); _depthRenderbuffer = 0; } if(_stencilBuffer) { glDeleteRenderbuffersOES(1, &_stencilBuffer); _stencilBuffer = 0; } if(_msaaRenderBuffer) { glDeleteRenderbuffersOES(1, &_msaaRenderBuffer); _msaaRenderBuffer = 0; } if(_msaaDepthBuffer) { glDeleteRenderbuffersOES(1, &_msaaDepthBuffer); _msaaDepthBuffer = 0; } if(_msaaFramebuffer) { glDeleteFramebuffersOES(1, &_msaaFramebuffer); _msaaFramebuffer = 0; } } // //Swap the view and render buffers // - (void)swapBuffers { #if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) if(_msaaFramebuffer) { glBindFramebufferOES(GL_FRAMEBUFFER_OES, _msaaFramebuffer); glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, _msaaFramebuffer); glBindFramebufferOES(GL_DRAW_FRAMEBUFFER_APPLE, _viewFramebuffer); glResolveMultisampleFramebufferAPPLE(); GLenum attachments[] = {GL_DEPTH_ATTACHMENT_OES, GL_COLOR_ATTACHMENT0_OES}; glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 2, attachments); } #endif //swap buffers (sort of i think?) glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); //display render in context [_context presentRenderbuffer:GL_RENDERBUFFER_OES]; //re bind the frame buffer for next frames renders glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer); #if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) if (_msaaFramebuffer) glBindFramebufferOES(GL_FRAMEBUFFER_OES, _msaaFramebuffer);; #endif } // //bind view buffer as current for new render pass // - (void)bindFrameBuffer { //bind the frame buffer glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer); #if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) if (_msaaFramebuffer) glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, _msaaFramebuffer); #endif } - (BOOL)acceptsFirstResponder { return YES; } - (BOOL)becomeFirstResponder { return YES; } - (BOOL)resignFirstResponder { return YES; } // //Touch input callbacks // - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSSet *allTouches = [event allTouches]; osg::ref_ptr osg_event(NULL); for(int i=0; i<[allTouches count]; i++) { UITouch *touch = [[allTouches allObjects] objectAtIndex:i]; CGPoint pos = [touch locationInView:self]; osg::Vec2 pixelPos = [self convertPointToPixel: osg::Vec2(pos.x,pos.y)]; unsigned int touch_id = [self computeTouchId: touch mayCleanup: FALSE]; if (!osg_event) { osg_event = _win->getEventQueue()->touchBegan(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); } else { osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); } } [super touchesBegan:touches withEvent:event]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { NSSet *allTouches = [event allTouches]; osg::ref_ptr osg_event(NULL); for(int i=0; i<[allTouches count]; i++) { UITouch *touch = [[allTouches allObjects] objectAtIndex:i]; CGPoint pos = [touch locationInView:self]; osg::Vec2 pixelPos = [self convertPointToPixel: osg::Vec2(pos.x,pos.y)]; unsigned int touch_id = [self computeTouchId: touch mayCleanup: FALSE]; if (!osg_event) { osg_event = _win->getEventQueue()->touchMoved(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); } else { osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); } } [super touchesMoved:touches withEvent:event]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { NSSet *allTouches = [event allTouches]; osg::ref_ptr osg_event(NULL); for(int i=0; i<[allTouches count]; i++) { UITouch *touch = [[allTouches allObjects] objectAtIndex:i]; CGPoint pos = [touch locationInView:self]; osg::Vec2 pixelPos = [self convertPointToPixel: osg::Vec2(pos.x,pos.y)]; unsigned int touch_id = [self computeTouchId: touch mayCleanup: TRUE]; if (!osg_event) { osg_event = _win->getEventQueue()->touchEnded(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y(), [touch tapCount]); } else { osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y(), [touch tapCount]); } } [super touchesEnded:touches withEvent:event]; } -(void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { [self touchesEnded: touches withEvent:event]; } @end @interface GraphicsWindowIOSGLViewController : UIViewController { } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation; - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration; @end @implementation GraphicsWindowIOSGLViewController - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { osgViewer::GraphicsWindowIOS* win = [(GraphicsWindowIOSGLView*)(self.view) getGraphicsWindow]; if(!win){return NO;} osgViewer::GraphicsWindowIOS::WindowData::DeviceOrientationFlags flags = win->getDeviceOrientationFlags(); BOOL result(NO); switch (interfaceOrientation) { case UIDeviceOrientationPortrait: if(flags & osgViewer::GraphicsWindowIOS::WindowData::PORTRAIT_ORIENTATION){ result = YES; } break; case UIDeviceOrientationPortraitUpsideDown: if(flags & osgViewer::GraphicsWindowIOS::WindowData::PORTRAIT_UPSIDEDOWN_ORIENTATION){ result = YES; } break; case UIInterfaceOrientationLandscapeLeft: if(win->getTraits()->supportsResize && flags & osgViewer::GraphicsWindowIOS::WindowData::LANDSCAPE_LEFT_ORIENTATION){ result = YES; } break; case UIInterfaceOrientationLandscapeRight: if(win->getTraits()->supportsResize && flags & osgViewer::GraphicsWindowIOS::WindowData::LANDSCAPE_RIGHT_ORIENTATION){ result = YES; } break; default: break; } OSG_INFO << "shouldAutorotateToInterfaceOrientation for " << interfaceOrientation << ": " << ((result==YES) ? "YES" : "NO") << std::endl; return result; } - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration { [(GraphicsWindowIOSGLView*)(self.view) updateDimensions]; } @end using namespace osgIOS; namespace osgViewer { #pragma mark GraphicsWindowIOS // ---------------------------------------------------------------------------------------------------------- // init // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowIOS::init() { if (_initialized) return; _ownsWindow = false; _context = NULL; _window = NULL; _view = NULL; _viewController = NULL; _updateContext = true; //if -1.0 we use the screens scale factor _viewContentScaleFactor = -1.0f; _valid = _initialized = true; // make sure the event queue has the correct window rectangle size and input range getEventQueue()->syncWindowRectangleWithGraphcisContext(); } // ---------------------------------------------------------------------------------------------------------- // realizeImplementation, creates the window + context // ---------------------------------------------------------------------------------------------------------- bool GraphicsWindowIOS::realizeImplementation() { if (_realized) return true; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; BOOL bar_hidden = (_traits->windowDecoration) ? NO: YES; #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED #if __IPHONE_OS_VERSION_MIN_REQUIRED > 30100 [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden withAnimation:UIStatusBarAnimationNone]; #else [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden animated:NO]; #endif #endif //Get info about the requested screen IOSWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); osg::Vec2 screenSizePoints; osg::Vec2 screenSizePixels; float screenScaleFactor = 1.0f; UIScreen* screen = nil; osg::GraphicsContext::ScreenSettings screenSettings; if (wsi) { wsi->getScreenContentScaleFactor((*_traits), screenScaleFactor); wsi->getScreenSizeInPoints((*_traits), screenSizePoints); screenSizePixels = osg::Vec2(screenSettings.width, screenSettings.height); wsi->getScreenSettings((*_traits), screenSettings); screen = wsi->getUIScreen((*_traits)); }else{ OSG_FATAL << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create IOS windowing system, OSG will be unable to create a vaild gl context and will not be able to render." << std::endl; return false; } _ownsWindow = true; // see if an existing inherited window was passed in WindowData* windowData = _traits->inheritedWindowData ? dynamic_cast(_traits->inheritedWindowData.get()) : NULL; if (windowData) { if (windowData->getWindowOrParentView()) { _ownsWindow = false; _window = windowData->getWindowOrParentView(); } _deviceOrientationFlags = windowData->_deviceOrientationFlags; _viewContentScaleFactor = windowData->_viewContentScaleFactor; } //if the user hasn't specified a viewScaleFactor we will use the screens scale factor //so we get a full res buffer if(_viewContentScaleFactor < 0.0f) {_viewContentScaleFactor = screenScaleFactor;} OSG_DEBUG << "GraphicsWindowIOS::realizeImplementation / ownsWindow: " << _ownsWindow << std::endl; //Here's the confusing bit, the default traits use the screen res which is in pixels and the user will want to use pixels also //but we need to create our views and windows in points. By default we create a full res buffer across all devices. This //means that for backward compatibility you need to set the windowData _viewContentScaleFactor to 1.0f and set the screen res to the //res of the older gen device. CGRect window_bounds; osg::Vec2 pointsOrigin = this->pixelToPoint(osg::Vec2(_traits->x, _traits->y)); osg::Vec2 pointsSize = this->pixelToPoint(osg::Vec2(_traits->width, _traits->height)); window_bounds.origin.x = pointsOrigin.x(); window_bounds.origin.y = pointsOrigin.y(); window_bounds.size.width = pointsSize.x(); window_bounds.size.height = pointsSize.y(); //if we own the window we need to create one if (_ownsWindow) { //create the IOS window object using the viewbounds (in points) required for our context size _window = [[GraphicsWindowIOSWindow alloc] initWithFrame: window_bounds];// styleMask: style backing: NSBackingStoreBuffered defer: NO]; if (!_window) { OSG_WARN << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create GraphicsWindowIOSWindow can not display gl view" << std::endl; return false; } OSG_DEBUG << "GraphicsWindowIOS::realizeImplementation: INFO: Created UIWindow with bounds '" << window_bounds.size.width << ", " << window_bounds.size.height << "' (points)." << std::endl; //if the user has requested a differnet screenNum from default 0 get the UIScreen object and //apply to our window (this is for IPad external screens, I don't have one, so I've no idea if it works) //I'm also not sure if we should apply this to external windows also? if(_traits->screenNum > 0 && screen != nil) { _window.screen = screen; } } //create the desired OpenGLES context type #if OSG_GLES1_FEATURES _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; #elif OSG_GLES2_FEATURES _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; #endif if (!_context || ![EAGLContext setCurrentContext:_context]) { #if OSG_GLES1_FEATURES OSG_FATAL << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create a valid OpenGLES1 context" << std::endl; #elif OSG_GLES2_FEATURES OSG_FATAL << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create a valid OpenGLES2 context" << std::endl; #endif return false; } //create the view to display our context in our window CGRect gl_view_bounds = (_ownsWindow) ? [_window frame] : window_bounds; GraphicsWindowIOSGLView* theView = [[ GraphicsWindowIOSGLView alloc ] initWithFrame: gl_view_bounds : this ]; if(!theView) { OSG_FATAL << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create GraphicsWindowIOSGLView, can not create frame buffers." << std::endl; return false; } [theView setAutoresizingMask: ( UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight) ]; //Apply our content scale factor to our view, this is what converts the views points //size to our desired context size. #if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) theView.contentScaleFactor = _viewContentScaleFactor; #endif [theView setGraphicsWindow: this]; [theView setOpenGLContext:_context]; _view = theView; OSG_DEBUG << "GraphicsWindowIOS::realizeImplementation / view: " << theView << std::endl; if (getDeviceOrientationFlags() != WindowData::IGNORE_ORIENTATION) { _viewController = [[GraphicsWindowIOSGLViewController alloc] init]; _viewController.view = _view; } // Attach view to window [_window addSubview: _view]; if ([_window isKindOfClass:[UIWindow class]]) _window.rootViewController = _viewController; [theView release]; //if we own the window also make it visible if (_ownsWindow) { //show window [_window makeKeyAndVisible]; } [pool release]; // IOSs origin is top/left: getEventQueue()->getCurrentEventState()->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS); // make sure the event queue has the correct window rectangle size and input range getEventQueue()->syncWindowRectangleWithGraphcisContext(); _valid = _initialized = _realized = true; return _valid; } // ---------------------------------------------------------------------------------------------------------- // closeImplementation // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowIOS::closeImplementation() { OSG_INFO << "close IOS window" << std::endl; _valid = false; _realized = false; if (_view) { [_view setOpenGLContext: NULL]; [_context release]; [_view removeFromSuperview]; [_view setGraphicsWindow: NULL]; } if (_viewController) { [_viewController release]; _viewController = NULL; } if (_window && _ownsWindow) { [_window release]; //[glView release]; } _window = NULL; _view = NULL; _context = NULL; } // ---------------------------------------------------------------------------------------------------------- // makeCurrentImplementation // ---------------------------------------------------------------------------------------------------------- bool GraphicsWindowIOS:: makeCurrentImplementation() { //bind the context [EAGLContext setCurrentContext:_context]; if (_updateContext) { [_view destroyFramebuffer]; [_view createFramebuffer]; _updateContext = false; } //i think we also want to bind the frame buffer here //[_view bindFrameBuffer]; return true; } // ---------------------------------------------------------------------------------------------------------- // releaseContextImplementation // ---------------------------------------------------------------------------------------------------------- bool GraphicsWindowIOS::releaseContextImplementation() { if ([EAGLContext currentContext] == _context) { [EAGLContext setCurrentContext:nil]; } return true; } // ---------------------------------------------------------------------------------------------------------- // swapBuffersImplementation // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowIOS::swapBuffersImplementation() { //[_context flushBuffer]; [_view swapBuffers]; } // ---------------------------------------------------------------------------------------------------------- // setWindowDecorationImplementation // // We will use this to toggle the status bar on IPhone, nearest thing to window decoration // ---------------------------------------------------------------------------------------------------------- bool GraphicsWindowIOS::setWindowDecorationImplementation(bool flag) { if (!_realized || !_ownsWindow) return false; BOOL bar_hidden = (flag) ? NO: YES; #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED #if __IPHONE_OS_VERSION_MIN_REQUIRED > 30100 [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden withAnimation:UIStatusBarAnimationNone]; #else [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden animated:NO]; #endif #endif return true; } // ---------------------------------------------------------------------------------------------------------- // grabFocus // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowIOS::grabFocus() { //i think make key is the equivalent of focus on iphone [_window makeKeyWindow]; } // ---------------------------------------------------------------------------------------------------------- // grabFocusIfPointerInWindow // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowIOS::grabFocusIfPointerInWindow() { OSG_INFO << "GraphicsWindowIOS :: grabFocusIfPointerInWindow not implemented yet " << std::endl; } // ---------------------------------------------------------------------------------------------------------- // raiseWindow // Raise the window to the top. // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowIOS::raiseWindow() { [_window bringSubviewToFront:_view]; } // ---------------------------------------------------------------------------------------------------------- // resizedImplementation // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowIOS::resizedImplementation(int x, int y, int width, int height) { GraphicsContext::resizedImplementation(x, y, width, height); _updateContext = true; getEventQueue()->windowResize(x,y,width, height, getEventQueue()->getTime()); } // ---------------------------------------------------------------------------------------------------------- // setWindowRectangleImplementation // ---------------------------------------------------------------------------------------------------------- bool GraphicsWindowIOS::setWindowRectangleImplementation(int x, int y, int width, int height) { OSG_INFO << "GraphicsWindowIOS :: setWindowRectangleImplementation not implemented yet " << std::endl; if (!_ownsWindow) return false; return true; } bool GraphicsWindowIOS::checkEvents() { return !(getEventQueue()->empty()); } // ---------------------------------------------------------------------------------------------------------- // setWindowName // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowIOS::setWindowName (const std::string & name) { OSG_INFO << "GraphicsWindowIOS :: setWindowName not implemented yet " << std::endl; } // ---------------------------------------------------------------------------------------------------------- // useCursor, no cursor on IOS // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowIOS::useCursor(bool cursorOn) { OSG_INFO << "GraphicsWindowIOS :: useCursor not implemented yet " << std::endl; } // ---------------------------------------------------------------------------------------------------------- // setCursor, no cursor on IOS // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowIOS::setCursor(MouseCursor mouseCursor) { OSG_INFO << "GraphicsWindowIOS :: setCursor not implemented yet " << std::endl; } // ---------------------------------------------------------------------------------------------------------- // setVSync, no vsync on IOS // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowIOS::setVSync(bool f) { OSG_INFO << "GraphicsWindowIOS :: setVSync not implemented yet " << std::endl; } // ---------------------------------------------------------------------------------------------------------- // helper funcs for converting points to pixels taking into account the views contents scale factor // ---------------------------------------------------------------------------------------------------------- osg::Vec2 GraphicsWindowIOS::pointToPixel(const osg::Vec2& point) { return point * _viewContentScaleFactor; } osg::Vec2 GraphicsWindowIOS::pixelToPoint(const osg::Vec2& pixel) { float scaler = 1.0f / _viewContentScaleFactor; return pixel * scaler; } // ---------------------------------------------------------------------------------------------------------- // d'tor // ---------------------------------------------------------------------------------------------------------- GraphicsWindowIOS::~GraphicsWindowIOS() { close(); } class ConcreteIOSWindowingSystemInterface : public IOSWindowingSystemInterface { public: ConcreteIOSWindowingSystemInterface() : IOSWindowingSystemInterface() { } virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits) { if (traits->pbuffer) { // pbuffers not supported on iOS return 0; } else { osg::ref_ptr window = new GraphicsWindowIOS(traits); if (window->valid()) return window.release(); else return 0; } } }; }//end namspace RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy; // declare C entry point for static compilation. extern "C" void graphicswindow_IOS(void) { osg::GraphicsContext::setWindowingSystemInterface(new osgViewer::ConcreteIOSWindowingSystemInterface()); } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/ViewerEventHandlers.cpp0000644000175000017500000007335312243630610026424 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace osgViewer { /* ** WindowSizeHandler */ WindowSizeHandler::WindowSizeHandler() : _keyEventToggleFullscreen('f'), _toggleFullscreen(true), _keyEventWindowedResolutionUp('>'), _keyEventWindowedResolutionDown('<'), _changeWindowedResolution(true), _currentResolutionIndex(-1) { _resolutionList.push_back(osg::Vec2(640, 480)); _resolutionList.push_back(osg::Vec2(800, 600)); _resolutionList.push_back(osg::Vec2(1024, 768)); _resolutionList.push_back(osg::Vec2(1152, 864)); _resolutionList.push_back(osg::Vec2(1280, 720)); _resolutionList.push_back(osg::Vec2(1280, 768)); _resolutionList.push_back(osg::Vec2(1280, 1024)); _resolutionList.push_back(osg::Vec2(1440, 900)); _resolutionList.push_back(osg::Vec2(1400, 1050)); _resolutionList.push_back(osg::Vec2(1600, 900)); _resolutionList.push_back(osg::Vec2(1600, 1024)); _resolutionList.push_back(osg::Vec2(1600, 1200)); _resolutionList.push_back(osg::Vec2(1680, 1050)); _resolutionList.push_back(osg::Vec2(1920, 1080)); _resolutionList.push_back(osg::Vec2(1920, 1200)); _resolutionList.push_back(osg::Vec2(2048, 1536)); _resolutionList.push_back(osg::Vec2(2560, 2048)); _resolutionList.push_back(osg::Vec2(3200, 2400)); _resolutionList.push_back(osg::Vec2(3840, 2400)); } void WindowSizeHandler::getUsage(osg::ApplicationUsage &usage) const { usage.addKeyboardMouseBinding(_keyEventToggleFullscreen, "Toggle full screen."); usage.addKeyboardMouseBinding(_keyEventWindowedResolutionUp, "Increase the screen resolution (in windowed mode)."); usage.addKeyboardMouseBinding(_keyEventWindowedResolutionDown, "Decrease the screen resolution (in windowed mode)."); } bool WindowSizeHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa) { osgViewer::View* view = dynamic_cast(&aa); if (!view) return false; osgViewer::ViewerBase* viewer = view->getViewerBase(); if (viewer == NULL) { return false; } if (ea.getHandled()) return false; switch(ea.getEventType()) { case(osgGA::GUIEventAdapter::KEYUP): { if (_toggleFullscreen == true && ea.getKey() == _keyEventToggleFullscreen) { // sleep to allow any viewer rendering threads to complete before we // resize the window OpenThreads::Thread::microSleep(100000); osgViewer::Viewer::Windows windows; viewer->getWindows(windows); for(osgViewer::Viewer::Windows::iterator itr = windows.begin(); itr != windows.end(); ++itr) { toggleFullscreen(*itr); } aa.requestRedraw(); return true; } else if (_changeWindowedResolution == true && ea.getKey() == _keyEventWindowedResolutionUp) { // sleep to allow any viewer rendering threads to complete before we // resize the window OpenThreads::Thread::microSleep(100000); // Increase resolution osgViewer::Viewer::Windows windows; viewer->getWindows(windows); for(osgViewer::Viewer::Windows::iterator itr = windows.begin(); itr != windows.end(); ++itr) { changeWindowedResolution(*itr, true); } aa.requestRedraw(); return true; } else if (_changeWindowedResolution == true && ea.getKey() == _keyEventWindowedResolutionDown) { // sleep to allow any viewer rendering threads to complete before we // resize the window OpenThreads::Thread::microSleep(100000); // Decrease resolution osgViewer::Viewer::Windows windows; viewer->getWindows(windows); for(osgViewer::Viewer::Windows::iterator itr = windows.begin(); itr != windows.end(); ++itr) { changeWindowedResolution(*itr, false); } aa.requestRedraw(); return true; } break; } default: break; } return false; } void WindowSizeHandler::toggleFullscreen(osgViewer::GraphicsWindow *window) { osg::GraphicsContext::WindowingSystemInterface *wsi = osg::GraphicsContext::getWindowingSystemInterface(); if (wsi == NULL) { OSG_NOTICE << "Error, no WindowSystemInterface available, cannot toggle window fullscreen." << std::endl; return; } unsigned int screenWidth; unsigned int screenHeight; wsi->getScreenResolution(*(window->getTraits()), screenWidth, screenHeight); int x; int y; int width; int height; window->getWindowRectangle(x, y, width, height); bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight; if (isFullScreen) { osg::Vec2 resolution; if (_currentResolutionIndex == -1) { _currentResolutionIndex = getNearestResolution(screenWidth, screenHeight, screenWidth / 2, screenHeight / 2); } resolution = _resolutionList[_currentResolutionIndex]; window->setWindowDecoration(true); window->setWindowRectangle((screenWidth - (int)resolution.x()) / 2, (screenHeight - (int)resolution.y()) / 2, (int)resolution.x(), (int)resolution.y()); OSG_INFO << "Screen resolution = " << (int)resolution.x() << "x" << (int)resolution.y() << std::endl; } else { window->setWindowDecoration(false); window->setWindowRectangle(0, 0, screenWidth, screenHeight); } window->grabFocusIfPointerInWindow(); } void WindowSizeHandler::changeWindowedResolution(osgViewer::GraphicsWindow *window, bool increase) { osg::GraphicsContext::WindowingSystemInterface *wsi = osg::GraphicsContext::getWindowingSystemInterface(); if (wsi == NULL) { OSG_NOTICE << "Error, no WindowSystemInterface available, cannot toggle window fullscreen." << std::endl; return; } unsigned int screenWidth; unsigned int screenHeight; wsi->getScreenResolution(*(window->getTraits()), screenWidth, screenHeight); int x; int y; int width; int height; window->getWindowRectangle(x, y, width, height); bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight; if (window->getWindowDecoration() == true || isFullScreen == false) { osg::Vec2 resolution; if (_currentResolutionIndex == -1) { _currentResolutionIndex = getNearestResolution(screenWidth, screenHeight, width, height); } if (increase == true) { // Find the next resolution for (int i = _currentResolutionIndex + 1; i < (int)_resolutionList.size(); ++i) { if ((unsigned int)_resolutionList[i].x() <= screenWidth && (unsigned int)_resolutionList[i].y() <= screenHeight) { _currentResolutionIndex = i; break; } } } else { // Find the previous resolution for (int i = _currentResolutionIndex - 1; i >= 0; --i) { if ((unsigned int)_resolutionList[i].x() <= screenWidth && (unsigned int)_resolutionList[i].y() <= screenHeight) { _currentResolutionIndex = i; break; } } } resolution = _resolutionList[_currentResolutionIndex]; window->setWindowDecoration(true); window->setWindowRectangle((screenWidth - (int)resolution.x()) / 2, (screenHeight - (int)resolution.y()) / 2, (int)resolution.x(), (int)resolution.y()); OSG_INFO << "Screen resolution = " << (int)resolution.x() << "x" << (int)resolution.y() << std::endl; window->grabFocusIfPointerInWindow(); } } unsigned int WindowSizeHandler::getNearestResolution(int screenWidth, int screenHeight, int width, int height) const { unsigned int position = 0; unsigned int result = 0; int delta = INT_MAX; for (std::vector::const_iterator it = _resolutionList.begin(); it != _resolutionList.end(); ++it, ++position) { if ((int)it->x() <= screenWidth && (int)it->y() <= screenHeight) { int tmp = static_cast(osg::absolute((width * height) - (it->x() * it->y()))); if (tmp < delta) { delta = tmp; result = position; } } } return (result); } /* ** ThreadingHandler */ ThreadingHandler::ThreadingHandler() : _keyEventChangeThreadingModel('m'), _changeThreadingModel(true), _keyEventChangeEndBarrierPosition('e'), _changeEndBarrierPosition(true) { _tickOrLastKeyPress = osg::Timer::instance()->tick(); } void ThreadingHandler::getUsage(osg::ApplicationUsage &usage) const { usage.addKeyboardMouseBinding(_keyEventChangeThreadingModel, "Toggle threading model."); usage.addKeyboardMouseBinding(_keyEventChangeEndBarrierPosition, "Toggle the placement of the end of frame barrier."); } bool ThreadingHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa) { osgViewer::View* view = dynamic_cast(&aa); if (!view) return false; osgViewer::ViewerBase* viewerBase = view->getViewerBase(); osgViewer::Viewer* viewer = dynamic_cast(viewerBase); if (viewerBase == NULL) { return false; } if (ea.getHandled()) return false; switch(ea.getEventType()) { case(osgGA::GUIEventAdapter::KEYUP): { double delta = osg::Timer::instance()->delta_s(_tickOrLastKeyPress, osg::Timer::instance()->tick()); if (_changeThreadingModel == true && ea.getKey() == _keyEventChangeThreadingModel && delta > 1.0) { _tickOrLastKeyPress = osg::Timer::instance()->tick(); switch(viewerBase->getThreadingModel()) { case(osgViewer::ViewerBase::SingleThreaded): viewerBase->setThreadingModel(osgViewer::ViewerBase::CullDrawThreadPerContext); OSG_NOTICE<<"Threading model 'CullDrawThreadPerContext' selected."<setThreadingModel(osgViewer::ViewerBase::DrawThreadPerContext); OSG_NOTICE<<"Threading model 'DrawThreadPerContext' selected."<setThreadingModel(osgViewer::ViewerBase::CullThreadPerCameraDrawThreadPerContext); OSG_NOTICE<<"Threading model 'CullThreadPerCameraDrawThreadPerContext' selected."<setThreadingModel(osgViewer::ViewerBase::SingleThreaded); OSG_NOTICE<<"Threading model 'SingleThreaded' selected."<setThreadingModel(osgViewer::ViewerBase::SingleThreaded); OSG_NOTICE<<"Threading model 'SingleThreaded' selected."<setThreadingModel(viewer->suggestBestThreadingModel()); OSG_NOTICE<<"Threading model 'AutomaticSelection' selected."<getEndBarrierPosition()) { case(osgViewer::Viewer::BeforeSwapBuffers): viewer->setEndBarrierPosition(osgViewer::Viewer::AfterSwapBuffers); OSG_NOTICE<<"Threading end of frame barrier position 'AfterSwapBuffers' selected."<setEndBarrierPosition(osgViewer::Viewer::BeforeSwapBuffers); OSG_NOTICE<<"Threading end of frame barrier position 'BeforeSwapBuffers' selected."<tick()) { const char* str = getenv("OSG_RECORD_CAMERA_PATH_FPS"); if (str) { _interval = 1.0f / osg::asciiToDouble(str); } else { _interval = 1.0f / fps; } } void RecordCameraPathHandler::getUsage(osg::ApplicationUsage &usage) const { usage.addKeyboardMouseBinding(_keyEventToggleRecord, "Toggle camera path recording."); usage.addKeyboardMouseBinding(_keyEventTogglePlayback, "Toggle camera path playback."); } bool RecordCameraPathHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa) { osgViewer::View* view = dynamic_cast(&aa); if (view == NULL) { return false; } if(ea.getEventType()==osgGA::GUIEventAdapter::FRAME) { // Calculate our current delta (difference) in time between the last frame and // current frame, regardless of whether we actually store a ControlPoint... osg::Timer_t time = osg::Timer::instance()->tick(); double delta = osg::Timer::instance()->delta_s(_lastFrameTime, time); _lastFrameTime = time; // If our internal _delta is finally large enough to warrant a ControlPoint // insertion, do so now. Be sure and reset the internal _delta, so we can start // calculating when the next insert should happen. if (_animPath.valid() && _currentlyRecording && _delta >= _interval) { const osg::Matrixd& m = view->getCamera()->getInverseViewMatrix(); double animationPathTime = osg::Timer::instance()->delta_s(_animStartTime, time); _animPath->insert(animationPathTime, osg::AnimationPath::ControlPoint(m.getTrans(), m.getRotate())); _delta = 0.0f; if (_fout) { _animPath->write(_animPath->getTimeControlPointMap().find(animationPathTime), _fout); _fout.flush(); } } else _delta += delta; return true; } if (ea.getHandled()) return false; switch(ea.getEventType()) { case(osgGA::GUIEventAdapter::KEYUP): { // The user has requested to toggle recording. if (ea.getKey() ==_keyEventToggleRecord) { // The user has requested to BEGIN recording. if (!_currentlyRecording) { _currentlyRecording = true; _animStartTime = osg::Timer::instance()->tick(); _animPath = new osg::AnimationPath(); if (!_filename.empty()) { std::stringstream ss; ss << osgDB::getNameLessExtension(_filename); if ( _autoinc != -1 ) { ss << "_"<empty()) { // In the future this will need to be written continuously, rather // than all at once. osgDB::ofstream out(_filename.c_str()); OSG_NOTICE<<"Writing camera file: "<<_filename<write(out); out.close(); } else { OSG_NOTICE<<"No animation path to write out."<empty()) { _animPathManipulator = new osgGA::AnimationPathManipulator(_animPath.get()); _animPathManipulator->home(ea,aa); // If we successfully found our _filename file, set it and keep a copy // around of the original CameraManipulator to restore later. if (_animPathManipulator.valid() && _animPathManipulator->valid()) { _oldManipulator = view->getCameraManipulator(); view->setCameraManipulator(_animPathManipulator.get()); _currentlyPlaying = true; } } } // The user has requested to STOP playback. else { // Restore the old manipulator if necessary and stop playback. if(_oldManipulator.valid()) view->setCameraManipulator(_oldManipulator.get()); _currentlyPlaying = false; _oldManipulator = 0; } return true; } break; } default: break; } return false; } LODScaleHandler::LODScaleHandler(): _keyEventIncreaseLODScale('*'), _keyEventDecreaseLODScale('/') { } bool LODScaleHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { osgViewer::View* view = dynamic_cast(&aa); osg::Camera* camera = view ? view->getCamera() : 0; if (!camera) return false; if (ea.getHandled()) return false; switch(ea.getEventType()) { case(osgGA::GUIEventAdapter::KEYUP): { if (ea.getKey() == _keyEventIncreaseLODScale) { camera->setLODScale(camera->getLODScale()*1.1); OSG_NOTICE<<"LODScale = "<getLODScale()<setLODScale(camera->getLODScale()/1.1); OSG_NOTICE<<"LODScale = "<getLODScale()<(&aa); if (!view) return false; osgViewer::ViewerBase* viewer = view->getViewerBase(); if (viewer == NULL) { return false; } if (ea.getHandled()) return false; switch(ea.getEventType()) { case(osgGA::GUIEventAdapter::KEYUP): { if (ea.getKey() == _keyEventToggleSyncToVBlank) { // Increase resolution osgViewer::Viewer::Windows windows; viewer->getWindows(windows); for(osgViewer::Viewer::Windows::iterator itr = windows.begin(); itr != windows.end(); ++itr) { (*itr)->setSyncToVBlank( !(*itr)->getSyncToVBlank() ); } aa.requestRedraw(); return true; } break; } default: break; } return false; } void ToggleSyncToVBlankHandler::getUsage(osg::ApplicationUsage& usage) const { usage.addKeyboardMouseBinding(_keyEventToggleSyncToVBlank,"Toggle SyncToVBlank."); } InteractiveImageHandler::InteractiveImageHandler(osg::Image* image) : _image(image), _texture(0), _fullscreen(false), _camera(0) { } InteractiveImageHandler::InteractiveImageHandler(osg::Image* image, osg::Texture2D* texture, osg::Camera* camera) : _image(image), _texture(texture), _fullscreen(true), _camera(camera) { if (_camera.valid() && _camera->getViewport()) { // Send an initial resize event (with the same size) so the image can // resize itself initially. double width = _camera->getViewport()->width(); double height = _camera->getViewport()->height(); resize(static_cast(width), static_cast(height)); } } bool InteractiveImageHandler::mousePosition(osgViewer::View* view, osg::NodeVisitor* nv, const osgGA::GUIEventAdapter& ea, int& x, int &y) const { if (!view) return false; osgUtil::LineSegmentIntersector::Intersections intersections; bool foundIntersection = (nv==0) ? view->computeIntersections(ea, intersections) : view->computeIntersections(ea, nv->getNodePath(), intersections); if (foundIntersection) { osg::Vec2 tc(0.5f,0.5f); // use the nearest intersection const osgUtil::LineSegmentIntersector::Intersection& intersection = *(intersections.begin()); osg::Drawable* drawable = intersection.drawable.get(); osg::Geometry* geometry = drawable ? drawable->asGeometry() : 0; osg::Vec3Array* vertices = geometry ? dynamic_cast(geometry->getVertexArray()) : 0; if (vertices) { // get the vertex indices. const osgUtil::LineSegmentIntersector::Intersection::IndexList& indices = intersection.indexList; const osgUtil::LineSegmentIntersector::Intersection::RatioList& ratios = intersection.ratioList; if (indices.size()==3 && ratios.size()==3) { unsigned int i1 = indices[0]; unsigned int i2 = indices[1]; unsigned int i3 = indices[2]; float r1 = ratios[0]; float r2 = ratios[1]; float r3 = ratios[2]; osg::Array* texcoords = (geometry->getNumTexCoordArrays()>0) ? geometry->getTexCoordArray(0) : 0; osg::Vec2Array* texcoords_Vec2Array = dynamic_cast(texcoords); if (texcoords_Vec2Array) { // we have tex coord array so now we can compute the final tex coord at the point of intersection. osg::Vec2 tc1 = (*texcoords_Vec2Array)[i1]; osg::Vec2 tc2 = (*texcoords_Vec2Array)[i2]; osg::Vec2 tc3 = (*texcoords_Vec2Array)[i3]; tc = tc1*r1 + tc2*r2 + tc3*r3; } } osg::TexMat* activeTexMat = 0; osg::Texture* activeTexture = 0; if (drawable->getStateSet()) { osg::TexMat* texMat = dynamic_cast(drawable->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXMAT)); if (texMat) activeTexMat = texMat; osg::Texture* texture = dynamic_cast(drawable->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXTURE)); if (texture) activeTexture = texture; } if (activeTexMat) { osg::Vec4 tc_transformed = osg::Vec4(tc.x(), tc.y(), 0.0f,0.0f) * activeTexMat->getMatrix(); tc.x() = tc_transformed.x(); tc.y() = tc_transformed.y(); } if (dynamic_cast(activeTexture)) { x = int( tc.x() ); y = int( tc.y() ); } else if (_image.valid()) { x = int( float(_image->s()) * tc.x() ); y = int( float(_image->t()) * tc.y() ); } return true; } } return false; } bool InteractiveImageHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv) { if (ea.getHandled()) return false; if (!_image) return false; switch(ea.getEventType()) { case(osgGA::GUIEventAdapter::MOVE): case(osgGA::GUIEventAdapter::DRAG): case(osgGA::GUIEventAdapter::PUSH): case(osgGA::GUIEventAdapter::RELEASE): { osgViewer::View* view = dynamic_cast(&aa); int x,y; if (mousePosition(view, nv, ea, x, y)) { return _image->sendPointerEvent(x, y, ea.getButtonMask()); } break; } case(osgGA::GUIEventAdapter::KEYDOWN): case(osgGA::GUIEventAdapter::KEYUP): { osgViewer::View* view = dynamic_cast(&aa); int x,y; bool sendKeyEvent = mousePosition(view, nv, ea, x, y); if (sendKeyEvent) { return _image->sendKeyEvent(ea.getKey(), ea.getEventType()==osgGA::GUIEventAdapter::KEYDOWN); } break; } case (osgGA::GUIEventAdapter::RESIZE): { if (_fullscreen && _camera.valid()) { _camera->setViewport(0, 0, ea.getWindowWidth(), ea.getWindowHeight()); resize(ea.getWindowWidth(), ea.getWindowHeight()); return true; } break; } default: return false; } return false; } bool InteractiveImageHandler::cull(osg::NodeVisitor* nv, osg::Drawable*, osg::RenderInfo*) const { if (_image.valid()) { _image->setFrameLastRendered(nv->getFrameStamp()); } return false; } void InteractiveImageHandler::resize(int width, int height) { if (_image.valid()) { _image->scaleImage(width, height, 1); } // Make sure the texture does not rescale the image because // it thinks it should still be the previous size... if (_texture.valid()) _texture->setTextureSize(width, height); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/CMakeLists.txt0000644000175000017500000002447712172157412024544 0ustar albertoalberto# FIXME: For OS X, need flag for Framework or dylib IF(DYNAMIC_OPENSCENEGRAPH) ADD_DEFINITIONS(-DOSGVIEWER_LIBRARY) ELSE() ADD_DEFINITIONS(-DOSG_LIBRARY_STATIC) ENDIF() SET(LIB_NAME osgViewer) SET(HEADER_PATH ${OpenSceneGraph_SOURCE_DIR}/include/${LIB_NAME}) SET(TARGET_H ${HEADER_PATH}/CompositeViewer ${HEADER_PATH}/Export ${HEADER_PATH}/GraphicsWindow ${HEADER_PATH}/Keystone ${HEADER_PATH}/Renderer ${HEADER_PATH}/Scene ${HEADER_PATH}/Version ${HEADER_PATH}/View ${HEADER_PATH}/Viewer ${HEADER_PATH}/ViewerBase ${HEADER_PATH}/ViewerEventHandlers ) FILE(GLOB LIB_COMMON_FILES config/*.cpp) SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} CompositeViewer.cpp GraphicsWindow.cpp HelpHandler.cpp Keystone.cpp Renderer.cpp Scene.cpp ScreenCaptureHandler.cpp StatsHandler.cpp Version.cpp View.cpp Viewer.cpp ViewerBase.cpp ViewerEventHandlers.cpp ${OPENSCENEGRAPH_VERSIONINFO_RC} ) # Collect all the configuration files SET(LIB_EXTRA_LIBS) IF(WIN32 AND NOT ANDROID) # # Enable workaround for OpenGL driver issues when used in multithreaded/multiscreen with NVidia drivers on Windows XP # For example: osgviewer dumptruck.osg was showing total garbage (screen looked like shattered, splashed hedgehog) # There were also serious issues with render to texture cameras. # Workaround repeats makeCurrentContext call as it was found that this causes the problems to dissapear. # OPTION(OSG_MULTIMONITOR_MULTITHREAD_WIN32_NVIDIA_WORKAROUND "Set to ON if you have NVidia board and drivers earlier than 177.92 ver" OFF) MARK_AS_ADVANCED(OSG_MULTIMONITOR_MULTITHREAD_WIN32_NVIDIA_WORKAROUND) IF(OSG_MULTIMONITOR_MULTITHREAD_WIN32_NVIDIA_WORKAROUND) ADD_DEFINITIONS(-DOSG_MULTIMONITOR_MULTITHREAD_WIN32_NVIDIA_WORKAROUND) ENDIF() SET(TARGET_H_NO_MODULE_INSTALL ${HEADER_PATH}/api/Win32/GraphicsHandleWin32 ${HEADER_PATH}/api/Win32/GraphicsWindowWin32 ${HEADER_PATH}/api/Win32/PixelBufferWin32 ) SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} GraphicsWindowWin32.cpp PixelBufferWin32.cpp ) ELSE() IF(APPLE AND NOT ANDROID) IF(OSG_BUILD_PLATFORM_IPHONE OR OSG_BUILD_PLATFORM_IPHONE_SIMULATOR) SET(OSG_WINDOWING_SYSTEM "IOS" CACHE STRING "Windowing system type for graphics window creation, options only IOS.") ELSE() IF(${OSG_OSX_SDK_NAME} STREQUAL "macosx10.4" OR ${OSG_OSX_SDK_NAME} STREQUAL "macosx10.3" OR ${OSG_OSX_SDK_NAME} STREQUAL "macosx10.2" OR ${OSG_OSX_SDK_NAME} STREQUAL "macosx10.1") SET(OSG_WINDOWING_SYSTEM "Carbon" CACHE STRING "Windowing system type for graphics window creation, options Carbon, Cocoa or X11.") ELSE() SET(OSG_WINDOWING_SYSTEM "Cocoa" CACHE STRING "Windowing system type for graphics window creation, options Carbon, Cocoa or X11.") ENDIF() ENDIF() ELSE() IF(ANDROID) SET(OSG_WINDOWING_SYSTEM "None" CACHE STRING "None Windowing system type for graphics window creation.") ELSE() SET(OSG_WINDOWING_SYSTEM "X11" CACHE STRING "Windowing system type for graphics window creation. options only X11") ENDIF() ENDIF() IF(${OSG_WINDOWING_SYSTEM} STREQUAL "Cocoa") ADD_DEFINITIONS(-DUSE_DARWIN_COCOA_IMPLEMENTATION) IF(OSG_COMPILE_FRAMEWORKS) SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} ${HEADER_PATH}/api/Cocoa/GraphicsHandleCocoa ${HEADER_PATH}/api/Cocoa/GraphicsWindowCocoa ${HEADER_PATH}/api/Cocoa/PixelBufferCocoa ) SET_PROPERTY(SOURCE ${HEADER_PATH}/api/Cocoa/GraphicsHandleCocoa PROPERTY MACOSX_PACKAGE_LOCATION Headers/api/Cocoa) SET_PROPERTY(SOURCE ${HEADER_PATH}/api/Cocoa/GraphicsWindowCocoa PROPERTY MACOSX_PACKAGE_LOCATION Headers/api/Cocoa) SET_PROPERTY(SOURCE ${HEADER_PATH}/api/Cocoa/PixelBufferCocoa PROPERTY MACOSX_PACKAGE_LOCATION Headers/api/Cocoa) ELSE() SET(TARGET_H_NO_MODULE_INSTALL ${HEADER_PATH}/api/Cocoa/GraphicsHandleCocoa ${HEADER_PATH}/api/Cocoa/GraphicsWindowCocoa ${HEADER_PATH}/api/Cocoa/PixelBufferCocoa ) ENDIF() SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} GraphicsWindowCocoa.mm DarwinUtils.h DarwinUtils.mm PixelBufferCocoa.mm ) SET(LIB_EXTRA_LIBS ${COCOA_LIBRARY} ${LIB_EXTRA_LIBS}) ELSEIF(${OSG_WINDOWING_SYSTEM} STREQUAL "Carbon") ADD_DEFINITIONS(-DUSE_DARWIN_CARBON_IMPLEMENTATION) IF(OSG_COMPILE_FRAMEWORKS) SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} ${HEADER_PATH}/api/Carbon/GraphicsHandleCarbon ${HEADER_PATH}/api/Carbon/GraphicsWindowCarbon ${HEADER_PATH}/api/Carbon/PixelBufferCarbon ) SET_PROPERTY(SOURCE ${HEADER_PATH}/api/Carbon/GraphicsHandleCarbon PROPERTY MACOSX_PACKAGE_LOCATION Headers/api/Carbon) SET_PROPERTY(SOURCE ${HEADER_PATH}/api/Carbon/GraphicsWindowCarbon PROPERTY MACOSX_PACKAGE_LOCATION Headers/api/Carbon) SET_PROPERTY(SOURCE ${HEADER_PATH}/api/Carbon/PixelBufferCarbon PROPERTY MACOSX_PACKAGE_LOCATION Headers/api/Carbon) ELSE() SET(TARGET_H_NO_MODULE_INSTALL ${HEADER_PATH}/api/Carbon/GraphicsHandleCarbon ${HEADER_PATH}/api/Carbon/GraphicsWindowCarbon ${HEADER_PATH}/api/Carbon/PixelBufferCarbon ) ENDIF() SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} GraphicsWindowCarbon.cpp DarwinUtils.h DarwinUtils.mm PixelBufferCarbon.cpp ) SET(LIB_EXTRA_LIBS ${COCOA_LIBRARY} ${AGL_LIBRARY} ${LIB_EXTRA_LIBS}) ELSEIF(${OSG_WINDOWING_SYSTEM} STREQUAL "IOS") ADD_DEFINITIONS(-DUSE_IOS_IMPLEMENTATION) IF(OSG_COMPILE_FRAMEWORKS) SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} ${HEADER_PATH}/api/IOS/GraphicsWindowIOS ) SET_PROPERTY(SOURCE ${HEADER_PATH}/api/IOS/GraphicsWindowIOS PROPERTY MACOSX_PACKAGE_LOCATION Headers/api/IOS) ELSE() SET(TARGET_H_NO_MODULE_INSTALL ${HEADER_PATH}/api/IOS/GraphicsWindowIOS #${HEADER_PATH}/api/IOS/PixelBufferIOS ) ENDIF() SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} GraphicsWindowIOS.mm IOSUtils.h IOSUtils.mm ) SET(LIB_EXTRA_LIBS ${COCOA_LIBRARY} ${LIB_EXTRA_LIBS}) ELSEIF(${OSG_WINDOWING_SYSTEM} STREQUAL "X11") # X11 for everybody else INCLUDE(FindPkgConfig OPTIONAL) IF(PKG_CONFIG_FOUND) PKG_CHECK_MODULES(XRANDR xrandr) IF(XRANDR_FOUND) OPTION(OSGVIEWER_USE_XRANDR "Set to ON to enable Xrandr support for GraphicsWindowX11." ON) ELSE() SET(OSGVIEWER_USE_XRANDR OFF) ENDIF() ELSE() SET(OSGVIEWER_USE_XRANDR OFF) ENDIF() SET(TARGET_H_NO_MODULE_INSTALL ${HEADER_PATH}/api/X11/GraphicsHandleX11 ${HEADER_PATH}/api/X11/GraphicsWindowX11 ${HEADER_PATH}/api/X11/PixelBufferX11 ) SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} GraphicsWindowX11.cpp PixelBufferX11.cpp ) IF(OSGVIEWER_USE_XRANDR) ADD_DEFINITIONS(-DOSGVIEWER_USE_XRANDR) SET(LIB_PRIVATE_HEADERS ${LIB_PRIVATE_HEADERS} ${XRANDR_INCLUDE_DIRS} ) IF(X11_Xrandr_LIB) SET(LIB_EXTRA_LIBS ${X11_Xrandr_LIB} ${LIB_EXTRA_LIBS}) ELSE() SET(LIB_EXTRA_LIBS ${XRANDR_LIBRARIES} ${LIB_EXTRA_LIBS}) ENDIF() ENDIF() # X11 on Apple requires X11 library plus OpenGL linking hack on Leopard IF(APPLE) # hack for finding the iphone opengl es lib IF(OSG_BUILD_PLATFORM_IPHONE OR OSG_BUILD_PLATFORM_IPHONE_SIMULATOR) SET(OPENGL_INCLUDE_DIR ${IPHONE_SDKROOT}System/Library/Frameworks) SET(OPENGL_LIBRARIES ${IPHONE_SDKROOT}System/Library/Frameworks/OpenGLES) ELSE() # Find GL/glx.h IF(EXISTS ${CMAKE_OSX_SYSROOT}/usr/X11/include/GL/glx.h) SET(OPENGL_INCLUDE_DIR /usr/X11/include) SET(OPENGL_LIBRARIES /usr/X11/lib/libGL.dylib) ELSEIF(EXISTS ${CMAKE_OSX_SYSROOT}/usr/X11R6/include/GL/glx.h) SET(OPENGL_INCLUDE_DIR /usr/X11R6/include) SET(OPENGL_LIBRARIES /usr/X11R6/lib/libGL.dylib) ENDIF() INCLUDE_DIRECTORIES(BEFORE SYSTEM ${OPENGL_INCLUDE_DIR}) SET(LIB_EXTRA_LIBS ${X11_X11_LIB} ${OPENGL_LIBRARIES} ${LIB_EXTRA_LIBS}) SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-dylib_file,/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:${CMAKE_OSX_SYSROOT}/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib") ENDIF() ELSE(APPLE) SET(LIB_EXTRA_LIBS ${X11_X11_LIB} ${LIB_EXTRA_LIBS}) ENDIF(APPLE) ELSE() MESSAGE(STATUS "Windowing system not supported") ENDIF() ENDIF() SET(TARGET_SRC ${LIB_PRIVATE_HEADERS} ${LIB_COMMON_FILES} ) SET(TARGET_LIBRARIES osgGA osgText osgDB osgUtil osg OpenThreads ) SET(TARGET_EXTERNAL_LIBRARIES ${LIB_EXTRA_LIBS}) IF(MINGW OR CYGWIN) SET(TARGET_EXTERNAL_LIBRARIES ${TARGET_EXTERNAL_LIBRARIES} gdi32 ) ENDIF() SETUP_LIBRARY(${LIB_NAME}) # install these headers manually since setup_library and moduleinstall # wouldn't keep the structure, e.g. api/X11/xyz.h FOREACH(HEADERFILE ${TARGET_H_NO_MODULE_INSTALL}) # get relative path to graphics system dependant header FILE(RELATIVE_PATH REL_INCLUDEFILE ${HEADER_PATH} ${HEADERFILE}) GET_FILENAME_COMPONENT(REL_INCLUDE_PATH ${REL_INCLUDEFILE} PATH) INSTALL(FILES ${HEADERFILE} DESTINATION ${INSTALL_INCDIR}/${LIB_NAME}/${REL_INCLUDE_PATH} COMPONENT libopenscenegraph-dev ) ENDFOREACH() # for structure in ide SOURCE_GROUP("${HEADERS_GROUP}\\api" FILES ${TARGET_H_NO_MODULE_INSTALL}) openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/GraphicsWindowCocoa.mm0000644000175000017500000016323312224507502026223 0ustar albertoalberto/* * GraphicsWindowCocoa.cpp * OpenSceneGraph * * Created by Stephan Huber on 27.06.08. * Copyright 2008 Stephan Maximilian Huber, digital mind. All rights reserved. * * Some code borrowed from the implementation of CocoaViewer, * Created by Eric Wing on 11/12/06. and ported by Martin Lavery 7/06/07 * * Other snippets are borrowed from the Cocoa-implementation of the SDL-lib */ #include #include #include #include #include "DarwinUtils.h" //#define DEBUG_OUT(s) std::cout << "GraphicsWindowCocoa :: " << s << std::endl; #define DEBUG_OUT(s) ; static bool s_quit_requested = false; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 @interface NSApplication(NSAppleMenu) - (void)setAppleMenu:(NSMenu *)menu; @end #endif // ---------------------------------------------------------------------------------------------------------- // small helper class remapping key-codes // ---------------------------------------------------------------------------------------------------------- // small helper class which maps the raw key codes to osgGA::GUIEventAdapter::Keys class CocoaKeyboardMap { public: CocoaKeyboardMap() { _keymap[27] = osgGA::GUIEventAdapter::KEY_Escape; _keymap[13] = osgGA::GUIEventAdapter::KEY_Return; _keymap[3] = osgGA::GUIEventAdapter::KEY_KP_Enter; _keymap[9] = osgGA::GUIEventAdapter::KEY_Tab; _keymap[32] = osgGA::GUIEventAdapter::KEY_Space; _keymap[127] = osgGA::GUIEventAdapter::KEY_BackSpace; _keymap[NSHomeFunctionKey] = osgGA::GUIEventAdapter::KEY_Home; _keymap[NSEndFunctionKey] = osgGA::GUIEventAdapter::KEY_End; _keymap[NSPageUpFunctionKey] = osgGA::GUIEventAdapter::KEY_Page_Up; _keymap[NSPageDownFunctionKey] = osgGA::GUIEventAdapter::KEY_Page_Down; _keymap[NSLeftArrowFunctionKey] = osgGA::GUIEventAdapter::KEY_Left; _keymap[NSRightArrowFunctionKey] = osgGA::GUIEventAdapter::KEY_Right; _keymap[NSUpArrowFunctionKey] = osgGA::GUIEventAdapter::KEY_Up; _keymap[NSDownArrowFunctionKey] = osgGA::GUIEventAdapter::KEY_Down; _keymap[NSDeleteFunctionKey] = osgGA::GUIEventAdapter::KEY_Delete; _keymap[NSF1FunctionKey] = osgGA::GUIEventAdapter::KEY_F1; _keymap[NSF2FunctionKey] = osgGA::GUIEventAdapter::KEY_F2; _keymap[NSF3FunctionKey] = osgGA::GUIEventAdapter::KEY_F3; _keymap[NSF4FunctionKey] = osgGA::GUIEventAdapter::KEY_F4; _keymap[NSF5FunctionKey] = osgGA::GUIEventAdapter::KEY_F5; _keymap[NSF6FunctionKey] = osgGA::GUIEventAdapter::KEY_F6; _keymap[NSF7FunctionKey] = osgGA::GUIEventAdapter::KEY_F7; _keymap[NSF8FunctionKey] = osgGA::GUIEventAdapter::KEY_F8; _keymap[NSF9FunctionKey] = osgGA::GUIEventAdapter::KEY_F9; _keymap[NSF10FunctionKey] = osgGA::GUIEventAdapter::KEY_F10; _keymap[NSF11FunctionKey] = osgGA::GUIEventAdapter::KEY_F11; _keymap[NSF12FunctionKey] = osgGA::GUIEventAdapter::KEY_F12; _keymap[NSF13FunctionKey] = osgGA::GUIEventAdapter::KEY_F13; _keymap[NSF14FunctionKey] = osgGA::GUIEventAdapter::KEY_F14; _keymap[NSF15FunctionKey] = osgGA::GUIEventAdapter::KEY_F15; _keymap[NSF16FunctionKey] = osgGA::GUIEventAdapter::KEY_F16; _keymap[NSF17FunctionKey] = osgGA::GUIEventAdapter::KEY_F17; _keymap[NSF18FunctionKey] = osgGA::GUIEventAdapter::KEY_F18; _keymap[NSF19FunctionKey] = osgGA::GUIEventAdapter::KEY_F19; _keymap[NSF20FunctionKey] = osgGA::GUIEventAdapter::KEY_F20; _keymap[NSF21FunctionKey] = osgGA::GUIEventAdapter::KEY_F21; _keymap[NSF22FunctionKey] = osgGA::GUIEventAdapter::KEY_F22; _keymap[NSF23FunctionKey] = osgGA::GUIEventAdapter::KEY_F23; _keymap[NSF24FunctionKey] = osgGA::GUIEventAdapter::KEY_F24; _keymap[NSF25FunctionKey] = osgGA::GUIEventAdapter::KEY_F25; _keymap[NSF26FunctionKey] = osgGA::GUIEventAdapter::KEY_F26; _keymap[NSF27FunctionKey] = osgGA::GUIEventAdapter::KEY_F27; _keymap[NSF28FunctionKey] = osgGA::GUIEventAdapter::KEY_F28; _keymap[NSF29FunctionKey] = osgGA::GUIEventAdapter::KEY_F29; _keymap[NSF30FunctionKey] = osgGA::GUIEventAdapter::KEY_F30; _keymap[NSF31FunctionKey] = osgGA::GUIEventAdapter::KEY_F31; _keymap[NSF32FunctionKey] = osgGA::GUIEventAdapter::KEY_F32; _keymap[NSF33FunctionKey] = osgGA::GUIEventAdapter::KEY_F33; _keymap[NSF34FunctionKey] = osgGA::GUIEventAdapter::KEY_F34; _keymap[NSF35FunctionKey] = osgGA::GUIEventAdapter::KEY_F35; _keypadmap['='] = osgGA::GUIEventAdapter::KEY_KP_Equal; _keypadmap['*'] = osgGA::GUIEventAdapter::KEY_KP_Multiply; _keypadmap['+'] = osgGA::GUIEventAdapter::KEY_KP_Add; _keypadmap['-'] = osgGA::GUIEventAdapter::KEY_KP_Subtract; _keypadmap['.'] = osgGA::GUIEventAdapter::KEY_KP_Decimal; _keypadmap['/'] = osgGA::GUIEventAdapter::KEY_KP_Divide; _keypadmap['0'] = osgGA::GUIEventAdapter::KEY_KP_0; _keypadmap['1'] = osgGA::GUIEventAdapter::KEY_KP_1; _keypadmap['2'] = osgGA::GUIEventAdapter::KEY_KP_2; _keypadmap['3'] = osgGA::GUIEventAdapter::KEY_KP_3; _keypadmap['4'] = osgGA::GUIEventAdapter::KEY_KP_4; _keypadmap['5'] = osgGA::GUIEventAdapter::KEY_KP_5; _keypadmap['6'] = osgGA::GUIEventAdapter::KEY_KP_6; _keypadmap['7'] = osgGA::GUIEventAdapter::KEY_KP_7; _keypadmap['8'] = osgGA::GUIEventAdapter::KEY_KP_8; _keypadmap['9'] = osgGA::GUIEventAdapter::KEY_KP_9; } ~CocoaKeyboardMap() { } unsigned int remapKey(unsigned int key, bool pressedOnKeypad = false) { if (pressedOnKeypad) { KeyMap::iterator itr = _keypadmap.find(key); if (itr == _keypadmap.end()) return key; else return itr->second; } KeyMap::iterator itr = _keymap.find(key); if (itr == _keymap.end()) return key; else return itr->second; } private: typedef std::map KeyMap; KeyMap _keymap, _keypadmap; }; // ---------------------------------------------------------------------------------------------------------- // remapCocoaKey // ---------------------------------------------------------------------------------------------------------- static unsigned int remapCocoaKey(unsigned int key, unsigned int modifiers) { static CocoaKeyboardMap s_CocoaKeyboardMap; bool pressedOnKeypad = modifiers & NSNumericPadKeyMask; if (modifiers & NSFunctionKeyMask) pressedOnKeypad = false; //std::cout << std::hex << "remap " << key << " keypad: " << pressedOnKeypad << " modifiers: " << modifiers << std::endl; return s_CocoaKeyboardMap.remapKey(key, pressedOnKeypad); } std::ostream& operator<<(std::ostream& os, const NSRect& rect) { os << rect.origin.x << "/" << rect.origin.y << " " << rect.size.width << "x" << rect.size.height; return os; } // ---------------------------------------------------------------------------------------------------------- // Cocoa uses a coordinate system where its origin is in the bottom left corner, // osg and quartz uses top left for the origin // // these 2 methods convets rects between the different coordinate systems // ---------------------------------------------------------------------------------------------------------- static NSRect convertFromQuartzCoordinates(const NSRect& rect) { NSRect frame = [[[NSScreen screens] objectAtIndex: 0] frame]; float y = frame.size.height - rect.origin.y - rect.size.height; NSRect converted = NSMakeRect(rect.origin.x, y, rect.size.width, rect.size.height); // std::cout << "converting from Quartz " << rect << " to " << converted << " using screen rect " << frame << std::endl; return converted; } static NSRect convertToQuartzCoordinates(const NSRect& rect) { NSRect frame = [[[NSScreen screens] objectAtIndex: 0] frame]; float y = frame.size.height - (rect.origin.y + rect.size.height); NSRect converted = NSMakeRect(rect.origin.x, y, rect.size.width, rect.size.height); // std::cout << "converting To Quartz " << rect << " to " << converted << " using screen rect " << frame << std::endl; return converted; } #pragma mark CocoaAppDelegate // ---------------------------------------------------------------------------------------------------------- // the app-delegate, handling quit-requests // ---------------------------------------------------------------------------------------------------------- @interface CocoaAppDelegate : NSObject { } - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; - (void)applicationDidFinishLaunching:(NSNotification *)aNotification; @end @implementation CocoaAppDelegate - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { s_quit_requested = true; DEBUG_OUT("quit requested "); return NSTerminateNow; } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { DEBUG_OUT("applicationDidFinishLaunching"); } @end #pragma mark GraphicsWindowCocoaWindow // ---------------------------------------------------------------------------------------------------------- // GraphicsWindowCocoaWindow, implements canBecomeKeyWindow + canBecomeMainWindow // ---------------------------------------------------------------------------------------------------------- @interface GraphicsWindowCocoaWindow : NSWindow { } - (BOOL) canBecomeKeyWindow; - (BOOL) canBecomeMainWindow; @end @implementation GraphicsWindowCocoaWindow - (BOOL) canBecomeKeyWindow { return YES; } - (BOOL) canBecomeMainWindow { return YES; } @end #pragma mark GraphicsWindowCocoaGLView // ---------------------------------------------------------------------------------------------------------- // GraphicsWindowCocoaGLView // custom NSOpenGLView-class handling mouse- and keyboard-events, forwarding them to the EventQueue // some code borrowed from the example osgCocoaViewer from E.Wing // ---------------------------------------------------------------------------------------------------------- @interface GraphicsWindowCocoaGLView : NSOpenGLView { @private osgViewer::GraphicsWindowCocoa* _win; BOOL _isUsingCtrlClick, _isUsingOptionClick; unsigned int _cachedModifierFlags; BOOL _handleTabletEvents; NSMutableDictionary* _touchPoints; unsigned int _lastTouchPointId; } - (void)setGraphicsWindowCocoa: (osgViewer::GraphicsWindowCocoa*) win; - (void)keyDown:(NSEvent *)theEvent; - (void)keyUp:(NSEvent *)theEvent; - (void)flagsChanged:(NSEvent *)theEvent; - (void) mouseMoved:(NSEvent*)theEvent; - (void) mouseDown:(NSEvent*)theEvent; - (void) mouseDragged:(NSEvent*)theEvent; - (void) mouseUp:(NSEvent*)theEvent; - (void) rightMouseDown:(NSEvent*)theEvent; - (void) rightMouseDragged:(NSEvent*)theEvent; - (void) rightMouseUp:(NSEvent*)theEvent; - (void) otherMouseDown:(NSEvent*)theEvent; - (void) otherMouseDragged:(NSEvent*)theEvent; - (void) otherMouseUp:(NSEvent*)theEvent; - (NSPoint) getLocalPoint: (NSEvent*)theEvent; - (void) handleModifiers: (NSEvent*)theEvent; - (void) setIsUsingCtrlClick:(BOOL)is_using_ctrl_click; - (BOOL) isUsingCtrlClick; - (void) setIsUsingOptionClick:(BOOL)is_using_option_click; - (BOOL) isUsingOptionClick; - (void) doLeftMouseButtonDown:(NSEvent*)theEvent; - (void) doLeftMouseButtonUp:(NSEvent*)theEvent; - (void) doRightMouseButtonDown:(NSEvent*)theEvent; - (void) doRightMouseButtonUp:(NSEvent*)theEvent; - (void) doMiddleMouseButtonDown:(NSEvent*)theEvent; - (void) doExtraMouseButtonDown:(NSEvent*)theEvent buttonNumber:(int)button_number; - (void) doMiddleMouseButtonUp:(NSEvent*)theEvent; - (void) doExtraMouseButtonUp:(NSEvent*)theEvent buttonNumber:(int)button_number; - (void) scrollWheel:(NSEvent*)theEvent; - (void)tabletPoint:(NSEvent *)theEvent; - (void)tabletProximity:(NSEvent *)theEvent; - (void)handleTabletEvents:(NSEvent*)theEvent; #if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) - (osgGA::GUIEventAdapter::TouchPhase) convertTouchPhase: (NSTouchPhase) phase; - (unsigned int)computeTouchId: (NSTouch*) touch mayCleanup: (BOOL) may_cleanup; - (void)touchesBeganWithEvent:(NSEvent *)event; - (void)touchesMovedWithEvent:(NSEvent *)event; - (void)touchesEndedWithEvent:(NSEvent *)event; - (void)touchesCancelledWithEvent:(NSEvent *)event; #endif - (BOOL)useMultiTouchOnly: (NSEvent*) event; - (BOOL)acceptsFirstResponder; - (BOOL)becomeFirstResponder; - (BOOL)resignFirstResponder; - (void)dealloc; @end @implementation GraphicsWindowCocoaGLView -(void) setGraphicsWindowCocoa: (osgViewer::GraphicsWindowCocoa*) win { _win = win; _touchPoints = NULL; } -(void) dealloc { if (_touchPoints) [_touchPoints release]; [super dealloc]; } - (BOOL)acceptsFirstResponder { return YES; } - (BOOL)becomeFirstResponder { return YES; } - (BOOL)resignFirstResponder { return YES; } - (BOOL) useMultiTouchOnly: (NSEvent*) event { #if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) return ([self acceptsTouchEvents] && ([event subtype] == NSTouchEventSubtype)); #else return false; #endif } - (NSPoint) getLocalPoint: (NSEvent*)theEvent { return [self convertPoint:[theEvent locationInWindow] fromView:nil]; } - (void) handleModifiers: (NSEvent*)theEvent { DEBUG_OUT("handling modifiers"); if ((!_win) || (!_win->getEventQueue())) return; // no event queue in place unsigned int flags = [theEvent modifierFlags]; if (flags == _cachedModifierFlags) return; const unsigned int masks[] = { NSShiftKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSCommandKeyMask, NSAlphaShiftKeyMask }; const unsigned int keys[] = { osgGA::GUIEventAdapter::KEY_Shift_L, osgGA::GUIEventAdapter::KEY_Control_L, osgGA::GUIEventAdapter::KEY_Alt_L, osgGA::GUIEventAdapter::KEY_Super_L, osgGA::GUIEventAdapter::KEY_Caps_Lock }; // std::cout << "flags: " << flags << " cached: " << _cachedModifierFlags << std::endl; for(unsigned int i = 0; i < 5; ++i) { if ((flags & masks[i]) && !(_cachedModifierFlags & masks[i])) { _win->getEventQueue()->keyPress(keys[i], _win->getEventQueue()->getTime(), keys[i]); // we don't get a key up for the caps lock so emulate it. if (i == 4) _win->getEventQueue()->keyRelease(keys[i], _win->getEventQueue()->getTime(), keys[i]); } if (!(flags & masks[i]) && (_cachedModifierFlags & masks[i])) { if (i == 4) { // emulate a key down for caps-lock. _win->getEventQueue()->keyPress(keys[i], _win->getEventQueue()->getTime(), keys[i]); } _win->getEventQueue()->keyRelease(keys[i], _win->getEventQueue()->getTime(), keys[i]); } } _cachedModifierFlags = flags; } - (void)flagsChanged:(NSEvent *)theEvent { [self handleModifiers: theEvent]; } - (void) mouseMoved:(NSEvent*)theEvent { // if multitouch is enabled, disable standard event handling if ([self useMultiTouchOnly: theEvent]) return; NSPoint converted_point = [self getLocalPoint: theEvent]; DEBUG_OUT("Mouse moved" << converted_point.x << "/" << converted_point.y); _win->getEventQueue()->mouseMotion(converted_point.x, converted_point.y); } - (void) mouseDown:(NSEvent*)theEvent { // if multitouch is enabled, disable standard event handling if ([self useMultiTouchOnly: theEvent]) return; DEBUG_OUT("Mouse down"); // Because many Mac users have only a 1-button mouse, we should provide ways // to access the button 2 and 3 actions of osgViewer. // I will use the Ctrl modifer to represent right-clicking // and Option modifier to represent middle clicking. if([theEvent modifierFlags] & NSControlKeyMask) { [self setIsUsingCtrlClick:YES]; [self doRightMouseButtonDown:theEvent]; } else if([theEvent modifierFlags] & NSAlternateKeyMask) { [self setIsUsingOptionClick:YES]; [self doMiddleMouseButtonDown:theEvent]; } else { [self doLeftMouseButtonDown:theEvent]; } if ([theEvent subtype] == NSTabletPointEventSubtype) { _handleTabletEvents = true; [self handleTabletEvents:theEvent]; } } - (void) mouseDragged:(NSEvent*)theEvent { // if multitouch is enabled, disable standard event handling if ([self useMultiTouchOnly: theEvent]) return; if (!_win) return; NSPoint converted_point = [self getLocalPoint: theEvent]; _win->getEventQueue()->mouseMotion(converted_point.x, converted_point.y); if (_handleTabletEvents) [self handleTabletEvents:theEvent]; } - (void) mouseUp:(NSEvent*)theEvent { // if multitouch is enabled, disable standard event handling if ([self useMultiTouchOnly: theEvent]) return; // Because many Mac users have only a 1-button mouse, we should provide ways // to access the button 2 and 3 actions of osgViewer. // I will use the Ctrl modifer to represent right-clicking // and Option modifier to represent middle clicking. if([self isUsingCtrlClick] == YES) { [self setIsUsingCtrlClick:NO]; [self doRightMouseButtonUp:theEvent]; } else if([self isUsingOptionClick] == YES) { [self setIsUsingOptionClick:NO]; [self doMiddleMouseButtonUp:theEvent]; } else { [self doLeftMouseButtonUp:theEvent]; } _handleTabletEvents = false; } - (void) rightMouseDown:(NSEvent*)theEvent { [self doRightMouseButtonDown:theEvent]; } - (void) rightMouseDragged:(NSEvent*)theEvent { if (!_win) return; NSPoint converted_point = [self getLocalPoint: theEvent]; _win->getEventQueue()->mouseMotion(converted_point.x, converted_point.y); } - (void) rightMouseUp:(NSEvent*)theEvent { [self doRightMouseButtonUp:theEvent]; _handleTabletEvents = false; } // "otherMouse" seems to capture middle button and any other buttons beyond (4th, etc). - (void) otherMouseDown:(NSEvent*)theEvent { // Button 0 is left // Button 1 is right // Button 2 is middle // Button 3 keeps going // osgViewer expects 1 for left, 3 for right, 2 for middle // osgViewer has a reversed number mapping for right and middle compared to Cocoa if([theEvent buttonNumber] == 2) { [self doMiddleMouseButtonDown:theEvent]; } else // buttonNumber should be 3,4,5,etc; must map to 4,5,6,etc in osgViewer { [self doExtraMouseButtonDown:theEvent buttonNumber:[theEvent buttonNumber]]; } } - (void) otherMouseDragged:(NSEvent*)theEvent { if (!_win) return; NSPoint converted_point = [self getLocalPoint: theEvent]; _win->getEventQueue()->mouseMotion(converted_point.x, converted_point.y); } // "otherMouse" seems to capture middle button and any other buttons beyond (4th, etc). - (void) otherMouseUp:(NSEvent*)theEvent { // Button 0 is left // Button 1 is right // Button 2 is middle // Button 3 keeps going // osgViewer expects 1 for left, 3 for right, 2 for middle // osgViewer has a reversed number mapping for right and middle compared to Cocoa if([theEvent buttonNumber] == 2) { [self doMiddleMouseButtonUp:theEvent]; } else // buttonNumber should be 3,4,5,etc; must map to 4,5,6,etc in osgViewer { // I don't think osgViewer does anything for these additional buttons, // but just in case, pass them along. But as a Cocoa programmer, you might // think about things you can do natively here instead of passing the buck. [self doExtraMouseButtonUp:theEvent buttonNumber:[theEvent buttonNumber]]; } } - (void) setIsUsingCtrlClick:(BOOL)is_using_ctrl_click { _isUsingCtrlClick = is_using_ctrl_click; } - (BOOL) isUsingCtrlClick { return _isUsingCtrlClick; } - (void) setIsUsingOptionClick:(BOOL)is_using_option_click { _isUsingOptionClick = is_using_option_click; } - (BOOL) isUsingOptionClick { return _isUsingOptionClick; } - (void)doSingleOrDoubleButtonPress:(NSEvent*)event forButton:(int)button { if (!_win) { return; } NSPoint convertedPoint = [self getLocalPoint:event]; if ([event clickCount] == 1) { _win->getEventQueue()->mouseButtonPress(convertedPoint.x, convertedPoint.y, button); } else { _win->getEventQueue()->mouseDoubleButtonPress(convertedPoint.x, convertedPoint.y, button); } //[self setNeedsDisplay:YES]; } - (void)doButtonRelease:(NSEvent*)event forButton:(int)button { if (!_win) { return; } NSPoint convertedPoint = [self getLocalPoint:event]; _win->getEventQueue()->mouseButtonRelease(convertedPoint.x, convertedPoint.y, button); //[self setNeedsDisplay:YES]; } // Left mouse button - (void) doLeftMouseButtonDown:(NSEvent*)theEvent { [self doSingleOrDoubleButtonPress:theEvent forButton:1]; } - (void) doLeftMouseButtonUp:(NSEvent*)theEvent { [self doButtonRelease:theEvent forButton:1]; } // Right mouse button - (void) doRightMouseButtonDown:(NSEvent*)theEvent { [self doSingleOrDoubleButtonPress:theEvent forButton:3]; } - (void) doRightMouseButtonUp:(NSEvent*)theEvent { [self doButtonRelease:theEvent forButton:3]; } // Middle mouse button - (void) doMiddleMouseButtonDown:(NSEvent*)theEvent { [self doSingleOrDoubleButtonPress:theEvent forButton:2]; } - (void) doMiddleMouseButtonUp:(NSEvent*)theEvent { [self doButtonRelease:theEvent forButton:2]; } // Extra mouse buttons - (void) doExtraMouseButtonDown:(NSEvent*)theEvent buttonNumber:(int)button_number { [self doButtonRelease:theEvent forButton:(button_number+1)]; } - (void) doExtraMouseButtonUp:(NSEvent*)theEvent buttonNumber:(int)button_number { [self doButtonRelease:theEvent forButton:(button_number+1)]; } - (void) scrollWheel:(NSEvent*)theEvent { if (!_win) return; // Unfortunately, it turns out mouseScroll2D doesn't actually do anything. // The camera manipulators don't seem to implement any code that utilize the scroll values. // This this call does nothing. _win->getEventQueue()->mouseScroll2D([theEvent deltaX], [theEvent deltaY]); } - (void)keyDown:(NSEvent *)theEvent { if (!_win) return; NSString* unmodified_chars = [theEvent charactersIgnoringModifiers]; if ([theEvent modifierFlags] && NSShiftKeyMask) { unmodified_chars = [unmodified_chars lowercaseString]; } NSString* chars = [theEvent characters]; if ((chars) && ([chars length] > 0)) { unsigned int unmodified_keyCode = remapCocoaKey([unmodified_chars characterAtIndex:0], [theEvent modifierFlags] ); unsigned int keyCode = remapCocoaKey([chars characterAtIndex:0], [theEvent modifierFlags] ); //std::cout << std::hex << "key dn: " <<[chars characterAtIndex:0] << "=" << keyCode << " unmodified: " << unmodified_keyCode << std::endl; _win->getEventQueue()->keyPress( keyCode, _win->getEventQueue()->getTime(), unmodified_keyCode); } } - (void)keyUp:(NSEvent *)theEvent { if (!_win) return; NSString* unmodified_chars = [theEvent charactersIgnoringModifiers]; if ([theEvent modifierFlags] && NSShiftKeyMask) { unmodified_chars = [unmodified_chars lowercaseString]; } NSString* chars = [theEvent characters]; if ((chars) && ([chars length] > 0)) { unsigned int unmodified_keyCode = remapCocoaKey([unmodified_chars characterAtIndex:0], [theEvent modifierFlags] ); unsigned int keyCode = remapCocoaKey([chars characterAtIndex:0], [theEvent modifierFlags] ); //std::cout << std::hex << "key up: " <<[chars characterAtIndex:0] << "=" << keyCode << " unmodified: " << unmodified_keyCode << std::endl; _win->getEventQueue()->keyRelease( keyCode, _win->getEventQueue()->getTime(), unmodified_keyCode); } } - (void)tabletPoint:(NSEvent *)theEvent { //_handleTabletEvents = YES; //[self handleTabletEvents:theEvent]; } -(void)handleTabletEvents:(NSEvent *)theEvent { if (!_win) return; float pressure = [theEvent pressure]; _win->getEventQueue()->penPressure(pressure); NSPoint tilt = [theEvent tilt]; _win->getEventQueue()->penOrientation (tilt.x, tilt.y, [theEvent rotation]); } - (void)tabletProximity:(NSEvent *)theEvent { if (!_win) return; osgGA::GUIEventAdapter::TabletPointerType pt(osgGA::GUIEventAdapter::UNKNOWN); switch ([theEvent pointingDeviceType]) { case NSPenPointingDevice: pt = osgGA::GUIEventAdapter::PEN; break; case NSCursorPointingDevice: pt = osgGA::GUIEventAdapter::PUCK; break; case NSEraserPointingDevice: pt = osgGA::GUIEventAdapter::ERASER; break; default: break; } _win->getEventQueue()->penProximity(pt, [theEvent isEnteringProximity]); } #if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) - (osgGA::GUIEventAdapter::TouchPhase) convertTouchPhase: (NSTouchPhase) phase { switch(phase) { case NSTouchPhaseBegan: return osgGA::GUIEventAdapter::TOUCH_BEGAN; break; case NSTouchPhaseMoved: return osgGA::GUIEventAdapter::TOUCH_MOVED; break; case NSTouchPhaseStationary: return osgGA::GUIEventAdapter::TOUCH_STATIONERY; break; case NSTouchPhaseEnded: case NSTouchPhaseCancelled: return osgGA::GUIEventAdapter::TOUCH_ENDED; break; } return osgGA::GUIEventAdapter::TOUCH_ENDED; } - (unsigned int)computeTouchId: (NSTouch*) touch mayCleanup: (BOOL) may_cleanup { unsigned int result(0); if(!_touchPoints) { _touchPoints = [[NSMutableDictionary alloc] init]; _lastTouchPointId = 0; } switch([touch phase]) { case NSTouchPhaseBegan: if ([_touchPoints objectForKey: [touch identity]] == nil) { [_touchPoints setObject: [NSNumber numberWithInt: _lastTouchPointId] forKey: [touch identity]]; result = _lastTouchPointId++; break; } // missing "break" by intention! case NSTouchPhaseMoved: case NSTouchPhaseStationary: { NSNumber* n = [_touchPoints objectForKey: [touch identity]]; result = [n intValue]; } break; case NSTouchPhaseEnded: case NSTouchPhaseCancelled: { NSNumber* n = [_touchPoints objectForKey: [touch identity]]; result = [n intValue]; if(may_cleanup) [_touchPoints removeObjectForKey: [touch identity]]; if([_touchPoints count] == 0) { _lastTouchPointId = 0; } } break; default: break; } return result; } - (void)touchesBeganWithEvent:(NSEvent *)event { NSSet *allTouches = [event touchesMatchingPhase: NSTouchPhaseAny inView: self]; osg::ref_ptr osg_event(NULL); NSRect bounds = [self bounds]; for(unsigned int i=0; i<[allTouches count]; i++) { NSTouch *touch = [[allTouches allObjects] objectAtIndex:i]; NSPoint pos = [touch normalizedPosition]; osg::Vec2 pixelPos(pos.x * bounds.size.width, (1-pos.y) * bounds.size.height); unsigned int touch_id = [self computeTouchId: touch mayCleanup:FALSE]; if (!osg_event) { osg_event = _win->getEventQueue()->touchBegan(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); } else { osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); } } } - (void)touchesMovedWithEvent:(NSEvent *)event { NSSet *allTouches = [event touchesMatchingPhase: NSTouchPhaseAny inView: self]; osg::ref_ptr osg_event(NULL); NSRect bounds = [self bounds]; for(unsigned int i=0; i<[allTouches count]; i++) { NSTouch *touch = [[allTouches allObjects] objectAtIndex:i]; NSPoint pos = [touch normalizedPosition]; osg::Vec2 pixelPos(pos.x * bounds.size.width, (1 - pos.y) * bounds.size.height); unsigned int touch_id = [self computeTouchId: touch mayCleanup:FALSE]; if (!osg_event) { osg_event = _win->getEventQueue()->touchMoved(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); } else { osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); } } } - (void)touchesEndedWithEvent:(NSEvent *)event { NSSet *allTouches = [event touchesMatchingPhase: NSTouchPhaseAny inView: self]; osg::ref_ptr osg_event(NULL); NSRect bounds = [self bounds]; for(unsigned int i=0; i<[allTouches count]; i++) { NSTouch *touch = [[allTouches allObjects] objectAtIndex:i]; NSPoint pos = [touch normalizedPosition]; osg::Vec2 pixelPos(pos.x * bounds.size.width, (1 - pos.y) * bounds.size.height); unsigned int touch_id = [self computeTouchId: touch mayCleanup: TRUE]; if (!osg_event) { osg_event = _win->getEventQueue()->touchEnded(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y(), 1); } else { osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y(), 1); } } } - (void)touchesCancelledWithEvent:(NSEvent *)event { [self touchesEndedWithEvent: event]; } #endif @end #pragma mark GraphicsWindowCocoaDelegate #ifndef MAC_OS_X_VERSION_10_6 #define MAC_OS_X_VERSION_10_6 1060 #endif // ---------------------------------------------------------------------------------------------------------- // the window-delegate, handles moving/resizing of the window etc. // ---------------------------------------------------------------------------------------------------------- @interface GraphicsWindowCocoaDelegate : NSObject #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 #endif { @private osgViewer::GraphicsWindowCocoa* _win; BOOL _inDidMove; } - (id)initWith: (osgViewer::GraphicsWindowCocoa*) win; - (void)windowDidMove:(NSNotification *)notification; - (void)windowDidResize:(NSNotification *)notification; - (BOOL)windowShouldClose:(id)window; - (void)updateWindowBounds; @end @implementation GraphicsWindowCocoaDelegate - (id)initWith: (osgViewer::GraphicsWindowCocoa*) win { _inDidMove = false; _win = win; return [super init]; } - (void)windowDidMove:(NSNotification *)notification { [self updateWindowBounds]; } - (void)windowDidResize:(NSNotification *)notification { [self updateWindowBounds]; } -(void)updateWindowBounds { if (_inDidMove) return; _inDidMove = true; GraphicsWindowCocoaWindow* nswin = _win->getWindow(); NSRect bounds = [nswin contentRectForFrameRect: [nswin frame] ]; // convert to quartz-coordinate-system bounds = convertToQuartzCoordinates(bounds); // std::cout << "windowdidmove: " << bounds.origin.x << " " << bounds.origin.y << " " << bounds.size.width << " " << bounds.size.height << std::endl; _win->adaptResize(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height); //_win->getEventQueue()->windowResize(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height, _win->getEventQueue()->getTime()); _win->requestRedraw(); _inDidMove = false; } - (BOOL)windowShouldClose:(id)window { return _win->requestClose(); } @end #pragma mark CocoaWindowAdapter using namespace osgDarwin; namespace osgViewer { // ---------------------------------------------------------------------------------------------------------- // small adapter class to handle the dock/menubar // ---------------------------------------------------------------------------------------------------------- class CocoaWindowAdapter : public MenubarController::WindowAdapter { public: CocoaWindowAdapter(GraphicsWindowCocoa* win) : MenubarController::WindowAdapter(), _win(win) {} virtual bool valid() { return (_win.valid() && _win->valid()); } virtual void getWindowBounds(CGRect& rect) { NSRect nsrect = [_win->getWindow() frame]; nsrect = convertToQuartzCoordinates(nsrect); rect.origin.x = nsrect.origin.x; rect.origin.y = nsrect.origin.y; rect.size.width = nsrect.size.width; rect.size.height = nsrect.size.height; } virtual osgViewer::GraphicsWindow* getWindow() {return _win.get(); } private: osg::observer_ptr _win; }; #pragma mark GraphicsWindowCocoa // ---------------------------------------------------------------------------------------------------------- // init // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowCocoa::init() { if (_initialized) return; _closeRequested = false; _ownsWindow = false; _context = NULL; _window = NULL; _pixelformat = NULL; _updateContext = false; _valid = _initialized = true; // make sure the event queue has the correct window rectangle size and input range getEventQueue()->syncWindowRectangleWithGraphcisContext(); } // ---------------------------------------------------------------------------------------------------------- // setupNSWindow // sets up the NSWindow, adds delegates, etc // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowCocoa::setupNSWindow(NSWindow* win) { [win setReleasedWhenClosed:NO]; [win setDisplaysWhenScreenProfileChanges:YES]; GraphicsWindowCocoaDelegate* delegate = [[GraphicsWindowCocoaDelegate alloc] initWith: this]; [win setDelegate: delegate ]; //[delegate autorelease]; [win makeKeyAndOrderFront:nil]; [win setAcceptsMouseMovedEvents: YES]; } // ---------------------------------------------------------------------------------------------------------- // realizeImplementation, creates the window + context // ---------------------------------------------------------------------------------------------------------- bool GraphicsWindowCocoa::realizeImplementation() { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; unsigned int style(NSBorderlessWindowMask); if (_traits->windowDecoration) { style = NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask; // supportsResize works only with windows with titlebar if (_traits->supportsResize) style |= NSResizableWindowMask; } DarwinWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); int screenLeft(0), screenTop(0); if (wsi) { wsi->getScreenTopLeft((*_traits), screenLeft, screenTop); } NSRect rect = NSMakeRect(_traits->x + screenLeft, _traits->y + screenTop, _traits->width, _traits->height); _ownsWindow = true; // should we create a NSView only?? WindowData* windowData = _traits->inheritedWindowData ? dynamic_cast(_traits->inheritedWindowData.get()) : NULL; if (windowData) { if (windowData->createOnlyView()) _ownsWindow = false; _checkForEvents = windowData->checkForEvents(); } OSG_DEBUG << "GraphicsWindowCocoa::realizeImplementation / ownsWindow: " << _ownsWindow << " checkForEvents: " << _checkForEvents << std::endl; if (_ownsWindow) { _window = [[GraphicsWindowCocoaWindow alloc] initWithContentRect: rect styleMask: style backing: NSBackingStoreBuffered defer: NO]; if (!_window) { OSG_WARN << "GraphicsWindowCocoa::realizeImplementation :: could not create window" << std::endl; return false; } rect = convertFromQuartzCoordinates(rect); [_window setFrameOrigin: rect.origin]; } NSOpenGLPixelFormatAttribute attr[32]; int i = 0; attr[i++] = NSOpenGLPFADepthSize; attr[i++] = static_cast(_traits->depth); if (_traits->doubleBuffer) { attr[i++] = NSOpenGLPFADoubleBuffer; } if (_traits->alpha) { attr[i++] = NSOpenGLPFAAlphaSize; attr[i++] = static_cast(_traits->alpha); } if (_traits->stencil) { attr[i++] = NSOpenGLPFAStencilSize; attr[i++] = static_cast(_traits->stencil); } if (_traits->sampleBuffers) { attr[i++] = NSOpenGLPFASampleBuffers; attr[i++] = static_cast(_traits->sampleBuffers); attr[i++] = NSOpenGLPFASamples; attr[i++] = static_cast(_traits->samples); } attr[i++] = NSOpenGLPFAAccelerated; attr[i] = static_cast(0); // create the context NSOpenGLContext* sharedContext = NULL; GraphicsHandleCocoa* graphicsHandleCocoa = dynamic_cast(_traits->sharedContext.get()); if (graphicsHandleCocoa) { sharedContext = graphicsHandleCocoa->getNSOpenGLContext(); } _pixelformat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr ]; _context = [[NSOpenGLContext alloc] initWithFormat: _pixelformat shareContext: sharedContext]; if (!_context) { OSG_WARN << "GraphicsWindowCocoa::realizeImplementation :: could not create context" << std::endl; return false; } // set graphics handle for shared usage setNSOpenGLContext(_context); _view = [[ GraphicsWindowCocoaGLView alloc ] initWithFrame:[ _window frame ] ]; [_view setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable) ]; [_view setGraphicsWindowCocoa: this]; [_view setOpenGLContext:_context]; // enable multitouch if (_multiTouchEnabled || (windowData && windowData->isMultiTouchEnabled())) { setMultiTouchEnabled(true); } OSG_DEBUG << "GraphicsWindowCocoa::realizeImplementation / view: " << _view << std::endl; if (_ownsWindow) { [_window setContentView: _view]; setupNSWindow(_window); [_view release]; MenubarController::instance()->attachWindow( new CocoaWindowAdapter(this) ); } else { windowData->setCreatedNSView(_view); } [pool release]; useCursor(_traits->useCursor); setWindowName(_traits->windowName); setSyncToVBlank(_traits->vsync); MenubarController::instance()->update(); // Cocoa's origin is bottom/left: getEventQueue()->getCurrentEventState()->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS); // make sure the event queue has the correct window rectangle size and input range getEventQueue()->syncWindowRectangleWithGraphcisContext(); _valid = _initialized = _realized = true; return _valid; } // ---------------------------------------------------------------------------------------------------------- // closeImplementation // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowCocoa::closeImplementation() { _valid = false; _realized = false; // there's a possibility that the MenubarController is destructed already, so prevent a crash: MenubarController* mbc = MenubarController::instance(); if (mbc) mbc->detachWindow(this); if (_view) { [_view setGraphicsWindowCocoa: NULL]; } if (_window) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // we have to close + release the window in the main-thread [_window performSelectorOnMainThread: @selector(close) withObject:NULL waitUntilDone: YES]; [_window performSelectorOnMainThread: @selector(release) withObject:NULL waitUntilDone: YES]; [pool release]; } _window = NULL; _view = NULL; } // ---------------------------------------------------------------------------------------------------------- // makeCurrentImplementation // ---------------------------------------------------------------------------------------------------------- bool GraphicsWindowCocoa:: makeCurrentImplementation() { if (_updateContext) { [_context update]; _updateContext = false; } [_context makeCurrentContext]; return true; } // ---------------------------------------------------------------------------------------------------------- // releaseContextImplementation // ---------------------------------------------------------------------------------------------------------- bool GraphicsWindowCocoa::releaseContextImplementation() { [NSOpenGLContext clearCurrentContext]; return true; } // ---------------------------------------------------------------------------------------------------------- // swapBuffersImplementation // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowCocoa::swapBuffersImplementation() { [_context flushBuffer]; } // ---------------------------------------------------------------------------------------------------------- // checkEvents // process all pending events // ---------------------------------------------------------------------------------------------------------- bool GraphicsWindowCocoa::checkEvents() { if (!_checkForEvents) return false; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; while(1) { /* NOTE: It may be better to use something like NSEventTrackingRunLoopMode since we don't necessarily want all timers/sources/observers to run, only those which would run while tracking events. However, it should be noted that NSEventTrackingRunLoopMode is in the common set of modes so it may not effectively make much of a difference. */ NSEvent *event = [ NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue: YES]; if(!event) break; [NSApp sendEvent: event]; } if (_closeRequested) getEventQueue()->closeWindow(); if (s_quit_requested) { getEventQueue()->quitApplication(); s_quit_requested = false; } [pool release]; return !(getEventQueue()->empty()); } // ---------------------------------------------------------------------------------------------------------- // setWindowDecorationImplementation // // unfortunately there's no way to change the decoration of a window, so we create an new one // and swap the content // ---------------------------------------------------------------------------------------------------------- bool GraphicsWindowCocoa::setWindowDecorationImplementation(bool flag) { if (!_realized || !_ownsWindow) return false; NSAutoreleasePool* localPool = [[NSAutoreleasePool alloc] init]; unsigned int style(NSBorderlessWindowMask); if (flag) { style = NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask; // supportsResize works only with windows with titlebar if (_traits->supportsResize) style |= NSResizableWindowMask; } NSRect rect = [_window contentRectForFrameRect: [_window frame] ]; GraphicsWindowCocoaWindow* new_win = [[GraphicsWindowCocoaWindow alloc] initWithContentRect: rect styleMask: style backing: NSBackingStoreBuffered defer: NO]; if (new_win) { [new_win setContentView: [_window contentView]]; setupNSWindow(new_win); NSString* title = (_traits.valid()) ? [NSString stringWithUTF8String: _traits->windowName.c_str()] : @""; [new_win setTitle: title ]; [_window close]; [_window release]; _window = new_win; [_window makeKeyAndOrderFront: nil]; } [localPool release]; return true; } // ---------------------------------------------------------------------------------------------------------- // grabFocus // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowCocoa::grabFocus() { if (_ownsWindow) [_window makeKeyAndOrderFront: nil]; } // ---------------------------------------------------------------------------------------------------------- // grabFocusIfPointerInWindow // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowCocoa::grabFocusIfPointerInWindow() { OSG_INFO << "GraphicsWindowCocoa :: grabFocusIfPointerInWindow not implemented yet " << std::endl; } // ---------------------------------------------------------------------------------------------------------- // resizedImplementation // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowCocoa::resizedImplementation(int x, int y, int width, int height) { DEBUG_OUT("resized implementation" << x << " " << y << " " << width << " " << height); GraphicsContext::resizedImplementation(x, y, width, height); _updateContext = true; MenubarController::instance()->update(); getEventQueue()->windowResize(x,y,width, height, getEventQueue()->getTime()); } // ---------------------------------------------------------------------------------------------------------- // setWindowRectangleImplementation // ---------------------------------------------------------------------------------------------------------- bool GraphicsWindowCocoa::setWindowRectangleImplementation(int x, int y, int width, int height) { if (!_ownsWindow) return false; NSAutoreleasePool* localPool = [[NSAutoreleasePool alloc] init]; DarwinWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); int screenLeft(0), screenTop(0); if (wsi) { wsi->getScreenTopLeft((*_traits), screenLeft, screenTop); } NSRect rect = NSMakeRect(x+screenLeft,y+screenTop,width, height); rect = convertFromQuartzCoordinates(rect); [_window setFrame: [NSWindow frameRectForContentRect: rect styleMask: [_window styleMask]] display: YES]; [_context update]; MenubarController::instance()->update(); [localPool release]; return true; } // ---------------------------------------------------------------------------------------------------------- // // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowCocoa::adaptResize(int x, int y, int w, int h) { DarwinWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); int screenLeft(0), screenTop(0); if (wsi) { // get the screen containing the window unsigned int screenNdx = wsi->getScreenContaining(x,y,w,h); // update traits _traits->screenNum = screenNdx; // get top left of screen wsi->getScreenTopLeft((*_traits), screenLeft, screenTop); } resized(x-screenLeft,y-screenTop,w,h); getEventQueue()->windowResize(x-screenLeft, y-screenTop, w, h, getEventQueue()->getTime()); } // ---------------------------------------------------------------------------------------------------------- // setWindowName // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowCocoa::setWindowName (const std::string & name) { if (_traits.valid()) _traits->windowName = name; if (!_ownsWindow) return; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString* title = [NSString stringWithUTF8String: name.c_str()]; [_window setTitle: title]; [pool release]; } // ---------------------------------------------------------------------------------------------------------- // requestWarpPointer // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowCocoa::requestWarpPointer(float x,float y) { CGPoint point; point.x = x + _traits->x; point.y = y + _traits->y; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 CGEventRef warpEvent = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, point, kCGMouseButtonLeft); CGEventPost(kCGHIDEventTap, warpEvent); CFRelease(warpEvent); #else DarwinWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); if (wsi == NULL) { osg::notify(osg::WARN) << "GraphicsWindowCocoa::useCursor :: could not get OSXCocoaWindowingSystemInterface" << std::endl; return; } CGDirectDisplayID displayId = wsi->getDisplayID((*_traits)); CGSetLocalEventsSuppressionInterval(0); CGDisplayMoveCursorToPoint(displayId, point); #endif getEventQueue()->mouseWarped(x,y); } // ---------------------------------------------------------------------------------------------------------- // useCursor // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowCocoa::useCursor(bool cursorOn) { if (_traits.valid()) _traits->useCursor = cursorOn; DarwinWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); if (wsi == NULL) { OSG_WARN << "GraphicsWindowCarbon::useCursor :: could not get OSXCarbonWindowingSystemInterface" << std::endl; return; } CGDirectDisplayID displayId = wsi->getDisplayID((*_traits)); CGDisplayErr err = kCGErrorSuccess; if (cursorOn) { err = CGDisplayShowCursor(displayId); } else { err = CGDisplayHideCursor(displayId); } if (err != kCGErrorSuccess) { OSG_WARN << "GraphicsWindowCocoa::useCursor failed with " << err << std::endl; } } // ---------------------------------------------------------------------------------------------------------- // setCursor // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowCocoa::setCursor(MouseCursor mouseCursor) { if (_currentCursor == mouseCursor) { return; } NSAutoreleasePool* localPool = [[NSAutoreleasePool alloc] init]; switch (mouseCursor) { case NoCursor: [NSCursor hide]; break; case LeftArrowCursor: case RightArrowCursor: [[NSCursor arrowCursor] set]; break; case TextCursor: [[NSCursor IBeamCursor] set]; break; case CrosshairCursor: [[NSCursor crosshairCursor] set]; break; default: OSG_INFO << "GraphicsWindowCocoa::setCursor :: unsupported MouseCursor: " << mouseCursor << std::endl; } if (_currentCursor == NoCursor) { [NSCursor unhide]; } _currentCursor = mouseCursor; [localPool release]; } // ---------------------------------------------------------------------------------------------------------- // setSyncToVBlank // ---------------------------------------------------------------------------------------------------------- void GraphicsWindowCocoa::setSyncToVBlank(bool f) { if (_traits.valid()) _traits->vsync = f; GLint VBL(f?1:0); [_context setValues:&VBL forParameter:NSOpenGLCPSwapInterval]; } bool GraphicsWindowCocoa::isMultiTouchEnabled() { return _multiTouchEnabled; } void GraphicsWindowCocoa::setMultiTouchEnabled(bool b) { _multiTouchEnabled = b; #if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) if (_view) [_view setAcceptsTouchEvents: b]; #else if (b) { OSG_WARN << "GraphicsWindowCocoa :: multi-touch only available for OS X >= 10.6, please check your compile settings" << std::endl; } #endif } // ---------------------------------------------------------------------------------------------------------- // d'tor // ---------------------------------------------------------------------------------------------------------- GraphicsWindowCocoa::~GraphicsWindowCocoa() { close(); } #pragma mark CocoaWindowingSystemInterface // ---------------------------------------------------------------------------------------------------------- // CocoaWindowingSystemInterface // ---------------------------------------------------------------------------------------------------------- struct CocoaWindowingSystemInterface : public DarwinWindowingSystemInterface { CocoaWindowingSystemInterface() : DarwinWindowingSystemInterface() { } void initAsStandaloneApplication() { _init(); static bool s_inited = false; if (s_inited) return; s_inited = true; OSG_INFO << "CocoaWindowingSystemInterface::initAsStandaloneApplication " << std::endl; ProcessSerialNumber psn; if (!GetCurrentProcess(&psn)) { TransformProcessType(&psn, kProcessTransformToForegroundApplication); SetFrontProcess(&psn); } NSAutoreleasePool* localPool = [[NSAutoreleasePool alloc] init]; if (NSApp == nil) { [NSApplication sharedApplication]; } [NSApp setDelegate: [[CocoaAppDelegate alloc] init] ]; createApplicationMenus(); [NSApp finishLaunching]; [localPool release]; } virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits) { _init(); if (!traits->pbuffer) { GraphicsWindowCocoa::WindowData* windowData = traits->inheritedWindowData ? dynamic_cast(traits->inheritedWindowData.get()) : NULL; if (!windowData || (windowData && windowData->poseAsStandaloneApp())) { initAsStandaloneApplication(); } } return createGraphicsContextImplementation(traits); } virtual ~CocoaWindowingSystemInterface() { } private: NSString *getApplicationName(void) { NSDictionary *dict; NSString *appName = 0; /* Determine the application name */ dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); if (dict) appName = [dict objectForKey: @"CFBundleName"]; if (![appName length]) appName = [[NSProcessInfo processInfo] processName]; return appName; } void createApplicationMenus(void) { NSString *appName; NSString *title; NSMenu *appleMenu; NSMenuItem *menuItem; /* Create the main menu bar */ [NSApp setMainMenu:[[NSMenu alloc] init]]; /* Create the application menu */ appName = getApplicationName(); appleMenu = [[NSMenu alloc] initWithTitle:@""]; /* Add menu items */ title = [@"About " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; [appleMenu addItem:[NSMenuItem separatorItem]]; NSMenu* service_menu = [[NSMenu alloc] init]; NSMenuItem* service_menu_item = [[NSMenuItem alloc] initWithTitle:@"Services" action:nil keyEquivalent:@""]; [service_menu_item setSubmenu: service_menu]; [appleMenu addItem: service_menu_item]; [NSApp setServicesMenu: service_menu]; [appleMenu addItem:[NSMenuItem separatorItem]]; title = [@"Hide " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@/*"h"*/"h"]; menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@/*"h"*/""]; [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; [appleMenu addItem:[NSMenuItem separatorItem]]; title = [@"Quit " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@/*"q"*/"q"]; /* Put menu into the menubar */ menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; [menuItem setSubmenu:appleMenu]; [[NSApp mainMenu] addItem:menuItem]; [menuItem release]; /* Tell the application object that this is now the application menu */ [NSApp setAppleMenu:appleMenu]; [appleMenu release]; } }; } #ifdef USE_DARWIN_COCOA_IMPLEMENTATION RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy; #endif // declare C entry point for static compilation. extern "C" void graphicswindow_Cocoa(void) { osg::GraphicsContext::setWindowingSystemInterface(new osgViewer::CocoaWindowingSystemInterface()); } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/Keystone.cpp0000644000175000017500000004763112232511235024300 0ustar albertoalberto/* OpenSceneGraph example, osgkeystone. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include #include #include using namespace osgViewer; Keystone::Keystone(): keystoneEditingEnabled(false), gridColour(1.0f,1.0f,1.0f,1.0f), bottom_left(-1.0,-1.0), bottom_right(1.0,-1.0), top_left(-1.0,1.0), top_right(1.0,1.0) {} Keystone::Keystone(const Keystone& rhs, const osg::CopyOp & copyop): osg::Object(rhs, copyop), keystoneEditingEnabled(rhs.keystoneEditingEnabled), gridColour(rhs.gridColour), bottom_left(rhs.bottom_left), bottom_right(rhs.bottom_right), top_left(rhs.top_left), top_right(rhs.top_right) {} void Keystone::reset() { bottom_left.set(-1.0,-1.0); bottom_right.set(1.0,-1.0); top_left.set(-1.0,1.0); top_right.set(1.0,1.0); } Keystone& Keystone::operator = (const Keystone& rhs) { if (&rhs==this) return *this; keystoneEditingEnabled = rhs.keystoneEditingEnabled; gridColour = rhs.gridColour; bottom_left = rhs.bottom_left; bottom_right = rhs.bottom_right; top_left = rhs.top_left; top_right = rhs.top_right; return *this; } void Keystone::compute3DPositions(osg::DisplaySettings* ds, osg::Vec3& tl, osg::Vec3& tr, osg::Vec3& br, osg::Vec3& bl) const { double tr_x = ((top_right-bottom_right).length()) / ((top_left-bottom_left).length()); double r_left = sqrt(tr_x); double r_right = r_left/tr_x; double tr_y = ((top_right-top_left).length()) / ((bottom_right-bottom_left).length()); double r_bottom = sqrt(tr_y); double r_top = r_bottom/tr_y; double screenDistance = ds->getScreenDistance(); double screenWidth = ds->getScreenWidth(); double screenHeight = ds->getScreenHeight(); tl = osg::Vec3(screenWidth*0.5*top_left.x(), screenHeight*0.5*top_left.y(), -screenDistance)*r_left*r_top; tr = osg::Vec3(screenWidth*0.5*top_right.x(), screenHeight*0.5*top_right.y(), -screenDistance)*r_right*r_top; br = osg::Vec3(screenWidth*0.5*bottom_right.x(), screenHeight*0.5*bottom_right.y(), -screenDistance)*r_right*r_bottom; bl = osg::Vec3(screenWidth*0.5*bottom_left.x(), screenHeight*0.5*bottom_left.y(), -screenDistance)*r_left*r_bottom; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Keystone helper functions // struct KeystoneCullCallback : public osg::Drawable::CullCallback { KeystoneCullCallback(Keystone* keystone=0):_keystone(keystone) {} KeystoneCullCallback(const KeystoneCullCallback&, const osg::CopyOp&) {} META_Object(osg,KeystoneCullCallback); /** do customized cull code, return true if drawable should be culled.*/ virtual bool cull(osg::NodeVisitor* /*nv*/, osg::Drawable* /*drawable*/, osg::RenderInfo* /*renderInfo*/) const { return _keystone.valid() ? !_keystone->getKeystoneEditingEnabled() : true; } osg::ref_ptr _keystone; }; struct KeystoneUpdateCallback : public osg::Drawable::UpdateCallback { KeystoneUpdateCallback(Keystone* keystone=0):_keystone(keystone) {} KeystoneUpdateCallback(const KeystoneUpdateCallback&, const osg::CopyOp&) {} META_Object(osg,KeystoneUpdateCallback); /** do customized update code.*/ virtual void update(osg::NodeVisitor*, osg::Drawable* drawable) { update(dynamic_cast(drawable)); } void update(osg::Geometry* geometry) { if (!geometry) return; osg::Vec3Array* vertices = dynamic_cast(geometry->getVertexArray()); if (!vertices) return; osg::Vec2Array* texcoords = dynamic_cast(geometry->getTexCoordArray(0)); if (!texcoords) return; osg::Vec3 tl, tr, br, bl; _keystone->compute3DPositions(osg::DisplaySettings::instance().get(), tl, tr, br, bl); for(unsigned int i=0; isize(); ++i) { osg::Vec3& v = (*vertices)[i]; osg::Vec2& t = (*texcoords)[i]; v = bl * ((1.0f-t.x())*(1.0f-t.y())) + br * ((t.x())*(1.0f-t.y())) + tl * ((1.0f-t.x())*(t.y())) + tr * ((t.x())*(t.y())); } geometry->dirtyBound(); } osg::ref_ptr _keystone; }; osg::Geode* Keystone::createKeystoneDistortionMesh() { osg::ref_ptr geode = new osg::Geode; osg::ref_ptr geometry = new osg::Geometry; geode->addDrawable(geometry.get()); geometry->setUseDisplayList(false); osg::ref_ptr kuc = new KeystoneUpdateCallback(this); geometry->setUpdateCallback(kuc.get()); osg::ref_ptr colours = new osg::Vec4Array; colours->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); geometry->setColorArray(colours.get(), osg::Array::BIND_OVERALL); osg::ref_ptr vertices = new osg::Vec3Array; geometry->setVertexArray(vertices.get()); osg::ref_ptr texcoords = new osg::Vec2Array; geometry->setTexCoordArray(0, texcoords.get()); unsigned int numRows = 7; unsigned int numColumns = 7; unsigned int numVertices = numRows*numColumns; vertices->resize(numVertices); texcoords->resize(numVertices); for(unsigned j=0; j(i)/static_cast(numColumns-1), static_cast(j)/static_cast(numRows-1)); } } osg::ref_ptr elements = new osg::DrawElementsUShort(GL_TRIANGLES); geometry->addPrimitiveSet(elements.get()); for(unsigned j=0; jpush_back(vi+numColumns); elements->push_back(vi); elements->push_back(vi+1); elements->push_back(vi+numColumns); elements->push_back(vi+1); elements->push_back(vi+1+numColumns); } } geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); geometry->getOrCreateStateSet()->setRenderBinDetails(0, "RenderBin"); geometry->getOrCreateStateSet()->setAttribute(new osg::PolygonMode(), osg::StateAttribute::ON|osg::StateAttribute::PROTECTED); kuc->update(geometry.get()); return geode.release(); } osg::Node* Keystone::createGrid() { osg::ref_ptr geode = new osg::Geode; osg::ref_ptr geometry = new osg::Geometry; geode->addDrawable(geometry.get()); geometry->setUseDisplayList(false); osg::ref_ptr kuc = new KeystoneUpdateCallback(this); geometry->setUpdateCallback(kuc.get()); geometry->setCullCallback(new KeystoneCullCallback(this)); osg::ref_ptr colours = new osg::Vec4Array; colours->push_back(getGridColor()); geometry->setColorArray(colours.get(), osg::Array::BIND_OVERALL); osg::ref_ptr vertices = new osg::Vec3Array; geometry->setVertexArray(vertices.get()); osg::ref_ptr texcoords = new osg::Vec2Array; geometry->setTexCoordArray(0, texcoords.get()); osg::Vec2 origin(0.0f, 0.0f); osg::Vec2 widthVector(1.0f, 0.0f); osg::Vec2 heightVector(0.0f, 1.0f); unsigned int numIntervals = 7; // border line { unsigned int vi = texcoords->size(); texcoords->push_back(origin); texcoords->push_back(origin+widthVector); texcoords->push_back(origin+widthVector+heightVector); texcoords->push_back(origin+heightVector); geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINE_LOOP, vi, 4)); } // cross lines { unsigned int vi = texcoords->size(); osg::Vec2 v = origin; osg::Vec2 dv = (widthVector+heightVector)/static_cast(numIntervals-1); for(unsigned int i=0; ipush_back(v); v += dv; } geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, vi, numIntervals)); vi = texcoords->size(); v = origin+heightVector; dv = (widthVector-heightVector)/static_cast(numIntervals-1); for(unsigned int i=0; ipush_back(v); v += dv; } geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, vi, numIntervals)); } // vertices lines { unsigned int vi = texcoords->size(); osg::Vec2 dv = widthVector/6.0; osg::Vec2 bv = origin+dv; osg::Vec2 tv = bv+heightVector; for(unsigned int i=0; i<5; ++i) { texcoords->push_back(bv); texcoords->push_back(tv); bv += dv; tv += dv; } geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINES, vi, 10)); } // horizontal lines { unsigned int vi = texcoords->size(); osg::Vec2 dv = heightVector/6.0; osg::Vec2 bv = origin+dv; osg::Vec2 tv = bv+widthVector; for(unsigned int i=0; i<5; ++i) { texcoords->push_back(bv); texcoords->push_back(tv); bv += dv; tv += dv; } geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINES, vi, 10)); } vertices->resize(texcoords->size()); geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); geometry->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); geometry->getOrCreateStateSet()->setRenderBinDetails(1, "RenderBin"); kuc->update(geometry.get()); return geode.release(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // KeystoneHandler // KeystoneHandler::KeystoneHandler(Keystone* keystone): _keystone(keystone), _defaultIncrement(0.0,0.0), _ctrlIncrement(1.0,1.0), _shiftIncrement(0.1,0.1), _keyIncrement(0.005, 0.005), _selectedRegion(NONE_SELECTED) { _startControlPoints = new Keystone; _currentControlPoints = keystone; //new Keystone; } KeystoneHandler::Region KeystoneHandler::computeRegion(const osgGA::GUIEventAdapter& ea) const { float x = ea.getXnormalized(); float y = ea.getYnormalized(); if (x<-0.33) { // left side if (y<-0.33) return BOTTOM_LEFT; else if (y<0.33) return LEFT; else return TOP_LEFT; } else if (x<0.33) { // center side if (y<-0.33) return BOTTOM; else if (y<0.33) return CENTER; else return TOP; } else { // right side if (y<-0.33) return BOTTOM_RIGHT; else if (y<0.33) return RIGHT; else return TOP_RIGHT; } return NONE_SELECTED; } void KeystoneHandler::move(Region region, const osg::Vec2d& delta) { switch(region) { case(TOP_LEFT): _currentControlPoints->getTopLeft() += delta; break; case(TOP): _currentControlPoints->getTopLeft() += delta; _currentControlPoints->getTopRight() += delta; break; case(TOP_RIGHT): _currentControlPoints->getTopRight() += delta; break; case(RIGHT): _currentControlPoints->getTopRight() += delta; _currentControlPoints->getBottomRight() += delta; break; case(BOTTOM_RIGHT): _currentControlPoints->getBottomRight() += delta; break; case(BOTTOM): _currentControlPoints->getBottomRight() += delta; _currentControlPoints->getBottomLeft() += delta; break; case(BOTTOM_LEFT): _currentControlPoints->getBottomLeft() += delta; break; case(LEFT): _currentControlPoints->getBottomLeft() += delta; _currentControlPoints->getTopLeft() += delta; break; case(CENTER): _currentControlPoints->getBottomLeft() += delta; _currentControlPoints->getTopLeft() += delta; _currentControlPoints->getBottomRight() += delta; _currentControlPoints->getTopRight() += delta; break; case(NONE_SELECTED): break; } } osg::Vec2d KeystoneHandler::incrementScale(const osgGA::GUIEventAdapter& ea) const { if (_ctrlIncrement!=osg::Vec2d(0.0,0.0) && (ea.getModKeyMask()==osgGA::GUIEventAdapter::MODKEY_LEFT_CTRL || ea.getModKeyMask()==osgGA::GUIEventAdapter::MODKEY_RIGHT_CTRL )) return _ctrlIncrement; if (_shiftIncrement!=osg::Vec2d(0.0,0.0) && (ea.getModKeyMask()==osgGA::GUIEventAdapter::MODKEY_LEFT_SHIFT || ea.getModKeyMask()==osgGA::GUIEventAdapter::MODKEY_RIGHT_SHIFT )) return _shiftIncrement; return _defaultIncrement; } bool KeystoneHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& /*aa*/, osg::Object* obj, osg::NodeVisitor* /*nv*/) { osg::Camera* camera = dynamic_cast(obj); osg::Viewport* viewport = camera ? camera->getViewport() : 0; if (!viewport) return false; if (ea.getEventType()==osgGA::GUIEventAdapter::KEYDOWN && ((ea.getModKeyMask()==osgGA::GUIEventAdapter::MODKEY_LEFT_CTRL || ea.getModKeyMask()==osgGA::GUIEventAdapter::MODKEY_RIGHT_CTRL))) { if (ea.getUnmodifiedKey()=='g') { setKeystoneEditingEnabled(!getKeystoneEditingEnabled()); return true; } if (ea.getUnmodifiedKey()=='r') { _selectedRegion = NONE_SELECTED; _startControlPoints->reset(); _currentControlPoints->reset(); return true; } else if (ea.getUnmodifiedKey()=='s') { _keystone->writeToFile(); return true; } } bool haveCameraMatch = false; float x = ea.getXnormalized(); float y = ea.getYnormalized(); for(unsigned int i=0; iobject==obj) { haveCameraMatch = true; x = pd->getXnormalized(); y = pd->getYnormalized(); break; } } if (!haveCameraMatch || !getKeystoneEditingEnabled()) return false; switch(ea.getEventType()) { case(osgGA::GUIEventAdapter::PUSH): { osg::Vec2d scale = incrementScale(ea); if (scale.length2()!=0.0) { _selectedRegion = computeRegion(ea); (*_startControlPoints) = (*_currentControlPoints); _startPosition.set(x,y); } else { _selectedRegion = NONE_SELECTED; } return false; } case(osgGA::GUIEventAdapter::DRAG): { if (_selectedRegion!=NONE_SELECTED) { (*_currentControlPoints) = (*_startControlPoints); osg::Vec2d currentPosition(x, y); osg::Vec2d delta(currentPosition-_startPosition); osg::Vec2d scale = incrementScale(ea); move(_selectedRegion, osg::Vec2d(delta.x()*scale.x(), delta.y()*scale.y()) ); return true; } return false; } case(osgGA::GUIEventAdapter::RELEASE): { _selectedRegion = NONE_SELECTED; return false; } case(osgGA::GUIEventAdapter::KEYDOWN): { if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Up) { move(computeRegion(ea), osg::Vec2d(0.0, _keyIncrement.y()*incrementScale(ea).y()) ); } else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Down) { move(computeRegion(ea), osg::Vec2d(0.0, -_keyIncrement.y()*incrementScale(ea).y()) ); } else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Left) { move(computeRegion(ea), osg::Vec2d(-_keyIncrement.x()*incrementScale(ea).x(), 0.0) ); } else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Right) { move(computeRegion(ea), osg::Vec2d(_keyIncrement.x()*incrementScale(ea).x(), 0.0) ); } else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_7 || ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Home) { _currentControlPoints->setTopLeft(osg::Vec2d(x, y)); } else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_9 || ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Page_Up) { _currentControlPoints->setTopRight(osg::Vec2d(x, y)); } else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_3 || ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Page_Down) { _currentControlPoints->setBottomRight(osg::Vec2d(x, y)); } else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_1 || ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_End) { _currentControlPoints->setBottomLeft(osg::Vec2d(x, y)); } return false; } default: return false; } } bool Keystone::writeToFile() { std::string filename; if (getUserDataContainer()!=0 && getUserValue("filename", filename)) { // we don't want to write the UDC to the keystone file so take a reference to it, and set the pointer to NULL. osg::ref_ptr temp_udc = getUserDataContainer(); setUserDataContainer(0); OSG_NOTICE<<"Writing keystone to: "<getKeystoneFileNames().empty()) { for(osg::DisplaySettings::FileNames::iterator itr = ds->getKeystoneFileNames().begin(); itr != ds->getKeystoneFileNames().end(); ++itr) { const std::string& filename = *itr; osg::ref_ptr keystone = osgDB::readFile(filename); if (keystone.valid()) { keystone->setUserValue("filename",filename); ds->getKeystones().push_back(keystone.get()); keystonesLoaded = true; } else { OSG_NOTICE<<"Creating Keystone for filename entry: "<setUserValue("filename",filename); ds->getKeystones().push_back(keystone.get()); keystonesLoaded = true; } } } return keystonesLoaded; } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/PixelBufferCocoa.mm0000644000175000017500000000756312434646657025533 0ustar albertoalberto/* * PixelBufferCocoa.cpp * OpenSceneGraph * * Created by Stephan Huber on 27.06.08. * Copyright 2008 Stephan Maximilian Huber, digital mind. All rights reserved. * */ #include #include #include #include namespace osgViewer { void PixelBufferCocoa::init() { //std::cout << "PixelBufferCocoa :: init not implemented yet " << std::endl; _valid = _initialized = true; } bool PixelBufferCocoa::realizeImplementation() { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSOpenGLPixelFormatAttribute attr[32]; int i = 0; attr[i++] = NSOpenGLPFADepthSize; attr[i++] = static_cast(_traits->depth); if (_traits->doubleBuffer) { attr[i++] = NSOpenGLPFADoubleBuffer; } if (_traits->alpha) { attr[i++] = NSOpenGLPFAAlphaSize; attr[i++] = static_cast(_traits->alpha); } if (_traits->stencil) { attr[i++] = NSOpenGLPFAStencilSize; attr[i++] = static_cast(_traits->stencil); } if (_traits->sampleBuffers) { attr[i++] = NSOpenGLPFASampleBuffers; attr[i++] = static_cast(_traits->sampleBuffers); attr[i++] = NSOpenGLPFASamples; attr[i++] = static_cast(_traits->samples); } attr[i++] = NSOpenGLPFAPixelBuffer; // for pbuffer usage attr[i++] = NSOpenGLPFAAccelerated; attr[i] = static_cast(0); // create the context NSOpenGLContext* sharedContext = NULL; GraphicsHandleCocoa* graphicsHandleCocoa = dynamic_cast(_traits->sharedContext.get()); if (graphicsHandleCocoa) { sharedContext = graphicsHandleCocoa->getNSOpenGLContext(); } NSOpenGLPixelFormat* pixelformat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr ]; _context = [[NSOpenGLContext alloc] initWithFormat: pixelformat shareContext: sharedContext]; NSOpenGLPixelBuffer* pbuffer = [[NSOpenGLPixelBuffer alloc] initWithTextureTarget: _traits->target textureInternalFormat: _traits->format textureMaxMipMapLevel: _traits->level pixelsWide: _traits->width pixelsHigh: _traits->height]; [_context setPixelBuffer: pbuffer cubeMapFace: _traits->face mipMapLevel:_traits->level currentVirtualScreen: 0]; [pool release]; _realized = (_context != nil); return _realized; } void PixelBufferCocoa::closeImplementation() { _realized = false; } /** Make this graphics context current.*/ bool PixelBufferCocoa::makeCurrentImplementation() { // OSG_INFO << "PixelBufferCocoa::makeCurrentImplementation" << std::endl; [_context makeCurrentContext]; return true; } /** Make this graphics context current with specified read context implementation. */ bool PixelBufferCocoa::makeContextCurrentImplementation(osg::GraphicsContext* readContext) { return makeCurrentImplementation(); } /** Release the graphics context.*/ bool PixelBufferCocoa::releaseContextImplementation() { // OSG_INFO << "PixelBufferCocoa::releaseContextImplementation" << std::endl; [NSOpenGLContext clearCurrentContext]; return true; } /** Bind the graphics context to associated texture implementation.*/ void PixelBufferCocoa::bindPBufferToTextureImplementation( GLenum buffer ) { std::cout << "PixelBufferCocoa :: bindPBufferToTextureImplementation not implemented yet " << std::endl; } /** Swap the front and back buffers.*/ void PixelBufferCocoa::swapBuffersImplementation() { OSG_INFO << "PixelBufferCocoa::swapBuffersImplementation" << std::endl; [_context flushBuffer]; } PixelBufferCocoa::~PixelBufferCocoa() { [_context release]; } } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/GraphicsWindowCarbon.cpp0000644000175000017500000011642212147632176026564 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #if defined (__APPLE__) && (!__LP64__) #include #include #include #include #include #include #include #include "DarwinUtils.h" using namespace osgViewer; using namespace osgDarwin; // Carbon-Eventhandler to handle the click in the close-widget and the resize of windows static pascal OSStatus GraphicsWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void* userData) { WindowRef window; Rect bounds; OSStatus result = eventNotHandledErr; /* report failure by default */ OSG_INFO << "GraphicsWindowEventHandler" << std::endl; GraphicsWindowCarbon* w = (GraphicsWindowCarbon*)userData; if (!w) return result; GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(window), NULL, &window); switch(GetEventClass(event)) { case kEventClassTablet: case kEventClassMouse: if (w->handleMouseEvent(event)) result = noErr; break; case kEventClassKeyboard: if (w->handleKeyboardEvent(event)) result = noErr; break; case kEventClassWindow: { switch (GetEventKind(event)) { case kEventWindowBoundsChanging: // left the code for live-resizing, but it is not used, because of window-refreshing issues... GetEventParameter( event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &bounds ); w->adaptResize(bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top); w->requestRedraw(); result = noErr; break; case kEventWindowBoundsChanged: InvalWindowRect(window, GetWindowPortBounds(window, &bounds)); GetWindowBounds(window, kWindowContentRgn, &bounds); w->adaptResize(bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top); result = noErr; break; case kEventWindowClose: w->requestClose(); result = noErr; break; default: break; } } default: //std::cout << "unknown: " << GetEventClass(event) << std::endl; break; } //if (result == eventNotHandledErr) // result = CallNextEventHandler (nextHandler, event); return result; } static bool s_quit_requested = false; // Application eventhandler -- listens for a quit-event static pascal OSStatus ApplicationEventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) { HICommand commandStruct; OSErr err = eventNotHandledErr; GetEventParameter (inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &commandStruct); switch(commandStruct.commandID) { case kHICommandQuit: s_quit_requested = true; err = noErr; break; } return err; } // AppleEventHandler, listens to the Quit-AppleEvent static pascal OSErr QuitAppleEventHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon ) { s_quit_requested = true; return (noErr); } namespace osgViewer { // small helper class which maps the raw key codes to osgGA::GUIEventAdapter::Keys class CarbonKeyboardMap { public: CarbonKeyboardMap() { _keymap[53 ] = osgGA::GUIEventAdapter::KEY_Escape; _keymap[115 ] = osgGA::GUIEventAdapter::KEY_Home; _keymap[76 ] = osgGA::GUIEventAdapter::KEY_KP_Enter; _keymap[119 ] = osgGA::GUIEventAdapter::KEY_End; _keymap[36 ] = osgGA::GUIEventAdapter::KEY_Return; _keymap[116 ] = osgGA::GUIEventAdapter::KEY_Page_Up; _keymap[121 ] = osgGA::GUIEventAdapter::KEY_Page_Down; _keymap[123 ] = osgGA::GUIEventAdapter::KEY_Left; _keymap[124 ] = osgGA::GUIEventAdapter::KEY_Right; _keymap[126 ] = osgGA::GUIEventAdapter::KEY_Up; _keymap[125 ] = osgGA::GUIEventAdapter::KEY_Down; _keymap[51 ] = osgGA::GUIEventAdapter::KEY_BackSpace; _keymap[48 ] = osgGA::GUIEventAdapter::KEY_Tab; _keymap[49 ] = osgGA::GUIEventAdapter::KEY_Space; _keymap[117 ] = osgGA::GUIEventAdapter::KEY_Delete; _keymap[122 ] = osgGA::GUIEventAdapter::KEY_F1; _keymap[120 ] = osgGA::GUIEventAdapter::KEY_F2; _keymap[99 ] = osgGA::GUIEventAdapter::KEY_F3; _keymap[118 ] = osgGA::GUIEventAdapter::KEY_F4; _keymap[96 ] = osgGA::GUIEventAdapter::KEY_F5; _keymap[97 ] = osgGA::GUIEventAdapter::KEY_F6; _keymap[98 ] = osgGA::GUIEventAdapter::KEY_F7; _keymap[100 ] = osgGA::GUIEventAdapter::KEY_F8; _keymap[101 ] = osgGA::GUIEventAdapter::KEY_F9; _keymap[109 ] = osgGA::GUIEventAdapter::KEY_F10; _keymap[103 ] = osgGA::GUIEventAdapter::KEY_F11; _keymap[111 ] = osgGA::GUIEventAdapter::KEY_F12; _keymap[75 ] = osgGA::GUIEventAdapter::KEY_KP_Divide; _keymap[67 ] = osgGA::GUIEventAdapter::KEY_KP_Multiply; _keymap[78 ] = osgGA::GUIEventAdapter::KEY_KP_Subtract; _keymap[69 ] = osgGA::GUIEventAdapter::KEY_KP_Add; _keymap[89 ] = osgGA::GUIEventAdapter::KEY_KP_Home; _keymap[91 ] = osgGA::GUIEventAdapter::KEY_KP_Up; _keymap[92 ] = osgGA::GUIEventAdapter::KEY_KP_Page_Up; _keymap[86 ] = osgGA::GUIEventAdapter::KEY_KP_Left; _keymap[87 ] = osgGA::GUIEventAdapter::KEY_KP_Begin; _keymap[88 ] = osgGA::GUIEventAdapter::KEY_KP_Right; _keymap[83 ] = osgGA::GUIEventAdapter::KEY_KP_End; _keymap[84 ] = osgGA::GUIEventAdapter::KEY_KP_Down; _keymap[85 ] = osgGA::GUIEventAdapter::KEY_KP_Page_Down; _keymap[82 ] = osgGA::GUIEventAdapter::KEY_KP_Insert; _keymap[65 ] = osgGA::GUIEventAdapter::KEY_KP_Delete; } ~CarbonKeyboardMap() { } unsigned int remapKey(unsigned int key, unsigned int rawkey) { KeyMap::iterator itr = _keymap.find(rawkey); if (itr == _keymap.end()) return key; else return itr->second; } private: typedef std::map KeyMap; KeyMap _keymap; }; /** remaps a native os x keycode to a GUIEventAdapter-keycode */ static unsigned int remapCarbonKey(unsigned int key, unsigned int rawkey) { static CarbonKeyboardMap s_CarbonKeyboardMap; return s_CarbonKeyboardMap.remapKey(key,rawkey); } class CarbonWindowAdapter : public MenubarController::WindowAdapter { public: CarbonWindowAdapter(GraphicsWindowCarbon* win) : MenubarController::WindowAdapter(), _win(win) {} virtual bool valid() {return (_win.valid() && _win->valid()); } virtual void getWindowBounds(CGRect& rect) { Rect windowBounds; OSErr error = GetWindowBounds(_win->getNativeWindowRef(), kWindowStructureRgn, &windowBounds); rect.origin.x = windowBounds.left; rect.origin.y = windowBounds.top; rect.size.width = windowBounds.right - windowBounds.left; rect.size.height = windowBounds.bottom - windowBounds.top; } osgViewer::GraphicsWindow* getWindow() { return _win.get(); } private: osg::observer_ptr _win; }; void GraphicsWindowCarbon::init() { if (_initialized) return; // getEventQueue()->setCurrentEventState(osgGA::GUIEventAdapter::getAccumulatedEventState().get()); _lastModifierKeys = 0; _windowTitleHeight = 0; _closeRequested = false; _ownsWindow = false; _context = NULL; _window = NULL; _pixelFormat = PixelBufferCarbon::createPixelFormat(_traits.get()); if (!_pixelFormat) { OSG_WARN << "GraphicsWindowCarbon::init could not create a valid pixelformat" << std::endl; } _valid = (_pixelFormat != NULL); _initialized = true; // make sure the event queue has the correct window rectangle size and input range getEventQueue()->syncWindowRectangleWithGraphcisContext(); } bool GraphicsWindowCarbon::setWindowDecorationImplementation(bool flag) { _useWindowDecoration = flag; if (_realized) { OSErr err = noErr; Rect bounds; GetWindowBounds(getNativeWindowRef(), kWindowContentRgn, &bounds); if (_useWindowDecoration) { err = ChangeWindowAttributes(getNativeWindowRef(), kWindowStandardDocumentAttributes, kWindowNoTitleBarAttribute | kWindowNoShadowAttribute); SetWindowBounds(getNativeWindowRef(), kWindowContentRgn, &bounds); } else { err = ChangeWindowAttributes(getNativeWindowRef(), kWindowNoTitleBarAttribute | kWindowNoShadowAttribute, kWindowStandardDocumentAttributes); SetWindowBounds(getNativeWindowRef(), kWindowContentRgn, &bounds); } if (err != noErr) { OSG_WARN << "GraphicsWindowCarbon::setWindowDecoration failed with " << err << std::endl; return false; } // update titlebar-height Rect titleRect; GetWindowBounds(_window, kWindowTitleBarRgn, &titleRect); _windowTitleHeight = abs(titleRect.bottom - titleRect.top); // sth: I don't know why I have to reattach the context to the window here, If I don't do this I get blank areas, where the titlebar was. // InvalWindowRect doesn't help here :-/ aglSetDrawable(_context, 0); aglSetDrawable(_context, GetWindowPort(_window)); MenubarController::instance()->update(); } return true; } WindowAttributes GraphicsWindowCarbon::computeWindowAttributes(bool useWindowDecoration, bool supportsResize) { WindowAttributes attr; if (useWindowDecoration) { if (supportsResize) attr = (kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute); else attr = (kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute) & ~kWindowResizableAttribute; } else { attr = kWindowNoTitleBarAttribute | kWindowNoShadowAttribute | kWindowStandardHandlerAttribute; if (supportsResize) attr |= kWindowResizableAttribute; } return attr; } void GraphicsWindowCarbon::installEventHandler() { // register window event handler to receive resize-events EventTypeSpec windEventList[] = { { kEventClassWindow, kEventWindowBoundsChanged}, { kEventClassWindow, kEventWindowClose}, {kEventClassMouse, kEventMouseDown}, {kEventClassMouse, kEventMouseUp}, {kEventClassMouse, kEventMouseMoved}, {kEventClassMouse, kEventMouseDragged}, {kEventClassMouse, kEventMouseWheelMoved}, {kEventClassMouse, 11 /* kEventMouseScroll */}, {kEventClassKeyboard, kEventRawKeyDown}, {kEventClassKeyboard, kEventRawKeyRepeat}, {kEventClassKeyboard, kEventRawKeyUp}, {kEventClassKeyboard, kEventRawKeyModifiersChanged}, {kEventClassKeyboard, kEventHotKeyPressed}, {kEventClassKeyboard, kEventHotKeyReleased}, }; InstallWindowEventHandler(_window, NewEventHandlerUPP(GraphicsWindowEventHandler), GetEventTypeCount(windEventList), windEventList, this, NULL); } bool GraphicsWindowCarbon::realizeImplementation() { if (!_initialized) init(); if (!_initialized) return false; if (!_traits) return false; OSG_INFO << "GraphicsWindowCarbon::realizeImplementation" << std::endl; setWindowDecoration(_traits->windowDecoration); useCursor(_traits->useCursor); // move the window to the right screen DarwinWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); int screenLeft = 0, screenTop = 0; if (wsi) { wsi->getScreenTopLeft((*_traits), screenLeft, screenTop); } WindowData *windowData = ( _traits.get() && _traits->inheritedWindowData.get() ) ? static_cast(_traits->inheritedWindowData.get()) : 0; _ownsWindow = (windowData) ? (windowData->getNativeWindowRef() == NULL) : true; if (_ownsWindow) { // create the window Rect bounds = {_traits->y + screenTop, _traits->x + screenLeft, _traits->y + _traits->height + screenTop, _traits->x + _traits->width + screenLeft}; OSStatus err = 0; WindowAttributes attr = computeWindowAttributes(_useWindowDecoration, _traits->supportsResize); err = CreateNewWindow(kDocumentWindowClass, attr, &bounds, &_window); if (err) { OSG_WARN << "GraphicsWindowCarbon::realizeImplementation: failed to create window: " << err << std::endl; return false; } else { OSG_INFO << "GraphicsWindowCarbon::realizeImplementation: window created with bounds(" << bounds.top << ", " << bounds.left << ", " << bounds.bottom << ", " << bounds.right << ")" << std::endl; } } else { _window = windowData->getNativeWindowRef(); } Rect titleRect; GetWindowBounds(_window, kWindowTitleBarRgn, &titleRect); _windowTitleHeight = abs(titleRect.bottom - titleRect.top); if ((_ownsWindow) || (windowData && windowData->installEventHandler())) installEventHandler(); // set the window title setWindowName(_traits->windowName); // create the context AGLContext sharedContextCarbon = NULL; GraphicsHandleCarbon* graphicsHandleCarbon = dynamic_cast(_traits->sharedContext.get()); if (graphicsHandleCarbon) { sharedContextCarbon = graphicsHandleCarbon->getAGLContext(); } _context = aglCreateContext (_pixelFormat, sharedContextCarbon); if (!_context) { OSG_WARN << "GraphicsWindowCarbon::realizeImplementation: failed to create context: " << aglGetError() << std::endl; return false; } if ( windowData && windowData->getAGLDrawable() ) { aglSetDrawable(_context, (AGLDrawable)*(windowData->getAGLDrawable()) ); } else { aglSetDrawable(_context, GetWindowPort(_window)); ShowWindow(_window); MenubarController::instance()->attachWindow( new CarbonWindowAdapter(this) ); } makeCurrent(); if ((_traits->useMultiThreadedOpenGLEngine) && (OpenThreads::GetNumberOfProcessors() > 1)) { // enable Multi-threaded OpenGL Execution: CGLError cgerr = kCGLNoError; CGLContextObj ctx = CGLGetCurrentContext(); #if 0 cgerr = CGLEnable( ctx, kCGLCEMPEngine); #else // the above use of kCGLCEMPEngine is not backwards compatible // so we'll use the raw value of it to keep things compiling on older // versions of OSX. cgerr = CGLEnable( ctx, static_cast (313) ); #endif if (cgerr != kCGLNoError ) { OSG_INFO << "GraphicsWindowCarbon::realizeImplementation: multi-threaded OpenGL Execution not available" << std::endl; } } InitCursor(); // enable vsync if (_traits->vsync) { GLint swap = 1; aglSetInteger (_context, AGL_SWAP_INTERVAL, &swap); } _currentVSync = _traits->vsync; _realized = true; // make sure the event queue has the correct window rectangle size and input range getEventQueue()->syncWindowRectangleWithGraphcisContext(); return _realized; } bool GraphicsWindowCarbon::makeCurrentImplementation() { return (aglSetCurrentContext(_context) == GL_TRUE); } bool GraphicsWindowCarbon::releaseContextImplementation() { if (!_realized) { OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<detachWindow(this); if (_pixelFormat) { aglDestroyPixelFormat(_pixelFormat); _pixelFormat = NULL; } if (_context) { aglSetDrawable(_context, NULL); aglSetCurrentContext(NULL); aglDestroyContext(_context); _context = NULL; } if (_ownsWindow && _window) DisposeWindow(_window); _window = NULL; } void GraphicsWindowCarbon::swapBuffersImplementation() { // check for vsync change if (_traits.valid() && _traits->vsync != _currentVSync) { const bool on = _traits->vsync; GLint swap = (on ? 1 : 0); aglSetInteger (_context, AGL_SWAP_INTERVAL, &swap); OSG_NOTICE << "GraphicsWindowCarbon: VSync=" << (on ? "on" : "off") << std::endl; _currentVSync = on; } aglSwapBuffers(_context); } void GraphicsWindowCarbon::resizedImplementation(int x, int y, int width, int height) { GraphicsContext::resizedImplementation(x, y, width, height); aglUpdateContext(_context); MenubarController::instance()->update(); getEventQueue()->windowResize(x,y,width, height, getEventQueue()->getTime()); } bool GraphicsWindowCarbon::handleMouseEvent(EventRef theEvent) { static unsigned int lastEmulatedMouseButton = 0; // mouse down event Point wheresMyMouse; GetEventParameter (theEvent, kEventParamWindowMouseLocation, typeQDPoint, NULL, sizeof(wheresMyMouse), NULL, &wheresMyMouse); wheresMyMouse.v -= _windowTitleHeight; if (_useWindowDecoration && (wheresMyMouse.v < 0)) return false; Point wheresMyMouseGlobal; GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(wheresMyMouse), NULL, &wheresMyMouseGlobal); EventMouseButton mouseButton = 0; GetEventParameter (theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(mouseButton), NULL, &mouseButton); UInt32 modifierKeys; GetEventParameter (theEvent,kEventParamKeyModifiers,typeUInt32, NULL,sizeof(modifierKeys), NULL,&modifierKeys); WindowRef win; int fwres = FindWindow(wheresMyMouseGlobal, &win); // return false when Window is inactive; For enabling click-to-active on window by delegating event to default handler if (((fwres != inContent) && (fwres > 0) && (mouseButton >= 1)) || !IsWindowActive(win)) { return false; } else { UInt32 clickCount; GetEventParameter(theEvent, kEventParamClickCount, typeUInt32, NULL, sizeof(clickCount), NULL, &clickCount); // swap right and middle buttons so that middle button is 2, right button is 3. if (mouseButton==3) mouseButton = 2; else if (mouseButton==2) mouseButton = 3; // check tablet pointer device and map it to a mouse button TabletProximityRec theTabletRecord; // The Tablet Proximity Record // Extract the Tablet Proximity reccord from the event. if(noErr == GetEventParameter(theEvent, kEventParamTabletProximityRec, typeTabletProximityRec, NULL, sizeof(TabletProximityRec), NULL, (void *)&theTabletRecord)) { osgGA::GUIEventAdapter::TabletPointerType pointerType; switch(theTabletRecord.pointerType) { case 1: // pen pointerType = osgGA::GUIEventAdapter::PEN; break; case 2: // puck pointerType = osgGA::GUIEventAdapter::PUCK; break; case 3: // eraser pointerType = osgGA::GUIEventAdapter::ERASER; break; default: pointerType = osgGA::GUIEventAdapter::UNKNOWN; break; } getEventQueue()->penProximity(pointerType, (theTabletRecord.enterProximity != 0)); } // get tilt and rotation from the pen TabletPointRec theTabletPointRecord; if(noErr == GetEventParameter(theEvent, kEventParamTabletPointRec, typeTabletPointRec, NULL, sizeof(TabletPointRec), NULL, (void *)&theTabletPointRecord)) { int penRotation = (int)theTabletPointRecord.rotation * 9 / 575; //to get angle between 0 to 360 grad penRotation = -(((penRotation + 180) % 360) - 180) ; //for same range on all plattforms we need -180 to 180 getEventQueue()->penOrientation ( theTabletPointRecord.tiltX * 60 / 32767.0f, //multiply with 60 to get angle between -60 to 60 grad -theTabletPointRecord.tiltY * 60 / 32767.0f, //multiply with 60 to get angle between -60 to 60 grad penRotation ); } switch(GetEventKind(theEvent)) { case kEventMouseDown: { float mx = wheresMyMouse.h; float my = wheresMyMouse.v; transformMouseXY(mx, my); lastEmulatedMouseButton = 0; if (mouseButton == 1) { if( modifierKeys & cmdKey ) { mouseButton = lastEmulatedMouseButton = 3; } else if( modifierKeys & optionKey ) { mouseButton = lastEmulatedMouseButton = 2; } } if (clickCount > 1) getEventQueue()->mouseDoubleButtonPress(mx,my, mouseButton); else getEventQueue()->mouseButtonPress(mx, my, mouseButton); } break; case kEventMouseUp: { float mx = wheresMyMouse.h; float my = wheresMyMouse.v; transformMouseXY(mx, my); if (lastEmulatedMouseButton > 0) { getEventQueue()->mouseButtonRelease(mx, my, lastEmulatedMouseButton); lastEmulatedMouseButton = 0; } else { getEventQueue()->mouseButtonRelease(mx, my, mouseButton); } } break; case kEventMouseDragged: { // get pressure from the pen, only when mouse/pen is dragged TabletPointRec theTabletRecord; if(noErr == GetEventParameter(theEvent, kEventParamTabletPointRec, typeTabletPointRec, NULL, sizeof(TabletPointRec), NULL, (void *)&theTabletRecord)) { getEventQueue()->penPressure(theTabletRecord.pressure / 65535.0f); } float mx = wheresMyMouse.h; float my = wheresMyMouse.v; transformMouseXY(mx, my); getEventQueue()->mouseMotion(mx, my); } break; case kEventMouseMoved: { float mx = wheresMyMouse.h; float my = wheresMyMouse.v; transformMouseXY(mx, my); getEventQueue()->mouseMotion(mx, my); } break; // mouse with scroll-wheels case kEventMouseWheelMoved: { EventMouseWheelAxis axis; SInt32 delta; if (noErr == GetEventParameter( theEvent, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(axis), NULL, &axis )) { if (noErr == GetEventParameter( theEvent, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(delta), NULL, &delta )) { switch (axis) { case kEventMouseWheelAxisX: getEventQueue()->mouseScroll( (delta > 0) ? osgGA::GUIEventAdapter::SCROLL_RIGHT : osgGA::GUIEventAdapter::SCROLL_LEFT); break; case kEventMouseWheelAxisY: getEventQueue()->mouseScroll( (delta < 0) ? osgGA::GUIEventAdapter::SCROLL_DOWN : osgGA::GUIEventAdapter::SCROLL_UP); break; } } } } break; // new trackpads and mighty mouse, (not officially documented, see http://developer.apple.com/qa/qa2005/qa1453.html ) case 11: { enum { kEventParamMouseWheelSmoothVerticalDelta = 'saxy', // typeSInt32 kEventParamMouseWheelSmoothHorizontalDelta = 'saxx' // typeSInt32 }; SInt32 scroll_delta_x = 0; SInt32 scroll_delta_y = 0; OSErr err = noErr; err = GetEventParameter( theEvent, kEventParamMouseWheelSmoothVerticalDelta, typeLongInteger, NULL, sizeof(scroll_delta_y), NULL, &scroll_delta_y ); err = GetEventParameter( theEvent, kEventParamMouseWheelSmoothHorizontalDelta, typeLongInteger, NULL, sizeof(scroll_delta_x), NULL, &scroll_delta_x ); if ((scroll_delta_x != 0) || (scroll_delta_y != 0)) { getEventQueue()->mouseScroll2D( scroll_delta_x, scroll_delta_y); } } break; default: return false; } } return true; } bool GraphicsWindowCarbon::handleKeyboardEvent(EventRef theEvent) { handleModifierKeys(theEvent); OSStatus status; UInt32 rawkey; GetEventParameter (theEvent,kEventParamKeyCode,typeUInt32, NULL,sizeof(rawkey), NULL,&rawkey); // OSG_INFO << "key code: " << rawkey << " modifiers: " << modifierKeys << std::endl; UInt32 dataSize; /* jbw check return status so that we don't allocate a huge array */ status = GetEventParameter( theEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL, 0, &dataSize, NULL ); if (status != noErr) return false; if (dataSize<=1) return false; UniChar* uniChars = new UniChar[dataSize+1]; GetEventParameter( theEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL, dataSize, NULL, (void*)uniChars ); unsigned int keychar = remapCarbonKey(static_cast(uniChars[0]), rawkey); switch(GetEventKind(theEvent)) { case kEventRawKeyDown: case kEventRawKeyRepeat: { //OSG_INFO << "GraphicsWindowCarbon::keyPress Up" << std::endl; //getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask); //OSG_INFO << "GraphicsWindowCarbon::keyPress" << std::endl; getEventQueue()->keyPress(keychar); break; } case kEventRawKeyUp: { //OSG_INFO << "GraphicsWindowCarbon::keyPress" << std::endl; //getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask); getEventQueue()->keyRelease(keychar); break; } default: break; } delete[] uniChars; return true; } void GraphicsWindowCarbon::handleModifierKey(UInt32 modifierKey, UInt32 modifierMask, osgGA::GUIEventAdapter::KeySymbol keySymbol) { if ((modifierKey & modifierMask) && !(_lastModifierKeys & modifierMask)) { getEventQueue()->keyPress(keySymbol); } if (!(modifierKey & modifierMask) && (_lastModifierKeys & modifierMask)) { getEventQueue()->keyRelease(keySymbol); } } bool GraphicsWindowCarbon::handleModifierKeys(EventRef theEvent) { UInt32 modifierKeys; GetEventParameter (theEvent,kEventParamKeyModifiers,typeUInt32, NULL,sizeof(modifierKeys), NULL,&modifierKeys); //std::cout << modifierKeys << std::endl; if (_lastModifierKeys == modifierKeys) return false; handleModifierKey(modifierKeys, shiftKey, osgGA::GUIEventAdapter::KEY_Shift_L); handleModifierKey(modifierKeys, controlKey, osgGA::GUIEventAdapter::KEY_Control_L); handleModifierKey(modifierKeys, optionKey, osgGA::GUIEventAdapter::KEY_Alt_L); handleModifierKey(modifierKeys, cmdKey, osgGA::GUIEventAdapter::KEY_Super_L); // Caps lock needs some special handling, i did not find a way to get informed when the caps-lock-key gets released if ((modifierKeys & alphaLock) && !(_lastModifierKeys & alphaLock)) { getEventQueue()->keyPress(osgGA::GUIEventAdapter::KEY_Caps_Lock); getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KEY_Caps_Lock); } if (!(modifierKeys & alphaLock) && (_lastModifierKeys & alphaLock)) { getEventQueue()->keyPress(osgGA::GUIEventAdapter::KEY_Caps_Lock); getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KEY_Caps_Lock); } _lastModifierKeys = modifierKeys; return true; } bool GraphicsWindowCarbon::checkEvents() { if (!_realized) return false; EventRef theEvent; EventTargetRef theTarget = GetEventDispatcherTarget(); while (ReceiveNextEvent(0, NULL, 0,true, &theEvent)== noErr) { switch(GetEventClass(theEvent)) { case kEventClassMouse: { // handle the menubar Point wheresMyMouse; GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(wheresMyMouse), NULL, &wheresMyMouse); EventMouseButton mouseButton = 0; GetEventParameter (theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(mouseButton), NULL, &mouseButton); WindowRef win; int fwres = FindWindow(wheresMyMouse, &win); if ((fwres == inMenuBar) && (mouseButton >= 1)) { MenuSelect(wheresMyMouse); HiliteMenu(0); return !(getEventQueue()->empty()); } break; } case kEventClassApplication: switch (GetEventKind(theEvent)) { case kEventAppQuit: getEventQueue()->quitApplication(); break; } break; case kEventClassAppleEvent: { EventRecord eventRecord; ConvertEventRefToEventRecord(theEvent, &eventRecord); AEProcessAppleEvent(&eventRecord); return; } break; } SendEventToEventTarget (theEvent, theTarget); ReleaseEvent(theEvent); } if (_closeRequested) getEventQueue()->closeWindow(); if (s_quit_requested) { getEventQueue()->quitApplication(); s_quit_requested = false; } return !(getEventQueue()->empty()); } bool GraphicsWindowCarbon::setWindowRectangleImplementation(int x, int y, int width, int height) { int screenLeft(0), screenTop(0); DarwinWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); if (wsi) { wsi->getScreenTopLeft((*_traits), screenLeft, screenTop); } Rect bounds = {y + screenTop, x + screenLeft, y + height + screenTop, x + width + screenLeft}; SetWindowBounds(getNativeWindowRef(), kWindowContentRgn, &bounds); aglUpdateContext(_context); MenubarController::instance()->update(); return true; } void GraphicsWindowCarbon::adaptResize(int x, int y, int w, int h) { DarwinWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); int screenLeft(0), screenTop(0); if (wsi) { // get the screen containing the window unsigned int screenNdx = wsi->getScreenContaining(x,y,w,h); // update traits _traits->screenNum = screenNdx; // get top left of screen wsi->getScreenTopLeft((*_traits), screenLeft, screenTop); } resized(x-screenLeft,y-screenTop,w,h); } void GraphicsWindowCarbon::grabFocus() { SelectWindow(_window); } void GraphicsWindowCarbon::grabFocusIfPointerInWindow() { // TODO: implement OSG_NOTIFY(osg::ALWAYS) << "GraphicsWindowCarbon::grabFocusIfPointerInWindow: not implemented" << std::endl; } void GraphicsWindowCarbon::useCursor(bool cursorOn) { if (_traits.valid()) _traits->useCursor = cursorOn; DarwinWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); if (wsi == NULL) { OSG_WARN << "GraphicsWindowCarbon::useCursor: could not get OSXCarbonWindowingSystemInterface" << std::endl; return; } CGDirectDisplayID displayId = wsi->getDisplayID((*_traits)); CGDisplayErr err = (cursorOn ? CGDisplayShowCursor(displayId) : CGDisplayHideCursor(displayId)); if (err != kCGErrorSuccess) { OSG_WARN << "GraphicsWindowCarbon::useCursor: failed with " << err << std::endl; } } // FIXME: need to implement all cursor types // FIXME: I used deprecated functions, but don't know if there are any substitutable newer functions... void GraphicsWindowCarbon::setCursor(MouseCursor mouseCursor) { if (_currentCursor == mouseCursor) return; UInt32 cursor; switch (mouseCursor) { case NoCursor: HideCursor(); _currentCursor = mouseCursor; return; case RightArrowCursor: cursor = kThemeArrowCursor; break; case CrosshairCursor: cursor = kThemeCrossCursor; break; case TextCursor: cursor = kThemeIBeamCursor; break; case UpDownCursor: cursor = kThemeResizeUpDownCursor; break; case LeftRightCursor: cursor = kThemeResizeLeftRightCursor; break; default: cursor = kThemeArrowCursor; OSG_WARN << "GraphicsWindowCarbon::setCursor doesn't implement cursor: type = " << mouseCursor << std::endl; } _currentCursor = mouseCursor; SetThemeCursor(cursor); ShowCursor(); } void GraphicsWindowCarbon::setSyncToVBlank(bool on) { if (_traits.valid()) { _traits->vsync = on; } } void GraphicsWindowCarbon::setWindowName (const std::string& name) { _traits->windowName = name; if (!_traits->windowName.empty()) { CFStringRef windowtitle = CFStringCreateWithBytes( kCFAllocatorDefault, (const UInt8*)(_traits->windowName.c_str()), _traits->windowName.length(),kCFStringEncodingUTF8, false ); SetWindowTitleWithCFString( _window, windowtitle ); CFRelease(windowtitle); } } void GraphicsWindowCarbon::requestWarpPointer(float x,float y) { if (!_realized) { OSG_INFO<<"GraphicsWindowCarbon::requestWarpPointer() - Window not realized; cannot warp pointer, screenNum="<< _traits->screenNum<(osg::GraphicsContext::getWindowingSystemInterface()); if (wsi == NULL) { OSG_WARN << "GraphicsWindowCarbon::useCursor: could not get OSXCarbonWindowingSystemInterface" << std::endl; return; } CGDirectDisplayID displayId = wsi->getDisplayID((*_traits)); CGPoint point; point.x = x + _traits->x; point.y = y + _traits->y; CGDisplayMoveCursorToPoint(displayId, point); getEventQueue()->mouseWarped(x,y); } void GraphicsWindowCarbon::transformMouseXY(float& x, float& y) { if (getEventQueue()->getUseFixedMouseInputRange()) { osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState(); x = eventState->getXmin() + (eventState->getXmax()-eventState->getXmin())*x/float(_traits->width); y = eventState->getYmin() + (eventState->getYmax()-eventState->getYmin())*y/float(_traits->height); } } class CarbonWindowingSystemInterface : public DarwinWindowingSystemInterface { public: CarbonWindowingSystemInterface() : DarwinWindowingSystemInterface() { } virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits) { _init(); return createGraphicsContextImplementation(traits); } virtual void _init() { if (_initialized) return; DarwinWindowingSystemInterface::_init(); // register application event handler and AppleEventHandler to get quit-events: static const EventTypeSpec menueventSpec = {kEventClassCommand, kEventCommandProcess}; OSErr status = InstallEventHandler(GetApplicationEventTarget(), NewEventHandlerUPP(ApplicationEventHandler), 1, &menueventSpec, 0, NULL); status = AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP(QuitAppleEventHandler), 0, false); } }; } #ifdef USE_DARWIN_CARBON_IMPLEMENTATION RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy; #endif // declare C entry point for static compilation. extern "C" void graphicswindow_Carbon(void) { osg::GraphicsContext::setWindowingSystemInterface(new osgViewer::CarbonWindowingSystemInterface()); } #endif openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/CompositeViewer.cpp0000644000175000017500000013376612535023504025633 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include using namespace osgViewer; CompositeViewer::CompositeViewer() { constructorInit(); } CompositeViewer::CompositeViewer(const CompositeViewer& cv,const osg::CopyOp& /*copyop*/): osg::Object(true), ViewerBase(cv) { constructorInit(); } CompositeViewer::CompositeViewer(osg::ArgumentParser& arguments) { constructorInit(); arguments.getApplicationUsage()->addCommandLineOption("--SingleThreaded","Select SingleThreaded threading model for viewer."); arguments.getApplicationUsage()->addCommandLineOption("--CullDrawThreadPerContext","Select CullDrawThreadPerContext threading model for viewer."); arguments.getApplicationUsage()->addCommandLineOption("--DrawThreadPerContext","Select DrawThreadPerContext threading model for viewer."); arguments.getApplicationUsage()->addCommandLineOption("--CullThreadPerCameraDrawThreadPerContext","Select CullThreadPerCameraDrawThreadPerContext threading model for viewer."); arguments.getApplicationUsage()->addCommandLineOption("--run-on-demand","Set the run methods frame rate management to only rendering frames when required."); arguments.getApplicationUsage()->addCommandLineOption("--run-continuous","Set the run methods frame rate management to rendering frames continuously."); arguments.getApplicationUsage()->addCommandLineOption("--run-max-frame-rate","Set the run methods maximum permissable frame rate, 0.0 is default and switching off frame rate capping."); std::string filename; bool readConfig = false; while (arguments.read("-c",filename)) { readConfig = readConfiguration(filename) || readConfig; } while (arguments.read("--SingleThreaded")) setThreadingModel(SingleThreaded); while (arguments.read("--CullDrawThreadPerContext")) setThreadingModel(CullDrawThreadPerContext); while (arguments.read("--DrawThreadPerContext")) setThreadingModel(DrawThreadPerContext); while (arguments.read("--CullThreadPerCameraDrawThreadPerContext")) setThreadingModel(CullThreadPerCameraDrawThreadPerContext); while(arguments.read("--run-on-demand")) { setRunFrameScheme(ON_DEMAND); } while(arguments.read("--run-continuous")) { setRunFrameScheme(CONTINUOUS); } double runMaxFrameRate; while(arguments.read("--run-max-frame-rate", runMaxFrameRate)) { setRunMaxFrameRate(runMaxFrameRate); } osg::DisplaySettings::instance()->readCommandLine(arguments); osgDB::readCommandLine(arguments); } void CompositeViewer::constructorInit() { _endBarrierPosition = AfterSwapBuffers; _startTick = 0; // make sure View is safe to reference multi-threaded. setThreadSafeRefUnref(true); _frameStamp = new osg::FrameStamp; _frameStamp->setFrameNumber(0); _frameStamp->setReferenceTime(0); _frameStamp->setSimulationTime(0); _eventVisitor = new osgGA::EventVisitor; _eventVisitor->setFrameStamp(_frameStamp.get()); _updateVisitor = new osgUtil::UpdateVisitor; _updateVisitor->setFrameStamp(_frameStamp.get()); setViewerStats(new osg::Stats("CompsiteViewer")); } CompositeViewer::~CompositeViewer() { OSG_INFO<<"CompositeViewer::~CompositeViewer()"<getDatabasePager()) { scene->getDatabasePager()->cancel(); scene->setDatabasePager(0); } } Contexts contexts; getContexts(contexts); // clear out all the previously assigned operations for(Contexts::iterator citr = contexts.begin(); citr != contexts.end(); ++citr) { (*citr)->close(); } OSG_INFO<<"finished CompositeViewer::~CompositeViewer()"< obj = osgDB::readObjectFile(filename); osgViewer::View * view = dynamic_cast(obj.get()); if (view) { addView(view); return true; } return false; } void CompositeViewer::addView(osgViewer::View* view) { if (!view) return; bool alreadyRealized = isRealized(); bool threadsWereRunning = _threadsRunning; if (threadsWereRunning) stopThreading(); _views.push_back(view); view->_viewerBase = this; if (view->getSceneData()) { // make sure that existing scene graph objects are allocated with thread safe ref/unref if (getThreadingModel()!=ViewerBase::SingleThreaded) { view->getSceneData()->setThreadSafeRefUnref(true); } // update the scene graph so that it has enough GL object buffer memory for the graphics contexts that will be using it. view->getSceneData()->resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts()); } view->setFrameStamp(_frameStamp.get()); if (alreadyRealized) { Contexts contexts; if (view->getCamera()->getGraphicsContext()) { contexts.push_back(view->getCamera()->getGraphicsContext()); } for(unsigned int i=0; igetNumSlaves(); ++i) { if (view->getSlave(i)._camera->getGraphicsContext()) { contexts.push_back(view->getSlave(i)._camera->getGraphicsContext()); } } for(Contexts::iterator itr = contexts.begin(); itr != contexts.end(); ++itr) { if (!((*itr)->isRealized())) { (*itr)->realize(); } } } if (threadsWereRunning) startThreading(); } void CompositeViewer::removeView(osgViewer::View* view) { for(RefViews::iterator itr = _views.begin(); itr != _views.end(); ++itr) { if (*itr == view) { bool threadsWereRunning = _threadsRunning; if (threadsWereRunning) stopThreading(); view->_viewerBase = 0; _views.erase(itr); if (threadsWereRunning) startThreading(); return; } } } bool CompositeViewer::isRealized() const { Contexts contexts; const_cast(this)->getContexts(contexts); unsigned int numRealizedWindows = 0; // clear out all the previously assigned operations for(Contexts::iterator citr = contexts.begin(); citr != contexts.end(); ++citr) { if ((*citr)->isRealized()) ++numRealizedWindows; } return numRealizedWindows > 0; } bool CompositeViewer::checkNeedToDoFrame() { if (_requestRedraw) return true; if (_requestContinousUpdate) return true; for(RefViews::iterator itr = _views.begin(); itr != _views.end(); ++itr) { osgViewer::View* view = itr->get(); if (view) { // If the database pager is going to update the scene the render flag is // set so that the updates show up if (view->getDatabasePager()->requiresUpdateSceneGraph() || view->getDatabasePager()->getRequestsInProgress()) return true; // if there update callbacks then we need to do frame. if (view->getCamera()->getUpdateCallback()) return true; if (view->getSceneData()!=0 && view->getSceneData()->getNumChildrenRequiringUpdateTraversal()>0) return true; } } // check if events are available and need processing if (checkEvents()) return true; if (_requestRedraw) return true; if (_requestContinousUpdate) return true; return false; } bool CompositeViewer::checkEvents() { for(RefViews::iterator itr = _views.begin(); itr != _views.end(); ++itr) { osgViewer::View* view = itr->get(); if (view) { // check events from any attached sources for(View::Devices::iterator eitr = view->getDevices().begin(); eitr != view->getDevices().end(); ++eitr) { osgGA::Device* es = eitr->get(); if (es->getCapabilities() & osgGA::Device::RECEIVE_EVENTS) { if (es->checkEvents()) return true; } } } } // get events from all windows attached to Viewer. Windows windows; getWindows(windows); for(Windows::iterator witr = windows.begin(); witr != windows.end(); ++witr) { if ((*witr)->checkEvents()) return true; } return false; } int CompositeViewer::run() { for(RefViews::iterator itr = _views.begin(); itr != _views.end(); ++itr) { osgViewer::View* view = itr->get(); if ((view->getCameraManipulator()==0) && view->getCamera()->getAllowEventFocus()) { view->setCameraManipulator(new osgGA::TrackballManipulator()); } } setReleaseContextAtEndOfFrameHint(false); return ViewerBase::run(); } void CompositeViewer::setStartTick(osg::Timer_t tick) { _startTick = tick; for(RefViews::iterator vitr = _views.begin(); vitr != _views.end(); ++vitr) { (*vitr)->setStartTick(tick); } Contexts contexts; getContexts(contexts,false); for(Contexts::iterator citr = contexts.begin(); citr != contexts.end(); ++citr) { osgViewer::GraphicsWindow* gw = dynamic_cast(*citr); if (gw) { gw->getEventQueue()->setStartTick(_startTick); } } } void CompositeViewer::setReferenceTime(double time) { osg::Timer_t tick = osg::Timer::instance()->tick(); double currentTime = osg::Timer::instance()->delta_s(_startTick, tick); double delta_ticks = (time-currentTime)/(osg::Timer::instance()->getSecondsPerTick()); if (delta_ticks>=0) tick += osg::Timer_t(delta_ticks); else tick -= osg::Timer_t(-delta_ticks); // assign the new start tick setStartTick(tick); } void CompositeViewer::viewerInit() { OSG_INFO<<"CompositeViewer::init()"<init(); } } void CompositeViewer::getContexts(Contexts& contexts, bool onlyValid) { typedef std::set ContextSet; ContextSet contextSet; contexts.clear(); for(RefViews::iterator vitr = _views.begin(); vitr != _views.end(); ++vitr) { osgViewer::View* view = vitr->get(); osg::GraphicsContext* gc = view->getCamera() ? view->getCamera()->getGraphicsContext() : 0; if (gc && (gc->valid() || !onlyValid)) { if (contextSet.count(gc)==0) { contextSet.insert(gc); contexts.push_back(gc); } } for(unsigned int i=0; igetNumSlaves(); ++i) { View::Slave& slave = view->getSlave(i); osg::GraphicsContext* sgc = slave._camera.valid() ? slave._camera->getGraphicsContext() : 0; if (sgc && (sgc->valid() || !onlyValid)) { if (contextSet.count(sgc)==0) { contextSet.insert(sgc); contexts.push_back(sgc); } } } } } void CompositeViewer::getCameras(Cameras& cameras, bool onlyActive) { cameras.clear(); for(RefViews::iterator vitr = _views.begin(); vitr != _views.end(); ++vitr) { View* view = vitr->get(); if (view->getCamera() && (!onlyActive || (view->getCamera()->getGraphicsContext() && view->getCamera()->getGraphicsContext()->valid())) ) cameras.push_back(view->getCamera()); for(View::Slaves::iterator itr = view->_slaves.begin(); itr != view->_slaves.end(); ++itr) { if (itr->_camera.valid() && (!onlyActive || (itr->_camera->getGraphicsContext() && itr->_camera->getGraphicsContext()->valid())) ) cameras.push_back(itr->_camera.get()); } } } void CompositeViewer::getScenes(Scenes& scenes, bool onlyValid) { scenes.clear(); typedef std::set SceneSet; SceneSet sceneSet; for(RefViews::iterator vitr = _views.begin(); vitr != _views.end(); ++vitr) { osgViewer::View* view = vitr->get(); if (view->getScene() && (!onlyValid || view->getScene()->getSceneData())) { if (sceneSet.count(view->getScene())==0) { sceneSet.insert(view->getScene()); scenes.push_back(view->getScene()); } } } } void CompositeViewer::getViews(Views& views, bool /*onlyValid*/) { views.clear(); for(RefViews::iterator vitr = _views.begin(); vitr != _views.end(); ++vitr) { views.push_back(vitr->get()); } } void CompositeViewer::getAllThreads(Threads& threads, bool onlyActive) { threads.clear(); OperationThreads operationThreads; getOperationThreads(operationThreads); for(OperationThreads::iterator itr = operationThreads.begin(); itr != operationThreads.end(); ++itr) { threads.push_back(*itr); } Scenes scenes; getScenes(scenes); for(Scenes::iterator sitr = scenes.begin(); sitr != scenes.end(); ++sitr) { Scene* scene = *sitr; osgDB::DatabasePager* dp = scene->getDatabasePager(); if (dp) { for(unsigned int i=0; igetNumDatabaseThreads(); ++i) { osgDB::DatabasePager::DatabaseThread* dt = dp->getDatabaseThread(i); if (!onlyActive || dt->isRunning()) { threads.push_back(dt); } } } } } void CompositeViewer::getOperationThreads(OperationThreads& threads, bool onlyActive) { threads.clear(); Contexts contexts; getContexts(contexts); for(Contexts::iterator gcitr = contexts.begin(); gcitr != contexts.end(); ++gcitr) { osg::GraphicsContext* gc = *gcitr; if (gc->getGraphicsThread() && (!onlyActive || gc->getGraphicsThread()->isRunning()) ) { threads.push_back(gc->getGraphicsThread()); } } Cameras cameras; getCameras(cameras); for(Cameras::iterator citr = cameras.begin(); citr != cameras.end(); ++citr) { osg::Camera* camera = *citr; if (camera->getCameraThread() && (!onlyActive || camera->getCameraThread()->isRunning()) ) { threads.push_back(camera->getCameraThread()); } } } void CompositeViewer::realize() { //OSG_INFO<<"CompositeViewer::realize()"<setUpViewAcrossAllScreens(); getContexts(contexts); } if (contexts.empty()) { OSG_NOTICE<<"CompositeViewer::realize() - failed to set up any windows"<getMaxTexturePoolSize(); unsigned int maxBufferObjectPoolSize = osg::DisplaySettings::instance()->getMaxBufferObjectPoolSize(); for(Contexts::iterator citr = contexts.begin(); citr != contexts.end(); ++citr) { osg::GraphicsContext* gc = *citr; // set the pool sizes, 0 the default will result in no GL object pools. gc->getState()->setMaxTexturePoolSize(maxTexturePoolSize); gc->getState()->setMaxBufferObjectPoolSize(maxBufferObjectPoolSize); gc->realize(); if (_realizeOperation.valid() && gc->valid()) { gc->makeCurrent(); (*_realizeOperation)(gc); gc->releaseContext(); } } // attach contexts to _incrementalCompileOperation if attached. if (_incrementalCompileOperation) _incrementalCompileOperation->assignContexts(contexts); bool grabFocus = true; if (grabFocus) { for(Contexts::iterator citr = contexts.begin(); citr != contexts.end(); ++citr) { osgViewer::GraphicsWindow* gw = dynamic_cast(*citr); if (gw) { gw->grabFocusIfPointerInWindow(); } } } startThreading(); // initialize the global timer to be relative to the current time. osg::Timer::instance()->setStartTick(); // pass on the start tick to all the associated eventqueues setStartTick(osg::Timer::instance()->getStartTick()); if (osg::DisplaySettings::instance()->getCompileContextsHint()) { int numProcessors = OpenThreads::GetNumberOfProcessors(); int processNum = 0; for(unsigned int i=0; i<= osg::GraphicsContext::getMaxContextID(); ++i) { osg::GraphicsContext* gc = osg::GraphicsContext::getOrCreateCompileContext(i); if (gc) { gc->createGraphicsThread(); gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors); gc->getGraphicsThread()->startThread(); ++processNum; } } } } void CompositeViewer::advance(double simulationTime) { if (_done) return; double previousReferenceTime = _frameStamp->getReferenceTime(); unsigned int previousFrameNumber = _frameStamp->getFrameNumber(); _frameStamp->setFrameNumber(_frameStamp->getFrameNumber()+1); _frameStamp->setReferenceTime( osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()) ); if (simulationTime==USE_REFERENCE_TIME) { _frameStamp->setSimulationTime(_frameStamp->getReferenceTime()); } else { _frameStamp->setSimulationTime(simulationTime); } if (getViewerStats() && getViewerStats()->collectStats("frame_rate")) { // update previous frame stats double deltaFrameTime = _frameStamp->getReferenceTime() - previousReferenceTime; getViewerStats()->setAttribute(previousFrameNumber, "Frame duration", deltaFrameTime); getViewerStats()->setAttribute(previousFrameNumber, "Frame rate", 1.0/deltaFrameTime); // update current frames stats getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Reference time", _frameStamp->getReferenceTime()); } } void CompositeViewer::setCameraWithFocus(osg::Camera* camera) { _cameraWithFocus = camera; if (camera) { for(RefViews::iterator vitr = _views.begin(); vitr != _views.end(); ++vitr) { View* view = vitr->get(); if (view->containsCamera(camera)) { _viewWithFocus = view; return; } } } _viewWithFocus = 0; } void CompositeViewer::generateSlavePointerData(osg::Camera* camera, osgGA::GUIEventAdapter& event) { osgViewer::GraphicsWindow* gw = dynamic_cast(event.getGraphicsContext()); if (!gw) return; // What type of Camera is it? // 1) Master Camera : do nothin extra // 2) Slave Camera, Relative RF, Same scene graph as master : transform coords into Master Camera and add to PointerData list // 3) Slave Camera, Relative RF, Different scene graph from master : do nothing extra? // 4) Slave Camera, Absolute RF, Same scene graph as master : do nothing extra? // 5) Slave Camera, Absolute RF, Different scene graph : do nothing extra? // 6) Slave Camera, Absolute RF, Different scene graph but a distortion correction subgraph depending upon RTT Camera (slave or master) // : project ray into RTT Camera's clip space, and RTT Camera's is Relative RF and sharing same scene graph as master then transform coords. // if camera isn't the master it must be a slave and could need reprojecting. osgViewer::View* view = dynamic_cast(camera->getView()); if (!view) return; osg::Camera* view_masterCamera = view->getCamera(); if (camera!=view_masterCamera) { float x = event.getX(); float y = event.getY(); bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS; if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y; double master_min_x = -1.0; double master_max_x = 1.0; double master_min_y = -1.0; double master_max_y = 1.0; osg::Matrix masterCameraVPW = view_masterCamera->getViewMatrix() * view_masterCamera->getProjectionMatrix(); if (view_masterCamera->getViewport()) { osg::Viewport* viewport = view_masterCamera->getViewport(); master_min_x = viewport->x(); master_min_y = viewport->y(); master_max_x = viewport->x()+viewport->width(); master_max_y = viewport->y()+viewport->height(); masterCameraVPW *= viewport->computeWindowMatrix(); } // slave Camera tahnks to sharing the same View osg::View::Slave* slave = view ? view->findSlaveForCamera(camera) : 0; if (slave) { if (camera->getReferenceFrame()==osg::Camera::RELATIVE_RF && slave->_useMastersSceneData) { osg::Viewport* viewport = camera->getViewport(); osg::Matrix localCameraVPW = camera->getViewMatrix() * camera->getProjectionMatrix(); if (viewport) localCameraVPW *= viewport->computeWindowMatrix(); osg::Matrix matrix( osg::Matrix::inverse(localCameraVPW) * masterCameraVPW ); osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix; //OSG_NOTICE<<" pointer event new_coord.x()="<second._texture.get()<<", "<second._face<(event.getGraphicsContext()); if (!gw) return; float x = event.getX(); float y = event.getY(); bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS; if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y; event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width, y, 0, gw->getTraits()->height)); typedef std::vector CameraVector; CameraVector activeCameras; osg::GraphicsContext::Cameras& cameras = gw->getCameras(); for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin(); citr != cameras.end(); ++citr) { osg::Camera* camera = *citr; if (camera->getAllowEventFocus() && camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER) { osg::Viewport* viewport = camera ? camera->getViewport() : 0; if (viewport && x >= viewport->x() && y >= viewport->y() && x <= (viewport->x()+viewport->width()) && y <= (viewport->y()+viewport->height()) ) { activeCameras.push_back(camera); } } } std::sort(activeCameras.begin(), activeCameras.end(), osg::CameraRenderOrderSortOp()); osg::Camera* camera = activeCameras.empty() ? 0 : activeCameras.back(); if (camera) { osg::Viewport* viewport = camera ? camera->getViewport() : 0; event.addPointerData(new osgGA::PointerData(camera, (x-viewport->x())/viewport->width()*2.0f-1.0f, -1.0, 1.0, (y-viewport->y())/viewport->height()*2.0f-1.0f, -1.0, 1.0)); osgViewer::View* view = dynamic_cast(camera->getView()); osg::Camera* view_masterCamera = view ? view->getCamera() : 0; // if camera isn't the master it must be a slave and could need reprojecting. if (view && camera!=view_masterCamera) { generateSlavePointerData(camera, event); } } } void CompositeViewer::reprojectPointerData(osgGA::GUIEventAdapter& source_event, osgGA::GUIEventAdapter& dest_event) { osgViewer::GraphicsWindow* gw = dynamic_cast(dest_event.getGraphicsContext()); if (!gw) return; float x = dest_event.getX(); float y = dest_event.getY(); bool invert_y = dest_event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS; if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y; dest_event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width, y, 0, gw->getTraits()->height)); osg::Camera* camera = (source_event.getNumPointerData()>=2) ? dynamic_cast(source_event.getPointerData(1)->object.get()) : 0; osg::Viewport* viewport = camera ? camera->getViewport() : 0; if (!viewport) return; dest_event.addPointerData(new osgGA::PointerData(camera, (x-viewport->x())/viewport->width()*2.0f-1.0f, -1.0, 1.0, (y-viewport->y())/viewport->height()*2.0f-1.0f, -1.0, 1.0)); osgViewer::View* view = dynamic_cast(camera->getView()); osg::Camera* view_masterCamera = view ? view->getCamera() : 0; // if camera isn't the master it must be a slave and could need reprojecting. if (view && camera!=view_masterCamera) { generateSlavePointerData(camera, dest_event); } } struct SortEvents { bool operator() (const osg::ref_ptr& lhs,const osg::ref_ptr& rhs) const { return lhs->getTime() < rhs->getTime(); } }; void CompositeViewer::eventTraversal() { if (_done) return; if (_views.empty()) return; double cutOffTime = _frameStamp->getReferenceTime(); double beginEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); // need to copy events from the GraphicsWindow's into local EventQueue for each view; typedef std::map ViewEventsMap; ViewEventsMap viewEventsMap; Contexts contexts; getContexts(contexts); // set done if there are no windows checkWindowStatus(contexts); if (_done) return; osgGA::EventQueue::Events all_events; for(Contexts::iterator citr = contexts.begin(); citr != contexts.end(); ++citr) { osgViewer::GraphicsWindow* gw = dynamic_cast(*citr); if (gw) { gw->checkEvents(); osgGA::EventQueue::Events gw_events; gw->getEventQueue()->takeEvents(gw_events, cutOffTime); for(osgGA::EventQueue::Events::iterator itr = gw_events.begin(); itr != gw_events.end(); ++itr) { (*itr)->setGraphicsContext(gw); } all_events.insert(all_events.end(), gw_events.begin(), gw_events.end()); } } // sort all the events in time order so we can make sure we pass them all on in the correct order. all_events.sort(SortEvents()); // pass on pointer data onto non mouse events to keep the position data usable by all recipients of all events. for(osgGA::EventQueue::Events::iterator itr = all_events.begin(); itr != all_events.end(); ++itr) { osgGA::GUIEventAdapter* event = itr->get(); switch(event->getEventType()) { case(osgGA::GUIEventAdapter::PUSH): case(osgGA::GUIEventAdapter::RELEASE): case(osgGA::GUIEventAdapter::DOUBLECLICK): case(osgGA::GUIEventAdapter::MOVE): case(osgGA::GUIEventAdapter::DRAG): { if ((event->getEventType()!=osgGA::GUIEventAdapter::DRAG && event->getEventType()!=osgGA::GUIEventAdapter::RELEASE) || !_previousEvent || _previousEvent->getGraphicsContext()!=event->getGraphicsContext() || _previousEvent->getNumPointerData()<2) { generatePointerData(*event); } else { reprojectPointerData(*_previousEvent, *event); } #if 0 // assign topmost PointeData settings as the events X,Y and InputRange osgGA::PointerData* pd = event->getPointerData(event->getNumPointerData()-1); event->setX(pd->x); event->setY(pd->y); event->setInputRange(pd->xMin, pd->yMin, pd->xMax, pd->yMax); event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS); #else if (event->getMouseYOrientation()!=osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS) { event->setY((event->getYmax()-event->getY())+event->getYmin()); event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS); } #endif _previousEvent = event; break; } default: if (_previousEvent.valid()) event->copyPointerDataFrom(*_previousEvent); break; } osgGA::PointerData* pd = event->getNumPointerData()>0 ? event->getPointerData(event->getNumPointerData()-1) : 0; osg::Camera* camera = pd ? dynamic_cast(pd->object.get()) : 0; osgViewer::View* view = camera ? dynamic_cast(camera->getView()) : 0; if (!view) { if (_viewWithFocus.valid()) { // OSG_NOTICE<<"Falling back to using _viewWithFocus"<getEventQueue()->getCurrentEventState(); eventState->copyPointerDataFrom(*event); } _previousEvent = event; } // handle any close windows for(osgGA::EventQueue::Events::iterator itr = all_events.begin(); itr != all_events.end(); ++itr) { osgGA::GUIEventAdapter* event = itr->get(); switch(event->getEventType()) { case(osgGA::GUIEventAdapter::CLOSE_WINDOW): { bool wasThreading = areThreadsRunning(); if (wasThreading) stopThreading(); if (event->getGraphicsContext()) { event->getGraphicsContext()->close(); } if (wasThreading) startThreading(); break; } default: break; } } for(RefViews::iterator vitr = _views.begin(); vitr != _views.end(); ++vitr) { View* view = vitr->get(); // get events from user Devices attached to Viewer. for(osgViewer::View::Devices::iterator eitr = view->getDevices().begin(); eitr != view->getDevices().end(); ++eitr) { osgGA::Device* es = eitr->get(); if (es->getCapabilities() & osgGA::Device::RECEIVE_EVENTS) es->checkEvents(); // open question, will we need to reproject mouse coordinates into current view's coordinate frame as is down for GraphicsWindow provided events? // for now assume now and just get the events directly without any reprojection. es->getEventQueue()->takeEvents(viewEventsMap[view], cutOffTime); } // generate frame event view->getEventQueue()->frame( getFrameStamp()->getReferenceTime() ); view->getEventQueue()->takeEvents(viewEventsMap[view], cutOffTime); } if ((_keyEventSetsDone!=0) || _quitEventSetsDone) { for(ViewEventsMap::iterator veitr = viewEventsMap.begin(); veitr != viewEventsMap.end(); ++veitr) { for(osgGA::EventQueue::Events::iterator itr = veitr->second.begin(); itr != veitr->second.end(); ++itr) { osgGA::GUIEventAdapter* event = itr->get(); switch(event->getEventType()) { case(osgGA::GUIEventAdapter::KEYUP): if (_keyEventSetsDone && event->getKey()==_keyEventSetsDone) _done = true; break; case(osgGA::GUIEventAdapter::QUIT_APPLICATION): if (_quitEventSetsDone) _done = true; break; default: break; } } } } if (_done) return; if (_eventVisitor.valid()) { _eventVisitor->setFrameStamp(getFrameStamp()); _eventVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber()); for(ViewEventsMap::iterator veitr = viewEventsMap.begin(); veitr != viewEventsMap.end(); ++veitr) { View* view = veitr->first; if (view && view->getSceneData()) { _eventVisitor->setActionAdapter(view); for(osgGA::EventQueue::Events::iterator itr = veitr->second.begin(); itr != veitr->second.end(); ++itr) { osgGA::GUIEventAdapter* event = itr->get(); _eventVisitor->reset(); _eventVisitor->addEvent( event ); view->getSceneData()->accept(*_eventVisitor); // Do EventTraversal for slaves with their own subgraph for(unsigned int i=0; igetNumSlaves(); ++i) { osg::View::Slave& slave = view->getSlave(i); osg::Camera* camera = slave._camera.get(); if(camera && !slave._useMastersSceneData) { camera->accept(*_eventVisitor); } } // call any camera event callbacks, but only traverse that callback, don't traverse its subgraph // leave that to the scene update traversal. osg::NodeVisitor::TraversalMode tm = _eventVisitor->getTraversalMode(); _eventVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE); if (view->getCamera() && view->getCamera()->getEventCallback()) view->getCamera()->accept(*_eventVisitor); for(unsigned int i=0; igetNumSlaves(); ++i) { osg::View::Slave& slave = view->getSlave(i); osg::Camera* camera = view->getSlave(i)._camera.get(); if (camera && slave._useMastersSceneData && camera->getEventCallback()) { camera->accept(*_eventVisitor); } } _eventVisitor->setTraversalMode(tm); } } } } for(ViewEventsMap::iterator veitr = viewEventsMap.begin(); veitr != viewEventsMap.end(); ++veitr) { View* view = veitr->first; for(osgGA::EventQueue::Events::iterator itr = veitr->second.begin(); itr != veitr->second.end(); ++itr) { osgGA::GUIEventAdapter* event = itr->get(); for(View::EventHandlers::iterator hitr = view->getEventHandlers().begin(); hitr != view->getEventHandlers().end(); ++hitr) { (*hitr)->handleWithCheckAgainstIgnoreHandledEventsMask( *event, *view, 0, _eventVisitor.get()); } } } for(ViewEventsMap::iterator veitr = viewEventsMap.begin(); veitr != viewEventsMap.end(); ++veitr) { View* view = veitr->first; for(osgGA::EventQueue::Events::iterator itr = veitr->second.begin(); itr != veitr->second.end(); ++itr) { osgGA::GUIEventAdapter* event = itr->get(); if (view->getCameraManipulator()) { view->getCameraManipulator()->handleWithCheckAgainstIgnoreHandledEventsMask( *event, *view); } } } if (getViewerStats() && getViewerStats()->collectStats("event")) { double endEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); // update current frames stats getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal begin time", beginEventTraversal); getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal end time", endEventTraversal); getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal time taken", endEventTraversal-beginEventTraversal); } } void CompositeViewer::updateTraversal() { if (_done) return; double beginUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); _updateVisitor->reset(); _updateVisitor->setFrameStamp(getFrameStamp()); _updateVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber()); Scenes scenes; getScenes(scenes); for(Scenes::iterator sitr = scenes.begin(); sitr != scenes.end(); ++sitr) { Scene* scene = *sitr; scene->updateSceneGraph(*_updateVisitor); } // if we have a shared state manager prune any unused entries if (osgDB::Registry::instance()->getSharedStateManager()) osgDB::Registry::instance()->getSharedStateManager()->prune(); // update the Registry object cache. osgDB::Registry::instance()->updateTimeStampOfObjectsInCacheWithExternalReferences(*getFrameStamp()); osgDB::Registry::instance()->removeExpiredObjectsInCache(*getFrameStamp()); if (_incrementalCompileOperation.valid()) { // merge subgraphs that have been compiled by the incremental compiler operation. _incrementalCompileOperation->mergeCompiledSubgraphs(getFrameStamp()); } if (_updateOperations.valid()) { _updateOperations->runOperations(this); } for(RefViews::iterator vitr = _views.begin(); vitr != _views.end(); ++vitr) { View* view = vitr->get(); { // Do UpdateTraversal for slaves with their own subgraph for(unsigned int i=0; igetNumSlaves(); ++i) { osg::View::Slave& slave = view->getSlave(i); osg::Camera* camera = slave._camera.get(); if(camera && !slave._useMastersSceneData) { camera->accept(*_updateVisitor); } } // call any camera update callbacks, but only traverse that callback, don't traverse its subgraph // leave that to the scene update traversal. osg::NodeVisitor::TraversalMode tm = _updateVisitor->getTraversalMode(); _updateVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE); if (view->getCamera() && view->getCamera()->getUpdateCallback()) view->getCamera()->accept(*_updateVisitor); for(unsigned int i=0; igetNumSlaves(); ++i) { osg::View::Slave& slave = view->getSlave(i); osg::Camera* camera = slave._camera.get(); if (camera && slave._useMastersSceneData && camera->getUpdateCallback()) { camera->accept(*_updateVisitor); } } _updateVisitor->setTraversalMode(tm); } if (view->getCameraManipulator()) { view->setFusionDistance( view->getCameraManipulator()->getFusionDistanceMode(), view->getCameraManipulator()->getFusionDistanceValue() ); view->getCameraManipulator()->updateCamera(*(view->getCamera())); } view->updateSlaves(); } if (getViewerStats() && getViewerStats()->collectStats("update")) { double endUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); // update current frames stats getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal begin time", beginUpdateTraversal); getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal end time", endUpdateTraversal); getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal time taken", endUpdateTraversal-beginUpdateTraversal); } } double CompositeViewer::elapsedTime() { return osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); } void CompositeViewer::getUsage(osg::ApplicationUsage& usage) const { for(RefViews::const_iterator vitr = _views.begin(); vitr != _views.end(); ++vitr) { const View* view = vitr->get(); if (view->getCameraManipulator()) { view->getCameraManipulator()->getUsage(usage); } for(View::EventHandlers::const_iterator hitr = view->_eventHandlers.begin(); hitr != view->_eventHandlers.end(); ++hitr) { (*hitr)->getUsage(usage); } } } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/PixelBufferWin32.cpp0000644000175000017500000006274112021737055025542 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. * * Some elements of GraphicsWindowWin32 have used the Producer implementation as a reference. * These elements are licensed under OSGPL as above, with Copyright (C) 2001-2004 Don Burns. */ #include #include #include #include #include #include #include #ifndef WGL_ARB_pbuffer #define WGL_ARB_pbuffer 1 DECLARE_HANDLE(HPBUFFERARB); #define WGL_DRAW_TO_PBUFFER_ARB 0x202D #define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E #define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F #define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 #define WGL_PBUFFER_LARGEST_ARB 0x2033 #define WGL_PBUFFER_WIDTH_ARB 0x2034 #define WGL_PBUFFER_HEIGHT_ARB 0x2035 #define WGL_PBUFFER_LOST_ARB 0x2036 #endif #ifndef WGL_ARB_pixel_format #define WGL_ARB_pixel_format 1 #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 #define WGL_DRAW_TO_WINDOW_ARB 0x2001 #define WGL_DRAW_TO_BITMAP_ARB 0x2002 #define WGL_ACCELERATION_ARB 0x2003 #define WGL_NEED_PALETTE_ARB 0x2004 #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 #define WGL_SWAP_METHOD_ARB 0x2007 #define WGL_NUMBER_OVERLAYS_ARB 0x2008 #define WGL_NUMBER_UNDERLAYS_ARB 0x2009 #define WGL_TRANSPARENT_ARB 0x200A #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B #define WGL_SHARE_DEPTH_ARB 0x200C #define WGL_SHARE_STENCIL_ARB 0x200D #define WGL_SHARE_ACCUM_ARB 0x200E #define WGL_SUPPORT_GDI_ARB 0x200F #define WGL_SUPPORT_OPENGL_ARB 0x2010 #define WGL_DOUBLE_BUFFER_ARB 0x2011 #define WGL_STEREO_ARB 0x2012 #define WGL_PIXEL_TYPE_ARB 0x2013 #define WGL_COLOR_BITS_ARB 0x2014 #define WGL_RED_BITS_ARB 0x2015 #define WGL_RED_SHIFT_ARB 0x2016 #define WGL_GREEN_BITS_ARB 0x2017 #define WGL_GREEN_SHIFT_ARB 0x2018 #define WGL_BLUE_BITS_ARB 0x2019 #define WGL_BLUE_SHIFT_ARB 0x201A #define WGL_ALPHA_BITS_ARB 0x201B #define WGL_ALPHA_SHIFT_ARB 0x201C #define WGL_ACCUM_BITS_ARB 0x201D #define WGL_ACCUM_RED_BITS_ARB 0x201E #define WGL_ACCUM_GREEN_BITS_ARB 0x201F #define WGL_ACCUM_BLUE_BITS_ARB 0x2020 #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 #define WGL_DEPTH_BITS_ARB 0x2022 #define WGL_STENCIL_BITS_ARB 0x2023 #define WGL_AUX_BUFFERS_ARB 0x2024 #define WGL_NO_ACCELERATION_ARB 0x2025 #define WGL_GENERIC_ACCELERATION_ARB 0x2026 #define WGL_FULL_ACCELERATION_ARB 0x2027 #define WGL_SWAP_EXCHANGE_ARB 0x2028 #define WGL_SWAP_COPY_ARB 0x2029 #define WGL_SWAP_UNDEFINED_ARB 0x202A #define WGL_TYPE_RGBA_ARB 0x202B #define WGL_TYPE_COLORINDEX_ARB 0x202C #define WGL_SAMPLE_BUFFERS_ARB 0x2041 #define WGL_SAMPLES_ARB 0x2042 #endif #ifndef WGL_ARB_render_texture #define WGL_ARB_render_texture 1 #define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 #define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 #define WGL_TEXTURE_FORMAT_ARB 0x2072 #define WGL_TEXTURE_TARGET_ARB 0x2073 #define WGL_MIPMAP_TEXTURE_ARB 0x2074 #define WGL_TEXTURE_RGB_ARB 0x2075 #define WGL_TEXTURE_RGBA_ARB 0x2076 #define WGL_NO_TEXTURE_ARB 0x2077 #define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 #define WGL_TEXTURE_1D_ARB 0x2079 #define WGL_TEXTURE_2D_ARB 0x207A #define WGL_MIPMAP_LEVEL_ARB 0x207B #define WGL_CUBE_MAP_FACE_ARB 0x207C #define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E #define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 #define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 #define WGL_FRONT_LEFT_ARB 0x2083 #define WGL_FRONT_RIGHT_ARB 0x2084 #define WGL_BACK_LEFT_ARB 0x2085 #define WGL_BACK_RIGHT_ARB 0x2086 #define WGL_AUX0_ARB 0x2087 #define WGL_AUX1_ARB 0x2088 #define WGL_AUX2_ARB 0x2089 #define WGL_AUX3_ARB 0x208A #define WGL_AUX4_ARB 0x208B #define WGL_AUX5_ARB 0x208C #define WGL_AUX6_ARB 0x208D #define WGL_AUX7_ARB 0x208E #define WGL_AUX8_ARB 0x208F #define WGL_AUX9_ARB 0x2090 #endif #ifndef WGL_NV_render_depth_texture #define WGL_NV_render_depth_texture 1 #define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 #define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 #define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 #define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 #define WGL_DEPTH_COMPONENT_NV 0x20A7 #endif #ifndef WGL_NV_render_texture_rectangle #define WGL_NV_render_texture_rectangle 1 #define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 #define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 #define WGL_TEXTURE_RECTANGLE_NV 0x20A2 #endif #ifndef WGL_SAMPLE_BUFFERS_ARB #define WGL_SAMPLE_BUFFERS_ARB 0x2041 #endif #ifndef WGL_SAMPLES_ARB #define WGL_SAMPLES_ARB 0x2042 #endif namespace { static std::string sysError() { DWORD stat, err = GetLastError(); LPVOID lpMsgBuf = 0; stat = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf,\ 0,NULL ); std::ostringstream msgResult; if ( stat > 0 && lpMsgBuf ) { msgResult << (LPCTSTR)lpMsgBuf; LocalFree( lpMsgBuf ); } else { msgResult << "Error code " << err; } return msgResult.str(); } static int __tempwnd_id = 0; class TemporaryWindow: public osg::Referenced { public: TemporaryWindow(): _handle(0), _dc(0), _context(0), _instance(0) { create(); } HWND getHandle() const { return _handle; } HDC getDC() const { return _dc; } HGLRC getContext() const { return _context; } bool makeCurrent(); protected: ~TemporaryWindow(); TemporaryWindow(const TemporaryWindow &): _handle(0), _dc(0), _context(0), _instance(0) {} TemporaryWindow &operator=(const TemporaryWindow &) { return *this; } void create(); void kill(); private: HWND _handle; HDC _dc; HGLRC _context; HINSTANCE _instance; std::string _classname; }; void TemporaryWindow::create() { std::ostringstream oss; oss << "tempwnd" << (++__tempwnd_id); _classname = oss.str(); _instance = GetModuleHandle(0); WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wndclass.lpfnWndProc = DefWindowProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = _instance; wndclass.hCursor = 0; wndclass.hIcon = 0; wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wndclass.lpszMenuName = 0; wndclass.lpszClassName = _classname.c_str(); if (!RegisterClass(&wndclass)) return; if (!(_handle = CreateWindowEx( 0, _classname.c_str(), TEXT(_classname.c_str()), WS_POPUP, 0, 0, 100, 100, 0, 0, _instance, 0))) { OSG_WARN << "PixelBufferWin32, could not create temporary window: " << sysError() << std::endl; kill(); return; } if (!(_dc = GetDC(_handle))) { OSG_WARN << "PixelBufferWin32, could not get device context for temporary window: " << sysError() << std::endl; kill(); return; } PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 }; int visual_id = ChoosePixelFormat(_dc, &pfd); if (!SetPixelFormat(_dc, visual_id, &pfd)) { OSG_WARN << "PixelBufferWin32, could not set pixel format for temporary window: " << sysError() << std::endl; kill(); return; } if (!(_context = wglCreateContext(_dc))) { OSG_WARN << "PixelBufferWin32, could not get graphics context for temporary window: " << sysError() << std::endl; kill(); return; } } TemporaryWindow::~TemporaryWindow() { kill(); } void TemporaryWindow::kill() { if (_context) { // mew 2005-05-09 commented out due to crashes. // possible causes are unsafe destructor ordering, or context already // deleted by window deletion; see: // http://openscenegraph.org/pipermail/osg-users/2005-May/052753.html //wglDeleteContext(_context); _context = 0; } if (_dc) { ReleaseDC(_handle, _dc); _dc = 0; } if (_handle) { DestroyWindow(_handle); _handle = 0; } UnregisterClass(_classname.c_str(), _instance); _instance = 0; } bool TemporaryWindow::makeCurrent() { bool result = wglMakeCurrent(_dc, _context) == TRUE ? true : false; if (!result) { OSG_NOTICE << "PixelBufferWin32, could not make the temporary window's context active: " << sysError() << std::endl; } return result; } class WGLExtensions : public osg::Referenced { public: typedef HPBUFFERARB (WINAPI * WGLCreatePBufferProc) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); typedef HDC (WINAPI * WGLGetPBufferDCProc) (HPBUFFERARB hPbuffer); typedef int (WINAPI * WGLReleasePBufferDCProc) (HPBUFFERARB hPbuffer, HDC hDC); typedef bool (WINAPI * WGLDestroyPBufferProc) (HPBUFFERARB hPbuffer); typedef bool (WINAPI * WGLQueryPBufferProc) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); typedef bool (WINAPI * WGLBindTexImageProc) (HPBUFFERARB hPbuffer, int iBuffer); typedef bool (WINAPI * WGLReleaseTexImageProc) (HPBUFFERARB hPbuffer, int iBuffer); typedef bool (WINAPI * WGLSetPbufferAttribProc) (HPBUFFERARB hPbuffer, const int * piAttribList); typedef bool (WINAPI * WGLChoosePixelFormatProc) (HDC, const int *, const float *, unsigned int, int *, unsigned int *); typedef bool (WINAPI * WGLMakeContextCurrentProc) (HDC, HDC, HGLRC); WGLCreatePBufferProc wglCreatePbufferARB; WGLGetPBufferDCProc wglGetPbufferDCARB; WGLReleasePBufferDCProc wglReleasePbufferDCARB; WGLDestroyPBufferProc wglDestroyPbufferARB; WGLQueryPBufferProc wglQueryPbufferARB; WGLBindTexImageProc wglBindTexImageARB; WGLReleaseTexImageProc wglReleaseTexImageARB; WGLChoosePixelFormatProc wglChoosePixelFormatARB; WGLMakeContextCurrentProc wglMakeContextCurrentARB; static WGLExtensions *instance(); bool isValid(); protected: WGLExtensions(); ~WGLExtensions(); private: static std::map > _instances; }; std::map > WGLExtensions::_instances; WGLExtensions::WGLExtensions() { wglCreatePbufferARB = (WGLCreatePBufferProc)wglGetProcAddress("wglCreatePbufferARB"); wglGetPbufferDCARB = (WGLGetPBufferDCProc)wglGetProcAddress("wglGetPbufferDCARB"); wglReleasePbufferDCARB = (WGLReleasePBufferDCProc)wglGetProcAddress("wglReleasePbufferDCARB"); wglDestroyPbufferARB = (WGLDestroyPBufferProc)wglGetProcAddress("wglDestroyPbufferARB"); wglQueryPbufferARB = (WGLQueryPBufferProc)wglGetProcAddress("wglQueryPbufferARB"); wglBindTexImageARB = (WGLBindTexImageProc)wglGetProcAddress("wglBindTexImageARB"); wglReleaseTexImageARB = (WGLReleaseTexImageProc)wglGetProcAddress("wglReleaseTexImageARB"); wglChoosePixelFormatARB = (WGLChoosePixelFormatProc)wglGetProcAddress("wglChoosePixelFormatARB"); wglMakeContextCurrentARB = (WGLMakeContextCurrentProc)wglGetProcAddress("wglMakeContextCurrentARB"); if (!wglMakeContextCurrentARB) { wglMakeContextCurrentARB = (WGLMakeContextCurrentProc)wglGetProcAddress("wglMakeContextCurrentEXT"); } } WGLExtensions::~WGLExtensions() { } bool WGLExtensions::isValid() { return (wglCreatePbufferARB && wglGetPbufferDCARB && wglReleasePbufferDCARB && wglDestroyPbufferARB && wglQueryPbufferARB && wglChoosePixelFormatARB ); } WGLExtensions *WGLExtensions::instance() { HGLRC context = wglGetCurrentContext(); // Get wgl function pointers for the current graphics context, or if there is no // current context then use a temporary window. if (!_instances[context]) { if ( context == 0 ) { osg::ref_ptr tempWin= new TemporaryWindow; tempWin->makeCurrent(); _instances[HGLRC(0)] = new WGLExtensions; } else { _instances[context] = new WGLExtensions; } } return _instances[context].get(); } } using namespace osgViewer; PixelBufferWin32::PixelBufferWin32( osg::GraphicsContext::Traits* traits ): _initialized(false), _valid(false), _realized(false), _boundBuffer(0) { _traits = traits; init(); if (valid()) { setState( new osg::State ); getState()->setGraphicsContext( this ); if (_traits.valid() && _traits->sharedContext.valid() ) { getState()->setContextID( _traits->sharedContext->getState()->getContextID() ); incrementContextIDUsageCount( getState()->getContextID() ); } else { getState()->setContextID( osg::GraphicsContext::createNewContextID() ); } } } PixelBufferWin32::~PixelBufferWin32() { closeImplementation(); } void PixelBufferWin32::init() { if (_initialized) return; if (!_traits) return; if (!_traits->pbuffer) return; WGLExtensions* wgle = WGLExtensions::instance(); if (!wgle || !wgle->isValid()) { OSG_NOTICE << "PixelBufferWin32::init(), Error: some wgl extensions not supported" << std::endl; return; } std::vector fAttribList; std::vector bAttribList; fAttribList.push_back(WGL_DRAW_TO_PBUFFER_ARB); fAttribList.push_back(true); fAttribList.push_back(WGL_SUPPORT_OPENGL_ARB); fAttribList.push_back(true); fAttribList.push_back(WGL_PIXEL_TYPE_ARB); fAttribList.push_back(WGL_TYPE_RGBA_ARB); bAttribList.push_back(WGL_PBUFFER_LARGEST_ARB); bAttribList.push_back(true); fAttribList.push_back(WGL_RED_BITS_ARB); fAttribList.push_back(_traits->red); fAttribList.push_back(WGL_GREEN_BITS_ARB); fAttribList.push_back(_traits->green); fAttribList.push_back(WGL_BLUE_BITS_ARB); fAttribList.push_back(_traits->blue); if (_traits->alpha) { fAttribList.push_back(WGL_ALPHA_BITS_ARB); fAttribList.push_back(_traits->alpha); } fAttribList.push_back(WGL_DEPTH_BITS_ARB); fAttribList.push_back(_traits->depth); if (_traits->stencil) { fAttribList.push_back(WGL_STENCIL_BITS_ARB); fAttribList.push_back(_traits->stencil); } if (_traits->sampleBuffers) { fAttribList.push_back(WGL_SAMPLE_BUFFERS_ARB); fAttribList.push_back(_traits->sampleBuffers); fAttribList.push_back(WGL_SAMPLES_ARB); fAttribList.push_back(_traits->samples); } if (_traits->doubleBuffer) { fAttribList.push_back(WGL_DOUBLE_BUFFER_ARB); fAttribList.push_back(true); } if (_traits->target != 0 && wgle->wglBindTexImageARB ) { // TODO: Cube Maps if (_traits->target == GL_TEXTURE_RECTANGLE) { bAttribList.push_back(WGL_TEXTURE_TARGET_ARB); bAttribList.push_back(WGL_TEXTURE_RECTANGLE_NV); if (_traits->alpha) fAttribList.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV); else fAttribList.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV); fAttribList.push_back(true); } else { bAttribList.push_back(WGL_TEXTURE_TARGET_ARB); bAttribList.push_back(WGL_TEXTURE_2D_ARB); if (_traits->alpha) fAttribList.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB); else fAttribList.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB); fAttribList.push_back(true); } bAttribList.push_back(WGL_TEXTURE_FORMAT_ARB); if (_traits->alpha) bAttribList.push_back(WGL_TEXTURE_RGBA_ARB); else bAttribList.push_back(WGL_TEXTURE_RGB_ARB); if (_traits->mipMapGeneration) { fAttribList.push_back(WGL_MIPMAP_TEXTURE_ARB); fAttribList.push_back(true); } } fAttribList.push_back(0); bAttribList.push_back(0); HDC hdc = 0; int format; osg::ref_ptr tempWin; tempWin = new TemporaryWindow; hdc = tempWin->getDC(); tempWin->makeCurrent(); wgle = WGLExtensions::instance(); unsigned int nformats = 0; wgle->wglChoosePixelFormatARB(hdc, &fAttribList[0], NULL, 1, &format, &nformats); if (nformats == 0) { OSG_NOTICE << "PixelBufferWin32::init(), Error: Couldn't find a suitable pixel format" << std::endl; return; } _hwnd = reinterpret_cast(wgle->wglCreatePbufferARB(hdc, format, _traits->width, _traits->height, &bAttribList[0])); if (!_hwnd) { OSG_NOTICE << "PixelBufferWin32::init, wglCreatePbufferARB error: " << sysError() << std::endl; return ; } _hdc = wgle->wglGetPbufferDCARB(reinterpret_cast(_hwnd)); if (!_hdc) { OSG_NOTICE << "PixelBufferWin32::init, wglGetPbufferDCARB error: " << sysError() << std::endl; return; } _hglrc = wglCreateContext(_hdc); if (!_hglrc) { OSG_NOTICE << "PixelBufferWin32::init, wglCreateContext error: " << sysError() << std::endl; return; } int iWidth = 0; int iHeight = 0; wgle->wglQueryPbufferARB(reinterpret_cast(_hwnd), WGL_PBUFFER_WIDTH_ARB, &iWidth); wgle->wglQueryPbufferARB(reinterpret_cast(_hwnd), WGL_PBUFFER_HEIGHT_ARB, &iHeight); if (_traits->width != iWidth || _traits->height != iHeight) { OSG_NOTICE << "PixelBufferWin32::init(), pbuffer created with different size then requsted" << std::endl; OSG_NOTICE << "\tRequested size (" << _traits->width << "," << _traits->height << ")" << std::endl; OSG_NOTICE << "\tPbuffer size (" << iWidth << "," << iHeight << ")" << std::endl; _traits->width = iWidth; _traits->height = iHeight; } _initialized = true; _valid = true; return; } bool PixelBufferWin32::realizeImplementation() { if (_realized) { OSG_NOTICE<<"PixelBufferWin32::realizeImplementation() Already realized"<sharedContext.valid() ) { GraphicsHandleWin32* graphicsHandleWin32 = dynamic_cast(_traits->sharedContext.get()); if (graphicsHandleWin32) { if ( !wglShareLists(graphicsHandleWin32->getWGLContext(), _hglrc) ) { OSG_NOTICE << "PixelBufferWin32::realizeImplementation, wglShareLists error: " << sysError() << std::endl; } } } _realized = true; return true; } void PixelBufferWin32::closeImplementation() { if (_hwnd) { WGLExtensions* wgle = WGLExtensions::instance(); wglMakeCurrent(NULL,NULL); if ( !wglDeleteContext(_hglrc) ) { OSG_NOTICE << "PixelBufferWin32::closeImplementation, wglDeleteContext error: " << sysError() << std::endl; } if (wgle && wgle->isValid()) { // Note that closeImplementation() should only be called from the same thread as created the pbuffer, // otherwise these routines will return an error. if ( !wgle->wglReleasePbufferDCARB(reinterpret_cast(_hwnd), _hdc) ) { OSG_NOTICE << "PixelBufferWin32::closeImplementation, wglReleasePbufferDCARB error: " << sysError() << std::endl; } if ( !wgle->wglDestroyPbufferARB(reinterpret_cast(_hwnd)) ) { OSG_NOTICE << "PixelBufferWin32::closeImplementation, wglDestroyPbufferARB error: " << sysError() << std::endl; } } } _valid = false; _initialized = false; _hwnd = 0; _hdc = 0; _hglrc = 0; } bool PixelBufferWin32::makeCurrentImplementation() { bool result = wglMakeCurrent(_hdc, _hglrc)==TRUE?true:false; if (!result) { OSG_NOTICE << "PixelBufferWin32::makeCurrentImplementation, wglMakeCurrent error: " << sysError() << std::endl; } // If the pbuffer is bound to a texture then release it. This operation requires a current context, so // do it after the MakeCurrent. if ( _boundBuffer!=0 ) { WGLExtensions* wgle = WGLExtensions::instance(); if ( wgle && wgle->wglReleaseTexImageARB ) { if ( !wgle->wglReleaseTexImageARB(reinterpret_cast(_hwnd), _boundBuffer) ) { OSG_NOTICE << "PixelBufferWin32::makeCurrentImplementation, wglReleaseTexImageARB error: " << sysError() << std::endl; } _boundBuffer=0; } } return result; } bool PixelBufferWin32::makeContextCurrentImplementation( GraphicsContext* readContext ) { WGLExtensions* wgle = WGLExtensions::instance(); if ( !wgle || !wgle->wglMakeContextCurrentARB ) { OSG_NOTICE << "PixelBufferWin32, wglMakeContextCurrentARB not available" << std::endl; return false; } GraphicsHandleWin32* graphicsHandleWin32 = dynamic_cast(readContext); if (graphicsHandleWin32) { return wgle->wglMakeContextCurrentARB(_hdc, graphicsHandleWin32->getHDC(), _hglrc); } return false; } bool PixelBufferWin32::releaseContextImplementation() { if (!_realized) { OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<wglBindTexImageARB ) { OSG_NOTICE << "PixelBufferWin32, wglBindTexImageARB not available" << std::endl; return; } int bindBuffer; switch (buffer) { case GL_BACK: bindBuffer = WGL_BACK_LEFT_ARB; break; case GL_FRONT: bindBuffer = WGL_FRONT_LEFT_ARB; break; default: bindBuffer = static_cast(buffer); } if ( bindBuffer != _boundBuffer ) { if ( _boundBuffer != 0 && !wgle->wglReleaseTexImageARB(reinterpret_cast(_hwnd), _boundBuffer) ) { OSG_NOTICE << "PixelBufferWin32::bindPBufferToTextureImplementation, wglReleaseTexImageARB error: " << sysError() << std::endl; } if ( !wgle->wglBindTexImageARB(reinterpret_cast(_hwnd), bindBuffer) ) { OSG_NOTICE << "PixelBufferWin32::bindPBufferToTextureImplementation, wglBindTexImageARB error: " << sysError() << std::endl; } _boundBuffer = bindBuffer; } } void PixelBufferWin32::swapBuffersImplementation() { SwapBuffers( _hdc ); } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/GraphicsWindowWin32.cpp0000644000175000017500000032032112222510673026244 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. * * This file is Copyright (C) 2007 - Andr Garneau (andre@pixdev.com) and licensed under OSGPL. * * Some elements of GraphicsWindowWin32 have used the Producer implementation as a reference. * These elements are licensed under OSGPL as above, with Copyright (C) 2001-2004 Don Burns. */ #include #include #include #include #include #include #include #include #include #include #define MOUSEEVENTF_FROMTOUCH 0xFF515700 #if(WINVER < 0x0601) // Provide Declarations for Multitouch #define WM_TOUCH 0x0240 /* * Touch Input defines and functions */ /* * Touch input handle */ DECLARE_HANDLE(HTOUCHINPUT); typedef struct tagTOUCHINPUT { LONG x; LONG y; HANDLE hSource; DWORD dwID; DWORD dwFlags; DWORD dwMask; DWORD dwTime; ULONG_PTR dwExtraInfo; DWORD cxContact; DWORD cyContact; } TOUCHINPUT, *PTOUCHINPUT; typedef TOUCHINPUT const * PCTOUCHINPUT; /* * Conversion of touch input coordinates to pixels */ #define TOUCH_COORD_TO_PIXEL(l) ((l) / 100) /* * Touch input flag values (TOUCHINPUT.dwFlags) */ #define TOUCHEVENTF_MOVE 0x0001 #define TOUCHEVENTF_DOWN 0x0002 #define TOUCHEVENTF_UP 0x0004 #define TOUCHEVENTF_INRANGE 0x0008 #define TOUCHEVENTF_PRIMARY 0x0010 #define TOUCHEVENTF_NOCOALESCE 0x0020 #define TOUCHEVENTF_PEN 0x0040 #define TOUCHEVENTF_PALM 0x0080 #endif typedef BOOL (WINAPI GetTouchInputInfoFunc)( HTOUCHINPUT hTouchInput, // input event handle; from touch message lParam UINT cInputs, // number of elements in the array PTOUCHINPUT pInputs, // array of touch inputs int cbSize); // sizeof(TOUCHINPUT) typedef BOOL (WINAPI CloseTouchInputHandleFunc( HTOUCHINPUT hTouchInput)); // input event handle; from touch message lParam typedef BOOL (WINAPI RegisterTouchWindowFunc( HWND hwnd, ULONG ulFlags)); // Declared static in order to get Header File clean static RegisterTouchWindowFunc *registerTouchWindowFunc = NULL; static CloseTouchInputHandleFunc *closeTouchInputHandleFunc = NULL; static GetTouchInputInfoFunc *getTouchInputInfoFunc = NULL; using namespace osgViewer; namespace osgViewer { static osg::ApplicationUsageProxy GraphicsWindowWin32_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_WIN32_NV_MULTIMON_MULTITHREAD_WORKAROUND on/off","Enable/disable duplicate makeCurrentContext call used as workaround for WinXP/NVidia/MultiView/MulitThread isues (pre 178.13 drivers)."); // // Defines from the WGL_ARB_pixel_format specification document // See http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt // #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 #define WGL_DRAW_TO_WINDOW_ARB 0x2001 #define WGL_DRAW_TO_BITMAP_ARB 0x2002 #define WGL_ACCELERATION_ARB 0x2003 #define WGL_NEED_PALETTE_ARB 0x2004 #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 #define WGL_SWAP_METHOD_ARB 0x2007 #define WGL_NUMBER_OVERLAYS_ARB 0x2008 #define WGL_NUMBER_UNDERLAYS_ARB 0x2009 #define WGL_TRANSPARENT_ARB 0x200A #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B #define WGL_SHARE_DEPTH_ARB 0x200C #define WGL_SHARE_STENCIL_ARB 0x200D #define WGL_SHARE_ACCUM_ARB 0x200E #define WGL_SUPPORT_GDI_ARB 0x200F #define WGL_SUPPORT_OPENGL_ARB 0x2010 #define WGL_DOUBLE_BUFFER_ARB 0x2011 #define WGL_STEREO_ARB 0x2012 #define WGL_PIXEL_TYPE_ARB 0x2013 #define WGL_COLOR_BITS_ARB 0x2014 #define WGL_RED_BITS_ARB 0x2015 #define WGL_RED_SHIFT_ARB 0x2016 #define WGL_GREEN_BITS_ARB 0x2017 #define WGL_GREEN_SHIFT_ARB 0x2018 #define WGL_BLUE_BITS_ARB 0x2019 #define WGL_BLUE_SHIFT_ARB 0x201A #define WGL_ALPHA_BITS_ARB 0x201B #define WGL_ALPHA_SHIFT_ARB 0x201C #define WGL_ACCUM_BITS_ARB 0x201D #define WGL_ACCUM_RED_BITS_ARB 0x201E #define WGL_ACCUM_GREEN_BITS_ARB 0x201F #define WGL_ACCUM_BLUE_BITS_ARB 0x2020 #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 #define WGL_DEPTH_BITS_ARB 0x2022 #define WGL_STENCIL_BITS_ARB 0x2023 #define WGL_AUX_BUFFERS_ARB 0x2024 #define WGL_NO_ACCELERATION_ARB 0x2025 #define WGL_GENERIC_ACCELERATION_ARB 0x2026 #define WGL_FULL_ACCELERATION_ARB 0x2027 #define WGL_SWAP_EXCHANGE_ARB 0x2028 #define WGL_SWAP_COPY_ARB 0x2029 #define WGL_SWAP_UNDEFINED_ARB 0x202A #define WGL_TYPE_RGBA_ARB 0x202B #define WGL_TYPE_COLORINDEX_ARB 0x202C #define WGL_SAMPLE_BUFFERS_ARB 0x2041 #define WGL_SAMPLES_ARB 0x2042 #ifndef WGL_ARB_create_context #define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 #define WGL_CONTEXT_FLAGS_ARB 0x2094 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 #define ERROR_INVALID_VERSION_ARB 0x2095 #endif #ifndef WGL_ARB_create_context #define WGL_ARB_create_context 1 #ifdef WGL_WGLEXT_PROTOTYPES extern HGLRC WINAPI wglCreateContextAttribsARB (HDC, HGLRC, const int *); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList); #endif // // Entry points used from the WGL extensions // // BOOL wglChoosePixelFormatARB(HDC hdc, // const int *piAttribIList, // const FLOAT *pfAttribFList, // UINT nMaxFormats, // int *piFormats, // UINT *nNumFormats); // typedef bool (WINAPI * WGLChoosePixelFormatARB) ( HDC, const int *, const float *, unsigned int, int *, unsigned int * ); // // Utility class to specify the visual attributes for wglChoosePixelFormatARB() function // template class WGLAttributes { public: WGLAttributes() {} ~WGLAttributes() {} void begin() { m_parameters.clear(); } void set( const T& id, const T& value ) { add(id); add(value); } void enable( const T& id ) { add(id); add(true); } void disable( const T& id ) { add(id); add(false); } void end() { add(0); } const T* get() const { return &m_parameters.front(); } protected: void add( const T& t ) { m_parameters.push_back(t); } std::vector m_parameters; // parameters added private: // No implementation for these WGLAttributes( const WGLAttributes& ); WGLAttributes& operator=( const WGLAttributes& ); }; typedef WGLAttributes WGLIntegerAttributes; typedef WGLAttributes WGLFloatAttributes; // // Class responsible for interfacing with the Win32 Window Manager // The behavior of this class is specific to OSG needs and is not a // generic Windowing interface. // // NOTE: This class is intended to be used by a single-thread. // Multi-threading is not enabled for performance reasons. // The creation/deletion of graphics windows should be done // by a single controller thread. That thread should then // call the checkEvents() method of all created windows periodically. // This is the case with OSG as a "main" thread does all // setup, update & event processing. Rendering is done (optionally) by other threads. // // !@todo Have a dedicated thread managed by the Win32WindowingSystem class handle the // creation and event message processing for all windows it manages. This // is to relieve the "main" thread from having to do this synchronously // during frame generation. The "main" thread would only have to process // each osgGA-type window event queue. // class Win32WindowingSystem : public osg::GraphicsContext::WindowingSystemInterface { public: // A class representing an OpenGL rendering context class OpenGLContext { public: OpenGLContext() : _previousHdc(0), _previousHglrc(0), _hwnd(0), _hdc(0), _hglrc(0), _restorePreviousOnExit(false) {} OpenGLContext( HWND hwnd, HDC hdc, HGLRC hglrc ) : _previousHdc(0), _previousHglrc(0), _hwnd(hwnd), _hdc(hdc), _hglrc(hglrc), _restorePreviousOnExit(false) {} ~OpenGLContext(); void set( HWND hwnd, HDC hdc, HGLRC hglrc ) { _hwnd = hwnd; _hdc = hdc; _hglrc = hglrc; } HDC deviceContext() { return _hdc; } bool makeCurrent( HDC restoreOnHdc, bool restorePreviousOnExit ); protected: // // Data members // HDC _previousHdc; // previously HDC to restore rendering context on HGLRC _previousHglrc; // previously current rendering context HWND _hwnd; // handle to OpenGL window HDC _hdc; // handle to device context HGLRC _hglrc; // handle to OpenGL rendering context bool _restorePreviousOnExit; // restore original context on exit private: // no implementation for these OpenGLContext( const OpenGLContext& ); OpenGLContext& operator=( const OpenGLContext& ); }; static std::string osgGraphicsWindowWithCursorClass; //!< Name of Win32 window class (with cursor) used by OSG graphics window instances static std::string osgGraphicsWindowWithoutCursorClass; //!< Name of Win32 window class (without cursor) used by OSG graphics window instances Win32WindowingSystem(); ~Win32WindowingSystem(); // Access the Win32 windowing system through this singleton class. static Win32WindowingSystem* getInterface() { static Win32WindowingSystem* win32Interface = new Win32WindowingSystem; return win32Interface; } // Return the number of screens present in the system virtual unsigned int getNumScreens( const osg::GraphicsContext::ScreenIdentifier& si ); // Return the resolution of specified screen // (0,0) is returned if screen is unknown virtual void getScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution ); // Return the bits per pixel of specified screen // (0) is returned if screen is unknown virtual void getScreenColorDepth( const osg::GraphicsContext::ScreenIdentifier& si, unsigned int& dmBitsPerPel ); // Set the resolution for given screen virtual bool setScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, const osg::GraphicsContext::ScreenSettings & resolution ); // Enumerates available resolutions virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, osg::GraphicsContext::ScreenSettingsList & resolution); // Return the screen position and width/height. // all zeros returned if screen is unknown virtual void getScreenPosition( const osg::GraphicsContext::ScreenIdentifier& si, int& originX, int& originY, unsigned int& width, unsigned int& height ); // Create a graphics context with given traits virtual osg::GraphicsContext* createGraphicsContext( osg::GraphicsContext::Traits* traits ); // Register a newly created native window along with its application counterpart // This is required to maintain a link between Windows messages and the application window object // at event processing time virtual void registerWindow( HWND hwnd, osgViewer::GraphicsWindowWin32* window ); // Unregister a window // This is called as part of a window being torn down virtual void unregisterWindow( HWND hwnd ); // Get the application window object associated with a native window virtual osgViewer::GraphicsWindowWin32* getGraphicsWindowFor( HWND hwnd ); // Return a valid sample OpenGL Device Context and current rendering context that can be used with wglXYZ extensions virtual bool getSampleOpenGLContext( OpenGLContext& context, HDC windowHDC, int windowOriginX, int windowOriginY ); protected: // Display devices present in the system typedef std::vector DisplayDevices; // Map Win32 window handles to GraphicsWindowWin32 instance typedef std::pair< HWND, osgViewer::GraphicsWindowWin32* > WindowHandleEntry; typedef std::map< HWND, osgViewer::GraphicsWindowWin32* > WindowHandles; // Enumerate all display devices and return in passed container void enumerateDisplayDevices( DisplayDevices& displayDevices ) const; // Get the screen device current mode information bool getScreenInformation( const osg::GraphicsContext::ScreenIdentifier& si, DISPLAY_DEVICE& displayDevice, DEVMODE& deviceMode ); // Change the screen settings (resolution, refresh rate, etc.) bool changeScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, DISPLAY_DEVICE& displayDevice, DEVMODE& deviceMode ); // Register the window classes used by OSG graphics window instances void registerWindowClasses(); // Unregister the window classes used by OSG graphics window instances void unregisterWindowClasses(); // Data members WindowHandles _activeWindows; //!< handles to active windows bool _windowClassesRegistered; //!< true after window classes have been registered private: // No implementation for these Win32WindowingSystem( const Win32WindowingSystem& ); Win32WindowingSystem& operator=( const Win32WindowingSystem& ); }; /////////////////////////////////////////////////////////////////////////////// // Error reporting ////////////////////////////////////////////////////////////////////////////// static void reportError( const std::string& msg ) { OSG_WARN << "Error: " << msg.c_str() << std::endl; } static void reportError( const std::string& msg, unsigned int errorCode ) { // // Some APIs are documented as returning the error in ::GetLastError but apparently do not // Skip "Reason" field if the errorCode is still success // if (errorCode==0) { reportError(msg); return; } OSG_WARN << "Windows Error #" << errorCode << ": " << msg.c_str(); LPVOID lpMsgBuf; if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorCode, 0, // Default language (LPTSTR) &lpMsgBuf, 0, NULL)!=0) { OSG_WARN << ". Reason: " << LPTSTR(lpMsgBuf) << std::endl; ::LocalFree(lpMsgBuf); } else { OSG_WARN << std::endl; } } static void reportErrorForScreen( const std::string& msg, const osg::GraphicsContext::ScreenIdentifier& si, unsigned int errorCode ) { std::ostringstream str; str << "[Screen #" << si.screenNum << "] " << msg; reportError(str.str(), errorCode); } ////////////////////////////////////////////////////////////////////////////// // Keyboard key mapping for Win32 ////////////////////////////////////////////////////////////////////////////// class Win32KeyboardMap { public: Win32KeyboardMap() { _keymap[VK_ESCAPE ] = osgGA::GUIEventAdapter::KEY_Escape; _keymap[VK_F1 ] = osgGA::GUIEventAdapter::KEY_F1; _keymap[VK_F2 ] = osgGA::GUIEventAdapter::KEY_F2; _keymap[VK_F3 ] = osgGA::GUIEventAdapter::KEY_F3; _keymap[VK_F4 ] = osgGA::GUIEventAdapter::KEY_F4; _keymap[VK_F5 ] = osgGA::GUIEventAdapter::KEY_F5; _keymap[VK_F6 ] = osgGA::GUIEventAdapter::KEY_F6; _keymap[VK_F7 ] = osgGA::GUIEventAdapter::KEY_F7; _keymap[VK_F8 ] = osgGA::GUIEventAdapter::KEY_F8; _keymap[VK_F9 ] = osgGA::GUIEventAdapter::KEY_F9; _keymap[VK_F10 ] = osgGA::GUIEventAdapter::KEY_F10; _keymap[VK_F11 ] = osgGA::GUIEventAdapter::KEY_F11; _keymap[VK_F12 ] = osgGA::GUIEventAdapter::KEY_F12; _keymap[0xc0 ] = osgGA::GUIEventAdapter::KEY_Backquote; _keymap['0' ] = osgGA::GUIEventAdapter::KEY_0; _keymap['1' ] = osgGA::GUIEventAdapter::KEY_1; _keymap['2' ] = osgGA::GUIEventAdapter::KEY_2; _keymap['3' ] = osgGA::GUIEventAdapter::KEY_3; _keymap['4' ] = osgGA::GUIEventAdapter::KEY_4; _keymap['5' ] = osgGA::GUIEventAdapter::KEY_5; _keymap['6' ] = osgGA::GUIEventAdapter::KEY_6; _keymap['7' ] = osgGA::GUIEventAdapter::KEY_7; _keymap['8' ] = osgGA::GUIEventAdapter::KEY_8; _keymap['9' ] = osgGA::GUIEventAdapter::KEY_9; _keymap[0xbd ] = osgGA::GUIEventAdapter::KEY_Minus; _keymap[0xbb ] = osgGA::GUIEventAdapter::KEY_Equals; _keymap[VK_BACK ] = osgGA::GUIEventAdapter::KEY_BackSpace; _keymap[VK_TAB ] = osgGA::GUIEventAdapter::KEY_Tab; _keymap['A' ] = osgGA::GUIEventAdapter::KEY_A; _keymap['B' ] = osgGA::GUIEventAdapter::KEY_B; _keymap['C' ] = osgGA::GUIEventAdapter::KEY_C; _keymap['D' ] = osgGA::GUIEventAdapter::KEY_D; _keymap['E' ] = osgGA::GUIEventAdapter::KEY_E; _keymap['F' ] = osgGA::GUIEventAdapter::KEY_F; _keymap['G' ] = osgGA::GUIEventAdapter::KEY_G; _keymap['H' ] = osgGA::GUIEventAdapter::KEY_H; _keymap['I' ] = osgGA::GUIEventAdapter::KEY_I; _keymap['J' ] = osgGA::GUIEventAdapter::KEY_J; _keymap['K' ] = osgGA::GUIEventAdapter::KEY_K; _keymap['L' ] = osgGA::GUIEventAdapter::KEY_L; _keymap['M' ] = osgGA::GUIEventAdapter::KEY_M; _keymap['N' ] = osgGA::GUIEventAdapter::KEY_N; _keymap['O' ] = osgGA::GUIEventAdapter::KEY_O; _keymap['P' ] = osgGA::GUIEventAdapter::KEY_P; _keymap['Q' ] = osgGA::GUIEventAdapter::KEY_Q; _keymap['R' ] = osgGA::GUIEventAdapter::KEY_R; _keymap['S' ] = osgGA::GUIEventAdapter::KEY_S; _keymap['T' ] = osgGA::GUIEventAdapter::KEY_T; _keymap['U' ] = osgGA::GUIEventAdapter::KEY_U; _keymap['V' ] = osgGA::GUIEventAdapter::KEY_V; _keymap['W' ] = osgGA::GUIEventAdapter::KEY_W; _keymap['X' ] = osgGA::GUIEventAdapter::KEY_X; _keymap['Y' ] = osgGA::GUIEventAdapter::KEY_Y; _keymap['Z' ] = osgGA::GUIEventAdapter::KEY_Z; _keymap[0xdb ] = osgGA::GUIEventAdapter::KEY_Leftbracket; _keymap[0xdd ] = osgGA::GUIEventAdapter::KEY_Rightbracket; _keymap[0xdc ] = osgGA::GUIEventAdapter::KEY_Backslash; _keymap[VK_CAPITAL ] = osgGA::GUIEventAdapter::KEY_Caps_Lock; _keymap[0xba ] = osgGA::GUIEventAdapter::KEY_Semicolon; _keymap[0xde ] = osgGA::GUIEventAdapter::KEY_Quote; _keymap[VK_RETURN ] = osgGA::GUIEventAdapter::KEY_Return; _keymap[VK_LSHIFT ] = osgGA::GUIEventAdapter::KEY_Shift_L; _keymap[0xbc ] = osgGA::GUIEventAdapter::KEY_Comma; _keymap[0xbe ] = osgGA::GUIEventAdapter::KEY_Period; _keymap[0xbf ] = osgGA::GUIEventAdapter::KEY_Slash; _keymap[VK_RSHIFT ] = osgGA::GUIEventAdapter::KEY_Shift_R; _keymap[VK_LCONTROL ] = osgGA::GUIEventAdapter::KEY_Control_L; _keymap[VK_LWIN ] = osgGA::GUIEventAdapter::KEY_Super_L; _keymap[VK_SPACE ] = osgGA::GUIEventAdapter::KEY_Space; _keymap[VK_LMENU ] = osgGA::GUIEventAdapter::KEY_Alt_L; _keymap[VK_RMENU ] = osgGA::GUIEventAdapter::KEY_Alt_R; _keymap[VK_RWIN ] = osgGA::GUIEventAdapter::KEY_Super_R; _keymap[VK_APPS ] = osgGA::GUIEventAdapter::KEY_Menu; _keymap[VK_RCONTROL ] = osgGA::GUIEventAdapter::KEY_Control_R; _keymap[VK_SNAPSHOT ] = osgGA::GUIEventAdapter::KEY_Print; _keymap[VK_SCROLL ] = osgGA::GUIEventAdapter::KEY_Scroll_Lock; _keymap[VK_PAUSE ] = osgGA::GUIEventAdapter::KEY_Pause; _keymap[VK_HOME ] = osgGA::GUIEventAdapter::KEY_Home; _keymap[VK_PRIOR ] = osgGA::GUIEventAdapter::KEY_Page_Up; _keymap[VK_END ] = osgGA::GUIEventAdapter::KEY_End; _keymap[VK_NEXT ] = osgGA::GUIEventAdapter::KEY_Page_Down; _keymap[VK_DELETE ] = osgGA::GUIEventAdapter::KEY_Delete; _keymap[VK_INSERT ] = osgGA::GUIEventAdapter::KEY_Insert; _keymap[VK_LEFT ] = osgGA::GUIEventAdapter::KEY_Left; _keymap[VK_UP ] = osgGA::GUIEventAdapter::KEY_Up; _keymap[VK_RIGHT ] = osgGA::GUIEventAdapter::KEY_Right; _keymap[VK_DOWN ] = osgGA::GUIEventAdapter::KEY_Down; _keymap[VK_NUMLOCK ] = osgGA::GUIEventAdapter::KEY_Num_Lock; _keymap[VK_DIVIDE ] = osgGA::GUIEventAdapter::KEY_KP_Divide; _keymap[VK_MULTIPLY ] = osgGA::GUIEventAdapter::KEY_KP_Multiply; _keymap[VK_SUBTRACT ] = osgGA::GUIEventAdapter::KEY_KP_Subtract; _keymap[VK_ADD ] = osgGA::GUIEventAdapter::KEY_KP_Add; _keymap[VK_NUMPAD7 ] = osgGA::GUIEventAdapter::KEY_KP_Home; _keymap[VK_NUMPAD8 ] = osgGA::GUIEventAdapter::KEY_KP_Up; _keymap[VK_NUMPAD9 ] = osgGA::GUIEventAdapter::KEY_KP_Page_Up; _keymap[VK_NUMPAD4 ] = osgGA::GUIEventAdapter::KEY_KP_Left; _keymap[VK_NUMPAD5 ] = osgGA::GUIEventAdapter::KEY_KP_Begin; _keymap[VK_NUMPAD6 ] = osgGA::GUIEventAdapter::KEY_KP_Right; _keymap[VK_NUMPAD1 ] = osgGA::GUIEventAdapter::KEY_KP_End; _keymap[VK_NUMPAD2 ] = osgGA::GUIEventAdapter::KEY_KP_Down; _keymap[VK_NUMPAD3 ] = osgGA::GUIEventAdapter::KEY_KP_Page_Down; _keymap[VK_NUMPAD0 ] = osgGA::GUIEventAdapter::KEY_KP_Insert; _keymap[VK_DECIMAL ] = osgGA::GUIEventAdapter::KEY_KP_Delete; _keymap[VK_CLEAR ] = osgGA::GUIEventAdapter::KEY_Clear; } ~Win32KeyboardMap() {} int remapKey(int key) { KeyMap::const_iterator map = _keymap.find(key); return map==_keymap.end() ? key : map->second; } protected: typedef std::map KeyMap; KeyMap _keymap; }; static Win32KeyboardMap s_win32KeyboardMap; static int remapWin32Key(int key) { return s_win32KeyboardMap.remapKey(key); } ////////////////////////////////////////////////////////////////////////////// // Window procedure for all GraphicsWindowWin32 instances // Dispatches the call to the actual instance ////////////////////////////////////////////////////////////////////////////// static LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { osgViewer::GraphicsWindowWin32* window = Win32WindowingSystem::getInterface()->getGraphicsWindowFor(hwnd); return window ? window->handleNativeWindowingEvent(hwnd, uMsg, wParam, lParam) : ::DefWindowProc(hwnd, uMsg, wParam, lParam); } ////////////////////////////////////////////////////////////////////////////// // Win32WindowingSystem::OpenGLContext implementation ////////////////////////////////////////////////////////////////////////////// Win32WindowingSystem::OpenGLContext::~OpenGLContext() { if (_restorePreviousOnExit && _previousHglrc!=_hglrc && !::wglMakeCurrent(_previousHdc, _previousHglrc)) { reportError("Win32WindowingSystem::OpenGLContext() - Unable to restore current OpenGL rendering context", ::GetLastError()); } _previousHdc = 0; _previousHglrc = 0; if (_hglrc) { ::wglMakeCurrent(_hdc, NULL); ::wglDeleteContext(_hglrc); _hglrc = 0; } if (_hdc) { ::ReleaseDC(_hwnd, _hdc); _hdc = 0; } if (_hwnd) { ::DestroyWindow(_hwnd); _hwnd = 0; } } bool Win32WindowingSystem::OpenGLContext::makeCurrent( HDC restoreOnHdc, bool restorePreviousOnExit ) { if (_hdc==0 || _hglrc==0) return false; _previousHglrc = restorePreviousOnExit ? ::wglGetCurrentContext() : 0; _previousHdc = restoreOnHdc; if (_hglrc==_previousHglrc) return true; if (!::wglMakeCurrent(_hdc, _hglrc)) { reportError("Win32WindowingSystem::OpenGLContext() - Unable to set current OpenGL rendering context", ::GetLastError()); return false; } _restorePreviousOnExit = restorePreviousOnExit; return true; } ////////////////////////////////////////////////////////////////////////////// // Win32WindowingSystem implementation ////////////////////////////////////////////////////////////////////////////// std::string Win32WindowingSystem::osgGraphicsWindowWithCursorClass; std::string Win32WindowingSystem::osgGraphicsWindowWithoutCursorClass; Win32WindowingSystem::Win32WindowingSystem() : _windowClassesRegistered(false) { // Detect presence of runtime support for multitouch HMODULE hModule = LoadLibrary("user32"); if (hModule) { registerTouchWindowFunc = (RegisterTouchWindowFunc *) GetProcAddress( hModule, "RegisterTouchWindow"); closeTouchInputHandleFunc = (CloseTouchInputHandleFunc *) GetProcAddress( hModule, "CloseTouchInputHandle"); getTouchInputInfoFunc = (GetTouchInputInfoFunc *) GetProcAddress( hModule, "GetTouchInputInfo"); if (!(registerTouchWindowFunc && closeTouchInputHandleFunc && getTouchInputInfoFunc)) { registerTouchWindowFunc = NULL; closeTouchInputHandleFunc = NULL; getTouchInputInfoFunc = NULL; FreeLibrary( hModule); } } } Win32WindowingSystem::~Win32WindowingSystem() { if (osg::Referenced::getDeleteHandler()) { osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); osg::Referenced::getDeleteHandler()->flushAll(); } unregisterWindowClasses(); } void Win32WindowingSystem::enumerateDisplayDevices( DisplayDevices& displayDevices ) const { for (unsigned int deviceNum=0;; ++deviceNum) { DISPLAY_DEVICE displayDevice; displayDevice.cb = sizeof(displayDevice); if (!::EnumDisplayDevices(NULL, deviceNum, &displayDevice, 0)) break; // Do not track devices used for remote access (Terminal Services pseudo-displays, etc.) if (displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) continue; // Only return display devices that are attached to the desktop if (!(displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) continue; displayDevices.push_back(displayDevice); } } void Win32WindowingSystem::registerWindowClasses() { if (_windowClassesRegistered) return; // // Register the window classes used by OSG GraphicsWindowWin32 instances // std::ostringstream str; str << "OSG Graphics Window for Win32 [" << ::GetCurrentProcessId() << "]"; osgGraphicsWindowWithCursorClass = str.str() + "{ with cursor }"; osgGraphicsWindowWithoutCursorClass = str.str() + "{ without cursor }"; WNDCLASSEX wc; HINSTANCE hinst = ::GetModuleHandle(NULL); // // First class: class for OSG Graphics Window with a cursor enabled // wc.cbSize = sizeof(wc); wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = WindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hinst; wc.hIcon = ::LoadIcon(hinst, "OSG_ICON"); wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = 0; wc.lpszClassName = osgGraphicsWindowWithCursorClass.c_str(); wc.hIconSm = NULL; if (::RegisterClassEx(&wc)==0) { unsigned int lastError = ::GetLastError(); if (lastError!=ERROR_CLASS_ALREADY_EXISTS) { reportError("Win32WindowingSystem::registerWindowClasses() - Unable to register first window class", lastError); return; } } // // Second class: class for OSG Graphics Window without a cursor // wc.hCursor = NULL; wc.lpszClassName = osgGraphicsWindowWithoutCursorClass.c_str(); if (::RegisterClassEx(&wc)==0) { unsigned int lastError = ::GetLastError(); if (lastError!=ERROR_CLASS_ALREADY_EXISTS) { reportError("Win32WindowingSystem::registerWindowClasses() - Unable to register second window class", lastError); return; } } _windowClassesRegistered = true; } void Win32WindowingSystem::unregisterWindowClasses() { if (_windowClassesRegistered) { ::UnregisterClass(osgGraphicsWindowWithCursorClass.c_str(), ::GetModuleHandle(NULL)); ::UnregisterClass(osgGraphicsWindowWithoutCursorClass.c_str(), ::GetModuleHandle(NULL)); _windowClassesRegistered = false; } } bool Win32WindowingSystem::getSampleOpenGLContext( OpenGLContext& context, HDC windowHDC, int windowOriginX, int windowOriginY ) { context.set(0, 0, 0); registerWindowClasses(); HWND hwnd = ::CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, osgGraphicsWindowWithoutCursorClass.c_str(), NULL, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED, windowOriginX, windowOriginY, 1, 1, NULL, NULL, ::GetModuleHandle(NULL), NULL); if (hwnd==0) { reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to create window", ::GetLastError()); return false; } // // Set the pixel format of the window // PIXELFORMATDESCRIPTOR pixelFormat = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 }; HDC hdc = ::GetDC(hwnd); if (hdc==0) { reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to get window device context", ::GetLastError()); ::DestroyWindow(hwnd); return false; } int pixelFormatIndex = ::ChoosePixelFormat(hdc, &pixelFormat); if (pixelFormatIndex==0) { reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to choose pixel format", ::GetLastError()); ::ReleaseDC(hwnd, hdc); ::DestroyWindow(hwnd); return false; } if (!::SetPixelFormat(hdc, pixelFormatIndex, &pixelFormat)) { reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to set pixel format", ::GetLastError()); ::ReleaseDC(hwnd, hdc); ::DestroyWindow(hwnd); return false; } HGLRC hglrc = ::wglCreateContext(hdc); if (hglrc==0) { reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to create an OpenGL rendering context", ::GetLastError()); ::ReleaseDC(hwnd, hdc); ::DestroyWindow(hwnd); return false; } context.set(hwnd, hdc, hglrc); if (!context.makeCurrent(windowHDC, true)) return false; return true; } unsigned int Win32WindowingSystem::getNumScreens( const osg::GraphicsContext::ScreenIdentifier& si ) { return si.displayNum==0 ? ::GetSystemMetrics(SM_CMONITORS) : 0; } bool Win32WindowingSystem::getScreenInformation( const osg::GraphicsContext::ScreenIdentifier& si, DISPLAY_DEVICE& displayDevice, DEVMODE& deviceMode ) { if (si.displayNum>0) { OSG_WARN << "Win32WindowingSystem::getScreenInformation() - The screen identifier on the Win32 platform must always use display number 0. Value received was " << si.displayNum << std::endl; return false; } DisplayDevices displayDevices; enumerateDisplayDevices(displayDevices); if (si.screenNum>=static_cast(displayDevices.size())) { OSG_WARN << "Win32WindowingSystem::getScreenInformation() - Cannot get information for screen " << si.screenNum << " because it does not exist." << std::endl; return false; } displayDevice = displayDevices[si.screenNum]; deviceMode.dmSize = sizeof(deviceMode); deviceMode.dmDriverExtra = 0; if (!::EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &deviceMode)) { std::ostringstream str; str << "Win32WindowingSystem::getScreenInformation() - Unable to query information for screen number " << si.screenNum; reportError(str.str(), ::GetLastError()); return false; } return true; } void Win32WindowingSystem::getScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution ) { DISPLAY_DEVICE displayDevice; DEVMODE deviceMode; if (!getScreenInformation(si, displayDevice, deviceMode)) deviceMode.dmFields = 0; // Set the fields to 0 so that it says 'nothing'. // Get resolution if ((deviceMode.dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) != 0) { resolution.width = deviceMode.dmPelsWidth; resolution.height = deviceMode.dmPelsHeight; } else { resolution.width = 0; resolution.height = 0; } // Get refersh rate if ((deviceMode.dmFields & DM_DISPLAYFREQUENCY) != 0) { resolution.refreshRate = deviceMode.dmDisplayFrequency; if (resolution.refreshRate == 0 || resolution.refreshRate == 1) { // Windows specific: 0 and 1 represent the hhardware's default refresh rate. // If someone knows how to get this refresh rate (in Hz)... OSG_NOTICE << "Win32WindowingSystem::getScreenSettings() is not fully implemented (cannot retreive the hardware's default refresh rate)."<0 && resolution.height>0) { deviceMode.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT; deviceMode.dmPelsWidth = static_cast(resolution.width); deviceMode.dmPelsHeight = static_cast(resolution.height); } // Set refersh rate if (resolution.refreshRate>0) { deviceMode.dmFields |= DM_DISPLAYFREQUENCY; deviceMode.dmDisplayFrequency = static_cast(resolution.refreshRate); } // Set bits per pixel for color buffer if (resolution.colorDepth>0) { deviceMode.dmFields |= DM_BITSPERPEL; deviceMode.dmBitsPerPel = static_cast(resolution.colorDepth); } return changeScreenSettings(si, displayDevice, deviceMode); } void Win32WindowingSystem::enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettingsList & resolutionList) { resolutionList.clear(); if (si.displayNum>0) { OSG_WARN << "Win32WindowingSystem::enumerateScreenSettings() - The screen identifier on the Win32 platform must always use display number 0. Value received was " << si.displayNum << std::endl; return; } DisplayDevices displayDevices; enumerateDisplayDevices(displayDevices); if (si.screenNum>=static_cast(displayDevices.size())) { OSG_WARN << "Win32WindowingSystem::enumerateScreenSettings() - Cannot get information for screen " << si.screenNum << " because it does not exist." << std::endl; return; } DISPLAY_DEVICE displayDevice = displayDevices[si.screenNum]; // Do the enumeration DEVMODE deviceMode; static const unsigned int MAX_RESOLUTIONS = 4046; // Upper limit to avoid infinite (= very long) loop. for (unsigned int i=0; ipbuffer) { osg::ref_ptr pbuffer = new PixelBufferWin32(traits); if (pbuffer->valid()) return pbuffer.release(); else return 0; } else { registerWindowClasses(); osg::ref_ptr window = new GraphicsWindowWin32(traits); if (window->valid()) return window.release(); else return 0; } } void Win32WindowingSystem::registerWindow( HWND hwnd, osgViewer::GraphicsWindowWin32* window ) { if (hwnd) _activeWindows.insert(WindowHandleEntry(hwnd, window)); } // // Unregister a window // This is called as part of a window being torn down // void Win32WindowingSystem::unregisterWindow( HWND hwnd ) { if (hwnd) _activeWindows.erase(hwnd); } // // Get the application window object associated with a native window // osgViewer::GraphicsWindowWin32* Win32WindowingSystem::getGraphicsWindowFor( HWND hwnd ) { WindowHandles::const_iterator entry = _activeWindows.find(hwnd); return entry==_activeWindows.end() ? 0 : entry->second; } ////////////////////////////////////////////////////////////////////////////// // GraphicsWindowWin32 implementation ////////////////////////////////////////////////////////////////////////////// GraphicsWindowWin32::GraphicsWindowWin32( osg::GraphicsContext::Traits* traits ) : _currentCursor(0), _windowProcedure(0), _timeOfLastCheckEvents(-1.0), _screenOriginX(0), _screenOriginY(0), _screenWidth(0), _screenHeight(0), _windowOriginXToRealize(0), _windowOriginYToRealize(0), _windowWidthToRealize(0), _windowHeightToRealize(0), _initialized(false), _valid(false), _realized(false), _ownsWindow(true), _closeWindow(false), _destroyWindow(false), _destroying(false), _mouseCursor(InheritCursor), _appMouseCursor(LeftArrowCursor), _applyWorkaroundForMultimonitorMultithreadNVidiaWin32Issues( false ) { _traits = traits; if (_traits->useCursor) setCursor(LeftArrowCursor); else setCursor(NoCursor); init(); if (valid()) { setState( new osg::State ); getState()->setGraphicsContext(this); if (_traits.valid() && _traits->sharedContext.valid()) { getState()->setContextID( _traits->sharedContext->getState()->getContextID() ); incrementContextIDUsageCount( getState()->getContextID() ); } else { getState()->setContextID( osg::GraphicsContext::createNewContextID() ); } } } GraphicsWindowWin32::~GraphicsWindowWin32() { close(); destroyWindow(); } void GraphicsWindowWin32::init() { if (_initialized) return; // getEventQueue()->setCurrentEventState(osgGA::GUIEventAdapter::getAccumulatedEventState().get()); WindowData *windowData = _traits.get() ? dynamic_cast(_traits->inheritedWindowData.get()) : 0; HWND windowHandle = windowData ? windowData->_hwnd : 0; _ownsWindow = windowHandle==0; _closeWindow = false; _destroyWindow = false; _destroying = false; _initialized = _ownsWindow ? createWindow() : setWindow(windowHandle); _valid = _initialized; // make sure the event queue has the correct window rectangle size and input range getEventQueue()->syncWindowRectangleWithGraphcisContext(); // 2008/10/03 // Few days ago NVidia released WHQL certified drivers ver 178.13. // These drivers (as well as former beta ver 177.92) were free from the bug described below. // So it looks like its high time to make the workaround inactive by default. // If you happen to still use earlier drivers and have problems consider changing to new ones or // activate OSG_MULTIMONITOR_MULTITHREAD_WIN32_NVIDIA_WORKAROUND macro def through CMake advanced vars. #ifdef OSG_MULTIMONITOR_MULTITHREAD_WIN32_NVIDIA_WORKAROUND // 2008/05/12 // Workaround for Bugs in NVidia drivers for windows XP / multithreaded / dualview / multicore CPU // affects GeForce 6x00, 7x00, 8x00 boards (others were not tested) driver versions 174.xx - 175.xx // pre 174.xx had other issues so reverting is not an option (statitistics, fbo) // drivers release 175.16 is the latest currently available // // When using OpenGL in threaded app ( main thread sets up context / renderer thread draws using it ) // first wglMakeCurrent seems to not work right and screw OpenGL context driver data: // 1: succesive drawing shows a number of artifacts in TriangleStrips and TriangleFans // 2: weird behaviour of FramBufferObjects (glGenFramebuffer generates already generated ids ...) // Looks like repeating wglMakeCurrent call fixes all these issues // wglMakeCurrent call can impact performance so I try to minimize number of // wglMakeCurrent calls by checking current HDC and GL context // and repeat wglMakeCurrent only when they change for current thread _applyWorkaroundForMultimonitorMultithreadNVidiaWin32Issues = true; #endif const char* str = getenv("OSG_WIN32_NV_MULTIMON_MULTITHREAD_WORKAROUND"); if (str) { _applyWorkaroundForMultimonitorMultithreadNVidiaWin32Issues = (strcmp(str, "on")==0 || strcmp(str, "ON")==0 || strcmp(str, "On")==0 ); } } bool GraphicsWindowWin32::createWindow() { unsigned int extendedStyle; unsigned int windowStyle; if (!determineWindowPositionAndStyle(_traits->screenNum, _traits->x, _traits->y, _traits->width, _traits->height, _traits->windowDecoration, _windowOriginXToRealize, _windowOriginYToRealize, _windowWidthToRealize, _windowHeightToRealize, windowStyle, extendedStyle)) { reportError("GraphicsWindowWin32::createWindow() - Unable to determine the window position and style"); return false; } _hwnd = ::CreateWindowEx(extendedStyle, _traits->useCursor ? Win32WindowingSystem::osgGraphicsWindowWithCursorClass.c_str() : Win32WindowingSystem::osgGraphicsWindowWithoutCursorClass.c_str(), _traits->windowName.c_str(), windowStyle, _windowOriginXToRealize, _windowOriginYToRealize, _windowWidthToRealize, _windowHeightToRealize, NULL, NULL, ::GetModuleHandle(NULL), NULL); if (_hwnd==0) { reportErrorForScreen("GraphicsWindowWin32::createWindow() - Unable to create window", _traits->screenNum, ::GetLastError()); return false; } _hdc = ::GetDC(_hwnd); if (_hdc==0) { reportErrorForScreen("GraphicsWindowWin32::createWindow() - Unable to get window device context", _traits->screenNum, ::GetLastError()); destroyWindow(); _hwnd = 0; return false; } // // Set the pixel format according to traits specified // if (!setPixelFormat()) { ::ReleaseDC(_hwnd, _hdc); _hdc = 0; destroyWindow(); return false; } // // Create the OpenGL rendering context associated with this window // _hglrc = createContextImplementation(); if (_hglrc==0) { reportErrorForScreen("GraphicsWindowWin32::createWindow() - Unable to create OpenGL rendering context", _traits->screenNum, ::GetLastError()); ::ReleaseDC(_hwnd, _hdc); _hdc = 0; destroyWindow(); return false; } Win32WindowingSystem::getInterface()->registerWindow(_hwnd, this); if (registerTouchWindowFunc) (*registerTouchWindowFunc)( _hwnd, 0); return true; } bool GraphicsWindowWin32::setWindow( HWND handle ) { if (_initialized) { reportErrorForScreen("GraphicsWindowWin32::setWindow() - Window already created; it cannot be changed", _traits->screenNum, ::GetLastError()); return false; } if (handle==0) { reportErrorForScreen("GraphicsWindowWin32::setWindow() - Invalid window handle passed", _traits->screenNum, ::GetLastError()); return false; } _hwnd = handle; if (_hwnd==0) { reportErrorForScreen("GraphicsWindowWin32::setWindow() - Unable to retrieve native window handle", _traits->screenNum, ::GetLastError()); return false; } _hdc = ::GetDC(_hwnd); if (_hdc==0) { reportErrorForScreen("GraphicsWindowWin32::setWindow() - Unable to get window device context", _traits->screenNum, ::GetLastError()); _hwnd = 0; return false; } // // Check if we must set the pixel format of the inherited window // if (!setPixelFormat()) { reportErrorForScreen("GraphicsWindowWin32::setWindow() - Unable to set the inherited window pixel format", _traits->screenNum, ::GetLastError()); ::ReleaseDC(_hwnd, _hdc); _hdc = 0; _hwnd = 0; return false; } _hglrc = createContextImplementation(); if (_hglrc==0) { reportErrorForScreen("GraphicsWindowWin32::setWindow() - Unable to create OpenGL rendering context", _traits->screenNum, ::GetLastError()); ::ReleaseDC(_hwnd, _hdc); _hdc = 0; _hwnd = 0; return false; } WindowData *windowData = _traits.get() ? dynamic_cast(_traits->inheritedWindowData.get()) : 0; if (!windowData || windowData->_installEventHandler) { if (!registerWindowProcedure()) { ::wglDeleteContext(_hglrc); _hglrc = 0; ::ReleaseDC(_hwnd, _hdc); _hdc = 0; _hwnd = 0; return false; } } Win32WindowingSystem::getInterface()->registerWindow(_hwnd, this); _initialized = true; _valid = true; return true; } void GraphicsWindowWin32::destroyWindow( bool deleteNativeWindow ) { if (_destroying) return; _destroying = true; if (_graphicsThread && _graphicsThread->isRunning()) { // find all the viewers that might own use this graphics context osg::GraphicsContext::Cameras cameras = getCameras(); for(osg::GraphicsContext::Cameras::iterator it=cameras.begin(); it!=cameras.end(); ++it) { osgViewer::View* view = dynamic_cast((*it)->getView()); osgViewer::ViewerBase* viewerBase = view ? view->getViewerBase() : 0; if (viewerBase && viewerBase->areThreadsRunning()) { viewerBase->stopThreading(); } } } if (_hdc) { releaseContext(); if (_hglrc) { ::wglDeleteContext(_hglrc); _hglrc = 0; } ::ReleaseDC(_hwnd, _hdc); _hdc = 0; } (void)unregisterWindowProcedure(); if (_hwnd) { Win32WindowingSystem::getInterface()->unregisterWindow(_hwnd); if (_ownsWindow && deleteNativeWindow) ::DestroyWindow(_hwnd); _hwnd = 0; } _initialized = false; _realized = false; _valid = false; _destroying = false; } void GraphicsWindowWin32::registerWindow() { Win32WindowingSystem::getInterface()->registerWindow(_hwnd, this); } void GraphicsWindowWin32::unregisterWindow() { Win32WindowingSystem::getInterface()->unregisterWindow(_hwnd); } bool GraphicsWindowWin32::registerWindowProcedure() { ::SetLastError(0); _windowProcedure = (WNDPROC)::SetWindowLongPtr(_hwnd, GWLP_WNDPROC, LONG_PTR(WindowProc)); unsigned int error = ::GetLastError(); if (_windowProcedure==0 && error) { reportErrorForScreen("GraphicsWindowWin32::registerWindowProcedure() - Unable to register window procedure", _traits->screenNum, error); return false; } return true; } bool GraphicsWindowWin32::unregisterWindowProcedure() { if (_windowProcedure==0 || _hwnd==0) return true; ::SetLastError(0); WNDPROC wndProc = (WNDPROC)::SetWindowLongPtr(_hwnd, GWLP_WNDPROC, LONG_PTR(_windowProcedure)); unsigned int error = ::GetLastError(); if (wndProc==0 && error) { reportErrorForScreen("GraphicsWindowWin32::unregisterWindowProcedure() - Unable to unregister window procedure", _traits->screenNum, error); return false; } _windowProcedure = 0; return true; } bool GraphicsWindowWin32::determineWindowPositionAndStyle( unsigned int screenNum, int clientAreaX, int clientAreaY, unsigned int clientAreaWidth, unsigned int clientAreaHeight, bool decorated, int& x, int& y, unsigned int& w, unsigned int& h, unsigned int& style, unsigned int& extendedStyle ) { if (_traits==0) return false; // // Query the screen position and size // osg::GraphicsContext::ScreenIdentifier screenId(screenNum); Win32WindowingSystem* windowManager = Win32WindowingSystem::getInterface(); windowManager->getScreenPosition(screenId, _screenOriginX, _screenOriginY, _screenWidth, _screenHeight); if (_screenWidth==0 || _screenHeight==0) return false; x = clientAreaX + _screenOriginX; y = clientAreaY + _screenOriginY; w = clientAreaWidth; h = clientAreaHeight; style = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; extendedStyle = 0; if (decorated) { style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; if (_traits->supportsResize) style |= WS_SIZEBOX; extendedStyle = WS_EX_APPWINDOW | WS_EX_OVERLAPPEDWINDOW | WS_EX_ACCEPTFILES | WS_EX_LTRREADING; RECT corners; corners.left = x; corners.top = y; corners.right = x + w - 1; corners.bottom = y + h - 1; // // Determine the location of the window corners in order to have // a client area of the requested size // if (!::AdjustWindowRectEx(&corners, style, FALSE, extendedStyle)) { reportErrorForScreen("GraphicsWindowWin32::determineWindowPositionAndStyle() - Unable to adjust window rectangle", _traits->screenNum, ::GetLastError()); return false; } x = corners.left; y = corners.top; w = corners.right - corners.left + 1; h = corners.bottom - corners.top + 1; } return true; } static void PreparePixelFormatSpecifications( const osg::GraphicsContext::Traits& traits, WGLIntegerAttributes& attributes, bool allowSwapExchangeARB ) { attributes.begin(); attributes.enable(WGL_DRAW_TO_WINDOW_ARB); attributes.enable(WGL_SUPPORT_OPENGL_ARB); attributes.set(WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB); attributes.set(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB); attributes.set(WGL_COLOR_BITS_ARB, traits.red + traits.green + traits.blue); attributes.set(WGL_RED_BITS_ARB, traits.red); attributes.set(WGL_GREEN_BITS_ARB, traits.green); attributes.set(WGL_BLUE_BITS_ARB, traits.blue); attributes.set(WGL_DEPTH_BITS_ARB, traits.depth); if (traits.doubleBuffer) { attributes.enable(WGL_DOUBLE_BUFFER_ARB); switch ( traits.swapMethod ) { case osg::DisplaySettings::SWAP_COPY: attributes.set(WGL_SWAP_METHOD_ARB, WGL_SWAP_COPY_ARB); break; case osg::DisplaySettings::SWAP_EXCHANGE: attributes.set(WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_ARB); break; case osg::DisplaySettings::SWAP_UNDEFINED: attributes.set(WGL_SWAP_METHOD_ARB, WGL_SWAP_UNDEFINED_ARB); break; case osg::DisplaySettings::SWAP_DEFAULT: // Wojtek Lewandowski 2010-09-28: // Keep backward compatibility if no method is selected via traits // and let wglSwapExchangeARB flag select swap method. // However, I would rather remove this flag because its // now redundant to Traits::swapMethod and it looks like // WGL_SWAP_EXCHANGE_ARB is the GL default when no WGL_SWAP attrib is given. // To be precise: At least on Windows 7 and Nvidia it seems to be a default. if ( allowSwapExchangeARB ) attributes.set(WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_ARB); break; } } if (traits.alpha) attributes.set(WGL_ALPHA_BITS_ARB, traits.alpha); if (traits.stencil) attributes.set(WGL_STENCIL_BITS_ARB, traits.stencil); if (traits.sampleBuffers) attributes.set(WGL_SAMPLE_BUFFERS_ARB, traits.sampleBuffers); if (traits.samples) attributes.set(WGL_SAMPLES_ARB, traits.samples); if (traits.quadBufferStereo) attributes.enable(WGL_STEREO_ARB); attributes.end(); } static int ChooseMatchingPixelFormat( HDC hdc, int screenNum, const WGLIntegerAttributes& formatSpecifications ,osg::GraphicsContext::Traits* _traits) { // // Access the entry point for the wglChoosePixelFormatARB function // WGLChoosePixelFormatARB wglChoosePixelFormatARB = (WGLChoosePixelFormatARB)wglGetProcAddress("wglChoosePixelFormatARB"); if (wglChoosePixelFormatARB==0) { // = openGLContext.getTraits() reportErrorForScreen("ChooseMatchingPixelFormat() - wglChoosePixelFormatARB extension not found, trying GDI", screenNum, ::GetLastError()); PIXELFORMATDESCRIPTOR pixelFormat = { sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd 1, // version number PFD_DRAW_TO_WINDOW | // support window PFD_SUPPORT_OPENGL | // support OpenGL (_traits->doubleBuffer ? PFD_DOUBLEBUFFER : NULL) | // double buffered ? (_traits->swapMethod == osg::DisplaySettings::SWAP_COPY ? PFD_SWAP_COPY : NULL) | (_traits->swapMethod == osg::DisplaySettings::SWAP_EXCHANGE ? PFD_SWAP_EXCHANGE : NULL), PFD_TYPE_RGBA, // RGBA type _traits->red + _traits->green + _traits->blue, // color depth _traits->red ,0, _traits->green ,0, _traits->blue, 0, // shift bits ignored _traits->alpha, // alpha buffer ? 0, // shift bit ignored 0, // no accumulation buffer 0, 0, 0, 0, // accum bits ignored _traits->depth, // 32 or 16 bit z-buffer ? _traits->stencil, // stencil buffer ? 0, // no auxiliary buffer PFD_MAIN_PLANE, // main layer 0, // reserved 0, 0, 0 // layer masks ignored }; int pixelFormatIndex = ::ChoosePixelFormat(hdc, &pixelFormat); if (pixelFormatIndex == 0) { reportErrorForScreen("ChooseMatchingPixelFormat() - GDI ChoosePixelFormat Failed.", screenNum, ::GetLastError()); return -1; } ::DescribePixelFormat(hdc, pixelFormatIndex ,sizeof(PIXELFORMATDESCRIPTOR),&pixelFormat); if (((pixelFormat.dwFlags & PFD_GENERIC_FORMAT) != 0) && ((pixelFormat.dwFlags & PFD_GENERIC_ACCELERATED) == 0)) { OSG_WARN << "Rendering in software: pixelFormatIndex " << pixelFormatIndex << std::endl; } return pixelFormatIndex; } int pixelFormatIndex = 0; unsigned int numMatchingPixelFormats = 0; if (!wglChoosePixelFormatARB(hdc, formatSpecifications.get(), NULL, 1, &pixelFormatIndex, &numMatchingPixelFormats)) { reportErrorForScreen("ChooseMatchingPixelFormat() - Unable to choose the requested pixel format", screenNum, ::GetLastError()); return -1; } return numMatchingPixelFormats==0 ? -1 : pixelFormatIndex; } bool GraphicsWindowWin32::setPixelFormat() { Win32WindowingSystem::OpenGLContext openGLContext; if (!Win32WindowingSystem::getInterface()->getSampleOpenGLContext(openGLContext, _hdc, _screenOriginX, _screenOriginY)) return false; // // Build the specifications of the requested pixel format // WGLIntegerAttributes formatSpecs; ::PreparePixelFormatSpecifications(*_traits, formatSpecs, true); // // Choose the closest matching pixel format from the specified traits // int pixelFormatIndex = ::ChooseMatchingPixelFormat(openGLContext.deviceContext(), _traits->screenNum, formatSpecs,_traits.get()); if (pixelFormatIndex<0) { unsigned int bpp; Win32WindowingSystem::getInterface()->getScreenColorDepth(*_traits.get(), bpp); if (bpp < 32) { OSG_INFO << "GraphicsWindowWin32::setPixelFormat() - Display setting is not 32 bit colors, " << bpp << " bits per pixel on screen #" << _traits->screenNum << std::endl; _traits->red = bpp / 4; //integer devide, determine minimum number of bits we will accept _traits->green = bpp / 4; _traits->blue = bpp / 4; ::PreparePixelFormatSpecifications(*_traits, formatSpecs, true);// try again with WGL_SWAP_METHOD_ARB pixelFormatIndex = ::ChooseMatchingPixelFormat(openGLContext.deviceContext(), _traits->screenNum, formatSpecs,_traits.get()); } } if (pixelFormatIndex<0) { ::PreparePixelFormatSpecifications(*_traits, formatSpecs, false); pixelFormatIndex = ::ChooseMatchingPixelFormat(openGLContext.deviceContext(), _traits->screenNum, formatSpecs,_traits.get()); if (pixelFormatIndex<0) { reportErrorForScreen("GraphicsWindowWin32::setPixelFormat() - No matching pixel format found based on traits specified", _traits->screenNum, 0); return false; } OSG_INFO << "GraphicsWindowWin32::setPixelFormat() - Found a matching pixel format but without the WGL_SWAP_METHOD_ARB specification for screen #" << _traits->screenNum << std::endl; } // // Set the pixel format found // PIXELFORMATDESCRIPTOR pfd; ::memset(&pfd, 0, sizeof(pfd)); pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); pfd.nVersion = 1; if (!::SetPixelFormat(_hdc, pixelFormatIndex, &pfd)) { reportErrorForScreen("GraphicsWindowWin32::setPixelFormat() - Unable to set pixel format", _traits->screenNum, ::GetLastError()); return false; } return true; } HGLRC GraphicsWindowWin32::createContextImplementation() { HGLRC context( NULL ); if( OSG_GL3_FEATURES ) { OSG_NOTIFY( osg::INFO ) << "GL3: Attempting to create OpenGL3 context." << std::endl; OSG_NOTIFY( osg::INFO ) << "GL3: version: " << _traits->glContextVersion << std::endl; OSG_NOTIFY( osg::INFO ) << "GL3: context flags: " << _traits->glContextFlags << std::endl; OSG_NOTIFY( osg::INFO ) << "GL3: profile: " << _traits->glContextProfileMask << std::endl; Win32WindowingSystem::OpenGLContext openGLContext; if( !Win32WindowingSystem::getInterface()->getSampleOpenGLContext( openGLContext, _hdc, _screenOriginX, _screenOriginY ) ) { reportErrorForScreen( "GL3: Can't create sample context.", _traits->screenNum, ::GetLastError() ); } else { PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = ( PFNWGLCREATECONTEXTATTRIBSARBPROC ) wglGetProcAddress( "wglCreateContextAttribsARB" ); if( wglCreateContextAttribsARB==0 ) { reportErrorForScreen( "GL3: wglCreateContextAttribsARB not available.", _traits->screenNum, ::GetLastError() ); } else { unsigned int idx( 0 ); int attribs[ 16 ]; unsigned int major = 1, minor = 0; if( !_traits->getContextVersion(major, minor) || major<3 ) { OSG_NOTIFY( osg::WARN ) << "GL3: Non-GL3 version number: " << _traits->glContextVersion << std::endl; } attribs[ idx++ ] = WGL_CONTEXT_MAJOR_VERSION_ARB; attribs[ idx++ ] = major; attribs[ idx++ ] = WGL_CONTEXT_MINOR_VERSION_ARB; attribs[ idx++ ] = minor; if( _traits->glContextFlags != 0 ) { attribs[ idx++ ] = WGL_CONTEXT_FLAGS_ARB; attribs[ idx++ ] = _traits->glContextFlags; } if( _traits->glContextProfileMask != 0 ) { attribs[ idx++ ] = WGL_CONTEXT_PROFILE_MASK_ARB; attribs[ idx++ ] = _traits->glContextProfileMask; } attribs[ idx++ ] = 0; context = wglCreateContextAttribsARB( _hdc, 0, attribs ); if( context == NULL ) { reportErrorForScreen( "GL3: wglCreateContextAttribsARB returned NULL.", _traits->screenNum, ::GetLastError() ); } else { OSG_NOTIFY( osg::INFO ) << "GL3: context created successfully." << std::endl; } } } } // TBD insert GL ES 2 suppurt, if required for Win32. // If platform context creation fails for any reason, // we'll create a standard context. This means you could // build OSG for GL3, have the context creation fail // (because you have the wrong driver), and end up with // a GL3 context. Something else will likely fail down // the line, as the GL3-built OSG will assume GL3 features // are present. // // This is also the typical path for GL 1/2 context creation. if( context == NULL ) context = ::wglCreateContext(_hdc); return( context ); } bool GraphicsWindowWin32::setWindowDecorationImplementation( bool decorated ) { unsigned int windowStyle; unsigned int extendedStyle; // // Determine position and size of window with/without decorations to retain the size specified in traits // int x, y; unsigned int w, h; if (!determineWindowPositionAndStyle(_traits->screenNum, _traits->x, _traits->y, _traits->width, _traits->height, decorated, x, y, w, h, windowStyle, extendedStyle)) { reportErrorForScreen("GraphicsWindowWin32::setWindowDecoration() - Unable to determine the window position and style", _traits->screenNum, 0); return false; } // // Change the window style // ::SetLastError(0); unsigned int result = ::SetWindowLong(_hwnd, GWL_STYLE, windowStyle); unsigned int error = ::GetLastError(); if (result==0 && error) { reportErrorForScreen("GraphicsWindowWin32::setWindowDecoration() - Unable to set window style", _traits->screenNum, error); return false; } // // Change the window extended style // ::SetLastError(0); result = ::SetWindowLong(_hwnd, GWL_EXSTYLE, extendedStyle); error = ::GetLastError(); if (result==0 && error) { reportErrorForScreen("GraphicsWindowWin32::setWindowDecoration() - Unable to set window extented style", _traits->screenNum, error); return false; } // // Change the window position and size and realize the style changes // if (!::SetWindowPos(_hwnd, HWND_TOP, x, y, w, h, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_SHOWWINDOW)) { reportErrorForScreen("GraphicsWindowWin32::setWindowDecoration() - Unable to set new window position and size", _traits->screenNum, ::GetLastError()); return false; } // // Force a repaint of the desktop // ::InvalidateRect(NULL, NULL, TRUE); return true; } bool GraphicsWindowWin32::realizeImplementation() { if (_realized) return true; if (!_initialized) { init(); if (!_initialized) return false; } if (_traits.valid() && (_traits->sharedContext.valid() || _traits->vsync || _traits->swapGroupEnabled)) { // make context current so we can test capabilities and set up context sharing struct RestoreContext { RestoreContext() { _hdc = wglGetCurrentDC(); _hglrc = wglGetCurrentContext(); } ~RestoreContext() { wglMakeCurrent(_hdc,_hglrc); } protected: HDC _hdc; HGLRC _hglrc; } restoreContext; _realized = true; bool result = makeCurrent(); _realized = false; if (!result) { return false; } // set up sharing of contexts if required GraphicsHandleWin32* graphicsHandleWin32 = dynamic_cast(_traits->sharedContext.get()); if (graphicsHandleWin32) { if (!wglShareLists(graphicsHandleWin32->getWGLContext(), getWGLContext())) { reportErrorForScreen("GraphicsWindowWin32::realizeImplementation() - Unable to share OpenGL context", _traits->screenNum, ::GetLastError()); return false; } } // if vysnc should be on then enable it. if (_traits->vsync) { setSyncToVBlank(_traits->vsync); } // If the swap group is active then enable it. if (_traits->swapGroupEnabled) { setSwapGroup(_traits->swapGroupEnabled, _traits->swapGroup, _traits->swapBarrier); } } if (_ownsWindow) { // // Bring the window on top of other ones (including the taskbar if it covers it completely) // // NOTE: To cover the taskbar with a window that does not completely cover it, the HWND_TOPMOST // Z-order must be used in the code below instead of HWND_TOP. // @todo: This should be controlled through a flag in the traits (topMostWindow) // if (!::SetWindowPos(_hwnd, HWND_TOP, _windowOriginXToRealize, _windowOriginYToRealize, _windowWidthToRealize, _windowHeightToRealize, SWP_SHOWWINDOW)) { reportErrorForScreen("GraphicsWindowWin32::realizeImplementation() - Unable to show window", _traits->screenNum, ::GetLastError()); return false; } if (!::UpdateWindow(_hwnd)) { reportErrorForScreen("GraphicsWindowWin32::realizeImplementation() - Unable to update window", _traits->screenNum, ::GetLastError()); return false; } } _realized = true; // make sure the event queue has the correct window rectangle size and input range getEventQueue()->syncWindowRectangleWithGraphcisContext(); return true; } bool GraphicsWindowWin32::makeCurrentImplementation() { if (!_realized) { reportErrorForScreen("GraphicsWindowWin32::makeCurrentImplementation() - Window not realized; cannot do makeCurrent.", _traits->screenNum, 0); return false; } if( _applyWorkaroundForMultimonitorMultithreadNVidiaWin32Issues ) { if( ::wglGetCurrentDC() != _hdc || ::wglGetCurrentContext() != _hglrc ) { if (!::wglMakeCurrent(_hdc, _hglrc)) { reportErrorForScreen("GraphicsWindowWin32::makeCurrentImplementation() - Unable to set current OpenGL rendering context", _traits->screenNum, ::GetLastError()); return false; } } } if (!::wglMakeCurrent(_hdc, _hglrc)) { reportErrorForScreen("GraphicsWindowWin32::makeCurrentImplementation() - Unable to set current OpenGL rendering context", _traits->screenNum, ::GetLastError()); return false; } return true; } bool GraphicsWindowWin32::releaseContextImplementation() { if (!::wglMakeCurrent(_hdc, NULL)) { reportErrorForScreen("GraphicsWindowWin32::releaseContextImplementation() - Unable to release current OpenGL rendering context", _traits->screenNum, ::GetLastError()); return false; } return true; } void GraphicsWindowWin32::closeImplementation() { destroyWindow(); _initialized = false; _valid = false; _realized = false; } void GraphicsWindowWin32::swapBuffersImplementation() { if (!_realized) return; if (!::SwapBuffers(_hdc) && ::GetLastError() != 0) { reportErrorForScreen("GraphicsWindowWin32::swapBuffersImplementation() - Unable to swap display buffers", _traits->screenNum, ::GetLastError()); } } bool GraphicsWindowWin32::checkEvents() { if (!_realized) return false; MSG msg; while (::PeekMessage(&msg, _hwnd, 0, 0, PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } if (_closeWindow) { _closeWindow = false; close(); } if (_destroyWindow) { _destroyWindow = false; destroyWindow(false); } return !(getEventQueue()->empty()); } void GraphicsWindowWin32::grabFocus() { if (!::SetForegroundWindow(_hwnd)) { OSG_WARN << "Warning: GraphicsWindowWin32::grabFocus() - Failed grabbing the focus" << std::endl; } } void GraphicsWindowWin32::grabFocusIfPointerInWindow() { POINT mousePos; if (!::GetCursorPos(&mousePos)) { reportErrorForScreen("GraphicsWindowWin32::grabFocusIfPointerInWindow() - Unable to get cursor position", _traits->screenNum, ::GetLastError()); return; } RECT windowRect; if (!::GetWindowRect(_hwnd, &windowRect)) { reportErrorForScreen("GraphicsWindowWin32::grabFocusIfPointerInWindow() - Unable to get window position", _traits->screenNum, ::GetLastError()); return; } if (mousePos.x>=windowRect.left && mousePos.x<=windowRect.right && mousePos.y>=windowRect.top && mousePos.y<=windowRect.bottom) { grabFocus(); } } void GraphicsWindowWin32::requestWarpPointer( float x, float y ) { if (!_realized) { OSG_INFO<<"GraphicsWindowWin32::requestWarpPointer() - Window not realized; cannot warp pointer, screenNum="<< _traits->screenNum<screenNum, ::GetLastError()); return; } if (!::SetCursorPos(windowRect.left + x, windowRect.top + y)) { reportErrorForScreen("GraphicsWindowWin32::requestWarpPointer() - Unable to set cursor position", _traits->screenNum, ::GetLastError()); return; } #else // MIKEC: NEW CODE POINT pt; pt.x = (LONG)x; pt.y = (LONG)y; // convert point in client area coordinates to screen coordinates if (!::ClientToScreen(_hwnd, &pt)) { reportErrorForScreen("GraphicsWindowWin32::requestWarpPointer() - Unable to convert cursor position to screen coordinates", _traits->screenNum, ::GetLastError()); } if (!::SetCursorPos(pt.x, pt.y)) { reportErrorForScreen("GraphicsWindowWin32::requestWarpPointer() - Unable to set cursor position", _traits->screenNum, ::GetLastError()); return; } #endif getEventQueue()->mouseWarped(x,y); } bool GraphicsWindowWin32::setWindowRectangleImplementation(int x, int y, int width, int height) { unsigned int windowStyle; unsigned int extendedStyle; // // Determine position and size of window with/without decorations to retain the size specified in traits // int wx, wy; unsigned int ww, wh; if (!determineWindowPositionAndStyle(_traits->screenNum, x, y, width, height, _traits->windowDecoration, wx, wy, ww, wh, windowStyle, extendedStyle)) { reportErrorForScreen("GraphicsWindowWin32::setWindowRectangleImplementation() - Unable to determine the window position and style", _traits->screenNum, 0); return false; } if (!::SetWindowPos(_hwnd, HWND_TOP, wx, wy, ww, wh, SWP_SHOWWINDOW | SWP_FRAMECHANGED)) { reportErrorForScreen("GraphicsWindowWin32::setWindowRectangleImplementation() - Unable to set new window position and size", _traits->screenNum, ::GetLastError()); return false; } return true; } void GraphicsWindowWin32::setWindowName( const std::string & name ) { _traits->windowName = name; SetWindowText(_hwnd, name.c_str()); } void GraphicsWindowWin32::useCursor( bool cursorOn ) { if (_traits.valid()) _traits->useCursor = cursorOn; // note, we are using setCursorImpl to set the cursor, so we can use // _appMouseCursor to cache the current mouse-cursor setCursorImpl(cursorOn ? _appMouseCursor : NoCursor); } void GraphicsWindowWin32::setCursor( MouseCursor mouseCursor ) { _appMouseCursor = mouseCursor; setCursorImpl(mouseCursor); } void GraphicsWindowWin32::setCursorImpl( MouseCursor mouseCursor ) { if (_mouseCursor != mouseCursor) { _mouseCursor = mouseCursor; HCURSOR newCursor = getOrCreateCursor( mouseCursor); if (newCursor == _currentCursor) return; _currentCursor = newCursor; _traits->useCursor = (_currentCursor != NULL) && (_mouseCursor != NoCursor); if (_mouseCursor != InheritCursor) ::SetCursor(_currentCursor); } } HCURSOR GraphicsWindowWin32::getOrCreateCursor(MouseCursor mouseCursor) { std::map::iterator i = _mouseCursorMap.find(mouseCursor); if (i != _mouseCursorMap.end()) return i->second; switch (mouseCursor) { case NoCursor: _mouseCursorMap[mouseCursor] = NULL; break; case RightArrowCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_ARROW); break; case LeftArrowCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_ARROW); break; case InfoCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZEALL); break; case DestroyCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_NO ); break; case HelpCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_HELP ); break; case CycleCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_NO ); break; case SprayCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZEALL ); break; case WaitCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_WAIT); break; case TextCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_IBEAM ); break; case CrosshairCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_CROSS ); break; case UpDownCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZENS ); break; case LeftRightCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZEWE ); break; case TopSideCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_UPARROW ); break; case BottomSideCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_UPARROW ); break; case LeftSideCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZEWE); break; case RightSideCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZEWE ); break; case TopLeftCorner: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZENWSE ); break; case TopRightCorner: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZENESW ); break; case BottomRightCorner: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZENWSE ); break; case BottomLeftCorner: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZENESW ); break; case HandCursor: _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_HAND ); break; default: break; } return _mouseCursorMap[mouseCursor]; } void GraphicsWindowWin32::setSwapGroup(bool on, GLuint group, GLuint barrier) { if (_traits.valid()) { _traits->swapGroupEnabled = on; _traits->swapGroup = group; _traits->swapBarrier = barrier; } typedef BOOL (GL_APIENTRY *PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group); PFNWGLJOINSWAPGROUPNVPROC wglJoinSwapGroupNV = (PFNWGLJOINSWAPGROUPNVPROC)wglGetProcAddress( "wglJoinSwapGroupNV" ); typedef BOOL (GL_APIENTRY *PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier); PFNWGLBINDSWAPBARRIERNVPROC wglBindSwapBarrierNV = (PFNWGLBINDSWAPBARRIERNVPROC)wglGetProcAddress( "wglBindSwapBarrierNV" ); if ((!wglJoinSwapGroupNV) || (!wglBindSwapBarrierNV)) { OSG_INFO << "GraphicsWindowWin32::wglJoinSwapGroupNV(bool, GLuint, GLuint) not supported" << std::endl; return; } int swapGroup = (on ? group : 0); BOOL resultJoin = wglJoinSwapGroupNV(_hdc, swapGroup); OSG_INFO << "GraphicsWindowWin32::wglJoinSwapGroupNV (" << swapGroup << ") returned " << resultJoin << std::endl; int swapBarrier = (on ? barrier : 0); BOOL resultBind = wglBindSwapBarrierNV(swapGroup, swapBarrier); OSG_INFO << "GraphicsWindowWin32::wglBindSwapBarrierNV (" << swapGroup << ", " << swapBarrier << ") returned " << resultBind << std::endl; } void GraphicsWindowWin32::setSyncToVBlank( bool on ) { if (_traits.valid()) { _traits->vsync = on; } //#if 0 // we ought to properly check if the extension is listed as supported rather than just // if the function pointer resolves through wglGetProcAddress, but in practice everything // supports this extension typedef BOOL (GL_APIENTRY *PFNWGLSWAPINTERVALFARPROC)( int ); PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = 0; wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress( "wglSwapIntervalEXT" ); if( wglSwapIntervalEXT ) { int swapInterval = (on ? 1 : 0); wglSwapIntervalEXT(swapInterval); OSG_INFO << "GraphicsWindowWin32::setSyncToVBlank " << (on ? "on" : "off") << std::endl; } else { OSG_INFO << "GraphicsWindowWin32::setSyncToVBlank(bool) not supported" << std::endl; } //#else // OSG_INFO << "GraphicsWindowWin32::setSyncToVBlank(bool) not yet implemented."<< std::endl; //#endif } void GraphicsWindowWin32::adaptKey( WPARAM wParam, LPARAM lParam, int& keySymbol, unsigned int& modifierMask, int& unmodifiedKeySymbol) { modifierMask = 0; bool rightSide = (lParam & 0x01000000)!=0; int virtualKey = ::MapVirtualKeyEx((lParam>>16) & 0xff, 3, ::GetKeyboardLayout(0)); BYTE keyState[256]; if (virtualKey==0 || !::GetKeyboardState(keyState)) { keySymbol = 0; return; } switch (virtualKey) { ////////////////// case VK_LSHIFT : ////////////////// modifierMask |= osgGA::GUIEventAdapter::MODKEY_LEFT_SHIFT; break; ////////////////// case VK_RSHIFT : ////////////////// modifierMask |= osgGA::GUIEventAdapter::MODKEY_RIGHT_SHIFT; break; ////////////////// case VK_CONTROL : case VK_LCONTROL : ////////////////// virtualKey = rightSide ? VK_RCONTROL : VK_LCONTROL; modifierMask |= rightSide ? osgGA::GUIEventAdapter::MODKEY_RIGHT_CTRL : osgGA::GUIEventAdapter::MODKEY_LEFT_CTRL; break; ////////////////// case VK_MENU : case VK_LMENU : ////////////////// virtualKey = rightSide ? VK_RMENU : VK_LMENU; modifierMask |= rightSide ? osgGA::GUIEventAdapter::MODKEY_RIGHT_ALT : osgGA::GUIEventAdapter::MODKEY_LEFT_ALT; break; ////////////////// default : ////////////////// virtualKey = wParam; break; } if (keyState[VK_CAPITAL] & 0x01) modifierMask |= osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK; if (keyState[VK_NUMLOCK] & 0x01) modifierMask |= osgGA::GUIEventAdapter::MODKEY_NUM_LOCK; keySymbol = remapWin32Key(virtualKey); if (keySymbol==osgGA::GUIEventAdapter::KEY_Return && rightSide) { keySymbol = osgGA::GUIEventAdapter::KEY_KP_Enter; } unmodifiedKeySymbol = keySymbol; if ((keySymbol & 0xff00)==0) { char asciiKey[2]; int numChars = ::ToAscii(wParam, (lParam>>16)&0xff, keyState, reinterpret_cast(asciiKey), 0); if (numChars>0) keySymbol = asciiKey[0]; } } void GraphicsWindowWin32::transformMouseXY( float& x, float& y ) { if (getEventQueue()->getUseFixedMouseInputRange()) { osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState(); x = eventState->getXmin() + (eventState->getXmax()-eventState->getXmin())*x/float(_traits->width); y = eventState->getYmin() + (eventState->getYmax()-eventState->getYmin())*y/float(_traits->height); } } LRESULT GraphicsWindowWin32::handleNativeWindowingEvent( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { if ((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) return TRUE; //!@todo adapt windows event time to osgGA event queue time for better resolution double eventTime = getEventQueue()->getTime(); double resizeTime = eventTime; _timeOfLastCheckEvents = eventTime; switch(uMsg) { // Wojtek Lewandowski 2010-09-28: // All web docs on Windows Aero and OpenGL compatibiltiy // suggest WM_ERASEBKGND should be handled with non NULL value return. // This sugesstion may be irrelevant for our window class // as default brush pattern is not set so erase flag is forwarded to WM_PAINT // and gets ignored when WM_PAINT is handled. // But it will certainly be safer and not make things worse // if we handle this message to be sure everything is done as suggested. case WM_ERASEBKGND : return TRUE; break; ///////////////// case WM_PAINT : ///////////////// if (_ownsWindow) { PAINTSTRUCT paint; ::BeginPaint(hwnd, &paint); ::EndPaint(hwnd, &paint); requestRedraw(); } break; /////////////////// case WM_MOUSEMOVE : /////////////////// { float mx = GET_X_LPARAM(lParam); float my = GET_Y_LPARAM(lParam); transformMouseXY(mx, my); getEventQueue()->mouseMotion(mx, my, eventTime); } break; ///////////////////// case WM_LBUTTONDOWN : case WM_MBUTTONDOWN : case WM_RBUTTONDOWN : ///////////////////// { ::SetCapture(hwnd); int button; if (uMsg==WM_LBUTTONDOWN) button = 1; else if (uMsg==WM_MBUTTONDOWN) button = 2; else button = 3; _capturedMouseButtons.insert(button); float mx = GET_X_LPARAM(lParam); float my = GET_Y_LPARAM(lParam); transformMouseXY(mx, my); getEventQueue()->mouseButtonPress(mx, my, button, eventTime); } break; ///////////////////// case WM_LBUTTONUP : case WM_MBUTTONUP : case WM_RBUTTONUP : ///////////////////// { int button; if (uMsg==WM_LBUTTONUP) button = 1; else if (uMsg==WM_MBUTTONUP) button = 2; else button = 3; _capturedMouseButtons.erase(button); if(_capturedMouseButtons.empty()) ::ReleaseCapture(); float mx = GET_X_LPARAM(lParam); float my = GET_Y_LPARAM(lParam); transformMouseXY(mx, my); getEventQueue()->mouseButtonRelease(mx, my, button, eventTime); } break; /////////////////////// case WM_LBUTTONDBLCLK : case WM_MBUTTONDBLCLK : case WM_RBUTTONDBLCLK : /////////////////////// { ::SetCapture(hwnd); int button; if (uMsg==WM_LBUTTONDBLCLK) button = 1; else if (uMsg==WM_MBUTTONDBLCLK) button = 2; else button = 3; _capturedMouseButtons.insert(button); float mx = GET_X_LPARAM(lParam); float my = GET_Y_LPARAM(lParam); transformMouseXY(mx, my); getEventQueue()->mouseDoubleButtonPress(mx, my, button, eventTime); } break; //////////////////// case WM_MOUSEWHEEL : //////////////////// getEventQueue()->mouseScroll(GET_WHEEL_DELTA_WPARAM(wParam)<0 ? osgGA::GUIEventAdapter::SCROLL_DOWN : osgGA::GUIEventAdapter::SCROLL_UP, eventTime); break; ///////////////// case WM_MOVE : case WM_SIZE : ///////////////// { POINT origin; origin.x = 0; origin.y = 0; ::ClientToScreen(hwnd, &origin); int windowX = origin.x - _screenOriginX; int windowY = origin.y - _screenOriginY; resizeTime = eventTime; RECT clientRect; ::GetClientRect(hwnd, &clientRect); int windowWidth = (clientRect.right == 0) ? 1 : clientRect.right ; int windowHeight = (clientRect.bottom == 0) ? 1 : clientRect.bottom;; // send resize event if window position or size was changed if (windowX!=_traits->x || windowY!=_traits->y || windowWidth!=_traits->width || windowHeight!=_traits->height) { resized(windowX, windowY, windowWidth, windowHeight); getEventQueue()->windowResize(windowX, windowY, windowWidth, windowHeight, resizeTime); // request redraw if window size was changed if (windowWidth!=_traits->width || windowHeight!=_traits->height) requestRedraw(); } } break; //////////////////// case WM_KEYDOWN : case WM_SYSKEYDOWN : //////////////////// { int keySymbol = 0; int unmodifiedKeySymbol = 0; unsigned int modifierMask = 0; adaptKey(wParam, lParam, keySymbol, modifierMask, unmodifiedKeySymbol); _keyMap[std::make_pair(keySymbol,unmodifiedKeySymbol)] = true; //getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask); getEventQueue()->keyPress(keySymbol, eventTime, unmodifiedKeySymbol); } break; ////////////////// case WM_KEYUP : case WM_SYSKEYUP : ////////////////// { int keySymbol = 0; int unmodifiedKeySymbol = 0; unsigned int modifierMask = 0; adaptKey(wParam, lParam, keySymbol, modifierMask, unmodifiedKeySymbol); _keyMap[std::make_pair(keySymbol, unmodifiedKeySymbol)] = false; //getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask); getEventQueue()->keyRelease(keySymbol, eventTime, unmodifiedKeySymbol); } break; /////////////////// case WM_SETCURSOR : /////////////////// //The cursor is only modified in response to the WM_SETCURSOR message if the mouse cursor isn't set to //InheritCursor. InheritCursor lets the user manage the cursor externally. if (_mouseCursor != InheritCursor) { if (_traits->useCursor) ::SetCursor( _currentCursor); else ::SetCursor(NULL); return TRUE; } break; /////////////////// case WM_SETFOCUS : /////////////////// // Check keys and send a message if the key is pressed when the // focus comes back to the window. // I don't really like this hard-coded loop, but the key codes // (VK_* constants) seem to go from 0x08 to 0xFE so it should be // ok. See winuser.h for the key codes. for (unsigned int i = 0x08; i < 0xFF; i++) { // Wojciech Lewandowski: 2011/09/12 // Skip CONTROL | MENU | SHIFT tests because we are polling exact left or right keys // above return press for both right and left so we may end up with incosistent // modifier mask if we report left control & right control while only right was pressed LONG rightSideCode = 0; switch( i ) { case VK_CONTROL: case VK_SHIFT: case VK_MENU: continue; case VK_RCONTROL: case VK_RSHIFT: case VK_RMENU: rightSideCode = 0x01000000; } if ((::GetAsyncKeyState(i) & 0x8000) != 0) { // Compute lParam because subsequent adaptKey will rely on correct lParam UINT scanCode = ::MapVirtualKeyEx( i, 0, ::GetKeyboardLayout(0)); // Set Extended Key bit + Scan Code + 30 bit to indicate key was set before sending message // See Windows SDK help on WM_KEYDOWN for explanation LONG lParam = rightSideCode | ( ( scanCode & 0xFF ) << 16 ) | (1 << 30); ::SendMessage(hwnd, WM_KEYDOWN, i, lParam ); } } break; /////////////////// case WM_KILLFOCUS : /////////////////// // Release all keys that were pressed when the window lost focus. for (std::map, bool>::iterator key = _keyMap.begin(); key != _keyMap.end(); ++key) { if (key->second) { getEventQueue()->keyRelease(key->first.first, key->first.second); key->second = false; } } _capturedMouseButtons.clear(); break; /////////////////// case WM_NCHITTEST : /////////////////// { LONG_PTR result = _windowProcedure==0 ? ::DefWindowProc(hwnd, uMsg, wParam, lParam) : ::CallWindowProc(_windowProcedure, hwnd, uMsg, wParam, lParam); switch(result) { case HTLEFT: case HTRIGHT: setCursorImpl(LeftRightCursor); break; case HTTOP: case HTBOTTOM: setCursorImpl(UpDownCursor); break; case HTTOPLEFT: setCursorImpl(TopLeftCorner); break; case HTTOPRIGHT: setCursorImpl(TopRightCorner); break; case HTBOTTOMLEFT: setCursorImpl(BottomLeftCorner); break; case HTBOTTOMRIGHT: case HTGROWBOX: setCursorImpl(BottomRightCorner); break; case HTSYSMENU: case HTCAPTION: case HTMAXBUTTON: case HTMINBUTTON: case HTCLOSE: case HTHELP: setCursorImpl(LeftArrowCursor); break; default: if (_traits->useCursor && _appMouseCursor != InheritCursor) setCursorImpl(_appMouseCursor); break; } return result; } break; ///////////////// case WM_CLOSE : ///////////////// getEventQueue()->closeWindow(eventTime); break; ///////////////// case WM_DESTROY : ///////////////// _destroyWindow = true; if (_ownsWindow) { ::PostQuitMessage(0); } break; ////////////// case WM_QUIT : ////////////// _closeWindow = true; return wParam; ////////////// case WM_TOUCH: ///////////// { unsigned int numInputs = (unsigned int) wParam; TOUCHINPUT* ti = new TOUCHINPUT[numInputs]; osg::ref_ptr osg_event(NULL); if(getTouchInputInfoFunc && (*getTouchInputInfoFunc)((HTOUCHINPUT)lParam, numInputs, ti, sizeof(TOUCHINPUT))) { // For each contact, dispatch the message to the appropriate message handler. for(unsigned int i=0; i< numInputs; ++i) { if(ti[i].dwFlags & TOUCHEVENTF_DOWN) { if (!osg_event) { osg_event = getEventQueue()->touchBegan( ti[i].dwID, osgGA::GUIEventAdapter::TOUCH_BEGAN, ti[i].x / 100 , ti[i].y/100); } else { osg_event->addTouchPoint( ti[i].dwID, osgGA::GUIEventAdapter::TOUCH_BEGAN, ti[i].x / 100, ti[i].y/100); } } else if(ti[i].dwFlags & TOUCHEVENTF_MOVE) { if (!osg_event) { osg_event = getEventQueue()->touchMoved( ti[i].dwID, osgGA::GUIEventAdapter::TOUCH_MOVED, ti[i].x/ 100, ti[i].y/ 100); } else { osg_event->addTouchPoint( ti[i].dwID, osgGA::GUIEventAdapter::TOUCH_MOVED, ti[i].x / 100, ti[i].y/100); } } else if(ti[i].dwFlags & TOUCHEVENTF_UP) { // No double tap detection with RAW TOUCH Events, sorry. if (!osg_event) { osg_event = getEventQueue()->touchEnded( ti[i].dwID, osgGA::GUIEventAdapter::TOUCH_ENDED, ti[i].x/ 100, ti[i].y/ 100, 1); } else { osg_event->addTouchPoint( ti[i].dwID, osgGA::GUIEventAdapter::TOUCH_ENDED, ti[i].x / 100, ti[i].y/100); } } } } if (closeTouchInputHandleFunc) (*closeTouchInputHandleFunc)((HTOUCHINPUT)lParam); delete [] ti; } break; ///////////////// default : ///////////////// if (_ownsWindow) return ::DefWindowProc(hwnd, uMsg, wParam, lParam); break; } if (_ownsWindow) return 0; return _windowProcedure==0 ? ::DefWindowProc(hwnd, uMsg, wParam, lParam) : ::CallWindowProc(_windowProcedure, hwnd, uMsg, wParam, lParam); } ////////////////////////////////////////////////////////////////////////////// // Class responsible for registering the Win32 Windowing System interface ////////////////////////////////////////////////////////////////////////////// struct RegisterWindowingSystemInterfaceProxy { RegisterWindowingSystemInterfaceProxy() { osg::GraphicsContext::setWindowingSystemInterface(Win32WindowingSystem::getInterface()); } ~RegisterWindowingSystemInterfaceProxy() { if (osg::Referenced::getDeleteHandler()) { osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); osg::Referenced::getDeleteHandler()->flushAll(); } osg::GraphicsContext::setWindowingSystemInterface(0); } }; static RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy; } // namespace OsgViewer // declare C entry point for static compilation. extern "C" void OSGVIEWER_EXPORT graphicswindow_Win32(void) { osg::GraphicsContext::setWindowingSystemInterface(osgViewer::Win32WindowingSystem::getInterface()); } void GraphicsWindowWin32::raiseWindow() { SetWindowPos(_hwnd, HWND_TOPMOST, _traits->x, _traits->y, _traits->width, _traits->height, SWP_NOMOVE|SWP_NOSIZE); SetWindowPos(_hwnd, HWND_NOTOPMOST, _traits->x, _traits->y, _traits->width, _traits->height, SWP_NOMOVE|SWP_NOSIZE); } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/GraphicsWindow.cpp0000644000175000017500000000314711553274642025436 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2011 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include using namespace osgViewer; void GraphicsWindow::getViews(Views& views) { views.clear(); osgViewer::View *prev = NULL; for(Cameras::iterator it = _cameras.begin(); it != _cameras.end(); it++) { osgViewer::View *v = dynamic_cast((*it)->getView()); if (v) // perform a simple test to reduce the number of duplicates if (v != prev) // append view views.push_back(v); } // remove duplicates views.sort(); views.unique(); } void GraphicsWindow::requestRedraw() { Views views; getViews(views); if (views.empty()) { OSG_INFO << "GraphicsWindow::requestRedraw(): No views assigned yet." << std::endl; return; } for(Views::iterator it = views.begin(); it != views.end(); it++) { (*it)->requestRedraw(); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/Viewer.cpp0000644000175000017500000013377412535023504023747 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace osgViewer; Viewer::Viewer() { _viewerBase = this; constructorInit(); } Viewer::Viewer(osg::ArgumentParser& arguments) { _viewerBase = this; constructorInit(); // Add help for command-line options read here arguments.getApplicationUsage()->addCommandLineOption("--SingleThreaded","Select SingleThreaded threading model for viewer."); arguments.getApplicationUsage()->addCommandLineOption("--CullDrawThreadPerContext","Select CullDrawThreadPerContext threading model for viewer."); arguments.getApplicationUsage()->addCommandLineOption("--DrawThreadPerContext","Select DrawThreadPerContext threading model for viewer."); arguments.getApplicationUsage()->addCommandLineOption("--CullThreadPerCameraDrawThreadPerContext","Select CullThreadPerCameraDrawThreadPerContext threading model for viewer."); arguments.getApplicationUsage()->addCommandLineOption("--clear-color ","Set the background color of the viewer in the form \"r,g,b[,a]\"."); arguments.getApplicationUsage()->addCommandLineOption("--screen ","Set the screen to use when multiple screens are present."); arguments.getApplicationUsage()->addCommandLineOption("--window ","Set the position (x,y) and size (w,h) of the viewer window."); arguments.getApplicationUsage()->addCommandLineOption("--run-on-demand","Set the run methods frame rate management to only rendering frames when required."); arguments.getApplicationUsage()->addCommandLineOption("--run-continuous","Set the run methods frame rate management to rendering frames continuously."); arguments.getApplicationUsage()->addCommandLineOption("--run-max-frame-rate","Set the run methods maximum permissable frame rate, 0.0 is default and switching off frame rate capping."); arguments.getApplicationUsage()->addCommandLineOption("--enable-object-cache","Enable caching of objects, images, etc."); // FIXME: Uncomment these lines when the options have been documented properly //arguments.getApplicationUsage()->addCommandLineOption("--3d-sd",""); //arguments.getApplicationUsage()->addCommandLineOption("--panoramic-sd",""); //arguments.getApplicationUsage()->addCommandLineOption("--radius",""); //arguments.getApplicationUsage()->addCommandLineOption("--collar",""); //arguments.getApplicationUsage()->addCommandLineOption("--im",""); if (arguments.read("--ico")) { setIncrementalCompileOperation(new osgUtil::IncrementalCompileOperation()); } std::string filename; bool readConfig = false; while (arguments.read("-c",filename)) { readConfig = readConfiguration(filename) || readConfig; } // Enable caching? while (arguments.read("--enable-object-cache")) { if (osgDB::Registry::instance()->getOptions()==0) osgDB::Registry::instance()->setOptions(new osgDB::Options()); osgDB::Registry::instance()->getOptions()->setObjectCacheHint(osgDB::Options::CACHE_ALL); } while (arguments.read("--SingleThreaded")) setThreadingModel(SingleThreaded); while (arguments.read("--CullDrawThreadPerContext")) setThreadingModel(CullDrawThreadPerContext); while (arguments.read("--DrawThreadPerContext")) setThreadingModel(DrawThreadPerContext); while (arguments.read("--CullThreadPerCameraDrawThreadPerContext")) setThreadingModel(CullThreadPerCameraDrawThreadPerContext); osg::DisplaySettings::instance()->readCommandLine(arguments); osgDB::readCommandLine(arguments); std::string colorStr; while (arguments.read("--clear-color",colorStr)) { float r, g, b; float a = 1.0f; int cnt = sscanf( colorStr.c_str(), "%f,%f,%f,%f", &r, &g, &b, &a ); if( cnt==3 || cnt==4 ) { getCamera()->setClearColor( osg::Vec4(r,g,b,a) ); } else { OSG_WARN<<"Invalid clear color \""< wow = new WoWVxDisplay; if (screenNum>=0) wow->setScreenNum(screenNum); if (wowvx20) wow->WoWVx20(); if (wowvx42) wow->WoWVx42(); unsigned int c; float v; while (arguments.read("--wow-content",c)) { wow->setContent(c); } while (arguments.read("--wow-factor",c)) { wow->setFactor(c); } while (arguments.read("--wow-offset",c)) { wow->setOffset(c); } while (arguments.read("--wow-zd",v)) { wow->setDisparityZD(v); } while (arguments.read("--wow-vz",v)) { wow->setDisparityVZ(v); } while (arguments.read("--wow-M",v)) { wow->setDisparityM(v); } while (arguments.read("--wow-C",v)) { wow->setDisparityC(v); } apply(wow.get()); } else if ((ss3d=arguments.read("--3d-sd")) || arguments.read("--panoramic-sd")) { double radius = 1.0; while (arguments.read("--radius",radius)) {} double collar = 0.45; while (arguments.read("--collar",collar)) {} std::string intensityMapFilename; while (arguments.read("--im",intensityMapFilename)) {} osg::ref_ptr intensityMap = intensityMapFilename.empty() ? 0 : osgDB::readImageFile(intensityMapFilename); if (screenNum<0) screenNum = 0; if (ss3d) { setThreadingModel(SingleThreaded); setUpViewFor3DSphericalDisplay(radius, collar, screenNum, intensityMap.get()); } else { setThreadingModel(SingleThreaded); setUpViewForPanoramicSphericalDisplay(radius, collar, screenNum, intensityMap.get()); } } else if (width>0 && height>0) { if (screenNum>=0) setUpViewInWindow(x, y, width, height, screenNum); else setUpViewInWindow(x,y,width,height); } else if (screenNum>=0) { setUpViewOnSingleScreen(screenNum); } } Viewer::Viewer(const osgViewer::Viewer& viewer, const osg::CopyOp& copyop): osg::Object(true), ViewerBase(viewer), View(viewer,copyop) { _viewerBase = this; } void Viewer::constructorInit() { _eventVisitor = new osgGA::EventVisitor; _eventVisitor->setActionAdapter(this); _eventVisitor->setFrameStamp(_frameStamp.get()); _updateVisitor = new osgUtil::UpdateVisitor; _updateVisitor->setFrameStamp(_frameStamp.get()); setViewerStats(new osg::Stats("Viewer")); } Viewer::~Viewer() { //OSG_NOTICE<<"Viewer::~Viewer()"< object = osgDB::readObjectFile(filename); if (!object) { //OSG_NOTICE<<"Error: Unable to load configuration file \""<(object.get()); if (config) { OSG_NOTICE<<"Using osgViewer::Config : "<className()<configure(*this); osgDB::writeObjectFile(*config,"test.osgt"); return true; } CompositeViewer* compositeViewer = dynamic_cast(object.get()); if (compositeViewer) { OSG_NOTICE<<"Error: Config file \""<(object.get()); if (view) { take(*view); return true; } else { OSG_NOTICE<<"Error: Config file \""<(this)->getContexts(contexts); unsigned int numRealizedWindows = 0; // clear out all the previously assigned operations for(Contexts::iterator citr = contexts.begin(); citr != contexts.end(); ++citr) { if ((*citr)->isRealized()) ++numRealizedWindows; } return numRealizedWindows > 0; } bool Viewer::checkNeedToDoFrame() { if (_requestRedraw) return true; if (_requestContinousUpdate) return true; // If the database pager is going to update the scene the render flag is // set so that the updates show up if(getDatabasePager()->requiresUpdateSceneGraph() || getDatabasePager()->getRequestsInProgress()) return true; // if there update callbacks then we need to do frame. if (_camera->getUpdateCallback()) return true; if (getSceneData()!=0 && getSceneData()->getNumChildrenRequiringUpdateTraversal()>0) return true; // check if events are available and need processing if (checkEvents()) return true; // now check if any of the event handles have prompted a redraw. if (_requestRedraw) return true; if (_requestContinousUpdate) return true; return false; } bool Viewer::checkEvents() { // check events from any attached sources for(Devices::iterator eitr = _eventSources.begin(); eitr != _eventSources.end(); ++eitr) { osgGA::Device* es = eitr->get(); if (es->getCapabilities() & osgGA::Device::RECEIVE_EVENTS) { if (es->checkEvents()) return true; } } // get events from all windows attached to Viewer. Windows windows; getWindows(windows); for(Windows::iterator witr = windows.begin(); witr != windows.end(); ++witr) { if ((*witr)->checkEvents()) return true; } return false; } int Viewer::run() { if (!getCameraManipulator() && getCamera()->getAllowEventFocus()) { setCameraManipulator(new osgGA::TrackballManipulator()); } setReleaseContextAtEndOfFrameHint(false); return ViewerBase::run(); } void Viewer::setStartTick(osg::Timer_t tick) { View::setStartTick(tick); Contexts contexts; getContexts(contexts,false); getEventQueue()->setStartTick(_startTick); for(Contexts::iterator citr = contexts.begin(); citr != contexts.end(); ++citr) { osgViewer::GraphicsWindow* gw = dynamic_cast(*citr); if (gw) { gw->getEventQueue()->setStartTick(_startTick); } } } void Viewer::setReferenceTime(double time) { osg::Timer_t tick = osg::Timer::instance()->tick(); double currentTime = osg::Timer::instance()->delta_s(_startTick, tick); double delta_ticks = (time-currentTime)/(osg::Timer::instance()->getSecondsPerTick()); if (delta_ticks>=0) tick += osg::Timer_t(delta_ticks); else tick -= osg::Timer_t(-delta_ticks); // assign the new start tick setStartTick(tick); } void Viewer::setSceneData(osg::Node* node) { setReferenceTime(0.0); View::setSceneData(node); } GraphicsWindowEmbedded* Viewer::setUpViewerAsEmbeddedInWindow(int x, int y, int width, int height) { setThreadingModel(SingleThreaded); osgViewer::GraphicsWindowEmbedded* gw = new osgViewer::GraphicsWindowEmbedded(x,y,width,height); getCamera()->setViewport(new osg::Viewport(0,0,width,height)); getCamera()->setProjectionMatrixAsPerspective(30.0f, static_cast(width)/static_cast(height), 1.0f, 10000.0f); getCamera()->setGraphicsContext(gw); return gw; } void Viewer::realize() { //OSG_INFO<<"Viewer::realize()"<> x >> y >> width >> height; } if (width>0 && height>0) { if (screenNum>=0) setUpViewInWindow(x, y, width, height, screenNum); else setUpViewInWindow(x,y,width,height); } else if (screenNum>=0) { setUpViewOnSingleScreen(screenNum); } else { setUpViewAcrossAllScreens(); } } getContexts(contexts); } if (contexts.empty()) { OSG_NOTICE<<"Viewer::realize() - failed to set up any windows"<getMaxTexturePoolSize(); if (_camera->getDisplaySettings()) maxTexturePoolSize = std::max(maxTexturePoolSize, _camera->getDisplaySettings()->getMaxTexturePoolSize()); if (_displaySettings.valid()) maxTexturePoolSize = std::max(maxTexturePoolSize, _displaySettings->getMaxTexturePoolSize()); unsigned int maxBufferObjectPoolSize = osg::DisplaySettings::instance()->getMaxBufferObjectPoolSize(); if (_displaySettings.valid()) maxBufferObjectPoolSize = std::max(maxBufferObjectPoolSize, _displaySettings->getMaxBufferObjectPoolSize()); if (_camera->getDisplaySettings()) maxBufferObjectPoolSize = std::max(maxBufferObjectPoolSize, _camera->getDisplaySettings()->getMaxBufferObjectPoolSize()); for(Contexts::iterator citr = contexts.begin(); citr != contexts.end(); ++citr) { osg::GraphicsContext* gc = *citr; // set the pool sizes, 0 the default will result in no GL object pools. gc->getState()->setMaxTexturePoolSize(maxTexturePoolSize); gc->getState()->setMaxBufferObjectPoolSize(maxBufferObjectPoolSize); gc->realize(); if (_realizeOperation.valid() && gc->valid()) { gc->makeCurrent(); (*_realizeOperation)(gc); gc->releaseContext(); } } // attach contexts to _incrementalCompileOperation if attached. if (_incrementalCompileOperation) _incrementalCompileOperation->assignContexts(contexts); bool grabFocus = true; if (grabFocus) { for(Contexts::iterator citr = contexts.begin(); citr != contexts.end(); ++citr) { osgViewer::GraphicsWindow* gw = dynamic_cast(*citr); if (gw) { gw->grabFocusIfPointerInWindow(); } } } // initialize the global timer to be relative to the current time. osg::Timer::instance()->setStartTick(); // pass on the start tick to all the associated event queues setStartTick(osg::Timer::instance()->getStartTick()); setUpThreading(); if (osg::DisplaySettings::instance()->getCompileContextsHint()) { int numProcessors = OpenThreads::GetNumberOfProcessors(); int processNum = 0; for(unsigned int i=0; i<= osg::GraphicsContext::getMaxContextID(); ++i) { osg::GraphicsContext* gc = osg::GraphicsContext::getOrCreateCompileContext(i); if (gc) { gc->createGraphicsThread(); gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors); gc->getGraphicsThread()->startThread(); ++processNum; } } } #if 0 osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState(); if (getCamera()->getViewport()) { osg::Viewport* viewport = getCamera()->getViewport(); eventState->setInputRange( viewport->x(), viewport->y(), viewport->x() + viewport->width(), viewport->y() + viewport->height()); } else { eventState->setInputRange(-1.0, -1.0, 1.0, 1.0); } #endif } void Viewer::advance(double simulationTime) { if (_done) return; double previousReferenceTime = _frameStamp->getReferenceTime(); unsigned int previousFrameNumber = _frameStamp->getFrameNumber(); _frameStamp->setFrameNumber(_frameStamp->getFrameNumber()+1); _frameStamp->setReferenceTime( osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()) ); if (simulationTime==USE_REFERENCE_TIME) { _frameStamp->setSimulationTime(_frameStamp->getReferenceTime()); } else { _frameStamp->setSimulationTime(simulationTime); } if (getViewerStats() && getViewerStats()->collectStats("frame_rate")) { // update previous frame stats double deltaFrameTime = _frameStamp->getReferenceTime() - previousReferenceTime; getViewerStats()->setAttribute(previousFrameNumber, "Frame duration", deltaFrameTime); getViewerStats()->setAttribute(previousFrameNumber, "Frame rate", 1.0/deltaFrameTime); // update current frames stats getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Reference time", _frameStamp->getReferenceTime()); } if (osg::Referenced::getDeleteHandler()) { osg::Referenced::getDeleteHandler()->flush(); osg::Referenced::getDeleteHandler()->setFrameNumber(_frameStamp->getFrameNumber()); } } void Viewer::generateSlavePointerData(osg::Camera* camera, osgGA::GUIEventAdapter& event) { osgViewer::GraphicsWindow* gw = dynamic_cast(event.getGraphicsContext()); if (!gw) return; // What type of Camera is it? // 1) Master Camera : do nothin extra // 2) Slave Camera, Relative RF, Same scene graph as master : transform coords into Master Camera and add to PointerData list // 3) Slave Camera, Relative RF, Different scene graph from master : do nothing extra? // 4) Slave Camera, Absolute RF, Same scene graph as master : do nothing extra? // 5) Slave Camera, Absolute RF, Different scene graph : do nothing extra? // 6) Slave Camera, Absolute RF, Different scene graph but a distortion correction subgraph depending upon RTT Camera (slave or master) // : project ray into RTT Camera's clip space, and RTT Camera's is Relative RF and sharing same scene graph as master then transform coords. // if camera isn't the master it must be a slave and could need reprojecting. if (camera!=getCamera()) { float x = event.getX(); float y = event.getY(); bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS; if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y; double master_min_x = -1.0; double master_max_x = 1.0; double master_min_y = -1.0; double master_max_y = 1.0; osg::Matrix masterCameraVPW = getCamera()->getViewMatrix() * getCamera()->getProjectionMatrix(); if (getCamera()->getViewport()) { osg::Viewport* viewport = getCamera()->getViewport(); master_min_x = viewport->x(); master_min_y = viewport->y(); master_max_x = viewport->x()+viewport->width(); master_max_y = viewport->y()+viewport->height(); masterCameraVPW *= viewport->computeWindowMatrix(); } // slave Camera if it shares the same View osg::View::Slave* slave = findSlaveForCamera(camera); if (slave) { if (camera->getReferenceFrame()==osg::Camera::RELATIVE_RF && slave->_useMastersSceneData) { osg::Viewport* viewport = camera->getViewport(); osg::Matrix localCameraVPW = camera->getViewMatrix() * camera->getProjectionMatrix(); if (viewport) { localCameraVPW *= viewport->computeWindowMatrix(); } osg::Matrix matrix( osg::Matrix::inverse(localCameraVPW) * masterCameraVPW ); osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix; event.addPointerData(new osgGA::PointerData(getCamera(), new_coord.x(), master_min_x, master_max_x, new_coord.y(), master_min_y, master_max_y)); } else if (!slave->_useMastersSceneData) { // Are their any RTT Camera's that this Camera depends upon for textures? osg::ref_ptr ray = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x,y); osgUtil::IntersectionVisitor iv(ray.get()); camera->accept(iv); if (ray->containsIntersections()) { osg::Vec3 tc; osg::Texture* texture = ray->getFirstIntersection().getTextureLookUp(tc); if (texture) { // look up Texture in RTT Camera's. for(unsigned int i=0; igetBufferAttachmentMap().find(osg::Camera::COLOR_BUFFER); if (ba_itr != slave_camera->getBufferAttachmentMap().end()) { if (ba_itr->second._texture == texture) { osg::TextureRectangle* tr = dynamic_cast(ba_itr->second._texture.get()); osg::TextureCubeMap* tcm = dynamic_cast(ba_itr->second._texture.get()); if (tr) { event.addPointerData(new osgGA::PointerData(slave_camera, tc.x(), 0.0f, static_cast(tr->getTextureWidth()), tc.y(), 0.0f, static_cast(tr->getTextureHeight()))); } else if (tcm) { OSG_NOTICE<<" Slave has matched texture cubemap"<second._texture.get()<<", "<second._face<(event.getGraphicsContext()); if (!gw) return; float x = event.getX(); float y = event.getY(); bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS; if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y; event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width, y, 0, gw->getTraits()->height)); typedef std::vector CameraVector; CameraVector activeCameras; osgViewer::View* this_view = dynamic_cast(this); osg::GraphicsContext::Cameras& cameras = gw->getCameras(); for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin(); citr != cameras.end(); ++citr) { osg::Camera* camera = *citr; if (camera->getView()==this_view && camera->getAllowEventFocus() && camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER) { osg::Viewport* viewport = camera ? camera->getViewport() : 0; if (viewport && x >= viewport->x() && y >= viewport->y() && x <= (viewport->x()+viewport->width()) && y <= (viewport->y()+viewport->height()) ) { activeCameras.push_back(camera); } } } std::sort(activeCameras.begin(), activeCameras.end(), osg::CameraRenderOrderSortOp()); osg::Camera* camera = activeCameras.empty() ? 0 : activeCameras.back(); if (camera) { osg::Viewport* viewport = camera ? camera->getViewport() : 0; event.addPointerData(new osgGA::PointerData(camera, (x-viewport->x())/viewport->width()*2.0f-1.0f, -1.0, 1.0, (y-viewport->y())/viewport->height()*2.0f-1.0f, -1.0, 1.0)); // if camera isn't the master it must be a slave and could need reprojecting. if (camera!=getCamera()) { generateSlavePointerData(camera, event); } } } void Viewer::reprojectPointerData(osgGA::GUIEventAdapter& source_event, osgGA::GUIEventAdapter& dest_event) { osgViewer::GraphicsWindow* gw = dynamic_cast(dest_event.getGraphicsContext()); if (!gw) return; float x = dest_event.getX(); float y = dest_event.getY(); bool invert_y = dest_event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS; if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y; dest_event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width, y, 0, gw->getTraits()->height)); osg::Camera* camera = (source_event.getNumPointerData()>=2) ? dynamic_cast(source_event.getPointerData(1)->object.get()) : 0; osg::Viewport* viewport = camera ? camera->getViewport() : 0; if (!viewport) return; dest_event.addPointerData(new osgGA::PointerData(camera, (x-viewport->x())/viewport->width()*2.0f-1.0f, -1.0, 1.0, (y-viewport->y())/viewport->height()*2.0f-1.0f, -1.0, 1.0)); // if camera isn't the master it must be a slave and could need reprojecting. if (camera!=getCamera()) { generateSlavePointerData(camera, dest_event); } } void Viewer::eventTraversal() { if (_done) return; double cutOffTime = _frameStamp->getReferenceTime(); double beginEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); // OSG_NOTICE<<"Viewer::frameEventTraversal()."<getCurrentEventState(); // get events from user Devices attached to Viewer. for(Devices::iterator eitr = _eventSources.begin(); eitr != _eventSources.end(); ++eitr) { osgGA::Device* es = eitr->get(); if (es->getCapabilities() & osgGA::Device::RECEIVE_EVENTS) es->checkEvents(); // open question, will we need to reproject mouse coordinates into current view's coordinate frame as is down for GraphicsWindow provided events? // for now assume now and just get the events directly without any reprojection. es->getEventQueue()->takeEvents(events, cutOffTime); } // get events from all windows attached to Viewer. for(Contexts::iterator citr = contexts.begin(); citr != contexts.end(); ++citr) { osgViewer::GraphicsWindow* gw = dynamic_cast(*citr); if (gw) { gw->checkEvents(); osgGA::EventQueue::Events gw_events; gw->getEventQueue()->takeEvents(gw_events, cutOffTime); osgGA::EventQueue::Events::iterator itr; for(itr = gw_events.begin(); itr != gw_events.end(); ++itr) { osgGA::GUIEventAdapter* event = itr->get(); event->setGraphicsContext(gw); switch(event->getEventType()) { case(osgGA::GUIEventAdapter::PUSH): case(osgGA::GUIEventAdapter::RELEASE): case(osgGA::GUIEventAdapter::DOUBLECLICK): case(osgGA::GUIEventAdapter::MOVE): case(osgGA::GUIEventAdapter::DRAG): { if (event->getEventType()!=osgGA::GUIEventAdapter::DRAG || eventState->getGraphicsContext()!=event->getGraphicsContext() || eventState->getNumPointerData()<2) { generatePointerData(*event); } else { reprojectPointerData(*eventState, *event); } #if 0 // assign topmost PointeData settings as the events X,Y and InputRange osgGA::PointerData* pd = event->getPointerData(event->getNumPointerData()-1); event->setX(pd->x); event->setY(pd->y); event->setInputRange(pd->xMin, pd->yMin, pd->xMax, pd->yMax); event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS); #else if (event->getMouseYOrientation()!=osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS) { event->setY((event->getYmax()-event->getY())+event->getYmin()); event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS); } #endif eventState->copyPointerDataFrom(*event); break; } default: event->copyPointerDataFrom(*eventState); break; } events.push_back(event); } for(itr = gw_events.begin(); itr != gw_events.end(); ++itr) { osgGA::GUIEventAdapter* event = itr->get(); switch(event->getEventType()) { case(osgGA::GUIEventAdapter::CLOSE_WINDOW): { bool wasThreading = areThreadsRunning(); if (wasThreading) stopThreading(); gw->close(); _currentContext = NULL; if (wasThreading) startThreading(); break; } default: break; } } } } // create a frame event for the new frame. _eventQueue->frame( getFrameStamp()->getReferenceTime() ); // OSG_NOTICE<<"mouseEventState Xmin = "<getXmin()<<" Ymin="<getYmin()<<" xMax="<getXmax()<<" Ymax="<getYmax()<takeEvents(events, cutOffTime); // OSG_NOTICE<<"Events "<get(); switch(event->getEventType()) { case(osgGA::GUIEventAdapter::KEYUP): if (_keyEventSetsDone && event->getKey()==_keyEventSetsDone) _done = true; break; case(osgGA::GUIEventAdapter::QUIT_APPLICATION): if (_quitEventSetsDone) _done = true; break; default: break; } } } if (_done) return; if (_eventVisitor.valid() && getSceneData()) { _eventVisitor->setFrameStamp(getFrameStamp()); _eventVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber()); for(osgGA::EventQueue::Events::iterator itr = events.begin(); itr != events.end(); ++itr) { osgGA::GUIEventAdapter* event = itr->get(); _eventVisitor->reset(); _eventVisitor->addEvent( event ); getSceneData()->accept(*_eventVisitor); // Do EventTraversal for slaves with their own subgraph for(unsigned int i=0; iaccept(*_eventVisitor); } } // call any camera event callbacks, but only traverse that callback, don't traverse its subgraph // leave that to the scene update traversal. osg::NodeVisitor::TraversalMode tm = _eventVisitor->getTraversalMode(); _eventVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE); if (_camera.valid() && _camera->getEventCallback()) _camera->accept(*_eventVisitor); for(unsigned int i=0; igetEventCallback()) { camera->accept(*_eventVisitor); } } _eventVisitor->setTraversalMode(tm); } } for(osgGA::EventQueue::Events::iterator itr = events.begin(); itr != events.end(); ++itr) { osgGA::GUIEventAdapter* event = itr->get(); for(EventHandlers::iterator hitr = _eventHandlers.begin(); hitr != _eventHandlers.end(); ++hitr) { (*hitr)->handleWithCheckAgainstIgnoreHandledEventsMask( *event, *this, 0, _eventVisitor.get()); } } for(osgGA::EventQueue::Events::iterator itr = events.begin(); itr != events.end(); ++itr) { osgGA::GUIEventAdapter* event = itr->get(); if (_cameraManipulator.valid()) { _cameraManipulator->handleWithCheckAgainstIgnoreHandledEventsMask( *event, *this); } } if (getViewerStats() && getViewerStats()->collectStats("event")) { double endEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); // update current frames stats getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal begin time", beginEventTraversal); getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal end time", endEventTraversal); getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal time taken", endEventTraversal-beginEventTraversal); } } void Viewer::updateTraversal() { if (_done) return; double beginUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); _updateVisitor->reset(); _updateVisitor->setFrameStamp(getFrameStamp()); _updateVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber()); _scene->updateSceneGraph(*_updateVisitor); // if we have a shared state manager prune any unused entries if (osgDB::Registry::instance()->getSharedStateManager()) osgDB::Registry::instance()->getSharedStateManager()->prune(); // update the Registry object cache. osgDB::Registry::instance()->updateTimeStampOfObjectsInCacheWithExternalReferences(*getFrameStamp()); osgDB::Registry::instance()->removeExpiredObjectsInCache(*getFrameStamp()); if (_updateOperations.valid()) { _updateOperations->runOperations(this); } if (_incrementalCompileOperation.valid()) { // merge subgraphs that have been compiled by the incremental compiler operation. _incrementalCompileOperation->mergeCompiledSubgraphs(getFrameStamp()); } { // Do UpdateTraversal for slaves with their own subgraph for(unsigned int i=0; iaccept(*_updateVisitor); } } } { // call any camera update callbacks, but only traverse that callback, don't traverse its subgraph // leave that to the scene update traversal. osg::NodeVisitor::TraversalMode tm = _updateVisitor->getTraversalMode(); _updateVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE); if (_camera.valid() && _camera->getUpdateCallback()) _camera->accept(*_updateVisitor); for(unsigned int i=0; igetUpdateCallback()) { camera->accept(*_updateVisitor); } } _updateVisitor->setTraversalMode(tm); } if (_cameraManipulator.valid()) { setFusionDistance( getCameraManipulator()->getFusionDistanceMode(), getCameraManipulator()->getFusionDistanceValue() ); _cameraManipulator->updateCamera(*_camera); } updateSlaves(); if (getViewerStats() && getViewerStats()->collectStats("update")) { double endUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); // update current frames stats getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal begin time", beginUpdateTraversal); getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal end time", endUpdateTraversal); getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal time taken", endUpdateTraversal-beginUpdateTraversal); } } void Viewer::getScenes(Scenes& scenes, bool /*onlyValid*/) { scenes.clear(); scenes.push_back(_scene.get()); } void Viewer::getViews(Views& views, bool /*onlyValid*/) { views.clear(); views.push_back(this); } void Viewer::getAllThreads(Threads& threads, bool onlyActive) { threads.clear(); OperationThreads operationThreads; getOperationThreads(operationThreads); for(OperationThreads::iterator itr = operationThreads.begin(); itr != operationThreads.end(); ++itr) { threads.push_back(*itr); } if (_scene.valid()) { osgDB::DatabasePager* dp = _scene->getDatabasePager(); if (dp) { for(unsigned int i=0; igetNumDatabaseThreads(); ++i) { osgDB::DatabasePager::DatabaseThread* dt = dp->getDatabaseThread(i); if (!onlyActive || dt->isRunning()) { threads.push_back(dt); } } } } } void Viewer::getOperationThreads(OperationThreads& threads, bool onlyActive) { threads.clear(); Contexts contexts; getContexts(contexts); for(Contexts::iterator gcitr = contexts.begin(); gcitr != contexts.end(); ++gcitr) { osg::GraphicsContext* gc = *gcitr; if (gc->getGraphicsThread() && (!onlyActive || gc->getGraphicsThread()->isRunning()) ) { threads.push_back(gc->getGraphicsThread()); } } Cameras cameras; getCameras(cameras); for(Cameras::iterator citr = cameras.begin(); citr != cameras.end(); ++citr) { osg::Camera* camera = *citr; if (camera->getCameraThread() && (!onlyActive || camera->getCameraThread()->isRunning()) ) { threads.push_back(camera->getCameraThread()); } } } void Viewer::getContexts(Contexts& contexts, bool onlyValid) { typedef std::set ContextSet; ContextSet contextSet; contexts.clear(); if (_camera.valid() && _camera->getGraphicsContext() && (_camera->getGraphicsContext()->valid() || !onlyValid)) { contextSet.insert(_camera->getGraphicsContext()); contexts.push_back(_camera->getGraphicsContext()); } for(unsigned int i=0; igetGraphicsContext() : 0; if (sgc && (sgc->valid() || !onlyValid)) { if (contextSet.count(sgc)==0) { contextSet.insert(sgc); contexts.push_back(sgc); } } } } void Viewer::getCameras(Cameras& cameras, bool onlyActive) { cameras.clear(); if (_camera.valid() && (!onlyActive || (_camera->getGraphicsContext() && _camera->getGraphicsContext()->valid())) ) cameras.push_back(_camera.get()); for(Slaves::iterator itr = _slaves.begin(); itr != _slaves.end(); ++itr) { if (itr->_camera.valid() && (!onlyActive || (itr->_camera->getGraphicsContext() && itr->_camera->getGraphicsContext()->valid())) ) cameras.push_back(itr->_camera.get()); } } double Viewer::elapsedTime() { return osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); } void Viewer::getUsage(osg::ApplicationUsage& usage) const { if (_cameraManipulator.valid()) { _cameraManipulator->getUsage(usage); } for(EventHandlers::const_iterator hitr = _eventHandlers.begin(); hitr != _eventHandlers.end(); ++hitr) { (*hitr)->getUsage(usage); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/Renderer.cpp0000644000175000017500000010175512163275353024256 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include using namespace osgViewer; //#define DEBUG_MESSAGE OSG_NOTICE #define DEBUG_MESSAGE OSG_DEBUG OpenGLQuerySupport::OpenGLQuerySupport(): _extensions(0) { } class OSGVIEWER_EXPORT EXTQuerySupport : public OpenGLQuerySupport { public: EXTQuerySupport(); void checkQuery(osg::Stats* stats, osg::State* state, osg::Timer_t startTick); virtual void beginQuery(unsigned int frameNumber, osg::State* state); virtual void endQuery(osg::State* state); virtual void initialize(osg::State* state, osg::Timer_t startTick); protected: GLuint createQueryObject(); typedef std::pair QueryFrameNumberPair; typedef std::list QueryFrameNumberList; typedef std::vector QueryList; QueryFrameNumberList _queryFrameNumberList; QueryList _availableQueryObjects; double _previousQueryTime; }; EXTQuerySupport::EXTQuerySupport(): _previousQueryTime(0.0) { } void EXTQuerySupport::checkQuery(osg::Stats* stats, osg::State* /*state*/, osg::Timer_t startTick) { for(QueryFrameNumberList::iterator itr = _queryFrameNumberList.begin(); itr != _queryFrameNumberList.end(); ) { GLuint query = itr->first; GLint available = 0; _extensions->glGetQueryObjectiv(query, GL_QUERY_RESULT_AVAILABLE, &available); if (available) { GLuint64EXT timeElapsed = 0; _extensions->glGetQueryObjectui64v(query, GL_QUERY_RESULT, &timeElapsed); double timeElapsedSeconds = double(timeElapsed)*1e-9; double currentTime = osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick()); double estimatedEndTime = (_previousQueryTime + currentTime) * 0.5; double estimatedBeginTime = estimatedEndTime - timeElapsedSeconds; stats->setAttribute(itr->second, "GPU draw begin time", estimatedBeginTime); stats->setAttribute(itr->second, "GPU draw end time", estimatedEndTime); stats->setAttribute(itr->second, "GPU draw time taken", timeElapsedSeconds); itr = _queryFrameNumberList.erase(itr); _availableQueryObjects.push_back(query); } else { ++itr; } } _previousQueryTime = osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick()); } GLuint EXTQuerySupport::createQueryObject() { if (_availableQueryObjects.empty()) { GLuint query; _extensions->glGenQueries(1, &query); return query; } else { GLuint query = _availableQueryObjects.back(); _availableQueryObjects.pop_back(); return query; } } void EXTQuerySupport::beginQuery(unsigned int frameNumber, osg::State* /*state*/) { GLuint query = createQueryObject(); _extensions->glBeginQuery(GL_TIME_ELAPSED, query); _queryFrameNumberList.push_back(QueryFrameNumberPair(query, frameNumber)); } void EXTQuerySupport::endQuery(osg::State* /*state*/) { _extensions->glEndQuery(GL_TIME_ELAPSED); } void OpenGLQuerySupport::initialize(osg::State* state, osg::Timer_t /*startTick*/) { _extensions = osg::Drawable::getExtensions(state->getContextID(),true); } void EXTQuerySupport::initialize(osg::State* state, osg::Timer_t startTick) { OpenGLQuerySupport::initialize(state, startTick); _previousQueryTime = osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick()); } class ARBQuerySupport : public OpenGLQuerySupport { public: virtual void checkQuery(osg::Stats* stats, osg::State* state, osg::Timer_t startTick); virtual void beginQuery(unsigned int frameNumber, osg::State* state); virtual void endQuery(osg::State* state); virtual void initialize(osg::State* state, osg::Timer_t startTick); protected: typedef std::pair QueryPair; struct ActiveQuery { ActiveQuery() : queries(0, 0), frameNumber(0) {} ActiveQuery(GLuint start_, GLuint end_, int frameNumber_) : queries(start_, end_), frameNumber(frameNumber_) { } ActiveQuery(const QueryPair& queries_, unsigned int frameNumber_) : queries(queries_), frameNumber(frameNumber_) { } QueryPair queries; unsigned int frameNumber; }; typedef std::list QueryFrameList; typedef std::vector QueryList; QueryFrameList _queryFrameList; QueryList _availableQueryObjects; }; void ARBQuerySupport::initialize(osg::State* state, osg::Timer_t startTick) { OpenGLQuerySupport::initialize(state, startTick); } void ARBQuerySupport::beginQuery(unsigned int frameNumber, osg::State* /*state*/) { QueryPair query; if (_availableQueryObjects.empty()) { _extensions->glGenQueries(1, &query.first); _extensions->glGenQueries(1, &query.second); } else { query = _availableQueryObjects.back(); _availableQueryObjects.pop_back(); } _extensions->glQueryCounter(query.first, GL_TIMESTAMP); _queryFrameList.push_back(ActiveQuery(query, frameNumber)); } void ARBQuerySupport::endQuery(osg::State* /*state*/) { _extensions->glQueryCounter(_queryFrameList.back().queries.second, GL_TIMESTAMP); } void ARBQuerySupport::checkQuery(osg::Stats* stats, osg::State* state, osg::Timer_t /*startTick*/) { for(QueryFrameList::iterator itr = _queryFrameList.begin(); itr != _queryFrameList.end(); ) { GLint available = 0; // If the end query is available, the begin query must be too. _extensions->glGetQueryObjectiv(itr->queries.second, GL_QUERY_RESULT_AVAILABLE, &available); if (available) { QueryPair queries = itr->queries; GLuint64EXT beginTimestamp = 0; GLuint64EXT endTimestamp = 0; _extensions->glGetQueryObjectui64v(queries.first, GL_QUERY_RESULT, &beginTimestamp); _extensions->glGetQueryObjectui64v(queries.second, GL_QUERY_RESULT, &endTimestamp); GLuint64EXT gpuTimestamp = state->getGpuTimestamp(); // Have any of the timestamps wrapped around? int tbits = state->getTimestampBits(); if (tbits < 64) { // If the high bits on any of the timestamp bits are // different then the counters may have wrapped. const int hiShift = (tbits - 1); const GLuint64EXT hiMask = 1 << hiShift; const GLuint64EXT sum = (beginTimestamp >> hiShift) + (endTimestamp >> hiShift) + (gpuTimestamp >> hiShift); if (sum == 1 || sum == 2) { const GLuint64EXT wrapAdd = 1 << tbits; // Counter wrapped between begin and end? if (beginTimestamp > endTimestamp) { endTimestamp += wrapAdd; } else if (gpuTimestamp < beginTimestamp && beginTimestamp - gpuTimestamp > (hiMask >> 1)) { gpuTimestamp += wrapAdd; } else if (endTimestamp < gpuTimestamp && gpuTimestamp - endTimestamp > (hiMask >> 1)) { beginTimestamp += wrapAdd; endTimestamp += wrapAdd; } } } GLuint64EXT timeElapsed = endTimestamp - beginTimestamp; double timeElapsedSeconds = double(timeElapsed)*1e-9; double gpuTick = state->getGpuTime(); double beginTime = 0.0; double endTime = 0.0; if (beginTimestamp > gpuTimestamp) beginTime = gpuTick + double(beginTimestamp - gpuTimestamp) * 1e-9; else beginTime = gpuTick - double(gpuTimestamp - beginTimestamp) * 1e-9; if (endTimestamp > gpuTimestamp) endTime = gpuTick + double(endTimestamp - gpuTimestamp) * 1e-9; else endTime = gpuTick - double(gpuTimestamp - endTimestamp) * 1e-9; stats->setAttribute(itr->frameNumber, "GPU draw begin time", beginTime); stats->setAttribute(itr->frameNumber, "GPU draw end time", endTime); stats->setAttribute(itr->frameNumber, "GPU draw time taken", timeElapsedSeconds); itr = _queryFrameList.erase(itr); _availableQueryObjects.push_back(queries); } else { ++itr; } } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // ThreadSafeQueue Renderer::ThreadSafeQueue::ThreadSafeQueue() : _isReleased(false) { } Renderer::ThreadSafeQueue::~ThreadSafeQueue() { } void Renderer::ThreadSafeQueue::release() { OpenThreads::ScopedLock lock(_mutex); _isReleased = true; _cond.broadcast(); } void Renderer::ThreadSafeQueue::reset() { OpenThreads::ScopedLock lock(_mutex); _queue.clear(); _isReleased = false; } osgUtil::SceneView* Renderer::ThreadSafeQueue::takeFront() { OpenThreads::ScopedLock lock(_mutex); // Loop in case there are spurious wakeups from the condition wait. while (true) { // If the queue has been released but nothing is enqueued, // just return. This prevents a deadlock when threading is // restarted. if (_isReleased) { if (!_queue.empty()) { osgUtil::SceneView* front = _queue.front(); _queue.pop_front(); if (_queue.empty()) _isReleased = false; return front; } return 0; } _cond.wait(&_mutex); } return 0; // Can't happen } void Renderer::ThreadSafeQueue::add(osgUtil::SceneView* sv) { OpenThreads::ScopedLock lock(_mutex); _queue.push_back(sv); _isReleased = true; _cond.broadcast(); } static OpenThreads::ReentrantMutex s_drawSerializerMutex; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // Renderer Renderer::Renderer(osg::Camera* camera): osg::GraphicsOperation("Renderer",true), _camera(camera), _done(false), _graphicsThreadDoesCull(true), _compileOnNextDraw(true), _serializeDraw(false), _initialized(false), _startTick(0) { DEBUG_MESSAGE<<"Render::Render() "<getView() ? _camera->getView()->getCamera() : camera; osg::StateSet* global_stateset = 0; osg::StateSet* secondary_stateset = 0; if (_camera != masterCamera) { global_stateset = masterCamera->getOrCreateStateSet(); secondary_stateset = _camera->getStateSet(); } else { global_stateset = _camera->getOrCreateStateSet(); } osgViewer::View* view = dynamic_cast(_camera->getView()); osgViewer::ViewerBase* viewer = view ? view->getViewerBase() : 0; osgUtil::IncrementalCompileOperation* ico = viewer ? viewer->getIncrementalCompileOperation() : 0; bool automaticFlush = (ico==NULL); osg::DisplaySettings* ds = _camera->getDisplaySettings() ? _camera->getDisplaySettings() : ((view && view->getDisplaySettings()) ? view->getDisplaySettings() : osg::DisplaySettings::instance().get()); _serializeDraw = ds ? ds->getSerializeDrawDispatch() : false; unsigned int sceneViewOptions = osgUtil::SceneView::HEADLIGHT; if (view) { switch(view->getLightingMode()) { case(osg::View::NO_LIGHT): sceneViewOptions = 0; break; case(osg::View::SKY_LIGHT): sceneViewOptions = osgUtil::SceneView::SKY_LIGHT; break; case(osg::View::HEADLIGHT): sceneViewOptions = osgUtil::SceneView::HEADLIGHT; break; } } _sceneView[0]->setAutomaticFlush(automaticFlush); _sceneView[0]->setGlobalStateSet(global_stateset); _sceneView[0]->setSecondaryStateSet(secondary_stateset); _sceneView[1]->setAutomaticFlush(automaticFlush); _sceneView[1]->setGlobalStateSet(global_stateset); _sceneView[1]->setSecondaryStateSet(secondary_stateset); _sceneView[0]->setDefaults(sceneViewOptions); _sceneView[1]->setDefaults(sceneViewOptions); if (ds->getUseSceneViewForStereoHint()) { _sceneView[0]->setDisplaySettings(ds); _sceneView[1]->setDisplaySettings(ds); } else { _sceneView[0]->setResetColorMaskToAllOn(false); _sceneView[1]->setResetColorMaskToAllOn(false); } _sceneView[0]->setCamera(_camera.get(), false); _sceneView[1]->setCamera(_camera.get(), false); { // assign CullVisitor::Identifier so that the double buffering of SceneView doesn't interfer // with code that requires a consistent knowledge and which effective cull traversal to taking place osg::ref_ptr leftEyeIdentifier = _sceneView[0]->getCullVisitor()->getIdentifier(); osg::ref_ptr rightEyeIdentifier = new osgUtil::CullVisitor::Identifier(); _sceneView[0]->setCullVisitorLeft(_sceneView[0]->getCullVisitor()->clone()); _sceneView[0]->getCullVisitorLeft()->setIdentifier(leftEyeIdentifier.get()); _sceneView[0]->setCullVisitorRight(_sceneView[0]->getCullVisitor()->clone()); _sceneView[0]->getCullVisitorRight()->setIdentifier(rightEyeIdentifier.get()); _sceneView[1]->getCullVisitor()->setIdentifier(leftEyeIdentifier.get()); _sceneView[1]->setCullVisitorLeft(_sceneView[1]->getCullVisitor()->clone()); _sceneView[1]->getCullVisitorLeft()->setIdentifier(leftEyeIdentifier.get()); _sceneView[1]->setCullVisitorRight(_sceneView[1]->getCullVisitor()->clone()); _sceneView[1]->getCullVisitorRight()->setIdentifier(rightEyeIdentifier.get()); } // lock the mutex for the current cull SceneView to // prevent the draw traversal from reading from it before the cull traversal has been completed. _availableQueue.add(_sceneView[0].get()); _availableQueue.add(_sceneView[1].get()); DEBUG_MESSAGE<<"_availableQueue.size()="<<_availableQueue._queue.size()<getContextID(), true); if (ext->isARBTimerQuerySupported() && state->getTimestampBits() > 0) _querySupport = new ARBQuerySupport(); else if (ext->isTimerQuerySupported()) _querySupport = new EXTQuerySupport(); if (_querySupport.valid()) _querySupport->initialize(state, _startTick); } } void Renderer::setGraphicsThreadDoesCull(bool flag) { if (_graphicsThreadDoesCull==flag) return; _graphicsThreadDoesCull = flag; } void Renderer::updateSceneView(osgUtil::SceneView* sceneView) { osg::Camera* masterCamera = _camera->getView() ? _camera->getView()->getCamera() : _camera.get(); osg::StateSet* global_stateset = 0; osg::StateSet* secondary_stateset = 0; if (_camera != masterCamera) { global_stateset = masterCamera->getOrCreateStateSet(); secondary_stateset = _camera->getStateSet(); } else { global_stateset = _camera->getOrCreateStateSet(); } if (sceneView->getGlobalStateSet()!=global_stateset) { sceneView->setGlobalStateSet(global_stateset); } if (sceneView->getSecondaryStateSet()!=secondary_stateset) { sceneView->setSecondaryStateSet(secondary_stateset); } osg::GraphicsContext* context = _camera->getGraphicsContext(); osg::State* state = context ? context->getState() : 0; if (sceneView->getState()!=state) { sceneView->setState(state); } osgViewer::View* view = dynamic_cast(_camera->getView()); osgViewer::ViewerBase* viewer = view ? view->getViewerBase() : 0; osgUtil::IncrementalCompileOperation* ico = viewer ? viewer->getIncrementalCompileOperation() : 0; bool automaticFlush = (ico==NULL); sceneView->setAutomaticFlush(automaticFlush); osgDB::DatabasePager* databasePager = view ? view->getDatabasePager() : 0; sceneView->getCullVisitor()->setDatabaseRequestHandler(databasePager); osgDB::ImagePager* imagePager = view ? view->getImagePager() : 0; sceneView->getCullVisitor()->setImageRequestHandler(imagePager); sceneView->setFrameStamp(view ? view->getFrameStamp() : state->getFrameStamp()); osg::DisplaySettings* ds = _camera->getDisplaySettings() ? _camera->getDisplaySettings() : ((view &&view->getDisplaySettings()) ? view->getDisplaySettings() : osg::DisplaySettings::instance().get()); if (ds->getUseSceneViewForStereoHint()) { sceneView->setDisplaySettings(ds); } if (view) { _startTick = view->getStartTick(); if (state) state->setStartTick(_startTick); } } void Renderer::compile() { DEBUG_MESSAGE<<"Renderer::compile()"<getState()->checkGLErrors("Before Renderer::compile"); if (sceneView->getSceneData()) { osgUtil::GLObjectsVisitor glov; glov.setState(sceneView->getState()); sceneView->getSceneData()->accept(glov); } sceneView->getState()->checkGLErrors("After Renderer::compile"); } static void collectSceneViewStats(unsigned int frameNumber, osgUtil::SceneView* sceneView, osg::Stats* stats) { osgUtil::Statistics sceneStats; sceneView->getStats(sceneStats); stats->setAttribute(frameNumber, "Visible vertex count", static_cast(sceneStats._vertexCount)); stats->setAttribute(frameNumber, "Visible number of drawables", static_cast(sceneStats.numDrawables)); stats->setAttribute(frameNumber, "Visible number of fast drawables", static_cast(sceneStats.numFastDrawables)); stats->setAttribute(frameNumber, "Visible number of lights", static_cast(sceneStats.nlights)); stats->setAttribute(frameNumber, "Visible number of render bins", static_cast(sceneStats.nbins)); stats->setAttribute(frameNumber, "Visible depth", static_cast(sceneStats.depth)); stats->setAttribute(frameNumber, "Number of StateGraphs", static_cast(sceneStats.numStateGraphs)); stats->setAttribute(frameNumber, "Visible number of impostors", static_cast(sceneStats.nimpostor)); stats->setAttribute(frameNumber, "Number of ordered leaves", static_cast(sceneStats.numOrderedLeaves)); unsigned int totalNumPrimitiveSets = 0; const osgUtil::Statistics::PrimitiveValueMap& pvm = sceneStats.getPrimitiveValueMap(); for(osgUtil::Statistics::PrimitiveValueMap::const_iterator pvm_itr = pvm.begin(); pvm_itr != pvm.end(); ++pvm_itr) { totalNumPrimitiveSets += pvm_itr->second.first; } stats->setAttribute(frameNumber, "Visible number of PrimitiveSets", static_cast(totalNumPrimitiveSets)); osgUtil::Statistics::PrimitiveCountMap& pcm = sceneStats.getPrimitiveCountMap(); stats->setAttribute(frameNumber, "Visible number of GL_POINTS", static_cast(pcm[GL_POINTS])); stats->setAttribute(frameNumber, "Visible number of GL_LINES", static_cast(pcm[GL_LINES])); stats->setAttribute(frameNumber, "Visible number of GL_LINE_STRIP", static_cast(pcm[GL_LINE_STRIP])); stats->setAttribute(frameNumber, "Visible number of GL_LINE_LOOP", static_cast(pcm[GL_LINE_LOOP])); stats->setAttribute(frameNumber, "Visible number of GL_TRIANGLES", static_cast(pcm[GL_TRIANGLES])); stats->setAttribute(frameNumber, "Visible number of GL_TRIANGLE_STRIP", static_cast(pcm[GL_TRIANGLE_STRIP])); stats->setAttribute(frameNumber, "Visible number of GL_TRIANGLE_FAN", static_cast(pcm[GL_TRIANGLE_FAN])); stats->setAttribute(frameNumber, "Visible number of GL_QUADS", static_cast(pcm[GL_QUADS])); stats->setAttribute(frameNumber, "Visible number of GL_QUAD_STRIP", static_cast(pcm[GL_QUAD_STRIP])); stats->setAttribute(frameNumber, "Visible number of GL_POLYGON", static_cast(pcm[GL_POLYGON])); } void Renderer::cull() { DEBUG_MESSAGE<<"cull()"<(sceneView->getCamera()->getView()); if (view) sceneView->setFusionDistance(view->getFusionDistanceMode(), view->getFusionDistanceValue()); osg::Stats* stats = sceneView->getCamera()->getStats(); osg::State* state = sceneView->getState(); const osg::FrameStamp* fs = state->getFrameStamp(); unsigned int frameNumber = fs ? fs->getFrameNumber() : 0; // do cull traversal osg::Timer_t beforeCullTick = osg::Timer::instance()->tick(); sceneView->inheritCullSettings(*(sceneView->getCamera())); sceneView->cull(); osg::Timer_t afterCullTick = osg::Timer::instance()->tick(); #if 0 if (sceneView->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback()) { // OSG_NOTICE<<"Completed in cull"<getDynamicObjectRenderingCompletedCallback()->completed(state); } #endif if (stats && stats->collectStats("rendering")) { DEBUG_MESSAGE<<"Collecting rendering stats"<setAttribute(frameNumber, "Cull traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeCullTick)); stats->setAttribute(frameNumber, "Cull traversal end time", osg::Timer::instance()->delta_s(_startTick, afterCullTick)); stats->setAttribute(frameNumber, "Cull traversal time taken", osg::Timer::instance()->delta_s(beforeCullTick, afterCullTick)); } if (stats && stats->collectStats("scene")) { collectSceneViewStats(frameNumber, sceneView, stats); } _drawQueue.add(sceneView); } DEBUG_MESSAGE<<"end cull() "<tick(); osgUtil::SceneView* sceneView = _drawQueue.takeFront(); DEBUG_MESSAGE<<"draw() got SceneView "<collateReferencesToDependentCameras(); if (_compileOnNextDraw) { compile(); } // OSG_NOTICE<<"Drawing buffer "<<_currentDraw<getCamera()->getStats(); osg::State* state = sceneView->getState(); unsigned int frameNumber = sceneView->getFrameStamp()->getFrameNumber(); if (!_initialized) { initialize(state); } state->setDynamicObjectCount(sceneView->getDynamicObjectCount()); if (sceneView->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback()) { // OSG_NOTICE<<"Completed in cull"<getDynamicObjectRenderingCompletedCallback()->completed(state); } bool acquireGPUStats = stats && _querySupport && stats->collectStats("gpu"); if (acquireGPUStats) { _querySupport->checkQuery(stats, state, _startTick); } // do draw traversal if (acquireGPUStats) { _querySupport->checkQuery(stats, state, _startTick); _querySupport->beginQuery(frameNumber, state); } osg::Timer_t beforeDrawTick; if (_serializeDraw) { OpenThreads::ScopedLock lock(s_drawSerializerMutex); beforeDrawTick = osg::Timer::instance()->tick(); sceneView->draw(); } else { beforeDrawTick = osg::Timer::instance()->tick(); sceneView->draw(); } _availableQueue.add(sceneView); if (acquireGPUStats) { _querySupport->endQuery(state); _querySupport->checkQuery(stats, state, _startTick); } //glFlush(); osg::Timer_t afterDrawTick = osg::Timer::instance()->tick(); // OSG_NOTICE<<"Time wait for draw = "<delta_m(startDrawTick, beforeDrawTick)<setAttribute(frameNumber, "Draw traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeDrawTick)); stats->setAttribute(frameNumber, "Draw traversal end time", osg::Timer::instance()->delta_s(_startTick, afterDrawTick)); stats->setAttribute(frameNumber, "Draw traversal time taken", osg::Timer::instance()->delta_s(beforeDrawTick, afterDrawTick)); } sceneView->clearReferencesToDependentCameras(); } DEBUG_MESSAGE<<"end draw() "<(_camera->getView()); // OSG_NOTICE<<"RenderingOperation"<setFusionDistance(view->getFusionDistanceMode(), view->getFusionDistanceValue()); osg::Stats* stats = sceneView->getCamera()->getStats(); osg::State* state = sceneView->getState(); const osg::FrameStamp* fs = sceneView->getFrameStamp(); unsigned int frameNumber = fs ? fs->getFrameNumber() : 0; if (!_initialized) { initialize(state); } bool acquireGPUStats = stats && _querySupport && stats->collectStats("gpu"); if (acquireGPUStats) { _querySupport->checkQuery(stats, state, _startTick); } // do cull traversal osg::Timer_t beforeCullTick = osg::Timer::instance()->tick(); sceneView->inheritCullSettings(*(sceneView->getCamera())); sceneView->cull(); osg::Timer_t afterCullTick = osg::Timer::instance()->tick(); if (stats && stats->collectStats("scene")) { collectSceneViewStats(frameNumber, sceneView, stats); } #if 0 if (state->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback()) { state->getDynamicObjectRenderingCompletedCallback()->completed(state); } #endif // do draw traversal if (acquireGPUStats) { _querySupport->checkQuery(stats, state, _startTick); _querySupport->beginQuery(frameNumber, state); } osg::Timer_t beforeDrawTick; if (_serializeDraw) { OpenThreads::ScopedLock lock(s_drawSerializerMutex); beforeDrawTick = osg::Timer::instance()->tick(); sceneView->draw(); } else { beforeDrawTick = osg::Timer::instance()->tick(); sceneView->draw(); } if (acquireGPUStats) { _querySupport->endQuery(state); _querySupport->checkQuery(stats, state, _startTick); } osg::Timer_t afterDrawTick = osg::Timer::instance()->tick(); if (stats && stats->collectStats("rendering")) { DEBUG_MESSAGE<<"Collecting rendering stats"<setAttribute(frameNumber, "Cull traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeCullTick)); stats->setAttribute(frameNumber, "Cull traversal end time", osg::Timer::instance()->delta_s(_startTick, afterCullTick)); stats->setAttribute(frameNumber, "Cull traversal time taken", osg::Timer::instance()->delta_s(beforeCullTick, afterCullTick)); stats->setAttribute(frameNumber, "Draw traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeDrawTick)); stats->setAttribute(frameNumber, "Draw traversal end time", osg::Timer::instance()->delta_s(_startTick, afterDrawTick)); stats->setAttribute(frameNumber, "Draw traversal time taken", osg::Timer::instance()->delta_s(beforeDrawTick, afterDrawTick)); } DEBUG_MESSAGE<<"end cull_draw() "<(object); if (context) operator()(context); osg::Camera* camera = dynamic_cast(object); if (camera) cull(); } void Renderer::operator () (osg::GraphicsContext* /*context*/) { if (_graphicsThreadDoesCull) { cull_draw(); } else { draw(); } } void Renderer::release() { OSG_INFO<<"Renderer::release()"<getRenderStage() : 0; if (rs) rs->setCameraRequiresSetUp(flag); rs = sv ? sv->getRenderStageLeft() : 0; if (rs) rs->setCameraRequiresSetUp(flag); rs = sv ? sv->getRenderStageRight() : 0; if (rs) rs->setCameraRequiresSetUp(flag); } } bool Renderer::getCameraRequiresSetUp() const { bool result = false; for (int i = 0; i < 2; ++i) { const osgUtil::SceneView* sv = getSceneView(i); const osgUtil::RenderStage* rs = sv ? sv->getRenderStage() : 0; if (rs) result = result || rs->getCameraRequiresSetUp(); rs = sv ? sv->getRenderStageLeft() : 0; if (rs) result = result || rs->getCameraRequiresSetUp(); rs = sv ? sv->getRenderStageRight() : 0; if (rs) result = result || rs->getCameraRequiresSetUp(); } return result; } openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/PixelBufferCarbon.cpp0000644000175000017500000001276512021737055026045 0ustar albertoalberto/* * PixelBufferCarbon.cpp * OpenSceneGraph * * Created by Stephan Huber on 27.06.07. * Copyright 2007 __MyCompanyName__. All rights reserved. * */ #if defined (__APPLE__) && (!__LP64__) #include #include #include #include #include using namespace osgViewer; /** creates a pixelformat from a Trait */ AGLPixelFormat PixelBufferCarbon::createPixelFormat(osg::GraphicsContext::Traits* traits) { std::vector attributes; attributes.push_back(AGL_NO_RECOVERY); attributes.push_back(AGL_RGBA); if (!traits->pbuffer) attributes.push_back(AGL_COMPLIANT); else attributes.push_back(AGL_CLOSEST_POLICY); if (traits->doubleBuffer) attributes.push_back(AGL_DOUBLEBUFFER); if (traits->quadBufferStereo) attributes.push_back(AGL_STEREO); attributes.push_back(AGL_RED_SIZE); attributes.push_back(traits->red); attributes.push_back(AGL_GREEN_SIZE); attributes.push_back(traits->green); attributes.push_back(AGL_BLUE_SIZE); attributes.push_back(traits->blue); attributes.push_back(AGL_DEPTH_SIZE); attributes.push_back(traits->depth); if (traits->alpha) { attributes.push_back(AGL_ALPHA_SIZE); attributes.push_back(traits->alpha); } if (traits->stencil) { attributes.push_back(AGL_STENCIL_SIZE); attributes.push_back(traits->stencil); } // TODO // missing accumulation-buffer-stuff #if defined(AGL_SAMPLE_BUFFERS_ARB) && defined (AGL_SAMPLES_ARB) if (traits->sampleBuffers) { attributes.push_back(AGL_SAMPLE_BUFFERS_ARB); attributes.push_back(traits->sampleBuffers); } if (traits->sampleBuffers) { attributes.push_back(AGL_SAMPLES_ARB); attributes.push_back(traits->samples); } #endif attributes.push_back(AGL_NONE); return aglChoosePixelFormat(NULL, 0, &(attributes.front())); } void PixelBufferCarbon::init() { _context = NULL; _pixelformat = PixelBufferCarbon::createPixelFormat(_traits.get()); if (!_pixelformat) OSG_WARN << "PixelBufferCarbon::init could not create a valid pixelformat" << std::endl; _valid = (_pixelformat != NULL); } /** This is the class we need to create for pbuffers, note its not a GraphicsWindow as it won't need any of the event handling and window mapping facilities.*/ /** Realise the GraphicsContext implementation, * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ bool PixelBufferCarbon::realizeImplementation() { if (!_valid) { OSG_WARN << "PixelBufferCarbon::realizeImplementation() aglChoosePixelFormat failed! " << aglErrorString(aglGetError()) << std::endl; return false; } AGLContext sharedContext = NULL; // get any shared AGL contexts GraphicsHandleCarbon* graphicsHandleCarbon = dynamic_cast(_traits->sharedContext.get()); if (graphicsHandleCarbon) { sharedContext = graphicsHandleCarbon->getAGLContext(); } _context = aglCreateContext (_pixelformat, sharedContext); if (!_context) { OSG_WARN << "PixelBufferCarbon::realizeImplementation() aglCreateContext failed! " << aglErrorString(aglGetError()) << std::endl; return false; } _realized = aglCreatePBuffer (_traits->width, _traits->height, _traits->target, GL_RGBA, _traits->level, &(_pbuffer)); if (!_realized) { OSG_WARN << "PixelBufferCarbon::realizeImplementation() aglCreatePBuffer failed! " << aglErrorString(aglGetError()) << std::endl; } makeCurrentImplementation(); _realized = aglSetPBuffer(_context, _pbuffer, _traits->face, _traits->level, 0); if (!_realized) { OSG_WARN << "PixelBufferCarbon::realizeImplementation() aglSetPBuffer failed! " << aglErrorString(aglGetError()) << std::endl; } return _realized; } void PixelBufferCarbon::closeImplementation() { if (_pbuffer) aglDestroyPBuffer(_pbuffer); if (_context) aglDestroyContext(_context); if (_pixelformat) aglDestroyPixelFormat(_pixelformat); _pbuffer = NULL; _context = NULL; _pixelformat = NULL; _valid = _realized = false; } /** Make this graphics context current implementation. * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ bool PixelBufferCarbon::makeCurrentImplementation() { return (_realized) ? (aglSetCurrentContext(_context) == GL_TRUE) : false; } /** Make this graphics context current with specified read context implementation. * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ bool PixelBufferCarbon::makeContextCurrentImplementation(GraphicsContext* /*readContext*/) { return makeCurrentImplementation(); } /** Release the graphics context.*/ bool PixelBufferCarbon::releaseContextImplementation() { return (aglSetCurrentContext(NULL) == GL_TRUE); } /** Pure virtual, Bind the graphics context to associated texture implementation. * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ void PixelBufferCarbon::bindPBufferToTextureImplementation( GLenum buffer ){ OSG_NOTICE<<"GraphicsWindow::void bindPBufferToTextureImplementation(..) not implemented."< #include #include #include //#define USE_DARWIN_COCOA_IMPLEMENTATION 1 //#define USE_DARWIN_CARBON_IMPLEMENTATION 1 namespace osgDarwin { /** the MenubarController class checks all open windows if they intersect with the menubar / dock and hide the menubar/dock if necessary */ class MenubarController : public osg::Referenced { public: class WindowAdapter : public osg::Referenced { public: WindowAdapter() : osg::Referenced() {} virtual bool valid() = 0; virtual void getWindowBounds(CGRect& rect) = 0; virtual osgViewer::GraphicsWindow* getWindow() = 0; protected: virtual ~WindowAdapter() {} }; MenubarController(); static MenubarController* instance(); void attachWindow(WindowAdapter* win); void update(); void detachWindow(osgViewer::GraphicsWindow* win); private: typedef std::list< osg::ref_ptr< WindowAdapter > > WindowList; WindowList _list; bool _menubarShown; CGRect _availRect; CGRect _mainScreenBounds; OpenThreads::Mutex _mutex; }; struct DarwinWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface { public: DarwinWindowingSystemInterface(); /** dtor */ ~DarwinWindowingSystemInterface(); /** @return a CGDirectDisplayID for a ScreenIdentifier */ CGDirectDisplayID getDisplayID(const osg::GraphicsContext::ScreenIdentifier& si); /** @return count of attached screens */ virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si) ; virtual void getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution); virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, osg::GraphicsContext::ScreenSettingsList & resolutionList); virtual bool setScreenSettings (const osg::GraphicsContext::ScreenIdentifier & si, const osg::GraphicsContext::ScreenSettings & settings); /** return the top left coord of a specific screen in global screen space */ void getScreenTopLeft(const osg::GraphicsContext::ScreenIdentifier& si, int& x, int& y); /** returns screen-ndx containing rect x,y,w,h */ unsigned int getScreenContaining(int x, int y, int w, int h); protected: virtual void _init(); /** implementation of setScreenResolution */ bool setScreenResolutionImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, unsigned int width, unsigned int height) ; /** implementation of setScreenRefreshRate */ bool setScreenRefreshRateImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, double refreshRate); template osg::GraphicsContext* createGraphicsContextImplementation(osg::GraphicsContext::Traits* traits) { if (traits->pbuffer) { osg::ref_ptr pbuffer = new PixelBufferImplementation(traits); if (pbuffer->valid()) return pbuffer.release(); else return 0; } else { osg::ref_ptr window = new GraphicsWindowImplementation(traits); if (window->valid()) return window.release(); else return 0; } } protected: bool _initialized; CGDisplayCount _displayCount; CGDirectDisplayID* _displayIds; }; template struct RegisterWindowingSystemInterfaceProxy { RegisterWindowingSystemInterfaceProxy() { osg::GraphicsContext::setWindowingSystemInterface(new WSI); } ~RegisterWindowingSystemInterfaceProxy() { if (osg::Referenced::getDeleteHandler()) { osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); osg::Referenced::getDeleteHandler()->flushAll(); } osg::GraphicsContext::setWindowingSystemInterface(0); } }; } #endif #endif // __APPLE__ openscenegraph-3.2.3/OpenSceneGraph/src/osgViewer/StatsHandler.cpp0000644000175000017500000020034212472604767025104 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include namespace osgViewer { StatsHandler::StatsHandler(): _keyEventTogglesOnScreenStats('s'), _keyEventPrintsOutStats('S'), _statsType(NO_STATS), _initialized(false), _threadingModel(ViewerBase::SingleThreaded), _frameRateChildNum(0), _viewerChildNum(0), _cameraSceneChildNum(0), _viewerSceneChildNum(0), _numBlocks(8), _blockMultiplier(10000.0), _statsWidth(1280.0f), _statsHeight(1024.0f), _font("fonts/arial.ttf"), _startBlocks(150.0f), _leftPos(10.0f), _characterSize(20.0f), _lineHeight(1.5f) { _camera = new osg::Camera; _camera->setRenderer(new Renderer(_camera.get())); _camera->setProjectionResizePolicy(osg::Camera::FIXED); } bool StatsHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { osgViewer::View* myview = dynamic_cast(&aa); if (!myview) return false; osgViewer::ViewerBase* viewer = myview->getViewerBase(); if (viewer && _threadingModelText.valid() && viewer->getThreadingModel()!=_threadingModel) { _threadingModel = viewer->getThreadingModel(); updateThreadingModelText(); } if (ea.getHandled()) return false; switch(ea.getEventType()) { case(osgGA::GUIEventAdapter::KEYDOWN): { if (ea.getKey()==_keyEventTogglesOnScreenStats) { if (viewer->getViewerStats()) { if (!_initialized) { setUpHUDCamera(viewer); setUpScene(viewer); } ++_statsType; if (_statsType==LAST) _statsType = NO_STATS; osgViewer::ViewerBase::Cameras cameras; viewer->getCameras(cameras); switch(_statsType) { case(NO_STATS): { viewer->getViewerStats()->collectStats("frame_rate",false); viewer->getViewerStats()->collectStats("event",false); viewer->getViewerStats()->collectStats("update",false); for(osgViewer::ViewerBase::Cameras::iterator itr = cameras.begin(); itr != cameras.end(); ++itr) { osg::Stats* stats = (*itr)->getStats(); if (stats) { stats->collectStats("rendering",false); stats->collectStats("gpu",false); stats->collectStats("scene",false); } } viewer->getViewerStats()->collectStats("scene",false); _camera->setNodeMask(0x0); _switch->setAllChildrenOff(); break; } case(FRAME_RATE): { viewer->getViewerStats()->collectStats("frame_rate",true); _camera->setNodeMask(0xffffffff); _switch->setValue(_frameRateChildNum, true); break; } case(VIEWER_STATS): { ViewerBase::Scenes scenes; viewer->getScenes(scenes); for(ViewerBase::Scenes::iterator itr = scenes.begin(); itr != scenes.end(); ++itr) { Scene* scene = *itr; osgDB::DatabasePager* dp = scene->getDatabasePager(); if (dp && dp->isRunning()) { dp->resetStats(); } } viewer->getViewerStats()->collectStats("event",true); viewer->getViewerStats()->collectStats("update",true); for(osgViewer::ViewerBase::Cameras::iterator itr = cameras.begin(); itr != cameras.end(); ++itr) { if ((*itr)->getStats()) (*itr)->getStats()->collectStats("rendering",true); if ((*itr)->getStats()) (*itr)->getStats()->collectStats("gpu",true); } _camera->setNodeMask(0xffffffff); _switch->setValue(_viewerChildNum, true); break; } case(CAMERA_SCENE_STATS): { _camera->setNodeMask(0xffffffff); _switch->setValue(_cameraSceneChildNum, true); for(osgViewer::ViewerBase::Cameras::iterator itr = cameras.begin(); itr != cameras.end(); ++itr) { osg::Stats* stats = (*itr)->getStats(); if (stats) { stats->collectStats("scene",true); } } break; } case(VIEWER_SCENE_STATS): { _camera->setNodeMask(0xffffffff); _switch->setValue(_viewerSceneChildNum, true); viewer->getViewerStats()->collectStats("scene",true); break; } default: break; } aa.requestRedraw(); } return true; } if (ea.getKey()==_keyEventPrintsOutStats) { if (viewer->getViewerStats()) { OSG_NOTICE< StatsList; StatsList statsList; statsList.push_back(viewer->getViewerStats()); osgViewer::ViewerBase::Contexts contexts; viewer->getContexts(contexts); for(osgViewer::ViewerBase::Contexts::iterator gcitr = contexts.begin(); gcitr != contexts.end(); ++gcitr) { osg::GraphicsContext::Cameras& cameras = (*gcitr)->getCameras(); for(osg::GraphicsContext::Cameras::iterator itr = cameras.begin(); itr != cameras.end(); ++itr) { if ((*itr)->getStats()) { statsList.push_back((*itr)->getStats()); } } } for(unsigned int i = viewer->getViewerStats()->getEarliestFrameNumber(); i< viewer->getViewerStats()->getLatestFrameNumber(); ++i) { for(StatsList::iterator itr = statsList.begin(); itr != statsList.end(); ++itr) { if (itr==statsList.begin()) (*itr)->report(osg::notify(osg::NOTICE), i); else (*itr)->report(osg::notify(osg::NOTICE), i, " "); } OSG_NOTICE<setText("ThreadingModel: SingleThreaded"); break; case(osgViewer::Viewer::CullDrawThreadPerContext): _threadingModelText->setText("ThreadingModel: CullDrawThreadPerContext"); break; case(osgViewer::Viewer::DrawThreadPerContext): _threadingModelText->setText("ThreadingModel: DrawThreadPerContext"); break; case(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext): _threadingModelText->setText("ThreadingModel: CullThreadPerCameraDrawThreadPerContext"); break; case(osgViewer::Viewer::AutomaticSelection): _threadingModelText->setText("ThreadingModel: AutomaticSelection"); break; default: _threadingModelText->setText("ThreadingModel: unknown"); break; } } void StatsHandler::reset() { _initialized = false; _camera->setGraphicsContext(0); _camera->removeChildren( 0, _camera->getNumChildren() ); } void StatsHandler::addUserStatsLine(const std::string& label, const osg::Vec4& textColor, const osg::Vec4& barColor, const std::string& timeTakenName, float multiplier, bool average, bool averageInInverseSpace, const std::string& beginTimeName, const std::string& endTimeName, float maxValue) { _userStatsLines.push_back(UserStatsLine(label, textColor, barColor, timeTakenName, multiplier, average, averageInInverseSpace, beginTimeName, endTimeName, maxValue)); reset(); // Rebuild the stats display with the new user stats line. } void StatsHandler::removeUserStatsLine(const std::string& label) { // Hopefully the labels are unique... This could be enforced. for (unsigned int i = 0; i < _userStatsLines.size(); ++i) { if (_userStatsLines[i].label == label) { _userStatsLines.erase(_userStatsLines.begin() + i); reset(); // Rebuild the stats display without the removed user stats line. break; } } } void StatsHandler::setUpHUDCamera(osgViewer::ViewerBase* viewer) { // Try GraphicsWindow first so we're likely to get the main viewer window osg::GraphicsContext* context = dynamic_cast(_camera->getGraphicsContext()); if (!context) { osgViewer::Viewer::Windows windows; viewer->getWindows(windows); if (!windows.empty()) context = windows.front(); else { // No GraphicsWindows were found, so let's try to find a GraphicsContext context = _camera->getGraphicsContext(); if (!context) { osgViewer::Viewer::Contexts contexts; viewer->getContexts(contexts); if (contexts.empty()) return; context = contexts.front(); } } } _camera->setGraphicsContext(context); _camera->setRenderOrder(osg::Camera::POST_RENDER, 10); _camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); _camera->setViewMatrix(osg::Matrix::identity()); setWindowSize(context->getTraits()->width, context->getTraits()->height); // only clear the depth buffer _camera->setClearMask(0); _camera->setAllowEventFocus(false); _camera->setRenderer(new Renderer(_camera.get())); _initialized = true; } void StatsHandler::setWindowSize(int width, int height) { if (width <= 0 || height <= 0) return; _camera->setViewport(0, 0, width, height); if (fabs(height*_statsWidth) <= fabs(width*_statsHeight)) { _camera->setProjectionMatrix(osg::Matrix::ortho2D(0.0,width*_statsHeight/height,0.0,_statsHeight)); } else { _camera->setProjectionMatrix(osg::Matrix::ortho2D(0.0,_statsWidth,_statsHeight-height*_statsWidth/width,_statsHeight)); } } // Drawcallback to draw averaged attribute struct AveragedValueTextDrawCallback : public virtual osg::Drawable::DrawCallback { AveragedValueTextDrawCallback(osg::Stats* stats, const std::string& name, int frameDelta, bool averageInInverseSpace, double multiplier): _stats(stats), _attributeName(name), _frameDelta(frameDelta), _averageInInverseSpace(averageInInverseSpace), _multiplier(multiplier), _tickLastUpdated(0) { } /** do customized draw code.*/ virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const { osgText::Text* text = (osgText::Text*)drawable; osg::Timer_t tick = osg::Timer::instance()->tick(); double delta = osg::Timer::instance()->delta_m(_tickLastUpdated, tick); if (delta>50) // update every 50ms { _tickLastUpdated = tick; double value; if (_stats->getAveragedAttribute( _attributeName, value, _averageInInverseSpace)) { char tmpText[128]; sprintf(tmpText,"%4.2f",value * _multiplier); text->setText(tmpText); } else { text->setText(""); } } text->drawImplementation(renderInfo); } osg::ref_ptr _stats; std::string _attributeName; int _frameDelta; bool _averageInInverseSpace; double _multiplier; mutable osg::Timer_t _tickLastUpdated; }; // Drawcallback to draw raw attribute struct RawValueTextDrawCallback : public virtual osg::Drawable::DrawCallback { RawValueTextDrawCallback(osg::Stats* stats, const std::string& name, int frameDelta, double multiplier): _stats(stats), _attributeName(name), _frameDelta(frameDelta), _multiplier(multiplier), _tickLastUpdated(0) { } /** do customized draw code.*/ virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const { osgText::Text* text = (osgText::Text*)drawable; osg::Timer_t tick = osg::Timer::instance()->tick(); double delta = osg::Timer::instance()->delta_m(_tickLastUpdated, tick); if (delta>50) // update every 50ms { _tickLastUpdated = tick; unsigned int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber(); double value; if (_stats->getAttribute(frameNumber, _attributeName, value)) { char tmpText[128]; sprintf(tmpText,"%4.2f",value * _multiplier); text->setText(tmpText); } else { text->setText(""); } } text->drawImplementation(renderInfo); } osg::ref_ptr _stats; std::string _attributeName; int _frameDelta; double _multiplier; mutable osg::Timer_t _tickLastUpdated; }; struct CameraSceneStatsTextDrawCallback : public virtual osg::Drawable::DrawCallback { CameraSceneStatsTextDrawCallback(osg::Camera* camera, int cameraNumber): _camera(camera), _tickLastUpdated(0), _cameraNumber(cameraNumber) { } /** do customized draw code.*/ virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const { if (!_camera) return; osgText::Text* text = (osgText::Text*)drawable; osg::Timer_t tick = osg::Timer::instance()->tick(); double delta = osg::Timer::instance()->delta_m(_tickLastUpdated, tick); if (delta > 100) // update every 100ms { _tickLastUpdated = tick; std::ostringstream viewStr; viewStr.clear(); osg::Stats* stats = _camera->getStats(); osgViewer::Renderer* renderer = dynamic_cast(_camera->getRenderer()); if (stats && renderer) { viewStr.setf(std::ios::left, std::ios::adjustfield); viewStr.width(14); // Used fixed formatting, as scientific will switch to "...e+.." notation for // large numbers of vertices/drawables/etc. viewStr.setf(std::ios::fixed); viewStr.precision(0); viewStr << std::setw(1) << "#" << _cameraNumber << std::endl; // Camera name if (!_camera->getName().empty()) viewStr << _camera->getName(); viewStr << std::endl; unsigned int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber(); if (!(renderer->getGraphicsThreadDoesCull())) { --frameNumber; } #define STATS_ATTRIBUTE(str) \ if (stats->getAttribute(frameNumber, str, value)) \ viewStr << std::setw(8) << value << std::endl; \ else \ viewStr << std::setw(8) << "." << std::endl; \ double value = 0.0; STATS_ATTRIBUTE("Visible number of lights") STATS_ATTRIBUTE("Visible number of render bins") STATS_ATTRIBUTE("Visible depth") STATS_ATTRIBUTE("Number of StateGraphs") STATS_ATTRIBUTE("Visible number of impostors") STATS_ATTRIBUTE("Visible number of drawables") STATS_ATTRIBUTE("Number of ordered leaves") STATS_ATTRIBUTE("Visible number of fast drawables") STATS_ATTRIBUTE("Visible vertex count") STATS_ATTRIBUTE("Visible number of PrimitiveSets") STATS_ATTRIBUTE("Visible number of GL_POINTS") STATS_ATTRIBUTE("Visible number of GL_LINES") STATS_ATTRIBUTE("Visible number of GL_LINE_STRIP") STATS_ATTRIBUTE("Visible number of GL_LINE_LOOP") STATS_ATTRIBUTE("Visible number of GL_TRIANGLES") STATS_ATTRIBUTE("Visible number of GL_TRIANGLE_STRIP") STATS_ATTRIBUTE("Visible number of GL_TRIANGLE_FAN") STATS_ATTRIBUTE("Visible number of GL_QUADS") STATS_ATTRIBUTE("Visible number of GL_QUAD_STRIP") STATS_ATTRIBUTE("Visible number of GL_POLYGON") text->setText(viewStr.str()); } } text->drawImplementation(renderInfo); } osg::observer_ptr _camera; mutable osg::Timer_t _tickLastUpdated; int _cameraNumber; }; struct ViewSceneStatsTextDrawCallback : public virtual osg::Drawable::DrawCallback { ViewSceneStatsTextDrawCallback(osgViewer::View* view, int viewNumber): _view(view), _tickLastUpdated(0), _viewNumber(viewNumber) { } /** do customized draw code.*/ virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const { if (!_view) return; osgText::Text* text = (osgText::Text*)drawable; osg::Timer_t tick = osg::Timer::instance()->tick(); double delta = osg::Timer::instance()->delta_m(_tickLastUpdated, tick); if (delta > 200) // update every 100ms { _tickLastUpdated = tick; osg::Stats* stats = _view->getStats(); if (stats) { std::ostringstream viewStr; viewStr.clear(); viewStr.setf(std::ios::left, std::ios::adjustfield); viewStr.width(20); viewStr.setf(std::ios::fixed); viewStr.precision(0); viewStr << std::setw(1) << "#" << _viewNumber; // View name if (!_view->getName().empty()) viewStr << ": " << _view->getName(); viewStr << std::endl; unsigned int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber(); // if (!(renderer->getGraphicsThreadDoesCull())) { --frameNumber; } #define STATS_ATTRIBUTE_PAIR(str1, str2) \ if (stats->getAttribute(frameNumber, str1, value)) \ viewStr << std::setw(9) << value; \ else \ viewStr << std::setw(9) << "."; \ if (stats->getAttribute(frameNumber, str2, value)) \ viewStr << std::setw(9) << value << std::endl; \ else \ viewStr << std::setw(9) << "." << std::endl; \ double value = 0.0; // header viewStr << std::setw(9) << "Unique" << std::setw(9) << "Instance" << std::endl; STATS_ATTRIBUTE_PAIR("Number of unique StateSet","Number of instanced Stateset") STATS_ATTRIBUTE_PAIR("Number of unique Group","Number of instanced Group") STATS_ATTRIBUTE_PAIR("Number of unique Transform","Number of instanced Transform") STATS_ATTRIBUTE_PAIR("Number of unique LOD","Number of instanced LOD") STATS_ATTRIBUTE_PAIR("Number of unique Switch","Number of instanced Switch") STATS_ATTRIBUTE_PAIR("Number of unique Geode","Number of instanced Geode") STATS_ATTRIBUTE_PAIR("Number of unique Drawable","Number of instanced Drawable") STATS_ATTRIBUTE_PAIR("Number of unique Geometry","Number of instanced Geometry") STATS_ATTRIBUTE_PAIR("Number of unique Vertices","Number of instanced Vertices") STATS_ATTRIBUTE_PAIR("Number of unique Primitives","Number of instanced Primitives") text->setText(viewStr.str()); } else { OSG_WARN<setText(""); } } text->drawImplementation(renderInfo); } osg::observer_ptr _view; mutable osg::Timer_t _tickLastUpdated; int _viewNumber; }; struct BlockDrawCallback : public virtual osg::Drawable::DrawCallback { BlockDrawCallback(StatsHandler* statsHandler, float xPos, osg::Stats* viewerStats, osg::Stats* stats, const std::string& beginName, const std::string& endName, int frameDelta, int numFrames): _statsHandler(statsHandler), _xPos(xPos), _viewerStats(viewerStats), _stats(stats), _beginName(beginName), _endName(endName), _frameDelta(frameDelta), _numFrames(numFrames) {} /** do customized draw code.*/ virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const { osg::Geometry* geom = (osg::Geometry*)drawable; osg::Vec3Array* vertices = (osg::Vec3Array*)geom->getVertexArray(); int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber(); int startFrame = frameNumber + _frameDelta - _numFrames + 1; int endFrame = frameNumber + _frameDelta; double referenceTime; if (!_viewerStats->getAttribute( startFrame, "Reference time", referenceTime)) { return; } unsigned int vi = 0; double beginValue, endValue; for(int i = startFrame; i <= endFrame; ++i) { if (_stats->getAttribute( i, _beginName, beginValue) && _stats->getAttribute( i, _endName, endValue) ) { (*vertices)[vi++].x() = _xPos + (beginValue - referenceTime) * _statsHandler->getBlockMultiplier(); (*vertices)[vi++].x() = _xPos + (beginValue - referenceTime) * _statsHandler->getBlockMultiplier(); (*vertices)[vi++].x() = _xPos + (endValue - referenceTime) * _statsHandler->getBlockMultiplier(); (*vertices)[vi++].x() = _xPos + (endValue - referenceTime) * _statsHandler->getBlockMultiplier(); } } osg::DrawArrays* drawArrays = static_cast(geom->getPrimitiveSet(0)); drawArrays->setCount(vi); drawable->drawImplementation(renderInfo); } StatsHandler* _statsHandler; float _xPos; osg::ref_ptr _viewerStats; osg::ref_ptr _stats; std::string _beginName; std::string _endName; int _frameDelta; int _numFrames; }; osg::Geometry* StatsHandler::createBackgroundRectangle(const osg::Vec3& pos, const float width, const float height, osg::Vec4& color) { osg::StateSet *ss = new osg::StateSet; osg::Geometry* geometry = new osg::Geometry; geometry->setUseDisplayList(false); geometry->setStateSet(ss); osg::Vec3Array* vertices = new osg::Vec3Array; geometry->setVertexArray(vertices); vertices->push_back(osg::Vec3(pos.x(), pos.y(), 0)); vertices->push_back(osg::Vec3(pos.x(), pos.y()-height,0)); vertices->push_back(osg::Vec3(pos.x()+width, pos.y()-height,0)); vertices->push_back(osg::Vec3(pos.x()+width, pos.y(),0)); osg::Vec4Array* colors = new osg::Vec4Array; colors->push_back(color); geometry->setColorArray(colors, osg::Array::BIND_OVERALL); osg::DrawElementsUShort *base = new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_FAN,0); base->push_back(0); base->push_back(1); base->push_back(2); base->push_back(3); geometry->addPrimitiveSet(base); return geometry; } struct StatsGraph : public osg::MatrixTransform { StatsGraph(osg::Vec3 pos, float width, float height) : _pos(pos), _width(width), _height(height), _statsGraphGeode(new osg::Geode) { _pos -= osg::Vec3(0, height, 0.1); setMatrix(osg::Matrix::translate(_pos)); addChild(_statsGraphGeode.get()); } void addStatGraph(osg::Stats* viewerStats, osg::Stats* stats, const osg::Vec4& color, float max, const std::string& nameBegin, const std::string& nameEnd = "") { _statsGraphGeode->addDrawable(new Graph(_pos, _width, _height, viewerStats, stats, color, max, nameBegin, nameEnd)); } osg::Vec3 _pos; float _width; float _height; osg::ref_ptr _statsGraphGeode; protected: struct Graph : public osg::Geometry { Graph(const osg::Vec3& pos, float width, float height, osg::Stats* viewerStats, osg::Stats* stats, const osg::Vec4& color, float max, const std::string& nameBegin, const std::string& nameEnd = "") { setUseDisplayList(false); setVertexArray(new osg::Vec3Array); osg::Vec4Array* colors = new osg::Vec4Array; colors->push_back(color); setColorArray(colors, osg::Array::BIND_OVERALL); setDrawCallback(new GraphUpdateCallback(pos, width, height, viewerStats, stats, max, nameBegin, nameEnd)); } }; struct GraphUpdateCallback : public osg::Drawable::DrawCallback { GraphUpdateCallback(const osg::Vec3& pos, float width, float height, osg::Stats* viewerStats, osg::Stats* stats, float max, const std::string& nameBegin, const std::string& nameEnd = "") : _pos(pos), _width((unsigned int)width), _height((unsigned int)height), _curX(0), _viewerStats(viewerStats), _stats(stats), _max(max), _nameBegin(nameBegin), _nameEnd(nameEnd) { } virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const { osg::Geometry* geometry = const_cast(drawable->asGeometry()); if (!geometry) return; osg::Vec3Array* vertices = dynamic_cast(geometry->getVertexArray()); if (!vertices) return; unsigned int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber(); // Get stats double value; if (_nameEnd.empty()) { if (!_stats->getAveragedAttribute( _nameBegin, value, true )) { value = 0.0; } } else { double beginValue, endValue; if (_stats->getAttribute( frameNumber, _nameBegin, beginValue) && _stats->getAttribute( frameNumber, _nameEnd, endValue) ) { value = endValue - beginValue; } else { value = 0.0; } } // Add new vertex for this frame. value = osg::clampTo(value, 0.0, double(_max)); vertices->push_back(osg::Vec3(float(_curX), float(_height) / _max * value, 0)); // One vertex per pixel in X. int excedent = vertices->size() - _width; if (excedent > 0) { vertices->erase(vertices->begin(), vertices->begin() + excedent); } // Create primitive set if none exists. if (geometry->getNumPrimitiveSets() == 0) geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, 0, 0)); // Update primitive set. osg::DrawArrays* drawArrays = dynamic_cast(geometry->getPrimitiveSet(0)); if (!drawArrays) return; drawArrays->setFirst(0); drawArrays->setCount(vertices->size()); // Make the graph scroll when there is enough data. // Note: We check the frame number so that even if we have // many graphs, the transform is translated only once per // frame. //static const float increment = -1.0; if (GraphUpdateCallback::_frameNumber != frameNumber) { // We know the exact layout of this part of the scene // graph, so this is OK... osg::MatrixTransform* transform = geometry->getParent(0)->getParent(0)->asTransform()->asMatrixTransform(); if (transform) { //osg::Matrix matrix = transform->getMatrix(); //matrix.setTrans(-(*vertices)[0].x(), matrix.getTrans().y(), matrix.getTrans().z()); transform->setMatrix(osg::Matrix::translate(_pos + osg::Vec3(-(*vertices)[0].x(), 0, 0))); } } _curX++; GraphUpdateCallback::_frameNumber = frameNumber; geometry->dirtyBound(); drawable->drawImplementation(renderInfo); } const osg::Vec3 _pos; const unsigned int _width; const unsigned int _height; mutable unsigned int _curX; osg::Stats* _viewerStats; osg::Stats* _stats; const float _max; const std::string _nameBegin; const std::string _nameEnd; static unsigned int _frameNumber; }; }; unsigned int StatsGraph::GraphUpdateCallback::_frameNumber = 0; osg::Geometry* StatsHandler::createGeometry(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numBlocks) { osg::Geometry* geometry = new osg::Geometry; geometry->setUseDisplayList(false); osg::Vec3Array* vertices = new osg::Vec3Array; geometry->setVertexArray(vertices); vertices->reserve(numBlocks*4); for(unsigned int i=0; ipush_back(pos+osg::Vec3(i*20, height, 0.0)); vertices->push_back(pos+osg::Vec3(i*20, 0.0, 0.0)); vertices->push_back(pos+osg::Vec3(i*20+10.0, 0.0, 0.0)); vertices->push_back(pos+osg::Vec3(i*20+10.0, height, 0.0)); } osg::Vec4Array* colours = new osg::Vec4Array; colours->push_back(colour); geometry->setColorArray(colours, osg::Array::BIND_OVERALL); geometry->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, numBlocks*4)); return geometry; } struct FrameMarkerDrawCallback : public virtual osg::Drawable::DrawCallback { FrameMarkerDrawCallback(StatsHandler* statsHandler, float xPos, osg::Stats* viewerStats, int frameDelta, int numFrames): _statsHandler(statsHandler), _xPos(xPos), _viewerStats(viewerStats), _frameDelta(frameDelta), _numFrames(numFrames) {} /** do customized draw code.*/ virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const { osg::Geometry* geom = (osg::Geometry*)drawable; osg::Vec3Array* vertices = (osg::Vec3Array*)geom->getVertexArray(); int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber(); int startFrame = frameNumber + _frameDelta - _numFrames + 1; int endFrame = frameNumber + _frameDelta; double referenceTime; if (!_viewerStats->getAttribute( startFrame, "Reference time", referenceTime)) { return; } unsigned int vi = 0; double currentReferenceTime; for(int i = startFrame; i <= endFrame; ++i) { if (_viewerStats->getAttribute( i, "Reference time", currentReferenceTime)) { (*vertices)[vi++].x() = _xPos + (currentReferenceTime - referenceTime) * _statsHandler->getBlockMultiplier(); (*vertices)[vi++].x() = _xPos + (currentReferenceTime - referenceTime) * _statsHandler->getBlockMultiplier(); } } drawable->drawImplementation(renderInfo); } StatsHandler* _statsHandler; float _xPos; osg::ref_ptr _viewerStats; std::string _endName; int _frameDelta; int _numFrames; }; struct PagerCallback : public virtual osg::NodeCallback { PagerCallback( osgDB::DatabasePager* dp, osgText::Text* minValue, osgText::Text* maxValue, osgText::Text* averageValue, osgText::Text* filerequestlist, osgText::Text* compilelist, double multiplier): _dp(dp), _minValue(minValue), _maxValue(maxValue), _averageValue(averageValue), _filerequestlist(filerequestlist), _compilelist(compilelist), _multiplier(multiplier) { } virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) { if (_dp.valid()) { char tmpText[128]; double value = _dp->getAverageTimeToMergeTiles(); if (value>= 0.0 && value <= 1000) { sprintf(tmpText,"%4.0f",value * _multiplier); _averageValue->setText(tmpText); } else { _averageValue->setText(""); } value = _dp->getMinimumTimeToMergeTile(); if (value>= 0.0 && value <= 1000) { sprintf(tmpText,"%4.0f",value * _multiplier); _minValue->setText(tmpText); } else { _minValue->setText(""); } value = _dp->getMaximumTimeToMergeTile(); if (value>= 0.0 && value <= 1000) { sprintf(tmpText,"%4.0f",value * _multiplier); _maxValue->setText(tmpText); } else { _maxValue->setText(""); } sprintf(tmpText,"%4d", _dp->getFileRequestListSize()); _filerequestlist->setText(tmpText); sprintf(tmpText,"%4d", _dp->getDataToCompileListSize()); _compilelist->setText(tmpText); } traverse(node,nv); } osg::observer_ptr _dp; osg::ref_ptr _minValue; osg::ref_ptr _maxValue; osg::ref_ptr _averageValue; osg::ref_ptr _filerequestlist; osg::ref_ptr _compilelist; double _multiplier; }; osg::Geometry* StatsHandler::createFrameMarkers(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numBlocks) { osg::Geometry* geometry = new osg::Geometry; geometry->setUseDisplayList(false); osg::Vec3Array* vertices = new osg::Vec3Array; geometry->setVertexArray(vertices); vertices->reserve(numBlocks*2); for(unsigned int i=0; ipush_back(pos+osg::Vec3(double(i)*_blockMultiplier*0.01, height, 0.0)); vertices->push_back(pos+osg::Vec3(double(i)*_blockMultiplier*0.01, 0.0, 0.0)); } osg::Vec4Array* colours = new osg::Vec4Array; colours->push_back(colour); geometry->setColorArray(colours, osg::Array::BIND_OVERALL); geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINES, 0, numBlocks*2)); return geometry; } osg::Geometry* StatsHandler::createTick(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numTicks) { osg::Geometry* geometry = new osg::Geometry; geometry->setUseDisplayList(false); osg::Vec3Array* vertices = new osg::Vec3Array; geometry->setVertexArray(vertices); vertices->reserve(numTicks*2); for(unsigned int i=0; ipush_back(pos+osg::Vec3(double(i)*_blockMultiplier*0.001, tickHeight , 0.0)); vertices->push_back(pos+osg::Vec3(double(i)*_blockMultiplier*0.001, 0.0, 0.0)); } osg::Vec4Array* colours = new osg::Vec4Array; colours->push_back(colour); geometry->setColorArray(colours, osg::Array::BIND_OVERALL); geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINES, 0, numTicks*2)); return geometry; } void StatsHandler::setUpScene(osgViewer::ViewerBase* viewer) { _switch = new osg::Switch; _camera->addChild(_switch.get()); osg::StateSet* stateset = _switch->getOrCreateStateSet(); stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); stateset->setMode(GL_BLEND,osg::StateAttribute::ON); stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF); #ifdef OSG_GL1_AVAILABLE stateset->setAttribute(new osg::PolygonMode(), osg::StateAttribute::PROTECTED); #endif // collect all the relevant cameras ViewerBase::Cameras validCameras; viewer->getCameras(validCameras); ViewerBase::Cameras cameras; for(ViewerBase::Cameras::iterator itr = validCameras.begin(); itr != validCameras.end(); ++itr) { if ((*itr)->getStats()) { cameras.push_back(*itr); } } // check for query time support unsigned int numCamrasWithTimerQuerySupport = 0; for(ViewerBase::Cameras::iterator citr = cameras.begin(); citr != cameras.end(); ++citr) { if ((*citr)->getGraphicsContext()) { const osg::State* state = (*citr)->getGraphicsContext()->getState(); unsigned int contextID = state->getContextID(); const osg::Drawable::Extensions* extensions = osg::Drawable::getExtensions(contextID, false); if (extensions && (((extensions->isARBTimerQuerySupported() && state->getTimestampBits() > 0)) || extensions->isTimerQuerySupported())) { ++numCamrasWithTimerQuerySupport; } } } bool acquireGPUStats = numCamrasWithTimerQuerySupport==cameras.size(); osg::Vec3 pos(_leftPos, _statsHeight-24.0f,0.0f); osg::Vec4 colorFR(1.0f,1.0f,1.0f,1.0f); osg::Vec4 colorFRAlpha(1.0f,1.0f,1.0f,0.5f); osg::Vec4 colorUpdate( 0.0f,1.0f,0.0f,1.0f); osg::Vec4 colorUpdateAlpha( 0.0f,1.0f,0.0f,0.5f); osg::Vec4 colorEvent(0.0f, 1.0f, 0.5f, 1.0f); osg::Vec4 colorEventAlpha(0.0f, 1.0f, 0.5f, 0.5f); osg::Vec4 colorCull( 0.0f,1.0f,1.0f,1.0f); osg::Vec4 colorCullAlpha( 0.0f,1.0f,1.0f,0.5f); osg::Vec4 colorDraw( 1.0f,1.0f,0.0f,1.0f); osg::Vec4 colorDrawAlpha( 1.0f,1.0f,0.0f,0.5f); osg::Vec4 colorGPU( 1.0f,0.5f,0.0f,1.0f); osg::Vec4 colorGPUAlpha( 1.0f,0.5f,0.0f,0.5f); osg::Vec4 colorDP( 1.0f,1.0f,0.5f,1.0f); // frame rate stats { osg::Geode* geode = new osg::Geode(); _frameRateChildNum = _switch->getNumChildren(); _switch->addChild(geode, false); osg::ref_ptr frameRateLabel = new osgText::Text; geode->addDrawable( frameRateLabel.get() ); frameRateLabel->setColor(colorFR); frameRateLabel->setFont(_font); frameRateLabel->setCharacterSize(_characterSize); frameRateLabel->setPosition(pos); frameRateLabel->setText("Frame Rate: "); pos.x() = frameRateLabel->getBound().xMax(); osg::ref_ptr frameRateValue = new osgText::Text; geode->addDrawable( frameRateValue.get() ); frameRateValue->setColor(colorFR); frameRateValue->setFont(_font); frameRateValue->setCharacterSize(_characterSize); frameRateValue->setPosition(pos); frameRateValue->setText("0.0"); frameRateValue->setDrawCallback(new AveragedValueTextDrawCallback(viewer->getViewerStats(),"Frame rate",-1, true, 1.0)); pos.y() -= _characterSize*_lineHeight; } osg::Vec4 backgroundColor(0.0, 0.0, 0.0f, 0.3); osg::Vec4 staticTextColor(1.0, 1.0, 0.0f, 1.0); osg::Vec4 dynamicTextColor(1.0, 1.0, 1.0f, 1.0); float backgroundMargin = 5; float backgroundSpacing = 3; // viewer stats { osg::Group* group = new osg::Group; _viewerChildNum = _switch->getNumChildren(); _switch->addChild(group, false); _statsGeode = new osg::Geode(); group->addChild(_statsGeode.get()); { pos.x() = _leftPos; _threadingModelText = new osgText::Text; _statsGeode->addDrawable( _threadingModelText.get() ); _threadingModelText->setColor(colorFR); _threadingModelText->setFont(_font); _threadingModelText->setCharacterSize(_characterSize); _threadingModelText->setPosition(pos); updateThreadingModelText(); pos.y() -= _characterSize*_lineHeight; } float topOfViewerStats = pos.y() + _characterSize; double cameraSize = _lineHeight * 3.0 * cameras.size(); if(!acquireGPUStats) //reduce size if GPU stats not needed { cameraSize -= _lineHeight * cameras.size(); } double userStatsLinesSize = _lineHeight * _userStatsLines.size(); _statsGeode->addDrawable(createBackgroundRectangle( pos + osg::Vec3(-backgroundMargin, _characterSize + backgroundMargin, 0), _statsWidth - 2 * backgroundMargin, (3 + cameraSize + userStatsLinesSize) * _characterSize + 2 * backgroundMargin, backgroundColor) ); // Add user stats lines before the normal viewer and per-camera stats. for (unsigned int i = 0; i < _userStatsLines.size(); ++i) { pos.x() = _leftPos; UserStatsLine& line = _userStatsLines[i]; createTimeStatsLine(line.label, pos, line.textColor, line.barColor, viewer->getViewerStats(), viewer->getViewerStats(), line.timeTakenName, line.multiplier, line.average, line.averageInInverseSpace, line.beginTimeName, line.endTimeName); pos.y() -= _characterSize*_lineHeight; } { pos.x() = _leftPos; createTimeStatsLine("Event", pos, colorUpdate, colorUpdateAlpha, viewer->getViewerStats(), viewer->getViewerStats(), "Event traversal time taken", 1000.0, true, false, "Event traversal begin time", "Event traversal end time"); pos.y() -= _characterSize*_lineHeight; } { pos.x() = _leftPos; createTimeStatsLine("Update", pos, colorUpdate, colorUpdateAlpha, viewer->getViewerStats(), viewer->getViewerStats(), "Update traversal time taken", 1000.0, true, false, "Update traversal begin time", "Update traversal end time"); pos.y() -= _characterSize*_lineHeight; } pos.x() = _leftPos; // add camera stats for(ViewerBase::Cameras::iterator citr = cameras.begin(); citr != cameras.end(); ++citr) { createCameraTimeStats(pos, acquireGPUStats, viewer->getViewerStats(), *citr); } // add frame ticks { osg::Geode* geode = new osg::Geode; group->addChild(geode); osg::Vec4 colourTicks(1.0f,1.0f,1.0f, 0.5f); pos.x() = _startBlocks; pos.y() += _characterSize; float height = topOfViewerStats - pos.y(); osg::Geometry* ticks = createTick(pos, 5.0f, colourTicks, 100); geode->addDrawable(ticks); osg::Geometry* frameMarkers = createFrameMarkers(pos, height, colourTicks, _numBlocks + 1); frameMarkers->setDrawCallback(new FrameMarkerDrawCallback(this, _startBlocks, viewer->getViewerStats(), 0, _numBlocks + 1)); geode->addDrawable(frameMarkers); pos.x() = _leftPos; } // Stats line graph { pos.y() -= (backgroundSpacing + 2 * backgroundMargin); float width = _statsWidth - 4 * backgroundMargin; float height = 5 * _characterSize; // Create a stats graph and add any stats we want to track with it. StatsGraph* statsGraph = new StatsGraph(pos, width, height); group->addChild(statsGraph); statsGraph->addStatGraph(viewer->getViewerStats(), viewer->getViewerStats(), colorFR, 100, "Frame rate"); statsGraph->addStatGraph(viewer->getViewerStats(), viewer->getViewerStats(), colorEvent, 0.016, "Event traversal time taken"); statsGraph->addStatGraph(viewer->getViewerStats(), viewer->getViewerStats(), colorUpdate, 0.016, "Update traversal time taken"); for (unsigned int i = 0; i < _userStatsLines.size(); ++i) { UserStatsLine& line = _userStatsLines[i]; if (!line.timeTakenName.empty() && line.average) { statsGraph->addStatGraph(viewer->getViewerStats(), viewer->getViewerStats(), line.textColor, line.maxValue, line.timeTakenName); } } for(ViewerBase::Cameras::iterator citr = cameras.begin(); citr != cameras.end(); ++citr) { statsGraph->addStatGraph(viewer->getViewerStats(), (*citr)->getStats(), colorCull, 0.016, "Cull traversal time taken"); statsGraph->addStatGraph(viewer->getViewerStats(), (*citr)->getStats(), colorDraw, 0.016, "Draw traversal time taken"); if(acquireGPUStats) { statsGraph->addStatGraph(viewer->getViewerStats(), (*citr)->getStats(), colorGPU, 0.016, "GPU draw time taken"); } } _statsGeode->addDrawable(createBackgroundRectangle( pos + osg::Vec3(-backgroundMargin, backgroundMargin, 0), width + 2 * backgroundMargin, height + 2 * backgroundMargin, backgroundColor) ); pos.x() = _leftPos; pos.y() -= height + 2 * backgroundMargin; } // Databasepager stats ViewerBase::Scenes scenes; viewer->getScenes(scenes); for(ViewerBase::Scenes::iterator itr = scenes.begin(); itr != scenes.end(); ++itr) { Scene* scene = *itr; osgDB::DatabasePager* dp = scene->getDatabasePager(); if (dp && dp->isRunning()) { pos.y() -= (_characterSize + backgroundSpacing); _statsGeode->addDrawable(createBackgroundRectangle( pos + osg::Vec3(-backgroundMargin, _characterSize + backgroundMargin, 0), _statsWidth - 2 * backgroundMargin, _characterSize + 2 * backgroundMargin, backgroundColor)); osg::ref_ptr averageLabel = new osgText::Text; _statsGeode->addDrawable( averageLabel.get() ); averageLabel->setColor(colorDP); averageLabel->setFont(_font); averageLabel->setCharacterSize(_characterSize); averageLabel->setPosition(pos); averageLabel->setText("DatabasePager time to merge new tiles - average: "); pos.x() = averageLabel->getBound().xMax(); osg::ref_ptr averageValue = new osgText::Text; _statsGeode->addDrawable( averageValue.get() ); averageValue->setColor(colorDP); averageValue->setFont(_font); averageValue->setCharacterSize(_characterSize); averageValue->setPosition(pos); averageValue->setText("1000"); pos.x() = averageValue->getBound().xMax() + 2.0f*_characterSize; osg::ref_ptr minLabel = new osgText::Text; _statsGeode->addDrawable( minLabel.get() ); minLabel->setColor(colorDP); minLabel->setFont(_font); minLabel->setCharacterSize(_characterSize); minLabel->setPosition(pos); minLabel->setText("min: "); pos.x() = minLabel->getBound().xMax(); osg::ref_ptr minValue = new osgText::Text; _statsGeode->addDrawable( minValue.get() ); minValue->setColor(colorDP); minValue->setFont(_font); minValue->setCharacterSize(_characterSize); minValue->setPosition(pos); minValue->setText("1000"); pos.x() = minValue->getBound().xMax() + 2.0f*_characterSize; osg::ref_ptr maxLabel = new osgText::Text; _statsGeode->addDrawable( maxLabel.get() ); maxLabel->setColor(colorDP); maxLabel->setFont(_font); maxLabel->setCharacterSize(_characterSize); maxLabel->setPosition(pos); maxLabel->setText("max: "); pos.x() = maxLabel->getBound().xMax(); osg::ref_ptr maxValue = new osgText::Text; _statsGeode->addDrawable( maxValue.get() ); maxValue->setColor(colorDP); maxValue->setFont(_font); maxValue->setCharacterSize(_characterSize); maxValue->setPosition(pos); maxValue->setText("1000"); pos.x() = maxValue->getBound().xMax(); osg::ref_ptr requestsLabel = new osgText::Text; _statsGeode->addDrawable( requestsLabel.get() ); requestsLabel->setColor(colorDP); requestsLabel->setFont(_font); requestsLabel->setCharacterSize(_characterSize); requestsLabel->setPosition(pos); requestsLabel->setText("requests: "); pos.x() = requestsLabel->getBound().xMax(); osg::ref_ptr requestList = new osgText::Text; _statsGeode->addDrawable( requestList.get() ); requestList->setColor(colorDP); requestList->setFont(_font); requestList->setCharacterSize(_characterSize); requestList->setPosition(pos); requestList->setText("0"); pos.x() = requestList->getBound().xMax() + 2.0f*_characterSize;; osg::ref_ptr compileLabel = new osgText::Text; _statsGeode->addDrawable( compileLabel.get() ); compileLabel->setColor(colorDP); compileLabel->setFont(_font); compileLabel->setCharacterSize(_characterSize); compileLabel->setPosition(pos); compileLabel->setText("tocompile: "); pos.x() = compileLabel->getBound().xMax(); osg::ref_ptr compileList = new osgText::Text; _statsGeode->addDrawable( compileList.get() ); compileList->setColor(colorDP); compileList->setFont(_font); compileList->setCharacterSize(_characterSize); compileList->setPosition(pos); compileList->setText("0"); pos.x() = maxLabel->getBound().xMax(); _statsGeode->setCullCallback(new PagerCallback(dp, minValue.get(), maxValue.get(), averageValue.get(), requestList.get(), compileList.get(), 1000.0)); } pos.x() = _leftPos; } } // Camera scene stats { pos.y() -= (_characterSize + backgroundSpacing + 2 * backgroundMargin); osg::Group* group = new osg::Group; _cameraSceneChildNum = _switch->getNumChildren(); _switch->addChild(group, false); osg::Geode* geode = new osg::Geode(); geode->setCullingActive(false); group->addChild(geode); geode->addDrawable(createBackgroundRectangle(pos + osg::Vec3(-backgroundMargin, _characterSize + backgroundMargin, 0), 10 * _characterSize + 2 * backgroundMargin, 22 * _characterSize + 2 * backgroundMargin, backgroundColor)); // Camera scene & primitive stats static text osg::ref_ptr camStaticText = new osgText::Text; geode->addDrawable( camStaticText.get() ); camStaticText->setColor(staticTextColor); camStaticText->setFont(_font); camStaticText->setCharacterSize(_characterSize); camStaticText->setPosition(pos); std::ostringstream viewStr; viewStr.clear(); viewStr.setf(std::ios::left, std::ios::adjustfield); viewStr.width(14); viewStr << "Camera" << std::endl; viewStr << "" << std::endl; // placeholder for Camera name viewStr << "Lights" << std::endl; viewStr << "Bins" << std::endl; viewStr << "Depth" << std::endl; viewStr << "State graphs" << std::endl; viewStr << "Imposters" << std::endl; viewStr << "Drawables" << std::endl; viewStr << "Sorted Drawables" << std::endl; viewStr << "Fast Drawables" << std::endl; viewStr << "Vertices" << std::endl; viewStr << "PrimitiveSets" << std::endl; viewStr << "Points" << std::endl; viewStr << "Lines" << std::endl; viewStr << "Line strips" << std::endl; viewStr << "Line loops" << std::endl; viewStr << "Triangles" << std::endl; viewStr << "Tri. strips" << std::endl; viewStr << "Tri. fans" << std::endl; viewStr << "Quads" << std::endl; viewStr << "Quad strips" << std::endl; viewStr << "Polygons" << std::endl; viewStr.setf(std::ios::right,std::ios::adjustfield); camStaticText->setText(viewStr.str()); // Move camera block to the right pos.x() += 10 * _characterSize + 2 * backgroundMargin + backgroundSpacing; // Add camera scene stats, one block per camera int cameraCounter = 0; for(ViewerBase::Cameras::iterator citr = cameras.begin(); citr != cameras.end(); ++citr) { geode->addDrawable(createBackgroundRectangle(pos + osg::Vec3(-backgroundMargin, _characterSize + backgroundMargin, 0), 5 * _characterSize + 2 * backgroundMargin, 22 * _characterSize + 2 * backgroundMargin, backgroundColor)); // Camera scene stats osg::ref_ptr camStatsText = new osgText::Text; geode->addDrawable( camStatsText.get() ); camStatsText->setColor(dynamicTextColor); camStatsText->setFont(_font); camStatsText->setCharacterSize(_characterSize); camStatsText->setPosition(pos); camStatsText->setText(""); camStatsText->setDrawCallback(new CameraSceneStatsTextDrawCallback(*citr, cameraCounter)); // Move camera block to the right pos.x() += 5 * _characterSize + 2 * backgroundMargin + backgroundSpacing; cameraCounter++; } } // Viewer scene stats { osg::Group* group = new osg::Group; _viewerSceneChildNum = _switch->getNumChildren(); _switch->addChild(group, false); osg::Geode* geode = new osg::Geode(); geode->setCullingActive(false); group->addChild(geode); geode->addDrawable(createBackgroundRectangle(pos + osg::Vec3(-backgroundMargin, _characterSize + backgroundMargin, 0), 6 * _characterSize + 2 * backgroundMargin, 12 * _characterSize + 2 * backgroundMargin, backgroundColor)); // View scene stats static text osg::ref_ptr camStaticText = new osgText::Text; geode->addDrawable( camStaticText.get() ); camStaticText->setColor(staticTextColor); camStaticText->setFont(_font); camStaticText->setCharacterSize(_characterSize); camStaticText->setPosition(pos); std::ostringstream viewStr; viewStr.clear(); viewStr.setf(std::ios::left, std::ios::adjustfield); viewStr.width(14); viewStr << "View" << std::endl; viewStr << " " << std::endl; viewStr << "Stateset" << std::endl; viewStr << "Group" << std::endl; viewStr << "Transform" << std::endl; viewStr << "LOD" << std::endl; viewStr << "Switch" << std::endl; viewStr << "Geode" << std::endl; viewStr << "Drawable" << std::endl; viewStr << "Geometry" << std::endl; viewStr << "Vertices" << std::endl; viewStr << "Primitives" << std::endl; viewStr.setf(std::ios::right, std::ios::adjustfield); camStaticText->setText(viewStr.str()); // Move viewer block to the right pos.x() += 6 * _characterSize + 2 * backgroundMargin + backgroundSpacing; std::vector views; viewer->getViews(views); std::vector::iterator it; int viewCounter = 0; for (it = views.begin(); it != views.end(); ++it) { geode->addDrawable(createBackgroundRectangle(pos + osg::Vec3(-backgroundMargin, _characterSize + backgroundMargin, 0), 10 * _characterSize + 2 * backgroundMargin, 12 * _characterSize + 2 * backgroundMargin, backgroundColor)); // Text for scene statistics osgText::Text* text = new osgText::Text; geode->addDrawable( text ); text->setColor(dynamicTextColor); text->setFont(_font); text->setCharacterSize(_characterSize); text->setPosition(pos); text->setDrawCallback(new ViewSceneStatsTextDrawCallback(*it, viewCounter)); pos.x() += 10 * _characterSize + 2 * backgroundMargin + backgroundSpacing; viewCounter++; } } } void StatsHandler::createTimeStatsLine(const std::string& lineLabel, osg::Vec3 pos, const osg::Vec4& textColor, const osg::Vec4& barColor, osg::Stats* viewerStats, osg::Stats* stats, const std::string& timeTakenName, float multiplier, bool average, bool averageInInverseSpace, const std::string& beginTimeName, const std::string& endTimeName) { osg::ref_ptr label = new osgText::Text; _statsGeode->addDrawable( label.get() ); label->setColor(textColor); label->setFont(_font); label->setCharacterSize(_characterSize); label->setPosition(pos); label->setText(lineLabel + ": "); pos.x() = label->getBound().xMax(); osg::ref_ptr value = new osgText::Text; _statsGeode->addDrawable( value.get() ); value->setColor(textColor); value->setFont(_font); value->setCharacterSize(_characterSize); value->setPosition(pos); value->setText("0.0"); if (!timeTakenName.empty()) { if (average) { value->setDrawCallback(new AveragedValueTextDrawCallback(stats, timeTakenName, -1, averageInInverseSpace, multiplier)); } else { value->setDrawCallback(new RawValueTextDrawCallback(stats, timeTakenName, -1, multiplier)); } } if (!beginTimeName.empty() && !endTimeName.empty()) { pos.x() = _startBlocks; osg::Geometry* geometry = createGeometry(pos, _characterSize *0.8, barColor, _numBlocks); geometry->setDrawCallback(new BlockDrawCallback(this, _startBlocks, viewerStats, stats, beginTimeName, endTimeName, -1, _numBlocks)); _statsGeode->addDrawable(geometry); } } void StatsHandler::createCameraTimeStats(osg::Vec3& pos, bool acquireGPUStats, osg::Stats* viewerStats, osg::Camera* camera) { osg::Stats* stats = camera->getStats(); if (!stats) return; osg::Vec4 colorCull( 0.0f,1.0f,1.0f,1.0f); osg::Vec4 colorCullAlpha( 0.0f,1.0f,1.0f,0.5f); osg::Vec4 colorDraw( 1.0f,1.0f,0.0f,1.0f); osg::Vec4 colorDrawAlpha( 1.0f,1.0f,0.0f,0.5f); osg::Vec4 colorGPU( 1.0f,0.5f,0.0f,1.0f); osg::Vec4 colorGPUAlpha( 1.0f,0.5f,0.0f,0.5f); { pos.x() = _leftPos; createTimeStatsLine("Cull", pos, colorCull, colorCullAlpha, viewerStats, stats, "Cull traversal time taken", 1000.0, true, false, "Cull traversal begin time", "Cull traversal end time"); pos.y() -= _characterSize*_lineHeight; } { pos.x() = _leftPos; createTimeStatsLine("Draw", pos, colorDraw, colorDrawAlpha, viewerStats, stats, "Draw traversal time taken", 1000.0, true, false, "Draw traversal begin time", "Draw traversal end time"); pos.y() -= _characterSize*_lineHeight; } if (acquireGPUStats) { pos.x() = _leftPos; createTimeStatsLine("GPU", pos, colorGPU, colorGPUAlpha, viewerStats, stats, "GPU draw time taken", 1000.0, true, false, "GPU draw begin time", "GPU draw end time"); pos.y() -= _characterSize*_lineHeight; } } void StatsHandler::getUsage(osg::ApplicationUsage& usage) const { usage.addKeyboardMouseBinding(_keyEventTogglesOnScreenStats,"On screen stats."); usage.addKeyboardMouseBinding(_keyEventPrintsOutStats,"Output stats to console."); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/0000755000175000017500000000000012674261220021014 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/src/osgGA/Version.cpp0000644000175000017500000000152411732410624023145 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include extern "C" { const char* osgGAGetVersion() { return osgGetVersion(); } const char* osgGAGetLibraryName() { return "OpenSceneGraph GA (Gui Adapter) Library"; } } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/UFOManipulator.cpp0000644000175000017500000004030211732410624024362 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ /* Written by Don Burns */ #include #include #include #ifndef M_PI # define M_PI 3.14159265358979323846 /* pi */ #endif using namespace osgGA; UFOManipulator::UFOManipulator(): _t0(0.0), _shift(false), _ctrl(false) { _minHeightAboveGround = 2.0; _minDistanceInFront = 5.0; _speedAccelerationFactor = 0.4; _speedDecelerationFactor = 0.90; _directionRotationRate = 0.0; _directionRotationAcceleration = M_PI*0.00005; _directionRotationDeceleration = 0.90; _speedEpsilon = 0.02; _directionRotationEpsilon = 0.0001; _viewOffsetDelta = M_PI * 0.0025; _pitchOffsetRate = 0.0; _pitchOffset = 0.0; _yawOffsetRate = 0.0; _yawOffset = 0.0; _offset.makeIdentity(); _decelerateOffsetRate = true; _straightenOffset = false; _direction.set( 0,1,0); _stop(); } UFOManipulator::~UFOManipulator() { } bool UFOManipulator::intersect(const osg::Vec3d& start, const osg::Vec3d& end, osg::Vec3d& intersection) const { osg::ref_ptr lsi = new osgUtil::LineSegmentIntersector(start,end); osgUtil::IntersectionVisitor iv(lsi.get()); iv.setTraversalMask(_intersectTraversalMask); _node->accept(iv); if (lsi->containsIntersections()) { intersection = lsi->getIntersections().begin()->getWorldIntersectPoint(); return true; } return false; } void UFOManipulator::setNode( osg::Node *node ) { _node = node; if (getAutoComputeHomePosition()) computeHomePosition(); home(0.0); } const osg::Node* UFOManipulator::getNode() const { return _node.get(); } osg::Node* UFOManipulator::getNode() { return _node.get(); } const char* UFOManipulator::className() const { return "UFO"; } void UFOManipulator::setByMatrix( const osg::Matrixd &mat ) { _inverseMatrix = mat; _matrix.invert( _inverseMatrix ); _position.set( _inverseMatrix(3,0), _inverseMatrix(3,1), _inverseMatrix(3,2 )); osg::Matrix R(_inverseMatrix); R(3,0) = R(3,1) = R(3,2) = 0.0; _direction = osg::Vec3d(0,0,-1) * R; // camera up is +Z, regardless of CoordinateFrame _stop(); } void UFOManipulator::setByInverseMatrix( const osg::Matrixd &invmat) { _matrix = invmat; _inverseMatrix.invert( _matrix ); _position.set( _inverseMatrix(3,0), _inverseMatrix(3,1), _inverseMatrix(3,2 )); osg::Matrix R(_inverseMatrix); R(3,0) = R(3,1) = R(3,2) = 0.0; _direction = osg::Vec3d(0,0,-1) * R; // camera up is +Z, regardless of CoordinateFrame _stop(); } osg::Matrixd UFOManipulator::getMatrix() const { return (osg::Matrix::inverse(_offset) * _matrix); } osg::Matrixd UFOManipulator::getInverseMatrix() const { return (_inverseMatrix * _offset); } void UFOManipulator::computeHomePosition() { if( !_node.valid() ) return; osg::BoundingSphere bs = _node->getBound(); /* * Find the ground - Assumption: The ground is the hit of an intersection * from a line segment extending from above to below the database at its * horizontal center, that intersects the database closest to zero. */ osg::CoordinateFrame cf( getCoordinateFrame(bs.center()) ); // not sure what position to use here osg::Vec3d upVec( getUpVector(cf) ); osg::Vec3d A = bs.center() + (upVec*(bs.radius()*2)); osg::Vec3d B = bs.center() + (-upVec*(bs.radius()*2)); if( (B-A).length() == 0.0) { return; } // start with it high double ground = bs.radius() * 3; osg::Vec3d ip; if (intersect(A, B, ip)) { double d = ip.length(); if( d < ground ) ground = d; } else { //OSG_WARN<<"UFOManipulator : I can't find the ground!"<", "Reset the viewing angle to 0.0"); usage.addKeyboardMouseBinding("UFO Manipulator: ", "Acceleration forward."); usage.addKeyboardMouseBinding("UFO Manipulator: ", "Acceleration backward (or deceleration forward"); usage.addKeyboardMouseBinding("UFO Manipulator: ", "Rotate view and direction of travel to the left."); usage.addKeyboardMouseBinding("UFO Manipulator: ", "Rotate view and direction of travel to the right."); usage.addKeyboardMouseBinding("UFO Manipulator: ", "Brake. Gradually decelerates linear and rotational movement."); usage.addKeyboardMouseBinding("UFO Manipulator: ", "Accelerate up."); usage.addKeyboardMouseBinding("UFO Manipulator: ", "Accelerate down."); usage.addKeyboardMouseBinding("UFO Manipulator: ", "Accelerate (linearly) left."); usage.addKeyboardMouseBinding("UFO Manipulator: ","Accelerate (linearly) right."); usage.addKeyboardMouseBinding("UFO Manipulator: ", "Instant brake. Immediately stop all linear and rotational movement."); usage.addKeyboardMouseBinding("UFO Manipulator: ", "Rotate view (but not direction of travel) up."); usage.addKeyboardMouseBinding("UFO Manipulator: ", "Rotate view (but not direction of travel) down."); usage.addKeyboardMouseBinding("UFO Manipulator: ", "Rotate view (but not direction of travel) left."); usage.addKeyboardMouseBinding("UFO Manipulator: ", "Rotate view (but not direction of travel) right."); */ usage.addKeyboardMouseBinding("UFO: ", "Please see http://www.openscenegraph.org/html/UFOCameraManipulator.html"); // Keep this one as it might be confusing usage.addKeyboardMouseBinding("UFO: H", "Reset the viewing position to home"); } void UFOManipulator::_keyUp( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter & ) { switch( ea.getKey() ) { case osgGA::GUIEventAdapter::KEY_Control_L: case osgGA::GUIEventAdapter::KEY_Control_R: _ctrl = false; _decelerateOffsetRate = true; _straightenOffset = false; break; case osgGA::GUIEventAdapter::KEY_Shift_L: case osgGA::GUIEventAdapter::KEY_Shift_R: _shift = false; _decelerateUpSideRate = true; break; } } void UFOManipulator::_keyDown( const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter & ) { switch( ea.getKey() ) { case osgGA::GUIEventAdapter::KEY_Control_L: case osgGA::GUIEventAdapter::KEY_Control_R: _ctrl = true; break; case osgGA::GUIEventAdapter::KEY_Shift_L : case osgGA::GUIEventAdapter::KEY_Shift_R : _shift = true; break; case osgGA::GUIEventAdapter::KEY_Up: if( _ctrl ) { _pitchOffsetRate -= _viewOffsetDelta; _decelerateOffsetRate = false; } else { if( _shift ) { _upSpeed += _speedAccelerationFactor; _decelerateUpSideRate = false; } else _forwardSpeed += _speedAccelerationFactor; } break; case osgGA::GUIEventAdapter::KEY_Down: if( _ctrl ) { _pitchOffsetRate += _viewOffsetDelta; _decelerateOffsetRate = false; } else { if( _shift ) { _upSpeed -= _speedAccelerationFactor; _decelerateUpSideRate = false; } else _forwardSpeed -= _speedAccelerationFactor; } break; case osgGA::GUIEventAdapter::KEY_Right: if( _ctrl ) { _yawOffsetRate += _viewOffsetDelta; _decelerateOffsetRate = false; } else { if(_shift) { _sideSpeed += _speedAccelerationFactor; _decelerateUpSideRate = false; } else _directionRotationRate -= _directionRotationAcceleration; } break; case osgGA::GUIEventAdapter::KEY_Left: if( _ctrl ) { _yawOffsetRate -= _viewOffsetDelta; _decelerateOffsetRate = false; } else { if(_shift) { _sideSpeed -= _speedAccelerationFactor; _decelerateUpSideRate = false; } else _directionRotationRate += _directionRotationAcceleration; } break; case osgGA::GUIEventAdapter::KEY_Return: if( _ctrl ) { _straightenOffset = true; } break; case ' ': if( _shift ) { _stop(); } else { if( fabs(_forwardSpeed) > 0.0 ) { _forwardSpeed *= _speedDecelerationFactor; if( fabs(_forwardSpeed ) < _speedEpsilon ) _forwardSpeed = 0.0; } if( fabs(_sideSpeed) > 0.0 ) { _sideSpeed *= _speedDecelerationFactor; if( fabs( _sideSpeed ) < _speedEpsilon ) _sideSpeed = 0.0; } if( fabs(_upSpeed) > 0.0 ) { _upSpeed *= _speedDecelerationFactor; if( fabs( _upSpeed ) < _speedEpsilon ) _sideSpeed = 0.0; } if( fabs(_directionRotationRate ) > 0.0 ) { _directionRotationRate *= _directionRotationDeceleration; if( fabs( _directionRotationRate ) < _directionRotationEpsilon ) _directionRotationRate = 0.0; } } break; case 'H': home(ea.getTime()); break; } } void UFOManipulator::_frame( const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter & ) { double t1 = ea.getTime(); if( _t0 == 0.0 ) { _t0 = ea.getTime(); _dt = 0.0; } else { _dt = t1 - _t0; _t0 = t1; } osg::CoordinateFrame cf( getCoordinateFrame(_position) ); osg::Vec3d upVec( getUpVector(cf) ); if( fabs( _directionRotationRate ) > _directionRotationEpsilon ) { _direction = _direction * osg::Matrix::rotate( _directionRotationRate, upVec); } { osg::Vec3d _sideVec = _direction * osg::Matrix::rotate( -M_PI*0.5, upVec); _position += ((_direction * _forwardSpeed) + (_sideVec * _sideSpeed) + (upVec * _upSpeed)) * _dt; } _pitchOffset += _pitchOffsetRate * _dt; if( _pitchOffset >= M_PI || _pitchOffset < -M_PI ) _pitchOffset *= -1; _yawOffset += _yawOffsetRate * _dt; if( _yawOffset >= M_PI || _yawOffset < -M_PI ) _yawOffset *= -1; _offset = osg::Matrix::rotate( _yawOffset, getSideVector(cf), _pitchOffset, getFrontVector(cf), 0.0, upVec); _adjustPosition(); _inverseMatrix.makeLookAt( _position, _position + _direction, upVec); _matrix.invert(_inverseMatrix); if( _decelerateUpSideRate ) { _upSpeed *= 0.98; _sideSpeed *= 0.98; } if( _decelerateOffsetRate ) { _yawOffsetRate *= 0.98; _pitchOffsetRate *= 0.98; } if( _straightenOffset ) { if( _shift ) { _pitchOffset = 0.0; _yawOffset = 0.0; _pitchOffsetRate = 0.0; _yawOffsetRate = 0.0; } else { _pitchOffsetRate = 0.0; _yawOffsetRate = 0.0; _pitchOffset *= 0.99; _yawOffset *= 0.99; if( fabs(_pitchOffset ) < 0.01 ) _pitchOffset = 0.0; if( fabs(_yawOffset ) < 0.01 ) _pitchOffset = 0.0; } if( _pitchOffset == 0.0 && _yawOffset == 0.0 ) _straightenOffset = false; } } void UFOManipulator::_adjustPosition() { if( !_node.valid() ) return; // Forward line segment at 3 times our intersect distance typedef std::vector Intersections; Intersections intersections; // Check intersects infront. osg::Vec3d ip; if (intersect(_position, _position + (_direction * (_minDistanceInFront * 3.0)), ip )) { double d = (ip - _position).length(); if( d < _minDistanceInFront ) { _position = ip + (_direction * -_minDistanceInFront); _stop(); } } // Check intersects below. osg::CoordinateFrame cf( getCoordinateFrame(_position) ); osg::Vec3d upVec( getUpVector(cf) ); if (intersect(_position, _position - upVec*_minHeightAboveGround*3, ip )) { double d = (ip - _position).length(); if( d < _minHeightAboveGround ) _position = ip + (upVec * _minHeightAboveGround); } } void UFOManipulator::_stop() { _forwardSpeed = 0.0; _sideSpeed = 0.0; _upSpeed = 0.0; _directionRotationRate = 0.0; } void UFOManipulator::getCurrentPositionAsLookAt( osg::Vec3d& eye, osg::Vec3d& center, osg::Vec3d& up ) { eye = _position; center = _position + _direction; up.set(getUpVector(getCoordinateFrame(_position))); } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/StandardManipulator.cpp0000644000175000017500000006152612474571503025514 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. * * StandardManipulator code Copyright (C) 2010 PCJohn (Jan Peciva) * while some pieces of code were taken from OSG. * Thanks to company Cadwork (www.cadwork.ch) and * Brno University of Technology (www.fit.vutbr.cz) for open-sourcing this work. */ #include #include using namespace osg; using namespace osgGA; using namespace osgUtil; int StandardManipulator::numRelativeFlagsAllocated = 0; int StandardManipulator::allocateRelativeFlag() { return numRelativeFlagsAllocated++; } /// Constructor. StandardManipulator::StandardManipulator( int flags ) : inherited(), _thrown( false ), _allowThrow( true ), _mouseCenterX(0.0f), _mouseCenterY(0.0f), _delta_frame_time(0.01), _last_frame_time(0.0), _modelSize( 0. ), _verticalAxisFixed( true ), _flags( flags ), _relativeFlags( 0 ) { } /// Constructor. StandardManipulator::StandardManipulator( const StandardManipulator& uim, const CopyOp& copyOp ) : osg::Object(uim, copyOp), inherited( uim, copyOp ), _thrown( uim._thrown ), _allowThrow( uim._allowThrow ), _mouseCenterX(0.0f), _mouseCenterY(0.0f), _ga_t1( dynamic_cast< GUIEventAdapter* >( copyOp( uim._ga_t1.get() ) ) ), _ga_t0( dynamic_cast< GUIEventAdapter* >( copyOp( uim._ga_t0.get() ) ) ), _delta_frame_time(0.01), _last_frame_time(0.0), _modelSize( uim._modelSize ), _verticalAxisFixed( uim._verticalAxisFixed ), _flags( uim._flags ), _relativeFlags( uim._relativeFlags ) { } /** Attach a node to the manipulator. Automatically detaches previously attached node. setNode(NULL) detaches previously attached nodes. Is ignored by manipulators which do not require a reference model.*/ void StandardManipulator::setNode( Node* node ) { _node = node; // update model size if( _node.get() ) { const BoundingSphere& boundingSphere = _node->getBound(); _modelSize = boundingSphere.radius(); } else { _modelSize = 0.; } // compute home position if( getAutoComputeHomePosition() ) computeHomePosition( NULL, ( _flags & COMPUTE_HOME_USING_BBOX ) != 0 ); } /** Return node if attached.*/ const Node* StandardManipulator::getNode() const { return _node.get(); } /** Return node if attached.*/ Node* StandardManipulator::getNode() { return _node.get(); } /** Makes manipulator to keep camera's "UP" vector. * * In general, fixed up vector makes camera control more user friendly. * * To change up vector, use CameraManipulator::setCoordinateFrameCallback.*/ void StandardManipulator::setVerticalAxisFixed( bool value ) { _verticalAxisFixed = value; } /// Sets manipulator animation time when centering on mouse wheel up is enabled. void StandardManipulator::setAnimationTime( const double t ) { if( t <= 0. ) { finishAnimation(); _animationData = NULL; return; } if( !_animationData ) allocAnimationData(); _animationData->_animationTime = t; } /// Returns manipulator animation time when centering on mouse wheel up is enabled. double StandardManipulator::getAnimationTime() const { if( _animationData ) return _animationData->_animationTime; else return 0.; } /// Returns whether manipulator is performing animation at the moment. bool StandardManipulator::isAnimating() const { if( _animationData ) return _animationData->_isAnimating; else return false; } /// Finishes the animation by performing a step that moves it to its final position. void StandardManipulator::finishAnimation() { _thrown = false; if( !isAnimating() ) return; applyAnimationStep( 1., _animationData->_phase ); } /** Move the camera to the default position. The user should probably want to use home(GUIEventAdapter&, GUIActionAdapter&) instead to set manipulator to the home position. This method does not trigger any redraw processing or updates continuous update processing. StandardManipulator implementation only updates its internal structures and recomputes its home position if autoComputeHomePosition is set. Descendant classes are expected to update camera position.*/ void StandardManipulator::home( double /*currentTime*/ ) { if( getAutoComputeHomePosition() ) computeHomePosition( NULL, ( _flags & COMPUTE_HOME_USING_BBOX ) != 0 ); _thrown = false; setTransformation( _homeEye, _homeCenter, _homeUp ); flushMouseEventStack(); } /** Move the camera to the default position. If autoComputeHomePosition is on, home position is computed. The computation considers camera fov and model size and positions camera far enough to fit the model to the screen. StandardManipulator implementation only updates its internal data. If home position is expected to be supported by the descendant manipulator, it has to reimplement the method to update manipulator transformation.*/ void StandardManipulator::home( const GUIEventAdapter& /*ea*/, GUIActionAdapter& us ) { if( getAutoComputeHomePosition() ) { const Camera *camera = us.asView() ? us.asView()->getCamera() : NULL; computeHomePosition( camera, ( _flags & COMPUTE_HOME_USING_BBOX ) != 0 ); } _thrown = false; setTransformation( _homeEye, _homeCenter, _homeUp ); us.requestRedraw(); us.requestContinuousUpdate( false ); flushMouseEventStack(); } /** Start/restart the manipulator.*/ void StandardManipulator::init( const GUIEventAdapter& /*ea*/, GUIActionAdapter& us ) { flushMouseEventStack(); // stop animation _thrown = false; us.requestContinuousUpdate(false); } /** Handles events. Returns true if handled, false otherwise.*/ bool StandardManipulator::handle( const GUIEventAdapter& ea, GUIActionAdapter& us ) { switch( ea.getEventType() ) { case GUIEventAdapter::FRAME: return handleFrame( ea, us ); case GUIEventAdapter::RESIZE: return handleResize( ea, us ); default: break; } if( ea.getHandled() ) return false; switch( ea.getEventType() ) { case GUIEventAdapter::MOVE: return handleMouseMove( ea, us ); case GUIEventAdapter::DRAG: return handleMouseDrag( ea, us ); case GUIEventAdapter::PUSH: return handleMousePush( ea, us ); case GUIEventAdapter::RELEASE: return handleMouseRelease( ea, us ); case GUIEventAdapter::KEYDOWN: return handleKeyDown( ea, us ); case GUIEventAdapter::KEYUP: return handleKeyUp( ea, us ); case GUIEventAdapter::SCROLL: if( _flags & PROCESS_MOUSE_WHEEL ) return handleMouseWheel( ea, us ); else return false; default: return false; } } /// Handles GUIEventAdapter::FRAME event. bool StandardManipulator::handleFrame( const GUIEventAdapter& ea, GUIActionAdapter& us ) { double current_frame_time = ea.getTime(); _delta_frame_time = current_frame_time - _last_frame_time; _last_frame_time = current_frame_time; if( _thrown && performMovement() ) { us.requestRedraw(); } if( _animationData && _animationData->_isAnimating ) { performAnimationMovement( ea, us ); } return false; } /// Handles GUIEventAdapter::RESIZE event. bool StandardManipulator::handleResize( const GUIEventAdapter& ea, GUIActionAdapter& us ) { init( ea, us ); us.requestRedraw(); return true; } /// Handles GUIEventAdapter::MOVE event. bool StandardManipulator::handleMouseMove( const GUIEventAdapter& /*ea*/, GUIActionAdapter& /*us*/ ) { return false; } /// Handles GUIEventAdapter::DRAG event. bool StandardManipulator::handleMouseDrag( const GUIEventAdapter& ea, GUIActionAdapter& us ) { addMouseEvent( ea ); if( performMovement() ) us.requestRedraw(); us.requestContinuousUpdate( false ); _thrown = false; return true; } /// Handles GUIEventAdapter::PUSH event. bool StandardManipulator::handleMousePush( const GUIEventAdapter& ea, GUIActionAdapter& us ) { flushMouseEventStack(); addMouseEvent( ea ); if( performMovement() ) us.requestRedraw(); us.requestContinuousUpdate( false ); _thrown = false; return true; } /// Handles GUIEventAdapter::RELEASE event. bool StandardManipulator::handleMouseRelease( const GUIEventAdapter& ea, GUIActionAdapter& us ) { if( ea.getButtonMask() == 0 ) { double timeSinceLastRecordEvent = _ga_t0.valid() ? (ea.getTime() - _ga_t0->getTime()) : DBL_MAX; if( timeSinceLastRecordEvent > 0.02 ) flushMouseEventStack(); if( isMouseMoving() ) { if( performMovement() && _allowThrow ) { us.requestRedraw(); us.requestContinuousUpdate( true ); _thrown = true; } return true; } } flushMouseEventStack(); addMouseEvent( ea ); if( performMovement() ) us.requestRedraw(); us.requestContinuousUpdate( false ); _thrown = false; return true; } /// Handles GUIEventAdapter::KEYDOWN event. bool StandardManipulator::handleKeyDown( const GUIEventAdapter& ea, GUIActionAdapter& us ) { if( ea.getKey() == GUIEventAdapter::KEY_Space ) { flushMouseEventStack(); _thrown = false; home(ea,us); return true; } return false; } /// Handles GUIEventAdapter::KEYUP event. bool StandardManipulator::handleKeyUp( const GUIEventAdapter& /*ea*/, GUIActionAdapter& /*us*/ ) { return false; } /// Handles GUIEventAdapter::SCROLL event. bool StandardManipulator::handleMouseWheel( const GUIEventAdapter& /*ea*/, GUIActionAdapter& /*us*/ ) { return false; } /** Get the keyboard and mouse usage of the manipulator.*/ void StandardManipulator::getUsage( ApplicationUsage& usage ) const { usage.addKeyboardMouseBinding( getManipulatorName() + ": Space", "Reset the viewing position to home" ); } /// Make movement step of manipulator. Returns true if any movement was made. bool StandardManipulator::performMovement() { // return if less then two events have been added if( _ga_t0.get() == NULL || _ga_t1.get() == NULL ) return false; // get delta time double eventTimeDelta = _ga_t0->getTime() - _ga_t1->getTime(); if( eventTimeDelta < 0. ) { OSG_WARN << "Manipulator warning: eventTimeDelta = " << eventTimeDelta << std::endl; eventTimeDelta = 0.; } // get deltaX and deltaY float dx = _ga_t0->getXnormalized() - _ga_t1->getXnormalized(); float dy = _ga_t0->getYnormalized() - _ga_t1->getYnormalized(); // return if there is no movement. if( dx == 0. && dy == 0. ) return false; // call appropriate methods unsigned int buttonMask = _ga_t1->getButtonMask(); if( buttonMask == GUIEventAdapter::LEFT_MOUSE_BUTTON ) { return performMovementLeftMouseButton( eventTimeDelta, dx, dy ); } else if( buttonMask == GUIEventAdapter::MIDDLE_MOUSE_BUTTON || buttonMask == (GUIEventAdapter::LEFT_MOUSE_BUTTON | GUIEventAdapter::RIGHT_MOUSE_BUTTON) ) { return performMovementMiddleMouseButton( eventTimeDelta, dx, dy ); } else if( buttonMask == GUIEventAdapter::RIGHT_MOUSE_BUTTON ) { return performMovementRightMouseButton( eventTimeDelta, dx, dy ); } return false; } /** Make movement step of manipulator. This method implements movement for left mouse button.*/ bool StandardManipulator::performMovementLeftMouseButton( const double /*eventTimeDelta*/, const double /*dx*/, const double /*dy*/ ) { return false; } /** Make movement step of manipulator. This method implements movement for middle mouse button or combination of left and right mouse button pressed together.*/ bool StandardManipulator::performMovementMiddleMouseButton( const double /*eventTimeDelta*/, const double /*dx*/, const double /*dy*/ ) { return false; } /** Make movement step of manipulator. This method implements movement for right mouse button.*/ bool StandardManipulator::performMovementRightMouseButton( const double /*eventTimeDelta*/, const double /*dx*/, const double /*dy*/ ) { return false; } /// The method processes events for manipulation based on relative mouse movement (mouse delta). bool StandardManipulator::handleMouseDeltaMovement( const GUIEventAdapter& ea, GUIActionAdapter& us ) { float dx = ea.getX() - _mouseCenterX; float dy = ea.getY() - _mouseCenterY; if( dx == 0.f && dy == 0.f ) return false; addMouseEvent( ea ); centerMousePointer( ea, us ); return performMouseDeltaMovement( dx, dy ); } /// The method performs manipulator update based on relative mouse movement (mouse delta). bool StandardManipulator::performMouseDeltaMovement( const float /*dx*/, const float /*dy*/ ) { return false; } /// Makes the manipulator progress in its current animation. bool StandardManipulator::performAnimationMovement( const GUIEventAdapter& ea, GUIActionAdapter& us ) { double f = (ea.getTime() - _animationData->_startTime) / _animationData->_animationTime; if( f >= 1. ) { f = 1.; _animationData->_isAnimating = false; if( !_thrown ) us.requestContinuousUpdate( false ); } applyAnimationStep( f, _animationData->_phase ); _animationData->_phase = f; us.requestRedraw(); return _animationData->_isAnimating; } /// Updates manipulator by a single animation step void StandardManipulator::applyAnimationStep( const double /*currentProgress*/, const double /*prevProgress*/ ) { } /// Centers mouse pointer void StandardManipulator::centerMousePointer( const GUIEventAdapter& ea, GUIActionAdapter& us ) { _mouseCenterX = (ea.getXmin() + ea.getXmax()) / 2.0f; _mouseCenterY = (ea.getYmin() + ea.getYmax()) / 2.0f; us.requestWarpPointer( _mouseCenterX, _mouseCenterY ); } /** Add the current mouse GUIEvent to internal stack.*/ void StandardManipulator::addMouseEvent( const GUIEventAdapter& ea ) { _ga_t1 = _ga_t0; _ga_t0 = &ea; } /** Reset the internal GUIEvent stack.*/ void StandardManipulator::flushMouseEventStack() { _ga_t1 = NULL; _ga_t0 = NULL; } /** Check the speed at which the mouse is moving. If speed is below a threshold then return false, otherwise return true.*/ bool StandardManipulator::isMouseMoving() const { if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false; static const float velocity = 0.1f; float dx = _ga_t0->getXnormalized()-_ga_t1->getXnormalized(); float dy = _ga_t0->getYnormalized()-_ga_t1->getYnormalized(); float len = sqrtf(dx*dx+dy*dy); float dt = _ga_t0->getTime()-_ga_t1->getTime(); return (len>dt*velocity); } /** Set the 'allow throw' flag. If it is set to true (default), releasing the mouse button while moving the mouse results in a throw. If manipulator was thrown, it continues spinning although no mouse button is down at the moment.*/ void StandardManipulator::setAllowThrow( bool allowThrow ) { _allowThrow = allowThrow; } /** Returns the scale that should be applied on animation of "thrown" manipulator state to avoid its dependency on varying frame rate. eventTimeDelta parameter gives the time difference between last two events that started the animation.*/ float StandardManipulator::getThrowScale( const double eventTimeDelta ) const { if( _thrown ) { if (eventTimeDelta == 0.f) return 0.f; return float( _delta_frame_time / eventTimeDelta ); } else return 1.f; } /** Update rotation by yaw and pitch. * * localUp parameter defines either camera's "UP" vector * that will be preserved during rotation, or it can be zero (0,0,0) to specify * that camera's "UP" vector will be not preserved and free rotation will be made.*/ void StandardManipulator::rotateYawPitch( Quat& rotation, const double yaw, const double pitch, const Vec3d& localUp ) { bool verticalAxisFixed = (localUp != Vec3d( 0.,0.,0. )); // fix current rotation if( verticalAxisFixed ) fixVerticalAxis( rotation, localUp, true ); // rotations Quat rotateYaw( -yaw, verticalAxisFixed ? localUp : rotation * Vec3d( 0.,1.,0. ) ); Quat rotatePitch; Quat newRotation; Vec3d cameraRight( rotation * Vec3d( 1.,0.,0. ) ); double my_dy = pitch; int i = 0; do { // rotations rotatePitch.makeRotate( my_dy, cameraRight ); newRotation = rotation * rotateYaw * rotatePitch; // update vertical axis if( verticalAxisFixed ) fixVerticalAxis( newRotation, localUp, false ); // check for viewer's up vector to be more than 90 degrees from "up" axis Vec3d newCameraUp = newRotation * Vec3d( 0.,1.,0. ); if( newCameraUp * localUp > 0. ) { // apply new rotation rotation = newRotation; return; } my_dy /= 2.; if( ++i == 20 ) { rotation = rotation * rotateYaw; return; } } while( true ); } /** The method corrects the rotation to make impression of fixed up direction. * Technically said, it makes the roll component of the rotation equal to zero. * * Up vector is given by CoordinateFrame and it is +z by default. * It can be changed by osgGA::CameraManipulator::setCoordinateFrameCallback(). * * Eye parameter is user position, rotation is the rotation to be fixed, and * disallowFlipOver, when set on true, avoids pitch rotation component to grow * over +/- 90 degrees. If this happens and disallowFlipOver is true, * manipulator is rotated by 180 degrees. More precisely, roll rotation component is changed by 180 degrees, * making pitch once again between -90..+90 degrees limits.*/ void StandardManipulator::fixVerticalAxis( Vec3d& eye, Quat& rotation, bool disallowFlipOver ) { CoordinateFrame coordinateFrame = getCoordinateFrame( eye ); Vec3d localUp = getUpVector( coordinateFrame ); fixVerticalAxis( rotation, localUp, disallowFlipOver ); } /** The method corrects the rotation to make impression of fixed up direction. * Technically said, it makes the roll component of the rotation equal to zero. * * rotation parameter is the rotation to be fixed. * localUp is UP vector and must not be zero length. * disallowFlipOver, when set on true, avoids pitch rotation component to grow * over +/- 90 degrees. If this happens and disallowFlipOver is true, * manipulator is rotated by 180 degrees. More precisely, roll rotation component is changed by 180 degrees, * making pitch once again between -90..+90 degrees limits.*/ void StandardManipulator::fixVerticalAxis( Quat& rotation, const Vec3d& localUp, bool disallowFlipOver ) { // camera direction vectors Vec3d cameraUp = rotation * Vec3d( 0.,1.,0. ); Vec3d cameraRight = rotation * Vec3d( 1.,0.,0. ); Vec3d cameraForward = rotation * Vec3d( 0.,0.,-1. ); // computed directions Vec3d newCameraRight1 = cameraForward ^ localUp; Vec3d newCameraRight2 = cameraUp ^ localUp; Vec3d newCameraRight = (newCameraRight1.length2() > newCameraRight2.length2()) ? newCameraRight1 : newCameraRight2; if( newCameraRight * cameraRight < 0. ) newCameraRight = -newCameraRight; // vertical axis correction Quat rotationVerticalAxisCorrection; rotationVerticalAxisCorrection.makeRotate( cameraRight, newCameraRight ); // rotate camera rotation *= rotationVerticalAxisCorrection; if( disallowFlipOver ) { // make viewer's up vector to be always less than 90 degrees from "up" axis Vec3d newCameraUp = newCameraRight ^ cameraForward; if( newCameraUp * localUp < 0. ) rotation = Quat( PI, Vec3d( 0.,0.,1. ) ) * rotation; } } /** The method corrects the rotation to make impression of fixed up direction. * Technically said, it makes the roll component of the rotation equal to zero. * * forward and up parameters are the forward and up vectors of the manipulator. * newUp will receive corrected UP manipulator vector. localUp is UP vector * that is used for vertical correction. * disallowFlipOver when set on true avoids pitch rotation component to grow * over +/- 90 degrees. If this happens and disallowFlipOver is true, * right and up camera vectors are negated (changing roll by 180 degrees), * making pitch once again between -90..+90 degrees limits.*/ void StandardManipulator::fixVerticalAxis( const osg::Vec3d& forward, const osg::Vec3d& up, osg::Vec3d& newUp, const osg::Vec3d& localUp, bool /*disallowFlipOver*/ ) { // right direction osg::Vec3d right1 = forward ^ localUp; osg::Vec3d right2 = up ^ localUp; osg::Vec3d right = (right1.length2() > right2.length2()) ? right1 : right2; // updatedUp osg::Vec3d updatedUp = right ^ forward; if( updatedUp.normalize() >= 0. ) // return updatedUp newUp = updatedUp; else { // return original up OSG_WARN << "StandardManipulator::fixVerticalAxis warning: Can not update vertical axis." << std::endl; newUp = up; } } /** The method sends a ray into the scene and the point of the closest intersection is used to set a new center for the manipulator. For Orbit-style manipulators, the orbiting center is set. For FirstPerson-style manipulators, view is pointed towards the center.*/ bool StandardManipulator::setCenterByMousePointerIntersection( const GUIEventAdapter& ea, GUIActionAdapter& us ) { osg::View* view = us.asView(); if( !view ) return false; Camera *camera = view->getCamera(); if( !camera ) return false; // prepare variables float x = ( ea.getX() - ea.getXmin() ) / ( ea.getXmax() - ea.getXmin() ); float y = ( ea.getY() - ea.getYmin() ) / ( ea.getYmax() - ea.getYmin() ); LineSegmentIntersector::CoordinateFrame cf; Viewport *vp = camera->getViewport(); if( vp ) { cf = Intersector::WINDOW; x *= vp->width(); y *= vp->height(); } else cf = Intersector::PROJECTION; // perform intersection computation ref_ptr< LineSegmentIntersector > picker = new LineSegmentIntersector( cf, x, y ); IntersectionVisitor iv( picker.get() ); camera->accept( iv ); // return on no intersections if( !picker->containsIntersections() ) return false; // get all intersections LineSegmentIntersector::Intersections& intersections = picker->getIntersections(); // get current transformation osg::Vec3d eye, oldCenter, up; getTransformation( eye, oldCenter, up ); // new center osg::Vec3d newCenter = (*intersections.begin()).getWorldIntersectPoint(); // make vertical axis correction if( getVerticalAxisFixed() ) { CoordinateFrame coordinateFrame = getCoordinateFrame( newCenter ); Vec3d localUp = getUpVector( coordinateFrame ); fixVerticalAxis( newCenter - eye, up, up, localUp, true ); } // set the new center setTransformation( eye, newCenter, up ); // warp pointer // note: this works for me on standard camera on GraphicsWindowEmbedded and Qt, // while it was necessary to implement requestWarpPointer like follows: // // void QOSGWidget::requestWarpPointer( float x, float y ) // { // osgViewer::Viewer::requestWarpPointer( x, y ); // QCursor::setPos( this->mapToGlobal( QPoint( int( x+.5f ), int( y+.5f ) ) ) ); // } // // Additions of .5f are just for the purpose of rounding. centerMousePointer( ea, us ); return true; } /** Makes mouse pointer intersection test with the geometry bellow the pointer and starts animation to center camera to look at the closest hit bellow the mouse pointer. If there is a hit, animation is started and true is returned. Otherwise, the method returns false.*/ bool StandardManipulator::startAnimationByMousePointerIntersection( const osgGA::GUIEventAdapter& /*ea*/, osgGA::GUIActionAdapter& /*us*/ ) { return false; } StandardManipulator::AnimationData::AnimationData() :_isAnimating( false ) { } void StandardManipulator::AnimationData::start( const double startTime ) { _isAnimating = true; _startTime = startTime; _phase = 0.; } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/GUIEventHandler.cpp0000644000175000017500000000342111732410624024442 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include using namespace osgGA; void GUIEventHandler::operator()(osg::Node* node, osg::NodeVisitor* nv) { osgGA::EventVisitor* ev = dynamic_cast(nv); if (ev && ev->getActionAdapter() && !ev->getEvents().empty()) { for(osgGA::EventQueue::Events::iterator itr = ev->getEvents().begin(); itr != ev->getEvents().end(); ++itr) { handleWithCheckAgainstIgnoreHandledEventsMask(*(*itr), *(ev->getActionAdapter()), node, nv); } } if (node->getNumChildrenRequiringEventTraversal()>0 || _nestedCallback.valid()) traverse(node,nv); } void GUIEventHandler::event(osg::NodeVisitor* nv, osg::Drawable* drawable) { osgGA::EventVisitor* ev = dynamic_cast(nv); if (ev && ev->getActionAdapter() && !ev->getEvents().empty()) { for(osgGA::EventQueue::Events::iterator itr = ev->getEvents().begin(); itr != ev->getEvents().end(); ++itr) { handleWithCheckAgainstIgnoreHandledEventsMask(*(*itr), *(ev->getActionAdapter()), drawable, nv); } } } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/StateSetManipulator.cpp0000644000175000017500000001747311732410624025502 0ustar albertoalberto#include #include #include #include #include #include #include // #define COMPILE_TEXENVFILTER_USAGE #if COMPILE_TEXENVFILTER_USAGE #include #endif using namespace osg; using namespace osgGA; StateSetManipulator::StateSetManipulator(osg::StateSet* stateset): _initialized(false), _backface(false), _lighting(false), _texture(false), _maxNumOfTextureUnits(4), _keyEventToggleBackfaceCulling('b'), _keyEventToggleLighting('l'), _keyEventToggleTexturing('t'), _keyEventCyclePolygonMode('w') { setStateSet(stateset); } StateSetManipulator::~StateSetManipulator() { } void StateSetManipulator::setStateSet(StateSet *stateset) { _stateset = stateset; #if 0 // specify that this stateset is dynamic so it prevents // the draw and update phase from overlapping - good for // stability but breaks all the performance advantage of // DrawThreadPerContex. _stateset->setDataVariance(osg::Object::DYNAMIC); #endif } StateSet *StateSetManipulator::getStateSet() { return _stateset.get(); } const StateSet *StateSetManipulator::getStateSet() const { return _stateset.get(); } void StateSetManipulator::clone() { if (!_stateset) return; // we clone the StateSet so that any draw traversals that might be running at the time of the // event traversal won't change the same StateSet that is being read. One could just set the // DataVariance to DYNAMIC to avoid this overlap, but this would introduce a performance penalty. StateSet::ParentList parents = _stateset->getParents(); osg::ref_ptr newStateSet = dynamic_cast(_stateset->clone(osg::CopyOp::SHALLOW_COPY)); // change the parents of the original StateSet to point to the new stateset for(StateSet::ParentList::iterator itr = parents.begin(); itr != parents.end(); ++itr) { osg::Object* object = *itr; osg::Node* node = dynamic_cast(object); if (node) node->setStateSet(newStateSet.get()); else { osg::Drawable* drawable = dynamic_cast(object); if (drawable) drawable->setStateSet(newStateSet.get()); } } _stateset = newStateSet; } bool StateSetManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& aa) { if(!_stateset.valid()) return false; if (!_initialized) { _initialized = true; _backface = (_stateset->getMode(GL_CULL_FACE)&osg::StateAttribute::ON); _lighting =(_stateset->getMode(GL_LIGHTING)&osg::StateAttribute::ON); unsigned int mode = osg::StateAttribute::INHERIT|osg::StateAttribute::ON; _texture = (_stateset->getTextureMode(0,GL_TEXTURE_2D)&mode)!=0 || (_stateset->getTextureMode(0,GL_TEXTURE_3D)&mode)!=0 || (_stateset->getTextureMode(0,GL_TEXTURE_RECTANGLE)&mode)!=0 || (_stateset->getTextureMode(0,GL_TEXTURE_CUBE_MAP)&mode)!=0; #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) _texture |= ((_stateset->getTextureMode(0,GL_TEXTURE_1D)&mode)!=0); #endif } if (ea.getHandled()) return false; if (ea.getEventType()==osgGA::GUIEventAdapter::KEYDOWN) { if ( ea.getKey() == _keyEventToggleBackfaceCulling ) { setBackfaceEnabled(!getBackfaceEnabled()); aa.requestRedraw(); return true; } if ( ea.getKey() == _keyEventToggleLighting ) { setLightingEnabled(!getLightingEnabled()); aa.requestRedraw(); return true; } if ( ea.getKey() == _keyEventToggleTexturing ) { setTextureEnabled(!getTextureEnabled()); aa.requestRedraw(); return true; } if ( ea.getKey() == _keyEventCyclePolygonMode ) { cyclePolygonMode(); aa.requestRedraw(); return true; } } return false; } void StateSetManipulator::getUsage(osg::ApplicationUsage& usage) const { usage.addKeyboardMouseBinding(reinterpret_cast(&_keyEventToggleBackfaceCulling),"Toggle backface culling"); usage.addKeyboardMouseBinding(reinterpret_cast(&_keyEventToggleLighting),"Toggle lighting"); usage.addKeyboardMouseBinding(reinterpret_cast(&_keyEventToggleTexturing),"Toggle texturing"); usage.addKeyboardMouseBinding(reinterpret_cast(&_keyEventCyclePolygonMode),"Toggle polygon fill mode between fill, line (wire frame) and points"); } void StateSetManipulator::setBackfaceEnabled(bool newbackface) { if (_backface == newbackface) return; clone(); _backface = newbackface; if( _backface ) _stateset->setMode(GL_CULL_FACE,osg::StateAttribute::ON); else _stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF); } void StateSetManipulator::setLightingEnabled(bool newlighting) { if (_lighting == newlighting) return; clone(); _lighting = newlighting; if( _lighting ) _stateset->setMode(GL_LIGHTING,osg::StateAttribute::ON); else _stateset->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF); } void StateSetManipulator::setTextureEnabled(bool newtexture) { if (_texture==newtexture) return; clone(); _texture = newtexture; // osg::ref_ptr< osg::Texture > tex = dynamic_cast // ( _stateset->getAttribute( osg::StateAttribute::TEXTURE ) ); // cout << tex->numTextureUnits() << endl; unsigned int mode = osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF; if ( _texture ) mode = osg::StateAttribute::INHERIT|osg::StateAttribute::ON; for( unsigned int ii=0; ii<_maxNumOfTextureUnits; ii++ ) { #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) _stateset->setTextureMode( ii, GL_TEXTURE_1D, mode ); #endif _stateset->setTextureMode( ii, GL_TEXTURE_2D, mode ); _stateset->setTextureMode( ii, GL_TEXTURE_3D, mode ); _stateset->setTextureMode( ii, GL_TEXTURE_RECTANGLE, mode ); _stateset->setTextureMode( ii, GL_TEXTURE_CUBE_MAP, mode); } } void StateSetManipulator::setPolygonMode(osg::PolygonMode::Mode newpolygonmode) { clone(); osg::PolygonMode* polyModeObj = getOrCreatePolygonMode(); polyModeObj->setMode(osg::PolygonMode::FRONT_AND_BACK,newpolygonmode); } void StateSetManipulator::cyclePolygonMode() { clone(); osg::PolygonMode* polyModeObj = getOrCreatePolygonMode(); osg::PolygonMode::Mode currentMode = getPolygonMode(); // cycle through the available modes. switch(currentMode) { case osg::PolygonMode::FILL : polyModeObj->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE); break; case osg::PolygonMode::LINE : polyModeObj->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::POINT); break; case osg::PolygonMode::POINT : polyModeObj->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::FILL); break; } } osg::PolygonMode::Mode StateSetManipulator::getPolygonMode() const { osg::PolygonMode* polyModeObj = dynamic_cast(_stateset->getAttribute(osg::StateAttribute::POLYGONMODE)); if (polyModeObj) return polyModeObj->getMode(osg::PolygonMode::FRONT_AND_BACK); else return osg::PolygonMode::FILL; } osg::PolygonMode* StateSetManipulator::getOrCreatePolygonMode() { osg::PolygonMode* polyModeObj = dynamic_cast(_stateset->getAttribute(osg::StateAttribute::POLYGONMODE)); if (!polyModeObj) { polyModeObj = new osg::PolygonMode; _stateset->setAttribute(polyModeObj); } return polyModeObj; } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/Device.cpp0000644000175000017500000000234412163275353022727 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include using namespace osgGA; Device::Device() : osg::Object() , _capabilities(UNKNOWN) { setEventQueue(new EventQueue); } Device::Device(const Device& es, const osg::CopyOp& copyop): osg::Object(es,copyop) { setEventQueue(new EventQueue); } void Device::sendEvent(const GUIEventAdapter& /*event*/) { OSG_WARN << "Device::sendEvent not implemented!" << std::endl; } void Device::sendEvents(const EventQueue::Events& events) { for(EventQueue::Events::const_iterator i = events.begin(); i != events.end(); i++) { sendEvent(**i); } } Device::~Device() { } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/TrackballManipulator.cpp0000644000175000017500000000201312163275353025634 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include using namespace osg; using namespace osgGA; /// Constructor. TrackballManipulator::TrackballManipulator( int flags ) : inherited( flags ) { setVerticalAxisFixed( false ); } /// Constructor. TrackballManipulator::TrackballManipulator( const TrackballManipulator& tm, const CopyOp& copyOp ) : osg::Object(tm, copyOp), inherited( tm, copyOp ) { } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/CameraViewSwitchManipulator.cpp0000644000175000017500000000600211732410624027135 0ustar albertoalberto#include #include #include #include using namespace osg; using namespace osgGA; class CollectCameraViewsNodeVisitor : public osg::NodeVisitor { public: CollectCameraViewsNodeVisitor(CameraViewSwitchManipulator::CameraViewList* cameraViews): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _cameraViews(cameraViews) {} virtual void apply(CameraView& node) { _cameraViews->push_back(&node); } CameraViewSwitchManipulator::CameraViewList* _cameraViews; }; void CameraViewSwitchManipulator::setNode(osg::Node* node) { _node = node; _cameraViews.clear(); CollectCameraViewsNodeVisitor visitor(&_cameraViews); _node->accept(visitor); } void CameraViewSwitchManipulator::getUsage(osg::ApplicationUsage& usage) const { usage.addKeyboardMouseBinding("CameraViewSwitcher: [","Decrease current camera number"); usage.addKeyboardMouseBinding("CameraViewSwitcher: ]","Increase current camera number"); } bool CameraViewSwitchManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter&) { if (ea.getHandled()) return false; switch(ea.getEventType()) { case(GUIEventAdapter::KEYDOWN): if (ea.getKey()=='[') { if (_currentView == 0) _currentView = _cameraViews.size()-1; else _currentView--; return true; } else if (ea.getKey()==']') { _currentView++; if (_currentView >= _cameraViews.size()) _currentView = 0; return true; } return false; default: return false; } } osg::Matrixd CameraViewSwitchManipulator::getMatrix() const { osg::Matrix mat; if (_currentView < _cameraViews.size()) { NodePathList parentNodePaths = _cameraViews[_currentView]->getParentalNodePaths(); if (!parentNodePaths.empty()) { mat = osg::computeLocalToWorld(parentNodePaths[0]); // TODO take into account the position and attitude of the CameraView } else { OSG_NOTICE<<"CameraViewSwitchManipulator::getMatrix(): Unable to calculate matrix due to empty parental path."<getParentalNodePaths(); if (!parentNodePaths.empty()) { mat = osg::computeWorldToLocal(parentNodePaths[0]); // TODO take into account the position and attitude of the CameraView } else { OSG_NOTICE<<"CameraViewSwitchManipulator::getInverseMatrix(): Unable to calculate matrix due to empty parental path."< using namespace osgGA; osg::ref_ptr& GUIEventAdapter::getAccumulatedEventState() { static osg::ref_ptr s_eventState = new GUIEventAdapter; return s_eventState; } GUIEventAdapter::GUIEventAdapter(): _handled(false), _eventType(NONE), _time(0.0), _windowX(0), _windowY(0), _windowWidth(1280), _windowHeight(1024), _key(0), _unmodifiedKey(0), _button(0), _Xmin(-1.0), _Xmax(1.0), _Ymin(-1.0), _Ymax(1.0), _mx(0.0), _my(0.0), _buttonMask(0), _modKeyMask(0), _mouseYOrientation(Y_INCREASING_DOWNWARDS), _scrolling(), _tabletPen(), _touchData(NULL) {} GUIEventAdapter::GUIEventAdapter(const GUIEventAdapter& rhs,const osg::CopyOp& copyop): osg::Object(rhs,copyop), _handled(rhs._handled), _eventType(rhs._eventType), _time(rhs._time), _context(rhs._context), _windowX(rhs._windowX), _windowY(rhs._windowY), _windowWidth(rhs._windowWidth), _windowHeight(rhs._windowHeight), _key(rhs._key), _unmodifiedKey(rhs._unmodifiedKey), _button(rhs._button), _Xmin(rhs._Xmin), _Xmax(rhs._Xmax), _Ymin(rhs._Ymin), _Ymax(rhs._Ymax), _mx(rhs._mx), _my(rhs._my), _buttonMask(rhs._buttonMask), _modKeyMask(rhs._modKeyMask), _mouseYOrientation(rhs._mouseYOrientation), _scrolling(rhs._scrolling), _tabletPen(rhs._tabletPen), _touchData(rhs._touchData) {} GUIEventAdapter::~GUIEventAdapter() { } void GUIEventAdapter::setWindowRectangle(int x, int y, int width, int height, bool updateMouseRange) { _windowX = x; _windowY = y; _windowWidth = width; _windowHeight = height; if (updateMouseRange) { setInputRange(0, 0, width, height); } } void GUIEventAdapter::setInputRange(float Xmin, float Ymin, float Xmax, float Ymax) { _Xmin = Xmin; _Ymin = Ymin; _Xmax = Xmax; _Ymax = Ymax; } const osg::Matrix GUIEventAdapter::getPenOrientation() const { float xRad = osg::DegreesToRadians ( getPenTiltY() ); float yRad = osg::DegreesToRadians ( getPenTiltX() ); float zRad = osg::DegreesToRadians ( getPenRotation() ); osg::Matrix xrot = osg::Matrix::rotate ( xRad, osg::Vec3f(1.0f, 0.0f, 0.0f) ); osg::Matrix yrot = osg::Matrix::rotate ( yRad, osg::Vec3f(0.0f, 0.0f, 1.0f) ); osg::Matrix zrot = osg::Matrix::rotate ( zRad, osg::Vec3f(0.0f, 1.0f, 0.0f) ); return ( zrot * yrot * xrot ); } void GUIEventAdapter::addTouchPoint(unsigned int id, TouchPhase phase, float x, float y, unsigned int tapCount) { if (!_touchData.valid()) { _touchData = new TouchData(); setX(x); setY(y); } _touchData->addTouchPoint(id, phase, x, y, tapCount); } void GUIEventAdapter::copyPointerDataFrom(const osgGA::GUIEventAdapter& sourceEvent) { setGraphicsContext(const_cast(sourceEvent.getGraphicsContext())); setX(sourceEvent.getX()); setY(sourceEvent.getY()); setInputRange(sourceEvent.getXmin(), sourceEvent.getYmin(), sourceEvent.getXmax(), sourceEvent.getYmax()); setButtonMask(sourceEvent.getButtonMask()); setMouseYOrientation(sourceEvent.getMouseYOrientation()); setPointerDataList(sourceEvent.getPointerDataList()); } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/EventVisitor.cpp0000644000175000017500000000230711732410624024161 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include using namespace osg; using namespace osgGA; EventVisitor::EventVisitor() : NodeVisitor(EVENT_VISITOR,TRAVERSE_ACTIVE_CHILDREN), _handled(false) { } EventVisitor::~EventVisitor() { } void EventVisitor::addEvent(GUIEventAdapter* event) { _events.push_back(event); } void EventVisitor::removeEvent(GUIEventAdapter* event) { EventList::iterator itr = std::find(_events.begin(),_events.end(),event); if (itr!=_events.end()) _events.erase(itr); } void EventVisitor::reset() { _events.clear(); _handled = false; } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/AnimationPathManipulator.cpp0000644000175000017500000001251311732410624026470 0ustar albertoalberto#include #include using namespace osgGA; AnimationPathManipulator::AnimationPathManipulator(osg::AnimationPath* animationPath) { _printOutTimingInfo = true; _animationPath = animationPath; _timeOffset = 0.0; _timeScale = 1.0; _isPaused = false; _realStartOfTimedPeriod = 0.0; _animStartOfTimedPeriod = 0.0; _numOfFramesSinceStartOfTimedPeriod = -1; // need to init. } AnimationPathManipulator::AnimationPathManipulator( const std::string& filename ) { _printOutTimingInfo = true; _animationPath = new osg::AnimationPath; _animationPath->setLoopMode(osg::AnimationPath::LOOP); _timeOffset = 0.0; _timeScale = 1.0; _isPaused = false; osgDB::ifstream in(filename.c_str()); if (!in) { OSG_WARN << "AnimationPathManipulator: Cannot open animation path file \"" << filename << "\".\n"; _valid = false; return; } _animationPath->read(in); in.close(); } void AnimationPathManipulator::home(double currentTime) { if (_animationPath.valid()) { _timeOffset = _animationPath->getFirstTime()-currentTime; } // reset the timing of the animation. _numOfFramesSinceStartOfTimedPeriod=-1; } void AnimationPathManipulator::home(const GUIEventAdapter& ea,GUIActionAdapter&) { home(ea.getTime()); } void AnimationPathManipulator::init(const GUIEventAdapter& ea,GUIActionAdapter& aa) { home(ea,aa); } bool AnimationPathManipulator::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us) { if( !valid() ) return false; switch( ea.getEventType() ) { case GUIEventAdapter::FRAME: if( _isPaused ) { handleFrame( _pauseTime ); } else { handleFrame( ea.getTime() ); } return false; case GUIEventAdapter::KEYDOWN: if (ea.getKey()==' ') { _isPaused = false; home(ea,us); us.requestRedraw(); us.requestContinuousUpdate(false); return true; } else if (ea.getKey()==')') { double time = _isPaused ? _pauseTime : ea.getTime(); double animationTime = (time+_timeOffset)*_timeScale; _timeScale *= 1.1; OSG_NOTICE<<"Animation speed = "<<_timeScale*100<<"%"<getInterpolatedControlPoint( animTime, cp ); if (_numOfFramesSinceStartOfTimedPeriod==-1) { _realStartOfTimedPeriod = time; _animStartOfTimedPeriod = animTime; } ++_numOfFramesSinceStartOfTimedPeriod; double animDelta = (animTime-_animStartOfTimedPeriod); if (animDelta>=_animationPath->getPeriod()) { if (_animationCompletedCallback.valid()) { _animationCompletedCallback->completed(this); } if (_printOutTimingInfo) { double delta = time-_realStartOfTimedPeriod; double frameRate = (double)_numOfFramesSinceStartOfTimedPeriod/delta; OSG_NOTICE <<"AnimatonPath completed in "<getParentalNodePaths(); if (!nodePaths.empty()) { if (nodePaths.size()>1) { OSG_NOTICE<<"osgGA::NodeTrackerManipualtor::setTrackNode(..) taking first parent path, ignoring others."<className()<getName()<<"): Path set"<getBound(); setHomePosition(boundingSphere._center+osg::Vec3d( 0.0,-3.5f * boundingSphere._radius,0.0f), boundingSphere._center, osg::Vec3d(0.0f,0.0f,1.0f), _autoComputeHomePosition); } } void NodeTrackerManipulator::setByMatrix(const osg::Matrixd& matrix) { osg::Vec3d eye,center,up; matrix.getLookAt(eye,center,up,_distance); computePosition(eye,center,up); } void NodeTrackerManipulator::computeNodeWorldToLocal(osg::Matrixd& worldToLocal) const { osg::NodePath nodePath; if (_trackNodePath.getNodePath(nodePath)) { worldToLocal = osg::computeWorldToLocal(nodePath); } } void NodeTrackerManipulator::computeNodeLocalToWorld(osg::Matrixd& localToWorld) const { osg::NodePath nodePath; if (_trackNodePath.getNodePath(nodePath)) { localToWorld = osg::computeLocalToWorld(nodePath); } } void NodeTrackerManipulator::computeNodeCenterAndRotation(osg::Vec3d& nodeCenter, osg::Quat& nodeRotation) const { osg::Matrixd localToWorld, worldToLocal; computeNodeLocalToWorld(localToWorld); computeNodeWorldToLocal(worldToLocal); osg::NodePath nodePath; if (_trackNodePath.getNodePath(nodePath) && !nodePath.empty()) nodeCenter = osg::Vec3d(nodePath.back()->getBound().center())*localToWorld; else nodeCenter = osg::Vec3d(0.0f,0.0f,0.0f)*localToWorld; switch(_trackerMode) { case(NODE_CENTER_AND_AZIM): { CoordinateFrame coordinateFrame = getCoordinateFrame(nodeCenter); osg::Matrixd localToFrame(localToWorld*osg::Matrixd::inverse(coordinateFrame)); double azim = atan2(-localToFrame(0,1),localToFrame(0,0)); osg::Quat nodeRotationRelToFrame, rotationOfFrame; nodeRotationRelToFrame.makeRotate(-azim,0.0,0.0,1.0); rotationOfFrame = coordinateFrame.getRotate(); nodeRotation = nodeRotationRelToFrame*rotationOfFrame; break; } case(NODE_CENTER_AND_ROTATION): { // scale the matrix to get rid of any scales before we extract the rotation. double sx = 1.0/sqrt(localToWorld(0,0)*localToWorld(0,0) + localToWorld(1,0)*localToWorld(1,0) + localToWorld(2,0)*localToWorld(2,0)); double sy = 1.0/sqrt(localToWorld(0,1)*localToWorld(0,1) + localToWorld(1,1)*localToWorld(1,1) + localToWorld(2,1)*localToWorld(2,1)); double sz = 1.0/sqrt(localToWorld(0,2)*localToWorld(0,2) + localToWorld(1,2)*localToWorld(1,2) + localToWorld(2,2)*localToWorld(2,2)); localToWorld = localToWorld*osg::Matrixd::scale(sx,sy,sz); nodeRotation = localToWorld.getRotate(); break; } case(NODE_CENTER): default: { CoordinateFrame coordinateFrame = getCoordinateFrame(nodeCenter); nodeRotation = coordinateFrame.getRotate(); break; } } } osg::Matrixd NodeTrackerManipulator::getMatrix() const { osg::Vec3d nodeCenter; osg::Quat nodeRotation; computeNodeCenterAndRotation(nodeCenter,nodeRotation); return osg::Matrixd::translate(0.0,0.0,_distance)*osg::Matrixd::rotate(_rotation)*osg::Matrixd::rotate(nodeRotation)*osg::Matrix::translate(nodeCenter); } osg::Matrixd NodeTrackerManipulator::getInverseMatrix() const { osg::Vec3d nodeCenter; osg::Quat nodeRotation; computeNodeCenterAndRotation(nodeCenter,nodeRotation); return osg::Matrixd::translate(-nodeCenter)*osg::Matrixd::rotate(nodeRotation.inverse())*osg::Matrixd::rotate(_rotation.inverse())*osg::Matrixd::translate(0.0,0.0,-_distance); } void NodeTrackerManipulator::computePosition(const osg::Vec3d& eye,const osg::Vec3d& center,const osg::Vec3d& up) { if (!_node) return; // compute rotation matrix osg::Vec3d lv(center-eye); _distance = lv.length(); osg::Matrixd lookat; lookat.makeLookAt(eye,center,up); _rotation = lookat.getRotate().inverse(); } // doc in parent bool NodeTrackerManipulator::performMovementLeftMouseButton( const double eventTimeDelta, const double dx, const double dy ) { osg::Vec3d nodeCenter; osg::Quat nodeRotation; computeNodeCenterAndRotation(nodeCenter, nodeRotation); // rotate camera if( getVerticalAxisFixed() ) { osg::Matrix rotation_matrix; rotation_matrix.makeRotate(_rotation); osg::Vec3d sideVector = getSideVector(rotation_matrix); osg::Vec3d localUp(0.0f,0.0f,1.0f); osg::Vec3d forwardVector = localUp^sideVector; sideVector = forwardVector^localUp; forwardVector.normalize(); sideVector.normalize(); osg::Quat rotate_elevation; rotate_elevation.makeRotate(dy,sideVector); osg::Quat rotate_azim; rotate_azim.makeRotate(-dx,localUp); _rotation = _rotation * rotate_elevation * rotate_azim; } else rotateTrackball( _ga_t0->getXnormalized(), _ga_t0->getYnormalized(), _ga_t1->getXnormalized(), _ga_t1->getYnormalized(), getThrowScale( eventTimeDelta ) ); return true; } // doc in parent bool NodeTrackerManipulator::performMovementMiddleMouseButton( const double /*eventTimeDelta*/, const double /*dx*/, const double /*dy*/ ) { osg::Vec3d nodeCenter; osg::Quat nodeRotation; computeNodeCenterAndRotation(nodeCenter, nodeRotation); return true; } // doc in parent bool NodeTrackerManipulator::performMovementRightMouseButton( const double eventTimeDelta, const double dx, const double dy ) { osg::Vec3d nodeCenter; osg::Quat nodeRotation; computeNodeCenterAndRotation(nodeCenter, nodeRotation); return inherited::performMovementRightMouseButton(eventTimeDelta, dx, dy); } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/EventQueue.cpp0000644000175000017500000004562412141015037023611 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include using namespace osgGA; EventQueue::EventQueue(GUIEventAdapter::MouseYOrientation mouseYOrientation) { _useFixedMouseInputRange = false; _startTick = osg::Timer::instance()->getStartTick(); _accumulateEventState = new GUIEventAdapter(); _accumulateEventState->setMouseYOrientation(mouseYOrientation); _firstTouchEmulatesMouse = true; } EventQueue::~EventQueue() { } void EventQueue::clear() { OpenThreads::ScopedLock lock(_eventQueueMutex); _eventQueue.clear(); } void EventQueue::setEvents(Events& events) { OpenThreads::ScopedLock lock(_eventQueueMutex); _eventQueue = events; } void EventQueue::appendEvents(Events& events) { OpenThreads::ScopedLock lock(_eventQueueMutex); _eventQueue.insert(_eventQueue.end(), events.begin(), events.end()); } void EventQueue::addEvent(GUIEventAdapter* event) { OpenThreads::ScopedLock lock(_eventQueueMutex); _eventQueue.push_back(event); } bool EventQueue::takeEvents(Events& events) { OpenThreads::ScopedLock lock(_eventQueueMutex); if (!_eventQueue.empty()) { events.splice(events.end(), _eventQueue); return true; } else { return false; } } bool EventQueue::takeEvents(Events& events, double cutOffTime) { OpenThreads::ScopedLock lock(_eventQueueMutex); if (!_eventQueue.empty()) { // find last event if queue that came in before the cuttof. Events::reverse_iterator ritr = _eventQueue.rbegin(); for(; ritr != _eventQueue.rend() && ((*ritr)->getTime() > cutOffTime); ++ritr) {} if (ritr==_eventQueue.rend()) return false; for(Events::iterator itr = _eventQueue.begin(); itr != ritr.base(); ++itr) { events.push_back(*itr); } // make sure that the events are in ascending time order, and any out of out events // have their time reset to the next valid time after them in the events list. double previousTime = cutOffTime; for(Events::reverse_iterator itr = events.rbegin(); itr != events.rend(); ++itr) { if ((*itr)->getTime() > previousTime) { OSG_INFO<<"Reset event time from "<<(*itr)->getTime()<<" to "<setTime(previousTime); } else { previousTime = (*itr)->getTime(); } } // remove the events we are taking from the original event queue. _eventQueue.erase(_eventQueue.begin(), ritr.base()); return true; } else { return false; } } bool EventQueue::copyEvents(Events& events) const { OpenThreads::ScopedLock lock(_eventQueueMutex); if (!_eventQueue.empty()) { events.insert(events.end(),_eventQueue.begin(),_eventQueue.end()); return true; } else { return false; } } void EventQueue::syncWindowRectangleWithGraphcisContext() { const osg::GraphicsContext::Traits* traits = (getGraphicsContext()!=0) ? getGraphicsContext()->getTraits() : 0; if (traits) _accumulateEventState->setWindowRectangle(traits->x, traits->y, traits->width, traits->height, !_useFixedMouseInputRange); } void EventQueue::windowResize(int x, int y, int width, int height, double time) { _accumulateEventState->setWindowRectangle(x, y, width, height, !_useFixedMouseInputRange); GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::RESIZE); event->setTime(time); addEvent(event); } void EventQueue::penPressure(float pressure, double time) { GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::PEN_PRESSURE); event->setPenPressure(pressure); event->setTime(time); addEvent(event); } void EventQueue::penOrientation(float tiltX, float tiltY, float rotation, double time) { GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::PEN_ORIENTATION); event->setPenTiltX(tiltX); event->setPenTiltY(tiltY); event->setPenRotation(rotation); event->setTime(time); addEvent(event); } void EventQueue::penProximity(GUIEventAdapter::TabletPointerType pt, bool isEntering, double time) { GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType( (isEntering) ? GUIEventAdapter::PEN_PROXIMITY_ENTER : GUIEventAdapter::PEN_PROXIMITY_LEAVE); event->setTabletPointerType(pt); event->setTime(time); addEvent(event); } void EventQueue::mouseScroll(GUIEventAdapter::ScrollingMotion sm, double time) { GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::SCROLL); event->setScrollingMotion(sm); event->setTime(time); addEvent(event); } void EventQueue::mouseScroll2D(float x, float y, double time) { GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::SCROLL); event->setScrollingMotionDelta(x,y); event->setTime(time); addEvent(event); } void EventQueue::mouseWarped(float x, float y) { _accumulateEventState->setX(x); _accumulateEventState->setY(y); } void EventQueue::mouseMotion(float x, float y, double time) { _accumulateEventState->setX(x); _accumulateEventState->setY(y); GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(event->getButtonMask() ? GUIEventAdapter::DRAG : GUIEventAdapter::MOVE); event->setTime(time); addEvent(event); } void EventQueue::mouseButtonPress(float x, float y, unsigned int button, double time) { _accumulateEventState->setX(x); _accumulateEventState->setY(y); switch(button) { case(1): _accumulateEventState->setButtonMask(GUIEventAdapter::LEFT_MOUSE_BUTTON | _accumulateEventState->getButtonMask()); break; case(2): _accumulateEventState->setButtonMask(GUIEventAdapter::MIDDLE_MOUSE_BUTTON | _accumulateEventState->getButtonMask()); break; case(3): _accumulateEventState->setButtonMask(GUIEventAdapter::RIGHT_MOUSE_BUTTON | _accumulateEventState->getButtonMask()); break; } GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::PUSH); event->setTime(time); switch(button) { case(1): event->setButton(GUIEventAdapter::LEFT_MOUSE_BUTTON); break; case(2): event->setButton(GUIEventAdapter::MIDDLE_MOUSE_BUTTON); break; case(3): event->setButton(GUIEventAdapter::RIGHT_MOUSE_BUTTON); break; } addEvent(event); } void EventQueue::mouseDoubleButtonPress(float x, float y, unsigned int button, double time) { _accumulateEventState->setX(x); _accumulateEventState->setY(y); switch(button) { case(1): _accumulateEventState->setButtonMask(GUIEventAdapter::LEFT_MOUSE_BUTTON | _accumulateEventState->getButtonMask()); break; case(2): _accumulateEventState->setButtonMask(GUIEventAdapter::MIDDLE_MOUSE_BUTTON | _accumulateEventState->getButtonMask()); break; case(3): _accumulateEventState->setButtonMask(GUIEventAdapter::RIGHT_MOUSE_BUTTON | _accumulateEventState->getButtonMask()); break; } GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::DOUBLECLICK); event->setTime(time); switch(button) { case(1): event->setButton(GUIEventAdapter::LEFT_MOUSE_BUTTON); break; case(2): event->setButton(GUIEventAdapter::MIDDLE_MOUSE_BUTTON); break; case(3): event->setButton(GUIEventAdapter::RIGHT_MOUSE_BUTTON); break; } addEvent(event); } void EventQueue::mouseButtonRelease(float x, float y, unsigned int button, double time) { _accumulateEventState->setX(x); _accumulateEventState->setY(y); switch(button) { case(1): _accumulateEventState->setButtonMask(~GUIEventAdapter::LEFT_MOUSE_BUTTON & _accumulateEventState->getButtonMask()); break; case(2): _accumulateEventState->setButtonMask(~GUIEventAdapter::MIDDLE_MOUSE_BUTTON & _accumulateEventState->getButtonMask()); break; case(3): _accumulateEventState->setButtonMask(~GUIEventAdapter::RIGHT_MOUSE_BUTTON & _accumulateEventState->getButtonMask()); break; } GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::RELEASE); event->setTime(time); switch(button) { case(1): event->setButton(GUIEventAdapter::LEFT_MOUSE_BUTTON); break; case(2): event->setButton(GUIEventAdapter::MIDDLE_MOUSE_BUTTON); break; case(3): event->setButton(GUIEventAdapter::RIGHT_MOUSE_BUTTON); break; } addEvent(event); } void EventQueue::keyPress(int key, double time, int unmodifiedKey) { switch(key) { case(GUIEventAdapter::KEY_Shift_L): _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_LEFT_SHIFT | _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Shift_R): _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_RIGHT_SHIFT | _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Control_L): _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_LEFT_CTRL | _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Control_R): _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_RIGHT_CTRL | _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Meta_L): _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_LEFT_META | _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Meta_R): _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_RIGHT_META | _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Alt_L): _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_LEFT_ALT | _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Alt_R): _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_RIGHT_ALT | _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Super_L): _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_LEFT_SUPER | _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Super_R): _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_RIGHT_SUPER | _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Hyper_L): _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_LEFT_HYPER | _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Hyper_R): _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_RIGHT_HYPER | _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Caps_Lock): { if ((_accumulateEventState->getModKeyMask() & GUIEventAdapter::MODKEY_CAPS_LOCK)!=0) _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_CAPS_LOCK & _accumulateEventState->getModKeyMask()); else _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_CAPS_LOCK | _accumulateEventState->getModKeyMask()); break; } case(GUIEventAdapter::KEY_Num_Lock): { if ((_accumulateEventState->getModKeyMask() & GUIEventAdapter::MODKEY_NUM_LOCK)!=0) _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_NUM_LOCK & _accumulateEventState->getModKeyMask()); else _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_NUM_LOCK | _accumulateEventState->getModKeyMask()); break; } default: break; } GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::KEYDOWN); event->setKey(key); event->setUnmodifiedKey(unmodifiedKey); event->setTime(time); addEvent(event); } void EventQueue::keyRelease(int key, double time, int unmodifiedKey) { switch(key) { case(GUIEventAdapter::KEY_Shift_L): _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_LEFT_SHIFT & _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Shift_R): _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_RIGHT_SHIFT & _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Control_L): _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_LEFT_CTRL & _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Control_R): _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_RIGHT_CTRL & _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Meta_L): _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_LEFT_META & _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Meta_R): _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_RIGHT_META & _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Alt_L): _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_LEFT_ALT & _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Alt_R): _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_RIGHT_ALT & _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Super_L): _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_LEFT_SUPER & _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Super_R): _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_RIGHT_SUPER & _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Hyper_L): _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_LEFT_HYPER & _accumulateEventState->getModKeyMask()); break; case(GUIEventAdapter::KEY_Hyper_R): _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_RIGHT_HYPER & _accumulateEventState->getModKeyMask()); break; default: break; } GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::KEYUP); event->setKey(key); event->setUnmodifiedKey(unmodifiedKey); event->setTime(time); addEvent(event); } GUIEventAdapter* EventQueue::touchBegan(unsigned int id, GUIEventAdapter::TouchPhase phase, float x, float y, double time) { if(_firstTouchEmulatesMouse) { // emulate left mouse button press _accumulateEventState->setButtonMask(GUIEventAdapter::LEFT_MOUSE_BUTTON | _accumulateEventState->getButtonMask()); _accumulateEventState->setX(x); _accumulateEventState->setY(y); } GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::PUSH); event->setTime(time); event->addTouchPoint(id, phase, x, y, 0); if(_firstTouchEmulatesMouse) event->setButton(GUIEventAdapter::LEFT_MOUSE_BUTTON); addEvent(event); return event; } GUIEventAdapter* EventQueue::touchMoved(unsigned int id, GUIEventAdapter::TouchPhase phase, float x, float y, double time) { if(_firstTouchEmulatesMouse) { _accumulateEventState->setX(x); _accumulateEventState->setY(y); } GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::DRAG); event->setTime(time); event->addTouchPoint(id, phase, x, y, 0); addEvent(event); return event; } GUIEventAdapter* EventQueue::touchEnded(unsigned int id, GUIEventAdapter::TouchPhase phase, float x, float y, unsigned int tap_count, double time) { if (_firstTouchEmulatesMouse) { _accumulateEventState->setButtonMask(~GUIEventAdapter::LEFT_MOUSE_BUTTON & _accumulateEventState->getButtonMask()); _accumulateEventState->setX(x); _accumulateEventState->setY(y); } GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::RELEASE); event->setTime(time); event->addTouchPoint(id, phase, x, y, tap_count); if(_firstTouchEmulatesMouse) event->setButton(GUIEventAdapter::LEFT_MOUSE_BUTTON); addEvent(event); return event; } void EventQueue::closeWindow(double time) { GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::CLOSE_WINDOW); event->setTime(time); addEvent(event); } void EventQueue::quitApplication(double time) { GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::QUIT_APPLICATION); event->setTime(time); addEvent(event); } void EventQueue::frame(double time) { GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState); event->setEventType(GUIEventAdapter::FRAME); event->setTime(time); // OSG_NOTICE<<"frame("<getX()="<getX()<<", event->getY()="<getY()<<", event->getXmin()="<getXmin()<<", event->getYmin()="<getYmin()<<", event->getXmax()="<getXmax()<<", event->getYmax()="<getYmax()<setEventType(GUIEventAdapter::USER); event->setUserData(userEventData); event->setTime(time); addEvent(event); } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/TerrainManipulator.cpp0000644000175000017500000002253112163275353025350 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include using namespace osg; using namespace osgGA; /// Constructor. TerrainManipulator::TerrainManipulator( int flags ) : inherited( flags ) { } /// Constructor. TerrainManipulator::TerrainManipulator( const TerrainManipulator& tm, const CopyOp& copyOp ) : osg::Object(tm, copyOp), inherited( tm, copyOp ), _previousUp( tm._previousUp ) { } /** Sets the manipulator rotation mode. RotationMode is now deprecated by osgGA::StandardManipulator::setVerticalAxisFixed() functionality, that is used across StandardManipulator derived classes.*/ void TerrainManipulator::setRotationMode( TerrainManipulator::RotationMode mode ) { setVerticalAxisFixed( mode == ELEVATION_AZIM ); } /** Returns the manipulator rotation mode.*/ TerrainManipulator::RotationMode TerrainManipulator::getRotationMode() const { return getVerticalAxisFixed() ? ELEVATION_AZIM : ELEVATION_AZIM_ROLL; } void TerrainManipulator::setNode( Node* node ) { inherited::setNode( node ); // update model size if( _flags & UPDATE_MODEL_SIZE ) { if( _node.valid() ) { setMinimumDistance( clampBetween( _modelSize * 0.001, 0.00001, 1.0 ) ); OSG_INFO << "TerrainManipulator: setting _minimumDistance to " << _minimumDistance << std::endl; } } } void TerrainManipulator::setByMatrix(const Matrixd& matrix) { Vec3d lookVector(- matrix(2,0),-matrix(2,1),-matrix(2,2)); Vec3d eye(matrix(3,0),matrix(3,1),matrix(3,2)); OSG_INFO<<"eye point "<getBound(); float distance = (eye-bs.center()).length() + _node->getBound().radius(); Vec3d start_segment = eye; Vec3d end_segment = eye + lookVector*distance; Vec3d ip; bool hitFound = false; if (intersect(start_segment, end_segment, ip)) { OSG_INFO << "Hit terrain ok A"<< std::endl; _center = ip; _distance = (eye-ip).length(); Matrixd rotation_matrix = Matrixd::translate(0.0,0.0,-_distance)* matrix* Matrixd::translate(-_center); _rotation = rotation_matrix.getRotate(); hitFound = true; } if (!hitFound) { CoordinateFrame eyePointCoordFrame = getCoordinateFrame( eye ); if (intersect(eye+getUpVector(eyePointCoordFrame)*distance, eye-getUpVector(eyePointCoordFrame)*distance, ip)) { _center = ip; _distance = (eye-ip).length(); _rotation.set(0,0,0,1); hitFound = true; } } CoordinateFrame coordinateFrame = getCoordinateFrame(_center); _previousUp = getUpVector(coordinateFrame); clampOrientation(); } void TerrainManipulator::setTransformation( const osg::Vec3d& eye, const osg::Vec3d& center, const osg::Vec3d& up ) { if (!_node) return; // compute rotation matrix Vec3d lv(center-eye); _distance = lv.length(); _center = center; OSG_INFO << "In compute"<< std::endl; if (_node.valid()) { bool hitFound = false; double distance = lv.length(); double maxDistance = distance+2*(eye-_node->getBound().center()).length(); Vec3d farPosition = eye+lv*(maxDistance/distance); Vec3d endPoint = center; for(int i=0; !hitFound && i<2; ++i, endPoint = farPosition) { // compute the intersection with the scene. Vec3d ip; if (intersect(eye, endPoint, ip)) { _center = ip; _distance = (ip-eye).length(); hitFound = true; } } } // note LookAt = inv(CF)*inv(RM)*inv(T) which is equivalent to: // inv(R) = CF*LookAt. Matrixd rotation_matrix = Matrixd::lookAt(eye,center,up); _rotation = rotation_matrix.getRotate().inverse(); CoordinateFrame coordinateFrame = getCoordinateFrame(_center); _previousUp = getUpVector(coordinateFrame); clampOrientation(); } bool TerrainManipulator::intersect( const Vec3d& start, const Vec3d& end, Vec3d& intersection ) const { ref_ptr lsi = new osgUtil::LineSegmentIntersector(start,end); osgUtil::IntersectionVisitor iv(lsi.get()); iv.setTraversalMask(_intersectTraversalMask); _node->accept(iv); if (lsi->containsIntersections()) { intersection = lsi->getIntersections().begin()->getWorldIntersectPoint(); return true; } return false; } bool TerrainManipulator::performMovementMiddleMouseButton( const double eventTimeDelta, const double dx, const double dy ) { // pan model. double scale = -0.3f * _distance * getThrowScale( eventTimeDelta ); Matrixd rotation_matrix; rotation_matrix.makeRotate(_rotation); // compute look vector. Vec3d sideVector = getSideVector(rotation_matrix); // CoordinateFrame coordinateFrame = getCoordinateFrame(_center); // Vec3d localUp = getUpVector(coordinateFrame); Vec3d localUp = _previousUp; Vec3d forwardVector =localUp^sideVector; sideVector = forwardVector^localUp; forwardVector.normalize(); sideVector.normalize(); Vec3d dv = forwardVector * (dy*scale) + sideVector * (dx*scale); _center += dv; // need to recompute the intersection point along the look vector. bool hitFound = false; if (_node.valid()) { // now reorientate the coordinate frame to the frame coords. CoordinateFrame coordinateFrame = getCoordinateFrame(_center); // need to reintersect with the terrain double distance = _node->getBound().radius()*0.25f; Vec3d ip1; Vec3d ip2; bool hit_ip1 = intersect(_center, _center + getUpVector(coordinateFrame) * distance, ip1); bool hit_ip2 = intersect(_center, _center - getUpVector(coordinateFrame) * distance, ip2); if (hit_ip1) { if (hit_ip2) { _center = (_center-ip1).length2() < (_center-ip2).length2() ? ip1 : ip2; hitFound = true; } else { _center = ip1; hitFound = true; } } else if (hit_ip2) { _center = ip2; hitFound = true; } if (!hitFound) { // ?? OSG_INFO<<"TerrainManipulator unable to intersect with terrain."< #include #include using namespace osg; using namespace osgGA; int OrbitManipulator::_minimumDistanceFlagIndex = allocateRelativeFlag(); /// Constructor. OrbitManipulator::OrbitManipulator( int flags ) : inherited( flags ), _distance( 1. ), _trackballSize( 0.8 ) { setMinimumDistance( 0.05, true ); setWheelZoomFactor( 0.1 ); if( _flags & SET_CENTER_ON_WHEEL_FORWARD_MOVEMENT ) setAnimationTime( 0.2 ); } /// Constructor. OrbitManipulator::OrbitManipulator( const OrbitManipulator& om, const CopyOp& copyOp ) : osg::Object(om, copyOp), inherited( om, copyOp ), _center( om._center ), _rotation( om._rotation ), _distance( om._distance ), _trackballSize( om._trackballSize ), _wheelZoomFactor( om._wheelZoomFactor ), _minimumDistance( om._minimumDistance ) { } /** Set the position of the manipulator using a 4x4 matrix.*/ void OrbitManipulator::setByMatrix( const osg::Matrixd& matrix ) { _center = osg::Vec3d( 0., 0., -_distance ) * matrix; _rotation = matrix.getRotate(); // fix current rotation if( getVerticalAxisFixed() ) fixVerticalAxis( _center, _rotation, true ); } /** Set the position of the manipulator using a 4x4 matrix.*/ void OrbitManipulator::setByInverseMatrix( const osg::Matrixd& matrix ) { setByMatrix( osg::Matrixd::inverse( matrix ) ); } /** Get the position of the manipulator as 4x4 matrix.*/ osg::Matrixd OrbitManipulator::getMatrix() const { return osg::Matrixd::translate( 0., 0., _distance ) * osg::Matrixd::rotate( _rotation ) * osg::Matrixd::translate( _center ); } /** Get the position of the manipulator as a inverse matrix of the manipulator, typically used as a model view matrix.*/ osg::Matrixd OrbitManipulator::getInverseMatrix() const { return osg::Matrixd::translate( -_center ) * osg::Matrixd::rotate( _rotation.inverse() ) * osg::Matrixd::translate( 0.0, 0.0, -_distance ); } // doc in parent void OrbitManipulator::setTransformation( const osg::Vec3d& eye, const osg::Quat& rotation ) { _center = eye + rotation * osg::Vec3d( 0., 0., -_distance ); _rotation = rotation; // fix current rotation if( getVerticalAxisFixed() ) fixVerticalAxis( _center, _rotation, true ); } // doc in parent void OrbitManipulator::getTransformation( osg::Vec3d& eye, osg::Quat& rotation ) const { eye = _center - _rotation * osg::Vec3d( 0., 0., -_distance ); rotation = _rotation; } // doc in parent void OrbitManipulator::setTransformation( const osg::Vec3d& eye, const osg::Vec3d& center, const osg::Vec3d& up ) { Vec3d lv( center - eye ); Vec3d f( lv ); f.normalize(); Vec3d s( f^up ); s.normalize(); Vec3d u( s^f ); u.normalize(); osg::Matrixd rotation_matrix( s[0], u[0], -f[0], 0.0f, s[1], u[1], -f[1], 0.0f, s[2], u[2], -f[2], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f ); _center = center; _distance = lv.length(); _rotation = rotation_matrix.getRotate().inverse(); // fix current rotation if( getVerticalAxisFixed() ) fixVerticalAxis( _center, _rotation, true ); } // doc in parent void OrbitManipulator::getTransformation( osg::Vec3d& eye, osg::Vec3d& center, osg::Vec3d& up ) const { center = _center; eye = _center + _rotation * osg::Vec3d( 0., 0., _distance ); up = _rotation * osg::Vec3d( 0., 1., 0. ); } /** Sets the transformation by heading. Heading is given as an angle in radians giving a azimuth in xy plane. Its meaning is similar to longitude used in cartography and navigation. Positive number is going to the east direction.*/ void OrbitManipulator::setHeading( double azimuth ) { CoordinateFrame coordinateFrame = getCoordinateFrame( _center ); Vec3d localUp = getUpVector( coordinateFrame ); Vec3d localRight = getSideVector( coordinateFrame ); Vec3d dir = Quat( getElevation(), localRight ) * Quat( azimuth, localUp ) * Vec3d( 0., -_distance, 0. ); setTransformation( _center + dir, _center, localUp ); } /// Returns the heading in radians. \sa setHeading double OrbitManipulator::getHeading() const { CoordinateFrame coordinateFrame = getCoordinateFrame( _center ); Vec3d localFront = getFrontVector( coordinateFrame ); Vec3d localRight = getSideVector( coordinateFrame ); Vec3d center, eye, tmp; getTransformation( eye, center, tmp ); Plane frontPlane( localFront, center ); double frontDist = frontPlane.distance( eye ); Plane rightPlane( localRight, center ); double rightDist = rightPlane.distance( eye ); return atan2( rightDist, -frontDist ); } /** Sets the transformation by elevation. Elevation is given as an angle in radians from xy plane. Its meaning is similar to latitude used in cartography and navigation. Positive number is going to the north direction, negative to the south.*/ void OrbitManipulator::setElevation( double elevation ) { CoordinateFrame coordinateFrame = getCoordinateFrame( _center ); Vec3d localUp = getUpVector( coordinateFrame ); Vec3d localRight = getSideVector( coordinateFrame ); Vec3d dir = Quat( -elevation, localRight ) * Quat( getHeading(), localUp ) * Vec3d( 0., -_distance, 0. ); setTransformation( _center + dir, _center, localUp ); } /// Returns the elevation in radians. \sa setElevation double OrbitManipulator::getElevation() const { CoordinateFrame coordinateFrame = getCoordinateFrame( _center ); Vec3d localUp = getUpVector( coordinateFrame ); localUp.normalize(); Vec3d center, eye, tmp; getTransformation( eye, center, tmp ); Plane plane( localUp, center ); double dist = plane.distance( eye ); return asin( -dist / (eye-center).length() ); } // doc in parent bool OrbitManipulator::handleMouseWheel( const GUIEventAdapter& ea, GUIActionAdapter& us ) { osgGA::GUIEventAdapter::ScrollingMotion sm = ea.getScrollingMotion(); // handle centering if( _flags & SET_CENTER_ON_WHEEL_FORWARD_MOVEMENT ) { if( ((sm == GUIEventAdapter::SCROLL_DOWN && _wheelZoomFactor > 0.)) || ((sm == GUIEventAdapter::SCROLL_UP && _wheelZoomFactor < 0.)) ) { if( getAnimationTime() <= 0. ) { // center by mouse intersection (no animation) setCenterByMousePointerIntersection( ea, us ); } else { // start new animation only if there is no animation in progress if( !isAnimating() ) startAnimationByMousePointerIntersection( ea, us ); } } } switch( sm ) { // mouse scroll up event case GUIEventAdapter::SCROLL_UP: { // perform zoom zoomModel( _wheelZoomFactor, true ); us.requestRedraw(); us.requestContinuousUpdate( isAnimating() || _thrown ); return true; } // mouse scroll down event case GUIEventAdapter::SCROLL_DOWN: { // perform zoom zoomModel( -_wheelZoomFactor, true ); us.requestRedraw(); us.requestContinuousUpdate( isAnimating() || _thrown ); return true; } // unhandled mouse scrolling motion default: return false; } } // doc in parent bool OrbitManipulator::performMovementLeftMouseButton( const double eventTimeDelta, const double dx, const double dy ) { // rotate camera if( getVerticalAxisFixed() ) rotateWithFixedVertical( dx, dy ); else rotateTrackball( _ga_t0->getXnormalized(), _ga_t0->getYnormalized(), _ga_t1->getXnormalized(), _ga_t1->getYnormalized(), getThrowScale( eventTimeDelta ) ); return true; } // doc in parent bool OrbitManipulator::performMovementMiddleMouseButton( const double eventTimeDelta, const double dx, const double dy ) { // pan model float scale = -0.3f * _distance * getThrowScale( eventTimeDelta ); panModel( dx*scale, dy*scale ); return true; } // doc in parent bool OrbitManipulator::performMovementRightMouseButton( const double eventTimeDelta, const double /*dx*/, const double dy ) { // zoom model zoomModel( dy * getThrowScale( eventTimeDelta ), true ); return true; } bool OrbitManipulator::performMouseDeltaMovement( const float dx, const float dy ) { // rotate camera if( getVerticalAxisFixed() ) rotateWithFixedVertical( dx, dy ); else rotateTrackball( 0.f, 0.f, dx, dy, 1.f ); return true; } void OrbitManipulator::applyAnimationStep( const double currentProgress, const double prevProgress ) { OrbitAnimationData *ad = dynamic_cast< OrbitAnimationData* >( _animationData.get() ); assert( ad ); // compute new center osg::Vec3d prevCenter, prevEye, prevUp; getTransformation( prevEye, prevCenter, prevUp ); osg::Vec3d newCenter = osg::Vec3d(prevCenter) + (ad->_movement * (currentProgress - prevProgress)); // fix vertical axis if( getVerticalAxisFixed() ) { CoordinateFrame coordinateFrame = getCoordinateFrame( newCenter ); Vec3d localUp = getUpVector( coordinateFrame ); fixVerticalAxis( newCenter - prevEye, prevUp, prevUp, localUp, false ); } // apply new transformation setTransformation( prevEye, newCenter, prevUp ); } bool OrbitManipulator::startAnimationByMousePointerIntersection( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us ) { // get current transformation osg::Vec3d prevCenter, prevEye, prevUp; getTransformation( prevEye, prevCenter, prevUp ); // center by mouse intersection if( !setCenterByMousePointerIntersection( ea, us ) ) return false; OrbitAnimationData *ad = dynamic_cast< OrbitAnimationData*>( _animationData.get() ); assert( ad ); // setup animation data and restore original transformation ad->start( osg::Vec3d(_center) - prevCenter, ea.getTime() ); setTransformation( prevEye, prevCenter, prevUp ); return true; } void OrbitManipulator::OrbitAnimationData::start( const osg::Vec3d& movement, const double startTime ) { AnimationData::start( startTime ); _movement = movement; } /** Performs trackball rotation based on two points given, for example, by mouse pointer on the screen. Scale parameter is useful, for example, when manipulator is thrown. It scales the amount of rotation based, for example, on the current frame time.*/ void OrbitManipulator::rotateTrackball( const float px0, const float py0, const float px1, const float py1, const float scale ) { osg::Vec3d axis; float angle; trackball( axis, angle, px0 + (px1-px0)*scale, py0 + (py1-py0)*scale, px0, py0 ); Quat new_rotate; new_rotate.makeRotate( angle, axis ); _rotation = _rotation * new_rotate; } /** Performs rotation horizontally by dx parameter and vertically by dy parameter, while keeping UP vector.*/ void OrbitManipulator::rotateWithFixedVertical( const float dx, const float dy ) { CoordinateFrame coordinateFrame = getCoordinateFrame( _center ); Vec3d localUp = getUpVector( coordinateFrame ); rotateYawPitch( _rotation, dx, dy, localUp ); } /** Performs rotation horizontally by dx parameter and vertically by dy parameter, while keeping UP vector given by up parameter.*/ void OrbitManipulator::rotateWithFixedVertical( const float dx, const float dy, const Vec3f& up ) { rotateYawPitch( _rotation, dx, dy, up ); } /** Moves camera in x,y,z directions given in camera local coordinates.*/ void OrbitManipulator::panModel( const float dx, const float dy, const float dz ) { Matrix rotation_matrix; rotation_matrix.makeRotate( _rotation ); Vec3d dv( dx, dy, dz ); _center += dv * rotation_matrix; } /** Changes the distance of camera to the focal center. If pushForwardIfNeeded is true and minimumDistance is reached, the focal center is moved forward. Otherwise, distance is limited to its minimum value. \sa OrbitManipulator::setMinimumDistance */ void OrbitManipulator::zoomModel( const float dy, bool pushForwardIfNeeded ) { // scale float scale = 1.0f + dy; // minimum distance float minDist = _minimumDistance; if( getRelativeFlag( _minimumDistanceFlagIndex ) ) minDist *= _modelSize; if( _distance*scale > minDist ) { // regular zoom _distance *= scale; } else { if( pushForwardIfNeeded ) { // push the camera forward float scale = -_distance; Matrixd rotation_matrix( _rotation ); Vec3d dv = (Vec3d( 0.0f, 0.0f, -1.0f ) * rotation_matrix) * (dy * scale); _center += dv; } else { // set distance on its minimum value _distance = minDist; } } } /** * Simulate a track-ball. Project the points onto the virtual * trackball, then figure out the axis of rotation, which is the cross * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) * Note: This is a deformed trackball-- is a trackball in the center, * but is deformed into a hyperbolic sheet of rotation away from the * center. This particular function was chosen after trying out * several variations. * * It is assumed that the arguments to this routine are in the range * (-1.0 ... 1.0) */ void OrbitManipulator::trackball( osg::Vec3d& axis, float& angle, float p1x, float p1y, float p2x, float p2y ) { /* * First, figure out z-coordinates for projection of P1 and P2 to * deformed sphere */ osg::Matrixd rotation_matrix(_rotation); osg::Vec3d uv = Vec3d(0.0f,1.0f,0.0f)*rotation_matrix; osg::Vec3d sv = Vec3d(1.0f,0.0f,0.0f)*rotation_matrix; osg::Vec3d lv = Vec3d(0.0f,0.0f,-1.0f)*rotation_matrix; osg::Vec3d p1 = sv * p1x + uv * p1y - lv * tb_project_to_sphere(_trackballSize, p1x, p1y); osg::Vec3d p2 = sv * p2x + uv * p2y - lv * tb_project_to_sphere(_trackballSize, p2x, p2y); /* * Now, we want the cross product of P1 and P2 */ axis = p2^p1; axis.normalize(); /* * Figure out how much to rotate around that axis. */ float t = (p2 - p1).length() / (2.0 * _trackballSize); /* * Avoid problems with out-of-control values... */ if (t > 1.0) t = 1.0; if (t < -1.0) t = -1.0; angle = inRadians(asin(t)); } /** * Helper trackball method that projects an x,y pair onto a sphere of radius r OR * a hyperbolic sheet if we are away from the center of the sphere. */ float OrbitManipulator::tb_project_to_sphere( float r, float x, float y ) { float d, t, z; d = sqrt(x*x + y*y); /* Inside sphere */ if (d < r * 0.70710678118654752440) { z = sqrt(r*r - d*d); } /* On hyperbola */ else { t = r / 1.41421356237309504880; z = t*t / d; } return z; } /** Get the FusionDistanceMode. Used by SceneView for setting up stereo convergence.*/ osgUtil::SceneView::FusionDistanceMode OrbitManipulator::getFusionDistanceMode() const { return osgUtil::SceneView::USE_FUSION_DISTANCE_VALUE; } /** Get the FusionDistanceValue. Used by SceneView for setting up stereo convergence.*/ float OrbitManipulator::getFusionDistanceValue() const { return _distance; } /** Set the center of the manipulator. */ void OrbitManipulator::setCenter( const Vec3d& center ) { _center = center; } /** Get the center of the manipulator. */ const Vec3d& OrbitManipulator::getCenter() const { return _center; } /** Set the rotation of the manipulator. */ void OrbitManipulator::setRotation( const Quat& rotation ) { _rotation = rotation; } /** Get the rotation of the manipulator. */ const Quat& OrbitManipulator::getRotation() const { return _rotation; } /** Set the distance of camera to the center. */ void OrbitManipulator::setDistance( double distance ) { _distance = distance; } /** Get the distance of the camera to the center. */ double OrbitManipulator::getDistance() const { return _distance; } /** Set the size of the trackball. Value is relative to the model size. */ void OrbitManipulator::setTrackballSize( const double& size ) { /* * This size should really be based on the distance from the center of * rotation to the point on the object underneath the mouse. That * point would then track the mouse as closely as possible. This is a * simple example, though, so that is left as an Exercise for the * Programmer. */ _trackballSize = size; clampBetweenRange( _trackballSize, 0.1, 1.0, "TrackballManipulator::setTrackballSize(float)" ); } /** Set the mouse wheel zoom factor. The amount of camera movement on each mouse wheel event is computed as the current distance to the center multiplied by this factor. For example, value of 0.1 will short distance to center by 10% on each wheel up event. Use negative value for reverse mouse wheel direction.*/ void OrbitManipulator::setWheelZoomFactor( double wheelZoomFactor ) { _wheelZoomFactor = wheelZoomFactor; } /** Set the minimum distance of the eye point from the center before the center is pushed forward.*/ void OrbitManipulator::setMinimumDistance( const double& minimumDistance, bool relativeToModelSize ) { _minimumDistance = minimumDistance; setRelativeFlag( _minimumDistanceFlagIndex, relativeToModelSize ); } /** Get the minimum distance of the eye point from the center before the center is pushed forward.*/ double OrbitManipulator::getMinimumDistance( bool *relativeToModelSize ) const { if( relativeToModelSize ) *relativeToModelSize = getRelativeFlag( _minimumDistanceFlagIndex ); return _minimumDistance; } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/DriveManipulator.cpp0000644000175000017500000003614111732410624025010 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #if defined(_MSC_VER) #pragma warning( disable : 4786 ) #endif #include #include #include #include using namespace osg; using namespace osgGA; #define DRIVER_HEIGHT 15 // #define ABOSULTE_PITCH 1 // #define INCREMENTAL_PITCH 1 #define KEYBOARD_PITCH 1 static double getHeightOfDriver() { double height = 1.5; if (getenv("OSG_DRIVE_MANIPULATOR_HEIGHT")) { height = osg::asciiToDouble(getenv("OSG_DRIVE_MANIPULATOR_HEIGHT")); } OSG_INFO<<"DriveManipulator::_height set to =="<getBound(); _modelScale = boundingSphere._radius; //_height = sqrtf(_modelScale)*0.03; //_buffer = sqrtf(_modelScale)*0.05; _height = getHeightOfDriver(); _buffer = _height*2.5; } if (getAutoComputeHomePosition()) computeHomePosition(); } const osg::Node* DriveManipulator::getNode() const { return _node.get(); } osg::Node* DriveManipulator::getNode() { return _node.get(); } bool DriveManipulator::intersect(const osg::Vec3d& start, const osg::Vec3d& end, osg::Vec3d& intersection, osg::Vec3d& normal) const { osg::ref_ptr lsi = new osgUtil::LineSegmentIntersector(start,end); osgUtil::IntersectionVisitor iv(lsi.get()); iv.setTraversalMask(_intersectTraversalMask); _node->accept(iv); if (lsi->containsIntersections()) { intersection = lsi->getIntersections().begin()->getWorldIntersectPoint(); normal = lsi->getIntersections().begin()->getWorldIntersectNormal(); return true; } return false; } void DriveManipulator::computeHomePosition() { if(_node.get()) { const osg::BoundingSphere& boundingSphere=_node->getBound(); osg::Vec3d ep = boundingSphere._center; osg::Vec3d bp = ep; osg::CoordinateFrame cf=getCoordinateFrame(ep); ep -= getUpVector(cf)* _modelScale*0.0001; bp -= getUpVector(cf)* _modelScale; // check to see if any obstruction in front. bool positionSet = false; osg::Vec3d ip, np; if (intersect(ep, bp, ip, np)) { osg::Vec3d uv; if (np * getUpVector(cf)>0.0) uv = np; else uv = -np; ep = ip; ep += getUpVector(cf)*_height; osg::Vec3d lv = uv^osg::Vec3d(1.0,0.0,0.0); setHomePosition(ep,ep+lv,uv); positionSet = true; } if (!positionSet) { bp = ep; bp += getUpVector(cf)*_modelScale; if (intersect(ep, bp, ip, np)) { osg::Vec3d uv; if (np*getUpVector(cf)>0.0) uv = np; else uv = -np; ep = ip; ep += getUpVector(cf)*_height; osg::Vec3d lv = uv^osg::Vec3d(1.0,0.0,0.0); setHomePosition(ep,ep+lv,uv); positionSet = true; } } if (!positionSet) { setHomePosition( boundingSphere._center+osg::Vec3d( 0.0,-2.0 * boundingSphere._radius,0.0), boundingSphere._center+osg::Vec3d( 0.0,-2.0 * boundingSphere._radius,0.0)+osg::Vec3d(0.0,1.0,0.0), osg::Vec3d(0.0,0.0,1.0)); } } } void DriveManipulator::home(const GUIEventAdapter& ea,GUIActionAdapter& us) { if (getAutoComputeHomePosition()) computeHomePosition(); computePosition(_homeEye, _homeCenter, _homeUp); _velocity = 0.0; _pitch = 0.0; us.requestRedraw(); us.requestContinuousUpdate(false); us.requestWarpPointer((ea.getXmin()+ea.getXmax())/2.0f,(ea.getYmin()+ea.getYmax())/2.0f); flushMouseEventStack(); } void DriveManipulator::init(const GUIEventAdapter& ea,GUIActionAdapter& us) { flushMouseEventStack(); us.requestContinuousUpdate(false); _velocity = 0.0; osg::Vec3d ep = _eye; osg::CoordinateFrame cf=getCoordinateFrame(ep); Matrixd rotation_matrix; rotation_matrix.makeRotate(_rotation); osg::Vec3d sv = osg::Vec3d(1.0,0.0,0.0) * rotation_matrix; osg::Vec3d bp = ep; bp -= getUpVector(cf)*_modelScale; bool positionSet = false; osg::Vec3d ip, np; if (intersect(ep, bp, ip, np)) { osg::Vec3d uv; if (np*getUpVector(cf)>0.0) uv = np; else uv = -np; ep = ip+uv*_height; osg::Vec3d lv = uv^sv; computePosition(ep,ep+lv,uv); positionSet = true; } if (!positionSet) { bp = ep; bp += getUpVector(cf)*_modelScale; if (intersect(ep, bp, ip, np)) { osg::Vec3d uv; if (np*getUpVector(cf)>0.0f) uv = np; else uv = -np; ep = ip+uv*_height; osg::Vec3d lv = uv^sv; computePosition(ep,ep+lv,uv); positionSet = true; } } if (ea.getEventType()!=GUIEventAdapter::RESIZE) { us.requestWarpPointer((ea.getXmin()+ea.getXmax())/2.0f,(ea.getYmin()+ea.getYmax())/2.0f); } } bool DriveManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& us) { switch(ea.getEventType()) { case(GUIEventAdapter::FRAME): addMouseEvent(ea); if (calcMovement()) us.requestRedraw(); return false; case(GUIEventAdapter::RESIZE): init(ea,us); us.requestRedraw(); return true; default: break; } if (ea.getHandled()) return false; switch(ea.getEventType()) { case(GUIEventAdapter::PUSH): { addMouseEvent(ea); us.requestContinuousUpdate(true); if (calcMovement()) us.requestRedraw(); return true; } case(GUIEventAdapter::RELEASE): { addMouseEvent(ea); us.requestContinuousUpdate(true); if (calcMovement()) us.requestRedraw(); return true; } case(GUIEventAdapter::DRAG): { addMouseEvent(ea); us.requestContinuousUpdate(true); if (calcMovement()) us.requestRedraw(); return true; } case(GUIEventAdapter::MOVE): { addMouseEvent(ea); us.requestContinuousUpdate(true); if (calcMovement()) us.requestRedraw(); return true; } case(GUIEventAdapter::KEYDOWN): { if (ea.getKey()==GUIEventAdapter::KEY_Space) { flushMouseEventStack(); home(ea,us); return true; } else if (ea.getKey()=='q') { _speedMode = USE_MOUSE_Y_FOR_SPEED; return true; } else if (ea.getKey()=='a') { _speedMode = USE_MOUSE_BUTTONS_FOR_SPEED; return true; } #ifdef KEYBOARD_PITCH else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Up || ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Up || ea.getKey()=='9') { _pitchUpKeyPressed = true; return true; } else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Down || ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Down || ea.getKey()=='6') { _pitchDownKeyPressed = true; return true; } #endif return false; } case(GUIEventAdapter::KEYUP): { #ifdef KEYBOARD_PITCH if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Up || ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Up || ea.getKey()=='9') { _pitchUpKeyPressed = false; return true; } else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Down || ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Down || ea.getKey()=='6') { _pitchDownKeyPressed = false; return true; } #endif return false; } default: return false; } } void DriveManipulator::getUsage(osg::ApplicationUsage& usage) const { usage.addKeyboardMouseBinding("Drive: Space","Reset the viewing position to home"); usage.addKeyboardMouseBinding("Drive: q","Use mouse y for controlling speed"); usage.addKeyboardMouseBinding("Drive: a","Use mouse middle,right mouse buttons for speed"); usage.addKeyboardMouseBinding("Drive: Down","Cursor down key to look downwards"); usage.addKeyboardMouseBinding("Drive: Up","Cursor up key to look upwards"); } void DriveManipulator::flushMouseEventStack() { _ga_t1 = NULL; _ga_t0 = NULL; } void DriveManipulator::addMouseEvent(const GUIEventAdapter& ea) { _ga_t1 = _ga_t0; _ga_t0 = &ea; } void DriveManipulator::setByMatrix(const osg::Matrixd& matrix) { _eye = matrix.getTrans(); _rotation = matrix.getRotate(); } osg::Matrixd DriveManipulator::getMatrix() const { return osg::Matrixd::rotate(_pitch,1.0,0.0,0.0)*osg::Matrixd::rotate(_rotation)*osg::Matrixd::translate(_eye); } osg::Matrixd DriveManipulator::getInverseMatrix() const { return osg::Matrixd::translate(-_eye)*osg::Matrixd::rotate(_rotation.inverse())*osg::Matrixd::rotate(-_pitch,1.0,0.0,0.0); } void DriveManipulator::computePosition(const osg::Vec3d& eye,const osg::Vec3d& center,const osg::Vec3d& up) { osg::Vec3d lv = center-eye; osg::Vec3d f(lv); f.normalize(); osg::Vec3d s(f^up); s.normalize(); osg::Vec3d u(s^f); u.normalize(); osg::Matrixd rotation_matrix(s[0], u[0], -f[0], 0.0, s[1], u[1], -f[1], 0.0, s[2], u[2], -f[2], 0.0, 0.0, 0.0, 0.0, 1.0); _eye = eye; _rotation = rotation_matrix.getRotate().inverse(); } bool DriveManipulator::calcMovement() { // return if less then two events have been added. if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false; double dt = _ga_t0->getTime()-_ga_t1->getTime(); if (dt<0.0f) { OSG_INFO << "warning dt = "<getYnormalized(); _velocity = _height*dy; break; } case(USE_MOUSE_BUTTONS_FOR_SPEED): { unsigned int buttonMask = _ga_t1->getButtonMask(); if (buttonMask==GUIEventAdapter::LEFT_MOUSE_BUTTON) { // pan model. _velocity += dt*accelerationFactor; } else if (buttonMask==GUIEventAdapter::MIDDLE_MOUSE_BUTTON || buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON|GUIEventAdapter::RIGHT_MOUSE_BUTTON)) { _velocity = 0.0; } else if (buttonMask==GUIEventAdapter::RIGHT_MOUSE_BUTTON) { _velocity -= dt*accelerationFactor; } break; } } osg::CoordinateFrame cf=getCoordinateFrame(_eye); osg::Matrixd rotation_matrix; rotation_matrix.makeRotate(_rotation); osg::Vec3d up = osg::Vec3d(0.0,1.0,0.0) * rotation_matrix; osg::Vec3d lv = osg::Vec3d(0.0,0.0,-1.0) * rotation_matrix; osg::Vec3d sv = osg::Vec3d(1.0,0.0,0.0) * rotation_matrix; // rotate the camera. double dx = _ga_t0->getXnormalized(); double yaw = -inDegrees(dx*50.0*dt); #ifdef KEYBOARD_PITCH double pitch_delta = 0.5; if (_pitchUpKeyPressed) _pitch += pitch_delta*dt; if (_pitchDownKeyPressed) _pitch -= pitch_delta*dt; #endif #if defined(ABOSULTE_PITCH) // absolute pitch double dy = _ga_t0->getYnormalized(); _pitch = -dy*0.5; #elif defined(INCREMENTAL_PITCH) // incremental pitch double dy = _ga_t0->getYnormalized(); _pitch += dy*dt; #endif osg::Quat yaw_rotation; yaw_rotation.makeRotate(yaw,up); _rotation *= yaw_rotation; rotation_matrix.makeRotate(_rotation); sv = osg::Vec3d(1.0,0.0,0.0) * rotation_matrix; // movement is big enough the move the eye point along the look vector. if (fabs(_velocity*dt)>1e-8) { double distanceToMove = _velocity*dt; double signedBuffer; if (distanceToMove>=0.0) signedBuffer=_buffer; else signedBuffer=-_buffer; // check to see if any obstruction in front. osg::Vec3d ip, np; if (intersect(_eye,_eye+lv*(signedBuffer+distanceToMove), ip, np)) { if (distanceToMove>=0.0) { distanceToMove = (ip-_eye).length()-_buffer; } else { distanceToMove = _buffer-(ip-_eye).length(); } _velocity = 0.0; } // check to see if forward point is correct height above terrain. osg::Vec3d fp = _eye + lv*distanceToMove; osg::Vec3d lfp = fp - up*(_height*5.0); if (intersect(fp, lfp, ip, np)) { if (up*np>0.0) up = np; else up = -np; _eye = ip+up*_height; lv = up^sv; computePosition(_eye,_eye+lv,up); return true; } // no hit on the terrain found therefore resort to a fall under // under the influence of gravity. osg::Vec3d dp = lfp; dp -= getUpVector(cf)* (2.0*_modelScale); if (intersect(lfp, dp, ip, np)) { if (up*np>0.0) up = np; else up = -np; _eye = ip+up*_height; lv = up^sv; computePosition(_eye,_eye+lv,up); return true; } // no collision with terrain has been found therefore track horizontally. lv *= (_velocity*dt); _eye += lv; } return true; } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/FlightManipulator.cpp0000644000175000017500000001401712163275353025161 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include using namespace osg; using namespace osgGA; /// Constructor. FlightManipulator::FlightManipulator( int flags ) : inherited( flags ), _yawMode( YAW_AUTOMATICALLY_WHEN_BANKED ) { } /// Constructor. FlightManipulator::FlightManipulator( const FlightManipulator& fm, const CopyOp& copyOp ) : osg::Object(fm, copyOp), inherited( fm, copyOp ), _yawMode( fm._yawMode ) { } void FlightManipulator::init( const GUIEventAdapter& ea, GUIActionAdapter& us ) { inherited::init( ea, us ); // center mouse pointer centerMousePointer( ea, us ); } void FlightManipulator::home( const GUIEventAdapter& ea, GUIActionAdapter& us ) { inherited::home( ea, us ); // center mouse pointer centerMousePointer( ea, us ); } // doc in parent bool FlightManipulator::handleFrame( const GUIEventAdapter& ea, GUIActionAdapter& us ) { addMouseEvent( ea ); if( performMovement() ) us.requestRedraw(); return false; } // doc in parent bool FlightManipulator::handleMouseMove( const GUIEventAdapter& ea, GUIActionAdapter& us ) { return flightHandleEvent( ea, us ); } // doc in parent bool FlightManipulator::handleMouseDrag( const GUIEventAdapter& ea, GUIActionAdapter& us ) { return flightHandleEvent( ea, us ); } // doc in parent bool FlightManipulator::handleMousePush( const GUIEventAdapter& ea, GUIActionAdapter& us ) { return flightHandleEvent( ea, us ); } // doc in parent bool FlightManipulator::handleMouseRelease( const GUIEventAdapter& ea, GUIActionAdapter& us ) { return flightHandleEvent( ea, us ); } bool FlightManipulator::handleKeyDown( const GUIEventAdapter& ea, GUIActionAdapter& us ) { if( inherited::handleKeyDown( ea, us ) ) return true; if( ea.getKey() == 'q' ) { _yawMode = YAW_AUTOMATICALLY_WHEN_BANKED; return true; } else if (ea.getKey()=='a') { _yawMode = NO_AUTOMATIC_YAW; return true; } return false; } /// General flight-style event handler bool FlightManipulator::flightHandleEvent( const GUIEventAdapter& ea, GUIActionAdapter& us ) { addMouseEvent( ea ); us.requestContinuousUpdate( true ); if( performMovement() ) us.requestRedraw(); return true; } void FlightManipulator::getUsage( ApplicationUsage& usage ) const { inherited::getUsage( usage ); usage.addKeyboardMouseBinding( getManipulatorName() + ": q", "Automatically yaw when banked (default)" ); usage.addKeyboardMouseBinding( getManipulatorName() + ": a", "No yaw when banked" ); } /** Configure the Yaw control for the flight model. */ void FlightManipulator::setYawControlMode( YawControlMode ycm ) { _yawMode = ycm; } bool FlightManipulator::performMovement() { // return if less then two events have been added. if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false; double eventTimeDelta = _ga_t0->getTime()-_ga_t1->getTime(); if (eventTimeDelta<0.0f) { OSG_WARN << "Manipulator warning: eventTimeDelta = " << eventTimeDelta << std::endl; eventTimeDelta = 0.0f; } unsigned int buttonMask = _ga_t1->getButtonMask(); if (buttonMask==GUIEventAdapter::LEFT_MOUSE_BUTTON) { performMovementLeftMouseButton(eventTimeDelta, 0., 0.); } else if (buttonMask==GUIEventAdapter::MIDDLE_MOUSE_BUTTON || buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON|GUIEventAdapter::RIGHT_MOUSE_BUTTON)) { performMovementMiddleMouseButton(eventTimeDelta, 0., 0.); } else if (buttonMask==GUIEventAdapter::RIGHT_MOUSE_BUTTON) { performMovementRightMouseButton(eventTimeDelta, 0., 0.); } float dx = _ga_t0->getXnormalized(); float dy = _ga_t0->getYnormalized(); CoordinateFrame cf=getCoordinateFrame(_eye); Matrixd rotation_matrix; rotation_matrix.makeRotate(_rotation); Vec3d up = Vec3d(0.0,1.0,0.0) * rotation_matrix; Vec3d lv = Vec3d(0.0,0.0,-1.0) * rotation_matrix; Vec3d sv = lv^up; sv.normalize(); double pitch = -inDegrees(dy*50.0f*eventTimeDelta); double roll = inDegrees(dx*50.0f*eventTimeDelta); Quat delta_rotate; Quat roll_rotate; Quat pitch_rotate; pitch_rotate.makeRotate(pitch,sv.x(),sv.y(),sv.z()); roll_rotate.makeRotate(roll,lv.x(),lv.y(),lv.z()); delta_rotate = pitch_rotate*roll_rotate; if (_yawMode==YAW_AUTOMATICALLY_WHEN_BANKED) { //float bank = asinf(sv.z()); double bank = asinf(sv *getUpVector(cf)); double yaw = inRadians(bank)*eventTimeDelta; Quat yaw_rotate; //yaw_rotate.makeRotate(yaw,0.0f,0.0f,1.0f); yaw_rotate.makeRotate(yaw,getUpVector(cf)); delta_rotate = delta_rotate*yaw_rotate; } lv *= (_velocity*eventTimeDelta); _eye += lv; _rotation = _rotation*delta_rotate; return true; } bool FlightManipulator::performMovementLeftMouseButton( const double eventTimeDelta, const double /*dx*/, const double /*dy*/ ) { // pan model _velocity += eventTimeDelta * (_acceleration + _velocity); return true; } bool FlightManipulator::performMovementMiddleMouseButton( const double /*eventTimeDelta*/, const double /*dx*/, const double /*dy*/ ) { _velocity = 0.0f; return true; } bool FlightManipulator::performMovementRightMouseButton( const double eventTimeDelta, const double /*dx*/, const double /*dy*/ ) { _velocity -= eventTimeDelta * (_acceleration + _velocity); return true; } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/FirstPersonManipulator.cpp0000644000175000017500000002566212163275353026232 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. * * FirstPersonManipulator code Copyright (C) 2010 PCJohn (Jan Peciva) * while some pieces of code were taken from OSG. * Thanks to company Cadwork (www.cadwork.ch) and * Brno University of Technology (www.fit.vutbr.cz) for open-sourcing this work. */ #include #include using namespace osg; using namespace osgGA; int FirstPersonManipulator::_accelerationFlagIndex = allocateRelativeFlag(); int FirstPersonManipulator::_maxVelocityFlagIndex = allocateRelativeFlag(); int FirstPersonManipulator::_wheelMovementFlagIndex = allocateRelativeFlag(); /// Constructor. FirstPersonManipulator::FirstPersonManipulator( int flags ) : inherited( flags ), _velocity( 0. ) { setAcceleration( 1.0, true ); setMaxVelocity( 0.25, true ); setWheelMovement( 0.05, true ); if( _flags & SET_CENTER_ON_WHEEL_FORWARD_MOVEMENT ) setAnimationTime( 0.2 ); } /// Constructor. FirstPersonManipulator::FirstPersonManipulator( const FirstPersonManipulator& fpm, const CopyOp& copyOp ) : osg::Object(fpm, copyOp), inherited( fpm, copyOp ), _eye( fpm._eye ), _rotation( fpm._rotation ), _velocity( fpm._velocity ), _acceleration( fpm._acceleration ), _maxVelocity( fpm._maxVelocity ), _wheelMovement( fpm._wheelMovement ) { } /** Set the position of the manipulator using a 4x4 matrix.*/ void FirstPersonManipulator::setByMatrix( const Matrixd& matrix ) { // set variables _eye = matrix.getTrans(); _rotation = matrix.getRotate(); // fix current rotation if( getVerticalAxisFixed() ) fixVerticalAxis( _eye, _rotation, true ); } /** Set the position of the manipulator using a 4x4 matrix.*/ void FirstPersonManipulator::setByInverseMatrix( const Matrixd& matrix ) { setByMatrix( Matrixd::inverse( matrix ) ); } /** Get the position of the manipulator as 4x4 matrix.*/ Matrixd FirstPersonManipulator::getMatrix() const { return Matrixd::rotate( _rotation ) * Matrixd::translate( _eye ); } /** Get the position of the manipulator as a inverse matrix of the manipulator, typically used as a model view matrix.*/ Matrixd FirstPersonManipulator::getInverseMatrix() const { return Matrixd::translate( -_eye ) * Matrixd::rotate( _rotation.inverse() ); } // doc in parent void FirstPersonManipulator::setTransformation( const osg::Vec3d& eye, const osg::Quat& rotation ) { // set variables _eye = eye; _rotation = rotation; // fix current rotation if( getVerticalAxisFixed() ) fixVerticalAxis( _eye, _rotation, true ); } // doc in parent void FirstPersonManipulator::getTransformation( osg::Vec3d& eye, osg::Quat& rotation ) const { eye = _eye; rotation = _rotation; } // doc in parent void FirstPersonManipulator::setTransformation( const osg::Vec3d& eye, const osg::Vec3d& center, const osg::Vec3d& up ) { // set variables osg::Matrixd m( osg::Matrixd::lookAt( eye, center, up ) ); _eye = eye; _rotation = m.getRotate().inverse(); // fix current rotation if( getVerticalAxisFixed() ) fixVerticalAxis( _eye, _rotation, true ); } // doc in parent void FirstPersonManipulator::getTransformation( osg::Vec3d& eye, osg::Vec3d& center, osg::Vec3d& up ) const { center = _eye + _rotation * osg::Vec3d( 0.,0.,-1. ); eye = _eye; up = _rotation * osg::Vec3d( 0.,1.,0. ); } /** Sets velocity. * * There are no checks for maximum velocity applied. */ void FirstPersonManipulator::setVelocity( const double& velocity ) { _velocity = velocity; } /** Sets acceleration. * * If acceleration effect is unwanted, it can be set to DBL_MAX. * Then, there will be no acceleration and object will reach its * maximum velocity immediately. */ void FirstPersonManipulator::setAcceleration( const double& acceleration, bool relativeToModelSize ) { _acceleration = acceleration; setRelativeFlag( _accelerationFlagIndex, relativeToModelSize ); } /// Returns acceleration speed. double FirstPersonManipulator::getAcceleration( bool *relativeToModelSize ) const { if( relativeToModelSize ) *relativeToModelSize = getRelativeFlag( _accelerationFlagIndex ); return _acceleration; } /** Sets maximum velocity. * * If acceleration is set to DBL_MAX, there is no speeding up. * Instead, maximum velocity is used for velocity at once without acceleration. */ void FirstPersonManipulator::setMaxVelocity( const double& maxVelocity, bool relativeToModelSize ) { _maxVelocity = maxVelocity; setRelativeFlag( _maxVelocityFlagIndex, relativeToModelSize ); } /// Returns maximum velocity. double FirstPersonManipulator::getMaxVelocity( bool *relativeToModelSize ) const { if( relativeToModelSize ) *relativeToModelSize = getRelativeFlag( _maxVelocityFlagIndex ); return _maxVelocity; } /// Sets movement size on single wheel step. void FirstPersonManipulator::setWheelMovement( const double& wheelMovement, bool relativeToModelSize ) { _wheelMovement = wheelMovement; setRelativeFlag( _wheelMovementFlagIndex, relativeToModelSize ); } /// Returns movement size on single wheel step. double FirstPersonManipulator::getWheelMovement( bool *relativeToModelSize ) const { if( relativeToModelSize ) *relativeToModelSize = getRelativeFlag( _wheelMovementFlagIndex ); return _wheelMovement; } void FirstPersonManipulator::home( double currentTime ) { inherited::home( currentTime ); _velocity = 0.; } void FirstPersonManipulator::home( const GUIEventAdapter& ea, GUIActionAdapter& us ) { inherited::home( ea, us ); _velocity = 0.; } void FirstPersonManipulator::init( const GUIEventAdapter& ea, GUIActionAdapter& us ) { inherited::init( ea, us ); // stop movement _velocity = 0.; } // doc in parent bool FirstPersonManipulator::handleMouseWheel( const GUIEventAdapter& ea, GUIActionAdapter& us ) { osgGA::GUIEventAdapter::ScrollingMotion sm = ea.getScrollingMotion(); // handle centering if( _flags & SET_CENTER_ON_WHEEL_FORWARD_MOVEMENT ) { if( ((sm == GUIEventAdapter::SCROLL_DOWN) && (_wheelMovement > 0.)) || ((sm == GUIEventAdapter::SCROLL_UP) && (_wheelMovement < 0.)) ) { // stop thrown animation _thrown = false; if( getAnimationTime() <= 0. ) // center by mouse intersection (no animation) setCenterByMousePointerIntersection( ea, us ); else { // start new animation only if there is no animation in progress if( !isAnimating() ) startAnimationByMousePointerIntersection( ea, us ); } } } switch( sm ) { // mouse scroll up event case GUIEventAdapter::SCROLL_UP: { // move forward moveForward( isAnimating() ? dynamic_cast< FirstPersonAnimationData* >( _animationData.get() )->_targetRot : _rotation, -_wheelMovement * (getRelativeFlag( _wheelMovementFlagIndex ) ? _modelSize : 1. )); us.requestRedraw(); us.requestContinuousUpdate( isAnimating() || _thrown ); return true; } // mouse scroll down event case GUIEventAdapter::SCROLL_DOWN: { // move backward moveForward( _wheelMovement * (getRelativeFlag( _wheelMovementFlagIndex ) ? _modelSize : 1. )); _thrown = false; us.requestRedraw(); us.requestContinuousUpdate( isAnimating() || _thrown ); return true; } // unhandled mouse scrolling motion default: return false; } } // doc in parent bool FirstPersonManipulator::performMovementLeftMouseButton( const double /*eventTimeDelta*/, const double dx, const double dy ) { // world up vector CoordinateFrame coordinateFrame = getCoordinateFrame( _eye ); Vec3d localUp = getUpVector( coordinateFrame ); rotateYawPitch( _rotation, dx, dy, localUp ); return true; } bool FirstPersonManipulator::performMouseDeltaMovement( const float dx, const float dy ) { // rotate camera if( getVerticalAxisFixed() ) { // world up vector CoordinateFrame coordinateFrame = getCoordinateFrame( _eye ); Vec3d localUp = getUpVector( coordinateFrame ); rotateYawPitch( _rotation, dx, dy, localUp ); } else rotateYawPitch( _rotation, dx, dy ); return true; } /// Move camera forward by distance parameter. void FirstPersonManipulator::moveForward( const double distance ) { moveForward( _rotation, distance ); } /// Move camera forward by distance parameter. void FirstPersonManipulator::moveForward( const Quat& rotation, const double distance ) { _eye += rotation * Vec3d( 0., 0., -distance ); } /// Move camera right by distance parameter. void FirstPersonManipulator::moveRight( const double distance ) { _eye += _rotation * Vec3d( distance, 0., 0. ); } /// Move camera up by distance parameter. void FirstPersonManipulator::moveUp( const double distance ) { _eye += _rotation * Vec3d( 0., distance, 0. ); } void FirstPersonManipulator::applyAnimationStep( const double currentProgress, const double /*prevProgress*/ ) { FirstPersonAnimationData *ad = dynamic_cast< FirstPersonAnimationData* >( _animationData.get() ); assert( ad ); // compute new rotation _rotation.slerp( currentProgress, ad->_startRot, ad->_targetRot ); // fix vertical axis if( getVerticalAxisFixed() ) fixVerticalAxis( _eye, _rotation, false ); } // doc in parent bool FirstPersonManipulator::startAnimationByMousePointerIntersection( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us ) { // get current transformation osg::Vec3d prevEye; osg::Quat prevRot; getTransformation( prevEye, prevRot ); // center by mouse intersection if( !setCenterByMousePointerIntersection( ea, us ) ) return false; FirstPersonAnimationData *ad = dynamic_cast< FirstPersonAnimationData*>( _animationData.get() ); assert( ad ); // setup animation data and restore original transformation ad->start( prevRot, _rotation, ea.getTime() ); setTransformation( _eye, prevRot ); return true; } void FirstPersonManipulator::FirstPersonAnimationData::start( const Quat& startRotation, const Quat& targetRotation, const double startTime ) { AnimationData::start( startTime ); _startRot = startRotation; _targetRot = targetRotation; } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/CameraManipulator.cpp0000644000175000017500000001007312163275353025132 0ustar albertoalberto#include #include #include #include #include #include using namespace osg; using namespace osgGA; CameraManipulator::CameraManipulator() { _intersectTraversalMask = 0xffffffff; _autoComputeHomePosition = true; _homeEye.set(0.0,-1.0,0.0); _homeCenter.set(0.0,0.0,0.0); _homeUp.set(0.0,0.0,1.0); } CameraManipulator::CameraManipulator(const CameraManipulator& mm, const CopyOp& copyOp) : osg::Object(mm, copyOp), inherited(mm, copyOp), _intersectTraversalMask(mm._intersectTraversalMask), _autoComputeHomePosition(mm._autoComputeHomePosition), _homeEye(mm._homeEye), _homeCenter(mm._homeCenter), _homeUp(mm._homeUp), _coordinateFrameCallback(dynamic_cast(copyOp(mm._coordinateFrameCallback.get()))) { } CameraManipulator::~CameraManipulator() { } std::string CameraManipulator::getManipulatorName() const { const char* className = this->className(); const char* manipString = strstr(className, "Manipulator"); if (!manipString) return std::string(className); else return std::string(className, manipString-className); } bool CameraManipulator::handle(const GUIEventAdapter&,GUIActionAdapter&) { return false; } /** Compute the home position. * * The computation considers camera's fov (field of view) and model size and * positions camera far enough to fit the model to the screen. * * camera parameter enables computations of camera's fov. If camera is NULL, * scene to camera distance can not be computed and default value is used, * based on model size only. * * useBoundingBox parameter enables to use bounding box instead of bounding sphere * for scene bounds. Bounding box provide more precise scene center that may be * important for many applications.*/ void CameraManipulator::computeHomePosition(const osg::Camera *camera, bool useBoundingBox) { if (getNode()) { osg::BoundingSphere boundingSphere; OSG_INFO<<" CameraManipulator::computeHomePosition("<accept(cbVisitor); osg::BoundingBox &bb = cbVisitor.getBoundingBox(); if (bb.valid()) boundingSphere.expandBy(bb); else boundingSphere = getNode()->getBound(); } else { // compute bounding sphere boundingSphere = getNode()->getBound(); } OSG_INFO<<" boundingSphere.center() = ("<= zoom_threshold) { // zoom gesture zoomModel( (gap_last - gap_now) * eventTimeDelta, true ); } // drag gesture osg::Vec2 delta = ((pt_1_last - pt_1_now) + (pt_2_last - pt_2_now)) / 2.0f; float scale = 0.2f * _distance * eventTimeDelta; // osg::notify(osg::ALWAYS) << "drag: " << delta << " scale: " << scale << std::endl; panModel( delta.x() * scale, delta.y() * scale * (-1)); // flip y-coord because of different origins. } bool MultiTouchTrackballManipulator::handle( const GUIEventAdapter& ea, GUIActionAdapter& us ) { bool handled(false); switch(ea.getEventType()) { case osgGA::GUIEventAdapter::PUSH: case osgGA::GUIEventAdapter::DRAG: case osgGA::GUIEventAdapter::RELEASE: if (ea.isMultiTouchEvent()) { double eventTimeDelta = 1/60.0; //_ga_t0->getTime() - _ga_t1->getTime(); if( eventTimeDelta < 0. ) { OSG_WARN << "Manipulator warning: eventTimeDelta = " << eventTimeDelta << std::endl; eventTimeDelta = 0.; } osgGA::GUIEventAdapter::TouchData* data = ea.getTouchData(); // three touches or two taps for home position if ((data->getNumTouchPoints() == 3) || ((data->getNumTouchPoints() == 1) && (data->get(0).tapCount >= 2))) { flushMouseEventStack(); _thrown = false; home(ea,us); handled = true; } else if (data->getNumTouchPoints() >= 2) { if ((_lastTouchData.valid()) && (_lastTouchData->getNumTouchPoints() >= 2)) { handleMultiTouchDrag(data, _lastTouchData.get(), eventTimeDelta); } handled = true; } _lastTouchData = data; // check if all touches ended unsigned int num_touches_ended(0); for(osgGA::GUIEventAdapter::TouchData::iterator i = data->begin(); i != data->end(); ++i) { if ((*i).phase == osgGA::GUIEventAdapter::TOUCH_ENDED) num_touches_ended++; } if(num_touches_ended == data->getNumTouchPoints()) { _lastTouchData = NULL; } } break; default: break; } return handled ? handled : TrackballManipulator::handle(ea, us); } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/SphericalManipulator.cpp0000644000175000017500000003157011732410624025652 0ustar albertoalberto #include #include #include #include using namespace osg; using namespace osgGA; //-------------------------------------------------------------------------------------------------- SphericalManipulator::SphericalManipulator() { _modelScale = 0.01; _minimumZoomScale = 0.1; _thrown = false; _allowThrow = true; _distance=1.0; _homeDistance=1.0; _zoomDelta = 0.1; _heading=0.0; _elevation=osg::PI_2; _rotationMode = ELEVATION_HEADING; } //-------------------------------------------------------------------------------------------------- SphericalManipulator::~SphericalManipulator() { } //-------------------------------------------------------------------------------------------------- void SphericalManipulator::setNode(osg::Node* node) { _node = node; if (_node.get()) { const osg::BoundingSphere& boundingSphere=_node->getBound(); _modelScale = boundingSphere._radius; } if (getAutoComputeHomePosition()) computeHomePosition(); } //-------------------------------------------------------------------------------------------------- const osg::Node* SphericalManipulator::getNode() const { return _node.get(); } //-------------------------------------------------------------------------------------------------- osg::Node* SphericalManipulator::getNode() { return _node.get(); } //-------------------------------------------------------------------------------------------------- void SphericalManipulator::setRotationMode(RotationMode mode) { if(_rotationMode == mode) return; _rotationMode=mode; if(_rotationMode == MAP) _elevation=PI_2; } //-------------------------------------------------------------------------------------------------- bool SphericalManipulator::setDistance(double distance) { if(distance <= 0) return false; _distance=distance; return true; } //-------------------------------------------------------------------------------------------------- void SphericalManipulator::home(double /*currentTime*/) { if(getAutoComputeHomePosition()) computeHomePosition(); _heading=3*PI_2; _elevation=0.0; _center=_homeCenter; _distance=_homeDistance; _thrown = false; } //-------------------------------------------------------------------------------------------------- void SphericalManipulator::home(const GUIEventAdapter& ea ,GUIActionAdapter& us) { home(ea.getTime()); us.requestRedraw(); us.requestContinuousUpdate(false); } //-------------------------------------------------------------------------------------------------- void SphericalManipulator::init(const GUIEventAdapter& ,GUIActionAdapter& ) { flushMouseEventStack(); } //-------------------------------------------------------------------------------------------------- void SphericalManipulator::getUsage(osg::ApplicationUsage& usage) const { usage.addKeyboardMouseBinding("Spherical: Space","Reset the viewing position to home"); usage.addKeyboardMouseBinding("Spherical: SHIFT","Rotates vertically only"); usage.addKeyboardMouseBinding("Spherical: ALT","Rotates horizontally only"); } //-------------------------------------------------------------------------------------------------- void SphericalManipulator::zoomOn(const osg::BoundingSphere& bound) { computeViewPosition(bound,_modelScale,_distance,_center); _thrown = false; } //-------------------------------------------------------------------------------------------------- bool SphericalManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& us) { switch(ea.getEventType()) { case(GUIEventAdapter::FRAME): { double current_frame_time = ea.getTime(); _delta_frame_time = current_frame_time - _last_frame_time; _last_frame_time = current_frame_time; if (_thrown) { if (calcMovement()) us.requestRedraw(); } return false; } default: break; } if (ea.getHandled()) return false; switch(ea.getEventType()) { case(GUIEventAdapter::PUSH): { flushMouseEventStack(); addMouseEvent(ea); us.requestContinuousUpdate(false); _thrown = false; return true; } case(GUIEventAdapter::RELEASE): { if (ea.getButtonMask()==0) { double timeSinceLastRecordEvent = _ga_t0.valid() ? (ea.getTime() - _ga_t0->getTime()) : DBL_MAX; if (timeSinceLastRecordEvent>0.02) flushMouseEventStack(); if (isMouseMoving()) { if (calcMovement()) { us.requestRedraw(); us.requestContinuousUpdate(true); _thrown = _allowThrow; } } else { flushMouseEventStack(); addMouseEvent(ea); if (calcMovement()) us.requestRedraw(); us.requestContinuousUpdate(false); _thrown = false; } } else { flushMouseEventStack(); addMouseEvent(ea); if (calcMovement()) us.requestRedraw(); us.requestContinuousUpdate(false); _thrown = false; } return true; } case(GUIEventAdapter::DRAG): case(GUIEventAdapter::SCROLL): { addMouseEvent(ea); if (calcMovement()) us.requestRedraw(); us.requestContinuousUpdate(false); _thrown = false; return true; } case(GUIEventAdapter::MOVE): { return false; } case(GUIEventAdapter::KEYDOWN): if (ea.getKey()== GUIEventAdapter::KEY_Space) { flushMouseEventStack(); _thrown = false; home(ea,us); return true; } return false; case(GUIEventAdapter::FRAME): if (_thrown) { if (calcMovement()) us.requestRedraw(); } return false; default: return false; } return false; } //-------------------------------------------------------------------------------------------------- bool SphericalManipulator::isMouseMoving() { if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false; const float velocity = 0.1f; float dx = _ga_t0->getXnormalized()-_ga_t1->getXnormalized(); float dy = _ga_t0->getYnormalized()-_ga_t1->getYnormalized(); float len = sqrtf(dx*dx+dy*dy); float dt = _ga_t0->getTime()-_ga_t1->getTime(); return (len>dt*velocity); } //-------------------------------------------------------------------------------------------------- void SphericalManipulator::flushMouseEventStack() { _ga_t1 = NULL; _ga_t0 = NULL; } //-------------------------------------------------------------------------------------------------- void SphericalManipulator::addMouseEvent(const GUIEventAdapter& ea) { _ga_t1 = _ga_t0; _ga_t0 = &ea; } //-------------------------------------------------------------------------------------------------- void SphericalManipulator::setByMatrix(const osg::Matrixd& matrix) { _center=osg::Vec3d(0,0,-_distance)*matrix; _heading=atan2(-matrix(0,0),matrix(0,1)); if(_rotationMode != MAP) { _elevation=asin(matrix(2,2)); } } //-------------------------------------------------------------------------------------------------- osg::Matrixd SphericalManipulator::getMatrix() const { return osg::Matrixd::translate(osg::Vec3d(0.0,0.0,_distance))* osg::Matrixd::rotate(PI_2-_elevation,1.0,0.0,0.0)* osg::Matrixd::rotate(PI_2+_heading,0.0,0.0,1.0)* osg::Matrixd::translate(_center); } //-------------------------------------------------------------------------------------------------- osg::Matrixd SphericalManipulator::getInverseMatrix() const { return osg::Matrixd::translate(-_center)* osg::Matrixd::rotate(PI_2+_heading,0.0,0.0,-1.0)* osg::Matrixd::rotate(PI_2-_elevation,-1.0,0.0,0.0)* osg::Matrixd::translate(osg::Vec3d(0.0,0.0,-_distance)); } //-------------------------------------------------------------------------------------------------- bool SphericalManipulator::calcMovement() { // mouse scroll is only a single event if (_ga_t0.get()==NULL) return false; float dx=0.0f; float dy=0.0f; unsigned int buttonMask=osgGA::GUIEventAdapter::NONE; if (_ga_t0->getEventType()==GUIEventAdapter::SCROLL) { dy = _ga_t0->getScrollingMotion() == osgGA::GUIEventAdapter::SCROLL_UP ? _zoomDelta : -_zoomDelta; buttonMask=GUIEventAdapter::SCROLL; } else { if (_ga_t1.get()==NULL) return false; dx = _ga_t0->getXnormalized()-_ga_t1->getXnormalized(); dy = _ga_t0->getYnormalized()-_ga_t1->getYnormalized(); float distance = sqrtf(dx*dx + dy*dy); // return if movement is too fast, indicating an error in event values or change in screen. if (distance>0.5) { return false; } // return if there is no movement. if (distance==0.0f) { return false; } buttonMask = _ga_t1->getButtonMask(); } double throwScale = (_thrown && _ga_t0.valid() && _ga_t1.valid()) ? _delta_frame_time / (_ga_t0->getTime() - _ga_t1->getTime()) : 1.0; if (buttonMask==GUIEventAdapter::LEFT_MOUSE_BUTTON) { // rotate camera. if(_rotationMode == MAP) { float pxc = (_ga_t0->getXmax()+_ga_t0->getXmin())/2; float pyc = (_ga_t0->getYmax()+_ga_t0->getYmin())/2; float px0 = _ga_t0->getX(); float py0 = _ga_t0->getY(); float px1 = _ga_t1->getX(); float py1 = _ga_t1->getY(); float angle=atan2(py1-pyc,px1-pxc)-atan2(py0-pyc,px0-pxc); _heading+=throwScale*angle; if(_heading < -PI) _heading+=2*PI; else if(_heading > PI) _heading-=2*PI; } else { if((_rotationMode != ELEVATION) && ((_ga_t1->getModKeyMask() & GUIEventAdapter::MODKEY_SHIFT) == 0)) { _heading-=throwScale*dx*PI_2; if(_heading < 0) _heading+=2*PI; else if(_heading > 2*PI) _heading-=2*PI; } if((_rotationMode != HEADING) && ((_ga_t1->getModKeyMask() & GUIEventAdapter::MODKEY_ALT) == 0)) { _elevation-=throwScale*dy*osg::PI_4; // Only allows vertical rotation of 180deg if(_elevation < -osg::PI_2) _elevation=-osg::PI_2; else if(_elevation > osg::PI_2) _elevation=osg::PI_2; } } return true; } else if (buttonMask==GUIEventAdapter::MIDDLE_MOUSE_BUTTON || buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON|GUIEventAdapter::RIGHT_MOUSE_BUTTON)) { // pan model. float scale = -0.3f*_distance; osg::Matrix rotation_matrix; rotation_matrix=osg::Matrixd::rotate(_elevation,-1,0,0)*osg::Matrixd::rotate(PI_2+_heading,0,0,1); osg::Vec3d dv(throwScale*dx*scale,0,throwScale*dy*scale); _center += dv*rotation_matrix; return true; } else if (buttonMask==GUIEventAdapter::RIGHT_MOUSE_BUTTON || _ga_t0->getEventType()==GUIEventAdapter::SCROLL) { // zoom model. double fd = _distance; double scale = 1.0+throwScale*dy; if(fd*scale > _modelScale*_minimumZoomScale) { _distance *= scale; } else { OSG_DEBUG << "Pushing forward"<getBound(),_modelScale,_homeDistance,_homeCenter); } //-------------------------------------------------------------------------------------------------- void SphericalManipulator::computeViewPosition(const osg::BoundingSphere& bound, double& scale,double& distance,osg::Vec3d& center) { scale=bound._radius; distance=3.5*bound._radius; if(distance <= 0) distance=1; center=bound._center; } openscenegraph-3.2.3/OpenSceneGraph/src/osgGA/KeySwitchMatrixManipulator.cpp0000644000175000017500000001442012022330524027023 0ustar albertoalberto#include #include using namespace osgGA; void KeySwitchMatrixManipulator::addMatrixManipulator(int key, std::string name, CameraManipulator *cm) { if(!cm) return; _manips[key]=std::make_pair(name,osg::ref_ptr(cm)); if(!_current) { _current=cm; _current->setHomePosition(_homeEye,_homeCenter,_homeUp,_autoComputeHomePosition); _current->setNode(0); _current->setCoordinateFrameCallback(getCoordinateFrameCallback()); _current->setByMatrix(getMatrix()); } } void KeySwitchMatrixManipulator::addNumberedMatrixManipulator(CameraManipulator *cm) { if(!cm) return; addMatrixManipulator('1'+_manips.size(),cm->className(),cm); } void KeySwitchMatrixManipulator::selectMatrixManipulator(unsigned int num) { unsigned int manipNo = 0; KeyManipMap::iterator itr; for(itr=_manips.begin(); manipNo!=num && itr!=_manips.end(); ++itr,++manipNo) { } if (itr!=_manips.end()) { itr->second.second->setHomePosition(_homeEye,_homeCenter,_homeUp,_autoComputeHomePosition); if (_current.valid()) { if ( !itr->second.second->getCoordinateFrameCallback() ) { itr->second.second->setCoordinateFrameCallback(_current->getCoordinateFrameCallback()); } if ( !itr->second.second->getNode() ) { itr->second.second->setNode(_current->getNode()); } itr->second.second->setByMatrix(_current->getMatrix()); } _current = itr->second.second; } } void KeySwitchMatrixManipulator::setNode(osg::Node* node) { for(KeyManipMap::iterator itr=_manips.begin(); itr!=_manips.end(); ++itr) { itr->second.second->setNode(node); } } void KeySwitchMatrixManipulator::setHomePosition(const osg::Vec3d& eye, const osg::Vec3d& center, const osg::Vec3d& up, bool autoComputeHomePosition) { CameraManipulator::setHomePosition(eye, center, up, autoComputeHomePosition); for(KeyManipMap::iterator itr=_manips.begin(); itr!=_manips.end(); ++itr) { itr->second.second->setHomePosition(eye, center, up, autoComputeHomePosition); } } void KeySwitchMatrixManipulator::setAutoComputeHomePosition(bool flag) { _autoComputeHomePosition = flag; for(KeyManipMap::iterator itr=_manips.begin(); itr!=_manips.end(); ++itr) { itr->second.second->setAutoComputeHomePosition(flag); } } void KeySwitchMatrixManipulator::computeHomePosition() { for(KeyManipMap::iterator itr=_manips.begin(); itr!=_manips.end(); ++itr) { itr->second.second->computeHomePosition(); } } void KeySwitchMatrixManipulator::home(const GUIEventAdapter& ee,GUIActionAdapter& aa) { // call home for all child manipulators // (this can not be done just for current manipulator, // because it is not possible to transfer some manipulator // settings across manipulators using just MatrixManipulator interface // (one problematic variable is for example OrbitManipulator::distance // that can not be passed by setByMatrix method), // thus we have to call home on all of them) for(KeyManipMap::iterator itr=_manips.begin(); itr!=_manips.end(); ++itr) { itr->second.second->home(ee,aa); } } void KeySwitchMatrixManipulator::setCoordinateFrameCallback(CoordinateFrameCallback* cb) { _coordinateFrameCallback = cb; for(KeyManipMap::iterator itr=_manips.begin(); itr!=_manips.end(); ++itr) { itr->second.second->setCoordinateFrameCallback(cb); } } CameraManipulator* KeySwitchMatrixManipulator::getMatrixManipulatorWithIndex(unsigned int index) { unsigned i=0; for(KeyManipMap::iterator itr = _manips.begin(); itr != _manips.end(); ++itr, ++i) { if (i==index) return itr->second.second.get(); } return 0; } const CameraManipulator* KeySwitchMatrixManipulator::getMatrixManipulatorWithIndex(unsigned int index) const { unsigned i=0; for(KeyManipMap::const_iterator itr = _manips.begin(); itr != _manips.end(); ++itr, ++i) { if (i==index) return itr->second.second.get(); } return 0; } CameraManipulator* KeySwitchMatrixManipulator::getMatrixManipulatorWithKey(unsigned int key) { KeyManipMap::iterator itr = _manips.find(key); if (itr!=_manips.end()) return itr->second.second.get(); else return 0; } const CameraManipulator* KeySwitchMatrixManipulator::getMatrixManipulatorWithKey(unsigned int key) const { KeyManipMap::const_iterator itr = _manips.find(key); if (itr!=_manips.end()) return itr->second.second.get(); else return 0; } bool KeySwitchMatrixManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& aa) { if (!_current) return false; bool handled = false; if (!ea.getHandled() && ea.getEventType()==GUIEventAdapter::KEYDOWN) { KeyManipMap::iterator it=_manips.find(ea.getKey()); if(it != _manips.end()) { CameraManipulator* selectedManipulator = it->second.second.get(); if (selectedManipulator!=_current) { OSG_INFO<<"Switching to manipulator: "<second.first<getNode() ) { selectedManipulator->setNode(_current->getNode()); } selectedManipulator->setByMatrix(_current->getMatrix()); selectedManipulator->init(ea,aa); _current = selectedManipulator; } handled = true; } } return _current->handle(ea,aa) || handled; } void KeySwitchMatrixManipulator::getUsage(osg::ApplicationUsage& usage) const { for(KeyManipMap::const_iterator itr=_manips.begin(); itr!=_manips.end(); ++itr) { std::string key; key += (char)(itr->first); std::string explanation(std::string("Select '")+itr->second.first+std::string("' camera manipulator")); if (_current==itr->second.second) explanation += " (default)"; usage.addKeyboardMouseBinding(key,explanation); itr->second.second->getUsage(usage); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/0000755000175000017500000000000012674261220022270 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/PrecipitationEffect.cpp0000644000175000017500000007544111732410624026734 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include using namespace osgParticle; #define USE_LOCAL_SHADERS static float random(float min,float max) { return min + (max-min)*(float)rand()/(float)RAND_MAX; } PrecipitationEffect::PrecipitationEffect(): _previousFrameTime(FLT_MAX) { setNumChildrenRequiringUpdateTraversal(1); setUpGeometries(1024); rain(0.5); } PrecipitationEffect::PrecipitationEffect(const PrecipitationEffect& copy, const osg::CopyOp& copyop): osg::Node(copy,copyop), _previousFrameTime(FLT_MAX) { setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1); _wind = copy._wind; _particleSpeed = copy._particleSpeed; _particleSize = copy._particleSize; _particleColor = copy._particleColor; _maximumParticleDensity = copy._maximumParticleDensity; _cellSize = copy._cellSize; _nearTransition = copy._nearTransition; _farTransition = copy._farTransition; _fog = copy._fog.valid() ? dynamic_cast(copy._fog->clone(copyop)) : 0; _useFarLineSegments = copy._useFarLineSegments; _dirty = true; update(); } void PrecipitationEffect::rain(float intensity) { _wind.set(0.0f,0.0f,0.0f); _particleSpeed = -2.0f + -5.0f*intensity; _particleSize = 0.01 + 0.02*intensity; _particleColor = osg::Vec4(0.6, 0.6, 0.6, 1.0) - osg::Vec4(0.1, 0.1, 0.1, 1.0)* intensity; _maximumParticleDensity = intensity * 8.5f; _cellSize.set(5.0f / (0.25f+intensity), 5.0f / (0.25f+intensity), 5.0f); _nearTransition = 25.f; _farTransition = 100.0f - 60.0f*sqrtf(intensity); if (!_fog) _fog = new osg::Fog; _fog->setMode(osg::Fog::EXP); _fog->setDensity(0.005f*intensity); _fog->setColor(osg::Vec4(0.5, 0.5, 0.5, 1.0)); _useFarLineSegments = false; _dirty = true; update(); } void PrecipitationEffect::snow(float intensity) { _wind.set(0.0f,0.0f,0.0f); _particleSpeed = -0.75f - 0.25f*intensity; _particleSize = 0.02f + 0.03f*intensity; _particleColor = osg::Vec4(0.85f, 0.85f, 0.85f, 1.0f) - osg::Vec4(0.1f, 0.1f, 0.1f, 1.0f)* intensity; _maximumParticleDensity = intensity * 8.2f; _cellSize.set(5.0f / (0.25f+intensity), 5.0f / (0.25f+intensity), 5.0f); _nearTransition = 25.f; _farTransition = 100.0f - 60.0f*sqrtf(intensity); if (!_fog) _fog = new osg::Fog; _fog->setMode(osg::Fog::EXP); _fog->setDensity(0.01f*intensity); _fog->setColor(osg::Vec4(0.6, 0.6, 0.6, 1.0)); _useFarLineSegments = false; _dirty = true; update(); } void PrecipitationEffect::compileGLObjects(osg::RenderInfo& renderInfo) const { if (_quadGeometry.valid()) { _quadGeometry->compileGLObjects(renderInfo); if (_quadGeometry->getStateSet()) _quadGeometry->getStateSet()->compileGLObjects(*renderInfo.getState()); } if (_lineGeometry.valid()) { _lineGeometry->compileGLObjects(renderInfo); if (_lineGeometry->getStateSet()) _lineGeometry->getStateSet()->compileGLObjects(*renderInfo.getState()); } if (_pointGeometry.valid()) { _pointGeometry->compileGLObjects(renderInfo); if (_pointGeometry->getStateSet()) _pointGeometry->getStateSet()->compileGLObjects(*renderInfo.getState()); } } void PrecipitationEffect::traverse(osg::NodeVisitor& nv) { if (nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR) { if (_dirty) update(); if (nv.getFrameStamp()) { double currentTime = nv.getFrameStamp()->getSimulationTime(); if (_previousFrameTime==FLT_MAX) _previousFrameTime = currentTime; double delta = currentTime - _previousFrameTime; _origin += _wind * delta; _previousFrameTime = currentTime; } return; } if (nv.getVisitorType() == osg::NodeVisitor::NODE_VISITOR) { if (_dirty) update(); osgUtil::GLObjectsVisitor* globjVisitor = dynamic_cast(&nv); if (globjVisitor) { if (globjVisitor->getMode() & osgUtil::GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES) { compileGLObjects(globjVisitor->getRenderInfo()); } } return; } if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR) { return; } osgUtil::CullVisitor* cv = dynamic_cast(&nv); if (!cv) { return; } ViewIdentifier viewIndentifier(cv, nv.getNodePath()); { PrecipitationDrawableSet* precipitationDrawableSet = 0; { OpenThreads::ScopedLock lock(_mutex); precipitationDrawableSet = &(_viewDrawableMap[viewIndentifier]); if (!precipitationDrawableSet->_quadPrecipitationDrawable) { precipitationDrawableSet->_quadPrecipitationDrawable = new PrecipitationDrawable; precipitationDrawableSet->_quadPrecipitationDrawable->setRequiresPreviousMatrix(true); precipitationDrawableSet->_quadPrecipitationDrawable->setGeometry(_quadGeometry.get()); precipitationDrawableSet->_quadPrecipitationDrawable->setStateSet(_quadStateSet.get()); precipitationDrawableSet->_quadPrecipitationDrawable->setDrawType(GL_QUADS); precipitationDrawableSet->_linePrecipitationDrawable = new PrecipitationDrawable; precipitationDrawableSet->_linePrecipitationDrawable->setRequiresPreviousMatrix(true); precipitationDrawableSet->_linePrecipitationDrawable->setGeometry(_lineGeometry.get()); precipitationDrawableSet->_linePrecipitationDrawable->setStateSet(_lineStateSet.get()); precipitationDrawableSet->_linePrecipitationDrawable->setDrawType(GL_LINES); precipitationDrawableSet->_pointPrecipitationDrawable = new PrecipitationDrawable; precipitationDrawableSet->_pointPrecipitationDrawable->setRequiresPreviousMatrix(false); precipitationDrawableSet->_pointPrecipitationDrawable->setGeometry(_pointGeometry.get()); precipitationDrawableSet->_pointPrecipitationDrawable->setStateSet(_pointStateSet.get()); precipitationDrawableSet->_pointPrecipitationDrawable->setDrawType(GL_POINTS); } } cull(*precipitationDrawableSet, cv); cv->pushStateSet(_stateset.get()); float depth = 0.0f; if (!precipitationDrawableSet->_quadPrecipitationDrawable->getCurrentCellMatrixMap().empty()) { cv->pushStateSet(precipitationDrawableSet->_quadPrecipitationDrawable->getStateSet()); cv->addDrawableAndDepth(precipitationDrawableSet->_quadPrecipitationDrawable.get(),cv->getModelViewMatrix(),depth); cv->popStateSet(); } if (!precipitationDrawableSet->_linePrecipitationDrawable->getCurrentCellMatrixMap().empty()) { cv->pushStateSet(precipitationDrawableSet->_linePrecipitationDrawable->getStateSet()); cv->addDrawableAndDepth(precipitationDrawableSet->_linePrecipitationDrawable.get(),cv->getModelViewMatrix(),depth); cv->popStateSet(); } if (!precipitationDrawableSet->_pointPrecipitationDrawable->getCurrentCellMatrixMap().empty()) { cv->pushStateSet(precipitationDrawableSet->_pointPrecipitationDrawable->getStateSet()); cv->addDrawableAndDepth(precipitationDrawableSet->_pointPrecipitationDrawable.get(),cv->getModelViewMatrix(),depth); cv->popStateSet(); } cv->popStateSet(); } } void PrecipitationEffect::update() { _dirty = false; OSG_INFO<<"PrecipitationEffect::update()"<setMode(GL_LIGHTING, osg::StateAttribute::OFF); _stateset->setMode(GL_BLEND, osg::StateAttribute::ON); osg::Texture2D* texture = new osg::Texture2D(createSpotLightImage(osg::Vec4(1.0f,1.0f,1.0f,1.0f),osg::Vec4(1.0f,1.0f,1.0f,0.0f),32,1.0)); _stateset->setTextureAttribute(0, texture); } if (!_inversePeriodUniform) { _inversePeriodUniform = new osg::Uniform("inversePeriod",1.0f/_period); _stateset->addUniform(_inversePeriodUniform.get()); } else _inversePeriodUniform->set(1.0f/_period); if (!_particleColorUniform) { _particleColorUniform = new osg::Uniform("particleColour", _particleColor); _stateset->addUniform(_particleColorUniform.get()); } else _particleColorUniform->set(_particleColor); if (!_particleSizeUniform) { _particleSizeUniform = new osg::Uniform("particleSize", _particleSize); _stateset->addUniform(_particleSizeUniform.get()); } else _particleSizeUniform->set(_particleSize); } } void PrecipitationEffect::createGeometry(unsigned int numParticles, osg::Geometry* quad_geometry, osg::Geometry* line_geometry, osg::Geometry* point_geometry) { // particle corner offsets osg::Vec2 offset00(0.0f,0.0f); osg::Vec2 offset10(1.0f,0.0f); osg::Vec2 offset01(0.0f,1.0f); osg::Vec2 offset11(1.0f,1.0f); osg::Vec2 offset0(0.5f,0.0f); osg::Vec2 offset1(0.5f,1.0f); osg::Vec2 offset(0.5f,0.5f); // configure quad_geometry; osg::Vec3Array* quad_vertices = 0; osg::Vec2Array* quad_offsets = 0; if (quad_geometry) { quad_geometry->setName("quad"); quad_vertices = new osg::Vec3Array(numParticles*4); quad_offsets = new osg::Vec2Array(numParticles*4); quad_geometry->setVertexArray(quad_vertices); quad_geometry->setTexCoordArray(0, quad_offsets); } // configure line_geometry; osg::Vec3Array* line_vertices = 0; osg::Vec2Array* line_offsets = 0; if (line_geometry) { line_geometry->setName("line"); line_vertices = new osg::Vec3Array(numParticles*2); line_offsets = new osg::Vec2Array(numParticles*2); line_geometry->setVertexArray(line_vertices); line_geometry->setTexCoordArray(0, line_offsets); } // configure point_geometry; osg::Vec3Array* point_vertices = 0; osg::Vec2Array* point_offsets = 0; if (point_geometry) { point_geometry->setName("point"); point_vertices = new osg::Vec3Array(numParticles); point_offsets = new osg::Vec2Array(numParticles); point_geometry->setVertexArray(point_vertices); point_geometry->setTexCoordArray(0, point_offsets); } // set up vertex attribute data. for(unsigned int i=0; i< numParticles; ++i) { osg::Vec3 pos( random(0.0f, 1.0f), random(0.0f, 1.0f), random(0.0f, 1.0f)); // quad particles if (quad_vertices) { (*quad_vertices)[i*4] = pos; (*quad_vertices)[i*4+1] = pos; (*quad_vertices)[i*4+2] = pos; (*quad_vertices)[i*4+3] = pos; (*quad_offsets)[i*4] = offset00; (*quad_offsets)[i*4+1] = offset01; (*quad_offsets)[i*4+2] = offset11; (*quad_offsets)[i*4+3] = offset10; } // line particles if (line_vertices) { (*line_vertices)[i*2] = pos; (*line_vertices)[i*2+1] = pos; (*line_offsets)[i*2] = offset0; (*line_offsets)[i*2+1] = offset1; } // point particles if (point_vertices) { (*point_vertices)[i] = pos; (*point_offsets)[i] = offset; } } } void PrecipitationEffect::setUpGeometries(unsigned int numParticles) { unsigned int quadRenderBin = 13; unsigned int lineRenderBin = 12; unsigned int pointRenderBin = 11; OSG_INFO<<"PrecipitationEffect::setUpGeometries("<getVertexArray()->getNumElements() != 4*numParticles) { _quadGeometry = new osg::Geometry; _quadGeometry->setUseVertexBufferObjects(true); needGeometryRebuild = true; } if (!_lineGeometry || _lineGeometry->getVertexArray()->getNumElements() != 2*numParticles) { _lineGeometry = new osg::Geometry; _lineGeometry->setUseVertexBufferObjects(true); needGeometryRebuild = true; } if (!_pointGeometry || _pointGeometry->getVertexArray()->getNumElements() != numParticles) { _pointGeometry = new osg::Geometry; _pointGeometry->setUseVertexBufferObjects(true); needGeometryRebuild = true; } if (needGeometryRebuild) { createGeometry(numParticles, _quadGeometry.get(), _lineGeometry.get(), _pointGeometry.get()); } if (!_quadStateSet) { _quadStateSet = new osg::StateSet; osg::Program* program = new osg::Program; _quadStateSet->setAttribute(program); _quadStateSet->setRenderBinDetails(quadRenderBin,"DepthSortedBin"); #ifdef USE_LOCAL_SHADERS char vertexShaderSource[] = "uniform float inversePeriod;\n" "uniform vec4 particleColour;\n" "uniform float particleSize;\n" "\n" "uniform float osg_SimulationTime;\n" "uniform float osg_DeltaSimulationTime;\n" "\n" "varying vec4 colour;\n" "varying vec2 texCoord;\n" "\n" "void main(void)\n" "{\n" " float offset = gl_Vertex.z;\n" " float startTime = gl_MultiTexCoord1.x;\n" " texCoord = gl_MultiTexCoord0.xy;\n" "\n" " vec4 v_previous = gl_Vertex;\n" " v_previous.z = fract( (osg_SimulationTime - startTime)*inversePeriod - offset);\n" " \n" " vec4 v_current = v_previous;\n" " v_current.z += (osg_DeltaSimulationTime*inversePeriod);\n" " \n" "\n" " colour = particleColour;\n" " \n" " vec4 v1 = gl_ModelViewMatrix * v_current;\n" " vec4 v2 = gl_TextureMatrix[0] * v_previous;\n" " \n" " vec3 dv = v2.xyz - v1.xyz;\n" " \n" " vec2 dv_normalized = normalize(dv.xy);\n" " dv.xy += dv_normalized * particleSize;\n" " vec2 dp = vec2( -dv_normalized.y, dv_normalized.x ) * particleSize;\n" " \n" " float area = length(dv.xy);\n" " colour.a = 0.05+(particleSize)/area;\n" " \n" "\n" " v1.xyz += dv*texCoord.y;\n" " v1.xy += dp*texCoord.x;\n" " \n" " gl_Position = gl_ProjectionMatrix * v1;\n" " gl_ClipVertex = v1;\n" "}\n"; char fragmentShaderSource[] = "uniform sampler2D baseTexture;\n" "varying vec2 texCoord;\n" "varying vec4 colour;\n" "\n" "void main (void)\n" "{\n" " gl_FragColor = colour * texture2D( baseTexture, texCoord);\n" "}\n"; program->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShaderSource)); program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource)); #else // get shaders from source program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, osgDB::findDataFile("quad_rain.vert"))); program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("rain.frag"))); #endif } if (!_lineStateSet) { _lineStateSet = new osg::StateSet; osg::Program* program = new osg::Program; _lineStateSet->setAttribute(program); _lineStateSet->setRenderBinDetails(lineRenderBin,"DepthSortedBin"); #ifdef USE_LOCAL_SHADERS char vertexShaderSource[] = "uniform float inversePeriod;\n" "uniform vec4 particleColour;\n" "uniform float particleSize;\n" "\n" "uniform float osg_SimulationTime;\n" "uniform float osg_DeltaSimulationTime;\n" "uniform mat4 previousModelViewMatrix;\n" "\n" "varying vec4 colour;\n" "varying vec2 texCoord;\n" "\n" "void main(void)\n" "{\n" " float offset = gl_Vertex.z;\n" " float startTime = gl_MultiTexCoord1.x;\n" " texCoord = gl_MultiTexCoord0.xy;\n" "\n" " vec4 v_previous = gl_Vertex;\n" " v_previous.z = fract( (osg_SimulationTime - startTime)*inversePeriod - offset);\n" " \n" " vec4 v_current = v_previous;\n" " v_current.z += (osg_DeltaSimulationTime*inversePeriod);\n" " \n" " colour = particleColour;\n" " \n" " vec4 v1 = gl_ModelViewMatrix * v_current;\n" " vec4 v2 = gl_TextureMatrix[0] * v_previous;\n" " \n" " vec3 dv = v2.xyz - v1.xyz;\n" " \n" " vec2 dv_normalized = normalize(dv.xy);\n" " dv.xy += dv_normalized * particleSize;\n" " \n" " float area = length(dv.xy);\n" " colour.a = (particleSize)/area;\n" " \n" " v1.xyz += dv*texCoord.y;\n" " \n" " gl_Position = gl_ProjectionMatrix * v1;\n" " gl_ClipVertex = v1;\n" "}\n"; char fragmentShaderSource[] = "uniform sampler2D baseTexture;\n" "varying vec2 texCoord;\n" "varying vec4 colour;\n" "\n" "void main (void)\n" "{\n" " gl_FragColor = colour * texture2D( baseTexture, texCoord);\n" "}\n"; program->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShaderSource)); program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource)); #else // get shaders from source program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, osgDB::findDataFile("line_rain.vert"))); program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("rain.frag"))); #endif } if (!_pointStateSet) { _pointStateSet = new osg::StateSet; osg::Program* program = new osg::Program; _pointStateSet->setAttribute(program); #ifdef USE_LOCAL_SHADERS char vertexShaderSource[] = "uniform float inversePeriod;\n" "uniform vec4 particleColour;\n" "uniform float particleSize;\n" "\n" "uniform float osg_SimulationTime;\n" "\n" "varying vec4 colour;\n" "\n" "void main(void)\n" "{\n" " float offset = gl_Vertex.z;\n" " float startTime = gl_MultiTexCoord1.x;\n" "\n" " vec4 v_current = gl_Vertex;\n" " v_current.z = fract( (osg_SimulationTime - startTime)*inversePeriod - offset);\n" " \n" " colour = particleColour;\n" "\n" " gl_Position = gl_ModelViewProjectionMatrix * v_current;\n" "\n" " float pointSize = abs(1280.0*particleSize / gl_Position.w);\n" "\n" " //gl_PointSize = max(ceil(pointSize),2);\n" " gl_PointSize = ceil(pointSize);\n" " \n" " colour.a = 0.05+(pointSize*pointSize)/(gl_PointSize*gl_PointSize);\n" " gl_ClipVertex = gl_ModelViewMatrix * v_current;\n" "}\n"; char fragmentShaderSource[] = "uniform sampler2D baseTexture;\n" "varying vec4 colour;\n" "\n" "void main (void)\n" "{\n" " gl_FragColor = colour * texture2D( baseTexture, gl_TexCoord[0].xy);\n" "}\n"; program->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShaderSource)); program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource)); #else // get shaders from source program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, osgDB::findDataFile("point_rain.vert"))); program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("point_rain.frag"))); #endif /// Setup the point sprites osg::PointSprite *sprite = new osg::PointSprite(); _pointStateSet->setTextureAttributeAndModes(0, sprite, osg::StateAttribute::ON); #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) _pointStateSet->setMode(GL_VERTEX_PROGRAM_POINT_SIZE, osg::StateAttribute::ON); #else OSG_NOTICE<<"Warning: ParticleEffect::setUpGeometries(..) not fully implemented."<setRenderBinDetails(pointRenderBin,"DepthSortedBin"); } } void PrecipitationEffect::cull(PrecipitationDrawableSet& pds, osgUtil::CullVisitor* cv) const { #ifdef DO_TIMING osg::Timer_t startTick = osg::Timer::instance()->tick(); #endif float cellVolume = _cellSize.x() * _cellSize.y() * _cellSize.z(); int numberOfParticles = (int)(_maximumParticleDensity * cellVolume); if (numberOfParticles==0) return; pds._quadPrecipitationDrawable->setNumberOfVertices(numberOfParticles*4); pds._linePrecipitationDrawable->setNumberOfVertices(numberOfParticles*2); pds._pointPrecipitationDrawable->setNumberOfVertices(numberOfParticles); pds._quadPrecipitationDrawable->newFrame(); pds._linePrecipitationDrawable->newFrame(); pds._pointPrecipitationDrawable->newFrame(); osg::Matrix inverse_modelview; inverse_modelview.invert(*(cv->getModelViewMatrix())); osg::Vec3 eyeLocal = osg::Vec3(0.0f,0.0f,0.0f) * inverse_modelview; //OSG_NOTICE<<" eyeLocal "<getProjectionMatrix())); frustum.transformProvidingInverse(*(cv->getModelViewMatrix())); float i_delta = _farTransition * _inverse_du.x(); float j_delta = _farTransition * _inverse_dv.y(); float k_delta = 1;//_nearTransition * _inverse_dw.z(); int i_min = (int)floor(eye_i - i_delta); int j_min = (int)floor(eye_j - j_delta); int k_min = (int)floor(eye_k - k_delta); int i_max = (int)ceil(eye_i + i_delta); int j_max = (int)ceil(eye_j + j_delta); int k_max = (int)ceil(eye_k + k_delta); //OSG_NOTICE<<"i_delta="<delta_m(startTick,endTick)<<"ms numTested="<getCurrentCellMatrixMap().size()<<" lines "<getCurrentCellMatrixMap().size()<<" points "<getCurrentCellMatrixMap().size()<getCurrentCellMatrixMap()[PrecipitationDrawable::Cell(i,k,j)]; mstp.depth = distance; mstp.startTime = startTime; mymodelview = &mstp.modelview; } else if (distance <= _farTransition) { if (_useFarLineSegments) { PrecipitationDrawable::DepthMatrixStartTime& mstp = pds._linePrecipitationDrawable->getCurrentCellMatrixMap()[PrecipitationDrawable::Cell(i,k,j)]; mstp.depth = distance; mstp.startTime = startTime; mymodelview = &mstp.modelview; } else { PrecipitationDrawable::DepthMatrixStartTime& mstp = pds._pointPrecipitationDrawable->getCurrentCellMatrixMap()[PrecipitationDrawable::Cell(i,k,j)]; mstp.depth = distance; mstp.startTime = startTime; mymodelview = &mstp.modelview; } } else { return false; } *mymodelview = *(cv->getModelViewMatrix()); mymodelview->preMultTranslate(position); mymodelview->preMultScale(scale); cv->updateCalculatedNearFar(*(cv->getModelViewMatrix()),bb); return true; } ///////////////////////////////////////////////////////////////////////////////////////////////////// // // Precipitation Drawable // //////////////////////////////////////////////////////////////////////////////////////////////////// PrecipitationEffect::PrecipitationDrawable::PrecipitationDrawable(): _requiresPreviousMatrix(true), _drawType(GL_QUADS), _numberOfVertices(0) { setSupportsDisplayList(false); } PrecipitationEffect::PrecipitationDrawable::PrecipitationDrawable(const PrecipitationDrawable& copy, const osg::CopyOp& copyop): osg::Drawable(copy,copyop), _requiresPreviousMatrix(copy._requiresPreviousMatrix), _geometry(copy._geometry), _drawType(copy._drawType), _numberOfVertices(copy._numberOfVertices) { } void PrecipitationEffect::PrecipitationDrawable::drawImplementation(osg::RenderInfo& renderInfo) const { #if defined(OSG_GL_MATRICES_AVAILABLE) if (!_geometry) return; const osg::Geometry::Extensions* extensions = osg::Geometry::getExtensions(renderInfo.getContextID(),true); // save OpenGL matrices glPushMatrix(); if (_requiresPreviousMatrix) { renderInfo.getState()->setActiveTextureUnit(0); glMatrixMode( GL_TEXTURE ); glPushMatrix(); } typedef std::vector DepthMatrixStartTimeVector; DepthMatrixStartTimeVector orderedEntries; orderedEntries.reserve(_currentCellMatrixMap.size()); for(CellMatrixMap::const_iterator citr = _currentCellMatrixMap.begin(); citr != _currentCellMatrixMap.end(); ++citr) { orderedEntries.push_back(&(*citr)); } std::sort(orderedEntries.begin(),orderedEntries.end(),LessFunctor()); for(DepthMatrixStartTimeVector::reverse_iterator itr = orderedEntries.rbegin(); itr != orderedEntries.rend(); ++itr) { extensions->glMultiTexCoord1f(GL_TEXTURE0+1, (*itr)->second.startTime); // load cells current modelview matrix if (_requiresPreviousMatrix) { glMatrixMode( GL_MODELVIEW ); glLoadMatrix((*itr)->second.modelview.ptr()); CellMatrixMap::const_iterator pitr = _previousCellMatrixMap.find((*itr)->first); if (pitr != _previousCellMatrixMap.end()) { // load previous frame modelview matrix for motion blurr effect glMatrixMode( GL_TEXTURE ); glLoadMatrix(pitr->second.modelview.ptr()); } else { // use current modelview matrix as "previous" frame value, cancelling motion blurr effect glMatrixMode( GL_TEXTURE ); glLoadMatrix((*itr)->second.modelview.ptr()); } } else { glLoadMatrix((*itr)->second.modelview.ptr()); } _geometry->draw(renderInfo); unsigned int numVertices = osg::minimum(_geometry->getVertexArray()->getNumElements(), _numberOfVertices); glDrawArrays(_drawType, 0, numVertices); } // restore OpenGL matrices if (_requiresPreviousMatrix) { glPopMatrix(); glMatrixMode( GL_MODELVIEW ); } glPopMatrix(); #else OSG_NOTICE<<"Warning: ParticleEffect::drawImplementation(..) not fully implemented."< osgParticle::FluidProgram::FluidProgram(): Program() { setFluidToAir(); } osgParticle::FluidProgram::FluidProgram(const FluidProgram& copy, const osg::CopyOp& copyop): Program(copy, copyop), _acceleration(copy._acceleration), _viscosity(copy._viscosity), _density(copy._density), _wind(copy._wind), _viscosityCoefficient(copy._viscosityCoefficient), _densityCoefficient(copy._densityCoefficient) { } void osgParticle::FluidProgram::execute(double dt) { const float four_over_three = 4.0f/3.0f; ParticleSystem* ps = getParticleSystem(); int n = ps->numParticles(); for (int i=0; igetParticle(i); if (particle->isAlive()) { float radius = particle->getRadius(); float Area = osg::PI*radius*radius; float Volume = Area*radius*four_over_three; // compute force due to gravity + boyancy of displacing the fluid that the particle is emersed in. osg::Vec3 accel_gravity = _acceleration * ((particle->getMass() - _density*Volume) * particle->getMassInv()); // compute force due to friction osg::Vec3 relative_wind = particle->getVelocity()-_wind; osg::Vec3 wind_force = - relative_wind * Area * (_viscosityCoefficient + _densityCoefficient*relative_wind.length()); osg::Vec3 wind_accel = wind_force * particle->getMassInv(); double compenstated_dt = dt; if (relative_wind.length2() < dt*dt*wind_accel.length2()) { // OSG_NOTICE<<"** Could be critical: dt="< #include #include #include #include #include using namespace osgParticle; SmokeEffect::SmokeEffect(bool automaticSetup): ParticleEffect(automaticSetup) { setDefaults(); _position.set(0.0f,0.0f,0.0f); _scale = 1.0f; _intensity = 1.0f; _emitterDuration = 65.0; _defaultParticleTemplate.setLifeTime(5.0*_scale); if (_automaticSetup) buildEffect(); } SmokeEffect::SmokeEffect(const osg::Vec3& position, float scale, float intensity) { setDefaults(); _position = position; _scale = scale; _intensity = intensity; _emitterDuration = 65.0; _defaultParticleTemplate.setLifeTime(5.0*_scale); if (_automaticSetup) buildEffect(); } SmokeEffect::SmokeEffect(const SmokeEffect& copy, const osg::CopyOp& copyop): ParticleEffect(copy,copyop) { if (_automaticSetup) buildEffect(); } void SmokeEffect::setDefaults() { ParticleEffect::setDefaults(); _textureFileName = "Images/smoke.rgb"; _emitterDuration = 65.0; // set up unit particle. _defaultParticleTemplate.setLifeTime(5.0*_scale); _defaultParticleTemplate.setSizeRange(osgParticle::rangef(0.75f, 2.0f)); _defaultParticleTemplate.setAlphaRange(osgParticle::rangef(0.1f, 1.0f)); _defaultParticleTemplate.setColorRange(osgParticle::rangev4( osg::Vec4(1, 1.0f, 1.0f, 1.0f), osg::Vec4(1, 1.0f, 1.f, 0.0f))); } void SmokeEffect::setUpEmitterAndProgram() { // set up particle system if (!_particleSystem) { _particleSystem = new osgParticle::ParticleSystem; } if (_particleSystem.valid()) { _particleSystem->setDefaultAttributes(_textureFileName, false, false); osgParticle::Particle& ptemplate = _particleSystem->getDefaultParticleTemplate(); float radius = 0.5f*_scale; float density = 1.0f; // 1.0kg/m^3 ptemplate.setLifeTime(_defaultParticleTemplate.getLifeTime()); // the following ranges set the envelope of the respective // graphical properties in time. ptemplate.setSizeRange(osgParticle::rangef(radius*_defaultParticleTemplate.getSizeRange().minimum, radius*_defaultParticleTemplate.getSizeRange().maximum)); ptemplate.setAlphaRange(_defaultParticleTemplate.getAlphaRange()); ptemplate.setColorRange(_defaultParticleTemplate.getColorRange()); // these are physical properties of the particle ptemplate.setRadius(radius); ptemplate.setMass(density*radius*radius*radius*osg::PI*4.0f/3.0f); } // set up emitter if (!_emitter) { _emitter = new osgParticle::ModularEmitter; _emitter->setNumParticlesToCreateMovementCompensationRatio(1.5f); _emitter->setCounter(new osgParticle::RandomRateCounter); _emitter->setPlacer(new osgParticle::SectorPlacer); _emitter->setShooter(new osgParticle::RadialShooter); } if (_emitter.valid()) { _emitter->setParticleSystem(_particleSystem.get()); _emitter->setReferenceFrame(_useLocalParticleSystem? osgParticle::ParticleProcessor::ABSOLUTE_RF: osgParticle::ParticleProcessor::RELATIVE_RF); _emitter->setStartTime(_startTime); _emitter->setLifeTime(_emitterDuration); _emitter->setEndless(false); osgParticle::RandomRateCounter* counter = dynamic_cast(_emitter->getCounter()); if (counter) { counter->setRateRange(3*_intensity,5*_intensity); } osgParticle::SectorPlacer* placer = dynamic_cast(_emitter->getPlacer()); if (placer) { placer->setCenter(_position); placer->setRadiusRange(0.0f*_scale,0.25f*_scale); } osgParticle::RadialShooter* shooter = dynamic_cast(_emitter->getShooter()); if (shooter) { shooter->setThetaRange(0.0f, osg::PI_4); shooter->setInitialSpeedRange(0.0f*_scale,0.0f*_scale); } } // set up program. if (!_program) { _program = new osgParticle::FluidProgram; } if (_program.valid()) { _program->setParticleSystem(_particleSystem.get()); _program->setWind(_wind); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/SinkOperator.cpp0000644000175000017500000000731412163275353025426 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ // Written by Wang Rui, (C) 2010 #include #include #include #define SINK_EPSILON 1e-3 using namespace osgParticle; void SinkOperator::beginOperate( Program* prg ) { // Don't transform domains if they are used for sinking velocities if ( _sinkTarget==SINK_POSITION ) DomainOperator::beginOperate(prg ); } void SinkOperator::handlePoint( const Domain& domain, Particle* P, double /*dt*/ ) { const osg::Vec3& value = getValue(P); kill( P, (domain.v1==value) ); } void SinkOperator::handleLineSegment( const Domain& domain, Particle* P, double /*dt*/ ) { const osg::Vec3& value = getValue(P); osg::Vec3 offset = value - domain.v1, normal = domain.v2 - domain.v1; normal.normalize(); float diff = fabs(normal*offset - offset.length()) / domain.r1; kill( P, (diffSINK_EPSILON ) insideDomain = false; else { float upos = offset * domain.s1; float vpos = offset * domain.s2; insideDomain = !(upos<0.0f || vpos<0.0f || (upos+vpos)>1.0f); } kill( P, insideDomain ); } void SinkOperator::handleRectangle( const Domain& domain, Particle* P, double /*dt*/ ) { bool insideDomain = false; const osg::Vec3& value = getValue(P); osg::Vec3 offset = value - domain.v1; if ( offset*domain.plane.getNormal()>SINK_EPSILON ) insideDomain = false; else { float upos = offset * domain.s1; float vpos = offset * domain.s2; insideDomain = !(upos<0.0f || upos>1.0f || vpos<0.0f || vpos>1.0f); } kill( P, insideDomain ); } void SinkOperator::handlePlane( const Domain& domain, Particle* P, double /*dt*/ ) { const osg::Vec3& value = getValue(P); bool insideDomain = (domain.plane.getNormal()*value>=-domain.plane[3]); kill( P, insideDomain ); } void SinkOperator::handleSphere( const Domain& domain, Particle* P, double /*dt*/ ) { const osg::Vec3& value = getValue(P); float r = (value - domain.v1).length(); kill( P, (r<=domain.r1) ); } void SinkOperator::handleBox( const Domain& domain, Particle* P, double /*dt*/ ) { const osg::Vec3& value = getValue(P); bool insideDomain = !( (value.x() < domain.v1.x()) || (value.x() > domain.v2.x()) || (value.y() < domain.v1.y()) || (value.y() > domain.v2.y()) || (value.z() < domain.v1.z()) || (value.z() > domain.v2.z()) ); kill( P, insideDomain ); } void SinkOperator::handleDisk( const Domain& domain, Particle* P, double /*dt*/ ) { bool insideDomain = false; const osg::Vec3& value = getValue(P); osg::Vec3 offset = value - domain.v1; if ( offset*domain.v2>SINK_EPSILON ) insideDomain = false; else { float length = offset.length(); insideDomain = (length<=domain.r1 && length>=domain.r2); } kill( P, insideDomain ); } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/ModularProgram.cpp0000644000175000017500000000156111732410624025730 0ustar albertoalberto#include #include #include #include osgParticle::ModularProgram::ModularProgram() : Program() { } osgParticle::ModularProgram::ModularProgram(const ModularProgram& copy, const osg::CopyOp& copyop) : Program(copy, copyop) { Operator_vector::const_iterator ci; for (ci=copy._operators.begin(); ci!=copy._operators.end(); ++ci) { _operators.push_back(static_cast(copyop(ci->get()))); } } void osgParticle::ModularProgram::execute(double dt) { Operator_vector::iterator ci; Operator_vector::iterator ci_end = _operators.end(); ParticleSystem* ps = getParticleSystem(); for (ci=_operators.begin(); ci!=ci_end; ++ci) { (*ci)->beginOperate(this); (*ci)->operateParticles(ps, dt); (*ci)->endOperate(); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/SmokeTrailEffect.cpp0000644000175000017500000001236311732410624026166 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include using namespace osgParticle; SmokeTrailEffect::SmokeTrailEffect(bool automaticSetup): ParticleEffect(automaticSetup) { setDefaults(); _position.set(0.0f,0.0f,0.0f); _scale = 1.0f; _intensity = 1.0f; _emitterDuration = 65.0; _defaultParticleTemplate.setLifeTime(5.0*_scale); if (_automaticSetup) buildEffect(); } SmokeTrailEffect::SmokeTrailEffect(const osg::Vec3& position, float scale, float intensity) { setDefaults(); _position = position; _scale = scale; _intensity = intensity; _emitterDuration = 65.0; _defaultParticleTemplate.setLifeTime(5.0*_scale); if (_automaticSetup) buildEffect(); } SmokeTrailEffect::SmokeTrailEffect(const SmokeTrailEffect& copy, const osg::CopyOp& copyop): ParticleEffect(copy,copyop) { if (_automaticSetup) buildEffect(); } void SmokeTrailEffect::setDefaults() { ParticleEffect::setDefaults(); _textureFileName = "Images/continous_smoke.rgb"; _emitterDuration = 65.0; // set up unit particle. _defaultParticleTemplate.setLifeTime(5.0*_scale); _defaultParticleTemplate.setSizeRange(osgParticle::rangef(0.75f, 2.0f)); _defaultParticleTemplate.setAlphaRange(osgParticle::rangef(0.7f, 1.0f)); _defaultParticleTemplate.setColorRange(osgParticle::rangev4( osg::Vec4(1, 1.0f, 1.0f, 1.0f), osg::Vec4(1, 1.0f, 1.f, 0.0f))); } void SmokeTrailEffect::setUpEmitterAndProgram() { // set up particle system if (!_particleSystem) { _particleSystem = new osgParticle::ConnectedParticleSystem; } if (_particleSystem.valid()) { _particleSystem->setDefaultAttributes(_textureFileName, false, false); osgParticle::Particle& ptemplate = _particleSystem->getDefaultParticleTemplate(); float radius = 0.5f*_scale; float density = 1.0f; // 1.0kg/m^3 ptemplate.setLifeTime(_defaultParticleTemplate.getLifeTime()); // the following ranges set the envelope of the respective // graphical properties in time. ptemplate.setSizeRange(osgParticle::rangef(radius*_defaultParticleTemplate.getSizeRange().minimum, radius*_defaultParticleTemplate.getSizeRange().maximum)); ptemplate.setAlphaRange(_defaultParticleTemplate.getAlphaRange()); ptemplate.setColorRange(_defaultParticleTemplate.getColorRange()); // these are physical properties of the particle ptemplate.setRadius(radius); ptemplate.setMass(density*radius*radius*radius*osg::PI*4.0f/3.0f); } // set up emitter if (!_emitter) { _emitter = new osgParticle::ModularEmitter; _emitter->setCounter(new osgParticle::ConstantRateCounter); _emitter->setPlacer(new osgParticle::SectorPlacer); _emitter->setShooter(new osgParticle::RadialShooter); } if (_emitter.valid()) { _emitter->setParticleSystem(_particleSystem.get()); _emitter->setReferenceFrame(_useLocalParticleSystem? osgParticle::ParticleProcessor::ABSOLUTE_RF: osgParticle::ParticleProcessor::RELATIVE_RF); _emitter->setStartTime(_startTime); _emitter->setLifeTime(_emitterDuration); _emitter->setEndless(false); osgParticle::ConstantRateCounter* counter = dynamic_cast(_emitter->getCounter()); if (counter) { counter->setMinimumNumberOfParticlesToCreate(1); counter->setNumberOfParticlesPerSecondToCreate(0.0); } osgParticle::SectorPlacer* placer = dynamic_cast(_emitter->getPlacer()); if (placer) { placer->setCenter(_position); placer->setRadiusRange(0.0f*_scale,0.0f*_scale); } osgParticle::RadialShooter* shooter = dynamic_cast(_emitter->getShooter()); if (shooter) { shooter->setThetaRange(0.0f, 0.0f); shooter->setInitialSpeedRange(0.0f*_scale,0.0f*_scale); } } // set up program. if (!_program) { _program = new osgParticle::FluidProgram; } if (_program.valid()) { _program->setParticleSystem(_particleSystem.get()); _program->setWind(_wind); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/ModularEmitter.cpp0000644000175000017500000000763611732410624025743 0ustar albertoalberto#include #include #include #include osgParticle::ModularEmitter::ModularEmitter() : Emitter(), _numParticleToCreateMovementCompensationRatio(0.0f), _counter(new RandomRateCounter), _placer(new PointPlacer), _shooter(new RadialShooter) { } osgParticle::ModularEmitter::ModularEmitter(const ModularEmitter& copy, const osg::CopyOp& copyop): Emitter(copy, copyop), _numParticleToCreateMovementCompensationRatio(copy._numParticleToCreateMovementCompensationRatio), _counter(static_cast(copyop(copy._counter.get()))), _placer(static_cast(copyop(copy._placer.get()))), _shooter(static_cast(copyop(copy._shooter.get()))) { } void osgParticle::ModularEmitter::emitParticles(double dt) { ConnectedParticleSystem* cps = dynamic_cast(getParticleSystem()); osg::Matrix worldToPs; osg::MatrixList worldMats = getParticleSystem()->getWorldMatrices(); if (!worldMats.empty()) { const osg::Matrix psToWorld = worldMats[0]; worldToPs = osg::Matrix::inverse(psToWorld); } if (getReferenceFrame() == RELATIVE_RF) { const osg::Matrix& ltw = getLocalToWorldMatrix(); const osg::Matrix& previous_ltw = getPreviousLocalToWorldMatrix(); const osg::Matrix emitterToPs = ltw * worldToPs; const osg::Matrix prevEmitterToPs = previous_ltw * worldToPs; int n = _counter->numParticlesToCreate(dt); if (_numParticleToCreateMovementCompensationRatio>0.0f) { // compute the distance moved between frames const osg::Vec3d controlPosition = osg::Vec3d(_placer->getControlPosition()); osg::Vec3d previousPosition = controlPosition * previous_ltw; osg::Vec3d currentPosition = controlPosition * ltw; float distance = (currentPosition-previousPosition).length(); float size = getUseDefaultTemplate() ? getParticleSystem()->getDefaultParticleTemplate().getSizeRange().minimum : getParticleTemplate().getSizeRange().minimum; float num_extra_samples = _numParticleToCreateMovementCompensationRatio*distance/size; float rounded_down = floor(num_extra_samples); float remainder = num_extra_samples-rounded_down; n = osg::maximum(n, int(rounded_down) + (((float) rand() < remainder * (float)RAND_MAX) ? 1 : 0)); } for (int i=0; icreateParticle(getUseDefaultTemplate()? 0: &getParticleTemplate()); if (P) { _placer->place(P); _shooter->shoot(P); // Now need to transform the position and velocity because we having a moving model. float r = ((float)rand()/(float)RAND_MAX); P->transformPositionVelocity(emitterToPs, prevEmitterToPs, r); //P->transformPositionVelocity(ltw); if (cps) P->setUpTexCoordsAsPartOfConnectedParticleSystem(cps); } else { OSG_NOTICE<<"run out of particle"<numParticlesToCreate(dt); for (int i=0; icreateParticle(getUseDefaultTemplate()? 0: &getParticleTemplate()); if (P) { _placer->place(P); P->setPosition(P->getPosition() * worldToPs); _shooter->shoot(P); P->setVelocity(osg::Matrix::transform3x3(P->getVelocity(), worldToPs)); if (cps) P->setUpTexCoordsAsPartOfConnectedParticleSystem(cps); } } } } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/DomainOperator.cpp0000644000175000017500000001025511732410624025720 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ // Written by Wang Rui, (C) 2010 #include #include #include using namespace osgParticle; void DomainOperator::operate( Particle* P, double dt ) { for ( std::vector::iterator itr=_domains.begin(); itr!=_domains.end(); ++itr ) { switch ( itr->type ) { case Domain::POINT_DOMAIN: handlePoint( *itr, P, dt ); break; case Domain::LINE_DOMAIN: handleLineSegment( *itr, P, dt ); break; case Domain::TRI_DOMAIN: handleTriangle( *itr, P, dt ); break; case Domain::RECT_DOMAIN: handleRectangle( *itr, P, dt ); break; case Domain::PLANE_DOMAIN: handlePlane( *itr, P, dt ); break; case Domain::SPHERE_DOMAIN: handleSphere( *itr, P, dt ); break; case Domain::BOX_DOMAIN: handleBox( *itr, P, dt ); break; case Domain::DISK_DOMAIN: handleDisk( *itr, P, dt ); break; default: break; } } } void DomainOperator::beginOperate( Program* prg ) { if ( prg->getReferenceFrame()==ModularProgram::RELATIVE_RF ) { _backupDomains = _domains; for ( std::vector::iterator itr=_domains.begin(); itr!=_domains.end(); ++itr ) { Domain& domain = *itr; switch ( domain.type ) { case Domain::POINT_DOMAIN: domain.v1 = prg->transformLocalToWorld(domain.v1); break; case Domain::LINE_DOMAIN: domain.v1 = prg->transformLocalToWorld(domain.v1); domain.v2 = prg->transformLocalToWorld(domain.v2); break; case Domain::TRI_DOMAIN: domain.v1 = prg->transformLocalToWorld(domain.v1); domain.v2 = prg->transformLocalToWorld(domain.v2); domain.v3 = prg->transformLocalToWorld(domain.v3); domain.plane.set(domain.v1, domain.v2, domain.v3); computeNewBasis( domain.v2-domain.v1, domain.v3-domain.v1, domain.s1, domain.s2 ); break; case Domain::RECT_DOMAIN: domain.v1 = prg->transformLocalToWorld(domain.v1); domain.v2 = prg->rotateLocalToWorld(domain.v2); // Width vector domain.v3 = prg->rotateLocalToWorld(domain.v3); // Height vector domain.plane.set(domain.v1, domain.v1+domain.v2, domain.v1+domain.v3); computeNewBasis( domain.v2, domain.v3, domain.s1, domain.s2 ); break; case Domain::PLANE_DOMAIN: domain.plane.transformProvidingInverse( prg->getLocalToWorldMatrix() ); break; case Domain::SPHERE_DOMAIN: domain.v1 = prg->transformLocalToWorld(domain.v1); break; case Domain::BOX_DOMAIN: domain.v1 = prg->transformLocalToWorld(domain.v1); domain.v2 = prg->transformLocalToWorld(domain.v2); break; case Domain::DISK_DOMAIN: domain.v1 = prg->transformLocalToWorld(domain.v1); domain.v2 = prg->rotateLocalToWorld(domain.v2); domain.v2.normalize(); // Normal break; default: break; } } } } void DomainOperator::endOperate() { if ( _backupDomains.size()>0 ) { _domains = _backupDomains; _backupDomains.clear(); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/ExplosionEffect.cpp0000644000175000017500000001231711732410624026073 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include using namespace osgParticle; ExplosionEffect::ExplosionEffect(bool automaticSetup): ParticleEffect(automaticSetup) { setDefaults(); _position.set(0.0f,0.0f,0.0f); _scale = 1.0f; _intensity = 1.0f; _emitterDuration = 1.0; if (_automaticSetup) buildEffect(); } ExplosionEffect::ExplosionEffect(const osg::Vec3& position, float scale, float intensity) { setDefaults(); _position = position; _scale = scale; _intensity = intensity; _emitterDuration = 1.0; if (_automaticSetup) buildEffect(); } ExplosionEffect::ExplosionEffect(const ExplosionEffect& copy, const osg::CopyOp& copyop): ParticleEffect(copy,copyop) { if (_automaticSetup) buildEffect(); } void ExplosionEffect::setDefaults() { ParticleEffect::setDefaults(); _textureFileName = "Images/smoke.rgb"; _emitterDuration = 1.0; // set up unit particle. _defaultParticleTemplate.setLifeTime(0.5+0.1*_scale); _defaultParticleTemplate.setSizeRange(osgParticle::rangef(0.75f, 3.0f)); _defaultParticleTemplate.setAlphaRange(osgParticle::rangef(0.1f, 1.0f)); _defaultParticleTemplate.setColorRange(osgParticle::rangev4( osg::Vec4(1.0f, 0.8f, 0.2f, 1.0f), osg::Vec4(1.0f, 0.4f, 0.1f, 0.0f))); } void ExplosionEffect::setUpEmitterAndProgram() { // set up particle system if (!_particleSystem) { _particleSystem = new osgParticle::ParticleSystem; } if (_particleSystem.valid()) { _particleSystem->setDefaultAttributes(_textureFileName, false, false); osgParticle::Particle& ptemplate = _particleSystem->getDefaultParticleTemplate(); float radius = 0.4f*_scale; float density = 1.2f; // 1.0kg/m^3 ptemplate.setLifeTime(_defaultParticleTemplate.getLifeTime()); // the following ranges set the envelope of the respective // graphical properties in time. ptemplate.setSizeRange(osgParticle::rangef(radius*_defaultParticleTemplate.getSizeRange().minimum, radius*_defaultParticleTemplate.getSizeRange().maximum)); ptemplate.setAlphaRange(_defaultParticleTemplate.getAlphaRange()); ptemplate.setColorRange(_defaultParticleTemplate.getColorRange()); // these are physical properties of the particle ptemplate.setRadius(radius); ptemplate.setMass(density*radius*radius*radius*osg::PI*4.0f/3.0f); } // set up emitter if (!_emitter) { _emitter = new osgParticle::ModularEmitter; _emitter->setCounter(new osgParticle::RandomRateCounter); _emitter->setPlacer(new osgParticle::SectorPlacer); _emitter->setShooter(new osgParticle::RadialShooter); } if (_emitter.valid()) { _emitter->setParticleSystem(_particleSystem.get()); _emitter->setReferenceFrame(_useLocalParticleSystem? osgParticle::ParticleProcessor::ABSOLUTE_RF: osgParticle::ParticleProcessor::RELATIVE_RF); _emitter->setStartTime(_startTime); _emitter->setLifeTime(_emitterDuration); _emitter->setEndless(false); osgParticle::RandomRateCounter* counter = dynamic_cast(_emitter->getCounter()); if (counter) { counter->setRateRange(50*_intensity,100*_intensity); } osgParticle::SectorPlacer* placer = dynamic_cast(_emitter->getPlacer()); if (placer) { placer->setCenter(_position); placer->setRadiusRange(0.0f*_scale,0.25f*_scale); } osgParticle::RadialShooter* shooter = dynamic_cast(_emitter->getShooter()); if (shooter) { shooter->setThetaRange(0.0f, osg::PI_2); shooter->setInitialSpeedRange(1.0f*_scale,10.0f*_scale); } } // set up the program if (!_program) { _program = new osgParticle::FluidProgram; } if (_program.valid()) { _program->setParticleSystem(_particleSystem.get()); _program->setWind(_wind); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/ParticleEffect.cpp0000644000175000017500000001053211732410624025653 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include using namespace osgParticle; ParticleEffect::ParticleEffect(const ParticleEffect& copy, const osg::CopyOp& copyop): osg::Group(copy,copyop), _automaticSetup(copy._automaticSetup), _useLocalParticleSystem(copy._useLocalParticleSystem), _textureFileName(copy._textureFileName), _defaultParticleTemplate(copy._defaultParticleTemplate), _position(copy._position), _scale(copy._scale), _intensity(copy._intensity), _startTime(copy._startTime), _emitterDuration(copy._emitterDuration), _wind(copy._wind) { } void ParticleEffect::setUseLocalParticleSystem(bool local) { if (_useLocalParticleSystem==local) return; _useLocalParticleSystem = local; if (_automaticSetup) buildEffect(); } void ParticleEffect::setTextureFileName(const std::string& filename) { _textureFileName = filename; if (_automaticSetup) setUpEmitterAndProgram(); } void ParticleEffect::setDefaultParticleTemplate(const Particle& p) { _defaultParticleTemplate = p; if (_automaticSetup) setUpEmitterAndProgram(); } void ParticleEffect::setPosition(const osg::Vec3& position) { if (_position==position) return; _position = position; if (_automaticSetup) setUpEmitterAndProgram(); } void ParticleEffect::setScale(float scale) { if (_scale==scale) return; _scale = scale; if (_automaticSetup) setUpEmitterAndProgram(); } void ParticleEffect::setIntensity(float intensity) { if (_intensity==intensity) return; _intensity = intensity; if (_automaticSetup) setUpEmitterAndProgram(); } void ParticleEffect::setStartTime(double startTime) { if (_startTime==startTime) return; _startTime =startTime; if (_automaticSetup) setUpEmitterAndProgram(); } void ParticleEffect::setEmitterDuration(double duration) { if (_emitterDuration==duration) return; _emitterDuration = duration; if (_automaticSetup) setUpEmitterAndProgram(); } void ParticleEffect::setParticleDuration(double duration) { if (_defaultParticleTemplate.getLifeTime()==duration) return; _defaultParticleTemplate.setLifeTime(duration); if (_automaticSetup) setUpEmitterAndProgram(); } void ParticleEffect::setWind(const osg::Vec3& wind) { if (_wind==wind) return; _wind = wind; if (_automaticSetup) setUpEmitterAndProgram(); } void ParticleEffect::setParticleSystem(ParticleSystem* ps) { if (_particleSystem==ps) return; _particleSystem = ps; if (_automaticSetup) buildEffect(); } void ParticleEffect::setDefaults() { _useLocalParticleSystem = true; _scale = 1.0f; _intensity = 1.0f; _startTime = 0.0; _emitterDuration = 1.0; _wind.set(0.0f,0.0f,0.0f); } void ParticleEffect::buildEffect() { setUpEmitterAndProgram(); osg::ref_ptr emitter = getEmitter(); osg::ref_ptr program = getProgram(); osg::ref_ptr particleSystem = getParticleSystem(); if (!emitter || !particleSystem || !program) return; // clear the children. removeChildren(0,getNumChildren()); // add the emitter addChild(emitter.get()); // add the program to update the particles addChild(program.get()); // add the particle system updater. osg::ref_ptr psu = new osgParticle::ParticleSystemUpdater; psu->addParticleSystem(particleSystem.get()); addChild(psu.get()); if (_useLocalParticleSystem) { particleSystem->setParticleScaleReferenceFrame(ParticleSystem::LOCAL_COORDINATES); // add the geode to the scene graph osg::Geode* geode = new osg::Geode; geode->addDrawable(particleSystem.get()); addChild(geode); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/ConnectedParticleSystem.cpp0000644000175000017500000001777211732410624027603 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include using namespace osgParticle; ConnectedParticleSystem::ConnectedParticleSystem(): _lastParticleCreated(Particle::INVALID_INDEX), _maxNumberOfParticlesToSkip(200), _startParticle(Particle::INVALID_INDEX) { } ConnectedParticleSystem::ConnectedParticleSystem(const ConnectedParticleSystem& copy, const osg::CopyOp& copyop): ParticleSystem(copy,copyop), _lastParticleCreated(copy._lastParticleCreated), _maxNumberOfParticlesToSkip(200), _startParticle(copy._startParticle) { } ConnectedParticleSystem::~ConnectedParticleSystem() { } Particle* ConnectedParticleSystem::createParticle(const Particle* ptemplate) { // OSG_NOTICE<setPreviousParticle(_lastParticleCreated); } // set the new particle as the last particle created. _lastParticleCreated = particleIndex; } return particle; } void ConnectedParticleSystem::reuseParticle(int particleIndex) { // OSG_NOTICE<=(int)_particles.size()) return; Particle* particle = &_particles[particleIndex]; int previous = particle->getPreviousParticle(); int next = particle->getNextParticle(); // update start and last entries if (_startParticle == particleIndex) { _startParticle = particle->getNextParticle(); } if (_lastParticleCreated == particleIndex) { _lastParticleCreated = Particle::INVALID_INDEX; } // join up the previous and next particles to account for // the deletion of the this particle if (previous != Particle::INVALID_INDEX) { _particles[previous].setNextParticle(next); } if (next != Particle::INVALID_INDEX) { _particles[next].setPreviousParticle(previous); } // reset the next and previous particle entries of this particle particle->setPreviousParticle(Particle::INVALID_INDEX); particle->setNextParticle(Particle::INVALID_INDEX); // put the particle on the death stack ParticleSystem::reuseParticle(particleIndex); } void ConnectedParticleSystem::drawImplementation(osg::RenderInfo& renderInfo) const { osg::State& state = *renderInfo.getState(); osg::GLBeginEndAdapter& gl = state.getGLBeginEndAdapter(); ScopedReadLock lock(_readWriteMutex); const Particle* particle = (_startParticle != Particle::INVALID_INDEX) ? &_particles[_startParticle] : 0; if (!particle) return; osg::Vec4 pixelSizeVector = osg::CullingSet::computePixelSizeVector(*state.getCurrentViewport(),state.getProjectionMatrix(),state.getModelViewMatrix()); float unitPixelSize = fabs(1.0/(particle->getPosition()*pixelSizeVector)); float pixelSizeOfFirstParticle = unitPixelSize * particle->getCurrentSize(); //float desiredGapBetweenDrawnParticles = 50.0f/unitPixelSize; //float desiredGapBetweenDrawnParticles2 = desiredGapBetweenDrawnParticles*desiredGapBetweenDrawnParticles; float maxPixelError2 = osg::square(1.0f/unitPixelSize); if (pixelSizeOfFirstParticle<1.0) { // draw the connected particles as a line gl.Begin(GL_LINE_STRIP); while(particle != 0) { const osg::Vec4& color = particle->getCurrentColor(); const osg::Vec3& pos = particle->getPosition(); gl.Color4f( color.r(), color.g(), color.b(), color.a() * particle->getCurrentAlpha()); gl.TexCoord2f( particle->getSTexCoord(), 0.5f ); gl.Vertex3fv(pos.ptr()); const Particle* nextParticle = (particle->getNextParticle() != Particle::INVALID_INDEX) ? &_particles[particle->getNextParticle()] : 0; if (nextParticle) { const osg::Vec3& nextPos = nextParticle->getPosition(); osg::Vec3 startDelta = nextPos-pos; startDelta.normalize(); float distance2 = 0.0; // now skip particles of required for(unsigned int i=0; i<_maxNumberOfParticlesToSkip && ((distance2getNextParticle()!=Particle::INVALID_INDEX)); ++i) { nextParticle = &_particles[nextParticle->getNextParticle()]; const osg::Vec3& nextPos = nextParticle->getPosition(); osg::Vec3 delta = nextPos-pos; distance2 = (delta^startDelta).length2(); } } particle = nextParticle; } gl.End(); } else { // draw the connected particles as a quad stripped aligned to be orthogonal to the eye osg::Matrix eyeToLocalTransform; eyeToLocalTransform.invert(state.getModelViewMatrix()); osg::Vec3 eyeLocal = osg::Vec3(0.0f,0.0,0.0f)*eyeToLocalTransform; osg::Vec3 delta(0.0f,0.0f,1.0f); gl.Begin(GL_QUAD_STRIP); while(particle != 0) { const osg::Vec4& color = particle->getCurrentColor(); const osg::Vec3& pos = particle->getPosition(); const Particle* nextParticle = (particle->getNextParticle() != Particle::INVALID_INDEX) ? &_particles[particle->getNextParticle()] : 0; if (nextParticle) { const osg::Vec3& nextPos = nextParticle->getPosition(); osg::Vec3 startDelta = nextPos-pos; startDelta.normalize(); float distance2 = 0.0; // now skip particles of required for(unsigned int i=0; i<_maxNumberOfParticlesToSkip && ((distance2getNextParticle()!=Particle::INVALID_INDEX)); ++i) { nextParticle = &_particles[nextParticle->getNextParticle()]; const osg::Vec3& nextPos = nextParticle->getPosition(); delta = nextPos-pos; distance2 = (delta^startDelta).length2(); } delta = nextPos-pos; } osg::Vec3 normal( delta ^ (pos-eyeLocal)); normal.normalize(); normal *= particle->getCurrentSize(); osg::Vec3 bottom(pos-normal); osg::Vec3 top(pos+normal); gl.Color4f( color.r(), color.g(), color.b(), color.a() * particle->getCurrentAlpha()); gl.TexCoord2f( particle->getSTexCoord(), 0.0f ); gl.Vertex3fv(bottom.ptr()); gl.TexCoord2f( particle->getSTexCoord(), 1.0f ); gl.Vertex3fv(top.ptr()); particle = nextParticle; } gl.End(); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/Program.cpp0000644000175000017500000000042510234401315024373 0ustar albertoalberto#include #include #include osgParticle::Program::Program() : ParticleProcessor() { } osgParticle::Program::Program(const Program& copy, const osg::CopyOp& copyop) : ParticleProcessor(copy, copyop) { } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/ExplosionDebrisEffect.cpp0000644000175000017500000001250011732410624027216 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include using namespace osgParticle; ExplosionDebrisEffect::ExplosionDebrisEffect(bool automaticSetup): ParticleEffect(automaticSetup) { setDefaults(); _position.set(0.0f,0.0f,0.0f); _scale = 1.0f; _intensity = 1.0f; _emitterDuration = 0.1; _defaultParticleTemplate.setLifeTime(1.0+0.6*_scale); if (_automaticSetup) buildEffect(); } ExplosionDebrisEffect::ExplosionDebrisEffect(const osg::Vec3& position, float scale, float intensity) { setDefaults(); _position = position; _scale = scale; _intensity = intensity; _emitterDuration = 0.1; _defaultParticleTemplate.setLifeTime(1.0+0.6*_scale); if (_automaticSetup) buildEffect(); } ExplosionDebrisEffect::ExplosionDebrisEffect(const ExplosionDebrisEffect& copy, const osg::CopyOp& copyop): ParticleEffect(copy,copyop) { if (_automaticSetup) buildEffect(); } void ExplosionDebrisEffect::setDefaults() { ParticleEffect::setDefaults(); _textureFileName = "Images/particle.rgb"; _emitterDuration = 0.1; // set up unit particle. _defaultParticleTemplate.setLifeTime(1.0+0.6*_scale); _defaultParticleTemplate.setSizeRange(osgParticle::rangef(0.75f, 3.0f)); _defaultParticleTemplate.setAlphaRange(osgParticle::rangef(0.0f, 1.0f)); _defaultParticleTemplate.setColorRange(osgParticle::rangev4( osg::Vec4(0.5f, 0.5f, 0.0f, 1.0f), osg::Vec4(0.2f, 0.2f, 0.2f, 0.5f))); } void ExplosionDebrisEffect::setUpEmitterAndProgram() { // set up particle system if (!_particleSystem) { _particleSystem = new osgParticle::ParticleSystem; } if (_particleSystem.valid()) { _particleSystem->setDefaultAttributes(_textureFileName, false, false); osgParticle::Particle& ptemplate = _particleSystem->getDefaultParticleTemplate(); float radius = 0.05f*_scale; float density = 1000.0f; // 1000.0kg/m^3 ptemplate.setLifeTime(_defaultParticleTemplate.getLifeTime()); // the following ranges set the envelope of the respective // graphical properties in time. ptemplate.setSizeRange(osgParticle::rangef(radius*_defaultParticleTemplate.getSizeRange().minimum, radius*_defaultParticleTemplate.getSizeRange().maximum)); ptemplate.setAlphaRange(_defaultParticleTemplate.getAlphaRange()); ptemplate.setColorRange(_defaultParticleTemplate.getColorRange()); // these are physical properties of the particle ptemplate.setRadius(radius); ptemplate.setMass(density*radius*radius*radius*osg::PI*4.0f/3.0f); } // set up emitter if (!_emitter) { _emitter = new osgParticle::ModularEmitter; _emitter->setCounter(new osgParticle::RandomRateCounter); _emitter->setPlacer(new osgParticle::SectorPlacer); _emitter->setShooter(new osgParticle::RadialShooter); } if (_emitter.valid()) { _emitter->setParticleSystem(_particleSystem.get()); _emitter->setReferenceFrame(_useLocalParticleSystem? osgParticle::ParticleProcessor::ABSOLUTE_RF: osgParticle::ParticleProcessor::RELATIVE_RF); _emitter->setStartTime(_startTime); _emitter->setLifeTime(_emitterDuration); _emitter->setEndless(false); osgParticle::RandomRateCounter* counter = dynamic_cast(_emitter->getCounter()); if (counter) { counter->setRateRange(2000*_intensity,2000*_intensity); } osgParticle::SectorPlacer* placer = dynamic_cast(_emitter->getPlacer()); if (placer) { placer->setCenter(_position); placer->setRadiusRange(0.0f*_scale,0.25f*_scale); } osgParticle::RadialShooter* shooter = dynamic_cast(_emitter->getShooter()); if (shooter) { shooter->setThetaRange(0.0f, osg::PI_2); shooter->setInitialSpeedRange(1.0f*_scale,5.0f*_scale); } } // set up program. if (!_program) { _program = new osgParticle::FluidProgram; } if (_program.valid()) { _program->setParticleSystem(_particleSystem.get()); _program->setWind(_wind); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/ParticleSystemUpdater.cpp0000644000175000017500000000713311732410624027273 0ustar albertoalberto#include #include #include using namespace osg; osgParticle::ParticleSystemUpdater::ParticleSystemUpdater() : osg::Node(), _t0(-1), _frameNumber(0) { setCullingActive(false); } osgParticle::ParticleSystemUpdater::ParticleSystemUpdater(const ParticleSystemUpdater& copy, const osg::CopyOp& copyop) : osg::Node(copy, copyop), _t0(copy._t0), _frameNumber(0) { ParticleSystem_Vector::const_iterator i; for (i=copy._psv.begin(); i!=copy._psv.end(); ++i) { _psv.push_back(static_cast(copyop(i->get()))); } } void osgParticle::ParticleSystemUpdater::traverse(osg::NodeVisitor& nv) { osgUtil::CullVisitor *cv = dynamic_cast(&nv); if (cv) { if (nv.getFrameStamp()) { if( _frameNumber < nv.getFrameStamp()->getFrameNumber()) { _frameNumber = nv.getFrameStamp()->getFrameNumber(); double t = nv.getFrameStamp()->getSimulationTime(); if (_t0 != -1.0) { ParticleSystem_Vector::iterator i; for (i=_psv.begin(); i!=_psv.end(); ++i) { ParticleSystem* ps = i->get(); ParticleSystem::ScopedWriteLock lock(*(ps->getReadWriteMutex())); if (!ps->isFrozen() && (ps->getLastFrameNumber() >= (nv.getFrameStamp()->getFrameNumber() - 1) || !ps->getFreezeOnCull())) { ps->update(t - _t0, nv); } } } _t0 = t; } } else { OSG_WARN << "osgParticle::ParticleSystemUpdater::traverse(NodeVisitor&) requires a valid FrameStamp to function, particles not updated.\n"; } } Node::traverse(nv); } osg::BoundingSphere osgParticle::ParticleSystemUpdater::computeBound() const { return osg::BoundingSphere(); } bool osgParticle::ParticleSystemUpdater::addParticleSystem(ParticleSystem* ps) { _psv.push_back(ps); return true; } bool osgParticle::ParticleSystemUpdater::removeParticleSystem(ParticleSystem* ps) { unsigned int i = getParticleSystemIndex( ps ); if( i >= _psv.size() ) return false; removeParticleSystem( i ); return true; } bool osgParticle::ParticleSystemUpdater::removeParticleSystem(unsigned int pos, unsigned int numParticleSystemsToRemove) { if( (pos < _psv.size()) && (numParticleSystemsToRemove > 0) ) { unsigned int endOfRemoveRange = pos + numParticleSystemsToRemove; if( endOfRemoveRange > _psv.size() ) { OSG_DEBUG<<"Warning: ParticleSystem::removeParticleSystem(i,numParticleSystemsToRemove) has been passed an excessive number"< #include #include #include osgParticle::MultiSegmentPlacer::MultiSegmentPlacer() : Placer(), _total_length(0) { } osgParticle::MultiSegmentPlacer::MultiSegmentPlacer(const MultiSegmentPlacer& copy, const osg::CopyOp& copyop) : Placer(copy, copyop), _vx(copy._vx), _total_length(copy._total_length) { } void osgParticle::MultiSegmentPlacer::recompute_length() { Vertex_vector::iterator i; Vertex_vector::iterator i0 = _vx.begin(); _total_length = 0; for (i=_vx.begin(); i!=_vx.end(); ++i) { _total_length += (i->first - i0->first).length(); i->second = _total_length; i0 = i; } } void osgParticle::MultiSegmentPlacer::place(Particle* P) const { if (_vx.size() >= 2) { float x = rangef(0, _total_length).get_random(); Vertex_vector::const_iterator i; Vertex_vector::const_iterator i0 = _vx.begin(); const Vertex_vector::const_iterator vend = _vx.end(); for (i=_vx.begin(); i!=vend; ++i) { if (x <= i->second) { float t = (x - i0->second) / (i->second - i0->second); P->setPosition(i0->first + (i->first - i0->first) * t); return; } i0 = i; } } else { OSG_WARN << "this MultiSegmentPlacer has less than 2 vertices\n"; } } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/FluidFrictionOperator.cpp0000644000175000017500000000304111732410624027245 0ustar albertoalberto#include #include #include #include #include osgParticle::FluidFrictionOperator::FluidFrictionOperator(): Operator(), _coeff_A(0), _coeff_B(0), _density(0), _viscosity(0), _ovr_rad(0), _current_program(0) { setFluidToAir(); } osgParticle::FluidFrictionOperator::FluidFrictionOperator(const FluidFrictionOperator& copy, const osg::CopyOp& copyop) : Operator(copy, copyop), _coeff_A(copy._coeff_A), _coeff_B(copy._coeff_B), _density(copy._density), _viscosity(copy._viscosity), _ovr_rad(copy._ovr_rad), _current_program(0) { } void osgParticle::FluidFrictionOperator::operate(Particle* P, double dt) { float r = (_ovr_rad > 0)? _ovr_rad : P->getRadius(); osg::Vec3 v = P->getVelocity()-_wind; float vm = v.normalize(); float R = _coeff_A * r * vm + _coeff_B * r * r * vm * vm; osg::Vec3 Fr(-R * v.x(), -R * v.y(), -R * v.z()); #if 0 // Commenting out rotation of force vector rotation from local to world as the particle velocity itself // should already be in world coords so shouldn't need rotating. if (_current_program->getReferenceFrame() == ModularProgram::RELATIVE_RF) { Fr = _current_program->rotateLocalToWorld(Fr); } #endif // correct unwanted velocity increments osg::Vec3 dv = Fr * P->getMassInv() * dt; float dvl = dv.length(); if (dvl > vm) { dv *= vm / dvl; } P->addVelocity(dv); } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/CMakeLists.txt0000644000175000017500000000505311535432121025026 0ustar albertoalberto IF(DYNAMIC_OPENSCENEGRAPH) ADD_DEFINITIONS(-DOSGPARTICLE_LIBRARY) ELSE() ADD_DEFINITIONS(-DOSG_LIBRARY_STATIC) ENDIF() SET(LIB_NAME osgParticle) SET(HEADER_PATH ${OpenSceneGraph_SOURCE_DIR}/include/${LIB_NAME}) SET(TARGET_H ${HEADER_PATH}/AccelOperator ${HEADER_PATH}/AngularAccelOperator ${HEADER_PATH}/BoxPlacer ${HEADER_PATH}/CenteredPlacer ${HEADER_PATH}/ConnectedParticleSystem ${HEADER_PATH}/ConstantRateCounter ${HEADER_PATH}/Counter ${HEADER_PATH}/Emitter ${HEADER_PATH}/ExplosionDebrisEffect ${HEADER_PATH}/ExplosionEffect ${HEADER_PATH}/Export ${HEADER_PATH}/FireEffect ${HEADER_PATH}/FluidFrictionOperator ${HEADER_PATH}/FluidProgram ${HEADER_PATH}/ForceOperator ${HEADER_PATH}/Interpolator ${HEADER_PATH}/LinearInterpolator ${HEADER_PATH}/ModularEmitter ${HEADER_PATH}/ModularProgram ${HEADER_PATH}/MultiSegmentPlacer ${HEADER_PATH}/Operator ${HEADER_PATH}/Particle ${HEADER_PATH}/ParticleEffect ${HEADER_PATH}/ParticleProcessor ${HEADER_PATH}/ParticleSystem ${HEADER_PATH}/ParticleSystemUpdater ${HEADER_PATH}/Placer ${HEADER_PATH}/PointPlacer ${HEADER_PATH}/PrecipitationEffect ${HEADER_PATH}/Program ${HEADER_PATH}/RadialShooter ${HEADER_PATH}/RandomRateCounter ${HEADER_PATH}/range ${HEADER_PATH}/SectorPlacer ${HEADER_PATH}/SegmentPlacer ${HEADER_PATH}/Shooter ${HEADER_PATH}/SmokeEffect ${HEADER_PATH}/SmokeTrailEffect ${HEADER_PATH}/VariableRateCounter ${HEADER_PATH}/Version ${HEADER_PATH}/CompositePlacer ${HEADER_PATH}/AngularDampingOperator ${HEADER_PATH}/DampingOperator ${HEADER_PATH}/ExplosionOperator ${HEADER_PATH}/OrbitOperator ${HEADER_PATH}/DomainOperator ${HEADER_PATH}/BounceOperator ${HEADER_PATH}/SinkOperator ) # FIXME: For OS X, need flag for Framework or dylib SET(TARGET_SRC ConnectedParticleSystem.cpp Emitter.cpp ExplosionDebrisEffect.cpp ExplosionEffect.cpp FireEffect.cpp FluidFrictionOperator.cpp FluidProgram.cpp ModularEmitter.cpp ModularProgram.cpp MultiSegmentPlacer.cpp Particle.cpp ParticleEffect.cpp ParticleProcessor.cpp ParticleSystem.cpp ParticleSystemUpdater.cpp PrecipitationEffect.cpp Program.cpp SmokeEffect.cpp SmokeTrailEffect.cpp Version.cpp DomainOperator.cpp BounceOperator.cpp SinkOperator.cpp ${OPENSCENEGRAPH_VERSIONINFO_RC} ) SET(TARGET_LIBRARIES osgUtil osgDB osg OpenThreads ) SETUP_LIBRARY(${LIB_NAME}) openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/ParticleSystem.cpp0000644000175000017500000004470112147460033025750 0ustar albertoalberto#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define USE_LOCAL_SHADERS static double distance(const osg::Vec3& coord, const osg::Matrix& matrix) { // copied from CullVisitor.cpp return -(coord[0]*matrix(0,2)+coord[1]*matrix(1,2)+coord[2]*matrix(2,2)+matrix(3,2)); } osgParticle::ParticleSystem::ParticleSystem() : osg::Drawable(), _def_bbox(osg::Vec3(-10, -10, -10), osg::Vec3(10, 10, 10)), _alignment(BILLBOARD), _align_X_axis(1, 0, 0), _align_Y_axis(0, 1, 0), _particleScaleReferenceFrame(WORLD_COORDINATES), _useVertexArray(false), _useShaders(false), _dirty_uniforms(false), _doublepass(false), _frozen(false), _bmin(0, 0, 0), _bmax(0, 0, 0), _reset_bounds_flag(false), _bounds_computed(false), _def_ptemp(Particle()), _last_frame(0), _dirty_dt(true), _freeze_on_cull(false), _t0(0.0), _dt(0.0), _detail(1), _sortMode(NO_SORT), _visibilityDistance(-1.0), _draw_count(0) { // we don't support display lists because particle systems // are dynamic, and they always changes between frames setSupportsDisplayList(false); } osgParticle::ParticleSystem::ParticleSystem(const ParticleSystem& copy, const osg::CopyOp& copyop) : osg::Drawable(copy, copyop), _def_bbox(copy._def_bbox), _alignment(copy._alignment), _align_X_axis(copy._align_X_axis), _align_Y_axis(copy._align_Y_axis), _particleScaleReferenceFrame(copy._particleScaleReferenceFrame), _useVertexArray(copy._useVertexArray), _useShaders(copy._useShaders), _dirty_uniforms(copy._dirty_uniforms), _doublepass(copy._doublepass), _frozen(copy._frozen), _bmin(copy._bmin), _bmax(copy._bmax), _reset_bounds_flag(copy._reset_bounds_flag), _bounds_computed(copy._bounds_computed), _def_ptemp(copy._def_ptemp), _last_frame(copy._last_frame), _dirty_dt(copy._dirty_dt), _freeze_on_cull(copy._freeze_on_cull), _t0(copy._t0), _dt(copy._dt), _detail(copy._detail), _sortMode(copy._sortMode), _visibilityDistance(copy._visibilityDistance), _draw_count(0) { } osgParticle::ParticleSystem::~ParticleSystem() { } void osgParticle::ParticleSystem::update(double dt, osg::NodeVisitor& nv) { // reset bounds _reset_bounds_flag = true; if (_useShaders) { // Update shader uniforms // This slightly reduces the consumption of traversing the particle vector, because we // don't compute tile and angle attributes that are useleff for shaders. // At present, our lcoal shader implementation will ignore these particle props: // _cur_tile, _s_coord, _t_coord, _prev_pos, _prev_angle and _angle osg::StateSet* stateset = getOrCreateStateSet(); if (_dirty_uniforms) { osg::Uniform* u_vd = stateset->getUniform("visibilityDistance"); if (u_vd) u_vd->set((float)_visibilityDistance); _dirty_uniforms = false; } } for(unsigned int i=0; i<_particles.size(); ++i) { Particle& particle = _particles[i]; if (particle.isAlive()) { if (particle.update(dt, _useShaders)) { update_bounds(particle.getPosition(), particle.getCurrentSize()); } else { reuseParticle(i); } } } if (_sortMode != NO_SORT) { // sort particles osgUtil::CullVisitor* cv = dynamic_cast(&nv); if (cv) { osg::Matrixd modelview = *(cv->getModelViewMatrix()); double scale = (_sortMode==SORT_FRONT_TO_BACK ? -1.0 : 1.0); double deadDistance = DBL_MAX; for (unsigned int i=0; i<_particles.size(); ++i) { Particle& particle = _particles[i]; if (particle.isAlive()) particle.setDepth(distance(particle.getPosition(), modelview) * scale); else particle.setDepth(deadDistance); } std::sort(_particles.begin(), _particles.end()); // Repopulate the death stack as it will have been invalidated by the sort. unsigned int numDead = _deadparts.size(); if (numDead>0) { // clear the death stack _deadparts = Death_stack(); // copy the tail of the _particles vector as this will contain all the dead Particle thanks to the depth sort against DBL_MAX Particle* first_dead_ptr = &_particles[_particles.size()-numDead]; Particle* last_dead_ptr = &_particles[_particles.size()-1]; for(Particle* dead_ptr = first_dead_ptr; dead_ptr<=last_dead_ptr; ++dead_ptr) { _deadparts.push(dead_ptr); } } } } // force recomputing of bounding box on next frame dirtyBound(); } void osgParticle::ParticleSystem::drawImplementation(osg::RenderInfo& renderInfo) const { osg::State& state = *renderInfo.getState(); ScopedReadLock lock(_readWriteMutex); // update the frame count, so other objects can detect when // this particle system is culled _last_frame = state.getFrameStamp()->getFrameNumber(); // update the dirty flag of delta time, so next time a new request for delta time // will automatically cause recomputing _dirty_dt = true; // get the current modelview matrix osg::Matrix modelview = state.getModelViewMatrix(); // set up depth mask for first rendering pass #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE) glPushAttrib(GL_DEPTH_BUFFER_BIT); #endif glDepthMask(GL_FALSE); // render, first pass if (_useVertexArray) render_vertex_array(renderInfo); else single_pass_render(renderInfo, modelview); #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE) // restore depth mask settings glPopAttrib(); #endif // render, second pass if (_doublepass) { // set up color mask for second rendering pass #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE) glPushAttrib(GL_COLOR_BUFFER_BIT); #endif glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // render the particles onto the depth buffer if (_useVertexArray) render_vertex_array(renderInfo); else single_pass_render(renderInfo, modelview); #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE) // restore color mask settings glPopAttrib(); #endif } #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE) OSG_NOTICE<<"Warning: ParticleSystem::drawImplementation(..) not fully implemented."<setMode(GL_LIGHTING, lighting? osg::StateAttribute::ON: osg::StateAttribute::OFF); stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); osg::Material *material = new osg::Material; material->setSpecular(osg::Material::FRONT, osg::Vec4(0, 0, 0, 1)); material->setEmission(osg::Material::FRONT, osg::Vec4(0, 0, 0, 1)); material->setColorMode(lighting? osg::Material::AMBIENT_AND_DIFFUSE : osg::Material::OFF); stateset->setAttributeAndModes(material, osg::StateAttribute::ON); if (!texturefile.empty()) { osg::Texture2D *texture = new osg::Texture2D; texture->setImage(osgDB::readImageFile(texturefile)); texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR); texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR); texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::MIRROR); texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::MIRROR); stateset->setTextureAttributeAndModes(texture_unit, texture, osg::StateAttribute::ON); osg::TexEnv *texenv = new osg::TexEnv; texenv->setMode(osg::TexEnv::MODULATE); stateset->setTextureAttribute(texture_unit, texenv); } osg::BlendFunc *blend = new osg::BlendFunc; if (emissive_particles) { blend->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE); } else { blend->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA); } stateset->setAttributeAndModes(blend, osg::StateAttribute::ON); setStateSet(stateset); setUseVertexArray(false); setUseShaders(false); } void osgParticle::ParticleSystem::setDefaultAttributesUsingShaders(const std::string& texturefile, bool emissive_particles, int texture_unit) { osg::StateSet *stateset = new osg::StateSet; stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); osg::PointSprite *sprite = new osg::PointSprite; stateset->setTextureAttributeAndModes(texture_unit, sprite, osg::StateAttribute::ON); #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) stateset->setMode(GL_VERTEX_PROGRAM_POINT_SIZE, osg::StateAttribute::ON); #else OSG_NOTICE<<"Warning: ParticleSystem::setDefaultAttributesUsingShaders(..) not fully implemented."<setImage(osgDB::readImageFile(texturefile)); texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR); texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR); texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::MIRROR); texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::MIRROR); stateset->setTextureAttributeAndModes(texture_unit, texture, osg::StateAttribute::ON); } osg::BlendFunc *blend = new osg::BlendFunc; if (emissive_particles) { blend->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE); } else { blend->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA); } stateset->setAttributeAndModes(blend, osg::StateAttribute::ON); osg::Program *program = new osg::Program; #ifdef USE_LOCAL_SHADERS char vertexShaderSource[] = "uniform float visibilityDistance;\n" "varying vec3 basic_prop;\n" "\n" "void main(void)\n" "{\n" " basic_prop = gl_MultiTexCoord0.xyz;\n" " \n" " vec4 ecPos = gl_ModelViewMatrix * gl_Vertex;\n" " float ecDepth = -ecPos.z;\n" " \n" " if (visibilityDistance > 0.0)\n" " {\n" " if (ecDepth <= 0.0 || ecDepth >= visibilityDistance)\n" " basic_prop.x = -1.0;\n" " }\n" " \n" " gl_Position = ftransform();\n" " gl_ClipVertex = ecPos;\n" " \n" " vec4 color = gl_Color;\n" " color.a *= basic_prop.z;\n" " gl_FrontColor = color;\n" " gl_BackColor = gl_FrontColor;\n" "}\n"; char fragmentShaderSource[] = "uniform sampler2D baseTexture;\n" "varying vec3 basic_prop;\n" "\n" "void main(void)\n" "{\n" " if (basic_prop.x < 0.0) discard;\n" " gl_FragColor = gl_Color * texture2D(baseTexture, gl_TexCoord[0].xy);\n" "}\n"; program->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShaderSource)); program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource)); #else program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, osgDB::findDataFile("shaders/particle.vert"))); program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("shaders/particle.frag"))); #endif stateset->setAttributeAndModes(program, osg::StateAttribute::ON); stateset->addUniform(new osg::Uniform("visibilityDistance", (float)_visibilityDistance)); stateset->addUniform(new osg::Uniform("baseTexture", texture_unit)); setStateSet(stateset); setUseVertexArray(true); setUseShaders(true); } void osgParticle::ParticleSystem::single_pass_render(osg::RenderInfo& renderInfo, const osg::Matrix& modelview) const { _draw_count = 0; if (_particles.size() <= 0) return; osg::GLBeginEndAdapter* gl = &(renderInfo.getState()->getGLBeginEndAdapter()); float scale = sqrtf(static_cast(_detail)); osg::Vec3 xAxis = _align_X_axis; osg::Vec3 yAxis = _align_Y_axis; osg::Vec3 scaled_aligned_xAxis = _align_X_axis; osg::Vec3 scaled_aligned_yAxis = _align_Y_axis; float xScale = 1.0f; float yScale = 1.0f; if (_alignment==BILLBOARD) { xAxis = osg::Matrix::transform3x3(modelview,_align_X_axis); yAxis = osg::Matrix::transform3x3(modelview,_align_Y_axis); float lengthX2 = xAxis.length2(); float lengthY2 = yAxis.length2(); if (_particleScaleReferenceFrame==LOCAL_COORDINATES) { xScale = 1.0f/sqrtf(lengthX2); yScale = 1.0f/sqrtf(lengthY2); } else { xScale = 1.0f/lengthX2; yScale = 1.0f/lengthY2; } scaled_aligned_xAxis *= xScale; scaled_aligned_yAxis *= yScale; xAxis *= xScale; yAxis *= yScale; } bool requiresEndRender = false; const Particle* startParticle = &_particles[0]; if (startParticle->getShape() != Particle::USER) { startParticle->beginRender(gl); requiresEndRender = true; } else { // Enable writing depth mask when drawing user-defined particles glDepthMask(GL_TRUE); } for(unsigned int i=0; i<_particles.size(); i+=_detail) { const Particle* currentParticle = &_particles[i]; bool insideDistance = true; if (_sortMode != NO_SORT && _visibilityDistance>0.0) insideDistance = (currentParticle->getDepth()>=0.0 && currentParticle->getDepth()<=_visibilityDistance); if (currentParticle->isAlive() && insideDistance) { if (currentParticle->getShape() != startParticle->getShape()) { startParticle->endRender(gl); startParticle = currentParticle; if (currentParticle->getShape() != Particle::USER) { currentParticle->beginRender(gl); requiresEndRender = true; glDepthMask(GL_FALSE); } else glDepthMask(GL_TRUE); } ++_draw_count; if (currentParticle->getShape() == Particle::USER) { if (requiresEndRender) { startParticle->endRender(gl); requiresEndRender = false; } currentParticle->render(renderInfo, currentParticle->getPosition(), currentParticle->getAngle()); continue; } const osg::Vec3& angle = currentParticle->getAngle(); bool requiresRotation = (angle.x()!=0.0f || angle.y()!=0.0f || angle.z()!=0.0f); if (requiresRotation) { osg::Matrix R; R.makeRotate( angle.x(), osg::Vec3(1, 0, 0), angle.y(), osg::Vec3(0, 1, 0), angle.z(), osg::Vec3(0, 0, 1)); if (_alignment==BILLBOARD) { xAxis = osg::Matrix::transform3x3(R,scaled_aligned_xAxis); xAxis = osg::Matrix::transform3x3(modelview,xAxis); yAxis = osg::Matrix::transform3x3(R,scaled_aligned_yAxis); yAxis = osg::Matrix::transform3x3(modelview,yAxis); currentParticle->render(gl,currentParticle->getPosition(), xAxis, yAxis, scale); } else { xAxis = osg::Matrix::transform3x3(R, scaled_aligned_xAxis); yAxis = osg::Matrix::transform3x3(R, scaled_aligned_yAxis); currentParticle->render(gl,currentParticle->getPosition(), xAxis, yAxis, scale); } } else { currentParticle->render(gl,currentParticle->getPosition(), xAxis, yAxis, scale); } } } if (requiresEndRender) startParticle->endRender(gl); } void osgParticle::ParticleSystem::render_vertex_array(osg::RenderInfo& renderInfo) const { if (_particles.size() <= 0) return; // Compute the pointer and offsets Particle_vector::const_iterator itr = _particles.begin(); float* ptr = (float*)(&(*itr)); GLsizei stride = 0; if (_particles.size() > 1) { float* ptr1 = (float*)(&(*(itr+1))); stride = ptr1 - ptr; } GLsizei posOffset = (float*)(&(itr->_position)) - ptr; // Position GLsizei colorOffset = (float*)(&(itr->_current_color)) - ptr; // Color GLsizei velOffset = (float*)(&(itr->_velocity)) - ptr; // Velocity GLsizei propOffset = (float*)(&(itr->_alive)) - ptr; // Alive, size & alpha // Draw particles as arrays osg::State& state = *renderInfo.getState(); state.lazyDisablingOfVertexAttributes(); state.setColorPointer(4, GL_FLOAT, stride * sizeof(float), ptr + colorOffset); state.setVertexPointer(3, GL_FLOAT, stride * sizeof(float), ptr + posOffset); if (_useShaders) { state.setNormalPointer(GL_FLOAT, stride * sizeof(float), ptr + velOffset); state.setTexCoordPointer(0, 3, GL_FLOAT, stride * sizeof(float), ptr + propOffset); } state.applyDisablingOfVertexAttributes(); glDrawArrays(GL_POINTS, 0, _particles.size()); } osg::BoundingBox osgParticle::ParticleSystem::computeBound() const { if (!_bounds_computed) { return _def_bbox; } else { return osg::BoundingBox(_bmin,_bmax); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/Particle.cpp0000644000175000017500000002127711732410624024546 0ustar albertoalberto#include #include #include #include #include #include #include #include namespace { const float cosPI3 = cosf(osg::PI / 3.0f); const float sinPI3 = sinf(osg::PI / 3.0f); const float hex_texcoord_x1 = 0.5f + 0.5f * cosPI3; const float hex_texcoord_x2 = 0.5f - 0.5f * cosPI3; const float hex_texcoord_y1 = 0.5f + 0.5f * sinPI3; const float hex_texcoord_y2 = 0.5f - 0.5f * sinPI3; } osgParticle::Particle::Particle() : _shape(QUAD), _sr(0.2f, 0.2f), _ar(1, 0), _cr(osg::Vec4(1, 1, 1, 1), osg::Vec4(1, 1, 1, 1)), _si(new LinearInterpolator), _ai(new LinearInterpolator), _ci(new LinearInterpolator), _mustdie(false), _lifeTime(2), _radius(0.2f), _mass(0.1f), _massinv(10.0f), _prev_pos(0, 0, 0), _position(0, 0, 0), _velocity(0, 0, 0), _prev_angle(0, 0, 0), _angle(0, 0, 0), _angul_arvel(0, 0, 0), _t0(0), _alive(1.0f), _current_size(0.0f), _current_alpha(0.0f), _s_tile(1.0f), _t_tile(1.0f), _start_tile(0), _end_tile(0), _cur_tile(-1), _s_coord(0.0f), _t_coord(0.0f), _previousParticle(INVALID_INDEX), _nextParticle(INVALID_INDEX), _depth(0.0) { } bool osgParticle::Particle::update(double dt, bool onlyTimeStamp) { // this method should return false when the particle dies; // so, if we were instructed to die, do it now and return. if (_mustdie) { _alive = -1.0; return false; } double x = 0; // if we don't live forever, compute our normalized age. if (_lifeTime > 0) { x = _t0 / _lifeTime; } _t0 += dt; // if our age is over the lifetime limit, then die and return. if (x > 1) { _alive = -1.0; return false; } // compute the current values for size, alpha and color. if (_lifeTime <= 0) { if (dt == _t0) { _current_size = _sr.get_random(); _current_alpha = _ar.get_random(); _current_color = _cr.get_random(); } } else { _current_size = _si.get()->interpolate(x, _sr); _current_alpha = _ai.get()->interpolate(x, _ar); _current_color = _ci.get()->interpolate(x, _cr); } // update position _prev_pos = _position; _position += _velocity * dt; // return now if we indicate that only time stamp should be updated // the shader will handle remain properties in this case if (onlyTimeStamp) return true; //Compute the current texture tile based on our normalized age int currentTile = _start_tile + static_cast(x * getNumTiles()); //If the current texture tile is different from previous, then compute new texture coords if(currentTile != _cur_tile) { _cur_tile = currentTile; _s_coord = _s_tile * fmod(_cur_tile , 1.0 / _s_tile); _t_coord = 1.0 - _t_tile * (static_cast(_cur_tile * _t_tile) + 1); // OSG_NOTICE< osg::PI*2) _angle.x() -= osg::PI*2; if (_angle.x() < -osg::PI*2) _angle.x() += osg::PI*2; if (_angle.y() > osg::PI*2) _angle.y() -= osg::PI*2; if (_angle.y() < -osg::PI*2) _angle.y() += osg::PI*2; if (_angle.z() > osg::PI*2) _angle.z() -= osg::PI*2; if (_angle.z() < -osg::PI*2) _angle.z() += osg::PI*2; return true; } void osgParticle::Particle::render(osg::GLBeginEndAdapter* gl, const osg::Vec3& xpos, const osg::Vec3& px, const osg::Vec3& py, float scale) const { gl->Color4f( _current_color.x(), _current_color.y(), _current_color.z(), _current_color.w() * _current_alpha); osg::Vec3 p1(px * _current_size * scale); osg::Vec3 p2(py * _current_size * scale); switch (_shape) { case POINT: gl->Vertex3f(xpos.x(), xpos.y(), xpos.z()); break; case QUAD: gl->TexCoord2f(_s_coord, _t_coord); gl->Vertex3fv((xpos-(p1+p2)).ptr()); gl->TexCoord2f(_s_coord+_s_tile, _t_coord); gl->Vertex3fv((xpos+(p1-p2)).ptr()); gl->TexCoord2f(_s_coord+_s_tile, _t_coord+_t_tile); gl->Vertex3fv((xpos+(p1+p2)).ptr()); gl->TexCoord2f(_s_coord, _t_coord+_t_tile); gl->Vertex3fv((xpos-(p1-p2)).ptr()); break; case QUAD_TRIANGLESTRIP: gl->PushMatrix(); gl->Translatef(xpos.x(), xpos.y(), xpos.z()); // we must gl.Begin() and gl.End() here, because each particle is a single strip gl->Begin(GL_TRIANGLE_STRIP); gl->TexCoord2f(_s_coord+_s_tile, _t_coord+_t_tile); gl->Vertex3fv((p1+p2).ptr()); gl->TexCoord2f(_s_coord, _t_coord+_t_tile); gl->Vertex3fv((-p1+p2).ptr()); gl->TexCoord2f(_s_coord+_s_tile, _t_coord); gl->Vertex3fv((p1-p2).ptr()); gl->TexCoord2f(_s_coord, _t_coord); gl->Vertex3fv((-p1-p2).ptr()); gl->End(); gl->PopMatrix(); break; case HEXAGON: gl->PushMatrix(); gl->Translatef(xpos.x(), xpos.y(), xpos.z()); // we must gl.Begin() and gl.End() here, because each particle is a single fan gl->Begin(GL_TRIANGLE_FAN); gl->TexCoord2f(_s_coord + _s_tile * 0.5f, _t_coord + _t_tile * 0.5f); gl->Vertex3f(0,0,0); gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x1, _t_coord + _t_tile * hex_texcoord_y1); gl->Vertex3fv((p1*cosPI3+p2*sinPI3).ptr()); gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x2, _t_coord + _t_tile * hex_texcoord_y1); gl->Vertex3fv((-p1*cosPI3+p2*sinPI3).ptr()); gl->TexCoord2f(_s_coord, _t_coord + _t_tile * 0.5f); gl->Vertex3fv((-p1).ptr()); gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x2, _t_coord + _t_tile * hex_texcoord_y2); gl->Vertex3fv((-p1*cosPI3-p2*sinPI3).ptr()); gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x1, _t_coord + _t_tile * hex_texcoord_y2); gl->Vertex3fv((p1*cosPI3-p2*sinPI3).ptr()); gl->TexCoord2f(_s_coord + _s_tile, _t_coord + _t_tile * 0.5f); gl->Vertex3fv((p1).ptr()); gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x1, _t_coord + _t_tile * hex_texcoord_y1); gl->Vertex3fv((p1*cosPI3+p2*sinPI3).ptr()); gl->End(); gl->PopMatrix(); break; case LINE: { // Get the normalized direction of the particle, to be used in the // calculation of one of the linesegment endpoints. float vl = _velocity.length(); if (vl != 0) { osg::Vec3 v = _velocity * _current_size * scale / vl; gl->TexCoord1f(0); gl->Vertex3f(xpos.x(), xpos.y(), xpos.z()); gl->TexCoord1f(1); gl->Vertex3f(xpos.x() + v.x(), xpos.y() + v.y(), xpos.z() + v.z()); } } break; default: OSG_WARN << "Invalid shape for particles\n"; } } void osgParticle::Particle::render(osg::RenderInfo& renderInfo, const osg::Vec3& xpos, const osg::Vec3& xrot) const { #if defined(OSG_GL_MATRICES_AVAILABLE) if (_drawable.valid()) { bool requiresRotation = (xrot.x()!=0.0f || xrot.y()!=0.0f || xrot.z()!=0.0f); glColor4f(_current_color.x(), _current_color.y(), _current_color.z(), _current_color.w() * _current_alpha); glPushMatrix(); glTranslatef(xpos.x(), xpos.y(), xpos.z()); if (requiresRotation) { osg::Quat rotation(xrot.x(), osg::X_AXIS, xrot.y(), osg::Y_AXIS, xrot.z(), osg::Z_AXIS); #if defined(OSG_GLES1_AVAILABLE) glMultMatrixf(osg::Matrixf(rotation).ptr()); #else glMultMatrixd(osg::Matrixd(rotation).ptr()); #endif } _drawable->draw(renderInfo); glPopMatrix(); } #else OSG_NOTICE<<"Warning: Particle::render(..) not supported for user-defined shape."<getParticle(getPreviousParticle()); const osg::Vec3& previousPosition = previousParticle->getPosition(); const osg::Vec3& newPosition = getPosition(); float distance = (newPosition-previousPosition).length(); float s_coord_delta = 0.5f*distance/getCurrentSize(); float s_coord = previousParticle->_s_coord + s_coord_delta; setTextureTile(1,1,0); _cur_tile = 0; _s_coord = s_coord; _t_coord = 0.0f; } } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/BounceOperator.cpp0000644000175000017500000001404411732410624025724 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ // Written by Wang Rui, (C) 2010 #include #include #include using namespace osgParticle; void BounceOperator::handleTriangle( const Domain& domain, Particle* P, double dt ) { osg::Vec3 nextpos = P->getPosition() + P->getVelocity() * dt; float distance = domain.plane.distance( P->getPosition() ); if ( distance*domain.plane.distance(nextpos)>=0 ) return; osg::Vec3 normal = domain.plane.getNormal(); float nv = normal * P->getVelocity(); osg::Vec3 hitPoint = P->getPosition() - P->getVelocity() * (distance / nv); float upos = (hitPoint - domain.v1) * domain.s1; float vpos = (hitPoint - domain.v1) * domain.s2; if ( upos<0.0f || vpos<0.0f || (upos + vpos)>1.0f ) return; // Compute tangential and normal components of velocity osg::Vec3 vn = normal * nv; osg::Vec3 vt = P->getVelocity() - vn; // Compute new velocity if ( vt.length2()<=_cutoff ) P->setVelocity( vt - vn*_resilience ); else P->setVelocity( vt*(1.0f-_friction) - vn*_resilience ); } void BounceOperator::handleRectangle( const Domain& domain, Particle* P, double dt ) { osg::Vec3 nextpos = P->getPosition() + P->getVelocity() * dt; float distance = domain.plane.distance( P->getPosition() ); if ( distance*domain.plane.distance(nextpos)>=0 ) return; osg::Vec3 normal = domain.plane.getNormal(); float nv = normal * P->getVelocity(); osg::Vec3 hitPoint = P->getPosition() - P->getVelocity() * (distance / nv); float upos = (hitPoint - domain.v1) * domain.s1; float vpos = (hitPoint - domain.v1) * domain.s2; if ( upos<0.0f || upos>1.0f || vpos<0.0f || vpos>1.0f ) return; // Compute tangential and normal components of velocity osg::Vec3 vn = normal * nv; osg::Vec3 vt = P->getVelocity() - vn; // Compute new velocity if ( vt.length2()<=_cutoff ) P->setVelocity( vt - vn*_resilience ); else P->setVelocity( vt*(1.0f-_friction) - vn*_resilience ); } void BounceOperator::handlePlane( const Domain& domain, Particle* P, double dt ) { osg::Vec3 nextpos = P->getPosition() + P->getVelocity() * dt; float distance = domain.plane.distance( P->getPosition() ); if ( distance*domain.plane.distance(nextpos)>=0 ) return; osg::Vec3 normal = domain.plane.getNormal(); float nv = normal * P->getVelocity(); // Compute tangential and normal components of velocity osg::Vec3 vn = normal * nv; osg::Vec3 vt = P->getVelocity() - vn; // Compute new velocity if ( vt.length2()<=_cutoff ) P->setVelocity( vt - vn*_resilience ); else P->setVelocity( vt*(1.0f-_friction) - vn*_resilience ); } void BounceOperator::handleSphere( const Domain& domain, Particle* P, double dt ) { osg::Vec3 nextpos = P->getPosition() + P->getVelocity() * dt; float distance1 = (P->getPosition() - domain.v1).length(); if ( distance1<=domain.r1 ) // Within the sphere { float distance2 = (nextpos - domain.v1).length(); if ( distance2<=domain.r1 ) return; // Bounce back in if going outside osg::Vec3 normal = domain.v1 - P->getPosition(); normal.normalize(); float nmag = P->getVelocity() * normal; // Compute tangential and normal components of velocity osg::Vec3 vn = normal * nmag; osg::Vec3 vt = P->getVelocity() - vn; if ( nmag<0 ) vn = -vn; // Compute new velocity float tanscale = (vt.length2()<=_cutoff) ? 1.0f : (1.0f - _friction); P->setVelocity( vt * tanscale + vn * _resilience ); // Make sure the particle is fixed to stay inside nextpos = P->getPosition() + P->getVelocity() * dt; distance2 = (nextpos - domain.v1).length(); if ( distance2>domain.r1 ) { normal = domain.v1 - nextpos; normal.normalize(); osg::Vec3 wishPoint = domain.v1 - normal * (0.999f * domain.r1); P->setVelocity( (wishPoint - P->getPosition()) / dt ); } } else // Outside the sphere { float distance2 = (nextpos - domain.v1).length(); if ( distance2>domain.r1 ) return; // Bounce back out if going inside osg::Vec3 normal = P->getPosition() - domain.v1; normal.normalize(); float nmag = P->getVelocity() * normal; // Compute tangential and normal components of velocity osg::Vec3 vn = normal * nmag; osg::Vec3 vt = P->getVelocity() - vn; if ( nmag<0 ) vn = -vn; // Compute new velocity float tanscale = (vt.length2()<=_cutoff) ? 1.0f : (1.0f - _friction); P->setVelocity( vt * tanscale + vn * _resilience ); } } void BounceOperator::handleDisk( const Domain& domain, Particle* P, double dt ) { osg::Vec3 nextpos = P->getPosition() + P->getVelocity() * dt; float distance = domain.plane.distance( P->getPosition() ); if ( distance*domain.plane.distance(nextpos)>=0 ) return; osg::Vec3 normal = domain.plane.getNormal(); float nv = normal * P->getVelocity(); osg::Vec3 hitPoint = P->getPosition() - P->getVelocity() * (distance / nv); float radius = (hitPoint - domain.v1).length(); if ( radius>domain.r1 || radiusgetVelocity() - vn; // Compute new velocity if ( vt.length2()<=_cutoff ) P->setVelocity( vt - vn*_resilience ); else P->setVelocity( vt*(1.0f-_friction) - vn*_resilience ); } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/ParticleProcessor.cpp0000644000175000017500000001132011732410624026432 0ustar albertoalberto#include #include #include #include #include #include #include using namespace osg; osgParticle::ParticleProcessor::ParticleProcessor() : osg::Node(), _rf(RELATIVE_RF), _enabled(true), _t0(-1), _ps(0), _first_ltw_compute(true), _need_ltw_matrix(false), _first_wtl_compute(true), _need_wtl_matrix(false), _current_nodevisitor(0), _endless(true), _lifeTime(0.0), _startTime(0.0), _currentTime(0.0), _resetTime(0.0), _frameNumber(0) { setCullingActive(false); } osgParticle::ParticleProcessor::ParticleProcessor(const ParticleProcessor& copy, const osg::CopyOp& copyop) : osg::Node(copy, copyop), _rf(copy._rf), _enabled(copy._enabled), _t0(copy._t0), _ps(static_cast(copyop(copy._ps.get()))), _first_ltw_compute(copy._first_ltw_compute), _need_ltw_matrix(copy._need_ltw_matrix), _first_wtl_compute(copy._first_wtl_compute), _need_wtl_matrix(copy._need_wtl_matrix), _current_nodevisitor(0), _endless(copy._endless), _lifeTime(copy._lifeTime), _startTime(copy._startTime), _currentTime(copy._currentTime), _resetTime(copy._resetTime) { } void osgParticle::ParticleProcessor::traverse(osg::NodeVisitor& nv) { // typecast the NodeVisitor to CullVisitor osgUtil::CullVisitor* cv = dynamic_cast(&nv); // continue only if the visitor actually is a cull visitor if (cv) { // continue only if the particle system is valid if (_ps.valid()) { if (nv.getFrameStamp()) { ParticleSystem::ScopedWriteLock lock(*(_ps->getReadWriteMutex())); //added- 1/17/06- bgandere@nps.edu //a check to make sure we havent updated yet this frame if(_frameNumber < nv.getFrameStamp()->getFrameNumber()) { // retrieve the current time double t = nv.getFrameStamp()->getSimulationTime(); // reset this processor if we've reached the reset point if ((_currentTime >= _resetTime) && (_resetTime > 0)) { _currentTime = 0; _t0 = -1; } // skip if we haven't initialized _t0 yet if (_t0 != -1) { // check whether the processor is alive bool alive = false; if (_currentTime >= _startTime) { if (_endless || (_currentTime < (_startTime + _lifeTime))) alive = true; } // update current time _currentTime += t - _t0; // process only if the particle system is not frozen/culled if (alive && _enabled && !_ps->isFrozen() && ((_ps->getLastFrameNumber()+1) >= (nv.getFrameStamp()->getFrameNumber()) || !_ps->getFreezeOnCull())) { // initialize matrix flags _need_ltw_matrix = true; _need_wtl_matrix = true; _current_nodevisitor = &nv; // do some process (unimplemented in this base class) process( t - _t0 ); } else { //The values of _previous_wtl_matrix and _previous_ltw_matrix will be invalid //since processing was skipped for this frame _first_ltw_compute = true; _first_wtl_compute = true; } } _t0 = t; } //added- 1/17/06- bgandere@nps.edu //updates the _frameNumber, keeping it current _frameNumber = nv.getFrameStamp()->getFrameNumber(); } else { OSG_WARN << "osgParticle::ParticleProcessor::traverse(NodeVisitor&) requires a valid FrameStamp to function, particles not updated.\n"; } } else { OSG_WARN << "ParticleProcessor \"" << getName() << "\": invalid particle system\n"; } } // call the inherited method Node::traverse(nv); } osg::BoundingSphere osgParticle::ParticleProcessor::computeBound() const { return osg::BoundingSphere(); } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/Emitter.cpp0000644000175000017500000000055111732410624024404 0ustar albertoalberto#include #include #include osgParticle::Emitter::Emitter() : ParticleProcessor(), _usedeftemp(true) { } osgParticle::Emitter::Emitter(const Emitter& copy, const osg::CopyOp& copyop) : ParticleProcessor(copy, copyop), _usedeftemp(copy._usedeftemp), _ptemp(copy._ptemp) { } openscenegraph-3.2.3/OpenSceneGraph/src/osgParticle/FireEffect.cpp0000644000175000017500000001254411732410624025002 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include using namespace osgParticle; FireEffect::FireEffect(bool automaticSetup): ParticleEffect(automaticSetup) { setDefaults(); _position.set(0.0f,0.0f,0.0f); _scale = 1.0f; _intensity = 1.0f; _emitterDuration = 60.0; _defaultParticleTemplate.setLifeTime(0.5+0.1*_scale); if (_automaticSetup) buildEffect(); } FireEffect::FireEffect(const osg::Vec3& position, float scale, float intensity) { setDefaults(); _position = position; _scale = scale; _intensity = intensity; _emitterDuration = 60.0; _defaultParticleTemplate.setLifeTime(0.5+0.1*_scale); if (_automaticSetup) buildEffect(); } FireEffect::FireEffect(const FireEffect& copy, const osg::CopyOp& copyop): ParticleEffect(copy,copyop) { if (_automaticSetup) buildEffect(); } void FireEffect::setDefaults() { ParticleEffect::setDefaults(); _textureFileName = "Images/smoke.rgb"; _emitterDuration = 60.0; // set up unit particle. _defaultParticleTemplate.setLifeTime(0.5+0.1*_scale); _defaultParticleTemplate.setSizeRange(osgParticle::rangef(0.75f, 3.0f)); _defaultParticleTemplate.setAlphaRange(osgParticle::rangef(0.1f, 1.0f)); _defaultParticleTemplate.setColorRange(osgParticle::rangev4( osg::Vec4(1, 0.8f, 0.2f, 1.0f), osg::Vec4(1, 0.3f, 0.2f, 0.0f))); } void FireEffect::setUpEmitterAndProgram() { // set up particle system if (!_particleSystem) { _particleSystem = new osgParticle::ParticleSystem; } if (_particleSystem.valid()) { _particleSystem->setDefaultAttributes(_textureFileName, false, false); osgParticle::Particle& ptemplate = _particleSystem->getDefaultParticleTemplate(); float radius = 0.25f*_scale; float density = 0.5f; // 0.5kg/m^3 ptemplate.setLifeTime(_defaultParticleTemplate.getLifeTime()); // the following ranges set the envelope of the respective // graphical properties in time. ptemplate.setSizeRange(osgParticle::rangef(radius*_defaultParticleTemplate.getSizeRange().minimum, radius*_defaultParticleTemplate.getSizeRange().maximum)); ptemplate.setAlphaRange(_defaultParticleTemplate.getAlphaRange()); ptemplate.setColorRange(_defaultParticleTemplate.getColorRange()); // these are physical properties of the particle // these are physical properties of the particle ptemplate.setRadius(radius); ptemplate.setMass(density*radius*radius*radius*osg::PI*4.0f/3.0f); } // set up emitter if (!_emitter) { _emitter = new osgParticle::ModularEmitter; _emitter->setNumParticlesToCreateMovementCompensationRatio(1.5f); _emitter->setCounter(new osgParticle::RandomRateCounter); _emitter->setPlacer(new osgParticle::SectorPlacer); _emitter->setShooter(new osgParticle::RadialShooter); } if (_emitter.valid()) { _emitter->setParticleSystem(_particleSystem.get()); _emitter->setReferenceFrame(_useLocalParticleSystem? osgParticle::ParticleProcessor::ABSOLUTE_RF: osgParticle::ParticleProcessor::RELATIVE_RF); _emitter->setStartTime(_startTime); _emitter->setLifeTime(_emitterDuration); _emitter->setEndless(false); osgParticle::RandomRateCounter* counter = dynamic_cast(_emitter->getCounter()); if (counter) { counter->setRateRange(10*_intensity,15*_intensity); } osgParticle::SectorPlacer* placer = dynamic_cast(_emitter->getPlacer()); if (placer) { placer->setCenter(_position); placer->setRadiusRange(0.0f*_scale,0.25f*_scale); } osgParticle::RadialShooter* shooter = dynamic_cast(_emitter->getShooter()); if (shooter) { shooter->setThetaRange(0.0f, osg::PI_4); shooter->setInitialSpeedRange(0.0f*_scale,0.0f*_scale); } } // set up program. if (!_program) { _program = new osgParticle::FluidProgram; } if (_program.valid()) { _program->setParticleSystem(_particleSystem.get()); _program->setWind(_wind); } } openscenegraph-3.2.3/OpenSceneGraph/src/osgText/0000755000175000017500000000000012674261217021457 5ustar albertoalbertoopenscenegraph-3.2.3/OpenSceneGraph/src/osgText/Text.cpp0000644000175000017500000021071011732410624023100 0ustar albertoalberto/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include using namespace osg; using namespace osgText; //#define TREES_CODE_FOR_MAKING_SPACES_EDITABLE Text::Text(): _enableDepthWrites(true), _backdropType(NONE), _backdropImplementation(DELAYED_DEPTH_WRITES), _backdropHorizontalOffset(0.07f), _backdropVerticalOffset(0.07f), _backdropColor(0.0f, 0.0f, 0.0f, 1.0f), _colorGradientMode(SOLID), _colorGradientTopLeft(1.0f, 0.0f, 0.0f, 1.0f), _colorGradientBottomLeft(0.0f, 1.0f, 0.0f, 1.0f), _colorGradientBottomRight(0.0f, 0.0f, 1.0f, 1.0f), _colorGradientTopRight(1.0f, 1.0f, 1.0f, 1.0f) {} Text::Text(const Text& text,const osg::CopyOp& copyop): osgText::TextBase(text,copyop), _enableDepthWrites(text._enableDepthWrites), _backdropType(text._backdropType), _backdropImplementation(text._backdropImplementation), _backdropHorizontalOffset(text._backdropHorizontalOffset), _backdropVerticalOffset(text._backdropVerticalOffset), _backdropColor(text._backdropColor), _colorGradientMode(text._colorGradientMode), _colorGradientTopLeft(text._colorGradientTopLeft), _colorGradientBottomLeft(text._colorGradientBottomLeft), _colorGradientBottomRight(text._colorGradientBottomRight), _colorGradientTopRight(text._colorGradientTopRight) { computeGlyphRepresentation(); } Text::~Text() { } void Text::setFont(osg::ref_ptr font) { if (_font==font) return; osg::StateSet* previousFontStateSet = _font.valid() ? _font->getStateSet() : Font::getDefaultFont()->getStateSet(); osg::StateSet* newFontStateSet = font.valid() ? font->getStateSet() : Font::getDefaultFont()->getStateSet(); if (getStateSet() == previousFontStateSet) { setStateSet( newFontStateSet ); } TextBase::setFont(font); } Font* Text::getActiveFont() { return _font.valid() ? _font.get() : Font::getDefaultFont().get(); } const Font* Text::getActiveFont() const { return _font.valid() ? _font.get() : Font::getDefaultFont().get(); } String::iterator Text::computeLastCharacterOnLine(osg::Vec2& cursor, String::iterator first,String::iterator last) { Font* activefont = getActiveFont(); if (!activefont) return last; float hr = _characterHeight; float wr = hr/getCharacterAspectRatio(); bool kerning = true; unsigned int previous_charcode = 0; String::iterator lastChar = first; for(bool outOfSpace=false;lastChar!=last;++lastChar) { unsigned int charcode = *lastChar; if (charcode=='\n') { return lastChar; } Glyph* glyph = activefont->getGlyph(_fontSize, charcode); if (glyph) { float width = (float)(glyph->getWidth()) * wr; if (_layout==RIGHT_TO_LEFT) { cursor.x() -= glyph->getHorizontalAdvance() * wr; } // adjust cursor position w.r.t any kerning. if (kerning && previous_charcode) { switch(_layout) { case LEFT_TO_RIGHT: { osg::Vec2 delta(activefont->getKerning(previous_charcode,charcode,_kerningType)); cursor.x() += delta.x() * wr; cursor.y() += delta.y() * hr; break; } case RIGHT_TO_LEFT: { osg::Vec2 delta(activefont->getKerning(charcode,previous_charcode,_kerningType)); cursor.x() -= delta.x() * wr; cursor.y() -= delta.y() * hr; break; } case VERTICAL: break; // no kerning when vertical. } // check to see if we are still within line if not move to next line. } switch(_layout) { case LEFT_TO_RIGHT: { if (_maximumWidth>0.0f && cursor.x()+width>_maximumWidth) outOfSpace=true; if(_maximumHeight>0.0f && cursor.y()<-_maximumHeight) outOfSpace=true; break; } case RIGHT_TO_LEFT: { if (_maximumWidth>0.0f && cursor.x()<-_maximumWidth) outOfSpace=true; if(_maximumHeight>0.0f && cursor.y()<-_maximumHeight) outOfSpace=true; break; } case VERTICAL: if (_maximumHeight>0.0f && cursor.y()<-_maximumHeight) outOfSpace=true; break; } // => word boundary detection & wrapping if (outOfSpace) break; // move the cursor onto the next character. switch(_layout) { case LEFT_TO_RIGHT: cursor.x() += glyph->getHorizontalAdvance() * wr; break; case VERTICAL: cursor.y() -= glyph->getVerticalAdvance() *hr; break; case RIGHT_TO_LEFT: break; // nop. } previous_charcode = charcode; } } // word boundary detection & wrapping if (lastChar!=last) { String::iterator lastValidChar = lastChar; String::iterator prevChar; while (lastValidChar != first){ prevChar = lastValidChar - 1; // last char is after a hyphen if(*lastValidChar == '-') return lastValidChar + 1; // last char is start of whitespace if((*lastValidChar == ' ' || *lastValidChar == '\n') && (*prevChar != ' ' && *prevChar != '\n')) return lastValidChar; // Subtract off glyphs from the cursor position (to correctly center text) if(*prevChar != '-') { Glyph* glyph = activefont->getGlyph(_fontSize, *prevChar); if (glyph) { switch(_layout) { case LEFT_TO_RIGHT: cursor.x() -= glyph->getHorizontalAdvance() * wr; break; case VERTICAL: cursor.y() += glyph->getVerticalAdvance() * hr; break; case RIGHT_TO_LEFT: break; // nop. } } } lastValidChar = prevChar; } } return lastChar; } void Text::computeGlyphRepresentation() { Font* activefont = getActiveFont(); if (!activefont) return; _textureGlyphQuadMap.clear(); _lineCount = 0; if (_text.empty()) { _textBB.set(0,0,0,0,0,0);//no size text TextBase::computePositions(); //to reset the origin return; } //OpenThreads::ScopedLock lock(*(activefont->getSerializeFontCallsMutex())); // initialize bounding box, it will be expanded during glyph position calculation _textBB.init(); osg::Vec2 startOfLine_coords(0.0f,0.0f); osg::Vec2 cursor(startOfLine_coords); osg::Vec2 local(0.0f,0.0f); unsigned int previous_charcode = 0; unsigned int linelength = 0; bool horizontal = _layout!=VERTICAL; bool kerning = true; unsigned int lineNumber = 0; float hr = _characterHeight; float wr = hr/getCharacterAspectRatio(); for(String::iterator itr=_text.begin(); itr!=_text.end(); ) { // record the start of the current line String::iterator startOfLine_itr = itr; // find the end of the current line. osg::Vec2 endOfLine_coords(cursor); String::iterator endOfLine_itr = computeLastCharacterOnLine(endOfLine_coords, itr,_text.end()); linelength = endOfLine_itr - startOfLine_itr; // Set line position to correct alignment. switch(_layout) { case LEFT_TO_RIGHT: { switch(_alignment) { // nothing to be done for these //case LEFT_TOP: //case LEFT_CENTER: //case LEFT_BOTTOM: //case LEFT_BASE_LINE: //case LEFT_BOTTOM_BASE_LINE: // break; case CENTER_TOP: case CENTER_CENTER: case CENTER_BOTTOM: case CENTER_BASE_LINE: case CENTER_BOTTOM_BASE_LINE: cursor.x() = (cursor.x() - endOfLine_coords.x()) * 0.5f; break; case RIGHT_TOP: case RIGHT_CENTER: case RIGHT_BOTTOM: case RIGHT_BASE_LINE: case RIGHT_BOTTOM_BASE_LINE: cursor.x() = cursor.x() - endOfLine_coords.x(); break; default: break; } break; } case RIGHT_TO_LEFT: { switch(_alignment) { case LEFT_TOP: case LEFT_CENTER: case LEFT_BOTTOM: case LEFT_BASE_LINE: case LEFT_BOTTOM_BASE_LINE: cursor.x() = 2*cursor.x() - endOfLine_coords.x(); break; case CENTER_TOP: case CENTER_CENTER: case CENTER_BOTTOM: case CENTER_BASE_LINE: case CENTER_BOTTOM_BASE_LINE: cursor.x() = cursor.x() + (cursor.x() - endOfLine_coords.x()) * 0.5f; break; // nothing to be done for these //case RIGHT_TOP: //case RIGHT_CENTER: //case RIGHT_BOTTOM: //case RIGHT_BASE_LINE: //case RIGHT_BOTTOM_BASE_LINE: // break; default: break; } break; } case VERTICAL: { switch(_alignment) { // TODO: current behaviour top baselines lined up in both cases - need to implement // top of characters alignment - Question is this necessary? // ... otherwise, nothing to be done for these 6 cases //case LEFT_TOP: //case CENTER_TOP: //case RIGHT_TOP: // break; //case LEFT_BASE_LINE: //case CENTER_BASE_LINE: //case RIGHT_BASE_LINE: // break; case LEFT_CENTER: case CENTER_CENTER: case RIGHT_CENTER: cursor.y() = cursor.y() + (cursor.y() - endOfLine_coords.y()) * 0.5f; break; case LEFT_BOTTOM_BASE_LINE: case CENTER_BOTTOM_BASE_LINE: case RIGHT_BOTTOM_BASE_LINE: cursor.y() = cursor.y() - (linelength * _characterHeight); break; case LEFT_BOTTOM: case CENTER_BOTTOM: case RIGHT_BOTTOM: cursor.y() = 2*cursor.y() - endOfLine_coords.y(); break; default: break; } break; } } if (itr!=endOfLine_itr) { for(;itr!=endOfLine_itr;++itr) { unsigned int charcode = *itr; Glyph* glyph = activefont->getGlyph(_fontSize, charcode); if (glyph) { float width = (float)(glyph->getWidth()) * wr; float height = (float)(glyph->getHeight()) * hr; if (_layout==RIGHT_TO_LEFT) { cursor.x() -= glyph->getHorizontalAdvance() * wr; } // adjust cursor position w.r.t any kerning. if (kerning && previous_charcode) { switch(_layout) { case LEFT_TO_RIGHT: { osg::Vec2 delta(activefont->getKerning(previous_charcode,charcode,_kerningType)); cursor.x() += delta.x() * wr; cursor.y() += delta.y() * hr; break; } case RIGHT_TO_LEFT: { osg::Vec2 delta(activefont->getKerning(charcode,previous_charcode,_kerningType)); cursor.x() -= delta.x() * wr; cursor.y() -= delta.y() * hr; break; } case VERTICAL: break; // no kerning when vertical. } } local = cursor; osg::Vec2 bearing(horizontal?glyph->getHorizontalBearing():glyph->getVerticalBearing()); local.x() += bearing.x() * wr; local.y() += bearing.y() * hr; GlyphQuads& glyphquad = _textureGlyphQuadMap[glyph->getTexture()]; glyphquad._glyphs.push_back(glyph); glyphquad._lineNumbers.push_back(lineNumber); // Adjust coordinates and texture coordinates to avoid // clipping the edges of antialiased characters. osg::Vec2 mintc = glyph->getMinTexCoord(); osg::Vec2 maxtc = glyph->getMaxTexCoord(); osg::Vec2 vDiff = maxtc - mintc; float fHorizTCMargin = 1.0f / glyph->getTexture()->getTextureWidth(); float fVertTCMargin = 1.0f / glyph->getTexture()->getTextureHeight(); float fHorizQuadMargin = vDiff.x() == 0.0f ? 0.0f : width * fHorizTCMargin / vDiff.x(); float fVertQuadMargin = vDiff.y() == 0.0f ? 0.0f : height * fVertTCMargin / vDiff.y(); mintc.x() -= fHorizTCMargin; mintc.y() -= fVertTCMargin; maxtc.x() += fHorizTCMargin; maxtc.y() += fVertTCMargin; // set up the coords of the quad osg::Vec2 upLeft = local+osg::Vec2(0.0f-fHorizQuadMargin,height+fVertQuadMargin); osg::Vec2 lowLeft = local+osg::Vec2(0.0f-fHorizQuadMargin,0.0f-fVertQuadMargin); osg::Vec2 lowRight = local+osg::Vec2(width+fHorizQuadMargin,0.0f-fVertQuadMargin); osg::Vec2 upRight = local+osg::Vec2(width+fHorizQuadMargin,height+fVertQuadMargin); glyphquad._coords.push_back(upLeft); glyphquad._coords.push_back(lowLeft); glyphquad._coords.push_back(lowRight); glyphquad._coords.push_back(upRight); // set up the tex coords of the quad glyphquad._texcoords.push_back(osg::Vec2(mintc.x(),maxtc.y())); glyphquad._texcoords.push_back(osg::Vec2(mintc.x(),mintc.y())); glyphquad._texcoords.push_back(osg::Vec2(maxtc.x(),mintc.y())); glyphquad._texcoords.push_back(osg::Vec2(maxtc.x(),maxtc.y())); // move the cursor onto the next character. // also expand bounding box switch(_layout) { case LEFT_TO_RIGHT: cursor.x() += glyph->getHorizontalAdvance() * wr; _textBB.expandBy(osg::Vec3(lowLeft.x(), lowLeft.y(), 0.0f)); //lower left corner _textBB.expandBy(osg::Vec3(upRight.x(), upRight.y(), 0.0f)); //upper right corner break; case VERTICAL: cursor.y() -= glyph->getVerticalAdvance() * hr; _textBB.expandBy(osg::Vec3(upLeft.x(),upLeft.y(),0.0f)); //upper left corner _textBB.expandBy(osg::Vec3(lowRight.x(),lowRight.y(),0.0f)); //lower right corner break; case RIGHT_TO_LEFT: _textBB.expandBy(osg::Vec3(lowRight.x(),lowRight.y(),0.0f)); //lower right corner _textBB.expandBy(osg::Vec3(upLeft.x(),upLeft.y(),0.0f)); //upper left corner break; } previous_charcode = charcode; } } // skip over spaces and return. while (itr != _text.end() && *itr==' ') ++itr; if (itr != _text.end() && *itr=='\n') ++itr; } else { ++itr; } // move to new line. switch(_layout) { case LEFT_TO_RIGHT: { startOfLine_coords.y() -= _characterHeight * (1.0 + _lineSpacing); cursor = startOfLine_coords; previous_charcode = 0; _lineCount++; break; } case RIGHT_TO_LEFT: { startOfLine_coords.y() -= _characterHeight * (1.0 + _lineSpacing); cursor = startOfLine_coords; previous_charcode = 0; _lineCount++; break; } case VERTICAL: { startOfLine_coords.x() += _characterHeight/getCharacterAspectRatio() * (1.0 + _lineSpacing); cursor = startOfLine_coords; previous_charcode = 0; // because _lineCount is the max vertical no. of characters.... _lineCount = (_lineCount >linelength)?_lineCount:linelength; } break; } ++lineNumber; } TextBase::computePositions(); computeBackdropBoundingBox(); computeBoundingBoxMargin(); computeColorGradients(); } // Returns false if there are no glyphs and the width/height values are invalid. // Also sets avg_width and avg_height to 0.0f if the value is invalid. // This method is used several times in a loop for the same object which will produce the same values. // Further optimization may try saving these values instead of recomputing them. bool Text::computeAverageGlyphWidthAndHeight(float& avg_width, float& avg_height) const { float width = 0.0f; float height = 0.0f; float running_width = 0.0f; float running_height = 0.0f; avg_width = 0.0f; avg_height = 0.0f; int counter = 0; unsigned int i; bool is_valid_size = true; // This section is going to try to compute the average width and height // for a character among the text. The reason I shift by an // average amount per-character instead of shifting each character // by its per-instance amount is because it may look strange to see // the individual backdrop text letters not space themselves the same // way the foreground text does. Using one value gives uniformity. // Note: This loop is repeated for each context. I think it may produce // the same values regardless of context. This code be optimized by moving // this loop outside the loop. for(TextureGlyphQuadMap::const_iterator const_titr=_textureGlyphQuadMap.begin(); const_titr!=_textureGlyphQuadMap.end(); ++const_titr) { const GlyphQuads& glyphquad = const_titr->second; const GlyphQuads::Coords2& coords2 = glyphquad._coords; for(i = 0; i < coords2.size(); i+=4) { width = coords2[i+2].x() - coords2[i].x(); height = coords2[i].y() - coords2[i+1].y(); running_width += width; running_height += height; counter++; } } if(0 == counter) { is_valid_size = false; } else { avg_width = running_width/counter; avg_height = running_height/counter; } return is_valid_size; } void Text::computePositions(unsigned int contextID) const { switch(_alignment) { case LEFT_TOP: _offset.set(_textBB.xMin(),_textBB.yMax(),_textBB.zMin()); break; case LEFT_CENTER: _offset.set(_textBB.xMin(),(_textBB.yMax()+_textBB.yMin())*0.5f,_textBB.zMin()); break; case LEFT_BOTTOM: _offset.set(_textBB.xMin(),_textBB.yMin(),_textBB.zMin()); break; case CENTER_TOP: _offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,_textBB.yMax(),_textBB.zMin()); break; case CENTER_CENTER: _offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,(_textBB.yMax()+_textBB.yMin())*0.5f,_textBB.zMin()); break; case CENTER_BOTTOM: _offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,_textBB.yMin(),_textBB.zMin()); break; case RIGHT_TOP: _offset.set(_textBB.xMax(),_textBB.yMax(),_textBB.zMin()); break; case RIGHT_CENTER: _offset.set(_textBB.xMax(),(_textBB.yMax()+_textBB.yMin())*0.5f,_textBB.zMin()); break; case RIGHT_BOTTOM: _offset.set(_textBB.xMax(),_textBB.yMin(),_textBB.zMin()); break; case LEFT_BASE_LINE: _offset.set(0.0f,0.0f,0.0f); break; case CENTER_BASE_LINE: _offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,0.0f,0.0f); break; case RIGHT_BASE_LINE: _offset.set(_textBB.xMax(),0.0f,0.0f); break; case LEFT_BOTTOM_BASE_LINE: _offset.set(0.0f,-_characterHeight*(1.0 + _lineSpacing)*(_lineCount-1),0.0f); break; case CENTER_BOTTOM_BASE_LINE: _offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,-_characterHeight*(1.0 + _lineSpacing)*(_lineCount-1),0.0f); break; case RIGHT_BOTTOM_BASE_LINE: _offset.set(_textBB.xMax(),-_characterHeight*(1.0 + _lineSpacing)*(_lineCount-1),0.0f); break; } AutoTransformCache& atc = _autoTransformCache[contextID]; osg::Matrix& matrix = atc._matrix; if (_characterSizeMode!=OBJECT_COORDS || _autoRotateToScreen) { matrix.makeTranslate(-_offset); osg::Matrix rotate_matrix; if (_autoRotateToScreen) { osg::Vec3d trans(atc._modelview.getTrans()); atc._modelview.setTrans(0.0f,0.0f,0.0f); rotate_matrix.invert(atc._modelview); atc._modelview.setTrans(trans); } matrix.postMultRotate(_rotation); if (_characterSizeMode!=OBJECT_COORDS) { osg::Matrix M(rotate_matrix); M.postMultTranslate(_position); M.postMult(atc._modelview); osg::Matrix& P = atc._projection; // compute the pixel size vector. // pre adjust P00,P20,P23,P33 by multiplying them by the viewport window matrix. // here we do it in short hand with the knowledge of how the window matrix is formed // note P23,P33 are multiplied by an implicit 1 which would come from the window matrix. // Robert Osfield, June 2002. // scaling for horizontal pixels float P00 = P(0,0)*atc._width*0.5f; float P20_00 = P(2,0)*atc._width*0.5f + P(2,3)*atc._width*0.5f; osg::Vec3 scale_00(M(0,0)*P00 + M(0,2)*P20_00, M(1,0)*P00 + M(1,2)*P20_00, M(2,0)*P00 + M(2,2)*P20_00); // scaling for vertical pixels float P10 = P(1,1)*atc._height*0.5f; float P20_10 = P(2,1)*atc._height*0.5f + P(2,3)*atc._height*0.5f; osg::Vec3 scale_10(M(0,1)*P10 + M(0,2)*P20_10, M(1,1)*P10 + M(1,2)*P20_10, M(2,1)*P10 + M(2,2)*P20_10); float P23 = P(2,3); float P33 = P(3,3); float pixelSizeVector_w = M(3,2)*P23 + M(3,3)*P33; float pixelSizeVert=(_characterHeight*sqrtf(scale_10.length2()))/(pixelSizeVector_w*0.701f); float pixelSizeHori=(_characterHeight/getCharacterAspectRatio()*sqrtf(scale_00.length2()))/(pixelSizeVector_w*0.701f); // avoid nasty math by preventing a divide by zero if (pixelSizeVert == 0.0f) pixelSizeVert= 1.0f; if (pixelSizeHori == 0.0f) pixelSizeHori= 1.0f; if (_characterSizeMode==SCREEN_COORDS) { float scale_font_vert=_characterHeight/pixelSizeVert; float scale_font_hori=_characterHeight/getCharacterAspectRatio()/pixelSizeHori; if (P10<0) scale_font_vert=-scale_font_vert; matrix.postMultScale(osg::Vec3f(scale_font_hori, scale_font_vert,1.0f)); } else if (pixelSizeVert>getFontHeight()) { float scale_font = getFontHeight()/pixelSizeVert; matrix.postMultScale(osg::Vec3f(scale_font, scale_font,1.0f)); } } if (_autoRotateToScreen) { matrix.postMult(rotate_matrix); } matrix.postMultTranslate(_position); } else if (!_rotation.zeroRotation()) { matrix.makeRotate(_rotation); matrix.preMultTranslate(-_offset); matrix.postMultTranslate(_position); } else { matrix.makeTranslate(_position-_offset); } // now apply matrix to the glyphs. for(TextureGlyphQuadMap::iterator titr=_textureGlyphQuadMap.begin(); titr!=_textureGlyphQuadMap.end(); ++titr) { GlyphQuads& glyphquad = titr->second; GlyphQuads::Coords2& coords2 = glyphquad._coords; GlyphQuads::Coords3& transformedCoords = glyphquad._transformedCoords[contextID]; unsigned int numCoords = coords2.size(); if (numCoords!=transformedCoords.size()) { transformedCoords.resize(numCoords); } for(unsigned int i=0;i(this)->dirtyBound(); } // Presumes the atc matrix is already up-to-date void Text::computeBackdropPositions(unsigned int contextID) const { if(_backdropType == NONE) { return; } float avg_width = 0.0f; float avg_height = 0.0f; unsigned int i; bool is_valid_size; AutoTransformCache& atc = _autoTransformCache[contextID]; osg::Matrix& matrix = atc._matrix; // FIXME: OPTIMIZE: This function produces the same value regardless of contextID. // Since we tend to loop over contextID, we should cache this value some how // instead of recomputing it each time. is_valid_size = computeAverageGlyphWidthAndHeight(avg_width, avg_height); if (!is_valid_size) return; // now apply matrix to the glyphs. for(TextureGlyphQuadMap::iterator titr=_textureGlyphQuadMap.begin(); titr!=_textureGlyphQuadMap.end(); ++titr) { GlyphQuads& glyphquad = titr->second; GlyphQuads::Coords2& coords2 = glyphquad._coords; unsigned int backdrop_index; unsigned int max_backdrop_index; if(_backdropType == OUTLINE) { // For outline, we want to draw the in every direction backdrop_index = 0; max_backdrop_index = 8; } else { // Yes, this may seem a little strange, // but since the code is using references, // I would have to duplicate the following code twice // for each part of the if/else because I can't // declare a reference without setting it immediately // and it wouldn't survive the scope. // So it happens that the _backdropType value matches // the index in the array I want to store the coordinates // in. So I'll just setup the for-loop so it only does // the one direction I'm interested in. backdrop_index = _backdropType; max_backdrop_index = _backdropType+1; } for( ; backdrop_index < max_backdrop_index; backdrop_index++) { GlyphQuads::Coords3& transformedCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; unsigned int numCoords = coords2.size(); if (numCoords!=transformedCoords.size()) { transformedCoords.resize(numCoords); } for(i=0;isecond; const GlyphQuads::Coords2& coords2 = glyphquad._coords; for(i=0;i max_x) { max_x = coords2[i].x(); } if(coords2[i].x() < min_x) { min_x = coords2[i].x(); } if(coords2[i].y() > max_y) { max_y = coords2[i].y(); } if(coords2[i].y() < min_y) { min_y = coords2[i].y(); } } } for(TextureGlyphQuadMap::iterator titr=_textureGlyphQuadMap.begin(); titr!=_textureGlyphQuadMap.end(); ++titr) { GlyphQuads& glyphquad = titr->second; GlyphQuads::Coords2& coords2 = glyphquad._coords; GlyphQuads::ColorCoords& colorCoords = glyphquad._colorCoords; unsigned int numCoords = coords2.size(); if (numCoords!=colorCoords.size()) { colorCoords.resize(numCoords); } for(i=0;isecond; GlyphQuads::Coords2& coords2 = glyphquad._coords; GlyphQuads::ColorCoords& colorCoords = glyphquad._colorCoords; unsigned int numCoords = coords2.size(); if (numCoords!=colorCoords.size()) { colorCoords.resize(numCoords); } for(unsigned int i=0;igetTexEnv()); #endif if (_characterSizeMode!=OBJECT_COORDS || _autoRotateToScreen) { unsigned int frameNumber = state.getFrameStamp()?state.getFrameStamp()->getFrameNumber():0; AutoTransformCache& atc = _autoTransformCache[contextID]; const osg::Matrix& modelview = state.getModelViewMatrix(); const osg::Matrix& projection = state.getProjectionMatrix(); osg::Vec3 newTransformedPosition = _position*modelview; int width = atc._width; int height = atc._height; const osg::Viewport* viewport = state.getCurrentViewport(); if (viewport) { width = static_cast(viewport->width()); height = static_cast(viewport->height()); } bool doUpdate = atc._traversalNumber==-1; if (atc._traversalNumber>=0) { if (atc._modelview!=modelview) { doUpdate = true; } else if (width!=atc._width || height!=atc._height) { doUpdate = true; } else if (atc._projection!=projection) { doUpdate = true; } } atc._traversalNumber = frameNumber; atc._width = width; atc._height = height; if (doUpdate) { atc._transformedPosition = newTransformedPosition; atc._projection = projection; atc._modelview = modelview; computePositions(contextID); } } // Ensure that the glyph coordinates have been transformed for // this context id. if ( !_textureGlyphQuadMap.empty() ) { const GlyphQuads& glyphquad = (_textureGlyphQuadMap.begin())->second; if ( glyphquad._transformedCoords[contextID].empty() ) { computePositions(contextID); } } osg::GLBeginEndAdapter& gl = (state.getGLBeginEndAdapter()); state.Normal(_normal.x(), _normal.y(), _normal.z()); if (_drawMode & FILLEDBOUNDINGBOX) { if (_textBB.valid()) { #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE) state.applyTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::OFF); const osg::Matrix& matrix = _autoTransformCache[contextID]._matrix; osg::Vec3 c00(osg::Vec3(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())*matrix); osg::Vec3 c10(osg::Vec3(_textBB.xMax(),_textBB.yMin(),_textBB.zMin())*matrix); osg::Vec3 c11(osg::Vec3(_textBB.xMax(),_textBB.yMax(),_textBB.zMin())*matrix); osg::Vec3 c01(osg::Vec3(_textBB.xMin(),_textBB.yMax(),_textBB.zMin())*matrix); switch(_backdropImplementation) { case NO_DEPTH_BUFFER: // Do nothing. The bounding box will be rendered before the text and that's all that matters. break; case DEPTH_RANGE: glPushAttrib(GL_DEPTH_BUFFER_BIT); //unsigned int backdrop_index = 0; //unsigned int max_backdrop_index = 8; //const double offset = double(max_backdrop_index - backdrop_index) * 0.003; glDepthRange(0.001, 1.001); break; /*case STENCIL_BUFFER: break;*/ default: glPushAttrib(GL_POLYGON_OFFSET_FILL); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(0.1f * osg::PolygonOffset::getFactorMultiplier(), 10.0f * osg::PolygonOffset::getUnitsMultiplier() ); } gl.Color4f(colorMultiplier.r()*_textBBColor.r(),colorMultiplier.g()*_textBBColor.g(),colorMultiplier.b()*_textBBColor.b(),colorMultiplier.a()*_textBBColor.a()); gl.Begin(GL_QUADS); gl.Vertex3fv(c00.ptr()); gl.Vertex3fv(c10.ptr()); gl.Vertex3fv(c11.ptr()); gl.Vertex3fv(c01.ptr()); gl.End(); switch(_backdropImplementation) { case NO_DEPTH_BUFFER: // Do nothing. break; case DEPTH_RANGE: glDepthRange(0.0, 1.0); glPopAttrib(); break; /*case STENCIL_BUFFER: break;*/ default: glDisable(GL_POLYGON_OFFSET_FILL); glPopAttrib(); } #else OSG_NOTICE<<"Warning: Text::drawImplementation() fillMode FILLEDBOUNDINGBOX not supported"<getTexEnv()); #endif if (_drawMode & TEXT) { state.disableAllVertexArrays(); // Okay, since ATI's cards/drivers are not working correctly, // we need alternative solutions to glPolygonOffset. // So this is a pick your poison approach. Each alternative // backend has trade-offs associated with it, but with luck, // the user may find that works for them. if(_backdropType != NONE && _backdropImplementation != DELAYED_DEPTH_WRITES) { switch(_backdropImplementation) { case POLYGON_OFFSET: renderWithPolygonOffset(state,colorMultiplier); break; case NO_DEPTH_BUFFER: renderWithNoDepthBuffer(state,colorMultiplier); break; case DEPTH_RANGE: renderWithDepthRange(state,colorMultiplier); break; case STENCIL_BUFFER: renderWithStencilBuffer(state,colorMultiplier); break; default: renderWithPolygonOffset(state,colorMultiplier); } } else { renderWithDelayedDepthWrites(state,colorMultiplier); } } if (_drawMode & BOUNDINGBOX) { if (_textBB.valid()) { state.applyTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::OFF); const osg::Matrix& matrix = _autoTransformCache[contextID]._matrix; osg::Vec3 c00(osg::Vec3(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())*matrix); osg::Vec3 c10(osg::Vec3(_textBB.xMax(),_textBB.yMin(),_textBB.zMin())*matrix); osg::Vec3 c11(osg::Vec3(_textBB.xMax(),_textBB.yMax(),_textBB.zMin())*matrix); osg::Vec3 c01(osg::Vec3(_textBB.xMin(),_textBB.yMax(),_textBB.zMin())*matrix); gl.Color4f(colorMultiplier.r()*_textBBColor.r(),colorMultiplier.g()*_textBBColor.g(),colorMultiplier.b()*_textBBColor.b(),colorMultiplier.a()*_textBBColor.a()); gl.Begin(GL_LINE_LOOP); gl.Vertex3fv(c00.ptr()); gl.Vertex3fv(c10.ptr()); gl.Vertex3fv(c11.ptr()); gl.Vertex3fv(c01.ptr()); gl.End(); } } if (_drawMode & ALIGNMENT) { gl.Color4fv(colorMultiplier.ptr()); float cursorsize = _characterHeight*0.5f; const osg::Matrix& matrix = _autoTransformCache[contextID]._matrix; osg::Vec3 hl(osg::Vec3(_offset.x()-cursorsize,_offset.y(),_offset.z())*matrix); osg::Vec3 hr(osg::Vec3(_offset.x()+cursorsize,_offset.y(),_offset.z())*matrix); osg::Vec3 vt(osg::Vec3(_offset.x(),_offset.y()-cursorsize,_offset.z())*matrix); osg::Vec3 vb(osg::Vec3(_offset.x(),_offset.y()+cursorsize,_offset.z())*matrix); state.applyTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::OFF); gl.Begin(GL_LINES); gl.Vertex3fv(hl.ptr()); gl.Vertex3fv(hr.ptr()); gl.Vertex3fv(vt.ptr()); gl.Vertex3fv(vb.ptr()); gl.End(); } } void Text::accept(osg::Drawable::ConstAttributeFunctor& af) const { for(TextureGlyphQuadMap::const_iterator titr=_textureGlyphQuadMap.begin(); titr!=_textureGlyphQuadMap.end(); ++titr) { const GlyphQuads& glyphquad = titr->second; af.apply(osg::Drawable::VERTICES,glyphquad._transformedCoords[0].size(),&(glyphquad._transformedCoords[0].front())); af.apply(osg::Drawable::TEXTURE_COORDS_0,glyphquad._texcoords.size(),&(glyphquad._texcoords.front())); } } void Text::accept(osg::PrimitiveFunctor& pf) const { for(TextureGlyphQuadMap::const_iterator titr=_textureGlyphQuadMap.begin(); titr!=_textureGlyphQuadMap.end(); ++titr) { const GlyphQuads& glyphquad = titr->second; pf.setVertexArray(glyphquad._transformedCoords[0].size(),&(glyphquad._transformedCoords[0].front())); pf.drawArrays(GL_QUADS,0,glyphquad._transformedCoords[0].size()); } } void Text::setThreadSafeRefUnref(bool threadSafe) { TextBase::setThreadSafeRefUnref(threadSafe); getActiveFont()->setThreadSafeRefUnref(threadSafe); } void Text::resizeGLObjectBuffers(unsigned int maxSize) { TextBase::resizeGLObjectBuffers(maxSize); getActiveFont()->resizeGLObjectBuffers(maxSize); } void Text::releaseGLObjects(osg::State* state) const { TextBase::releaseGLObjects(state); getActiveFont()->releaseGLObjects(state); } void Text::setBackdropType(BackdropType type) { if (_backdropType==type) return; _backdropType = type; computeGlyphRepresentation(); } void Text::setBackdropImplementation(BackdropImplementation implementation) { if (_backdropImplementation==implementation) return; _backdropImplementation = implementation; computeGlyphRepresentation(); } void Text::setBackdropOffset(float offset) { _backdropHorizontalOffset = offset; _backdropVerticalOffset = offset; computeGlyphRepresentation(); } void Text::setBackdropOffset(float horizontal, float vertical) { _backdropHorizontalOffset = horizontal; _backdropVerticalOffset = vertical; computeGlyphRepresentation(); } void Text::setBackdropColor(const osg::Vec4& color) { _backdropColor = color; } void Text::setColorGradientMode(ColorGradientMode mode) { if (_colorGradientMode==mode) return; _colorGradientMode = mode; computeGlyphRepresentation(); } void Text::setColorGradientCorners(const osg::Vec4& topLeft, const osg::Vec4& bottomLeft, const osg::Vec4& bottomRight, const osg::Vec4& topRight) { _colorGradientTopLeft = topLeft; _colorGradientBottomLeft = bottomLeft; _colorGradientBottomRight = bottomRight; _colorGradientTopRight = topRight; computeGlyphRepresentation(); } // Formula for f(x,y) from Wikipedia "Bilinear interpolation", 2006-06-18 float Text::bilinearInterpolate(float x1, float x2, float y1, float y2, float x, float y, float q11, float q12, float q21, float q22) const { return ( ((q11 / ((x2-x1)*(y2-y1))) * (x2-x)*(y2-y)) + ((q21 / ((x2-x1)*(y2-y1))) * (x-x1)*(y2-y)) + ((q12 / ((x2-x1)*(y2-y1))) * (x2-x)*(y-y1)) + ((q22 / ((x2-x1)*(y2-y1))) * (x-x1)*(y-y1)) ); } void Text::drawForegroundText(osg::State& state, const GlyphQuads& glyphquad, const osg::Vec4& colorMultiplier) const { unsigned int contextID = state.getContextID(); const GlyphQuads::Coords3& transformedCoords = glyphquad._transformedCoords[contextID]; if (!transformedCoords.empty()) { state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedCoords.front())); state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); if(_colorGradientMode == SOLID) { state.disableColorPointer(); state.Color(colorMultiplier.r()*_color.r(),colorMultiplier.g()*_color.g(),colorMultiplier.b()*_color.b(),colorMultiplier.a()*_color.a()); } else { state.setColorPointer( 4, GL_FLOAT, 0, &(glyphquad._colorCoords.front())); } state.drawQuads(0,transformedCoords.size()); } } void Text::renderOnlyForegroundText(osg::State& state, const osg::Vec4& colorMultiplier) const { for(TextureGlyphQuadMap::iterator titr=_textureGlyphQuadMap.begin(); titr!=_textureGlyphQuadMap.end(); ++titr) { // need to set the texture here... state.applyTextureAttribute(0,titr->first.get()); const GlyphQuads& glyphquad = titr->second; drawForegroundText(state, glyphquad, colorMultiplier); } } void Text::renderWithDelayedDepthWrites(osg::State& state, const osg::Vec4& colorMultiplier) const { // If depth testing is disabled, then just render text as normal if( !state.getLastAppliedMode(GL_DEPTH_TEST) ) { drawTextWithBackdrop(state,colorMultiplier); return; } //glPushAttrib( _enableDepthWrites ? (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) : GL_DEPTH_BUFFER_BIT); // Render to color buffer without writing to depth buffer. glDepthMask(GL_FALSE); drawTextWithBackdrop(state,colorMultiplier); // Render to depth buffer if depth writes requested. if( _enableDepthWrites ) { glDepthMask(GL_TRUE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); drawTextWithBackdrop(state,colorMultiplier); } state.haveAppliedAttribute(osg::StateAttribute::DEPTH); state.haveAppliedAttribute(osg::StateAttribute::COLORMASK); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); //glPopAttrib(); } void Text::drawTextWithBackdrop(osg::State& state, const osg::Vec4& colorMultiplier) const { unsigned int contextID = state.getContextID(); for(TextureGlyphQuadMap::iterator titr=_textureGlyphQuadMap.begin(); titr!=_textureGlyphQuadMap.end(); ++titr) { // need to set the texture here... state.applyTextureAttribute(0,titr->first.get()); const GlyphQuads& glyphquad = titr->second; if(_backdropType != NONE) { unsigned int backdrop_index; unsigned int max_backdrop_index; if(_backdropType == OUTLINE) { backdrop_index = 0; max_backdrop_index = 8; } else { backdrop_index = _backdropType; max_backdrop_index = _backdropType+1; } state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); state.disableColorPointer(); state.Color(_backdropColor.r(),_backdropColor.g(),_backdropColor.b(),_backdropColor.a()); for( ; backdrop_index < max_backdrop_index; backdrop_index++) { const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; if (!transformedBackdropCoords.empty()) { state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); state.drawQuads(0,transformedBackdropCoords.size()); } } } drawForegroundText(state, glyphquad, colorMultiplier); } } void Text::renderWithPolygonOffset(osg::State& state, const osg::Vec4& colorMultiplier) const { #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE) unsigned int contextID = state.getContextID(); if (!osg::PolygonOffset::areFactorAndUnitsMultipliersSet()) { osg::PolygonOffset::setFactorAndUnitsMultipliersUsingBestGuessForDriver(); } // Do I really need to do this for glPolygonOffset? glPushAttrib(GL_POLYGON_OFFSET_FILL); glEnable(GL_POLYGON_OFFSET_FILL); for(TextureGlyphQuadMap::iterator titr=_textureGlyphQuadMap.begin(); titr!=_textureGlyphQuadMap.end(); ++titr) { // need to set the texture here... state.applyTextureAttribute(0,titr->first.get()); const GlyphQuads& glyphquad = titr->second; unsigned int backdrop_index; unsigned int max_backdrop_index; if(_backdropType == OUTLINE) { backdrop_index = 0; max_backdrop_index = 8; } else { backdrop_index = _backdropType; max_backdrop_index = _backdropType+1; } state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); state.disableColorPointer(); state.Color(_backdropColor.r(),_backdropColor.g(),_backdropColor.b(),_backdropColor.a()); for( ; backdrop_index < max_backdrop_index; backdrop_index++) { const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; if (!transformedBackdropCoords.empty()) { state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); glPolygonOffset(0.1f * osg::PolygonOffset::getFactorMultiplier(), osg::PolygonOffset::getUnitsMultiplier() * (max_backdrop_index-backdrop_index) ); state.drawQuads(0,transformedBackdropCoords.size()); } } // Reset the polygon offset so the foreground text is on top glPolygonOffset(0.0f,0.0f); drawForegroundText(state, glyphquad, colorMultiplier); } glPopAttrib(); #else OSG_NOTICE<<"Warning: Text::renderWithPolygonOffset(..) not implemented."<first.get()); const GlyphQuads& glyphquad = titr->second; unsigned int backdrop_index; unsigned int max_backdrop_index; if(_backdropType == OUTLINE) { backdrop_index = 0; max_backdrop_index = 8; } else { backdrop_index = _backdropType; max_backdrop_index = _backdropType+1; } state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); state.disableColorPointer(); state.Color(_backdropColor.r(),_backdropColor.g(),_backdropColor.b(),_backdropColor.a()); for( ; backdrop_index < max_backdrop_index; backdrop_index++) { const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; if (!transformedBackdropCoords.empty()) { state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); state.drawQuads(0,transformedBackdropCoords.size()); } } drawForegroundText(state, glyphquad, colorMultiplier); } glPopAttrib(); #else OSG_NOTICE<<"Warning: Text::renderWithNoDepthBuffer(..) not implemented."<first.get()); const GlyphQuads& glyphquad = titr->second; unsigned int backdrop_index; unsigned int max_backdrop_index; if(_backdropType == OUTLINE) { backdrop_index = 0; max_backdrop_index = 8; } else { backdrop_index = _backdropType; max_backdrop_index = _backdropType+1; } state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); state.disableColorPointer(); state.Color(_backdropColor.r(),_backdropColor.g(),_backdropColor.b(),_backdropColor.a()); for( ; backdrop_index < max_backdrop_index; backdrop_index++) { const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; if (!transformedBackdropCoords.empty()) { state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); double offset = double(max_backdrop_index-backdrop_index)*0.0001; glDepthRange( offset, 1.0+offset); state.drawQuads(0,transformedBackdropCoords.size()); } } glDepthRange(0.0, 1.0); drawForegroundText(state, glyphquad, colorMultiplier); } glPopAttrib(); #else OSG_NOTICE<<"Warning: Text::renderWithDepthRange(..) not implemented."<first.get()); const GlyphQuads& glyphquad = titr->second; unsigned int backdrop_index; unsigned int max_backdrop_index; if(_backdropType == OUTLINE) { backdrop_index = 0; max_backdrop_index = 8; } else { backdrop_index = _backdropType; max_backdrop_index = _backdropType+1; } state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); state.disableColorPointer(); for( ; backdrop_index < max_backdrop_index; backdrop_index++) { const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; if (!transformedBackdropCoords.empty()) { state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); state.drawQuads(0,transformedBackdropCoords.size()); } } // Draw the foreground text const GlyphQuads::Coords3& transformedCoords = glyphquad._transformedCoords[contextID]; if (!transformedCoords.empty()) { state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedCoords.front())); state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); state.drawQuads(0,transformedCoords.size()); } } // disable the depth buffer // glDisable(GL_DEPTH_TEST); // glDepthMask(GL_FALSE); // glDepthMask(GL_TRUE); // glDepthFunc(GL_ALWAYS); // Set the stencil function to pass when the stencil is 1 // Bug: This call seems to have no effect. Try changing to NOTEQUAL // and see the exact same results. glStencilFunc(GL_EQUAL, 1, 1); // disable writing to the stencil buffer glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilMask(GL_FALSE); // Re-enable writing to the color buffer so we can see the results glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // Draw all the text again for(titr=_textureGlyphQuadMap.begin(); titr!=_textureGlyphQuadMap.end(); ++titr) { // need to set the texture here... state.applyTextureAttribute(0,titr->first.get()); const GlyphQuads& glyphquad = titr->second; unsigned int backdrop_index; unsigned int max_backdrop_index; if(_backdropType == OUTLINE) { backdrop_index = 0; max_backdrop_index = 8; } else { backdrop_index = _backdropType; max_backdrop_index = _backdropType+1; } state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); state.disableColorPointer(); state.Color(_backdropColor.r(),_backdropColor.g(),_backdropColor.b(),_backdropColor.a()); for( ; backdrop_index < max_backdrop_index; backdrop_index++) { const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; if (!transformedBackdropCoords.empty()) { state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); state.drawQuads(0,transformedBackdropCoords.size()); } } drawForegroundText(state, glyphquad, colorMultiplier); } glPopAttrib(); #else OSG_NOTICE<<"Warning: Text::renderWithStencilBuffer(..) not implemented."< #include #include using namespace osgText; ///////////////////////////////////////////////////////////////////////////////////////// // // Bevel // Bevel::Bevel() { _thickness = 0.02f; flatBevel(); } Bevel::Bevel(const Bevel& bevel, const osg::CopyOp& copyop): osg::Object(bevel, copyop), _thickness(bevel._thickness), _vertices(bevel._vertices) { } void Bevel::flatBevel(float width) { _vertices.clear(); if (width>0.5f) width = 0.5f; _vertices.push_back(osg::Vec2(0.0f,0.0f)); _vertices.push_back(osg::Vec2(width,1.0f)); if (width<0.5f) _vertices.push_back(osg::Vec2(1-width,1.0f)); _vertices.push_back(osg::Vec2(1.0f,0.0f)); } void Bevel::roundedBevel(float width, unsigned int numSteps) { _vertices.clear(); if (width>0.5f) width = 0.5f; unsigned int i = 0; for(; i<=numSteps; ++i) { float angle = float(osg::PI)*0.5f*(float(i)/float(numSteps)); _vertices.push_back( osg::Vec2((1.0f-cosf(angle))*width, sinf(angle)) ); } // start the second half one into the curve if the width is half way across i = width<0.5f ? 0 : 1; for(; i<=numSteps; ++i) { float angle = float(osg::PI)*0.5f*(float(numSteps-i)/float(numSteps)); _vertices.push_back( osg::Vec2(1.0-(1.0f-cosf(angle))*width, sin(angle)) ); } } void Bevel::roundedBevel2(float width, unsigned int numSteps) { _vertices.clear(); if (width>0.5f) width = 0.5f; float h = 0.1f; float r = 1.0f-h; _vertices.push_back(osg::Vec2(0.0,0.0)); unsigned int i = 0; for(; i<=numSteps; ++i) { float angle = float(osg::PI)*0.5f*(float(i)/float(numSteps)); _vertices.push_back( osg::Vec2((1.0f-cosf(angle))*width, h + sinf(angle)*r) ); } // start the second half one into the curve if the width is half way across i = width<0.5f ? 0 : 1; for(; i<=numSteps; ++i) { float angle = float(osg::PI)*0.5f*(float(numSteps-i)/float(numSteps)); _vertices.push_back( osg::Vec2(1.0-(1.0f-cosf(angle))*width, h + sin(angle)*r) ); } _vertices.push_back(osg::Vec2(1.0,0.0)); } void Bevel::print(std::ostream& /*fout*/) { OSG_NOTICE<<"print bevel"<(copyop(style._bevel.get()))), _widthRatio(style._widthRatio), _thicknessRatio(style._thicknessRatio), _outlineRatio(style._outlineRatio), _sampleDensity(style._sampleDensity) { } /// default Layout implementation used if no other is specified on TextNode osg::ref_ptr