GLS.Scene.pas 252 KB

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