From 48138fee3bc027ffa3d850e33214a9a337fd7fb3 Mon Sep 17 00:00:00 2001 From: cecilkorik Date: Wed, 15 Jun 2011 19:21:13 -0600 Subject: [PATCH] more stuff added --- asset.py | 13 +++ data/tex/black.png | Bin 0 -> 2795 bytes data/tex/nm_flat.png | Bin 0 -> 2805 bytes data/tex/plasma1.png | Bin 0 -> 14532 bytes data/tex/plasma2.png | Bin 0 -> 19707 bytes data/tex/test1.png | Bin 0 -> 19078 bytes data/tex/white.png | Bin 0 -> 2805 bytes data/xml/def/sprites.xml | 21 ++++ data/xml/sprites.xml | 5 + deprecate.py | 20 ++++ enums.py | 7 ++ gamedata.py | 19 +++- gameobj.py | 5 + lesson6.py | 226 +++++++++++++++++++++++++++++++++++++++ looprun.bat | 1 + models.py | 146 +++++++++++++++++++++++++ roc.py | 86 +++++++++++++++ roc_test.py | 21 +--- shader.py | 31 +++++- sprite.py | 69 ++++++++++++ texture.py | 21 ++++ video.py | 63 ++++++++++- 22 files changed, 725 insertions(+), 29 deletions(-) create mode 100755 asset.py create mode 100755 data/tex/black.png create mode 100755 data/tex/nm_flat.png create mode 100755 data/tex/plasma1.png create mode 100755 data/tex/plasma2.png create mode 100755 data/tex/test1.png create mode 100755 data/tex/white.png create mode 100755 data/xml/def/sprites.xml create mode 100755 data/xml/sprites.xml create mode 100755 deprecate.py create mode 100755 gameobj.py create mode 100755 lesson6.py mode change 100644 => 100755 looprun.bat create mode 100755 models.py create mode 100755 roc.py create mode 100755 sprite.py create mode 100755 texture.py diff --git a/asset.py b/asset.py new file mode 100755 index 0000000..a65eb41 --- /dev/null +++ b/asset.py @@ -0,0 +1,13 @@ + +from gameobj import gameobj + +class asset_manager(object): + def __init__(self): + self.renderable_cache = {} + def get_obj(self, name): + go = gameobj() + go.set_renderable(self.renderable_cache[name]) + return go + + +mgr = asset_manager() \ No newline at end of file diff --git a/data/tex/black.png b/data/tex/black.png new file mode 100755 index 0000000000000000000000000000000000000000..31d8067b01c0aca9cffa6bc4fb048085e1fb9d92 GIT binary patch literal 2795 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 Hu0mjfABZsH literal 0 HcmV?d00001 diff --git a/data/tex/plasma1.png b/data/tex/plasma1.png new file mode 100755 index 0000000000000000000000000000000000000000..70c2ad08b3b6e23a3548830cea2f81c4a486d974 GIT binary patch literal 14532 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 literal 0 HcmV?d00001 diff --git a/data/tex/test1.png b/data/tex/test1.png new file mode 100755 index 0000000000000000000000000000000000000000..6cdfb488726e6b334ef1851fadeda8b9511ac567 GIT binary patch literal 19078 zcmV)MK)An&P)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z002L+Nkl(8lhv z+uirEUn?K`an@S%vDU6`OZm9frRut;&SO93nscr(#~jl*=ZpaW=kWOJ@z-noT5QPx zj}7Ya*X#dPJiY{vzrGM();T;5g^#~p_fTlVM~yKCFvb8dMF9h2jG6vm42&tv@Hmc>D2ifwn__%ud~#6~FlPSS^1tz~ zMKM3SC=84#i*kOa@q^0w31)n3`fqwk@SdgrUgQ5z6s7T>SuO{&e7Gr!a=ZjZQ5J_| z8$S-?QPcTke-R{44k)493&&{#h9R zx#NuwZux8rnN8144|tXb2WMam3}6m_H1kj60B3;dLyVgZc6zn(o;v;C z83(xKq3P8C;KtX@N92~zGu}Z>OT;@=;|^~Qm@$ns^CtslJgUV*Pp>8C>&%pZI(Ime z@x8s5n)#>y-Z0L&`LxGpx_K$P@f4>Q88aW__$u$X=g)&1k9E12IQ(NdWoHftF~7Hi z_uhvCbpHJ`&cOlBIpaLTa4`NW54X{~^y6WT&oVCh94^N?Ts3FBcNs5=apN1hz~bh6 zGuntVn0E!!8@Ty0y7}ascL~h+Y&TuR!zG+9==k=N#f=9tSzB<8f@61{9Zr{de8?;x zFj{R+24LKB2=ls_SD$gyJHmLkbbNE?-N^Y|j5}Dqn@)Ezau?o!Wr>ZqdA73oRE!w| zO1K*5!*i1cajEXT;FbT z(U);!uNuR%)ko};Tjpu!GBw~Ts>nZ!=2r%nUBet z!|F5$OnvbyCOo$>$2Mj*UvJ$W;+8wCF7GJawD9B4;S9?y9|~t+T;R@)o0i<@xZuwy2On6a@^N(+GR-^BqUu>LP7D2p?GTyD5jem4{(~Vjj zkbmml`WO$+EO&HX{BF7EOLSjWAn_Vg=IzI5&ywc5=2VYm7Pmj%V$TJdDaIM!cf|K` zxwLLco7~~`fh#Z|{%g9*5bu5lOA5w!5zhN?cQDi0yv*X$%;9FbL!vq^`opJ~(DAt_`JF#&^mcB! z=7-Sh4weVHHr?`k&(D}3pCzv;xP-zx7jua9Zc2dN!K9-c$4s}_%cxvrw2OT@E;Smj zlyQMW@GRBOn&GBv>=};>vJ~h2&zQNuU_2*gu*91sF%4s?|Bl{T_fy<4M=((sH;2P_ z2D5{iSH~f5Jft0d&~t}V3M21wQpUesfvq@%0o@pXx8U5eD>CyI3kT01Spk+j#T;^1 zbNECzhZ+;-sv1BV>;VpuHop7__iQfo8eTkKk`ZT&Sv-|lPH}Ncp?e!|_d);v9|h#?P#<#A)_g9X@2q1Kr|o5M;p9M;qs*MUjCYHZD<$ zjwQD=CQ8)~m)%8C=#cBVgB=GS>m@{H$z`Vt3HF>_WDX&Y}1a1H~=f|(lPrC*@0XzY0#qtpaB}-5%36j zIDbEwzaIkkyHm2%_VT#&9PWKV*c1 zlCB{=wp(L=Mm1XpvUQ8Dm6NPQ{dl8XWW%i` zM^+vCE>6EsZq2fc&eG*A7B$C`mPb~RJHjubqf&04vV_d4kIg&(jKgQG%0u_~Tby%z zE_@%Rq(O?2+LANjlO6js4k}63wtRBJ>Y7!_De{a?};tY=k+1ISd zDjc~9^er6sO#i|;E==%C!Kn$IOD%uiR~Qn^jj&(INq`-9haKd!o&8Amv`mICUXkE9 z?vX2nLYL>g47aF^@>+d6V1x@H1w@y*fSjDFo76thNlwe9HZ=Z%+G{fVPeA~o0MbIBtx=BDNH*#Ep_s`Ok5gd-pZW4nv(-uCa%K9Q=>#& zBV=bz$jB4fxyyJ2*~@2T@}9Y~bb@(B&e*wd!I_NAmfDa>!BV;2-3hneCF6ONZfBlH zer{r@@hT{iA=?L&k-{>|#;6cX&hBabu2BEL+{Dl10ZE3W5&EsuKHIF!8w|;H>DDq4 zi(KC4v5B~&@q%64I>6}Ed|!0uPL7~SAAKbpE5}x)tzP^%-L@!@PI6OhBp5J)@+4T# z=v5|+aF)`p8BE)`Hsj$bu$AabeI;W%$+^z756t_BE#_1XYZC)kk7 z0HK0+Fd0~(%g7a62Kd2WtYknng3mN82w=FQcB&^#22i8>4yW#4*}V#HIVQt@n-omy z(%6mev0O$DtN;y$G@kH@vg169S+i5oFaf7J1f^)AMFkc^cd1>!;i7s_r!;bmlRnJl zp&-r=AIL5i=*fzl=bFc&AdkOZ$FIef9uxf@e|t>kkX$Wsy7ygXwDYB1l zX24RbqNdh)&t!j&AKDVj9*Au@z!l!IUB0XEGW%DW8i#K*o0Od`?@*JwXT6UuiTTKe zwULu?WqVqNCPi0}73_(cPAxxPafU@!P+(hyo2|;fRf- z87(e~I;Wa5rdo~%)MJ&ohILJKPEy;eC8?Ekq8qYsHnM-(aMvkXO3||QeHHu&xVQw? zSNR^L<>Fu~e=CtuvZsz5#uD|G<8&b5&%ewi34d%lrDs%Z1oT~$5)zg?Hrud#98F@$ zIuZ&ad!{Gqhy6NiMXBUaSaCs+y5=~q8pzV8LD0`~A|q(RUzFUOeP+w$YPw1J?rH*z zd`DG;=gRu3n#-Dn>xJ(AmIvwM)JxUGOD(5c zELPQfsk#&a=>|~AuB1I6>)3qL^ml))Y*Neyu;9X<<@QCjya$vL_Kob}DzfQ{KK-!O zUJ(j!s^wY9;39Wf%Z62R9*d2AY*tyS(LS)M-h&ke0aIXOU*v(LsHf!Votjidsnrsu z$Jjk>01Gbs(QKV=xNT@OoB1ZN&S?{F{c6snEN4W(); zYQ<*pH2AZjJ^(nJ2P^a;Smh^JlCM&{l%8WrIawd>{yI7QE#C)Nq2SUf{~FYx$EpNy zp;nh_#bp^bL>AZxI2zV;QL_x|NiMZY*0n1c0@WQ=CFE89@0RndqSI@zft zp{eKzio2p-swGHO7oux09IOyQpp~3%D7lpGx-8iMO1^5bc;mbSuku4-4)rneSnMfQ zDQHSc)%7iJWL2@R>Pc!9-CYWScB%bcE1;u#9PCM6bbmXkgUp&fH}TO3V&?0sMNhs#qIuRURC(MYPDfWbsK$GNRhaD4Ypo!)dU**s&F}* zfdK1l5zw!kw5p@()I_QwTfd&XRT5SRtjchyIz`nhE^^f*?`De>8`%*3*OpucTZF3^ z3*_uy@^yxVH5Nu!3R?=S1)xFS@``?$t<~sBRTmmWzDY@s&{}dwcAx{Xs(y|oajIU1 zU={UMvM+=vCu zrG%a4=`^nz!UD4hRuw`K(2^UUQvsBU%1L0|H|0Wy6$W9$jn@%wka8?`(-*;{?3zl# z3N`|(`aHf~l(y>_RU>5R9had?30BX2GaMKj;tP~SAZ-9?&QuGj`i78aEO(77vULbH zfPIR_mRl<{sge%;+6XCm6be}mOwA#5)GrqfrWZUi>#JB6Xe(f$`UbG&?5SH*R~Er4 zOUQZ@|EyF$R0|n;t=9f%`kJsR1suc`N;*bvWO2k}>1aZdTTE9_0Ic_N_SkdIBTCy@ z$J21^JZfQmDyh=z%KgGtC{i4lnhSyoQl-!qtdO`?Qc27^yckxXCe^JCh1ahn;kO~M zf|ciL9y<$W;;t#igSRuN`KMORR-vOwwbX$4Gy5<&F>PN%Z=dVvGe zk*vfSm9M9?n^-x<#othXa&(v?<1y&!$$3^(aV38uzbp;wT1?l zPViDogrb!eCDL^=Yfqx=4Fm%1h+7T7Di&C;QY=swSeLS^io?33%WR3SDliA_p5q)* zlUiq3n>>D>A%<0{Z8ntvR{2!OApAwJ!oYEur0R03ZtL`|pH%IkE~-;^e}Ppgb!E%7 zEl5Z~lDZyU=8{X*OO6FPS=B&J!uM6tWoTC=?==U9BBcef$*a}SBA`@PE(XE@@6-gc zQ)yMwF0T>(+7TA0?+$6hR!8c}Ov6?(sj|Wvtc9L|N_c+7xkJlkc!dvv_916M!EpL; zxn&sE0Bhv_e|fx<#AQfsd`q(BjbR1pL|ejBXoc|CaQLV0x;pOtS!6#-)%zr@phKY2 z){iaG(DbX~R;~nA#T=NZLZ&3K5$c>_SnbNKAVJ0c4ZU91Xc|hOSt1WY`vGwW*AnJmr`+tCDm|P zDs{<5d$xS=)3|quOXqoN|1RFZ(Rbsvlp8f_Pehkdx>0=91Kf2uDsVesR?!OJ)GoZo z{pY99^UQOoj^oxiOQ>iY!I)~b2_m^ET1q!?WDnS-$ZT!6klS33^+@RaVo}j2nO&j8 z=b$yurMc8nwt~NK-jC-$h@EuwC)jRryGu39_@>4_q2~-s2df_9w7}NlcEGIiE4bq= z9M@5|$4jTvK|g(h>R9wrN@cZ@^D3RcZ9TR^0<7v&txWV{XB$?2caG<=Hu8B}kD_5Y zY`su=0F#JT_(-Bl?!m!>%|nQfQtI*;}6idsmuoKH$9iUwBs%V)IX z55xU8?EWThji2`qasD1`zZ1r#(xyhhAR4((wUhfG4u!uZG4R=N1!-1Z&i?uqZ+3BC zja6k7YE@l8YJ`tq!Kf2ZLD5*2Xs2+yA2k3M|jss91k8| z;(uKP*7N7Lc=Zw=xtRWWa)LJ=am=cypwI5MJK3mmlpvMYr`A_5QI_`Ms#>E5XnHT79 zP48vTVYdueRRJFfU-(VuczSy%A&)&`xH)&upKYV9(V6!58x?mZ(zIB$r|im z!Mz9AbwGvZ1{@E7!?DHLFe!H21NH!5j#1s78cjFHjISEMpFKmf$0zR{F8PMUzOQ}` z@7m)06qkE^@GeT=eP@%i`MFbkYL8#Ii?2ArpV>}t{;%%hlY0R8<}JQuI|br@dKbUH z2Y_$e;@h`)$FU4nbs6|z$B~R$(g`3yRKB?FzcIP21_ylaVY~R>$rdGI=O4BugI7NA z>mhA;#&kpStJvL{ea4UC{424I&hIC2>vymN@GQ39hjSlm_!sl3d?n7_jyvO@{_FhU z7vby(cNT+w6}wN*A9Nk(2HPQ&f`PdOw*!E3i<{?xfMF>Vm0#ZBL$f3K_H(>_%X1b^ z=S%*+GknjT>95~AKlp=Z_^WrOcYg2u;E$Z)hweLE zcc;sNIs6zaZp(NqDGth@!-flg743JFV1-`Rtn&XEd8~+)uxz~k2p2z(TW*or;9Ok? zdFNU!wo|glJ}f=a?VdaA zZ7=^oz*K$1x`yq;>D~4%_BV0qrhVvc=kDw4O#Nw za;3dEM9SjH{%}ReLNAhK7}l#-+!eCi;zK8(L*cmHNK3Z4tZL)(i=Vtx@N@B4Z^ibz zaNfv7zvbdRf$cltK7+e2;q+5;__Nqv!#UruHOBLv7#7QciN2$&#fo-B9;+r6xloOK z!&-p#coF4mS@?v7Mj(qcLf^@n`9^?(Z&;Fc6Agu|$Ff9CG1frS6;isC z^iGqllhWpTEDEw4F8n!B(XWhjU?N(Tl0CMva#eH&J=bgM8wwR} z^tkA8tHhbZowy6W|&a@|=(3?sxzjoLs}Un?S6)!=y-eQexXr zT2E&K_C4+m*f{{jb108vW|cocrUoAF@aSSX`!Bo0G#}Soj>Ym}BEzzr$6}3p0;_zF z)e1$xP7ocJWbKoF>kFG>QC}4kl{y)(YE>dA&9PWYOysfrxBVC4#f$|geNzER9)Tp%qoB3 z52Vi7azAwyRmqr|s~A=eltnyNPy|fYIa`7EDzVi6F>bwjD5T&&;dFze@14P_@tN<% z*_Y$;gSd5xi(esd!!?||8D~qCrUj00-r(X@oIb+6X7o=Jl5hzC<~GXbU{4qUmN%Ti zT;dbA@bCg3yM<;C0Pi@%GbfB_tOeeG3(eu+@gGm|%SZU(bA|{)Jr)}ZOW@z1<2Nqw zqo?@i_wa#pa!*)~)nzpE(mHCB8p@HKyc>C5s=#jWQ}t3Jj}1bJx0Q*-%Y*+rgb)4@ z7a-?%6DOO=pIv^2zzqeCMz^#aK!L59Zo+;-(t{TqquTPCRrUlG@Cl&5#LM#sJ#&J$ zY*hsp3*{8VVPr`PO#&(|(Wro}+!}dWMv**UBRkIA8U;G*8FMrf`1PPmqftt_k9V0#0O0jsP$3}X5DCtcR;sT%mZP9%j! z9GG8q49xt8j!_3Ifm>U+Fn2Xid4{!?1JkJ)m1KffDncs>yNTa~hZTAu&Uf6x=~BJO zdM|vJ%`Ik|OC1$0mYN_cdH0u3SFeRe9YqS;m#zB1`4sAppT+T)5^=qOWU##qrsqr9 zvoBxiu@t#?;m@<$~I&XjvK&R-!WbLvme8qzePBay@1&%5}9839CEu# zUN)0ImNQ#Rk{0UM3V|ZzgO|d{8tSepuKgjYfu_uxO3L;x9GJ5o$9|7{KZV@~mTrCk zIDQ*$e?LyXN|Cu2?1qOay&@KU=maU491?YM{GWb)>?8QeE(Mw!A_mOYB(^{V)(Nf!G53~-ynf6%Cm2h`SwXw@X7W6Z2WNbKJUytrp!8UC9nN7`2$g_EpjecJ| zn^)-)7K{$es@YRr#w@cgPj_6BM`_pTV>R-AP>F^EH?x%GWOV9ytxg!MMY)WPKpNmtX~5VOH1jtpqNORY!T+NM6>dou%xIg#39fO+qz6zM*H+2H%jlrRS{-CoMvy*;b~sw6F4~bf!$nCwq?|c_md-{7 z+T}KTrKsG?tDwo&8=_f5Pb|3Sz$#v}nAO*-1dSm@lD}3lg(@`+mz@t3`zl>qp<5%o znsdFQ(toRtwC>i-(s@E|QI&IerMo7%6_JK`v)SX4JFs1c5tD*xf+z)GorbDfH7o@P zWp%J4;YLfl0=%)MW)Sv({mKnstK#fR2Ft=YRDFEakfv+g937gphkr^g934_u0Ie>h z`1dNTFmU>M@zk19&{nAAZirfSSFGjfZ2<(@=LxJ!dWM;`npS0#C_~Ly7$?WD zu4klFB%N=`(6&xCsho3d)t#;)+dr`5;8_ApDctxvrLU*d1S@U;IE$*=5StC;WtA$1 z)K6Jsm8YN& zo6D(5^d4c^OAUClErz3Z8Swc3<2S1XJ3 zUu_mrmb@$#Eta$ute_gsx~QbSUX_vt^T7pX7SbS0a?xR`PTmNug+SSID?2G6->`0G z%nu-7yq=`@8RV)?V1ZH&3^lBQ1*;;$i8NnC8i`vAoyyXvEw%(ya@e|0rZ9s#x%6rq zK>AOmVxx%9_43@sLu@EzGa-hRowG|GtH~4ZZ)FXNOkWk<6GsPk7er5~k{jW3kOh4b zgymEl{ni?vO)p9|4ss8m(psZasgks+9O-d?Qi3xW3fk6x6~ls-yz6L5&iI<-!s!J3 zb14F9bK5dy`&m&?g;lIXz)~mz25bdKa^WtcR-+7v&1CK6Pm1Lyni;qv?67>zhQ$TS zWMg)69K5crK)qBH=VM=03hF{t_69Jy4Wt|xzY~y`T=l`Kfz$Hs)mcd08X|XcMfYkR z+jFS%1h5rh9sf!>mLWuUZeu8+a*YbLcPZI^b^|ERLW%^|*{L;|;ZM)8Xo6p=~zQdpKsggs0`)}i^qeHwK zmZlnD04_g^dp|{VuuBeArzE>1o?gql#R_+x#ihf&&*s&YOMe6C!jRsrnLU-96(kWT z6=b33+|@v;`3Gc>)#OqQ>q)^~LGW91DAW@yR>!21he7yzz`yhyzI7`e{qC1=?`MS3 zZB)2fssLtA*s24gJbOEKpU1sdWzGJQf>lW+LuD3H4r#bir@gQZP02#W#Al1BA&YHg zBk!**d2cdU#mQMnUG`*(KvR#l0hT1WR@hX@PMi5{&%PWdH;G`C1gw_``JY3oK~6HP zM&PsM?75o^OraA9A_L|PV8JOht}!el2t^8re3PPscHHpNJ{$5;$L zgoffz8{T+7m%nbp5kY>q^ks~ce!vo>Ej(gYwSpX@a{U_am+|*UB++dIp~p_xEVWUy zoFP_4`503{*hA;RtN=sZoQAG)tvt`A5=Ya|*PviV6;`cnMasJHw%tzRHWy8wKgU0P{bF!c&VB&LZ^50vf{Pch+fRmdy2J4saQo}AeHN(k{Kv6>h&x}0<0k=N z_ZjRivF|2p+YdN>amrwCKaFDx0Q(;Inu+K7EFF z9OH>Qcy^070=S3Y-s5v;_{L*Ac?a*kzzaM4?s%o|;G2(e1Yn2X+To*10(Xoz-Ntup z@gAUk9>285$5kmO7FHM}(VddhE6L`(8?HnsTNT!iZtF8xi36)HM0Lr$@8`Y?+dmBe z`#;3pe;wpTXFq`BH{tC2aQchby)b3#cYh7rcjETfWBWF2--e6NWB(bPy?1sJm$>`M zLw3I(aCe5Rwl`i#}jj44CxAp3@cb@_wWZmcZPQy(nhfXQiq3I`@0++A`WD}q4hV>@{_&VOPN=L}z11WEnHOStumcAa*-Nm#8sc4aC8&f zuai&LGptKs_bHsb6#!1=Z0WL_@+xuU6g4bn7Lwr_Tf}btB?fuVrj0(*#ivwn?P_9koBqhPC@J zZv6ueCRoH2BANA)ATScQn0hSB>A;LKluXp?Wwuc(4BzMs{vMZQEP49Byo;YF9NwG_ zpkD!WRLx%Da}JEbjgJBBda1UUD*Mk^H(|WA+WM zB&(dn})6Uhs*O#xSlpn6D7@8kf4VZ^3~ygr7?d*&fSB z$!XL}8dfIfsN<#?O%SL*d02uKEH^wiI~1Z3a&@-E^8`!ulNyL5U*(rN17=l0SSXQU zMc*bgEYFPY{J9y%d&hW$IA1-jQ z$8Qr>@h}GlS8#2Yg)q}oYHP|;^fUMb$K~T?8yvoL{N;NL4}sDkPq%?ivZ|2Xd;YUH zdKxERJ$>}W|H0)exb=5}Q#^SWj-JB#-^S&AT)g064F=n{1{cRD&hVxaT-)L0(YNjJ(giNh@XixFy~B$a_{=FjG~-f#>I84x;%)P;@TEOI zbBgz0;P<#t*l+Q*CwRvh{`y?KnYe04cGd6mh$d-59>Ltix+@D27sgM*uFD9 z$jcVHPY21?_6_sizQyk0WXikQ9UPZ9E^#!@=n2(@E~b+xk6^a5BfY?*9qum+XOD+_ zbeA{+u*Fj|nEA&${Lv-e24IUn;g6F#!5bE<0&t9Hj`7S9YObQu0qqXI3OodGjJF=+ zt)psZ3_HJ>Woyi4iY9$QuhT zX{4m}I)k*Xw3tfTvXTx=ECf1`#+8oKUTssVjrnc7EcTqlKRddLOAe_jWu!{-Rm&y( zC)plL$*Xwi-Iws!wH11H7%nS?U6P@#y1=^Sn4c2wik;b9XRX{5uCy#mM9{dDZ@5%lsw-D&TT^r)^9>6rskJyzw(^LP zUTOm@ga{}t94P|U+2d=f48;ys2JN8Oq0GtCiN*SW$tERB(8-fx`xIE!`)c-*?v9o7 z4kdl4*BI6VP82IKOCTxR&x2Kz=|k1YR*AsaP+&;u0c0Z}OIMG_!7C=!rv}&P{PZSc z98xEITrba_8cdi@6&(I4Nkv;(N2gv_D~zW?XF*w#4mRtq7?UdH3a4&Zx>S{7Tau%) zk+_~Cz`8Vcqn8=iNkyE3=ZzHLN8?59WtLW$Gm_7}9Zr zYkH2a2bPvmsSz+a4Uo2#ZsatdorT1v>al1so2|F0$)1foTC#i1E#kc@x-%4lmTyS} zD=T?Rql*euYdn^exw8uJvCg~LK%{6ZlrpAZ<))fCWoK5N2`J@NrLQhT3A;I3pt??U z!;OP)^MpW?YW6|7MhXn290codFJ5zLEp=L%hV_bCe&z$BG76BHTC+-9q0ZO|DoTwt zXHUx9wm@BoosvGt8^A7vij$K!k~4Fa@>t7>b{r_T(e|U{`b)};0gP5w*119`d`&v< zg9KJBr&xJR7^P}pvlWZ$)CRET_5_h)M*u6(R6Rl#T4Bm^ml~6xOW8}J9lfdr8g;=B z(JZrq1AUW&T@>?*9$6a-jXYqL!Lj(R>H{gFJYuSI3ztZAwiZrqE@`S@i54u#jstr8DLkp6BEHYO4jpzRZ?MAncG%zOk!53m>socRo&vnqzcECYuIg9D@QdMJ|NSz0S)^ZjQ2^iV%m(?5?b{0~bQnSyTaNT7HtoKUK z7Ry%9wO4HhupR--R)$7b8P-FALCSJU1COQ6Lb7B7D3xni@lRG0+j2g-BC3s+s{m$k zVA?e^JzD|!)H8aiKfL7#6uBH2E7M@CaM|=(unH+;RS{a*1M=lU-m0uzI z?|2DUq53K-3xQUtJe~ck74j-+7CbL6+jG;~6b_6s3_`c0MrMK1*w@Z|f=YjQ(6FT^ zRXV52%KN@LW0>_SxZ%-N#(zm1m?U9AmjIPUx>Xr0(2`TbW`^NP0_$DqpZdHFV5>^+ zNPK0fwA>K^a%aMFjS~LY?i#5|lf)D((cHX(VL7fphh_f-GH4nfQ6C0Tr<_(TjFzMk zuq5N)3u;yD7>Hh_6zdy6nyTw#aN7(aP{vo4T+gND=-kq{AU0>poVZwVZ=P>hjS4QX zWoZsrm%_W=1i?C|4HpC{WjW$BmsGUaFVsjgCL`3UQHQf+HbJy2XC&|%VddP+R<0So zk)$Bm)WBh#aJ0&>QX`;gB{9brv!}Ajc3qa6FJcA#PfJHE_v#+76XuJwLXXYbdDi)` zg3l2-=)xykYf5!etj%C6NR0u~)~MuEFGRyK=#uRdOb%}eVpOl^7AsCmZ>^~~b#)O| z7`#2#K$5C9qg$&ZlOS?xg;%UALzQe)njmZjd?1lRt?aHS>YQa*RW?<|MK9C&demdB z;=t50S+61&yP#GzsHl3U4oYW>#L4!DWW!cZ$W`JjB&j=2Nve`PTYC7bNp5U8aBziT z)$4YHVU9(YOic(dR)wjO_Ed2}kevjX*eB{dn`(HuqJfCm;yIaxuo zs^r3-8P+CW3514130SY?2{yIR16Xq}tO)p7Nv$;q^Yln* zy$uH~vnYTb;8uC8KE>CgLn{Kp5j)StW^iDVE~=J^a1nE>6p)-;!+JvI#~3yU`udBO zOBZ#9u`+F|%8T=5*wz%o3X;1@&O&PQx=b?%*RbPjB#kgvcoC3g9@&iWr(^4NDkM~b zVNse_uE$~vgo(k>b*fyWl#^?jqCxShGW1w92x_yCB8e^*PuFdWs`x5-m7+eL=Dx&Az@(_g@2S!FRldtCuJOV?I6r+0$`OGKwjrTZ*^W1M6H%< zXkB>}1?2~K=Zu3_>dHCgWOhJT&+Y!CM)<39U}|*`vCSYE)dEhzuHsN8Y>p5n&toNr z*fU=hR|}y1@AVpa1xmRn+;P*Y$FyNlqiz%u!Q{N z-Q<~9oMT;K3Vf}Gzltmw9#&9f(0W-@j}3^Cl5v-kF3wT(?F4z*o|T;|h5mOdbe}}m zZuE1M{)|f^X~Et>xRll7U71Cj4vpSH*^D|ttWWPuP;U#Z`(WnG*zApjz@(QEEkjk3%-=E8MI#tQBAW$!)?sy&`i>R|$buY|`ks z4WKd(UPskCIWed6hkK&Y&~o!?6m5kS4O>-)ZZV5p)hXFDtF~RT;V;N$dv4T*Vpun2 zz#R&^p;~E4wS2B6$*T%#RlV9=nk4IWL|8UcTcIOX*mHcnPMrqm%CtyymKJETRZH0k zR$OVh;=*6BN9s5j=L(_FUHi?l)b2{ zY>--O3bOrWZ-24@kaliW+5O>`t4nI!+vRj~4C~1}5Gyvg%^EcrEA#-C+`MkfZUCiy zp9Fq(d0orN9zcZ%s!!gS=<1TZtWC8nXBGjg6j%X23c&ShIaHmMvxt?#2AOh;H8_?s zzgP2EIa1hc`5@APiM16#)FFC-ei@lppCN_K)&X;bKwDCO?3C7;OnKQ-#uRFmS*2_M zZJwO3rF{alpSSbch}vw!y3XnLIr%}}u#&nREIGqUtH#OAr4m?`j% zxJ7`pA}TnwtOG-vOPSW1RgLgU1yIp}$?2<6r0i+J?j%^DRA(Vcc$L(yO9@9-5FJm} zYJx`bUQqO9Yxj6vi_k{j73y__oVv0Z1kI`;<*1Z~t(C|Yb) z2-K=Yy;`8+TA{5}(z0Ojs%b4dL2sbvieZ_Cbxn}7P1Jcd9Fd{Q0INiGp~$K_L1M4v z$W=+@swO47kQ7$vQmr*Zk=I(2-v+36#Oq*HC2(M(Z8rlebn4)#c8y^fZj`FasTEe7 z6r7Z;v%cz}E+jRVc5;8|T1-I~waSsg_MPb9iS7(KtWe6`TFDGuuiIFT%v%bjd>bZz zf&Sc(8oS}M|1&x7tKAhs#%q<)vt>OFOx&>5bG}LftNJiQ?^7lfU6Ph0^<9Q$Kb_k) z;3baDcJr&qZ9pV6_R5~)Umv*Bf~|8 zj9ExsN(@a2e_aY>?}h5J*aldtUGOE>r(orhM6GIp)^g2`>?lEPtUBX(;qS!5DwCZ|Rb8%y9`Y(B1w$*Y6&WF3Bpbyg2@87hnl&EFIz`T%FdPiQv8+5|q)g62Vh7iB zLS0#Dgik8>Oa81Qr1j_k1}|0bXlsoX=*7utd6{j1RmR*!B{szRa}rXeG{rTXZDpy= zv};-^He^?*@bXKpu55->s-CRXtP(@(vdcAWQ%xV5RGa1-HeY8qgrvR{&^)iPPB zCOqaSRgZ+=nT$jCRSl_ut@2oSNH7K?tFJ|dW#u-&EP2^MRV-emgw|vL4b)wAT*FpE zURIfCRtc>&IXW;Bze;E7u}DtAX0sGl=rekknsA-2@K}#Blt2~>dopB@QV6spYA{7o z2c{Qj<89vVugxz1B{?wKKu^QXNGJs1#vFC^oSssJ$tFS03Is9oA)mYjF(jLGr*;-SQrW&@cOgRfxhH_PvvD>al zv$7Q`fPqydMVuP4la36lS+grVsBt4>=(wM3(Kyd?i<#D%K^`!fYy(WrgUB3NlPoH) z(5$k8Vd-7)io3EhWMw(oSFK@73V*#E02(e7HY?$V*syf{hDdlVIbuX?tziduEAk4B zFb+O{fLnhhEzn5^rW6?K?5I3e1C2E-yB-3yvbqp6fXzZ?wMj} zELWW^Ef3rtaFW6<$xP2odD$wZ8fMj|IHfig)iNUHQ4A|c&EXOt7-duozHs$W$cn7# z7MA9~BwK4DNwkjB-Op(&ZB^y|jvHCiD#=1%iRB5{`bXcL|*a|%t1K3$DN@~?yp``OlQWlc)SU!W=u*@p9Yq?cbK-qsb z+$_l^qpsX>YA|A+owrhx9gw>Q&w^0Vyur2WXpk;-wuJkKQlmwd>{&EOMRtSQHVpSa(In|N= zw@yygB}cW|V=3b(Af)h`ylfKdRp8L8wUu^)XnV(v4&Y}Y8C6}q%$mxaGJGT^HMFrNi z)*8i_@;Na2lo5(ANL=nxnZX#*L|V>QMT^wG(vQLirG&k`+OAMf*d1qBnhwmsDcrRr zThE!@olK|b{8EVw6Gv)8Du5*iq*SVxvMFCBAq$iRS_*Z*l5$}D-O<1eo|2Yc6Yd0? z)RvGPO1#2jNr;0~(h&!D>wCZ?2PV>{(t)e|xoxz$lo2gvYc)Eps!D0BOJb`Lxhk{s z@{r9c+~Ph1|726BMtG10jCD8`OK_0XLegMWm+Dte_G~p7fv=Ul6t(ifx2h$t(xtGI ztYXWJqO#m1YrPY&^Y|!d6f=fK4_BrV+3! zDFSwDWQ=fMouuO=@dnxjPeXkpv-a{EmmBVa(V3;K3RA^Gpi*aPsj^?HRBBb{xhrMH zBsHlxRnOr>N=%qX0xqTO1X()wI>Rz@5M(xny{xU!Wejc08H3xXfPz9PX19Uy;BKh} zzFgA;kt4CE>%dq6UJsfeoKWXv_b_ZHV4DGlCWGKQ!+OXyr@CZ&VV6;>=`#v^4QEdh zBRO(}J=e3vP8o5F3KWY}m87lI<~2Upj0f3{lS-J_R#0`Jqzsx)RbbO|$zyfowQMtQ zZZm}^?YDmOx69m za?jD#bU>k#H-K~}NC$eZ=+ZGVr%z1h^$G%uFEkm=rA^*2T()P6kynW5>WW^YB-<~I zqDl^M)4R14$;Ohl)+kF@62WA1rbhUsl_~ESdYJ6_Z;j04FHyU6y;8@ziKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0000WNkl + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data/xml/sprites.xml b/data/xml/sprites.xml new file mode 100755 index 0000000..fe02b6b --- /dev/null +++ b/data/xml/sprites.xml @@ -0,0 +1,5 @@ + + + tex/test1.png + + \ No newline at end of file diff --git a/deprecate.py b/deprecate.py new file mode 100755 index 0000000..cce8950 --- /dev/null +++ b/deprecate.py @@ -0,0 +1,20 @@ +import warnings +import functools + + +def deprecated(func): + """This is a decorator which can be used to mark functions + as deprecated. It will result in a warning being emitted + when the function is used.""" + + @functools.wraps(func) + def new_func(*args, **kwargs): + warnings.warn( + "Call to deprecated function %(funcname)s." % { + 'funcname': func.__name__, + }, + category=DeprecationWarning, + stacklevel=2 + ) + return func(*args, **kwargs) + return new_func diff --git a/enums.py b/enums.py index 8e6b649..e00ecb3 100755 --- a/enums.py +++ b/enums.py @@ -49,3 +49,10 @@ pl.particle = 4 pl.sprite = 5 pl.composite1 = 6 pl.composite2 = 7 + +tt = enum() +tt.diffuse = 0 # the diffuse texture sets the colors and general brightness of the texture. if the same texture is used as the emissive texture, the model is effectively "fullbright" +tt.emissive = 1 # this texture is blended with the diffuse texture as the light level drops (this can be used to add running lights or glow to a ship, or light up the dark side of a planet, otherwise pure "black" is a good choice) +tt.specular = 2 # adding a specular map allows you to add areas of low or high reflectivity to your texture +tt.normal = 3 # normal maps allow bump mapping and other tweaks, with each channel representing the direction of the normal (red = -1x to 1x, green = -1y to 1y, blue = 0z to 1z) + diff --git a/gamedata.py b/gamedata.py index 638e76c..b086eb0 100755 --- a/gamedata.py +++ b/gamedata.py @@ -6,6 +6,7 @@ except ImportError: from elementtree.ElementTree import parse import files import shader +from deprecate import deprecated class MissingNode(object): def __init__(self): @@ -221,7 +222,24 @@ def load_xml_files(binfile, xmlfile): return XMLGameDataReader(bintree, xmltree) +def get(dataname): + if dataname in get.cache: + return get.cache[dataname] + + bin = files.mgr.path("xml/def", "%s.xml" % (dataname,)) + xml = files.mgr.path("xml", "%s.xml" % (dataname,)) + + if not os.path.exists(bin) or not os.path.exists(xml): + raise OSError("XML data file does not exist") + + dataobj = load_xml_files(bin, xml) + + get.cache[dataname] = dataobj + return dataobj + +get.cache = {} +@deprecated def load_gamedata(): bins = glob.glob(files.mgr.path("xml/def", "*.xml")) xmls = glob.glob(files.mgr.path("xml", "*.xml")) @@ -235,7 +253,6 @@ def load_gamedata(): dataobjs = {} for fn in ffns: - print fn #DELME binfile = files.mgr.path("xml/def", fn) xmlfile = files.mgr.path("xml", fn) dataobj = load_xml_files(binfile, xmlfile) diff --git a/gameobj.py b/gameobj.py new file mode 100755 index 0000000..c57501b --- /dev/null +++ b/gameobj.py @@ -0,0 +1,5 @@ + +class gameobj(object): + def __init__(self): + pass + diff --git a/lesson6.py b/lesson6.py new file mode 100755 index 0000000..72e97c6 --- /dev/null +++ b/lesson6.py @@ -0,0 +1,226 @@ +#!/usr/bin/env python + +# +# This code was created by Richard Campbell '99 (ported to Python/PyOpenGL by John Ferguson 2000) +# +# The port was based on the lesson5 tutorial module by Tony Colston (tonetheman@hotmail.com). +# +# If you've found this code useful, please let me know (email John Ferguson at hakuin@voicenet.com). +# +# See original source and C based tutorial at http:#nehe.gamedev.net +# +# Note: +# ----- +# Now, I assume you've read the prior tutorial notes and know the deal here. The one major, new requirement +# is to have a working version of PIL (Python Image Library) on your machine. +# +# General Users: +# -------------- +# I think to use textures at all you need Nunmeric Python, I tried without it and BAM Python didn't "like" the texture API. +# +# Win32 Users: +# ------------ +# Well, here's the install I used to get it working: +# [1] py152.exe - include the TCL install! +# [2] PyOpenGL.EXE - probably the latest, the Vaults notes should give you a clue. +# [3] Distutils-0.9.win32.exe for step #4 +# [4] Numerical-15.3.tgz - run the setup.py (need VC++ on your machine, otherwise, have fun with #3, it looks fixable to use gCC). +# +# Win98 users (yes Win98, I have Mandrake on the other partition okay?), you need to the Tcl bin directory in your PATH, not PYTHONPATH, +# just the DOS PATH. +# +# BTW, since this is Python make sure you use tabs or spaces to indent, I had numerous problems since I +# was using editors that were not sensitive to Python. +# +from OpenGL.GL import * +from OpenGL.GLUT import * +from OpenGL.GLU import * +from Image import * + +# Some api in the chain is translating the keystrokes to this octal string +# so instead of saying: ESCAPE = 27, we use the following. +ESCAPE = '\033' + +# Number of the glut window. +window = 0 + +# Rotations for cube. +xrot = yrot = zrot = 0.0 + +texture = 0 + +def LoadTextures(): + #global texture + image = open("NeHe.bmp") + + ix = image.size[0] + iy = image.size[1] + image = image.tostring("raw", "RGBX", 0, -1) + + # Create Texture + # There does not seem to be support for this call or the version of PyOGL I have is broken. + #glGenTextures(1, texture) + #glBindTexture(GL_TEXTURE_2D, texture) # 2d texture (x and y size) + + glPixelStorei(GL_UNPACK_ALIGNMENT,1) + glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL) + +# A general OpenGL initialization function. Sets all of the initial parameters. +def InitGL(Width, Height): # We call this right after our OpenGL window is created. + LoadTextures() + glEnable(GL_TEXTURE_2D) + glClearColor(0.0, 0.0, 0.0, 0.0) # This Will Clear The Background Color To Black + glClearDepth(1.0) # Enables Clearing Of The Depth Buffer + glDepthFunc(GL_LESS) # The Type Of Depth Test To Do + glEnable(GL_DEPTH_TEST) # Enables Depth Testing + glShadeModel(GL_SMOOTH) # Enables Smooth Color Shading + + glMatrixMode(GL_PROJECTION) + glLoadIdentity() # Reset The Projection Matrix + # Calculate The Aspect Ratio Of The Window + gluPerspective(45.0, float(Width)/float(Height), 0.1, 100.0) + + glMatrixMode(GL_MODELVIEW) + +# The function called when our window is resized (which shouldn't happen if you enable fullscreen, below) +def ReSizeGLScene(Width, Height): + if Height == 0: # Prevent A Divide By Zero If The Window Is Too Small + Height = 1 + + glViewport(0, 0, Width, Height) # Reset The Current Viewport And Perspective Transformation + glMatrixMode(GL_PROJECTION) + glLoadIdentity() + gluPerspective(45.0, float(Width)/float(Height), 0.1, 100.0) + glMatrixMode(GL_MODELVIEW) + +# The main drawing function. +def DrawGLScene(): + global xrot, yrot, zrot, texture + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Clear The Screen And The Depth Buffer + glLoadIdentity() # Reset The View + glTranslatef(0.0,0.0,-5.0) # Move Into The Screen + + glRotatef(xrot,1.0,0.0,0.0) # Rotate The Cube On It's X Axis + glRotatef(yrot,0.0,1.0,0.0) # Rotate The Cube On It's Y Axis + glRotatef(zrot,0.0,0.0,1.0) # Rotate The Cube On It's Z Axis + + # Note there does not seem to be support for this call. + #glBindTexture(GL_TEXTURE_2D,texture) # Rotate The Pyramid On It's Y Axis + + glBegin(GL_QUADS) # Start Drawing The Cube + + # Front Face (note that the texture's corners have to match the quad's corners) + glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 1.0) # Bottom Left Of The Texture and Quad + glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, 1.0) # Bottom Right Of The Texture and Quad + glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, 1.0) # Top Right Of The Texture and Quad + glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 1.0) # Top Left Of The Texture and Quad + + # Back Face + glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, -1.0) # Bottom Right Of The Texture and Quad + glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, -1.0) # Top Right Of The Texture and Quad + glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, 1.0, -1.0) # Top Left Of The Texture and Quad + glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, -1.0) # Bottom Left Of The Texture and Quad + + # Top Face + glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0) # Top Left Of The Texture and Quad + glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, 1.0, 1.0) # Bottom Left Of The Texture and Quad + glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, 1.0, 1.0) # Bottom Right Of The Texture and Quad + glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, -1.0) # Top Right Of The Texture and Quad + + # Bottom Face + glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, -1.0, -1.0) # Top Right Of The Texture and Quad + glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, -1.0, -1.0) # Top Left Of The Texture and Quad + glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, 1.0) # Bottom Left Of The Texture and Quad + glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0) # Bottom Right Of The Texture and Quad + + # Right face + glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, -1.0) # Bottom Right Of The Texture and Quad + glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, -1.0) # Top Right Of The Texture and Quad + glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, 1.0, 1.0) # Top Left Of The Texture and Quad + glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, 1.0) # Bottom Left Of The Texture and Quad + + # Left Face + glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0) # Bottom Left Of The Texture and Quad + glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0) # Bottom Right Of The Texture and Quad + glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, 1.0) # Top Right Of The Texture and Quad + glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0) # Top Left Of The Texture and Quad + + glEnd(); # Done Drawing The Cube + + xrot = xrot + 0.2 # X rotation + yrot = yrot + 0.2 # Y rotation + zrot = zrot + 0.2 # Z rotation + + # since this is double buffered, swap the buffers to display what just got drawn. + glutSwapBuffers() + +# The function called whenever a key is pressed. Note the use of Python tuples to pass in: (key, x, y) +def keyPressed(*args): + # If escape is pressed, kill everything. + if args[0] == ESCAPE: + glutDestroyWindow(window) + sys.exit() + +def main(): + global window + # For now we just pass glutInit one empty argument. I wasn't sure what should or could be passed in (tuple, list, ...) + # Once I find out the right stuff based on reading the PyOpenGL source, I'll address this. + glutInit("") + + # Select type of Display mode: + # Double buffer + # RGBA color + # Alpha components supported + # Depth buffer + glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH) + + # get a 640 x 480 window + glutInitWindowSize(640, 480) + + # the window starts at the upper left corner of the screen + glutInitWindowPosition(0, 0) + + # Okay, like the C version we retain the window id to use when closing, but for those of you new + # to Python (like myself), remember this assignment would make the variable local and not global + # if it weren't for the global declaration at the start of main. + window = glutCreateWindow("Jeff Molofee's GL Code Tutorial ... NeHe '99") + + # Register the drawing function with glut, BUT in Python land, at least using PyOpenGL, we need to + # set the function pointer and invoke a function to actually register the callback, otherwise it + # would be very much like the C version of the code. + glutSetDisplayFuncCallback(DrawGLScene) + glutDisplayFunc() + + # Uncomment this line to get full screen. + # glutFullScreen() + + # When we are doing nothing, redraw the scene. + glutSetIdleFuncCallback(DrawGLScene) + glutIdleFunc() + + # Register the function called when our window is resized. + glutSetReshapeFuncCallback(ReSizeGLScene) + glutReshapeFunc() + + # Register the function called when the keyboard is pressed. + glutSetKeyboardFuncCallback(keyPressed) + glutKeyboardFunc() + + # Initialize our window. + InitGL(640, 480) + + # Start Event Processing Engine + glutMainLoop() + +# Print message to console, and kick off the main to get it rolling. +print "Hit ESC key to quit." +main() + diff --git a/looprun.bat b/looprun.bat old mode 100644 new mode 100755 index c24d6b9..9f601e3 --- a/looprun.bat +++ b/looprun.bat @@ -2,4 +2,5 @@ :restart roc_test.py pause +echo Starting... goto restart diff --git a/models.py b/models.py new file mode 100755 index 0000000..bb04bf1 --- /dev/null +++ b/models.py @@ -0,0 +1,146 @@ +import enums + +class Vertex(object): + __slots__ = [ + 'v', # vertex coordinates + 'n', # normal + 't', # texture coordinates + 'c', # color + ] + +class Model_Manager(object): + def __init__(self): + self.load_textypes() + self.load_textures() + self.load_materials() + self.load_models() + + def load_textypes(): + self.textypes = {} + self.textypes[enums.tt.diffuse] = TextureType(GL_TEXTURE0, GL_TEXTURE_2D, GL_CLAMP, GL_CLAMP, GL_NEAREST, GL_NEAREST) + self.textypes[enums.tt.dark] = TextureType(GL_TEXTURE1, GL_TEXTURE_2D) + self.textypes[enums.tt.specular] = TextureType(GL_TEXTURE2, GL_TEXTURE_2D) + self.textypes[enums.tt.normal] = TextureType(GL_TEXTURE3, GL_TEXTURE_2D) + + def get_textype(self, textype): + if isinstance(textype, TextureType): + return textype + return self.textypes[textype] + + def load_textures(self): + gamedata.get('textures') + + def load_textures(self): + gamedata.get('materials') + + def load_textures(self): + gamedata.get('models') + +mgr = Model_Manager() + +class TextureType(object): + def __init__(self, texunit, texdim, wrap_s=GL_CLAMP, wrap_t=GL_CLAMP, mag=GL_LINEAR, min=GL_LINEAR) + self.texunit = texunit + self.texdim = texdim + self.wrap_s = wrap_s + self.wrap_t = wrap_t + self.mag = mag + self.min = min + + def initialize(self): + glActiveTexture(self.texunit) + glTexParameterf(self.texdim, GL_TEXTURE_WRAP_S, self.wrap_s) + glTexParameterf(self.texdim, GL_TEXTURE_WRAP_T, self.wrap_t) + glTexParameterf(self.texdim, GL_TEXTURE_MAG_FILTER, self.mag) + glTexParameterf(self.texdim, GL_TEXTURE_MIN_FILTER, self.min) + + def get_dimension(self): + return self.texdim + + def activate(self): + glActiveTexture(self.texunit) + + + + +class Material(object): + + def __init__(self): + pass + def attach_texture(self, textype, texid): + textype = mgr.get_textype(textype) + textype.activate() + + self.texid + +class Texture(object): + def __init__(self): + pass + def load(self, file): + img = files.mgr.png(file) + texid, = glGenTextures(1) + + self.id = texid + + imgdata = pygame.image.tostring(img, "RGBA") + imgr = img.get_rect() + + glBindTexture(textype.get_dimension(), texid) + glTexImage2D(textype.get_dimension(), 0, GL_RGBA8, imgr.w, imgr.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgdata) + glBindTexture(textype.get_dimension(), 0) + +class Model(object): + def __init__(self): + self.vertexes = [] + + + def set_rotation(self): + glPushMatrix() + glMultMatrixf(self.rot.get_matrix()) + + def unset_rotation(self): + glPopMatrix() + + def bind_textures(self): + glBindTexture(GL_TEXTURE_2D + def unbind_textures(self): + + def draw(self): + self.bind_textures() + glBegin(GL_TRIANGLES) + for v in self.vertexes: + self.draw_vertex(v) + glEnd(GL_TRIANGLES) + self.unbind_textures() + + def draw_vertex(self, v): + glColor3f(v.c[0], v.c[1], v.c[2]) + glNormal3f(v.n.x, v.n.y, v.n.z) + glTexCoord2f(v.t[0], v.t[1]) + glVertex3f(v.v.x, v.v.y, v.v.z) + + + + +class Sprite(object): + def __init__(self): + Model.__init__(self) + vl = [Vertex() for x in xrange(4)] + + normal = vect(0.0, 0.0, 1.0) + white = (1.0, 1.0, 1.0) + for v in vl: + v.n = normal + v.c = white + + tl, bl, tr, br = vl + + tl.v = vect(-0.5, -0.5, 0.0); tl.t = (0.0, 0.0) + bl.v = vect(-0.5, 0.5, 0.0); bl.t = (0.0, 1.0) + tr.v = vect( 0.5, -0.5, 0.0); tr.t = (1.0, 0.0) + br.v = vect( 0.5, 0.5, 0.0); br.t = (1.0, 1.0) + + self.corners = vl + self.vertexes = [tl, bl, tr, bl, tr, br] + + def set_texture( \ No newline at end of file diff --git a/roc.py b/roc.py new file mode 100755 index 0000000..f713ce4 --- /dev/null +++ b/roc.py @@ -0,0 +1,86 @@ +import pygame +from pygame.locals import * +import gamedata +import gametimer +import video +import shader +import inputs +from OpenGL.GL import * + + +def init2d(): + init(videoinit=video.init2d) + +def init3d(): + init(videoinit=video.init3d) + +def init(videoinit): + pygame.init() + + size = width, height = (1600,1200) + size = width, height = (1024,768) + + video.set_res(size) + videoinit() + video.enable_vsync() + +def test_frame(): + from PIL import Image + + # pink triangle + glBegin(GL_TRIANGLE_STRIP) + glNormal3f(0.0, 0.0, 1.0) + glColor4f(1.0, 0.0, 0.5, 1.0) + glVertex3f( 20.0, 50.0, 1.0) + glVertex3f( 20.0, 600.0, 1.0) + glVertex3f( 400.0, 50.0, 1.0) + glEnd() + + # yellow square + glBegin(GL_TRIANGLE_STRIP) + glNormal3f(0.0, 0.0, 1.0) + glColor4f(1.0, 1.0, 0.0, 1.0) + glVertex3f( 150.0, 20.0, -50.0) + glVertex3f( 150.0, 400.0, -50.0) + glVertex3f( 360.0, 20.0, -50.0) + glVertex3f( 360.0, 400.0, -50.0) + glEnd() + + # texture test + glBegin(GL_TRIANGLE_STRIP) + glNormal3f(0.0, 0.0, 1.0) + glColor4f(1.0, 1.0, 1.0, 1.0) + glVertex3f( 500.0, 300.0, 5.0) + glVertex3f( 500.0, 500.0, 5.0) + glVertex3f( 700.0, 300.0, 5.0) + glVertex3f( 700.0, 500.0, 5.0) + glEnd() + + +def main(): + gametimer.start_loop() + while True: + events = pygame.event.get() + gametimer.next_frame() + pygame.event.pump() + for ev in events: + if ev.type == QUIT: + inputs.add_command('exit') + break + elif ev.type == KEYUP: + inputs.keyup(ev.key) + elif ev.type == KEYDOWN: + inputs.keydown(ev.key) + #elif ev.type == VIDEOEXPOSE: + # video.force_redraw() + elif ev.type in (MOUSEBUTTONDOWN, MOUSEBUTTONUP): + pass + + if 'exit' in inputs.commands: + break + + video.predraw() + + test_frame() + + video.next_frame() diff --git a/roc_test.py b/roc_test.py index 9f39b7e..d61fffc 100755 --- a/roc_test.py +++ b/roc_test.py @@ -1,19 +1,4 @@ -import pygame -from pygame.locals import * -import gamedata -import gametimer -import video -import shader +import roc -pygame.init() -gamedata.load_gamedata() - -size = width, height = (1600,1200) -size = width, height = (1024,768) - -video.set_res(size) -video.init() -video.enable_vsync() -gametimer.start_loop() - -print shader.mgr.detect() +roc.init2d() +roc.main() \ No newline at end of file diff --git a/shader.py b/shader.py index a0ab67f..56443a3 100755 --- a/shader.py +++ b/shader.py @@ -7,13 +7,19 @@ except ImportError: pass from OpenGL.arrays import GLintArray, GLcharArray, GLsizeiArray, GLcharARBArray import sys +import gamedata + class shader_manager(object): def __init__(self): # Fixed Pipeline is always zero self.shaderlib = {'ffp': 0} self.shaderprograms = {} - self.shadersources = [] + + self.initshadersources = [] + self.initmode = 'auto' + self.initialized = False + def use_gl2_shaders(self): self.funcs = { 'create': glCreateShader, @@ -74,6 +80,10 @@ class shader_manager(object): } def init_gl(self): + if self.initialized: + return + + self.initialized = True import files #print glGetString(GL_EXTENSIONS) if True: @@ -82,7 +92,7 @@ class shader_manager(object): self.use_arb_shaders() #self.use_gl2_shaders() - for name, vertex, fragment in self.shadersources: + for name, vertex, fragment in self.initshadersources: vf = files.mgr.open('shaders/%s.vert' % (vertex,)) ff = files.mgr.open('shaders/%s.frag' % (fragment,)) vs = self.funcs['create'](GL_VERTEX_SHADER) @@ -129,6 +139,13 @@ class shader_manager(object): return workable_shaders + def autoinit(self): + shadertypes = self.detect() + + if not shadertypes: + raise ValueError, "No working shaders detected" + + self.init_shadertype(shadertypes[0]) def init_shadertype(self, shadertype): if shadertype == "GL2": @@ -143,9 +160,9 @@ class shader_manager(object): def select(self, shader): - if self.shadersources: + if self.initshadersources: self.init_gl() - self.shadersources = [] + self.initshadersources = [] if not shader in self.shaderlib: self.funcs['use'](0) return True @@ -187,8 +204,12 @@ class shader_manager(object): return True + def load(self): + shader_data = gamedata.get('shaders') + self.load_shaders(shader_data) + def load_shaders(self, shaders): for shader in shaders.shader: - self.shadersources.append((shader['id'], shader['vertex'], shader['fragment'])) + self.initshadersources.append((shader['id'], shader['vertex'], shader['fragment'])) mgr = shader_manager() diff --git a/sprite.py b/sprite.py new file mode 100755 index 0000000..1f36a08 --- /dev/null +++ b/sprite.py @@ -0,0 +1,69 @@ +import files +import os +from OpenGL.GL import * +from py3ds.example.gltexture import Texture + +class renderable_sprite(object): + """ + Internal class to create a textured quad for a sprite to live on. + Multiple sprites can use the same sprite_tex if the graphic they want to + display is the same. + """ + def __init__(self): + self.gltex = None + self.gllist = None + self.texfile = None + self.scale = 1.0 + def load_name(self, name): + self.texfile = files.mgr.open(os.path.join('sprite', name + '.png')) + def set_file(self, fileobj): + self.texfile = fileobj + def update(self): + pass + def render(self): + if self.gltex == None: + self.gltex = Texture(self.texfile) + self.texfile.close() + self.texfile = None + if self.gllist == None: + glPushMatrix() + #glLoadIdentity() + dl = glGenLists(1) + if dl == 0: + raise GLError, "cannot allocate display list" + glNewList(dl, GL_COMPILE) + glEnable(GL_BLEND) + glEnable(GL_DEPTH_TEST) + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) + self.gltex.enable() + self.gltex.bind() + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) + glBegin(GL_TRIANGLE_STRIP) + glNormal3f(1.0, 0.0, 0.0) + glTexCoord2f(1.0, 1.0); glVertex3f( 0.0, 1.0, 1.0) + glTexCoord2f(0.0, 1.0); glVertex3f( 0.0, 1.0, -1.0) + glTexCoord2f(1.0, 0.0); glVertex3f(-0.0, -1.0, 1.0) + glTexCoord2f(0.0, 0.0); glVertex3f(-0.0, -1.0, -1.0) + glEnd() + + self.gltex.disable() + glDisable(GL_BLEND) + glEndList() + self.gllist = dl + glPopMatrix() + glCallList(self.gllist) + + +class sprite_manager(object): + def __init__(self): + self.sprite_cache = {} + def get(self, name): + if name in self.sprite_cache: + return self.sprite_cache[name] + + s = renderable_sprite() + s.load_name(name) + self.sprite_cache[name] = s + return s + +mgr = sprite_manager() \ No newline at end of file diff --git a/texture.py b/texture.py new file mode 100755 index 0000000..57d9eab --- /dev/null +++ b/texture.py @@ -0,0 +1,21 @@ + +class texture_wrapper(object): + def __init__(self): + pass + + def load_name(self, name): + pass + +class texture_manager(object): + def __init__(self): + self.texture_cache = {} + def get(self, name): + if name in self.texture_cache: + return self.texture_cache[name] + + t = texture_wrapper() + t.load_name(name) + self.texture_cache[name] = t + return t + +mgr = texture_manager() \ No newline at end of file diff --git a/video.py b/video.py index d04334a..58eb880 100755 --- a/video.py +++ b/video.py @@ -6,6 +6,10 @@ from OpenGL.arrays import GLcharArray import pygame from pygame.locals import * import sys +import shader + +height=None +width=None def enable_vsync(): if sys.platform != 'darwin': @@ -20,13 +24,60 @@ def enable_vsync(): print "Unable to set vsync mode, using driver defaults" def skipping_next_frame(): return False -def set_res((width, height)): +def set_res((width_in, height_in)): + global height, width + + height = height_in + width = width_in + if height==0: height=1 - pygame.display.gl_set_attribute(GL_DEPTH_SIZE, 24) + if width==0: + width=1 + #pygame.display.gl_set_attribute(GL_DEPTH_SIZE, 24) video_flags = OPENGL|DOUBLEBUF #video_flags = OPENGL|DOUBLEBUF|FULLSCREEN pygame.display.set_mode((width, height), video_flags) + +def get_res(): + return (height, width) + +def get_height(): + return height + +def get_width(): + return width + + +def init2d(): + #print pygame.display.gl_get_attribute(GL_DEPTH_SIZE) + glViewport(0, 0, width, height) + glMatrixMode(GL_PROJECTION) + glLoadIdentity() + glOrtho(-0.5, float(width)-0.5, float(height)-0.5, -0.5, 256.0, -256.0) + glMatrixMode(GL_MODELVIEW) + glLoadIdentity() + #glRotatef(120.0, 1.0, 0.0, 0.0) + + + glClearColor(0.0, 0.0, 0.0, 0.0) + glClearDepth(-256.0) + + glShadeModel(GL_SMOOTH) + glEnable(GL_DEPTH_TEST) + glEnable(GL_CULL_FACE) + glEnable(GL_TEXTURE_2D) + glDepthFunc(GL_GEQUAL) + glEnable(GL_BLEND) + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) + + shader.mgr.load() + shader.mgr.init_gl() + shader.mgr.select("ffp") + glDisable(GL_LIGHTING) + + +def init3d(): #print pygame.display.gl_get_attribute(GL_DEPTH_SIZE) glViewport(0, 0, width, height) glMatrixMode(GL_PROJECTION) @@ -35,8 +86,6 @@ def set_res((width, height)): glMatrixMode(GL_MODELVIEW) glLoadIdentity() -def init(): - import shader glShadeModel(GL_SMOOTH) glClearColor(0.0, 0.0, 0.0, 0.0) glClearDepth(1.0) @@ -60,16 +109,20 @@ def init(): glEnable( GL_LIGHT1 ) """ """ + + shader.mgr.load() + shader.mgr.init_gl() shader.mgr.select("standard") glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (0.3, 0.3, 0.3, 1.0)) #glEnable(GL_AUTO_NORMAL) + def predraw(): glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) glLoadIdentity() #glTranslatef(-1.0, 0.0, -9.0) - glRotatef(270.0, 1.0, 0.0, 0.0) + #glRotatef(270.0, 1.0, 0.0, 0.0) def next_frame(): pygame.display.flip()