GLS.Scene.pas 252 KB

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