GLS.Scene.pas 252 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004
  1. //
  2. // The graphics engine GLScene
  3. //
  4. unit GLS.Scene;
  5. (*
  6. Base classes and structures. The registered classes are:
  7. [TGLScene, TGLLightSource, TGLCamera, TGLProxyObject,
  8. TGLRenderPoint, TGLMemoryViewer, TGLDirectOpenGL]
  9. *)
  10. interface
  11. {$I Stage.Defines.inc}
  12. uses
  13. Winapi.Windows,
  14. Winapi.OpenGL,
  15. Winapi.OpenGLext,
  16. System.Classes,
  17. System.SysUtils,
  18. System.UITypes,
  19. System.Math,
  20. Vcl.Graphics,
  21. Vcl.Controls,
  22. Stage.VectorTypes,
  23. Stage.VectorGeometry,
  24. Stage.OpenGLTokens,
  25. GLS.XCollection,
  26. Stage.Strings,
  27. Stage.PipelineTransform,
  28. Stage.TextureFormat,
  29. Stage.Utils,
  30. Stage.Logger,
  31. GLS.Context,
  32. GLS.Silhouette,
  33. GLS.PersistentClasses,
  34. GLS.State,
  35. GLS.Graphics,
  36. GLS.GeometryBB,
  37. GLS.VectorLists,
  38. GLS.Texture,
  39. GLS.Color,
  40. GLS.BaseClasses,
  41. GLS.Coordinates,
  42. GLS.RenderContextInfo,
  43. GLS.Material,
  44. GLS.XOpenGL,
  45. GLS.Selection,
  46. GLS.ApplicationFileIO,
  47. GLS.ImageUtils;
  48. type
  49. // Defines which features are taken from the master object.
  50. TGLProxyObjectOption = (pooEffects, pooObjects, pooTransformation);
  51. TGLProxyObjectOptions = set of TGLProxyObjectOption;
  52. TGLCameraInvarianceMode = (cimNone, cimPosition, cimOrientation);
  53. TGLSceneViewerMode = (svmDisabled, svmDefault, svmNavigation, svmGizmo);
  54. const
  55. cDefaultProxyOptions = [pooEffects, pooObjects, pooTransformation];
  56. GLSCENE_REVISION = '$Revision: 2024$';
  57. GLSCENE_VERSION = 'v2.5 %s';
  58. type
  59. TGLNormalDirection = (ndInside, ndOutside);
  60. // Used to describe the changes in an object, which have to be reflected in the scene
  61. TGLObjectChange = (ocTransformation, ocAbsoluteMatrix, ocInvAbsoluteMatrix, ocStructure);
  62. TGLObjectChanges = set of TGLObjectChange;
  63. TGLObjectBBChange = (oBBcChild, oBBcStructure);
  64. TGLObjectBBChanges = set of TGLObjectBBChange;
  65. // Flags for design notification
  66. TGLSceneOperation = (soAdd, soRemove, soMove, soRename, soSelect, soBeginUpdate, soEndUpdate);
  67. (* Options for the rendering context.
  68. roSoftwareMode: force software rendering.
  69. roDoubleBuffer: enables double-buffering.
  70. roRenderToWindows: ignored (legacy).
  71. roTwoSideLighting: enables two-side lighting model.
  72. roStereo: enables stereo support in the driver (need to test with a stereo device...)
  73. roDestinationAlpha: request an Alpha channel for the rendered output
  74. roNoColorBuffer: don't request a color buffer (color depth setting ignored)
  75. roNoColorBufferClear: do not clear the color buffer automatically, if the
  76. whole viewer is fully repainted each frame, this can improve framerate
  77. roNoSwapBuffers: don't perform RenderingContext.SwapBuffers after rendering
  78. roNoDepthBufferClear: do not clear the depth buffer automatically. Useful for early-z culling.
  79. roForwardContext: force OpenGL forward context *)
  80. TGLContextOption = (roSoftwareMode, roDoubleBuffer, roStencilBuffer,
  81. roRenderToWindow, roTwoSideLighting, roStereo,
  82. roDestinationAlpha, roNoColorBuffer, roNoColorBufferClear,
  83. roNoSwapBuffers, roNoDepthBufferClear, roDebugContext, roForwardContext, roOpenGL_ES2_Context);
  84. TGLContextOptions = set of TGLContextOption;
  85. // IDs for limit determination
  86. TGLLimitType = (limClipPlanes, limEvalOrder, limLights, limListNesting,
  87. limModelViewStack, limNameStack, limPixelMapTable, limProjectionStack,
  88. limTextureSize, limTextureStack, limViewportDims, limAccumAlphaBits,
  89. limAccumBlueBits, limAccumGreenBits, limAccumRedBits, limAlphaBits,
  90. limAuxBuffers, limBlueBits, limGreenBits, limRedBits, limIndexBits,
  91. limStereo, limDoubleBuffer, limSubpixelBits, limDepthBits, limStencilBits,
  92. limNbTextureUnits);
  93. TGLBaseSceneObject = class;
  94. TGLSceneObjectClass = class of TGLBaseSceneObject;
  95. TGLCustomSceneObject = class;
  96. TGLScene = class;
  97. TGLBehaviour = class;
  98. TGLBehaviourClass = class of TGLBehaviour;
  99. TGLBehaviours = class;
  100. TGLEffect = class;
  101. TGLEffectClass = class of TGLEffect;
  102. TGLEffects = class;
  103. TGLSceneBuffer = class;
  104. (* Possible styles/options for a GLScene object. Allowed styles are:
  105. osDirectDraw : object shall not make use of compiled call lists, but issue
  106. direct calls each time a render should be performed.
  107. osIgnoreDepthBuffer : object is rendered with depth test disabled,
  108. this is true for its children too.
  109. osNoVisibilityCulling : whatever the VisibilityCulling setting,
  110. it will be ignored and the object rendered *)
  111. TGLObjectStyle = (
  112. osDirectDraw,
  113. osIgnoreDepthBuffer,
  114. osNoVisibilityCulling);
  115. TGLObjectStyles = set of TGLObjectStyle;
  116. // Interface to objects that need initialization
  117. IGLInitializable = interface
  118. ['{EA40AE8E-79B3-42F5-ADF1-7A901B665E12}']
  119. procedure InitializeObject(ASender: TObject; const ARci: TGLRenderContextInfo);
  120. end;
  121. // Just a list of objects that support IGLInitializable.
  122. TGLInitializableObjectList = class(TList)
  123. private
  124. function GetItems(const Index: Integer): IGLInitializable;
  125. procedure PutItems(const Index: Integer; const Value: IGLInitializable);
  126. public
  127. function Add(const Item: IGLInitializable): Integer;
  128. property Items[const Index: Integer]: IGLInitializable read GetItems write PutItems; default;
  129. end;
  130. (* Base class for all scene objects.
  131. A scene object is part of scene hierarchy (each scene object can have
  132. multiple children), this hierarchy primarily defines transformations
  133. (each child coordinates are relative to its parent), but is also used
  134. for depth-sorting, bounding and visibility culling purposes.
  135. Subclasses implement either visual scene objects (that are made to be
  136. visible at runtime, like a Cube) or structural objects (that influence
  137. rendering or are used for varied structural manipulations,
  138. like the ProxyObject).
  139. To add children at runtime, use the AddNewChild method of TGLBaseSceneObject;
  140. other children manipulations methods and properties are provided (to browse,
  141. move and delete them). Using the regular TComponent methods is not encouraged *)
  142. TGLBaseSceneObject = class(TGLCoordinatesUpdateAbleComponent)
  143. private
  144. FAbsoluteMatrix, FInvAbsoluteMatrix: TGLMatrix;
  145. FLocalMatrix: TGLMatrix;
  146. FObjectStyle: TGLObjectStyles;
  147. FListHandle: TGLListHandle; // created on 1st use
  148. FPosition: TGLCoordinates;
  149. FDirection, FUp: TGLCoordinates;
  150. FScaling: TGLCoordinates;
  151. FChanges: TGLObjectChanges;
  152. FParent: TGLBaseSceneObject;
  153. FScene: TGLScene;
  154. FBBChanges: TGLObjectBBChanges;
  155. FBoundingBoxPersonalUnscaled: THmgBoundingBox;
  156. FBoundingBoxOfChildren: THmgBoundingBox;
  157. FBoundingBoxIncludingChildren: THmgBoundingBox;
  158. FChildren: TGLPersistentObjectList; // created on 1st use
  159. FVisible: Boolean;
  160. FUpdateCount: Integer;
  161. FShowAxes: Boolean;
  162. FRotation: TGLCoordinates; // current rotation angles
  163. FIsCalculating: Boolean;
  164. FObjectsSorting: TGLObjectsSorting;
  165. FVisibilityCulling: TGLVisibilityCulling;
  166. FOnProgress: TGLProgressEvent;
  167. FOnAddedToParent: TNotifyEvent;
  168. FBehaviours: TGLBehaviours;
  169. FEffects: TGLEffects;
  170. FPickable: Boolean;
  171. FOnPicked: TNotifyEvent;
  172. FTagObject: TObject;
  173. FTagFloat: Single;
  174. objList: TGLPersistentObjectList;
  175. distList: TGLSingleList;
  176. /// FOriginalFiler: TFiler; //used to allow persistent events in behaviours & effects
  177. (* If somebody could look at DefineProperties, ReadBehaviours, ReadEffects
  178. and verify code is safe to use then it could be uncommented *)
  179. function Get(Index: Integer): TGLBaseSceneObject; inline;
  180. function GetCount: Integer; inline;
  181. function GetIndex: Integer; inline;
  182. procedure SetParent(const val: TGLBaseSceneObject); inline;
  183. procedure SetIndex(aValue: Integer);
  184. procedure SetDirection(AVector: TGLCoordinates);
  185. procedure SetUp(AVector: TGLCoordinates);
  186. function GetMatrix: PGLMatrix; inline;
  187. procedure SetPosition(APosition: TGLCoordinates);
  188. procedure SetPitchAngle(AValue: Single);
  189. procedure SetRollAngle(AValue: Single);
  190. procedure SetTurnAngle(AValue: Single);
  191. procedure SetRotation(aRotation: TGLCoordinates);
  192. function GetPitchAngle: Single; inline;
  193. function GetTurnAngle: Single; inline;
  194. function GetRollAngle: Single; inline;
  195. procedure SetShowAxes(AValue: Boolean);
  196. procedure SetScaling(AValue: TGLCoordinates);
  197. procedure SetObjectsSorting(const val: TGLObjectsSorting);
  198. procedure SetVisibilityCulling(const val: TGLVisibilityCulling);
  199. procedure SetBehaviours(const val: TGLBehaviours);
  200. function GetBehaviours: TGLBehaviours;
  201. procedure SetEffects(const val: TGLEffects);
  202. function GetEffects: TGLEffects;
  203. function GetAbsoluteAffineScale: TAffineVector;
  204. function GetAbsoluteScale: TGLVector;
  205. procedure SetAbsoluteAffineScale(const Value: TAffineVector);
  206. procedure SetAbsoluteScale(const Value: TGLVector);
  207. function GetAbsoluteMatrix: TGLMatrix; inline;
  208. procedure SetAbsoluteMatrix(const Value: TGLMatrix);
  209. procedure SetBBChanges(const Value: TGLObjectBBChanges);
  210. function GetDirectAbsoluteMatrix: PGLMatrix;
  211. function GetLocalMatrix: PGLMatrix; inline;
  212. protected
  213. procedure Loaded; override;
  214. procedure SetScene(const Value: TGLScene); virtual;
  215. procedure DefineProperties(Filer: TFiler); override;
  216. procedure WriteBehaviours(stream: TStream);
  217. procedure ReadBehaviours(stream: TStream);
  218. procedure WriteEffects(stream: TStream);
  219. procedure ReadEffects(stream: TStream);
  220. procedure WriteRotations(stream: TStream);
  221. procedure ReadRotations(stream: TStream);
  222. function GetVisible: Boolean; virtual;
  223. function GetPickable: Boolean; virtual;
  224. procedure SetVisible(aValue: Boolean); virtual;
  225. procedure SetPickable(aValue: Boolean); virtual;
  226. procedure SetAbsolutePosition(const v: TGLVector);
  227. function GetAbsolutePosition: TGLVector; inline;
  228. procedure SetAbsoluteUp(const v: TGLVector);
  229. function GetAbsoluteUp: TGLVector;
  230. procedure SetAbsoluteDirection(const v: TGLVector);
  231. function GetAbsoluteDirection: TGLVector;
  232. function GetAbsoluteAffinePosition: TAffineVector;
  233. procedure SetAbsoluteAffinePosition(const Value: TAffineVector);
  234. procedure SetAbsoluteAffineUp(const v: TAffineVector);
  235. function GetAbsoluteAffineUp: TAffineVector;
  236. procedure SetAbsoluteAffineDirection(const v: TAffineVector);
  237. function GetAbsoluteAffineDirection: TAffineVector;
  238. procedure RecTransformationChanged; inline;
  239. procedure DrawAxes(var rci: TGLRenderContextInfo; pattern: Word);
  240. procedure GetChildren(AProc: TGetChildProc; Root: TComponent); override;
  241. // Should the object be considered as blended for sorting purposes?
  242. function Blended: Boolean; virtual;
  243. procedure RebuildMatrix;
  244. procedure SetName(const NewName: TComponentName); override;
  245. procedure SetParentComponent(Value: TComponent); override;
  246. procedure DestroyHandle; virtual;
  247. procedure DestroyHandles;
  248. procedure DeleteChildCameras;
  249. procedure DoOnAddedToParent; virtual;
  250. (* Used to re-calculate BoundingBoxes every time we need it.
  251. GetLocalUnscaleBB() must return the local BB, not the axis-aligned one.
  252. By default it is calculated from AxisAlignedBoundingBoxUnscaled and
  253. BarycenterAbsolutePosition, but for most objects there is a more
  254. efficient method, that's why it is virtual. *)
  255. procedure CalculateBoundingBoxPersonalUnscaled(var ANewBoundingBox:
  256. THmgBoundingBox); virtual;
  257. public
  258. constructor Create(AOwner: TComponent); override;
  259. constructor CreateAsChild(aParentOwner: TGLBaseSceneObject);
  260. destructor Destroy; override;
  261. procedure Assign(Source: TPersistent); override;
  262. (* Controls and adjusts internal optimizations based on object's style.
  263. Advanced user only. *)
  264. property ObjectStyle: TGLObjectStyles read FObjectStyle write FObjectStyle;
  265. (* Returns the handle to the object's build list.
  266. Use with caution! Some objects don't support buildlists! *)
  267. function GetHandle(var rci: TGLRenderContextInfo): Cardinal;
  268. function ListHandleAllocated: Boolean; inline;
  269. (* The local transformation (relative to parent).
  270. If you're *sure* the local matrix is up-to-date, you may use LocalMatrix
  271. for quicker access. *)
  272. procedure SetMatrix(const aValue: TGLMatrix); inline;
  273. property Matrix: PGLMatrix read GetMatrix;
  274. (* Holds the local transformation (relative to parent).
  275. If you're not *sure* the local matrix is up-to-date, use Matrix property. *)
  276. property LocalMatrix: PGLMatrix read GetLocalMatrix;
  277. (* Forces the local matrix to the specified value.
  278. AbsoluteMatrix, InverseMatrix, etc. will honour that change, but
  279. may become invalid if the specified matrix isn't orthonormal (can
  280. be used for specific rendering or projection effects).
  281. The local matrix will be reset by the next TransformationChanged,
  282. position or attitude change. *)
  283. procedure ForceLocalMatrix(const aMatrix: TGLMatrix); inline;
  284. // See AbsoluteMatrix.
  285. function AbsoluteMatrixAsAddress: PGLMatrix;
  286. (* Holds the absolute transformation matrix.
  287. If you're not *sure* the absolute matrix is up-to-date,
  288. use the AbsoluteMatrix property, this one may be nil... *)
  289. property DirectAbsoluteMatrix: PGLMatrix read GetDirectAbsoluteMatrix;
  290. (* Calculates the object's absolute inverse matrix.
  291. Multiplying an absolute coordinate with this matrix gives a local coordinate.
  292. The current implem uses transposition(AbsoluteMatrix), which is true
  293. unless you're using some scaling... *)
  294. function InvAbsoluteMatrix: TGLMatrix; inline;
  295. //See InvAbsoluteMatrix.
  296. function InvAbsoluteMatrixAsAddress: PGLMatrix;
  297. (* The object's absolute matrix by composing all local matrices.
  298. Multiplying a local coordinate with this matrix gives an absolute coordinate. *)
  299. property AbsoluteMatrix: TGLMatrix read GetAbsoluteMatrix write SetAbsoluteMatrix;
  300. // Direction vector in absolute coordinates.
  301. property AbsoluteDirection: TGLVector read GetAbsoluteDirection write SetAbsoluteDirection;
  302. property AbsoluteAffineDirection: TAffineVector read GetAbsoluteAffineDirection write SetAbsoluteAffineDirection;
  303. (* Scale vector in absolute coordinates.
  304. Warning: SetAbsoluteScale() does not work correctly at the moment. *)
  305. property AbsoluteScale: TGLVector read GetAbsoluteScale write SetAbsoluteScale;
  306. property AbsoluteAffineScale: TAffineVector read GetAbsoluteAffineScale write SetAbsoluteAffineScale;
  307. // Up vector in absolute coordinates.
  308. property AbsoluteUp: TGLVector read GetAbsoluteUp write SetAbsoluteUp;
  309. property AbsoluteAffineUp: TAffineVector read GetAbsoluteAffineUp write SetAbsoluteAffineUp;
  310. // Calculate the right vector in absolute coordinates.
  311. function AbsoluteRight: TGLVector;
  312. // Calculate the left vector in absolute coordinates.
  313. function AbsoluteLeft: TGLVector;
  314. // Computes and allows to set the object's absolute coordinates.
  315. property AbsolutePosition: TGLVector read GetAbsolutePosition write SetAbsolutePosition;
  316. property AbsoluteAffinePosition: TAffineVector read GetAbsoluteAffinePosition write SetAbsoluteAffinePosition;
  317. function AbsolutePositionAsAddress: PGLVector;
  318. // Returns the Absolute X Vector expressed in local coordinates.
  319. function AbsoluteXVector: TGLVector;
  320. // Returns the Absolute Y Vector expressed in local coordinates.
  321. function AbsoluteYVector: TGLVector;
  322. // Returns the Absolute Z Vector expressed in local coordinates.
  323. function AbsoluteZVector: TGLVector;
  324. // Converts a vector/point from absolute coordinates to local coordinates.
  325. function AbsoluteToLocal(const v: TGLVector): TGLVector; overload;
  326. // Converts a vector from absolute coordinates to local coordinates.
  327. function AbsoluteToLocal(const v: TAffineVector): TAffineVector; overload;
  328. // Converts a vector/point from local coordinates to absolute coordinates.
  329. function LocalToAbsolute(const v: TGLVector): TGLVector; overload;
  330. // Converts a vector from local coordinates to absolute coordinates.
  331. function LocalToAbsolute(const v: TAffineVector): TAffineVector; overload;
  332. // Returns the Right vector (based on Up and Direction)
  333. function Right: TGLVector; inline;
  334. // Returns the Left vector (based on Up and Direction)
  335. function LeftVector: TGLVector; inline;
  336. // Returns the Right vector (based on Up and Direction)
  337. function AffineRight: TAffineVector; inline;
  338. // Returns the Left vector (based on Up and Direction)
  339. function AffineLeftVector: TAffineVector; inline;
  340. (* Calculates the object's square distance to a point/object.
  341. pt is assumed to be in absolute coordinates,
  342. AbsolutePosition is considered as being the object position. *)
  343. function SqrDistanceTo(anObject: TGLBaseSceneObject): Single; overload;
  344. function SqrDistanceTo(const pt: TGLVector): Single; overload;
  345. function SqrDistanceTo(const pt: TAffineVector): Single; overload;
  346. (* Computes the object's distance to a point/object.
  347. Only objects AbsolutePositions are considered. *)
  348. function DistanceTo(anObject: TGLBaseSceneObject): Single; overload;
  349. function DistanceTo(const pt: TAffineVector): Single; overload;
  350. function DistanceTo(const pt: TGLVector): Single; overload;
  351. (* Calculates the object's barycenter in absolute coordinates.
  352. Default behaviour is to consider Barycenter=AbsolutePosition
  353. (whatever the number of children).
  354. SubClasses where AbsolutePosition is not the barycenter should
  355. override this method as it is used for distance calculation, during
  356. rendering for instance, and may lead to visual inconsistencies. *)
  357. function BarycenterAbsolutePosition: TGLVector; virtual;
  358. // Calculates the object's barycenter distance to a point.
  359. function BarycenterSqrDistanceTo(const pt: TGLVector): Single;
  360. (* Shall returns the object's axis aligned extensions.
  361. The dimensions are measured from object center and are expressed
  362. with scale accounted for, in the object's coordinates (not in absolute ones).
  363. Default value is half the object's Scale. *)
  364. function AxisAlignedDimensions: TGLVector; virtual;
  365. function AxisAlignedDimensionsUnscaled: TGLVector; virtual;
  366. (* Calculates and return the AABB for the object.
  367. The AABB is currently calculated from the BB.
  368. There is no caching scheme for them. *)
  369. function AxisAlignedBoundingBox(const AIncludeChilden: Boolean = True): TAABB;
  370. function AxisAlignedBoundingBoxUnscaled(const AIncludeChilden: Boolean = True): TAABB;
  371. function AxisAlignedBoundingBoxAbsolute(const AIncludeChilden: Boolean =
  372. True; const AUseBaryCenter: Boolean = False): TAABB;
  373. (* Advanced AABB functions that use a caching scheme.
  374. Also they include children and use BaryCenter. *)
  375. function AxisAlignedBoundingBoxEx: TAABB;
  376. function AxisAlignedBoundingBoxAbsoluteEx: TAABB;
  377. (* Calculates and return the Bounding Box for the object.
  378. The BB is calculated each time this method is invoked,
  379. based on the AxisAlignedDimensions of the object and that of its
  380. children. There is no caching scheme for them. *)
  381. function BoundingBox(const AIncludeChilden: Boolean = True; const
  382. AUseBaryCenter: Boolean = False): THmgBoundingBox;
  383. function BoundingBoxUnscaled(const AIncludeChilden: Boolean = True; const
  384. AUseBaryCenter: Boolean = False): THmgBoundingBox;
  385. function BoundingBoxAbsolute(const AIncludeChilden: Boolean = True; const
  386. AUseBaryCenter: Boolean = False): THmgBoundingBox;
  387. (* Advanced BB functions that use a caching scheme.
  388. Also they include children and use BaryCenter. *)
  389. function BoundingBoxPersonalUnscaledEx: THmgBoundingBox;
  390. function BoundingBoxOfChildrenEx: THmgBoundingBox;
  391. function BoundingBoxIncludingChildrenEx: THmgBoundingBox;
  392. // Max distance of corners of the BoundingBox.
  393. function BoundingSphereRadius: Single; inline;
  394. function BoundingSphereRadiusUnscaled: Single; inline;
  395. (* Indicates if a point is within an object.
  396. Given coordinate is an absolute coordinate.
  397. Linear or surfacic objects shall always return False.
  398. Default value is based on AxisAlignedDimension and a cube bounding. *)
  399. function PointInObject(const point: TGLVector): Boolean; virtual;
  400. (* Request to determine an intersection with a casted ray.
  401. Given coordinates & vector are in absolute coordinates, rayVector
  402. must be normalized.
  403. rayStart may be a point inside the object, allowing retrieval of
  404. the multiple intersects of the ray.
  405. When intersectXXX parameters are nil (default) implementation should
  406. take advantage of this to optimize calculus, if not, and an intersect
  407. is found, non nil parameters should be defined.
  408. The intersectNormal needs NOT be normalized by the implementations.
  409. Default value is based on bounding sphere. *)
  410. function RayCastIntersect(const rayStart, rayVector: TGLVector;
  411. intersectPoint: PGLVector = nil;
  412. intersectNormal: PGLVector = nil): Boolean; virtual;
  413. (* Request to generate silhouette outlines.
  414. Default implementation assumes the objects is a sphere of
  415. AxisAlignedDimensionUnscaled size. Subclasses may choose to return
  416. nil instead, which will be understood as an empty silhouette. *)
  417. function GenerateSilhouette(const silhouetteParameters:
  418. TGLSilhouetteParameters): TGLSilhouette; virtual;
  419. property Children[Index: Integer]: TGLBaseSceneObject read Get; default;
  420. property Count: Integer read GetCount;
  421. property Index: Integer read GetIndex write SetIndex;
  422. // Creates a new scene object and add it to this object as new child
  423. function AddNewChild(aChild: TGLSceneObjectClass): TGLBaseSceneObject; virtual;
  424. // Creates a new scene object and add it to this object as first child
  425. function AddNewChildFirst(aChild: TGLSceneObjectClass): TGLBaseSceneObject; virtual;
  426. procedure AddChild(aChild: TGLBaseSceneObject); virtual;
  427. function GetOrCreateBehaviour(aBehaviour: TGLBehaviourClass): TGLBehaviour;
  428. function AddNewBehaviour(aBehaviour: TGLBehaviourClass): TGLBehaviour;
  429. function GetOrCreateEffect(aEffect: TGLEffectClass): TGLEffect;
  430. function AddNewEffect(aEffect: TGLEffectClass): TGLEffect;
  431. function HasSubChildren: Boolean;
  432. procedure DeleteChildren; virtual;
  433. procedure Insert(aIndex: Integer; aChild: TGLBaseSceneObject); virtual;
  434. (* Takes a scene object out of the child list, but doesn't destroy it.
  435. If 'KeepChildren' is true its children will be kept as new children
  436. in this scene object. *)
  437. procedure Remove(aChild: TGLBaseSceneObject; keepChildren: Boolean); virtual;
  438. function IndexOfChild(aChild: TGLBaseSceneObject): Integer;
  439. function FindChild(const aName: string; ownChildrenOnly: Boolean): TGLBaseSceneObject;
  440. (* The "safe" version of this procedure checks if indexes are inside
  441. the list. If not, no exception if raised. *)
  442. procedure ExchangeChildrenSafe(anIndex1, anIndex2: Integer);
  443. (* The "regular" version of this procedure does not perform any checks
  444. and calls FChildren.Exchange directly. User should/can perform range checks manualy. *)
  445. procedure ExchangeChildren(anIndex1, anIndex2: Integer);
  446. //These procedures are safe.
  447. procedure MoveChildUp(anIndex: Integer);
  448. procedure MoveChildDown(anIndex: Integer);
  449. procedure MoveChildFirst(anIndex: Integer);
  450. procedure MoveChildLast(anIndex: Integer);
  451. procedure DoProgress(const progressTime: TGLProgressTimes); override;
  452. procedure MoveTo(newParent: TGLBaseSceneObject); virtual;
  453. procedure MoveUp;
  454. procedure MoveDown;
  455. procedure MoveFirst;
  456. procedure MoveLast;
  457. procedure BeginUpdate; inline;
  458. procedure EndUpdate; inline;
  459. (* Make object-specific geometry description here.
  460. Subclasses should MAINTAIN OpenGL states (restore the states if
  461. they were altered). *)
  462. procedure BuildList(var rci: TGLRenderContextInfo); virtual;
  463. function GetParentComponent: TComponent; override;
  464. function HasParent: Boolean; override; final;
  465. function IsUpdating: Boolean; inline;
  466. // Moves the object along the Up vector (move up/down)
  467. procedure Lift(ADistance: Single);
  468. // Moves the object along the direction vector
  469. procedure Move(ADistance: Single);
  470. // Translates the object
  471. procedure Translate(tx, ty, tz: Single);
  472. procedure MoveObjectAround(anObject: TGLBaseSceneObject; pitchDelta, turnDelta: Single);
  473. procedure MoveObjectAllAround(anObject: TGLBaseSceneObject; pitchDelta, turnDelta: Single);
  474. procedure Pitch(angle: Single);
  475. procedure Roll(angle: Single);
  476. procedure Turn(angle: Single);
  477. (* Sets all rotations to zero and restores default Direction/Up.
  478. Using this function then applying roll/pitch/turn in the order that
  479. suits you, you can give an "absolute" meaning to rotation angles
  480. (they are still applied locally though).
  481. Scale and Position are not affected. *)
  482. procedure ResetRotations;
  483. //Reset rotations and applies them back in the specified order.
  484. procedure ResetAndPitchTurnRoll(const degX, degY, degZ: Single);
  485. //Applies rotations around absolute X, Y and Z axis.
  486. procedure RotateAbsolute(const rx, ry, rz: Single); overload;
  487. //Applies rotations around the absolute given vector (angle in degrees).
  488. procedure RotateAbsolute(const axis: TAffineVector; angle: Single); overload;
  489. // Moves camera along the right vector (move left and right)
  490. procedure Slide(ADistance: Single);
  491. // Orients the object toward a target object
  492. procedure PointTo(const ATargetObject: TGLBaseSceneObject; const AUpVector: TGLVector); overload;
  493. // Orients the object toward a target absolute position
  494. procedure PointTo(const AAbsolutePosition, AUpVector: TGLVector); overload;
  495. procedure Render(var ARci: TGLRenderContextInfo);
  496. procedure DoRender(var ARci: TGLRenderContextInfo;
  497. ARenderSelf, ARenderChildren: Boolean); virtual;
  498. procedure RenderChildren(firstChildIndex, lastChildIndex: Integer;
  499. var rci: TGLRenderContextInfo);
  500. procedure StructureChanged; virtual;
  501. procedure ClearStructureChanged; inline;
  502. // Recalculate an orthonormal system
  503. procedure CoordinateChanged(Sender: TGLCustomCoordinates); override;
  504. procedure TransformationChanged; inline;
  505. procedure NotifyChange(Sender: TObject); override;
  506. property Rotation: TGLCoordinates read FRotation write SetRotation;
  507. property PitchAngle: Single read GetPitchAngle write SetPitchAngle;
  508. property RollAngle: Single read GetRollAngle write SetRollAngle;
  509. property TurnAngle: Single read GetTurnAngle write SetTurnAngle;
  510. property ShowAxes: Boolean read FShowAxes write SetShowAxes default False;
  511. property Changes: TGLObjectChanges read FChanges;
  512. property BBChanges: TGLObjectBBChanges read fBBChanges write SetBBChanges;
  513. property Parent: TGLBaseSceneObject read FParent write SetParent;
  514. property Position: TGLCoordinates read FPosition write SetPosition;
  515. property Direction: TGLCoordinates read FDirection write SetDirection;
  516. property Up: TGLCoordinates read FUp write SetUp;
  517. property Scale: TGLCoordinates read FScaling write SetScaling;
  518. property Scene: TGLScene read FScene; // Scene
  519. property Visible: Boolean read FVisible write SetVisible default True;
  520. property Pickable: Boolean read FPickable write SetPickable default True;
  521. property ObjectsSorting: TGLObjectsSorting read FObjectsSorting write
  522. SetObjectsSorting default osInherited;
  523. property VisibilityCulling: TGLVisibilityCulling read FVisibilityCulling
  524. write SetVisibilityCulling default vcInherited;
  525. property OnProgress: TGLProgressEvent read FOnProgress write FOnProgress;
  526. property OnPicked: TNotifyEvent read FOnPicked write FOnPicked;
  527. property OnAddedToParent: TNotifyEvent read FOnAddedToParent write FOnAddedToParent;
  528. property Behaviours: TGLBehaviours read GetBehaviours write SetBehaviours stored False;
  529. property Effects: TGLEffects read GetEffects write SetEffects stored False;
  530. property TagObject: TObject read FTagObject write FTagObject;
  531. published
  532. property TagFloat: Single read FTagFloat write FTagFloat;
  533. end;
  534. (* Base class for implementing behaviours in TGLScene.
  535. Behaviours are regrouped in a collection attached to a TGLBaseSceneObject,
  536. and are part of the "Progress" chain of events. Behaviours allows clean
  537. application of time-based alterations to objects (movements, shape or
  538. texture changes...).
  539. Since behaviours are implemented as classes, there are basicly two kinds
  540. of strategies for subclasses :
  541. stand-alone : the subclass does it all, and holds all necessary data
  542. (covers animation, inertia etc.)
  543. proxy : the subclass is an interface to and external, shared operator
  544. (like gravity, force-field effects etc.)
  545. Some behaviours may be cooperative (like force-fields affects inertia)
  546. or unique (e.g. only one inertia behaviour per object).
  547. NOTES : Don't forget to override the ReadFromFiler/WriteToFiler persistence
  548. methods if you add data in a subclass !
  549. Subclasses must be registered using the RegisterXCollectionItemClass function *)
  550. TGLBaseBehaviour = class(TXCollectionItem)
  551. protected
  552. procedure SetName(const val: string); override;
  553. // Override this function to write subclass data.
  554. procedure WriteToFiler(writer: TWriter); override;
  555. // Override this function to read subclass data.
  556. procedure ReadFromFiler(reader: TReader); override;
  557. (* Returns the TGLBaseSceneObject on which the behaviour should be applied.
  558. Does NOT check for nil owners. *)
  559. function OwnerBaseSceneObject: TGLBaseSceneObject;
  560. public
  561. constructor Create(aOwner: TXCollection); override;
  562. destructor Destroy; override;
  563. procedure DoProgress(const progressTime: TGLProgressTimes); virtual;
  564. end;
  565. (* Ancestor for non-rendering behaviours.
  566. This class shall never receive any properties, it's just here to differentiate
  567. rendereing and non-rendering behaviours. Rendereing behaviours are named
  568. "TGLEffect", non-rendering effects (like inertia) are simply named
  569. "TGLBehaviour". *)
  570. TGLBehaviour = class(TGLBaseBehaviour)
  571. end;
  572. (* Holds a list of TGLBehaviour objects.
  573. This object expects itself to be owned by a TGLBaseSceneObject.
  574. As a TXCollection (and contrary to a TCollection), this list can contain
  575. objects of varying class, the only constraint being that they should all
  576. be TGLBehaviour subclasses. *)
  577. TGLBehaviours = class(TXCollection)
  578. protected
  579. function GetBehaviour(index: Integer): TGLBehaviour;
  580. public
  581. constructor Create(aOwner: TPersistent); override;
  582. function GetNamePath: string; override;
  583. class function ItemsClass: TXCollectionItemClass; override;
  584. property Behaviour[index: Integer]: TGLBehaviour read GetBehaviour; default;
  585. function CanAdd(aClass: TXCollectionItemClass): Boolean; override;
  586. procedure DoProgress(const progressTimes: TGLProgressTimes); inline;
  587. end;
  588. (* A rendering effect that can be applied to SceneObjects.
  589. ObjectEffect is a subclass of behaviour that gets a chance to Render
  590. an object-related special effect.
  591. TGLEffect should not be used as base class for custom effects,
  592. instead you should use the following base classes :
  593. TGLObjectPreEffect is rendered before owner object render
  594. TGLObjectPostEffect is rendered after the owner object render
  595. TGLObjectAfterEffect is rendered at the end of the scene rendering
  596. NOTES :
  597. Don't forget to override the ReadFromFiler/WriteToFiler persistence
  598. methods if you add data in a subclass !
  599. Subclasses must be registered using the RegisterXCollectionItemClass function *)
  600. TGLEffect = class(TGLBaseBehaviour)
  601. protected
  602. // Override this function to write subclass data.
  603. procedure WriteToFiler(writer: TWriter); override;
  604. // Override this function to read subclass data.
  605. procedure ReadFromFiler(reader: TReader); override;
  606. public
  607. procedure Render(var rci: TGLRenderContextInfo); virtual;
  608. end;
  609. (* An object effect that gets rendered before owner object's render.
  610. The current OpenGL matrices and material are that of the owner object. *)
  611. TGLObjectPreEffect = class(TGLEffect)
  612. end;
  613. (*An object effect that gets rendered after owner object's render.
  614. The current OpenGL matrices and material are that of the owner object. *)
  615. TGLObjectPostEffect = class(TGLEffect)
  616. end;
  617. (*An object effect that gets rendered at scene's end.
  618. No particular OpenGL matrices or material should be assumed. *)
  619. TGLObjectAfterEffect = class(TGLEffect)
  620. end;
  621. (*Holds a list of object effects.
  622. This object expects itself to be owned by a TGLBaseSceneObject. *)
  623. TGLEffects = class(TXCollection)
  624. protected
  625. function GetEffect(index: Integer): TGLEffect;
  626. public
  627. constructor Create(aOwner: TPersistent); override;
  628. function GetNamePath: string; override;
  629. class function ItemsClass: TXCollectionItemClass; override;
  630. property ObjectEffect[index: Integer]: TGLEffect read GetEffect; default;
  631. function CanAdd(aClass: TXCollectionItemClass): Boolean; override;
  632. procedure DoProgress(const progressTime: TGLProgressTimes);
  633. procedure RenderPreEffects(var rci: TGLRenderContextInfo); inline;
  634. //Also take care of registering after effects with the GLSceneViewer.
  635. procedure RenderPostEffects(var rci: TGLRenderContextInfo); inline;
  636. end;
  637. (*Extended base scene object class with a material property.
  638. The material allows defining a color and texture for the object, see TGLMaterial *)
  639. TGLCustomSceneObject = class(TGLBaseSceneObject)
  640. private
  641. FMaterial: TGLMaterial;
  642. FHint: string;
  643. protected
  644. function Blended: Boolean; override;
  645. procedure SetGLMaterial(AValue: TGLMaterial); inline;
  646. procedure DestroyHandle; override;
  647. procedure Loaded; override;
  648. public
  649. constructor Create(AOwner: TComponent); override;
  650. destructor Destroy; override;
  651. procedure Assign(Source: TPersistent); override;
  652. procedure DoRender(var ARci: TGLRenderContextInfo;
  653. ARenderSelf, ARenderChildren: Boolean); override;
  654. property Material: TGLMaterial read FMaterial write SetGLMaterial;
  655. property Hint: string read FHint write FHint;
  656. end;
  657. (* This class shall be used only as a hierarchy root.
  658. It exists only as a container and shall never be rotated/scaled etc. as
  659. the class type is used in parenting optimizations.
  660. Shall never implement or add any functionality, the "Create" override
  661. only take cares of disabling the build list. *)
  662. TGLSceneRootObject = class(TGLBaseSceneObject)
  663. public
  664. constructor Create(AOwner: TComponent); override;
  665. end;
  666. (*Base class for objects that do not have a published "material".
  667. Note that the material is available in public properties, but isn't
  668. applied automatically before invoking BuildList.
  669. Subclassing should be reserved to structural objects and objects that
  670. have no material of their own. *)
  671. TGLImmaterialSceneObject = class(TGLCustomSceneObject)
  672. public
  673. procedure DoRender(var ARci: TGLRenderContextInfo;
  674. ARenderSelf, ARenderChildren: Boolean); override;
  675. published
  676. property ObjectsSorting;
  677. property VisibilityCulling;
  678. property Direction;
  679. property PitchAngle;
  680. property Position;
  681. property RollAngle;
  682. property Scale;
  683. property ShowAxes;
  684. property TurnAngle;
  685. property Up;
  686. property Visible;
  687. property Pickable;
  688. property OnProgress;
  689. property OnPicked;
  690. property Behaviours;
  691. property Effects;
  692. property Hint;
  693. end;
  694. (* Base class for camera invariant objects.
  695. Camera invariant objects bypass camera settings, such as camera
  696. position (object is always centered on camera) or camera orientation
  697. (object always has same orientation as camera). *)
  698. TGLCameraInvariantObject = class(TGLImmaterialSceneObject)
  699. private
  700. FCamInvarianceMode: TGLCameraInvarianceMode;
  701. protected
  702. procedure SetCamInvarianceMode(const val: TGLCameraInvarianceMode);
  703. property CamInvarianceMode: TGLCameraInvarianceMode read FCamInvarianceMode
  704. write SetCamInvarianceMode;
  705. public
  706. constructor Create(AOwner: TComponent); override;
  707. procedure Assign(Source: TPersistent); override;
  708. procedure DoRender(var ARci: TGLRenderContextInfo;
  709. ARenderSelf, ARenderChildren: Boolean); override;
  710. end;
  711. // Base class for standard scene objects. Publishes the Material property.
  712. TGLSceneObject = class(TGLCustomSceneObject)
  713. published
  714. property Material;
  715. property ObjectsSorting;
  716. property VisibilityCulling;
  717. property Direction;
  718. property PitchAngle;
  719. property Position;
  720. property RollAngle;
  721. property Scale;
  722. property ShowAxes;
  723. property TurnAngle;
  724. property Up;
  725. property Visible;
  726. property Pickable;
  727. property OnProgress;
  728. property OnPicked;
  729. property Behaviours;
  730. property Effects;
  731. property Hint;
  732. end;
  733. // Event for user-specific rendering in a TGLDirectOpenGL object.
  734. TGLDirectRenderEvent = procedure(Sender: TObject; var rci: TGLRenderContextInfo) of object;
  735. (* Provides a way to issue direct OpenGL calls during the rendering.
  736. You can use this object to do your specific rendering task in its OnRender
  737. event. The OpenGL calls shall restore the OpenGL states they found when
  738. entering, or exclusively use the GLMisc utility functions to alter the states. *)
  739. TGLDirectOpenGL = class(TGLImmaterialSceneObject)
  740. private
  741. FUseBuildList: Boolean;
  742. FOnRender: TGLDirectRenderEvent;
  743. FBlend: Boolean;
  744. protected
  745. procedure SetUseBuildList(const val: Boolean);
  746. function Blended: Boolean; override;
  747. procedure SetBlend(const val: Boolean);
  748. public
  749. constructor Create(AOwner: TComponent); override;
  750. procedure Assign(Source: TPersistent); override;
  751. procedure BuildList(var rci: TGLRenderContextInfo); override;
  752. function AxisAlignedDimensionsUnscaled: TGLVector; override;
  753. published
  754. (* Specifies if a build list be made.
  755. If True, GLScene will generate a build list (side cache),
  756. ie. OnRender will only be invoked once for the first render, or after
  757. a StructureChanged call. This is suitable for "static" geometry and
  758. will usually speed up rendering of things that don't change.
  759. If false, OnRender will be invoked for each render. This is suitable
  760. for dynamic geometry (things that change often or constantly). *)
  761. property UseBuildList: Boolean read FUseBuildList write SetUseBuildList;
  762. (* Place your specific OpenGL code here.
  763. The OpenGL calls shall restore the OpenGL states they found when
  764. entering, or exclusively use the GLMisc utility functions to alter
  765. the states. *)
  766. property OnRender: TGLDirectRenderEvent read FOnRender write FOnRender;
  767. (* Defines if the object uses blending.
  768. This property will allow direct opengl objects to be flagged as
  769. blended for object sorting purposes. *)
  770. property Blend: Boolean read FBlend write SetBlend;
  771. end;
  772. (* Scene object that allows other objects to issue rendering at some point.
  773. This object is used to specify a render point for which other components
  774. have (rendering) tasks to perform. It doesn't render anything itself
  775. and is invisible, but other components can register and be notified
  776. when the point is reached in the rendering phase.
  777. Callbacks must be explicitly unregistered. *)
  778. TGLRenderPoint = class(TGLImmaterialSceneObject)
  779. private
  780. FCallBacks: array of TGLDirectRenderEvent;
  781. FFreeCallBacks: array of TNotifyEvent;
  782. public
  783. constructor Create(AOwner: TComponent); override;
  784. destructor Destroy; override;
  785. procedure BuildList(var rci: TGLRenderContextInfo); override;
  786. procedure RegisterCallBack(renderEvent: TGLDirectRenderEvent;
  787. renderPointFreed: TNotifyEvent);
  788. procedure UnRegisterCallBack(renderEvent: TGLDirectRenderEvent);
  789. procedure Clear;
  790. end;
  791. (* A full proxy object.
  792. This object literally uses another object's Render method to do its own
  793. rendering, however, it has a coordinate system and a life of its own.
  794. Use it for duplicates of an object. *)
  795. TGLProxyObject = class(TGLBaseSceneObject)
  796. private
  797. FMasterObject: TGLBaseSceneObject;
  798. FProxyOptions: TGLProxyObjectOptions;
  799. protected
  800. FRendering: Boolean;
  801. procedure Notification(AComponent: TComponent; Operation: TOperation);
  802. override;
  803. procedure SetMasterObject(const val: TGLBaseSceneObject); virtual;
  804. procedure SetProxyOptions(const val: TGLProxyObjectOptions);
  805. public
  806. constructor Create(AOwner: TComponent); override;
  807. destructor Destroy; override;
  808. procedure Assign(Source: TPersistent); override;
  809. procedure DoRender(var ARci: TGLRenderContextInfo;
  810. ARenderSelf, ARenderChildren: Boolean); override;
  811. function BarycenterAbsolutePosition: TGLVector; override;
  812. function AxisAlignedDimensions: TGLVector; override;
  813. function AxisAlignedDimensionsUnscaled: TGLVector; override;
  814. function RayCastIntersect(const rayStart, rayVector: TGLVector;
  815. intersectPoint: PGLVector = nil;
  816. intersectNormal: PGLVector = nil): Boolean; override;
  817. function GenerateSilhouette(const silhouetteParameters:
  818. TGLSilhouetteParameters): TGLSilhouette; override;
  819. published
  820. // Specifies the Master object which will be proxy'ed.
  821. property MasterObject: TGLBaseSceneObject read FMasterObject write
  822. SetMasterObject;
  823. // Specifies how and what is proxy'ed.
  824. property ProxyOptions: TGLProxyObjectOptions read FProxyOptions write
  825. SetProxyOptions default cDefaultProxyOptions;
  826. property ObjectsSorting;
  827. property Direction;
  828. property PitchAngle;
  829. property Position;
  830. property RollAngle;
  831. property Scale;
  832. property ShowAxes;
  833. property TurnAngle;
  834. property Up;
  835. property Visible;
  836. property Pickable;
  837. property OnProgress;
  838. property OnPicked;
  839. property Behaviours;
  840. end;
  841. TGLProxyObjectClass = class of TGLProxyObject;
  842. (* Defines the various styles for lightsources.
  843. lsSpot : a spot light, oriented and with a cutoff zone (note that if
  844. cutoff is 180, the spot is rendered as an omni source)
  845. lsOmni : an omnidirectionnal source, punctual and sending light in
  846. all directions uniformously
  847. lsParallel : a parallel light, oriented as the light source is (this
  848. type of light can help speed up rendering) *)
  849. TGLLightStyle = (lsSpot, lsOmni, lsParallel, lsParallelSpot);
  850. (* Standard light source.
  851. The standard GLScene light source covers spotlights, omnidirectionnal and
  852. parallel sources (see TLightStyle).
  853. Lights are colored, have distance attenuation parameters and are turned
  854. on/off through their Shining property.
  855. Lightsources are managed in a specific object by the TGLScene for rendering
  856. purposes. The maximum number of light source in a scene is limited by the
  857. OpenGL implementation (8 lights are supported under most ICDs), though the
  858. more light you use, the slower rendering may get. If you want to render
  859. many more light/lightsource, you may have to resort to other techniques
  860. like lightmapping. *)
  861. TGLLightSource = class(TGLBaseSceneObject)
  862. private
  863. FLightID: Cardinal;
  864. FSpotDirection: TGLCoordinates;
  865. FSpotExponent, FSpotCutOff: Single;
  866. FConstAttenuation, FLinearAttenuation, FQuadraticAttenuation: Single;
  867. FShining: Boolean;
  868. FAmbient, FDiffuse, FSpecular: TGLColor;
  869. FLightStyle: TGLLightStyle;
  870. protected
  871. procedure SetAmbient(AValue: TGLColor);
  872. procedure SetDiffuse(AValue: TGLColor);
  873. procedure SetSpecular(AValue: TGLColor);
  874. procedure SetConstAttenuation(AValue: Single);
  875. procedure SetLinearAttenuation(AValue: Single);
  876. procedure SetQuadraticAttenuation(AValue: Single);
  877. procedure SetShining(AValue: Boolean);
  878. procedure SetSpotDirection(AVector: TGLCoordinates);
  879. procedure SetSpotExponent(AValue: Single);
  880. procedure SetSpotCutOff(const val: Single);
  881. procedure SetLightStyle(const val: TGLLightStyle);
  882. public
  883. constructor Create(AOwner: TComponent); override;
  884. destructor Destroy; override;
  885. procedure DoRender(var ARci: TGLRenderContextInfo;
  886. ARenderSelf, ARenderChildren: Boolean); override;
  887. // light sources have different handle types than normal scene objects
  888. function RayCastIntersect(const rayStart, rayVector: TGLVector;
  889. intersectPoint: PGLVector = nil;
  890. intersectNormal: PGLVector = nil): Boolean; override;
  891. procedure CoordinateChanged(Sender: TGLCustomCoordinates); override;
  892. function GenerateSilhouette(const silhouetteParameters:
  893. TGLSilhouetteParameters): TGLSilhouette; override;
  894. property LightID: Cardinal read FLightID;
  895. function Attenuated: Boolean;
  896. published
  897. property Ambient: TGLColor read FAmbient write SetAmbient;
  898. property ConstAttenuation: Single read FConstAttenuation write
  899. SetConstAttenuation;
  900. property Diffuse: TGLColor read FDiffuse write SetDiffuse;
  901. property LinearAttenuation: Single read FLinearAttenuation write
  902. SetLinearAttenuation;
  903. property QuadraticAttenuation: Single read FQuadraticAttenuation write
  904. SetQuadraticAttenuation;
  905. property Position;
  906. property LightStyle: TGLLightStyle read FLightStyle write SetLightStyle default lsSpot;
  907. property Shining: Boolean read FShining write SetShining default True;
  908. property Specular: TGLColor read FSpecular write SetSpecular;
  909. property SpotCutOff: Single read FSpotCutOff write SetSpotCutOff;
  910. property SpotDirection: TGLCoordinates read FSpotDirection write
  911. SetSpotDirection;
  912. property SpotExponent: Single read FSpotExponent write SetSpotExponent;
  913. property OnProgress;
  914. end;
  915. TGLCameraStyle = (csPerspective, csOrthogonal, csOrtho2D, csCustom,
  916. csInfinitePerspective, csPerspectiveKeepFOV);
  917. TGLCameraKeepFOVMode = (ckmHorizontalFOV, ckmVerticalFOV);
  918. TOnCustomPerspective = procedure(const viewport: TRectangle;
  919. width, height: Integer; DPI: Integer;
  920. var viewPortRadius: Single) of object;
  921. (* Camera object.
  922. This object is commonly referred by TGLSceneViewer and defines a position,
  923. direction, focal length, depth of view... all the properties needed for
  924. defining a point of view and optical characteristics. *)
  925. TGLCamera = class(TGLBaseSceneObject)
  926. private
  927. FFocalLength: Single;
  928. FDepthOfView: Single;
  929. FNearPlane: Single; // nearest distance to the camera
  930. FNearPlaneBias: Single; // scaling bias applied to near plane
  931. FViewPortRadius: Single; // viewport bounding radius per distance unit
  932. FTargetObject: TGLBaseSceneObject;
  933. FLastDirection: TGLVector; // Not persistent
  934. FCameraStyle: TGLCameraStyle;
  935. FKeepFOVMode: TGLCameraKeepFOVMode;
  936. FSceneScale: Single;
  937. FDeferredApply: TNotifyEvent;
  938. FOnCustomPerspective: TOnCustomPerspective;
  939. FDesign: Boolean;
  940. FFOVY, FFOVX: Double;
  941. protected
  942. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  943. procedure SetTargetObject(const val: TGLBaseSceneObject);
  944. procedure SetDepthOfView(AValue: Single);
  945. procedure SetFocalLength(AValue: Single);
  946. procedure SetCameraStyle(const val: TGLCameraStyle);
  947. procedure SetKeepFOVMode(const val: TGLCameraKeepFOVMode);
  948. procedure SetSceneScale(value: Single);
  949. function StoreSceneScale: Boolean;
  950. procedure SetNearPlaneBias(value: Single);
  951. function StoreNearPlaneBias: Boolean;
  952. public
  953. constructor Create(aOwner: TComponent); override;
  954. destructor Destroy; override;
  955. procedure Assign(Source: TPersistent); override;
  956. (* Nearest clipping plane for the frustum.
  957. This value depends on the FocalLength and DepthOfView fields and
  958. is calculated to minimize Z-Buffer crawling as suggested by the OpenGL documentation. *)
  959. property NearPlane: Single read FNearPlane;
  960. // Apply camera transformation
  961. procedure Apply;
  962. procedure DoRender(var ARci: TGLRenderContextInfo;
  963. ARenderSelf, ARenderChildren: Boolean); override;
  964. function RayCastIntersect(const rayStart, rayVector: TGLVector;
  965. intersectPoint: PGLVector = nil;
  966. intersectNormal: PGLVector = nil): Boolean; override;
  967. procedure ApplyPerspective(const AViewport: TRectangle;
  968. AWidth, AHeight: Integer; ADPI: Integer);
  969. procedure AutoLeveling(Factor: Single);
  970. procedure Reset(aSceneBuffer: TGLSceneBuffer);
  971. // Position the camera so that the whole scene can be seen
  972. procedure ZoomAll(aSceneBuffer: TGLSceneBuffer);
  973. procedure RotateObject(obj: TGLBaseSceneObject; pitchDelta, turnDelta: Single; rollDelta: Single = 0);
  974. procedure RotateTarget(pitchDelta, turnDelta: Single; rollDelta: Single = 0);
  975. (* Change camera's position to make it move around its target.
  976. If TargetObject is nil, nothing happens. This method helps in quickly
  977. implementing camera controls. Camera's Up and Direction properties are unchanged.
  978. Angle deltas are in degrees, camera parent's coordinates should be identity.
  979. Tip : make the camera a child of a "target" dummycube and make
  980. it a target the dummycube. Now, to pan across the scene, just move
  981. the dummycube, to change viewing angle, use this method. *)
  982. procedure MoveAroundTarget(pitchDelta, turnDelta: Single);
  983. (* Change camera's position to make it move all around its target.
  984. If TargetObject is nil, nothing happens. This method helps in quickly
  985. implementing camera controls. Camera's Up and Direction properties are changed.
  986. Angle deltas are in degrees. *)
  987. procedure MoveAllAroundTarget(pitchDelta, turnDelta :Single);
  988. // Moves the camera in eye space coordinates.
  989. procedure MoveInEyeSpace(forwardDistance, rightDistance, upDistance: Single);
  990. // Moves the target in eye space coordinates.
  991. procedure MoveTargetInEyeSpace(forwardDistance, rightDistance, upDistance: Single);
  992. // Computes the absolute vector corresponding to the eye-space translations.
  993. function AbsoluteEyeSpaceVector(forwardDistance, rightDistance, upDistance:
  994. Single): TGLVector;
  995. (* Adjusts distance from camera to target by applying a ratio.
  996. If TargetObject is nil, nothing happens. This method helps in quickly
  997. implementing camera controls. Only the camera's position is changed. *)
  998. procedure AdjustDistanceToTarget(distanceRatio: Single);
  999. (* Returns the distance from camera to target.
  1000. If TargetObject is nil, returns 1. *)
  1001. function DistanceToTarget: Single;
  1002. (* Computes the absolute normalized vector to the camera target.
  1003. If no target is defined, AbsoluteDirection is returned. *)
  1004. function AbsoluteVectorToTarget: TGLVector;
  1005. (* Computes the absolute normalized right vector to the camera target.
  1006. If no target is defined, AbsoluteRight is returned. *)
  1007. function AbsoluteRightVectorToTarget: TGLVector;
  1008. (* Computes the absolute normalized up vector to the camera target.
  1009. If no target is defined, AbsoluteUpt is returned. *)
  1010. function AbsoluteUpVectorToTarget: TGLVector;
  1011. (* Calculate an absolute translation vector from a screen vector.
  1012. Ratio is applied to both screen delta, planeNormal should be the
  1013. translation plane's normal. *)
  1014. function ScreenDeltaToVector(deltaX, deltaY: Integer; ratio: Single;
  1015. const planeNormal: TGLVector): TGLVector;
  1016. // Same as ScreenDeltaToVector but optimized for XY plane.
  1017. function ScreenDeltaToVectorXY(deltaX, deltaY: Integer; ratio: Single): TGLVector;
  1018. // Same as ScreenDeltaToVector but optimized for XZ plane.
  1019. function ScreenDeltaToVectorXZ(deltaX, deltaY: Integer; ratio: Single): TGLVector;
  1020. // Same as ScreenDeltaToVector but optimized for YZ plane.
  1021. function ScreenDeltaToVectorYZ(deltaX, deltaY: Integer; ratio: Single): TGLVector;
  1022. // Returns true if a point is in front of the camera.
  1023. function PointInFront(const point: TGLVector): boolean; overload;
  1024. (* Calculates the field of view in degrees, given a viewport dimension
  1025. (width or height). F.i. you may wish to use the minimum of the two. *)
  1026. function GetFieldOfView(const AViewportDimension: single): single;
  1027. (* Sets the FocalLength in degrees, given a field of view and a viewport
  1028. dimension (width or height). *)
  1029. procedure SetFieldOfView(const AFieldOfView, AViewportDimension: single);
  1030. published
  1031. (* Depth of field/view.
  1032. Adjusts the maximum distance, beyond which objects will be clipped
  1033. (ie. not visisble).
  1034. You must adjust this value if you are experiencing disappearing
  1035. objects (increase the value) of Z-Buffer crawling (decrease the
  1036. value). Z-Buffer crawling happens when depth of view is too large
  1037. and the Z-Buffer precision cannot account for all that depth
  1038. accurately : objects farther overlap closer objects and vice-versa.
  1039. Note that this value is ignored in cSOrtho2D mode. *)
  1040. property DepthOfView: Single read FDepthOfView write SetDepthOfView;
  1041. (* Focal Length of the camera.
  1042. Adjusting this value allows for lens zooming effects (use SceneScale
  1043. for linear zooming). This property affects near/far planes clipping. *)
  1044. property FocalLength: Single read FFocalLength write SetFocalLength;
  1045. {Scene scaling for camera point.
  1046. This is a linear 2D scaling of the camera's output, allows for
  1047. linear zooming (use FocalLength for lens zooming). }
  1048. property SceneScale: Single read FSceneScale write SetSceneScale stored StoreSceneScale;
  1049. (* Scaling bias applied to near-plane calculation.
  1050. Values inferior to one will move the nearplane nearer, and also
  1051. reduce medium/long range Z-Buffer precision, values superior
  1052. to one will move the nearplane farther, and also improve medium/long
  1053. range Z-Buffer precision. *)
  1054. property NearPlaneBias: Single read FNearPlaneBias write SetNearPlaneBias stored StoreNearPlaneBias;
  1055. (* If set, camera will point to this object.
  1056. When camera is pointing an object, the Direction vector is ignored
  1057. and the Up vector is used as an absolute vector to the up. *)
  1058. property TargetObject: TGLBaseSceneObject read FTargetObject write SetTargetObject;
  1059. (* Adjust the camera style.
  1060. Three styles are available :
  1061. csPerspective, the default value for perspective projection
  1062. csOrthogonal, for orthogonal (or isometric) projection.
  1063. csOrtho2D, setups orthogonal 2D projection in which 1 unit
  1064. (in x or y) represents 1 pixel.
  1065. csInfinitePerspective, for perspective view without depth limit.
  1066. csKeepCamAnglePerspective, for perspective view with keeping aspect on view resize.
  1067. csCustom, setup is deferred to the OnCustomPerspective event. *)
  1068. property CameraStyle: TGLCameraStyle read FCameraStyle write SetCameraStyle default csPerspective;
  1069. (* Keep camera angle mode.
  1070. When CameraStyle is csKeepCamAnglePerspective, select which camera angle you want to keep.
  1071. kaHeight, for Keep Height oriented camera angle
  1072. kaWidth, for Keep Width oriented camera angle *)
  1073. property KeepFOVMode: TGLCameraKeepFOVMode read FKeepFOVMode write SetKeepFOVMode default ckmHorizontalFOV;
  1074. (* Custom perspective event.
  1075. This event allows you to specify your custom perpective, either
  1076. with a glFrustrum, a glOrtho or whatever method suits you.
  1077. You must compute viewPortRadius for culling to work.
  1078. This event is only called if CameraStyle is csCustom. *)
  1079. property OnCustomPerspective: TOnCustomPerspective read FOnCustomPerspective write FOnCustomPerspective;
  1080. property Position;
  1081. property Direction;
  1082. property Up;
  1083. property OnProgress;
  1084. end;
  1085. (* Scene component class.
  1086. The scene contains the scene description (lights, geometry...), which is
  1087. basicly a hierarchical scene graph made of TGLBaseSceneObject. It will
  1088. usually contain one or more TGLCamera object, which can be referred by
  1089. a Viewer component for rendering purposes.
  1090. The scene's objects can be accessed directly from code (as regular
  1091. components), but those are edited with a specific editor (double-click
  1092. on the TGLScene component at design-time to invoke it). To add objects
  1093. at runtime, use the AddNewChild method of TGLBaseSceneObject. *)
  1094. TGLScene = class(TGLUpdateAbleComponent)
  1095. private
  1096. FUpdateCount: Integer;
  1097. FObjects: TGLSceneRootObject;
  1098. FBaseContext: TGLContext; //reference, not owned!
  1099. FLights, FBuffers: TGLPersistentObjectList;
  1100. FCurrentGLCamera: TGLCamera;
  1101. FCurrentBuffer: TGLSceneBuffer;
  1102. FObjectsSorting: TGLObjectsSorting;
  1103. FVisibilityCulling: TGLVisibilityCulling;
  1104. FOnBeforeProgress: TGLProgressEvent;
  1105. FOnProgress: TGLProgressEvent;
  1106. FCurrentDeltaTime: Double;
  1107. FInitializableObjects: TGLInitializableObjectList;
  1108. protected
  1109. procedure AddLight(aLight: TGLLightSource);
  1110. procedure RemoveLight(aLight: TGLLightSource);
  1111. // Adds all lights in the subtree (anObj included)
  1112. procedure AddLights(anObj: TGLBaseSceneObject);
  1113. // Removes all lights in the subtree (anObj included)
  1114. procedure RemoveLights(anObj: TGLBaseSceneObject);
  1115. procedure GetChildren(AProc: TGetChildProc; Root: TComponent); override;
  1116. procedure SetChildOrder(AChild: TComponent; Order: Integer); override;
  1117. procedure SetObjectsSorting(const val: TGLObjectsSorting);
  1118. procedure SetVisibilityCulling(const val: TGLVisibilityCulling);
  1119. procedure ReadState(Reader: TReader); override;
  1120. public
  1121. constructor Create(AOwner: TComponent); override;
  1122. destructor Destroy; override;
  1123. procedure BeginUpdate;
  1124. procedure EndUpdate;
  1125. function IsUpdating: Boolean;
  1126. procedure AddBuffer(aBuffer: TGLSceneBuffer);
  1127. procedure RemoveBuffer(aBuffer: TGLSceneBuffer);
  1128. procedure SetupLights(maxLights: Integer);
  1129. procedure NotifyChange(Sender: TObject); override;
  1130. procedure Progress(const deltaTime, newTime: Double);
  1131. function FindSceneObject(const AName: string): TGLBaseSceneObject;
  1132. (* Calculates, finds and returns the first object intercepted by the ray.
  1133. Returns nil if no intersection was found. This function will be
  1134. accurate only for objects that overrided their RayCastIntersect
  1135. method with accurate code, otherwise, bounding sphere intersections
  1136. will be returned. *)
  1137. function RayCastIntersect(const rayStart, rayVector: TGLVector; intersectPoint: PGLVector = nil;
  1138. intersectNormal: PGLVector = nil): TGLBaseSceneObject;
  1139. procedure ShutdownAllLights;
  1140. // Saves the scene to a file (recommended extension : .GLSM)
  1141. procedure SaveToFile(const fileName: string);
  1142. (* Load the scene from a file.
  1143. Existing objects/lights/cameras are freed, then the file is loaded.
  1144. Delphi's IDE is not handling this behaviour properly yet, ie. if
  1145. you load a scene in the IDE, objects will be properly loaded, but
  1146. no declare will be placed in the code. *)
  1147. procedure LoadFromFile(const fileName: string);
  1148. procedure SaveToStream(aStream: TStream);
  1149. procedure LoadFromStream(aStream: TStream);
  1150. // Saves the scene to a text file
  1151. procedure SaveToTextFile(const fileName: string);
  1152. // Load the scene from a text files. See LoadFromFile for details.
  1153. procedure LoadFromTextFile(const fileName: string);
  1154. property CurrentGLCamera: TGLCamera read FCurrentGLCamera;
  1155. property Lights: TGLPersistentObjectList read FLights;
  1156. property Objects: TGLSceneRootObject read FObjects;
  1157. property CurrentBuffer: TGLSceneBuffer read FCurrentBuffer;
  1158. (* List of objects that request to be initialized when rendering context is active.
  1159. They are removed automaticly from this list once initialized. *)
  1160. property InitializableObjects: TGLInitializableObjectList read
  1161. FInitializableObjects;
  1162. property CurrentDeltaTime: Double read FCurrentDeltaTime;
  1163. published
  1164. // Defines default ObjectSorting option for scene objects.
  1165. property ObjectsSorting: TGLObjectsSorting read FObjectsSorting write
  1166. SetObjectsSorting default osRenderBlendedLast;
  1167. // Defines default VisibilityCulling option for scene objects.
  1168. property VisibilityCulling: TGLVisibilityCulling read FVisibilityCulling
  1169. write SetVisibilityCulling default vcNone;
  1170. property OnBeforeProgress: TGLProgressEvent read FOnBeforeProgress write FOnBeforeProgress;
  1171. property OnProgress: TGLProgressEvent read FOnProgress write FOnProgress;
  1172. end;
  1173. TFogMode = (fmLinear, fmExp, fmExp2);
  1174. (*Fog distance calculation mode. fdDefault: let OpenGL use its default formula
  1175. fdEyeRadial: uses radial "true" distance (best quality)
  1176. fdEyePlane: uses the distance to the projection plane (same as Z-Buffer, faster)
  1177. Requires support of GL_NV_fog_distance extension, otherwise, it is ignored. *)
  1178. TFogDistance = (fdDefault, fdEyeRadial, fdEyePlane);
  1179. (* Parameters for fog environment in a scene.
  1180. The fog descibed by this object is a distance-based fog, ie. the "intensity"
  1181. of the fog is given by a formula depending solely on the distance, this
  1182. intensity is used for blending to a fixed color. *)
  1183. TGLFogEnvironment = class(TGLUpdateAbleObject)
  1184. private
  1185. FSceneBuffer: TGLSceneBuffer;
  1186. FFogColor: TGLColor; // alpha value means the fog density
  1187. FFogStart, FFogEnd: Single;
  1188. FFogMode: TFogMode;
  1189. FFogDistance: TFogDistance;
  1190. protected
  1191. procedure SetFogColor(Value: TGLColor);
  1192. procedure SetFogStart(Value: Single);
  1193. procedure SetFogEnd(Value: Single);
  1194. procedure SetFogMode(Value: TFogMode);
  1195. procedure SetFogDistance(const val: TFogDistance);
  1196. public
  1197. constructor Create(AOwner: TPersistent); override;
  1198. destructor Destroy; override;
  1199. procedure ApplyFog;
  1200. procedure Assign(Source: TPersistent); override;
  1201. function IsAtDefaultValues: Boolean;
  1202. published
  1203. // Color of the fog when it is at 100% intensity.
  1204. property FogColor: TGLColor read FFogColor write SetFogColor;
  1205. // Minimum distance for fog, what is closer is not affected.
  1206. property FogStart: Single read FFogStart write SetFogStart;
  1207. // Maximum distance for fog, what is farther is at 100% fog intensity.
  1208. property FogEnd: Single read FFogEnd write SetFogEnd;
  1209. // The formula used for converting distance to fog intensity.
  1210. property FogMode: TFogMode read FFogMode write SetFogMode default fmLinear;
  1211. (* Adjusts the formula used for calculating fog distances.
  1212. This option is honoured if and only if the OpenGL ICD supports the
  1213. GL_NV_fog_distance extension, otherwise, it is ignored.
  1214. fdDefault: let OpenGL use its default formula
  1215. fdEyeRadial: uses radial "true" distance (best quality)
  1216. fdEyePlane: uses the distance to the projection plane (same as Z-Buffer, faster)*)
  1217. property FogDistance: TFogDistance read FFogDistance write SetFogDistance
  1218. default fdDefault;
  1219. end;
  1220. TGLDepthPrecision = (dpDefault, dp16bits, dp24bits, dp32bits);
  1221. TGLColorDepth = (cdDefault, cd8bits, cd16bits, cd24bits, cdFloat64bits, cdFloat128bits);
  1222. TGLShadeModel = (smDefault, smSmooth, smFlat);
  1223. // Encapsulates a frame/rendering buffer.
  1224. TGLSceneBuffer = class(TGLUpdateAbleObject)
  1225. private
  1226. // Internal state
  1227. FRendering: Boolean;
  1228. FRenderingContext: TGLContext;
  1229. FAfterRenderEffects: TGLPersistentObjectList;
  1230. FViewMatrixStack: array of TGLMatrix;
  1231. FProjectionMatrixStack: array of TGLMatrix;
  1232. FBaseProjectionMatrix: TGLMatrix;
  1233. FCameraAbsolutePosition: TGLVector;
  1234. FViewPort: TRectangle;
  1235. FSelector: TGLBaseSelectTechnique;
  1236. // Options & User Properties
  1237. FFaceCulling, FFogEnable, FLighting: Boolean;
  1238. FDepthTest: Boolean;
  1239. FBackgroundColor: TColor;
  1240. FBackgroundAlpha: Single;
  1241. FAmbientColor: TGLColor;
  1242. FAntiAliasing: TGLAntiAliasing;
  1243. FDepthPrecision: TGLDepthPrecision;
  1244. FColorDepth: TGLColorDepth;
  1245. FContextOptions: TGLContextOptions;
  1246. FShadeModel: TGLShadeModel;
  1247. FRenderDPI: Integer;
  1248. FFogEnvironment: TGLFogEnvironment;
  1249. FAccumBufferBits: Integer;
  1250. FLayer: TGLContextLayer;
  1251. // Cameras
  1252. FCamera: TGLCamera;
  1253. // Freezing
  1254. FFreezeBuffer: Pointer;
  1255. FFreezed: Boolean;
  1256. FFreezedViewPort: TRectangle;
  1257. // Monitoring
  1258. FFrameCount: Longint;
  1259. FFramesPerSecond: Single;
  1260. FFirstPerfCounter: Int64;
  1261. FLastFrameTime: Single;
  1262. // Events
  1263. FOnChange: TNotifyEvent;
  1264. FOnStructuralChange: TNotifyEvent;
  1265. FOnPrepareGLContext: TNotifyEvent;
  1266. FBeforeRender: TNotifyEvent;
  1267. FViewerBeforeRender: TNotifyEvent;
  1268. FPostRender: TNotifyEvent;
  1269. FAfterRender: TNotifyEvent;
  1270. FInitiateRendering: TGLDirectRenderEvent;
  1271. FWrapUpRendering: TGLDirectRenderEvent;
  1272. procedure SetLayer(const Value: TGLContextLayer);
  1273. protected
  1274. procedure SetBackgroundColor(AColor: TColor);
  1275. procedure SetBackgroundAlpha(alpha: Single);
  1276. procedure SetAmbientColor(AColor: TGLColor);
  1277. function GetLimit(Which: TGLLimitType): Integer;
  1278. procedure SetCamera(ACamera: TGLCamera);
  1279. procedure SetContextOptions(Options: TGLContextOptions);
  1280. procedure SetDepthTest(AValue: Boolean);
  1281. procedure SetFaceCulling(AValue: Boolean);
  1282. procedure SetLighting(AValue: Boolean);
  1283. procedure SetAntiAliasing(const val: TGLAntiAliasing);
  1284. procedure SetDepthPrecision(const val: TGLDepthPrecision);
  1285. procedure SetColorDepth(const val: TGLColorDepth);
  1286. procedure SetShadeModel(const val: TGLShadeModel);
  1287. procedure SetFogEnable(AValue: Boolean);
  1288. procedure SetGLFogEnvironment(AValue: TGLFogEnvironment);
  1289. function StoreFog: Boolean;
  1290. procedure SetAccumBufferBits(const val: Integer);
  1291. procedure PrepareRenderingMatrices(const aViewPort: TRectangle;
  1292. resolution: Integer; pickingRect: PRect = nil); inline;
  1293. procedure DoBaseRender(const aViewPort: TRectangle; resolution: Integer;
  1294. drawState: TGLDrawState; baseObject: TGLBaseSceneObject);
  1295. procedure SetupRenderingContext(context: TGLContext);
  1296. procedure SetupRCOptions(context: TGLContext);
  1297. procedure PrepareGLContext;
  1298. procedure DoChange;
  1299. procedure DoStructuralChange;
  1300. // DPI for current/last render
  1301. property RenderDPI: Integer read FRenderDPI;
  1302. property OnPrepareGLContext: TNotifyEvent read FOnPrepareGLContext write
  1303. FOnPrepareGLContext;
  1304. public
  1305. constructor Create(AOwner: TPersistent); override;
  1306. destructor Destroy; override;
  1307. procedure NotifyChange(Sender: TObject); override;
  1308. procedure CreateRC(AWindowHandle: HWND; memoryContext: Boolean;
  1309. BufferCount: integer = 1); overload;
  1310. procedure ClearBuffers; inline;
  1311. procedure DestroyRC;
  1312. function RCInstantiated: Boolean;
  1313. procedure Resize(newLeft, newTop, newWidth, newHeight: Integer);
  1314. // Indicates hardware acceleration support
  1315. function Acceleration: TGLContextAcceleration; inline;
  1316. // ViewPort for current/last render
  1317. property ViewPort: TRectangle read FViewPort;
  1318. // Fills the PickList with objects in Rect area
  1319. procedure PickObjects(const rect: TRect; pickList: TGLPickList;
  1320. objectCountGuess: Integer);
  1321. (* Returns a PickList with objects in Rect area.
  1322. Returned list should be freed by caller.
  1323. Objects are sorted by depth (nearest objects first). *)
  1324. function GetPickedObjects(const rect: TRect; objectCountGuess: Integer =
  1325. 64): TGLPickList;
  1326. // Returns the nearest object at x, y coordinates or nil if there is none
  1327. function GetPickedObject(x, y: Integer): TGLBaseSceneObject;
  1328. // Returns the color of the pixel at x, y in the frame buffer
  1329. function GetPixelColor(x, y: Integer): TColor;
  1330. (* Returns the raw depth (Z buffer) of the pixel at x, y in the frame buffer.
  1331. This value does not map to the actual eye-object distance, but to
  1332. a depth buffer value in the [0; 1] range. *)
  1333. function GetPixelDepth(x, y: Integer): Single;
  1334. (* Converts a raw depth (Z buffer value) to frustrum distance.
  1335. This calculation is only accurate for the pixel at the centre of the viewer,
  1336. because it does not take into account that the corners of the frustrum
  1337. are further from the eye than its centre. *)
  1338. function PixelDepthToDistance(aDepth: Single): Single;
  1339. (* Converts a raw depth (Z buffer value) to world distance.
  1340. It also compensates for the fact that the corners of the frustrum
  1341. are further from the eye, than its centre.*)
  1342. function PixelToDistance(x, y: integer): Single;
  1343. // Design time notification
  1344. procedure NotifyMouseMove(Shift: TShiftState; X, Y: Integer);
  1345. (* Renders the scene on the viewer.
  1346. You do not need to call this method, unless you explicitly want a
  1347. render at a specific time. If you just want the control to get
  1348. refreshed, use Invalidate instead. *)
  1349. procedure Render(baseObject: TGLBaseSceneObject); overload;
  1350. procedure Render; overload; inline;
  1351. procedure RenderScene(aScene: TGLScene;
  1352. const viewPortSizeX, viewPortSizeY: Integer;
  1353. drawState: TGLDrawState; baseObject: TGLBaseSceneObject);
  1354. (*Render the scene to a bitmap at given DPI.
  1355. DPI = "dots per inch".
  1356. The "magic" DPI of the screen is 96 under Windows. *)
  1357. procedure RenderToBitmap(ABitmap: TBitmap; DPI: Integer = 0);
  1358. (* Render the scene to a bitmap at given DPI and saves it to a file.
  1359. DPI = "dots per inch".
  1360. The "magic" DPI of the screen is 96 under Windows. *)
  1361. procedure RenderToFile(const AFile: string; DPI: Integer = 0); overload;
  1362. (* Renders to bitmap of given size, then saves it to a file.
  1363. DPI is adjusted to make the bitmap similar to the viewer. *)
  1364. procedure RenderToFile(const AFile: string; bmpWidth, bmpHeight: Integer);
  1365. overload;
  1366. (* Creates a TGLBitmap32 that is a snapshot of current OpenGL content.
  1367. When possible, use this function instead of RenderToBitmap, it won't
  1368. request a redraw and will be significantly faster.
  1369. The returned TGLBitmap32 should be freed by calling code. *)
  1370. function CreateSnapShot: TGLImage;
  1371. // Creates a bitmap that is a snapshot of current OpenGL content.
  1372. function CreateSnapShotBitmap: TBitmap;
  1373. procedure CopyToTexture(aTexture: TGLTexture); overload;
  1374. procedure CopyToTexture(aTexture: TGLTexture; xSrc, ySrc, AWidth, AHeight: Integer;
  1375. xDest, yDest: Integer; glCubeFace: Cardinal = 0); overload;
  1376. // Save as raw float data to a file
  1377. procedure SaveAsFloatToFile(const aFilename: string);
  1378. // Event reserved for viewer-specific uses.
  1379. property ViewerBeforeRender: TNotifyEvent read FViewerBeforeRender write
  1380. FViewerBeforeRender stored False;
  1381. procedure SetViewPort(X, Y, W, H: Integer);
  1382. function Width: Integer;
  1383. function Height: Integer;
  1384. // Indicates if the Viewer is "frozen".
  1385. property Freezed: Boolean read FFreezed;
  1386. (* Freezes rendering leaving the last rendered scene on the buffer. This
  1387. is usefull in windowed applications for temporarily stoping rendering
  1388. (when moving the window, for example). *)
  1389. procedure Freeze;
  1390. // Restarts rendering after it was freezed.
  1391. procedure Melt;
  1392. // Displays a window with info on current OpenGL ICD and context.
  1393. procedure ShowInfo(Modal: boolean = false);
  1394. // Currently Rendering?
  1395. property Rendering: Boolean read FRendering;
  1396. // Adjusts background alpha channel.
  1397. property BackgroundAlpha: Single read FBackgroundAlpha write SetBackgroundAlpha;
  1398. // Returns the projection matrix in use or used for the last rendering.
  1399. function ProjectionMatrix: TGLMatrix; deprecated;
  1400. // Returns the view matrix in use or used for the last rendering.
  1401. function ViewMatrix: TGLMatrix; deprecated;
  1402. function ModelMatrix: TGLMatrix; deprecated;
  1403. (* Returns the base projection matrix in use or used for the last rendering.
  1404. The "base" projection is (as of now) either identity or the pick
  1405. matrix, ie. it is the matrix on which the perspective or orthogonal
  1406. matrix gets applied. *)
  1407. property BaseProjectionMatrix: TGLMatrix read FBaseProjectionMatrix;
  1408. (* Back up current View matrix and replace it with newMatrix.
  1409. This method has no effect on the OpenGL matrix, only on the Buffer's
  1410. matrix, and is intended for special effects rendering. *)
  1411. procedure PushViewMatrix(const newMatrix: TGLMatrix); deprecated;
  1412. // Restore a View matrix previously pushed.
  1413. procedure PopViewMatrix; deprecated;
  1414. procedure PushProjectionMatrix(const newMatrix: TGLMatrix); deprecated;
  1415. procedure PopProjectionMatrix; deprecated;
  1416. (* Converts a screen pixel coordinate into 3D coordinates for orthogonal projection.
  1417. This function accepts standard canvas coordinates, with (0,0) being
  1418. the top left corner, and returns, when the camera is in orthogonal
  1419. mode, the corresponding 3D world point that is in the camera's plane. *)
  1420. function OrthoScreenToWorld(screenX, screenY: Integer): TAffineVector; overload;
  1421. (* Converts a screen coordinate into world (3D) coordinates.
  1422. This methods wraps a call to gluUnProject.
  1423. Note that screen coord (0,0) is the lower left corner. *)
  1424. function ScreenToWorld(const aPoint: TAffineVector): TAffineVector; overload;
  1425. function ScreenToWorld(const aPoint: TGLVector): TGLVector; overload;
  1426. {Converts a screen pixel coordinate into 3D world coordinates.
  1427. This function accepts standard canvas coordinates, with (0,0) being
  1428. the top left corner. }
  1429. function ScreenToWorld(screenX, screenY: Integer): TAffineVector; overload;
  1430. (* Converts an absolute world coordinate into screen coordinate.
  1431. This methods wraps a call to gluProject.
  1432. Note that screen coord (0,0) is the lower left corner. *)
  1433. function WorldToScreen(const aPoint: TAffineVector): TAffineVector; overload;
  1434. function WorldToScreen(const aPoint: TGLVector): TGLVector; overload;
  1435. // Converts a set of point absolute world coordinates into screen coordinates.
  1436. procedure WorldToScreen(points: PGLVector; nbPoints: Integer); overload;
  1437. (* Calculates the 3D vector corresponding to a 2D screen coordinate.
  1438. The vector originates from the camera's absolute position and is
  1439. expressed in absolute coordinates.
  1440. Note that screen coord (0,0) is the lower left corner. *)
  1441. function ScreenToVector(const aPoint: TAffineVector): TAffineVector; overload;
  1442. function ScreenToVector(const aPoint: TGLVector): TGLVector; overload;
  1443. function ScreenToVector(const x, y: Integer): TGLVector; overload;
  1444. (* Calculates the 2D screen coordinate of a vector from the camera's
  1445. absolute position and is expressed in absolute coordinates.
  1446. Note that screen coord (0,0) is the lower left corner. *)
  1447. function VectorToScreen(const VectToCam: TAffineVector): TAffineVector;
  1448. (* Calculates intersection between a plane and screen vector.
  1449. If an intersection is found, returns True and places result in
  1450. intersectPoint. *)
  1451. function ScreenVectorIntersectWithPlane(
  1452. const aScreenPoint: TGLVector;
  1453. const planePoint, planeNormal: TGLVector;
  1454. var intersectPoint: TGLVector): Boolean;
  1455. (* Calculates intersection between plane XY and screen vector.
  1456. If an intersection is found, returns True and places result in
  1457. intersectPoint. *)
  1458. function ScreenVectorIntersectWithPlaneXY(
  1459. const aScreenPoint: TGLVector; const z: Single;
  1460. var intersectPoint: TGLVector): Boolean;
  1461. (* Calculates intersection between plane YZ and screen vector.
  1462. If an intersection is found, returns True and places result in
  1463. intersectPoint. *)
  1464. function ScreenVectorIntersectWithPlaneYZ(
  1465. const aScreenPoint: TGLVector; const x: Single;
  1466. var intersectPoint: TGLVector): Boolean;
  1467. (* Calculates intersection between plane XZ and screen vector.
  1468. If an intersection is found, returns True and places result in
  1469. intersectPoint. *)
  1470. function ScreenVectorIntersectWithPlaneXZ(
  1471. const aScreenPoint: TGLVector; const y: Single;
  1472. var intersectPoint: TGLVector): Boolean;
  1473. (* Calculates a 3D coordinate from screen position and ZBuffer.
  1474. This function returns a world absolute coordinate from a 2D point
  1475. in the viewer, the depth being extracted from the ZBuffer data
  1476. (DepthTesting and ZBuffer must be enabled for this function to work).
  1477. Note that ZBuffer precision is not linear and can be quite low on
  1478. some boards (either from compression or resolution approximations). *)
  1479. function PixelRayToWorld(x, y: Integer): TAffineVector;
  1480. (* Time (in second) spent to issue rendering order for the last frame.
  1481. Be aware that since execution by the hardware isn't synchronous,
  1482. this value may not be an accurate measurement of the time it took
  1483. to render the last frame, it's a measurement of only the time it
  1484. took to issue rendering orders. *)
  1485. property LastFrameTime: Single read FLastFrameTime;
  1486. (* Current FramesPerSecond rendering speed.
  1487. You must keep the renderer busy to get accurate figures from this
  1488. property.
  1489. This is an average value, to reset the counter, call
  1490. ResetPerfomanceMonitor. *)
  1491. property FramesPerSecond: Single read FFramesPerSecond;
  1492. (* Resets the perfomance monitor and begin a new statistics set.
  1493. See FramesPerSecond. *)
  1494. procedure ResetPerformanceMonitor;
  1495. (* Retrieve one of the OpenGL limits for the current viewer.
  1496. Limits include max texture size, OpenGL stack depth, etc. *)
  1497. property LimitOf[Which: TGLLimitType]: Integer read GetLimit;
  1498. (* Current rendering context.
  1499. The context is a wrapper around platform-specific contexts
  1500. (see TGLContext) and takes care of context activation and handle
  1501. management. *)
  1502. property RenderingContext: TGLContext read FRenderingContext;
  1503. (* The camera from which the scene is rendered.
  1504. A camera is an object you can add and define in a TGLScene component. *)
  1505. property Camera: TGLCamera read FCamera write SetCamera;
  1506. // Specifies the layer plane that the rendering context is bound to.
  1507. property Layer: TGLContextLayer read FLayer write SetLayer
  1508. default clMainPlane;
  1509. published
  1510. // Fog environment options. See TGLFogEnvironment.
  1511. property FogEnvironment: TGLFogEnvironment read FFogEnvironment write
  1512. SetGLFogEnvironment stored StoreFog;
  1513. // Color used for filling the background prior to any rendering.
  1514. property BackgroundColor: TColor read FBackgroundColor write
  1515. SetBackgroundColor default clBtnFace;
  1516. (* Scene ambient color vector.
  1517. This ambient color is defined independantly from all lightsources,
  1518. which can have their own ambient components. *)
  1519. property AmbientColor: TGLColor read FAmbientColor write SetAmbientColor;
  1520. (* Context options allows to setup specifics of the rendering context.
  1521. Not all contexts support all options. *)
  1522. property ContextOptions: TGLContextOptions read FContextOptions write
  1523. SetContextOptions default [roDoubleBuffer, roRenderToWindow, roDebugContext];
  1524. // Number of precision bits for the accumulation buffer.
  1525. property AccumBufferBits: Integer read FAccumBufferBits write
  1526. SetAccumBufferBits default 0;
  1527. (* DepthTest enabling.
  1528. When DepthTest is enabled, objects closer to the camera will hide
  1529. farther ones (via use of Z-Buffering).
  1530. When DepthTest is disabled, the latest objects drawn/rendered overlap
  1531. all previous objects, whatever their distance to the camera.
  1532. Even when DepthTest is enabled, objects may chose to ignore depth
  1533. testing through the osIgnoreDepthBuffer of their ObjectStyle property. *)
  1534. property DepthTest: Boolean read FDepthTest write SetDepthTest default True;
  1535. (* Enable or disable face culling in the renderer.
  1536. Face culling is used in hidden faces removal algorithms : each face
  1537. is given a normal or 'outside' direction. When face culling is enabled,
  1538. only faces whose normal points towards the observer are rendered. *)
  1539. property FaceCulling: Boolean read FFaceCulling write SetFaceCulling default True;
  1540. // Toggle to enable or disable the fog settings.
  1541. property FogEnable: Boolean read FFogEnable write SetFogEnable default
  1542. False;
  1543. (* Toggle to enable or disable lighting calculations.
  1544. When lighting is enabled, objects will be lit according to lightsources,
  1545. when lighting is disabled, objects are rendered in their own colors,
  1546. without any shading.
  1547. Lighting does NOT generate shadows. *)
  1548. property Lighting: Boolean read FLighting write SetLighting default True;
  1549. (* AntiAliasing option.
  1550. Ignored if not hardware supported, currently based on ARB_multisample. *)
  1551. property AntiAliasing: TGLAntiAliasing read FAntiAliasing write
  1552. SetAntiAliasing default aaDefault;
  1553. (* Depth buffer precision.
  1554. Default is highest available (below and including 24 bits) *)
  1555. property DepthPrecision: TGLDepthPrecision read FDepthPrecision write
  1556. SetDepthPrecision default dpDefault;
  1557. (* Color buffer depth.
  1558. Default depth buffer is highest available (below and including 24 bits) *)
  1559. property ColorDepth: TGLColorDepth read FColorDepth write SetColorDepth
  1560. default cdDefault;
  1561. // Shade model. Default is "Smooth".
  1562. property ShadeModel: TGLShadeModel read FShadeModel write SetShadeModel
  1563. default smDefault;
  1564. (* Indicates a change in the scene or buffer options.
  1565. A simple re-render is enough to take into account the changes. *)
  1566. property OnChange: TNotifyEvent read FOnChange write FOnChange stored False;
  1567. (* Indicates a structural change in the scene or buffer options.
  1568. A reconstruction of the RC is necessary to take into account the
  1569. changes (this may lead to a driver switch or lengthy operations). *)
  1570. property OnStructuralChange: TNotifyEvent read FOnStructuralChange write
  1571. FOnStructuralChange stored False;
  1572. (* Triggered before the scene's objects get rendered.
  1573. You may use this event to execute your own OpenGL rendering
  1574. (usually background stuff). *)
  1575. property BeforeRender: TNotifyEvent read FBeforeRender write FBeforeRender
  1576. stored False;
  1577. (* Triggered after BeforeRender, before rendering objects.
  1578. This one is fired after the rci has been initialized and can be used
  1579. to alter it or perform early renderings that require an rci,
  1580. the Sender is the buffer. *)
  1581. property InitiateRendering: TGLDirectRenderEvent read FInitiateRendering write
  1582. FInitiateRendering stored False;
  1583. (* Triggered after rendering all scene objects, before PostRender.
  1584. This is the last point after which the rci becomes unavailable,
  1585. the Sender is the buffer. *)
  1586. property WrapUpRendering: TGLDirectRenderEvent read FWrapUpRendering write
  1587. FWrapUpRendering stored False;
  1588. (* Triggered just after all the scene's objects have been rendered.
  1589. The OpenGL context is still active in this event, and you may use it
  1590. to execute your own OpenGL rendering (usually for HUD, 2D overlays
  1591. or after effects). *)
  1592. property PostRender: TNotifyEvent read FPostRender write FPostRender stored
  1593. False;
  1594. (* Called after rendering.
  1595. You cannot issue OpenGL calls in this event, if you want to do your own
  1596. OpenGL stuff, use the PostRender event. *)
  1597. property AfterRender: TNotifyEvent read FAfterRender write FAfterRender
  1598. stored False;
  1599. end;
  1600. (* Base class for non-visual viewer.
  1601. Non-visual viewer may actually render visuals, but they are non-visual
  1602. (ie. non interactive) at design time. Such viewers include memory or full-screen viewers. *)
  1603. TGLNonVisualViewer = class(TComponent)
  1604. private
  1605. FBuffer: TGLSceneBuffer;
  1606. FWidth, FHeight: Integer;
  1607. FCubeMapRotIdx: Integer;
  1608. FCubeMapZNear, FCubeMapZFar: Single;
  1609. FCubeMapTranslation: TAffineVector;
  1610. //FCreateTexture : Boolean;
  1611. protected
  1612. procedure SetBeforeRender(const val: TNotifyEvent);
  1613. function GetBeforeRender: TNotifyEvent;
  1614. procedure SetPostRender(const val: TNotifyEvent);
  1615. function GetPostRender: TNotifyEvent;
  1616. procedure SetAfterRender(const val: TNotifyEvent);
  1617. function GetAfterRender: TNotifyEvent;
  1618. procedure SetCamera(const val: TGLCamera);
  1619. function GetCamera: TGLCamera;
  1620. procedure SetBuffer(const val: TGLSceneBuffer);
  1621. procedure SetWidth(const val: Integer);
  1622. procedure SetHeight(const val: Integer);
  1623. procedure SetupCubeMapCamera(Sender: TObject);
  1624. procedure DoOnPrepareGLContext(Sender: TObject);
  1625. procedure PrepareGLContext; virtual;
  1626. procedure DoBufferChange(Sender: TObject); virtual;
  1627. procedure DoBufferStructuralChange(Sender: TObject); virtual;
  1628. public
  1629. constructor Create(AOwner: TComponent); override;
  1630. destructor Destroy; override;
  1631. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  1632. procedure Render(baseObject: TGLBaseSceneObject = nil); virtual; abstract;
  1633. procedure CopyToTexture(aTexture: TGLTexture); overload; virtual;
  1634. procedure CopyToTexture(aTexture: TGLTexture; xSrc, ySrc, width, height:
  1635. Integer;
  1636. xDest, yDest: Integer); overload;
  1637. // CopyToTexture for Multiple-Render-Target
  1638. procedure CopyToTextureMRT(aTexture: TGLTexture; BufferIndex: integer);
  1639. overload; virtual;
  1640. procedure CopyToTextureMRT(aTexture: TGLTexture; xSrc, ySrc, width, height:
  1641. Integer;
  1642. xDest, yDest: Integer; BufferIndex: integer); overload;
  1643. (* Renders the 6 texture maps from a scene.
  1644. The viewer is used to render the 6 images, one for each face
  1645. of the cube, from the absolute position of the camera.
  1646. This does NOT alter the content of the Pictures in the image,
  1647. and will only change or define the content of textures as registered by OpenGL. *)
  1648. procedure RenderCubeMapTextures(cubeMapTexture: TGLTexture;
  1649. zNear: Single = 0;
  1650. zFar: Single = 0);
  1651. published
  1652. // Camera from which the scene is rendered.
  1653. property Camera: TGLCamera read GetCamera write SetCamera;
  1654. property Width: Integer read FWidth write SetWidth default 256;
  1655. property Height: Integer read FHeight write SetHeight default 256;
  1656. (* Triggered before the scene's objects get rendered.
  1657. You may use this event to execute your own OpenGL rendering. *)
  1658. property BeforeRender: TNotifyEvent read GetBeforeRender write SetBeforeRender;
  1659. (* Triggered just after all the scene's objects have been rendered.
  1660. The OpenGL context is still active in this event, and you may use it
  1661. to execute your own OpenGL rendering. *)
  1662. property PostRender: TNotifyEvent read GetPostRender write SetPostRender;
  1663. (* Called after rendering.
  1664. You cannot issue OpenGL calls in this event, if you want to do your own
  1665. OpenGL stuff, use the PostRender event. *)
  1666. property AfterRender: TNotifyEvent read GetAfterRender write SetAfterRender;
  1667. // Access to buffer properties.
  1668. property Buffer: TGLSceneBuffer read FBuffer write SetBuffer;
  1669. end;
  1670. (* Component to render a scene to memory only.
  1671. This component curently requires that the OpenGL ICD supports the
  1672. WGL_ARB_pbuffer extension (indirectly). *)
  1673. TGLMemoryViewer = class(TGLNonVisualViewer)
  1674. private
  1675. FBufferCount: integer;
  1676. procedure SetBufferCount(const Value: integer);
  1677. public
  1678. constructor Create(AOwner: TComponent); override;
  1679. procedure InstantiateRenderingContext;
  1680. procedure Render(baseObject: TGLBaseSceneObject = nil); override;
  1681. published
  1682. (* Set BufferCount > 1 for multiple render targets.
  1683. Users should check if the corresponding extension (GL_ATI_draw_buffers)
  1684. is supported. Current hardware limit is BufferCount = 4. *)
  1685. property BufferCount: integer read FBufferCount write SetBufferCount default 1;
  1686. end;
  1687. TInvokeInfoForm = procedure(aSceneBuffer: TGLSceneBuffer; Modal: boolean);
  1688. (* Register an event handler triggered by any TGLBaseSceneObject Name change.
  1689. *INCOMPLETE*, currently allows for only 1 (one) event, and is used by
  1690. GLSceneEdit in the IDE. *)
  1691. procedure RegisterGLBaseSceneObjectNameChangeEvent(notifyEvent: TNotifyEvent);
  1692. (* Deregister an event handler triggered by any TGLBaseSceneObject Name change.
  1693. See RegisterGLBaseSceneObjectNameChangeEvent. *)
  1694. procedure DeRegisterGLBaseSceneObjectNameChangeEvent(notifyEvent: TNotifyEvent);
  1695. (* Register an event handler triggered by any TGLBehaviour Name change.
  1696. *INCOMPLETE*, currently allows for only 1 (one) event, and is used by
  1697. FBehavioursEditor in the IDE. *)
  1698. procedure RegisterGLBehaviourNameChangeEvent(notifyEvent: TNotifyEvent);
  1699. (* Deregister an event handler triggered by any TGLBaseSceneObject Name change.
  1700. See RegisterGLBaseSceneObjectNameChangeEvent. *)
  1701. procedure DeRegisterGLBehaviourNameChangeEvent(notifyEvent: TNotifyEvent);
  1702. // Issues OpenGL calls for drawing X, Y, Z axes in a standard style.
  1703. procedure AxesBuildList(var rci: TGLRenderContextInfo; pattern: Word; AxisLen: Single);
  1704. // Registers the procedure call used to invoke the info form.
  1705. procedure RegisterInfoForm(infoForm: TInvokeInfoForm);
  1706. procedure InvokeInfoForm(aSceneBuffer: TGLSceneBuffer; Modal: boolean);
  1707. function GetCurrentRenderingObject: TGLBaseSceneObject;
  1708. var
  1709. vCounterFrequency: Int64;
  1710. {$IFNDEF USE_MULTITHREAD}
  1711. var
  1712. {$ELSE}
  1713. threadvar
  1714. {$ENDIF}
  1715. vCurrentRenderingObject: TGLBaseSceneObject;
  1716. //------------------------------------------------------------------------------
  1717. implementation
  1718. //------------------------------------------------------------------------------
  1719. function GetCurrentRenderingObject: TGLBaseSceneObject;
  1720. begin
  1721. Result := vCurrentRenderingObject;
  1722. end;
  1723. procedure AxesBuildList(var rci: TGLRenderContextInfo; pattern: Word; axisLen:
  1724. Single);
  1725. begin
  1726. {$IFDEF USE_OPENGL_DEBUG}
  1727. if GL.GREMEDY_string_marker then
  1728. GL.StringMarkerGREMEDY(13, 'AxesBuildList');
  1729. {$ENDIF}
  1730. with rci.GLStates do
  1731. begin
  1732. Disable(stLighting);
  1733. if not rci.ignoreBlendingRequests then
  1734. begin
  1735. Enable(stBlend);
  1736. SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
  1737. end;
  1738. LineWidth := 1;
  1739. Enable(stLineStipple);
  1740. LineStippleFactor := 1;
  1741. LineStipplePattern := Pattern;
  1742. DepthWriteMask := True;
  1743. DepthFunc := cfLEqual;
  1744. if rci.bufferDepthTest then
  1745. Enable(stDepthTest);
  1746. end;
  1747. gl.Begin_(GL_LINES);
  1748. gl.Color3f(0.5, 0.0, 0.0);
  1749. gl.Vertex3f(0, 0, 0);
  1750. gl.Vertex3f(-AxisLen, 0, 0);
  1751. gl.Color3f(1.0, 0.0, 0.0);
  1752. gl.Vertex3f(0, 0, 0);
  1753. gl.Vertex3f(AxisLen, 0, 0);
  1754. gl.Color3f(0.0, 0.5, 0.0);
  1755. gl.Vertex3f(0, 0, 0);
  1756. gl.Vertex3f(0, -AxisLen, 0);
  1757. gl.Color3f(0.0, 1.0, 0.0);
  1758. gl.Vertex3f(0, 0, 0);
  1759. gl.Vertex3f(0, AxisLen, 0);
  1760. gl.Color3f(0.0, 0.0, 0.5);
  1761. gl.Vertex3f(0, 0, 0);
  1762. gl.Vertex3f(0, 0, -AxisLen);
  1763. gl.Color3f(0.0, 0.0, 1.0);
  1764. gl.Vertex3f(0, 0, 0);
  1765. gl.Vertex3f(0, 0, AxisLen);
  1766. gl.End_;
  1767. end;
  1768. var
  1769. vInfoForm: TInvokeInfoForm = nil;
  1770. procedure RegisterInfoForm(infoForm: TInvokeInfoForm);
  1771. begin
  1772. vInfoForm := infoForm;
  1773. end;
  1774. procedure InvokeInfoForm(aSceneBuffer: TGLSceneBuffer; Modal: boolean);
  1775. begin
  1776. if Assigned(vInfoForm) then
  1777. vInfoForm(aSceneBuffer, Modal)
  1778. else
  1779. InformationDlg('InfoForm not available.');
  1780. end;
  1781. //------------------ internal global routines ----------------------------------
  1782. var
  1783. vGLBaseSceneObjectNameChangeEvent: TNotifyEvent;
  1784. vGLBehaviourNameChangeEvent: TNotifyEvent;
  1785. procedure RegisterGLBaseSceneObjectNameChangeEvent(notifyEvent: TNotifyEvent);
  1786. begin
  1787. vGLBaseSceneObjectNameChangeEvent := notifyEvent;
  1788. end;
  1789. procedure DeRegisterGLBaseSceneObjectNameChangeEvent(notifyEvent: TNotifyEvent);
  1790. begin
  1791. vGLBaseSceneObjectNameChangeEvent := nil;
  1792. end;
  1793. procedure RegisterGLBehaviourNameChangeEvent(notifyEvent: TNotifyEvent);
  1794. begin
  1795. vGLBehaviourNameChangeEvent := notifyEvent;
  1796. end;
  1797. procedure DeRegisterGLBehaviourNameChangeEvent(notifyEvent: TNotifyEvent);
  1798. begin
  1799. vGLBehaviourNameChangeEvent := nil;
  1800. end;
  1801. // ------------------
  1802. // ------------------ TGLBaseSceneObject ------------------
  1803. // ------------------
  1804. constructor TGLBaseSceneObject.Create(AOwner: TComponent);
  1805. begin
  1806. inherited Create(AOwner);
  1807. FListHandle := TGLListHandle.Create;
  1808. FObjectStyle := [];
  1809. FChanges := [ocTransformation, ocStructure,
  1810. ocAbsoluteMatrix, ocInvAbsoluteMatrix];
  1811. FPosition := TGLCoordinates.CreateInitialized(Self, NullHmgPoint, csPoint);
  1812. FRotation := TGLCoordinates.CreateInitialized(Self, NullHmgVector, csVector);
  1813. FDirection := TGLCoordinates.CreateInitialized(Self, ZHmgVector, csVector);
  1814. FUp := TGLCoordinates.CreateInitialized(Self, YHmgVector, csVector);
  1815. FScaling := TGLCoordinates.CreateInitialized(Self, XYZHmgVector, csVector);
  1816. FLocalMatrix := IdentityHmgMatrix;
  1817. FVisible := True;
  1818. FPickable := True;
  1819. FObjectsSorting := osInherited;
  1820. FVisibilityCulling := vcInherited;
  1821. FChildren := TGLPersistentObjectList.Create;
  1822. fBBChanges := [oBBcChild, oBBcStructure];
  1823. FBoundingBoxPersonalUnscaled := NullBoundingBox;
  1824. FBoundingBoxOfChildren := NullBoundingBox;
  1825. FBoundingBoxIncludingChildren := NullBoundingBox;
  1826. distList := TGLSingleList.Create;
  1827. objList := TGLPersistentObjectList.Create;
  1828. end;
  1829. constructor TGLBaseSceneObject.CreateAsChild(aParentOwner: TGLBaseSceneObject);
  1830. begin
  1831. Create(aParentOwner);
  1832. aParentOwner.AddChild(Self);
  1833. end;
  1834. destructor TGLBaseSceneObject.Destroy;
  1835. begin
  1836. DeleteChildCameras;
  1837. FEffects.Free;
  1838. FBehaviours.Free;
  1839. FListHandle.Free;
  1840. FPosition.Free;
  1841. FRotation.Free;
  1842. FDirection.Free;
  1843. FUp.Free;
  1844. FScaling.Free;
  1845. if Assigned(FParent) then
  1846. FParent.Remove(Self, False);
  1847. DeleteChildren;
  1848. FChildren.Free;
  1849. objList.Free;
  1850. distList.Free;
  1851. inherited Destroy;
  1852. end;
  1853. function TGLBaseSceneObject.GetHandle(var rci: TGLRenderContextInfo): Cardinal;
  1854. begin
  1855. // Special case.. dirty trixxors
  1856. if not Assigned(FListHandle) then
  1857. begin
  1858. Result := 0;
  1859. Exit;
  1860. end;
  1861. Result := FListHandle.Handle;
  1862. if Result = 0 then
  1863. Result := FListHandle.AllocateHandle;
  1864. if ocStructure in FChanges then
  1865. begin
  1866. ClearStructureChanged;
  1867. FListHandle.NotifyChangesOfData;
  1868. end;
  1869. if FListHandle.IsDataNeedUpdate then
  1870. begin
  1871. rci.GLStates.NewList(Result, GL_COMPILE);
  1872. try
  1873. BuildList(rci);
  1874. finally
  1875. rci.GLStates.EndList;
  1876. end;
  1877. FListHandle.NotifyDataUpdated;
  1878. end;
  1879. end;
  1880. function TGLBaseSceneObject.ListHandleAllocated: Boolean;
  1881. begin
  1882. Result := Assigned(FListHandle)
  1883. and (FListHandle.Handle <> 0)
  1884. and not (ocStructure in FChanges);
  1885. end;
  1886. procedure TGLBaseSceneObject.DestroyHandle;
  1887. begin
  1888. if Assigned(FListHandle) then
  1889. FListHandle.DestroyHandle;
  1890. end;
  1891. procedure TGLBaseSceneObject.DestroyHandles;
  1892. var
  1893. i: Integer;
  1894. begin
  1895. for i := 0 to Count - 1 do
  1896. Children[i].DestroyHandles;
  1897. DestroyHandle;
  1898. end;
  1899. procedure TGLBaseSceneObject.SetBBChanges(const Value: TGLObjectBBChanges);
  1900. begin
  1901. if value <> fBBChanges then
  1902. begin
  1903. fBBChanges := Value;
  1904. if Assigned(FParent) then
  1905. FParent.BBChanges := FParent.BBChanges + [oBBcChild];
  1906. end;
  1907. end;
  1908. function TGLBaseSceneObject.Blended: Boolean;
  1909. begin
  1910. Result := False;
  1911. end;
  1912. procedure TGLBaseSceneObject.BeginUpdate;
  1913. begin
  1914. Inc(FUpdateCount);
  1915. end;
  1916. procedure TGLBaseSceneObject.EndUpdate;
  1917. begin
  1918. if FUpdateCount > 0 then
  1919. begin
  1920. Dec(FUpdateCount);
  1921. if FUpdateCount = 0 then
  1922. NotifyChange(Self);
  1923. end
  1924. else
  1925. Assert(False, strUnBalancedBeginEndUpdate);
  1926. end;
  1927. procedure TGLBaseSceneObject.BuildList(var rci: TGLRenderContextInfo);
  1928. begin
  1929. // nothing
  1930. end;
  1931. procedure TGLBaseSceneObject.DeleteChildCameras;
  1932. var
  1933. i: Integer;
  1934. child: TGLBaseSceneObject;
  1935. begin
  1936. i := 0;
  1937. while i < FChildren.Count do
  1938. begin
  1939. child := TGLBaseSceneObject(FChildren.List^[i]);
  1940. child.DeleteChildCameras;
  1941. if child is TGLCamera then
  1942. begin
  1943. Remove(child, True);
  1944. child.Free;
  1945. end
  1946. else
  1947. Inc(i);
  1948. end;
  1949. end;
  1950. procedure TGLBaseSceneObject.DeleteChildren;
  1951. var
  1952. child: TGLBaseSceneObject;
  1953. begin
  1954. DeleteChildCameras;
  1955. if Assigned(FScene) then
  1956. FScene.RemoveLights(Self);
  1957. while FChildren.Count > 0 do
  1958. begin
  1959. child := TGLBaseSceneObject(FChildren.Pop);
  1960. child.FParent := nil;
  1961. child.Free;
  1962. end;
  1963. BBChanges := BBChanges + [oBBcChild];
  1964. end;
  1965. procedure TGLBaseSceneObject.Loaded;
  1966. begin
  1967. inherited;
  1968. FPosition.W := 1;
  1969. if Assigned(FBehaviours) then
  1970. FBehaviours.Loaded;
  1971. if Assigned(FEffects) then
  1972. FEffects.Loaded;
  1973. end;
  1974. procedure TGLBaseSceneObject.DefineProperties(Filer: TFiler);
  1975. begin
  1976. inherited;
  1977. (*FOriginalFiler := Filer;*)
  1978. Filer.DefineBinaryProperty('BehavioursData', ReadBehaviours, WriteBehaviours,
  1979. (Assigned(FBehaviours) and (FBehaviours.Count > 0)));
  1980. Filer.DefineBinaryProperty('EffectsData', ReadEffects, WriteEffects,
  1981. (Assigned(FEffects) and (FEffects.Count > 0)));
  1982. (*FOriginalFiler := nil;*)
  1983. end;
  1984. procedure TGLBaseSceneObject.WriteBehaviours(stream: TStream);
  1985. var
  1986. writer: TWriter;
  1987. begin
  1988. writer := TWriter.Create(stream, 16384);
  1989. try
  1990. Behaviours.WriteToFiler(writer);
  1991. finally
  1992. writer.Free;
  1993. end;
  1994. end;
  1995. procedure TGLBaseSceneObject.ReadBehaviours(stream: TStream);
  1996. var
  1997. reader: TReader;
  1998. begin
  1999. reader := TReader.Create(stream, 16384);
  2000. (* with TReader(FOriginalFiler) do *)
  2001. try
  2002. (*
  2003. reader.Root := Root;
  2004. reader.OnError := OnError;
  2005. reader.OnFindMethod := OnFindMethod;
  2006. reader.OnSetName := OnSetName;
  2007. reader.OnReferenceName := OnReferenceName;
  2008. reader.OnAncestorNotFound := OnAncestorNotFound;
  2009. reader.OnCreateComponent := OnCreateComponent;
  2010. reader.OnFindComponentClass := OnFindComponentClass;
  2011. *)
  2012. Behaviours.ReadFromFiler(reader);
  2013. finally
  2014. reader.Free;
  2015. end;
  2016. end;
  2017. procedure TGLBaseSceneObject.WriteEffects(stream: TStream);
  2018. var
  2019. writer: TWriter;
  2020. begin
  2021. writer := TWriter.Create(stream, 16384);
  2022. try
  2023. Effects.WriteToFiler(writer);
  2024. finally
  2025. writer.Free;
  2026. end;
  2027. end;
  2028. procedure TGLBaseSceneObject.ReadEffects(stream: TStream);
  2029. var
  2030. reader: TReader;
  2031. begin
  2032. reader := TReader.Create(stream, 16384);
  2033. (*with TReader(FOriginalFiler) do *)
  2034. try
  2035. (*
  2036. reader.Root := Root;
  2037. reader.OnError := OnError;
  2038. reader.OnFindMethod := OnFindMethod;
  2039. reader.OnSetName := OnSetName;
  2040. reader.OnReferenceName := OnReferenceName;
  2041. reader.OnAncestorNotFound := OnAncestorNotFound;
  2042. reader.OnCreateComponent := OnCreateComponent;
  2043. reader.OnFindComponentClass := OnFindComponentClass;
  2044. *)
  2045. Effects.ReadFromFiler(reader);
  2046. finally
  2047. reader.Free;
  2048. end;
  2049. end;
  2050. procedure TGLBaseSceneObject.WriteRotations(stream: TStream);
  2051. begin
  2052. stream.Write(FRotation.AsAddress^, 3 * SizeOf(TGLFloat));
  2053. end;
  2054. procedure TGLBaseSceneObject.ReadRotations(stream: TStream);
  2055. begin
  2056. stream.Read(FRotation.AsAddress^, 3 * SizeOf(TGLFloat));
  2057. end;
  2058. procedure TGLBaseSceneObject.DrawAxes(var rci: TGLRenderContextInfo; pattern: Word);
  2059. begin
  2060. AxesBuildList(rci, Pattern, rci.rcci.farClippingDistance - rci.rcci.nearClippingDistance);
  2061. end;
  2062. procedure TGLBaseSceneObject.GetChildren(AProc: TGetChildProc; Root: TComponent);
  2063. var
  2064. i: Integer;
  2065. begin
  2066. for i := 0 to FChildren.Count - 1 do
  2067. if not IsSubComponent(TComponent(FChildren.List^[i])) then
  2068. AProc(TComponent(FChildren.List^[i]));
  2069. end;
  2070. function TGLBaseSceneObject.Get(Index: Integer): TGLBaseSceneObject;
  2071. begin
  2072. Result := TGLBaseSceneObject(FChildren[Index]);
  2073. end;
  2074. function TGLBaseSceneObject.GetCount: Integer;
  2075. begin
  2076. Result := FChildren.Count;
  2077. end;
  2078. function TGLBaseSceneObject.GetDirectAbsoluteMatrix: PGLMatrix;
  2079. begin
  2080. Result := @FAbsoluteMatrix;
  2081. end;
  2082. function TGLBaseSceneObject.HasSubChildren: Boolean;
  2083. var
  2084. I: Integer;
  2085. begin
  2086. Result := False;
  2087. if Count <> 0 then
  2088. for I := 0 to Count - 1 do
  2089. if IsSubComponent(Children[i]) then
  2090. begin
  2091. Result := True;
  2092. Exit;
  2093. end;
  2094. end;
  2095. procedure TGLBaseSceneObject.AddChild(aChild: TGLBaseSceneObject);
  2096. begin
  2097. if Assigned(FScene) then
  2098. FScene.AddLights(aChild);
  2099. FChildren.Add(aChild);
  2100. aChild.FParent := Self;
  2101. aChild.SetScene(FScene);
  2102. TransformationChanged;
  2103. aChild.TransformationChanged;
  2104. aChild.DoOnAddedToParent;
  2105. BBChanges := BBChanges + [oBBcChild];
  2106. end;
  2107. function TGLBaseSceneObject.AddNewChild(aChild: TGLSceneObjectClass): TGLBaseSceneObject;
  2108. begin
  2109. Result := aChild.Create(Owner);
  2110. AddChild(Result);
  2111. end;
  2112. function TGLBaseSceneObject.AddNewChildFirst(aChild: TGLSceneObjectClass): TGLBaseSceneObject;
  2113. begin
  2114. Result := aChild.Create(Owner);
  2115. Insert(0, Result);
  2116. end;
  2117. function TGLBaseSceneObject.GetOrCreateBehaviour(aBehaviour: TGLBehaviourClass): TGLBehaviour;
  2118. begin
  2119. Result := TGLBehaviour(Behaviours.GetOrCreate(aBehaviour));
  2120. end;
  2121. function TGLBaseSceneObject.AddNewBehaviour(aBehaviour: TGLBehaviourClass): TGLBehaviour;
  2122. begin
  2123. Assert(Behaviours.CanAdd(aBehaviour));
  2124. result := aBehaviour.Create(Behaviours)
  2125. end;
  2126. function TGLBaseSceneObject.GetOrCreateEffect(aEffect: TGLEffectClass): TGLEffect;
  2127. begin
  2128. Result := TGLEffect(Effects.GetOrCreate(aEffect));
  2129. end;
  2130. function TGLBaseSceneObject.AddNewEffect(aEffect: TGLEffectClass): TGLEffect;
  2131. begin
  2132. Assert(Effects.CanAdd(aEffect));
  2133. result := aEffect.Create(Effects)
  2134. end;
  2135. procedure TGLBaseSceneObject.RebuildMatrix;
  2136. begin
  2137. if ocTransformation in Changes then
  2138. begin
  2139. VectorScale(LeftVector, Scale.X, FLocalMatrix.X);
  2140. VectorScale(FUp.AsVector, Scale.Y, FLocalMatrix.Y);
  2141. VectorScale(FDirection.AsVector, Scale.Z, FLocalMatrix.Z);
  2142. SetVector(FLocalMatrix.W, FPosition.AsVector);
  2143. Exclude(FChanges, ocTransformation);
  2144. Include(FChanges, ocAbsoluteMatrix);
  2145. Include(FChanges, ocInvAbsoluteMatrix);
  2146. end;
  2147. end;
  2148. procedure TGLBaseSceneObject.ForceLocalMatrix(const aMatrix: TGLMatrix);
  2149. begin
  2150. FLocalMatrix := aMatrix;
  2151. Exclude(FChanges, ocTransformation);
  2152. Include(FChanges, ocAbsoluteMatrix);
  2153. Include(FChanges, ocInvAbsoluteMatrix);
  2154. end;
  2155. function TGLBaseSceneObject.AbsoluteMatrixAsAddress: PGLMatrix;
  2156. begin
  2157. if ocAbsoluteMatrix in FChanges then
  2158. begin
  2159. RebuildMatrix;
  2160. if Assigned(Parent) (*and (not (Parent is TGLSceneRootObject))*) then
  2161. begin
  2162. MatrixMultiply(FLocalMatrix, TGLBaseSceneObject(Parent).AbsoluteMatrixAsAddress^,
  2163. FAbsoluteMatrix);
  2164. end
  2165. else
  2166. FAbsoluteMatrix := FLocalMatrix;
  2167. Exclude(FChanges, ocAbsoluteMatrix);
  2168. Include(FChanges, ocInvAbsoluteMatrix);
  2169. end;
  2170. Result := @FAbsoluteMatrix;
  2171. end;
  2172. function TGLBaseSceneObject.InvAbsoluteMatrix: TGLMatrix;
  2173. begin
  2174. Result := InvAbsoluteMatrixAsAddress^;
  2175. end;
  2176. function TGLBaseSceneObject.InvAbsoluteMatrixAsAddress: PGLMatrix;
  2177. begin
  2178. if ocInvAbsoluteMatrix in FChanges then
  2179. begin
  2180. if VectorEquals(Scale.DirectVector, XYZHmgVector) then
  2181. begin
  2182. RebuildMatrix;
  2183. if Parent <> nil then
  2184. FInvAbsoluteMatrix :=
  2185. MatrixMultiply(Parent.InvAbsoluteMatrixAsAddress^,
  2186. AnglePreservingMatrixInvert(FLocalMatrix))
  2187. else
  2188. FInvAbsoluteMatrix := AnglePreservingMatrixInvert(FLocalMatrix);
  2189. end
  2190. else
  2191. begin
  2192. FInvAbsoluteMatrix := AbsoluteMatrixAsAddress^;
  2193. InvertMatrix(FInvAbsoluteMatrix);
  2194. end;
  2195. Exclude(FChanges, ocInvAbsoluteMatrix);
  2196. end;
  2197. Result := @FInvAbsoluteMatrix;
  2198. end;
  2199. function TGLBaseSceneObject.GetAbsoluteMatrix: TGLMatrix;
  2200. begin
  2201. Result := AbsoluteMatrixAsAddress^;
  2202. end;
  2203. procedure TGLBaseSceneObject.SetAbsoluteMatrix(const Value: TGLMatrix);
  2204. begin
  2205. if not MatrixEquals(Value, FAbsoluteMatrix) then
  2206. begin
  2207. FAbsoluteMatrix := Value;
  2208. if Parent <> nil then
  2209. SetMatrix(MatrixMultiply(FAbsoluteMatrix,
  2210. Parent.InvAbsoluteMatrixAsAddress^))
  2211. else
  2212. SetMatrix(Value);
  2213. end;
  2214. end;
  2215. function TGLBaseSceneObject.GetAbsoluteDirection: TGLVector;
  2216. begin
  2217. Result := VectorNormalize(AbsoluteMatrixAsAddress^.V[2]);
  2218. end;
  2219. procedure TGLBaseSceneObject.SetAbsoluteDirection(const v: TGLVector);
  2220. begin
  2221. if Parent <> nil then
  2222. Direction.AsVector := Parent.AbsoluteToLocal(v)
  2223. else
  2224. Direction.AsVector := v;
  2225. end;
  2226. function TGLBaseSceneObject.GetAbsoluteScale: TGLVector;
  2227. begin
  2228. Result.X := AbsoluteMatrixAsAddress^.X.X;
  2229. Result.Y := AbsoluteMatrixAsAddress^.Y.Y;
  2230. Result.Z := AbsoluteMatrixAsAddress^.Z.Z;
  2231. Result.W := 0;
  2232. end;
  2233. procedure TGLBaseSceneObject.SetAbsoluteScale(const Value: TGLVector);
  2234. begin
  2235. if Parent <> nil then
  2236. Scale.AsVector := Parent.AbsoluteToLocal(Value)
  2237. else
  2238. Scale.AsVector := Value;
  2239. end;
  2240. function TGLBaseSceneObject.GetAbsoluteUp: TGLVector;
  2241. begin
  2242. Result := VectorNormalize(AbsoluteMatrixAsAddress^.Y);
  2243. end;
  2244. procedure TGLBaseSceneObject.SetAbsoluteUp(const v: TGLVector);
  2245. begin
  2246. if Parent <> nil then
  2247. Up.AsVector := Parent.AbsoluteToLocal(v)
  2248. else
  2249. Up.AsVector := v;
  2250. end;
  2251. function TGLBaseSceneObject.AbsoluteRight: TGLVector;
  2252. begin
  2253. Result := VectorNormalize(AbsoluteMatrixAsAddress^.X);
  2254. end;
  2255. function TGLBaseSceneObject.AbsoluteLeft: TGLVector;
  2256. begin
  2257. Result := VectorNegate(AbsoluteRight);
  2258. end;
  2259. function TGLBaseSceneObject.GetAbsolutePosition: TGLVector;
  2260. begin
  2261. Result := AbsoluteMatrixAsAddress^.W;
  2262. end;
  2263. procedure TGLBaseSceneObject.SetAbsolutePosition(const v: TGLVector);
  2264. begin
  2265. if Assigned(Parent) then
  2266. Position.AsVector := Parent.AbsoluteToLocal(v)
  2267. else
  2268. Position.AsVector := v;
  2269. end;
  2270. function TGLBaseSceneObject.AbsolutePositionAsAddress: PGLVector;
  2271. begin
  2272. Result := @AbsoluteMatrixAsAddress^.W;
  2273. end;
  2274. function TGLBaseSceneObject.AbsoluteXVector: TGLVector;
  2275. begin
  2276. AbsoluteMatrixAsAddress;
  2277. SetVector(Result, PAffineVector(@FAbsoluteMatrix.X)^);
  2278. end;
  2279. function TGLBaseSceneObject.AbsoluteYVector: TGLVector;
  2280. begin
  2281. AbsoluteMatrixAsAddress;
  2282. SetVector(Result, PAffineVector(@FAbsoluteMatrix.Y)^);
  2283. end;
  2284. function TGLBaseSceneObject.AbsoluteZVector: TGLVector;
  2285. begin
  2286. AbsoluteMatrixAsAddress;
  2287. SetVector(Result, PAffineVector(@FAbsoluteMatrix.Z)^);
  2288. end;
  2289. function TGLBaseSceneObject.AbsoluteToLocal(const v: TGLVector): TGLVector;
  2290. begin
  2291. Result := VectorTransform(v, InvAbsoluteMatrixAsAddress^);
  2292. end;
  2293. function TGLBaseSceneObject.AbsoluteToLocal(const v: TAffineVector):
  2294. TAffineVector;
  2295. begin
  2296. Result := VectorTransform(v, InvAbsoluteMatrixAsAddress^);
  2297. end;
  2298. function TGLBaseSceneObject.LocalToAbsolute(const v: TGLVector): TGLVector;
  2299. begin
  2300. Result := VectorTransform(v, AbsoluteMatrixAsAddress^);
  2301. end;
  2302. function TGLBaseSceneObject.LocalToAbsolute(const v: TAffineVector):
  2303. TAffineVector;
  2304. begin
  2305. Result := VectorTransform(v, AbsoluteMatrixAsAddress^);
  2306. end;
  2307. function TGLBaseSceneObject.Right: TGLVector;
  2308. begin
  2309. Result := VectorCrossProduct(FDirection.AsVector, FUp.AsVector);
  2310. end;
  2311. function TGLBaseSceneObject.LeftVector: TGLVector;
  2312. begin
  2313. Result := VectorCrossProduct(FUp.AsVector, FDirection.AsVector);
  2314. end;
  2315. function TGLBaseSceneObject.BarycenterAbsolutePosition: TGLVector;
  2316. begin
  2317. Result := AbsolutePosition;
  2318. end;
  2319. function TGLBaseSceneObject.SqrDistanceTo(anObject: TGLBaseSceneObject): Single;
  2320. begin
  2321. if Assigned(anObject) then
  2322. Result := VectorDistance2(AbsolutePosition, anObject.AbsolutePosition)
  2323. else
  2324. Result := 0;
  2325. end;
  2326. function TGLBaseSceneObject.SqrDistanceTo(const pt: TGLVector): Single;
  2327. begin
  2328. Result := VectorDistance2(pt, AbsolutePosition);
  2329. end;
  2330. function TGLBaseSceneObject.DistanceTo(anObject: TGLBaseSceneObject): Single;
  2331. begin
  2332. if Assigned(anObject) then
  2333. Result := VectorDistance(AbsolutePosition, anObject.AbsolutePosition)
  2334. else
  2335. Result := 0;
  2336. end;
  2337. function TGLBaseSceneObject.DistanceTo(const pt: TGLVector): Single;
  2338. begin
  2339. Result := VectorDistance(AbsolutePosition, pt);
  2340. end;
  2341. function TGLBaseSceneObject.BarycenterSqrDistanceTo(const pt: TGLVector): Single;
  2342. var
  2343. d: TGLVector;
  2344. begin
  2345. d := BarycenterAbsolutePosition;
  2346. Result := VectorDistance2(d, pt);
  2347. end;
  2348. function TGLBaseSceneObject.AxisAlignedDimensions: TGLVector;
  2349. begin
  2350. Result := AxisAlignedDimensionsUnscaled();
  2351. ScaleVector(Result, Scale.AsVector);
  2352. end;
  2353. function TGLBaseSceneObject.AxisAlignedDimensionsUnscaled: TGLVector;
  2354. begin
  2355. Result.X := 0.5;
  2356. Result.Y := 0.5;
  2357. Result.Z := 0.5;
  2358. Result.W := 0;
  2359. end;
  2360. function TGLBaseSceneObject.AxisAlignedBoundingBox(const AIncludeChilden: Boolean): TAABB;
  2361. var
  2362. i: Integer;
  2363. aabb: TAABB;
  2364. child: TGLBaseSceneObject;
  2365. begin
  2366. SetAABB(Result, AxisAlignedDimensionsUnscaled);
  2367. // not tested for child objects
  2368. if AIncludeChilden then
  2369. begin
  2370. for i := 0 to FChildren.Count - 1 do
  2371. begin
  2372. child := TGLBaseSceneObject(FChildren.List^[i]);
  2373. aabb := child.AxisAlignedBoundingBoxUnscaled(AIncludeChilden);
  2374. AABBTransform(aabb, child.Matrix^);
  2375. AddAABB(Result, aabb);
  2376. end;
  2377. end;
  2378. AABBScale(Result, Scale.AsAffineVector);
  2379. end;
  2380. function TGLBaseSceneObject.AxisAlignedBoundingBoxUnscaled(
  2381. const AIncludeChilden: Boolean): TAABB;
  2382. var
  2383. i: Integer;
  2384. aabb: TAABB;
  2385. begin
  2386. SetAABB(Result, AxisAlignedDimensionsUnscaled);
  2387. //not tested for child objects
  2388. if AIncludeChilden then
  2389. begin
  2390. for i := 0 to FChildren.Count - 1 do
  2391. begin
  2392. aabb :=
  2393. TGLBaseSceneObject(FChildren.List^[i]).AxisAlignedBoundingBoxUnscaled(AIncludeChilden);
  2394. AABBTransform(aabb, TGLBaseSceneObject(FChildren.List^[i]).Matrix^);
  2395. AddAABB(Result, aabb);
  2396. end;
  2397. end;
  2398. end;
  2399. function TGLBaseSceneObject.AxisAlignedBoundingBoxAbsolute(
  2400. const AIncludeChilden: Boolean; const AUseBaryCenter: Boolean): TAABB;
  2401. begin
  2402. Result := BBToAABB(BoundingBoxAbsolute(AIncludeChilden, AUseBaryCenter));
  2403. end;
  2404. function TGLBaseSceneObject.BoundingBox(const AIncludeChilden: Boolean;
  2405. const AUseBaryCenter: Boolean): THmgBoundingBox;
  2406. var
  2407. CurrentBaryOffset: TGLVector;
  2408. begin
  2409. Result := AABBToBB(AxisAlignedBoundingBox(AIncludeChilden));
  2410. // code not tested...
  2411. if AUseBaryCenter then
  2412. begin
  2413. CurrentBaryOffset :=
  2414. VectorSubtract(AbsoluteToLocal(BarycenterAbsolutePosition),
  2415. Position.AsVector);
  2416. OffsetBBPoint(Result, CurrentBaryOffset);
  2417. end;
  2418. end;
  2419. function TGLBaseSceneObject.BoundingBoxUnscaled(
  2420. const AIncludeChilden: Boolean;
  2421. const AUseBaryCenter: Boolean): THmgBoundingBox;
  2422. var
  2423. CurrentBaryOffset: TGLVector;
  2424. begin
  2425. Result := AABBToBB(AxisAlignedBoundingBoxUnscaled(AIncludeChilden));
  2426. // code not tested...
  2427. if AUseBaryCenter then
  2428. begin
  2429. CurrentBaryOffset :=
  2430. VectorSubtract(AbsoluteToLocal(BarycenterAbsolutePosition),
  2431. Position.AsVector);
  2432. OffsetBBPoint(Result, CurrentBaryOffset);
  2433. end;
  2434. end;
  2435. function TGLBaseSceneObject.BoundingBoxAbsolute(const AIncludeChilden: Boolean;
  2436. const AUseBaryCenter: Boolean): THmgBoundingBox;
  2437. var
  2438. I: Integer;
  2439. CurrentBaryOffset: TGLVector;
  2440. begin
  2441. Result := BoundingBoxUnscaled(AIncludeChilden, False);
  2442. for I := 0 to 7 do
  2443. Result.BBox[I] := LocalToAbsolute(Result.BBox[I]);
  2444. if AUseBaryCenter then
  2445. begin
  2446. CurrentBaryOffset := VectorSubtract(BarycenterAbsolutePosition,
  2447. AbsolutePosition);
  2448. OffsetBBPoint(Result, CurrentBaryOffset);
  2449. end;
  2450. end;
  2451. function TGLBaseSceneObject.BoundingSphereRadius: Single;
  2452. begin
  2453. Result := VectorLength(AxisAlignedDimensions);
  2454. end;
  2455. function TGLBaseSceneObject.BoundingSphereRadiusUnscaled: Single;
  2456. begin
  2457. Result := VectorLength(AxisAlignedDimensionsUnscaled);
  2458. end;
  2459. function TGLBaseSceneObject.PointInObject(const point: TGLVector): Boolean;
  2460. var
  2461. localPt, dim: TGLVector;
  2462. begin
  2463. dim := AxisAlignedDimensions;
  2464. localPt := VectorTransform(point, InvAbsoluteMatrix);
  2465. Result := (Abs(localPt.X * Scale.X) <= dim.X) and
  2466. (Abs(localPt.Y * Scale.Y) <= dim.Y) and
  2467. (Abs(localPt.Z * Scale.Z) <= dim.Z);
  2468. end;
  2469. procedure TGLBaseSceneObject.CalculateBoundingBoxPersonalUnscaled(var ANewBoundingBox: THmgBoundingBox);
  2470. begin
  2471. // Using the standard method to get the local BB.
  2472. ANewBoundingBox := AABBToBB(AxisAlignedBoundingBoxUnscaled(False));
  2473. OffsetBBPoint(ANewBoundingBox, AbsoluteToLocal(BarycenterAbsolutePosition));
  2474. end;
  2475. function TGLBaseSceneObject.BoundingBoxPersonalUnscaledEx: THmgBoundingBox;
  2476. begin
  2477. if oBBcStructure in FBBChanges then
  2478. begin
  2479. CalculateBoundingBoxPersonalUnscaled(FBoundingBoxPersonalUnscaled);
  2480. Exclude(FBBChanges, oBBcStructure);
  2481. end;
  2482. Result := FBoundingBoxPersonalUnscaled;
  2483. end;
  2484. function TGLBaseSceneObject.AxisAlignedBoundingBoxAbsoluteEx: TAABB;
  2485. var
  2486. pBB: THmgBoundingBox;
  2487. begin
  2488. pBB := BoundingBoxIncludingChildrenEx;
  2489. BBTransform(pBB, AbsoluteMatrix);
  2490. Result := BBtoAABB(pBB);
  2491. end;
  2492. function TGLBaseSceneObject.AxisAlignedBoundingBoxEx: TAABB;
  2493. begin
  2494. Result := BBtoAABB(BoundingBoxIncludingChildrenEx);
  2495. AABBScale(Result, Scale.AsAffineVector);
  2496. end;
  2497. function TGLBaseSceneObject.BoundingBoxOfChildrenEx: THmgBoundingBox;
  2498. var
  2499. i: Integer;
  2500. pBB: THmgBoundingBox;
  2501. begin
  2502. if oBBcChild in FBBChanges then
  2503. begin
  2504. // Computing
  2505. FBoundingBoxOfChildren := NullBoundingBox;
  2506. for i := 0 to FChildren.count - 1 do
  2507. begin
  2508. pBB :=
  2509. TGLBaseSceneObject(FChildren.List^[i]).BoundingBoxIncludingChildrenEx;
  2510. if not BoundingBoxesAreEqual(@pBB, @NullBoundingBox) then
  2511. begin
  2512. // transformation with local matrix
  2513. BBTransform(pbb, TGLBaseSceneObject(FChildren.List^[i]).Matrix^);
  2514. if BoundingBoxesAreEqual(@FBoundingBoxOfChildren, @NullBoundingBox) then
  2515. FBoundingBoxOfChildren := pBB
  2516. else
  2517. AddBB(FBoundingBoxOfChildren, pBB);
  2518. end;
  2519. end;
  2520. exclude(FBBChanges, oBBcChild);
  2521. end;
  2522. result := FBoundingBoxOfChildren;
  2523. end;
  2524. function TGLBaseSceneObject.BoundingBoxIncludingChildrenEx: THmgBoundingBox;
  2525. var
  2526. pBB: THmgBoundingBox;
  2527. begin
  2528. if (oBBcStructure in FBBChanges) or (oBBcChild in FBBChanges) then
  2529. begin
  2530. pBB := BoundingBoxPersonalUnscaledEx;
  2531. if BoundingBoxesAreEqual(@pBB, @NullBoundingBox) then
  2532. FBoundingBoxIncludingChildren := BoundingBoxOfChildrenEx
  2533. else
  2534. begin
  2535. FBoundingBoxIncludingChildren := pBB;
  2536. pBB := BoundingBoxOfChildrenEx;
  2537. if not BoundingBoxesAreEqual(@pBB, @NullBoundingBox) then
  2538. AddBB(FBoundingBoxIncludingChildren, pBB);
  2539. end;
  2540. end;
  2541. Result := FBoundingBoxIncludingChildren;
  2542. end;
  2543. function TGLBaseSceneObject.RayCastIntersect(const rayStart, rayVector: TGLVector;
  2544. intersectPoint: PGLVector = nil;
  2545. intersectNormal: PGLVector = nil): Boolean;
  2546. var
  2547. i1, i2, absPos: TGLVector;
  2548. begin
  2549. SetVector(absPos, AbsolutePosition);
  2550. if RayCastSphereIntersect(rayStart, rayVector, absPos, BoundingSphereRadius,
  2551. i1, i2) > 0 then
  2552. begin
  2553. Result := True;
  2554. if Assigned(intersectPoint) then
  2555. SetVector(intersectPoint^, i1);
  2556. if Assigned(intersectNormal) then
  2557. begin
  2558. SubtractVector(i1, absPos);
  2559. NormalizeVector(i1);
  2560. SetVector(intersectNormal^, i1);
  2561. end;
  2562. end
  2563. else
  2564. Result := False;
  2565. end;
  2566. function TGLBaseSceneObject.GenerateSilhouette(const silhouetteParameters: TGLSilhouetteParameters): TGLSilhouette;
  2567. const
  2568. cNbSegments = 21;
  2569. var
  2570. i, j: Integer;
  2571. d, r, vr, s, c, angleFactor: Single;
  2572. sVec, tVec: TAffineVector;
  2573. begin
  2574. r := BoundingSphereRadiusUnscaled;
  2575. d := VectorLength(silhouetteParameters.SeenFrom);
  2576. // determine visible radius
  2577. case silhouetteParameters.Style of
  2578. ssOmni: vr := SphereVisibleRadius(d, r);
  2579. ssParallel: vr := r;
  2580. else
  2581. Assert(False);
  2582. vr := r;
  2583. end;
  2584. // determine a local orthonormal matrix, viewer-oriented
  2585. sVec := VectorCrossProduct(silhouetteParameters.SeenFrom, XVector);
  2586. if VectorLength(sVec) < 1e-3 then
  2587. sVec := VectorCrossProduct(silhouetteParameters.SeenFrom, YVector);
  2588. tVec := VectorCrossProduct(silhouetteParameters.SeenFrom, sVec);
  2589. NormalizeVector(sVec);
  2590. NormalizeVector(tVec);
  2591. // generate the silhouette (outline and capping)
  2592. Result := TGLSilhouette.Create;
  2593. angleFactor := (2 * PI) / cNbSegments;
  2594. vr := vr * 0.98;
  2595. for i := 0 to cNbSegments - 1 do
  2596. begin
  2597. SinCosine(i * angleFactor, vr, s, c);
  2598. Result.Vertices.AddPoint(VectorCombine(sVec, tVec, s, c));
  2599. j := (i + 1) mod cNbSegments;
  2600. Result.Indices.Add(i, j);
  2601. if silhouetteParameters.CappingRequired then
  2602. Result.CapIndices.Add(cNbSegments, i, j)
  2603. end;
  2604. if silhouetteParameters.CappingRequired then
  2605. Result.Vertices.Add(NullHmgPoint);
  2606. end;
  2607. procedure TGLBaseSceneObject.Assign(Source: TPersistent);
  2608. var
  2609. i: Integer;
  2610. child, newChild: TGLBaseSceneObject;
  2611. begin
  2612. if Assigned(Source) and (Source is TGLBaseSceneObject) then
  2613. begin
  2614. DestroyHandles;
  2615. FVisible := TGLBaseSceneObject(Source).FVisible;
  2616. TGLBaseSceneObject(Source).RebuildMatrix;
  2617. SetMatrix(TGLBaseSceneObject(Source).FLocalMatrix);
  2618. FShowAxes := TGLBaseSceneObject(Source).FShowAxes;
  2619. FObjectsSorting := TGLBaseSceneObject(Source).FObjectsSorting;
  2620. FVisibilityCulling := TGLBaseSceneObject(Source).FVisibilityCulling;
  2621. FRotation.Assign(TGLBaseSceneObject(Source).FRotation);
  2622. DeleteChildren;
  2623. if Assigned(Scene) then
  2624. Scene.BeginUpdate;
  2625. if Assigned(TGLBaseSceneObject(Source).FChildren) then
  2626. begin
  2627. for i := 0 to TGLBaseSceneObject(Source).FChildren.Count - 1 do
  2628. begin
  2629. child := TGLBaseSceneObject(TGLBaseSceneObject(Source).FChildren[i]);
  2630. newChild := AddNewChild(TGLSceneObjectClass(child.ClassType));
  2631. newChild.Assign(child);
  2632. end;
  2633. end;
  2634. if Assigned(Scene) then
  2635. Scene.EndUpdate;
  2636. OnProgress := TGLBaseSceneObject(Source).OnProgress;
  2637. if Assigned(TGLBaseSceneObject(Source).FBehaviours) then
  2638. Behaviours.Assign(TGLBaseSceneObject(Source).Behaviours)
  2639. else
  2640. FreeAndNil(FBehaviours);
  2641. if Assigned(TGLBaseSceneObject(Source).FEffects) then
  2642. Effects.Assign(TGLBaseSceneObject(Source).Effects)
  2643. else
  2644. FreeAndNil(FEffects);
  2645. Tag := TGLBaseSceneObject(Source).Tag;
  2646. FTagFloat := TGLBaseSceneObject(Source).FTagFloat;
  2647. end
  2648. else
  2649. inherited Assign(Source);
  2650. end;
  2651. function TGLBaseSceneObject.IsUpdating: Boolean;
  2652. begin
  2653. Result := (FUpdateCount <> 0) or (csReading in ComponentState);
  2654. end;
  2655. function TGLBaseSceneObject.GetParentComponent: TComponent;
  2656. begin
  2657. if FParent is TGLSceneRootObject then
  2658. Result := FScene
  2659. else
  2660. Result := FParent;
  2661. end;
  2662. function TGLBaseSceneObject.HasParent: Boolean;
  2663. begin
  2664. Result := assigned(FParent);
  2665. end;
  2666. procedure TGLBaseSceneObject.Lift(aDistance: Single);
  2667. begin
  2668. FPosition.AddScaledVector(aDistance, FUp.AsVector);
  2669. TransformationChanged;
  2670. end;
  2671. procedure TGLBaseSceneObject.Move(ADistance: Single);
  2672. begin
  2673. FPosition.AddScaledVector(ADistance, FDirection.AsVector);
  2674. TransformationChanged;
  2675. end;
  2676. procedure TGLBaseSceneObject.Slide(ADistance: Single);
  2677. begin
  2678. FPosition.AddScaledVector(ADistance, Right);
  2679. TransformationChanged;
  2680. end;
  2681. procedure TGLBaseSceneObject.ResetRotations;
  2682. begin
  2683. FillChar(FLocalMatrix, SizeOf(TGLMatrix), 0);
  2684. FLocalMatrix.X.X := Scale.DirectX;
  2685. FLocalMatrix.Y.Y := Scale.DirectY;
  2686. FLocalMatrix.Z.Z := Scale.DirectZ;
  2687. SetVector(FLocalMatrix.W, Position.DirectVector);
  2688. FRotation.DirectVector := NullHmgPoint;
  2689. FDirection.DirectVector := ZHmgVector;
  2690. FUp.DirectVector := YHmgVector;
  2691. TransformationChanged;
  2692. Exclude(FChanges, ocTransformation);
  2693. end;
  2694. procedure TGLBaseSceneObject.ResetAndPitchTurnRoll(const degX, degY, degZ: Single);
  2695. var
  2696. rotMatrix: TGLMatrix;
  2697. V: TGLVector;
  2698. begin
  2699. ResetRotations;
  2700. // set DegX (Pitch)
  2701. rotMatrix := CreateRotationMatrix(Right, degX * cPIdiv180);
  2702. V := VectorTransform(FUp.AsVector, rotMatrix);
  2703. NormalizeVector(V);
  2704. FUp.DirectVector := V;
  2705. V := VectorTransform(FDirection.AsVector, rotMatrix);
  2706. NormalizeVector(V);
  2707. FDirection.DirectVector := V;
  2708. FRotation.DirectX := NormalizeDegAngle(DegX);
  2709. // set DegY (Turn)
  2710. rotMatrix := CreateRotationMatrix(FUp.AsVector, degY * cPIdiv180);
  2711. V := VectorTransform(FUp.AsVector, rotMatrix);
  2712. NormalizeVector(V);
  2713. FUp.DirectVector := V;
  2714. V := VectorTransform(FDirection.AsVector, rotMatrix);
  2715. NormalizeVector(V);
  2716. FDirection.DirectVector := V;
  2717. FRotation.DirectY := NormalizeDegAngle(DegY);
  2718. // set DegZ (Roll)
  2719. rotMatrix := CreateRotationMatrix(Direction.AsVector, degZ * cPIdiv180);
  2720. V := VectorTransform(FUp.AsVector, rotMatrix);
  2721. NormalizeVector(V);
  2722. FUp.DirectVector := V;
  2723. V := VectorTransform(FDirection.AsVector, rotMatrix);
  2724. NormalizeVector(V);
  2725. FDirection.DirectVector := V;
  2726. FRotation.DirectZ := NormalizeDegAngle(DegZ);
  2727. TransformationChanged;
  2728. NotifyChange(self);
  2729. end;
  2730. procedure TGLBaseSceneObject.RotateAbsolute(const rx, ry, rz: Single);
  2731. var
  2732. resMat: TGLMatrix;
  2733. v: TAffineVector;
  2734. begin
  2735. resMat := Matrix^;
  2736. // No we build rotation matrices and use them to rotate the obj
  2737. if rx <> 0 then
  2738. begin
  2739. SetVector(v, AbsoluteToLocal(XVector));
  2740. resMat := MatrixMultiply(CreateRotationMatrix(v, -DegToRadian(rx)), resMat);
  2741. end;
  2742. if ry <> 0 then
  2743. begin
  2744. SetVector(v, AbsoluteToLocal(YVector));
  2745. resMat := MatrixMultiply(CreateRotationMatrix(v, -DegToRadian(ry)), resMat);
  2746. end;
  2747. if rz <> 0 then
  2748. begin
  2749. SetVector(v, AbsoluteToLocal(ZVector));
  2750. resMat := MatrixMultiply(CreateRotationMatrix(v, -DegToRadian(rz)), resMat);
  2751. end;
  2752. SetMatrix(resMat);
  2753. end;
  2754. procedure TGLBaseSceneObject.RotateAbsolute(const axis: TAffineVector; angle: Single);
  2755. var
  2756. v: TAffineVector;
  2757. begin
  2758. if angle <> 0 then
  2759. begin
  2760. SetVector(v, AbsoluteToLocal(axis));
  2761. SetMatrix(MatrixMultiply(CreateRotationMatrix(v, DegToRadian(angle)), Matrix^));
  2762. end;
  2763. end;
  2764. procedure TGLBaseSceneObject.Pitch(angle: Single);
  2765. var
  2766. r: Single;
  2767. rightVector: TGLVector;
  2768. begin
  2769. FIsCalculating := True;
  2770. try
  2771. angle := -DegToRad(angle);
  2772. rightVector := Right;
  2773. FUp.Rotate(rightVector, angle);
  2774. FUp.Normalize;
  2775. FDirection.Rotate(rightVector, angle);
  2776. FDirection.Normalize;
  2777. r := -RadToDeg(ArcTan2(FDirection.Y, VectorLength(FDirection.X, FDirection.Z)));
  2778. if FDirection.X < 0 then
  2779. if FDirection.Y < 0 then
  2780. r := 180 - r
  2781. else
  2782. r := -180 - r;
  2783. FRotation.X := r;
  2784. finally
  2785. FIsCalculating := False;
  2786. end;
  2787. TransformationChanged;
  2788. end;
  2789. procedure TGLBaseSceneObject.SetPitchAngle(AValue: Single);
  2790. var
  2791. diff: Single;
  2792. rotMatrix: TGLMatrix;
  2793. begin
  2794. if AValue <> FRotation.X then
  2795. begin
  2796. if not (csLoading in ComponentState) then
  2797. begin
  2798. FIsCalculating := True;
  2799. try
  2800. diff := DegToRadian(FRotation.X - AValue);
  2801. rotMatrix := CreateRotationMatrix(Right, diff);
  2802. FUp.DirectVector := VectorTransform(FUp.AsVector, rotMatrix);
  2803. FUp.Normalize;
  2804. FDirection.DirectVector := VectorTransform(FDirection.AsVector,
  2805. rotMatrix);
  2806. FDirection.Normalize;
  2807. TransformationChanged;
  2808. finally
  2809. FIsCalculating := False;
  2810. end;
  2811. end;
  2812. FRotation.DirectX := NormalizeDegAngle(AValue);
  2813. end;
  2814. end;
  2815. procedure TGLBaseSceneObject.Roll(angle: Single);
  2816. var
  2817. r: Single;
  2818. rightVector, directionVector: TGLVector;
  2819. begin
  2820. FIsCalculating := True;
  2821. try
  2822. angle := DegToRadian(angle);
  2823. directionVector := Direction.AsVector;
  2824. FUp.Rotate(directionVector, angle);
  2825. FUp.Normalize;
  2826. FDirection.Rotate(directionVector, angle);
  2827. FDirection.Normalize;
  2828. // calculate new rotation angle from vectors
  2829. rightVector := Right;
  2830. r := -RadToDeg(ArcTan2(rightVector.Y,
  2831. VectorLength(rightVector.X,
  2832. rightVector.Z)));
  2833. if rightVector.X < 0 then
  2834. if rightVector.Y < 0 then
  2835. r := 180 - r
  2836. else
  2837. r := -180 - r;
  2838. FRotation.Z := r;
  2839. finally
  2840. FIsCalculating := False;
  2841. end;
  2842. TransformationChanged;
  2843. end;
  2844. procedure TGLBaseSceneObject.SetRollAngle(AValue: Single);
  2845. var
  2846. diff: Single;
  2847. rotMatrix: TGLMatrix;
  2848. begin
  2849. if AValue <> FRotation.Z then
  2850. begin
  2851. if not (csLoading in ComponentState) then
  2852. begin
  2853. FIsCalculating := True;
  2854. try
  2855. diff := DegToRadian(FRotation.Z - AValue);
  2856. rotMatrix := CreateRotationMatrix(Direction.AsVector, diff);
  2857. FUp.DirectVector := VectorTransform(FUp.AsVector, rotMatrix);
  2858. FUp.Normalize;
  2859. FDirection.DirectVector := VectorTransform(FDirection.AsVector,
  2860. rotMatrix);
  2861. FDirection.Normalize;
  2862. TransformationChanged;
  2863. finally
  2864. FIsCalculating := False;
  2865. end;
  2866. end;
  2867. FRotation.DirectZ := NormalizeDegAngle(AValue);
  2868. end;
  2869. end;
  2870. procedure TGLBaseSceneObject.Turn(angle: Single);
  2871. var
  2872. r: Single;
  2873. upVector: TGLVector;
  2874. begin
  2875. FIsCalculating := True;
  2876. try
  2877. angle := DegToRadian(angle);
  2878. upVector := Up.AsVector;
  2879. FUp.Rotate(upVector, angle);
  2880. FUp.Normalize;
  2881. FDirection.Rotate(upVector, angle);
  2882. FDirection.Normalize;
  2883. r := -RadToDeg(ArcTan2(FDirection.X, VectorLength(FDirection.Y, FDirection.Z)));
  2884. if FDirection.X < 0 then
  2885. if FDirection.Y < 0 then
  2886. r := 180 - r
  2887. else
  2888. r := -180 - r;
  2889. FRotation.Y := r;
  2890. finally
  2891. FIsCalculating := False;
  2892. end;
  2893. TransformationChanged;
  2894. end;
  2895. procedure TGLBaseSceneObject.SetTurnAngle(AValue: Single);
  2896. var
  2897. diff: Single;
  2898. rotMatrix: TGLMatrix;
  2899. begin
  2900. if AValue <> FRotation.Y then
  2901. begin
  2902. if not (csLoading in ComponentState) then
  2903. begin
  2904. FIsCalculating := True;
  2905. try
  2906. diff := DegToRadian(FRotation.Y - AValue);
  2907. rotMatrix := CreateRotationMatrix(Up.AsVector, diff);
  2908. FUp.DirectVector := VectorTransform(FUp.AsVector, rotMatrix);
  2909. FUp.Normalize;
  2910. FDirection.DirectVector := VectorTransform(FDirection.AsVector, rotMatrix);
  2911. FDirection.Normalize;
  2912. TransformationChanged;
  2913. finally
  2914. FIsCalculating := False;
  2915. end;
  2916. end;
  2917. FRotation.DirectY := NormalizeDegAngle(AValue);
  2918. end;
  2919. end;
  2920. procedure TGLBaseSceneObject.SetRotation(aRotation: TGLCoordinates);
  2921. begin
  2922. FRotation.Assign(aRotation);
  2923. TransformationChanged;
  2924. end;
  2925. function TGLBaseSceneObject.GetPitchAngle: Single;
  2926. begin
  2927. Result := FRotation.X;
  2928. end;
  2929. function TGLBaseSceneObject.GetTurnAngle: Single;
  2930. begin
  2931. Result := FRotation.Y;
  2932. end;
  2933. function TGLBaseSceneObject.GetRollAngle: Single;
  2934. begin
  2935. Result := FRotation.Z;
  2936. end;
  2937. procedure TGLBaseSceneObject.PointTo(const ATargetObject: TGLBaseSceneObject; const AUpVector: TGLVector);
  2938. begin
  2939. PointTo(ATargetObject.AbsolutePosition, AUpVector);
  2940. end;
  2941. procedure TGLBaseSceneObject.PointTo(const AAbsolutePosition, AUpVector: TGLVector);
  2942. var
  2943. absDir, absRight, absUp: TGLVector;
  2944. begin
  2945. // first compute absolute attitude for pointing
  2946. absDir := VectorSubtract(AAbsolutePosition, Self.AbsolutePosition);
  2947. NormalizeVector(absDir);
  2948. absRight := VectorCrossProduct(absDir, AUpVector);
  2949. NormalizeVector(absRight);
  2950. absUp := VectorCrossProduct(absRight, absDir);
  2951. // convert absolute to local and adjust object
  2952. if Parent <> nil then
  2953. begin
  2954. FUp.AsVector := Parent.AbsoluteToLocal(absUp);
  2955. FDirection.AsVector := Parent.AbsoluteToLocal(absDir);
  2956. end
  2957. else
  2958. begin
  2959. FUp.AsVector := absUp;
  2960. FDirection.AsVector := absDir;
  2961. end;
  2962. TransformationChanged
  2963. end;
  2964. procedure TGLBaseSceneObject.SetShowAxes(AValue: Boolean);
  2965. begin
  2966. if FShowAxes <> AValue then
  2967. begin
  2968. FShowAxes := AValue;
  2969. NotifyChange(Self);
  2970. end;
  2971. end;
  2972. procedure TGLBaseSceneObject.SetScaling(AValue: TGLCoordinates);
  2973. begin
  2974. FScaling.Assign(AValue);
  2975. TransformationChanged;
  2976. end;
  2977. procedure TGLBaseSceneObject.SetName(const NewName: TComponentName);
  2978. begin
  2979. if Name <> NewName then
  2980. begin
  2981. inherited SetName(NewName);
  2982. if Assigned(vGLBaseSceneObjectNameChangeEvent) then
  2983. vGLBaseSceneObjectNameChangeEvent(Self);
  2984. end;
  2985. end;
  2986. procedure TGLBaseSceneObject.SetParent(const val: TGLBaseSceneObject);
  2987. begin
  2988. MoveTo(val);
  2989. end;
  2990. function TGLBaseSceneObject.GetIndex: Integer;
  2991. begin
  2992. if Assigned(FParent) then
  2993. Result := FParent.FChildren.IndexOf(Self)
  2994. else
  2995. Result := -1;
  2996. end;
  2997. function TGLBaseSceneObject.GetLocalMatrix: PGLMatrix;
  2998. begin
  2999. Result := @FLocalMatrix;
  3000. end;
  3001. procedure TGLBaseSceneObject.SetIndex(aValue: Integer);
  3002. var
  3003. LCount: Integer;
  3004. parentBackup: TGLBaseSceneObject;
  3005. begin
  3006. if Assigned(FParent) then
  3007. begin
  3008. if aValue < 0 then
  3009. aValue := 0;
  3010. LCount := FParent.Count;
  3011. if aValue >= LCount then
  3012. aValue := LCount - 1;
  3013. if aValue <> Index then
  3014. begin
  3015. if Assigned(FScene) then
  3016. FScene.BeginUpdate;
  3017. parentBackup := FParent;
  3018. parentBackup.Remove(Self, False);
  3019. parentBackup.Insert(AValue, Self);
  3020. if Assigned(FScene) then
  3021. FScene.EndUpdate;
  3022. end;
  3023. end;
  3024. end;
  3025. procedure TGLBaseSceneObject.SetParentComponent(Value: TComponent);
  3026. begin
  3027. inherited;
  3028. if Value = FParent then
  3029. Exit;
  3030. if Value is TGLScene then
  3031. SetParent(TGLScene(Value).Objects)
  3032. else if Value is TGLBaseSceneObject then
  3033. SetParent(TGLBaseSceneObject(Value))
  3034. else
  3035. SetParent(nil);
  3036. end;
  3037. procedure TGLBaseSceneObject.StructureChanged;
  3038. begin
  3039. if not (ocStructure in FChanges) then
  3040. begin
  3041. Include(FChanges, ocStructure);
  3042. NotifyChange(Self);
  3043. end
  3044. else if osDirectDraw in ObjectStyle then
  3045. NotifyChange(Self);
  3046. end;
  3047. procedure TGLBaseSceneObject.ClearStructureChanged;
  3048. begin
  3049. Exclude(FChanges, ocStructure);
  3050. SetBBChanges(BBChanges + [oBBcStructure]);
  3051. end;
  3052. procedure TGLBaseSceneObject.RecTransformationChanged;
  3053. var
  3054. i: Integer;
  3055. list: PGLPointerObjectList;
  3056. matSet: TGLObjectChanges;
  3057. begin
  3058. matSet := [ocAbsoluteMatrix, ocInvAbsoluteMatrix];
  3059. if matSet * FChanges <> matSet then
  3060. begin
  3061. FChanges := FChanges + matSet;
  3062. list := FChildren.List;
  3063. for i := 0 to FChildren.Count - 1 do
  3064. TGLBaseSceneObject(list^[i]).RecTransformationChanged;
  3065. end;
  3066. end;
  3067. procedure TGLBaseSceneObject.TransformationChanged;
  3068. begin
  3069. if not (ocTransformation in FChanges) then
  3070. begin
  3071. Include(FChanges, ocTransformation);
  3072. RecTransformationChanged;
  3073. if not (csLoading in ComponentState) then
  3074. NotifyChange(Self);
  3075. end;
  3076. end;
  3077. procedure TGLBaseSceneObject.MoveTo(newParent: TGLBaseSceneObject);
  3078. begin
  3079. if newParent = FParent then
  3080. Exit;
  3081. if Assigned(FParent) then
  3082. begin
  3083. FParent.Remove(Self, False);
  3084. FParent := nil;
  3085. end;
  3086. if Assigned(newParent) then
  3087. newParent.AddChild(Self)
  3088. else
  3089. SetScene(nil);
  3090. end;
  3091. procedure TGLBaseSceneObject.MoveUp;
  3092. begin
  3093. if Assigned(parent) then
  3094. parent.MoveChildUp(parent.IndexOfChild(Self));
  3095. end;
  3096. procedure TGLBaseSceneObject.MoveDown;
  3097. begin
  3098. if Assigned(parent) then
  3099. parent.MoveChildDown(parent.IndexOfChild(Self));
  3100. end;
  3101. procedure TGLBaseSceneObject.MoveFirst;
  3102. begin
  3103. if Assigned(parent) then
  3104. parent.MoveChildFirst(parent.IndexOfChild(Self));
  3105. end;
  3106. procedure TGLBaseSceneObject.MoveLast;
  3107. begin
  3108. if Assigned(parent) then
  3109. parent.MoveChildLast(parent.IndexOfChild(Self));
  3110. end;
  3111. procedure TGLBaseSceneObject.MoveObjectAround(anObject: TGLBaseSceneObject; pitchDelta, turnDelta: Single);
  3112. var
  3113. originalT2C, normalT2C, normalCameraRight, newPos: TGLVector;
  3114. pitchNow, dist: Single;
  3115. begin
  3116. if Assigned(anObject) then
  3117. begin
  3118. // normalT2C points away from the direction the camera is looking
  3119. originalT2C := VectorSubtract(AbsolutePosition, anObject.AbsolutePosition);
  3120. SetVector(normalT2C, originalT2C);
  3121. dist := VectorLength(normalT2C);
  3122. NormalizeVector(normalT2C);
  3123. // normalRight points to the camera's right
  3124. // the camera is pitching around this axis.
  3125. normalCameraRight := VectorCrossProduct(AbsoluteUp, normalT2C);
  3126. if VectorLength(normalCameraRight) < 0.001 then
  3127. SetVector(normalCameraRight, XVector) // arbitrary vector
  3128. else
  3129. NormalizeVector(normalCameraRight);
  3130. // calculate the current pitch.
  3131. // 0 is looking down and PI is looking up
  3132. pitchNow := ArcCos(VectorDotProduct(AbsoluteUp, normalT2C));
  3133. pitchNow := ClampValue(pitchNow + DegToRad(pitchDelta), 0 + 0.025, PI - 0.025);
  3134. // creates a new vector pointing up and then rotate it down
  3135. // into the new position
  3136. SetVector(normalT2C, AbsoluteUp);
  3137. RotateVector(normalT2C, normalCameraRight, -pitchNow);
  3138. RotateVector(normalT2C, AbsoluteUp, -DegToRadian(turnDelta));
  3139. ScaleVector(normalT2C, dist);
  3140. newPos := VectorAdd(AbsolutePosition, VectorSubtract(normalT2C,
  3141. originalT2C));
  3142. if Assigned(Parent) then
  3143. newPos := Parent.AbsoluteToLocal(newPos);
  3144. Position.AsVector := newPos;
  3145. end;
  3146. end;
  3147. procedure TGLBaseSceneObject.MoveObjectAllAround(anObject: TGLBaseSceneObject;
  3148. pitchDelta, turnDelta: Single);
  3149. var
  3150. upvector: TGLVector;
  3151. lookat : TGLVector;
  3152. rightvector : TGLVector;
  3153. tempvector: TGLVector;
  3154. T2C: TGLVector;
  3155. begin
  3156. // if camera has got a target
  3157. if Assigned(anObject) then
  3158. begin
  3159. //vector camera to target
  3160. lookat := VectorNormalize(VectorSubtract(anObject.AbsolutePosition, AbsolutePosition));
  3161. //camera up vector
  3162. upvector := VectorNormalize(AbsoluteUp);
  3163. // if upvector and lookat vector are colinear, it is necessary to compute new up vector
  3164. if Abs(VectorDotProduct(lookat,upvector))>0.99 then
  3165. begin
  3166. //X or Y vector use to generate upvector
  3167. SetVector(tempvector,1,0,0);
  3168. //if lookat is colinear to X vector use Y vector to generate upvector
  3169. if Abs(VectorDotProduct(tempvector,lookat))>0.99 then
  3170. begin
  3171. SetVector(tempvector,0,1,0);
  3172. end;
  3173. upvector:= VectorCrossProduct(tempvector,lookat);
  3174. rightvector := VectorCrossProduct(lookat,upvector);
  3175. end
  3176. else
  3177. begin
  3178. rightvector := VectorCrossProduct(lookat,upvector);
  3179. upvector:= VectorCrossProduct(rightvector,lookat);
  3180. end;
  3181. //now the up right and look at vector are orthogonal
  3182. // vector Target to camera
  3183. T2C:= VectorSubtract(AbsolutePosition,anObject.AbsolutePosition);
  3184. RotateVector(T2C,rightvector,DegToRadian(-PitchDelta));
  3185. RotateVector(T2C,upvector,DegToRadian(-TurnDelta));
  3186. AbsolutePosition := VectorAdd(anObject.AbsolutePosition, T2C);
  3187. //now update new up vector
  3188. RotateVector(upvector,rightvector,DegToRadian(-PitchDelta));
  3189. AbsoluteUp := upvector;
  3190. AbsoluteDirection := VectorSubtract(anObject.AbsolutePosition,AbsolutePosition);
  3191. end;
  3192. end;
  3193. procedure TGLBaseSceneObject.CoordinateChanged(Sender: TGLCustomCoordinates);
  3194. var
  3195. rightVector: TGLVector;
  3196. begin
  3197. if FIsCalculating then
  3198. Exit;
  3199. FIsCalculating := True;
  3200. try
  3201. if Sender = FDirection then
  3202. begin
  3203. if FDirection.VectorLength = 0 then
  3204. FDirection.DirectVector := ZHmgVector;
  3205. FDirection.Normalize;
  3206. // adjust up vector
  3207. rightVector := VectorCrossProduct(FDirection.AsVector, FUp.AsVector);
  3208. // Rightvector is zero if direction changed exactly by 90 degrees,
  3209. // in this case assume a default vector
  3210. if VectorLength(rightVector) < 1e-5 then
  3211. begin
  3212. rightVector := VectorCrossProduct(ZHmgVector, FUp.AsVector);
  3213. if VectorLength(rightVector) < 1e-5 then
  3214. rightVector := VectorCrossProduct(XHmgVector, FUp.AsVector);
  3215. end;
  3216. FUp.DirectVector := VectorCrossProduct(rightVector, FDirection.AsVector);
  3217. FUp.Normalize;
  3218. end
  3219. else if Sender = FUp then
  3220. begin
  3221. if FUp.VectorLength = 0 then
  3222. FUp.DirectVector := YHmgVector;
  3223. FUp.Normalize;
  3224. // adjust up vector
  3225. rightVector := VectorCrossProduct(FDirection.AsVector, FUp.AsVector);
  3226. // Rightvector is zero if direction changed exactly by 90 degrees,
  3227. // in this case assume a default vector
  3228. if VectorLength(rightVector) < 1e-5 then
  3229. begin
  3230. rightVector := VectorCrossProduct(ZHmgVector, FUp.AsVector);
  3231. if VectorLength(rightVector) < 1e-5 then
  3232. rightVector := VectorCrossProduct(XHmgVector, FUp.AsVector);
  3233. end;
  3234. FDirection.DirectVector := VectorCrossProduct(FUp.AsVector, RightVector);
  3235. FDirection.Normalize;
  3236. end;
  3237. TransformationChanged;
  3238. finally
  3239. FIsCalculating := False;
  3240. end;
  3241. end;
  3242. procedure TGLBaseSceneObject.DoProgress(const progressTime: TGLProgressTimes);
  3243. var
  3244. i: Integer;
  3245. begin
  3246. for i := FChildren.Count - 1 downto 0 do
  3247. TGLBaseSceneObject(FChildren.List^[i]).DoProgress(progressTime);
  3248. if Assigned(FBehaviours) then
  3249. FBehaviours.DoProgress(progressTime);
  3250. if Assigned(FEffects) then
  3251. FEffects.DoProgress(progressTime);
  3252. if Assigned(FOnProgress) then
  3253. with progressTime do
  3254. FOnProgress(Self, deltaTime, newTime);
  3255. end;
  3256. procedure TGLBaseSceneObject.Insert(aIndex: Integer; aChild: TGLBaseSceneObject);
  3257. begin
  3258. with FChildren do
  3259. begin
  3260. if Assigned(aChild.FParent) then
  3261. aChild.FParent.Remove(aChild, False);
  3262. Insert(aIndex, aChild);
  3263. end;
  3264. aChild.FParent := Self;
  3265. if AChild.FScene <> FScene then
  3266. AChild.DestroyHandles;
  3267. AChild.SetScene(FScene);
  3268. if Assigned(FScene) then
  3269. FScene.AddLights(aChild);
  3270. AChild.TransformationChanged;
  3271. aChild.DoOnAddedToParent;
  3272. end;
  3273. procedure TGLBaseSceneObject.Remove(aChild: TGLBaseSceneObject; keepChildren: Boolean);
  3274. var
  3275. I: Integer;
  3276. begin
  3277. if not Assigned(FChildren) then
  3278. Exit;
  3279. if aChild.Parent = Self then
  3280. begin
  3281. if Assigned(FScene) then
  3282. FScene.RemoveLights(aChild);
  3283. if aChild.Owner = Self then
  3284. RemoveComponent(aChild);
  3285. FChildren.Remove(aChild);
  3286. aChild.FParent := nil;
  3287. if keepChildren then
  3288. begin
  3289. BeginUpdate;
  3290. if aChild.Count <> 0 then
  3291. for I := aChild.Count - 1 downto 0 do
  3292. if not IsSubComponent(aChild.Children[I]) then
  3293. aChild.Children[I].MoveTo(Self);
  3294. EndUpdate;
  3295. end
  3296. else
  3297. NotifyChange(Self);
  3298. end;
  3299. end;
  3300. function TGLBaseSceneObject.IndexOfChild(aChild: TGLBaseSceneObject): Integer;
  3301. begin
  3302. Result := FChildren.IndexOf(aChild)
  3303. end;
  3304. function TGLBaseSceneObject.FindChild(const aName: string;
  3305. ownChildrenOnly: Boolean): TGLBaseSceneObject;
  3306. var
  3307. i: integer;
  3308. res: TGLBaseSceneObject;
  3309. begin
  3310. res := nil;
  3311. Result := nil;
  3312. for i := 0 to FChildren.Count - 1 do
  3313. begin
  3314. if CompareText(TGLBaseSceneObject(FChildren[i]).Name, aName) = 0 then
  3315. begin
  3316. res := TGLBaseSceneObject(FChildren[i]);
  3317. Break;
  3318. end;
  3319. end;
  3320. if not ownChildrenOnly then
  3321. begin
  3322. for i := 0 to FChildren.Count - 1 do
  3323. with TGLBaseSceneObject(FChildren[i]) do
  3324. begin
  3325. Result := FindChild(aName, ownChildrenOnly);
  3326. if Assigned(Result) then
  3327. Break;
  3328. end;
  3329. end;
  3330. if not Assigned(Result) then
  3331. Result := res;
  3332. end;
  3333. procedure TGLBaseSceneObject.ExchangeChildren(anIndex1, anIndex2: Integer);
  3334. begin
  3335. Assert(Assigned(FChildren), 'No children found!');
  3336. FChildren.Exchange(anIndex1, anIndex2);
  3337. NotifyChange(Self);
  3338. end;
  3339. procedure TGLBaseSceneObject.ExchangeChildrenSafe(anIndex1, anIndex2: Integer);
  3340. begin
  3341. Assert(Assigned(FChildren), 'No children found!');
  3342. if (anIndex1 < FChildren.Count) and (anIndex2 < FChildren.Count) and
  3343. (anIndex1 > -1) and (anIndex2 > -1) and (anIndex1 <> anIndex2) then
  3344. begin
  3345. FChildren.Exchange(anIndex1, anIndex2);
  3346. NotifyChange(Self);
  3347. end;
  3348. end;
  3349. procedure TGLBaseSceneObject.MoveChildUp(anIndex: Integer);
  3350. begin
  3351. Assert(Assigned(FChildren), 'No children found!');
  3352. if anIndex > 0 then
  3353. begin
  3354. FChildren.Exchange(anIndex, anIndex - 1);
  3355. NotifyChange(Self);
  3356. end;
  3357. end;
  3358. procedure TGLBaseSceneObject.MoveChildDown(anIndex: Integer);
  3359. begin
  3360. Assert(Assigned(FChildren), 'No children found!');
  3361. if anIndex < FChildren.Count - 1 then
  3362. begin
  3363. FChildren.Exchange(anIndex, anIndex + 1);
  3364. NotifyChange(Self);
  3365. end;
  3366. end;
  3367. procedure TGLBaseSceneObject.MoveChildFirst(anIndex: Integer);
  3368. begin
  3369. Assert(Assigned(FChildren), 'No children found!');
  3370. if anIndex <> 0 then
  3371. begin
  3372. FChildren.Move(anIndex, 0);
  3373. NotifyChange(Self);
  3374. end;
  3375. end;
  3376. procedure TGLBaseSceneObject.MoveChildLast(anIndex: Integer);
  3377. begin
  3378. Assert(Assigned(FChildren), 'No children found!');
  3379. if anIndex <> FChildren.Count - 1 then
  3380. begin
  3381. FChildren.Move(anIndex, FChildren.Count - 1);
  3382. NotifyChange(Self);
  3383. end;
  3384. end;
  3385. procedure TGLBaseSceneObject.Render(var ARci: TGLRenderContextInfo);
  3386. var
  3387. shouldRenderSelf, shouldRenderChildren: Boolean;
  3388. aabb: TAABB;
  3389. master: TObject;
  3390. begin
  3391. {$IFDEF USE_OPENGL_DEBUG}
  3392. if gl.GREMEDY_string_marker then
  3393. gl.StringMarkerGREMEDY(
  3394. Length(Name) + Length('.Render'), PChar(TString(Name + '.Render')));
  3395. {$ENDIF}
  3396. if (ARci.drawState = dsPicking) and not FPickable then
  3397. exit;
  3398. // visibility culling determination
  3399. if ARci.visibilityCulling in [vcObjectBased, vcHierarchical] then
  3400. begin
  3401. if ARci.visibilityCulling = vcObjectBased then
  3402. begin
  3403. shouldRenderSelf := (osNoVisibilityCulling in ObjectStyle)
  3404. or (not IsVolumeClipped(BarycenterAbsolutePosition,
  3405. BoundingSphereRadius,
  3406. ARci.rcci.frustum));
  3407. shouldRenderChildren := FChildren.Count>0;
  3408. end
  3409. else
  3410. begin // vcHierarchical
  3411. aabb := AxisAlignedBoundingBox;
  3412. shouldRenderSelf := (osNoVisibilityCulling in ObjectStyle)
  3413. or (not IsVolumeClipped(aabb.min, aabb.max, ARci.rcci.frustum));
  3414. shouldRenderChildren := shouldRenderSelf and Assigned(FChildren);
  3415. end;
  3416. if not (shouldRenderSelf or shouldRenderChildren) then
  3417. Exit;
  3418. end
  3419. else
  3420. begin
  3421. Assert(ARci.visibilityCulling in [vcNone, vcInherited], 'Unknown visibility culling option');
  3422. shouldRenderSelf := True;
  3423. shouldRenderChildren := FChildren.Count>0;
  3424. end;
  3425. // Prepare Matrix and PickList stuff
  3426. ARci.PipelineTransformation.Push;
  3427. if ocTransformation in FChanges then
  3428. RebuildMatrix;
  3429. if ARci.proxySubObject then
  3430. ARci.PipelineTransformation.SetModelMatrix(
  3431. MatrixMultiply(LocalMatrix^, ARci.PipelineTransformation.ModelMatrix^))
  3432. else
  3433. ARci.PipelineTransformation.SetModelMatrix(AbsoluteMatrix);
  3434. master := nil;
  3435. if ARci.drawState = dsPicking then
  3436. begin
  3437. if ARci.proxySubObject then
  3438. master := TGLSceneBuffer(ARci.buffer).FSelector.CurrentObject;
  3439. TGLSceneBuffer(ARci.buffer).FSelector.CurrentObject := Self;
  3440. end;
  3441. // Start rendering
  3442. if shouldRenderSelf then
  3443. begin
  3444. vCurrentRenderingObject := Self;
  3445. {$IFNDEF USE_OPTIMIZATIONS}
  3446. if FShowAxes then
  3447. DrawAxes(ARci, $CCCC);
  3448. {$ENDIF}
  3449. if Assigned(FEffects) and (FEffects.Count > 0) then
  3450. begin
  3451. ARci.PipelineTransformation.Push;
  3452. FEffects.RenderPreEffects(ARci);
  3453. ARci.PipelineTransformation.Pop;
  3454. ARci.PipelineTransformation.Push;
  3455. if osIgnoreDepthBuffer in ObjectStyle then
  3456. begin
  3457. ARci.GLStates.Disable(stDepthTest);
  3458. DoRender(ARci, True, shouldRenderChildren);
  3459. ARci.GLStates.Enable(stDepthTest);
  3460. end
  3461. else
  3462. DoRender(ARci, True, shouldRenderChildren);
  3463. FEffects.RenderPostEffects(ARci);
  3464. ARci.PipelineTransformation.Pop;
  3465. end
  3466. else
  3467. begin
  3468. if osIgnoreDepthBuffer in ObjectStyle then
  3469. begin
  3470. ARci.GLStates.Disable(stDepthTest);
  3471. DoRender(ARci, True, shouldRenderChildren);
  3472. ARci.GLStates.Enable(stDepthTest);
  3473. end
  3474. else
  3475. DoRender(ARci, True, shouldRenderChildren);
  3476. end;
  3477. vCurrentRenderingObject := nil;
  3478. end
  3479. else
  3480. begin
  3481. if (osIgnoreDepthBuffer in ObjectStyle) and
  3482. TGLSceneBuffer(ARCi.buffer).DepthTest then
  3483. begin
  3484. ARci.GLStates.Disable(stDepthTest);
  3485. DoRender(ARci, False, shouldRenderChildren);
  3486. ARci.GLStates.Enable(stDepthTest);
  3487. end
  3488. else
  3489. DoRender(ARci, False, shouldRenderChildren);
  3490. end;
  3491. // Pop Name & Matrix
  3492. if Assigned(master) then
  3493. TGLSceneBuffer(ARci.buffer).FSelector.CurrentObject := master;
  3494. ARci.PipelineTransformation.Pop;
  3495. end;
  3496. procedure TGLBaseSceneObject.DoRender(var ARci: TGLRenderContextInfo;
  3497. ARenderSelf, ARenderChildren: Boolean);
  3498. begin
  3499. // start rendering self
  3500. if ARenderSelf then
  3501. begin
  3502. if (osDirectDraw in ObjectStyle) or ARci.amalgamating then
  3503. BuildList(ARci)
  3504. else
  3505. ARci.GLStates.CallList(GetHandle(ARci));
  3506. end;
  3507. // start rendering children (if any)
  3508. if ARenderChildren then
  3509. Self.RenderChildren(0, Count - 1, ARci);
  3510. end;
  3511. procedure TGLBaseSceneObject.RenderChildren(firstChildIndex, lastChildIndex:
  3512. Integer;
  3513. var rci: TGLRenderContextInfo);
  3514. var
  3515. i: Integer;
  3516. plist: PGLPointerObjectList;
  3517. obj: TGLBaseSceneObject;
  3518. oldSorting: TGLObjectsSorting;
  3519. oldCulling: TGLVisibilityCulling;
  3520. begin
  3521. oldCulling := rci.visibilityCulling;
  3522. if Self.VisibilityCulling <> vcInherited then
  3523. rci.visibilityCulling := Self.VisibilityCulling;
  3524. if lastChildIndex = firstChildIndex then
  3525. begin
  3526. obj := TGLBaseSceneObject(FChildren.List^[firstChildIndex]);
  3527. if obj.Visible then
  3528. obj.Render(rci)
  3529. end
  3530. else if lastChildIndex > firstChildIndex then
  3531. begin
  3532. oldSorting := rci.objectsSorting;
  3533. if Self.ObjectsSorting <> osInherited then
  3534. rci.objectsSorting := Self.ObjectsSorting;
  3535. case rci.objectsSorting of
  3536. osNone:
  3537. begin
  3538. plist := FChildren.List;
  3539. for i := firstChildIndex to lastChildIndex do
  3540. begin
  3541. obj := TGLBaseSceneObject(plist^[i]);
  3542. if obj.Visible then
  3543. obj.Render(rci);
  3544. end;
  3545. end;
  3546. osRenderFarthestFirst, osRenderBlendedLast, osRenderNearestFirst:
  3547. begin
  3548. distList.Flush;
  3549. objList.Count := 0;
  3550. distList.GrowthDelta := lastChildIndex + 1; // no reallocations
  3551. objList.GrowthDelta := distList.GrowthDelta;
  3552. //try
  3553. case rci.objectsSorting of
  3554. osRenderBlendedLast:
  3555. // render opaque stuff
  3556. for i := firstChildIndex to lastChildIndex do
  3557. begin
  3558. obj := TGLBaseSceneObject(FChildren.List^[i]);
  3559. if obj.Visible then
  3560. begin
  3561. if not obj.Blended then
  3562. obj.Render(rci)
  3563. else
  3564. begin
  3565. objList.Add(obj);
  3566. distList.Add(1 +
  3567. obj.BarycenterSqrDistanceTo(rci.cameraPosition));
  3568. end;
  3569. end;
  3570. end;
  3571. osRenderFarthestFirst:
  3572. for i := firstChildIndex to lastChildIndex do
  3573. begin
  3574. obj := TGLBaseSceneObject(FChildren.List^[i]);
  3575. if obj.Visible then
  3576. begin
  3577. objList.Add(obj);
  3578. distList.Add(1 +
  3579. obj.BarycenterSqrDistanceTo(rci.cameraPosition));
  3580. end;
  3581. end;
  3582. osRenderNearestFirst:
  3583. for i := firstChildIndex to lastChildIndex do
  3584. begin
  3585. obj := TGLBaseSceneObject(FChildren.List^[i]);
  3586. if obj.Visible then
  3587. begin
  3588. objList.Add(obj);
  3589. distList.Add(-1 -
  3590. obj.BarycenterSqrDistanceTo(rci.cameraPosition));
  3591. end;
  3592. end;
  3593. else
  3594. Assert(False);
  3595. end;
  3596. if distList.Count > 0 then
  3597. begin
  3598. if distList.Count > 1 then
  3599. FastQuickSortLists(0, distList.Count - 1, distList, objList);
  3600. plist := objList.List;
  3601. for i := objList.Count - 1 downto 0 do
  3602. TGLBaseSceneObject(plist^[i]).Render(rci);
  3603. end;
  3604. //finally
  3605. //end;
  3606. end;
  3607. else
  3608. Assert(False);
  3609. end;
  3610. rci.objectsSorting := oldSorting;
  3611. end;
  3612. rci.visibilityCulling := oldCulling;
  3613. end;
  3614. procedure TGLBaseSceneObject.NotifyChange(Sender: TObject);
  3615. begin
  3616. if Assigned(FScene) and (not IsUpdating) then
  3617. FScene.NotifyChange(Self);
  3618. end;
  3619. function TGLBaseSceneObject.GetMatrix: PGLMatrix;
  3620. begin
  3621. RebuildMatrix;
  3622. Result := @FLocalMatrix;
  3623. end;
  3624. procedure TGLBaseSceneObject.SetMatrix(const aValue: TGLMatrix);
  3625. begin
  3626. FLocalMatrix := aValue;
  3627. FDirection.DirectVector := VectorNormalize(FLocalMatrix.Z);
  3628. FUp.DirectVector := VectorNormalize(FLocalMatrix.Y);
  3629. Scale.SetVector(VectorLength(FLocalMatrix.X),
  3630. VectorLength(FLocalMatrix.Y),
  3631. VectorLength(FLocalMatrix.Z), 0);
  3632. FPosition.DirectVector := FLocalMatrix.W;
  3633. TransformationChanged;
  3634. end;
  3635. procedure TGLBaseSceneObject.SetPosition(APosition: TGLCoordinates);
  3636. begin
  3637. FPosition.SetPoint(APosition.DirectX, APosition.DirectY, APosition.DirectZ);
  3638. end;
  3639. procedure TGLBaseSceneObject.SetDirection(AVector: TGLCoordinates);
  3640. begin
  3641. if not VectorIsNull(AVector.DirectVector) then
  3642. FDirection.SetVector(AVector.DirectX, AVector.DirectY, AVector.DirectZ);
  3643. end;
  3644. procedure TGLBaseSceneObject.SetUp(AVector: TGLCoordinates);
  3645. begin
  3646. if not VectorIsNull(AVector.DirectVector) then
  3647. FUp.SetVector(AVector.DirectX, AVector.DirectY, AVector.DirectZ);
  3648. end;
  3649. function TGLBaseSceneObject.GetVisible: Boolean;
  3650. begin
  3651. Result := FVisible;
  3652. end;
  3653. function TGLBaseSceneObject.GetPickable: Boolean;
  3654. begin
  3655. Result := FPickable;
  3656. end;
  3657. procedure TGLBaseSceneObject.SetVisible(aValue: Boolean);
  3658. begin
  3659. if FVisible <> aValue then
  3660. begin
  3661. FVisible := AValue;
  3662. NotifyChange(Self);
  3663. end;
  3664. end;
  3665. procedure TGLBaseSceneObject.SetPickable(aValue: Boolean);
  3666. begin
  3667. if FPickable <> aValue then
  3668. begin
  3669. FPickable := AValue;
  3670. NotifyChange(Self);
  3671. end;
  3672. end;
  3673. procedure TGLBaseSceneObject.SetObjectsSorting(const val: TGLObjectsSorting);
  3674. begin
  3675. if FObjectsSorting <> val then
  3676. begin
  3677. FObjectsSorting := val;
  3678. NotifyChange(Self);
  3679. end;
  3680. end;
  3681. procedure TGLBaseSceneObject.SetVisibilityCulling(const val:
  3682. TGLVisibilityCulling);
  3683. begin
  3684. if FVisibilityCulling <> val then
  3685. begin
  3686. FVisibilityCulling := val;
  3687. NotifyChange(Self);
  3688. end;
  3689. end;
  3690. procedure TGLBaseSceneObject.SetBehaviours(const val: TGLBehaviours);
  3691. begin
  3692. Behaviours.Assign(val);
  3693. end;
  3694. function TGLBaseSceneObject.GetBehaviours: TGLBehaviours;
  3695. begin
  3696. if not Assigned(FBehaviours) then
  3697. FBehaviours := TGLBehaviours.Create(Self);
  3698. Result := FBehaviours;
  3699. end;
  3700. procedure TGLBaseSceneObject.SetEffects(const val: TGLEffects);
  3701. begin
  3702. Effects.Assign(val);
  3703. end;
  3704. function TGLBaseSceneObject.GetEffects: TGLEffects;
  3705. begin
  3706. if not Assigned(FEffects) then
  3707. FEffects := TGLEffects.Create(Self);
  3708. Result := FEffects;
  3709. end;
  3710. procedure TGLBaseSceneObject.SetScene(const value: TGLScene);
  3711. var
  3712. i: Integer;
  3713. begin
  3714. if value <> FScene then
  3715. begin
  3716. // must be freed, the new scene may be using a non-compatible RC
  3717. if FScene <> nil then
  3718. DestroyHandles;
  3719. FScene := value;
  3720. // propagate for childs
  3721. if Assigned(FChildren) then
  3722. for i := 0 to FChildren.Count - 1 do
  3723. Children[I].SetScene(FScene);
  3724. end;
  3725. end;
  3726. procedure TGLBaseSceneObject.Translate(tx, ty, tz: Single);
  3727. begin
  3728. FPosition.Translate(AffineVectorMake(tx, ty, tz));
  3729. end;
  3730. function TGLBaseSceneObject.GetAbsoluteAffinePosition: TAffineVector;
  3731. var
  3732. temp: TGLVector;
  3733. begin
  3734. temp := GetAbsolutePosition;
  3735. Result := AffineVectorMake(temp.X, temp.Y, temp.Z);
  3736. end;
  3737. function TGLBaseSceneObject.GetAbsoluteAffineDirection: TAffineVector;
  3738. var
  3739. temp: TGLVector;
  3740. begin
  3741. temp := GetAbsoluteDirection;
  3742. Result := AffineVectorMake(temp.X, temp.Y, temp.Z);
  3743. end;
  3744. function TGLBaseSceneObject.GetAbsoluteAffineUp: TAffineVector;
  3745. var
  3746. temp: TGLVector;
  3747. begin
  3748. temp := GetAbsoluteUp;
  3749. Result := AffineVectorMake(temp.X, temp.Y, temp.Z);
  3750. end;
  3751. procedure TGLBaseSceneObject.SetAbsoluteAffinePosition(const Value:
  3752. TAffineVector);
  3753. begin
  3754. SetAbsolutePosition(VectorMake(Value, 1));
  3755. end;
  3756. procedure TGLBaseSceneObject.SetAbsoluteAffineUp(const v: TAffineVector);
  3757. begin
  3758. SetAbsoluteUp(VectorMake(v, 1));
  3759. end;
  3760. procedure TGLBaseSceneObject.SetAbsoluteAffineDirection(const v: TAffineVector);
  3761. begin
  3762. SetAbsoluteDirection(VectorMake(v, 1));
  3763. end;
  3764. function TGLBaseSceneObject.AffineLeftVector: TAffineVector;
  3765. begin
  3766. Result := AffineVectorMake(LeftVector);
  3767. end;
  3768. function TGLBaseSceneObject.AffineRight: TAffineVector;
  3769. begin
  3770. Result := AffineVectorMake(Right);
  3771. end;
  3772. function TGLBaseSceneObject.DistanceTo(const pt: TAffineVector): Single;
  3773. begin
  3774. Result := VectorDistance(AbsoluteAffinePosition, pt);
  3775. end;
  3776. function TGLBaseSceneObject.SqrDistanceTo(const pt: TAffineVector): Single;
  3777. begin
  3778. Result := VectorDistance2(AbsoluteAffinePosition, pt);
  3779. end;
  3780. procedure TGLBaseSceneObject.DoOnAddedToParent;
  3781. begin
  3782. if Assigned(FOnAddedToParent) then
  3783. FOnAddedToParent(self);
  3784. end;
  3785. function TGLBaseSceneObject.GetAbsoluteAffineScale: TAffineVector;
  3786. begin
  3787. Result := AffineVectorMake(GetAbsoluteScale);
  3788. end;
  3789. procedure TGLBaseSceneObject.SetAbsoluteAffineScale(
  3790. const Value: TAffineVector);
  3791. begin
  3792. SetAbsoluteScale(VectorMake(Value, GetAbsoluteScale.W));
  3793. end;
  3794. // ------------------
  3795. // ------------------ TGLBaseBehaviour ------------------
  3796. // ------------------
  3797. constructor TGLBaseBehaviour.Create(aOwner: TXCollection);
  3798. begin
  3799. inherited Create(aOwner);
  3800. // nothing more, yet
  3801. end;
  3802. destructor TGLBaseBehaviour.Destroy;
  3803. begin
  3804. // nothing more, yet
  3805. inherited Destroy;
  3806. end;
  3807. procedure TGLBaseBehaviour.SetName(const val: string);
  3808. begin
  3809. inherited SetName(val);
  3810. if Assigned(vGLBehaviourNameChangeEvent) then
  3811. vGLBehaviourNameChangeEvent(Self);
  3812. end;
  3813. procedure TGLBaseBehaviour.WriteToFiler(writer: TWriter);
  3814. begin
  3815. inherited;
  3816. with writer do
  3817. begin
  3818. WriteInteger(0); // Archive Version 0
  3819. // nothing more, yet
  3820. end;
  3821. end;
  3822. procedure TGLBaseBehaviour.ReadFromFiler(reader: TReader);
  3823. begin
  3824. if Owner.ArchiveVersion > 0 then
  3825. inherited;
  3826. with reader do
  3827. begin
  3828. if ReadInteger <> 0 then
  3829. Assert(False);
  3830. // nothing more, yet
  3831. end;
  3832. end;
  3833. function TGLBaseBehaviour.OwnerBaseSceneObject: TGLBaseSceneObject;
  3834. begin
  3835. Result := TGLBaseSceneObject(Owner.Owner);
  3836. end;
  3837. procedure TGLBaseBehaviour.DoProgress(const progressTime: TGLProgressTimes);
  3838. begin
  3839. // does nothing
  3840. end;
  3841. // ------------------
  3842. // ------------------ TGLBehaviours ------------------
  3843. // ------------------
  3844. constructor TGLBehaviours.Create(aOwner: TPersistent);
  3845. begin
  3846. Assert(aOwner is TGLBaseSceneObject);
  3847. inherited Create(aOwner);
  3848. end;
  3849. function TGLBehaviours.GetNamePath: string;
  3850. var
  3851. s: string;
  3852. begin
  3853. Result := ClassName;
  3854. if GetOwner = nil then
  3855. Exit;
  3856. s := GetOwner.GetNamePath;
  3857. if s = '' then
  3858. Exit;
  3859. Result := s + '.Behaviours';
  3860. end;
  3861. class function TGLBehaviours.ItemsClass: TXCollectionItemClass;
  3862. begin
  3863. Result := TGLBehaviour;
  3864. end;
  3865. function TGLBehaviours.GetBehaviour(index: Integer): TGLBehaviour;
  3866. begin
  3867. Result := TGLBehaviour(Items[index]);
  3868. end;
  3869. function TGLBehaviours.CanAdd(aClass: TXCollectionItemClass): Boolean;
  3870. begin
  3871. Result := (not aClass.InheritsFrom(TGLEffect)) and (inherited
  3872. CanAdd(aClass));
  3873. end;
  3874. procedure TGLBehaviours.DoProgress(const progressTimes: TGLProgressTimes);
  3875. var
  3876. i: Integer;
  3877. begin
  3878. for i := 0 to Count - 1 do
  3879. TGLBehaviour(Items[i]).DoProgress(progressTimes);
  3880. end;
  3881. // ------------------
  3882. // ------------------ TGLEffect ------------------
  3883. // ------------------
  3884. procedure TGLEffect.WriteToFiler(writer: TWriter);
  3885. begin
  3886. inherited;
  3887. with writer do
  3888. begin
  3889. WriteInteger(0); // Archive Version 0
  3890. // nothing more, yet
  3891. end;
  3892. end;
  3893. procedure TGLEffect.ReadFromFiler(reader: TReader);
  3894. begin
  3895. if Owner.ArchiveVersion > 0 then
  3896. inherited;
  3897. with reader do
  3898. begin
  3899. if ReadInteger <> 0 then
  3900. Assert(False);
  3901. // nothing more, yet
  3902. end;
  3903. end;
  3904. procedure TGLEffect.Render(var rci: TGLRenderContextInfo);
  3905. begin
  3906. // nothing here, this implem is just to avoid "abstract error"
  3907. end;
  3908. // ------------------
  3909. // ------------------ TGLEffects ------------------
  3910. // ------------------
  3911. constructor TGLEffects.Create(aOwner: TPersistent);
  3912. begin
  3913. Assert(aOwner is TGLBaseSceneObject);
  3914. inherited Create(aOwner);
  3915. end;
  3916. function TGLEffects.GetNamePath: string;
  3917. var
  3918. s: string;
  3919. begin
  3920. Result := ClassName;
  3921. if GetOwner = nil then
  3922. Exit;
  3923. s := GetOwner.GetNamePath;
  3924. if s = '' then
  3925. Exit;
  3926. Result := s + '.Effects';
  3927. end;
  3928. class function TGLEffects.ItemsClass: TXCollectionItemClass;
  3929. begin
  3930. Result := TGLEffect;
  3931. end;
  3932. function TGLEffects.GetEffect(index: Integer): TGLEffect;
  3933. begin
  3934. Result := TGLEffect(Items[index]);
  3935. end;
  3936. function TGLEffects.CanAdd(aClass: TXCollectionItemClass): Boolean;
  3937. begin
  3938. Result := (aClass.InheritsFrom(TGLEffect)) and (inherited
  3939. CanAdd(aClass));
  3940. end;
  3941. procedure TGLEffects.DoProgress(const progressTime: TGLProgressTimes);
  3942. var
  3943. i: Integer;
  3944. begin
  3945. for i := 0 to Count - 1 do
  3946. TGLEffect(Items[i]).DoProgress(progressTime);
  3947. end;
  3948. procedure TGLEffects.RenderPreEffects(var rci: TGLRenderContextInfo);
  3949. var
  3950. i: Integer;
  3951. effect: TGLEffect;
  3952. begin
  3953. for i := 0 to Count - 1 do
  3954. begin
  3955. effect := TGLEffect(Items[i]);
  3956. if effect is TGLObjectPreEffect then
  3957. effect.Render(rci);
  3958. end;
  3959. end;
  3960. procedure TGLEffects.RenderPostEffects(var rci: TGLRenderContextInfo);
  3961. var
  3962. i: Integer;
  3963. effect: TGLEffect;
  3964. begin
  3965. for i := 0 to Count - 1 do
  3966. begin
  3967. effect := TGLEffect(Items[i]);
  3968. if effect is TGLObjectPostEffect then
  3969. effect.Render(rci)
  3970. else if Assigned(rci.afterRenderEffects) and (effect is TGLObjectAfterEffect) then
  3971. rci.afterRenderEffects.Add(effect);
  3972. end;
  3973. end;
  3974. // ------------------
  3975. // ------------------ TGLCustomSceneObject ------------------
  3976. // ------------------
  3977. constructor TGLCustomSceneObject.Create(AOwner: TComponent);
  3978. begin
  3979. inherited Create(AOwner);
  3980. FMaterial := TGLMaterial.Create(Self);
  3981. end;
  3982. destructor TGLCustomSceneObject.Destroy;
  3983. begin
  3984. inherited Destroy;
  3985. FMaterial.Free;
  3986. end;
  3987. procedure TGLCustomSceneObject.Assign(Source: TPersistent);
  3988. begin
  3989. if Source is TGLCustomSceneObject then
  3990. begin
  3991. FMaterial.Assign(TGLCustomSceneObject(Source).FMaterial);
  3992. FHint := TGLCustomSceneObject(Source).FHint;
  3993. end;
  3994. inherited Assign(Source);
  3995. end;
  3996. function TGLCustomSceneObject.Blended: Boolean;
  3997. begin
  3998. Result := Material.Blended;
  3999. end;
  4000. procedure TGLCustomSceneObject.Loaded;
  4001. begin
  4002. inherited;
  4003. FMaterial.Loaded;
  4004. end;
  4005. procedure TGLCustomSceneObject.SetGLMaterial(AValue: TGLMaterial);
  4006. begin
  4007. FMaterial.Assign(AValue);
  4008. NotifyChange(Self);
  4009. end;
  4010. procedure TGLCustomSceneObject.DestroyHandle;
  4011. begin
  4012. inherited;
  4013. FMaterial.DestroyHandles;
  4014. end;
  4015. procedure TGLCustomSceneObject.DoRender(var ARci: TGLRenderContextInfo;
  4016. ARenderSelf, ARenderChildren: Boolean);
  4017. begin
  4018. // start rendering self
  4019. if ARenderSelf then
  4020. if ARci.ignoreMaterials then
  4021. if (osDirectDraw in ObjectStyle) or ARci.amalgamating then
  4022. BuildList(ARci)
  4023. else
  4024. ARci.GLStates.CallList(GetHandle(ARci))
  4025. else
  4026. begin
  4027. FMaterial.Apply(ARci);
  4028. repeat
  4029. if (osDirectDraw in ObjectStyle) or ARci.amalgamating then
  4030. BuildList(ARci)
  4031. else
  4032. ARci.GLStates.CallList(GetHandle(ARci));
  4033. until not FMaterial.UnApply(ARci);
  4034. end;
  4035. // start rendering children (if any)
  4036. if ARenderChildren then
  4037. Self.RenderChildren(0, Count - 1, ARci);
  4038. end;
  4039. // ------------------
  4040. // ------------------ TGLSceneRootObject ------------------
  4041. // ------------------
  4042. constructor TGLSceneRootObject.Create(AOwner: TComponent);
  4043. begin
  4044. Assert(AOwner is TGLScene);
  4045. inherited Create(AOwner);
  4046. ObjectStyle := ObjectStyle + [osDirectDraw];
  4047. FScene := TGLScene(AOwner);
  4048. end;
  4049. // ------------------
  4050. // ------------------ TGLCamera ------------------
  4051. // ------------------
  4052. constructor TGLCamera.Create(aOwner: TComponent);
  4053. begin
  4054. inherited Create(aOwner);
  4055. FFocalLength := 50;
  4056. FDepthOfView := 100;
  4057. FNearPlaneBias := 1;
  4058. FDirection.Initialize(VectorMake(0, 0, -1, 0));
  4059. FCameraStyle := csPerspective;
  4060. FSceneScale := 1;
  4061. FDesign := False;
  4062. FFOVY := -1;
  4063. FKeepFOVMode := ckmHorizontalFOV;
  4064. end;
  4065. destructor TGLCamera.Destroy;
  4066. begin
  4067. TargetObject := nil;
  4068. inherited;
  4069. end;
  4070. procedure TGLCamera.Assign(Source: TPersistent);
  4071. var
  4072. cam: TGLCamera;
  4073. dir: TGLVector;
  4074. begin
  4075. if Assigned(Source) then
  4076. begin
  4077. inherited Assign(Source);
  4078. if Source is TGLCamera then
  4079. begin
  4080. cam := TGLCamera(Source);
  4081. SetDepthOfView(cam.DepthOfView);
  4082. SetFocalLength(cam.FocalLength);
  4083. SetCameraStyle(cam.CameraStyle);
  4084. SetSceneScale(cam.SceneScale);
  4085. SetNearPlaneBias(cam.NearPlaneBias);
  4086. SetScene(cam.Scene);
  4087. SetKeepFOVMode(cam.FKeepFOVMode);
  4088. if Parent <> nil then
  4089. begin
  4090. SetTargetObject(cam.TargetObject);
  4091. end
  4092. else // Design camera
  4093. begin
  4094. Position.AsVector := cam.AbsolutePosition;
  4095. if Assigned(cam.TargetObject) then
  4096. begin
  4097. VectorSubtract(cam.TargetObject.AbsolutePosition, AbsolutePosition, dir);
  4098. NormalizeVector(dir);
  4099. Direction.AsVector := dir;
  4100. end;
  4101. end;
  4102. end;
  4103. end;
  4104. end;
  4105. function TGLCamera.AbsoluteVectorToTarget: TGLVector;
  4106. begin
  4107. if TargetObject <> nil then
  4108. begin
  4109. VectorSubtract(TargetObject.AbsolutePosition, AbsolutePosition, Result);
  4110. NormalizeVector(Result);
  4111. end
  4112. else
  4113. Result := AbsoluteDirection;
  4114. end;
  4115. function TGLCamera.AbsoluteRightVectorToTarget: TGLVector;
  4116. begin
  4117. if TargetObject <> nil then
  4118. begin
  4119. VectorSubtract(TargetObject.AbsolutePosition, AbsolutePosition, Result);
  4120. Result := VectorCrossProduct(Result, AbsoluteUp);
  4121. NormalizeVector(Result);
  4122. end
  4123. else
  4124. Result := AbsoluteRight;
  4125. end;
  4126. function TGLCamera.AbsoluteUpVectorToTarget: TGLVector;
  4127. begin
  4128. if TargetObject <> nil then
  4129. Result := VectorCrossProduct(AbsoluteRightVectorToTarget,
  4130. AbsoluteVectorToTarget)
  4131. else
  4132. Result := AbsoluteUp;
  4133. end;
  4134. procedure TGLCamera.Apply;
  4135. var
  4136. v, d, v2: TGLVector;
  4137. absPos: TGLVector;
  4138. LM, mat: TGLMatrix;
  4139. begin
  4140. if Assigned(FDeferredApply) then
  4141. FDeferredApply(Self)
  4142. else
  4143. begin
  4144. if Assigned(FTargetObject) then
  4145. begin
  4146. v := TargetObject.AbsolutePosition;
  4147. absPos := AbsolutePosition;
  4148. VectorSubtract(v, absPos, d);
  4149. NormalizeVector(d);
  4150. FLastDirection := d;
  4151. LM := CreateLookAtMatrix(absPos, v, Up.AsVector);
  4152. end
  4153. else
  4154. begin
  4155. if Assigned(Parent) then
  4156. mat := Parent.AbsoluteMatrix
  4157. else
  4158. mat := IdentityHmgMatrix;
  4159. absPos := AbsolutePosition;
  4160. v := VectorTransform(Direction.AsVector, mat);
  4161. FLastDirection := v;
  4162. d := VectorTransform(Up.AsVector, mat);
  4163. v2 := VectorAdd(absPos, v);
  4164. LM := CreateLookAtMatrix(absPos, v2, d);
  4165. end;
  4166. with CurrentGLContext.PipelineTransformation do
  4167. SetViewMatrix(MatrixMultiply(LM, ViewMatrix^));
  4168. ClearStructureChanged;
  4169. end;
  4170. end;
  4171. procedure TGLCamera.ApplyPerspective(const AViewport: TRectangle;
  4172. AWidth, AHeight: Integer; ADPI: Integer);
  4173. var
  4174. vLeft, vRight, vBottom, vTop, vFar: Single;
  4175. MaxDim, Ratio, f: Double;
  4176. xmax, ymax: Double;
  4177. mat: TGLMatrix;
  4178. const
  4179. cEpsilon: Single = 1e-4;
  4180. function IsPerspective(CamStyle: TGLCameraStyle): Boolean;
  4181. begin
  4182. Result := CamStyle in [csPerspective, csInfinitePerspective, csPerspectiveKeepFOV];
  4183. end;
  4184. begin
  4185. if (AWidth <= 0) or (AHeight <= 0) then
  4186. Exit;
  4187. if CameraStyle = csOrtho2D then
  4188. begin
  4189. vLeft := 0;
  4190. vRight := AWidth;
  4191. vBottom := 0;
  4192. vTop := AHeight;
  4193. FNearPlane := -1;
  4194. vFar := 1;
  4195. mat := CreateOrthoMatrix(vLeft, vRight, vBottom, vTop, FNearPlane, vFar);
  4196. with CurrentGLContext.PipelineTransformation do
  4197. SetProjectionMatrix(MatrixMultiply(mat, ProjectionMatrix^));
  4198. FViewPortRadius := VectorLength(AWidth, AHeight) / 2;
  4199. end
  4200. else if CameraStyle = csCustom then
  4201. begin
  4202. FViewPortRadius := VectorLength(AWidth, AHeight) / 2;
  4203. if Assigned(FOnCustomPerspective) then
  4204. FOnCustomPerspective(AViewport, AWidth, AHeight, ADPI, FViewPortRadius);
  4205. end
  4206. else
  4207. begin
  4208. // determine biggest dimension and resolution (height or width)
  4209. MaxDim := AWidth;
  4210. if AHeight > MaxDim then
  4211. MaxDim := AHeight;
  4212. // calculate near plane distance and extensions;
  4213. // Scene ratio is determined by the window ratio. The viewport is just a
  4214. // specific part of the entire window and has therefore no influence on the
  4215. // scene ratio. What we need to know, though, is the ratio between the window
  4216. // borders (left, top, right and bottom) and the viewport borders.
  4217. // Note: viewport.top is actually bottom, because the window (and viewport) origin
  4218. // in OGL is the lower left corner
  4219. if IsPerspective(CameraStyle) then
  4220. f := FNearPlaneBias / (AWidth * FSceneScale)
  4221. else
  4222. f := 100 * FNearPlaneBias / (focalLength * AWidth * FSceneScale);
  4223. // calculate window/viewport ratio for right extent
  4224. Ratio := (2 * AViewport.Width + 2 * AViewport.Left - AWidth) * f;
  4225. // calculate aspect ratio correct right value of the view frustum and take
  4226. // the window/viewport ratio also into account
  4227. vRight := Ratio * AWidth / (2 * MaxDim);
  4228. // the same goes here for the other three extents
  4229. // left extent:
  4230. Ratio := (AWidth - 2 * AViewport.Left) * f;
  4231. vLeft := -Ratio * AWidth / (2 * MaxDim);
  4232. if IsPerspective(CameraStyle) then
  4233. f := FNearPlaneBias / (AHeight * FSceneScale)
  4234. else
  4235. f := 100 * FNearPlaneBias / (focalLength * AHeight * FSceneScale);
  4236. // top extent (keep in mind the origin is left lower corner):
  4237. Ratio := (2 * AViewport.Height + 2 * AViewport.Top - AHeight) * f;
  4238. vTop := Ratio * AHeight / (2 * MaxDim);
  4239. // bottom extent:
  4240. Ratio := (AHeight - 2 * AViewport.Top) * f;
  4241. vBottom := -Ratio * AHeight / (2 * MaxDim);
  4242. FNearPlane := FFocalLength * 2 * ADPI / (25.4 * MaxDim) * FNearPlaneBias;
  4243. vFar := FNearPlane + FDepthOfView;
  4244. // finally create view frustum (perspective or orthogonal)
  4245. case CameraStyle of
  4246. csPerspective:
  4247. begin
  4248. mat := CreateMatrixFromFrustum(vLeft, vRight, vBottom, vTop, FNearPlane, vFar);
  4249. end;
  4250. csPerspectiveKeepFOV:
  4251. begin
  4252. if FFOVY < 0 then // Need Update FOV
  4253. begin
  4254. FFOVY := ArcTan2(vTop - vBottom, 2 * FNearPlane) * 2;
  4255. FFOVX := ArcTan2(vRight - vLeft, 2 * FNearPlane) * 2;
  4256. end;
  4257. case FKeepFOVMode of
  4258. ckmVerticalFOV:
  4259. begin
  4260. ymax := FNearPlane * Tan(FFOVY / 2);
  4261. xmax := ymax * AWidth / AHeight;
  4262. end;
  4263. ckmHorizontalFOV:
  4264. begin
  4265. xmax := FNearPlane * Tan(FFOVX / 2);
  4266. ymax := xmax * AHeight / AWidth;
  4267. end;
  4268. else
  4269. begin
  4270. xmax := 0;
  4271. ymax := 0;
  4272. Assert(False, 'Unknown keep camera angle mode');
  4273. end;
  4274. end;
  4275. mat := CreateMatrixFromFrustum(-xmax, xmax, -ymax, ymax, FNearPlane, vFar);
  4276. end;
  4277. csInfinitePerspective:
  4278. begin
  4279. mat := IdentityHmgMatrix;
  4280. mat.X.X := 2 * FNearPlane / (vRight - vLeft);
  4281. mat.Y.Y := 2 * FNearPlane / (vTop - vBottom);
  4282. mat.Z.X := (vRight + vLeft) / (vRight - vLeft);
  4283. mat.Z.Y := (vTop + vBottom) / (vTop - vBottom);
  4284. mat.Z.Z := cEpsilon - 1;
  4285. mat.Z.W := -1;
  4286. mat.W.Z := FNearPlane * (cEpsilon - 2);
  4287. mat.W.W := 0;
  4288. end;
  4289. csOrthogonal:
  4290. begin
  4291. mat := CreateOrthoMatrix(vLeft, vRight, vBottom, vTop, FNearPlane, vFar);
  4292. end;
  4293. else
  4294. Assert(False);
  4295. end;
  4296. with CurrentGLContext.PipelineTransformation do
  4297. SetProjectionMatrix(MatrixMultiply(mat, ProjectionMatrix^));
  4298. FViewPortRadius := VectorLength(vRight, vTop) / FNearPlane
  4299. end;
  4300. end;
  4301. //------------------------------------------------------------------------------
  4302. procedure TGLCamera.AutoLeveling(Factor: Single);
  4303. var
  4304. rightVector, rotAxis: TGLVector;
  4305. angle: Single;
  4306. begin
  4307. angle := RadToDeg(ArcCos(VectorDotProduct(FUp.AsVector, YVector)));
  4308. rotAxis := VectorCrossProduct(YHmgVector, FUp.AsVector);
  4309. if (angle > 1) and (VectorLength(rotAxis) > 0) then
  4310. begin
  4311. rightVector := VectorCrossProduct(FDirection.AsVector, FUp.AsVector);
  4312. FUp.Rotate(AffineVectorMake(rotAxis), Angle / (10 * Factor));
  4313. FUp.Normalize;
  4314. // adjust local coordinates
  4315. FDirection.DirectVector := VectorCrossProduct(FUp.AsVector, rightVector);
  4316. FRotation.Z := -RadToDeg(ArcTan2(RightVector.Y,
  4317. VectorLength(RightVector.X, RightVector.Z)));
  4318. end;
  4319. end;
  4320. //------------------------------------------------------------------------------
  4321. procedure TGLCamera.Notification(AComponent: TComponent; Operation: TOperation);
  4322. begin
  4323. if (Operation = opRemove) and (AComponent = FTargetObject) then
  4324. TargetObject := nil;
  4325. inherited;
  4326. end;
  4327. procedure TGLCamera.SetTargetObject(const val: TGLBaseSceneObject);
  4328. begin
  4329. if (FTargetObject <> val) then
  4330. begin
  4331. if Assigned(FTargetObject) then
  4332. FTargetObject.RemoveFreeNotification(Self);
  4333. FTargetObject := val;
  4334. if Assigned(FTargetObject) then
  4335. FTargetObject.FreeNotification(Self);
  4336. if not (csLoading in ComponentState) then
  4337. TransformationChanged;
  4338. end;
  4339. end;
  4340. procedure TGLCamera.Reset(aSceneBuffer: TGLSceneBuffer);
  4341. var
  4342. Extent: Single;
  4343. begin
  4344. FRotation.Z := 0;
  4345. FFocalLength := 50;
  4346. with aSceneBuffer do
  4347. begin
  4348. ApplyPerspective(FViewport, FViewport.Width, FViewport.Height, FRenderDPI);
  4349. FUp.DirectVector := YHmgVector;
  4350. if FViewport.Height < FViewport.Width then
  4351. Extent := FViewport.Height * 0.25
  4352. else
  4353. Extent := FViewport.Width * 0.25;
  4354. end;
  4355. FPosition.SetPoint(0, 0, FNearPlane * Extent);
  4356. FDirection.SetVector(0, 0, -1, 0);
  4357. TransformationChanged;
  4358. end;
  4359. procedure TGLCamera.ZoomAll(aSceneBuffer: TGLSceneBuffer);
  4360. var
  4361. extent: Single;
  4362. begin
  4363. with aSceneBuffer do
  4364. begin
  4365. if FViewport.Height < FViewport.Width then
  4366. Extent := FViewport.Height * 0.25
  4367. else
  4368. Extent := FViewport.Width * 0.25;
  4369. FPosition.DirectVector := NullHmgPoint;
  4370. Move(-FNearPlane * Extent);
  4371. // let the camera look at the scene center
  4372. FDirection.SetVector(-FPosition.X, -FPosition.Y, -FPosition.Z, 0);
  4373. end;
  4374. end;
  4375. procedure TGLCamera.RotateObject(obj: TGLBaseSceneObject; pitchDelta, turnDelta: Single;
  4376. rollDelta: Single = 0);
  4377. var
  4378. resMat: TGLMatrix;
  4379. vDir, vUp, vRight: TGLVector;
  4380. v: TAffineVector;
  4381. position1: TGLVector;
  4382. Scale1: TGLVector;
  4383. begin
  4384. // First we need to compute the actual camera's vectors, which may not be
  4385. // directly available if we're in "targeting" mode
  4386. vUp := AbsoluteUp;
  4387. if TargetObject <> nil then
  4388. begin
  4389. vDir := AbsoluteVectorToTarget;
  4390. vRight := VectorCrossProduct(vDir, vUp);
  4391. vUp := VectorCrossProduct(vRight, vDir);
  4392. end
  4393. else
  4394. begin
  4395. vDir := AbsoluteDirection;
  4396. vRight := VectorCrossProduct(vDir, vUp);
  4397. end;
  4398. //save scale & position info
  4399. Scale1 := obj.Scale.AsVector;
  4400. position1 := obj.Position.asVector;
  4401. resMat := obj.Matrix^;
  4402. //get rid of scaling & location info
  4403. NormalizeMatrix(resMat);
  4404. // Now we build rotation matrices and use them to rotate the obj
  4405. if rollDelta <> 0 then
  4406. begin
  4407. SetVector(v, obj.AbsoluteToLocal(vDir));
  4408. resMat := MatrixMultiply(CreateRotationMatrix(v, DegToRadian(rollDelta)), resMat);
  4409. end;
  4410. if turnDelta <> 0 then
  4411. begin
  4412. SetVector(v, obj.AbsoluteToLocal(vUp));
  4413. resMat := MatrixMultiply(CreateRotationMatrix(v, DegToRadian(turnDelta)), resMat);
  4414. end;
  4415. if pitchDelta <> 0 then
  4416. begin
  4417. SetVector(v, obj.AbsoluteToLocal(vRight));
  4418. resMat := MatrixMultiply(CreateRotationMatrix(v, DegToRadian(pitchDelta)), resMat);
  4419. end;
  4420. obj.SetMatrix(resMat);
  4421. //restore scaling & rotation info
  4422. obj.Scale.AsVector := Scale1;
  4423. obj.Position.AsVector := Position1;
  4424. end;
  4425. procedure TGLCamera.RotateTarget(pitchDelta, turnDelta: Single; rollDelta: Single = 0);
  4426. begin
  4427. if Assigned(FTargetObject) then
  4428. RotateObject(FTargetObject, pitchDelta, turnDelta, rollDelta)
  4429. end;
  4430. procedure TGLCamera.MoveAroundTarget(pitchDelta, turnDelta: Single);
  4431. begin
  4432. MoveObjectAround(FTargetObject, pitchDelta, turnDelta);
  4433. end;
  4434. procedure TGLCamera.MoveAllAroundTarget(pitchDelta, turnDelta :Single);
  4435. begin
  4436. MoveObjectAllAround(FTargetObject, pitchDelta, turnDelta);
  4437. end;
  4438. procedure TGLCamera.MoveInEyeSpace(forwardDistance, rightDistance, upDistance: Single);
  4439. var
  4440. trVector: TGLVector;
  4441. begin
  4442. trVector := AbsoluteEyeSpaceVector(forwardDistance, rightDistance, upDistance);
  4443. if Assigned(Parent) then
  4444. Position.Translate(Parent.AbsoluteToLocal(trVector))
  4445. else
  4446. Position.Translate(trVector);
  4447. end;
  4448. procedure TGLCamera.MoveTargetInEyeSpace(forwardDistance, rightDistance, upDistance: Single);
  4449. var
  4450. trVector: TGLVector;
  4451. begin
  4452. if TargetObject <> nil then
  4453. begin
  4454. trVector := AbsoluteEyeSpaceVector(forwardDistance, rightDistance,
  4455. upDistance);
  4456. TargetObject.Position.Translate(TargetObject.Parent.AbsoluteToLocal(trVector));
  4457. end;
  4458. end;
  4459. function TGLCamera.AbsoluteEyeSpaceVector(forwardDistance, rightDistance, upDistance: Single): TGLVector;
  4460. begin
  4461. Result := NullHmgVector;
  4462. if forwardDistance <> 0 then
  4463. CombineVector(Result, AbsoluteVectorToTarget, forwardDistance);
  4464. if rightDistance <> 0 then
  4465. CombineVector(Result, AbsoluteRightVectorToTarget, rightDistance);
  4466. if upDistance <> 0 then
  4467. CombineVector(Result, AbsoluteUpVectorToTarget, upDistance);
  4468. end;
  4469. procedure TGLCamera.AdjustDistanceToTarget(distanceRatio: Single);
  4470. var
  4471. vect: TGLVector;
  4472. begin
  4473. if Assigned(FTargetObject) then
  4474. begin
  4475. // calculate vector from target to camera in absolute coordinates
  4476. vect := VectorSubtract(AbsolutePosition, TargetObject.AbsolutePosition);
  4477. // ratio -> translation vector
  4478. ScaleVector(vect, -(1 - distanceRatio));
  4479. AddVector(vect, AbsolutePosition);
  4480. if Assigned(Parent) then
  4481. vect := Parent.AbsoluteToLocal(vect);
  4482. Position.AsVector := vect;
  4483. end;
  4484. end;
  4485. function TGLCamera.DistanceToTarget: Single;
  4486. var
  4487. vect: TGLVector;
  4488. begin
  4489. if Assigned(FTargetObject) then
  4490. begin
  4491. vect := VectorSubtract(AbsolutePosition, TargetObject.AbsolutePosition);
  4492. Result := VectorLength(vect);
  4493. end
  4494. else
  4495. Result := 1;
  4496. end;
  4497. function TGLCamera.ScreenDeltaToVector(deltaX, deltaY: Integer; ratio: Single;
  4498. const planeNormal: TGLVector): TGLVector;
  4499. var
  4500. screenY, screenX: TGLVector;
  4501. screenYoutOfPlaneComponent: Single;
  4502. begin
  4503. // calculate projection of direction vector on the plane
  4504. if Assigned(FTargetObject) then
  4505. screenY := VectorSubtract(TargetObject.AbsolutePosition, AbsolutePosition)
  4506. else
  4507. screenY := Direction.AsVector;
  4508. screenYoutOfPlaneComponent := VectorDotProduct(screenY, planeNormal);
  4509. screenY := VectorCombine(screenY, planeNormal, 1, -screenYoutOfPlaneComponent);
  4510. NormalizeVector(screenY);
  4511. // calc the screenX vector
  4512. screenX := VectorCrossProduct(screenY, planeNormal);
  4513. // and here, we're done
  4514. Result := VectorCombine(screenX, screenY, deltaX * ratio, deltaY * ratio);
  4515. end;
  4516. function TGLCamera.ScreenDeltaToVectorXY(deltaX, deltaY: Integer; ratio: Single): TGLVector;
  4517. var
  4518. screenY: TGLVector;
  4519. dxr, dyr, d: Single;
  4520. begin
  4521. // calculate projection of direction vector on the plane
  4522. if Assigned(FTargetObject) then
  4523. screenY := VectorSubtract(TargetObject.AbsolutePosition, AbsolutePosition)
  4524. else
  4525. screenY := Direction.AsVector;
  4526. d := VectorLength(screenY.X, screenY.Y);
  4527. if d <= 1e-10 then
  4528. d := ratio
  4529. else
  4530. d := ratio / d;
  4531. // and here, we're done
  4532. dxr := deltaX * d;
  4533. dyr := deltaY * d;
  4534. Result.X := screenY.Y * dxr + screenY.X * dyr;
  4535. Result.Y := screenY.Y * dyr - screenY.X * dxr;
  4536. Result.Z := 0;
  4537. Result.W := 0;
  4538. end;
  4539. function TGLCamera.ScreenDeltaToVectorXZ(deltaX, deltaY: Integer; ratio: Single): TGLVector;
  4540. var
  4541. screenY: TGLVector;
  4542. d, dxr, dzr: Single;
  4543. begin
  4544. // calculate the projection of direction vector on the plane
  4545. if Assigned(fTargetObject) then
  4546. screenY := VectorSubtract(TargetObject.AbsolutePosition, AbsolutePosition)
  4547. else
  4548. screenY := Direction.AsVector;
  4549. d := VectorLength(screenY.X, screenY.Z);
  4550. if d <= 1e-10 then
  4551. d := ratio
  4552. else
  4553. d := ratio / d;
  4554. dxr := deltaX * d;
  4555. dzr := deltaY * d;
  4556. Result.X := -screenY.Z * dxr + screenY.X * dzr;
  4557. Result.Y := 0;
  4558. Result.Z := screenY.Z * dzr + screenY.X * dxr;
  4559. Result.W := 0;
  4560. end;
  4561. function TGLCamera.ScreenDeltaToVectorYZ(deltaX, deltaY: Integer; ratio: Single): TGLVector;
  4562. var
  4563. screenY: TGLVector;
  4564. d, dyr, dzr: single;
  4565. begin
  4566. // calculate the projection of direction vector on the plane
  4567. if Assigned(fTargetObject) then
  4568. screenY := VectorSubtract(TargetObject.AbsolutePosition, AbsolutePosition)
  4569. else
  4570. screenY := Direction.AsVector;
  4571. d := VectorLength(screenY.Y, screenY.Z);
  4572. if d <= 1e-10 then
  4573. d := ratio
  4574. else
  4575. d := ratio / d;
  4576. dyr := deltaX * d;
  4577. dzr := deltaY * d;
  4578. Result.X := 0;
  4579. Result.Y := screenY.Z * dyr + screenY.Y * dzr;
  4580. Result.Z := screenY.Z * dzr - screenY.Y * dyr;
  4581. Result.W := 0;
  4582. end;
  4583. function TGLCamera.PointInFront(const point: TGLVector): boolean;
  4584. begin
  4585. result := PointIsInHalfSpace(point, AbsolutePosition, AbsoluteDirection);
  4586. end;
  4587. procedure TGLCamera.SetDepthOfView(AValue: Single);
  4588. begin
  4589. if FDepthOfView <> AValue then
  4590. begin
  4591. FDepthOfView := AValue;
  4592. FFOVY := - 1;
  4593. if not (csLoading in ComponentState) then
  4594. TransformationChanged;
  4595. end;
  4596. end;
  4597. procedure TGLCamera.SetFocalLength(AValue: Single);
  4598. begin
  4599. if AValue <= 0 then
  4600. AValue := 1;
  4601. if FFocalLength <> AValue then
  4602. begin
  4603. FFocalLength := AValue;
  4604. FFOVY := - 1;
  4605. if not (csLoading in ComponentState) then
  4606. TransformationChanged;
  4607. end;
  4608. end;
  4609. function TGLCamera.GetFieldOfView(const AViewportDimension: single): single;
  4610. begin
  4611. if FFocalLength = 0 then
  4612. result := 0
  4613. else
  4614. result := RadToDeg(2 * ArcTan2(AViewportDimension * 0.5, FFocalLength));
  4615. end;
  4616. procedure TGLCamera.SetFieldOfView(const AFieldOfView, AViewportDimension: single);
  4617. begin
  4618. FocalLength := AViewportDimension / (2 * Tan(DegToRadian(AFieldOfView / 2)));
  4619. end;
  4620. procedure TGLCamera.SetCameraStyle(const val: TGLCameraStyle);
  4621. begin
  4622. if FCameraStyle <> val then
  4623. begin
  4624. FCameraStyle := val;
  4625. FFOVY := -1;
  4626. NotifyChange(Self);
  4627. end;
  4628. end;
  4629. procedure TGLCamera.SetKeepFOVMode(const val: TGLCameraKeepFOVMode);
  4630. begin
  4631. if FKeepFOVMode <> val then
  4632. begin
  4633. FKeepFOVMode := val;
  4634. FFOVY := -1;
  4635. if FCameraStyle = csPerspectiveKeepFOV then
  4636. NotifyChange(Self);
  4637. end;
  4638. end;
  4639. procedure TGLCamera.SetSceneScale(value: Single);
  4640. begin
  4641. if value = 0 then
  4642. value := 1;
  4643. if FSceneScale <> value then
  4644. begin
  4645. FSceneScale := value;
  4646. FFOVY := -1;
  4647. NotifyChange(Self);
  4648. end;
  4649. end;
  4650. function TGLCamera.StoreSceneScale: Boolean;
  4651. begin
  4652. Result := (FSceneScale <> 1);
  4653. end;
  4654. procedure TGLCamera.SetNearPlaneBias(value: Single);
  4655. begin
  4656. if value <= 0 then
  4657. value := 1;
  4658. if FNearPlaneBias <> value then
  4659. begin
  4660. FNearPlaneBias := value;
  4661. FFOVY := -1;
  4662. NotifyChange(Self);
  4663. end;
  4664. end;
  4665. function TGLCamera.StoreNearPlaneBias: Boolean;
  4666. begin
  4667. Result := (FNearPlaneBias <> 1);
  4668. end;
  4669. procedure TGLCamera.DoRender(var ARci: TGLRenderContextInfo;
  4670. ARenderSelf, ARenderChildren: Boolean);
  4671. begin
  4672. if ARenderChildren and (Count > 0) then
  4673. Self.RenderChildren(0, Count - 1, ARci);
  4674. end;
  4675. function TGLCamera.RayCastIntersect(const rayStart, rayVector: TGLVector;
  4676. intersectPoint: PGLVector = nil;
  4677. intersectNormal: PGLVector = nil): Boolean;
  4678. begin
  4679. Result := False;
  4680. end;
  4681. // ------------------
  4682. // ------------------ TGLImmaterialSceneObject ------------------
  4683. // ------------------
  4684. procedure TGLImmaterialSceneObject.DoRender(var ARci: TGLRenderContextInfo;
  4685. ARenderSelf, ARenderChildren: Boolean);
  4686. begin
  4687. // start rendering self
  4688. if ARenderSelf then
  4689. begin
  4690. if (osDirectDraw in ObjectStyle) or ARci.amalgamating then
  4691. BuildList(ARci)
  4692. else
  4693. ARci.GLStates.CallList(GetHandle(ARci));
  4694. end;
  4695. // start rendering children (if any)
  4696. if ARenderChildren then
  4697. Self.RenderChildren(0, Count - 1, ARci);
  4698. end;
  4699. // ------------------
  4700. // ------------------ TGLCameraInvariantObject ------------------
  4701. // ------------------
  4702. constructor TGLCameraInvariantObject.Create(AOwner: TComponent);
  4703. begin
  4704. inherited;
  4705. FCamInvarianceMode := cimNone;
  4706. end;
  4707. procedure TGLCameraInvariantObject.Assign(Source: TPersistent);
  4708. begin
  4709. if Source is TGLCameraInvariantObject then
  4710. begin
  4711. FCamInvarianceMode := TGLCameraInvariantObject(Source).FCamInvarianceMode;
  4712. end;
  4713. inherited Assign(Source);
  4714. end;
  4715. procedure TGLCameraInvariantObject.DoRender(var ARci: TGLRenderContextInfo;
  4716. ARenderSelf, ARenderChildren: Boolean);
  4717. begin
  4718. if CamInvarianceMode <> cimNone then
  4719. with ARci.PipelineTransformation do
  4720. begin
  4721. Push;
  4722. //try
  4723. // prepare
  4724. case CamInvarianceMode of
  4725. cimPosition:
  4726. begin
  4727. SetViewMatrix(MatrixMultiply(
  4728. CreateTranslationMatrix(ARci.cameraPosition),
  4729. ARci.PipelineTransformation.ViewMatrix^));
  4730. end;
  4731. cimOrientation:
  4732. begin
  4733. // makes the coordinates system more 'intuitive' (Z+ forward)
  4734. SetViewMatrix(CreateScaleMatrix(Vector3fMake(1, -1, -1)))
  4735. end;
  4736. else
  4737. Assert(False);
  4738. end;
  4739. // Apply local transform
  4740. SetModelMatrix(LocalMatrix^);
  4741. if ARenderSelf then
  4742. begin
  4743. if (osDirectDraw in ObjectStyle) or ARci.amalgamating then
  4744. BuildList(ARci)
  4745. else
  4746. ARci.GLStates.CallList(GetHandle(ARci));
  4747. end;
  4748. if ARenderChildren then
  4749. Self.RenderChildren(0, Count - 1, ARci);
  4750. //finally
  4751. Pop;
  4752. //end;
  4753. end
  4754. else
  4755. inherited;
  4756. end;
  4757. procedure TGLCameraInvariantObject.SetCamInvarianceMode(const val:
  4758. TGLCameraInvarianceMode);
  4759. begin
  4760. if FCamInvarianceMode <> val then
  4761. begin
  4762. FCamInvarianceMode := val;
  4763. NotifyChange(Self);
  4764. end;
  4765. end;
  4766. // ------------------
  4767. // ------------------ TGLDirectOpenGL ------------------
  4768. // ------------------
  4769. constructor TGLDirectOpenGL.Create(AOwner: TComponent);
  4770. begin
  4771. inherited;
  4772. ObjectStyle := ObjectStyle + [osDirectDraw];
  4773. FBlend := False;
  4774. end;
  4775. procedure TGLDirectOpenGL.Assign(Source: TPersistent);
  4776. begin
  4777. if Source is TGLDirectOpenGL then
  4778. begin
  4779. UseBuildList := TGLDirectOpenGL(Source).UseBuildList;
  4780. FOnRender := TGLDirectOpenGL(Source).FOnRender;
  4781. FBlend := TGLDirectOpenGL(Source).Blend;
  4782. end;
  4783. inherited Assign(Source);
  4784. end;
  4785. procedure TGLDirectOpenGL.BuildList(var rci: TGLRenderContextInfo);
  4786. begin
  4787. if Assigned(FOnRender) then
  4788. begin
  4789. xgl.MapTexCoordToMain; // single texturing by default
  4790. OnRender(Self, rci);
  4791. end;
  4792. end;
  4793. function TGLDirectOpenGL.AxisAlignedDimensionsUnscaled: TGLVector;
  4794. begin
  4795. Result := NullHmgPoint;
  4796. end;
  4797. procedure TGLDirectOpenGL.SetUseBuildList(const val: Boolean);
  4798. begin
  4799. if val <> FUseBuildList then
  4800. begin
  4801. FUseBuildList := val;
  4802. if val then
  4803. ObjectStyle := ObjectStyle - [osDirectDraw]
  4804. else
  4805. ObjectStyle := ObjectStyle + [osDirectDraw];
  4806. end;
  4807. end;
  4808. function TGLDirectOpenGL.Blended: Boolean;
  4809. begin
  4810. Result := FBlend;
  4811. end;
  4812. procedure TGLDirectOpenGL.SetBlend(const val: Boolean);
  4813. begin
  4814. if val <> FBlend then
  4815. begin
  4816. FBlend := val;
  4817. StructureChanged;
  4818. end;
  4819. end;
  4820. // ------------------
  4821. // ------------------ TGLRenderPoint ------------------
  4822. // ------------------
  4823. constructor TGLRenderPoint.Create(AOwner: TComponent);
  4824. begin
  4825. inherited;
  4826. ObjectStyle := ObjectStyle + [osDirectDraw];
  4827. end;
  4828. destructor TGLRenderPoint.Destroy;
  4829. begin
  4830. Clear;
  4831. inherited;
  4832. end;
  4833. procedure TGLRenderPoint.BuildList(var rci: TGLRenderContextInfo);
  4834. var
  4835. i: Integer;
  4836. begin
  4837. for i := 0 to High(FCallBacks) do
  4838. FCallBacks[i](Self, rci);
  4839. end;
  4840. procedure TGLRenderPoint.RegisterCallBack(renderEvent: TGLDirectRenderEvent;
  4841. renderPointFreed: TNotifyEvent);
  4842. var
  4843. n: Integer;
  4844. begin
  4845. n := Length(FCallBacks);
  4846. SetLength(FCallBacks, n + 1);
  4847. SetLength(FFreeCallBacks, n + 1);
  4848. FCallBacks[n] := renderEvent;
  4849. FFreeCallBacks[n] := renderPointFreed;
  4850. end;
  4851. procedure TGLRenderPoint.UnRegisterCallBack(renderEvent: TGLDirectRenderEvent);
  4852. type
  4853. TEventContainer = record
  4854. event: TGLDirectRenderEvent;
  4855. end;
  4856. var
  4857. i, j, n: Integer;
  4858. refContainer, listContainer: TEventContainer;
  4859. begin
  4860. refContainer.event := renderEvent;
  4861. n := Length(FCallBacks);
  4862. for i := 0 to n - 1 do
  4863. begin
  4864. listContainer.event := FCallBacks[i];
  4865. if CompareMem(@listContainer, @refContainer, SizeOf(TEventContainer)) then
  4866. begin
  4867. for j := i + 1 to n - 1 do
  4868. begin
  4869. FCallBacks[j - 1] := FCallBacks[j];
  4870. FFreeCallBacks[j - 1] := FFreeCallBacks[j];
  4871. end;
  4872. SetLength(FCallBacks, n - 1);
  4873. SetLength(FFreeCallBacks, n - 1);
  4874. Break;
  4875. end;
  4876. end;
  4877. end;
  4878. procedure TGLRenderPoint.Clear;
  4879. begin
  4880. while Length(FCallBacks) > 0 do
  4881. begin
  4882. FFreeCallBacks[High(FCallBacks)](Self);
  4883. SetLength(FCallBacks, Length(FCallBacks) - 1);
  4884. end;
  4885. end;
  4886. // ------------------
  4887. // ------------------ TGLProxyObject ------------------
  4888. // ------------------
  4889. constructor TGLProxyObject.Create(AOwner: TComponent);
  4890. begin
  4891. inherited;
  4892. FProxyOptions := cDefaultProxyOptions;
  4893. end;
  4894. destructor TGLProxyObject.Destroy;
  4895. begin
  4896. SetMasterObject(nil);
  4897. inherited;
  4898. end;
  4899. procedure TGLProxyObject.Assign(Source: TPersistent);
  4900. begin
  4901. if Source is TGLProxyObject then
  4902. begin
  4903. SetMasterObject(TGLProxyObject(Source).MasterObject);
  4904. end;
  4905. inherited Assign(Source);
  4906. end;
  4907. procedure TGLProxyObject.DoRender(var ARci: TGLRenderContextInfo;
  4908. ARenderSelf, ARenderChildren: Boolean);
  4909. var
  4910. gotMaster, masterGotEffects, oldProxySubObject: Boolean;
  4911. begin
  4912. if FRendering then
  4913. Exit;
  4914. FRendering := True;
  4915. try
  4916. gotMaster := Assigned(FMasterObject);
  4917. masterGotEffects := gotMaster and (pooEffects in FProxyOptions)
  4918. and (FMasterObject.Effects.Count > 0);
  4919. if gotMaster then
  4920. begin
  4921. if pooObjects in FProxyOptions then
  4922. begin
  4923. oldProxySubObject := ARci.proxySubObject;
  4924. ARci.proxySubObject := True;
  4925. if pooTransformation in FProxyOptions then
  4926. with ARci.PipelineTransformation do
  4927. SetModelMatrix(MatrixMultiply(FMasterObject.Matrix^, ModelMatrix^));
  4928. FMasterObject.DoRender(ARci, ARenderSelf, (FMasterObject.Count > 0));
  4929. ARci.proxySubObject := oldProxySubObject;
  4930. end;
  4931. end;
  4932. // now render self stuff (our children, our effects, etc.)
  4933. if ARenderChildren and (Count > 0) then
  4934. Self.RenderChildren(0, Count - 1, ARci);
  4935. if masterGotEffects then
  4936. FMasterObject.Effects.RenderPostEffects(ARci);
  4937. finally
  4938. FRendering := False;
  4939. end;
  4940. ClearStructureChanged;
  4941. end;
  4942. function TGLProxyObject.AxisAlignedDimensions: TGLVector;
  4943. begin
  4944. If Assigned(FMasterObject) then
  4945. begin
  4946. Result := FMasterObject.AxisAlignedDimensionsUnscaled;
  4947. If (pooTransformation in ProxyOptions) then
  4948. ScaleVector(Result,FMasterObject.Scale.AsVector)
  4949. else
  4950. ScaleVector(Result, Scale.AsVector);
  4951. end
  4952. else
  4953. Result := inherited AxisAlignedDimensions;
  4954. end;
  4955. function TGLProxyObject.AxisAlignedDimensionsUnscaled: TGLVector;
  4956. begin
  4957. if Assigned(FMasterObject) then
  4958. begin
  4959. Result := FMasterObject.AxisAlignedDimensionsUnscaled;
  4960. end
  4961. else
  4962. Result := inherited AxisAlignedDimensionsUnscaled;
  4963. end;
  4964. function TGLProxyObject.BarycenterAbsolutePosition: TGLVector;
  4965. var
  4966. lAdjustVector: TGLVector;
  4967. begin
  4968. if Assigned(FMasterObject) then
  4969. begin
  4970. // Not entirely correct, but better than nothing...
  4971. lAdjustVector := VectorSubtract(FMasterObject.BarycenterAbsolutePosition,
  4972. FMasterObject.AbsolutePosition);
  4973. Position.AsVector := VectorAdd(Position.AsVector, lAdjustVector);
  4974. Result := AbsolutePosition;
  4975. Position.AsVector := VectorSubtract(Position.AsVector, lAdjustVector);
  4976. end
  4977. else
  4978. Result := inherited BarycenterAbsolutePosition;
  4979. end;
  4980. procedure TGLProxyObject.Notification(AComponent: TComponent; Operation: TOperation);
  4981. begin
  4982. if (Operation = opRemove) and (AComponent = FMasterObject) then
  4983. MasterObject := nil;
  4984. inherited;
  4985. end;
  4986. procedure TGLProxyObject.SetMasterObject(const val: TGLBaseSceneObject);
  4987. begin
  4988. if FMasterObject <> val then
  4989. begin
  4990. if Assigned(FMasterObject) then
  4991. FMasterObject.RemoveFreeNotification(Self);
  4992. FMasterObject := val;
  4993. if Assigned(FMasterObject) then
  4994. FMasterObject.FreeNotification(Self);
  4995. StructureChanged;
  4996. end;
  4997. end;
  4998. procedure TGLProxyObject.SetProxyOptions(const val: TGLProxyObjectOptions);
  4999. begin
  5000. if FProxyOptions <> val then
  5001. begin
  5002. FProxyOptions := val;
  5003. StructureChanged;
  5004. end;
  5005. end;
  5006. function TGLProxyObject.RayCastIntersect(const rayStart, rayVector: TGLVector;
  5007. intersectPoint: PGLVector = nil;
  5008. intersectNormal: PGLVector = nil): Boolean;
  5009. var
  5010. localRayStart, localRayVector: TGLVector;
  5011. begin
  5012. if Assigned(MasterObject) then
  5013. begin
  5014. SetVector(localRayStart, AbsoluteToLocal(rayStart));
  5015. SetVector(localRayStart, MasterObject.LocalToAbsolute(localRayStart));
  5016. SetVector(localRayVector, AbsoluteToLocal(rayVector));
  5017. SetVector(localRayVector, MasterObject.LocalToAbsolute(localRayVector));
  5018. NormalizeVector(localRayVector);
  5019. Result := MasterObject.RayCastIntersect(localRayStart, localRayVector,
  5020. intersectPoint, intersectNormal);
  5021. if Result then
  5022. begin
  5023. if Assigned(intersectPoint) then
  5024. begin
  5025. SetVector(intersectPoint^,
  5026. MasterObject.AbsoluteToLocal(intersectPoint^));
  5027. SetVector(intersectPoint^, LocalToAbsolute(intersectPoint^));
  5028. end;
  5029. if Assigned(intersectNormal) then
  5030. begin
  5031. SetVector(intersectNormal^,
  5032. MasterObject.AbsoluteToLocal(intersectNormal^));
  5033. SetVector(intersectNormal^, LocalToAbsolute(intersectNormal^));
  5034. end;
  5035. end;
  5036. end
  5037. else
  5038. Result := False;
  5039. end;
  5040. function TGLProxyObject.GenerateSilhouette(const silhouetteParameters:
  5041. TGLSilhouetteParameters): TGLSilhouette;
  5042. begin
  5043. if Assigned(MasterObject) then
  5044. Result := MasterObject.GenerateSilhouette(silhouetteParameters)
  5045. else
  5046. Result := nil;
  5047. end;
  5048. // ------------------
  5049. // ------------------ TGLLightSource ------------------
  5050. // ------------------
  5051. constructor TGLLightSource.Create(AOwner: TComponent);
  5052. begin
  5053. inherited Create(AOwner);
  5054. FShining := True;
  5055. FSpotDirection := TGLCoordinates.CreateInitialized(Self, VectorMake(0, 0, -1, 0), csVector);
  5056. FConstAttenuation := 1;
  5057. FLinearAttenuation := 0;
  5058. FQuadraticAttenuation := 0;
  5059. FSpotCutOff := 180;
  5060. FSpotExponent := 0;
  5061. FLightStyle := lsSpot;
  5062. FAmbient := TGLColor.Create(Self);
  5063. FDiffuse := TGLColor.Create(Self);
  5064. FDiffuse.Initialize(clrWhite);
  5065. FSpecular := TGLColor.Create(Self);
  5066. end;
  5067. destructor TGLLightSource.Destroy;
  5068. begin
  5069. FSpotDirection.Free;
  5070. FAmbient.Free;
  5071. FDiffuse.Free;
  5072. FSpecular.Free;
  5073. inherited Destroy;
  5074. end;
  5075. procedure TGLLightSource.DoRender(var ARci: TGLRenderContextInfo;
  5076. ARenderSelf, ARenderChildren: Boolean);
  5077. begin
  5078. if ARenderChildren and Assigned(FChildren) then
  5079. Self.RenderChildren(0, Count - 1, ARci);
  5080. end;
  5081. function TGLLightSource.RayCastIntersect(const rayStart, rayVector: TGLVector;
  5082. intersectPoint: PGLVector = nil;
  5083. intersectNormal: PGLVector = nil): Boolean;
  5084. begin
  5085. Result := False;
  5086. end;
  5087. procedure TGLLightSource.CoordinateChanged(Sender: TGLCustomCoordinates);
  5088. begin
  5089. inherited;
  5090. if Sender = FSpotDirection then
  5091. TransformationChanged;
  5092. end;
  5093. function TGLLightSource.GenerateSilhouette(const silhouetteParameters:
  5094. TGLSilhouetteParameters): TGLSilhouette;
  5095. begin
  5096. Result := nil;
  5097. end;
  5098. procedure TGLLightSource.SetShining(AValue: Boolean);
  5099. begin
  5100. if AValue <> FShining then
  5101. begin
  5102. FShining := AValue;
  5103. NotifyChange(Self);
  5104. end;
  5105. end;
  5106. procedure TGLLightSource.SetSpotDirection(AVector: TGLCoordinates);
  5107. begin
  5108. FSpotDirection.DirectVector := AVector.AsVector;
  5109. FSpotDirection.W := 0;
  5110. NotifyChange(Self);
  5111. end;
  5112. procedure TGLLightSource.SetSpotExponent(AValue: Single);
  5113. begin
  5114. if FSpotExponent <> AValue then
  5115. begin
  5116. FSpotExponent := AValue;
  5117. NotifyChange(Self);
  5118. end;
  5119. end;
  5120. procedure TGLLightSource.SetSpotCutOff(const val: Single);
  5121. begin
  5122. if FSpotCutOff <> val then
  5123. begin
  5124. if ((val >= 0) and (val <= 90)) or (val = 180) then
  5125. begin
  5126. FSpotCutOff := val;
  5127. NotifyChange(Self);
  5128. end;
  5129. end;
  5130. end;
  5131. procedure TGLLightSource.SetLightStyle(const val: TGLLightStyle);
  5132. begin
  5133. if FLightStyle <> val then
  5134. begin
  5135. FLightStyle := val;
  5136. NotifyChange(Self);
  5137. end;
  5138. end;
  5139. procedure TGLLightSource.SetAmbient(AValue: TGLColor);
  5140. begin
  5141. FAmbient.Color := AValue.Color;
  5142. NotifyChange(Self);
  5143. end;
  5144. procedure TGLLightSource.SetDiffuse(AValue: TGLColor);
  5145. begin
  5146. FDiffuse.Color := AValue.Color;
  5147. NotifyChange(Self);
  5148. end;
  5149. procedure TGLLightSource.SetSpecular(AValue: TGLColor);
  5150. begin
  5151. FSpecular.Color := AValue.Color;
  5152. NotifyChange(Self);
  5153. end;
  5154. procedure TGLLightSource.SetConstAttenuation(AValue: Single);
  5155. begin
  5156. if FConstAttenuation <> AValue then
  5157. begin
  5158. FConstAttenuation := AValue;
  5159. NotifyChange(Self);
  5160. end;
  5161. end;
  5162. procedure TGLLightSource.SetLinearAttenuation(AValue: Single);
  5163. begin
  5164. if FLinearAttenuation <> AValue then
  5165. begin
  5166. FLinearAttenuation := AValue;
  5167. NotifyChange(Self);
  5168. end;
  5169. end;
  5170. procedure TGLLightSource.SetQuadraticAttenuation(AValue: Single);
  5171. begin
  5172. if FQuadraticAttenuation <> AValue then
  5173. begin
  5174. FQuadraticAttenuation := AValue;
  5175. NotifyChange(Self);
  5176. end;
  5177. end;
  5178. function TGLLightSource.Attenuated: Boolean;
  5179. begin
  5180. Result := (LightStyle <> lsParallel)
  5181. and ((ConstAttenuation <> 1) or (LinearAttenuation <> 0) or
  5182. (QuadraticAttenuation <> 0));
  5183. end;
  5184. // ------------------
  5185. // ------------------ TGLScene ------------------
  5186. // ------------------
  5187. constructor TGLScene.Create(AOwner: TComponent);
  5188. begin
  5189. inherited;
  5190. // root creation
  5191. FCurrentBuffer := nil;
  5192. FObjects := TGLSceneRootObject.Create(Self);
  5193. FObjects.Name := 'ObjectRoot';
  5194. FLights := TGLPersistentObjectList.Create;
  5195. FObjectsSorting := osRenderBlendedLast;
  5196. FVisibilityCulling := vcNone;
  5197. // actual maximum number of lights is stored in TGLSceneViewer
  5198. FLights.Count := 8;
  5199. FInitializableObjects := TGLInitializableObjectList.Create;
  5200. end;
  5201. destructor TGLScene.Destroy;
  5202. begin
  5203. InitializableObjects.Free;
  5204. FObjects.DestroyHandles;
  5205. FLights.Free;
  5206. FObjects.Free;
  5207. if Assigned(FBuffers) then
  5208. FreeAndNil(FBuffers);
  5209. inherited Destroy;
  5210. end;
  5211. procedure TGLScene.AddLight(ALight: TGLLightSource);
  5212. var
  5213. i: Integer;
  5214. begin
  5215. for i := 0 to FLights.Count - 1 do
  5216. if FLights.List^[i] = nil then
  5217. begin
  5218. FLights.List^[i] := ALight;
  5219. ALight.FLightID := i;
  5220. Break;
  5221. end;
  5222. end;
  5223. procedure TGLScene.RemoveLight(ALight: TGLLightSource);
  5224. var
  5225. idx: Integer;
  5226. begin
  5227. idx := FLights.IndexOf(ALight);
  5228. if idx >= 0 then
  5229. FLights[idx] := nil;
  5230. end;
  5231. procedure TGLScene.AddLights(anObj: TGLBaseSceneObject);
  5232. var
  5233. i: Integer;
  5234. begin
  5235. if anObj is TGLLightSource then
  5236. AddLight(TGLLightSource(anObj));
  5237. for i := 0 to anObj.Count - 1 do
  5238. AddLights(anObj.Children[i]);
  5239. end;
  5240. procedure TGLScene.RemoveLights(anObj: TGLBaseSceneObject);
  5241. var
  5242. i: Integer;
  5243. begin
  5244. if anObj is TGLLightSource then
  5245. RemoveLight(TGLLightSource(anObj));
  5246. for i := 0 to anObj.Count - 1 do
  5247. RemoveLights(anObj.Children[i]);
  5248. end;
  5249. procedure TGLScene.ShutdownAllLights;
  5250. procedure DoShutdownLight(Obj: TGLBaseSceneObject);
  5251. var
  5252. i: integer;
  5253. begin
  5254. if Obj is TGLLightSource then
  5255. TGLLightSource(Obj).Shining := False;
  5256. for i := 0 to Obj.Count - 1 do
  5257. DoShutDownLight(Obj[i]);
  5258. end;
  5259. begin
  5260. DoShutdownLight(FObjects);
  5261. end;
  5262. procedure TGLScene.AddBuffer(aBuffer: TGLSceneBuffer);
  5263. begin
  5264. if not Assigned(FBuffers) then
  5265. FBuffers := TGLPersistentObjectList.Create;
  5266. if FBuffers.IndexOf(aBuffer) < 0 then
  5267. begin
  5268. FBuffers.Add(aBuffer);
  5269. if FBaseContext = nil then
  5270. FBaseContext := TGLSceneBuffer(FBuffers[0]).RenderingContext;
  5271. if (FBuffers.Count > 1) and Assigned(FBaseContext) then
  5272. aBuffer.RenderingContext.ShareLists(FBaseContext);
  5273. end;
  5274. end;
  5275. procedure TGLScene.RemoveBuffer(aBuffer: TGLSceneBuffer);
  5276. var
  5277. i: Integer;
  5278. begin
  5279. if Assigned(FBuffers) then
  5280. begin
  5281. i := FBuffers.IndexOf(aBuffer);
  5282. if i >= 0 then
  5283. begin
  5284. if FBuffers.Count = 1 then
  5285. begin
  5286. FreeAndNil(FBuffers);
  5287. FBaseContext := nil;
  5288. end
  5289. else
  5290. begin
  5291. FBuffers.Delete(i);
  5292. FBaseContext := TGLSceneBuffer(FBuffers[0]).RenderingContext;
  5293. end;
  5294. end;
  5295. end;
  5296. end;
  5297. procedure TGLScene.GetChildren(AProc: TGetChildProc; Root: TComponent);
  5298. begin
  5299. FObjects.GetChildren(AProc, Root);
  5300. end;
  5301. procedure TGLScene.SetChildOrder(AChild: TComponent; Order: Integer);
  5302. begin
  5303. (AChild as TGLBaseSceneObject).Index := Order;
  5304. end;
  5305. function TGLScene.IsUpdating: Boolean;
  5306. begin
  5307. Result := (FUpdateCount <> 0) or (csLoading in ComponentState) or (csDestroying in ComponentState);
  5308. end;
  5309. procedure TGLScene.BeginUpdate;
  5310. begin
  5311. Inc(FUpdateCount);
  5312. end;
  5313. procedure TGLScene.EndUpdate;
  5314. begin
  5315. Assert(FUpdateCount > 0);
  5316. Dec(FUpdateCount);
  5317. if FUpdateCount = 0 then
  5318. NotifyChange(Self);
  5319. end;
  5320. procedure TGLScene.SetObjectsSorting(const val: TGLObjectsSorting);
  5321. begin
  5322. if FObjectsSorting <> val then
  5323. begin
  5324. if val = osInherited then
  5325. FObjectsSorting := osRenderBlendedLast
  5326. else
  5327. FObjectsSorting := val;
  5328. NotifyChange(Self);
  5329. end;
  5330. end;
  5331. procedure TGLScene.SetVisibilityCulling(const val: TGLVisibilityCulling);
  5332. begin
  5333. if FVisibilityCulling <> val then
  5334. begin
  5335. if val = vcInherited then
  5336. FVisibilityCulling := vcNone
  5337. else
  5338. FVisibilityCulling := val;
  5339. NotifyChange(Self);
  5340. end;
  5341. end;
  5342. procedure TGLScene.ReadState(Reader: TReader);
  5343. var
  5344. SaveRoot: TComponent;
  5345. begin
  5346. SaveRoot := Reader.Root;
  5347. try
  5348. if Owner <> nil then
  5349. Reader.Root := Owner;
  5350. inherited;
  5351. finally
  5352. Reader.Root := SaveRoot;
  5353. end;
  5354. end;
  5355. procedure TGLScene.Progress(const deltaTime, newTime: Double);
  5356. var
  5357. pt: TGLProgressTimes;
  5358. begin
  5359. pt.deltaTime := deltaTime;
  5360. pt.newTime := newTime;
  5361. FCurrentDeltaTime := deltaTime;
  5362. if Assigned(FOnBeforeProgress) then
  5363. FOnBeforeProgress(Self, deltaTime, newTime);
  5364. FObjects.DoProgress(pt);
  5365. if Assigned(FOnProgress) then
  5366. FOnProgress(Self, deltaTime, newTime);
  5367. end;
  5368. procedure TGLScene.SaveToFile(const fileName: string);
  5369. var
  5370. stream: TStream;
  5371. begin
  5372. stream := TFileStream.Create(fileName, fmCreate);
  5373. try
  5374. SaveToStream(stream);
  5375. finally
  5376. stream.Free;
  5377. end;
  5378. end;
  5379. procedure TGLScene.LoadFromFile(const fileName: string);
  5380. procedure CheckResFileStream(Stream: TStream);
  5381. var
  5382. N: Integer;
  5383. B: Byte;
  5384. begin
  5385. N := Stream.Position;
  5386. Stream.Read(B, Sizeof(B));
  5387. Stream.Position := N;
  5388. if B = $FF then
  5389. Stream.ReadResHeader;
  5390. end;
  5391. var
  5392. stream: TStream;
  5393. begin
  5394. stream := TFileStream.Create(fileName, fmOpenRead);
  5395. try
  5396. CheckResFileStream(stream);
  5397. LoadFromStream(stream);
  5398. finally
  5399. stream.Free;
  5400. end;
  5401. end;
  5402. procedure TGLScene.SaveToTextFile(const fileName: string);
  5403. var
  5404. mem: TMemoryStream;
  5405. fil: TStream;
  5406. begin
  5407. mem := TMemoryStream.Create;
  5408. fil := TFileStream.Create(fileName, fmCreate);
  5409. try
  5410. SaveToStream(mem);
  5411. mem.Position := 0;
  5412. ObjectBinaryToText(mem, fil);
  5413. finally
  5414. fil.Free;
  5415. mem.Free;
  5416. end;
  5417. end;
  5418. procedure TGLScene.LoadFromTextFile(const fileName: string);
  5419. var
  5420. Mem: TMemoryStream;
  5421. Fil: TStream;
  5422. begin
  5423. Mem := TMemoryStream.Create;
  5424. Fil := TFileStream.Create(fileName, fmOpenRead);
  5425. try
  5426. ObjectTextToBinary(Fil, Mem);
  5427. Mem.Position := 0;
  5428. LoadFromStream(Mem);
  5429. finally
  5430. Fil.Free;
  5431. Mem.Free;
  5432. end;
  5433. end;
  5434. procedure TGLScene.LoadFromStream(aStream: TStream);
  5435. var
  5436. fixups: TStringList;
  5437. i: Integer;
  5438. obj: TGLBaseSceneObject;
  5439. begin
  5440. Fixups := TStringList.Create;
  5441. try
  5442. if Assigned(FBuffers) then
  5443. begin
  5444. for i := 0 to FBuffers.Count - 1 do
  5445. Fixups.AddObject(TGLSceneBuffer(FBuffers[i]).Camera.Name, FBuffers[i]);
  5446. end;
  5447. ShutdownAllLights;
  5448. // will remove Viewer from FBuffers
  5449. Objects.DeleteChildren;
  5450. aStream.ReadComponent(Self);
  5451. for i := 0 to Fixups.Count - 1 do
  5452. begin
  5453. obj := FindSceneObject(fixups[I]);
  5454. if obj is TGLCamera then
  5455. TGLSceneBuffer(Fixups.Objects[i]).Camera := TGLCamera(obj)
  5456. else { can assign default camera (if existing, of course) instead }
  5457. ;
  5458. end;
  5459. finally
  5460. Fixups.Free;
  5461. end;
  5462. end;
  5463. procedure TGLScene.SaveToStream(aStream: TStream);
  5464. begin
  5465. aStream.WriteComponent(Self);
  5466. end;
  5467. function TGLScene.FindSceneObject(const AName: string): TGLBaseSceneObject;
  5468. begin
  5469. Result := FObjects.FindChild(AName, False);
  5470. end;
  5471. function TGLScene.RayCastIntersect(const rayStart, rayVector: TGLVector;
  5472. intersectPoint: PGLVector = nil;
  5473. intersectNormal: PGLVector = nil): TGLBaseSceneObject;
  5474. var
  5475. bestDist2: Single;
  5476. bestHit: TGLBaseSceneObject;
  5477. iPoint, iNormal: TGLVector;
  5478. pINormal: PGLVector;
  5479. function RecursiveDive(baseObject: TGLBaseSceneObject): TGLBaseSceneObject;
  5480. var
  5481. i: Integer;
  5482. curObj: TGLBaseSceneObject;
  5483. dist2: Single;
  5484. fNear, fFar: single;
  5485. begin
  5486. Result := nil;
  5487. for i := 0 to baseObject.Count - 1 do
  5488. begin
  5489. curObj := baseObject.Children[i];
  5490. if curObj.Visible then
  5491. begin
  5492. if RayCastAABBIntersect(rayStart, rayVector,
  5493. curObj.AxisAlignedBoundingBoxAbsoluteEx, fNear, fFar) then
  5494. begin
  5495. if fnear * fnear > bestDist2 then
  5496. begin
  5497. if not PointInAABB(rayStart, curObj.AxisAlignedBoundingBoxAbsoluteEx) then
  5498. continue;
  5499. end;
  5500. if curObj.RayCastIntersect(rayStart, rayVector, @iPoint, pINormal) then
  5501. begin
  5502. dist2 := VectorDistance2(rayStart, iPoint);
  5503. if dist2 < bestDist2 then
  5504. begin
  5505. bestHit := curObj;
  5506. bestDist2 := dist2;
  5507. if Assigned(intersectPoint) then
  5508. intersectPoint^ := iPoint;
  5509. if Assigned(intersectNormal) then
  5510. intersectNormal^ := iNormal;
  5511. end;
  5512. end;
  5513. RecursiveDive(curObj);
  5514. end;
  5515. end;
  5516. end;
  5517. end;
  5518. begin
  5519. bestDist2 := 1e20;
  5520. bestHit := nil;
  5521. if Assigned(intersectNormal) then
  5522. pINormal := @iNormal
  5523. else
  5524. pINormal := nil;
  5525. RecursiveDive(Objects);
  5526. Result := bestHit;
  5527. end;
  5528. procedure TGLScene.NotifyChange(Sender: TObject);
  5529. var
  5530. i: Integer;
  5531. begin
  5532. if (not IsUpdating) and Assigned(FBuffers) then
  5533. for i := 0 to FBuffers.Count - 1 do
  5534. TGLSceneBuffer(FBuffers[i]).NotifyChange(Self);
  5535. end;
  5536. procedure TGLScene.SetupLights(maxLights: Integer);
  5537. var
  5538. i: Integer;
  5539. lightSource: TGLLightSource;
  5540. nbLights: Integer;
  5541. lPos: TGLVector;
  5542. begin
  5543. nbLights := FLights.Count;
  5544. if nbLights > maxLights then
  5545. nbLights := maxLights;
  5546. // setup all light sources
  5547. with CurrentGLContext.GLStates, CurrentGLContext.PipelineTransformation do
  5548. begin
  5549. for i := 0 to nbLights - 1 do
  5550. begin
  5551. lightSource := TGLLightSource(FLights[i]);
  5552. if Assigned(lightSource) then
  5553. with lightSource do
  5554. begin
  5555. LightEnabling[FLightID] := Shining;
  5556. if Shining then
  5557. begin
  5558. if FixedFunctionPipeLight then
  5559. begin
  5560. RebuildMatrix;
  5561. if LightStyle in [lsParallel, lsParallelSpot] then
  5562. begin
  5563. SetModelMatrix(AbsoluteMatrix);
  5564. gl.Lightfv(GL_LIGHT0 + FLightID, GL_POSITION, SpotDirection.AsAddress);
  5565. end
  5566. else
  5567. begin
  5568. SetModelMatrix(Parent.AbsoluteMatrix);
  5569. gl.Lightfv(GL_LIGHT0 + FLightID, GL_POSITION, Position.AsAddress);
  5570. end;
  5571. if LightStyle in [lsSpot, lsParallelSpot] then
  5572. begin
  5573. if FSpotCutOff <> 180 then
  5574. gl.Lightfv(GL_LIGHT0 + FLightID, GL_SPOT_DIRECTION, FSpotDirection.AsAddress);
  5575. end;
  5576. end;
  5577. lPos := lightSource.AbsolutePosition;
  5578. if LightStyle in [lsParallel, lsParallelSpot] then
  5579. lPos.W := 0.0
  5580. else
  5581. lPos.W := 1.0;
  5582. LightPosition[FLightID] := lPos;
  5583. LightSpotDirection[FLightID] := lightSource.SpotDirection.AsAffineVector;
  5584. LightAmbient[FLightID] := FAmbient.Color;
  5585. LightDiffuse[FLightID] := FDiffuse.Color;
  5586. LightSpecular[FLightID] := FSpecular.Color;
  5587. LightConstantAtten[FLightID] := FConstAttenuation;
  5588. LightLinearAtten[FLightID] := FLinearAttenuation;
  5589. LightQuadraticAtten[FLightID] := FQuadraticAttenuation;
  5590. LightSpotExponent[FLightID] := FSpotExponent;
  5591. LightSpotCutoff[FLightID] := FSpotCutOff;
  5592. end;
  5593. end
  5594. else
  5595. LightEnabling[i] := False;
  5596. end;
  5597. // turn off other lights
  5598. for i := nbLights to maxLights - 1 do
  5599. LightEnabling[i] := False;
  5600. SetModelMatrix(IdentityHmgMatrix);
  5601. end;
  5602. end;
  5603. // ------------------
  5604. // ------------------ TGLFogEnvironment ------------------
  5605. // ------------------
  5606. // Note: The fog implementation is not conformal with the rest of the scene management
  5607. // because it is viewer bound not scene bound.
  5608. constructor TGLFogEnvironment.Create(AOwner: TPersistent);
  5609. begin
  5610. inherited;
  5611. FSceneBuffer := (AOwner as TGLSceneBuffer);
  5612. FFogColor := TGLColor.CreateInitialized(Self, clrBlack);
  5613. FFogMode := fmLinear;
  5614. FFogStart := 10;
  5615. FFogEnd := 1000;
  5616. FFogDistance := fdDefault;
  5617. end;
  5618. destructor TGLFogEnvironment.Destroy;
  5619. begin
  5620. FFogColor.Free;
  5621. inherited Destroy;
  5622. end;
  5623. procedure TGLFogEnvironment.SetFogColor(Value: TGLColor);
  5624. begin
  5625. if Assigned(Value) then
  5626. begin
  5627. FFogColor.Assign(Value);
  5628. NotifyChange(Self);
  5629. end;
  5630. end;
  5631. procedure TGLFogEnvironment.SetFogStart(Value: Single);
  5632. begin
  5633. if Value <> FFogStart then
  5634. begin
  5635. FFogStart := Value;
  5636. NotifyChange(Self);
  5637. end;
  5638. end;
  5639. procedure TGLFogEnvironment.SetFogEnd(Value: Single);
  5640. begin
  5641. if Value <> FFogEnd then
  5642. begin
  5643. FFogEnd := Value;
  5644. NotifyChange(Self);
  5645. end;
  5646. end;
  5647. procedure TGLFogEnvironment.Assign(Source: TPersistent);
  5648. begin
  5649. if Source is TGLFogEnvironment then
  5650. begin
  5651. FFogColor.Assign(TGLFogEnvironment(Source).FFogColor);
  5652. FFogStart := TGLFogEnvironment(Source).FFogStart;
  5653. FFogEnd := TGLFogEnvironment(Source).FFogEnd;
  5654. FFogMode := TGLFogEnvironment(Source).FFogMode;
  5655. FFogDistance := TGLFogEnvironment(Source).FFogDistance;
  5656. NotifyChange(Self);
  5657. end;
  5658. inherited;
  5659. end;
  5660. function TGLFogEnvironment.IsAtDefaultValues: Boolean;
  5661. begin
  5662. Result := VectorEquals(FogColor.Color, FogColor.DefaultColor)
  5663. and (FogStart = 10)
  5664. and (FogEnd = 1000)
  5665. and (FogMode = fmLinear)
  5666. and (FogDistance = fdDefault);
  5667. end;
  5668. procedure TGLFogEnvironment.SetFogMode(Value: TFogMode);
  5669. begin
  5670. if Value <> FFogMode then
  5671. begin
  5672. FFogMode := Value;
  5673. NotifyChange(Self);
  5674. end;
  5675. end;
  5676. procedure TGLFogEnvironment.SetFogDistance(const val: TFogDistance);
  5677. begin
  5678. if val <> FFogDistance then
  5679. begin
  5680. FFogDistance := val;
  5681. NotifyChange(Self);
  5682. end;
  5683. end;
  5684. var
  5685. vImplemDependantFogDistanceDefault: Integer = -1;
  5686. procedure TGLFogEnvironment.ApplyFog;
  5687. var
  5688. tempActivation: Boolean;
  5689. begin
  5690. with FSceneBuffer do
  5691. begin
  5692. if not Assigned(FRenderingContext) then
  5693. Exit;
  5694. tempActivation := not FRenderingContext.Active;
  5695. if tempActivation then
  5696. FRenderingContext.Activate;
  5697. end;
  5698. case FFogMode of
  5699. fmLinear: gl.Fogi(GL_FOG_MODE, GL_LINEAR);
  5700. fmExp:
  5701. begin
  5702. gl.Fogi(GL_FOG_MODE, GL_EXP);
  5703. gl.Fogf(GL_FOG_DENSITY, FFogColor.Alpha);
  5704. end;
  5705. fmExp2:
  5706. begin
  5707. gl.Fogi(GL_FOG_MODE, GL_EXP2);
  5708. gl.Fogf(GL_FOG_DENSITY, FFogColor.Alpha);
  5709. end;
  5710. end;
  5711. gl.Fogfv(GL_FOG_COLOR, FFogColor.AsAddress);
  5712. gl.Fogf(GL_FOG_START, FFogStart);
  5713. gl.Fogf(GL_FOG_END, FFogEnd);
  5714. if gl.NV_fog_distance then
  5715. begin
  5716. case FogDistance of
  5717. fdDefault:
  5718. begin
  5719. if vImplemDependantFogDistanceDefault = -1 then
  5720. gl.GetIntegerv(GL_FOG_DISTANCE_MODE_NV,
  5721. @vImplemDependantFogDistanceDefault)
  5722. else
  5723. gl.Fogi(GL_FOG_DISTANCE_MODE_NV, vImplemDependantFogDistanceDefault);
  5724. end;
  5725. fdEyePlane:
  5726. gl.Fogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
  5727. fdEyeRadial:
  5728. gl.Fogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
  5729. else
  5730. Assert(False);
  5731. end;
  5732. end;
  5733. if tempActivation then
  5734. FSceneBuffer.RenderingContext.Deactivate;
  5735. end;
  5736. // ------------------
  5737. // ------------------ TGLSceneBuffer ------------------
  5738. // ------------------
  5739. constructor TGLSceneBuffer.Create(AOwner: TPersistent);
  5740. begin
  5741. inherited Create(AOwner);
  5742. // initialize private state variables
  5743. FFogEnvironment := TGLFogEnvironment.Create(Self);
  5744. FBackgroundColor := clBtnFace;
  5745. FBackgroundAlpha := 1;
  5746. FAmbientColor := TGLColor.CreateInitialized(Self, clrGray20);
  5747. FDepthTest := True;
  5748. FFaceCulling := True;
  5749. FLighting := True;
  5750. FAntiAliasing := aaDefault;
  5751. FDepthPrecision := dpDefault;
  5752. FColorDepth := cdDefault;
  5753. FShadeModel := smDefault;
  5754. FFogEnable := False;
  5755. FLayer := clMainPlane;
  5756. FAfterRenderEffects := TGLPersistentObjectList.Create;
  5757. FContextOptions := [roDoubleBuffer, roRenderToWindow, roDebugContext];
  5758. ResetPerformanceMonitor;
  5759. end;
  5760. destructor TGLSceneBuffer.Destroy;
  5761. begin
  5762. Melt;
  5763. DestroyRC;
  5764. FAmbientColor.Free;
  5765. FAfterRenderEffects.Free;
  5766. FFogEnvironment.Free;
  5767. inherited Destroy;
  5768. end;
  5769. procedure TGLSceneBuffer.PrepareGLContext;
  5770. begin
  5771. if Assigned(FOnPrepareGLContext) then
  5772. FOnPrepareGLContext(Self);
  5773. end;
  5774. procedure TGLSceneBuffer.SetupRCOptions(context: TGLContext);
  5775. const
  5776. cColorDepthToColorBits: array[cdDefault..cdFloat128bits] of Integer =
  5777. (24, 8, 16, 24, 64, 128); // float_type
  5778. cDepthPrecisionToDepthBits: array[dpDefault..dp32bits] of Integer =
  5779. (24, 16, 24, 32);
  5780. var
  5781. locOptions: TGLRCOptions;
  5782. locStencilBits, locAlphaBits, locColorBits: Integer;
  5783. begin
  5784. locOptions := [];
  5785. if roDoubleBuffer in ContextOptions then
  5786. locOptions := locOptions + [rcoDoubleBuffered];
  5787. if roStereo in ContextOptions then
  5788. locOptions := locOptions + [rcoStereo];
  5789. if roDebugContext in ContextOptions then
  5790. locOptions := locOptions + [rcoDebug];
  5791. if roOpenGL_ES2_Context in ContextOptions then
  5792. locOptions := locOptions + [rcoOGL_ES];
  5793. if roNoColorBuffer in ContextOptions then
  5794. locColorBits := 0
  5795. else
  5796. locColorBits := cColorDepthToColorBits[ColorDepth];
  5797. if roStencilBuffer in ContextOptions then
  5798. locStencilBits := 8
  5799. else
  5800. locStencilBits := 0;
  5801. if roDestinationAlpha in ContextOptions then
  5802. locAlphaBits := 8
  5803. else
  5804. locAlphaBits := 0;
  5805. with context do
  5806. begin
  5807. if roSoftwareMode in ContextOptions then
  5808. Acceleration := chaSoftware
  5809. else
  5810. Acceleration := chaHardware;
  5811. Options := locOptions;
  5812. ColorBits := locColorBits;
  5813. DepthBits := cDepthPrecisionToDepthBits[DepthPrecision];
  5814. StencilBits := locStencilBits;
  5815. AlphaBits := locAlphaBits;
  5816. AccumBits := AccumBufferBits;
  5817. AuxBuffers := 0;
  5818. AntiAliasing := Self.AntiAliasing;
  5819. Layer := Self.Layer;
  5820. { GLStates.ForwardContext := roForwardContext in ContextOptions;}
  5821. PrepareGLContext;
  5822. end;
  5823. end;
  5824. procedure TGLSceneBuffer.CreateRC(AWindowHandle: HWND; memoryContext:
  5825. Boolean; BufferCount: Integer);
  5826. begin
  5827. DestroyRC;
  5828. FRendering := True;
  5829. try
  5830. // will be freed in DestroyWindowHandle
  5831. FRenderingContext := GLContextManager.CreateContext;
  5832. if not Assigned(FRenderingContext) then
  5833. raise Exception.Create('Failed to create RenderingContext.');
  5834. SetupRCOptions(FRenderingContext);
  5835. if Assigned(FCamera) and Assigned(FCamera.FScene) then
  5836. FCamera.FScene.AddBuffer(Self);
  5837. with FRenderingContext do
  5838. begin
  5839. try
  5840. if memoryContext then
  5841. CreateMemoryContext(AWindowHandle, FViewPort.Width, FViewPort.Height,
  5842. BufferCount)
  5843. else
  5844. CreateContext(AWindowHandle);
  5845. except
  5846. FreeAndNil(FRenderingContext);
  5847. if Assigned(FCamera) and Assigned(FCamera.FScene) then
  5848. FCamera.FScene.RemoveBuffer(Self);
  5849. raise;
  5850. end;
  5851. end;
  5852. FRenderingContext.Activate;
  5853. try
  5854. // this one should NOT be replaced with an assert
  5855. if not gl.VERSION_1_1 then
  5856. begin
  5857. GLSLogger.LogFatalError(strWrongVersion);
  5858. Abort;
  5859. end;
  5860. // define viewport, this is necessary because the first WM_SIZE message
  5861. // is posted before the rendering context has been created
  5862. FRenderingContext.GLStates.ViewPort :=
  5863. Vector4iMake(FViewPort.Left, FViewPort.Top, FViewPort.Width, FViewPort.Height);
  5864. // set up initial context states
  5865. SetupRenderingContext(FRenderingContext);
  5866. FRenderingContext.GLStates.ColorClearValue :=
  5867. ConvertWinColor(FBackgroundColor);
  5868. finally
  5869. FRenderingContext.Deactivate;
  5870. end;
  5871. finally
  5872. FRendering := False;
  5873. end;
  5874. end;
  5875. procedure TGLSceneBuffer.DestroyRC;
  5876. begin
  5877. if Assigned(FRenderingContext) then
  5878. begin
  5879. Melt;
  5880. // for some obscure reason, Mesa3D doesn't like this call... any help welcome
  5881. FreeAndNil(FSelector);
  5882. FreeAndNil(FRenderingContext);
  5883. if Assigned(FCamera) and Assigned(FCamera.FScene) then
  5884. FCamera.FScene.RemoveBuffer(Self);
  5885. end;
  5886. end;
  5887. function TGLSceneBuffer.RCInstantiated: Boolean;
  5888. begin
  5889. Result := Assigned(FRenderingContext);
  5890. end;
  5891. procedure TGLSceneBuffer.Resize(newLeft, newTop, newWidth, newHeight: Integer);
  5892. begin
  5893. if newWidth < 1 then
  5894. newWidth := 1;
  5895. if newHeight < 1 then
  5896. newHeight := 1;
  5897. FViewPort.Left := newLeft;
  5898. FViewPort.Top := newTop;
  5899. FViewPort.Width := newWidth;
  5900. FViewPort.Height := newHeight;
  5901. if Assigned(FRenderingContext) then
  5902. begin
  5903. FRenderingContext.Activate;
  5904. try
  5905. // Part of workaround for MS OpenGL "black borders" bug
  5906. FRenderingContext.GLStates.ViewPort :=
  5907. Vector4iMake(FViewPort.Left, FViewPort.Top, FViewPort.Width, FViewPort.Height);
  5908. finally
  5909. FRenderingContext.Deactivate;
  5910. end;
  5911. end;
  5912. end;
  5913. function TGLSceneBuffer.Acceleration: TGLContextAcceleration;
  5914. begin
  5915. if Assigned(FRenderingContext) then
  5916. Result := FRenderingContext.Acceleration
  5917. else
  5918. Result := chaUnknown;
  5919. end;
  5920. procedure TGLSceneBuffer.SetupRenderingContext(context: TGLContext);
  5921. procedure SetState(context: TGLContext; bool: Boolean; csState: TGLState); inline;
  5922. begin
  5923. case bool of
  5924. true: context.GLStates.PerformEnable(csState);
  5925. false: context.GLStates.PerformDisable(csState);
  5926. end;
  5927. end;
  5928. var
  5929. LColorDepth: Cardinal;
  5930. begin
  5931. if not Assigned(context) then
  5932. Exit;
  5933. if not (roForwardContext in ContextOptions) then
  5934. begin
  5935. gl.LightModelfv(GL_LIGHT_MODEL_AMBIENT, FAmbientColor.AsAddress);
  5936. if roTwoSideLighting in FContextOptions then
  5937. gl.LightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE)
  5938. else
  5939. gl.LightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
  5940. gl.Hint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  5941. case ShadeModel of
  5942. smDefault, smSmooth: gl.ShadeModel(GL_SMOOTH);
  5943. smFlat: gl.ShadeModel(GL_FLAT);
  5944. else
  5945. Assert(False, strErrorEx + strUnknownType);
  5946. end;
  5947. end;
  5948. with context.GLStates do
  5949. begin
  5950. Enable(stNormalize);
  5951. SetState(context, DepthTest, stDepthTest);
  5952. SetState(context, FaceCulling, stCullFace);
  5953. SetState(context, Lighting, stLighting);
  5954. SetState(context, FogEnable, stFog);
  5955. if gl.ARB_depth_clamp then
  5956. Disable(stDepthClamp);
  5957. if not (roForwardContext in ContextOptions) then
  5958. begin
  5959. gl.GetIntegerv(GL_BLUE_BITS, @LColorDepth); // could've used red or green too
  5960. SetState(context, (LColorDepth < 8), stDither);
  5961. end;
  5962. ResetAllTextureMatrix;
  5963. end;
  5964. end;
  5965. function TGLSceneBuffer.GetLimit(Which: TGLLimitType): Integer;
  5966. var
  5967. VP: array[0..1] of Double;
  5968. begin
  5969. case Which of
  5970. limClipPlanes: gl.GetIntegerv(GL_MAX_CLIP_PLANES, @Result);
  5971. limEvalOrder: gl.GetIntegerv(GL_MAX_EVAL_ORDER, @Result);
  5972. limLights: gl.GetIntegerv(GL_MAX_LIGHTS, @Result);
  5973. limListNesting: gl.GetIntegerv(GL_MAX_LIST_NESTING, @Result);
  5974. limModelViewStack: gl.GetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, @Result);
  5975. limNameStack: gl.GetIntegerv(GL_MAX_NAME_STACK_DEPTH, @Result);
  5976. limPixelMapTable: gl.GetIntegerv(GL_MAX_PIXEL_MAP_TABLE, @Result);
  5977. limProjectionStack: gl.GetIntegerv(GL_MAX_PROJECTION_STACK_DEPTH, @Result);
  5978. limTextureSize: gl.GetIntegerv(GL_MAX_TEXTURE_SIZE, @Result);
  5979. limTextureStack: gl.GetIntegerv(GL_MAX_TEXTURE_STACK_DEPTH, @Result);
  5980. limViewportDims:
  5981. begin
  5982. gl.GetDoublev(GL_MAX_VIEWPORT_DIMS, @VP);
  5983. if VP[0] > VP[1] then
  5984. Result := Round(VP[0])
  5985. else
  5986. Result := Round(VP[1]);
  5987. end;
  5988. limAccumAlphaBits: gl.GetIntegerv(GL_ACCUM_ALPHA_BITS, @Result);
  5989. limAccumBlueBits: gl.GetIntegerv(GL_ACCUM_BLUE_BITS, @Result);
  5990. limAccumGreenBits: gl.GetIntegerv(GL_ACCUM_GREEN_BITS, @Result);
  5991. limAccumRedBits: gl.GetIntegerv(GL_ACCUM_RED_BITS, @Result);
  5992. limAlphaBits: gl.GetIntegerv(GL_ALPHA_BITS, @Result);
  5993. limAuxBuffers: gl.GetIntegerv(GL_AUX_BUFFERS, @Result);
  5994. limDepthBits: gl.GetIntegerv(GL_DEPTH_BITS, @Result);
  5995. limStencilBits: gl.GetIntegerv(GL_STENCIL_BITS, @Result);
  5996. limBlueBits: gl.GetIntegerv(GL_BLUE_BITS, @Result);
  5997. limGreenBits: gl.GetIntegerv(GL_GREEN_BITS, @Result);
  5998. limRedBits: gl.GetIntegerv(GL_RED_BITS, @Result);
  5999. limIndexBits: gl.GetIntegerv(GL_INDEX_BITS, @Result);
  6000. limStereo: gl.GetIntegerv(GL_STEREO, @Result);
  6001. limDoubleBuffer: gl.GetIntegerv(GL_DOUBLEBUFFER, @Result);
  6002. limSubpixelBits: gl.GetIntegerv(GL_SUBPIXEL_BITS, @Result);
  6003. limNbTextureUnits:
  6004. if gl.ARB_multitexture then
  6005. gl.GetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, @Result)
  6006. else
  6007. Result := 1;
  6008. else
  6009. Result := 0;
  6010. end;
  6011. end;
  6012. procedure TGLSceneBuffer.RenderToFile(const aFile: string; DPI: Integer);
  6013. var
  6014. aBitmap: TBitmap;
  6015. saveAllowed: Boolean;
  6016. fileName: string;
  6017. begin
  6018. Assert((not FRendering), strAlreadyRendering);
  6019. aBitmap := TBitmap.Create;
  6020. try
  6021. aBitmap.Width := FViewPort.Width;
  6022. aBitmap.Height := FViewPort.Height;
  6023. aBitmap.PixelFormat := pf24Bit;
  6024. RenderToBitmap(ABitmap, DPI);
  6025. fileName := aFile;
  6026. if fileName = '' then
  6027. saveAllowed := SavePictureDialog(fileName)
  6028. else
  6029. saveAllowed := True;
  6030. if saveAllowed then
  6031. begin
  6032. if FileExists(fileName) then
  6033. saveAllowed := QuestionDlg(Format('Overwrite file %s?', [fileName]));
  6034. if saveAllowed then
  6035. aBitmap.SaveToFile(fileName);
  6036. end;
  6037. finally
  6038. aBitmap.Free;
  6039. end;
  6040. end;
  6041. procedure TGLSceneBuffer.RenderToFile(const AFile: string; bmpWidth, bmpHeight:
  6042. Integer);
  6043. var
  6044. aBitmap: TBitmap;
  6045. saveAllowed: Boolean;
  6046. fileName: string;
  6047. begin
  6048. Assert((not FRendering), strAlreadyRendering);
  6049. aBitmap := TBitmap.Create;
  6050. try
  6051. aBitmap.Width := bmpWidth;
  6052. aBitmap.Height := bmpHeight;
  6053. aBitmap.PixelFormat := pf24Bit;
  6054. RenderToBitmap(aBitmap,
  6055. (GetDeviceLogicalPixelsX(Cardinal(ABitmap.Canvas.Handle)) * bmpWidth) div
  6056. FViewPort.Width);
  6057. fileName := AFile;
  6058. if fileName = '' then
  6059. saveAllowed := SavePictureDialog(fileName)
  6060. else
  6061. saveAllowed := True;
  6062. if saveAllowed then
  6063. begin
  6064. if FileExists(fileName) then
  6065. saveAllowed := QuestionDlg(Format('Overwrite file %s?', [fileName]));
  6066. if SaveAllowed then
  6067. aBitmap.SaveToFile(fileName);
  6068. end;
  6069. finally
  6070. aBitmap.Free;
  6071. end;
  6072. end;
  6073. function TGLSceneBuffer.CreateSnapShot: TGLBitmap32;
  6074. begin
  6075. Result := TGLBitmap32.Create;
  6076. Result.Width := FViewPort.Width;
  6077. Result.Height := FViewPort.Height;
  6078. if Assigned(Camera) and Assigned(Camera.Scene) then
  6079. begin
  6080. FRenderingContext.Activate;
  6081. try
  6082. Result.ReadPixels(Rect(0, 0, FViewPort.Width, FViewPort.Height));
  6083. finally
  6084. FRenderingContext.DeActivate;
  6085. end;
  6086. end;
  6087. end;
  6088. function TGLSceneBuffer.CreateSnapShotBitmap: TBitmap;
  6089. var
  6090. bmp32: TGLBitmap32;
  6091. begin
  6092. bmp32 := CreateSnapShot;
  6093. try
  6094. Result := bmp32.Create32BitsBitmap;
  6095. finally
  6096. bmp32.Free;
  6097. end;
  6098. end;
  6099. procedure TGLSceneBuffer.CopyToTexture(aTexture: TGLTexture);
  6100. begin
  6101. CopyToTexture(aTexture, 0, 0, Width, Height, 0, 0);
  6102. end;
  6103. procedure TGLSceneBuffer.CopyToTexture(aTexture: TGLTexture;
  6104. xSrc, ySrc, AWidth, AHeight: Integer;
  6105. xDest, yDest: Integer;
  6106. glCubeFace: Cardinal = 0);
  6107. var
  6108. bindTarget: TGLTextureTarget;
  6109. begin
  6110. if RenderingContext <> nil then
  6111. begin
  6112. RenderingContext.Activate;
  6113. try
  6114. if not (aTexture.Image is TGLBlankImage) then
  6115. aTexture.ImageClassName := TGLBlankImage.ClassName;
  6116. if aTexture.Image.Width <> AWidth then
  6117. TGLBlankImage(aTexture.Image).Width := AWidth;
  6118. if aTexture.Image.Height <> AHeight then
  6119. TGLBlankImage(aTexture.Image).Height := AHeight;
  6120. if aTexture.Image.Depth <> 0 then
  6121. TGLBlankImage(aTexture.Image).Depth := 0;
  6122. if TGLBlankImage(aTexture.Image).CubeMap <> (glCubeFace > 0) then
  6123. TGLBlankImage(aTexture.Image).CubeMap := (glCubeFace > 0);
  6124. bindTarget := aTexture.Image.NativeTextureTarget;
  6125. RenderingContext.GLStates.TextureBinding[0, bindTarget] := aTexture.Handle;
  6126. if glCubeFace > 0 then
  6127. gl.CopyTexSubImage2D(glCubeFace,
  6128. 0, xDest, yDest, xSrc, ySrc, AWidth, AHeight)
  6129. else
  6130. gl.CopyTexSubImage2D(DecodeTextureTarget(bindTarget),
  6131. 0, xDest, yDest, xSrc, ySrc, AWidth, AHeight)
  6132. finally
  6133. RenderingContext.Deactivate;
  6134. end;
  6135. end;
  6136. end;
  6137. procedure TGLSceneBuffer.SaveAsFloatToFile(const aFilename: string);
  6138. var
  6139. Data: pointer;
  6140. DataSize: integer;
  6141. Stream: TMemoryStream;
  6142. const
  6143. FloatSize = 4;
  6144. begin
  6145. if Assigned(Camera) and Assigned(Camera.Scene) then
  6146. begin
  6147. DataSize := Width * Height * FloatSize * FloatSize;
  6148. GetMem(Data, DataSize);
  6149. FRenderingContext.Activate;
  6150. try
  6151. gl.ReadPixels(0, 0, Width, Height, GL_RGBA, GL_FLOAT, Data);
  6152. gl.CheckError;
  6153. Stream := TMemoryStream.Create;
  6154. try
  6155. Stream.Write(Data^, DataSize);
  6156. Stream.SaveToFile(aFilename);
  6157. finally
  6158. Stream.Free;
  6159. end;
  6160. finally
  6161. FRenderingContext.DeActivate;
  6162. FreeMem(Data);
  6163. end;
  6164. end;
  6165. end;
  6166. procedure TGLSceneBuffer.SetViewPort(X, Y, W, H: Integer);
  6167. begin
  6168. with FViewPort do
  6169. begin
  6170. Left := X;
  6171. Top := Y;
  6172. Width := W;
  6173. Height := H;
  6174. end;
  6175. NotifyChange(Self);
  6176. end;
  6177. function TGLSceneBuffer.Width: Integer;
  6178. begin
  6179. Result := FViewPort.Width;
  6180. end;
  6181. function TGLSceneBuffer.Height: Integer;
  6182. begin
  6183. Result := FViewPort.Height;
  6184. end;
  6185. procedure TGLSceneBuffer.Freeze;
  6186. begin
  6187. if Freezed then
  6188. Exit;
  6189. if RenderingContext = nil then
  6190. Exit;
  6191. Render;
  6192. FFreezed := True;
  6193. RenderingContext.Activate;
  6194. try
  6195. FFreezeBuffer := AllocMem(FViewPort.Width * FViewPort.Height * 4);
  6196. gl.ReadPixels(0, 0, FViewport.Width, FViewPort.Height,
  6197. GL_RGBA, GL_UNSIGNED_BYTE, FFreezeBuffer);
  6198. FFreezedViewPort := FViewPort;
  6199. finally
  6200. RenderingContext.Deactivate;
  6201. end;
  6202. end;
  6203. procedure TGLSceneBuffer.Melt;
  6204. begin
  6205. if not Freezed then
  6206. Exit;
  6207. FreeMem(FFreezeBuffer);
  6208. FFreezeBuffer := nil;
  6209. FFreezed := False;
  6210. end;
  6211. procedure TGLSceneBuffer.RenderToBitmap(ABitmap: TBitmap; DPI: Integer);
  6212. var
  6213. nativeContext: TGLContext;
  6214. aColorBits: Integer;
  6215. begin
  6216. Assert((not FRendering), strAlreadyRendering);
  6217. FRendering := True;
  6218. nativeContext := RenderingContext;
  6219. try
  6220. aColorBits := PixelFormatToColorBits(ABitmap.PixelFormat);
  6221. if aColorBits < 8 then
  6222. aColorBits := 8;
  6223. FRenderingContext := GLContextManager.CreateContext;
  6224. SetupRCOptions(FRenderingContext);
  6225. with FRenderingContext do
  6226. begin
  6227. Options := []; // no such things for bitmap rendering
  6228. ColorBits := aColorBits; // honour Bitmap's pixel depth
  6229. AntiAliasing := aaNone; // no AA for bitmap rendering
  6230. CreateContext(ABitmap.Canvas.Handle);
  6231. end;
  6232. try
  6233. FRenderingContext.Activate;
  6234. try
  6235. SetupRenderingContext(FRenderingContext);
  6236. FRenderingContext.GLStates.ColorClearValue := ConvertWinColor(FBackgroundColor);
  6237. // set the desired viewport and limit output to this rectangle
  6238. with FViewport do
  6239. begin
  6240. Left := 0;
  6241. Top := 0;
  6242. Width := ABitmap.Width;
  6243. Height := ABitmap.Height;
  6244. FRenderingContext.GLStates.ViewPort := Vector4iMake(Left, Top, Width, Height);
  6245. end;
  6246. ClearBuffers;
  6247. FRenderDPI := DPI;
  6248. if FRenderDPI = 0 then
  6249. FRenderDPI := GetDeviceLogicalPixelsX(ABitmap.Canvas.Handle);
  6250. // render
  6251. DoBaseRender(FViewport, FRenderDPI, dsPrinting, nil);
  6252. if nativeContext <> nil then
  6253. FViewport := TRectangle(nativeContext.GLStates.ViewPort);
  6254. gl.Finish;
  6255. finally
  6256. FRenderingContext.Deactivate;
  6257. end;
  6258. finally
  6259. FRenderingContext.Free;
  6260. end;
  6261. finally
  6262. FRenderingContext := nativeContext;
  6263. FRendering := False;
  6264. end;
  6265. if Assigned(FAfterRender) then
  6266. if Owner is TComponent then
  6267. if not (csDesigning in TComponent(Owner).ComponentState) then
  6268. FAfterRender(Self);
  6269. end;
  6270. procedure TGLSceneBuffer.ShowInfo(Modal: boolean);
  6271. begin
  6272. if not Assigned(FRenderingContext) then
  6273. Exit;
  6274. // most info is available with active context only
  6275. FRenderingContext.Activate;
  6276. try
  6277. InvokeInfoForm(Self, Modal);
  6278. finally
  6279. FRenderingContext.Deactivate;
  6280. end;
  6281. end;
  6282. procedure TGLSceneBuffer.ResetPerformanceMonitor;
  6283. begin
  6284. FFramesPerSecond := 0;
  6285. FFrameCount := 0;
  6286. FFirstPerfCounter := 0;
  6287. end;
  6288. procedure TGLSceneBuffer.PushViewMatrix(const newMatrix: TGLMatrix);
  6289. var
  6290. n: Integer;
  6291. begin
  6292. n := Length(FViewMatrixStack);
  6293. SetLength(FViewMatrixStack, n + 1);
  6294. FViewMatrixStack[n] := RenderingContext.PipelineTransformation.ViewMatrix^;
  6295. RenderingContext.PipelineTransformation.SetViewMatrix(newMatrix);
  6296. end;
  6297. procedure TGLSceneBuffer.PopViewMatrix;
  6298. var
  6299. n: Integer;
  6300. begin
  6301. n := High(FViewMatrixStack);
  6302. Assert(n >= 0, 'Unbalanced PopViewMatrix');
  6303. RenderingContext.PipelineTransformation.SetViewMatrix(FViewMatrixStack[n]);
  6304. SetLength(FViewMatrixStack, n);
  6305. end;
  6306. procedure TGLSceneBuffer.PushProjectionMatrix(const newMatrix: TGLMatrix);
  6307. var
  6308. n: Integer;
  6309. begin
  6310. n := Length(FProjectionMatrixStack);
  6311. SetLength(FProjectionMatrixStack, n + 1);
  6312. FProjectionMatrixStack[n] := RenderingContext.PipelineTransformation.ProjectionMatrix^;
  6313. RenderingContext.PipelineTransformation.SetProjectionMatrix(newMatrix);
  6314. end;
  6315. procedure TGLSceneBuffer.PopProjectionMatrix;
  6316. var
  6317. n: Integer;
  6318. begin
  6319. n := High(FProjectionMatrixStack);
  6320. Assert(n >= 0, 'Unbalanced PopProjectionMatrix');
  6321. RenderingContext.PipelineTransformation.SetProjectionMatrix(FProjectionMatrixStack[n]);
  6322. SetLength(FProjectionMatrixStack, n);
  6323. end;
  6324. function TGLSceneBuffer.ProjectionMatrix;
  6325. begin
  6326. Result := RenderingContext.PipelineTransformation.ProjectionMatrix^;
  6327. end;
  6328. function TGLSceneBuffer.ViewMatrix: TGLMatrix;
  6329. begin
  6330. Result := RenderingContext.PipelineTransformation.ViewMatrix^;
  6331. end;
  6332. function TGLSceneBuffer.ModelMatrix: TGLMatrix;
  6333. begin
  6334. Result := RenderingContext.PipelineTransformation.ModelMatrix^;
  6335. end;
  6336. function TGLSceneBuffer.OrthoScreenToWorld(screenX, screenY: Integer):
  6337. TAffineVector;
  6338. var
  6339. camPos, camUp, camRight: TAffineVector;
  6340. f: Single;
  6341. begin
  6342. if Assigned(FCamera) then
  6343. begin
  6344. SetVector(camPos, FCameraAbsolutePosition);
  6345. if Camera.TargetObject <> nil then
  6346. begin
  6347. SetVector(camUp, FCamera.AbsoluteUpVectorToTarget);
  6348. SetVector(camRight, FCamera.AbsoluteRightVectorToTarget);
  6349. end
  6350. else
  6351. begin
  6352. SetVector(camUp, Camera.AbsoluteUp);
  6353. SetVector(camRight, Camera.AbsoluteRight);
  6354. end;
  6355. f := 100 * FCamera.NearPlaneBias / (FCamera.FocalLength *
  6356. FCamera.SceneScale);
  6357. if FViewPort.Width > FViewPort.Height then
  6358. f := f / FViewPort.Width
  6359. else
  6360. f := f / FViewPort.Height;
  6361. SetVector(Result,
  6362. VectorCombine3(camPos, camUp, camRight, 1,
  6363. (screenY - (FViewPort.Height div 2)) * f,
  6364. (screenX - (FViewPort.Width div 2)) * f));
  6365. end
  6366. else
  6367. Result := NullVector;
  6368. end;
  6369. function TGLSceneBuffer.ScreenToWorld(const aPoint: TAffineVector):
  6370. TAffineVector;
  6371. var
  6372. rslt: TGLVector;
  6373. begin
  6374. if Assigned(FCamera)
  6375. and UnProject(
  6376. VectorMake(aPoint),
  6377. RenderingContext.PipelineTransformation.ViewProjectionMatrix^,
  6378. PHomogeneousIntVector(@FViewPort)^, rslt) then
  6379. Result := Vector3fMake(rslt)
  6380. else
  6381. Result := aPoint;
  6382. end;
  6383. function TGLSceneBuffer.ScreenToWorld(const aPoint: TGLVector): TGLVector;
  6384. begin
  6385. MakePoint(Result, ScreenToWorld(AffineVectorMake(aPoint)));
  6386. end;
  6387. function TGLSceneBuffer.ScreenToWorld(screenX, screenY: Integer): TAffineVector;
  6388. begin
  6389. Result := ScreenToWorld(AffineVectorMake(screenX, FViewPort.Height - screenY,
  6390. 0));
  6391. end;
  6392. function TGLSceneBuffer.WorldToScreen(const aPoint: TAffineVector): TAffineVector;
  6393. var
  6394. rslt: TGLVector;
  6395. begin
  6396. RenderingContext.Activate;
  6397. try
  6398. PrepareRenderingMatrices(FViewPort, FRenderDPI);
  6399. if Assigned(FCamera)
  6400. and Project(
  6401. VectorMake(aPoint),
  6402. RenderingContext.PipelineTransformation.ViewProjectionMatrix^,
  6403. TVector4i(FViewPort),
  6404. rslt) then
  6405. Result := Vector3fMake(rslt)
  6406. else
  6407. Result := aPoint;
  6408. finally
  6409. RenderingContext.Deactivate;
  6410. end;
  6411. end;
  6412. function TGLSceneBuffer.WorldToScreen(const aPoint: TGLVector): TGLVector;
  6413. begin
  6414. SetVector(Result, WorldToScreen(AffineVectorMake(aPoint)));
  6415. end;
  6416. procedure TGLSceneBuffer.WorldToScreen(points: PGLVector; nbPoints: Integer);
  6417. var
  6418. i: Integer;
  6419. begin
  6420. if Assigned(FCamera) then
  6421. begin
  6422. for i := nbPoints - 1 downto 0 do
  6423. begin
  6424. Project(points^, RenderingContext.PipelineTransformation.ViewProjectionMatrix^, PHomogeneousIntVector(@FViewPort)^, points^);
  6425. Inc(points);
  6426. end;
  6427. end;
  6428. end;
  6429. function TGLSceneBuffer.ScreenToVector(const aPoint: TAffineVector):
  6430. TAffineVector;
  6431. begin
  6432. Result := VectorSubtract(ScreenToWorld(aPoint),
  6433. PAffineVector(@FCameraAbsolutePosition)^);
  6434. end;
  6435. function TGLSceneBuffer.ScreenToVector(const aPoint: TGLVector): TGLVector;
  6436. begin
  6437. SetVector(Result, VectorSubtract(ScreenToWorld(aPoint),
  6438. FCameraAbsolutePosition));
  6439. Result.W := 0;
  6440. end;
  6441. function TGLSceneBuffer.ScreenToVector(const x, y: Integer): TGLVector;
  6442. var
  6443. av: TAffineVector;
  6444. begin
  6445. av.X := x;
  6446. av.Y := y;
  6447. av.Z := 0;
  6448. SetVector(Result, ScreenToVector(av));
  6449. end;
  6450. function TGLSceneBuffer.VectorToScreen(const VectToCam: TAffineVector):
  6451. TAffineVector;
  6452. begin
  6453. Result := WorldToScreen(VectorAdd(VectToCam,
  6454. PAffineVector(@FCameraAbsolutePosition)^));
  6455. end;
  6456. function TGLSceneBuffer.ScreenVectorIntersectWithPlane(
  6457. const aScreenPoint: TGLVector;
  6458. const planePoint, planeNormal: TGLVector;
  6459. var intersectPoint: TGLVector): Boolean;
  6460. var
  6461. v: TGLVector;
  6462. begin
  6463. if Assigned(FCamera) then
  6464. begin
  6465. SetVector(v, ScreenToVector(aScreenPoint));
  6466. Result := RayCastPlaneIntersect(FCameraAbsolutePosition,
  6467. v, planePoint, planeNormal, @intersectPoint);
  6468. intersectPoint.W := 1;
  6469. end
  6470. else
  6471. Result := False;
  6472. end;
  6473. function TGLSceneBuffer.ScreenVectorIntersectWithPlaneXY(
  6474. const aScreenPoint: TGLVector; const z: Single;
  6475. var intersectPoint: TGLVector): Boolean;
  6476. begin
  6477. Result := ScreenVectorIntersectWithPlane(aScreenPoint, VectorMake(0, 0, z),
  6478. ZHmgVector, intersectPoint);
  6479. intersectPoint.W := 0;
  6480. end;
  6481. function TGLSceneBuffer.ScreenVectorIntersectWithPlaneYZ(
  6482. const aScreenPoint: TGLVector; const x: Single;
  6483. var intersectPoint: TGLVector): Boolean;
  6484. begin
  6485. Result := ScreenVectorIntersectWithPlane(aScreenPoint, VectorMake(x, 0, 0),
  6486. XHmgVector, intersectPoint);
  6487. intersectPoint.W := 0;
  6488. end;
  6489. function TGLSceneBuffer.ScreenVectorIntersectWithPlaneXZ(
  6490. const aScreenPoint: TGLVector; const y: Single;
  6491. var intersectPoint: TGLVector): Boolean;
  6492. begin
  6493. Result := ScreenVectorIntersectWithPlane(aScreenPoint, VectorMake(0, y, 0),
  6494. YHmgVector, intersectPoint);
  6495. intersectPoint.W := 0;
  6496. end;
  6497. function TGLSceneBuffer.PixelRayToWorld(x, y: Integer): TAffineVector;
  6498. var
  6499. dov, np, fp, z, dst, wrpdst: Single;
  6500. vec, cam, targ, rayhit, pix: TAffineVector;
  6501. camAng: real;
  6502. begin
  6503. if Camera.CameraStyle = csOrtho2D then
  6504. dov := 2
  6505. else
  6506. dov := Camera.DepthOfView;
  6507. np := Camera.NearPlane;
  6508. fp := Camera.NearPlane + dov;
  6509. z := GetPixelDepth(x, y);
  6510. dst := (fp * np) / (fp - z * dov); //calc from z-buffer value to world depth
  6511. //------------------------
  6512. //z:=1-(fp/d-1)/(fp/np-1); //calc from world depth to z-buffer value
  6513. //------------------------
  6514. vec.X := x;
  6515. vec.Y := FViewPort.Height - y;
  6516. vec.Z := 0;
  6517. vec := ScreenToVector(vec);
  6518. NormalizeVector(vec);
  6519. SetVector(cam, Camera.AbsolutePosition);
  6520. //targ:=Camera.TargetObject.Position.AsAffineVector;
  6521. //SubtractVector(targ,cam);
  6522. pix.X := FViewPort.Width * 0.5;
  6523. pix.Y := FViewPort.Height * 0.5;
  6524. pix.Z := 0;
  6525. targ := self.ScreenToVector(pix);
  6526. camAng := VectorAngleCosine(targ, vec);
  6527. wrpdst := dst / camAng;
  6528. rayhit := cam;
  6529. CombineVector(rayhit, vec, wrpdst);
  6530. result := rayhit;
  6531. end;
  6532. procedure TGLSceneBuffer.ClearBuffers;
  6533. var
  6534. bufferBits: TGLBitfield;
  6535. begin
  6536. if roNoDepthBufferClear in ContextOptions then
  6537. bufferBits := 0
  6538. else
  6539. begin
  6540. bufferBits := GL_DEPTH_BUFFER_BIT;
  6541. CurrentGLContext.GLStates.DepthWriteMask := True;
  6542. end;
  6543. if ContextOptions * [roNoColorBuffer, roNoColorBufferClear] = [] then
  6544. begin
  6545. bufferBits := bufferBits or GL_COLOR_BUFFER_BIT;
  6546. CurrentGLContext.GLStates.SetColorMask(cAllColorComponents);
  6547. end;
  6548. if roStencilBuffer in ContextOptions then
  6549. begin
  6550. bufferBits := bufferBits or GL_STENCIL_BUFFER_BIT;
  6551. end;
  6552. if bufferBits<>0 then
  6553. gl.Clear(BufferBits);
  6554. end;
  6555. procedure TGLSceneBuffer.NotifyChange(Sender: TObject);
  6556. begin
  6557. DoChange;
  6558. end;
  6559. procedure TGLSceneBuffer.PickObjects(const rect: TRect; pickList: TGLPickList; objectCountGuess: Integer);
  6560. var
  6561. I: Integer;
  6562. obj: TGLBaseSceneObject;
  6563. begin
  6564. if not Assigned(FCamera) then
  6565. Exit;
  6566. Assert((not FRendering), strAlreadyRendering);
  6567. Assert(Assigned(PickList));
  6568. FRenderingContext.Activate;
  6569. FRendering := True;
  6570. try
  6571. // Creates best selector which techniques is hardware can do
  6572. if not Assigned(FSelector) then
  6573. FSelector := GetBestSelectorClass.Create;
  6574. xgl.MapTexCoordToNull; // turn off
  6575. PrepareRenderingMatrices(FViewPort, RenderDPI, @Rect);
  6576. FSelector.Hits := -1;
  6577. if objectCountGuess > 0 then
  6578. FSelector.ObjectCountGuess := objectCountGuess;
  6579. repeat
  6580. FSelector.Start;
  6581. // render the scene (in select mode, nothing is drawn)
  6582. FRenderDPI := 96;
  6583. if Assigned(FCamera) and Assigned(FCamera.FScene) then
  6584. RenderScene(FCamera.FScene, FViewPort.Width, FViewPort.Height,
  6585. dsPicking, nil);
  6586. until FSelector.Stop;
  6587. FSelector.FillPickingList(PickList);
  6588. for I := 0 to PickList.Count-1 do
  6589. begin
  6590. obj := TGLBaseSceneObject(PickList[I]);
  6591. if Assigned(obj.FOnPicked) then
  6592. obj.FOnPicked(obj);
  6593. end;
  6594. finally
  6595. FRendering := False;
  6596. FRenderingContext.Deactivate;
  6597. end;
  6598. end;
  6599. function TGLSceneBuffer.GetPickedObjects(const rect: TRect; objectCountGuess:
  6600. Integer = 64): TGLPickList;
  6601. begin
  6602. Result := TGLPickList.Create(psMinDepth);
  6603. PickObjects(Rect, Result, objectCountGuess);
  6604. end;
  6605. function TGLSceneBuffer.GetPickedObject(x, y: Integer): TGLBaseSceneObject;
  6606. var
  6607. pkList: TGLPickList;
  6608. begin
  6609. pkList := GetPickedObjects(Rect(x - 1, y - 1, x + 1, y + 1));
  6610. try
  6611. if pkList.Count > 0 then
  6612. Result := TGLBaseSceneObject(pkList.Hit[0])
  6613. else
  6614. Result := nil;
  6615. finally
  6616. pkList.Free;
  6617. end;
  6618. end;
  6619. function TGLSceneBuffer.GetPixelColor(x, y: Integer): TColor;
  6620. var
  6621. buf: array[0..2] of Byte;
  6622. begin
  6623. if not Assigned(FCamera) then
  6624. begin
  6625. Result := 0;
  6626. Exit;
  6627. end;
  6628. FRenderingContext.Activate;
  6629. try
  6630. gl.ReadPixels(x, FViewPort.Height - y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, @buf[0]);
  6631. finally
  6632. FRenderingContext.Deactivate;
  6633. end;
  6634. Result := RGB2Color(buf[0], buf[1], buf[2]);
  6635. end;
  6636. function TGLSceneBuffer.GetPixelDepth(x, y: Integer): Single;
  6637. begin
  6638. if not Assigned(FCamera) then
  6639. begin
  6640. Result := 0;
  6641. Exit;
  6642. end;
  6643. FRenderingContext.Activate;
  6644. try
  6645. gl.ReadPixels(x, FViewPort.Height - y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT,
  6646. @Result);
  6647. finally
  6648. FRenderingContext.Deactivate;
  6649. end;
  6650. end;
  6651. function TGLSceneBuffer.PixelDepthToDistance(aDepth: Single): Single;
  6652. var
  6653. dov, np, fp: Single;
  6654. begin
  6655. if Camera.CameraStyle = csOrtho2D then
  6656. dov := 2
  6657. else
  6658. dov := Camera.DepthOfView; // Depth of View (from np to fp)
  6659. np := Camera.NearPlane; // Near plane distance
  6660. fp := np + dov; // Far plane distance
  6661. Result := (fp * np) / (fp - aDepth * dov);
  6662. // calculate world distance from z-buffer value
  6663. end;
  6664. function TGLSceneBuffer.PixelToDistance(x, y: integer): Single;
  6665. var
  6666. z, dov, np, fp, dst, camAng: Single;
  6667. norm, coord, vec: TAffineVector;
  6668. begin
  6669. z := GetPixelDepth(x, y);
  6670. if Camera.CameraStyle = csOrtho2D then
  6671. dov := 2
  6672. else
  6673. dov := Camera.DepthOfView; // Depth of View (from np to fp)
  6674. np := Camera.NearPlane; // Near plane distance
  6675. fp := np + dov; // Far plane distance
  6676. dst := (np * fp) / (fp - z * dov);
  6677. //calculate from z-buffer value to frustrum depth
  6678. coord.X := x;
  6679. coord.Y := y;
  6680. vec := self.ScreenToVector(coord); //get the pixel vector
  6681. coord.X := FViewPort.Width div 2;
  6682. coord.Y := FViewPort.Height div 2;
  6683. norm := self.ScreenToVector(coord); //get the absolute camera direction
  6684. camAng := VectorAngleCosine(norm, vec);
  6685. Result := dst / camAng; //compensate for flat frustrum face
  6686. end;
  6687. procedure TGLSceneBuffer.NotifyMouseMove(Shift: TShiftState; X, Y: Integer);
  6688. begin
  6689. // Nothing
  6690. end;
  6691. procedure TGLSceneBuffer.PrepareRenderingMatrices(const aViewPort: TRectangle;
  6692. resolution: Integer; pickingRect: PRect = nil);
  6693. begin
  6694. RenderingContext.PipelineTransformation.IdentityAll;
  6695. // setup projection matrix
  6696. if Assigned(pickingRect) then
  6697. begin
  6698. CurrentGLContext.PipelineTransformation.SetProjectionMatrix(
  6699. CreatePickMatrix(
  6700. (pickingRect^.Left + pickingRect^.Right) div 2,
  6701. FViewPort.Height - ((pickingRect^.Top + pickingRect^.Bottom) div 2),
  6702. Abs(pickingRect^.Right - pickingRect^.Left),
  6703. Abs(pickingRect^.Bottom - pickingRect^.Top),
  6704. TVector4i(FViewport)));
  6705. end;
  6706. FBaseProjectionMatrix := CurrentGLContext.PipelineTransformation.ProjectionMatrix^;
  6707. if Assigned(FCamera) then
  6708. begin
  6709. FCamera.Scene.FCurrentGLCamera := FCamera;
  6710. // apply camera perpective
  6711. FCamera.ApplyPerspective(
  6712. aViewport,
  6713. FViewPort.Width,
  6714. FViewPort.Height,
  6715. resolution);
  6716. // setup model view matrix
  6717. // apply camera transformation (viewpoint)
  6718. FCamera.Apply;
  6719. FCameraAbsolutePosition := FCamera.AbsolutePosition;
  6720. end;
  6721. end;
  6722. procedure TGLSceneBuffer.DoBaseRender(const aViewPort: TRectangle; resolution:
  6723. Integer;
  6724. drawState: TGLDrawState; baseObject: TGLBaseSceneObject);
  6725. begin
  6726. with RenderingContext.GLStates do
  6727. begin
  6728. PrepareRenderingMatrices(aViewPort, resolution);
  6729. (* if not ForwardContext then *)
  6730. begin
  6731. xgl.MapTexCoordToNull; // force XGL rebind
  6732. xgl.MapTexCoordToMain;
  6733. end;
  6734. if Assigned(FViewerBeforeRender) and (drawState <> dsPrinting) then
  6735. FViewerBeforeRender(Self);
  6736. if Assigned(FBeforeRender) then
  6737. if Owner is TComponent then
  6738. if not (csDesigning in TComponent(Owner).ComponentState) then
  6739. FBeforeRender(Self);
  6740. if Assigned(FCamera) and Assigned(FCamera.FScene) then
  6741. begin
  6742. with FCamera.FScene do
  6743. begin
  6744. SetupLights(MaxLights);
  6745. (* if not ForwardContext then *)
  6746. begin
  6747. if FogEnable then
  6748. begin
  6749. Enable(stFog);
  6750. FogEnvironment.ApplyFog;
  6751. end
  6752. else
  6753. Disable(stFog);
  6754. end;
  6755. RenderScene(FCamera.FScene, aViewPort.Width, aViewPort.Height,
  6756. drawState,
  6757. baseObject);
  6758. end;
  6759. end;
  6760. if Assigned(FPostRender) then
  6761. if Owner is TComponent then
  6762. if not (csDesigning in TComponent(Owner).ComponentState) then
  6763. FPostRender(Self);
  6764. end;
  6765. Assert(Length(FViewMatrixStack) = 0,
  6766. 'Unbalance Push/PopViewMatrix.');
  6767. Assert(Length(FProjectionMatrixStack) = 0,
  6768. 'Unbalance Push/PopProjectionMatrix.');
  6769. end;
  6770. procedure TGLSceneBuffer.Render;
  6771. begin
  6772. Render(nil);
  6773. end;
  6774. procedure TGLSceneBuffer.Render(baseObject: TGLBaseSceneObject);
  6775. var
  6776. perfCounter, framePerf: Int64;
  6777. begin
  6778. if FRendering then
  6779. Exit;
  6780. if not Assigned(FRenderingContext) then
  6781. Exit;
  6782. if Freezed and (FFreezeBuffer <> nil) then
  6783. begin
  6784. RenderingContext.Activate;
  6785. try
  6786. RenderingContext.GLStates.ColorClearValue :=
  6787. ConvertWinColor(FBackgroundColor, FBackgroundAlpha);
  6788. ClearBuffers;
  6789. gl.MatrixMode(GL_PROJECTION);
  6790. gl.LoadIdentity;
  6791. gl.MatrixMode(GL_MODELVIEW);
  6792. gl.LoadIdentity;
  6793. gl.RasterPos2f(-1, -1);
  6794. gl.DrawPixels(FFreezedViewPort.Width, FFreezedViewPort.Height,
  6795. GL_RGBA, GL_UNSIGNED_BYTE, FFreezeBuffer);
  6796. if not (roNoSwapBuffers in ContextOptions) then
  6797. RenderingContext.SwapBuffers;
  6798. finally
  6799. RenderingContext.Deactivate;
  6800. end;
  6801. Exit;
  6802. end;
  6803. QueryPerformanceCounter(framePerf);
  6804. if Assigned(FCamera) and Assigned(FCamera.FScene) then
  6805. begin
  6806. FCamera.AbsoluteMatrixAsAddress;
  6807. FCamera.FScene.AddBuffer(Self);
  6808. end;
  6809. FRendering := True;
  6810. try
  6811. FRenderingContext.Activate;
  6812. try
  6813. if FFrameCount = 0 then
  6814. QueryPerformanceCounter(FFirstPerfCounter);
  6815. FRenderDPI := 96; // default value for screen
  6816. gl.ClearError;
  6817. SetupRenderingContext(FRenderingContext);
  6818. // clear the buffers
  6819. FRenderingContext.GLStates.ColorClearValue :=
  6820. ConvertWinColor(FBackgroundColor, FBackgroundAlpha);
  6821. ClearBuffers;
  6822. gl.CheckError;
  6823. // render
  6824. DoBaseRender(FViewport, RenderDPI, dsRendering, baseObject);
  6825. if not (roNoSwapBuffers in ContextOptions) then
  6826. RenderingContext.SwapBuffers;
  6827. // yes, calculate average frames per second...
  6828. Inc(FFrameCount);
  6829. QueryPerformanceCounter(perfCounter);
  6830. FLastFrameTime := (perfCounter - framePerf) / vCounterFrequency;
  6831. Dec(perfCounter, FFirstPerfCounter);
  6832. if perfCounter > 0 then
  6833. FFramesPerSecond := (FFrameCount * vCounterFrequency) / perfCounter;
  6834. gl.CheckError;
  6835. finally
  6836. FRenderingContext.Deactivate;
  6837. end;
  6838. if Assigned(FAfterRender) and (Owner is TComponent) then
  6839. if not (csDesigning in TComponent(Owner).ComponentState) then
  6840. FAfterRender(Self);
  6841. finally
  6842. FRendering := False;
  6843. end;
  6844. end;
  6845. procedure TGLSceneBuffer.RenderScene(aScene: TGLScene;
  6846. const viewPortSizeX, viewPortSizeY: Integer;
  6847. drawState: TGLDrawState;
  6848. baseObject: TGLBaseSceneObject);
  6849. var
  6850. i: Integer;
  6851. rci: TGLRenderContextInfo;
  6852. rightVector: TGLVector;
  6853. begin
  6854. FAfterRenderEffects.Clear;
  6855. aScene.FCurrentBuffer := Self;
  6856. FillChar(rci, SizeOf(rci), 0);
  6857. rci.scene := aScene;
  6858. rci.buffer := Self;
  6859. rci.afterRenderEffects := FAfterRenderEffects;
  6860. rci.objectsSorting := aScene.ObjectsSorting;
  6861. rci.visibilityCulling := aScene.VisibilityCulling;
  6862. rci.bufferFaceCull := FFaceCulling;
  6863. rci.bufferLighting := FLighting;
  6864. rci.bufferFog := FFogEnable;
  6865. rci.bufferDepthTest := FDepthTest;
  6866. rci.drawState := drawState;
  6867. rci.sceneAmbientColor := FAmbientColor.Color;
  6868. rci.primitiveMask := cAllMeshPrimitive;
  6869. with FCamera do
  6870. begin
  6871. rci.cameraPosition := FCameraAbsolutePosition;
  6872. rci.cameraDirection := FLastDirection;
  6873. NormalizeVector(rci.cameraDirection);
  6874. rci.cameraDirection.W := 0;
  6875. rightVector := VectorCrossProduct(rci.cameraDirection, Up.AsVector);
  6876. rci.cameraUp := VectorCrossProduct(rightVector, rci.cameraDirection);
  6877. NormalizeVector(rci.cameraUp);
  6878. with rci.rcci do
  6879. begin
  6880. origin := rci.cameraPosition;
  6881. clippingDirection := rci.cameraDirection;
  6882. viewPortRadius := FViewPortRadius;
  6883. nearClippingDistance := FNearPlane;
  6884. farClippingDistance := FNearPlane + FDepthOfView;
  6885. frustum := RenderingContext.PipelineTransformation.Frustum;
  6886. end;
  6887. end;
  6888. rci.viewPortSize.cx := viewPortSizeX;
  6889. rci.viewPortSize.cy := viewPortSizeY;
  6890. rci.renderDPI := FRenderDPI;
  6891. rci.GLStates := RenderingContext.GLStates;
  6892. rci.PipelineTransformation := RenderingContext.PipelineTransformation;
  6893. rci.proxySubObject := False;
  6894. rci.ignoreMaterials := (roNoColorBuffer in FContextOptions)
  6895. or (rci.drawState = dsPicking);
  6896. rci.amalgamating := rci.drawState = dsPicking;
  6897. rci.GLStates.SetColorWriting(not rci.ignoreMaterials);
  6898. if Assigned(FInitiateRendering) then
  6899. FInitiateRendering(Self, rci);
  6900. if aScene.InitializableObjects.Count <> 0 then
  6901. begin
  6902. // First initialize all objects and delete them from the list.
  6903. for I := aScene.InitializableObjects.Count - 1 downto 0 do
  6904. begin
  6905. aScene.InitializableObjects.Items[I].InitializeObject({Self?}aScene, rci);
  6906. aScene.InitializableObjects.Delete(I);
  6907. end;
  6908. end;
  6909. if RenderingContext.IsPraparationNeed then
  6910. RenderingContext.PrepareHandlesData;
  6911. if baseObject = nil then
  6912. begin
  6913. aScene.Objects.Render(rci);
  6914. end
  6915. else
  6916. baseObject.Render(rci);
  6917. rci.GLStates.SetColorWriting(True);
  6918. with FAfterRenderEffects do
  6919. if Count > 0 then
  6920. for i := 0 to Count - 1 do
  6921. TGLObjectAfterEffect(Items[i]).Render(rci);
  6922. if Assigned(FWrapUpRendering) then
  6923. FWrapUpRendering(Self, rci);
  6924. end;
  6925. procedure TGLSceneBuffer.SetBackgroundColor(AColor: TColor);
  6926. begin
  6927. if FBackgroundColor <> AColor then
  6928. begin
  6929. FBackgroundColor := AColor;
  6930. NotifyChange(Self);
  6931. end;
  6932. end;
  6933. procedure TGLSceneBuffer.SetBackgroundAlpha(alpha: Single);
  6934. begin
  6935. if FBackgroundAlpha <> alpha then
  6936. begin
  6937. FBackgroundAlpha := alpha;
  6938. NotifyChange(Self);
  6939. end;
  6940. end;
  6941. procedure TGLSceneBuffer.SetAmbientColor(AColor: TGLColor);
  6942. begin
  6943. FAmbientColor.Assign(AColor);
  6944. end;
  6945. procedure TGLSceneBuffer.SetCamera(ACamera: TGLCamera);
  6946. begin
  6947. if FCamera <> ACamera then
  6948. begin
  6949. if Assigned(FCamera) then
  6950. begin
  6951. if Assigned(FCamera.FScene) then
  6952. FCamera.FScene.RemoveBuffer(Self);
  6953. FCamera := nil;
  6954. end;
  6955. if Assigned(ACamera) and Assigned(ACamera.FScene) then
  6956. begin
  6957. FCamera := ACamera;
  6958. FCamera.TransformationChanged;
  6959. end;
  6960. NotifyChange(Self);
  6961. end;
  6962. end;
  6963. procedure TGLSceneBuffer.SetContextOptions(Options: TGLContextOptions);
  6964. begin
  6965. if FContextOptions <> Options then
  6966. begin
  6967. FContextOptions := Options;
  6968. DoStructuralChange;
  6969. end;
  6970. end;
  6971. procedure TGLSceneBuffer.SetDepthTest(AValue: Boolean);
  6972. begin
  6973. if FDepthTest <> AValue then
  6974. begin
  6975. FDepthTest := AValue;
  6976. NotifyChange(Self);
  6977. end;
  6978. end;
  6979. procedure TGLSceneBuffer.SetFaceCulling(AValue: Boolean);
  6980. begin
  6981. if FFaceCulling <> AValue then
  6982. begin
  6983. FFaceCulling := AValue;
  6984. NotifyChange(Self);
  6985. end;
  6986. end;
  6987. procedure TGLSceneBuffer.SetLayer(const Value: TGLContextLayer);
  6988. begin
  6989. if FLayer <> Value then
  6990. begin
  6991. FLayer := Value;
  6992. DoStructuralChange;
  6993. end;
  6994. end;
  6995. procedure TGLSceneBuffer.SetLighting(aValue: Boolean);
  6996. begin
  6997. if FLighting <> aValue then
  6998. begin
  6999. FLighting := aValue;
  7000. NotifyChange(Self);
  7001. end;
  7002. end;
  7003. procedure TGLSceneBuffer.SetAntiAliasing(const val: TGLAntiAliasing);
  7004. begin
  7005. if FAntiAliasing <> val then
  7006. begin
  7007. FAntiAliasing := val;
  7008. DoStructuralChange;
  7009. end;
  7010. end;
  7011. procedure TGLSceneBuffer.SetDepthPrecision(const val: TGLDepthPrecision);
  7012. begin
  7013. if FDepthPrecision <> val then
  7014. begin
  7015. FDepthPrecision := val;
  7016. DoStructuralChange;
  7017. end;
  7018. end;
  7019. procedure TGLSceneBuffer.SetColorDepth(const val: TGLColorDepth);
  7020. begin
  7021. if FColorDepth <> val then
  7022. begin
  7023. FColorDepth := val;
  7024. DoStructuralChange;
  7025. end;
  7026. end;
  7027. procedure TGLSceneBuffer.SetShadeModel(const val: TGLShadeModel);
  7028. begin
  7029. if FShadeModel <> val then
  7030. begin
  7031. FShadeModel := val;
  7032. NotifyChange(Self);
  7033. end;
  7034. end;
  7035. procedure TGLSceneBuffer.SetFogEnable(AValue: Boolean);
  7036. begin
  7037. if FFogEnable <> AValue then
  7038. begin
  7039. FFogEnable := AValue;
  7040. NotifyChange(Self);
  7041. end;
  7042. end;
  7043. procedure TGLSceneBuffer.SetGLFogEnvironment(AValue: TGLFogEnvironment);
  7044. begin
  7045. FFogEnvironment.Assign(AValue);
  7046. NotifyChange(Self);
  7047. end;
  7048. function TGLSceneBuffer.StoreFog: Boolean;
  7049. begin
  7050. Result := (not FFogEnvironment.IsAtDefaultValues);
  7051. end;
  7052. procedure TGLSceneBuffer.SetAccumBufferBits(const val: Integer);
  7053. begin
  7054. if FAccumBufferBits <> val then
  7055. begin
  7056. FAccumBufferBits := val;
  7057. DoStructuralChange;
  7058. end;
  7059. end;
  7060. procedure TGLSceneBuffer.DoChange;
  7061. begin
  7062. if (not FRendering) and Assigned(FOnChange) then
  7063. FOnChange(Self);
  7064. end;
  7065. procedure TGLSceneBuffer.DoStructuralChange;
  7066. var
  7067. bCall: Boolean;
  7068. begin
  7069. if Assigned(Owner) then
  7070. bCall := not (csLoading in TComponent(GetOwner).ComponentState)
  7071. else
  7072. bCall := True;
  7073. if bCall and Assigned(FOnStructuralChange) then
  7074. FOnStructuralChange(Self);
  7075. end;
  7076. // ------------------
  7077. // ------------------ TGLNonVisualViewer ------------------
  7078. // ------------------
  7079. constructor TGLNonVisualViewer.Create(AOwner: TComponent);
  7080. begin
  7081. inherited Create(AOwner);
  7082. FWidth := 256;
  7083. FHeight := 256;
  7084. FBuffer := TGLSceneBuffer.Create(Self);
  7085. FBuffer.OnChange := DoBufferChange;
  7086. FBuffer.OnStructuralChange := DoBufferStructuralChange;
  7087. FBuffer.OnPrepareGLContext := DoOnPrepareGLContext;
  7088. end;
  7089. destructor TGLNonVisualViewer.Destroy;
  7090. begin
  7091. FBuffer.Free;
  7092. inherited Destroy;
  7093. end;
  7094. procedure TGLNonVisualViewer.Notification(AComponent: TComponent; Operation:
  7095. TOperation);
  7096. begin
  7097. if (Operation = opRemove) and (AComponent = Camera) then
  7098. Camera := nil;
  7099. inherited;
  7100. end;
  7101. procedure TGLNonVisualViewer.CopyToTexture(aTexture: TGLTexture);
  7102. begin
  7103. CopyToTexture(aTexture, 0, 0, Width, Height, 0, 0);
  7104. end;
  7105. procedure TGLNonVisualViewer.CopyToTexture(aTexture: TGLTexture;
  7106. xSrc, ySrc, width, height: Integer;
  7107. xDest, yDest: Integer);
  7108. begin
  7109. Buffer.CopyToTexture(aTexture, xSrc, ySrc, width, height, xDest, yDest);
  7110. end;
  7111. procedure TGLNonVisualViewer.CopyToTextureMRT(aTexture: TGLTexture;
  7112. BufferIndex: integer);
  7113. begin
  7114. CopyToTextureMRT(aTexture, 0, 0, Width, Height, 0, 0, BufferIndex);
  7115. end;
  7116. procedure TGLNonVisualViewer.CopyToTextureMRT(aTexture: TGLTexture; xSrc,
  7117. ySrc, width, height, xDest, yDest, BufferIndex: integer);
  7118. var
  7119. target, handle: Integer;
  7120. buf: Pointer;
  7121. createTexture: Boolean;
  7122. procedure CreateNewTexture;
  7123. begin
  7124. GetMem(buf, Width * Height * 4);
  7125. try // float_type
  7126. gl.ReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
  7127. case aTexture.MinFilter of
  7128. miNearest, miLinear:
  7129. gl.TexImage2d(target, 0, aTexture.OpenGLTextureFormat, Width, Height,
  7130. 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
  7131. else
  7132. if gl.SGIS_generate_mipmap and (target = GL_TEXTURE_2D) then
  7133. begin
  7134. // hardware-accelerated when supported
  7135. gl.TexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
  7136. gl.TexImage2d(target, 0, aTexture.OpenGLTextureFormat, Width, Height,
  7137. 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
  7138. end
  7139. else
  7140. begin
  7141. gl.TexImage2d(target, 0, aTexture.OpenGLTextureFormat, Width, Height,
  7142. 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
  7143. gl.GenerateMipmap(target);
  7144. end;
  7145. end;
  7146. finally
  7147. FreeMem(buf);
  7148. end;
  7149. end;
  7150. begin
  7151. if Buffer.RenderingContext <> nil then
  7152. begin
  7153. Buffer.RenderingContext.Activate;
  7154. try
  7155. target := DecodeTextureTarget(aTexture.Image.NativeTextureTarget);
  7156. CreateTexture := true;
  7157. if aTexture.IsFloatType then
  7158. begin // float_type special treatment
  7159. CreateTexture := false;
  7160. handle := aTexture.Handle;
  7161. end
  7162. else if (target <> GL_TEXTURE_CUBE_MAP_ARB) or (FCubeMapRotIdx = 0) then
  7163. begin
  7164. CreateTexture := not aTexture.IsHandleAllocated;
  7165. if CreateTexture then
  7166. handle := aTexture.AllocateHandle
  7167. else
  7168. handle := aTexture.Handle;
  7169. end
  7170. else
  7171. handle := aTexture.Handle;
  7172. // For MRT
  7173. gl.ReadBuffer(MRT_BUFFERS[BufferIndex]);
  7174. Buffer.RenderingContext.GLStates.TextureBinding[0, EncodeGLTextureTarget(target)] := handle;
  7175. if target = GL_TEXTURE_CUBE_MAP_ARB then
  7176. target := GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + FCubeMapRotIdx;
  7177. if CreateTexture then
  7178. CreateNewTexture
  7179. else
  7180. gl.CopyTexSubImage2D(target, 0, xDest, yDest, xSrc, ySrc, Width, Height);
  7181. gl.ClearError;
  7182. finally
  7183. Buffer.RenderingContext.Deactivate;
  7184. end;
  7185. end;
  7186. end;
  7187. procedure TGLNonVisualViewer.SetupCubeMapCamera(Sender: TObject);
  7188. (*
  7189. const
  7190. cFaceMat: array[0..5] of TGLMatrix =
  7191. (
  7192. (X: (X:0; Y:0; Z:-1; W:0);
  7193. Y: (X:0; Y:-1; Z:0; W:0);
  7194. Z: (X:-1; Y:0; Z:0; W:0);
  7195. W: (X:0; Y:0; Z:0; W:1)),
  7196. (X:(X:2.4335928828e-08; Y:0; Z:1; W:0);
  7197. Y:(X:0; Y:-1; Z:0; W:0);
  7198. Z:(X:1; Y:0; Z:-2.4335928828e-08; W:0);
  7199. W:(X:0; Y:0; Z:0; W:1)),
  7200. (X:(X:1; Y:1.2167964414e-08; Z:-1.4805936071e-16; W:0);
  7201. Y:(X:0; Y:-1.2167964414e-08; Z:-1; W:0);
  7202. Z:(X:-1.2167964414e-08; Y:1; Z:-1.2167964414e-08; W:0);
  7203. W:(X:0; Y:0; Z:0; W:1)),
  7204. (X:(X:1; Y:-1.2167964414e-08; Z:-1.4805936071e-16; W:0);
  7205. Y:(X:0; Y:-1.2167964414e-08; Z:1; W:0);
  7206. Z:(X:-1.2167964414e-08; Y:-1; Z:-1.2167964414e-08; W:0);
  7207. W:(X:0; Y:0; Z:0; W:1)),
  7208. (X:(X:1; Y:0; Z:-1.2167964414e-08; W:0);
  7209. Y:(X:0; Y:-1; Z:0; W:0);
  7210. Z:(X:-1.2167964414e-08; Y:0; Z:-1; W:0);
  7211. W:(X:0; Y:0; Z:0; W:1)),
  7212. (X:(X:-1; Y:0; Z:-1.2167964414e-08; W:0);
  7213. Y:(X:0; Y:-1; Z:0; W:0);
  7214. Z:(X:-1.2167964414e-08; Y:0; Z:1; W:0);
  7215. W:(X:0; Y:0; Z:0; W:1))
  7216. );
  7217. *)
  7218. var
  7219. TM: TGLMatrix;
  7220. begin
  7221. // Setup appropriate FOV
  7222. with CurrentGLContext.PipelineTransformation do
  7223. begin
  7224. SetProjectionMatrix(CreatePerspectiveMatrix(90, 1, FCubeMapZNear, FCubeMapZFar));
  7225. TM := CreateTranslationMatrix(FCubeMapTranslation);
  7226. (* SetViewMatrix(MatrixMultiply(cFaceMat[FCubeMapRotIdx], TM)); *)
  7227. end;
  7228. end;
  7229. procedure TGLNonVisualViewer.RenderCubeMapTextures(cubeMapTexture: TGLTexture;
  7230. zNear: Single = 0;
  7231. zFar: Single = 0);
  7232. var
  7233. oldEvent: TNotifyEvent;
  7234. begin
  7235. Assert((Width = Height), 'Memory Viewer must render to a square!');
  7236. Assert(Assigned(FBuffer.FCamera), 'Camera not specified');
  7237. Assert(Assigned(cubeMapTexture), 'Texture not specified');
  7238. if zFar <= 0 then
  7239. zFar := FBuffer.FCamera.DepthOfView;
  7240. if zNear <= 0 then
  7241. zNear := zFar * 0.001;
  7242. oldEvent := FBuffer.FCamera.FDeferredApply;
  7243. FBuffer.FCamera.FDeferredApply := SetupCubeMapCamera;
  7244. FCubeMapZNear := zNear;
  7245. FCubeMapZFar := zFar;
  7246. VectorScale(FBuffer.FCamera.AbsolutePosition, -1, FCubeMapTranslation);
  7247. try
  7248. FCubeMapRotIdx := 0;
  7249. while FCubeMapRotIdx < 6 do
  7250. begin
  7251. Render;
  7252. Buffer.CopyToTexture(cubeMapTexture, 0, 0, Width, Height, 0, 0,
  7253. GL_TEXTURE_CUBE_MAP_POSITIVE_X + FCubeMapRotIdx);
  7254. Inc(FCubeMapRotIdx);
  7255. end;
  7256. finally
  7257. FBuffer.FCamera.FDeferredApply := oldEvent;
  7258. end;
  7259. end;
  7260. procedure TGLNonVisualViewer.SetBeforeRender(const val: TNotifyEvent);
  7261. begin
  7262. FBuffer.BeforeRender := val;
  7263. end;
  7264. function TGLNonVisualViewer.GetBeforeRender: TNotifyEvent;
  7265. begin
  7266. Result := FBuffer.BeforeRender;
  7267. end;
  7268. procedure TGLNonVisualViewer.SetPostRender(const val: TNotifyEvent);
  7269. begin
  7270. FBuffer.PostRender := val;
  7271. end;
  7272. function TGLNonVisualViewer.GetPostRender: TNotifyEvent;
  7273. begin
  7274. Result := FBuffer.PostRender;
  7275. end;
  7276. procedure TGLNonVisualViewer.SetAfterRender(const val: TNotifyEvent);
  7277. begin
  7278. FBuffer.AfterRender := val;
  7279. end;
  7280. function TGLNonVisualViewer.GetAfterRender: TNotifyEvent;
  7281. begin
  7282. Result := FBuffer.AfterRender;
  7283. end;
  7284. procedure TGLNonVisualViewer.SetCamera(const val: TGLCamera);
  7285. begin
  7286. FBuffer.Camera := val;
  7287. end;
  7288. function TGLNonVisualViewer.GetCamera: TGLCamera;
  7289. begin
  7290. Result := FBuffer.Camera;
  7291. end;
  7292. procedure TGLNonVisualViewer.SetBuffer(const val: TGLSceneBuffer);
  7293. begin
  7294. FBuffer.Assign(val);
  7295. end;
  7296. procedure TGLNonVisualViewer.DoOnPrepareGLContext(sender: TObject);
  7297. begin
  7298. PrepareGLContext;
  7299. end;
  7300. procedure TGLNonVisualViewer.PrepareGLContext;
  7301. begin
  7302. // nothing, reserved for subclasses
  7303. end;
  7304. procedure TGLNonVisualViewer.DoBufferChange(Sender: TObject);
  7305. begin
  7306. // nothing, reserved for subclasses
  7307. end;
  7308. procedure TGLNonVisualViewer.DoBufferStructuralChange(Sender: TObject);
  7309. begin
  7310. FBuffer.DestroyRC;
  7311. end;
  7312. procedure TGLNonVisualViewer.SetWidth(const val: Integer);
  7313. begin
  7314. if val <> FWidth then
  7315. begin
  7316. FWidth := val;
  7317. if FWidth < 1 then
  7318. FWidth := 1;
  7319. DoBufferStructuralChange(Self);
  7320. end;
  7321. end;
  7322. procedure TGLNonVisualViewer.SetHeight(const val: Integer);
  7323. begin
  7324. if val <> FHeight then
  7325. begin
  7326. FHeight := val;
  7327. if FHeight < 1 then
  7328. FHeight := 1;
  7329. DoBufferStructuralChange(Self);
  7330. end;
  7331. end;
  7332. // ------------------
  7333. // ------------------ TGLMemoryViewer ------------------
  7334. // ------------------
  7335. constructor TGLMemoryViewer.Create(AOwner: TComponent);
  7336. begin
  7337. inherited Create(AOwner);
  7338. Width := 256;
  7339. Height := 256;
  7340. FBufferCount := 1;
  7341. end;
  7342. procedure TGLMemoryViewer.InstantiateRenderingContext;
  7343. begin
  7344. if FBuffer.RenderingContext = nil then
  7345. begin
  7346. FBuffer.SetViewPort(0, 0, Width, Height);
  7347. FBuffer.CreateRC(HWND(0), True, FBufferCount);
  7348. end;
  7349. end;
  7350. procedure TGLMemoryViewer.Render(baseObject: TGLBaseSceneObject = nil);
  7351. begin
  7352. InstantiateRenderingContext;
  7353. FBuffer.Render(baseObject);
  7354. end;
  7355. procedure TGLMemoryViewer.SetBufferCount(const Value: integer);
  7356. const
  7357. MaxAxuBufCount = 4; // Current hardware limit = 4
  7358. begin
  7359. if FBufferCount = Value then
  7360. Exit;
  7361. FBufferCount := Value;
  7362. if FBufferCount < 1 then
  7363. FBufferCount := 1;
  7364. if FBufferCount > MaxAxuBufCount then
  7365. FBufferCount := MaxAxuBufCount;
  7366. // Request a new Instantiation of RC on next render
  7367. FBuffer.DestroyRC;
  7368. end;
  7369. // ------------------
  7370. // ------------------ TGLInitializableObjectList ------------------
  7371. // ------------------
  7372. function TGLInitializableObjectList.Add(const Item: IGLInitializable): Integer;
  7373. begin
  7374. Result := inherited Add(Pointer(Item));
  7375. end;
  7376. function TGLInitializableObjectList.GetItems(
  7377. const Index: Integer): IGLInitializable;
  7378. begin
  7379. Result := IGLInitializable(inherited Get(Index));
  7380. end;
  7381. procedure TGLInitializableObjectList.PutItems(const Index: Integer;
  7382. const Value: IGLInitializable);
  7383. begin
  7384. inherited Put(Index, Pointer(Value));
  7385. end;
  7386. //------------------------------------------------------------------------------
  7387. initialization
  7388. //------------------------------------------------------------------------------
  7389. RegisterClasses([TGLLightSource, TGLCamera, TGLProxyObject,
  7390. TGLScene, TGLDirectOpenGL, TGLRenderPoint, TGLMemoryViewer]);
  7391. // preparation for high resolution timer
  7392. QueryPerformanceFrequency(vCounterFrequency);
  7393. end.