GLS.VectorLists.pas 86 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397
  1. //
  2. // The graphics engine GLScene https://github.com/glscene
  3. //
  4. unit GLS.VectorLists;
  5. (*
  6. Misc. lists of vectors and entities
  7. The registered classes are:
  8. [TGLAffineVectorList, TGLVectorList, TGLTexPointList,
  9. TGLSingleList, TGLDoubleList, TGL4ByteList, TGLLongWordList]
  10. *)
  11. interface
  12. {$I GLScene.Defines.inc}
  13. uses
  14. System.Classes,
  15. System.SysUtils,
  16. GLScene.VectorTypes,
  17. GLScene.VectorGeometry,
  18. GLS.PersistentClasses;
  19. type
  20. TGLBaseListOption = (bloExternalMemory, bloSetCountResetsMemory);
  21. TGLBaseListOptions = set of TGLBaseListOption;
  22. // Base class for lists, introduces common behaviours
  23. TGLBaseList = class(TGLPersistentObject)
  24. private
  25. FCount: Integer;
  26. FCapacity: Integer;
  27. FGrowthDelta: Integer;
  28. FBufferItem: PByteArray;
  29. FOptions: TGLBaseListOptions;
  30. FRevision: LongWord;
  31. FTagString: string;
  32. protected
  33. // The base list pointer (untyped)
  34. FBaseList: PByteArray;
  35. // Must be defined by all subclasses in their constructor(s)
  36. FItemSize: Integer;
  37. procedure SetCount(Val: Integer); inline;
  38. (* Only function where list may be alloc'ed & freed.
  39. Resizes the array pointed by FBaseList, adjust the subclass's
  40. typed pointer accordingly if any *)
  41. procedure SetCapacity(NewCapacity: Integer); virtual;
  42. function BufferItem: PByteArray; inline;
  43. function GetSetCountResetsMemory: Boolean; inline;
  44. procedure SetSetCountResetsMemory(const Val: Boolean);
  45. // Borland-style persistency support.
  46. procedure ReadItemsData(AReader : TReader); virtual;
  47. procedure WriteItemsData(AWriter : TWriter); virtual;
  48. procedure DefineProperties(AFiler: TFiler); override;
  49. public
  50. constructor Create; override;
  51. destructor Destroy; override;
  52. procedure Assign(Src: TPersistent); override;
  53. procedure WriteToFiler(writer: TGVirtualWriter); override;
  54. procedure ReadFromFiler(reader: TGVirtualReader); override;
  55. procedure AddNulls(nbVals: Cardinal);
  56. procedure InsertNulls(Index: Integer; nbVals: Cardinal);
  57. procedure AdjustCapacityToAtLeast(const size: Integer);
  58. function DataSize: Integer;
  59. (*Tell the list to use the specified range instead of its own.
  60. rangeCapacity should be expressed in bytes.
  61. The allocated memory is NOT managed by the list, current content
  62. if copied to the location, if the capacity is later changed, regular
  63. memory will be allocated, and the specified range no longer used *)
  64. procedure UseMemory(rangeStart: Pointer; rangeCapacity: Integer);
  65. // Empties the list without altering capacity
  66. procedure Flush; inline;
  67. // Empties the list and release
  68. procedure Clear;
  69. procedure Delete(Index: Integer);
  70. procedure DeleteItems(Index: Integer; nbVals: Cardinal);
  71. procedure Exchange(index1, index2: Integer); inline;
  72. procedure Move(curIndex, newIndex: Integer); inline;
  73. procedure Reverse;
  74. // Nb of items in the list. When assigning a Count, added items are reset to zero
  75. property Count: Integer read FCount write SetCount;
  76. // Current list capacity. Not persistent
  77. property Capacity: Integer read FCapacity write SetCapacity;
  78. // List growth granularity. Not persistent
  79. property GrowthDelta: Integer read FGrowthDelta write FGrowthDelta;
  80. (* If true (default value) adjusting count will reset added values.
  81. Switching this option to true will turn off this memory reset,
  82. which can improve performance is that having empty values isn't required. *)
  83. property SetCountResetsMemory: Boolean read GetSetCountResetsMemory write SetSetCountResetsMemory;
  84. property TagString: string read FTagString write FTagString;
  85. // Increase by one after every content changes
  86. property Revision: LongWord read FRevision write FRevision;
  87. end;
  88. // Base class for vector lists, introduces common behaviours
  89. TGLBaseVectorList = class(TGLBaseList)
  90. protected
  91. function GetItemAddress(Index: Integer): PFloatArray; inline;
  92. public
  93. procedure WriteToFiler(writer: TGVirtualWriter); override;
  94. procedure ReadFromFiler(reader: TGVirtualReader); override;
  95. procedure GetExtents(out min, max: TAffineVector); virtual;
  96. function Sum: TAffineVector;
  97. procedure Normalize; virtual;
  98. function MaxSpacing(list2: TGLBaseVectorList): Single;
  99. procedure Translate(const delta: TAffineVector); overload; virtual;
  100. procedure Translate(const delta: TGLBaseVectorList); overload; virtual;
  101. procedure TranslateInv(const delta: TGLBaseVectorList); overload; virtual;
  102. (*Replace content of the list with lerp results between the two given lists.
  103. Note: you can't Lerp with Self!!! *)
  104. procedure Lerp(const list1, list2: TGLBaseVectorList; lerpFactor: Single); virtual; abstract;
  105. (* Replace content of the list with angle lerp between the two given lists.
  106. Note: you can't Lerp with Self!!! *)
  107. procedure AngleLerp(const list1, list2: TGLBaseVectorList; lerpFactor: Single);
  108. procedure AngleCombine(const list1: TGLBaseVectorList; intensity: Single);
  109. //Linear combination of Self with another list. Self[i]:=Self[i]+list2[i]*factor
  110. procedure Combine(const list2: TGLBaseVectorList; factor: Single); virtual;
  111. property ItemAddress[Index: Integer]: PFloatArray read GetItemAddress;
  112. end;
  113. (*A list of TAffineVector.
  114. Similar to TList, but using TAffineVector as items.
  115. The list has stack-like push/pop methods *)
  116. TGLAffineVectorList = class(TGLBaseVectorList)
  117. private
  118. FList: PAffineVectorArray;
  119. protected
  120. function Get(Index: Integer): TAffineVector; inline;
  121. procedure Put(Index: Integer; const item: TAffineVector); inline;
  122. procedure SetCapacity(NewCapacity: Integer); override;
  123. public
  124. constructor Create; override;
  125. procedure Assign(Src: TPersistent); override;
  126. function Add(const item: TAffineVector): Integer; overload;
  127. function Add(const item: TGLVector): Integer; overload;
  128. procedure Add(const i1, i2: TAffineVector); overload;
  129. procedure Add(const i1, i2, i3: TAffineVector); overload;
  130. function Add(const item: TVector2f): Integer; overload;
  131. function Add(const item: TTexPoint): Integer; overload;
  132. function Add(const X, Y: Single): Integer; overload;
  133. function Add(const X, Y, Z: Single): Integer; overload;
  134. function Add(const X, Y, Z: Integer): Integer; overload;
  135. // Add (3 ints, no capacity check)
  136. function AddNC(const X, Y, Z: Integer): Integer; overload;
  137. // Add (2 ints in array + 1)
  138. function Add(const xy: PIntegerArray; const Z: Integer): Integer; overload;
  139. // AddNC (2 ints in array + 1, no capacity check)
  140. function AddNC(const xy: PIntegerArray; const Z: Integer): Integer; overload;
  141. procedure Add(const list: TGLAffineVectorList); overload;
  142. procedure Push(const Val: TAffineVector);
  143. function Pop: TAffineVector;
  144. procedure Insert(Index: Integer; const item: TAffineVector); inline;
  145. function IndexOf(const item: TAffineVector): Integer;
  146. function FindOrAdd(const item: TAffineVector): Integer;
  147. property Items[Index: Integer]: TAffineVector read Get write Put; default;
  148. property List: PAffineVectorArray read FList;
  149. procedure Translate(const delta: TAffineVector); overload; override;
  150. procedure Translate(const delta: TAffineVector; base, nb: Integer); overload;
  151. // Translates the given item
  152. procedure TranslateItem(Index: Integer; const delta: TAffineVector);
  153. // Translates given items
  154. procedure TranslateItems(Index: Integer; const delta: TAffineVector; nb: Integer);
  155. // Combines the given item
  156. procedure CombineItem(Index: Integer; const vector: TAffineVector; const f: Single);
  157. (*Transforms all items by the matrix as if they were points.
  158. ie. the translation component of the matrix is honoured. *)
  159. procedure TransformAsPoints(const matrix: TGLMatrix);
  160. (* Transforms all items by the matrix as if they were vectors.
  161. ie. the translation component of the matrix is not honoured. *)
  162. procedure TransformAsVectors(const matrix: TGLMatrix); overload;
  163. procedure TransformAsVectors(const matrix: TAffineMatrix); overload;
  164. procedure Normalize; override;
  165. procedure Lerp(const list1, list2: TGLBaseVectorList; lerpFactor: Single); override;
  166. procedure Scale(factor: Single); overload;
  167. procedure Scale(const factors: TAffineVector); overload;
  168. end;
  169. (* A list of TGLVectors.
  170. Similar to TList, but using TGLVector as items.
  171. The list has stack-like push/pop methods *)
  172. TGLVectorList = class(TGLBaseVectorList)
  173. private
  174. FList: PVectorArray;
  175. protected
  176. function Get(Index: Integer): TGLVector; inline;
  177. procedure Put(Index: Integer; const item: TGLVector); inline;
  178. procedure SetCapacity(NewCapacity: Integer); override;
  179. public
  180. constructor Create; override;
  181. procedure Assign(Src: TPersistent); override;
  182. function Add(const item: TGLVector): Integer; overload; inline;
  183. function Add(const item: TAffineVector; w: Single): Integer; overload; inline;
  184. function Add(const X, Y, Z, w: Single): Integer; overload; inline;
  185. procedure Add(const i1, i2, i3: TAffineVector; w: Single); overload; inline;
  186. function AddVector(const item: TAffineVector): Integer; overload;
  187. function AddPoint(const item: TAffineVector): Integer; overload;
  188. function AddPoint(const X, Y: Single; const Z: Single = 0): Integer; overload;
  189. procedure Push(const Val: TGLVector);
  190. function Pop: TGLVector;
  191. function IndexOf(const item: TGLVector): Integer;
  192. function FindOrAdd(const item: TGLVector): Integer;
  193. function FindOrAddPoint(const item: TAffineVector): Integer;
  194. procedure Insert(Index: Integer; const item: TGLVector);
  195. property Items[Index: Integer]: TGLVector read Get write Put; default;
  196. property List: PVectorArray read FList;
  197. procedure Lerp(const list1, list2: TGLBaseVectorList; lerpFactor: Single); override;
  198. end;
  199. (* A list of TGLTexPoint. Similar to TList, but using TTexPoint as items.
  200. The list has stack-like push/pop methods. *)
  201. TGLTexPointList = class(TGLBaseVectorList)
  202. private
  203. FList: PTexPointArray;
  204. protected
  205. function Get(Index: Integer): TTexPoint;
  206. procedure Put(Index: Integer; const item: TTexPoint);
  207. procedure SetCapacity(NewCapacity: Integer); override;
  208. public
  209. constructor Create; override;
  210. procedure Assign(Src: TPersistent); override;
  211. function IndexOf(const item: TTexpoint): Integer;
  212. function FindOrAdd(const item: TTexpoint): Integer;
  213. function Add(const item: TTexPoint): Integer; overload;
  214. function Add(const item: TVector2f): Integer; overload;
  215. function Add(const texS, Text: Single): Integer; overload;
  216. function Add(const texS, Text: Integer): Integer; overload;
  217. function AddNC(const texS, Text: Integer): Integer; overload;
  218. function Add(const texST: PIntegerArray): Integer; overload;
  219. function AddNC(const texST: PIntegerArray): Integer; overload;
  220. procedure Push(const Val: TTexPoint);
  221. function Pop: TTexPoint;
  222. procedure Insert(Index: Integer; const item: TTexPoint);
  223. property Items[Index: Integer]: TTexPoint read Get write Put; default;
  224. property List: PTexPointArray read FList;
  225. procedure Translate(const delta: TTexPoint);
  226. procedure ScaleAndTranslate(const scale, delta: TTexPoint); overload;
  227. procedure ScaleAndTranslate(const scale, delta: TTexPoint; base, nb: Integer); overload;
  228. procedure Lerp(const list1, list2: TGLBaseVectorList; lerpFactor: Single); override;
  229. end;
  230. (* A list of Integers. Similar to TList, but using TTexPoint as items.
  231. The list has stack-like push/pop methods. *)
  232. TGLIntegerList = class(TGLBaseList)
  233. private
  234. FList: PIntegerArray;
  235. protected
  236. function Get(Index: Integer): Integer; inline;
  237. procedure Put(Index: Integer; const item: Integer); inline;
  238. procedure SetCapacity(newCapacity: Integer); override;
  239. public
  240. constructor Create; override;
  241. procedure Assign(src: TPersistent); override;
  242. function Add(const item: Integer): Integer; overload; inline;
  243. function AddNC(const item: Integer): Integer; overload; inline;
  244. procedure Add(const i1, i2: Integer); overload; inline;
  245. procedure Add(const i1, i2, i3: Integer); overload; inline;
  246. procedure Add(const AList: TGLIntegerList); overload; inline;
  247. procedure Push(const Val: Integer); inline;
  248. function Pop: Integer; inline;
  249. procedure Insert(Index: Integer; const item: Integer); inline;
  250. procedure Remove(const item: Integer); inline;
  251. function IndexOf(item: Integer): Integer; inline;
  252. property Items[Index: Integer]: Integer read Get write Put; default;
  253. property List: PIntegerArray read FList;
  254. // Adds count items in an arithmetic serie. Items are (aBase),(aBase+aDelta)...(aBase+(aCount-1)*aDelta)
  255. procedure AddSerie(aBase, aDelta, aCount: Integer);
  256. // Add n integers at the address starting at (and including) first
  257. procedure AddIntegers(const First: PInteger; n: Integer); overload;
  258. // Add all integers from aList into the list
  259. procedure AddIntegers(const aList: TGLIntegerList); overload;
  260. // Add all integers from anArray into the list
  261. procedure AddIntegers(const anArray: array of Integer); overload;
  262. // Returns the minimum integer item, zero if list is empty
  263. function MinInteger: Integer;
  264. // Returns the maximum integer item, zero if list is empty
  265. function MaxInteger: Integer;
  266. // Sort items in ascending order
  267. procedure Sort;
  268. // Sort items in ascending order and remove duplicated integers
  269. procedure SortAndRemoveDuplicates;
  270. // Locate a value in a sorted list
  271. function BinarySearch(const Value: Integer): Integer; overload;
  272. (* Locate a value in a sorted list.
  273. If ReturnBestFit is set to true, the routine will return the position
  274. of the largest value that's smaller than the sought value. Found will
  275. be set to True if the exact value was found, False if a "BestFit" was found *)
  276. function BinarySearch(const Value: Integer; returnBestFit: Boolean; var found: Boolean): Integer; overload;
  277. (* Add integer to a sorted list.
  278. Maintains the list sorted. If you have to add "a lot" of integers
  279. at once, use the Add method then Sort the list for better performance. *)
  280. function AddSorted(const Value: Integer; const ignoreDuplicates: Boolean = False): Integer;
  281. // Removes an integer from a sorted list
  282. procedure RemoveSorted(const Value: Integer);
  283. // Adds delta to all items in the list
  284. procedure Offset(delta: Integer); overload;
  285. procedure Offset(delta: Integer; const base, nb: Integer); overload;
  286. end;
  287. TGLSingleArrayList = array[0..MaxInt shr 4] of Single;
  288. PGLSingleArrayList = ^TGLSingleArrayList;
  289. (* A list of Single. Similar to TList, but using Single as items.
  290. The list has stack-like push/pop methods *)
  291. TGLSingleList = class(TGLBaseList)
  292. private
  293. FList: PGLSingleArrayList;
  294. protected
  295. function Get(Index: Integer): Single; inline;
  296. procedure Put(Index: Integer; const item: Single); inline;
  297. procedure SetCapacity(NewCapacity: Integer); override;
  298. public
  299. constructor Create; override;
  300. procedure Assign(Src: TPersistent); override;
  301. function Add(const item: Single): Integer; overload; inline;
  302. procedure Add(const i1, i2: Single); overload; inline;
  303. procedure AddSingles(const First: PSingle; n: Integer); overload; inline;
  304. procedure AddSingles(const anArray: array of Single); overload;
  305. procedure Push(const Val: Single); inline;
  306. function Pop: Single; inline;
  307. procedure Insert(Index: Integer; const item: Single); inline;
  308. property Items[Index: Integer]: Single read Get write Put; default;
  309. property List: PGLSingleArrayList read FList;
  310. procedure AddSerie(aBase, aDelta: Single; aCount: Integer);
  311. // Adds delta to all items in the list
  312. procedure Offset(delta: Single); overload;
  313. (* Adds to each item the corresponding item in the delta list.
  314. Performs 'Items[i]:=Items[i]+delta[i]'.
  315. If both lists don't have the same item count, an exception is raised *)
  316. procedure Offset(const delta: TGLSingleList); overload;
  317. // Multiplies all items by factor
  318. procedure Scale(factor: Single);
  319. // Square all items
  320. procedure Sqr;
  321. // SquareRoot all items
  322. procedure Sqrt;
  323. // Computes the sum of all elements
  324. function Sum: Single;
  325. function Min: Single;
  326. function Max: Single;
  327. end;
  328. TGLDoubleArrayList = array[0..MaxInt shr 4] of Double;
  329. PGLDoubleArrayList = ^TGLDoubleArrayList;
  330. (* A list of Double. Similar to TList, but using Double as items.
  331. The list has stack-like push/pop methods *)
  332. TGLDoubleList = class(TGLBaseList)
  333. private
  334. FList: PGLDoubleArrayList;
  335. protected
  336. function Get(Index: Integer): Double;
  337. procedure Put(Index: Integer; const item: Double);
  338. procedure SetCapacity(NewCapacity: Integer); override;
  339. public
  340. constructor Create; override;
  341. procedure Assign(Src: TPersistent); override;
  342. function Add(const item: Double): Integer;
  343. procedure Push(const Val: Double);
  344. function Pop: Double;
  345. procedure Insert(Index: Integer; const item: Double);
  346. property Items[Index: Integer]: Double read Get write Put; default;
  347. property List: PGLDoubleArrayList read FList;
  348. procedure AddSerie(aBase, aDelta: Double; aCount: Integer);
  349. // Adds delta to all items in the list
  350. procedure Offset(delta: Double); overload;
  351. (* Adds to each item the corresponding item in the delta list.
  352. Performs 'Items[i] := Items[i] + delta[i]'.
  353. If both lists don't have the same item count, an exception is raised *)
  354. procedure Offset(const delta: TGLDoubleList); overload;
  355. // Multiplies all items by factor
  356. procedure Scale(factor: Double);
  357. // Square all items
  358. procedure Sqr;
  359. // SquareRoot all items
  360. procedure Sqrt;
  361. // Computes the sum of all elements
  362. function Sum: Double;
  363. function Min: Single;
  364. function Max: Single;
  365. end;
  366. // A list of bytes. Similar to TList, but using Byte as items
  367. TGLByteList = class(TGLBaseList)
  368. private
  369. FList: PByteArray;
  370. protected
  371. function Get(Index: Integer): Byte; inline;
  372. procedure Put(Index: Integer; const item: Byte); inline;
  373. procedure SetCapacity(NewCapacity: Integer); override;
  374. public
  375. constructor Create; override;
  376. procedure Assign(Src: TPersistent); override;
  377. function Add(const item: Byte): Integer; inline;
  378. procedure Insert(Index: Integer; const item: Byte); inline;
  379. property Items[Index: Integer]: Byte read Get write Put; default;
  380. property List: PByteArray read FList;
  381. end;
  382. (* A list of TQuaternion. Similar to TList, but using TQuaternion as items.
  383. The list has stack-like push/pop methods *)
  384. TGLQuaternionList = class(TGLBaseVectorList)
  385. private
  386. FList: PQuaternionArray;
  387. protected
  388. function Get(Index: Integer): TQuaternion;
  389. procedure Put(Index: Integer; const item: TQuaternion);
  390. procedure SetCapacity(NewCapacity: Integer); override;
  391. public
  392. constructor Create; override;
  393. procedure Assign(Src: TPersistent); override;
  394. function Add(const item: TQuaternion): Integer; overload;
  395. function Add(const item: TAffineVector; w: Single): Integer; overload;
  396. function Add(const X, Y, Z, W: Single): Integer; overload;
  397. procedure Push(const Val: TQuaternion);
  398. function Pop: TQuaternion;
  399. function IndexOf(const item: TQuaternion): Integer;
  400. function FindOrAdd(const item: TQuaternion): Integer;
  401. procedure Insert(Index: Integer; const item: TQuaternion);
  402. property Items[Index: Integer]: TQuaternion read Get write Put; default;
  403. property List: PQuaternionArray read FList;
  404. // Lerps corresponding quaternions from both lists using QuaternionSlerp
  405. procedure Lerp(const list1, list2: TGLBaseVectorList; lerpFactor: Single); override;
  406. (* Multiplies corresponding quaternions after the second quaternion is
  407. slerped with the IdentityQuaternion using factor. This allows for weighted
  408. combining of rotation transforms using quaternions *)
  409. procedure Combine(const list2: TGLBaseVectorList; factor: Single); override;
  410. end;
  411. // 4 byte union contain access like Integer, Single and four Byte
  412. TGL4ByteData = packed record
  413. case Byte of
  414. 0 : (Bytes : record Value : array[0..3] of Byte; end);
  415. 1 : (Int : record Value : Integer; end);
  416. 2 : (UInt : record Value : Cardinal; end);
  417. 3 : (Float : record Value : Single; end);
  418. 4 : (Word : record Value : array[0..1] of Word; end);
  419. end;
  420. T4ByteArrayList = array[0..MaxInt shr 4] of TGL4ByteData;
  421. P4ByteArrayList = ^T4ByteArrayList;
  422. // A list of TGL4ByteData
  423. TGL4ByteList = class(TGLBaseList)
  424. private
  425. FList: P4ByteArrayList;
  426. protected
  427. function Get(Index: Integer): TGL4ByteData;
  428. procedure Put(Index: Integer; const item: TGL4ByteData);
  429. procedure SetCapacity(NewCapacity: Integer); override;
  430. public
  431. constructor Create; override;
  432. procedure Assign(Src: TPersistent); override;
  433. function Add(const item: TGL4ByteData): Integer; overload;
  434. procedure Add(const i1: Single); overload;
  435. procedure Add(const i1, i2: Single); overload;
  436. procedure Add(const i1, i2, i3: Single); overload;
  437. procedure Add(const i1, i2, i3, i4: Single); overload;
  438. procedure Add(const i1: Integer); overload;
  439. procedure Add(const i1, i2: Integer); overload;
  440. procedure Add(const i1, i2, i3: Integer); overload;
  441. procedure Add(const i1, i2, i3, i4: Integer); overload;
  442. procedure Add(const i1: Cardinal); overload;
  443. procedure Add(const i1, i2: Cardinal); overload;
  444. procedure Add(const i1, i2, i3: Cardinal); overload;
  445. procedure Add(const i1, i2, i3, i4: Cardinal); overload;
  446. procedure Add(const AList: TGL4ByteList); overload;
  447. procedure Push(const Val: TGL4ByteData);
  448. function Pop: TGL4ByteData;
  449. procedure Insert(Index: Integer; const item: TGL4ByteData);
  450. property Items[Index: Integer]: TGL4ByteData read Get write Put; default;
  451. property List: P4ByteArrayList read FList;
  452. end;
  453. TGLLongWordList = class(TGLBaseList)
  454. private
  455. FList: PLongWordArray;
  456. protected
  457. function Get(Index: Integer): LongWord;
  458. procedure Put(Index: Integer; const item: LongWord);
  459. procedure SetCapacity(newCapacity: Integer); override;
  460. public
  461. constructor Create; override;
  462. procedure Assign(src: TPersistent); override;
  463. function Add(const item: LongWord): Integer; overload;
  464. function AddNC(const item: LongWord): Integer; overload;
  465. procedure Add(const i1, i2: LongWord); overload;
  466. procedure Add(const i1, i2, i3: LongWord); overload;
  467. procedure Add(const AList: TGLLongWordList); overload;
  468. procedure Push(const Val: LongWord);
  469. function Pop: LongWord;
  470. procedure Insert(Index: Integer; const item: LongWord);
  471. procedure Remove(const item: LongWord);
  472. function IndexOf(item: Integer): LongWord;
  473. property Items[Index: Integer]: LongWord read Get write Put; default;
  474. property List: PLongWordArray read FList;
  475. // Add n integers at the address starting at (and including) first
  476. procedure AddLongWords(const First: PLongWord; n: Integer); overload;
  477. // Add all integers from aList into the list
  478. procedure AddLongWords(const aList: TGLLongWordList); overload;
  479. // Add all integers from anArray into the list
  480. procedure AddLongWords(const anArray: array of LongWord); overload;
  481. end;
  482. // Sort the refList in ascending order, ordering objList (TList) on the way
  483. procedure QuickSortLists(startIndex, endIndex: Integer; refList: TGLSingleList; objList: TList); overload;
  484. // Sort the refList in ascending order, ordering objList (TGLBaseList) on the way
  485. procedure QuickSortLists(startIndex, endIndex: Integer; refList: TGLSingleList; objList: TGLBaseList); overload;
  486. (* Sort the refList in ascending order, ordering objList on the way.
  487. Use if, and *ONLY* if refList contains only values superior or equal to 1 *)
  488. procedure FastQuickSortLists(startIndex, endIndex: Integer; const refList: TGLSingleList; const objList: TGLPersistentObjectList);
  489. // ------------------------------------------------------------------
  490. implementation
  491. // ------------------------------------------------------------------
  492. const
  493. cDefaultListGrowthDelta = 16;
  494. procedure QuickSortLists(startIndex, endIndex: Integer; refList: TGLSingleList; objList: TList);
  495. var
  496. I, J: Integer;
  497. P: Single;
  498. begin
  499. if endIndex - startIndex > 1 then
  500. begin
  501. repeat
  502. I := startIndex;
  503. J := endIndex;
  504. P := refList.List^[(I + J) shr 1];
  505. repeat
  506. while Single(refList.List^[I]) < P do
  507. Inc(I);
  508. while Single(refList.List^[J]) > P do
  509. Dec(J);
  510. if I <= J then
  511. begin
  512. refList.Exchange(I, J);
  513. objList.Exchange(I, J);
  514. Inc(I);
  515. Dec(J);
  516. end;
  517. until I > J;
  518. if startIndex < J then
  519. QuickSortLists(startIndex, J, refList, objList);
  520. startIndex := I;
  521. until I >= endIndex;
  522. end
  523. else
  524. if endIndex - startIndex > 0 then
  525. begin
  526. p := refList.List^[startIndex];
  527. if refList.List^[endIndex] < p then
  528. begin
  529. refList.Exchange(startIndex, endIndex);
  530. objList.Exchange(startIndex, endIndex);
  531. end;
  532. end;
  533. end;
  534. procedure QuickSortLists(startIndex, endIndex: Integer; refList: TGLSingleList; objList: TGLBaseList);
  535. var
  536. I, J: Integer;
  537. P: Single;
  538. begin
  539. if endIndex - startIndex > 1 then
  540. begin
  541. repeat
  542. I := startIndex;
  543. J := endIndex;
  544. P := refList.List^[(I + J) shr 1];
  545. repeat
  546. while Single(refList.List^[I]) < P do
  547. Inc(I);
  548. while Single(refList.List^[J]) > P do
  549. Dec(J);
  550. if I <= J then
  551. begin
  552. refList.Exchange(I, J);
  553. objList.Exchange(I, J);
  554. Inc(I);
  555. Dec(J);
  556. end;
  557. until I > J;
  558. if startIndex < J then
  559. QuickSortLists(startIndex, J, refList, objList);
  560. startIndex := I;
  561. until I >= endIndex;
  562. end
  563. else
  564. if endIndex - startIndex > 0 then
  565. begin
  566. p := refList.List^[startIndex];
  567. if refList.List^[endIndex] < p then
  568. begin
  569. refList.Exchange(startIndex, endIndex);
  570. objList.Exchange(startIndex, endIndex);
  571. end;
  572. end;
  573. end;
  574. procedure FastInsertionSortLists(startIndex, endIndex: Integer; const ppl: PIntegerArray; const oppl: PPointerArray); inline;
  575. var
  576. oTemp: Pointer;
  577. I, J: Integer;
  578. Temp: Integer;
  579. begin
  580. for I := startIndex+1 to endIndex-1 do
  581. begin
  582. J := i-1;
  583. Temp := ppl^[I];
  584. oTemp := oppl^[I];
  585. while (J>=startIndex) and (Temp < ppl^[J]) do
  586. begin
  587. ppl^[J+1] := ppl^[J];
  588. oppl^[J+1] := oppl^[J];
  589. Dec(j);
  590. end;
  591. ppl^[J+1] := Temp;
  592. oppl^[J+1] := oTemp;
  593. end;
  594. end;
  595. procedure FastQuickSortLists(startIndex, endIndex: Integer; const refList: TGLSingleList; const objList: TGLPersistentObjectList);
  596. var
  597. ppl: PIntegerArray;
  598. oTemp: Pointer;
  599. oppl: PPointerArray;
  600. I, J: Integer;
  601. p, Temp: Integer;
  602. begin
  603. // All singles are >=1, so IEEE format allows comparing them as if they were integers
  604. ppl := PIntegerArray(@refList.List[0]);
  605. oppl := PPointerArray(objList.List);
  606. if endIndex > startIndex + 1 then
  607. begin
  608. if (endIndex-startIndex)<16 then
  609. begin
  610. FastInsertionSortLists(startIndex, endIndex, ppl, oppl);
  611. end else
  612. begin
  613. repeat
  614. I := startIndex;
  615. J := endIndex;
  616. p := PInteger(@refList.List[(I + J) shr 1])^;
  617. repeat
  618. while ppl^[I] < p do
  619. Inc(I);
  620. while ppl^[J] > p do
  621. Dec(J);
  622. if I <= J then
  623. begin
  624. // swap integers
  625. Temp := ppl^[I];
  626. ppl^[I] := ppl^[J];
  627. ppl^[J] := Temp;
  628. // swap pointers
  629. oTemp := oppl^[I];
  630. oppl^[I] := oppl^[J];
  631. oppl^[J] := oTemp;
  632. Inc(I);
  633. Dec(J);
  634. end;
  635. until I > J;
  636. if startIndex < J then
  637. FastQuickSortLists(startIndex, J, refList, objList);
  638. startIndex := I;
  639. until I >= endIndex;
  640. end;
  641. end else if endIndex > startIndex then
  642. begin
  643. if ppl^[endIndex] < ppl^[startIndex] then
  644. begin
  645. I := endIndex;
  646. J := startIndex;
  647. // swap integers
  648. Temp := ppl^[I];
  649. ppl^[I] := ppl^[J];
  650. ppl^[J] := Temp;
  651. // swap pointers
  652. oTemp := oppl^[I];
  653. oppl^[I] := oppl^[J];
  654. oppl^[J] := oTemp;
  655. end;
  656. end;
  657. end;
  658. // ------------------
  659. // ------------------ TGLBaseList ------------------
  660. // ------------------
  661. constructor TGLBaseList.Create;
  662. begin
  663. inherited Create;
  664. FOptions := [bloSetCountResetsMemory];
  665. end;
  666. destructor TGLBaseList.Destroy;
  667. begin
  668. Clear;
  669. if Assigned(FBufferItem) then
  670. FreeMem(FBufferItem);
  671. inherited;
  672. end;
  673. procedure TGLBaseList.Assign(Src: TPersistent);
  674. begin
  675. if (Src is TGLBaseList) then
  676. begin
  677. SetCapacity(TGLBaseList(Src).Count);
  678. FGrowthDelta := TGLBaseList(Src).FGrowthDelta;
  679. FCount := FCapacity;
  680. FTagString := TGLBaseList(Src).FTagString;
  681. Inc(FRevision);
  682. end
  683. else
  684. inherited;
  685. end;
  686. procedure TGLBaseList.DefineProperties(AFiler: TFiler);
  687. begin
  688. inherited DefineProperties(AFiler);
  689. AFiler.DefineProperty('Items', ReadItemsData, WriteItemsData, True);
  690. end;
  691. procedure TGLBaseList.ReadItemsData(AReader: TReader);
  692. var
  693. lData: AnsiString;
  694. lOutputText: string;
  695. begin
  696. lOutputText := AReader.ReadString;
  697. SetLength(lData, Length(lOutputText) div 2 + 1);
  698. HexToBin(PChar(lOutputText), PAnsiChar(lData), Length(lData));
  699. LoadFromString(string(lData));
  700. end;
  701. procedure TGLBaseList.WriteItemsData(AWriter: TWriter);
  702. var
  703. lData: AnsiString;
  704. lOutputText: String;
  705. begin
  706. lData := AnsiString(SaveToString);
  707. SetLength(lOutputText, Length(lData) * 2);
  708. BinToHex(PAnsiChar(lData), PChar(lOutputText), Length(lData));
  709. AWriter.WriteString(lOutputText);
  710. end;
  711. procedure TGLBaseList.WriteToFiler(writer: TGVirtualWriter);
  712. begin
  713. inherited;
  714. with writer do
  715. begin
  716. WriteInteger(0); // Archive Version 0
  717. WriteInteger(Count);
  718. WriteInteger(FItemSize);
  719. if Count > 0 then
  720. write(FBaseList[0], Count * FItemSize);
  721. end;
  722. end;
  723. procedure TGLBaseList.ReadFromFiler(reader: TGVirtualReader);
  724. var
  725. archiveVersion: Integer;
  726. begin
  727. inherited;
  728. archiveVersion := reader.ReadInteger;
  729. if archiveVersion = 0 then
  730. with reader do
  731. begin
  732. FCount := ReadInteger;
  733. FItemSize := ReadInteger;
  734. SetCapacity(Count);
  735. if Count > 0 then
  736. read(FBaseList[0], Count * FItemSize);
  737. end
  738. else
  739. RaiseFilerException(archiveVersion);
  740. Inc(FRevision);
  741. end;
  742. procedure TGLBaseList.SetCount(Val: Integer);
  743. begin
  744. Assert(Val >= 0);
  745. if Val > FCapacity then
  746. SetCapacity(Val);
  747. if (Val > FCount) and (bloSetCountResetsMemory in FOptions) then
  748. FillChar(FBaseList[FItemSize * FCount], (Val - FCount) * FItemSize, 0);
  749. FCount := Val;
  750. Inc(FRevision);
  751. end;
  752. procedure TGLBaseList.SetCapacity(newCapacity: Integer);
  753. begin
  754. if newCapacity <> FCapacity then
  755. begin
  756. if bloExternalMemory in FOptions then
  757. begin
  758. Exclude(FOptions, bloExternalMemory);
  759. FBaseList := nil;
  760. end;
  761. ReallocMem(FBaseList, newCapacity * FItemSize);
  762. FCapacity := newCapacity;
  763. Inc(FRevision);
  764. end;
  765. end;
  766. procedure TGLBaseList.AddNulls(nbVals: Cardinal);
  767. begin
  768. if Integer(nbVals) + Count > Capacity then
  769. SetCapacity(Integer(nbVals) + Count);
  770. FillChar(FBaseList[FCount * FItemSize], Integer(nbVals) * FItemSize, 0);
  771. FCount := FCount + Integer(nbVals);
  772. Inc(FRevision);
  773. end;
  774. procedure TGLBaseList.InsertNulls(Index: Integer; nbVals: Cardinal);
  775. var
  776. nc: Integer;
  777. begin
  778. {$IFOPT R+}
  779. Assert(Cardinal(Index) < Cardinal(FCount));
  780. {$ENDIF}
  781. if nbVals > 0 then
  782. begin
  783. nc := FCount + Integer(nbVals);
  784. if nc > FCapacity then
  785. SetCapacity(nc);
  786. if Index < FCount then
  787. System.Move(FBaseList[Index * FItemSize],
  788. FBaseList[(Index + Integer(nbVals)) * FItemSize],
  789. (FCount - Index) * FItemSize);
  790. FillChar(FBaseList[Index * FItemSize], Integer(nbVals) * FItemSize, 0);
  791. FCount := nc;
  792. Inc(FRevision);
  793. end;
  794. end;
  795. procedure TGLBaseList.AdjustCapacityToAtLeast(const size: Integer);
  796. begin
  797. if Capacity < size then
  798. Capacity := size;
  799. end;
  800. function TGLBaseList.DataSize: Integer;
  801. begin
  802. Result := FItemSize * FCount;
  803. end;
  804. function TGLBaseList.BufferItem: PByteArray;
  805. begin
  806. if not Assigned(FBufferItem) then
  807. GetMem(FBufferItem, FItemSize);
  808. Result := FBufferItem;
  809. end;
  810. function TGLBaseList.GetSetCountResetsMemory: Boolean;
  811. begin
  812. Result := (bloSetCountResetsMemory in FOptions);
  813. end;
  814. procedure TGLBaseList.SetSetCountResetsMemory(const Val: Boolean);
  815. begin
  816. if Val then
  817. Include(FOptions, bloSetCountResetsMemory)
  818. else
  819. Exclude(FOptions, bloSetCountResetsMemory);
  820. end;
  821. procedure TGLBaseList.UseMemory(rangeStart: Pointer; rangeCapacity: Integer);
  822. begin
  823. rangeCapacity := rangeCapacity div FItemSize;
  824. if rangeCapacity < FCount then
  825. Exit;
  826. // transfer data
  827. System.Move(FBaseList^, rangeStart^, FCount * FItemSize);
  828. if not (bloExternalMemory in FOptions) then
  829. begin
  830. FreeMem(FBaseList);
  831. Include(FOptions, bloExternalMemory);
  832. end;
  833. FBaseList := rangeStart;
  834. FCapacity := rangeCapacity;
  835. SetCapacity(FCapacity); // notify subclasses
  836. end;
  837. procedure TGLBaseList.Flush;
  838. begin
  839. if Assigned(Self) then
  840. begin
  841. SetCount(0);
  842. end;
  843. end;
  844. procedure TGLBaseList.Clear;
  845. begin
  846. if Assigned(Self) then
  847. begin
  848. SetCount(0);
  849. SetCapacity(0);
  850. end;
  851. end;
  852. procedure TGLBaseList.Delete(Index: Integer);
  853. begin
  854. {$IFOPT R+}
  855. Assert(Cardinal(index) < Cardinal(FCount));
  856. {$ENDIF}
  857. Dec(FCount);
  858. if Index < FCount then
  859. System.Move(FBaseList[(Index + 1) * FItemSize],
  860. FBaseList[Index * FItemSize],
  861. (FCount - Index) * FItemSize);
  862. Inc(FRevision);
  863. end;
  864. procedure TGLBaseList.DeleteItems(Index: Integer; nbVals: Cardinal);
  865. begin
  866. {$IFOPT R+}
  867. Assert(Cardinal(index) < Cardinal(FCount));
  868. {$ENDIF}
  869. if nbVals > 0 then
  870. begin
  871. if Index + Integer(nbVals) < FCount then
  872. begin
  873. System.Move(FBaseList[(Index + Integer(nbVals)) * FItemSize],
  874. FBaseList[Index * FItemSize],
  875. (FCount - Index - Integer(nbVals)) * FItemSize);
  876. end;
  877. Dec(FCount, nbVals);
  878. Inc(FRevision);
  879. end;
  880. end;
  881. procedure TGLBaseList.Exchange(index1, index2: Integer);
  882. var
  883. buf: Integer;
  884. p: PIntegerArray;
  885. begin
  886. {$IFOPT R+}
  887. Assert((Cardinal(index1) < Cardinal(FCount)) and (Cardinal(index2) < Cardinal(FCount)));
  888. {$ENDIF}
  889. if FItemSize = 4 then
  890. begin
  891. p := PIntegerArray(FBaseList);
  892. buf := p^[index1];
  893. p^[index1] := p^[index2];
  894. p^[index2] := buf;
  895. end
  896. else
  897. begin
  898. System.Move(FBaseList[index1 * FItemSize], BufferItem[0], FItemSize);
  899. System.Move(FBaseList[index2 * FItemSize], FBaseList[index1 * FItemSize], FItemSize);
  900. System.Move(BufferItem[0], FBaseList[index2 * FItemSize], FItemSize);
  901. end;
  902. Inc(FRevision);
  903. end;
  904. procedure TGLBaseList.Move(curIndex, newIndex: Integer);
  905. begin
  906. if curIndex <> newIndex then
  907. begin
  908. {$IFOPT R+}
  909. Assert(Cardinal(newIndex) < Cardinal(Count));
  910. Assert(Cardinal(curIndex) < Cardinal(Count));
  911. {$ENDIF}
  912. if FItemSize = 4 then
  913. PInteger(BufferItem)^ := PInteger(@FBaseList[curIndex * FItemSize])^
  914. else
  915. System.Move(FBaseList[curIndex * FItemSize], BufferItem[0], FItemSize);
  916. if curIndex < newIndex then
  917. begin
  918. // curIndex+1 necessarily exists since curIndex<newIndex and newIndex<Count
  919. System.Move(FBaseList[(curIndex + 1) * FItemSize], FBaseList[curIndex * FItemSize],
  920. (newIndex - curIndex) * FItemSize);
  921. end
  922. else
  923. begin
  924. // newIndex+1 necessarily exists since newIndex<curIndex and curIndex<Count
  925. System.Move(FBaseList[newIndex * FItemSize], FBaseList[(newIndex + 1) * FItemSize],
  926. (curIndex - newIndex) * FItemSize);
  927. end;
  928. if FItemSize = 4 then
  929. PInteger(@FBaseList[newIndex * FItemSize])^ := PInteger(BufferItem)^
  930. else
  931. System.Move(BufferItem[0], FBaseList[newIndex * FItemSize], FItemSize);
  932. Inc(FRevision);
  933. end;
  934. end;
  935. procedure TGLBaseList.Reverse;
  936. var
  937. s, e: Integer;
  938. begin
  939. s := 0;
  940. e := Count - 1;
  941. while s < e do
  942. begin
  943. Exchange(s, e);
  944. Inc(s);
  945. Dec(e);
  946. end;
  947. Inc(FRevision);
  948. end;
  949. // ------------------
  950. // ------------------ TGLBaseVectorList ------------------
  951. // ------------------
  952. procedure TGLBaseVectorList.WriteToFiler(writer: TGVirtualWriter);
  953. begin
  954. inherited;
  955. if Self is TGLTexPointList then
  956. exit;
  957. with writer do
  958. begin
  959. WriteInteger(0); // Archive Version 0
  960. // nothing
  961. end;
  962. end;
  963. procedure TGLBaseVectorList.ReadFromFiler(reader: TGVirtualReader);
  964. var
  965. archiveVersion: Integer;
  966. begin
  967. inherited;
  968. if Self is TGLTexPointList then
  969. exit;
  970. archiveVersion := reader.ReadInteger;
  971. if archiveVersion = 0 then
  972. with reader do
  973. begin
  974. // nothing
  975. end
  976. else
  977. RaiseFilerException(archiveVersion);
  978. end;
  979. procedure TGLBaseVectorList.GetExtents(out min, max: TAffineVector);
  980. var
  981. I, K: Integer;
  982. f: Single;
  983. ref: PFloatArray;
  984. const
  985. cBigValue: Single = 1E50;
  986. cSmallValue: Single = -1E50;
  987. begin
  988. SetVector(min, cBigValue, cBigValue, cBigValue);
  989. SetVector(max, cSmallValue, cSmallValue, cSmallValue);
  990. for I := 0 to Count - 1 do
  991. begin
  992. ref := ItemAddress[I];
  993. for K := 0 to 2 do
  994. begin
  995. f := ref^[K];
  996. if f < min.V[K] then
  997. min.V[K] := f;
  998. if f > max.V[K] then
  999. max.V[K] := f;
  1000. end;
  1001. end;
  1002. end;
  1003. function TGLBaseVectorList.Sum: TAffineVector;
  1004. var
  1005. I: Integer;
  1006. begin
  1007. Result := NullVector;
  1008. for I := 0 to Count - 1 do
  1009. AddVector(Result, PAffineVector(ItemAddress[I])^);
  1010. end;
  1011. procedure TGLBaseVectorList.Normalize;
  1012. var
  1013. I: Integer;
  1014. begin
  1015. for I := 0 to Count - 1 do
  1016. NormalizeVector(PAffineVector(ItemAddress[I])^);
  1017. Inc(FRevision);
  1018. end;
  1019. function TGLBaseVectorList.MaxSpacing(list2: TGLBaseVectorList): Single;
  1020. var
  1021. I: Integer;
  1022. s: Single;
  1023. begin
  1024. Assert(list2.Count = Count);
  1025. Result := 0;
  1026. for I := 0 to Count - 1 do
  1027. begin
  1028. s := VectorSpacing(PAffineVector(ItemAddress[I])^,
  1029. PAffineVector(list2.ItemAddress[I])^);
  1030. if s > Result then
  1031. Result := s;
  1032. end;
  1033. end;
  1034. procedure TGLBaseVectorList.Translate(const delta: TAffineVector);
  1035. var
  1036. I: Integer;
  1037. begin
  1038. for I := 0 to Count - 1 do
  1039. AddVector(PAffineVector(ItemAddress[I])^, delta);
  1040. Inc(FRevision);
  1041. end;
  1042. procedure TGLBaseVectorList.Translate(const delta: TGLBaseVectorList);
  1043. var
  1044. I: Integer;
  1045. begin
  1046. Assert(Count <= delta.Count);
  1047. for I := 0 to Count - 1 do
  1048. AddVector(PAffineVector(ItemAddress[I])^, PAffineVector(delta.ItemAddress[I])^);
  1049. Inc(FRevision);
  1050. end;
  1051. procedure TGLBaseVectorList.TranslateInv(const delta: TGLBaseVectorList);
  1052. var
  1053. I: Integer;
  1054. begin
  1055. Assert(Count <= delta.Count);
  1056. for I := 0 to Count - 1 do
  1057. SubtractVector(PAffineVector(ItemAddress[I])^, PAffineVector(delta.ItemAddress[I])^);
  1058. Inc(FRevision);
  1059. end;
  1060. procedure TGLBaseVectorList.AngleLerp(const list1, list2: TGLBaseVectorList; lerpFactor: Single);
  1061. var
  1062. I: Integer;
  1063. begin
  1064. Assert(list1.Count = list2.Count);
  1065. if list1 <> list2 then
  1066. begin
  1067. if lerpFactor = 0 then
  1068. Assign(list1)
  1069. else
  1070. if lerpFactor = 1 then
  1071. Assign(list2)
  1072. else
  1073. begin
  1074. Capacity := list1.Count;
  1075. FCount := list1.Count;
  1076. for I := 0 to list1.Count - 1 do
  1077. PAffineVector(ItemAddress[I])^ := VectorAngleLerp(PAffineVector(list1.ItemAddress[I])^,
  1078. PAffineVector(list2.ItemAddress[I])^,
  1079. lerpFactor);
  1080. end;
  1081. end
  1082. else
  1083. Assign(list1);
  1084. Inc(FRevision);
  1085. end;
  1086. procedure TGLBaseVectorList.AngleCombine(const list1: TGLBaseVectorList; intensity: Single);
  1087. var
  1088. I: Integer;
  1089. begin
  1090. Assert(list1.Count = Count);
  1091. for I := 0 to Count - 1 do
  1092. PAffineVector(ItemAddress[I])^ := VectorAngleCombine(PAffineVector(ItemAddress[I])^,
  1093. PAffineVector(list1.ItemAddress[I])^,
  1094. intensity);
  1095. Inc(FRevision);
  1096. end;
  1097. procedure TGLBaseVectorList.Combine(const list2: TGLBaseVectorList; factor: Single);
  1098. var
  1099. I: Integer;
  1100. begin
  1101. Assert(list2.Count >= Count);
  1102. for I := 0 to Count - 1 do
  1103. CombineVector(PAffineVector(ItemAddress[I])^,
  1104. PAffineVector(list2.ItemAddress[I])^,
  1105. factor);
  1106. Inc(FRevision);
  1107. end;
  1108. function TGLBaseVectorList.GetItemAddress(Index: Integer): PFloatArray;
  1109. begin
  1110. {$IFOPT R+}
  1111. Assert(Cardinal(Index) < Cardinal(FCount));
  1112. {$ENDIF}
  1113. Result := PFloatArray(@FBaseList[Index * FItemSize]);
  1114. end;
  1115. // ------------------
  1116. // ------------------ TGLAffineVectorList ------------------
  1117. // ------------------
  1118. constructor TGLAffineVectorList.Create;
  1119. begin
  1120. FItemSize := SizeOf(TAffineVector);
  1121. inherited Create;
  1122. FGrowthDelta := cDefaultListGrowthDelta;
  1123. end;
  1124. procedure TGLAffineVectorList.Assign(Src: TPersistent);
  1125. begin
  1126. if Assigned(Src) then
  1127. begin
  1128. inherited;
  1129. if (Src is TGLAffineVectorList) then
  1130. System.Move(TGLAffineVectorList(Src).FList^, FList^, FCount * SizeOf(TAffineVector));
  1131. end
  1132. else
  1133. Clear;
  1134. end;
  1135. function TGLAffineVectorList.Add(const item: TAffineVector): Integer;
  1136. begin
  1137. Result := FCount;
  1138. if Result = FCapacity then
  1139. SetCapacity(FCapacity + FGrowthDelta);
  1140. FList^[Result] := Item;
  1141. Inc(FCount);
  1142. Inc(FRevision);
  1143. end;
  1144. function TGLAffineVectorList.Add(const item: TGLVector): Integer;
  1145. begin
  1146. Result := Add(PAffineVector(@item)^);
  1147. end;
  1148. procedure TGLAffineVectorList.Add(const i1, i2: TAffineVector);
  1149. begin
  1150. Inc(FCount, 2);
  1151. while FCount > FCapacity do
  1152. SetCapacity(FCapacity + FGrowthDelta);
  1153. FList^[FCount - 2] := i1;
  1154. FList^[FCount - 1] := i2;
  1155. Inc(FRevision);
  1156. end;
  1157. procedure TGLAffineVectorList.Add(const i1, i2, i3: TAffineVector);
  1158. begin
  1159. Inc(FCount, 3);
  1160. while FCount > FCapacity do
  1161. SetCapacity(FCapacity + FGrowthDelta);
  1162. FList^[FCount - 3] := i1;
  1163. FList^[FCount - 2] := i2;
  1164. FList^[FCount - 1] := i3;
  1165. Inc(FRevision);
  1166. end;
  1167. function TGLAffineVectorList.Add(const item: TVector2f): Integer;
  1168. begin
  1169. Result := Add(AffineVectorMake(item.X, item.Y, 0));
  1170. end;
  1171. function TGLAffineVectorList.Add(const item: TTexPoint): Integer;
  1172. begin
  1173. Result := Add(AffineVectorMake(item.S, item.T, 0));
  1174. end;
  1175. function TGLAffineVectorList.Add(const X, Y: Single): Integer;
  1176. var
  1177. v: PAffineVector;
  1178. begin
  1179. Result := FCount;
  1180. Inc(FCount);
  1181. while FCount > FCapacity do
  1182. SetCapacity(FCapacity + FGrowthDelta);
  1183. v := @List[Result];
  1184. v^.X := X;
  1185. v^.Y := Y;
  1186. v^.Z := 0;
  1187. Inc(FRevision);
  1188. end;
  1189. function TGLAffineVectorList.Add(const X, Y, Z: Single): Integer;
  1190. var
  1191. v: PAffineVector;
  1192. begin
  1193. Result := FCount;
  1194. Inc(FCount);
  1195. while FCount > FCapacity do
  1196. SetCapacity(FCapacity + FGrowthDelta);
  1197. v := @List[Result];
  1198. v^.X := X;
  1199. v^.Y := Y;
  1200. v^.Z := Z;
  1201. Inc(FRevision);
  1202. end;
  1203. function TGLAffineVectorList.Add(const X, Y, Z: Integer): Integer;
  1204. var
  1205. v: PAffineVector;
  1206. begin
  1207. Result := FCount;
  1208. if Result = FCapacity then
  1209. SetCapacity(FCapacity + FGrowthDelta);
  1210. v := @List[Result];
  1211. v^.X := X;
  1212. v^.Y := Y;
  1213. v^.Z := Z;
  1214. Inc(FCount);
  1215. Inc(FRevision);
  1216. end;
  1217. function TGLAffineVectorList.AddNC(const X, Y, Z: Integer): Integer;
  1218. var
  1219. v: PAffineVector;
  1220. begin
  1221. Result := FCount;
  1222. v := @List[Result];
  1223. v^.X := X;
  1224. v^.Y := Y;
  1225. v^.Z := Z;
  1226. Inc(FCount);
  1227. Inc(FRevision);
  1228. end;
  1229. function TGLAffineVectorList.Add(const xy: PIntegerArray; const Z: Integer): Integer;
  1230. var
  1231. v: PAffineVector;
  1232. begin
  1233. Result := FCount;
  1234. if Result = FCapacity then
  1235. SetCapacity(FCapacity + FGrowthDelta);
  1236. v := @List[Result];
  1237. v^.X := xy^[0];
  1238. v^.Y := xy^[1];
  1239. v^.Z := Z;
  1240. Inc(FCount);
  1241. Inc(FRevision);
  1242. end;
  1243. function TGLAffineVectorList.AddNC(const xy: PIntegerArray; const Z: Integer): Integer;
  1244. var
  1245. v: PAffineVector;
  1246. begin
  1247. Result := FCount;
  1248. v := @List[Result];
  1249. v^.X := xy^[0];
  1250. v^.Y := xy^[1];
  1251. v^.Z := Z;
  1252. Inc(FCount);
  1253. Inc(FRevision);
  1254. end;
  1255. procedure TGLAffineVectorList.Add(const list: TGLAffineVectorList);
  1256. begin
  1257. if Assigned(list) and (list.Count > 0) then
  1258. begin
  1259. if Count + list.Count > Capacity then
  1260. Capacity := Count + list.Count;
  1261. System.Move(list.FList[0], FList[Count], list.Count * SizeOf(TAffineVector));
  1262. Inc(FCount, list.Count);
  1263. end;
  1264. Inc(FRevision);
  1265. end;
  1266. function TGLAffineVectorList.Get(Index: Integer): TAffineVector;
  1267. begin
  1268. {$IFOPT R+}
  1269. Assert(Cardinal(Index) < Cardinal(FCount));
  1270. {$ENDIF}
  1271. Result := FList^[Index];
  1272. end;
  1273. procedure TGLAffineVectorList.Insert(Index: Integer; const Item: TAffineVector);
  1274. begin
  1275. {$IFOPT R+}
  1276. Assert(Cardinal(Index) < Cardinal(FCount));
  1277. {$ENDIF}
  1278. if FCount = FCapacity then
  1279. SetCapacity(FCapacity + FGrowthDelta);
  1280. if Index < FCount then
  1281. System.Move(FList[Index], FList[Index + 1],
  1282. (FCount - Index) * SizeOf(TAffineVector));
  1283. FList^[Index] := Item;
  1284. Inc(FCount);
  1285. Inc(FRevision);
  1286. end;
  1287. function TGLAffineVectorList.IndexOf(const item: TAffineVector): Integer;
  1288. var
  1289. I: Integer;
  1290. begin
  1291. Result := -1;
  1292. for I := 0 to Count - 1 do
  1293. if VectorEquals(item, FList^[I]) then
  1294. begin
  1295. Result := I;
  1296. Break;
  1297. end;
  1298. end;
  1299. function TGLAffineVectorList.FindOrAdd(const item: TAffineVector): Integer;
  1300. begin
  1301. Result := IndexOf(item);
  1302. if Result < 0 then
  1303. begin
  1304. Result := Add(item);
  1305. Inc(FRevision);
  1306. end;
  1307. end;
  1308. procedure TGLAffineVectorList.Put(Index: Integer; const Item: TAffineVector);
  1309. begin
  1310. {$IFOPT R+}
  1311. Assert(Cardinal(Index) < Cardinal(FCount));
  1312. {$ENDIF}
  1313. FList^[Index] := Item;
  1314. Inc(FRevision);
  1315. end;
  1316. procedure TGLAffineVectorList.SetCapacity(NewCapacity: Integer);
  1317. begin
  1318. inherited;
  1319. FList := PAffineVectorArray(FBaseList);
  1320. end;
  1321. procedure TGLAffineVectorList.Push(const Val: TAffineVector);
  1322. begin
  1323. Add(Val);
  1324. end;
  1325. function TGLAffineVectorList.Pop: TAffineVector;
  1326. begin
  1327. if FCount > 0 then
  1328. begin
  1329. Result := Get(FCount - 1);
  1330. Delete(FCount - 1);
  1331. Inc(FRevision);
  1332. end
  1333. else
  1334. Result := NullVector;
  1335. end;
  1336. procedure TGLAffineVectorList.Translate(const delta: TAffineVector);
  1337. begin
  1338. VectorArrayAdd(FList, delta, Count, FList);
  1339. Inc(FRevision);
  1340. end;
  1341. procedure TGLAffineVectorList.Translate(const delta: TAffineVector; base, nb: Integer);
  1342. begin
  1343. VectorArrayAdd(@FList[base], delta, nb, @FList[base]);
  1344. Inc(FRevision);
  1345. end;
  1346. procedure TGLAffineVectorList.TranslateItem(Index: Integer; const delta: TAffineVector);
  1347. begin
  1348. {$IFOPT R+}
  1349. Assert(Cardinal(Index) < Cardinal(FCount));
  1350. {$ENDIF}
  1351. AddVector(FList^[Index], delta);
  1352. Inc(FRevision);
  1353. end;
  1354. procedure TGLAffineVectorList.TranslateItems(Index: Integer; const delta: TAffineVector; nb: Integer);
  1355. begin
  1356. nb := Index + nb;
  1357. {$IFOPT R+}
  1358. Assert(Cardinal(index) < Cardinal(FCount));
  1359. if nb > FCount then
  1360. nb := FCount;
  1361. {$ENDIF}
  1362. VectorArrayAdd(@FList[Index], delta, nb - Index, @FList[Index]);
  1363. Inc(FRevision);
  1364. end;
  1365. procedure TGLAffineVectorList.CombineItem(Index: Integer; const vector: TAffineVector; const f: Single);
  1366. begin
  1367. {$IFOPT R+}
  1368. Assert(Cardinal(Index) < Cardinal(FCount));
  1369. {$ENDIF}
  1370. CombineVector(FList^[Index], vector, @f);
  1371. Inc(FRevision);
  1372. end;
  1373. procedure TGLAffineVectorList.TransformAsPoints(const matrix: TGLMatrix);
  1374. var
  1375. I: Integer;
  1376. begin
  1377. for I := 0 to FCount - 1 do
  1378. FList^[I] := VectorTransform(FList^[I], matrix);
  1379. Inc(FRevision);
  1380. end;
  1381. procedure TGLAffineVectorList.TransformAsVectors(const matrix: TGLMatrix);
  1382. var
  1383. m: TAffineMatrix;
  1384. begin
  1385. if FCount > 0 then
  1386. begin
  1387. SetMatrix(m, matrix);
  1388. TransformAsVectors(m);
  1389. end;
  1390. end;
  1391. procedure TGLAffineVectorList.TransformAsVectors(const matrix: TAffineMatrix);
  1392. var
  1393. I: Integer;
  1394. begin
  1395. for I := 0 to FCount - 1 do
  1396. FList^[I] := VectorTransform(FList^[I], matrix);
  1397. Inc(FRevision);
  1398. end;
  1399. procedure TGLAffineVectorList.Normalize;
  1400. begin
  1401. NormalizeVectorArray(List, Count);
  1402. Inc(FRevision);
  1403. end;
  1404. procedure TGLAffineVectorList.Lerp(const list1, list2: TGLBaseVectorList; lerpFactor: Single);
  1405. begin
  1406. if (list1 is TGLAffineVectorList) and (list2 is TGLAffineVectorList) then
  1407. begin
  1408. Assert(list1.Count = list2.Count);
  1409. Capacity := list1.Count;
  1410. FCount := list1.Count;
  1411. VectorArrayLerp(TGLAffineVectorList(list1).List, TGLAffineVectorList(list2).List,
  1412. lerpFactor, FCount, List);
  1413. Inc(FRevision);
  1414. end;
  1415. end;
  1416. procedure TGLAffineVectorList.Scale(factor: Single);
  1417. begin
  1418. if (Count > 0) and (factor <> 1) then
  1419. begin
  1420. ScaleFloatArray(@FList[0].X, Count * 3, factor);
  1421. Inc(FRevision);
  1422. end;
  1423. end;
  1424. procedure TGLAffineVectorList.Scale(const factors: TAffineVector);
  1425. var
  1426. I: Integer;
  1427. begin
  1428. for I := 0 to Count - 1 do
  1429. ScaleVector(FList^[I], factors);
  1430. Inc(FRevision);
  1431. end;
  1432. // ------------------
  1433. // ------------------ TGLVectorList ------------------
  1434. // ------------------
  1435. constructor TGLVectorList.Create;
  1436. begin
  1437. FItemSize := SizeOf(TGLVector);
  1438. inherited Create;
  1439. FGrowthDelta := cDefaultListGrowthDelta;
  1440. end;
  1441. procedure TGLVectorList.Assign(Src: TPersistent);
  1442. begin
  1443. if Assigned(Src) then
  1444. begin
  1445. inherited;
  1446. if (Src is TGLVectorList) then
  1447. System.Move(TGLVectorList(Src).FList^, FList^, FCount * SizeOf(TGLVector));
  1448. end
  1449. else
  1450. Clear;
  1451. end;
  1452. function TGLVectorList.Add(const item: TGLVector): Integer;
  1453. begin
  1454. Result := FCount;
  1455. if Result = FCapacity then
  1456. SetCapacity(FCapacity + FGrowthDelta);
  1457. FList^[Result] := Item;
  1458. Inc(FCount);
  1459. end;
  1460. function TGLVectorList.Add(const item: TAffineVector; w: Single): Integer;
  1461. begin
  1462. Result := Add(VectorMake(item, w));
  1463. end;
  1464. function TGLVectorList.Add(const X, Y, Z, w: Single): Integer;
  1465. begin
  1466. Result := Add(VectorMake(X, Y, Z, w));
  1467. end;
  1468. procedure TGLVectorList.Add(const i1, i2, i3: TAffineVector; w: Single);
  1469. begin
  1470. Inc(FCount, 3);
  1471. while FCount > FCapacity do
  1472. SetCapacity(FCapacity + FGrowthDelta);
  1473. PAffineVector(@FList[FCount - 3])^ := i1;
  1474. FList^[FCount - 3].W := w;
  1475. PAffineVector(@FList[FCount - 2])^ := i2;
  1476. FList^[FCount - 2].W := w;
  1477. PAffineVector(@FList[FCount - 1])^ := i3;
  1478. FList^[FCount - 1].W := w;
  1479. end;
  1480. function TGLVectorList.AddVector(const item: TAffineVector): Integer;
  1481. begin
  1482. Result := Add(VectorMake(item));
  1483. end;
  1484. function TGLVectorList.AddPoint(const item: TAffineVector): Integer;
  1485. begin
  1486. Result := Add(PointMake(item));
  1487. end;
  1488. function TGLVectorList.AddPoint(const X, Y: Single; const Z: Single = 0): Integer;
  1489. begin
  1490. Result := Add(PointMake(X, Y, Z));
  1491. end;
  1492. function TGLVectorList.Get(Index: Integer): TGLVector;
  1493. begin
  1494. {$IFOPT R+}
  1495. Assert(Cardinal(Index) < Cardinal(FCount));
  1496. {$ENDIF}
  1497. Result := FList^[Index];
  1498. end;
  1499. procedure TGLVectorList.Insert(Index: Integer; const Item: TGLVector);
  1500. begin
  1501. {$IFOPT R+}
  1502. Assert(Cardinal(Index) < Cardinal(FCount));
  1503. {$ENDIF}
  1504. if FCount = FCapacity then
  1505. SetCapacity(FCapacity + FGrowthDelta);
  1506. if Index < FCount then
  1507. System.Move(FList[Index], FList[Index + 1],
  1508. (FCount - Index) * SizeOf(TGLVector));
  1509. FList^[Index] := Item;
  1510. Inc(FCount);
  1511. end;
  1512. procedure TGLVectorList.Put(Index: Integer; const Item: TGLVector);
  1513. begin
  1514. {$IFOPT R+}
  1515. Assert(Cardinal(Index) < Cardinal(FCount));
  1516. {$ENDIF}
  1517. FList^[Index] := Item;
  1518. end;
  1519. procedure TGLVectorList.SetCapacity(NewCapacity: Integer);
  1520. begin
  1521. inherited;
  1522. FList := PVectorArray(FBaseList);
  1523. end;
  1524. procedure TGLVectorList.Push(const Val: TGLVector);
  1525. begin
  1526. Add(Val);
  1527. end;
  1528. function TGLVectorList.Pop: TGLVector;
  1529. begin
  1530. if FCount > 0 then
  1531. begin
  1532. Result := Get(FCount - 1);
  1533. Delete(FCount - 1);
  1534. end
  1535. else
  1536. Result := NullHmgVector;
  1537. end;
  1538. function TGLVectorList.IndexOf(const item: TGLVector): Integer;
  1539. var
  1540. I: Integer;
  1541. begin
  1542. Result := -1;
  1543. for I := 0 to Count - 1 do
  1544. if VectorEquals(item, FList^[I]) then
  1545. begin
  1546. Result := I;
  1547. Break;
  1548. end;
  1549. end;
  1550. function TGLVectorList.FindOrAdd(const item: TGLVector): Integer;
  1551. begin
  1552. Result := IndexOf(item);
  1553. if Result < 0 then
  1554. Result := Add(item);
  1555. end;
  1556. function TGLVectorList.FindOrAddPoint(const item: TAffineVector): Integer;
  1557. var
  1558. ptItem: TGLVector;
  1559. begin
  1560. MakePoint(ptItem, item);
  1561. Result := IndexOf(ptItem);
  1562. if Result < 0 then
  1563. Result := Add(ptItem);
  1564. end;
  1565. procedure TGLVectorList.Lerp(const list1, list2: TGLBaseVectorList; lerpFactor: Single);
  1566. begin
  1567. if (list1 is TGLVectorList) and (list2 is TGLVectorList) then
  1568. begin
  1569. Assert(list1.Count = list2.Count);
  1570. Capacity := list1.Count;
  1571. FCount := list1.Count;
  1572. VectorArrayLerp(TGLVectorList(list1).List, TGLVectorList(list2).List,
  1573. lerpFactor, FCount, List);
  1574. end;
  1575. end;
  1576. // ------------------
  1577. // ------------------ TGLTexPointList ------------------
  1578. // ------------------
  1579. constructor TGLTexPointList.Create;
  1580. begin
  1581. FItemSize := SizeOf(TTexPoint);
  1582. inherited Create;
  1583. FGrowthDelta := cDefaultListGrowthDelta;
  1584. end;
  1585. procedure TGLTexPointList.Assign(Src: TPersistent);
  1586. begin
  1587. if Assigned(Src) then
  1588. begin
  1589. inherited;
  1590. if (Src is TGLTexPointList) then
  1591. System.Move(TGLTexPointList(Src).FList^, FList^, FCount * SizeOf(TTexPoint));
  1592. end
  1593. else
  1594. Clear;
  1595. end;
  1596. function TGLTexPointList.IndexOf(const item: TTexpoint): Integer;
  1597. var
  1598. I: Integer;
  1599. begin
  1600. Result := -1;
  1601. for I := 0 to Count - 1 do
  1602. if TexpointEquals(FList^[I], item) then
  1603. begin
  1604. Result := I;
  1605. Break;
  1606. end;
  1607. end;
  1608. function TGLTexPointList.FindOrAdd(const item: TTexPoint): Integer;
  1609. begin
  1610. Result := IndexOf(item);
  1611. if Result < 0 then
  1612. Result := Add(item);
  1613. end;
  1614. function TGLTexPointList.Add(const item: TTexPoint): Integer;
  1615. begin
  1616. Result := FCount;
  1617. if Result = FCapacity then
  1618. SetCapacity(FCapacity + FGrowthDelta);
  1619. FList^[Result] := Item;
  1620. Inc(FCount);
  1621. end;
  1622. function TGLTexPointList.Add(const item: TVector2f): Integer;
  1623. begin
  1624. Result := FCount;
  1625. if Result = FCapacity then
  1626. SetCapacity(FCapacity + FGrowthDelta);
  1627. FList^[Result] := PTexPoint(@Item)^;
  1628. Inc(FCount);
  1629. end;
  1630. function TGLTexPointList.Add(const texS, Text: Single): Integer;
  1631. begin
  1632. Result := FCount;
  1633. if Result = FCapacity then
  1634. SetCapacity(FCapacity + FGrowthDelta);
  1635. with FList^[Result] do
  1636. begin
  1637. s := texS;
  1638. t := Text;
  1639. end;
  1640. Inc(FCount);
  1641. end;
  1642. function TGLTexPointList.Add(const texS, Text: Integer): Integer;
  1643. begin
  1644. Result := FCount;
  1645. if Result = FCapacity then
  1646. SetCapacity(FCapacity + FGrowthDelta);
  1647. with FList^[Result] do
  1648. begin
  1649. s := texS;
  1650. t := Text;
  1651. end;
  1652. Inc(FCount);
  1653. end;
  1654. function TGLTexPointList.AddNC(const texS, Text: Integer): Integer;
  1655. begin
  1656. Result := FCount;
  1657. with FList^[Result] do
  1658. begin
  1659. s := texS;
  1660. t := Text;
  1661. end;
  1662. Inc(FCount);
  1663. end;
  1664. function TGLTexPointList.Add(const texST: PIntegerArray): Integer;
  1665. begin
  1666. Result := FCount;
  1667. if Result = FCapacity then
  1668. SetCapacity(FCapacity + FGrowthDelta);
  1669. with FList^[Result] do
  1670. begin
  1671. s := texST^[0];
  1672. t := texST^[1];
  1673. end;
  1674. Inc(FCount);
  1675. end;
  1676. function TGLTexPointList.AddNC(const texST: PIntegerArray): Integer;
  1677. begin
  1678. Result := FCount;
  1679. with FList^[Result] do
  1680. begin
  1681. s := texST^[0];
  1682. t := texST^[1];
  1683. end;
  1684. Inc(FCount);
  1685. end;
  1686. function TGLTexPointList.Get(Index: Integer): TTexPoint;
  1687. begin
  1688. {$IFOPT R+}
  1689. Assert(Cardinal(Index) < Cardinal(FCount));
  1690. {$ENDIF}
  1691. Result := FList^[Index];
  1692. end;
  1693. procedure TGLTexPointList.Insert(Index: Integer; const Item: TTexPoint);
  1694. begin
  1695. {$IFOPT R+}
  1696. Assert(Cardinal(Index) < Cardinal(FCount));
  1697. {$ENDIF}
  1698. if FCount = FCapacity then
  1699. SetCapacity(FCapacity + FGrowthDelta);
  1700. if Index < FCount then
  1701. System.Move(FList[Index], FList[Index + 1],
  1702. (FCount - Index) * SizeOf(TTexPoint));
  1703. FList^[Index] := Item;
  1704. Inc(FCount);
  1705. end;
  1706. procedure TGLTexPointList.Put(Index: Integer; const Item: TTexPoint);
  1707. begin
  1708. {$IFOPT R+}
  1709. Assert(Cardinal(Index) < Cardinal(FCount));
  1710. {$ENDIF}
  1711. FList^[Index] := Item;
  1712. end;
  1713. procedure TGLTexPointList.SetCapacity(NewCapacity: Integer);
  1714. begin
  1715. inherited;
  1716. FList := PTexPointArray(FBaseList);
  1717. end;
  1718. procedure TGLTexPointList.Push(const Val: TTexPoint);
  1719. begin
  1720. Add(Val);
  1721. end;
  1722. function TGLTexPointList.Pop: TTexPoint;
  1723. begin
  1724. if FCount > 0 then
  1725. begin
  1726. Result := Get(FCount - 1);
  1727. Delete(FCount - 1);
  1728. end
  1729. else
  1730. Result := NullTexPoint;
  1731. end;
  1732. procedure TGLTexPointList.Translate(const delta: TTexPoint);
  1733. begin
  1734. TexPointArrayAdd(List, delta, FCount, FList);
  1735. end;
  1736. procedure TGLTexPointList.ScaleAndTranslate(const scale, delta: TTexPoint);
  1737. begin
  1738. TexPointArrayScaleAndAdd(FList, delta, FCount, scale, FList);
  1739. end;
  1740. procedure TGLTexPointList.ScaleAndTranslate(const scale, delta: TTexPoint; base, nb: Integer);
  1741. var
  1742. p: PTexPointArray;
  1743. begin
  1744. p := @FList[base];
  1745. TexPointArrayScaleAndAdd(p, delta, nb, scale, p);
  1746. end;
  1747. procedure TGLTexPointList.Lerp(const list1, list2: TGLBaseVectorList; lerpFactor: Single);
  1748. begin
  1749. if (list1 is TGLTexPointList) and (list2 is TGLTexPointList) then
  1750. begin
  1751. Assert(list1.Count = list2.Count);
  1752. Capacity := list1.Count;
  1753. FCount := list1.Count;
  1754. VectorArrayLerp(TGLTexPointList(list1).List, TGLTexPointList(list2).List,
  1755. lerpFactor, FCount, List);
  1756. end;
  1757. end;
  1758. // ------------------
  1759. // ------------------ TGLIntegerList ------------------
  1760. // ------------------
  1761. constructor TGLIntegerList.Create;
  1762. begin
  1763. FItemSize := SizeOf(Integer);
  1764. inherited Create;
  1765. FGrowthDelta := cDefaultListGrowthDelta;
  1766. end;
  1767. procedure TGLIntegerList.Assign(Src: TPersistent);
  1768. begin
  1769. if Assigned(Src) then
  1770. begin
  1771. inherited;
  1772. if (Src is TGLIntegerList) then
  1773. System.Move(TGLIntegerList(Src).FList^, FList^, FCount * SizeOf(Integer));
  1774. end
  1775. else
  1776. Clear;
  1777. end;
  1778. function TGLIntegerList.Add(const item: Integer): Integer;
  1779. begin
  1780. Result := FCount;
  1781. if Result = FCapacity then
  1782. SetCapacity(FCapacity + FGrowthDelta);
  1783. FList^[Result] := Item;
  1784. Inc(FCount);
  1785. end;
  1786. function TGLIntegerList.AddNC(const item: Integer): Integer;
  1787. begin
  1788. Result := FCount;
  1789. FList^[Result] := Item;
  1790. Inc(FCount);
  1791. end;
  1792. procedure TGLIntegerList.Add(const i1, i2: Integer);
  1793. var
  1794. tmpList : PIntegerArray;
  1795. begin
  1796. Inc(FCount, 2);
  1797. while FCount > FCapacity do
  1798. SetCapacity(FCapacity + FGrowthDelta);
  1799. tmpList := @FList[FCount - 2];
  1800. tmpList^[0] := i1;
  1801. tmpList^[1] := i2;
  1802. end;
  1803. procedure TGLIntegerList.Add(const i1, i2, i3: Integer);
  1804. var
  1805. tmpList : PIntegerArray;
  1806. begin
  1807. Inc(FCount, 3);
  1808. while FCount > FCapacity do
  1809. SetCapacity(FCapacity + FGrowthDelta);
  1810. tmpList := @FList[FCount - 3];
  1811. tmpList^[0] := i1;
  1812. tmpList^[1] := i2;
  1813. tmpList^[2] := i3;
  1814. end;
  1815. procedure TGLIntegerList.Add(const AList: TGLIntegerList);
  1816. begin
  1817. if Assigned(AList) and (AList.Count > 0) then
  1818. begin
  1819. if Count + AList.Count > Capacity then
  1820. Capacity := Count + AList.Count;
  1821. System.Move(AList.FList[0], FList[Count], AList.Count * SizeOf(Integer));
  1822. Inc(FCount, AList.Count);
  1823. end;
  1824. end;
  1825. function TGLIntegerList.Get(Index: Integer): Integer;
  1826. begin
  1827. {$IFOPT R+}
  1828. Assert(Cardinal(Index) < Cardinal(FCount));
  1829. {$ENDIF}
  1830. Result := FList^[Index];
  1831. end;
  1832. procedure TGLIntegerList.Insert(Index: Integer; const Item: Integer);
  1833. begin
  1834. {$IFOPT R+}
  1835. Assert(Cardinal(Index) < Cardinal(FCount));
  1836. {$ENDIF}
  1837. if FCount = FCapacity then
  1838. SetCapacity(FCapacity + FGrowthDelta);
  1839. if Index < FCount then
  1840. System.Move(FList[Index], FList[Index + 1], (FCount - Index) * SizeOf(Integer));
  1841. FList^[Index] := Item;
  1842. Inc(FCount);
  1843. end;
  1844. procedure TGLIntegerList.Remove(const item: Integer);
  1845. var
  1846. I: Integer;
  1847. begin
  1848. for I := 0 to Count - 1 do
  1849. begin
  1850. if FList^[I] = item then
  1851. begin
  1852. System.Move(FList[I + 1], FList[I], (FCount - 1 - I) * SizeOf(Integer));
  1853. Dec(FCount);
  1854. Break;
  1855. end;
  1856. end;
  1857. end;
  1858. procedure TGLIntegerList.Put(Index: Integer; const Item: Integer);
  1859. begin
  1860. {$IFOPT R+}
  1861. Assert(Cardinal(Index) < Cardinal(FCount));
  1862. {$ENDIF}
  1863. FList^[Index] := Item;
  1864. end;
  1865. procedure TGLIntegerList.SetCapacity(NewCapacity: Integer);
  1866. begin
  1867. inherited;
  1868. FList := PIntegerArray(FBaseList);
  1869. end;
  1870. procedure TGLIntegerList.Push(const Val: Integer);
  1871. begin
  1872. Add(Val);
  1873. end;
  1874. function TGLIntegerList.Pop: Integer;
  1875. begin
  1876. if FCount > 0 then
  1877. begin
  1878. Result := FList^[FCount - 1];
  1879. Delete(FCount - 1);
  1880. end
  1881. else
  1882. Result := 0;
  1883. end;
  1884. procedure TGLIntegerList.AddSerie(aBase, aDelta, aCount: Integer);
  1885. var
  1886. tmpList : PInteger;
  1887. I: Integer;
  1888. begin
  1889. if aCount <= 0 then
  1890. Exit;
  1891. AdjustCapacityToAtLeast(Count + aCount);
  1892. tmpList := @FList[Count];
  1893. for I := Count to Count + aCount - 1 do
  1894. begin
  1895. tmpList^ := aBase;
  1896. Inc(tmpList);
  1897. aBase := aBase + aDelta;
  1898. end;
  1899. FCount := Count + aCount;
  1900. end;
  1901. procedure TGLIntegerList.AddIntegers(const First: PInteger; n: Integer);
  1902. begin
  1903. if n < 1 then
  1904. Exit;
  1905. AdjustCapacityToAtLeast(Count + n);
  1906. System.Move(First^, FList[FCount], n * SizeOf(Integer));
  1907. FCount := FCount + n;
  1908. end;
  1909. procedure TGLIntegerList.AddIntegers(const aList: TGLIntegerList);
  1910. begin
  1911. if not Assigned(aList) then
  1912. Exit;
  1913. AddIntegers(@aList.List[0], aList.Count);
  1914. end;
  1915. procedure TGLIntegerList.AddIntegers(const anArray: array of Integer);
  1916. var
  1917. n: Integer;
  1918. begin
  1919. n := Length(anArray);
  1920. if n > 0 then
  1921. AddIntegers(@anArray[0], n);
  1922. end;
  1923. function IntegerSearch(item: Integer; list: PIntegerVector; Count: Integer): Integer; register; inline;
  1924. var i : integer;
  1925. begin
  1926. result:=-1;
  1927. for i := 0 to Count-1 do begin
  1928. if list^[i]=item then begin
  1929. result:=i;
  1930. break;
  1931. end;
  1932. end;
  1933. end;
  1934. function TGLIntegerList.IndexOf(item: Integer): Integer; register;
  1935. begin
  1936. Result := IntegerSearch(item, FList, FCount);
  1937. end;
  1938. function TGLIntegerList.MinInteger: Integer;
  1939. var
  1940. I: Integer;
  1941. locList: PIntegerVector;
  1942. begin
  1943. if FCount > 0 then
  1944. begin
  1945. locList := FList;
  1946. Result := locList^[0];
  1947. for I := 1 to FCount - 1 do
  1948. if locList^[I] < Result then
  1949. Result := locList^[I];
  1950. end
  1951. else
  1952. Result := 0;
  1953. end;
  1954. function TGLIntegerList.MaxInteger: Integer;
  1955. var
  1956. I: Integer;
  1957. locList: PIntegerVector;
  1958. begin
  1959. if FCount > 0 then
  1960. begin
  1961. locList := FList;
  1962. Result := locList^[0];
  1963. for I := 1 to FCount - 1 do
  1964. if locList^[I] > Result then
  1965. Result := locList^[I];
  1966. end
  1967. else
  1968. Result := 0;
  1969. end;
  1970. procedure IntegerQuickSort(sortList: PIntegerArray; left, right: Integer);
  1971. var
  1972. I, J: Integer;
  1973. p, t: Integer;
  1974. begin
  1975. repeat
  1976. I := left;
  1977. J := right;
  1978. p := sortList^[(left + right) shr 1];
  1979. repeat
  1980. while sortList^[I] < p do
  1981. Inc(I);
  1982. while sortList^[J] > p do
  1983. Dec(J);
  1984. if I <= J then
  1985. begin
  1986. t := sortList^[I];
  1987. sortList^[I] := sortList^[J];
  1988. sortList^[J] := t;
  1989. Inc(I);
  1990. Dec(J);
  1991. end;
  1992. until I > J;
  1993. if left < J then
  1994. IntegerQuickSort(sortList, left, J);
  1995. left := I;
  1996. until I >= right;
  1997. end;
  1998. procedure TGLIntegerList.Sort;
  1999. begin
  2000. if (FList <> nil) and (Count > 1) then
  2001. IntegerQuickSort(FList, 0, Count - 1);
  2002. end;
  2003. procedure TGLIntegerList.SortAndRemoveDuplicates;
  2004. var
  2005. I, J, lastVal: Integer;
  2006. localList: PIntegerArray;
  2007. begin
  2008. if (FList <> nil) and (Count > 1) then
  2009. begin
  2010. IntegerQuickSort(FList, 0, Count - 1);
  2011. J := 0;
  2012. localList := FList;
  2013. lastVal := localList^[J];
  2014. for I := 1 to Count - 1 do
  2015. begin
  2016. if localList^[I] <> lastVal then
  2017. begin
  2018. lastVal := localList^[I];
  2019. Inc(J);
  2020. localList^[J] := lastVal;
  2021. end;
  2022. end;
  2023. FCount := J + 1;
  2024. end;
  2025. end;
  2026. function TGLIntegerList.BinarySearch(const Value: Integer): Integer;
  2027. var
  2028. found: Boolean;
  2029. begin
  2030. Result := BinarySearch(Value, False, found);
  2031. end;
  2032. function TGLIntegerList.BinarySearch(const Value: Integer; returnBestFit: Boolean; var found: Boolean): Integer;
  2033. var
  2034. Index: Integer;
  2035. min, max, mid: Integer;
  2036. intList: PIntegerArray;
  2037. begin
  2038. // Assume we won't find it
  2039. found := False;
  2040. // If the list is empty, we won't find the sought value!
  2041. if Count = 0 then
  2042. begin
  2043. Result := -1;
  2044. Exit;
  2045. end;
  2046. min := -1; // ONE OFF!
  2047. max := Count; // ONE OFF!
  2048. // We now know that Min and Max AREN'T the values!
  2049. Index := -1;
  2050. intList := List;
  2051. repeat
  2052. // Find the middle of the current scope
  2053. mid := (min + max) shr 1;
  2054. // Reduce the search scope by half
  2055. if intList^[mid] <= Value then
  2056. begin
  2057. // Is this the one?
  2058. if intList^[mid] = Value then
  2059. begin
  2060. Index := mid;
  2061. found := True;
  2062. Break;
  2063. end
  2064. else
  2065. min := mid;
  2066. end
  2067. else
  2068. max := mid;
  2069. until min + 1 = max;
  2070. if returnBestFit then
  2071. begin
  2072. if Index >= 0 then
  2073. Result := Index
  2074. else
  2075. Result := min;
  2076. end
  2077. else
  2078. Result := Index;
  2079. end;
  2080. function TGLIntegerList.AddSorted(const Value: Integer; const ignoreDuplicates: Boolean = False): Integer;
  2081. var
  2082. Index: Integer;
  2083. found: Boolean;
  2084. begin
  2085. Index := BinarySearch(Value, True, found);
  2086. if ignoreDuplicates and Found then
  2087. Result := -1
  2088. else
  2089. begin
  2090. Insert(Index + 1, Value);
  2091. Result := Index + 1;
  2092. end;
  2093. end;
  2094. procedure TGLIntegerList.RemoveSorted(const Value: Integer);
  2095. var
  2096. Index: Integer;
  2097. begin
  2098. Index := BinarySearch(Value);
  2099. if Index >= 0 then
  2100. Delete(Index);
  2101. end;
  2102. procedure TGLIntegerList.Offset(delta: Integer);
  2103. var
  2104. I: Integer;
  2105. locList: PIntegerArray;
  2106. begin
  2107. locList := FList;
  2108. for I := 0 to FCount - 1 do
  2109. locList^[I] := locList^[I] + delta;
  2110. end;
  2111. procedure TGLIntegerList.Offset(delta: Integer; const base, nb: Integer);
  2112. var
  2113. I: Integer;
  2114. locList: PIntegerArray;
  2115. begin
  2116. locList := FList;
  2117. for I := base to base + nb - 1 do
  2118. locList^[I] := locList^[I] + delta;
  2119. end;
  2120. // ------------------
  2121. // ------------------ TGLSingleList ------------------
  2122. // ------------------
  2123. constructor TGLSingleList.Create;
  2124. begin
  2125. FItemSize := SizeOf(Single);
  2126. inherited Create;
  2127. FGrowthDelta := cDefaultListGrowthDelta;
  2128. end;
  2129. procedure TGLSingleList.Assign(Src: TPersistent);
  2130. begin
  2131. if Assigned(Src) then
  2132. begin
  2133. inherited;
  2134. if (Src is TGLSingleList) then
  2135. System.Move(TGLSingleList(Src).FList^, FList^, FCount * SizeOf(Single));
  2136. end
  2137. else
  2138. Clear;
  2139. end;
  2140. function TGLSingleList.Add(const item: Single): Integer;
  2141. begin
  2142. Result := FCount;
  2143. if Result = FCapacity then
  2144. SetCapacity(FCapacity + FGrowthDelta);
  2145. FList^[Result] := Item;
  2146. Inc(FCount);
  2147. end;
  2148. procedure TGLSingleList.Add(const i1, i2: Single);
  2149. var
  2150. tmpList : PSingleArray;
  2151. begin
  2152. Inc(FCount, 2);
  2153. while FCount > FCapacity do
  2154. SetCapacity(FCapacity + FGrowthDelta);
  2155. tmpList := @FList[FCount - 2];
  2156. tmpList^[0] := i1;
  2157. tmpList^[1] := i2;
  2158. end;
  2159. procedure TGLSingleList.AddSingles(const First: PSingle; n: Integer);
  2160. begin
  2161. if n < 1 then
  2162. Exit;
  2163. AdjustCapacityToAtLeast(Count + n);
  2164. System.Move(First^, FList[FCount], n * SizeOf(Single));
  2165. FCount := FCount + n;
  2166. end;
  2167. procedure TGLSingleList.AddSingles(const anArray: array of Single);
  2168. var
  2169. n: Integer;
  2170. begin
  2171. n := Length(anArray);
  2172. if n > 0 then
  2173. AddSingles(@anArray[0], n);
  2174. end;
  2175. function TGLSingleList.Get(Index: Integer): Single;
  2176. begin
  2177. {$IFOPT R+}
  2178. Assert(Cardinal(Index) < Cardinal(FCount));
  2179. {$ENDIF}
  2180. Result := FList^[Index];
  2181. end;
  2182. procedure TGLSingleList.Insert(Index: Integer; const Item: Single);
  2183. begin
  2184. {$IFOPT R+}
  2185. Assert(Cardinal(Index) < Cardinal(FCount));
  2186. {$ENDIF}
  2187. if FCount = FCapacity then
  2188. SetCapacity(FCapacity + FGrowthDelta);
  2189. if Index < FCount then
  2190. System.Move(FList[Index], FList[Index + 1],
  2191. (FCount - Index) * SizeOf(Single));
  2192. FList^[Index] := Item;
  2193. Inc(FCount);
  2194. end;
  2195. procedure TGLSingleList.Put(Index: Integer; const Item: Single);
  2196. begin
  2197. {$IFOPT R+}
  2198. Assert(Cardinal(Index) < Cardinal(FCount));
  2199. {$ENDIF}
  2200. FList^[Index] := Item;
  2201. end;
  2202. procedure TGLSingleList.SetCapacity(NewCapacity: Integer);
  2203. begin
  2204. inherited;
  2205. FList := PGLSingleArrayList(FBaseList);
  2206. end;
  2207. procedure TGLSingleList.Push(const Val: Single);
  2208. begin
  2209. Add(Val);
  2210. end;
  2211. function TGLSingleList.Pop: Single;
  2212. begin
  2213. if FCount > 0 then
  2214. begin
  2215. Result := Get(FCount - 1);
  2216. Delete(FCount - 1);
  2217. end
  2218. else
  2219. Result := 0;
  2220. end;
  2221. procedure TGLSingleList.AddSerie(aBase, aDelta: Single; aCount: Integer);
  2222. var
  2223. tmpList : PSingle;
  2224. I: Integer;
  2225. begin
  2226. if aCount <= 0 then
  2227. Exit;
  2228. AdjustCapacityToAtLeast(Count + aCount);
  2229. tmpList := @FList[Count];
  2230. for I := Count to Count + aCount - 1 do
  2231. begin
  2232. tmpList^ := aBase;
  2233. Inc(tmpList);
  2234. aBase := aBase + aDelta;
  2235. end;
  2236. FCount := Count + aCount;
  2237. end;
  2238. procedure TGLSingleList.Offset(delta: Single);
  2239. begin
  2240. OffsetFloatArray(PFloatVector(FList), FCount, delta);
  2241. end;
  2242. procedure TGLSingleList.Offset(const delta: TGLSingleList);
  2243. begin
  2244. if FCount = delta.FCount then
  2245. OffsetFloatArray(PFloatVector(FList), PFloatVector(delta.FList), FCount)
  2246. else
  2247. raise Exception.Create('SingleList count do not match');
  2248. end;
  2249. procedure TGLSingleList.Scale(factor: Single);
  2250. begin
  2251. ScaleFloatArray(PFloatVector(FList), FCount, factor);
  2252. end;
  2253. procedure TGLSingleList.Sqr;
  2254. var
  2255. I: Integer;
  2256. locList: PGLSingleArrayList;
  2257. begin
  2258. locList := FList;
  2259. for I := 0 to Count - 1 do
  2260. locList^[I] := locList^[I] * locList^[I];
  2261. end;
  2262. procedure TGLSingleList.Sqrt;
  2263. var
  2264. I: Integer;
  2265. locList: PGLSingleArrayList;
  2266. begin
  2267. locList := FList;
  2268. for I := 0 to Count - 1 do
  2269. locList^[I] := System.Sqrt(locList^[I]);
  2270. end;
  2271. function TGLSingleList.Sum: Single;
  2272. var
  2273. i: Integer;
  2274. begin
  2275. Result := 0;
  2276. for i := 0 to FCount-1 do
  2277. Result := Result + FList^[i];
  2278. end;
  2279. function TGLSingleList.Min: Single;
  2280. var
  2281. I: Integer;
  2282. locList: PGLSingleArrayList;
  2283. begin
  2284. if FCount > 0 then
  2285. begin
  2286. locList := FList;
  2287. Result := locList^[0];
  2288. for I := 1 to FCount - 1 do
  2289. if locList^[I] < Result then
  2290. Result := locList^[I];
  2291. end
  2292. else
  2293. Result := 0;
  2294. end;
  2295. function TGLSingleList.Max: Single;
  2296. var
  2297. I: Integer;
  2298. locList: PGLSingleArrayList;
  2299. begin
  2300. if FCount > 0 then
  2301. begin
  2302. locList := FList;
  2303. Result := locList^[0];
  2304. for I := 1 to FCount - 1 do
  2305. if locList^[I] > Result then
  2306. Result := locList^[I];
  2307. end
  2308. else
  2309. Result := 0;
  2310. end;
  2311. // ------------------
  2312. // ------------------ TGLByteList ------------------
  2313. // ------------------
  2314. constructor TGLByteList.Create;
  2315. begin
  2316. FItemSize := SizeOf(Byte);
  2317. inherited Create;
  2318. FGrowthDelta := cDefaultListGrowthDelta;
  2319. end;
  2320. procedure TGLByteList.Assign(Src: TPersistent);
  2321. begin
  2322. if Assigned(Src) then
  2323. begin
  2324. inherited;
  2325. if (Src is TGLByteList) then
  2326. System.Move(TGLByteList(Src).FList^, FList^, FCount * SizeOf(Byte));
  2327. end
  2328. else
  2329. Clear;
  2330. end;
  2331. function TGLByteList.Add(const item: Byte): Integer;
  2332. begin
  2333. Result := FCount;
  2334. if Result = FCapacity then
  2335. SetCapacity(FCapacity + FGrowthDelta);
  2336. FList^[Result] := Item;
  2337. Inc(FCount);
  2338. end;
  2339. function TGLByteList.Get(Index: Integer): Byte;
  2340. begin
  2341. {$IFOPT R+}
  2342. Assert(Cardinal(Index) < Cardinal(FCount));
  2343. {$ENDIF}
  2344. Result := FList^[Index];
  2345. end;
  2346. procedure TGLByteList.Insert(Index: Integer; const Item: Byte);
  2347. begin
  2348. {$IFOPT R+}
  2349. Assert(Cardinal(Index) < Cardinal(FCount));
  2350. {$ENDIF}
  2351. if FCount = FCapacity then
  2352. SetCapacity(FCapacity + FGrowthDelta);
  2353. if Index < FCount then
  2354. System.Move(FList[Index], FList[Index + 1],
  2355. (FCount - Index) * SizeOf(Byte));
  2356. FList^[Index] := Item;
  2357. Inc(FCount);
  2358. end;
  2359. procedure TGLByteList.Put(Index: Integer; const Item: Byte);
  2360. begin
  2361. {$IFOPT R+}
  2362. Assert(Cardinal(Index) < Cardinal(FCount));
  2363. {$ENDIF}
  2364. FList^[Index] := Item;
  2365. end;
  2366. procedure TGLByteList.SetCapacity(NewCapacity: Integer);
  2367. begin
  2368. inherited;
  2369. FList := PByteArray(FBaseList);
  2370. end;
  2371. // ------------------
  2372. // ------------------ TGLDoubleList ------------------
  2373. // ------------------
  2374. constructor TGLDoubleList.Create;
  2375. begin
  2376. FItemSize := SizeOf(Double);
  2377. inherited Create;
  2378. FGrowthDelta := cDefaultListGrowthDelta;
  2379. end;
  2380. procedure TGLDoubleList.Assign(Src: TPersistent);
  2381. begin
  2382. if Assigned(Src) then
  2383. begin
  2384. inherited;
  2385. if (Src is TGLDoubleList) then
  2386. System.Move(TGLDoubleList(Src).FList^, FList^, FCount * SizeOf(Double));
  2387. end
  2388. else
  2389. Clear;
  2390. end;
  2391. function TGLDoubleList.Add(const item: Double): Integer;
  2392. begin
  2393. Result := FCount;
  2394. if Result = FCapacity then
  2395. SetCapacity(FCapacity + FGrowthDelta);
  2396. FList^[Result] := Item;
  2397. Inc(FCount);
  2398. end;
  2399. function TGLDoubleList.Get(Index: Integer): Double;
  2400. begin
  2401. {$IFOPT R+}
  2402. Assert(Cardinal(Index) < Cardinal(FCount));
  2403. {$ENDIF}
  2404. Result := FList^[Index];
  2405. end;
  2406. procedure TGLDoubleList.Insert(Index: Integer; const Item: Double);
  2407. begin
  2408. {$IFOPT R+}
  2409. Assert(Cardinal(Index) < Cardinal(FCount));
  2410. {$ENDIF}
  2411. if FCount = FCapacity then
  2412. SetCapacity(FCapacity + FGrowthDelta);
  2413. if Index < FCount then
  2414. System.Move(FList[Index], FList[Index + 1],
  2415. (FCount - Index) * SizeOf(Double));
  2416. FList^[Index] := Item;
  2417. Inc(FCount);
  2418. end;
  2419. procedure TGLDoubleList.Put(Index: Integer; const Item: Double);
  2420. begin
  2421. {$IFOPT R+}
  2422. Assert(Cardinal(Index) < Cardinal(FCount));
  2423. {$ENDIF}
  2424. FList^[Index] := Item;
  2425. end;
  2426. procedure TGLDoubleList.SetCapacity(NewCapacity: Integer);
  2427. begin
  2428. inherited;
  2429. FList := PGLDoubleArrayList(FBaseList);
  2430. end;
  2431. procedure TGLDoubleList.Push(const Val: Double);
  2432. begin
  2433. Add(Val);
  2434. end;
  2435. function TGLDoubleList.Pop: Double;
  2436. begin
  2437. if FCount > 0 then
  2438. begin
  2439. Result := Get(FCount - 1);
  2440. Delete(FCount - 1);
  2441. end
  2442. else
  2443. Result := 0;
  2444. end;
  2445. procedure TGLDoubleList.AddSerie(aBase, aDelta: Double; aCount: Integer);
  2446. var
  2447. tmpList: PDouble;
  2448. I: Integer;
  2449. begin
  2450. if aCount <= 0 then
  2451. Exit;
  2452. AdjustCapacityToAtLeast(Count + aCount);
  2453. tmpList := @FList[Count];
  2454. for I := Count to Count + aCount - 1 do
  2455. begin
  2456. tmpList^ := aBase;
  2457. Inc(tmpList);
  2458. aBase := aBase + aDelta;
  2459. end;
  2460. FCount := Count + aCount;
  2461. end;
  2462. procedure TGLDoubleList.Offset(delta: Double);
  2463. var
  2464. I: Integer;
  2465. begin
  2466. for I := 0 to Count - 1 do
  2467. FList^[I] := FList^[I] + delta;
  2468. end;
  2469. procedure TGLDoubleList.Offset(const delta: TGLDoubleList);
  2470. var
  2471. I: Integer;
  2472. begin
  2473. if FCount = delta.FCount then
  2474. for I := 0 to Count - 1 do
  2475. FList^[I] := FList^[I] + delta[I]
  2476. else
  2477. raise Exception.Create('DoubleList count do not match');
  2478. end;
  2479. procedure TGLDoubleList.Scale(factor: Double);
  2480. var
  2481. I: Integer;
  2482. begin
  2483. for I := 0 to Count - 1 do
  2484. FList^[I] := FList^[I] * factor;
  2485. end;
  2486. procedure TGLDoubleList.Sqr;
  2487. var
  2488. I: Integer;
  2489. locList: PGLDoubleArrayList;
  2490. begin
  2491. locList := FList;
  2492. for I := 0 to Count - 1 do
  2493. locList^[I] := locList^[I] * locList^[I];
  2494. end;
  2495. procedure TGLDoubleList.Sqrt;
  2496. var
  2497. I: Integer;
  2498. locList: PGLDoubleArrayList;
  2499. begin
  2500. locList := FList;
  2501. for I := 0 to Count - 1 do
  2502. locList^[I] := System.Sqrt(locList^[I]);
  2503. end;
  2504. function TGLDoubleList.Sum: Double;
  2505. var
  2506. i: Integer;
  2507. begin
  2508. Result := 0;
  2509. for i := 0 to FCount-1 do
  2510. Result := Result + FList^[i];
  2511. end;
  2512. function TGLDoubleList.Min: Single;
  2513. var
  2514. I: Integer;
  2515. locList: PGLDoubleArrayList;
  2516. begin
  2517. if FCount > 0 then
  2518. begin
  2519. locList := FList;
  2520. Result := locList^[0];
  2521. for I := 1 to FCount - 1 do
  2522. if locList^[I] < Result then
  2523. Result := locList^[I];
  2524. end
  2525. else
  2526. Result := 0;
  2527. end;
  2528. function TGLDoubleList.Max: Single;
  2529. var
  2530. I: Integer;
  2531. locList: PGLDoubleArrayList;
  2532. begin
  2533. if FCount > 0 then
  2534. begin
  2535. locList := FList;
  2536. Result := locList^[0];
  2537. for I := 1 to FCount - 1 do
  2538. if locList^[I] > Result then
  2539. Result := locList^[I];
  2540. end
  2541. else
  2542. Result := 0;
  2543. end;
  2544. // ------------------
  2545. // ------------------ TGLQuaternionList ------------------
  2546. // ------------------
  2547. constructor TGLQuaternionList.Create;
  2548. begin
  2549. FItemSize := SizeOf(TQuaternion);
  2550. inherited Create;
  2551. FGrowthDelta := cDefaultListGrowthDelta;
  2552. end;
  2553. procedure TGLQuaternionList.Assign(Src: TPersistent);
  2554. begin
  2555. if Assigned(Src) then
  2556. begin
  2557. inherited;
  2558. if (Src is TGLQuaternionList) then
  2559. System.Move(TGLQuaternionList(Src).FList^, FList^, FCount * SizeOf(TQuaternion));
  2560. end
  2561. else
  2562. Clear;
  2563. end;
  2564. function TGLQuaternionList.Add(const item: TQuaternion): Integer;
  2565. begin
  2566. Result := FCount;
  2567. if Result = FCapacity then
  2568. SetCapacity(FCapacity + FGrowthDelta);
  2569. FList^[Result] := Item;
  2570. Inc(FCount);
  2571. end;
  2572. function TGLQuaternionList.Add(const item: TAffineVector; w: Single): Integer;
  2573. begin
  2574. Result := Add(QuaternionMake([item.X, item.Y, item.Z], w));
  2575. end;
  2576. function TGLQuaternionList.Add(const X, Y, Z, w: Single): Integer;
  2577. begin
  2578. Result := Add(QuaternionMake([X, Y, Z], w));
  2579. end;
  2580. function TGLQuaternionList.Get(Index: Integer): TQuaternion;
  2581. begin
  2582. {$IFOPT R+}
  2583. Assert(Cardinal(Index) < Cardinal(FCount));
  2584. {$ENDIF}
  2585. Result := FList^[Index];
  2586. end;
  2587. procedure TGLQuaternionList.Insert(Index: Integer; const Item: TQuaternion);
  2588. begin
  2589. {$IFOPT R+}
  2590. Assert(Cardinal(Index) < Cardinal(FCount));
  2591. {$ENDIF}
  2592. if FCount = FCapacity then
  2593. SetCapacity(FCapacity + FGrowthDelta);
  2594. if Index < FCount then
  2595. System.Move(FList[Index], FList[Index + 1],
  2596. (FCount - Index) * SizeOf(TQuaternion));
  2597. FList^[Index] := Item;
  2598. Inc(FCount);
  2599. end;
  2600. procedure TGLQuaternionList.Put(Index: Integer; const Item: TQuaternion);
  2601. begin
  2602. {$IFOPT R+}
  2603. Assert(Cardinal(Index) < Cardinal(FCount));
  2604. {$ENDIF}
  2605. FList^[Index] := Item;
  2606. end;
  2607. procedure TGLQuaternionList.SetCapacity(NewCapacity: Integer);
  2608. begin
  2609. inherited;
  2610. FList := PQuaternionArray(FBaseList);
  2611. end;
  2612. procedure TGLQuaternionList.Push(const Val: TQuaternion);
  2613. begin
  2614. Add(Val);
  2615. end;
  2616. function TGLQuaternionList.Pop: TQuaternion;
  2617. begin
  2618. if FCount > 0 then
  2619. begin
  2620. Result := Get(FCount - 1);
  2621. Delete(FCount - 1);
  2622. end
  2623. else
  2624. Result := IdentityQuaternion;
  2625. end;
  2626. function TGLQuaternionList.IndexOf(const item: TQuaternion): Integer;
  2627. var
  2628. I: Integer;
  2629. curItem: PQuaternion;
  2630. begin
  2631. for I := 0 to Count - 1 do
  2632. begin
  2633. curItem := @FList[I];
  2634. if (item.RealPart = curItem^.RealPart) and VectorEquals(item.ImagPart, curItem^.ImagPart) then
  2635. begin
  2636. Result := I;
  2637. Exit;
  2638. end;
  2639. end;
  2640. Result := -1;
  2641. end;
  2642. function TGLQuaternionList.FindOrAdd(const item: TQuaternion): Integer;
  2643. begin
  2644. Result := IndexOf(item);
  2645. if Result < 0 then
  2646. Result := Add(item);
  2647. end;
  2648. procedure TGLQuaternionList.Lerp(const list1, list2: TGLBaseVectorList; lerpFactor: Single);
  2649. var
  2650. I: Integer;
  2651. begin
  2652. if (list1 is TGLQuaternionList) and (list2 is TGLQuaternionList) then
  2653. begin
  2654. Assert(list1.Count = list2.Count);
  2655. Capacity := list1.Count;
  2656. FCount := list1.Count;
  2657. for I := 0 to FCount - 1 do
  2658. Put(I, QuaternionSlerp(TGLQuaternionList(list1)[I], TGLQuaternionList(list2)[I], lerpFactor));
  2659. end;
  2660. end;
  2661. procedure TGLQuaternionList.Combine(const list2: TGLBaseVectorList; factor: Single);
  2662. procedure CombineQuaternion(var q1: TQuaternion; const q2: TQuaternion; factor: Single);
  2663. begin
  2664. q1 := QuaternionMultiply(q1, QuaternionSlerp(IdentityQuaternion, q2, factor));
  2665. end;
  2666. var
  2667. I: Integer;
  2668. begin
  2669. Assert(list2.Count >= Count);
  2670. if list2 is TGLQuaternionList then
  2671. begin
  2672. for I := 0 to Count - 1 do
  2673. begin
  2674. CombineQuaternion(PQuaternion(ItemAddress[I])^,
  2675. PQuaternion(list2.ItemAddress[I])^,
  2676. factor);
  2677. end;
  2678. end
  2679. else
  2680. inherited;
  2681. end;
  2682. // ------------------
  2683. // ------------------ TGL4ByteList ------------------
  2684. // ------------------
  2685. constructor TGL4ByteList.Create;
  2686. begin
  2687. FItemSize := SizeOf(TGL4ByteList);
  2688. inherited Create;
  2689. FGrowthDelta := cDefaultListGrowthDelta;
  2690. end;
  2691. procedure TGL4ByteList.Assign(Src: TPersistent);
  2692. begin
  2693. if Assigned(Src) then
  2694. begin
  2695. inherited;
  2696. if (Src is TGL4ByteList) then
  2697. System.Move(TGL4ByteList(Src).FList^, FList^, FCount * SizeOf(TGL4ByteData));
  2698. end
  2699. else
  2700. Clear;
  2701. end;
  2702. function TGL4ByteList.Add(const item: TGL4ByteData): Integer;
  2703. begin
  2704. Result := FCount;
  2705. if Result = FCapacity then
  2706. SetCapacity(FCapacity + FGrowthDelta);
  2707. FList^[Result] := Item;
  2708. Inc(FCount);
  2709. Inc(FRevision);
  2710. end;
  2711. procedure TGL4ByteList.Add(const i1: Single);
  2712. var
  2713. tmpList: PSingle;
  2714. begin
  2715. Inc(FCount);
  2716. if FCount >= FCapacity then
  2717. SetCapacity(FCapacity + FGrowthDelta);
  2718. tmpList := @FList[FCount - 1];
  2719. tmpList^ := i1;
  2720. Inc(FRevision);
  2721. end;
  2722. procedure TGL4ByteList.Add(const i1, i2: Single);
  2723. var
  2724. tmpList: PSingleArray;
  2725. begin
  2726. Inc(FCount, 2);
  2727. while FCount > FCapacity do
  2728. SetCapacity(FCapacity + FGrowthDelta);
  2729. tmpList := @FList[FCount - 2];
  2730. tmpList^[0] := i1;
  2731. tmpList^[1] := i2;
  2732. Inc(FRevision);
  2733. end;
  2734. procedure TGL4ByteList.Add(const i1, i2, i3: Single);
  2735. var
  2736. tmpList: PSingleArray;
  2737. begin
  2738. Inc(FCount, 3);
  2739. while FCount > FCapacity do
  2740. SetCapacity(FCapacity + FGrowthDelta);
  2741. tmpList := @FList[FCount - 3];
  2742. tmpList^[0] := i1;
  2743. tmpList^[1] := i2;
  2744. tmpList^[2] := i3;
  2745. Inc(FRevision);
  2746. end;
  2747. procedure TGL4ByteList.Add(const i1, i2, i3, i4: Single);
  2748. var
  2749. tmpList: PSingleArray;
  2750. begin
  2751. Inc(FCount, 4);
  2752. while FCount > FCapacity do
  2753. SetCapacity(FCapacity + FGrowthDelta);
  2754. tmpList := @FList[FCount - 4];
  2755. tmpList^[0] := i1;
  2756. tmpList^[1] := i2;
  2757. tmpList^[2] := i3;
  2758. tmpList^[3] := i4;
  2759. Inc(FRevision);
  2760. end;
  2761. procedure TGL4ByteList.Add(const i1: Integer);
  2762. var
  2763. tmpList: PInteger;
  2764. begin
  2765. Inc(FCount);
  2766. while FCount > FCapacity do
  2767. SetCapacity(FCapacity + FGrowthDelta);
  2768. tmpList := @FList[FCount - 1];
  2769. tmpList^ := i1;
  2770. Inc(FRevision);
  2771. end;
  2772. procedure TGL4ByteList.Add(const i1, i2: Integer);
  2773. var
  2774. tmpList: PIntegerArray;
  2775. begin
  2776. Inc(FCount, 2);
  2777. while FCount > FCapacity do
  2778. SetCapacity(FCapacity + FGrowthDelta);
  2779. tmpList := @FList[FCount - 2];
  2780. tmpList^[0] := i1;
  2781. tmpList^[1] := i2;
  2782. Inc(FRevision);
  2783. end;
  2784. procedure TGL4ByteList.Add(const i1, i2, i3: Integer);
  2785. var
  2786. tmpList: PIntegerArray;
  2787. begin
  2788. Inc(FCount, 3);
  2789. while FCount > FCapacity do
  2790. SetCapacity(FCapacity + FGrowthDelta);
  2791. tmpList := @FList[FCount - 3];
  2792. tmpList^[0] := i1;
  2793. tmpList^[1] := i2;
  2794. tmpList^[2] := i3;
  2795. Inc(FRevision);
  2796. end;
  2797. procedure TGL4ByteList.Add(const i1, i2, i3, i4: Integer);
  2798. var
  2799. tmpList: PIntegerArray;
  2800. begin
  2801. Inc(FCount, 4);
  2802. while FCount > FCapacity do
  2803. SetCapacity(FCapacity + FGrowthDelta);
  2804. tmpList := @FList[FCount - 4];
  2805. tmpList^[0] := i1;
  2806. tmpList^[1] := i2;
  2807. tmpList^[2] := i3;
  2808. tmpList^[3] := i4;
  2809. Inc(FRevision);
  2810. end;
  2811. procedure TGL4ByteList.Add(const i1: Cardinal);
  2812. var
  2813. tmpList: PLongWord;
  2814. begin
  2815. Inc(FCount);
  2816. while FCount > FCapacity do
  2817. SetCapacity(FCapacity + FGrowthDelta);
  2818. tmpList := @FList[FCount - 1];
  2819. tmpList^ := i1;
  2820. Inc(FRevision);
  2821. end;
  2822. procedure TGL4ByteList.Add(const i1, i2: Cardinal);
  2823. var
  2824. tmpList: PLongWordArray;
  2825. begin
  2826. Inc(FCount, 2);
  2827. while FCount > FCapacity do
  2828. SetCapacity(FCapacity + FGrowthDelta);
  2829. tmpList := @FList[FCount - 2];
  2830. tmpList^[0] := i1;
  2831. tmpList^[1] := i2;
  2832. Inc(FRevision);
  2833. end;
  2834. procedure TGL4ByteList.Add(const i1, i2, i3: Cardinal);
  2835. var
  2836. tmpList: PLongWordArray;
  2837. begin
  2838. Inc(FCount, 3);
  2839. while FCount > FCapacity do
  2840. SetCapacity(FCapacity + FGrowthDelta);
  2841. tmpList := @FList[FCount - 3];
  2842. tmpList^[0] := i1;
  2843. tmpList^[1] := i2;
  2844. tmpList^[2] := i3;
  2845. Inc(FRevision);
  2846. end;
  2847. procedure TGL4ByteList.Add(const i1, i2, i3, i4: Cardinal);
  2848. var
  2849. tmpList: PLongWordArray;
  2850. begin
  2851. Inc(FCount, 4);
  2852. while FCount > FCapacity do
  2853. SetCapacity(FCapacity + FGrowthDelta);
  2854. tmpList := @FList[FCount - 4];
  2855. tmpList^[0] := i1;
  2856. tmpList^[1] := i2;
  2857. tmpList^[2] := i3;
  2858. tmpList^[3] := i4;
  2859. Inc(FRevision);
  2860. end;
  2861. procedure TGL4ByteList.Add(const AList: TGL4ByteList);
  2862. begin
  2863. if Assigned(AList) and (AList.Count > 0) then
  2864. begin
  2865. if Count + AList.Count > Capacity then
  2866. Capacity := Count + AList.Count;
  2867. System.Move(AList.FList[0], FList[Count], AList.Count * SizeOf(TGL4ByteData));
  2868. Inc(FCount, AList.Count);
  2869. Inc(FRevision);
  2870. end;
  2871. end;
  2872. function TGL4ByteList.Get(Index: Integer): TGL4ByteData;
  2873. begin
  2874. {$IFOPT R+}
  2875. Assert(Cardinal(Index) < Cardinal(FCount));
  2876. {$ENDIF}
  2877. Result := FList^[Index];
  2878. end;
  2879. procedure TGL4ByteList.Insert(Index: Integer; const Item: TGL4ByteData);
  2880. begin
  2881. {$IFOPT R+}
  2882. Assert(Cardinal(Index) < Cardinal(FCount));
  2883. {$ENDIF}
  2884. if FCount = FCapacity then
  2885. SetCapacity(FCapacity + FGrowthDelta);
  2886. if Index < FCount then
  2887. System.Move(FList[Index], FList[Index + 1],
  2888. (FCount - Index) * SizeOf(TGL4ByteData));
  2889. FList^[Index] := Item;
  2890. Inc(FCount);
  2891. Inc(FRevision);
  2892. end;
  2893. procedure TGL4ByteList.Put(Index: Integer; const Item: TGL4ByteData);
  2894. begin
  2895. {$IFOPT R+}
  2896. Assert(Cardinal(Index) < Cardinal(FCount));
  2897. {$ENDIF}
  2898. FList^[Index] := Item;
  2899. INc(FRevision);
  2900. end;
  2901. procedure TGL4ByteList.SetCapacity(NewCapacity: Integer);
  2902. begin
  2903. inherited;
  2904. FList := P4ByteArrayList(FBaseList);
  2905. end;
  2906. procedure TGL4ByteList.Push(const Val: TGL4ByteData);
  2907. begin
  2908. Add(Val);
  2909. end;
  2910. function TGL4ByteList.Pop: TGL4ByteData;
  2911. const
  2912. Zero : TGL4ByteData = ( Int: (Value:0) );
  2913. begin
  2914. if FCount > 0 then
  2915. begin
  2916. Result := Get(FCount - 1);
  2917. Delete(FCount - 1);
  2918. end
  2919. else
  2920. Result := Zero;
  2921. end;
  2922. // ------------------
  2923. // ------------------ TGLLongWordList ------------------
  2924. // ------------------
  2925. constructor TGLLongWordList.Create;
  2926. begin
  2927. FItemSize := SizeOf(LongWord);
  2928. inherited Create;
  2929. FGrowthDelta := cDefaultListGrowthDelta;
  2930. end;
  2931. procedure TGLLongWordList.Assign(Src: TPersistent);
  2932. begin
  2933. if Assigned(Src) then
  2934. begin
  2935. inherited;
  2936. if (Src is TGLLongWordList) then
  2937. System.Move(TGLLongWordList(Src).FList^, FList^, FCount * SizeOf(LongWord));
  2938. end
  2939. else
  2940. Clear;
  2941. end;
  2942. function TGLLongWordList.Add(const item: LongWord): Integer;
  2943. begin
  2944. Result := FCount;
  2945. if Result = FCapacity then
  2946. SetCapacity(FCapacity + FGrowthDelta);
  2947. FList^[Result] := Item;
  2948. Inc(FCount);
  2949. end;
  2950. function TGLLongWordList.AddNC(const item: LongWord): Integer;
  2951. begin
  2952. Result := FCount;
  2953. FList^[Result] := Item;
  2954. Inc(FCount);
  2955. end;
  2956. procedure TGLLongWordList.Add(const i1, i2: LongWord);
  2957. var
  2958. tmpList : PLongWordArray;
  2959. begin
  2960. Inc(FCount, 2);
  2961. while FCount > FCapacity do
  2962. SetCapacity(FCapacity + FGrowthDelta);
  2963. tmpList := @FList[FCount - 2];
  2964. tmpList^[0] := i1;
  2965. tmpList^[1] := i2;
  2966. end;
  2967. procedure TGLLongWordList.Add(const i1, i2, i3: LongWord);
  2968. var
  2969. tmpList : PLongWordArray;
  2970. begin
  2971. Inc(FCount, 3);
  2972. while FCount > FCapacity do
  2973. SetCapacity(FCapacity + FGrowthDelta);
  2974. tmpList := @FList[FCount - 3];
  2975. tmpList^[0] := i1;
  2976. tmpList^[1] := i2;
  2977. tmpList^[2] := i3;
  2978. end;
  2979. procedure TGLLongWordList.Add(const AList: TGLLongWordList);
  2980. begin
  2981. if Assigned(AList) and (AList.Count > 0) then
  2982. begin
  2983. if Count + AList.Count > Capacity then
  2984. Capacity := Count + AList.Count;
  2985. System.Move(AList.FList[0], FList[Count], AList.Count * SizeOf(LongWord));
  2986. Inc(FCount, AList.Count);
  2987. end;
  2988. end;
  2989. function TGLLongWordList.Get(Index: Integer): LongWord;
  2990. begin
  2991. {$IFOPT R+}
  2992. Assert(Cardinal(Index) < Cardinal(FCount));
  2993. {$ENDIF}
  2994. Result := FList^[Index];
  2995. end;
  2996. procedure TGLLongWordList.Insert(Index: Integer; const Item: LongWord);
  2997. begin
  2998. {$IFOPT R+}
  2999. Assert(Cardinal(Index) < Cardinal(FCount));
  3000. {$ENDIF}
  3001. if FCount = FCapacity then
  3002. SetCapacity(FCapacity + FGrowthDelta);
  3003. if Index < FCount then
  3004. System.Move(FList[Index], FList[Index + 1], (FCount - Index) * SizeOf(LongWord));
  3005. FList^[Index] := Item;
  3006. Inc(FCount);
  3007. end;
  3008. procedure TGLLongWordList.Remove(const item: LongWord);
  3009. var
  3010. I: Integer;
  3011. begin
  3012. for I := 0 to Count - 1 do
  3013. begin
  3014. if FList^[I] = item then
  3015. begin
  3016. System.Move(FList[I + 1], FList[I], (FCount - 1 - I) * SizeOf(LongWord));
  3017. Dec(FCount);
  3018. Break;
  3019. end;
  3020. end;
  3021. end;
  3022. procedure TGLLongWordList.Put(Index: Integer; const Item: LongWord);
  3023. begin
  3024. {$IFOPT R+}
  3025. Assert(Cardinal(Index) < Cardinal(FCount));
  3026. {$ENDIF}
  3027. FList^[Index] := Item;
  3028. end;
  3029. procedure TGLLongWordList.SetCapacity(NewCapacity: Integer);
  3030. begin
  3031. inherited;
  3032. FList := PLongWordArray(FBaseList);
  3033. end;
  3034. procedure TGLLongWordList.Push(const Val: LongWord);
  3035. begin
  3036. Add(Val);
  3037. end;
  3038. function TGLLongWordList.Pop: LongWord;
  3039. begin
  3040. if FCount > 0 then
  3041. begin
  3042. Result := FList^[FCount - 1];
  3043. Delete(FCount - 1);
  3044. end
  3045. else
  3046. Result := 0;
  3047. end;
  3048. procedure TGLLongWordList.AddLongWords(const First: PLongWord; n: Integer);
  3049. begin
  3050. if n < 1 then
  3051. Exit;
  3052. AdjustCapacityToAtLeast(Count + n);
  3053. System.Move(First^, FList[FCount], n * SizeOf(LongWord));
  3054. FCount := FCount + n;
  3055. end;
  3056. procedure TGLLongWordList.AddLongWords(const aList: TGLLongWordList);
  3057. begin
  3058. if not Assigned(aList) then
  3059. Exit;
  3060. AddLongWords(@aList.List[0], aList.Count);
  3061. end;
  3062. procedure TGLLongWordList.AddLongWords(const anArray: array of LongWord);
  3063. var
  3064. n: Integer;
  3065. begin
  3066. n := Length(anArray);
  3067. if n > 0 then
  3068. AddLongWords(@anArray[0], n);
  3069. end;
  3070. function LongWordSearch(item: LongWord; list: PLongWordVector; Count: Integer): Integer; register;
  3071. var i : integer;
  3072. begin
  3073. result:=-1;
  3074. for i := 0 to Count-1 do begin
  3075. if list^[i]=item then begin
  3076. result:=i;
  3077. break;
  3078. end;
  3079. end;
  3080. end;
  3081. function TGLLongWordList.IndexOf(item: Integer): LongWord; register;
  3082. begin
  3083. Result := LongWordSearch(item, FList, FCount);
  3084. end;
  3085. // ------------------------------------------------------------------
  3086. initialization
  3087. // ------------------------------------------------------------------
  3088. RegisterClasses([TGLAffineVectorList, TGLVectorList, TGLTexPointList, TGLSingleList,
  3089. TGLDoubleList, TGL4ByteList, TGLLongWordList]);
  3090. end.