GLVectorGeometry.pas 251 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852
  1. //
  2. // This unit is part of the GLScene Engine, http://glscene.org
  3. //
  4. unit GLVectorGeometry;
  5. (*
  6. Base classes and structures.
  7. Most common functions/procedures come in various flavours (using overloads),
  8. the naming convention is :
  9. TypeOperation: functions returning a result, or accepting a "var" as last
  10. parameter to place result (VectorAdd, VectorCrossProduct...)
  11. OperationType : procedures taking as first parameter a "var" that will be
  12. used as operand and result (AddVector, CombineVector...)
  13. As a general rule, procedures implementations (asm or not) are the fastest
  14. (up to 800% faster than function equivalents), due to reduced return value
  15. duplication overhead (the exception being the matrix operations).
  16. For better performance, it is recommended not to use the "Math" unit
  17. that comes with Delphi, and only use functions/procedures from this unit
  18. (the single-based functions have been optimized and are up to 100% faster,
  19. than extended-based ones from "Math").
  20. *)
  21. interface
  22. {$I GLScene.inc}
  23. uses
  24. System.SysUtils,
  25. System.Types,
  26. System.Math,
  27. GLVectorTypes;
  28. const
  29. cMaxArray = (MaxInt shr 4);
  30. cColinearBias = 1E-8;
  31. type
  32. (* Data types needed for 3D graphics calculation, included are 'C like'
  33. aliases for each type (to be conformal with OpenGL types) *)
  34. PFloat = PSingle;
  35. PTexPoint = ^TTexPoint;
  36. TTexPoint = packed record
  37. S, T: Single;
  38. end;
  39. (* Types to specify continous streams of a specific type
  40. switch off range checking to access values beyond the limits *)
  41. PByteVector = ^TByteVector;
  42. PByteArray = PByteVector;
  43. TByteVector = array [0 .. cMaxArray] of Byte;
  44. PWordVector = ^TWordVector;
  45. TWordVector = array [0 .. cMaxArray] of Word;
  46. PIntegerVector = ^TIntegerVector;
  47. PIntegerArray = PIntegerVector;
  48. TIntegerVector = array [0 .. cMaxArray] of Integer;
  49. PFloatVector = ^TFloatVector;
  50. PFloatArray = PFloatVector;
  51. PSingleArray = PFloatArray;
  52. TFloatVector = array [0 .. cMaxArray] of Single;
  53. TSingleArray = array of Single;
  54. PDoubleVector = ^TDoubleVector;
  55. PDoubleArray = PDoubleVector;
  56. TDoubleVector = array [0 .. cMaxArray] of Double;
  57. PExtendedVector = ^TExtendedVector;
  58. PExtendedArray = PExtendedVector;
  59. TExtendedVector = array [0 .. cMaxArray] of Extended;
  60. PPointerVector = ^TPointerVector;
  61. PPointerArray = PPointerVector;
  62. TPointerVector = array [0 .. cMaxArray] of Pointer;
  63. PCardinalVector = ^TCardinalVector;
  64. PCardinalArray = PCardinalVector;
  65. TCardinalVector = array [0 .. cMaxArray] of Cardinal;
  66. PLongWordVector = ^TLongWordVector;
  67. PLongWordArray = PLongWordVector;
  68. TLongWordVector = array [0 .. cMaxArray] of LongWord;
  69. (*
  70. Common vector and matrix types with predefined limits
  71. indices correspond like: x -> 0
  72. y -> 1
  73. z -> 2
  74. w -> 3
  75. *)
  76. PHomogeneousByteVector = ^THomogeneousByteVector;
  77. THomogeneousByteVector = TVector4b;
  78. PHomogeneousWordVector = ^THomogeneousWordVector;
  79. THomogeneousWordVector = TVector4w;
  80. PHomogeneousIntVector = ^THomogeneousIntVector;
  81. THomogeneousIntVector = TVector4i;
  82. PHomogeneousFltVector = ^THomogeneousFltVector;
  83. THomogeneousFltVector = TVector4f;
  84. PHomogeneousDblVector = ^THomogeneousDblVector;
  85. THomogeneousDblVector = TVector4d;
  86. PHomogeneousExtVector = ^THomogeneousExtVector;
  87. THomogeneousExtVector = TVector4e;
  88. PHomogeneousPtrVector = ^THomogeneousPtrVector;
  89. THomogeneousPtrVector = TVector4p;
  90. PAffineByteVector = ^TAffineByteVector;
  91. TAffineByteVector = TVector3b;
  92. PAffineWordVector = ^TAffineWordVector;
  93. TAffineWordVector = TVector3w;
  94. PAffineIntVector = ^TAffineIntVector;
  95. TAffineIntVector = TVector3i;
  96. PAffineFltVector = ^TAffineFltVector;
  97. TAffineFltVector = TVector3f;
  98. PAffineDblVector = ^TAffineDblVector;
  99. TAffineDblVector = TVector3d;
  100. PAffineExtVector = ^TAffineExtVector;
  101. TAffineExtVector = TVector3e;
  102. PAffinePtrVector = ^TAffinePtrVector;
  103. TAffinePtrVector = TVector3p;
  104. PVector2f = ^TVector2f;
  105. // some simplified names
  106. PVector = ^TVector;
  107. TVector = THomogeneousFltVector;
  108. PHomogeneousVector = ^THomogeneousVector;
  109. THomogeneousVector = THomogeneousFltVector;
  110. PAffineVector = ^TAffineVector;
  111. TAffineVector = TVector3f;
  112. PVertex = ^TVertex;
  113. TVertex = TAffineVector;
  114. // Arrays of vectors
  115. PAffineVectorArray = ^TAffineVectorArray;
  116. TAffineVectorArray = array [0 .. MaxInt shr 4] of TAffineVector;
  117. PVectorArray = ^TVectorArray;
  118. TVectorArray = array [0 .. MaxInt shr 5] of TVector;
  119. PTexPointArray = ^TTexPointArray;
  120. TTexPointArray = array [0 .. MaxInt shr 4] of TTexPoint;
  121. // Matrices
  122. THomogeneousByteMatrix = TMatrix4b;
  123. THomogeneousWordMatrix = array [0 .. 3] of THomogeneousWordVector;
  124. THomogeneousIntMatrix = TMatrix4i;
  125. THomogeneousFltMatrix = TMatrix4f;
  126. THomogeneousDblMatrix = TMatrix4d;
  127. THomogeneousExtMatrix = array [0 .. 3] of THomogeneousExtVector;
  128. TAffineByteMatrix = TMatrix3b;
  129. TAffineWordMatrix = array [0 .. 2] of TAffineWordVector;
  130. TAffineIntMatrix = TMatrix3i;
  131. TAffineFltMatrix = TMatrix3f;
  132. TAffineDblMatrix = TMatrix3d;
  133. TAffineExtMatrix = array [0 .. 2] of TAffineExtVector;
  134. // Some simplified names
  135. PMatrix = ^TMatrix;
  136. TMatrix = THomogeneousFltMatrix;
  137. TMatrixArray = array [0 .. MaxInt shr 7] of TMatrix;
  138. PMatrixArray = ^TMatrixArray;
  139. PHomogeneousMatrix = ^THomogeneousMatrix;
  140. THomogeneousMatrix = THomogeneousFltMatrix;
  141. PAffineMatrix = ^TAffineMatrix;
  142. TAffineMatrix = TAffineFltMatrix;
  143. (* A plane equation.
  144. Defined by its equation A.x+B.y+C.z+D , a plane can be mapped to the
  145. homogeneous space coordinates, and this is what we are doing here.
  146. The typename is just here for easing up data manipulation *)
  147. THmgPlane = TVector;
  148. TDoubleHmgPlane = THomogeneousDblVector;
  149. // q = ([x, y, z], w)
  150. PQuaternion = ^TQuaternion;
  151. TQuaternion = record
  152. case Integer of
  153. 0: (ImagPart: TAffineVector;
  154. RealPart: Single);
  155. 1: (X, Y, Z, W: Single);
  156. end;
  157. PQuaternionArray = ^TQuaternionArray;
  158. TQuaternionArray = array [0 .. MaxInt shr 5] of TQuaternion;
  159. TRectangle = record
  160. Left, Top, Width, Height: Integer;
  161. end;
  162. PFrustum = ^TFrustum;
  163. TFrustum = record
  164. pLeft, pTop, pRight, pBottom, pNear, pFar: THmgPlane;
  165. end;
  166. TTransType = (ttScaleX, ttScaleY, ttScaleZ,
  167. ttShearXY, ttShearXZ, ttShearYZ,
  168. ttRotateX, ttRotateY, ttRotateZ,
  169. ttTranslateX, ttTranslateY, ttTranslateZ,
  170. ttPerspectiveX, ttPerspectiveY, ttPerspectiveZ, ttPerspectiveW);
  171. (* Used to describe a sequence of transformations in following order:
  172. [Sx][Sy][Sz][ShearXY][ShearXZ][ShearZY][Rx][Ry][Rz][Tx][Ty][Tz][P(x,y,z,w)]
  173. constants are declared for easier access (see MatrixDecompose below) *)
  174. TTransformations = array [TTransType] of Single;
  175. TPackedRotationMatrix = array [0 .. 2] of SmallInt;
  176. const
  177. // TexPoints (2D space)
  178. XTexPoint: TTexPoint = (S: 1; T: 0);
  179. YTexPoint: TTexPoint = (S: 0; T: 1);
  180. XYTexPoint: TTexPoint = (S: 1; T: 1);
  181. NullTexPoint: TTexPoint = (S: 0; T: 0);
  182. MidTexPoint: TTexPoint = (S: 0.5; T: 0.5);
  183. // standard vectors
  184. XVector: TAffineVector = (X: 1; Y: 0; Z: 0);
  185. YVector: TAffineVector = (X: 0; Y: 1; Z: 0);
  186. ZVector: TAffineVector = (X: 0; Y: 0; Z: 1);
  187. XYVector: TAffineVector = (X: 1; Y: 1; Z: 0);
  188. XZVector: TAffineVector = (X: 1; Y: 0; Z: 1);
  189. YZVector: TAffineVector = (X: 0; Y: 1; Z: 1);
  190. XYZVector: TAffineVector = (X: 1; Y: 1; Z: 1);
  191. NullVector: TAffineVector = (X: 0; Y: 0; Z: 0);
  192. MinusXVector: TAffineVector = (X: - 1; Y: 0; Z: 0);
  193. MinusYVector: TAffineVector = (X: 0; Y: - 1; Z: 0);
  194. MinusZVector: TAffineVector = (X: 0; Y: 0; Z: - 1);
  195. // Standard homogeneous vectors
  196. XHmgVector: THomogeneousVector = (X: 1; Y: 0; Z: 0; W: 0);
  197. YHmgVector: THomogeneousVector = (X: 0; Y: 1; Z: 0; W: 0);
  198. ZHmgVector: THomogeneousVector = (X: 0; Y: 0; Z: 1; W: 0);
  199. WHmgVector: THomogeneousVector = (X: 0; Y: 0; Z: 0; W: 1);
  200. XYHmgVector: THomogeneousVector = (X: 1; Y: 1; Z: 0; W: 0);
  201. YZHmgVector: THomogeneousVector = (X: 0; Y: 1; Z: 1; W: 0);
  202. XZHmgVector: THomogeneousVector = (X: 1; Y: 0; Z: 1; W: 0);
  203. XYZHmgVector: THomogeneousVector = (X: 1; Y: 1; Z: 1; W: 0);
  204. XYZWHmgVector: THomogeneousVector = (X: 1; Y: 1; Z: 1; W: 1);
  205. NullHmgVector: THomogeneousVector = (X: 0; Y: 0; Z: 0; W: 0);
  206. // Standard homogeneous points
  207. XHmgPoint: THomogeneousVector = (X: 1; Y: 0; Z: 0; W: 1);
  208. YHmgPoint: THomogeneousVector = (X: 0; Y: 1; Z: 0; W: 1);
  209. ZHmgPoint: THomogeneousVector = (X: 0; Y: 0; Z: 1; W: 1);
  210. WHmgPoint: THomogeneousVector = (X: 0; Y: 0; Z: 0; W: 1);
  211. NullHmgPoint: THomogeneousVector = (X: 0; Y: 0; Z: 0; W: 1);
  212. IdentityMatrix: TAffineMatrix = (V: ((X: 1; Y: 0; Z: 0), (X: 0; Y: 1;
  213. Z: 0), (X: 0; Y: 0; Z: 1)));
  214. IdentityHmgMatrix: TMatrix = (V: ((X: 1; Y: 0; Z: 0; W: 0), (X: 0; Y: 1; Z: 0;
  215. W: 0), (X: 0; Y: 0; Z: 1; W: 0), (X: 0; Y: 0; Z: 0; W: 1)));
  216. IdentityHmgDblMatrix: THomogeneousDblMatrix = (V: ((X: 1; Y: 0; Z: 0;
  217. W: 0), (X: 0; Y: 1; Z: 0; W: 0), (X: 0; Y: 0; Z: 1; W: 0), (X: 0; Y: 0;
  218. Z: 0; W: 1)));
  219. EmptyMatrix: TAffineMatrix = (V: ((X: 0; Y: 0; Z: 0), (X: 0; Y: 0;
  220. Z: 0), (X: 0; Y: 0; Z: 0)));
  221. EmptyHmgMatrix: TMatrix = (V: ((X: 0; Y: 0; Z: 0; W: 0), (X: 0; Y: 0; Z: 0;
  222. W: 0), (X: 0; Y: 0; Z: 0; W: 0), (X: 0; Y: 0; Z: 0; W: 0)));
  223. // Quaternions
  224. IdentityQuaternion: TQuaternion = (ImagPart: (X: 0; Y: 0; Z: 0); RealPart: 1);
  225. // Some very small numbers
  226. EPSILON: Single = 1E-40;
  227. EPSILON2: Single = 1E-30;
  228. (* --------------------------------------------------------------------------
  229. Vector functions
  230. --------------------------------------------------------------------------*)
  231. function TexPointMake(const S, T: Single): TTexPoint; inline;
  232. function AffineVectorMake(const X, Y, Z: Single): TAffineVector; overload; inline;
  233. function AffineVectorMake(const V: TVector): TAffineVector; overload; inline;
  234. procedure SetAffineVector(out V: TAffineVector; const X, Y, Z: Single); overload; inline;
  235. procedure SetVector(out V: TAffineVector; const X, Y, Z: Single); overload;inline;
  236. procedure SetVector(out V: TAffineVector; const vSrc: TVector); overload; inline;
  237. procedure SetVector(out V: TAffineVector; const vSrc: TAffineVector); overload; inline;
  238. procedure SetVector(out V: TAffineDblVector; const vSrc: TAffineVector); overload; inline;
  239. procedure SetVector(out V: TAffineDblVector; const vSrc: TVector); overload; inline;
  240. function VectorMake(const V: TAffineVector; W: Single = 0): TVector; overload; inline;
  241. function VectorMake(const X, Y, Z: Single; W: Single = 0): TVector; overload; inline;
  242. function VectorMake(const Q: TQuaternion): TVector; overload; inline;
  243. function PointMake(const X, Y, Z: Single): TVector; overload; inline;
  244. function PointMake(const V: TAffineVector): TVector; overload; inline;
  245. function PointMake(const V: TVector): TVector; overload;inline;
  246. procedure SetVector(out V: TVector; const X, Y, Z: Single; W: Single = 0); overload; inline;
  247. procedure SetVector(out V: TVector; const av: TAffineVector; W: Single = 0); overload; inline;
  248. procedure SetVector(out V: TVector; const vSrc: TVector); overload; inline;
  249. procedure MakePoint(out V: TVector; const X, Y, Z: Single); overload; inline;
  250. procedure MakePoint(out V: TVector; const av: TAffineVector); overload;inline;
  251. procedure MakePoint(out V: TVector; const av: TVector); overload; inline;
  252. procedure MakeVector(out V: TAffineVector; const X, Y, Z: Single); overload; inline;
  253. procedure MakeVector(out V: TVector; const X, Y, Z: Single); overload; inline;
  254. procedure MakeVector(out V: TVector; const av: TAffineVector); overload; inline;
  255. procedure MakeVector(out V: TVector; const av: TVector); overload; inline;
  256. procedure RstVector(var V: TAffineVector); overload; inline;
  257. procedure RstVector(var V: TVector); overload; inline;
  258. function VectorEquals(const Vector1, Vector2: TVector2f): Boolean; overload; inline;
  259. function VectorEquals(const Vector1, Vector2: TVector2i): Boolean; overload; inline;
  260. function VectorEquals(const V1, V2: TVector2d): Boolean; overload;inline;
  261. function VectorEquals(const V1, V2: TVector2s): Boolean; overload;inline;
  262. function VectorEquals(const V1, V2: TVector2b): Boolean; overload;inline;
  263. // function VectorEquals(const V1, V2: TVector3f): Boolean; overload; //declared further
  264. function VectorEquals(const V1, V2: TVector3i): Boolean; overload;inline;
  265. function VectorEquals(const V1, V2: TVector3d): Boolean; overload;inline;
  266. function VectorEquals(const V1, V2: TVector3s): Boolean; overload;inline;
  267. function VectorEquals(const V1, V2: TVector3b): Boolean; overload;inline;
  268. // function VectorEquals(const V1, V2: TVector4f): Boolean; overload; //declared further
  269. function VectorEquals(const V1, V2: TVector4i): Boolean; overload;inline;
  270. function VectorEquals(const V1, V2: TVector4d): Boolean; overload;inline;
  271. function VectorEquals(const V1, V2: TVector4s): Boolean; overload;inline;
  272. function VectorEquals(const V1, V2: TVector4b): Boolean; overload;inline;
  273. // 3x3
  274. function MatrixEquals(const Matrix1, Matrix2: TMatrix3f): Boolean; overload;
  275. function MatrixEquals(const Matrix1, Matrix2: TMatrix3i): Boolean; overload;
  276. function MatrixEquals(const Matrix1, Matrix2: TMatrix3d): Boolean; overload;
  277. function MatrixEquals(const Matrix1, Matrix2: TMatrix3s): Boolean; overload;
  278. function MatrixEquals(const Matrix1, Matrix2: TMatrix3b): Boolean; overload;
  279. // 4x4
  280. function MatrixEquals(const Matrix1, Matrix2: TMatrix4f): Boolean; overload;
  281. function MatrixEquals(const Matrix1, Matrix2: TMatrix4i): Boolean; overload;
  282. function MatrixEquals(const Matrix1, Matrix2: TMatrix4d): Boolean; overload;
  283. function MatrixEquals(const Matrix1, Matrix2: TMatrix4s): Boolean; overload;
  284. function MatrixEquals(const Matrix1, Matrix2: TMatrix4b): Boolean; overload;
  285. // 2x
  286. function Vector2fMake(const X, Y: Single): TVector2f; overload; inline;
  287. function Vector2iMake(const X, Y: Longint): TVector2i; overload; inline;
  288. function Vector2sMake(const X, Y: SmallInt): TVector2s; overload; inline;
  289. function Vector2dMake(const X, Y: Double): TVector2d; overload; inline;
  290. function Vector2bMake(const X, Y: Byte): TVector2b; overload; inline;
  291. function Vector2fMake(const Vector: TVector3f): TVector2f; overload; inline;
  292. function Vector2iMake(const Vector: TVector3i): TVector2i; overload; inline;
  293. function Vector2sMake(const Vector: TVector3s): TVector2s; overload; inline;
  294. function Vector2dMake(const Vector: TVector3d): TVector2d; overload; inline;
  295. function Vector2bMake(const Vector: TVector3b): TVector2b; overload; inline;
  296. function Vector2fMake(const Vector: TVector4f): TVector2f; overload; inline;
  297. function Vector2iMake(const Vector: TVector4i): TVector2i; overload; inline;
  298. function Vector2sMake(const Vector: TVector4s): TVector2s; overload; inline;
  299. function Vector2dMake(const Vector: TVector4d): TVector2d; overload; inline;
  300. function Vector2bMake(const Vector: TVector4b): TVector2b; overload; inline;
  301. // 3x
  302. function Vector3fMake(const X: Single; const Y: Single = 0; const Z: Single = 0) : TVector3f; overload; inline;
  303. function Vector3iMake(const X: Longint; const Y: Longint = 0; const Z: Longint = 0): TVector3i; overload;inline;
  304. function Vector3sMake(const X: SmallInt; const Y: SmallInt = 0; const Z: SmallInt = 0): TVector3s; overload;inline;
  305. function Vector3dMake(const X: Double; const Y: Double = 0; const Z: Double = 0): TVector3d; overload; inline;
  306. function Vector3bMake(const X: Byte; const Y: Byte = 0; const Z: Byte = 0): TVector3b; overload; inline;
  307. function Vector3fMake(const Vector: TVector2f; const Z: Single = 0): TVector3f; overload; inline;
  308. function Vector3iMake(const Vector: TVector2i; const Z: Longint = 0): TVector3i; overload; inline;
  309. function Vector3sMake(const Vector: TVector2s; const Z: SmallInt = 0): TVector3s; overload; inline;
  310. function Vector3dMake(const Vector: TVector2d; const Z: Double = 0): TVector3d; overload; inline;
  311. function Vector3bMake(const Vector: TVector2b; const Z: Byte = 0): TVector3b; overload; inline;
  312. function Vector3fMake(const Vector: TVector4f): TVector3f; overload; inline;
  313. function Vector3iMake(const Vector: TVector4i): TVector3i; overload; inline;
  314. function Vector3sMake(const Vector: TVector4s): TVector3s; overload; inline;
  315. function Vector3dMake(const Vector: TVector4d): TVector3d; overload; inline;
  316. function Vector3bMake(const Vector: TVector4b): TVector3b; overload; inline;
  317. // 4x
  318. function Vector4fMake(const X: Single; const Y: Single = 0; const Z: Single = 0; const W: Single = 0): TVector4f; overload; inline;
  319. function Vector4iMake(const X: Longint; const Y: Longint = 0; const Z: Longint = 0; const W: Longint = 0): TVector4i; overload; inline;
  320. function Vector4sMake(const X: SmallInt; const Y: SmallInt = 0; const Z: SmallInt = 0; const W: SmallInt = 0): TVector4s; overload; inline;
  321. function Vector4dMake(const X: Double; const Y: Double = 0; const Z: Double = 0; const W: Double = 0): TVector4d; overload; inline;
  322. function Vector4bMake(const X: Byte; const Y: Byte = 0; const Z: Byte = 0; const W: Byte = 0): TVector4b; overload; inline;
  323. function Vector4fMake(const Vector: TVector3f; const W: Single = 0): TVector4f; overload; inline;
  324. function Vector4iMake(const Vector: TVector3i; const W: Longint = 0): TVector4i; overload; inline;
  325. function Vector4sMake(const Vector: TVector3s; const W: SmallInt = 0) : TVector4s; overload; inline;
  326. function Vector4dMake(const Vector: TVector3d; const W: Double = 0): TVector4d; overload; inline;
  327. function Vector4bMake(const Vector: TVector3b; const W: Byte = 0): TVector4b; overload; inline;
  328. function Vector4fMake(const Vector: TVector2f; const Z: Single = 0; const W: Single = 0): TVector4f; overload; inline;
  329. function Vector4iMake(const Vector: TVector2i; const Z: Longint = 0; const W: Longint = 0): TVector4i; overload;inline;
  330. function Vector4sMake(const Vector: TVector2s; const Z: SmallInt = 0; const W: SmallInt = 0): TVector4s; overload;inline;
  331. function Vector4dMake(const Vector: TVector2d; const Z: Double = 0; const W: Double = 0): TVector4d; overload; inline;
  332. function Vector4bMake(const Vector: TVector2b; const Z: Byte = 0; const W: Byte = 0): TVector4b; overload; inline;
  333. // Vector comparison functions:
  334. // 3f
  335. function VectorMoreThen(const SourceVector, ComparedVector: TVector3f): Boolean; overload;
  336. function VectorMoreEqualThen(const SourceVector, ComparedVector: TVector3f): Boolean; overload;
  337. function VectorLessThen(const SourceVector, ComparedVector: TVector3f): Boolean; overload;
  338. function VectorLessEqualThen(const SourceVector, ComparedVector: TVector3f): Boolean; overload;
  339. // 4f
  340. function VectorMoreThen(const SourceVector, ComparedVector: TVector4f): Boolean; overload;
  341. function VectorMoreEqualThen(const SourceVector, ComparedVector: TVector4f): Boolean; overload;
  342. function VectorLessThen(const SourceVector, ComparedVector: TVector4f): Boolean; overload;
  343. function VectorLessEqualThen(const SourceVector, ComparedVector: TVector4f): Boolean; overload;
  344. // 3i
  345. function VectorMoreThen(const SourceVector, ComparedVector: TVector3i): Boolean; overload;
  346. function VectorMoreEqualThen(const SourceVector, ComparedVector: TVector3i): Boolean; overload;
  347. function VectorLessThen(const SourceVector, ComparedVector: TVector3i): Boolean; overload;
  348. function VectorLessEqualThen(const SourceVector, ComparedVector: TVector3i): Boolean; overload;
  349. // 4i
  350. function VectorMoreThen(const SourceVector, ComparedVector: TVector4i): Boolean; overload;
  351. function VectorMoreEqualThen(const SourceVector, ComparedVector: TVector4i): Boolean; overload;
  352. function VectorLessThen(const SourceVector, ComparedVector: TVector4i): Boolean; overload;
  353. function VectorLessEqualThen(const SourceVector, ComparedVector: TVector4i): Boolean; overload;
  354. // 3s
  355. function VectorMoreThen(const SourceVector, ComparedVector: TVector3s): Boolean; overload;
  356. function VectorMoreEqualThen(const SourceVector, ComparedVector: TVector3s): Boolean; overload;
  357. function VectorLessThen(const SourceVector, ComparedVector: TVector3s): Boolean; overload;
  358. function VectorLessEqualThen(const SourceVector, ComparedVector: TVector3s): Boolean; overload;
  359. // 4s
  360. function VectorMoreThen(const SourceVector, ComparedVector: TVector4s): Boolean; overload;
  361. function VectorMoreEqualThen(const SourceVector, ComparedVector: TVector4s): Boolean; overload;
  362. function VectorLessThen(const SourceVector, ComparedVector: TVector4s): Boolean; overload;
  363. function VectorLessEqualThen(const SourceVector, ComparedVector: TVector4s): Boolean; overload;
  364. // ComparedNumber
  365. // 3f
  366. function VectorMoreThen(const SourceVector: TVector3f; const ComparedNumber: Single): Boolean; overload;
  367. function VectorMoreEqualThen(const SourceVector: TVector3f; const ComparedNumber: Single): Boolean; overload;
  368. function VectorLessThen(const SourceVector: TVector3f; const ComparedNumber: Single): Boolean; overload;
  369. function VectorLessEqualThen(const SourceVector: TVector3f; const ComparedNumber: Single): Boolean; overload;
  370. // 4f
  371. function VectorMoreThen(const SourceVector: TVector4f; const ComparedNumber: Single): Boolean; overload;
  372. function VectorMoreEqualThen(const SourceVector: TVector4f; const ComparedNumber: Single): Boolean; overload;
  373. function VectorLessThen(const SourceVector: TVector4f; const ComparedNumber: Single): Boolean; overload;
  374. function VectorLessEqualThen(const SourceVector: TVector4f; const ComparedNumber: Single): Boolean; overload;
  375. // 3i
  376. function VectorMoreThen(const SourceVector: TVector3i; const ComparedNumber: Single): Boolean; overload;
  377. function VectorMoreEqualThen(const SourceVector: TVector3i; const ComparedNumber: Single): Boolean; overload;
  378. function VectorLessThen(const SourceVector: TVector3i; const ComparedNumber: Single): Boolean; overload;
  379. function VectorLessEqualThen(const SourceVector: TVector3i; const ComparedNumber: Single): Boolean; overload;
  380. // 4i
  381. function VectorMoreThen(const SourceVector: TVector4i; const ComparedNumber: Single): Boolean; overload;
  382. function VectorMoreEqualThen(const SourceVector: TVector4i; const ComparedNumber: Single): Boolean; overload;
  383. function VectorLessThen(const SourceVector: TVector4i; const ComparedNumber: Single): Boolean; overload;
  384. function VectorLessEqualThen(const SourceVector: TVector4i; const ComparedNumber: Single): Boolean; overload;
  385. // 3s
  386. function VectorMoreThen(const SourceVector: TVector3s; const ComparedNumber: Single): Boolean; overload;
  387. function VectorMoreEqualThen(const SourceVector: TVector3s; const ComparedNumber: Single): Boolean; overload;
  388. function VectorLessThen(const SourceVector: TVector3s; const ComparedNumber: Single): Boolean; overload;
  389. function VectorLessEqualThen(const SourceVector: TVector3s; const ComparedNumber: Single): Boolean; overload;
  390. // 4s
  391. function VectorMoreThen(const SourceVector: TVector4s; const ComparedNumber: Single): Boolean; overload;
  392. function VectorMoreEqualThen(const SourceVector: TVector4s; const ComparedNumber: Single): Boolean; overload;
  393. function VectorLessThen(const SourceVector: TVector4s; const ComparedNumber: Single): Boolean; overload;
  394. function VectorLessEqualThen(const SourceVector: TVector4s; const ComparedNumber: Single): Boolean; overload;
  395. function VectorAdd(const V1, V2: TVector2f): TVector2f; overload;
  396. // Returns the sum of two affine vectors
  397. function VectorAdd(const V1, V2: TAffineVector): TAffineVector; overload;
  398. // Adds two vectors and places result in vr
  399. procedure VectorAdd(const V1, V2: TAffineVector; var vr: TAffineVector); overload;
  400. procedure VectorAdd(const V1, V2: TAffineVector; vr: PAffineVector); overload;
  401. // Returns the sum of two homogeneous vectors
  402. function VectorAdd(const V1, V2: TVector): TVector; overload;
  403. procedure VectorAdd(const V1, V2: TVector; var vr: TVector); overload;
  404. // Sums up f to each component of the vector
  405. function VectorAdd(const V: TAffineVector; const f: Single): TAffineVector; overload; inline;
  406. // Sums up f to each component of the vector
  407. function VectorAdd(const V: TVector; const f: Single): TVector; overload; inline;
  408. // Adds V2 to V1, result is placed in V1
  409. procedure AddVector(var V1: TAffineVector; const V2: TAffineVector); overload;
  410. // Adds V2 to V1, result is placed in V1
  411. procedure AddVector(var V1: TAffineVector; const V2: TVector); overload;
  412. // Adds V2 to V1, result is placed in V1
  413. procedure AddVector(var V1: TVector; const V2: TVector); overload;
  414. // Sums up f to each component of the vector
  415. procedure AddVector(var V: TAffineVector; const f: Single); overload; inline;
  416. // Sums up f to each component of the vector
  417. procedure AddVector(var V: TVector; const f: Single); overload; inline;
  418. // Adds V2 to V1, result is placed in V1. W coordinate is always 1.
  419. procedure AddPoint(var V1: TVector; const V2: TVector); overload; inline;
  420. // Returns the sum of two homogeneous vectors. W coordinate is always 1.
  421. function PointAdd(var V1: TVector; const V2: TVector): TVector; overload; inline;
  422. // Adds delta to nb texpoints in src and places result in dest
  423. procedure TexPointArrayAdd(const src: PTexPointArray; const delta: TTexPoint; const nb: Integer; dest: PTexPointArray); overload;
  424. procedure TexPointArrayScaleAndAdd(const src: PTexPointArray; const delta: TTexPoint;
  425. const nb: Integer; const scale: TTexPoint; dest: PTexPointArray); overload;
  426. // Adds delta to nb vectors in src and places result in dest
  427. procedure VectorArrayAdd(const src: PAffineVectorArray;
  428. const delta: TAffineVector; const nb: Integer; dest: PAffineVectorArray); overload;
  429. // Returns V1-V2
  430. function VectorSubtract(const V1, V2: TVector2f): TVector2f; overload;
  431. // Subtracts V2 from V1, result is placed in V1
  432. procedure SubtractVector(var V1: TVector2f; const V2: TVector2f); overload;
  433. // Returns V1-V2
  434. function VectorSubtract(const V1, V2: TAffineVector): TAffineVector; overload;
  435. // Subtracts V2 from V1 and return value in result
  436. procedure VectorSubtract(const V1, V2: TAffineVector; var result: TAffineVector); overload;
  437. // Subtracts V2 from V1 and return value in result
  438. procedure VectorSubtract(const V1, V2: TAffineVector; var result: TVector); overload;
  439. // Subtracts V2 from V1 and return value in result
  440. procedure VectorSubtract(const V1: TVector; const V2: TAffineVector; var result: TVector); overload;
  441. // Returns V1-V2
  442. function VectorSubtract(const V1, V2: TVector): TVector; overload;
  443. // Subtracts V2 from V1 and return value in result
  444. procedure VectorSubtract(const V1, V2: TVector; var result: TVector); overload;
  445. // Subtracts V2 from V1 and return value in result
  446. procedure VectorSubtract(const V1, V2: TVector; var result: TAffineVector); overload;
  447. function VectorSubtract(const V1: TAffineVector; delta: Single): TAffineVector; overload; inline;
  448. function VectorSubtract(const V1: TVector; delta: Single): TVector; overload;inline;
  449. // Subtracts V2 from V1, result is placed in V1
  450. procedure SubtractVector(var V1: TAffineVector; const V2: TAffineVector); overload;
  451. // Subtracts V2 from V1, result is placed in V1
  452. procedure SubtractVector(var V1: TVector; const V2: TVector); overload;
  453. // Combine the first vector with the second : vr:=vr+v*f
  454. procedure CombineVector(var vr: TAffineVector; const V: TAffineVector; var f: Single); overload;
  455. procedure CombineVector(var vr: TAffineVector; const V: TAffineVector; pf: PFloat); overload;
  456. // Makes a linear combination of two texpoints
  457. function TexPointCombine(const t1, t2: TTexPoint; f1, f2: Single): TTexPoint; inline;
  458. // Makes a linear combination of two vectors and return the result
  459. function VectorCombine(const V1, V2: TAffineVector; const f1, f2: Single): TAffineVector; overload; inline;
  460. // Makes a linear combination of three vectors and return the result
  461. function VectorCombine3(const V1, V2, V3: TAffineVector; const f1, f2, F3: Single): TAffineVector; overload;inline;
  462. procedure VectorCombine3(const V1, V2, V3: TAffineVector;
  463. const f1, f2, F3: Single; var vr: TAffineVector); overload;inline;
  464. // Combine the first vector with the second : vr:=vr+v*f
  465. procedure CombineVector(var vr: TVector; const V: TVector; var f: Single); overload;
  466. // Combine the first vector with the second : vr:=vr+v*f
  467. procedure CombineVector(var vr: TVector; const V: TAffineVector; var f: Single); overload;
  468. // Makes a linear combination of two vectors and return the result
  469. function VectorCombine(const V1, V2: TVector; const F1, F2: Single): TVector; overload; inline;
  470. // Makes a linear combination of two vectors and return the result
  471. function VectorCombine(const V1: TVector; const V2: TAffineVector;
  472. const F1, F2: Single): TVector; overload; inline;
  473. // Makes a linear combination of two vectors and place result in vr
  474. procedure VectorCombine(const V1: TVector; const V2: TAffineVector; const F1, F2: Single; var VR: TVector); overload;inline;
  475. // Makes a linear combination of two vectors and place result in vr
  476. procedure VectorCombine(const V1, V2: TVector; const F1, F2: Single; var vr: TVector); overload;
  477. // Makes a linear combination of two vectors and place result in vr, F1=1.0
  478. procedure VectorCombine(const V1, V2: TVector; const F2: Single; var vr: TVector); overload;
  479. // Makes a linear combination of three vectors and return the result
  480. function VectorCombine3(const V1, V2, V3: TVector; const F1, F2, F3: Single): TVector; overload; inline;
  481. // Makes a linear combination of three vectors and return the result
  482. procedure VectorCombine3(const V1, V2, V3: TVector; const F1, F2, F3: Single; var vr: TVector); overload;
  483. (* Calculates the dot product between V1 and V2.
  484. Result:=V1[X] * V2[X] + V1[Y] * V2[Y] *)
  485. function VectorDotProduct(const V1, V2: TVector2f): Single; overload;
  486. (* Calculates the dot product between V1 and V2.
  487. Result:=V1[X] * V2[X] + V1[Y] * V2[Y] + V1[Z] * V2[Z] *)
  488. function VectorDotProduct(const V1, V2: TAffineVector): Single; overload;
  489. (* Calculates the dot product between V1 and V2.
  490. Result:=V1[X] * V2[X] + V1[Y] * V2[Y] + V1[Z] * V2[Z] *)
  491. function VectorDotProduct(const V1, V2: TVector): Single; overload;
  492. (* Calculates the dot product between V1 and V2.
  493. Result:=V1[X] * V2[X] + V1[Y] * V2[Y] + V1[Z] * V2[Z] *)
  494. function VectorDotProduct(const V1: TVector; const V2: TAffineVector): Single; overload;
  495. (* Projects p on the line defined by o and direction.
  496. Performs VectorDotProduct(VectorSubtract(p, origin), direction), which,
  497. if direction is normalized, computes the distance between origin and the
  498. projection of p on the (origin, direction) line *)
  499. function PointProject(const p, origin, direction: TAffineVector): Single; overload;
  500. function PointProject(const p, origin, direction: TVector): Single; overload;
  501. // Calculates the cross product between vector 1 and 2
  502. function VectorCrossProduct(const V1, V2: TAffineVector): TAffineVector; overload;
  503. // Calculates the cross product between vector 1 and 2
  504. function VectorCrossProduct(const V1, V2: TVector): TVector; overload;
  505. // Calculates the cross product between vector 1 and 2, place result in vr
  506. procedure VectorCrossProduct(const V1, V2: TVector; var vr: TVector); overload;
  507. // Calculates the cross product between vector 1 and 2, place result in vr
  508. procedure VectorCrossProduct(const V1, V2: TAffineVector; var vr: TVector); overload;
  509. // Calculates the cross product between vector 1 and 2, place result in vr
  510. procedure VectorCrossProduct(const V1, V2: TVector; var vr: TAffineVector); overload;
  511. // Calculates the cross product between vector 1 and 2, place result in vr
  512. procedure VectorCrossProduct(const V1, V2: TAffineVector; var vr: TAffineVector); overload;
  513. // Calculates linear interpolation between start and stop at point t
  514. function Lerp(const start, stop, T: Single): Single; inline;
  515. // Calculates angular interpolation between start and stop at point t
  516. function AngleLerp(start, stop, T: Single): Single; inline;
  517. (* This is used for interpolating between 2 matrices. The result
  518. is used to reposition the model parts each frame. *)
  519. function MatrixLerp(const m1, m2: TMatrix; const delta: Single): TMatrix;
  520. (* Calculates the angular distance between two angles in radians.
  521. Result is in the [0; PI] range. *)
  522. function DistanceBetweenAngles(angle1, angle2: Single): Single;
  523. // Calculates linear interpolation between texpoint1 and texpoint2 at point t
  524. function TexPointLerp(const t1, t2: TTexPoint; T: Single): TTexPoint; overload; inline;
  525. // Calculates linear interpolation between vector1 and vector2 at point t
  526. function VectorLerp(const V1, V2: TAffineVector; T: Single): TAffineVector; overload; inline;
  527. // Calculates linear interpolation between vector1 and vector2 at point t, places result in vr
  528. procedure VectorLerp(const V1, V2: TAffineVector; T: Single; var vr: TAffineVector); overload;
  529. // Calculates linear interpolation between vector1 and vector2 at point t
  530. function VectorLerp(const V1, V2: TVector; T: Single): TVector; overload; inline;
  531. // Calculates linear interpolation between vector1 and vector2 at point t, places result in vr
  532. procedure VectorLerp(const V1, V2: TVector; T: Single; var vr: TVector); overload; inline;
  533. function VectorAngleLerp(const V1, V2: TAffineVector; T: Single): TAffineVector; overload;
  534. function VectorAngleCombine(const V1, V2: TAffineVector; f: Single): TAffineVector; overload;
  535. // Calculates linear interpolation between vector arrays
  536. procedure VectorArrayLerp(const src1, src2: PVectorArray; T: Single; n: Integer; dest: PVectorArray); overload;
  537. procedure VectorArrayLerp(const src1, src2: PAffineVectorArray; T: Single; n: Integer; dest: PAffineVectorArray); overload;
  538. procedure VectorArrayLerp(const src1, src2: PTexPointArray; T: Single; n: Integer; dest: PTexPointArray); overload;
  539. type
  540. TGLInterpolationType = (itLinear, itPower, itSin, itSinAlt, itTan, itLn, itExp);
  541. // There functions that do the same as "Lerp", but add some distortions
  542. function InterpolatePower(const start, stop, delta: Single; const DistortionDegree: Single): Single;
  543. function InterpolateLn(const start, stop, delta: Single; const DistortionDegree: Single): Single;
  544. function InterpolateExp(const start, stop, delta: Single; const DistortionDegree: Single): Single;
  545. // Only valid where Delta belongs to [0..1]
  546. function InterpolateSin(const start, stop, delta: Single): Single;
  547. function InterpolateTan(const start, stop, delta: Single): Single;
  548. // "Alt" functions are valid everywhere
  549. function InterpolateSinAlt(const start, stop, delta: Single): Single;
  550. function InterpolateCombinedFastPower(const OriginalStart, OriginalStop,
  551. OriginalCurrent: Single; const TargetStart, TargetStop: Single;
  552. const DistortionDegree: Single): Single; inline;
  553. function InterpolateCombinedSafe(const OriginalStart, OriginalStop,
  554. OriginalCurrent: Single; const TargetStart, TargetStop: Single;
  555. const DistortionDegree: Single;
  556. const InterpolationType: TGLInterpolationType): Single; inline;
  557. function InterpolateCombinedFast(const OriginalStart, OriginalStop,
  558. OriginalCurrent: Single; const TargetStart, TargetStop: Single;
  559. const DistortionDegree: Single;
  560. const InterpolationType: TGLInterpolationType): Single; inline;
  561. function InterpolateCombined(const start, stop, delta: Single;
  562. const DistortionDegree: Single;
  563. const InterpolationType: TGLInterpolationType): Single; inline;
  564. { Calculates the length of a vector following the equation sqrt(x*x+y*y). }
  565. function VectorLength(const X, Y: Single): Single; overload;
  566. { Calculates the length of a vector following the equation sqrt(x*x+y*y+z*z). }
  567. function VectorLength(const X, Y, Z: Single): Single; overload;
  568. // Calculates the length of a vector following the equation sqrt(x*x+y*y).
  569. function VectorLength(const V: TVector2f): Single; overload;
  570. // Calculates the length of a vector following the equation sqrt(x*x+y*y+z*z).
  571. function VectorLength(const V: TAffineVector): Single; overload;
  572. // Calculates the length of a vector following the equation sqrt(x*x+y*y+z*z+w*w).
  573. function VectorLength(const V: TVector): Single; overload;
  574. (* Calculates the length of a vector following the equation: sqrt(x*x+y*y+...).
  575. Note: The parameter of this function is declared as open array. Thus
  576. there's no restriction about the number of the components of the vector. *)
  577. function VectorLength(const V: array of Single): Single; overload;
  578. (* Calculates norm of a vector which is defined as norm = x * x + y * y
  579. Also known as "Norm 2" in the math world, this is sqr(VectorLength). *)
  580. function VectorNorm(const X, Y: Single): Single; overload;
  581. (* Calculates norm of a vector which is defined as norm = x*x + y*y + z*z
  582. Also known as "Norm 2" in the math world, this is sqr(VectorLength). *)
  583. function VectorNorm(const V: TAffineVector): Single; overload;
  584. (* Calculates norm of a vector which is defined as norm = x*x + y*y + z*z
  585. Also known as "Norm 2" in the math world, this is sqr(VectorLength). *)
  586. function VectorNorm(const V: TVector): Single; overload;
  587. (* Calculates norm of a vector which is defined as norm = v.X*v.X + ...
  588. Also known as "Norm 2" in the math world, this is sqr(VectorLength). *)
  589. function VectorNorm(var V: array of Single): Single; overload;
  590. // Transforms a vector to unit length
  591. procedure NormalizeVector(var V: TVector2f); overload;
  592. (* Returns the vector transformed to unit length
  593. Transforms a vector to unit length *)
  594. procedure NormalizeVector(var V: TAffineVector); overload;
  595. // Transforms a vector to unit length
  596. procedure NormalizeVector(var V: TVector); overload;
  597. // Returns the vector transformed to unit length
  598. function VectorNormalize(const V: TVector2f): TVector2f; overload;
  599. // Returns the vector transformed to unit length
  600. function VectorNormalize(const V: TAffineVector): TAffineVector; overload;
  601. // Returns the vector transformed to unit length (w component dropped)
  602. function VectorNormalize(const V: TVector): TVector; overload;
  603. // Transforms vectors to unit length
  604. procedure NormalizeVectorArray(list: PAffineVectorArray; n: Integer); overload; inline;
  605. (* Calculates the cosine of the angle between Vector1 and Vector2.
  606. Result = DotProduct(V1, V2) / (Length(V1) * Length(V2)) *)
  607. function VectorAngleCosine(const V1, V2: TAffineVector): Single; overload;
  608. (* Calculates the cosine of the angle between Vector1 and Vector2.
  609. Result = DotProduct(V1, V2) / (Length(V1) * Length(V2)) *)
  610. function VectorAngleCosine(const V1, V2: TVector): Single; overload;
  611. // Negates the vector
  612. function VectorNegate(const Vector: TAffineVector): TAffineVector; overload;
  613. function VectorNegate(const Vector: TVector): TVector; overload;
  614. // Negates the vector
  615. procedure NegateVector(var V: TAffineVector); overload;
  616. // Negates the vector
  617. procedure NegateVector(var V: TVector); overload;
  618. // Negates the vector
  619. procedure NegateVector(var V: array of Single); overload;
  620. // Scales given vector by a factor
  621. procedure ScaleVector(var V: TVector2f; factor: Single); overload;
  622. // Scales given vector by a factor
  623. procedure ScaleVector(var V: TAffineVector; factor: Single); overload;
  624. (* Scales given vector by another vector.
  625. v[x]:=v[x]*factor[x], v[y]:=v[y]*factor[y] etc. *)
  626. procedure ScaleVector(var V: TAffineVector; const factor: TAffineVector); overload;
  627. // Scales given vector by a factor
  628. procedure ScaleVector(var V: TVector; factor: Single); overload;
  629. (* Scales given vector by another vector.
  630. v[x]:=v[x]*factor[x], v[y]:=v[y]*factor[y] etc. *)
  631. procedure ScaleVector(var V: TVector; const factor: TVector); overload;
  632. // Returns a vector scaled by a factor
  633. function VectorScale(const V: TVector2f; factor: Single): TVector2f; overload;
  634. // Returns a vector scaled by a factor
  635. function VectorScale(const V: TAffineVector; factor: Single): TAffineVector; overload;
  636. // Scales a vector by a factor and places result in vr
  637. procedure VectorScale(const V: TAffineVector; factor: Single; var vr: TAffineVector); overload;
  638. // Returns a vector scaled by a factor
  639. function VectorScale(const V: TVector; factor: Single): TVector; overload;
  640. // Scales a vector by a factor and places result in vr
  641. procedure VectorScale(const V: TVector; factor: Single; var vr: TVector); overload;
  642. // Scales a vector by a factor and places result in vr
  643. procedure VectorScale(const V: TVector; factor: Single; var vr: TAffineVector); overload;
  644. // Scales given vector by another vector
  645. function VectorScale(const V: TAffineVector; const factor: TAffineVector): TAffineVector; overload;
  646. // RScales given vector by another vector
  647. function VectorScale(const V: TVector; const factor: TVector): TVector; overload;
  648. (* Divides given vector by another vector.
  649. v[x]:=v[x]/divider[x], v[y]:=v[y]/divider[y] etc. *)
  650. procedure DivideVector(var V: TVector; const divider: TVector); overload; inline;
  651. procedure DivideVector(var V: TAffineVector; const divider: TAffineVector); overload; inline;
  652. function VectorDivide(const V: TVector; const divider: TVector): TVector; overload; inline;
  653. function VectorDivide(const V: TAffineVector; const divider: TAffineVector): TAffineVector; overload; inline;
  654. // True if all components are equal.
  655. function TexpointEquals(const p1, p2: TTexPoint): Boolean; inline;
  656. // True if all components are equal.
  657. function RectEquals(const Rect1, Rect2: TRect): Boolean; inline;
  658. // True if all components are equal.
  659. function VectorEquals(const V1, V2: TVector): Boolean; overload; inline;
  660. // True if all components are equal.
  661. function VectorEquals(const V1, V2: TAffineVector): Boolean; overload; inline;
  662. // True if X, Y and Z components are equal.
  663. function AffineVectorEquals(const V1, V2: TVector): Boolean; overload; inline;
  664. // True if x=y=z=0, w ignored
  665. function VectorIsNull(const V: TVector): Boolean; overload; inline;
  666. // True if x=y=z=0, w ignored
  667. function VectorIsNull(const V: TAffineVector): Boolean; overload; inline;
  668. // Calculates Abs(v1[x]-v2[x])+Abs(v1[y]-v2[y]), also know as "Norm1".
  669. function VectorSpacing(const V1, V2: TTexPoint): Single; overload;
  670. // Calculates Abs(v1[x]-v2[x])+Abs(v1[y]-v2[y])+..., also know as "Norm1".
  671. function VectorSpacing(const V1, V2: TAffineVector): Single; overload;
  672. // Calculates Abs(v1[x]-v2[x])+Abs(v1[y]-v2[y])+..., also know as "Norm1".
  673. function VectorSpacing(const V1, V2: TVector): Single; overload;
  674. // Calculates distance between two vectors. ie. sqrt(sqr(v1[x]-v2[x])+...)
  675. function VectorDistance(const V1, V2: TAffineVector): Single; overload;
  676. (* Calculates distance between two vectors.
  677. ie. sqrt(sqr(v1[x]-v2[x])+...) (w component ignored) *)
  678. function VectorDistance(const V1, V2: TVector): Single; overload;
  679. // Calculates the "Norm 2" between two vectors. ie. sqr(v1[x]-v2[x])+...
  680. function VectorDistance2(const V1, V2: TAffineVector): Single; overload;
  681. // Calculates the "Norm 2" between two vectors. ie. sqr(v1[x]-v2[x])+...(w component ignored)
  682. function VectorDistance2(const V1, V2: TVector): Single; overload;
  683. // Calculates a vector perpendicular to N. N is assumed to be of unit length, subtract out any component parallel to N
  684. function VectorPerpendicular(const V, n: TAffineVector): TAffineVector;
  685. // Reflects vector V against N (assumes N is normalized)
  686. function VectorReflect(const V, n: TAffineVector): TAffineVector;
  687. // Rotates Vector about Axis with Angle radians
  688. procedure RotateVector(var Vector: TVector; const axis: TAffineVector; angle: Single); overload;
  689. // Rotates Vector about Axis with Angle radians
  690. procedure RotateVector(var Vector: TVector; const axis: TVector; angle: Single); overload;
  691. // Rotate given vector around the Y axis (alpha is in rad)
  692. procedure RotateVectorAroundY(var V: TAffineVector; alpha: Single);
  693. // Returns given vector rotated around the X axis (alpha is in rad)
  694. function VectorRotateAroundX(const V: TAffineVector; alpha: Single): TAffineVector; overload;
  695. // Returns given vector rotated around the Y axis (alpha is in rad)
  696. function VectorRotateAroundY(const V: TAffineVector; alpha: Single): TAffineVector; overload;
  697. // Returns given vector rotated around the Y axis in vr (alpha is in rad)
  698. procedure VectorRotateAroundY(const V: TAffineVector; alpha: Single; var vr: TAffineVector); overload;
  699. // Returns given vector rotated around the Z axis (alpha is in rad)
  700. function VectorRotateAroundZ(const V: TAffineVector; alpha: Single): TAffineVector; overload;
  701. // Vector components are replaced by their Abs() value. }
  702. procedure AbsVector(var V: TVector); overload; inline;
  703. // Vector components are replaced by their Abs() value. }
  704. procedure AbsVector(var V: TAffineVector); overload;inline;
  705. // Returns a vector with components replaced by their Abs value. }
  706. function VectorAbs(const V: TVector): TVector; overload; inline;
  707. // Returns a vector with components replaced by their Abs value. }
  708. function VectorAbs(const V: TAffineVector): TAffineVector; overload;inline;
  709. // Returns true if both vector are colinear
  710. function IsColinear(const V1, V2: TVector2f): Boolean; overload;
  711. // Returns true if both vector are colinear
  712. function IsColinear(const V1, V2: TAffineVector): Boolean; overload;
  713. // Returns true if both vector are colinear
  714. function IsColinear(const V1, V2: TVector): Boolean; overload;
  715. (* ----------------------------------------------------------------------------
  716. Matrix functions
  717. ---------------------------------------------------------------------------- *)
  718. procedure SetMatrix(var dest: THomogeneousDblMatrix; const src: TMatrix); overload;
  719. procedure SetMatrix(var dest: TAffineMatrix; const src: TMatrix); overload;
  720. procedure SetMatrix(var dest: TMatrix; const src: TAffineMatrix); overload;
  721. procedure SetMatrixRow(var dest: TMatrix; rowNb: Integer; const aRow: TVector); overload;
  722. // Creates scale matrix
  723. function CreateScaleMatrix(const V: TAffineVector): TMatrix; overload;
  724. // Creates scale matrix
  725. function CreateScaleMatrix(const V: TVector): TMatrix; overload;
  726. // Creates translation matrix
  727. function CreateTranslationMatrix(const V: TAffineVector): TMatrix; overload;
  728. // Creates translation matrix
  729. function CreateTranslationMatrix(const V: TVector): TMatrix; overload;
  730. { Creates a scale+translation matrix.
  731. Scale is applied BEFORE applying offset }
  732. function CreateScaleAndTranslationMatrix(const scale, offset: TVector): TMatrix; overload;
  733. // Creates matrix for rotation about x-axis (angle in rad)
  734. function CreateRotationMatrixX(const sine, cosine: Single): TMatrix; overload;
  735. function CreateRotationMatrixX(const angle: Single): TMatrix; overload;
  736. // Creates matrix for rotation about y-axis (angle in rad)
  737. function CreateRotationMatrixY(const sine, cosine: Single): TMatrix; overload;
  738. function CreateRotationMatrixY(const angle: Single): TMatrix; overload;
  739. // Creates matrix for rotation about z-axis (angle in rad)
  740. function CreateRotationMatrixZ(const sine, cosine: Single): TMatrix; overload;
  741. function CreateRotationMatrixZ(const angle: Single): TMatrix; overload;
  742. // Creates a rotation matrix along the given Axis by the given Angle in radians.
  743. function CreateRotationMatrix(const anAxis: TAffineVector; angle: Single): TMatrix; overload;
  744. function CreateRotationMatrix(const anAxis: TVector; angle: Single): TMatrix; overload;
  745. // Creates a rotation matrix along the given Axis by the given Angle in radians.
  746. function CreateAffineRotationMatrix(const anAxis: TAffineVector; angle: Single): TAffineMatrix;
  747. // Multiplies two 3x3 matrices
  748. function MatrixMultiply(const m1, m2: TAffineMatrix): TAffineMatrix; overload;
  749. // Multiplies two 4x4 matrices
  750. function MatrixMultiply(const m1, m2: TMatrix): TMatrix; overload;
  751. // Multiplies M1 by M2 and places result in MResult
  752. procedure MatrixMultiply(const m1, m2: TMatrix; var MResult: TMatrix); overload;
  753. // Transforms a homogeneous vector by multiplying it with a matrix
  754. function VectorTransform(const V: TVector; const M: TMatrix): TVector; overload;
  755. // Transforms a homogeneous vector by multiplying it with a matrix
  756. function VectorTransform(const V: TVector; const M: TAffineMatrix): TVector; overload;
  757. // Transforms an affine vector by multiplying it with a matrix
  758. function VectorTransform(const V: TAffineVector; const M: TMatrix): TAffineVector; overload;
  759. // Transforms an affine vector by multiplying it with a matrix
  760. function VectorTransform(const V: TAffineVector; const M: TAffineMatrix): TAffineVector; overload;
  761. // Determinant of a 3x3 matrix
  762. function MatrixDeterminant(const M: TAffineMatrix): Single; overload;
  763. // Determinant of a 4x4 matrix
  764. function MatrixDeterminant(const M: TMatrix): Single; overload;
  765. // Adjoint of a 4x4 matrix, used in the computation of the inverse of a 4x4 matrix
  766. procedure AdjointMatrix(var M: TMatrix); overload;
  767. // Adjoint of a 3x3 matrix, used in the computation of the inverse of a 3x3 matrix
  768. procedure AdjointMatrix(var M: TAffineMatrix); overload;
  769. // Multiplies all elements of a 3x3 matrix with a factor
  770. procedure ScaleMatrix(var M: TAffineMatrix; const factor: Single); overload;
  771. // Multiplies all elements of a 4x4 matrix with a factor
  772. procedure ScaleMatrix(var M: TMatrix; const factor: Single); overload;
  773. // Adds the translation vector into the matrix
  774. procedure TranslateMatrix(var M: TMatrix; const V: TAffineVector); overload;
  775. procedure TranslateMatrix(var M: TMatrix; const V: TVector); overload;
  776. (* Normalize the matrix and remove the translation component.
  777. The resulting matrix is an orthonormal matrix (Y direction preserved, then Z) *)
  778. procedure NormalizeMatrix(var M: TMatrix);
  779. // Computes transpose of 3x3 matrix
  780. procedure TransposeMatrix(var M: TAffineMatrix); overload;
  781. // Computes transpose of 4x4 matrix
  782. procedure TransposeMatrix(var M: TMatrix); overload;
  783. // Finds the inverse of a 4x4 matrix
  784. procedure InvertMatrix(var M: TMatrix); overload;
  785. function MatrixInvert(const M: TMatrix): TMatrix; overload;
  786. // Finds the inverse of a 3x3 matrix;
  787. procedure InvertMatrix(var M: TAffineMatrix); overload;
  788. function MatrixInvert(const M: TAffineMatrix): TAffineMatrix; overload;
  789. (* Finds the inverse of an angle preserving matrix.
  790. Angle preserving matrices can combine translation, rotation and isotropic
  791. scaling, other matrices won't be properly inverted by this function. *)
  792. function AnglePreservingMatrixInvert(const mat: TMatrix): TMatrix;
  793. (* Decompose a non-degenerated 4x4 transformation matrix into the sequence of transformations that produced it.
  794. Modified by ml then eg, original Author: Spencer W. Thomas, University of Michigan
  795. The coefficient of each transformation is returned in the corresponding
  796. element of the vector Tran. Returns true upon success, false if the matrix is singular. *)
  797. function MatrixDecompose(const M: TMatrix; var Tran: TTransformations): Boolean;
  798. function CreateLookAtMatrix(const eye, center, normUp: TVector): TMatrix;
  799. function CreateMatrixFromFrustum(Left, Right, Bottom, Top, ZNear, ZFar: Single): TMatrix;
  800. function CreatePerspectiveMatrix(FOV, Aspect, ZNear, ZFar: Single): TMatrix;
  801. function CreateOrthoMatrix(Left, Right, Bottom, Top, ZNear, ZFar: Single): TMatrix;
  802. function CreatePickMatrix(X, Y, deltax, deltay: Single; const viewport: TVector4i): TMatrix;
  803. function Project(objectVector: TVector; const ViewProjMatrix: TMatrix; const viewport: TVector4i; out WindowVector: TVector): Boolean;
  804. function UnProject(WindowVector: TVector; ViewProjMatrix: TMatrix; const viewport: TVector4i; out objectVector: TVector): Boolean;
  805. (* ----------------------------------------------------------------------------
  806. Plane functions
  807. -----------------------------------------------------------------------------*)
  808. // Computes the parameters of a plane defined by three points.
  809. function PlaneMake(const p1, p2, p3: TAffineVector): THmgPlane; overload;
  810. function PlaneMake(const p1, p2, p3: TVector): THmgPlane; overload;
  811. // Computes the parameters of a plane defined by a point and a normal.
  812. function PlaneMake(const point, normal: TAffineVector): THmgPlane; overload;
  813. function PlaneMake(const point, normal: TVector): THmgPlane; overload;
  814. // Converts from single to double representation
  815. procedure SetPlane(var dest: TDoubleHmgPlane; const src: THmgPlane);
  816. // Normalize a plane so that point evaluation = plane distance. }
  817. procedure NormalizePlane(var plane: THmgPlane);
  818. (* Calculates the cross-product between the plane normal and plane to point vector.
  819. This functions gives an hint as to were the point is, if the point is in the
  820. half-space pointed by the vector, result is positive.
  821. This function performs an homogeneous space dot-product. *)
  822. function PlaneEvaluatePoint(const plane: THmgPlane; const point: TAffineVector): Single; overload;
  823. function PlaneEvaluatePoint(const plane: THmgPlane; const point: TVector): Single; overload;
  824. // Calculate the normal of a plane defined by three points.
  825. function CalcPlaneNormal(const p1, p2, p3: TAffineVector): TAffineVector; overload;
  826. procedure CalcPlaneNormal(const p1, p2, p3: TAffineVector; var vr: TAffineVector); overload;
  827. procedure CalcPlaneNormal(const p1, p2, p3: TVector; var vr: TAffineVector); overload;
  828. (* Returns true if point is in the half-space defined by a plane with normal.
  829. The plane itself is not considered to be in the tested halfspace. *)
  830. function PointIsInHalfSpace(const point, planePoint, planeNormal: TVector): Boolean; overload;
  831. function PointIsInHalfSpace(const point, planePoint, planeNormal: TAffineVector): Boolean; overload;
  832. function PointIsInHalfSpace(const point: TAffineVector; const plane: THmgPlane): Boolean; overload;
  833. (* Computes algebraic distance between point and plane.
  834. Value will be positive if the point is in the halfspace pointed by the normal,
  835. negative on the other side. *)
  836. function PointPlaneDistance(const point, planePoint, planeNormal: TVector): Single; overload;
  837. function PointPlaneDistance(const point, planePoint, planeNormal: TAffineVector): Single; overload;
  838. function PointPlaneDistance(const point: TAffineVector; const plane: THmgPlane): Single; overload;
  839. // Computes point to plane projection. Plane and direction have to be normalized
  840. function PointPlaneOrthoProjection(const point: TAffineVector; const plane: THmgPlane; var inter: TAffineVector; bothface: Boolean = True): Boolean;
  841. function PointPlaneProjection(const point, direction: TAffineVector; const plane: THmgPlane; var inter: TAffineVector; bothface: Boolean = True): Boolean;
  842. // Computes segment / plane intersection return false if there isn't an intersection
  843. function SegmentPlaneIntersection(const ptA, ptB: TAffineVector; const plane: THmgPlane; var inter: TAffineVector): Boolean;
  844. // Computes point to triangle projection. Direction has to be normalized
  845. function PointTriangleOrthoProjection(const point, ptA, ptB, ptC: TAffineVector; var inter: TAffineVector; bothface: Boolean = True): Boolean;
  846. function PointTriangleProjection(const point, direction, ptA, ptB, ptC: TAffineVector; var inter: TAffineVector; bothface: Boolean = True): Boolean;
  847. // Returns true if line intersect ABC triangle
  848. function IsLineIntersectTriangle(const point, direction, ptA, ptB, ptC: TAffineVector): Boolean;
  849. // Computes point to Quad projection. Direction has to be normalized. Quad have to be flat and convex
  850. function PointQuadOrthoProjection(const point, ptA, ptB, ptC, ptD: TAffineVector; var inter: TAffineVector; bothface: Boolean = True): Boolean;
  851. function PointQuadProjection(const point, direction, ptA, ptB, ptC, ptD: TAffineVector; var inter: TAffineVector; bothface: Boolean = True): Boolean;
  852. // Returns true if line intersect ABCD quad. Quad have to be flat and convex
  853. function IsLineIntersectQuad(const point, direction, ptA, ptB, ptC, ptD: TAffineVector): Boolean;
  854. // Computes point to disk projection. Direction has to be normalized
  855. function PointDiskOrthoProjection(const point, center, up: TAffineVector; const radius: Single; var inter: TAffineVector; bothface: Boolean = True): Boolean;
  856. function PointDiskProjection(const point, direction, center, up: TAffineVector; const radius: Single; var inter: TAffineVector; bothface: Boolean = True): Boolean;
  857. // Computes closest point on a segment (a segment is a limited line)
  858. function PointSegmentClosestPoint(const point, segmentStart, segmentStop: TAffineVector): TAffineVector; overload;
  859. function PointSegmentClosestPoint(const point, segmentStart, segmentStop: TVector): TVector; overload;
  860. // Computes algebraic distance between segment and line (a segment is a limited line)
  861. function PointSegmentDistance(const point, segmentStart, segmentStop: TAffineVector): Single;
  862. // Computes closest point on a line
  863. function PointLineClosestPoint(const point, linePoint, lineDirection: TAffineVector): TAffineVector;
  864. // Computes algebraic distance between point and line
  865. function PointLineDistance(const point, linePoint, lineDirection: TAffineVector): Single;
  866. // Computes the closest points (2) given two segments
  867. procedure SegmentSegmentClosestPoint(const S0Start, S0Stop, S1Start,
  868. S1Stop: TAffineVector; var Segment0Closest, Segment1Closest: TAffineVector);
  869. // Computes the closest distance between two segments
  870. function SegmentSegmentDistance(const S0Start, S0Stop, S1Start, S1Stop: TAffineVector): Single;
  871. // Computes the closest distance between two lines
  872. function LineLineDistance(const linePt0, lineDir0, linePt1, lineDir1: TAffineVector): Single;
  873. (* ----------------------------------------------------------------------------
  874. Quaternion functions
  875. ----------------------------------------------------------------------------*)
  876. type
  877. TEulerOrder = (eulXYZ, eulXZY, eulYXZ, eulYZX, eulZXY, eulZYX);
  878. // Creates a quaternion from the given values
  879. function QuaternionMake(const Imag: array of Single; Real: Single): TQuaternion; overload;
  880. function QuaternionMake(const X,Y,Z,W: Single): TQuaternion; overload;
  881. function QuaternionMake(const V: TVector): TQuaternion; overload;
  882. // Returns the conjugate of a quaternion
  883. function QuaternionConjugate(const Q: TQuaternion): TQuaternion;
  884. // Returns the magnitude of the quaternion
  885. function QuaternionMagnitude(const Q: TQuaternion): Single;
  886. // Normalizes the given quaternion
  887. procedure NormalizeQuaternion(var Q: TQuaternion);
  888. // Constructs a unit quaternion from two points on unit sphere
  889. function QuaternionFromPoints(const V1, V2: TAffineVector): TQuaternion;
  890. // Converts a unit quaternion into two points on a unit sphere
  891. procedure QuaternionToPoints(const Q: TQuaternion; var ArcFrom, ArcTo: TAffineVector);
  892. // Constructs a unit quaternion from a rotation matrix
  893. function QuaternionFromMatrix(const mat: TMatrix): TQuaternion;
  894. (* Constructs a rotation matrix from (possibly non-unit) quaternion.
  895. Assumes matrix is used to multiply column vector on the left: vnew = mat vold.
  896. Works correctly for right-handed coordinate system and right-handed rotations *)
  897. function QuaternionToMatrix(quat: TQuaternion): TMatrix;
  898. // Constructs an affine rotation matrix from (possibly non-unit) quaternion
  899. function QuaternionToAffineMatrix(quat: TQuaternion): TAffineMatrix;
  900. // Constructs quaternion from angle (in deg) and axis
  901. function QuaternionFromAngleAxis(const angle: Single; const axis: TAffineVector): TQuaternion;
  902. // Constructs quaternion from Euler angles
  903. function QuaternionFromRollPitchYaw(const r, p, Y: Single): TQuaternion;
  904. // Constructs quaternion from Euler angles in arbitrary order (angles in degrees)
  905. function QuaternionFromEuler(const X, Y, Z: Single; eulerOrder: TEulerOrder): TQuaternion;
  906. (* Returns quaternion product qL * qR. Note: order is important!
  907. To combine rotations, use the product QuaternionMuliply(qSecond, qFirst),
  908. which gives the effect of rotating by qFirst then qSecond *)
  909. function QuaternionMultiply(const qL, qR: TQuaternion): TQuaternion;
  910. (* Spherical linear interpolation of unit quaternions with spins.
  911. QStart, QEnd - start and end unit quaternions
  912. t - interpolation parameter (0 to 1)
  913. Spin - number of extra spin rotations to involve *)
  914. function QuaternionSlerp(const QStart, QEnd: TQuaternion; Spin: Integer; T: Single): TQuaternion; overload;
  915. function QuaternionSlerp(const source, dest: TQuaternion; const T: Single): TQuaternion; overload;
  916. (* ----------------------------------------------------------------------------
  917. Exponential functions
  918. -----------------------------------------------------------------------------*)
  919. function Logarithm2(const X: Single): Single; inline;
  920. // Raise base to any power. For fractional exponents, or |exponents| > MaxInt, base must be > 0
  921. function PowerSingle(const Base, Exponent: Single): Single; overload;
  922. // Raise base to an integer
  923. function PowerInteger(Base: Single; Exponent: Integer): Single; overload;
  924. function PowerInt64(Base: Single; Exponent: Int64): Single; overload;
  925. (* ----------------------------------------------------------------------------
  926. Trigonometric functions
  927. ----------------------------------------------------------------------------*)
  928. function DegToRadian(const Degrees: Extended): Extended; overload;
  929. function DegToRadian(const Degrees: Single): Single; overload;
  930. function RadianToDeg(const Radians: Extended): Extended; overload;
  931. function RadianToDeg(const Radians: Single): Single; overload;
  932. // Normalize to an angle in the [-PI; +PI] range
  933. function NormalizeAngle(angle: Single): Single;
  934. // Normalize to an angle in the [-180; 180] range
  935. function NormalizeDegAngle(angle: Single): Single;
  936. // Calculates sine and cosine from the given angle Theta
  937. procedure SinCosine(const Theta: Double; out Sin, Cos: Double); overload;
  938. // Calculates sine and cosine from the given angle Theta
  939. procedure SinCosine(const Theta: Single; out Sin, Cos: Single); overload;
  940. (* Calculates sine and cosine from the given angle Theta and Radius.
  941. sin and cos values calculated from theta are multiplicated by radius *)
  942. procedure SinCosine(const Theta, radius: Double; out Sin, Cos: Double); overload;
  943. (* Calculates sine and cosine from the given angle Theta and Radius.
  944. sin and cos values calculated from theta are multiplicated by radius *)
  945. procedure SinCosine(const Theta, radius: Single; out Sin, Cos: Single); overload;
  946. (* Fills up the two given dynamic arrays with sin cos values.
  947. start and stop angles must be given in degrees, the number of steps is
  948. determined by the length of the given arrays. *)
  949. procedure PrepareSinCosCache(var S, c: array of Single; startAngle, stopAngle: Single);
  950. function ArcCosine(const X: Extended): Extended; overload;
  951. // Fast ArcTangent2 approximation, about 0.07 rads accuracy
  952. function FastArcTangent2(Y, X: Single): Single;
  953. // ------------------------------------------------------------------------------
  954. // Miscellanious math functions
  955. // ------------------------------------------------------------------------------
  956. // Computes 1/Sqrt(v)
  957. function RSqrt(V: Single): Single;
  958. // Computes 1/Sqrt(Sqr(x)+Sqr(y)).
  959. function RLength(X, Y: Single): Single;
  960. // Computes an integer sqrt approximation
  961. function ISqrt(i: Integer): Integer;
  962. // Computes an integer length Result:=Sqrt(x*x+y*y)
  963. function ILength(X, Y: Integer): Integer; overload;
  964. function ILength(X, Y, Z: Integer): Integer; overload;
  965. // Generates a random point on the unit sphere.
  966. // Point repartition is correctly isotropic with no privilegied direction
  967. procedure RandomPointOnSphere(var p: TAffineVector);
  968. // Rounds the floating point value to the closest integer.
  969. // Behaves like Round but returns a floating point value like Int.
  970. function RoundInt(V: Single): Single; overload;
  971. function RoundInt(V: Extended): Extended; overload;
  972. // Multiples i by s and returns the rounded result.
  973. function ScaleAndRound(i: Integer; var S: Single): Integer;
  974. // Returns the sign of the x value using the (-1, 0, +1) convention
  975. function SignStrict(X: Single): Integer;
  976. // Returns True if x is in [a; b]
  977. function IsInRange(const X, a, b: Single): Boolean; overload;
  978. function IsInRange(const X, a, b: Double): Boolean; overload;
  979. // Returns True if p is in the cube defined by d.
  980. function IsInCube(const p, d: TAffineVector): Boolean; overload;
  981. function IsInCube(const p, d: TVector): Boolean; overload;
  982. // Returns the minimum value of the array.
  983. function MinFloat(values: PSingleArray; nbItems: Integer): Single; overload;
  984. function MinFloat(values: PDoubleArray; nbItems: Integer): Double; overload;
  985. function MinFloat(values: PExtendedArray; nbItems: Integer): Extended; overload;
  986. // Returns the minimum of given values.
  987. function MinFloat(const V1, V2: Single): Single; overload;
  988. function MinFloat(const V: array of Single): Single; overload;
  989. function MinFloat(const V1, V2: Double): Double; overload;
  990. {$IFDEF USE_PLATFORM_HAS_EXTENDED}
  991. function MinFloat(const V1, V2: Extended): Extended; overload;
  992. {$ENDIF}
  993. function MinFloat(const V1, V2, V3: Single): Single; overload;
  994. function MinFloat(const V1, V2, V3: Double): Double; overload;
  995. {$IFDEF USE_PLATFORM_HAS_EXTENDED}
  996. function MinFloat(const V1, V2, V3: Extended): Extended; overload;
  997. {$ENDIF}
  998. // Returns the maximum value of the array.
  999. function MaxFloat(values: PSingleArray; nbItems: Integer): Single; overload;
  1000. function MaxFloat(values: PDoubleArray; nbItems: Integer): Double; overload;
  1001. function MaxFloat(values: PExtendedArray; nbItems: Integer): Extended; overload;
  1002. function MaxFloat(const V: array of Single): Single; overload;
  1003. // Returns the maximum of given values.
  1004. function MaxFloat(const V1, V2: Single): Single; overload;
  1005. function MaxFloat(const V1, V2: Double): Double; overload;
  1006. {$IFDEF USE_PLATFORM_HAS_EXTENDED}
  1007. function MaxFloat(const V1, V2: Extended): Extended; overload;
  1008. {$ENDIF USE_PLATFORM_HAS_EXTENDED}
  1009. function MaxFloat(const V1, V2, V3: Single): Single; overload;
  1010. function MaxFloat(const V1, V2, V3: Double): Double; overload;
  1011. {$IFDEF USE_PLATFORM_HAS_EXTENDED}
  1012. function MaxFloat(const V1, V2, V3: Extended): Extended; overload;
  1013. {$ENDIF USE_PLATFORM_HAS_EXTENDED}
  1014. function MinInteger(const V1, V2: Integer): Integer; overload;
  1015. function MinInteger(const V1, V2: Cardinal): Cardinal; overload;
  1016. function MinInteger(const V1, V2, V3: Integer): Integer; overload;
  1017. function MinInteger(const V1, V2, V3: Cardinal): Cardinal; overload;
  1018. function MaxInteger(const V1, V2: Integer): Integer; overload;
  1019. function MaxInteger(const V1, V2: Cardinal): Cardinal; overload;
  1020. function MaxInteger(const V1, V2, V3: Integer): Integer; overload;
  1021. function MaxInteger(const V1, V2, V3: Cardinal): Cardinal; overload;
  1022. function ClampInteger(const value, min, max: Integer): Integer; overload; inline;
  1023. function ClampInteger(const value, min, max: Cardinal): Cardinal; overload; inline;
  1024. // Computes the triangle's area
  1025. function TriangleArea(const p1, p2, p3: TAffineVector): Single; overload;
  1026. // Computes the polygons's area. Points must be coplanar. Polygon needs not be convex
  1027. function PolygonArea(const p: PAffineVectorArray; nSides: Integer): Single; overload;
  1028. // Computes a 2D triangle's signed area. Only X and Y coordinates are used, Z is ignored
  1029. function TriangleSignedArea(const p1, p2, p3: TAffineVector): Single; overload;
  1030. // Computes a 2D polygon's signed area. Only X and Y coordinates are used, Z is ignored. Polygon needs not be convex
  1031. function PolygonSignedArea(const p: PAffineVectorArray; nSides: Integer): Single; overload;
  1032. (* Multiplies values in the array by factor.
  1033. This function is especially efficient for large arrays, it is not recommended
  1034. for arrays that have less than 10 items.
  1035. Expected performance is 4 to 5 times that of a Deliph-compiled loop on AMD
  1036. CPUs, and 2 to 3 when 3DNow! isn't available *)
  1037. procedure ScaleFloatArray(values: PSingleArray; nb: Integer; var factor: Single); overload;
  1038. procedure ScaleFloatArray(var values: TSingleArray; factor: Single); overload;
  1039. // Adds delta to values in the array. Array size must be a multiple of four
  1040. procedure OffsetFloatArray(values: PSingleArray; nb: Integer; var delta: Single); overload;
  1041. procedure OffsetFloatArray(var values: array of Single; delta: Single); overload;
  1042. procedure OffsetFloatArray(valuesDest, valuesDelta: PSingleArray; nb: Integer); overload;
  1043. // Returns the max of the X, Y and Z components of a vector (W is ignored)
  1044. function MaxXYZComponent(const V: TVector): Single; overload;
  1045. function MaxXYZComponent(const V: TAffineVector): Single; overload;
  1046. // Returns the min of the X, Y and Z components of a vector (W is ignored)
  1047. function MinXYZComponent(const V: TVector): Single; overload;
  1048. function MinXYZComponent(const V: TAffineVector): Single; overload;
  1049. // Returns the max of the Abs(X), Abs(Y) and Abs(Z) components of a vector (W is ignored)
  1050. function MaxAbsXYZComponent(V: TVector): Single;
  1051. // Returns the min of the Abs(X), Abs(Y) and Abs(Z) components of a vector (W is ignored)
  1052. function MinAbsXYZComponent(V: TVector): Single;
  1053. // Replace components of v with the max of v or v1 component. Maximum is computed per component
  1054. procedure MaxVector(var V: TVector; const V1: TVector); overload;
  1055. procedure MaxVector(var V: TAffineVector; const V1: TAffineVector); overload;
  1056. // Replace components of v with the min of v or v1 component. Minimum is computed per component
  1057. procedure MinVector(var V: TVector; const V1: TVector); overload;
  1058. procedure MinVector(var V: TAffineVector; const V1: TAffineVector); overload;
  1059. // Sorts given array in ascending order. NOTE : current implementation is a slow bubble sort...
  1060. procedure SortArrayAscending(var a: array of Extended);
  1061. // Clamps aValue in the aMin-aMax interval
  1062. function ClampValue(const aValue, aMin, aMax: Single): Single; overload;
  1063. // Clamps aValue in the aMin-INF interval
  1064. function ClampValue(const aValue, aMin: Single): Single; overload;
  1065. // Returns the detected optimization mode. Returned values is either 'FPU', '3DNow!' or 'SSE'
  1066. function GeometryOptimizationMode: String;
  1067. (* Begins a FPU-only section.
  1068. You can use a FPU-only section to force use of FPU versions of the math
  1069. functions, though typically slower than their SIMD counterparts, they have
  1070. a higher precision (80 bits internally) that may be required in some cases.
  1071. Each BeginFPUOnlySection call must be balanced by a EndFPUOnlySection (calls
  1072. can be nested). *)
  1073. procedure BeginFPUOnlySection;
  1074. // Ends a FPU-only section. See BeginFPUOnlySection
  1075. procedure EndFPUOnlySection;
  1076. // --------------------- Unstandardized functions after these lines
  1077. // Mixed functions
  1078. // Turn a triplet of rotations about x, y, and z (in that order) into an equivalent rotation around a single axis (all in radians)
  1079. function ConvertRotation(const Angles: TAffineVector): TVector;
  1080. // Miscellaneous functions
  1081. function MakeAffineDblVector(var V: array of Double): TAffineDblVector;
  1082. function MakeDblVector(var V: array of Double): THomogeneousDblVector;
  1083. // Converts a vector containing double sized values into a vector with single sized values
  1084. function VectorAffineDblToFlt(const V: TAffineDblVector): TAffineVector;
  1085. // Converts a vector containing double sized values into a vector with single sized values
  1086. function VectorDblToFlt(const V: THomogeneousDblVector): THomogeneousVector;
  1087. // Converts a vector containing single sized values into a vector with double sized values
  1088. function VectorAffineFltToDbl(const V: TAffineVector): TAffineDblVector;
  1089. // Converts a vector containing single sized values into a vector with double sized values
  1090. function VectorFltToDbl(const V: TVector): THomogeneousDblVector;
  1091. (* The code below is from Wm. Randolph Franklin <[email protected]>
  1092. with some minor modifications for speed. It returns 1 for strictly
  1093. interior points, 0 for strictly exterior, and 0 or 1 for points on the boundary *)
  1094. function PointInPolygon(const xp, yp: array of Single; X, Y: Single): Boolean;
  1095. // PtInRegion
  1096. function IsPointInPolygon(const Polygon: array of TPoint; const p: TPoint): Boolean;
  1097. procedure DivMod(Dividend: Integer; Divisor: Word; var result, Remainder: Word);
  1098. // Coordinate system manipulation functions
  1099. // Rotates the given coordinate system (represented by the matrix) around its Y-axis
  1100. function Turn(const Matrix: TMatrix; Angle: Single): TMatrix; overload;
  1101. // Rotates the given coordinate system (represented by the matrix) around MasterUp
  1102. function Turn(const Matrix: TMatrix; const MasterUp: TAffineVector; Angle: Single): TMatrix; overload;
  1103. // Rotates the given coordinate system (represented by the matrix) around its X-axis
  1104. function Pitch(const Matrix: TMatrix; Angle: Single): TMatrix; overload;
  1105. // Rotates the given coordinate system (represented by the matrix) around MasterRight
  1106. function Pitch(const Matrix: TMatrix; const MasterRight: TAffineVector; Angle: Single): TMatrix; overload;
  1107. // Rotates the given coordinate system (represented by the matrix) around its Z-axis
  1108. function Roll(const Matrix: TMatrix; Angle: Single): TMatrix; overload;
  1109. // Rotates the given coordinate system (represented by the matrix) around MasterDirection
  1110. function Roll(const Matrix: TMatrix; const MasterDirection: TAffineVector; Angle: Single): TMatrix; overload;
  1111. // Intersection functions
  1112. (* Compute the intersection point "res" of a line with a plane.
  1113. Return value:
  1114. 0 : no intersection, line parallel to plane
  1115. 1 : res is valid
  1116. -1 : line is inside plane
  1117. Adapted from:
  1118. E.Hartmann, Computeruntersttzte Darstellende Geometrie, B.G. Teubner Stuttgart 1988 *)
  1119. function IntersectLinePlane(const point, direction: TVector;
  1120. const plane: THmgPlane; intersectPoint: PVector = nil): Integer; overload;
  1121. (* Compute intersection between a triangle and a box.
  1122. Returns True if an intersection was found *)
  1123. function IntersectTriangleBox(const p1, p2, p3, aMinExtent, aMaxExtent: TAffineVector): Boolean;
  1124. (* Compute intersection between a Sphere and a box.
  1125. Up, Direction and Right must be normalized!
  1126. Use CubDepth, CubeHeight and CubeWidth to scale TGLCube *)
  1127. function IntersectSphereBox(const SpherePos: TVector;
  1128. const SphereRadius: Single; const BoxMatrix: TMatrix;
  1129. const BoxScale: TAffineVector; intersectPoint: PAffineVector = nil;
  1130. normal: PAffineVector = nil; depth: PSingle = nil): Boolean;
  1131. (* Compute intersection between a ray and a plane.
  1132. Returns True if an intersection was found, the intersection point is placed
  1133. in intersectPoint is the reference is not nil *)
  1134. function RayCastPlaneIntersect(const rayStart, rayVector: TVector;
  1135. const planePoint, planeNormal: TVector; intersectPoint: PVector = nil): Boolean; overload;
  1136. function RayCastPlaneXZIntersect(const rayStart, rayVector: TVector;
  1137. const planeY: Single; intersectPoint: PVector = nil): Boolean; overload;
  1138. // Compute intersection between a ray and a triangle
  1139. function RayCastTriangleIntersect(const rayStart, rayVector: TVector;
  1140. const p1, p2, p3: TAffineVector; intersectPoint: PVector = nil;
  1141. intersectNormal: PVector = nil): Boolean; overload;
  1142. // Compute the min distance a ray will pass to a point
  1143. function RayCastMinDistToPoint(const rayStart, rayVector: TVector; const point: TVector): Single;
  1144. // Determines if a ray will intersect with a given sphere
  1145. function RayCastIntersectsSphere(const rayStart, rayVector: TVector;
  1146. const sphereCenter: TVector; const SphereRadius: Single): Boolean; overload;
  1147. (* Calculates the intersections between a sphere and a ray.
  1148. Returns 0 if no intersection is found (i1 and i2 untouched), 1 if one
  1149. intersection was found (i1 defined, i2 untouched), and 2 is two intersections
  1150. were found (i1 and i2 defined) *)
  1151. function RayCastSphereIntersect(const rayStart, rayVector: TVector;
  1152. const sphereCenter: TVector; const SphereRadius: Single; var i1, i2: TVector): Integer; overload;
  1153. (* Compute intersection between a ray and a box.
  1154. Returns True if an intersection was found, the intersection point is
  1155. placed in intersectPoint if the reference is not nil *)
  1156. function RayCastBoxIntersect(const rayStart, rayVector, aMinExtent,
  1157. aMaxExtent: TAffineVector; intersectPoint: PAffineVector = nil): Boolean;
  1158. (* Some 2d intersection functions *)
  1159. // Determine if 2 rectanges intersect
  1160. function RectanglesIntersect(const ACenterOfRect1, ACenterOfRect2, ASizeOfRect1,
  1161. ASizeOfRect2: TVector2f): Boolean;
  1162. // Determine if BigRect completely contains SmallRect
  1163. function RectangleContains(const ACenterOfBigRect1, ACenterOfSmallRect2,
  1164. ASizeOfBigRect1, ASizeOfSmallRect2: TVector2f;
  1165. const AEps: Single = 0.0): Boolean;
  1166. (* Computes the visible radius of a sphere in a perspective projection.
  1167. This radius can be used for occlusion culling (cone extrusion) or 2D
  1168. intersection testing. *)
  1169. function SphereVisibleRadius(distance, radius: Single): Single;
  1170. // Extracts a TFrustum for combined modelview and projection matrices
  1171. function ExtractFrustumFromModelViewProjection(const modelViewProj: TMatrix): TFrustum;
  1172. // Determines if volume is clipped or not
  1173. function IsVolumeClipped(const objPos: TAffineVector; const objRadius: Single;
  1174. const Frustum: TFrustum): Boolean; overload;
  1175. function IsVolumeClipped(const objPos: TVector; const objRadius: Single;
  1176. const Frustum: TFrustum): Boolean; overload; inline;
  1177. function IsVolumeClipped(const min, max: TAffineVector; const Frustum: TFrustum): Boolean; overload; inline;
  1178. (* Misc funcs *)
  1179. (* Creates a parallel projection matrix.
  1180. Transformed points will projected on the plane along the specified direction *)
  1181. function MakeParallelProjectionMatrix(const plane: THmgPlane; const dir: TVector): TMatrix;
  1182. (* Creates a shadow projection matrix.
  1183. Shadows will be projected onto the plane defined by planePoint and planeNormal,
  1184. from lightPos *)
  1185. function MakeShadowMatrix(const planePoint, planeNormal, lightPos: TVector): TMatrix;
  1186. (* Builds a reflection matrix for the given plane.
  1187. Reflection matrix allow implementing planar reflectors (mirrors) *)
  1188. function MakeReflectionMatrix(const planePoint, planeNormal: TAffineVector): TMatrix;
  1189. (* Packs an homogeneous rotation matrix to 6 bytes.
  1190. The 6:64 (or 6:36) compression ratio is achieved by computing the quaternion
  1191. associated to the matrix and storing its Imaginary components at 16 bits
  1192. precision each. Deviation is typically below 0.01% and around 0.1% in worst case situations.
  1193. Note: quaternion conversion is faster and more robust than an angle decomposition *)
  1194. function PackRotationMatrix(const mat: TMatrix): TPackedRotationMatrix;
  1195. // Restores a packed rotation matrix. See PackRotationMatrix
  1196. function UnPackRotationMatrix(const packedMatrix: TPackedRotationMatrix): TMatrix;
  1197. (* Calculates the barycentric coordinates for the point p on the triangle
  1198. defined by the vertices v1, v2 and v3. That is, solves
  1199. p = u * v1 + v * v2 + (1-u-v) * v3
  1200. for u,v.
  1201. Returns true if the point is inside the triangle, false otherwise.
  1202. NOTE: This function assumes that the point lies on the plane defined by the triangle.
  1203. If this is not the case, the function will not work correctly! *)
  1204. function BarycentricCoordinates(const V1, V2, V3, p: TAffineVector; var u, V: Single): Boolean;
  1205. (*Calculates angles for the Camera.MoveAroundTarget(pitch, turn) procedure.
  1206. Initially from then GLCameraColtroller unit, requires AOriginalUpVector to contain only -1, 0 or 1.
  1207. Result contains pitch and turn angles *)
  1208. function GetSafeTurnAngle(const AOriginalPosition, AOriginalUpVector,
  1209. ATargetPosition, AMoveAroundTargetCenter: TVector): TVector2f; overload;
  1210. function GetSafeTurnAngle(const AOriginalPosition, AOriginalUpVector,
  1211. ATargetPosition, AMoveAroundTargetCenter: TAffineVector): TVector2f; overload;
  1212. // Extracted from Camera.MoveAroundTarget(pitch, turn)
  1213. function MoveObjectAround(const AMovingObjectPosition, AMovingObjectUp,
  1214. ATargetPosition: TVector; pitchDelta, turnDelta: Single): TVector;
  1215. // Calcualtes Angle between 2 Vectors: (A-CenterPoint) and (B-CenterPoint). In radians
  1216. function AngleBetweenVectors(const a, b, ACenterPoint: TVector): Single; overload;
  1217. function AngleBetweenVectors(const a, b, ACenterPoint: TAffineVector): Single; overload;
  1218. (*AOriginalPosition - Object initial position.
  1219. ACenter - some point, from which is should be distanced.
  1220. ADistance + AFromCenterSpot - distance, which object should keep from ACenter or
  1221. ADistance + not AFromCenterSpot - distance, which object should shift
  1222. from his current position away from center *)
  1223. function ShiftObjectFromCenter(const AOriginalPosition: TVector;
  1224. const ACenter: TVector; const ADistance: Single;
  1225. const AFromCenterSpot: Boolean): TVector; overload;
  1226. function ShiftObjectFromCenter(const AOriginalPosition: TAffineVector;
  1227. const ACenter: TAffineVector; const ADistance: Single;
  1228. const AFromCenterSpot: Boolean): TAffineVector; overload;
  1229. const
  1230. cPI: Single = 3.141592654;
  1231. cPIdiv180: Single = 0.017453292;
  1232. c180divPI: Single = 57.29577951;
  1233. c2PI: Single = 6.283185307;
  1234. cPIdiv2: Single = 1.570796326;
  1235. cPIdiv4: Single = 0.785398163;
  1236. c3PIdiv2: Single = 4.71238898;
  1237. c3PIdiv4: Single = 2.35619449;
  1238. cInv2PI: Single = 1 / 6.283185307;
  1239. cInv360: Single = 1 / 360;
  1240. c180: Single = 180;
  1241. c360: Single = 360;
  1242. cOneHalf: Single = 0.5;
  1243. cLn10: Single = 2.302585093;
  1244. // Ranges of the IEEE floating point types, including denormals
  1245. // with Math.pas compatible name
  1246. MinSingle = 1.5E-45;
  1247. MaxSingle = 3.4E+38;
  1248. MinDouble = 5.0E-324;
  1249. MaxDouble = 1.7E+308;
  1250. MinExtended = 3.4E-4932;
  1251. MaxExtended = MaxDouble; //1.1E+4932 <-Overflowing in c++;
  1252. MinComp = -9.223372036854775807E+18;
  1253. MaxComp = 9.223372036854775807E+18;
  1254. var
  1255. (* This var is adjusted during "initialization", current values are
  1256. + 0 : use standard optimized FPU code
  1257. + 1 : use 3DNow! optimized code (requires K6-2/3 CPU)
  1258. + 2 : use Intel SSE code (Pentium III, NOT IMPLEMENTED YET !) *)
  1259. vSIMD: Byte = 0;
  1260. // ==============================================================
  1261. implementation
  1262. // ==============================================================
  1263. const
  1264. {$IFDEF USE_ASM}
  1265. // FPU status flags (high order byte)
  1266. cwChop: Word = $1F3F;
  1267. {$ENDIF}
  1268. // to be used as descriptive indices
  1269. X = 0;
  1270. Y = 1;
  1271. Z = 2;
  1272. W = 3;
  1273. cZero: Single = 0.0;
  1274. cOne: Single = 1.0;
  1275. cOneDotFive: Single = 0.5;
  1276. function GeometryOptimizationMode: String;
  1277. begin
  1278. case vSIMD of
  1279. 0: result := 'FPU';
  1280. 1: result := '3DNow!';
  1281. 2: result := 'SSE';
  1282. else
  1283. result := '*ERR*';
  1284. end;
  1285. end;
  1286. var
  1287. vOldSIMD: Byte;
  1288. vFPUOnlySectionCounter: Integer;
  1289. procedure BeginFPUOnlySection;
  1290. begin
  1291. if vFPUOnlySectionCounter = 0 then
  1292. vOldSIMD := vSIMD;
  1293. Inc(vFPUOnlySectionCounter);
  1294. vSIMD := 0;
  1295. end;
  1296. procedure EndFPUOnlySection;
  1297. begin
  1298. Dec(vFPUOnlySectionCounter);
  1299. Assert(vFPUOnlySectionCounter >= 0);
  1300. if vFPUOnlySectionCounter = 0 then
  1301. vSIMD := vOldSIMD;
  1302. end;
  1303. // ------------------------------------------------------------------------------
  1304. // ----------------- vector functions -------------------------------------------
  1305. // ------------------------------------------------------------------------------
  1306. function TexPointMake(const S, T: Single): TTexPoint;
  1307. begin
  1308. result.S := S;
  1309. result.T := T;
  1310. end;
  1311. function AffineVectorMake(const X, Y, Z: Single): TAffineVector; overload;
  1312. begin
  1313. result.X := X;
  1314. result.Y := Y;
  1315. result.Z := Z;
  1316. end;
  1317. function AffineVectorMake(const V: TVector): TAffineVector;
  1318. begin
  1319. result.X := V.X;
  1320. result.Y := V.Y;
  1321. result.Z := V.Z;
  1322. end;
  1323. procedure SetAffineVector(out V: TAffineVector; const X, Y, Z: Single);
  1324. begin
  1325. V.X := X;
  1326. V.Y := Y;
  1327. V.Z := Z;
  1328. end;
  1329. procedure SetVector(out V: TAffineVector; const X, Y, Z: Single);
  1330. begin
  1331. V.X := X;
  1332. V.Y := Y;
  1333. V.Z := Z;
  1334. end;
  1335. procedure SetVector(out V: TAffineVector; const vSrc: TVector);
  1336. begin
  1337. V.X := vSrc.X;
  1338. V.Y := vSrc.Y;
  1339. V.Z := vSrc.Z;
  1340. end;
  1341. procedure SetVector(out V: TAffineVector; const vSrc: TAffineVector);
  1342. begin
  1343. V.X := vSrc.X;
  1344. V.Y := vSrc.Y;
  1345. V.Z := vSrc.Z;
  1346. end;
  1347. procedure SetVector(out V: TAffineDblVector; const vSrc: TAffineVector);
  1348. begin
  1349. V.X := vSrc.X;
  1350. V.Y := vSrc.Y;
  1351. V.Z := vSrc.Z;
  1352. end;
  1353. procedure SetVector(out V: TAffineDblVector; const vSrc: TVector);
  1354. begin
  1355. V.X := vSrc.X;
  1356. V.Y := vSrc.Y;
  1357. V.Z := vSrc.Z;
  1358. end;
  1359. function VectorMake(const V: TAffineVector; W: Single = 0): TVector;
  1360. begin
  1361. result.X := V.X;
  1362. result.Y := V.Y;
  1363. result.Z := V.Z;
  1364. result.W := W;
  1365. end;
  1366. function VectorMake(const X, Y, Z: Single; W: Single = 0): TVector;
  1367. begin
  1368. result.X := X;
  1369. result.Y := Y;
  1370. result.Z := Z;
  1371. result.W := W;
  1372. end;
  1373. function VectorMake(const Q: TQuaternion): TVector; overload; inline;
  1374. begin
  1375. result.X := Q.X;
  1376. result.Y := Q.Y;
  1377. result.Z := Q.Z;
  1378. result.W := Q.W;
  1379. end;
  1380. function PointMake(const X, Y, Z: Single): TVector; overload;
  1381. begin
  1382. result.X := X;
  1383. result.Y := Y;
  1384. result.Z := Z;
  1385. result.W := 1;
  1386. end;
  1387. function PointMake(const V: TAffineVector): TVector; overload;
  1388. begin
  1389. result.X := V.X;
  1390. result.Y := V.Y;
  1391. result.Z := V.Z;
  1392. result.W := 1;
  1393. end;
  1394. function PointMake(const V: TVector): TVector; overload;
  1395. begin
  1396. result.X := V.X;
  1397. result.Y := V.Y;
  1398. result.Z := V.Z;
  1399. result.W := 1;
  1400. end;
  1401. procedure SetVector(out V: TVector; const X, Y, Z: Single; W: Single = 0);
  1402. begin
  1403. V.X := X;
  1404. V.Y := Y;
  1405. V.Z := Z;
  1406. V.W := W;
  1407. end;
  1408. procedure SetVector(out V: TVector; const av: TAffineVector; W: Single = 0);
  1409. begin
  1410. V.X := av.X;
  1411. V.Y := av.Y;
  1412. V.Z := av.Z;
  1413. V.W := W;
  1414. end;
  1415. procedure SetVector(out V: TVector; const vSrc: TVector);
  1416. begin
  1417. // faster than memcpy, move or ':=' on the TVector...
  1418. V.X := vSrc.X;
  1419. V.Y := vSrc.Y;
  1420. V.Z := vSrc.Z;
  1421. V.W := vSrc.W;
  1422. end;
  1423. procedure MakePoint(out V: TVector; const X, Y, Z: Single);
  1424. begin
  1425. V.X := X;
  1426. V.Y := Y;
  1427. V.Z := Z;
  1428. V.W := 1.0;
  1429. end;
  1430. procedure MakePoint(out V: TVector; const av: TAffineVector);
  1431. begin
  1432. V.X := av.X;
  1433. V.Y := av.Y;
  1434. V.Z := av.Z;
  1435. V.W := 1.0; // cOne
  1436. end;
  1437. procedure MakePoint(out V: TVector; const av: TVector);
  1438. begin
  1439. V.X := av.X;
  1440. V.Y := av.Y;
  1441. V.Z := av.Z;
  1442. V.W := 1.0; // cOne
  1443. end;
  1444. procedure MakeVector(out V: TAffineVector; const X, Y, Z: Single); overload;
  1445. begin
  1446. V.X := X;
  1447. V.Y := Y;
  1448. V.Z := Z;
  1449. end;
  1450. procedure MakeVector(out V: TVector; const X, Y, Z: Single);
  1451. begin
  1452. V.X := X;
  1453. V.Y := Y;
  1454. V.Z := Z;
  1455. V.W := 0.0 // cZero;
  1456. end;
  1457. procedure MakeVector(out V: TVector; const av: TAffineVector);
  1458. begin
  1459. V.X := av.X;
  1460. V.Y := av.Y;
  1461. V.Z := av.Z;
  1462. V.W := 0.0 // cZero;
  1463. end;
  1464. procedure MakeVector(out V: TVector; const av: TVector);
  1465. begin
  1466. V.X := av.X;
  1467. V.Y := av.Y;
  1468. V.Z := av.Z;
  1469. V.W := 0.0; // cZero;
  1470. end;
  1471. procedure RstVector(var V: TAffineVector);
  1472. begin
  1473. V.X := 0;
  1474. V.Y := 0;
  1475. V.Z := 0;
  1476. end;
  1477. procedure RstVector(var V: TVector);
  1478. begin
  1479. V.X := 0;
  1480. V.Y := 0;
  1481. V.Z := 0;
  1482. V.W := 0;
  1483. end;
  1484. function VectorAdd(const V1, V2: TVector2f): TVector2f;
  1485. begin
  1486. result.X := V1.X + V2.X;
  1487. result.Y := V1.Y + V2.Y;
  1488. end;
  1489. function VectorAdd(const V1, V2: TAffineVector): TAffineVector;
  1490. begin
  1491. result.X := V1.X + V2.X;
  1492. result.Y := V1.Y + V2.Y;
  1493. result.Z := V1.Z + V2.Z;
  1494. end;
  1495. procedure VectorAdd(const V1, V2: TAffineVector; var vr: TAffineVector); overload;
  1496. begin
  1497. vr.X := V1.X + V2.X;
  1498. vr.Y := V1.Y + V2.Y;
  1499. vr.Z := V1.Z + V2.Z;
  1500. end;
  1501. procedure VectorAdd(const V1, V2: TAffineVector; vr: PAffineVector); overload;
  1502. begin
  1503. vr^.X := V1.X + V2.X;
  1504. vr^.Y := V1.Y + V2.Y;
  1505. vr^.Z := V1.Z + V2.Z;
  1506. end;
  1507. function VectorAdd(const V1, V2: TVector): TVector;
  1508. begin
  1509. result.X := V1.X + V2.X;
  1510. result.Y := V1.Y + V2.Y;
  1511. result.Z := V1.Z + V2.Z;
  1512. result.W := V1.W + V2.W;
  1513. end;
  1514. procedure VectorAdd(const V1, V2: TVector; var vr: TVector);
  1515. begin
  1516. vr.X := V1.X + V2.X;
  1517. vr.Y := V1.Y + V2.Y;
  1518. vr.Z := V1.Z + V2.Z;
  1519. vr.W := V1.W + V2.W;
  1520. end;
  1521. function VectorAdd(const V: TAffineVector; const f: Single): TAffineVector;
  1522. begin
  1523. result.X := V.X + f;
  1524. result.Y := V.Y + f;
  1525. result.Z := V.Z + f;
  1526. end;
  1527. function VectorAdd(const V: TVector; const f: Single): TVector;
  1528. begin
  1529. result.X := V.X + f;
  1530. result.Y := V.Y + f;
  1531. result.Z := V.Z + f;
  1532. result.W := V.W + f;
  1533. end;
  1534. function PointAdd(var V1: TVector; const V2: TVector): TVector;
  1535. begin
  1536. result.X := V1.X + V2.X;
  1537. result.Y := V1.Y + V2.Y;
  1538. result.Z := V1.Z + V2.Z;
  1539. result.W := 1;
  1540. end;
  1541. procedure AddVector(var V1: TAffineVector; const V2: TAffineVector);
  1542. begin
  1543. V1.X := V1.X + V2.X;
  1544. V1.Y := V1.Y + V2.Y;
  1545. V1.Z := V1.Z + V2.Z;
  1546. end;
  1547. procedure AddVector(var V1: TAffineVector; const V2: TVector);
  1548. begin
  1549. V1.X := V1.X + V2.X;
  1550. V1.Y := V1.Y + V2.Y;
  1551. V1.Z := V1.Z + V2.Z;
  1552. end;
  1553. procedure AddVector(var V1: TVector; const V2: TVector);
  1554. begin
  1555. V1.X := V1.X + V2.X;
  1556. V1.Y := V1.Y + V2.Y;
  1557. V1.Z := V1.Z + V2.Z;
  1558. V1.W := V1.W + V2.W;
  1559. end;
  1560. procedure AddVector(var V: TAffineVector; const f: Single);
  1561. begin
  1562. V.X := V.X + f;
  1563. V.Y := V.Y + f;
  1564. V.Z := V.Z + f;
  1565. end;
  1566. procedure AddVector(var V: TVector; const f: Single);
  1567. begin
  1568. V.X := V.X + f;
  1569. V.Y := V.Y + f;
  1570. V.Z := V.Z + f;
  1571. V.W := V.W + f;
  1572. end;
  1573. procedure AddPoint(var V1: TVector; const V2: TVector);
  1574. begin
  1575. V1.X := V1.X + V2.X;
  1576. V1.Y := V1.Y + V2.Y;
  1577. V1.Z := V1.Z + V2.Z;
  1578. V1.W := 1;
  1579. end;
  1580. procedure TexPointArrayAdd(const src: PTexPointArray; const delta: TTexPoint;
  1581. const nb: Integer; dest: PTexPointArray); overload;
  1582. var
  1583. i: Integer;
  1584. begin
  1585. for i := 0 to nb - 1 do
  1586. begin
  1587. dest^[i].S := src^[i].S + delta.S;
  1588. dest^[i].T := src^[i].T + delta.T;
  1589. end;
  1590. end;
  1591. procedure TexPointArrayScaleAndAdd(const src: PTexPointArray;
  1592. const delta: TTexPoint; const nb: Integer; const scale: TTexPoint;
  1593. dest: PTexPointArray); overload;
  1594. var
  1595. i: Integer;
  1596. begin
  1597. for i := 0 to nb - 1 do
  1598. begin
  1599. dest^[i].S := src^[i].S * scale.S + delta.S;
  1600. dest^[i].T := src^[i].T * scale.T + delta.T;
  1601. end;
  1602. end;
  1603. procedure VectorArrayAdd(const src: PAffineVectorArray;
  1604. const delta: TAffineVector; const nb: Integer; dest: PAffineVectorArray);
  1605. var
  1606. i: Integer;
  1607. begin
  1608. for i := 0 to nb - 1 do
  1609. begin
  1610. dest^[i].X := src^[i].X + delta.X;
  1611. dest^[i].Y := src^[i].Y + delta.Y;
  1612. dest^[i].Z := src^[i].Z + delta.Z;
  1613. end;
  1614. end;
  1615. function VectorSubtract(const V1, V2: TAffineVector): TAffineVector;
  1616. begin
  1617. result.X := V1.X - V2.X;
  1618. result.Y := V1.Y - V2.Y;
  1619. result.Z := V1.Z - V2.Z;
  1620. end;
  1621. function VectorSubtract(const V1, V2: TVector2f): TVector2f;
  1622. begin
  1623. result.X := V1.X - V2.X;
  1624. result.Y := V1.Y - V2.Y;
  1625. end;
  1626. procedure VectorSubtract(const V1, V2: TAffineVector;
  1627. var result: TAffineVector);
  1628. begin
  1629. result.X := V1.X - V2.X;
  1630. result.Y := V1.Y - V2.Y;
  1631. result.Z := V1.Z - V2.Z;
  1632. end;
  1633. procedure VectorSubtract(const V1, V2: TAffineVector; var result: TVector);
  1634. begin
  1635. result.X := V1.X - V2.X;
  1636. result.Y := V1.Y - V2.Y;
  1637. result.Z := V1.Z - V2.Z;
  1638. result.W := 0;
  1639. end;
  1640. procedure VectorSubtract(const V1: TVector; const V2: TAffineVector; var result: TVector);
  1641. begin
  1642. result.X := V1.X - V2.X;
  1643. result.Y := V1.Y - V2.Y;
  1644. result.Z := V1.Z - V2.Z;
  1645. result.W := V1.W;
  1646. end;
  1647. function VectorSubtract(const V1, V2: TVector): TVector;
  1648. begin
  1649. result.X := V1.X - V2.X;
  1650. result.Y := V1.Y - V2.Y;
  1651. result.Z := V1.Z - V2.Z;
  1652. result.W := V1.W - V2.W;
  1653. end;
  1654. procedure VectorSubtract(const V1, V2: TVector; var result: TVector);
  1655. begin
  1656. result.X := V1.X - V2.X;
  1657. result.Y := V1.Y - V2.Y;
  1658. result.Z := V1.Z - V2.Z;
  1659. result.W := V1.W - V2.W;
  1660. end;
  1661. procedure VectorSubtract(const V1, V2: TVector;
  1662. var result: TAffineVector); overload;
  1663. begin
  1664. result.X := V1.X - V2.X;
  1665. result.Y := V1.Y - V2.Y;
  1666. result.Z := V1.Z - V2.Z;
  1667. end;
  1668. function VectorSubtract(const V1: TAffineVector; delta: Single): TAffineVector;
  1669. begin
  1670. result.X := V1.X - delta;
  1671. result.Y := V1.Y - delta;
  1672. result.Z := V1.Z - delta;
  1673. end;
  1674. function VectorSubtract(const V1: TVector; delta: Single): TVector;
  1675. begin
  1676. result.X := V1.X - delta;
  1677. result.Y := V1.Y - delta;
  1678. result.Z := V1.Z - delta;
  1679. result.W := V1.W - delta;
  1680. end;
  1681. procedure SubtractVector(var V1: TAffineVector; const V2: TAffineVector);
  1682. begin
  1683. V1.X := V1.X - V2.X;
  1684. V1.Y := V1.Y - V2.Y;
  1685. V1.Z := V1.Z - V2.Z;
  1686. end;
  1687. procedure SubtractVector(var V1: TVector2f; const V2: TVector2f);
  1688. begin
  1689. V1.X := V1.X - V2.X;
  1690. V1.Y := V1.Y - V2.Y;
  1691. end;
  1692. procedure SubtractVector(var V1: TVector; const V2: TVector);
  1693. begin
  1694. V1.X := V1.X - V2.X;
  1695. V1.Y := V1.Y - V2.Y;
  1696. V1.Z := V1.Z - V2.Z;
  1697. V1.W := V1.W - V2.W;
  1698. end;
  1699. procedure CombineVector(var vr: TAffineVector; const V: TAffineVector;
  1700. var f: Single);
  1701. begin
  1702. vr.X := vr.X + V.X * f;
  1703. vr.Y := vr.Y + V.Y * f;
  1704. vr.Z := vr.Z + V.Z * f;
  1705. end;
  1706. procedure CombineVector(var vr: TAffineVector; const V: TAffineVector;
  1707. pf: PFloat);
  1708. begin
  1709. vr.X := vr.X + V.X * pf^;
  1710. vr.Y := vr.Y + V.Y * pf^;
  1711. vr.Z := vr.Z + V.Z * pf^;
  1712. end;
  1713. function TexPointCombine(const t1, t2: TTexPoint; f1, f2: Single): TTexPoint;
  1714. begin
  1715. result.S := (f1 * t1.S) + (f2 * t2.S);
  1716. result.T := (f1 * t1.T) + (f2 * t2.T);
  1717. end;
  1718. function VectorCombine(const V1, V2: TAffineVector; const f1, f2: Single)
  1719. : TAffineVector;
  1720. begin
  1721. result.V[X] := (f1 * V1.V[X]) + (f2 * V2.V[X]);
  1722. result.V[Y] := (f1 * V1.V[Y]) + (f2 * V2.V[Y]);
  1723. result.V[Z] := (f1 * V1.V[Z]) + (f2 * V2.V[Z]);
  1724. end;
  1725. function VectorCombine3(const V1, V2, V3: TAffineVector;
  1726. const f1, f2, F3: Single): TAffineVector;
  1727. begin
  1728. result.V[X] := (f1 * V1.V[X]) + (f2 * V2.V[X]) + (F3 * V3.V[X]);
  1729. result.V[Y] := (f1 * V1.V[Y]) + (f2 * V2.V[Y]) + (F3 * V3.V[Y]);
  1730. result.V[Z] := (f1 * V1.V[Z]) + (f2 * V2.V[Z]) + (F3 * V3.V[Z]);
  1731. end;
  1732. procedure VectorCombine3(const V1, V2, V3: TAffineVector;
  1733. const f1, f2, F3: Single; var vr: TAffineVector);
  1734. begin
  1735. vr.V[X] := (f1 * V1.V[X]) + (f2 * V2.V[X]) + (F3 * V3.V[X]);
  1736. vr.V[Y] := (f1 * V1.V[Y]) + (f2 * V2.V[Y]) + (F3 * V3.V[Y]);
  1737. vr.V[Z] := (f1 * V1.V[Z]) + (f2 * V2.V[Z]) + (F3 * V3.V[Z]);
  1738. end;
  1739. procedure CombineVector(var vr: TVector; const V: TVector;
  1740. var f: Single); overload;
  1741. begin
  1742. vr.X := vr.X + V.X * f;
  1743. vr.Y := vr.Y + V.Y * f;
  1744. vr.Z := vr.Z + V.Z * f;
  1745. vr.W := vr.W + V.W * f;
  1746. end;
  1747. procedure CombineVector(var vr: TVector; const V: TAffineVector;
  1748. var f: Single); overload;
  1749. begin
  1750. vr.X := vr.X + V.X * f;
  1751. vr.Y := vr.Y + V.Y * f;
  1752. vr.Z := vr.Z + V.Z * f;
  1753. end;
  1754. function VectorCombine(const V1, V2: TVector; const F1, F2: Single): TVector;
  1755. begin
  1756. result.V[X] := (F1 * V1.V[X]) + (F2 * V2.V[X]);
  1757. result.V[Y] := (F1 * V1.V[Y]) + (F2 * V2.V[Y]);
  1758. result.V[Z] := (F1 * V1.V[Z]) + (F2 * V2.V[Z]);
  1759. result.V[W] := (F1 * V1.V[W]) + (F2 * V2.V[W]);
  1760. end;
  1761. function VectorCombine(const V1: TVector; const V2: TAffineVector;
  1762. const F1, F2: Single): TVector; overload;
  1763. begin
  1764. result.V[X] := (F1 * V1.V[X]) + (F2 * V2.V[X]);
  1765. result.V[Y] := (F1 * V1.V[Y]) + (F2 * V2.V[Y]);
  1766. result.V[Z] := (F1 * V1.V[Z]) + (F2 * V2.V[Z]);
  1767. result.V[W] := F1 * V1.V[W];
  1768. end;
  1769. procedure VectorCombine(const V1, V2: TVector; const F1, F2: Single;
  1770. var vr: TVector); overload;
  1771. begin
  1772. vr.X := (F1 * V1.X) + (F2 * V2.X);
  1773. vr.Y := (F1 * V1.Y) + (F2 * V2.Y);
  1774. vr.Z := (F1 * V1.Z) + (F2 * V2.Z);
  1775. vr.W := (F1 * V1.W) + (F2 * V2.W);
  1776. end;
  1777. procedure VectorCombine(const V1, V2: TVector; const f2: Single;
  1778. var vr: TVector); overload;
  1779. begin // 201283
  1780. vr.X := V1.X + (f2 * V2.X);
  1781. vr.Y := V1.Y + (f2 * V2.Y);
  1782. vr.Z := V1.Z + (f2 * V2.Z);
  1783. vr.W := V1.W + (f2 * V2.W);
  1784. end;
  1785. procedure VectorCombine(const V1: TVector; const V2: TAffineVector;
  1786. const F1, F2: Single; var vr: TVector);
  1787. begin
  1788. vr.V[X] := (F1 * V1.V[X]) + (F2 * V2.V[X]);
  1789. vr.V[Y] := (F1 * V1.V[Y]) + (F2 * V2.V[Y]);
  1790. vr.V[Z] := (F1 * V1.V[Z]) + (F2 * V2.V[Z]);
  1791. vr.V[W] := F1 * V1.V[W];
  1792. end;
  1793. function VectorCombine3(const V1, V2, V3: TVector;
  1794. const F1, F2, F3: Single): TVector;
  1795. begin
  1796. result.V[X] := (F1 * V1.V[X]) + (F2 * V2.V[X]) + (F3 * V3.V[X]);
  1797. result.V[Y] := (F1 * V1.V[Y]) + (F2 * V2.V[Y]) + (F3 * V3.V[Y]);
  1798. result.V[Z] := (F1 * V1.V[Z]) + (F2 * V2.V[Z]) + (F3 * V3.V[Z]);
  1799. result.V[W] := (F1 * V1.V[W]) + (F2 * V2.V[W]) + (F3 * V3.V[W]);
  1800. end;
  1801. procedure VectorCombine3(const V1, V2, V3: TVector; const F1, F2, F3: Single;
  1802. var vr: TVector);
  1803. begin
  1804. vr.V[X] := (F1 * V1.V[X]) + (F2 * V2.V[X]) + (F3 * V3.V[X]);
  1805. vr.V[Y] := (F1 * V1.V[Y]) + (F2 * V2.V[Y]) + (F3 * V3.V[Y]);
  1806. vr.V[Z] := (F1 * V1.V[Z]) + (F2 * V2.V[Z]) + (F3 * V3.V[Z]);
  1807. vr.V[W] := (F1 * V1.V[W]) + (F2 * V2.V[W]) + (F3 * V3.V[W]);
  1808. end;
  1809. function VectorDotProduct(const V1, V2: TVector2f): Single;
  1810. begin
  1811. result := V1.X * V2.X + V1.Y * V2.Y;
  1812. end;
  1813. function VectorDotProduct(const V1, V2: TAffineVector): Single;
  1814. begin
  1815. result := V1.X * V2.X + V1.Y * V2.Y + V1.Z * V2.Z;
  1816. end;
  1817. function VectorDotProduct(const V1, V2: TVector): Single;
  1818. begin
  1819. result := V1.X * V2.X + V1.Y * V2.Y + V1.Z * V2.Z + V1.W * V2.W;
  1820. end;
  1821. function VectorDotProduct(const V1: TVector; const V2: TAffineVector): Single;
  1822. begin
  1823. result := V1.X * V2.X + V1.Y * V2.Y + V1.Z * V2.Z;
  1824. end;
  1825. function PointProject(const p, origin, direction: TAffineVector): Single;
  1826. begin
  1827. result := direction.X * (p.X - origin.X) + direction.Y *
  1828. (p.Y - origin.Y) + direction.Z * (p.Z - origin.Z);
  1829. end;
  1830. function PointProject(const p, origin, direction: TVector): Single;
  1831. begin
  1832. result := direction.X * (p.X - origin.X) + direction.Y *
  1833. (p.Y - origin.Y) + direction.Z * (p.Z - origin.Z);
  1834. end;
  1835. function VectorCrossProduct(const V1, V2: TAffineVector): TAffineVector;
  1836. begin
  1837. result.X := V1.Y * V2.Z - V1.Z * V2.Y;
  1838. result.Y := V1.Z * V2.X - V1.X * V2.Z;
  1839. result.Z := V1.X * V2.Y - V1.Y * V2.X;
  1840. end;
  1841. function VectorCrossProduct(const V1, V2: TVector): TVector;
  1842. begin
  1843. result.X := V1.Y * V2.Z - V1.Z * V2.Y;
  1844. result.Y := V1.Z * V2.X - V1.X * V2.Z;
  1845. result.Z := V1.X * V2.Y - V1.Y * V2.X;
  1846. result.W := 0;
  1847. end;
  1848. procedure VectorCrossProduct(const V1, V2: TVector; var vr: TVector);
  1849. begin
  1850. vr.X := V1.Y * V2.Z - V1.Z * V2.Y;
  1851. vr.Y := V1.Z * V2.X - V1.X * V2.Z;
  1852. vr.Z := V1.X * V2.Y - V1.Y * V2.X;
  1853. vr.W := 0;
  1854. end;
  1855. procedure VectorCrossProduct(const V1, V2: TAffineVector;
  1856. var vr: TVector); overload;
  1857. begin
  1858. vr.X := V1.Y * V2.Z - V1.Z * V2.Y;
  1859. vr.Y := V1.Z * V2.X - V1.X * V2.Z;
  1860. vr.Z := V1.X * V2.Y - V1.Y * V2.X;
  1861. vr.W := 0;
  1862. end;
  1863. procedure VectorCrossProduct(const V1, V2: TVector;
  1864. var vr: TAffineVector); overload;
  1865. begin
  1866. vr.V[X] := V1.V[Y] * V2.V[Z] - V1.V[Z] * V2.V[Y];
  1867. vr.V[Y] := V1.V[Z] * V2.V[X] - V1.V[X] * V2.V[Z];
  1868. vr.V[Z] := V1.V[X] * V2.V[Y] - V1.V[Y] * V2.V[X];
  1869. end;
  1870. procedure VectorCrossProduct(const V1, V2: TAffineVector;
  1871. var vr: TAffineVector); overload;
  1872. begin
  1873. vr.V[X] := V1.V[Y] * V2.V[Z] - V1.V[Z] * V2.V[Y];
  1874. vr.V[Y] := V1.V[Z] * V2.V[X] - V1.V[X] * V2.V[Z];
  1875. vr.V[Z] := V1.V[X] * V2.V[Y] - V1.V[Y] * V2.V[X];
  1876. end;
  1877. function Lerp(const start, stop, T: Single): Single;
  1878. begin
  1879. result := start + (stop - start) * T;
  1880. end;
  1881. function AngleLerp(start, stop, T: Single): Single;
  1882. var
  1883. d: Single;
  1884. begin
  1885. start := NormalizeAngle(start);
  1886. stop := NormalizeAngle(stop);
  1887. d := stop - start;
  1888. if d > PI then
  1889. begin
  1890. // positive d, angle on opposite side, becomes negative i.e. changes direction
  1891. d := -d - c2PI;
  1892. end
  1893. else if d < -PI then
  1894. begin
  1895. // negative d, angle on opposite side, becomes positive i.e. changes direction
  1896. d := d + c2PI;
  1897. end;
  1898. result := start + d * T;
  1899. end;
  1900. function DistanceBetweenAngles(angle1, angle2: Single): Single;
  1901. begin
  1902. angle1 := NormalizeAngle(angle1);
  1903. angle2 := NormalizeAngle(angle2);
  1904. result := Abs(angle2 - angle1);
  1905. if result > PI then
  1906. result := c2PI - result;
  1907. end;
  1908. function TexPointLerp(const t1, t2: TTexPoint; T: Single): TTexPoint; overload;
  1909. begin
  1910. result.S := t1.S + (t2.S - t1.S) * T;
  1911. result.T := t1.T + (t2.T - t1.T) * T;
  1912. end;
  1913. function VectorLerp(const V1, V2: TAffineVector; T: Single): TAffineVector;
  1914. begin
  1915. result.X := V1.X + (V2.X - V1.X) * T;
  1916. result.Y := V1.Y + (V2.Y - V1.Y) * T;
  1917. result.Z := V1.Z + (V2.Z - V1.Z) * T;
  1918. end;
  1919. procedure VectorLerp(const V1, V2: TAffineVector; T: Single;
  1920. var vr: TAffineVector);
  1921. begin
  1922. vr.X := V1.X + (V2.X - V1.X) * T;
  1923. vr.Y := V1.Y + (V2.Y - V1.Y) * T;
  1924. vr.Z := V1.Z + (V2.Z - V1.Z) * T;
  1925. end;
  1926. function VectorLerp(const V1, V2: TVector; T: Single): TVector;
  1927. begin
  1928. result.X := V1.X + (V2.X - V1.X) * T;
  1929. result.Y := V1.Y + (V2.Y - V1.Y) * T;
  1930. result.Z := V1.Z + (V2.Z - V1.Z) * T;
  1931. result.W := V1.W + (V2.W - V1.W) * T;
  1932. end;
  1933. procedure VectorLerp(const V1, V2: TVector; T: Single; var vr: TVector);
  1934. begin
  1935. vr.X := V1.X + (V2.X - V1.X) * T;
  1936. vr.Y := V1.Y + (V2.Y - V1.Y) * T;
  1937. vr.Z := V1.Z + (V2.Z - V1.Z) * T;
  1938. vr.W := V1.W + (V2.W - V1.W) * T;
  1939. end;
  1940. function VectorAngleLerp(const V1, V2: TAffineVector; T: Single): TAffineVector;
  1941. var
  1942. q1, q2, qR: TQuaternion;
  1943. M: TMatrix;
  1944. Tran: TTransformations;
  1945. begin
  1946. if VectorEquals(V1, V2) then
  1947. begin
  1948. result := V1;
  1949. end
  1950. else
  1951. begin
  1952. q1 := QuaternionFromEuler(RadToDeg(V1.X), RadToDeg(V1.Y),
  1953. RadToDeg(V1.Z), eulZYX);
  1954. q2 := QuaternionFromEuler(RadToDeg(V2.X), RadToDeg(V2.Y),
  1955. RadToDeg(V2.Z), eulZYX);
  1956. qR := QuaternionSlerp(q1, q2, T);
  1957. M := QuaternionToMatrix(qR);
  1958. MatrixDecompose(M, Tran);
  1959. result.X := Tran[ttRotateX];
  1960. result.Y := Tran[ttRotateY];
  1961. result.Z := Tran[ttRotateZ];
  1962. end;
  1963. end;
  1964. function VectorAngleCombine(const V1, V2: TAffineVector; f: Single)
  1965. : TAffineVector;
  1966. begin
  1967. result := VectorCombine(V1, V2, 1, f);
  1968. end;
  1969. procedure VectorArrayLerp(const src1, src2: PVectorArray; T: Single; n: Integer;
  1970. dest: PVectorArray);
  1971. var
  1972. i: Integer;
  1973. begin
  1974. for i := 0 to n - 1 do
  1975. begin
  1976. dest^[i].X := src1^[i].X + (src2^[i].X - src1^[i].X) * T;
  1977. dest^[i].Y := src1^[i].Y + (src2^[i].Y - src1^[i].Y) * T;
  1978. dest^[i].Z := src1^[i].Z + (src2^[i].Z - src1^[i].Z) * T;
  1979. dest^[i].W := src1^[i].W + (src2^[i].W - src1^[i].W) * T;
  1980. end;
  1981. end;
  1982. procedure VectorArrayLerp(const src1, src2: PAffineVectorArray; T: Single;
  1983. n: Integer; dest: PAffineVectorArray);
  1984. var
  1985. i: Integer;
  1986. begin
  1987. for i := 0 to n - 1 do
  1988. begin
  1989. dest^[i].X := src1^[i].X + (src2^[i].X - src1^[i].X) * T;
  1990. dest^[i].Y := src1^[i].Y + (src2^[i].Y - src1^[i].Y) * T;
  1991. dest^[i].Z := src1^[i].Z + (src2^[i].Z - src1^[i].Z) * T;
  1992. end;
  1993. end;
  1994. procedure VectorArrayLerp(const src1, src2: PTexPointArray; T: Single;
  1995. n: Integer; dest: PTexPointArray);
  1996. var
  1997. i: Integer;
  1998. begin
  1999. for i := 0 to n - 1 do
  2000. begin
  2001. dest^[i].S := src1^[i].S + (src2^[i].S - src1^[i].S) * T;
  2002. dest^[i].T := src1^[i].T + (src2^[i].T - src1^[i].T) * T;
  2003. end;
  2004. end;
  2005. function InterpolateCombined(const start, stop, delta: Single;
  2006. const DistortionDegree: Single;
  2007. const InterpolationType: TGLInterpolationType): Single;
  2008. begin
  2009. case InterpolationType of
  2010. itLinear:
  2011. result := Lerp(start, stop, delta);
  2012. itPower:
  2013. result := InterpolatePower(start, stop, delta, DistortionDegree);
  2014. itSin:
  2015. result := InterpolateSin(start, stop, delta);
  2016. itSinAlt:
  2017. result := InterpolateSinAlt(start, stop, delta);
  2018. itTan:
  2019. result := InterpolateTan(start, stop, delta);
  2020. itLn:
  2021. result := InterpolateLn(start, stop, delta, DistortionDegree);
  2022. itExp:
  2023. result := InterpolateExp(start, stop, delta, DistortionDegree);
  2024. else
  2025. begin
  2026. result := -1;
  2027. Assert(False);
  2028. end;
  2029. end;
  2030. end;
  2031. function InterpolateCombinedFastPower(const OriginalStart, OriginalStop,
  2032. OriginalCurrent: Single; const TargetStart, TargetStop: Single;
  2033. const DistortionDegree: Single): Single;
  2034. begin
  2035. result := InterpolatePower(TargetStart, TargetStop,
  2036. (OriginalCurrent - OriginalStart) / (OriginalStop - OriginalStart),
  2037. DistortionDegree);
  2038. end;
  2039. function InterpolateCombinedSafe(const OriginalStart, OriginalStop,
  2040. OriginalCurrent: Single; const TargetStart, TargetStop: Single;
  2041. const DistortionDegree: Single;
  2042. const InterpolationType: TGLInterpolationType): Single;
  2043. var
  2044. ChangeDelta: Single;
  2045. begin
  2046. if OriginalStop = OriginalStart then
  2047. result := TargetStart
  2048. else
  2049. begin
  2050. ChangeDelta := (OriginalCurrent - OriginalStart) /
  2051. (OriginalStop - OriginalStart);
  2052. result := InterpolateCombined(TargetStart, TargetStop, ChangeDelta,
  2053. DistortionDegree, InterpolationType);
  2054. end;
  2055. end;
  2056. function InterpolateCombinedFast(const OriginalStart, OriginalStop,
  2057. OriginalCurrent: Single; const TargetStart, TargetStop: Single;
  2058. const DistortionDegree: Single;
  2059. const InterpolationType: TGLInterpolationType): Single;
  2060. var
  2061. ChangeDelta: Single;
  2062. begin
  2063. ChangeDelta := (OriginalCurrent - OriginalStart) /
  2064. (OriginalStop - OriginalStart);
  2065. result := InterpolateCombined(TargetStart, TargetStop, ChangeDelta,
  2066. DistortionDegree, InterpolationType);
  2067. end;
  2068. function InterpolateLn(const start, stop, delta: Single;
  2069. const DistortionDegree: Single): Single;
  2070. begin
  2071. result := (stop - start) * Ln(1 + delta * DistortionDegree) /
  2072. Ln(1 + DistortionDegree) + start;
  2073. end;
  2074. function InterpolateExp(const start, stop, delta: Single;
  2075. const DistortionDegree: Single): Single;
  2076. begin
  2077. result := (stop - start) * Exp(-DistortionDegree * (1 - delta)) + start;
  2078. end;
  2079. function InterpolateSinAlt(const start, stop, delta: Single): Single;
  2080. begin
  2081. result := (stop - start) * delta * Sin(delta * PI / 2) + start;
  2082. end;
  2083. function InterpolateSin(const start, stop, delta: Single): Single;
  2084. begin
  2085. result := (stop - start) * Sin(delta * PI / 2) + start;
  2086. end;
  2087. function InterpolateTan(const start, stop, delta: Single): Single;
  2088. begin
  2089. result := (stop - start) * Tan(delta * PI / 4) + start;
  2090. end;
  2091. function InterpolatePower(const start, stop, delta: Single;
  2092. const DistortionDegree: Single): Single;
  2093. var
  2094. i: Integer;
  2095. begin
  2096. if (Round(DistortionDegree) <> DistortionDegree) and (delta < 0) then
  2097. begin
  2098. i := Round(DistortionDegree);
  2099. result := (stop - start) * PowerInteger(delta, i) + start;
  2100. end
  2101. else
  2102. result := (stop - start) * Power(delta, DistortionDegree) + start;
  2103. end;
  2104. function MatrixLerp(const m1, m2: TMatrix; const delta: Single): TMatrix;
  2105. var
  2106. i, J: Integer;
  2107. begin
  2108. for J := 0 to 3 do
  2109. for i := 0 to 3 do
  2110. result.V[i].V[J] := m1.V[i].V[J] + (m2.V[i].V[J] - m1.V[i].V[J]) * delta;
  2111. end;
  2112. function RSqrt(V: Single): Single;
  2113. begin
  2114. result := 1 / Sqrt(V);
  2115. end;
  2116. function VectorLength(const V: array of Single): Single;
  2117. var
  2118. i: Integer;
  2119. begin
  2120. result := 0;
  2121. for i := Low(V) to High(V) do
  2122. result := result + Sqr(V[i]);
  2123. result := Sqrt(result);
  2124. end;
  2125. function VectorLength(const X, Y: Single): Single;
  2126. begin
  2127. result := Sqrt(X * X + Y * Y);
  2128. end;
  2129. function VectorLength(const X, Y, Z: Single): Single;
  2130. begin
  2131. result := Sqrt(X * X + Y * Y + Z * Z);
  2132. end;
  2133. function VectorLength(const V: TVector2f): Single;
  2134. begin
  2135. result := Sqrt(VectorNorm(V.X, V.Y));
  2136. end;
  2137. function VectorLength(const V: TAffineVector): Single;
  2138. begin
  2139. result := Sqrt(VectorNorm(V));
  2140. end;
  2141. function VectorLength(const V: TVector): Single;
  2142. begin
  2143. result := Sqrt(VectorNorm(V));
  2144. end;
  2145. function VectorNorm(const X, Y: Single): Single;
  2146. begin
  2147. result := Sqr(X) + Sqr(Y);
  2148. end;
  2149. function VectorNorm(const V: TAffineVector): Single;
  2150. begin
  2151. result := V.X * V.X + V.Y * V.Y + V.Z * V.Z;
  2152. end;
  2153. function VectorNorm(const V: TVector): Single;
  2154. begin
  2155. result := V.X * V.X + V.Y * V.Y + V.Z * V.Z;
  2156. end;
  2157. function VectorNorm(var V: array of Single): Single;
  2158. var
  2159. i: Integer;
  2160. begin
  2161. result := 0;
  2162. for i := Low(V) to High(V) do
  2163. result := result + V[i] * V[i];
  2164. end;
  2165. procedure NormalizeVector(var V: TVector2f);
  2166. var
  2167. invLen: Single;
  2168. vn: Single;
  2169. begin
  2170. vn := VectorNorm(V.X, V.Y);
  2171. if vn > 0 then
  2172. begin
  2173. invLen := RSqrt(vn);
  2174. V.X := V.X * invLen;
  2175. V.Y := V.Y * invLen;
  2176. end;
  2177. end;
  2178. procedure NormalizeVector(var V: TAffineVector);
  2179. var
  2180. invLen: Single;
  2181. vn: Single;
  2182. begin
  2183. vn := VectorNorm(V);
  2184. if vn > 0 then
  2185. begin
  2186. invLen := RSqrt(vn);
  2187. V.X := V.X * invLen;
  2188. V.Y := V.Y * invLen;
  2189. V.Z := V.Z * invLen;
  2190. end;
  2191. end;
  2192. function VectorNormalize(const V: TVector2f): TVector2f;
  2193. var
  2194. invLen: Single;
  2195. vn: Single;
  2196. begin
  2197. vn := VectorNorm(V.X, V.Y);
  2198. if vn = 0 then
  2199. result := V
  2200. else
  2201. begin
  2202. invLen := RSqrt(vn);
  2203. result.X := V.X * invLen;
  2204. result.Y := V.Y * invLen;
  2205. end;
  2206. end;
  2207. function VectorNormalize(const V: TAffineVector): TAffineVector;
  2208. var
  2209. invLen: Single;
  2210. vn: Single;
  2211. begin
  2212. vn := VectorNorm(V);
  2213. if vn = 0 then
  2214. SetVector(result, V)
  2215. else
  2216. begin
  2217. invLen := RSqrt(vn);
  2218. result.X := V.X * invLen;
  2219. result.Y := V.Y * invLen;
  2220. result.Z := V.Z * invLen;
  2221. end;
  2222. end;
  2223. procedure NormalizeVectorArray(list: PAffineVectorArray; n: Integer);
  2224. var
  2225. i: Integer;
  2226. begin
  2227. for i := 0 to n - 1 do
  2228. NormalizeVector(list^[i]);
  2229. end;
  2230. procedure NormalizeVector(var V: TVector);
  2231. var
  2232. invLen: Single;
  2233. vn: Single;
  2234. begin
  2235. vn := VectorNorm(V);
  2236. if vn > 0 then
  2237. begin
  2238. invLen := RSqrt(vn);
  2239. V.X := V.X * invLen;
  2240. V.Y := V.Y * invLen;
  2241. V.Z := V.Z * invLen;
  2242. end;
  2243. V.W := 0;
  2244. end;
  2245. function VectorNormalize(const V: TVector): TVector;
  2246. var
  2247. invLen: Single;
  2248. vn: Single;
  2249. begin
  2250. vn := VectorNorm(V);
  2251. if vn = 0 then
  2252. SetVector(result, V)
  2253. else
  2254. begin
  2255. invLen := RSqrt(vn);
  2256. result.X := V.X * invLen;
  2257. result.Y := V.Y * invLen;
  2258. result.Z := V.Z * invLen;
  2259. end;
  2260. result.W := 0;
  2261. end;
  2262. function VectorAngleCosine(const V1, V2: TAffineVector): Single;
  2263. begin
  2264. result := VectorDotProduct(V1, V2) / (VectorLength(V1) * VectorLength(V2));
  2265. end;
  2266. function VectorAngleCosine(const V1, V2: TVector): Single;
  2267. begin
  2268. result := VectorDotProduct(V1, V2) / (VectorLength(V1) * VectorLength(V2));
  2269. end;
  2270. function VectorNegate(const Vector: TAffineVector): TAffineVector;
  2271. begin
  2272. result.X := -Vector.X;
  2273. result.Y := -Vector.Y;
  2274. result.Z := -Vector.Z;
  2275. end;
  2276. function VectorNegate(const Vector: TVector): TVector;
  2277. begin
  2278. result.X := -Vector.X;
  2279. result.Y := -Vector.Y;
  2280. result.Z := -Vector.Z;
  2281. result.W := -Vector.W;
  2282. end;
  2283. procedure NegateVector(var V: TAffineVector);
  2284. begin
  2285. V.X := -V.X;
  2286. V.Y := -V.Y;
  2287. V.Z := -V.Z;
  2288. end;
  2289. procedure NegateVector(var V: TVector);
  2290. begin
  2291. V.X := -V.X;
  2292. V.Y := -V.Y;
  2293. V.Z := -V.Z;
  2294. V.W := -V.W;
  2295. end;
  2296. procedure NegateVector(var V: array of Single);
  2297. var
  2298. i: Integer;
  2299. begin
  2300. for i := Low(V) to High(V) do
  2301. V[i] := -V[i];
  2302. end;
  2303. procedure ScaleVector(var V: TVector2f; factor: Single);
  2304. begin
  2305. V.X := V.X * factor;
  2306. V.Y := V.Y * factor;
  2307. end;
  2308. procedure ScaleVector(var V: TAffineVector; factor: Single);
  2309. begin
  2310. V.X := V.X * factor;
  2311. V.Y := V.Y * factor;
  2312. V.Z := V.Z * factor;
  2313. end;
  2314. procedure ScaleVector(var V: TVector; factor: Single);
  2315. begin
  2316. V.X := V.X * factor;
  2317. V.Y := V.Y * factor;
  2318. V.Z := V.Z * factor;
  2319. V.W := V.W * factor;
  2320. end;
  2321. procedure ScaleVector(var V: TAffineVector; const factor: TAffineVector);
  2322. begin
  2323. V.X := V.X * factor.X;
  2324. V.Y := V.Y * factor.Y;
  2325. V.Z := V.Z * factor.Z;
  2326. end;
  2327. procedure ScaleVector(var V: TVector; const factor: TVector);
  2328. begin
  2329. V.X := V.X * factor.X;
  2330. V.Y := V.Y * factor.Y;
  2331. V.Z := V.Z * factor.Z;
  2332. V.W := V.W * factor.W;
  2333. end;
  2334. function VectorScale(const V: TVector2f; factor: Single): TVector2f;
  2335. begin
  2336. result.X := V.X * factor;
  2337. result.Y := V.Y * factor;
  2338. end;
  2339. function VectorScale(const V: TAffineVector; factor: Single): TAffineVector;
  2340. begin
  2341. result.X := V.X * factor;
  2342. result.Y := V.Y * factor;
  2343. result.Z := V.Z * factor;
  2344. end;
  2345. procedure VectorScale(const V: TAffineVector; factor: Single;
  2346. var vr: TAffineVector);
  2347. begin
  2348. vr.X := V.X * factor;
  2349. vr.Y := V.Y * factor;
  2350. vr.Z := V.Z * factor;
  2351. end;
  2352. function VectorScale(const V: TVector; factor: Single): TVector;
  2353. begin
  2354. result.X := V.X * factor;
  2355. result.Y := V.Y * factor;
  2356. result.Z := V.Z * factor;
  2357. result.W := V.W * factor;
  2358. end;
  2359. procedure VectorScale(const V: TVector; factor: Single; var vr: TVector);
  2360. begin
  2361. vr.X := V.X * factor;
  2362. vr.Y := V.Y * factor;
  2363. vr.Z := V.Z * factor;
  2364. vr.W := V.W * factor;
  2365. end;
  2366. procedure VectorScale(const V: TVector; factor: Single; var vr: TAffineVector);
  2367. begin
  2368. vr.X := V.X * factor;
  2369. vr.Y := V.Y * factor;
  2370. vr.Z := V.Z * factor;
  2371. end;
  2372. function VectorScale(const V: TAffineVector; const factor: TAffineVector)
  2373. : TAffineVector;
  2374. begin
  2375. result.X := V.X * factor.X;
  2376. result.Y := V.Y * factor.Y;
  2377. result.Z := V.Z * factor.Z;
  2378. end;
  2379. function VectorScale(const V: TVector; const factor: TVector): TVector;
  2380. begin
  2381. result.X := V.X * factor.X;
  2382. result.Y := V.Y * factor.Y;
  2383. result.Z := V.Z * factor.Z;
  2384. result.W := V.W * factor.W;
  2385. end;
  2386. procedure DivideVector(var V: TVector; const divider: TVector);
  2387. begin
  2388. V.X := V.X / divider.X;
  2389. V.Y := V.Y / divider.Y;
  2390. V.Z := V.Z / divider.Z;
  2391. V.W := V.W / divider.W;
  2392. end;
  2393. procedure DivideVector(var V: TAffineVector;
  2394. const divider: TAffineVector); overload;
  2395. begin
  2396. V.X := V.X / divider.X;
  2397. V.Y := V.Y / divider.Y;
  2398. V.Z := V.Z / divider.Z;
  2399. end;
  2400. function VectorDivide(const V: TVector; const divider: TVector)
  2401. : TVector; overload;
  2402. begin
  2403. result.X := V.X / divider.X;
  2404. result.Y := V.Y / divider.Y;
  2405. result.Z := V.Z / divider.Z;
  2406. result.W := V.W / divider.W;
  2407. end;
  2408. function VectorDivide(const V: TAffineVector; const divider: TAffineVector)
  2409. : TAffineVector; overload;
  2410. begin
  2411. result.X := V.X / divider.X;
  2412. result.Y := V.Y / divider.Y;
  2413. result.Z := V.Z / divider.Z;
  2414. end;
  2415. function TexpointEquals(const p1, p2: TTexPoint): Boolean;
  2416. begin
  2417. result := (p1.S = p2.S) and (p1.T = p2.T);
  2418. end;
  2419. function RectEquals(const Rect1, Rect2: TRect): Boolean;
  2420. begin
  2421. result := (Rect1.Left = Rect2.Left) and (Rect1.Right = Rect2.Right) and
  2422. (Rect1.Top = Rect2.Top) and (Rect1.Bottom = Rect2.Bottom);
  2423. end;
  2424. function VectorEquals(const V1, V2: TVector): Boolean;
  2425. begin
  2426. result := (V1.X = V2.X) and (V1.Y = V2.Y) and (V1.Z = V2.Z)
  2427. and (V1.W = V2.W);
  2428. end;
  2429. function VectorEquals(const V1, V2: TAffineVector): Boolean;
  2430. begin
  2431. result := (V1.X = V2.X) and (V1.Y = V2.Y) and (V1.Z = V2.Z);
  2432. end;
  2433. function AffineVectorEquals(const V1, V2: TVector): Boolean;
  2434. begin
  2435. result := (V1.X = V2.X) and (V1.Y = V2.Y) and (V1.Z = V2.Z);
  2436. end;
  2437. function VectorIsNull(const V: TVector): Boolean;
  2438. begin
  2439. result := ((V.X = 0) and (V.Y = 0) and (V.Z = 0));
  2440. end;
  2441. function VectorIsNull(const V: TAffineVector): Boolean; overload;
  2442. begin
  2443. result := ((V.X = 0) and (V.Y = 0) and (V.Z = 0));
  2444. end;
  2445. function VectorSpacing(const V1, V2: TTexPoint): Single; overload;
  2446. begin
  2447. result := Abs(V2.S - V1.S) + Abs(V2.T - V1.T);
  2448. end;
  2449. function VectorSpacing(const V1, V2: TAffineVector): Single;
  2450. begin
  2451. result := Abs(V2.X - V1.X) + Abs(V2.Y - V1.Y) +
  2452. Abs(V2.Z - V1.Z);
  2453. end;
  2454. function VectorSpacing(const V1, V2: TVector): Single;
  2455. begin
  2456. result := Abs(V2.X - V1.X) + Abs(V2.Y - V1.Y) +
  2457. Abs(V2.Z - V1.Z) + Abs(V2.W - V1.W);
  2458. end;
  2459. function VectorDistance(const V1, V2: TAffineVector): Single;
  2460. begin
  2461. result := Sqrt(Sqr(V2.X - V1.X) + Sqr(V2.Y - V1.Y) + Sqr(V2.Z - V1.Z));
  2462. end;
  2463. function VectorDistance(const V1, V2: TVector): Single;
  2464. begin
  2465. result := Sqrt(Sqr(V2.X - V1.X) + Sqr(V2.Y - V1.Y) + Sqr(V2.Z - V1.Z));
  2466. end;
  2467. function VectorDistance2(const V1, V2: TAffineVector): Single;
  2468. begin
  2469. result := Sqr(V2.X - V1.X) + Sqr(V2.Y - V1.Y) + Sqr(V2.Z - V1.Z);
  2470. end;
  2471. function VectorDistance2(const V1, V2: TVector): Single;
  2472. begin
  2473. result := Sqr(V2.X - V1.X) + Sqr(V2.Y - V1.Y) + Sqr(V2.Z - V1.Z);
  2474. end;
  2475. function VectorPerpendicular(const V, n: TAffineVector): TAffineVector;
  2476. var
  2477. dot: Single;
  2478. begin
  2479. dot := VectorDotProduct(V, n);
  2480. result.X := V.X - dot * n.X;
  2481. result.Y := V.Y - dot * n.Y;
  2482. result.Z := V.Z - dot * n.Z;
  2483. end;
  2484. function VectorReflect(const V, n: TAffineVector): TAffineVector;
  2485. begin
  2486. result := VectorCombine(V, n, 1, -2 * VectorDotProduct(V, n));
  2487. end;
  2488. procedure RotateVector(var Vector: TVector; const axis: TAffineVector;
  2489. angle: Single);
  2490. var
  2491. rotMatrix: TMatrix4f;
  2492. begin
  2493. rotMatrix := CreateRotationMatrix(axis, angle);
  2494. Vector := VectorTransform(Vector, rotMatrix);
  2495. end;
  2496. procedure RotateVector(var Vector: TVector; const axis: TVector;
  2497. angle: Single); overload;
  2498. var
  2499. rotMatrix: TMatrix4f;
  2500. begin
  2501. rotMatrix := CreateRotationMatrix(PAffineVector(@axis)^, angle);
  2502. Vector := VectorTransform(Vector, rotMatrix);
  2503. end;
  2504. procedure RotateVectorAroundY(var V: TAffineVector; alpha: Single);
  2505. var
  2506. c, S, v0: Single;
  2507. begin
  2508. SinCosine(alpha, S, c);
  2509. v0 := V.X;
  2510. V.X := c * v0 + S * V.Z;
  2511. V.Z := c * V.Z - S * v0;
  2512. end;
  2513. function VectorRotateAroundX(const V: TAffineVector; alpha: Single)
  2514. : TAffineVector;
  2515. var
  2516. c, S: Single;
  2517. begin
  2518. SinCosine(alpha, S, c);
  2519. result.X := V.X;
  2520. result.Y := c * V.Y + S * V.Z;
  2521. result.Z := c * V.Z - S * V.Y;
  2522. end;
  2523. function VectorRotateAroundY(const V: TAffineVector; alpha: Single)
  2524. : TAffineVector;
  2525. var
  2526. c, S: Single;
  2527. begin
  2528. SinCosine(alpha, S, c);
  2529. result.Y := V.Y;
  2530. result.X := c * V.X + S * V.Z;
  2531. result.Z := c * V.Z - S * V.X;
  2532. end;
  2533. procedure VectorRotateAroundY(const V: TAffineVector; alpha: Single;
  2534. var vr: TAffineVector);
  2535. var
  2536. c, S: Single;
  2537. begin
  2538. SinCosine(alpha, S, c);
  2539. vr.Y := V.Y;
  2540. vr.X := c * V.X + S * V.Z;
  2541. vr.Z := c * V.Z - S * V.X;
  2542. end;
  2543. function VectorRotateAroundZ(const V: TAffineVector; alpha: Single)
  2544. : TAffineVector;
  2545. var
  2546. c, S: Single;
  2547. begin
  2548. SinCosine(alpha, S, c);
  2549. result.X := c * V.X + S * V.Y;
  2550. result.Y := c * V.Y - S * V.X;
  2551. result.Z := V.Z;
  2552. end;
  2553. procedure AbsVector(var V: TVector);
  2554. begin
  2555. V.X := Abs(V.X);
  2556. V.Y := Abs(V.Y);
  2557. V.Z := Abs(V.Z);
  2558. V.W := Abs(V.W);
  2559. end;
  2560. procedure AbsVector(var V: TAffineVector);
  2561. begin
  2562. V.X := Abs(V.X);
  2563. V.Y := Abs(V.Y);
  2564. V.Z := Abs(V.Z);
  2565. end;
  2566. function VectorAbs(const V: TVector): TVector;
  2567. begin
  2568. result.X := Abs(V.X);
  2569. result.Y := Abs(V.Y);
  2570. result.Z := Abs(V.Z);
  2571. result.W := Abs(V.W);
  2572. end;
  2573. function VectorAbs(const V: TAffineVector): TAffineVector;
  2574. begin
  2575. result.X := Abs(V.X);
  2576. result.Y := Abs(V.Y);
  2577. result.Z := Abs(V.Z);
  2578. end;
  2579. function IsColinear(const V1, V2: TVector2f): Boolean; overload;
  2580. var
  2581. a, b, c: Single;
  2582. begin
  2583. a := VectorDotProduct(V1, V1);
  2584. b := VectorDotProduct(V1, V2);
  2585. c := VectorDotProduct(V2, V2);
  2586. result := (a * c - b * b) < cColinearBias;
  2587. end;
  2588. function IsColinear(const V1, V2: TAffineVector): Boolean; overload;
  2589. var
  2590. a, b, c: Single;
  2591. begin
  2592. a := VectorDotProduct(V1, V1);
  2593. b := VectorDotProduct(V1, V2);
  2594. c := VectorDotProduct(V2, V2);
  2595. result := (a * c - b * b) < cColinearBias;
  2596. end;
  2597. function IsColinear(const V1, V2: TVector): Boolean; overload;
  2598. var
  2599. a, b, c: Single;
  2600. begin
  2601. a := VectorDotProduct(V1, V1);
  2602. b := VectorDotProduct(V1, V2);
  2603. c := VectorDotProduct(V2, V2);
  2604. result := (a * c - b * b) < cColinearBias;
  2605. end;
  2606. procedure SetMatrix(var dest: THomogeneousDblMatrix; const src: TMatrix);
  2607. var
  2608. i: Integer;
  2609. begin
  2610. for i := X to W do
  2611. begin
  2612. dest.V[i].X := src.V[i].X;
  2613. dest.V[i].Y := src.V[i].Y;
  2614. dest.V[i].Z := src.V[i].Z;
  2615. dest.V[i].W := src.V[i].W;
  2616. end;
  2617. end;
  2618. procedure SetMatrix(var dest: TAffineMatrix; const src: TMatrix);
  2619. begin
  2620. dest.X.X := src.X.X;
  2621. dest.X.Y := src.X.Y;
  2622. dest.X.Z := src.X.Z;
  2623. dest.Y.X := src.Y.X;
  2624. dest.Y.Y := src.Y.Y;
  2625. dest.Y.Z := src.Y.Z;
  2626. dest.Z.X := src.Z.X;
  2627. dest.Z.Y := src.Z.Y;
  2628. dest.Z.Z := src.Z.Z;
  2629. end;
  2630. procedure SetMatrix(var dest: TMatrix; const src: TAffineMatrix);
  2631. begin
  2632. dest.X.X := src.X.X;
  2633. dest.X.Y := src.X.Y;
  2634. dest.X.Z := src.X.Z;
  2635. dest.X.W := 0;
  2636. dest.Y.X := src.Y.X;
  2637. dest.Y.Y := src.Y.Y;
  2638. dest.Y.Z := src.Y.Z;
  2639. dest.Y.W := 0;
  2640. dest.Z.X := src.Z.X;
  2641. dest.Z.Y := src.Z.Y;
  2642. dest.Z.Z := src.Z.Z;
  2643. dest.Z.W := 0;
  2644. dest.W.X := 0;
  2645. dest.W.Y := 0;
  2646. dest.W.Z := 0;
  2647. dest.W.W := 1;
  2648. end;
  2649. procedure SetMatrixRow(var dest: TMatrix; rowNb: Integer; const aRow: TVector);
  2650. begin
  2651. dest.X.V[rowNb] := aRow.X;
  2652. dest.Y.V[rowNb] := aRow.Y;
  2653. dest.Z.V[rowNb] := aRow.Z;
  2654. dest.W.V[rowNb] := aRow.W;
  2655. end;
  2656. function CreateScaleMatrix(const V: TAffineVector): TMatrix;
  2657. begin
  2658. result := IdentityHmgMatrix;
  2659. result.X.X := V.V[X];
  2660. result.Y.Y := V.V[Y];
  2661. result.Z.Z := V.V[Z];
  2662. end;
  2663. function CreateScaleMatrix(const V: TVector): TMatrix;
  2664. begin
  2665. result := IdentityHmgMatrix;
  2666. result.X.X := V.V[X];
  2667. result.Y.Y := V.V[Y];
  2668. result.Z.Z := V.V[Z];
  2669. end;
  2670. function CreateTranslationMatrix(const V: TAffineVector): TMatrix;
  2671. begin
  2672. result := IdentityHmgMatrix;
  2673. result.W.X := V.V[X];
  2674. result.W.Y := V.V[Y];
  2675. result.W.Z := V.V[Z];
  2676. end;
  2677. function CreateTranslationMatrix(const V: TVector): TMatrix;
  2678. begin
  2679. result := IdentityHmgMatrix;
  2680. result.W.X := V.V[X];
  2681. result.W.Y := V.V[Y];
  2682. result.W.Z := V.V[Z];
  2683. end;
  2684. function CreateScaleAndTranslationMatrix(const scale, offset: TVector): TMatrix;
  2685. begin
  2686. result := IdentityHmgMatrix;
  2687. result.X.X := scale.V[X];
  2688. result.W.X := offset.V[X];
  2689. result.Y.Y := scale.V[Y];
  2690. result.W.Y := offset.V[Y];
  2691. result.Z.Z := scale.V[Z];
  2692. result.W.Z := offset.V[Z];
  2693. end;
  2694. function CreateRotationMatrixX(const sine, cosine: Single): TMatrix;
  2695. begin
  2696. result := EmptyHmgMatrix;
  2697. result.X.X := 1;
  2698. result.Y.Y := cosine;
  2699. result.Y.Z := sine;
  2700. result.Z.Y := -sine;
  2701. result.Z.Z := cosine;
  2702. result.W.W := 1;
  2703. end;
  2704. function CreateRotationMatrixX(const angle: Single): TMatrix;
  2705. var
  2706. S, c: Single;
  2707. begin
  2708. SinCosine(angle, S, c);
  2709. result := CreateRotationMatrixX(S, c);
  2710. end;
  2711. function CreateRotationMatrixY(const sine, cosine: Single): TMatrix;
  2712. begin
  2713. result := EmptyHmgMatrix;
  2714. result.X.X := cosine;
  2715. result.X.Z := -sine;
  2716. result.Y.Y := 1;
  2717. result.Z.X := sine;
  2718. result.Z.Z := cosine;
  2719. result.W.W := 1;
  2720. end;
  2721. function CreateRotationMatrixY(const angle: Single): TMatrix;
  2722. var
  2723. S, c: Single;
  2724. begin
  2725. SinCosine(angle, S, c);
  2726. result := CreateRotationMatrixY(S, c);
  2727. end;
  2728. function CreateRotationMatrixZ(const sine, cosine: Single): TMatrix;
  2729. begin
  2730. result := EmptyHmgMatrix;
  2731. result.X.X := cosine;
  2732. result.X.Y := sine;
  2733. result.Y.X := -sine;
  2734. result.Y.Y := cosine;
  2735. result.Z.Z := 1;
  2736. result.W.W := 1;
  2737. end;
  2738. function CreateRotationMatrixZ(const angle: Single): TMatrix;
  2739. var
  2740. S, c: Single;
  2741. begin
  2742. SinCosine(angle, S, c);
  2743. result := CreateRotationMatrixZ(S, c);
  2744. end;
  2745. function CreateRotationMatrix(const anAxis: TAffineVector;
  2746. angle: Single): TMatrix;
  2747. var
  2748. axis: TAffineVector;
  2749. cosine, sine, one_minus_cosine: Single;
  2750. begin
  2751. SinCosine(angle, sine, cosine);
  2752. one_minus_cosine := 1 - cosine;
  2753. axis := VectorNormalize(anAxis);
  2754. result.X.X := (one_minus_cosine * axis.X * axis.X) + cosine;
  2755. result.X.Y := (one_minus_cosine * axis.X * axis.Y) - (axis.Z * sine);
  2756. result.X.Z := (one_minus_cosine * axis.Z * axis.X) + (axis.Y * sine);
  2757. result.X.W := 0;
  2758. result.Y.X := (one_minus_cosine * axis.X * axis.Y) + (axis.Z * sine);
  2759. result.Y.Y := (one_minus_cosine * axis.Y * axis.Y) + cosine;
  2760. result.Y.Z := (one_minus_cosine * axis.Y * axis.Z) - (axis.X * sine);
  2761. result.Y.W := 0;
  2762. result.Z.X := (one_minus_cosine * axis.Z * axis.X) - (axis.Y * sine);
  2763. result.Z.Y := (one_minus_cosine * axis.Y * axis.Z) + (axis.X * sine);
  2764. result.Z.Z := (one_minus_cosine * axis.Z * axis.Z) + cosine;
  2765. result.Z.W := 0;
  2766. result.W.X := 0;
  2767. result.W.Y := 0;
  2768. result.W.Z := 0;
  2769. result.W.W := 1;
  2770. end;
  2771. function CreateRotationMatrix(const anAxis: TVector; angle: Single): TMatrix;
  2772. begin
  2773. result := CreateRotationMatrix(PAffineVector(@anAxis)^, angle);
  2774. end;
  2775. function CreateAffineRotationMatrix(const anAxis: TAffineVector; angle: Single)
  2776. : TAffineMatrix;
  2777. var
  2778. axis: TAffineVector;
  2779. cosine, sine, one_minus_cosine: Single;
  2780. begin
  2781. SinCosine(angle, sine, cosine);
  2782. one_minus_cosine := 1 - cosine;
  2783. axis := VectorNormalize(anAxis);
  2784. result.X.X := (one_minus_cosine * Sqr(axis.X)) + cosine;
  2785. result.X.Y := (one_minus_cosine * axis.X * axis.Y) - (axis.Z * sine);
  2786. result.X.Z := (one_minus_cosine * axis.Z * axis.X) + (axis.Y * sine);
  2787. result.Y.X := (one_minus_cosine * axis.X * axis.Y) + (axis.Z * sine);
  2788. result.Y.Y := (one_minus_cosine * Sqr(axis.Y)) + cosine;
  2789. result.Y.Z := (one_minus_cosine * axis.Y * axis.Z) - (axis.X * sine);
  2790. result.Z.X := (one_minus_cosine * axis.Z * axis.X) - (axis.Y * sine);
  2791. result.Z.Y := (one_minus_cosine * axis.Y * axis.Z) + (axis.X * sine);
  2792. result.Z.Z := (one_minus_cosine * Sqr(axis.Z)) + cosine;
  2793. end;
  2794. function MatrixMultiply(const m1, m2: TAffineMatrix): TAffineMatrix;
  2795. begin
  2796. result.X.X := m1.X.X * m2.X.X + m1.X.Y * m2.Y.X + m1.X.Z * m2.Z.X;
  2797. result.X.Y := m1.X.X * m2.X.Y + m1.X.Y * m2.Y.Y + m1.X.Z * m2.Z.Y;
  2798. result.X.Z := m1.X.X * m2.X.Z + m1.X.Y * m2.Y.Z + m1.X.Z * m2.Z.Z;
  2799. result.Y.X := m1.Y.X * m2.X.X + m1.Y.Y * m2.Y.X + m1.Y.Z * m2.Z.X;
  2800. result.Y.Y := m1.Y.X * m2.X.Y + m1.Y.Y * m2.Y.Y + m1.Y.Z * m2.Z.Y;
  2801. result.Y.Z := m1.Y.X * m2.X.Z + m1.Y.Y * m2.Y.Z + m1.Y.Z * m2.Z.Z;
  2802. result.Z.X := m1.Z.X * m2.X.X + m1.Z.Y * m2.Y.X + m1.Z.Z * m2.Z.X;
  2803. result.Z.Y := m1.Z.X * m2.X.Y + m1.Z.Y * m2.Y.Y + m1.Z.Z * m2.Z.Y;
  2804. result.Z.Z := m1.Z.X * m2.X.Z + m1.Z.Y * m2.Y.Z + m1.Z.Z * m2.Z.Z;
  2805. end;
  2806. function MatrixMultiply(const m1, m2: TMatrix): TMatrix;
  2807. begin
  2808. result.X.X := m1.X.X * m2.X.X + m1.X.Y * m2.Y.X + m1.X.Z * m2.Z.X +
  2809. m1.X.W * m2.W.X;
  2810. result.X.Y := m1.X.X * m2.X.Y + m1.X.Y * m2.Y.Y + m1.X.Z * m2.Z.Y +
  2811. m1.X.W * m2.W.Y;
  2812. result.X.Z := m1.X.X * m2.X.Z + m1.X.Y * m2.Y.Z + m1.X.Z * m2.Z.Z +
  2813. m1.X.W * m2.W.Z;
  2814. result.X.W := m1.X.X * m2.X.W + m1.X.Y * m2.Y.W + m1.X.Z * m2.Z.W +
  2815. m1.X.W * m2.W.W;
  2816. result.Y.X := m1.Y.X * m2.X.X + m1.Y.Y * m2.Y.X + m1.Y.Z * m2.Z.X +
  2817. m1.Y.W * m2.W.X;
  2818. result.Y.Y := m1.Y.X * m2.X.Y + m1.Y.Y * m2.Y.Y + m1.Y.Z * m2.Z.Y +
  2819. m1.Y.W * m2.W.Y;
  2820. result.Y.Z := m1.Y.X * m2.X.Z + m1.Y.Y * m2.Y.Z + m1.Y.Z * m2.Z.Z +
  2821. m1.Y.W * m2.W.Z;
  2822. result.Y.W := m1.Y.X * m2.X.W + m1.Y.Y * m2.Y.W + m1.Y.Z * m2.Z.W +
  2823. m1.Y.W * m2.W.W;
  2824. result.Z.X := m1.Z.X * m2.X.X + m1.Z.Y * m2.Y.X + m1.Z.Z * m2.Z.X +
  2825. m1.Z.W * m2.W.X;
  2826. result.Z.Y := m1.Z.X * m2.X.Y + m1.Z.Y * m2.Y.Y + m1.Z.Z * m2.Z.Y +
  2827. m1.Z.W * m2.W.Y;
  2828. result.Z.Z := m1.Z.X * m2.X.Z + m1.Z.Y * m2.Y.Z + m1.Z.Z * m2.Z.Z +
  2829. m1.Z.W * m2.W.Z;
  2830. result.Z.W := m1.Z.X * m2.X.W + m1.Z.Y * m2.Y.W + m1.Z.Z * m2.Z.W +
  2831. m1.Z.W * m2.W.W;
  2832. result.W.X := m1.W.X * m2.X.X + m1.W.Y * m2.Y.X + m1.W.Z * m2.Z.X +
  2833. m1.W.W * m2.W.X;
  2834. result.W.Y := m1.W.X * m2.X.Y + m1.W.Y * m2.Y.Y + m1.W.Z * m2.Z.Y +
  2835. m1.W.W * m2.W.Y;
  2836. result.W.Z := m1.W.X * m2.X.Z + m1.W.Y * m2.Y.Z + m1.W.Z * m2.Z.Z +
  2837. m1.W.W * m2.W.Z;
  2838. result.W.W := m1.W.X * m2.X.W + m1.W.Y * m2.Y.W + m1.W.Z * m2.Z.W +
  2839. m1.W.W * m2.W.W;
  2840. end;
  2841. procedure MatrixMultiply(const m1, m2: TMatrix; var MResult: TMatrix);
  2842. begin
  2843. MResult.X.X := m1.X.X * m2.X.X + m1.X.Y * m2.Y.X + m1.X.Z * m2.Z.X + m1.X.W * m2.W.X;
  2844. MResult.X.Y := m1.X.X * m2.X.Y + m1.X.Y * m2.Y.Y + m1.X.Z * m2.Z.Y + m1.X.W * m2.W.Y;
  2845. MResult.X.Z := m1.X.X * m2.X.Z + m1.X.Y * m2.Y.Z + m1.X.Z * m2.Z.Z + m1.X.W * m2.W.Z;
  2846. MResult.X.W := m1.X.X * m2.X.W + m1.X.Y * m2.Y.W + m1.X.Z * m2.Z.W + m1.X.W * m2.W.W;
  2847. MResult.Y.X := m1.Y.X * m2.X.X + m1.Y.Y * m2.Y.X + m1.Y.Z * m2.Z.X + m1.Y.W * m2.W.X;
  2848. MResult.Y.Y := m1.Y.X * m2.X.Y + m1.Y.Y * m2.Y.Y + m1.Y.Z * m2.Z.Y + m1.Y.W * m2.W.Y;
  2849. MResult.Y.Z := m1.Y.X * m2.X.Z + m1.Y.Y * m2.Y.Z + m1.Y.Z * m2.Z.Z + m1.Y.W * m2.W.Z;
  2850. MResult.Y.W := m1.Y.X * m2.X.W + m1.Y.Y * m2.Y.W + m1.Y.Z * m2.Z.W + m1.Y.W * m2.W.W;
  2851. MResult.Z.X := m1.Z.X * m2.X.X + m1.Z.Y * m2.Y.X + m1.Z.Z * m2.Z.X + m1.Z.W * m2.W.X;
  2852. MResult.Z.Y := m1.Z.X * m2.X.Y + m1.Z.Y * m2.Y.Y + m1.Z.Z * m2.Z.Y + m1.Z.W * m2.W.Y;
  2853. MResult.Z.Z := m1.Z.X * m2.X.Z + m1.Z.Y * m2.Y.Z + m1.Z.Z * m2.Z.Z + m1.Z.W * m2.W.Z;
  2854. MResult.Z.W := m1.Z.X * m2.X.W + m1.Z.Y * m2.Y.W + m1.Z.Z * m2.Z.W + m1.Z.W * m2.W.W;
  2855. MResult.W.X := m1.W.X * m2.X.X + m1.W.Y * m2.Y.X + m1.W.Z * m2.Z.X + m1.W.W * m2.W.X;
  2856. MResult.W.Y := m1.W.X * m2.X.Y + m1.W.Y * m2.Y.Y + m1.W.Z * m2.Z.Y + m1.W.W * m2.W.Y;
  2857. MResult.W.Z := m1.W.X * m2.X.Z + m1.W.Y * m2.Y.Z + m1.W.Z * m2.Z.Z + m1.W.W * m2.W.Z;
  2858. MResult.W.W := m1.W.X * m2.X.W + m1.W.Y * m2.Y.W + m1.W.Z * m2.Z.W + m1.W.W * m2.W.W;
  2859. end;
  2860. function VectorTransform(const V: TVector; const M: TMatrix): TVector;
  2861. begin
  2862. result.V[X] := V.V[X] * M.X.X + V.V[Y] * M.Y.X + V.V[Z] * M.Z.X + V.V[W] * M.W.X;
  2863. result.V[Y] := V.V[X] * M.X.Y + V.V[Y] * M.Y.Y + V.V[Z] * M.Z.Y + V.V[W] * M.W.Y;
  2864. result.V[Z] := V.V[X] * M.X.Z + V.V[Y] * M.Y.Z + V.V[Z] * M.Z.Z + V.V[W] * M.W.Z;
  2865. result.V[W] := V.V[X] * M.X.W + V.V[Y] * M.Y.W + V.V[Z] * M.Z.W + V.V[W] * M.W.W;
  2866. end;
  2867. function VectorTransform(const V: TVector; const M: TAffineMatrix): TVector;
  2868. begin
  2869. result.X := V.X * M.V[X].X + V.Y * M.V[Y].X + V.Z * M.V[Z].X;
  2870. result.Y := V.X * M.V[X].Y + V.Y * M.V[Y].Y + V.Z * M.V[Z].Y;
  2871. result.Z := V.X * M.V[X].Z + V.Y * M.V[Y].Z + V.Z * M.V[Z].Z;
  2872. result.W := V.W;
  2873. end;
  2874. function VectorTransform(const V: TAffineVector; const M: TMatrix)
  2875. : TAffineVector;
  2876. begin
  2877. result.X := V.X * M.V[X].X + V.Y * M.V[Y].X + V.Z * M.V[Z].X + M.V[W].X;
  2878. result.Y := V.X * M.V[X].Y + V.Y * M.V[Y].Y + V.Z * M.V[Z].Y + M.V[W].Y;
  2879. result.Z := V.X * M.V[X].Z + V.Y * M.V[Y].Z + V.Z * M.V[Z].Z + M.V[W].Z;
  2880. end;
  2881. function VectorTransform(const V: TAffineVector; const M: TAffineMatrix)
  2882. : TAffineVector;
  2883. begin
  2884. result.V[X] := V.V[X] * M.X.X + V.V[Y] * M.Y.X + V.V[Z] * M.Z.X;
  2885. result.V[Y] := V.V[X] * M.X.Y + V.V[Y] * M.Y.Y + V.V[Z] * M.Z.Y;
  2886. result.V[Z] := V.V[X] * M.X.Z + V.V[Y] * M.Y.Z + V.V[Z] * M.Z.Z;
  2887. end;
  2888. function MatrixDeterminant(const M: TAffineMatrix): Single;
  2889. begin
  2890. result := M.X.X * (M.Y.Y * M.Z.Z - M.Z.Y * M.Y.Z) - M.X.Y *
  2891. (M.Y.X * M.Z.Z - M.Z.X * M.Y.Z) + M.X.Z * (M.Y.X * M.Z.Y - M.Z.X * M.Y.Y);
  2892. end;
  2893. function MatrixDetInternal(const a1, a2, a3, b1, b2, b3, c1, c2,
  2894. c3: Single): Single;
  2895. // internal version for the determinant of a 3x3 matrix
  2896. begin
  2897. result := a1 * (b2 * c3 - b3 * c2) - b1 * (a2 * c3 - a3 * c2) + c1 *
  2898. (a2 * b3 - a3 * b2);
  2899. end;
  2900. function MatrixDeterminant(const M: TMatrix): Single;
  2901. begin
  2902. result := M.X.X * MatrixDetInternal(M.Y.Y, M.Z.Y, M.W.Y, M.Y.Z, M.Z.Z, M.W.Z,
  2903. M.Y.W, M.Z.W, M.W.W) - M.X.Y * MatrixDetInternal(M.Y.X, M.Z.X, M.W.X, M.Y.Z,
  2904. M.Z.Z, M.W.Z, M.Y.W, M.Z.W, M.W.W) + M.X.Z * MatrixDetInternal(M.Y.X, M.Z.X,
  2905. M.W.X, M.Y.Y, M.Z.Y, M.W.Y, M.Y.W, M.Z.W, M.W.W) - M.X.W *
  2906. MatrixDetInternal(M.Y.X, M.Z.X, M.W.X, M.Y.Y, M.Z.Y, M.W.Y, M.Y.Z,
  2907. M.Z.Z, M.W.Z);
  2908. end;
  2909. procedure AdjointMatrix(var M: TMatrix);
  2910. var
  2911. a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4: Single;
  2912. begin
  2913. a1 := M.X.X;
  2914. b1 := M.X.Y;
  2915. c1 := M.X.Z;
  2916. d1 := M.X.W;
  2917. a2 := M.Y.X;
  2918. b2 := M.Y.Y;
  2919. c2 := M.Y.Z;
  2920. d2 := M.Y.W;
  2921. a3 := M.Z.X;
  2922. b3 := M.Z.Y;
  2923. c3 := M.Z.Z;
  2924. d3 := M.Z.W;
  2925. a4 := M.W.X;
  2926. b4 := M.W.Y;
  2927. c4 := M.W.Z;
  2928. d4 := M.W.W;
  2929. // row column labeling reversed since we transpose rows & columns
  2930. M.X.X := MatrixDetInternal(b2, b3, b4, c2, c3, c4, d2, d3, d4);
  2931. M.Y.X := -MatrixDetInternal(a2, a3, a4, c2, c3, c4, d2, d3, d4);
  2932. M.Z.X := MatrixDetInternal(a2, a3, a4, b2, b3, b4, d2, d3, d4);
  2933. M.W.X := -MatrixDetInternal(a2, a3, a4, b2, b3, b4, c2, c3, c4);
  2934. M.X.Y := -MatrixDetInternal(b1, b3, b4, c1, c3, c4, d1, d3, d4);
  2935. M.Y.Y := MatrixDetInternal(a1, a3, a4, c1, c3, c4, d1, d3, d4);
  2936. M.Z.Y := -MatrixDetInternal(a1, a3, a4, b1, b3, b4, d1, d3, d4);
  2937. M.W.Y := MatrixDetInternal(a1, a3, a4, b1, b3, b4, c1, c3, c4);
  2938. M.X.Z := MatrixDetInternal(b1, b2, b4, c1, c2, c4, d1, d2, d4);
  2939. M.Y.Z := -MatrixDetInternal(a1, a2, a4, c1, c2, c4, d1, d2, d4);
  2940. M.Z.Z := MatrixDetInternal(a1, a2, a4, b1, b2, b4, d1, d2, d4);
  2941. M.W.Z := -MatrixDetInternal(a1, a2, a4, b1, b2, b4, c1, c2, c4);
  2942. M.X.W := -MatrixDetInternal(b1, b2, b3, c1, c2, c3, d1, d2, d3);
  2943. M.Y.W := MatrixDetInternal(a1, a2, a3, c1, c2, c3, d1, d2, d3);
  2944. M.Z.W := -MatrixDetInternal(a1, a2, a3, b1, b2, b3, d1, d2, d3);
  2945. M.W.W := MatrixDetInternal(a1, a2, a3, b1, b2, b3, c1, c2, c3);
  2946. end;
  2947. procedure AdjointMatrix(var M: TAffineMatrix);
  2948. var
  2949. a1, a2, a3, b1, b2, b3, c1, c2, c3: Single;
  2950. begin
  2951. a1 := M.X.X;
  2952. a2 := M.X.Y;
  2953. a3 := M.X.Z;
  2954. b1 := M.Y.X;
  2955. b2 := M.Y.Y;
  2956. b3 := M.Y.Z;
  2957. c1 := M.Z.X;
  2958. c2 := M.Z.Y;
  2959. c3 := M.Z.Z;
  2960. M.X.X := (b2 * c3 - c2 * b3);
  2961. M.Y.X := -(b1 * c3 - c1 * b3);
  2962. M.Z.X := (b1 * c2 - c1 * b2);
  2963. M.X.Y := -(a2 * c3 - c2 * a3);
  2964. M.Y.Y := (a1 * c3 - c1 * a3);
  2965. M.Z.Y := -(a1 * c2 - c1 * a2);
  2966. M.X.Z := (a2 * b3 - b2 * a3);
  2967. M.Y.Z := -(a1 * b3 - b1 * a3);
  2968. M.Z.Z := (a1 * b2 - b1 * a2);
  2969. end;
  2970. procedure ScaleMatrix(var M: TAffineMatrix; const factor: Single);
  2971. var
  2972. i: Integer;
  2973. begin
  2974. for i := 0 to 2 do
  2975. begin
  2976. M.V[i].X := M.V[i].X * factor;
  2977. M.V[i].Y := M.V[i].Y * factor;
  2978. M.V[i].Z := M.V[i].Z * factor;
  2979. end;
  2980. end;
  2981. procedure ScaleMatrix(var M: TMatrix; const factor: Single);
  2982. var
  2983. i: Integer;
  2984. begin
  2985. for i := 0 to 3 do
  2986. begin
  2987. M.V[i].X := M.V[i].X * factor;
  2988. M.V[i].Y := M.V[i].Y * factor;
  2989. M.V[i].Z := M.V[i].Z * factor;
  2990. M.V[i].W := M.V[i].W * factor;
  2991. end;
  2992. end;
  2993. procedure TranslateMatrix(var M: TMatrix; const V: TAffineVector);
  2994. begin
  2995. M.W.X := M.W.X + V.X;
  2996. M.W.Y := M.W.Y + V.Y;
  2997. M.W.Z := M.W.Z + V.Z;
  2998. end;
  2999. procedure TranslateMatrix(var M: TMatrix; const V: TVector);
  3000. begin
  3001. M.W.X := M.W.X + V.X;
  3002. M.W.Y := M.W.Y + V.Y;
  3003. M.W.Z := M.W.Z + V.Z;
  3004. end;
  3005. procedure NormalizeMatrix(var M: TMatrix);
  3006. begin
  3007. M.X.W := 0;
  3008. NormalizeVector(M.X);
  3009. M.Y.W := 0;
  3010. NormalizeVector(M.Y);
  3011. M.Z := VectorCrossProduct(M.X, M.Y);
  3012. M.X := VectorCrossProduct(M.Y, M.Z);
  3013. M.W := WHmgVector;
  3014. end;
  3015. procedure TransposeMatrix(var M: TAffineMatrix);
  3016. var
  3017. f: Single;
  3018. begin
  3019. f := M.X.Y;
  3020. M.X.Y := M.Y.X;
  3021. M.Y.X := f;
  3022. f := M.X.Z;
  3023. M.X.Z := M.Z.X;
  3024. M.Z.X := f;
  3025. f := M.Y.Z;
  3026. M.Y.Z := M.Z.Y;
  3027. M.Z.Y := f;
  3028. end;
  3029. procedure TransposeMatrix(var M: TMatrix);
  3030. var
  3031. f: Single;
  3032. begin
  3033. f := M.X.Y;
  3034. M.X.Y := M.Y.X;
  3035. M.Y.X := f;
  3036. f := M.X.Z;
  3037. M.X.Z := M.Z.X;
  3038. M.Z.X := f;
  3039. f := M.X.W;
  3040. M.X.W := M.W.X;
  3041. M.W.X := f;
  3042. f := M.Y.Z;
  3043. M.Y.Z := M.Z.Y;
  3044. M.Z.Y := f;
  3045. f := M.Y.W;
  3046. M.Y.W := M.W.Y;
  3047. M.W.Y := f;
  3048. f := M.Z.W;
  3049. M.Z.W := M.W.Z;
  3050. M.W.Z := f;
  3051. end;
  3052. procedure InvertMatrix(var M: TMatrix);
  3053. var
  3054. det: Single;
  3055. begin
  3056. det := MatrixDeterminant(M);
  3057. if Abs(det) < EPSILON then
  3058. M := IdentityHmgMatrix
  3059. else
  3060. begin
  3061. AdjointMatrix(M);
  3062. ScaleMatrix(M, 1 / det);
  3063. end;
  3064. end;
  3065. function MatrixInvert(const M: TMatrix): TMatrix;
  3066. begin
  3067. result := M;
  3068. InvertMatrix(result);
  3069. end;
  3070. procedure InvertMatrix(var M: TAffineMatrix);
  3071. var
  3072. det: Single;
  3073. begin
  3074. det := MatrixDeterminant(M);
  3075. if Abs(det) < EPSILON then
  3076. M := IdentityMatrix
  3077. else
  3078. begin
  3079. AdjointMatrix(M);
  3080. ScaleMatrix(M, 1 / det);
  3081. end;
  3082. end;
  3083. function MatrixInvert(const M: TAffineMatrix): TAffineMatrix;
  3084. begin
  3085. result := M;
  3086. InvertMatrix(result);
  3087. end;
  3088. procedure Transpose_Scale_M33(const src: TMatrix; var dest: TMatrix;
  3089. var scale: Single);
  3090. begin
  3091. dest.X.X := scale * src.X.X;
  3092. dest.Y.X := scale * src.X.Y;
  3093. dest.Z.X := scale * src.X.Z;
  3094. dest.X.Y := scale * src.Y.X;
  3095. dest.Y.Y := scale * src.Y.Y;
  3096. dest.Z.Y := scale * src.Y.Z;
  3097. dest.X.Z := scale * src.Z.X;
  3098. dest.Y.Z := scale * src.Z.Y;
  3099. dest.Z.Z := scale * src.Z.Z;
  3100. end;
  3101. function AnglePreservingMatrixInvert(const mat: TMatrix): TMatrix;
  3102. var
  3103. scale: Single;
  3104. begin
  3105. scale := VectorNorm(mat.X);
  3106. // Is the submatrix A singular?
  3107. if Abs(scale) < EPSILON then
  3108. begin
  3109. // Matrix M has no inverse
  3110. result := IdentityHmgMatrix;
  3111. Exit;
  3112. end
  3113. else
  3114. begin
  3115. // Calculate the inverse of the square of the isotropic scale factor
  3116. scale := 1.0 / scale;
  3117. end;
  3118. // Fill in last row while CPU is busy with the division
  3119. result.X.W := 0.0;
  3120. result.Y.W := 0.0;
  3121. result.Z.W := 0.0;
  3122. result.W.W := 1.0;
  3123. // Transpose and scale the 3 by 3 upper-left submatrix
  3124. Transpose_Scale_M33(mat, result, scale);
  3125. // Calculate -(transpose(A) / s*s) C
  3126. result.W.X := -(result.X.X * mat.W.X + result.Y.X *
  3127. mat.W.Y + result.Z.X * mat.W.Z);
  3128. result.W.Y := -(result.X.Y * mat.W.X + result.Y.Y *
  3129. mat.W.Y + result.Z.Y * mat.W.Z);
  3130. result.W.Z := -(result.X.Z * mat.W.X + result.Y.Z *
  3131. mat.W.Y + result.Z.Z * mat.W.Z);
  3132. end;
  3133. function MatrixDecompose(const M: TMatrix; var Tran: TTransformations): Boolean;
  3134. var
  3135. I, J: Integer;
  3136. LocMat, pmat, invpmat: TMatrix;
  3137. prhs, psol: TVector;
  3138. row0, row1, row2: TAffineVector;
  3139. f: Single;
  3140. begin
  3141. Result := False;
  3142. LocMat := M;
  3143. // normalize the matrix
  3144. if LocMat.W.W = 0 then
  3145. Exit;
  3146. for I := 0 to 3 do
  3147. for J := 0 to 3 do
  3148. LocMat.V[I].V[J] := LocMat.V[I].V[J] / LocMat.W.W;
  3149. // pmat is used to solve for perspective, but it also provides
  3150. // an easy way to test for singularity of the upper 3x3 component.
  3151. pmat := LocMat;
  3152. for I := 0 to 2 do
  3153. pmat.V[I].V[W] := 0;
  3154. pmat.W.W := 1;
  3155. if MatrixDeterminant(pmat) = 0 then
  3156. Exit;
  3157. // First, isolate perspective. This is the messiest.
  3158. if (LocMat.X.W <> 0) or (LocMat.Y.W <> 0) or (LocMat.Z.W <> 0) then
  3159. begin
  3160. // prhs is the right hand side of the equation.
  3161. prhs.X := LocMat.X.W;
  3162. prhs.Y := LocMat.Y.W;
  3163. prhs.Z := LocMat.Z.W;
  3164. prhs.W := LocMat.W.W;
  3165. // Solve the equation by inverting pmat and multiplying
  3166. // prhs by the inverse. (This is the easiest way, not
  3167. // necessarily the best.)
  3168. invpmat := pmat;
  3169. InvertMatrix(invpmat);
  3170. TransposeMatrix(invpmat);
  3171. psol := VectorTransform(prhs, invpmat);
  3172. // stuff the answer away
  3173. Tran[ttPerspectiveX] := psol.X;
  3174. Tran[ttPerspectiveY] := psol.Y;
  3175. Tran[ttPerspectiveZ] := psol.Z;
  3176. Tran[ttPerspectiveW] := psol.W;
  3177. // clear the perspective partition
  3178. LocMat.X.W := 0;
  3179. LocMat.Y.W := 0;
  3180. LocMat.Z.W := 0;
  3181. LocMat.W.W := 1;
  3182. end
  3183. else
  3184. begin
  3185. // no perspective
  3186. Tran[ttPerspectiveX] := 0;
  3187. Tran[ttPerspectiveY] := 0;
  3188. Tran[ttPerspectiveZ] := 0;
  3189. Tran[ttPerspectiveW] := 0;
  3190. end;
  3191. // next take care of translation (easy)
  3192. for I := 0 to 2 do
  3193. begin
  3194. Tran[TTransType(Ord(ttTranslateX) + I)] := LocMat.V[W].V[I];
  3195. LocMat.V[W].V[I] := 0;
  3196. end;
  3197. // now get scale and shear
  3198. SetVector(row0, LocMat.X);
  3199. SetVector(row1, LocMat.Y);
  3200. SetVector(row2, LocMat.Z);
  3201. // compute X scale factor and normalize first row
  3202. Tran[ttScaleX] := VectorNorm(row0);
  3203. VectorScale(row0, RSqrt(Tran[ttScaleX]));
  3204. // compute XY shear factor and make 2nd row orthogonal to 1st
  3205. Tran[ttShearXY] := VectorDotProduct(row0, row1);
  3206. f := -Tran[ttShearXY];
  3207. CombineVector(row1, row0, f);
  3208. // now, compute Y scale and normalize 2nd row
  3209. Tran[ttScaleY] := VectorNorm(row1);
  3210. VectorScale(row1, RSqrt(Tran[ttScaleY]));
  3211. Tran[ttShearXY] := Tran[ttShearXY] / Tran[ttScaleY];
  3212. // compute XZ and YZ shears, orthogonalize 3rd row
  3213. Tran[ttShearXZ] := VectorDotProduct(row0, row2);
  3214. f := -Tran[ttShearXZ];
  3215. CombineVector(row2, row0, f);
  3216. Tran[ttShearYZ] := VectorDotProduct(row1, row2);
  3217. f := -Tran[ttShearYZ];
  3218. CombineVector(row2, row1, f);
  3219. // next, get Z scale and normalize 3rd row
  3220. Tran[ttScaleZ] := VectorNorm(row2);
  3221. VectorScale(row2, RSqrt(Tran[ttScaleZ]));
  3222. Tran[ttShearXZ] := Tran[ttShearXZ] / Tran[ttScaleZ];
  3223. Tran[ttShearYZ] := Tran[ttShearYZ] / Tran[ttScaleZ];
  3224. // At this point, the matrix (in rows[]) is orthonormal.
  3225. // Check for a coordinate system flip. If the determinant
  3226. // is -1, then negate the matrix and the scaling factors.
  3227. if VectorDotProduct(row0, VectorCrossProduct(row1, row2)) < 0 then
  3228. begin
  3229. for I := 0 to 2 do
  3230. Tran[TTransType(Ord(ttScaleX) + I)] :=
  3231. -Tran[TTransType(Ord(ttScaleX) + I)];
  3232. NegateVector(row0);
  3233. NegateVector(row1);
  3234. NegateVector(row2);
  3235. end;
  3236. // now, get the rotations out, as described in the gem
  3237. Tran[ttRotateY] := ArcSin(-row0.Z);
  3238. if Cos(Tran[ttRotateY]) <> 0 then
  3239. begin
  3240. Tran[ttRotateX] := ArcTan2(row1.V[Z], row2.V[Z]);
  3241. Tran[ttRotateZ] := ArcTan2(row0.V[Y], row0.V[X]);
  3242. end
  3243. else
  3244. begin
  3245. Tran[ttRotateX] := ArcTan2(row1.V[X], row1.V[Y]);
  3246. Tran[ttRotateZ] := 0;
  3247. end;
  3248. // All done!
  3249. result := True;
  3250. end;
  3251. function CreateLookAtMatrix(const eye, center, normUp: TVector): TMatrix;
  3252. var
  3253. XAxis, YAxis, ZAxis, negEye: TVector;
  3254. begin
  3255. ZAxis := VectorSubtract(center, eye);
  3256. NormalizeVector(ZAxis);
  3257. XAxis := VectorCrossProduct(ZAxis, normUp);
  3258. NormalizeVector(XAxis);
  3259. YAxis := VectorCrossProduct(XAxis, ZAxis);
  3260. result.X := XAxis;
  3261. result.Y := YAxis;
  3262. result.Z := ZAxis;
  3263. NegateVector(result.Z);
  3264. result.W := NullHmgPoint;
  3265. TransposeMatrix(result);
  3266. negEye := eye;
  3267. NegateVector(negEye);
  3268. negEye.W := 1;
  3269. negEye := VectorTransform(negEye, result);
  3270. result.W := negEye;
  3271. end;
  3272. function CreateMatrixFromFrustum(Left, Right, Bottom, Top, ZNear,
  3273. ZFar: Single): TMatrix;
  3274. begin
  3275. result.X.X := 2 * ZNear / (Right - Left);
  3276. result.X.Y := 0;
  3277. result.X.Z := 0;
  3278. result.X.W := 0;
  3279. result.Y.X := 0;
  3280. result.Y.Y := 2 * ZNear / (Top - Bottom);
  3281. result.Y.Z := 0;
  3282. result.Y.W := 0;
  3283. result.Z.X := (Right + Left) / (Right - Left);
  3284. result.Z.Y := (Top + Bottom) / (Top - Bottom);
  3285. result.Z.Z := -(ZFar + ZNear) / (ZFar - ZNear);
  3286. result.Z.W := -1;
  3287. result.W.X := 0;
  3288. result.W.Y := 0;
  3289. result.W.Z := -2 * ZFar * ZNear / (ZFar - ZNear);
  3290. result.W.W := 0;
  3291. end;
  3292. function CreatePerspectiveMatrix(FOV, Aspect, ZNear, ZFar: Single): TMatrix;
  3293. var
  3294. X, Y: Single;
  3295. begin
  3296. FOV := MinFloat(179.9, MaxFloat(0, FOV));
  3297. Y := ZNear * Tangent(DegToRadian(FOV) * 0.5);
  3298. X := Y * Aspect;
  3299. result := CreateMatrixFromFrustum(-X, X, -Y, Y, ZNear, ZFar);
  3300. end;
  3301. function CreateOrthoMatrix(Left, Right, Bottom, Top, ZNear,
  3302. ZFar: Single): TMatrix;
  3303. begin
  3304. result.X.X := 2 / (Right - Left);
  3305. result.X.Y := 0;
  3306. result.X.Z := 0;
  3307. result.X.W := 0;
  3308. result.Y.X := 0;
  3309. result.Y.Y := 2 / (Top - Bottom);
  3310. result.Y.Z := 0;
  3311. result.Y.W := 0;
  3312. result.Z.X := 0;
  3313. result.Z.Y := 0;
  3314. result.Z.Z := -2 / (ZFar - ZNear);
  3315. result.Z.W := 0;
  3316. result.W.X := (Left + Right) / (Left - Right);
  3317. result.W.Y := (Bottom + Top) / (Bottom - Top);
  3318. result.W.Z := (ZNear + ZFar) / (ZNear - ZFar);
  3319. result.W.W := 1;
  3320. end;
  3321. function CreatePickMatrix(X, Y, deltax, deltay: Single;
  3322. const viewport: TVector4i): TMatrix;
  3323. begin
  3324. if (deltax <= 0) or (deltay <= 0) then
  3325. begin
  3326. result := IdentityHmgMatrix;
  3327. Exit;
  3328. end;
  3329. // Translate and scale the picked region to the entire window
  3330. result := CreateTranslationMatrix
  3331. (AffineVectorMake((viewport.Z - 2 * (X - viewport.X)) / deltax,
  3332. (viewport.W - 2 * (Y - viewport.Y)) / deltay, 0.0));
  3333. result.X.X := viewport.Z / deltax;
  3334. result.Y.Y := viewport.W / deltay;
  3335. end;
  3336. function Project(objectVector: TVector; const ViewProjMatrix: TMatrix;
  3337. const viewport: TVector4i; out WindowVector: TVector): Boolean;
  3338. begin
  3339. result := False;
  3340. objectVector.W := 1.0;
  3341. WindowVector := VectorTransform(objectVector, ViewProjMatrix);
  3342. if WindowVector.W = 0.0 then
  3343. Exit;
  3344. WindowVector.X := WindowVector.X / WindowVector.W;
  3345. WindowVector.Y := WindowVector.Y / WindowVector.W;
  3346. WindowVector.Z := WindowVector.Z / WindowVector.W;
  3347. // Map x, y and z to range 0-1
  3348. WindowVector.X := WindowVector.X * 0.5 + 0.5;
  3349. WindowVector.Y := WindowVector.Y * 0.5 + 0.5;
  3350. WindowVector.Z := WindowVector.Z * 0.5 + 0.5;
  3351. // Map x,y to viewport
  3352. WindowVector.X := WindowVector.X * viewport.Z + viewport.X;
  3353. WindowVector.Y := WindowVector.Y * viewport.W + viewport.Y;
  3354. result := True;
  3355. end;
  3356. function UnProject(WindowVector: TVector; ViewProjMatrix: TMatrix;
  3357. const viewport: TVector4i; out objectVector: TVector): Boolean;
  3358. begin
  3359. result := False;
  3360. InvertMatrix(ViewProjMatrix);
  3361. WindowVector.W := 1.0;
  3362. // Map x and y from window coordinates
  3363. WindowVector.X := (WindowVector.X - viewport.X) / viewport.Z;
  3364. WindowVector.Y := (WindowVector.Y - viewport.Y) / viewport.W;
  3365. // Map to range -1 to 1
  3366. WindowVector.X := WindowVector.X * 2 - 1;
  3367. WindowVector.Y := WindowVector.Y * 2 - 1;
  3368. WindowVector.Z := WindowVector.Z * 2 - 1;
  3369. objectVector := VectorTransform(WindowVector, ViewProjMatrix);
  3370. if objectVector.W = 0.0 then
  3371. Exit;
  3372. objectVector.X := objectVector.X / objectVector.W;
  3373. objectVector.Y := objectVector.Y / objectVector.W;
  3374. objectVector.Z := objectVector.Z / objectVector.W;
  3375. result := True;
  3376. end;
  3377. function CalcPlaneNormal(const p1, p2, p3: TAffineVector): TAffineVector;
  3378. var
  3379. V1, V2: TAffineVector;
  3380. begin
  3381. VectorSubtract(p2, p1, V1);
  3382. VectorSubtract(p3, p1, V2);
  3383. VectorCrossProduct(V1, V2, result);
  3384. NormalizeVector(result);
  3385. end;
  3386. procedure CalcPlaneNormal(const p1, p2, p3: TAffineVector; var vr: TAffineVector);
  3387. var
  3388. V1, V2: TAffineVector;
  3389. begin
  3390. VectorSubtract(p2, p1, V1);
  3391. VectorSubtract(p3, p1, V2);
  3392. VectorCrossProduct(V1, V2, vr);
  3393. NormalizeVector(vr);
  3394. end;
  3395. procedure CalcPlaneNormal(const p1, p2, p3: TVector; var vr: TAffineVector); overload;
  3396. var
  3397. V1, V2: TVector;
  3398. begin
  3399. VectorSubtract(p2, p1, V1);
  3400. VectorSubtract(p3, p1, V2);
  3401. VectorCrossProduct(V1, V2, vr);
  3402. NormalizeVector(vr);
  3403. end;
  3404. function PlaneMake(const point, normal: TAffineVector): THmgPlane;
  3405. begin
  3406. PAffineVector(@result)^ := normal;
  3407. result.W := -VectorDotProduct(point, normal);
  3408. end;
  3409. function PlaneMake(const point, normal: TVector): THmgPlane;
  3410. begin
  3411. PAffineVector(@result)^ := PAffineVector(@normal)^;
  3412. Result.W := -VectorDotProduct(PAffineVector(@point)^, PAffineVector(@normal)^);
  3413. end;
  3414. function PlaneMake(const p1, p2, p3: TAffineVector): THmgPlane;
  3415. begin
  3416. CalcPlaneNormal(p1, p2, p3, PAffineVector(@result)^);
  3417. result.W := -VectorDotProduct(p1, PAffineVector(@result)^);
  3418. end;
  3419. function PlaneMake(const p1, p2, p3: TVector): THmgPlane;
  3420. begin
  3421. CalcPlaneNormal(p1, p2, p3, PAffineVector(@result)^);
  3422. result.W := -VectorDotProduct(p1, PAffineVector(@result)^);
  3423. end;
  3424. procedure SetPlane(var dest: TDoubleHmgPlane; const src: THmgPlane);
  3425. begin
  3426. dest.X := src.X;
  3427. dest.Y := src.Y;
  3428. dest.Z := src.Z;
  3429. dest.W := src.W;
  3430. end;
  3431. procedure NormalizePlane(var plane: THmgPlane);
  3432. var
  3433. n: Single;
  3434. begin
  3435. n := RSqrt(plane.X * plane.X + plane.Y * plane.Y + plane.Z *
  3436. plane.Z);
  3437. ScaleVector(plane, n);
  3438. end;
  3439. function PlaneEvaluatePoint(const plane: THmgPlane; const point: TAffineVector): Single;
  3440. begin
  3441. result := plane.X * point.X + plane.Y * point.Y + plane.Z *
  3442. point.Z + plane.W;
  3443. end;
  3444. function PlaneEvaluatePoint(const plane: THmgPlane;
  3445. const point: TVector): Single;
  3446. begin
  3447. result := plane.X * point.X + plane.Y * point.Y + plane.Z * point.Z + plane.W;
  3448. end;
  3449. function PointIsInHalfSpace(const point, planePoint, planeNormal: TVector): Boolean;
  3450. begin
  3451. result := (PointPlaneDistance(point, planePoint, planeNormal) > 0); // 44
  3452. end;
  3453. function PointIsInHalfSpace(const point, planePoint,
  3454. planeNormal: TAffineVector): Boolean;
  3455. begin
  3456. result := (PointPlaneDistance(point, planePoint, planeNormal) > 0);
  3457. end;
  3458. function PointIsInHalfSpace(const point: TAffineVector;
  3459. const plane: THmgPlane): Boolean;
  3460. begin
  3461. result := (PointPlaneDistance(point, plane) > 0);
  3462. end;
  3463. function PointPlaneDistance(const point, planePoint,
  3464. planeNormal: TVector): Single;
  3465. begin
  3466. result := (point.X - planePoint.X) * planeNormal.X +
  3467. (point.Y - planePoint.Y) * planeNormal.Y +
  3468. (point.Z - planePoint.Z) * planeNormal.Z;
  3469. end;
  3470. function PointPlaneDistance(const point, planePoint,
  3471. planeNormal: TAffineVector): Single;
  3472. begin
  3473. result := (point.X - planePoint.X) * planeNormal.X +
  3474. (point.Y - planePoint.Y) * planeNormal.Y +
  3475. (point.Z - planePoint.Z) * planeNormal.Z;
  3476. end;
  3477. function PointPlaneDistance(const point: TAffineVector;
  3478. const plane: THmgPlane): Single;
  3479. begin
  3480. result := PlaneEvaluatePoint(plane, point);
  3481. end;
  3482. function PointPlaneOrthoProjection(const point: TAffineVector;
  3483. const plane: THmgPlane; var inter: TAffineVector;
  3484. bothface: Boolean = True): Boolean;
  3485. var
  3486. h: Single;
  3487. normal: TAffineVector;
  3488. begin
  3489. result := False;
  3490. h := PointPlaneDistance(point, plane);
  3491. if (not bothface) and (h < 0) then
  3492. Exit;
  3493. normal := Vector3fMake(plane);
  3494. inter := VectorAdd(point, VectorScale(normal, -h));
  3495. result := True;
  3496. end;
  3497. function PointPlaneProjection(const point, direction: TAffineVector;
  3498. const plane: THmgPlane; var inter: TAffineVector;
  3499. bothface: Boolean = True): Boolean;
  3500. var
  3501. h, dot: Single;
  3502. normal: TAffineVector;
  3503. begin
  3504. result := False;
  3505. normal := Vector3fMake(plane);
  3506. dot := VectorDotProduct(VectorNormalize(direction), normal);
  3507. if (not bothface) and (dot > 0) then
  3508. Exit;
  3509. if Abs(dot) >= 0.000000001 then
  3510. begin
  3511. h := PointPlaneDistance(point, plane);
  3512. inter := VectorAdd(point, VectorScale(direction, -h / dot));
  3513. result := True;
  3514. end;
  3515. end;
  3516. function SegmentPlaneIntersection(const ptA, ptB: TAffineVector;
  3517. const plane: THmgPlane; var inter: TAffineVector): Boolean;
  3518. var
  3519. hA, hB, dot: Single;
  3520. normal, direction: TVector3f;
  3521. begin
  3522. result := False;
  3523. hA := PointPlaneDistance(ptA, plane);
  3524. hB := PointPlaneDistance(ptB, plane);
  3525. if hA * hB <= 0 then
  3526. begin
  3527. normal := Vector3fMake(plane);
  3528. direction := VectorNormalize(VectorSubtract(ptB, ptA));
  3529. dot := VectorDotProduct(direction, normal);
  3530. if Abs(dot) >= 0.000000001 then
  3531. begin
  3532. inter := VectorAdd(ptA, VectorScale(direction, -hA / dot));
  3533. result := True;
  3534. end;
  3535. end;
  3536. end;
  3537. function PointTriangleOrthoProjection(const point, ptA, ptB, ptC: TAffineVector;
  3538. var inter: TAffineVector; bothface: Boolean = True): Boolean;
  3539. var
  3540. plane: THmgPlane;
  3541. begin
  3542. result := False;
  3543. plane := PlaneMake(ptA, ptB, ptC);
  3544. if not IsLineIntersectTriangle(point, Vector3fMake(plane), ptA, ptB, ptC) then
  3545. Exit;
  3546. result := PointPlaneOrthoProjection(point, plane, inter, bothface);
  3547. end;
  3548. function PointTriangleProjection(const point, direction, ptA, ptB,
  3549. ptC: TAffineVector; var inter: TAffineVector;
  3550. bothface: Boolean = True): Boolean;
  3551. var
  3552. plane: THmgPlane;
  3553. begin
  3554. result := False;
  3555. if not IsLineIntersectTriangle(point, direction, ptA, ptB, ptC) then
  3556. Exit;
  3557. plane := PlaneMake(ptA, ptB, ptC);
  3558. result := PointPlaneProjection(point, direction, plane, inter, bothface);
  3559. end;
  3560. function IsLineIntersectTriangle(const point, direction, ptA, ptB,
  3561. ptC: TAffineVector): Boolean;
  3562. var
  3563. PA, PB, PC: TAffineVector;
  3564. crossAB, crossBC, crossCA: TAffineVector;
  3565. begin
  3566. result := False;
  3567. PA := VectorSubtract(ptA, point);
  3568. PB := VectorSubtract(ptB, point);
  3569. PC := VectorSubtract(ptC, point);
  3570. crossAB := VectorCrossProduct(PA, PB);
  3571. crossBC := VectorCrossProduct(PB, PC);
  3572. if VectorDotProduct(crossAB, direction) > 0 then
  3573. begin
  3574. if VectorDotProduct(crossBC, direction) > 0 then
  3575. begin
  3576. crossCA := VectorCrossProduct(PC, PA);
  3577. if VectorDotProduct(crossCA, direction) > 0 then
  3578. result := True;
  3579. end;
  3580. end
  3581. else if VectorDotProduct(crossBC, direction) < 0 then
  3582. begin
  3583. crossCA := VectorCrossProduct(PC, PA);
  3584. if VectorDotProduct(crossCA, direction) < 0 then
  3585. result := True;
  3586. end
  3587. end;
  3588. function PointQuadOrthoProjection(const point, ptA, ptB, ptC,
  3589. ptD: TAffineVector; var inter: TAffineVector;
  3590. bothface: Boolean = True): Boolean;
  3591. var
  3592. plane: THmgPlane;
  3593. begin
  3594. result := False;
  3595. plane := PlaneMake(ptA, ptB, ptC);
  3596. if not IsLineIntersectQuad(point, Vector3fMake(plane), ptA, ptB, ptC, ptD)
  3597. then
  3598. Exit;
  3599. result := PointPlaneOrthoProjection(point, plane, inter, bothface);
  3600. end;
  3601. function PointQuadProjection(const point, direction, ptA, ptB, ptC,
  3602. ptD: TAffineVector; var inter: TAffineVector;
  3603. bothface: Boolean = True): Boolean;
  3604. var
  3605. plane: THmgPlane;
  3606. begin
  3607. result := False;
  3608. if not IsLineIntersectQuad(point, direction, ptA, ptB, ptC, ptD) then
  3609. Exit;
  3610. plane := PlaneMake(ptA, ptB, ptC);
  3611. result := PointPlaneProjection(point, direction, plane, inter, bothface);
  3612. end;
  3613. function IsLineIntersectQuad(const point, direction, ptA, ptB, ptC,
  3614. ptD: TAffineVector): Boolean;
  3615. var
  3616. PA, PB, PC, PD: TAffineVector;
  3617. crossAB, crossBC, crossCD, crossDA: TAffineVector;
  3618. begin
  3619. result := False;
  3620. PA := VectorSubtract(ptA, point);
  3621. PB := VectorSubtract(ptB, point);
  3622. PC := VectorSubtract(ptC, point);
  3623. PD := VectorSubtract(ptD, point);
  3624. crossAB := VectorCrossProduct(PA, PB);
  3625. crossBC := VectorCrossProduct(PB, PC);
  3626. if VectorDotProduct(crossAB, direction) > 0 then
  3627. begin
  3628. if VectorDotProduct(crossBC, direction) > 0 then
  3629. begin
  3630. crossCD := VectorCrossProduct(PC, PD);
  3631. if VectorDotProduct(crossCD, direction) > 0 then
  3632. begin
  3633. crossDA := VectorCrossProduct(PD, PA);
  3634. if VectorDotProduct(crossDA, direction) > 0 then
  3635. result := True;
  3636. end;
  3637. end;
  3638. end
  3639. else if VectorDotProduct(crossBC, direction) < 0 then
  3640. begin
  3641. crossCD := VectorCrossProduct(PC, PD);
  3642. if VectorDotProduct(crossCD, direction) < 0 then
  3643. begin
  3644. crossDA := VectorCrossProduct(PD, PA);
  3645. if VectorDotProduct(crossDA, direction) < 0 then
  3646. result := True;
  3647. end;
  3648. end
  3649. end;
  3650. function PointDiskOrthoProjection(const point, center, up: TAffineVector;
  3651. const radius: Single; var inter: TAffineVector;
  3652. bothface: Boolean = True): Boolean;
  3653. begin
  3654. if PointPlaneOrthoProjection(point, PlaneMake(center, up), inter, bothface)
  3655. then
  3656. result := (VectorDistance2(inter, center) <= radius * radius)
  3657. else
  3658. result := False;
  3659. end;
  3660. function PointDiskProjection(const point, direction, center, up: TAffineVector;
  3661. const radius: Single; var inter: TAffineVector;
  3662. bothface: Boolean = True): Boolean;
  3663. begin
  3664. if PointPlaneProjection(point, direction, PlaneMake(center, up), inter,
  3665. bothface) then
  3666. result := VectorDistance2(inter, center) <= radius * radius
  3667. else
  3668. result := False;
  3669. end;
  3670. function PointLineClosestPoint(const point, linePoint, lineDirection
  3671. : TAffineVector): TAffineVector;
  3672. var
  3673. W: TAffineVector;
  3674. c1, c2, b: Single;
  3675. begin
  3676. W := VectorSubtract(point, linePoint);
  3677. c1 := VectorDotProduct(W, lineDirection);
  3678. c2 := VectorDotProduct(lineDirection, lineDirection);
  3679. b := c1 / c2;
  3680. VectorAdd(linePoint, VectorScale(lineDirection, b), result);
  3681. end;
  3682. function PointLineDistance(const point, linePoint, lineDirection: TAffineVector): Single;
  3683. var
  3684. PB: TAffineVector;
  3685. begin
  3686. PB := PointLineClosestPoint(point, linePoint, lineDirection);
  3687. result := VectorDistance(point, PB);
  3688. end;
  3689. function PointSegmentClosestPoint(const point, segmentStart,
  3690. segmentStop: TVector): TVector;
  3691. var
  3692. W, lineDirection: TVector;
  3693. c1, c2, b: Single;
  3694. begin
  3695. lineDirection := VectorSubtract(segmentStop, segmentStart);
  3696. W := VectorSubtract(point, segmentStart);
  3697. c1 := VectorDotProduct(W, lineDirection);
  3698. c2 := VectorDotProduct(lineDirection, lineDirection);
  3699. b := ClampValue(c1 / c2, 0, 1);
  3700. VectorAdd(segmentStart, VectorScale(lineDirection, b), result);
  3701. end;
  3702. function PointSegmentClosestPoint(const point, segmentStart,
  3703. segmentStop: TAffineVector): TAffineVector;
  3704. var
  3705. W, lineDirection: TAffineVector;
  3706. c1, c2, b: Single;
  3707. begin
  3708. lineDirection := VectorSubtract(segmentStop, segmentStart);
  3709. W := VectorSubtract(point, segmentStart);
  3710. c1 := VectorDotProduct(W, lineDirection);
  3711. c2 := VectorDotProduct(lineDirection, lineDirection);
  3712. b := ClampValue(c1 / c2, 0, 1);
  3713. VectorAdd(segmentStart, VectorScale(lineDirection, b), result);
  3714. end;
  3715. function PointSegmentDistance(const point, segmentStart,
  3716. segmentStop: TAffineVector): Single;
  3717. var
  3718. PB: TAffineVector;
  3719. begin
  3720. PB := PointSegmentClosestPoint(point, segmentStart, segmentStop);
  3721. result := VectorDistance(point, PB);
  3722. end;
  3723. // http://geometryalgorithms.com/Archive/algorithm_0104/algorithm_0104B.htm
  3724. procedure SegmentSegmentClosestPoint(const S0Start, S0Stop, S1Start,
  3725. S1Stop: TAffineVector; var Segment0Closest, Segment1Closest: TAffineVector);
  3726. const
  3727. cSMALL_NUM = 0.000000001;
  3728. var
  3729. u, V, W: TAffineVector;
  3730. a, b, c, smalld, e, largeD, sc, sn, sD, tc, tN, tD: Single;
  3731. begin
  3732. VectorSubtract(S0Stop, S0Start, u);
  3733. VectorSubtract(S1Stop, S1Start, V);
  3734. VectorSubtract(S0Start, S1Start, W);
  3735. a := VectorDotProduct(u, u);
  3736. b := VectorDotProduct(u, V);
  3737. c := VectorDotProduct(V, V);
  3738. smalld := VectorDotProduct(u, W);
  3739. e := VectorDotProduct(V, W);
  3740. largeD := a * c - b * b;
  3741. sD := largeD;
  3742. tD := largeD;
  3743. if largeD < cSMALL_NUM then
  3744. begin
  3745. sn := 0.0;
  3746. sD := 1.0;
  3747. tN := e;
  3748. tD := c;
  3749. end
  3750. else
  3751. begin
  3752. sn := (b * e - c * smalld);
  3753. tN := (a * e - b * smalld);
  3754. if (sn < 0.0) then
  3755. begin
  3756. sn := 0.0;
  3757. tN := e;
  3758. tD := c;
  3759. end
  3760. else if (sn > sD) then
  3761. begin
  3762. sn := sD;
  3763. tN := e + b;
  3764. tD := c;
  3765. end;
  3766. end;
  3767. if (tN < 0.0) then
  3768. begin
  3769. tN := 0.0;
  3770. // recompute sc for this edge
  3771. if (-smalld < 0.0) then
  3772. sn := 0.0
  3773. else if (-smalld > a) then
  3774. sn := sD
  3775. else
  3776. begin
  3777. sn := -smalld;
  3778. sD := a;
  3779. end;
  3780. end
  3781. else if (tN > tD) then
  3782. begin
  3783. tN := tD;
  3784. // recompute sc for this edge
  3785. if ((-smalld + b) < 0.0) then
  3786. sn := 0
  3787. else if ((-smalld + b) > a) then
  3788. sn := sD
  3789. else
  3790. begin
  3791. sn := (-smalld + b);
  3792. sD := a;
  3793. end;
  3794. end;
  3795. // finally do the division to get sc and tc
  3796. // sc := (abs(sN) < SMALL_NUM ? 0.0 : sN / sD);
  3797. if Abs(sn) < cSMALL_NUM then
  3798. sc := 0
  3799. else
  3800. sc := sn / sD;
  3801. // tc := (abs(tN) < SMALL_NUM ? 0.0 : tN / tD);
  3802. if Abs(tN) < cSMALL_NUM then
  3803. tc := 0
  3804. else
  3805. tc := tN / tD;
  3806. // get the difference of the two closest points
  3807. // Vector dP = w + (sc * u) - (tc * v); // = S0(sc) - S1(tc)
  3808. Segment0Closest := VectorAdd(S0Start, VectorScale(u, sc));
  3809. Segment1Closest := VectorAdd(S1Start, VectorScale(V, tc));
  3810. end;
  3811. function SegmentSegmentDistance(const S0Start, S0Stop, S1Start,
  3812. S1Stop: TAffineVector): Single;
  3813. var
  3814. Pb0, PB1: TAffineVector;
  3815. begin
  3816. SegmentSegmentClosestPoint(S0Start, S0Stop, S1Start, S1Stop, Pb0, PB1);
  3817. result := VectorDistance(Pb0, PB1);
  3818. end;
  3819. function LineLineDistance(const linePt0, lineDir0, linePt1,
  3820. lineDir1: TAffineVector): Single;
  3821. const
  3822. cBIAS = 0.000000001;
  3823. var
  3824. det: Single;
  3825. begin
  3826. det := Abs((linePt1.X - linePt0.X) * (lineDir0.Y * lineDir1.Z -
  3827. lineDir1.Y * lineDir0.Z) - (linePt1.Y - linePt0.Y) *
  3828. (lineDir0.X * lineDir1.Z - lineDir1.X * lineDir0.Z) +
  3829. (linePt1.Z - linePt0.Z) * (lineDir0.X * lineDir1.Y -
  3830. lineDir1.X * lineDir0.Y));
  3831. if det < cBIAS then
  3832. result := PointLineDistance(linePt0, linePt1, lineDir1)
  3833. else
  3834. result := det / VectorLength(VectorCrossProduct(lineDir0, lineDir1));
  3835. end;
  3836. function QuaternionMake(const Imag: array of Single; Real: Single): TQuaternion;
  3837. var
  3838. n: Integer;
  3839. begin
  3840. n := Length(Imag);
  3841. if n >= 1 then
  3842. result.ImagPart.X := Imag[0];
  3843. if n >= 2 then
  3844. result.ImagPart.Y := Imag[1];
  3845. if n >= 3 then
  3846. result.ImagPart.Z := Imag[2];
  3847. result.RealPart := Real;
  3848. end;
  3849. function QuaternionMake(const X,Y,Z,W: Single): TQuaternion; overload;
  3850. begin
  3851. Result.X := X;
  3852. Result.Y := Y;
  3853. Result.Z := Z;
  3854. Result.W := W;
  3855. end;
  3856. function QuaternionMake(const V: TVector): TQuaternion; overload;
  3857. begin
  3858. Result.X := V.X;
  3859. Result.Y := V.Y;
  3860. Result.Z := V.Z;
  3861. Result.W := V.W;
  3862. end;
  3863. function QuaternionConjugate(const Q: TQuaternion): TQuaternion;
  3864. begin
  3865. result.ImagPart.X := -Q.ImagPart.X;
  3866. result.ImagPart.Y := -Q.ImagPart.Y;
  3867. result.ImagPart.Z := -Q.ImagPart.Z;
  3868. result.RealPart := Q.RealPart;
  3869. end;
  3870. function QuaternionMagnitude(const Q: TQuaternion): Single;
  3871. begin
  3872. result := Sqrt(VectorNorm(Q.ImagPart) + Sqr(Q.RealPart));
  3873. end;
  3874. procedure NormalizeQuaternion(var Q: TQuaternion);
  3875. var
  3876. M, f: Single;
  3877. begin
  3878. M := QuaternionMagnitude(Q);
  3879. if M > EPSILON2 then
  3880. begin
  3881. f := 1 / M;
  3882. ScaleVector(Q.ImagPart, f);
  3883. Q.RealPart := Q.RealPart * f;
  3884. end
  3885. else
  3886. Q := IdentityQuaternion;
  3887. end;
  3888. function QuaternionFromPoints(const V1, V2: TAffineVector): TQuaternion;
  3889. begin
  3890. result.ImagPart := VectorCrossProduct(V1, V2);
  3891. result.RealPart := Sqrt((VectorDotProduct(V1, V2) + 1) / 2);
  3892. end;
  3893. function QuaternionFromMatrix(const mat: TMatrix): TQuaternion;
  3894. // the matrix must be a rotation matrix!
  3895. var
  3896. traceMat, S, invS: Double;
  3897. begin
  3898. traceMat := 1 + mat.X.X + mat.Y.Y + mat.Z.Z;
  3899. if traceMat > EPSILON2 then
  3900. begin
  3901. S := Sqrt(traceMat) * 2;
  3902. invS := 1 / S;
  3903. result.ImagPart.X := (mat.Y.Z - mat.Z.Y) * invS;
  3904. result.ImagPart.Y := (mat.Z.X - mat.X.Z) * invS;
  3905. result.ImagPart.Z := (mat.X.Y - mat.Y.X) * invS;
  3906. result.RealPart := 0.25 * S;
  3907. end
  3908. else if (mat.X.X > mat.Y.Y) and (mat.X.X > mat.Z.Z)
  3909. then
  3910. begin // Row 0:
  3911. S := Sqrt(MaxFloat(EPSILON2, cOne + mat.X.X - mat.Y.Y -
  3912. mat.Z.Z)) * 2;
  3913. invS := 1 / S;
  3914. result.ImagPart.X := 0.25 * S;
  3915. result.ImagPart.Y := (mat.X.Y + mat.Y.X) * invS;
  3916. result.ImagPart.Z := (mat.Z.X + mat.X.Z) * invS;
  3917. result.RealPart := (mat.Y.Z - mat.Z.Y) * invS;
  3918. end
  3919. else if (mat.Y.Y > mat.Z.Z) then
  3920. begin // Row 1:
  3921. S := Sqrt(MaxFloat(EPSILON2, cOne + mat.Y.Y - mat.X.X -
  3922. mat.Z.Z)) * 2;
  3923. invS := 1 / S;
  3924. result.ImagPart.X := (mat.X.Y + mat.Y.X) * invS;
  3925. result.ImagPart.Y := 0.25 * S;
  3926. result.ImagPart.Z := (mat.Y.Z + mat.Z.Y) * invS;
  3927. result.RealPart := (mat.Z.X - mat.X.Z) * invS;
  3928. end
  3929. else
  3930. begin // Row 2:
  3931. S := Sqrt(MaxFloat(EPSILON2, cOne + mat.Z.Z - mat.X.X -
  3932. mat.Y.Y)) * 2;
  3933. invS := 1 / S;
  3934. result.ImagPart.X := (mat.Z.X + mat.X.Z) * invS;
  3935. result.ImagPart.Y := (mat.Y.Z + mat.Z.Y) * invS;
  3936. result.ImagPart.Z := 0.25 * S;
  3937. result.RealPart := (mat.X.Y - mat.Y.X) * invS;
  3938. end;
  3939. NormalizeQuaternion(result);
  3940. end;
  3941. function QuaternionMultiply(const qL, qR: TQuaternion): TQuaternion;
  3942. var
  3943. Temp: TQuaternion;
  3944. begin
  3945. Temp.RealPart := qL.RealPart * qR.RealPart - qL.ImagPart.V[X] * qR.ImagPart.V
  3946. [X] - qL.ImagPart.V[Y] * qR.ImagPart.V[Y] - qL.ImagPart.V[Z] *
  3947. qR.ImagPart.V[Z];
  3948. Temp.ImagPart.V[X] := qL.RealPart * qR.ImagPart.V[X] + qL.ImagPart.V[X] *
  3949. qR.RealPart + qL.ImagPart.V[Y] * qR.ImagPart.V[Z] - qL.ImagPart.V[Z] *
  3950. qR.ImagPart.V[Y];
  3951. Temp.ImagPart.V[Y] := qL.RealPart * qR.ImagPart.V[Y] + qL.ImagPart.V[Y] *
  3952. qR.RealPart + qL.ImagPart.V[Z] * qR.ImagPart.V[X] - qL.ImagPart.V[X] *
  3953. qR.ImagPart.V[Z];
  3954. Temp.ImagPart.V[Z] := qL.RealPart * qR.ImagPart.V[Z] + qL.ImagPart.V[Z] *
  3955. qR.RealPart + qL.ImagPart.V[X] * qR.ImagPart.V[Y] - qL.ImagPart.V[Y] *
  3956. qR.ImagPart.V[X];
  3957. result := Temp;
  3958. end;
  3959. function QuaternionToMatrix(quat: TQuaternion): TMatrix;
  3960. var
  3961. W, X, Y, Z, xx, xy, xz, xw, yy, yz, yw, zz, zw: Single;
  3962. begin
  3963. NormalizeQuaternion(quat);
  3964. W := quat.RealPart;
  3965. X := quat.ImagPart.X;
  3966. Y := quat.ImagPart.Y;
  3967. Z := quat.ImagPart.Z;
  3968. xx := X * X;
  3969. xy := X * Y;
  3970. xz := X * Z;
  3971. xw := X * W;
  3972. yy := Y * Y;
  3973. yz := Y * Z;
  3974. yw := Y * W;
  3975. zz := Z * Z;
  3976. zw := Z * W;
  3977. result.X.X := 1 - 2 * (yy + zz);
  3978. result.Y.X := 2 * (xy - zw);
  3979. result.Z.X := 2 * (xz + yw);
  3980. result.W.X := 0;
  3981. result.X.Y := 2 * (xy + zw);
  3982. result.Y.Y := 1 - 2 * (xx + zz);
  3983. result.Z.Y := 2 * (yz - xw);
  3984. result.W.Y := 0;
  3985. result.X.Z := 2 * (xz - yw);
  3986. result.Y.Z := 2 * (yz + xw);
  3987. result.Z.Z := 1 - 2 * (xx + yy);
  3988. result.W.Z := 0;
  3989. result.X.W := 0;
  3990. result.Y.W := 0;
  3991. result.Z.W := 0;
  3992. result.W.W := 1;
  3993. end;
  3994. function QuaternionToAffineMatrix(quat: TQuaternion): TAffineMatrix;
  3995. var
  3996. W, X, Y, Z, xx, xy, xz, xw, yy, yz, yw, zz, zw: Single;
  3997. begin
  3998. NormalizeQuaternion(quat);
  3999. W := quat.RealPart;
  4000. X := quat.ImagPart.X;
  4001. Y := quat.ImagPart.Y;
  4002. Z := quat.ImagPart.Z;
  4003. xx := X * X;
  4004. xy := X * Y;
  4005. xz := X * Z;
  4006. xw := X * W;
  4007. yy := Y * Y;
  4008. yz := Y * Z;
  4009. yw := Y * W;
  4010. zz := Z * Z;
  4011. zw := Z * W;
  4012. result.X.X := 1 - 2 * (yy + zz);
  4013. result.Y.X := 2 * (xy - zw);
  4014. result.Z.X := 2 * (xz + yw);
  4015. result.X.Y := 2 * (xy + zw);
  4016. result.Y.Y := 1 - 2 * (xx + zz);
  4017. result.Z.Y := 2 * (yz - xw);
  4018. result.X.Z := 2 * (xz - yw);
  4019. result.Y.Z := 2 * (yz + xw);
  4020. result.Z.Z := 1 - 2 * (xx + yy);
  4021. end;
  4022. function QuaternionFromAngleAxis(const angle: Single; const axis: TAffineVector)
  4023. : TQuaternion;
  4024. var
  4025. f, S, c: Single;
  4026. begin
  4027. SinCosine(DegToRadian(angle * cOneDotFive), S, c);
  4028. result.RealPart := c;
  4029. f := S / VectorLength(axis);
  4030. result.ImagPart.X := axis.X * f;
  4031. result.ImagPart.Y := axis.Y * f;
  4032. result.ImagPart.Z := axis.Z * f;
  4033. end;
  4034. function QuaternionFromRollPitchYaw(const r, p, Y: Single): TQuaternion;
  4035. var
  4036. qp, qy: TQuaternion;
  4037. begin
  4038. result := QuaternionFromAngleAxis(r, ZVector);
  4039. qp := QuaternionFromAngleAxis(p, XVector);
  4040. qy := QuaternionFromAngleAxis(Y, YVector);
  4041. result := QuaternionMultiply(qp, result);
  4042. result := QuaternionMultiply(qy, result);
  4043. end;
  4044. function QuaternionFromEuler(const X, Y, Z: Single; eulerOrder: TEulerOrder): TQuaternion;
  4045. // input angles in degrees
  4046. var
  4047. gimbalLock: Boolean;
  4048. quat1, quat2: TQuaternion;
  4049. function EulerToQuat(const X, Y, Z: Single; eulerOrder: TEulerOrder)
  4050. : TQuaternion;
  4051. const
  4052. cOrder: array [Low(TEulerOrder) .. High(TEulerOrder)] of array [1 .. 3]
  4053. of Byte = ((1, 2, 3), (1, 3, 2), (2, 1, 3), // eulXYZ, eulXZY, eulYXZ,
  4054. (3, 1, 2), (2, 3, 1), (3, 2, 1)); // eulYZX, eulZXY, eulZYX
  4055. var
  4056. Q: array [1 .. 3] of TQuaternion;
  4057. begin
  4058. Q[cOrder[eulerOrder][1]] := QuaternionFromAngleAxis(X, XVector);
  4059. Q[cOrder[eulerOrder][2]] := QuaternionFromAngleAxis(Y, YVector);
  4060. Q[cOrder[eulerOrder][3]] := QuaternionFromAngleAxis(Z, ZVector);
  4061. result := QuaternionMultiply(Q[2], Q[3]);
  4062. result := QuaternionMultiply(Q[1], result);
  4063. end;
  4064. const
  4065. SMALL_ANGLE = 0.001;
  4066. begin
  4067. NormalizeDegAngle(X);
  4068. NormalizeDegAngle(Y);
  4069. NormalizeDegAngle(Z);
  4070. case eulerOrder of
  4071. eulXYZ, eulZYX:
  4072. gimbalLock := Abs(Abs(Y) - 90.0) <= EPSILON2; // cos(Y) = 0;
  4073. eulYXZ, eulZXY:
  4074. gimbalLock := Abs(Abs(X) - 90.0) <= EPSILON2; // cos(X) = 0;
  4075. eulXZY, eulYZX:
  4076. gimbalLock := Abs(Abs(Z) - 90.0) <= EPSILON2; // cos(Z) = 0;
  4077. else
  4078. Assert(False);
  4079. gimbalLock := False;
  4080. end;
  4081. if gimbalLock then
  4082. begin
  4083. case eulerOrder of
  4084. eulXYZ, eulZYX:
  4085. quat1 := EulerToQuat(X, Y - SMALL_ANGLE, Z, eulerOrder);
  4086. eulYXZ, eulZXY:
  4087. quat1 := EulerToQuat(X - SMALL_ANGLE, Y, Z, eulerOrder);
  4088. eulXZY, eulYZX:
  4089. quat1 := EulerToQuat(X, Y, Z - SMALL_ANGLE, eulerOrder);
  4090. end;
  4091. case eulerOrder of
  4092. eulXYZ, eulZYX:
  4093. quat2 := EulerToQuat(X, Y + SMALL_ANGLE, Z, eulerOrder);
  4094. eulYXZ, eulZXY:
  4095. quat2 := EulerToQuat(X + SMALL_ANGLE, Y, Z, eulerOrder);
  4096. eulXZY, eulYZX:
  4097. quat2 := EulerToQuat(X, Y, Z + SMALL_ANGLE, eulerOrder);
  4098. end;
  4099. result := QuaternionSlerp(quat1, quat2, 0.5);
  4100. end
  4101. else
  4102. begin
  4103. result := EulerToQuat(X, Y, Z, eulerOrder);
  4104. end;
  4105. end;
  4106. procedure QuaternionToPoints(const Q: TQuaternion;
  4107. var ArcFrom, ArcTo: TAffineVector);
  4108. var
  4109. S, invS: Single;
  4110. begin
  4111. S := Q.ImagPart.V[X] * Q.ImagPart.V[X] + Q.ImagPart.V[Y] * Q.ImagPart.V[Y];
  4112. if S = 0 then
  4113. SetAffineVector(ArcFrom, 0, 1, 0)
  4114. else
  4115. begin
  4116. invS := RSqrt(S);
  4117. SetAffineVector(ArcFrom, -Q.ImagPart.V[Y] * invS,
  4118. Q.ImagPart.V[X] * invS, 0);
  4119. end;
  4120. ArcTo.V[X] := Q.RealPart * ArcFrom.V[X] - Q.ImagPart.V[Z] * ArcFrom.V[Y];
  4121. ArcTo.V[Y] := Q.RealPart * ArcFrom.V[Y] + Q.ImagPart.V[Z] * ArcFrom.V[X];
  4122. ArcTo.V[Z] := Q.ImagPart.V[X] * ArcFrom.V[Y] - Q.ImagPart.V[Y] * ArcFrom.V[X];
  4123. if Q.RealPart < 0 then
  4124. SetAffineVector(ArcFrom, -ArcFrom.V[X], -ArcFrom.V[Y], 0);
  4125. end;
  4126. function Logarithm2(const X: Single): Single;
  4127. begin
  4128. result := Log2(X);
  4129. end;
  4130. function PowerSingle(const Base, Exponent: Single): Single;
  4131. begin
  4132. {$HINTS OFF}
  4133. if Exponent = cZero then
  4134. result := cOne
  4135. else if (Base = cZero) and (Exponent > cZero) then
  4136. result := cZero
  4137. else if RoundInt(Exponent) = Exponent then
  4138. result := Power(Base, Integer(Round(Exponent)))
  4139. else
  4140. result := Exp(Exponent * Ln(Base));
  4141. {$HINTS ON}
  4142. end;
  4143. function PowerInteger(Base: Single; Exponent: Integer): Single;
  4144. begin
  4145. {$HINTS OFF}
  4146. result := Power(Base, Exponent);
  4147. {$HINTS ON}
  4148. end;
  4149. function PowerInt64(Base: Single; Exponent: Int64): Single;
  4150. begin
  4151. {$HINTS OFF}
  4152. result := System.Math.Power(Base, Exponent);
  4153. {$HINTS ON}
  4154. end;
  4155. function DegToRadian(const Degrees: Extended): Extended;
  4156. begin
  4157. result := Degrees * (PI / 180);
  4158. end;
  4159. function DegToRadian(const Degrees: Single): Single;
  4160. begin
  4161. result := Degrees * cPIdiv180;
  4162. end;
  4163. function RadianToDeg(const Radians: Extended): Extended;
  4164. begin
  4165. result := Radians * (180 / PI);
  4166. end;
  4167. function RadianToDeg(const Radians: Single): Single;
  4168. begin
  4169. result := Radians * c180divPI;
  4170. end;
  4171. function NormalizeAngle(angle: Single): Single;
  4172. begin
  4173. result := angle - Int(angle * cInv2PI) * c2PI;
  4174. if result > PI then
  4175. result := result - 2 * PI
  4176. else if result < -PI then
  4177. result := result + 2 * PI;
  4178. end;
  4179. function NormalizeDegAngle(angle: Single): Single;
  4180. begin
  4181. result := angle - Int(angle * cInv360) * c360;
  4182. if result > c180 then
  4183. result := result - c360
  4184. else if result < -c180 then
  4185. result := result + c360;
  4186. end;
  4187. {$IFDEF USE_PLATFORM_HAS_EXTENDED}
  4188. procedure SinCosine(const Theta: Extended; out Sin, Cos: Extended);
  4189. begin
  4190. Math.SinCos(Theta, Sin, Cos);
  4191. end;
  4192. {$ENDIF GLS_PLATFORM_HAS_EXTENDED}
  4193. procedure SinCosine(const Theta: Double; out Sin, Cos: Double);
  4194. var
  4195. S, c: Extended;
  4196. begin
  4197. SinCos(Theta, S, c);
  4198. {$HINTS OFF}
  4199. Sin := S;
  4200. Cos := c;
  4201. {$HINTS ON}
  4202. end;
  4203. procedure SinCosine(const Theta: Single; out Sin, Cos: Single);
  4204. var
  4205. S, c: Extended;
  4206. begin
  4207. SinCos(Theta, S, c);
  4208. {$HINTS OFF}
  4209. Sin := S;
  4210. Cos := c;
  4211. {$HINTS ON}
  4212. end;
  4213. {$IFDEF USE_PLATFORM_HAS_EXTENDED}
  4214. procedure SinCosine(const Theta, radius: Double; out Sin, Cos: Extended);
  4215. var
  4216. S, c: Extended;
  4217. begin
  4218. SinCos(Theta, S, c);
  4219. Sin := S * radius;
  4220. Cos := c * radius;
  4221. end;
  4222. {$ENDIF GLS_PLATFORM_HAS_EXTENDED}
  4223. procedure SinCosine(const Theta, radius: Double; out Sin, Cos: Double);
  4224. var
  4225. S, c: Extended;
  4226. begin
  4227. SinCos(Theta, S, c);
  4228. Sin := S * radius;
  4229. Cos := c * radius;
  4230. end;
  4231. procedure SinCosine(const Theta, radius: Single; out Sin, Cos: Single);
  4232. var
  4233. S, c: Extended;
  4234. begin
  4235. SinCos(Theta, S, c);
  4236. Sin := S * radius;
  4237. Cos := c * radius;
  4238. end;
  4239. procedure PrepareSinCosCache(var S, c: array of Single;
  4240. startAngle, stopAngle: Single);
  4241. var
  4242. i: Integer;
  4243. d, alpha, beta: Single;
  4244. begin
  4245. Assert((High(S) = High(c)) and (Low(S) = Low(c)));
  4246. stopAngle := stopAngle + 1E-5;
  4247. if High(S) > Low(S) then
  4248. d := cPIdiv180 * (stopAngle - startAngle) / (High(S) - Low(S))
  4249. else
  4250. d := 0;
  4251. if High(S) - Low(S) < 1000 then
  4252. begin
  4253. // Fast computation (approx 5.5x)
  4254. alpha := 2 * Sqr(Sin(d * 0.5));
  4255. beta := Sin(d);
  4256. SinCos(startAngle * cPIdiv180, S[Low(S)], c[Low(S)]);
  4257. for i := Low(S) to High(S) - 1 do
  4258. begin
  4259. // Make use of the incremental formulae:
  4260. // cos (theta+delta) = cos(theta) - [alpha*cos(theta) + beta*sin(theta)]
  4261. // sin (theta+delta) = sin(theta) - [alpha*sin(theta) - beta*cos(theta)]
  4262. c[i + 1] := c[i] - alpha * c[i] - beta * S[i];
  4263. S[i + 1] := S[i] - alpha * S[i] + beta * c[i];
  4264. end;
  4265. end
  4266. else
  4267. begin
  4268. // Slower, but maintains precision when steps are small
  4269. startAngle := startAngle * cPIdiv180;
  4270. for i := Low(S) to High(S) do
  4271. SinCos((i - Low(S)) * d + startAngle, S[i], c[i]);
  4272. end;
  4273. end;
  4274. function ArcCosine(const X: Extended): Extended; overload;
  4275. begin
  4276. {$HINTS OFF}
  4277. result := ArcCos(X);
  4278. {$HINTS ON}
  4279. end;
  4280. function ArcSinus(const X: Extended): Extended; overload;
  4281. begin
  4282. {$HINTS OFF}
  4283. result := ArcSin(X);
  4284. {$HINTS ON}
  4285. end;
  4286. function FastArcTangent2(Y, X: Single): Single;
  4287. // accuracy of about 0.07 rads
  4288. const
  4289. cEpsilon: Single = 1E-10;
  4290. var
  4291. abs_y: Single;
  4292. begin
  4293. abs_y := Abs(Y) + cEpsilon; // prevent 0/0 condition
  4294. if Y < 0 then
  4295. begin
  4296. if X >= 0 then
  4297. result := cPIdiv4 * (X - abs_y) / (X + abs_y) - cPIdiv4
  4298. else
  4299. result := cPIdiv4 * (X + abs_y) / (abs_y - X) - c3PIdiv4;
  4300. end
  4301. else
  4302. begin
  4303. if X >= 0 then
  4304. result := cPIdiv4 - cPIdiv4 * (X - abs_y) / (X + abs_y)
  4305. else
  4306. result := c3PIdiv4 - cPIdiv4 * (X + abs_y) / (abs_y - X);
  4307. end;
  4308. end;
  4309. function ISqrt(i: Integer): Integer;
  4310. begin
  4311. {$HINTS OFF}
  4312. result := Round(Sqrt(i));
  4313. {$HINTS ON}
  4314. end;
  4315. function ILength(X, Y: Integer): Integer;
  4316. begin
  4317. {$HINTS OFF}
  4318. result := Round(Sqrt(X * X + Y * Y));
  4319. {$HINTS ON}
  4320. end;
  4321. function ILength(X, Y, Z: Integer): Integer;
  4322. begin
  4323. {$HINTS OFF}
  4324. result := Round(Sqrt(X * X + Y * Y + Z * Z));
  4325. {$HINTS ON}
  4326. end;
  4327. function RLength(X, Y: Single): Single;
  4328. begin
  4329. result := 1 / Sqrt(X * X + Y * Y);
  4330. end;
  4331. procedure RandomPointOnSphere(var p: TAffineVector);
  4332. var
  4333. T, W: Single;
  4334. begin
  4335. p.Z := 2 * Random - 1;
  4336. T := 2 * PI * Random;
  4337. W := Sqrt(1 - p.Z * p.Z);
  4338. SinCosine(T, W, p.Y, p.X);
  4339. end;
  4340. function RoundInt(V: Single): Single;
  4341. begin
  4342. {$HINTS OFF}
  4343. result := Int(V + 0.5);
  4344. {$HINTS ON}
  4345. end;
  4346. function RoundInt(V: Extended): Extended;
  4347. begin
  4348. result := Int(V + 0.5);
  4349. end;
  4350. function SignStrict(X: Single): Integer;
  4351. begin
  4352. if X < 0 then
  4353. result := -1
  4354. else
  4355. result := 1
  4356. end;
  4357. function ScaleAndRound(i: Integer; var S: Single): Integer;
  4358. begin
  4359. {$HINTS OFF}
  4360. result := Round(i * S);
  4361. {$HINTS ON}
  4362. end;
  4363. function IsInRange(const X, a, b: Single): Boolean;
  4364. begin
  4365. if a < b then
  4366. result := (a <= X) and (X <= b)
  4367. else
  4368. result := (b <= X) and (X <= a);
  4369. end;
  4370. function IsInRange(const X, a, b: Double): Boolean;
  4371. begin
  4372. if a < b then
  4373. result := (a <= X) and (X <= b)
  4374. else
  4375. result := (b <= X) and (X <= a);
  4376. end;
  4377. function IsInCube(const p, d: TAffineVector): Boolean; overload;
  4378. begin
  4379. result := ((p.X >= -d.X) and (p.X <= d.X)) and
  4380. ((p.Y >= -d.Y) and (p.Y <= d.Y)) and
  4381. ((p.Z >= -d.Z) and (p.Z <= d.Z));
  4382. end;
  4383. function IsInCube(const p, d: TVector): Boolean; overload;
  4384. begin
  4385. result := ((p.X >= -d.X) and (p.X <= d.X)) and
  4386. ((p.Y >= -d.Y) and (p.Y <= d.Y)) and
  4387. ((p.Z >= -d.Z) and (p.Z <= d.Z));
  4388. end;
  4389. function MinFloat(values: PSingleArray; nbItems: Integer): Single;
  4390. var
  4391. i, k: Integer;
  4392. begin
  4393. if nbItems > 0 then
  4394. begin
  4395. k := 0;
  4396. for i := 1 to nbItems - 1 do
  4397. if values^[i] < values^[k] then
  4398. k := i;
  4399. result := values^[k];
  4400. end
  4401. else
  4402. result := 0;
  4403. end;
  4404. function MinFloat(values: PDoubleArray; nbItems: Integer): Double;
  4405. var
  4406. i, k: Integer;
  4407. begin
  4408. if nbItems > 0 then
  4409. begin
  4410. k := 0;
  4411. for i := 1 to nbItems - 1 do
  4412. if values^[i] < values^[k] then
  4413. k := i;
  4414. result := values^[k];
  4415. end
  4416. else
  4417. result := 0;
  4418. end;
  4419. function MinFloat(values: PExtendedArray; nbItems: Integer): Extended;
  4420. var
  4421. i, k: Integer;
  4422. begin
  4423. if nbItems > 0 then
  4424. begin
  4425. k := 0;
  4426. for i := 1 to nbItems - 1 do
  4427. if values^[i] < values^[k] then
  4428. k := i;
  4429. result := values^[k];
  4430. end
  4431. else
  4432. result := 0;
  4433. end;
  4434. function MinFloat(const V: array of Single): Single;
  4435. var
  4436. i: Integer;
  4437. begin
  4438. if Length(V) > 0 then
  4439. begin
  4440. result := V[0];
  4441. for i := 1 to High(V) do
  4442. if V[i] < result then
  4443. result := V[i];
  4444. end
  4445. else
  4446. result := 0;
  4447. end;
  4448. function MinFloat(const V1, V2: Single): Single;
  4449. begin
  4450. if V1 < V2 then
  4451. result := V1
  4452. else
  4453. result := V2;
  4454. end;
  4455. function MinFloat(const V1, V2: Double): Double;
  4456. begin
  4457. if V1 < V2 then
  4458. result := V1
  4459. else
  4460. result := V2;
  4461. end;
  4462. function MinFloat(const V1, V2: Extended): Extended; overload;
  4463. begin
  4464. if V1 < V2 then
  4465. result := V1
  4466. else
  4467. result := V2;
  4468. end;
  4469. function MinFloat(const V1, V2, V3: Single): Single;
  4470. begin
  4471. if V1 <= V2 then
  4472. if V1 <= V3 then
  4473. result := V1
  4474. else if V3 <= V2 then
  4475. result := V3
  4476. else
  4477. result := V2
  4478. else if V2 <= V3 then
  4479. result := V2
  4480. else if V3 <= V1 then
  4481. result := V3
  4482. else
  4483. result := V1;
  4484. end;
  4485. function MinFloat(const V1, V2, V3: Double): Double;
  4486. begin
  4487. if V1 <= V2 then
  4488. if V1 <= V3 then
  4489. result := V1
  4490. else if V3 <= V2 then
  4491. result := V3
  4492. else
  4493. result := V2
  4494. else if V2 <= V3 then
  4495. result := V2
  4496. else if V3 <= V1 then
  4497. result := V3
  4498. else
  4499. result := V1;
  4500. end;
  4501. function MinFloat(const V1, V2, V3: Extended): Extended; overload;
  4502. begin
  4503. if V1 <= V2 then
  4504. if V1 <= V3 then
  4505. result := V1
  4506. else if V3 <= V2 then
  4507. result := V3
  4508. else
  4509. result := V2
  4510. else if V2 <= V3 then
  4511. result := V2
  4512. else if V3 <= V1 then
  4513. result := V3
  4514. else
  4515. result := V1;
  4516. end;
  4517. function MaxFloat(values: PSingleArray; nbItems: Integer): Single; overload;
  4518. var
  4519. i, k: Integer;
  4520. begin
  4521. if nbItems > 0 then
  4522. begin
  4523. k := 0;
  4524. for i := 1 to nbItems - 1 do
  4525. if values^[i] > values^[k] then
  4526. k := i;
  4527. result := values^[k];
  4528. end
  4529. else
  4530. result := 0;
  4531. end;
  4532. function MaxFloat(values: PDoubleArray; nbItems: Integer): Double; overload;
  4533. var
  4534. i, k: Integer;
  4535. begin
  4536. if nbItems > 0 then
  4537. begin
  4538. k := 0;
  4539. for i := 1 to nbItems - 1 do
  4540. if values^[i] > values^[k] then
  4541. k := i;
  4542. result := values^[k];
  4543. end
  4544. else
  4545. result := 0;
  4546. end;
  4547. function MaxFloat(values: PExtendedArray; nbItems: Integer): Extended; overload;
  4548. var
  4549. i, k: Integer;
  4550. begin
  4551. if nbItems > 0 then
  4552. begin
  4553. k := 0;
  4554. for i := 1 to nbItems - 1 do
  4555. if values^[i] > values^[k] then
  4556. k := i;
  4557. result := values^[k];
  4558. end
  4559. else
  4560. result := 0;
  4561. end;
  4562. function MaxFloat(const V: array of Single): Single;
  4563. var
  4564. i: Integer;
  4565. begin
  4566. if Length(V) > 0 then
  4567. begin
  4568. result := V[0];
  4569. for i := 1 to High(V) do
  4570. if V[i] > result then
  4571. result := V[i];
  4572. end
  4573. else
  4574. result := 0;
  4575. end;
  4576. function MaxFloat(const V1, V2: Single): Single;
  4577. begin
  4578. if V1 > V2 then
  4579. result := V1
  4580. else
  4581. result := V2;
  4582. end;
  4583. function MaxFloat(const V1, V2: Double): Double;
  4584. begin
  4585. if V1 > V2 then
  4586. result := V1
  4587. else
  4588. result := V2;
  4589. end;
  4590. function MaxFloat(const V1, V2: Extended): Extended; overload;
  4591. begin
  4592. if V1 > V2 then
  4593. result := V1
  4594. else
  4595. result := V2;
  4596. end;
  4597. function MaxFloat(const V1, V2, V3: Single): Single;
  4598. begin
  4599. if V1 >= V2 then
  4600. if V1 >= V3 then
  4601. result := V1
  4602. else if V3 >= V2 then
  4603. result := V3
  4604. else
  4605. result := V2
  4606. else if V2 >= V3 then
  4607. result := V2
  4608. else if V3 >= V1 then
  4609. result := V3
  4610. else
  4611. result := V1;
  4612. end;
  4613. function MaxFloat(const V1, V2, V3: Double): Double;
  4614. begin
  4615. if V1 >= V2 then
  4616. if V1 >= V3 then
  4617. result := V1
  4618. else if V3 >= V2 then
  4619. result := V3
  4620. else
  4621. result := V2
  4622. else if V2 >= V3 then
  4623. result := V2
  4624. else if V3 >= V1 then
  4625. result := V3
  4626. else
  4627. result := V1;
  4628. end;
  4629. function MaxFloat(const V1, V2, V3: Extended): Extended; overload;
  4630. begin
  4631. if V1 >= V2 then
  4632. if V1 >= V3 then
  4633. result := V1
  4634. else if V3 >= V2 then
  4635. result := V3
  4636. else
  4637. result := V2
  4638. else if V2 >= V3 then
  4639. result := V2
  4640. else if V3 >= V1 then
  4641. result := V3
  4642. else
  4643. result := V1;
  4644. end;
  4645. function MinInteger(const V1, V2: Integer): Integer;
  4646. begin
  4647. if V1 < V2 then
  4648. result := V1
  4649. else
  4650. result := V2;
  4651. end;
  4652. function MinInteger(const V1, V2: Cardinal): Cardinal;
  4653. begin
  4654. if V1 < V2 then
  4655. result := V1
  4656. else
  4657. result := V2;
  4658. end;
  4659. function MinInteger(const V1, V2, V3: Integer): Integer;
  4660. begin
  4661. if V1 <= V2 then
  4662. if V1 <= V3 then
  4663. result := V1
  4664. else if V3 <= V2 then
  4665. result := V3
  4666. else
  4667. result := V2
  4668. else if V2 <= V3 then
  4669. result := V2
  4670. else if V3 <= V1 then
  4671. result := V3
  4672. else
  4673. result := V1;
  4674. end;
  4675. function MinInteger(const V1, V2, V3: Cardinal): Cardinal;
  4676. begin
  4677. if V1 <= V2 then
  4678. if V1 <= V3 then
  4679. result := V1
  4680. else if V3 <= V2 then
  4681. result := V3
  4682. else
  4683. result := V2
  4684. else if V2 <= V3 then
  4685. result := V2
  4686. else if V3 <= V1 then
  4687. result := V3
  4688. else
  4689. result := V1;
  4690. end;
  4691. function MaxInteger(const V1, V2: Integer): Integer;
  4692. begin
  4693. if V1 > V2 then
  4694. result := V1
  4695. else
  4696. result := V2;
  4697. end;
  4698. function MaxInteger(const V1, V2: Cardinal): Cardinal;
  4699. begin
  4700. if V1 > V2 then
  4701. result := V1
  4702. else
  4703. result := V2;
  4704. end;
  4705. function MaxInteger(const V1, V2, V3: Integer): Integer;
  4706. begin
  4707. if V1 >= V2 then
  4708. if V1 >= V3 then
  4709. result := V1
  4710. else if V3 >= V2 then
  4711. result := V3
  4712. else
  4713. result := V2
  4714. else if V2 >= V3 then
  4715. result := V2
  4716. else if V3 >= V1 then
  4717. result := V3
  4718. else
  4719. result := V1;
  4720. end;
  4721. function MaxInteger(const V1, V2, V3: Cardinal): Cardinal;
  4722. begin
  4723. if V1 >= V2 then
  4724. if V1 >= V3 then
  4725. result := V1
  4726. else if V3 >= V2 then
  4727. result := V3
  4728. else
  4729. result := V2
  4730. else if V2 >= V3 then
  4731. result := V2
  4732. else if V3 >= V1 then
  4733. result := V3
  4734. else
  4735. result := V1;
  4736. end;
  4737. function ClampInteger(const value, min, max: Integer): Integer;
  4738. begin
  4739. result := MinInteger(MaxInteger(value, min), max);
  4740. end;
  4741. function ClampInteger(const value, min, max: Cardinal): Cardinal;
  4742. begin
  4743. result := MinInteger(MaxInteger(value, min), max);
  4744. end;
  4745. function TriangleArea(const p1, p2, p3: TAffineVector): Single;
  4746. begin
  4747. result := 0.5 * VectorLength(VectorCrossProduct(VectorSubtract(p2, p1),
  4748. VectorSubtract(p3, p1)));
  4749. end;
  4750. function PolygonArea(const p: PAffineVectorArray; nSides: Integer): Single;
  4751. var
  4752. r: TAffineVector;
  4753. i: Integer;
  4754. p1, p2, p3: PAffineVector;
  4755. begin
  4756. result := 0;
  4757. if nSides > 2 then
  4758. begin
  4759. RstVector(r);
  4760. p1 := @p[0];
  4761. p2 := @p[1];
  4762. for i := 2 to nSides - 1 do
  4763. begin
  4764. p3 := @p[i];
  4765. AddVector(r, VectorCrossProduct(VectorSubtract(p2^, p1^),
  4766. VectorSubtract(p3^, p1^)));
  4767. p2 := p3;
  4768. end;
  4769. result := VectorLength(r) * 0.5;
  4770. end;
  4771. end;
  4772. function TriangleSignedArea(const p1, p2, p3: TAffineVector): Single;
  4773. begin
  4774. result := 0.5 * ((p2.X - p1.X) * (p3.Y - p1.Y) -
  4775. (p3.X - p1.X) * (p2.Y - p1.Y));
  4776. end;
  4777. function PolygonSignedArea(const p: PAffineVectorArray;
  4778. nSides: Integer): Single;
  4779. var
  4780. i: Integer;
  4781. p1, p2, p3: PAffineVector;
  4782. begin
  4783. result := 0;
  4784. if nSides > 2 then
  4785. begin
  4786. p1 := @(p^[0]);
  4787. p2 := @(p^[1]);
  4788. for i := 2 to nSides - 1 do
  4789. begin
  4790. p3 := @(p^[i]);
  4791. result := result + (p2^.X - p1^.X) * (p3^.Y - p1^.Y) -
  4792. (p3^.X - p1^.X) * (p2^.Y - p1^.Y);
  4793. p2 := p3;
  4794. end;
  4795. result := result * 0.5;
  4796. end;
  4797. end;
  4798. procedure ScaleFloatArray(values: PSingleArray; nb: Integer;
  4799. var factor: Single);
  4800. var
  4801. i: Integer;
  4802. begin
  4803. for i := 0 to nb - 1 do
  4804. values^[i] := values^[i] * factor;
  4805. end;
  4806. procedure ScaleFloatArray(var values: TSingleArray; factor: Single);
  4807. begin
  4808. if Length(values) > 0 then
  4809. ScaleFloatArray(@values[0], Length(values), factor);
  4810. end;
  4811. procedure OffsetFloatArray(values: PSingleArray; nb: Integer;
  4812. var delta: Single);
  4813. var
  4814. i: Integer;
  4815. begin
  4816. for i := 0 to nb - 1 do
  4817. values^[i] := values^[i] + delta;
  4818. end;
  4819. procedure OffsetFloatArray(var values: array of Single; delta: Single);
  4820. begin
  4821. if Length(values) > 0 then
  4822. ScaleFloatArray(@values[0], Length(values), delta);
  4823. end;
  4824. procedure OffsetFloatArray(valuesDest, valuesDelta: PSingleArray; nb: Integer);
  4825. var
  4826. i: Integer;
  4827. begin
  4828. for i := 0 to nb - 1 do
  4829. valuesDest^[i] := valuesDest^[i] + valuesDelta^[i];
  4830. end;
  4831. function MaxXYZComponent(const V: TVector): Single; overload;
  4832. begin
  4833. result := MaxFloat(V.X, V.Y, V.Z);
  4834. end;
  4835. function MaxXYZComponent(const V: TAffineVector): Single; overload;
  4836. begin
  4837. result := MaxFloat(V.X, V.Y, V.Z);
  4838. end;
  4839. function MinXYZComponent(const V: TVector): Single; overload;
  4840. begin
  4841. if V.X <= V.Y then
  4842. if V.X <= V.Z then
  4843. result := V.X
  4844. else if V.Z <= V.Y then
  4845. result := V.Z
  4846. else
  4847. result := V.Y
  4848. else if V.Y <= V.Z then
  4849. result := V.Y
  4850. else if V.Z <= V.X then
  4851. result := V.Z
  4852. else
  4853. result := V.X;
  4854. end;
  4855. function MinXYZComponent(const V: TAffineVector): Single; overload;
  4856. begin
  4857. result := MinFloat(V.X, V.Y, V.Z);
  4858. end;
  4859. function MaxAbsXYZComponent(V: TVector): Single;
  4860. begin
  4861. AbsVector(V);
  4862. result := MaxXYZComponent(V);
  4863. end;
  4864. function MinAbsXYZComponent(V: TVector): Single;
  4865. begin
  4866. AbsVector(V);
  4867. result := MinXYZComponent(V);
  4868. end;
  4869. procedure MaxVector(var V: TVector; const V1: TVector);
  4870. begin
  4871. if V1.X > V.X then
  4872. V.X := V1.X;
  4873. if V1.Y > V.Y then
  4874. V.Y := V1.Y;
  4875. if V1.Z > V.Z then
  4876. V.Z := V1.Z;
  4877. if V1.W > V.W then
  4878. V.W := V1.W;
  4879. end;
  4880. procedure MaxVector(var V: TAffineVector; const V1: TAffineVector); overload;
  4881. begin
  4882. if V1.X > V.X then
  4883. V.X := V1.X;
  4884. if V1.Y > V.Y then
  4885. V.Y := V1.Y;
  4886. if V1.Z > V.Z then
  4887. V.Z := V1.Z;
  4888. end;
  4889. procedure MinVector(var V: TVector; const V1: TVector);
  4890. begin
  4891. if V1.X < V.X then
  4892. V.X := V1.X;
  4893. if V1.Y < V.Y then
  4894. V.Y := V1.Y;
  4895. if V1.Z < V.Z then
  4896. V.Z := V1.Z;
  4897. if V1.W < V.W then
  4898. V.W := V1.W;
  4899. end;
  4900. procedure MinVector(var V: TAffineVector; const V1: TAffineVector);
  4901. begin
  4902. if V1.X < V.X then
  4903. V.X := V1.X;
  4904. if V1.Y < V.Y then
  4905. V.Y := V1.Y;
  4906. if V1.Z < V.Z then
  4907. V.Z := V1.Z;
  4908. end;
  4909. procedure SortArrayAscending(var a: array of Extended);
  4910. var
  4911. i, J, M: Integer;
  4912. buf: Extended;
  4913. begin
  4914. for i := Low(a) to High(a) - 1 do
  4915. begin
  4916. M := i;
  4917. for J := i + 1 to High(a) do
  4918. if a[J] < a[M] then
  4919. M := J;
  4920. if M <> i then
  4921. begin
  4922. buf := a[M];
  4923. a[M] := a[i];
  4924. a[i] := buf;
  4925. end;
  4926. end;
  4927. end;
  4928. function ClampValue(const aValue, aMin, aMax: Single): Single;
  4929. begin
  4930. if aValue < aMin then
  4931. result := aMin
  4932. else if aValue > aMax then
  4933. result := aMax
  4934. else
  4935. result := aValue;
  4936. end;
  4937. function ClampValue(const aValue, aMin: Single): Single;
  4938. begin
  4939. if aValue < aMin then
  4940. result := aMin
  4941. else
  4942. result := aValue;
  4943. end;
  4944. function MakeAffineDblVector(var V: array of Double): TAffineDblVector;
  4945. begin
  4946. result.X := V[0];
  4947. result.Y := V[1];
  4948. result.Z := V[2];
  4949. end;
  4950. function MakeDblVector(var V: array of Double): THomogeneousDblVector;
  4951. begin
  4952. result.X := V[0];
  4953. result.Y := V[1];
  4954. result.Z := V[2];
  4955. result.W := V[3];
  4956. end;
  4957. function PointInPolygon(const xp, yp: array of Single; X, Y: Single): Boolean;
  4958. var
  4959. i, J: Integer;
  4960. begin
  4961. result := False;
  4962. if High(xp) = High(yp) then
  4963. begin
  4964. J := High(xp);
  4965. for i := 0 to High(xp) do
  4966. begin
  4967. if ((((yp[i] <= Y) and (Y < yp[J])) or ((yp[J] <= Y) and (Y < yp[i]))) and
  4968. (X < (xp[J] - xp[i]) * (Y - yp[i]) / (yp[J] - yp[i]) + xp[i])) then
  4969. result := not result;
  4970. J := i;
  4971. end;
  4972. end;
  4973. end;
  4974. function IsPointInPolygon(const Polygon: array of TPoint; const p: TPoint): Boolean;
  4975. var
  4976. a: array of TPoint;
  4977. n, i: Integer;
  4978. inside: Boolean;
  4979. begin
  4980. n := High(Polygon) + 1;
  4981. SetLength(a, n + 2);
  4982. a[0] := p;
  4983. for i := 1 to n do
  4984. a[i] := Polygon[i - 1];
  4985. a[n + 1] := a[0];
  4986. inside := True;
  4987. for i := 1 to n do
  4988. begin
  4989. if (a[0].Y > a[i].Y) xor (a[0].Y <= a[i + 1].Y) then
  4990. Continue;
  4991. if (a[0].X - a[i].X) < ((a[0].Y - a[i].Y) * (a[i + 1].X - a[i].X) /
  4992. (a[i + 1].Y - a[i].Y)) then
  4993. inside := not inside;
  4994. end;
  4995. inside := not inside;
  4996. result := inside;
  4997. end;
  4998. procedure DivMod(Dividend: Integer; Divisor: Word; var result, Remainder: Word);
  4999. begin
  5000. result := Dividend div Divisor;
  5001. Remainder := Dividend mod Divisor;
  5002. end;
  5003. function ConvertRotation(const Angles: TAffineVector): TVector;
  5004. { Rotation of the Angle t about the axis (X, Y, Z) is given by:
  5005. | X^2 + (1-X^2) Cos(t), XY(1-Cos(t)) + Z Sin(t), XZ(1-Cos(t))-Y Sin(t) |
  5006. M = | XY(1-Cos(t))-Z Sin(t), Y^2 + (1-Y^2) Cos(t), YZ(1-Cos(t)) + X Sin(t) |
  5007. | XZ(1-Cos(t)) + Y Sin(t), YZ(1-Cos(t))-X Sin(t), Z^2 + (1-Z^2) Cos(t) |
  5008. Rotation about the three axes (Angles a1, a2, a3) can be represented as
  5009. the product of the individual rotation matrices:
  5010. | 1 0 0 | | Cos(a2) 0 -Sin(a2) | | Cos(a3) Sin(a3) 0 |
  5011. | 0 Cos(a1) Sin(a1) | * | 0 1 0 | * | -Sin(a3) Cos(a3) 0 |
  5012. | 0 -Sin(a1) Cos(a1) | | Sin(a2) 0 Cos(a2) | | 0 0 1 |
  5013. Mx My Mz
  5014. We now want to solve for X, Y, Z, and t given 9 equations in 4 unknowns.
  5015. Using the diagonal elements of the two matrices, we get:
  5016. X^2 + (1-X^2) Cos(t) = M[0][0]
  5017. Y^2 + (1-Y^2) Cos(t) = M[1][1]
  5018. Z^2 + (1-Z^2) Cos(t) = M[2][2]
  5019. Adding the three equations, we get:
  5020. X^2 + Y^2 + Z^2 - (M[0][0] + M[1][1] + M[2][2]) =
  5021. - (3 - X^2 - Y^2 - Z^2) Cos(t)
  5022. Since (X^2 + Y^2 + Z^2) = 1, we can rewrite as:
  5023. Cos(t) = (1 - (M[0][0] + M[1][1] + M[2][2])) / 2
  5024. Solving for t, we get:
  5025. t = Acos(((M[0][0] + M[1][1] + M[2][2]) - 1) / 2)
  5026. We can substitute t into the equations for X^2, Y^2, and Z^2 above
  5027. to get the values for X, Y, and Z. To find the proper signs we note
  5028. that:
  5029. 2 X Sin(t) = M[1][2] - M[2][1]
  5030. 2 Y Sin(t) = M[2][0] - M[0][2]
  5031. 2 Z Sin(t) = M[0][1] - M[1][0]
  5032. }
  5033. var
  5034. Axis1, Axis2: TVector3f;
  5035. M, m1, m2: TMatrix;
  5036. cost, cost1, sint, s1, s2, s3: Single;
  5037. i: Integer;
  5038. begin
  5039. // see if we are only rotating about a single Axis
  5040. if Abs(Angles.X) < EPSILON then
  5041. begin
  5042. if Abs(Angles.Y) < EPSILON then
  5043. begin
  5044. SetVector(result, 0, 0, 1, Angles.Z);
  5045. Exit;
  5046. end
  5047. else if Abs(Angles.Z) < EPSILON then
  5048. begin
  5049. SetVector(result, 0, 1, 0, Angles.Y);
  5050. Exit;
  5051. end
  5052. end
  5053. else if (Abs(Angles.Y) < EPSILON) and (Abs(Angles.Z) < EPSILON) then
  5054. begin
  5055. SetVector(result, 1, 0, 0, Angles.X);
  5056. Exit;
  5057. end;
  5058. // make the rotation matrix
  5059. Axis1 := XVector;
  5060. M := CreateRotationMatrix(Axis1, Angles.X);
  5061. Axis2 := YVector;
  5062. m2 := CreateRotationMatrix(Axis2, Angles.Y);
  5063. m1 := MatrixMultiply(M, m2);
  5064. Axis2 := ZVector;
  5065. m2 := CreateRotationMatrix(Axis2, Angles.Z);
  5066. M := MatrixMultiply(m1, m2);
  5067. cost := ((M.X.X + M.Y.Y + M.Z.Z) - 1) / 2;
  5068. if cost < -1 then
  5069. cost := -1
  5070. else if cost > 1 - EPSILON then
  5071. begin
  5072. // Bad Angle - this would cause a crash
  5073. SetVector(result, XHmgVector);
  5074. Exit;
  5075. end;
  5076. cost1 := 1 - cost;
  5077. SetVector(result, Sqrt((M.X.X - cost) / cost1), Sqrt((M.Y.Y - cost) / cost1),
  5078. Sqrt((M.Z.Z - cost) / cost1), ArcCosine(cost));
  5079. sint := 2 * Sqrt(1 - cost * cost); // This is actually 2 Sin(t)
  5080. // Determine the proper signs
  5081. for i := 0 to 7 do
  5082. begin
  5083. if (i and 1) > 1 then
  5084. s1 := -1
  5085. else
  5086. s1 := 1;
  5087. if (i and 2) > 1 then
  5088. s2 := -1
  5089. else
  5090. s2 := 1;
  5091. if (i and 4) > 1 then
  5092. s3 := -1
  5093. else
  5094. s3 := 1;
  5095. if (Abs(s1 * result.V[X] * sint - M.Y.Z + M.Z.Y) < EPSILON2) and
  5096. (Abs(s2 * result.V[Y] * sint - M.Z.X + M.X.Z) < EPSILON2) and
  5097. (Abs(s3 * result.V[Z] * sint - M.X.Y + M.Y.X) < EPSILON2) then
  5098. begin
  5099. // We found the right combination of signs
  5100. result.V[X] := result.V[X] * s1;
  5101. result.V[Y] := result.V[Y] * s2;
  5102. result.V[Z] := result.V[Z] * s3;
  5103. Exit;
  5104. end;
  5105. end;
  5106. end;
  5107. function QuaternionSlerp(const QStart, QEnd: TQuaternion; Spin: Integer;
  5108. T: Single): TQuaternion;
  5109. var
  5110. beta, // complementary interp parameter
  5111. Theta, // Angle between A and B
  5112. sint, cost, // sine, cosine of theta
  5113. phi: Single; // theta plus spins
  5114. bflip: Boolean; // use negativ t?
  5115. begin
  5116. // cosine theta
  5117. cost := VectorAngleCosine(QStart.ImagPart, QEnd.ImagPart);
  5118. // if QEnd is on opposite hemisphere from QStart, use -QEnd instead
  5119. if cost < 0 then
  5120. begin
  5121. cost := -cost;
  5122. bflip := True;
  5123. end
  5124. else
  5125. bflip := False;
  5126. // if QEnd is (within precision limits) the same as QStart,
  5127. // just linear interpolate between QStart and QEnd.
  5128. // Can't do spins, since we don't know what direction to spin.
  5129. if (1 - cost) < EPSILON then
  5130. beta := 1 - T
  5131. else
  5132. begin
  5133. // normal case
  5134. Theta := ArcCosine(cost);
  5135. phi := Theta + Spin * PI;
  5136. sint := Sin(Theta);
  5137. beta := Sin(Theta - T * phi) / sint;
  5138. T := Sin(T * phi) / sint;
  5139. end;
  5140. if bflip then
  5141. T := -T;
  5142. // interpolate
  5143. result.ImagPart.V[X] := beta * QStart.ImagPart.V[X] + T * QEnd.ImagPart.V[X];
  5144. result.ImagPart.V[Y] := beta * QStart.ImagPart.V[Y] + T * QEnd.ImagPart.V[Y];
  5145. result.ImagPart.V[Z] := beta * QStart.ImagPart.V[Z] + T * QEnd.ImagPart.V[Z];
  5146. result.RealPart := beta * QStart.RealPart + T * QEnd.RealPart;
  5147. end;
  5148. function QuaternionSlerp(const source, dest: TQuaternion; const T: Single)
  5149. : TQuaternion;
  5150. var
  5151. to1: array [0 .. 4] of Single;
  5152. omega, cosom, sinom, scale0, scale1: Extended;
  5153. // t goes from 0 to 1
  5154. // absolute rotations
  5155. begin
  5156. // calc cosine
  5157. cosom := source.ImagPart.X * dest.ImagPart.X + source.ImagPart.Y *
  5158. dest.ImagPart.Y + source.ImagPart.Z * dest.ImagPart.Z +
  5159. source.RealPart * dest.RealPart;
  5160. // adjust signs (if necessary)
  5161. if cosom < 0 then
  5162. begin
  5163. cosom := -cosom;
  5164. to1[0] := -dest.ImagPart.X;
  5165. to1[1] := -dest.ImagPart.Y;
  5166. to1[2] := -dest.ImagPart.Z;
  5167. to1[3] := -dest.RealPart;
  5168. end
  5169. else
  5170. begin
  5171. to1[0] := dest.ImagPart.X;
  5172. to1[1] := dest.ImagPart.Y;
  5173. to1[2] := dest.ImagPart.Z;
  5174. to1[3] := dest.RealPart;
  5175. end;
  5176. // calculate coefficients
  5177. if ((1.0 - cosom) > EPSILON2) then
  5178. begin // standard case (slerp)
  5179. omega := ArcCosine(cosom);
  5180. sinom := 1 / Sin(omega);
  5181. scale0 := Sin((1.0 - T) * omega) * sinom;
  5182. scale1 := Sin(T * omega) * sinom;
  5183. end
  5184. else
  5185. begin // "from" and "to" quaternions are very close
  5186. // ... so we can do a linear interpolation
  5187. scale0 := 1.0 - T;
  5188. scale1 := T;
  5189. end;
  5190. // calculate final values
  5191. result.ImagPart.X := scale0 * source.ImagPart.X + scale1 * to1[0];
  5192. result.ImagPart.Y := scale0 * source.ImagPart.Y + scale1 * to1[1];
  5193. result.ImagPart.Z := scale0 * source.ImagPart.Z + scale1 * to1[2];
  5194. result.RealPart := scale0 * source.RealPart + scale1 * to1[3];
  5195. NormalizeQuaternion(result);
  5196. end;
  5197. function VectorDblToFlt(const V: THomogeneousDblVector): THomogeneousVector;
  5198. begin
  5199. {$HINTS OFF}
  5200. result.X := V.X;
  5201. result.Y := V.Y;
  5202. result.Z := V.Z;
  5203. result.W := V.W;
  5204. {$HINTS ON}
  5205. end;
  5206. function VectorAffineDblToFlt(const V: TAffineDblVector): TAffineVector;
  5207. begin
  5208. {$HINTS OFF}
  5209. result.X := V.X;
  5210. result.Y := V.Y;
  5211. result.Z := V.Z;
  5212. {$HINTS ON}
  5213. end;
  5214. function VectorAffineFltToDbl(const V: TAffineVector): TAffineDblVector;
  5215. begin
  5216. result.X := V.X;
  5217. result.Y := V.Y;
  5218. result.Z := V.Z;
  5219. end;
  5220. function VectorFltToDbl(const V: TVector): THomogeneousDblVector;
  5221. begin
  5222. result.X := V.X;
  5223. result.Y := V.Y;
  5224. result.Z := V.Z;
  5225. result.W := V.W;
  5226. end;
  5227. // ----------------- coordinate system manipulation functions -----------------------------------------------------------
  5228. function Turn(const Matrix: TMatrix; angle: Single): TMatrix;
  5229. begin
  5230. result := MatrixMultiply(Matrix,
  5231. CreateRotationMatrix(AffineVectorMake(Matrix.Y.X, Matrix.Y.Y,
  5232. Matrix.Y.Z), angle));
  5233. end;
  5234. function Turn(const Matrix: TMatrix; const MasterUp: TAffineVector;
  5235. angle: Single): TMatrix;
  5236. begin
  5237. result := MatrixMultiply(Matrix, CreateRotationMatrix(MasterUp, angle));
  5238. end;
  5239. function Pitch(const Matrix: TMatrix; angle: Single): TMatrix;
  5240. begin
  5241. result := MatrixMultiply(Matrix,
  5242. CreateRotationMatrix(AffineVectorMake(Matrix.X.X, Matrix.X.Y,
  5243. Matrix.X.Z), angle));
  5244. end;
  5245. function Pitch(const Matrix: TMatrix; const MasterRight: TAffineVector;
  5246. angle: Single): TMatrix; overload;
  5247. begin
  5248. result := MatrixMultiply(Matrix, CreateRotationMatrix(MasterRight, angle));
  5249. end;
  5250. function Roll(const Matrix: TMatrix; angle: Single): TMatrix;
  5251. begin
  5252. result := MatrixMultiply(Matrix,
  5253. CreateRotationMatrix(AffineVectorMake(Matrix.Z.X, Matrix.Z.Y,
  5254. Matrix.Z.Z), angle));
  5255. end;
  5256. function Roll(const Matrix: TMatrix; const MasterDirection: TAffineVector;
  5257. angle: Single): TMatrix; overload;
  5258. begin
  5259. result := MatrixMultiply(Matrix,
  5260. CreateRotationMatrix(MasterDirection, angle));
  5261. end;
  5262. function RayCastPlaneIntersect(const rayStart, rayVector: TVector;
  5263. const planePoint, planeNormal: TVector;
  5264. intersectPoint: PVector = nil): Boolean;
  5265. var
  5266. sp: TVector;
  5267. T, d: Single;
  5268. begin
  5269. d := VectorDotProduct(rayVector, planeNormal);
  5270. result := ((d > EPSILON2) or (d < -EPSILON2));
  5271. if result and Assigned(intersectPoint) then
  5272. begin
  5273. VectorSubtract(planePoint, rayStart, sp);
  5274. d := 1 / d; // will keep one FPU unit busy during dot product calculation
  5275. T := VectorDotProduct(sp, planeNormal) * d;
  5276. if T > 0 then
  5277. VectorCombine(rayStart, rayVector, T, intersectPoint^)
  5278. else
  5279. result := False;
  5280. end;
  5281. end;
  5282. function RayCastPlaneXZIntersect(const rayStart, rayVector: TVector;
  5283. const planeY: Single; intersectPoint: PVector = nil): Boolean;
  5284. var
  5285. T: Single;
  5286. begin
  5287. if rayVector.Y = 0 then
  5288. result := False
  5289. else
  5290. begin
  5291. T := (rayStart.Y - planeY) / rayVector.Y;
  5292. if T < 0 then
  5293. begin
  5294. if Assigned(intersectPoint) then
  5295. VectorCombine(rayStart, rayVector, T, intersectPoint^);
  5296. result := True;
  5297. end
  5298. else
  5299. result := False;
  5300. end;
  5301. end;
  5302. function RayCastTriangleIntersect(const rayStart, rayVector: TVector;
  5303. const p1, p2, p3: TAffineVector; intersectPoint: PVector = nil;
  5304. intersectNormal: PVector = nil): Boolean;
  5305. var
  5306. pvec: TAffineVector;
  5307. V1, V2, qvec, tvec: TVector;
  5308. T, u, V, det, invDet: Single;
  5309. begin
  5310. VectorSubtract(p2, p1, V1);
  5311. VectorSubtract(p3, p1, V2);
  5312. VectorCrossProduct(rayVector, V2, pvec);
  5313. det := VectorDotProduct(V1, pvec);
  5314. if ((det < EPSILON2) and (det > -EPSILON2)) then
  5315. begin // vector is parallel to triangle's plane
  5316. result := False;
  5317. Exit;
  5318. end;
  5319. invDet := cOne / det;
  5320. VectorSubtract(rayStart, p1, tvec);
  5321. u := VectorDotProduct(tvec, pvec) * invDet;
  5322. if (u < 0) or (u > 1) then
  5323. result := False
  5324. else
  5325. begin
  5326. qvec := VectorCrossProduct(tvec, V1);
  5327. V := VectorDotProduct(rayVector, qvec) * invDet;
  5328. result := (V >= 0) and (u + V <= 1);
  5329. if result then
  5330. begin
  5331. T := VectorDotProduct(V2, qvec) * invDet;
  5332. if T > 0 then
  5333. begin
  5334. if intersectPoint <> nil then
  5335. VectorCombine(rayStart, rayVector, T, intersectPoint^);
  5336. if intersectNormal <> nil then
  5337. VectorCrossProduct(V1, V2, intersectNormal^);
  5338. end
  5339. else
  5340. result := False;
  5341. end;
  5342. end;
  5343. end;
  5344. function RayCastMinDistToPoint(const rayStart, rayVector: TVector;
  5345. const point: TVector): Single;
  5346. var
  5347. proj: Single;
  5348. begin
  5349. proj := PointProject(point, rayStart, rayVector);
  5350. if proj <= 0 then
  5351. proj := 0; // rays don't go backward!
  5352. result := VectorDistance(point, VectorCombine(rayStart, rayVector, 1, proj));
  5353. end;
  5354. function RayCastIntersectsSphere(const rayStart, rayVector: TVector;
  5355. const sphereCenter: TVector; const SphereRadius: Single): Boolean;
  5356. var
  5357. proj: Single;
  5358. begin
  5359. proj := PointProject(sphereCenter, rayStart, rayVector);
  5360. if proj <= 0 then
  5361. proj := 0; // rays don't go backward!
  5362. result := (VectorDistance2(sphereCenter, VectorCombine(rayStart, rayVector, 1,
  5363. proj)) <= Sqr(SphereRadius));
  5364. end;
  5365. function RayCastSphereIntersect(const rayStart, rayVector: TVector;
  5366. const sphereCenter: TVector; const SphereRadius: Single;
  5367. var i1, i2: TVector): Integer;
  5368. var
  5369. proj, d2: Single;
  5370. id2: Integer;
  5371. projPoint: TVector;
  5372. begin
  5373. proj := PointProject(sphereCenter, rayStart, rayVector);
  5374. VectorCombine(rayStart, rayVector, proj, projPoint);
  5375. d2 := SphereRadius * SphereRadius - VectorDistance2(sphereCenter, projPoint);
  5376. id2 := PInteger(@d2)^;
  5377. if id2 >= 0 then
  5378. begin
  5379. if id2 = 0 then
  5380. begin
  5381. if PInteger(@proj)^ > 0 then
  5382. begin
  5383. VectorCombine(rayStart, rayVector, proj, i1);
  5384. result := 1;
  5385. Exit;
  5386. end;
  5387. end
  5388. else if id2 > 0 then
  5389. begin
  5390. d2 := Sqrt(d2);
  5391. if proj >= d2 then
  5392. begin
  5393. VectorCombine(rayStart, rayVector, proj - d2, i1);
  5394. VectorCombine(rayStart, rayVector, proj + d2, i2);
  5395. result := 2;
  5396. Exit;
  5397. end
  5398. else if proj + d2 >= 0 then
  5399. begin
  5400. VectorCombine(rayStart, rayVector, proj + d2, i1);
  5401. result := 1;
  5402. Exit;
  5403. end;
  5404. end;
  5405. end;
  5406. result := 0;
  5407. end;
  5408. function RayCastBoxIntersect(const rayStart, rayVector, aMinExtent,
  5409. aMaxExtent: TAffineVector; intersectPoint: PAffineVector = nil): Boolean;
  5410. var
  5411. i, planeInd: Integer;
  5412. ResAFV, MaxDist, plane: TAffineVector;
  5413. isMiddle: array [0 .. 2] of Boolean;
  5414. begin
  5415. // Find plane.
  5416. result := True;
  5417. for i := 0 to 2 do
  5418. if rayStart.V[i] < aMinExtent.V[i] then
  5419. begin
  5420. plane.V[i] := aMinExtent.V[i];
  5421. isMiddle[i] := False;
  5422. result := False;
  5423. end
  5424. else if rayStart.V[i] > aMaxExtent.V[i] then
  5425. begin
  5426. plane.V[i] := aMaxExtent.V[i];
  5427. isMiddle[i] := False;
  5428. result := False;
  5429. end
  5430. else
  5431. begin
  5432. isMiddle[i] := True;
  5433. end;
  5434. if result then
  5435. begin
  5436. // rayStart inside box.
  5437. if intersectPoint <> nil then
  5438. intersectPoint^ := rayStart;
  5439. end
  5440. else
  5441. begin
  5442. // Distance to plane.
  5443. planeInd := 0;
  5444. for i := 0 to 2 do
  5445. if isMiddle[i] or (rayVector.V[i] = 0) then
  5446. MaxDist.V[i] := -1
  5447. else
  5448. begin
  5449. MaxDist.V[i] := (plane.V[i] - rayStart.V[i]) / rayVector.V[i];
  5450. if MaxDist.V[i] > 0 then
  5451. begin
  5452. if MaxDist.V[planeInd] < MaxDist.V[i] then
  5453. planeInd := i;
  5454. result := True;
  5455. end;
  5456. end;
  5457. // Inside box ?
  5458. if result then
  5459. begin
  5460. for i := 0 to 2 do
  5461. if planeInd = i then
  5462. ResAFV.V[i] := plane.V[i]
  5463. else
  5464. begin
  5465. ResAFV.V[i] := rayStart.V[i] + MaxDist.V[planeInd] * rayVector.V[i];
  5466. result := (ResAFV.V[i] >= aMinExtent.V[i]) and
  5467. (ResAFV.V[i] <= aMaxExtent.V[i]);
  5468. if not result then
  5469. Exit;
  5470. end;
  5471. if intersectPoint <> nil then
  5472. intersectPoint^ := ResAFV;
  5473. end;
  5474. end;
  5475. end;
  5476. function SphereVisibleRadius(distance, radius: Single): Single;
  5477. var
  5478. d2, r2, ir, tr: Single;
  5479. begin
  5480. d2 := distance * distance;
  5481. r2 := radius * radius;
  5482. ir := Sqrt(d2 - r2);
  5483. tr := (d2 + r2 - Sqr(ir)) / (2 * ir);
  5484. result := Sqrt(r2 + Sqr(tr));
  5485. end;
  5486. function IntersectLinePlane(const point, direction: TVector;
  5487. const plane: THmgPlane; intersectPoint: PVector = nil): Integer;
  5488. var
  5489. a, b: Extended;
  5490. T: Single;
  5491. begin
  5492. a := VectorDotProduct(plane, direction);
  5493. // direction projected to plane normal
  5494. b := PlaneEvaluatePoint(plane, point); // distance to plane
  5495. if a = 0 then
  5496. begin // direction is parallel to plane
  5497. if b = 0 then
  5498. result := -1 // line is inside plane
  5499. else
  5500. result := 0; // line is outside plane
  5501. end
  5502. else
  5503. begin
  5504. if Assigned(intersectPoint) then
  5505. begin
  5506. T := -b / a; // parameter of intersection
  5507. intersectPoint^ := point;
  5508. // calculate intersection = p + t*d
  5509. CombineVector(intersectPoint^, direction, T);
  5510. end;
  5511. result := 1;
  5512. end;
  5513. end;
  5514. function IntersectTriangleBox(const p1, p2, p3, aMinExtent,
  5515. aMaxExtent: TAffineVector): Boolean;
  5516. var
  5517. RayDir, iPoint: TAffineVector;
  5518. BoxDiagPt, BoxDiagPt2, BoxDiagDir, iPnt: TVector;
  5519. begin
  5520. // Triangle edge (p2, p1) - Box intersection
  5521. VectorSubtract(p2, p1, RayDir);
  5522. result := RayCastBoxIntersect(p1, RayDir, aMinExtent, aMaxExtent, @iPoint);
  5523. if result then
  5524. result := VectorNorm(VectorSubtract(p1, iPoint)) <
  5525. VectorNorm(VectorSubtract(p1, p2));
  5526. if result then
  5527. Exit;
  5528. // Triangle edge (p3, p1) - Box intersection
  5529. VectorSubtract(p3, p1, RayDir);
  5530. result := RayCastBoxIntersect(p1, RayDir, aMinExtent, aMaxExtent, @iPoint);
  5531. if result then
  5532. result := VectorNorm(VectorSubtract(p1, iPoint)) <
  5533. VectorNorm(VectorSubtract(p1, p3));
  5534. if result then
  5535. Exit;
  5536. // Triangle edge (p2, p3) - Box intersection
  5537. VectorSubtract(p2, p3, RayDir);
  5538. result := RayCastBoxIntersect(p3, RayDir, aMinExtent, aMaxExtent, @iPoint);
  5539. if result then
  5540. result := VectorNorm(VectorSubtract(p3, iPoint)) <
  5541. VectorNorm(VectorSubtract(p3, p2));
  5542. if result then
  5543. Exit;
  5544. // Triangle - Box diagonal 1 intersection
  5545. BoxDiagPt := VectorMake(aMinExtent);
  5546. VectorSubtract(aMaxExtent, aMinExtent, BoxDiagDir);
  5547. result := RayCastTriangleIntersect(BoxDiagPt, BoxDiagDir, p1, p2, p3, @iPnt);
  5548. if result then
  5549. result := VectorNorm(VectorSubtract(BoxDiagPt, iPnt)) <
  5550. VectorNorm(VectorSubtract(aMaxExtent, aMinExtent));
  5551. if result then
  5552. Exit;
  5553. // Triangle - Box diagonal 2 intersection
  5554. BoxDiagPt := VectorMake(aMinExtent.X, aMinExtent.Y, aMaxExtent.Z);
  5555. BoxDiagPt2 := VectorMake(aMaxExtent.X, aMaxExtent.Y, aMinExtent.Z);
  5556. VectorSubtract(BoxDiagPt2, BoxDiagPt, BoxDiagDir);
  5557. result := RayCastTriangleIntersect(BoxDiagPt, BoxDiagDir, p1, p2, p3, @iPnt);
  5558. if result then
  5559. result := VectorNorm(VectorSubtract(BoxDiagPt, iPnt)) <
  5560. VectorNorm(VectorSubtract(BoxDiagPt, BoxDiagPt2));
  5561. if result then
  5562. Exit;
  5563. // Triangle - Box diagonal 3 intersection
  5564. BoxDiagPt := VectorMake(aMinExtent.X, aMaxExtent.Y, aMinExtent.Z);
  5565. BoxDiagPt2 := VectorMake(aMaxExtent.X, aMinExtent.Y, aMaxExtent.Z);
  5566. VectorSubtract(BoxDiagPt, BoxDiagPt, BoxDiagDir);
  5567. result := RayCastTriangleIntersect(BoxDiagPt, BoxDiagDir, p1, p2, p3, @iPnt);
  5568. if result then
  5569. result := VectorLength(VectorSubtract(BoxDiagPt, iPnt)) <
  5570. VectorLength(VectorSubtract(BoxDiagPt, BoxDiagPt));
  5571. if result then
  5572. Exit;
  5573. // Triangle - Box diagonal 4 intersection
  5574. BoxDiagPt := VectorMake(aMaxExtent.X, aMinExtent.Y, aMinExtent.Z);
  5575. BoxDiagPt2 := VectorMake(aMinExtent.X, aMaxExtent.Y, aMaxExtent.Z);
  5576. VectorSubtract(BoxDiagPt, BoxDiagPt, BoxDiagDir);
  5577. result := RayCastTriangleIntersect(BoxDiagPt, BoxDiagDir, p1, p2, p3, @iPnt);
  5578. if result then
  5579. result := VectorLength(VectorSubtract(BoxDiagPt, iPnt)) <
  5580. VectorLength(VectorSubtract(BoxDiagPt, BoxDiagPt));
  5581. end;
  5582. function IntersectSphereBox(const SpherePos: TVector;
  5583. const SphereRadius: Single; const BoxMatrix: TMatrix;
  5584. // Up Direction and Right must be normalized!
  5585. // Use CubDepht, CubeHeight and CubeWidth
  5586. // for scale TGLCube.
  5587. const BoxScale: TAffineVector; intersectPoint: PAffineVector = nil;
  5588. normal: PAffineVector = nil; depth: PSingle = nil): Boolean;
  5589. function dDOTByColumn(const V: TAffineVector; const M: TMatrix;
  5590. const aColumn: Integer): Single;
  5591. begin
  5592. result := V.X * M.X.V[aColumn] + V.Y * M.Y.V[aColumn] + V.Z *
  5593. M.Z.V[aColumn];
  5594. end;
  5595. function dDotByRow(const V: TAffineVector; const M: TMatrix;
  5596. const aRow: Integer): Single;
  5597. begin
  5598. // Equal with: Result := VectorDotProduct(v, AffineVectorMake(m[aRow]));
  5599. result := V.X * M.V[aRow].X + V.Y * M.V[aRow].Y + V.Z *
  5600. M.V[aRow].Z;
  5601. end;
  5602. function dDotMatrByColumn(const V: TAffineVector; const M: TMatrix)
  5603. : TAffineVector;
  5604. begin
  5605. result.X := dDOTByColumn(V, M, 0);
  5606. result.Y := dDOTByColumn(V, M, 1);
  5607. result.Z := dDOTByColumn(V, M, 2);
  5608. end;
  5609. function dDotMatrByRow(const V: TAffineVector; const M: TMatrix)
  5610. : TAffineVector;
  5611. begin
  5612. result.X := dDotByRow(V, M, 0);
  5613. result.Y := dDotByRow(V, M, 1);
  5614. result.Z := dDotByRow(V, M, 2);
  5615. end;
  5616. var
  5617. tmp, l, T, p, Q, r: TAffineVector;
  5618. FaceDistance, MinDistance, Depth1: Single;
  5619. mini, i: Integer;
  5620. isSphereCenterInsideBox: Boolean;
  5621. begin
  5622. // this is easy. get the sphere center `p' relative to the box, and then clip
  5623. // that to the boundary of the box (call that point `q'). if q is on the
  5624. // boundary of the box and |p-q| is <= sphere radius, they touch.
  5625. // if q is inside the box, the sphere is inside the box, so set a contact
  5626. // normal to push the sphere to the closest box face.
  5627. p.X := SpherePos.X - BoxMatrix.W.X;
  5628. p.Y := SpherePos.Y - BoxMatrix.W.Y;
  5629. p.Z := SpherePos.Z - BoxMatrix.W.Z;
  5630. isSphereCenterInsideBox := True;
  5631. for i := 0 to 2 do
  5632. begin
  5633. l.V[i] := 0.5 * BoxScale.V[i];
  5634. T.V[i] := dDotByRow(p, BoxMatrix, i);
  5635. if T.V[i] < -l.V[i] then
  5636. begin
  5637. T.V[i] := -l.V[i];
  5638. isSphereCenterInsideBox := False;
  5639. end
  5640. else if T.V[i] > l.V[i] then
  5641. begin
  5642. T.V[i] := l.V[i];
  5643. isSphereCenterInsideBox := False;
  5644. end;
  5645. end;
  5646. if isSphereCenterInsideBox then
  5647. begin
  5648. MinDistance := l.X - Abs(T.X);
  5649. mini := 0;
  5650. for i := 1 to 2 do
  5651. begin
  5652. FaceDistance := l.V[i] - Abs(T.V[i]);
  5653. if FaceDistance < MinDistance then
  5654. begin
  5655. MinDistance := FaceDistance;
  5656. mini := i;
  5657. end;
  5658. end;
  5659. if intersectPoint <> nil then
  5660. intersectPoint^ := AffineVectorMake(SpherePos);
  5661. if normal <> nil then
  5662. begin
  5663. tmp := NullVector;
  5664. if T.V[mini] > 0 then
  5665. tmp.V[mini] := 1
  5666. else
  5667. tmp.V[mini] := -1;
  5668. normal^ := dDotMatrByRow(tmp, BoxMatrix);
  5669. end;
  5670. if depth <> nil then
  5671. depth^ := MinDistance + SphereRadius;
  5672. result := True;
  5673. end
  5674. else
  5675. begin
  5676. Q := dDotMatrByColumn(T, BoxMatrix);
  5677. r := VectorSubtract(p, Q);
  5678. Depth1 := SphereRadius - VectorLength(r);
  5679. if Depth1 < 0 then
  5680. begin
  5681. result := False;
  5682. end
  5683. else
  5684. begin
  5685. if intersectPoint <> nil then
  5686. intersectPoint^ := VectorAdd(Q, AffineVectorMake(BoxMatrix.W));
  5687. if normal <> nil then
  5688. begin
  5689. normal^ := VectorNormalize(r);
  5690. end;
  5691. if depth <> nil then
  5692. depth^ := Depth1;
  5693. result := True;
  5694. end;
  5695. end;
  5696. end;
  5697. function ExtractFrustumFromModelViewProjection(const modelViewProj: TMatrix)
  5698. : TFrustum;
  5699. begin
  5700. with result do
  5701. begin
  5702. // extract left plane
  5703. pLeft.X := modelViewProj.X.W + modelViewProj.X.X;
  5704. pLeft.Y := modelViewProj.Y.W + modelViewProj.Y.X;
  5705. pLeft.Z := modelViewProj.Z.W + modelViewProj.Z.X;
  5706. pLeft.W := modelViewProj.W.W + modelViewProj.W.X;
  5707. NormalizePlane(pLeft);
  5708. // extract top plane
  5709. pTop.X := modelViewProj.X.W - modelViewProj.X.Y;
  5710. pTop.Y := modelViewProj.Y.W - modelViewProj.Y.Y;
  5711. pTop.Z := modelViewProj.Z.W - modelViewProj.Z.Y;
  5712. pTop.W := modelViewProj.W.W - modelViewProj.W.Y;
  5713. NormalizePlane(pTop);
  5714. // extract right plane
  5715. pRight.X := modelViewProj.X.W - modelViewProj.X.X;
  5716. pRight.Y := modelViewProj.Y.W - modelViewProj.Y.X;
  5717. pRight.Z := modelViewProj.Z.W - modelViewProj.Z.X;
  5718. pRight.W := modelViewProj.W.W - modelViewProj.W.X;
  5719. NormalizePlane(pRight);
  5720. // extract bottom plane
  5721. pBottom.X := modelViewProj.X.W + modelViewProj.X.Y;
  5722. pBottom.Y := modelViewProj.Y.W + modelViewProj.Y.Y;
  5723. pBottom.Z := modelViewProj.Z.W + modelViewProj.Z.Y;
  5724. pBottom.W := modelViewProj.W.W + modelViewProj.W.Y;
  5725. NormalizePlane(pBottom);
  5726. // extract far plane
  5727. pFar.X := modelViewProj.X.W - modelViewProj.X.Z;
  5728. pFar.Y := modelViewProj.Y.W - modelViewProj.Y.Z;
  5729. pFar.Z := modelViewProj.Z.W - modelViewProj.Z.Z;
  5730. pFar.W := modelViewProj.W.W - modelViewProj.W.Z;
  5731. NormalizePlane(pFar);
  5732. // extract near plane
  5733. pNear.X := modelViewProj.X.W + modelViewProj.X.Z;
  5734. pNear.Y := modelViewProj.Y.W + modelViewProj.Y.Z;
  5735. pNear.Z := modelViewProj.Z.W + modelViewProj.Z.Z;
  5736. pNear.W := modelViewProj.W.W + modelViewProj.W.Z;
  5737. NormalizePlane(pNear);
  5738. end;
  5739. end;
  5740. function IsVolumeClipped(const objPos: TAffineVector; const objRadius: Single;
  5741. const Frustum: TFrustum): Boolean;
  5742. var
  5743. negRadius: Single;
  5744. begin
  5745. negRadius := -objRadius;
  5746. result := (PlaneEvaluatePoint(Frustum.pLeft, objPos) < negRadius) or
  5747. (PlaneEvaluatePoint(Frustum.pTop, objPos) < negRadius) or
  5748. (PlaneEvaluatePoint(Frustum.pRight, objPos) < negRadius) or
  5749. (PlaneEvaluatePoint(Frustum.pBottom, objPos) < negRadius) or
  5750. (PlaneEvaluatePoint(Frustum.pNear, objPos) < negRadius) or
  5751. (PlaneEvaluatePoint(Frustum.pFar, objPos) < negRadius);
  5752. end;
  5753. function IsVolumeClipped(const objPos: TVector; const objRadius: Single;
  5754. const Frustum: TFrustum): Boolean;
  5755. begin
  5756. result := IsVolumeClipped(PAffineVector(@objPos)^, objRadius, Frustum);
  5757. end;
  5758. function IsVolumeClipped(const min, max: TAffineVector;
  5759. const Frustum: TFrustum): Boolean;
  5760. begin
  5761. // change box to sphere
  5762. result := IsVolumeClipped(VectorScale(VectorAdd(min, max), 0.5),
  5763. VectorDistance(min, max) * 0.5, Frustum);
  5764. end;
  5765. function MakeParallelProjectionMatrix(const plane: THmgPlane;
  5766. const dir: TVector): TMatrix;
  5767. // Based on material from a course by William D. Shoaff (www.cs.fit.edu)
  5768. var
  5769. dot, invDot: Single;
  5770. begin
  5771. dot := plane.X * dir.X + plane.Y * dir.Y + plane.Z * dir.Z;
  5772. if Abs(dot) < 1E-5 then
  5773. begin
  5774. result := IdentityHmgMatrix;
  5775. Exit;
  5776. end;
  5777. invDot := 1 / dot;
  5778. result.X.X := (plane.Y * dir.Y + plane.Z * dir.Z) * invDot;
  5779. result.Y.X := (-plane.Y * dir.X) * invDot;
  5780. result.Z.X := (-plane.Z * dir.X) * invDot;
  5781. result.W.X := (-plane.W * dir.X) * invDot;
  5782. result.X.Y := (-plane.X * dir.Y) * invDot;
  5783. result.Y.Y := (plane.X * dir.X + plane.Z * dir.Z) * invDot;
  5784. result.Z.Y := (-plane.Z * dir.Y) * invDot;
  5785. result.W.Y := (-plane.W * dir.Y) * invDot;
  5786. result.X.Z := (-plane.X * dir.Z) * invDot;
  5787. result.Y.Z := (-plane.Y * dir.Z) * invDot;
  5788. result.Z.Z := (plane.X * dir.X + plane.Y * dir.Y) * invDot;
  5789. result.W.Z := (-plane.W * dir.Z) * invDot;
  5790. result.X.W := 0;
  5791. result.Y.W := 0;
  5792. result.Z.W := 0;
  5793. result.W.W := 1;
  5794. end;
  5795. function MakeShadowMatrix(const planePoint, planeNormal,
  5796. lightPos: TVector): TMatrix;
  5797. var
  5798. planeNormal3, dot: Single;
  5799. begin
  5800. // Find the last coefficient by back substitutions
  5801. planeNormal3 := -(planeNormal.X * planePoint.X + planeNormal.Y *
  5802. planePoint.Y + planeNormal.Z * planePoint.Z);
  5803. // Dot product of plane and light position
  5804. dot := planeNormal.X * lightPos.X + planeNormal.Y * lightPos.Y +
  5805. planeNormal.Z * lightPos.Z + planeNormal3 * lightPos.W;
  5806. // Now do the projection
  5807. // First column
  5808. result.X.X := dot - lightPos.X * planeNormal.X;
  5809. result.Y.X := -lightPos.X * planeNormal.Y;
  5810. result.Z.X := -lightPos.X * planeNormal.Z;
  5811. result.W.X := -lightPos.X * planeNormal3;
  5812. // Second column
  5813. result.X.Y := -lightPos.Y * planeNormal.X;
  5814. result.Y.Y := dot - lightPos.Y * planeNormal.Y;
  5815. result.Z.Y := -lightPos.Y * planeNormal.Z;
  5816. result.W.Y := -lightPos.Y * planeNormal3;
  5817. // Third Column
  5818. result.X.Z := -lightPos.Z * planeNormal.X;
  5819. result.Y.Z := -lightPos.Z * planeNormal.Y;
  5820. result.Z.Z := dot - lightPos.Z * planeNormal.Z;
  5821. result.W.Z := -lightPos.Z * planeNormal3;
  5822. // Fourth Column
  5823. result.X.W := -lightPos.W * planeNormal.X;
  5824. result.Y.W := -lightPos.W * planeNormal.Y;
  5825. result.Z.W := -lightPos.W * planeNormal.Z;
  5826. result.W.W := dot - lightPos.W * planeNormal3;
  5827. end;
  5828. function MakeReflectionMatrix(const planePoint, planeNormal
  5829. : TAffineVector): TMatrix;
  5830. var
  5831. pv2: Single;
  5832. begin
  5833. // Precalcs
  5834. pv2 := 2 * VectorDotProduct(planePoint, planeNormal);
  5835. // 1st column
  5836. result.X.X := 1 - 2 * Sqr(planeNormal.X);
  5837. result.X.Y := -2 * planeNormal.X * planeNormal.Y;
  5838. result.X.Z := -2 * planeNormal.X * planeNormal.Z;
  5839. result.X.W := 0;
  5840. // 2nd column
  5841. result.Y.X := -2 * planeNormal.Y * planeNormal.X;
  5842. result.Y.Y := 1 - 2 * Sqr(planeNormal.Y);
  5843. result.Y.Z := -2 * planeNormal.Y * planeNormal.Z;
  5844. result.Y.W := 0;
  5845. // 3rd column
  5846. result.Z.X := -2 * planeNormal.Z * planeNormal.X;
  5847. result.Z.Y := -2 * planeNormal.Z * planeNormal.Y;
  5848. result.Z.Z := 1 - 2 * Sqr(planeNormal.Z);
  5849. result.Z.W := 0;
  5850. // 4th column
  5851. result.W.X := pv2 * planeNormal.X;
  5852. result.W.Y := pv2 * planeNormal.Y;
  5853. result.W.Z := pv2 * planeNormal.Z;
  5854. result.W.W := 1;
  5855. end;
  5856. function PackRotationMatrix(const mat: TMatrix): TPackedRotationMatrix;
  5857. var
  5858. Q: TQuaternion;
  5859. const
  5860. cFact: Single = 32767;
  5861. begin
  5862. Q := QuaternionFromMatrix(mat);
  5863. NormalizeQuaternion(Q);
  5864. {$HINTS OFF}
  5865. if Q.RealPart < 0 then
  5866. begin
  5867. result[0] := Round(-Q.ImagPart.X * cFact);
  5868. result[1] := Round(-Q.ImagPart.Y * cFact);
  5869. result[2] := Round(-Q.ImagPart.Z * cFact);
  5870. end
  5871. else
  5872. begin
  5873. result[0] := Round(Q.ImagPart.X * cFact);
  5874. result[1] := Round(Q.ImagPart.Y * cFact);
  5875. result[2] := Round(Q.ImagPart.Z * cFact);
  5876. end;
  5877. {$HINTS ON}
  5878. end;
  5879. function UnPackRotationMatrix(const packedMatrix
  5880. : TPackedRotationMatrix): TMatrix;
  5881. var
  5882. Q: TQuaternion;
  5883. const
  5884. cFact: Single = 1 / 32767;
  5885. begin
  5886. Q.ImagPart.X := packedMatrix[0] * cFact;
  5887. Q.ImagPart.Y := packedMatrix[1] * cFact;
  5888. Q.ImagPart.Z := packedMatrix[2] * cFact;
  5889. Q.RealPart := 1 - VectorNorm(Q.ImagPart);
  5890. if Q.RealPart < 0 then
  5891. Q.RealPart := 0
  5892. else
  5893. Q.RealPart := Sqrt(Q.RealPart);
  5894. result := QuaternionToMatrix(Q);
  5895. end;
  5896. function BarycentricCoordinates(const V1, V2, V3, p: TAffineVector;
  5897. var u, V: Single): Boolean;
  5898. var
  5899. a1, a2: Integer;
  5900. n, e1, e2, pt: TAffineVector;
  5901. begin
  5902. // calculate edges
  5903. VectorSubtract(V1, V3, e1);
  5904. VectorSubtract(V2, V3, e2);
  5905. // calculate p relative to v3
  5906. VectorSubtract(p, V3, pt);
  5907. // find the dominant axis
  5908. n := VectorCrossProduct(e1, e2);
  5909. AbsVector(n);
  5910. a1 := 0;
  5911. if n.Y > n.V[a1] then
  5912. a1 := 1;
  5913. if n.Z > n.V[a1] then
  5914. a1 := 2;
  5915. // use dominant axis for projection
  5916. case a1 of
  5917. 0:
  5918. begin
  5919. a1 := 1;
  5920. a2 := 2;
  5921. end;
  5922. 1:
  5923. begin
  5924. a1 := 0;
  5925. a2 := 2;
  5926. end;
  5927. else // 2:
  5928. a1 := 0;
  5929. a2 := 1;
  5930. end;
  5931. // solve for u and v
  5932. u := (pt.V[a2] * e2.V[a1] - pt.V[a1] * e2.V[a2]) /
  5933. (e1.V[a2] * e2.V[a1] - e1.V[a1] * e2.V[a2]);
  5934. V := (pt.V[a2] * e1.V[a1] - pt.V[a1] * e1.V[a2]) /
  5935. (e2.V[a2] * e1.V[a1] - e2.V[a1] * e1.V[a2]);
  5936. result := (u >= 0) and (V >= 0) and (u + V <= 1);
  5937. end;
  5938. { ***************************************************************************** }
  5939. function Vector2fMake(const X, Y: Single): TVector2f;
  5940. begin
  5941. result.X := X;
  5942. result.Y := Y;
  5943. end;
  5944. function Vector2iMake(const X, Y: Longint): TVector2i;
  5945. begin
  5946. result.X := X;
  5947. result.Y := Y;
  5948. end;
  5949. function Vector2sMake(const X, Y: SmallInt): TVector2s;
  5950. begin
  5951. result.X := X;
  5952. result.Y := Y;
  5953. end;
  5954. function Vector2dMake(const X, Y: Double): TVector2d;
  5955. begin
  5956. result.X := X;
  5957. result.Y := Y;
  5958. end;
  5959. function Vector2bMake(const X, Y: Byte): TVector2b;
  5960. begin
  5961. result.X := X;
  5962. result.Y := Y;
  5963. end;
  5964. // **************
  5965. function Vector2fMake(const Vector: TVector3f): TVector2f;
  5966. begin
  5967. result.X := Vector.X;
  5968. result.Y := Vector.Y;
  5969. end;
  5970. function Vector2iMake(const Vector: TVector3i): TVector2i;
  5971. begin
  5972. result.X := Vector.X;
  5973. result.Y := Vector.Y;
  5974. end;
  5975. function Vector2sMake(const Vector: TVector3s): TVector2s;
  5976. begin
  5977. result.X := Vector.X;
  5978. result.Y := Vector.Y;
  5979. end;
  5980. function Vector2dMake(const Vector: TVector3d): TVector2d;
  5981. begin
  5982. result.X := Vector.X;
  5983. result.Y := Vector.Y;
  5984. end;
  5985. function Vector2bMake(const Vector: TVector3b): TVector2b;
  5986. begin
  5987. result.X := Vector.X;
  5988. result.Y := Vector.Y;
  5989. end;
  5990. // **********
  5991. function Vector2fMake(const Vector: TVector4f): TVector2f;
  5992. begin
  5993. result.X := Vector.X;
  5994. result.Y := Vector.Y;
  5995. end;
  5996. function Vector2iMake(const Vector: TVector4i): TVector2i;
  5997. begin
  5998. result.X := Vector.X;
  5999. result.Y := Vector.Y;
  6000. end;
  6001. function Vector2sMake(const Vector: TVector4s): TVector2s;
  6002. begin
  6003. result.X := Vector.X;
  6004. result.Y := Vector.Y;
  6005. end;
  6006. function Vector2dMake(const Vector: TVector4d): TVector2d;
  6007. begin
  6008. result.X := Vector.X;
  6009. result.Y := Vector.Y;
  6010. end;
  6011. function Vector2bMake(const Vector: TVector4b): TVector2b;
  6012. begin
  6013. result.X := Vector.X;
  6014. result.Y := Vector.Y;
  6015. end;
  6016. { ***************************************************************************** }
  6017. function Vector3fMake(const X, Y, Z: Single): TVector3f;
  6018. begin
  6019. result.X := X;
  6020. result.Y := Y;
  6021. result.Z := Z;
  6022. end;
  6023. function Vector3iMake(const X, Y, Z: Longint): TVector3i;
  6024. begin
  6025. result.X := X;
  6026. result.Y := Y;
  6027. result.Z := Z;
  6028. end;
  6029. function Vector3sMake(const X, Y, Z: SmallInt): TVector3s;
  6030. begin
  6031. result.X := X;
  6032. result.Y := Y;
  6033. result.Z := Z;
  6034. end;
  6035. function Vector3dMake(const X, Y, Z: Double): TVector3d;
  6036. begin
  6037. result.X := X;
  6038. result.Y := Y;
  6039. result.Z := Z;
  6040. end;
  6041. function Vector3bMake(const X, Y, Z: Byte): TVector3b;
  6042. begin
  6043. result.X := X;
  6044. result.Y := Y;
  6045. result.Z := Z;
  6046. end;
  6047. function Vector3fMake(const Vector: TVector2f; const Z: Single): TVector3f;
  6048. begin
  6049. result.X := Vector.X;
  6050. result.Y := Vector.Y;
  6051. result.Z := Z;
  6052. end;
  6053. function Vector3iMake(const Vector: TVector2i; const Z: Longint): TVector3i;
  6054. begin
  6055. result.X := Vector.X;
  6056. result.Y := Vector.Y;
  6057. result.Z := Z;
  6058. end;
  6059. function Vector3sMake(const Vector: TVector2s; const Z: SmallInt): TVector3s;
  6060. begin
  6061. result.X := Vector.X;
  6062. result.Y := Vector.Y;
  6063. result.Z := Z;
  6064. end;
  6065. function Vector3dMake(const Vector: TVector2d; const Z: Double): TVector3d;
  6066. begin
  6067. result.X := Vector.X;
  6068. result.Y := Vector.Y;
  6069. result.Z := Z;
  6070. end;
  6071. function Vector3bMake(const Vector: TVector2b; const Z: Byte): TVector3b;
  6072. begin
  6073. result.X := Vector.X;
  6074. result.Y := Vector.Y;
  6075. result.Z := Z;
  6076. end;
  6077. function Vector3fMake(const Vector: TVector4f): TVector3f;
  6078. begin
  6079. result.X := Vector.X;
  6080. result.Y := Vector.Y;
  6081. result.Z := Vector.Z;
  6082. end;
  6083. function Vector3iMake(const Vector: TVector4i): TVector3i;
  6084. begin
  6085. result.X := Vector.X;
  6086. result.Y := Vector.Y;
  6087. result.Z := Vector.Z;
  6088. end;
  6089. function Vector3sMake(const Vector: TVector4s): TVector3s;
  6090. begin
  6091. result.X := Vector.X;
  6092. result.Y := Vector.Y;
  6093. result.Z := Vector.Z;
  6094. end;
  6095. function Vector3dMake(const Vector: TVector4d): TVector3d;
  6096. begin
  6097. result.X := Vector.X;
  6098. result.Y := Vector.Y;
  6099. result.Z := Vector.Z;
  6100. end;
  6101. function Vector3bMake(const Vector: TVector4b): TVector3b;
  6102. begin
  6103. result.X := Vector.X;
  6104. result.Y := Vector.Y;
  6105. result.Z := Vector.Z;
  6106. end;
  6107. { ***************************************************************************** }
  6108. function Vector4fMake(const X, Y, Z, W: Single): TVector4f;
  6109. begin
  6110. result.X := X;
  6111. result.Y := Y;
  6112. result.Z := Z;
  6113. result.W := W;
  6114. end;
  6115. function Vector4iMake(const X, Y, Z, W: Longint): TVector4i;
  6116. begin
  6117. result.X := X;
  6118. result.Y := Y;
  6119. result.Z := Z;
  6120. result.W := W;
  6121. end;
  6122. function Vector4sMake(const X, Y, Z, W: SmallInt): TVector4s;
  6123. begin
  6124. result.X := X;
  6125. result.Y := Y;
  6126. result.Z := Z;
  6127. result.W := W;
  6128. end;
  6129. function Vector4dMake(const X, Y, Z, W: Double): TVector4d;
  6130. begin
  6131. result.X := X;
  6132. result.Y := Y;
  6133. result.Z := Z;
  6134. result.W := W;
  6135. end;
  6136. function Vector4bMake(const X, Y, Z, W: Byte): TVector4b;
  6137. begin
  6138. result.X := X;
  6139. result.Y := Y;
  6140. result.Z := Z;
  6141. result.W := W;
  6142. end;
  6143. function Vector4fMake(const Vector: TVector3f; const W: Single): TVector4f;
  6144. begin
  6145. result.X := Vector.X;
  6146. result.Y := Vector.Y;
  6147. result.Z := Vector.Z;
  6148. result.W := W;
  6149. end;
  6150. function Vector4iMake(const Vector: TVector3i; const W: Longint): TVector4i;
  6151. begin
  6152. result.X := Vector.X;
  6153. result.Y := Vector.Y;
  6154. result.Z := Vector.Z;
  6155. result.W := W;
  6156. end;
  6157. function Vector4sMake(const Vector: TVector3s; const W: SmallInt): TVector4s;
  6158. begin
  6159. result.X := Vector.X;
  6160. result.Y := Vector.Y;
  6161. result.Z := Vector.Z;
  6162. result.W := W;
  6163. end;
  6164. function Vector4dMake(const Vector: TVector3d; const W: Double): TVector4d;
  6165. begin
  6166. result.X := Vector.X;
  6167. result.Y := Vector.Y;
  6168. result.Z := Vector.Z;
  6169. result.W := W;
  6170. end;
  6171. function Vector4bMake(const Vector: TVector3b; const W: Byte): TVector4b;
  6172. begin
  6173. result.X := Vector.X;
  6174. result.Y := Vector.Y;
  6175. result.Z := Vector.Z;
  6176. result.W := W;
  6177. end;
  6178. function Vector4fMake(const Vector: TVector2f; const Z: Single; const W: Single)
  6179. : TVector4f;
  6180. begin
  6181. result.X := Vector.X;
  6182. result.Y := Vector.Y;
  6183. result.Z := Z;
  6184. result.W := W;
  6185. end;
  6186. function Vector4iMake(const Vector: TVector2i; const Z: Longint;
  6187. const W: Longint): TVector4i;
  6188. begin
  6189. result.X := Vector.X;
  6190. result.Y := Vector.Y;
  6191. result.Z := Z;
  6192. result.W := W;
  6193. end;
  6194. function Vector4sMake(const Vector: TVector2s; const Z: SmallInt;
  6195. const W: SmallInt): TVector4s;
  6196. begin
  6197. result.X := Vector.X;
  6198. result.Y := Vector.Y;
  6199. result.Z := Z;
  6200. result.W := W;
  6201. end;
  6202. function Vector4dMake(const Vector: TVector2d; const Z: Double; const W: Double)
  6203. : TVector4d;
  6204. begin
  6205. result.X := Vector.X;
  6206. result.Y := Vector.Y;
  6207. result.Z := Z;
  6208. result.W := W;
  6209. end;
  6210. function Vector4bMake(const Vector: TVector2b; const Z: Byte; const W: Byte)
  6211. : TVector4b;
  6212. begin
  6213. result.X := Vector.X;
  6214. result.Y := Vector.Y;
  6215. result.Z := Z;
  6216. result.W := W;
  6217. end;
  6218. { ***************************************************************************** }
  6219. function VectorEquals(const Vector1, Vector2: TVector2f): Boolean;
  6220. begin
  6221. result := (Vector1.X = Vector2.X) and (Vector1.Y = Vector2.Y);
  6222. end;
  6223. function VectorEquals(const Vector1, Vector2: TVector2i): Boolean;
  6224. begin
  6225. result := (Vector1.X = Vector2.X) and (Vector1.Y = Vector2.Y);
  6226. end;
  6227. function VectorEquals(const V1, V2: TVector2d): Boolean;
  6228. begin
  6229. result := (V1.X = V2.X) and (V1.Y = V2.Y);
  6230. end;
  6231. function VectorEquals(const V1, V2: TVector2s): Boolean;
  6232. begin
  6233. result := (V1.X = V2.X) and (V1.Y = V2.Y);
  6234. end;
  6235. function VectorEquals(const V1, V2: TVector2b): Boolean;
  6236. begin
  6237. result := (V1.X = V2.X) and (V1.Y = V2.Y);
  6238. end;
  6239. { ***************************************************************************** }
  6240. function VectorEquals(const V1, V2: TVector3i): Boolean;
  6241. begin
  6242. result := (V1.X = V2.X) and (V1.Y = V2.Y) and (V1.Z = V2.Z);
  6243. end;
  6244. function VectorEquals(const V1, V2: TVector3d): Boolean;
  6245. begin
  6246. result := (V1.X = V2.X) and (V1.Y = V2.Y) and (V1.Z = V2.Z);
  6247. end;
  6248. function VectorEquals(const V1, V2: TVector3s): Boolean;
  6249. begin
  6250. result := (V1.X = V2.X) and (V1.Y = V2.Y) and (V1.Z = V2.Z);
  6251. end;
  6252. function VectorEquals(const V1, V2: TVector3b): Boolean;
  6253. begin
  6254. result := (V1.X = V2.X) and (V1.Y = V2.Y) and (V1.Z = V2.Z);
  6255. end;
  6256. { ***************************************************************************** }
  6257. function VectorEquals(const V1, V2: TVector4i): Boolean;
  6258. begin
  6259. result := (V1.X = V2.X) and (V1.Y = V2.Y) and (V1.Z = V2.Z)
  6260. and (V1.W = V2.W);
  6261. end;
  6262. function VectorEquals(const V1, V2: TVector4d): Boolean;
  6263. begin
  6264. result := (V1.X = V2.X) and (V1.Y = V2.Y) and (V1.Z = V2.Z)
  6265. and (V1.W = V2.W);
  6266. end;
  6267. function VectorEquals(const V1, V2: TVector4s): Boolean;
  6268. begin
  6269. result := (V1.X = V2.X) and (V1.Y = V2.Y) and (V1.Z = V2.Z)
  6270. and (V1.W = V2.W);
  6271. end;
  6272. function VectorEquals(const V1, V2: TVector4b): Boolean;
  6273. begin
  6274. result := (V1.X = V2.X) and (V1.Y = V2.Y) and (V1.Z = V2.Z)
  6275. and (V1.W = V2.W);
  6276. end;
  6277. { ***************************************************************************** }
  6278. function MatrixEquals(const Matrix1, Matrix2: TMatrix3f): Boolean;
  6279. begin
  6280. result := VectorEquals(Matrix1.X, Matrix2.X) and
  6281. VectorEquals(Matrix1.Y, Matrix2.Y) and
  6282. VectorEquals(Matrix1.Z, Matrix2.Z);
  6283. end;
  6284. // 3x3i
  6285. function MatrixEquals(const Matrix1, Matrix2: TMatrix3i): Boolean;
  6286. begin
  6287. result := VectorEquals(Matrix1.X, Matrix2.X) and
  6288. VectorEquals(Matrix1.Y, Matrix2.Y) and
  6289. VectorEquals(Matrix1.Z, Matrix2.Z);
  6290. end;
  6291. function MatrixEquals(const Matrix1, Matrix2: TMatrix3d): Boolean;
  6292. begin
  6293. result := VectorEquals(Matrix1.X, Matrix2.X) and
  6294. VectorEquals(Matrix1.Y, Matrix2.Y) and
  6295. VectorEquals(Matrix1.Z, Matrix2.Z);
  6296. end;
  6297. function MatrixEquals(const Matrix1, Matrix2: TMatrix3s): Boolean;
  6298. begin
  6299. result := VectorEquals(Matrix1.X, Matrix2.X) and
  6300. VectorEquals(Matrix1.Y, Matrix2.Y) and
  6301. VectorEquals(Matrix1.Z, Matrix2.Z);
  6302. end;
  6303. function MatrixEquals(const Matrix1, Matrix2: TMatrix3b): Boolean;
  6304. begin
  6305. result := VectorEquals(Matrix1.X, Matrix2.X) and
  6306. VectorEquals(Matrix1.Y, Matrix2.Y) and
  6307. VectorEquals(Matrix1.Z, Matrix2.Z);
  6308. end;
  6309. { ***************************************************************************** }
  6310. // 4x4f
  6311. function MatrixEquals(const Matrix1, Matrix2: TMatrix4f): Boolean;
  6312. begin
  6313. result := VectorEquals(Matrix1.X, Matrix2.X) and
  6314. VectorEquals(Matrix1.Y, Matrix2.Y) and
  6315. VectorEquals(Matrix1.Z, Matrix2.Z) and
  6316. VectorEquals(Matrix1.W, Matrix2.W);
  6317. end;
  6318. // 4x4i
  6319. function MatrixEquals(const Matrix1, Matrix2: TMatrix4i): Boolean;
  6320. begin
  6321. result := VectorEquals(Matrix1.X, Matrix2.X) and
  6322. VectorEquals(Matrix1.Y, Matrix2.Y) and
  6323. VectorEquals(Matrix1.Z, Matrix2.Z) and
  6324. VectorEquals(Matrix1.W, Matrix2.W);
  6325. end;
  6326. // 4x4d
  6327. function MatrixEquals(const Matrix1, Matrix2: TMatrix4d): Boolean;
  6328. begin
  6329. result := VectorEquals(Matrix1.X, Matrix2.X) and
  6330. VectorEquals(Matrix1.Y, Matrix2.Y) and
  6331. VectorEquals(Matrix1.Z, Matrix2.Z) and
  6332. VectorEquals(Matrix1.W, Matrix2.W);
  6333. end;
  6334. function MatrixEquals(const Matrix1, Matrix2: TMatrix4s): Boolean;
  6335. begin
  6336. result := VectorEquals(Matrix1.X, Matrix2.X) and
  6337. VectorEquals(Matrix1.Y, Matrix2.Y) and
  6338. VectorEquals(Matrix1.Z, Matrix2.Z) and
  6339. VectorEquals(Matrix1.W, Matrix2.W);
  6340. end;
  6341. function MatrixEquals(const Matrix1, Matrix2: TMatrix4b): Boolean;
  6342. begin
  6343. result := VectorEquals(Matrix1.X, Matrix2.X) and
  6344. VectorEquals(Matrix1.Y, Matrix2.Y) and
  6345. VectorEquals(Matrix1.Z, Matrix2.Z) and
  6346. VectorEquals(Matrix1.W, Matrix2.W);
  6347. end;
  6348. { ***************************************************************************** }
  6349. function VectorMoreThen(const SourceVector, ComparedVector: TVector3f)
  6350. : Boolean; overload;
  6351. begin
  6352. result := (SourceVector.X > ComparedVector.X) and
  6353. (SourceVector.Y > ComparedVector.Y) and
  6354. (SourceVector.Z > ComparedVector.Z);
  6355. end;
  6356. function VectorMoreEqualThen(const SourceVector, ComparedVector: TVector3f)
  6357. : Boolean; overload;
  6358. begin
  6359. result := (SourceVector.X >= ComparedVector.X) and
  6360. (SourceVector.Y >= ComparedVector.Y) and
  6361. (SourceVector.Z >= ComparedVector.Z);
  6362. end;
  6363. function VectorLessThen(const SourceVector, ComparedVector: TVector3f)
  6364. : Boolean; overload;
  6365. begin
  6366. result := (SourceVector.X < ComparedVector.X) and
  6367. (SourceVector.Y < ComparedVector.Y) and
  6368. (SourceVector.Z < ComparedVector.Z);
  6369. end;
  6370. function VectorLessEqualThen(const SourceVector, ComparedVector: TVector3f)
  6371. : Boolean; overload;
  6372. begin
  6373. result := (SourceVector.X <= ComparedVector.X) and
  6374. (SourceVector.Y <= ComparedVector.Y) and
  6375. (SourceVector.Z <= ComparedVector.Z);
  6376. end;
  6377. function VectorMoreThen(const SourceVector, ComparedVector: TVector4f)
  6378. : Boolean; overload;
  6379. begin
  6380. result := (SourceVector.X > ComparedVector.X) and
  6381. (SourceVector.Y > ComparedVector.Y) and
  6382. (SourceVector.Z > ComparedVector.Z) and
  6383. (SourceVector.W > ComparedVector.W);
  6384. end;
  6385. function VectorMoreEqualThen(const SourceVector, ComparedVector: TVector4f)
  6386. : Boolean; overload;
  6387. begin
  6388. result := (SourceVector.X >= ComparedVector.X) and
  6389. (SourceVector.Y >= ComparedVector.Y) and
  6390. (SourceVector.Z >= ComparedVector.Z) and
  6391. (SourceVector.W >= ComparedVector.W);
  6392. end;
  6393. function VectorLessThen(const SourceVector, ComparedVector: TVector4f)
  6394. : Boolean; overload;
  6395. begin
  6396. result := (SourceVector.X < ComparedVector.X) and
  6397. (SourceVector.Y < ComparedVector.Y) and
  6398. (SourceVector.Z < ComparedVector.Z) and
  6399. (SourceVector.W < ComparedVector.W);
  6400. end;
  6401. function VectorLessEqualThen(const SourceVector, ComparedVector: TVector4f)
  6402. : Boolean; overload;
  6403. begin
  6404. result := (SourceVector.X <= ComparedVector.X) and
  6405. (SourceVector.Y <= ComparedVector.Y) and
  6406. (SourceVector.Z <= ComparedVector.Z) and
  6407. (SourceVector.W <= ComparedVector.W);
  6408. end;
  6409. function VectorMoreThen(const SourceVector, ComparedVector: TVector3i)
  6410. : Boolean; overload;
  6411. begin
  6412. result := (SourceVector.X > ComparedVector.X) and
  6413. (SourceVector.Y > ComparedVector.Y) and
  6414. (SourceVector.Z > ComparedVector.Z);
  6415. end;
  6416. function VectorMoreEqualThen(const SourceVector, ComparedVector: TVector3i)
  6417. : Boolean; overload;
  6418. begin
  6419. result := (SourceVector.X >= ComparedVector.X) and
  6420. (SourceVector.Y >= ComparedVector.Y) and
  6421. (SourceVector.Z >= ComparedVector.Z);
  6422. end;
  6423. function VectorLessThen(const SourceVector, ComparedVector: TVector3i)
  6424. : Boolean; overload;
  6425. begin
  6426. result := (SourceVector.X < ComparedVector.X) and
  6427. (SourceVector.Y < ComparedVector.Y) and
  6428. (SourceVector.Z < ComparedVector.Z);
  6429. end;
  6430. function VectorLessEqualThen(const SourceVector, ComparedVector: TVector3i)
  6431. : Boolean; overload;
  6432. begin
  6433. result := (SourceVector.X <= ComparedVector.X) and
  6434. (SourceVector.Y <= ComparedVector.Y) and
  6435. (SourceVector.Z <= ComparedVector.Z);
  6436. end;
  6437. function VectorMoreThen(const SourceVector, ComparedVector: TVector4i)
  6438. : Boolean; overload;
  6439. begin
  6440. result := (SourceVector.X > ComparedVector.X) and
  6441. (SourceVector.Y > ComparedVector.Y) and
  6442. (SourceVector.Z > ComparedVector.Z) and
  6443. (SourceVector.W > ComparedVector.W);
  6444. end;
  6445. function VectorMoreEqualThen(const SourceVector, ComparedVector: TVector4i)
  6446. : Boolean; overload;
  6447. begin
  6448. result := (SourceVector.X >= ComparedVector.X) and
  6449. (SourceVector.Y >= ComparedVector.Y) and
  6450. (SourceVector.Z >= ComparedVector.Z) and
  6451. (SourceVector.W >= ComparedVector.W);
  6452. end;
  6453. function VectorLessThen(const SourceVector, ComparedVector: TVector4i)
  6454. : Boolean; overload;
  6455. begin
  6456. result := (SourceVector.X < ComparedVector.X) and
  6457. (SourceVector.Y < ComparedVector.Y) and
  6458. (SourceVector.Z < ComparedVector.Z) and
  6459. (SourceVector.W < ComparedVector.W);
  6460. end;
  6461. function VectorLessEqualThen(const SourceVector, ComparedVector: TVector4i)
  6462. : Boolean; overload;
  6463. begin
  6464. result := (SourceVector.X <= ComparedVector.X) and
  6465. (SourceVector.Y <= ComparedVector.Y) and
  6466. (SourceVector.Z <= ComparedVector.Z) and
  6467. (SourceVector.W <= ComparedVector.W);
  6468. end;
  6469. function VectorMoreThen(const SourceVector, ComparedVector: TVector3s)
  6470. : Boolean; overload;
  6471. begin
  6472. result := (SourceVector.X > ComparedVector.X) and
  6473. (SourceVector.Y > ComparedVector.Y) and
  6474. (SourceVector.Z > ComparedVector.Z);
  6475. end;
  6476. function VectorMoreEqualThen(const SourceVector, ComparedVector: TVector3s)
  6477. : Boolean; overload;
  6478. begin
  6479. result := (SourceVector.X >= ComparedVector.X) and
  6480. (SourceVector.Y >= ComparedVector.Y) and
  6481. (SourceVector.Z >= ComparedVector.Z);
  6482. end;
  6483. function VectorLessThen(const SourceVector, ComparedVector: TVector3s)
  6484. : Boolean; overload;
  6485. begin
  6486. result := (SourceVector.X < ComparedVector.X) and
  6487. (SourceVector.Y < ComparedVector.Y) and
  6488. (SourceVector.Z < ComparedVector.Z);
  6489. end;
  6490. function VectorLessEqualThen(const SourceVector, ComparedVector: TVector3s)
  6491. : Boolean; overload;
  6492. begin
  6493. result := (SourceVector.X <= ComparedVector.X) and
  6494. (SourceVector.Y <= ComparedVector.Y) and
  6495. (SourceVector.Z <= ComparedVector.Z);
  6496. end;
  6497. // 4s
  6498. function VectorMoreThen(const SourceVector, ComparedVector: TVector4s)
  6499. : Boolean; overload;
  6500. begin
  6501. result := (SourceVector.X > ComparedVector.X) and
  6502. (SourceVector.Y > ComparedVector.Y) and
  6503. (SourceVector.Z > ComparedVector.Z) and
  6504. (SourceVector.W > ComparedVector.W);
  6505. end;
  6506. function VectorMoreEqualThen(const SourceVector, ComparedVector: TVector4s)
  6507. : Boolean; overload;
  6508. begin
  6509. result := (SourceVector.X >= ComparedVector.X) and
  6510. (SourceVector.Y >= ComparedVector.Y) and
  6511. (SourceVector.Z >= ComparedVector.Z) and
  6512. (SourceVector.W >= ComparedVector.W);
  6513. end;
  6514. function VectorLessThen(const SourceVector, ComparedVector: TVector4s)
  6515. : Boolean; overload;
  6516. begin
  6517. result := (SourceVector.X < ComparedVector.X) and
  6518. (SourceVector.Y < ComparedVector.Y) and
  6519. (SourceVector.Z < ComparedVector.Z) and
  6520. (SourceVector.W < ComparedVector.W);
  6521. end;
  6522. function VectorLessEqualThen(const SourceVector, ComparedVector: TVector4s)
  6523. : Boolean; overload;
  6524. begin
  6525. result := (SourceVector.X <= ComparedVector.X) and
  6526. (SourceVector.Y <= ComparedVector.Y) and
  6527. (SourceVector.Z <= ComparedVector.Z) and
  6528. (SourceVector.W <= ComparedVector.W);
  6529. end;
  6530. function VectorMoreThen(const SourceVector: TVector3f;
  6531. const ComparedNumber: Single): Boolean; overload;
  6532. begin
  6533. result := (SourceVector.X > ComparedNumber) and
  6534. (SourceVector.Y > ComparedNumber) and
  6535. (SourceVector.Z > ComparedNumber);
  6536. end;
  6537. function VectorMoreEqualThen(const SourceVector: TVector3f;
  6538. const ComparedNumber: Single): Boolean; overload;
  6539. begin
  6540. result := (SourceVector.X >= ComparedNumber) and
  6541. (SourceVector.Y >= ComparedNumber) and
  6542. (SourceVector.Z >= ComparedNumber);
  6543. end;
  6544. function VectorLessThen(const SourceVector: TVector3f;
  6545. const ComparedNumber: Single): Boolean; overload;
  6546. begin
  6547. result := (SourceVector.X < ComparedNumber) and
  6548. (SourceVector.Y < ComparedNumber) and
  6549. (SourceVector.Z < ComparedNumber);
  6550. end;
  6551. function VectorLessEqualThen(const SourceVector: TVector3f;
  6552. const ComparedNumber: Single): Boolean; overload;
  6553. begin
  6554. result := (SourceVector.X <= ComparedNumber) and
  6555. (SourceVector.Y <= ComparedNumber) and
  6556. (SourceVector.Z <= ComparedNumber);
  6557. end;
  6558. function VectorMoreThen(const SourceVector: TVector4f;
  6559. const ComparedNumber: Single): Boolean; overload;
  6560. begin
  6561. result := (SourceVector.X > ComparedNumber) and
  6562. (SourceVector.Y > ComparedNumber) and
  6563. (SourceVector.Z > ComparedNumber) and
  6564. (SourceVector.W > ComparedNumber);
  6565. end;
  6566. function VectorMoreEqualThen(const SourceVector: TVector4f;
  6567. const ComparedNumber: Single): Boolean; overload;
  6568. begin
  6569. result := (SourceVector.X >= ComparedNumber) and
  6570. (SourceVector.Y >= ComparedNumber) and
  6571. (SourceVector.Z >= ComparedNumber) and
  6572. (SourceVector.W >= ComparedNumber);
  6573. end;
  6574. function VectorLessThen(const SourceVector: TVector4f;
  6575. const ComparedNumber: Single): Boolean; overload;
  6576. begin
  6577. result := (SourceVector.X < ComparedNumber) and
  6578. (SourceVector.Y < ComparedNumber) and
  6579. (SourceVector.Z < ComparedNumber) and
  6580. (SourceVector.W < ComparedNumber);
  6581. end;
  6582. function VectorLessEqualThen(const SourceVector: TVector4f;
  6583. const ComparedNumber: Single): Boolean; overload;
  6584. begin
  6585. result := (SourceVector.X <= ComparedNumber) and
  6586. (SourceVector.Y <= ComparedNumber) and
  6587. (SourceVector.Z <= ComparedNumber) and
  6588. (SourceVector.W <= ComparedNumber);
  6589. end;
  6590. function VectorMoreThen(const SourceVector: TVector3i;
  6591. const ComparedNumber: Single): Boolean; overload;
  6592. begin
  6593. result := (SourceVector.X > ComparedNumber) and
  6594. (SourceVector.Y > ComparedNumber) and
  6595. (SourceVector.Z > ComparedNumber);
  6596. end;
  6597. function VectorMoreEqualThen(const SourceVector: TVector3i;
  6598. const ComparedNumber: Single): Boolean; overload;
  6599. begin
  6600. result := (SourceVector.X >= ComparedNumber) and
  6601. (SourceVector.Y >= ComparedNumber) and
  6602. (SourceVector.Z >= ComparedNumber);
  6603. end;
  6604. function VectorLessThen(const SourceVector: TVector3i;
  6605. const ComparedNumber: Single): Boolean; overload;
  6606. begin
  6607. result := (SourceVector.X < ComparedNumber) and
  6608. (SourceVector.Y < ComparedNumber) and
  6609. (SourceVector.Z < ComparedNumber);
  6610. end;
  6611. function VectorLessEqualThen(const SourceVector: TVector3i;
  6612. const ComparedNumber: Single): Boolean; overload;
  6613. begin
  6614. result := (SourceVector.X <= ComparedNumber) and
  6615. (SourceVector.Y <= ComparedNumber) and
  6616. (SourceVector.Z <= ComparedNumber);
  6617. end;
  6618. function VectorMoreThen(const SourceVector: TVector4i;
  6619. const ComparedNumber: Single): Boolean; overload;
  6620. begin
  6621. result := (SourceVector.X > ComparedNumber) and
  6622. (SourceVector.Y > ComparedNumber) and
  6623. (SourceVector.Z > ComparedNumber) and
  6624. (SourceVector.W > ComparedNumber);
  6625. end;
  6626. function VectorMoreEqualThen(const SourceVector: TVector4i;
  6627. const ComparedNumber: Single): Boolean; overload;
  6628. begin
  6629. result := (SourceVector.X >= ComparedNumber) and
  6630. (SourceVector.Y >= ComparedNumber) and
  6631. (SourceVector.Z >= ComparedNumber) and
  6632. (SourceVector.W >= ComparedNumber);
  6633. end;
  6634. function VectorLessThen(const SourceVector: TVector4i;
  6635. const ComparedNumber: Single): Boolean; overload;
  6636. begin
  6637. result := (SourceVector.X < ComparedNumber) and
  6638. (SourceVector.Y < ComparedNumber) and
  6639. (SourceVector.Z < ComparedNumber) and
  6640. (SourceVector.W < ComparedNumber);
  6641. end;
  6642. function VectorLessEqualThen(const SourceVector: TVector4i;
  6643. const ComparedNumber: Single): Boolean; overload;
  6644. begin
  6645. result := (SourceVector.X <= ComparedNumber) and
  6646. (SourceVector.Y <= ComparedNumber) and
  6647. (SourceVector.Z <= ComparedNumber) and
  6648. (SourceVector.W <= ComparedNumber);
  6649. end;
  6650. function VectorMoreThen(const SourceVector: TVector3s;
  6651. const ComparedNumber: Single): Boolean; overload;
  6652. begin
  6653. result := (SourceVector.X > ComparedNumber) and
  6654. (SourceVector.Y > ComparedNumber) and
  6655. (SourceVector.Z > ComparedNumber);
  6656. end;
  6657. function VectorMoreEqualThen(const SourceVector: TVector3s;
  6658. const ComparedNumber: Single): Boolean; overload;
  6659. begin
  6660. result := (SourceVector.X >= ComparedNumber) and
  6661. (SourceVector.Y >= ComparedNumber) and
  6662. (SourceVector.Z >= ComparedNumber);
  6663. end;
  6664. function VectorLessThen(const SourceVector: TVector3s;
  6665. const ComparedNumber: Single): Boolean; overload;
  6666. begin
  6667. result := (SourceVector.X < ComparedNumber) and
  6668. (SourceVector.Y < ComparedNumber) and
  6669. (SourceVector.Z < ComparedNumber);
  6670. end;
  6671. function VectorLessEqualThen(const SourceVector: TVector3s;
  6672. const ComparedNumber: Single): Boolean; overload;
  6673. begin
  6674. result := (SourceVector.X <= ComparedNumber) and
  6675. (SourceVector.Y <= ComparedNumber) and
  6676. (SourceVector.Z <= ComparedNumber);
  6677. end;
  6678. function VectorMoreThen(const SourceVector: TVector4s;
  6679. const ComparedNumber: Single): Boolean; overload;
  6680. begin
  6681. result := (SourceVector.X > ComparedNumber) and
  6682. (SourceVector.Y > ComparedNumber) and
  6683. (SourceVector.Z > ComparedNumber) and
  6684. (SourceVector.W > ComparedNumber);
  6685. end;
  6686. function VectorMoreEqualThen(const SourceVector: TVector4s;
  6687. const ComparedNumber: Single): Boolean; overload;
  6688. begin
  6689. result := (SourceVector.X >= ComparedNumber) and
  6690. (SourceVector.Y >= ComparedNumber) and
  6691. (SourceVector.Z >= ComparedNumber) and
  6692. (SourceVector.W >= ComparedNumber);
  6693. end;
  6694. function VectorLessThen(const SourceVector: TVector4s;
  6695. const ComparedNumber: Single): Boolean; overload;
  6696. begin
  6697. result := (SourceVector.X < ComparedNumber) and
  6698. (SourceVector.Y < ComparedNumber) and
  6699. (SourceVector.Z < ComparedNumber) and
  6700. (SourceVector.W < ComparedNumber);
  6701. end;
  6702. function VectorLessEqualThen(const SourceVector: TVector4s;
  6703. const ComparedNumber: Single): Boolean; overload;
  6704. begin
  6705. result := (SourceVector.X <= ComparedNumber) and
  6706. (SourceVector.Y <= ComparedNumber) and
  6707. (SourceVector.Z <= ComparedNumber) and
  6708. (SourceVector.W <= ComparedNumber);
  6709. end;
  6710. function RectanglesIntersect(const ACenterOfRect1, ACenterOfRect2, ASizeOfRect1,
  6711. ASizeOfRect2: TVector2f): Boolean;
  6712. begin
  6713. result := (Abs(ACenterOfRect1.X - ACenterOfRect2.X) <
  6714. (ASizeOfRect1.X + ASizeOfRect2.X) / 2) and
  6715. (Abs(ACenterOfRect1.Y - ACenterOfRect2.Y) <
  6716. (ASizeOfRect1.Y + ASizeOfRect2.Y) / 2);
  6717. end;
  6718. function RectangleContains(const ACenterOfBigRect1, ACenterOfSmallRect2,
  6719. ASizeOfBigRect1, ASizeOfSmallRect2: TVector2f;
  6720. const AEps: Single = 0.0): Boolean;
  6721. begin
  6722. result := (Abs(ACenterOfBigRect1.X - ACenterOfSmallRect2.X) +
  6723. ASizeOfSmallRect2.X / 2 - ASizeOfBigRect1.X / 2 < AEps) and
  6724. (Abs(ACenterOfBigRect1.Y - ACenterOfSmallRect2.Y) +
  6725. ASizeOfSmallRect2.Y / 2 - ASizeOfBigRect1.Y / 2 < AEps);
  6726. end;
  6727. function GetSafeTurnAngle(const AOriginalPosition, AOriginalUpVector,
  6728. ATargetPosition, AMoveAroundTargetCenter: TVector): TVector2f;
  6729. var
  6730. pitchangle0, pitchangle1, turnangle0, turnangle1, pitchangledif, turnangledif,
  6731. dx0, dy0, dz0, dx1, dy1, dz1: Double;
  6732. Sign: shortint;
  6733. begin
  6734. // determine relative positions to determine the lines which form the angles
  6735. // distances from initial camera pos to target object
  6736. dx0 := AOriginalPosition.X - AMoveAroundTargetCenter.X;
  6737. dy0 := AOriginalPosition.Y - AMoveAroundTargetCenter.Y;
  6738. dz0 := AOriginalPosition.Z - AMoveAroundTargetCenter.Z;
  6739. // distances from final camera pos to target object
  6740. dx1 := ATargetPosition.X - AMoveAroundTargetCenter.X;
  6741. dy1 := ATargetPosition.Y - AMoveAroundTargetCenter.Y;
  6742. dz1 := ATargetPosition.Z - AMoveAroundTargetCenter.Z;
  6743. // just to make sure we don't get division by 0 exceptions
  6744. if dx0 = 0 then
  6745. dx0 := 0.001;
  6746. if dy0 = 0 then
  6747. dy0 := 0.001;
  6748. if dz0 = 0 then
  6749. dz0 := 0.001;
  6750. if dx1 = 0 then
  6751. dx1 := 0.001;
  6752. if dy1 = 0 then
  6753. dy1 := 0.001;
  6754. if dz1 = 0 then
  6755. dz1 := 0.001;
  6756. // determine "pitch" and "turn" angles for the initial and final camera position
  6757. // the formulas differ depending on the camera.Up vector
  6758. // I tested all quadrants for all possible integer FJoblist.Camera.Up directions
  6759. if Abs(AOriginalUpVector.Z) = 1 then // Z=1/-1
  6760. begin
  6761. Sign := Round(AOriginalUpVector.Z / Abs(AOriginalUpVector.Z));
  6762. pitchangle0 := arctan(dz0 / Sqrt(Sqr(dx0) + Sqr(dy0)));
  6763. pitchangle1 := arctan(dz1 / Sqrt(Sqr(dx1) + Sqr(dy1)));
  6764. turnangle0 := arctan(dy0 / dx0);
  6765. if (dx0 < 0) and (dy0 < 0) then
  6766. turnangle0 := -(PI - turnangle0)
  6767. else if (dx0 < 0) and (dy0 > 0) then
  6768. turnangle0 := -(PI - turnangle0);
  6769. turnangle1 := arctan(dy1 / dx1);
  6770. if (dx1 < 0) and (dy1 < 0) then
  6771. turnangle1 := -(PI - turnangle1)
  6772. else if (dx1 < 0) and (dy1 > 0) then
  6773. turnangle1 := -(PI - turnangle1);
  6774. end
  6775. else if Abs(AOriginalUpVector.Y) = 1 then // Y=1/-1
  6776. begin
  6777. Sign := Round(AOriginalUpVector.Y / Abs(AOriginalUpVector.Y));
  6778. pitchangle0 := arctan(dy0 / Sqrt(Sqr(dx0) + Sqr(dz0)));
  6779. pitchangle1 := arctan(dy1 / Sqrt(Sqr(dx1) + Sqr(dz1)));
  6780. turnangle0 := -arctan(dz0 / dx0);
  6781. if (dx0 < 0) and (dz0 < 0) then
  6782. turnangle0 := -(PI - turnangle0)
  6783. else if (dx0 < 0) and (dz0 > 0) then
  6784. turnangle0 := -(PI - turnangle0);
  6785. turnangle1 := -arctan(dz1 / dx1);
  6786. if (dx1 < 0) and (dz1 < 0) then
  6787. turnangle1 := -(PI - turnangle1)
  6788. else if (dx1 < 0) and (dz1 > 0) then
  6789. turnangle1 := -(PI - turnangle1);
  6790. end
  6791. else if Abs(AOriginalUpVector.X) = 1 then // X=1/-1
  6792. begin
  6793. Sign := Round(AOriginalUpVector.X / Abs(AOriginalUpVector.X));
  6794. pitchangle0 := arctan(dx0 / Sqrt(Sqr(dz0) + Sqr(dy0)));
  6795. pitchangle1 := arctan(dx1 / Sqrt(Sqr(dz1) + Sqr(dy1)));
  6796. turnangle0 := arctan(dz0 / dy0);
  6797. if (dz0 > 0) and (dy0 > 0) then
  6798. turnangle0 := -(PI - turnangle0)
  6799. else if (dz0 < 0) and (dy0 > 0) then
  6800. turnangle0 := -(PI - turnangle0);
  6801. turnangle1 := arctan(dz1 / dy1);
  6802. if (dz1 > 0) and (dy1 > 0) then
  6803. turnangle1 := -(PI - turnangle1)
  6804. else if (dz1 < 0) and (dy1 > 0) then
  6805. turnangle1 := -(PI - turnangle1);
  6806. end
  6807. else
  6808. begin
  6809. Raise Exception.Create('The Camera.Up vector may contain only -1, 0 or 1');
  6810. end;
  6811. // determine pitch and turn angle differences
  6812. pitchangledif := Sign * (pitchangle1 - pitchangle0);
  6813. turnangledif := Sign * (turnangle1 - turnangle0);
  6814. if Abs(turnangledif) > PI then
  6815. turnangledif := -Abs(turnangledif) / turnangledif *
  6816. (2 * PI - Abs(turnangledif));
  6817. // Determine rotation speeds
  6818. result.X := RadianToDeg(-pitchangledif);
  6819. result.Y := RadianToDeg(turnangledif);
  6820. end;
  6821. function GetSafeTurnAngle(const AOriginalPosition, AOriginalUpVector,
  6822. ATargetPosition, AMoveAroundTargetCenter: TAffineVector): TVector2f;
  6823. var
  6824. pitchangle0, pitchangle1, turnangle0, turnangle1, pitchangledif, turnangledif,
  6825. dx0, dy0, dz0, dx1, dy1, dz1: Double;
  6826. Sign: shortint;
  6827. begin
  6828. // determine relative positions to determine the lines which form the angles
  6829. // distances from initial camera pos to target object
  6830. dx0 := AOriginalPosition.X - AMoveAroundTargetCenter.X;
  6831. dy0 := AOriginalPosition.Y - AMoveAroundTargetCenter.Y;
  6832. dz0 := AOriginalPosition.Z - AMoveAroundTargetCenter.Z;
  6833. // distances from final camera pos to target object
  6834. dx1 := ATargetPosition.X - AMoveAroundTargetCenter.X;
  6835. dy1 := ATargetPosition.Y - AMoveAroundTargetCenter.Y;
  6836. dz1 := ATargetPosition.Z - AMoveAroundTargetCenter.Z;
  6837. // just to make sure we don't get division by 0 exceptions
  6838. if dx0 = 0 then
  6839. dx0 := 0.001;
  6840. if dy0 = 0 then
  6841. dy0 := 0.001;
  6842. if dz0 = 0 then
  6843. dz0 := 0.001;
  6844. if dx1 = 0 then
  6845. dx1 := 0.001;
  6846. if dy1 = 0 then
  6847. dy1 := 0.001;
  6848. if dz1 = 0 then
  6849. dz1 := 0.001;
  6850. // determine "pitch" and "turn" angles for the initial and final camera position
  6851. // the formulas differ depending on the camera.Up vector
  6852. // I tested all quadrants for all possible integer FJoblist.Camera.Up directions
  6853. if Abs(AOriginalUpVector.Z) = 1 then // Z=1/-1
  6854. begin
  6855. Sign := Round(AOriginalUpVector.Z / Abs(AOriginalUpVector.Z));
  6856. pitchangle0 := arctan(dz0 / Sqrt(Sqr(dx0) + Sqr(dy0)));
  6857. pitchangle1 := arctan(dz1 / Sqrt(Sqr(dx1) + Sqr(dy1)));
  6858. turnangle0 := arctan(dy0 / dx0);
  6859. if (dx0 < 0) and (dy0 < 0) then
  6860. turnangle0 := -(PI - turnangle0)
  6861. else if (dx0 < 0) and (dy0 > 0) then
  6862. turnangle0 := -(PI - turnangle0);
  6863. turnangle1 := arctan(dy1 / dx1);
  6864. if (dx1 < 0) and (dy1 < 0) then
  6865. turnangle1 := -(PI - turnangle1)
  6866. else if (dx1 < 0) and (dy1 > 0) then
  6867. turnangle1 := -(PI - turnangle1);
  6868. end
  6869. else if Abs(AOriginalUpVector.Y) = 1 then // Y=1/-1
  6870. begin
  6871. Sign := Round(AOriginalUpVector.Y / Abs(AOriginalUpVector.Y));
  6872. pitchangle0 := arctan(dy0 / Sqrt(Sqr(dx0) + Sqr(dz0)));
  6873. pitchangle1 := arctan(dy1 / Sqrt(Sqr(dx1) + Sqr(dz1)));
  6874. turnangle0 := -arctan(dz0 / dx0);
  6875. if (dx0 < 0) and (dz0 < 0) then
  6876. turnangle0 := -(PI - turnangle0)
  6877. else if (dx0 < 0) and (dz0 > 0) then
  6878. turnangle0 := -(PI - turnangle0);
  6879. turnangle1 := -arctan(dz1 / dx1);
  6880. if (dx1 < 0) and (dz1 < 0) then
  6881. turnangle1 := -(PI - turnangle1)
  6882. else if (dx1 < 0) and (dz1 > 0) then
  6883. turnangle1 := -(PI - turnangle1);
  6884. end
  6885. else if Abs(AOriginalUpVector.X) = 1 then // X=1/-1
  6886. begin
  6887. Sign := Round(AOriginalUpVector.X / Abs(AOriginalUpVector.X));
  6888. pitchangle0 := arctan(dx0 / Sqrt(Sqr(dz0) + Sqr(dy0)));
  6889. pitchangle1 := arctan(dx1 / Sqrt(Sqr(dz1) + Sqr(dy1)));
  6890. turnangle0 := arctan(dz0 / dy0);
  6891. if (dz0 > 0) and (dy0 > 0) then
  6892. turnangle0 := -(PI - turnangle0)
  6893. else if (dz0 < 0) and (dy0 > 0) then
  6894. turnangle0 := -(PI - turnangle0);
  6895. turnangle1 := arctan(dz1 / dy1);
  6896. if (dz1 > 0) and (dy1 > 0) then
  6897. turnangle1 := -(PI - turnangle1)
  6898. else if (dz1 < 0) and (dy1 > 0) then
  6899. turnangle1 := -(PI - turnangle1);
  6900. end
  6901. else
  6902. begin
  6903. Raise Exception.Create('The Camera.Up vector may contain only -1, 0 or 1');
  6904. end;
  6905. // determine pitch and turn angle differences
  6906. pitchangledif := Sign * (pitchangle1 - pitchangle0);
  6907. turnangledif := Sign * (turnangle1 - turnangle0);
  6908. if Abs(turnangledif) > PI then
  6909. turnangledif := -Abs(turnangledif) / turnangledif *
  6910. (2 * PI - Abs(turnangledif));
  6911. // Determine rotation speeds
  6912. result.X := RadianToDeg(-pitchangledif);
  6913. result.Y := RadianToDeg(turnangledif);
  6914. end;
  6915. function MoveObjectAround(const AMovingObjectPosition, AMovingObjectUp,
  6916. ATargetPosition: TVector; pitchDelta, turnDelta: Single): TVector;
  6917. var
  6918. originalT2C, normalT2C, normalCameraRight: TVector;
  6919. pitchNow, dist: Single;
  6920. begin
  6921. // normalT2C points away from the direction the camera is looking
  6922. originalT2C := VectorSubtract(AMovingObjectPosition, ATargetPosition);
  6923. SetVector(normalT2C, originalT2C);
  6924. dist := VectorLength(normalT2C);
  6925. NormalizeVector(normalT2C);
  6926. // normalRight points to the camera's right the camera is pitching around this axis.
  6927. normalCameraRight := VectorCrossProduct(AMovingObjectUp, normalT2C);
  6928. if VectorLength(normalCameraRight) < 0.001 then
  6929. SetVector(normalCameraRight, XVector) // arbitrary vector
  6930. else
  6931. NormalizeVector(normalCameraRight);
  6932. // calculate the current pitch. 0 is looking down and PI is looking up
  6933. pitchNow := ArcCosine(VectorDotProduct(AMovingObjectUp, normalT2C));
  6934. pitchNow := ClampValue(pitchNow + DegToRadian(pitchDelta), 0 + 0.025,
  6935. PI - 0.025);
  6936. // creates a new vector pointing up and then rotate it down into the new position
  6937. SetVector(normalT2C, AMovingObjectUp);
  6938. RotateVector(normalT2C, normalCameraRight, -pitchNow);
  6939. RotateVector(normalT2C, AMovingObjectUp, -DegToRadian(turnDelta));
  6940. ScaleVector(normalT2C, dist);
  6941. result := VectorAdd(AMovingObjectPosition, VectorSubtract(normalT2C,
  6942. originalT2C));
  6943. end;
  6944. function AngleBetweenVectors(const a, b, ACenterPoint: TVector): Single;
  6945. begin
  6946. result := ArcCosine(VectorAngleCosine(VectorNormalize(VectorSubtract(a,
  6947. ACenterPoint)), VectorNormalize(VectorSubtract(b, ACenterPoint))));
  6948. end;
  6949. function AngleBetweenVectors(const a, b, ACenterPoint: TAffineVector): Single;
  6950. begin
  6951. result := ArcCosine(VectorAngleCosine(VectorNormalize(VectorSubtract(a,
  6952. ACenterPoint)), VectorNormalize(VectorSubtract(b, ACenterPoint))));
  6953. end;
  6954. function ShiftObjectFromCenter(const AOriginalPosition: TVector;
  6955. const ACenter: TVector; const ADistance: Single;
  6956. const AFromCenterSpot: Boolean): TVector;
  6957. var
  6958. lDirection: TVector;
  6959. begin
  6960. lDirection := VectorNormalize(VectorSubtract(AOriginalPosition, ACenter));
  6961. if AFromCenterSpot then
  6962. result := VectorAdd(ACenter, VectorScale(lDirection, ADistance))
  6963. else
  6964. result := VectorAdd(AOriginalPosition, VectorScale(lDirection, ADistance))
  6965. end;
  6966. function ShiftObjectFromCenter(const AOriginalPosition: TAffineVector;
  6967. const ACenter: TAffineVector; const ADistance: Single;
  6968. const AFromCenterSpot: Boolean): TAffineVector;
  6969. var
  6970. lDirection: TAffineVector;
  6971. begin
  6972. lDirection := VectorNormalize(VectorSubtract(AOriginalPosition, ACenter));
  6973. if AFromCenterSpot then
  6974. result := VectorAdd(ACenter, VectorScale(lDirection, ADistance))
  6975. else
  6976. result := VectorAdd(AOriginalPosition, VectorScale(lDirection, ADistance))
  6977. end;
  6978. // --------------------------------------------------------------
  6979. initialization
  6980. // --------------------------------------------------------------
  6981. vSIMD := 0;
  6982. end.