GLS.Objects.pas 99 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636
  1. //
  2. // The graphics rendering engine GLScene http://glscene.org
  3. //
  4. unit GLS.Objects;
  5. (*
  6. Implementation of basic scene objects plus some management routines:
  7. - TGLDummyCube, TGLPlane, TGLSprite, TGLPoints, TGLLines, TGLCube,
  8. TGLSphere, TGLPolygonBase, TGLSuperellipsoid.
  9. All objects declared in this unit are part of the basic GLScene package,
  10. these are only simple objects and should be kept simple and lightweight.
  11. More complex or more specialized versions should be placed in dedicated
  12. units where they can grow and prosper untammed. "Generic" geometrical
  13. objects can be found GLS.GeomObjects.
  14. *)
  15. interface
  16. {$I GLScene.inc}
  17. uses
  18. Winapi.OpenGL,
  19. Winapi.OpenGLext,
  20. System.Types,
  21. System.Classes,
  22. System.SysUtils,
  23. System.Math,
  24. GLS.OpenGLTokens,
  25. GLS.OpenGLAdapter,
  26. GLS.VectorTypes,
  27. GLS.VectorLists,
  28. GLS.VectorGeometry,
  29. GLS.Spline,
  30. GLS.Scene,
  31. GLS.PipelineTransformation,
  32. GLS.Context,
  33. GLS.Silhouette,
  34. GLS.Color,
  35. GLS.RenderContextInfo,
  36. GLS.PersistentClasses,
  37. GLS.BaseClasses,
  38. GLS.Nodes,
  39. GLS.Coordinates,
  40. GLS.XOpenGL,
  41. GLS.State;
  42. const
  43. cDefaultPointSize: Single = 1.0;
  44. type
  45. TGLVisibilityDeterminationEvent = function(Sender: TObject;
  46. var rci: TGLRenderContextInfo): Boolean of object;
  47. PGLVertexRec = ^TGLVertexRec;
  48. TGLVertexRec = record
  49. Position: TVector3f;
  50. Normal: TVector3f;
  51. Binormal: TVector3f;
  52. Tangent: TVector3f;
  53. TexCoord: TVector2f;
  54. end;
  55. (* A simple cube, invisible at run-time.
  56. This is a usually non-visible object -except at design-time- used for
  57. building hierarchies or groups, when some kind of joint or movement
  58. mechanism needs be described, you can use DummyCubes.
  59. DummyCube's barycenter is its children's barycenter.
  60. The DummyCube can optionnally amalgamate all its children into a single
  61. display list (see Amalgamate property). *)
  62. TGLDummyCube = class(TGLCameraInvariantObject)
  63. private
  64. FCubeSize: TGLFloat;
  65. FEdgeColor: TGLColor;
  66. FVisibleAtRunTime, FAmalgamate: Boolean;
  67. FGroupList: TGLListHandle;
  68. FOnVisibilityDetermination: TGLVisibilityDeterminationEvent;
  69. protected
  70. procedure SetCubeSize(const val: TGLFloat); inline;
  71. procedure SetEdgeColor(const val: TGLColor); inline;
  72. procedure SetVisibleAtRunTime(const val: Boolean); inline;
  73. procedure SetAmalgamate(const val: Boolean); inline;
  74. public
  75. constructor Create(AOwner: TComponent); override;
  76. destructor Destroy; override;
  77. procedure Assign(Source: TPersistent); override;
  78. function AxisAlignedDimensionsUnscaled: TVector; override;
  79. function RayCastIntersect(const rayStart, rayVector: TVector;
  80. intersectPoint: PVector = nil; intersectNormal: PVector = nil)
  81. : Boolean; override;
  82. procedure BuildList(var rci: TGLRenderContextInfo); override;
  83. procedure DoRender(var rci: TGLRenderContextInfo;
  84. renderSelf, renderChildren: Boolean); override;
  85. procedure StructureChanged; override;
  86. function BarycenterAbsolutePosition: TVector; override;
  87. published
  88. property CubeSize: TGLFloat read FCubeSize write SetCubeSize;
  89. property EdgeColor: TGLColor read FEdgeColor write SetEdgeColor;
  90. (* If true the dummycube's edges will be visible at runtime.
  91. The default behaviour of the dummycube is to be visible at design-time
  92. only, and invisible at runtime. *)
  93. property VisibleAtRunTime: Boolean read FVisibleAtRunTime
  94. write SetVisibleAtRunTime default False;
  95. (* Amalgamate the dummy's children in a single OpenGL entity.
  96. This activates a special rendering mode, which will compile
  97. the rendering of all of the dummycube's children objects into a
  98. single display list. This may provide a significant speed up in some
  99. situations, however, this means that changes to the children will
  100. be ignored until you call StructureChanged on the dummy cube.
  101. Some objects, that have their own display list management, may not
  102. be compatible with this behaviour. This will also prevents sorting
  103. and culling to operate as usual.
  104. In short, this features is best used for static, non-transparent
  105. geometry, or when the point of view won't change over a large
  106. number of frames. *)
  107. property Amalgamate: Boolean read FAmalgamate write SetAmalgamate
  108. default False;
  109. (* Camera Invariance Options.
  110. These options allow to "deactivate" sensitivity to camera, f.i. by
  111. centering the object on the camera or ignoring camera orientation. *)
  112. property CamInvarianceMode default cimNone;
  113. (* Event for custom visibility determination.
  114. Event handler should return True if the dummycube and its children
  115. are to be considered visible for the current render. *)
  116. property OnVisibilityDetermination: TGLVisibilityDeterminationEvent
  117. read FOnVisibilityDetermination write FOnVisibilityDetermination;
  118. end;
  119. TGLPlaneStyle = (psSingleQuad, psTileTexture);
  120. TGLPlaneStyles = set of TGLPlaneStyle;
  121. (* A simple plane object.
  122. Note that a plane is always made of a single quad (two triangles) and the
  123. tiling is only applied to texture coordinates. *)
  124. TGLPlane = class(TGLSceneObject)
  125. private
  126. FXOffset, FYOffset: TGLFloat;
  127. FXScope, FYScope: TGLFloat;
  128. FWidth, FHeight: TGLFloat;
  129. FXTiles, FYTiles: Cardinal;
  130. FStyle: TGLPlaneStyles;
  131. FMesh: array of array of TGLVertexRec;
  132. protected
  133. procedure SetHeight(const aValue: Single);
  134. procedure SetWidth(const aValue: Single);
  135. procedure SetXOffset(const Value: TGLFloat);
  136. procedure SetXScope(const Value: TGLFloat);
  137. function StoreXScope: Boolean;
  138. procedure SetXTiles(const Value: Cardinal);
  139. procedure SetYOffset(const Value: TGLFloat);
  140. procedure SetYScope(const Value: TGLFloat);
  141. function StoreYScope: Boolean;
  142. procedure SetYTiles(const Value: Cardinal);
  143. procedure SetStyle(const val: TGLPlaneStyles);
  144. public
  145. constructor Create(AOwner: TComponent); override;
  146. procedure Assign(Source: TPersistent); override;
  147. procedure BuildList(var rci: TGLRenderContextInfo); override;
  148. function GenerateSilhouette(const silhouetteParameters
  149. : TGLSilhouetteParameters): TGLSilhouette; override;
  150. function AxisAlignedDimensionsUnscaled: TVector; override;
  151. function RayCastIntersect(const rayStart, rayVector: TVector;
  152. intersectPoint: PVector = nil; intersectNormal: PVector = nil)
  153. : Boolean; override;
  154. (* Computes the screen coordinates of the smallest rectangle encompassing the plane.
  155. Returned extents are NOT limited to any physical screen extents. *)
  156. function ScreenRect(aBuffer: TGLSceneBuffer): TRect;
  157. (* Computes the signed distance to the point.
  158. Point coordinates are expected in absolute coordinates. *)
  159. function PointDistance(const aPoint: TVector): Single;
  160. published
  161. property Height: TGLFloat read FHeight write SetHeight;
  162. property Width: TGLFloat read FWidth write SetWidth;
  163. property XOffset: TGLFloat read FXOffset write SetXOffset;
  164. property XScope: TGLFloat read FXScope write SetXScope stored StoreXScope;
  165. property XTiles: Cardinal read FXTiles write SetXTiles default 1;
  166. property YOffset: TGLFloat read FYOffset write SetYOffset;
  167. property YScope: TGLFloat read FYScope write SetYScope stored StoreYScope;
  168. property YTiles: Cardinal read FYTiles write SetYTiles default 1;
  169. property Style: TGLPlaneStyles read FStyle write SetStyle
  170. default [psSingleQuad, psTileTexture];
  171. end;
  172. (* A rectangular area, perspective projected, but always facing the camera.
  173. A TGLSprite is perspective projected and as such is scaled with distance,
  174. if you want a 2D sprite that does not get scaled, see TGLHUDSprite. *)
  175. TGLSprite = class(TGLSceneObject)
  176. private
  177. FWidth: TGLFloat;
  178. FHeight: TGLFloat;
  179. FRotation: TGLFloat;
  180. FAlphaChannel: Single;
  181. FMirrorU, FMirrorV: Boolean;
  182. protected
  183. procedure SetWidth(const val: TGLFloat);
  184. procedure SetHeight(const val: TGLFloat);
  185. procedure SetRotation(const val: TGLFloat);
  186. procedure SetAlphaChannel(const val: Single);
  187. function StoreAlphaChannel: Boolean;
  188. procedure SetMirrorU(const val: Boolean);
  189. procedure SetMirrorV(const val: Boolean);
  190. public
  191. constructor Create(AOwner: TComponent); override;
  192. procedure Assign(Source: TPersistent); override;
  193. procedure BuildList(var rci: TGLRenderContextInfo); override;
  194. function AxisAlignedDimensionsUnscaled: TVector; override;
  195. procedure SetSize(const Width, Height: TGLFloat);
  196. // Set width and height to "size"
  197. procedure SetSquareSize(const Size: TGLFloat);
  198. published
  199. // Sprite Width in 3D world units.
  200. property Width: TGLFloat read FWidth write SetWidth;
  201. // Sprite Height in 3D world units.
  202. property Height: TGLFloat read FHeight write SetHeight;
  203. (* This the ON-SCREEN rotation of the sprite.
  204. Rotatation=0 is handled faster. *)
  205. property Rotation: TGLFloat read FRotation write SetRotation;
  206. // If different from 1, this value will replace that of Diffuse.Alpha
  207. property AlphaChannel: Single read FAlphaChannel write SetAlphaChannel
  208. stored StoreAlphaChannel;
  209. // Reverses the texture coordinates in the U and V direction to mirror the texture.
  210. property MirrorU: Boolean read FMirrorU write SetMirrorU default False;
  211. property MirrorV: Boolean read FMirrorV write SetMirrorV default False;
  212. end;
  213. TGLPointStyle = (psSquare, psRound, psSmooth, psSmoothAdditive,
  214. psSquareAdditive);
  215. (* Point parameters as in ARB_point_parameters.
  216. Make sure to read the ARB_point_parameters spec if you want to understand
  217. what each parameter does. *)
  218. TGLPointParameters = class(TGLUpdateAbleObject)
  219. private
  220. FEnabled: Boolean;
  221. FMinSize, FMaxSize: Single;
  222. FFadeTresholdSize: Single;
  223. FDistanceAttenuation: TGLCoordinates;
  224. protected
  225. procedure SetEnabled(const val: Boolean);
  226. procedure SetMinSize(const val: Single);
  227. procedure SetMaxSize(const val: Single);
  228. procedure SetFadeTresholdSize(const val: Single);
  229. procedure SetDistanceAttenuation(const val: TGLCoordinates);
  230. procedure DefineProperties(Filer: TFiler); override;
  231. procedure ReadData(Stream: TStream);
  232. procedure WriteData(Stream: TStream);
  233. public
  234. constructor Create(AOwner: TPersistent); override;
  235. destructor Destroy; override;
  236. procedure Assign(Source: TPersistent); override;
  237. procedure Apply;
  238. procedure UnApply;
  239. published
  240. property Enabled: Boolean read FEnabled write SetEnabled default False;
  241. property MinSize: Single read FMinSize write SetMinSize stored False;
  242. property MaxSize: Single read FMaxSize write SetMaxSize stored False;
  243. property FadeTresholdSize: Single read FFadeTresholdSize
  244. write SetFadeTresholdSize stored False;
  245. // Components XYZ are for constant, linear and quadratic attenuation.
  246. property DistanceAttenuation: TGLCoordinates read FDistanceAttenuation
  247. write SetDistanceAttenuation;
  248. end;
  249. (* Renders a set of non-transparent colored points.
  250. The points positions and their color are defined through the Positions
  251. and Colors properties *)
  252. TGLPoints = class(TGLImmaterialSceneObject)
  253. private
  254. FPositions: TAffineVectorList;
  255. FColors: TVectorList;
  256. FSize: Single;
  257. FStyle: TGLPointStyle;
  258. FPointParameters: TGLPointParameters;
  259. FStatic, FNoZWrite: Boolean;
  260. protected
  261. function StoreSize: Boolean; inline;
  262. procedure SetNoZWrite(const val: Boolean);
  263. procedure SetStatic(const val: Boolean);
  264. procedure SetSize(const val: Single);
  265. procedure SetPositions(const val: TAffineVectorList); inline;
  266. procedure SetColors(const val: TVectorList);
  267. procedure SetStyle(const val: TGLPointStyle);
  268. procedure SetPointParameters(const val: TGLPointParameters);
  269. public
  270. constructor Create(AOwner: TComponent); override;
  271. destructor Destroy; override;
  272. procedure Assign(Source: TPersistent); override;
  273. procedure BuildList(var rci: TGLRenderContextInfo); override;
  274. // Points positions. If empty, a single point is assumed at (0, 0, 0)
  275. property Positions: TAffineVectorList read FPositions write SetPositions;
  276. (* Defines the points colors:
  277. if empty, point color will be opaque white
  278. if contains a single color, all points will use that color
  279. if contains N colors, the first N points (at max) will be rendered
  280. using the corresponding colors *)
  281. property Colors: TVectorList read FColors write SetColors;
  282. published
  283. // If true points do not write their Z to the depth buffer.
  284. property NoZWrite: Boolean read FNoZWrite write SetNoZWrite;
  285. (* Tells the component if point coordinates are static.
  286. If static, changes to the positions should be notified via an
  287. explicit StructureChanged call, or may not refresh.
  288. Static sets of points may render faster than dynamic ones. *)
  289. property Static: Boolean read FStatic write SetStatic;
  290. // Point size, all points have a fixed size.
  291. property Size: Single read FSize write SetSize stored StoreSize;
  292. // Points style.
  293. property Style: TGLPointStyle read FStyle write SetStyle default psSquare;
  294. (* Point parameters as of ARB_point_parameters.
  295. Allows to vary the size and transparency of points depending
  296. on their distance to the observer. *)
  297. property PointParameters: TGLPointParameters read FPointParameters
  298. write SetPointParameters;
  299. end;
  300. // Possible aspects for the nodes of a TLine.
  301. TGLLineNodesAspect = (lnaInvisible, lnaAxes, lnaCube);
  302. // Available spline modes for a TLine.
  303. TGLLineSplineMode = (lsmLines, lsmCubicSpline, lsmBezierSpline, lsmNURBSCurve,
  304. lsmSegments, lsmLoop);
  305. // Specialized Node for use in a TGLLines objects. Adds a Color property (TGLColor) }
  306. TGLLinesNode = class(TGLNode)
  307. private
  308. FColor: TGLColor;
  309. protected
  310. procedure SetColor(const val: TGLColor);
  311. procedure OnColorChange(Sender: TObject);
  312. function StoreColor: Boolean;
  313. public
  314. constructor Create(Collection: TCollection); override;
  315. destructor Destroy; override;
  316. procedure Assign(Source: TPersistent); override;
  317. published
  318. (* The node color.
  319. Can also defined the line color (interpolated between nodes) if
  320. loUseNodeColorForLines is set (in TGLLines). *)
  321. property Color: TGLColor read FColor write SetColor stored StoreColor;
  322. end;
  323. (* Specialized collection for Nodes in a TGLLines objects. Stores TGLLinesNode items *)
  324. TGLLinesNodes = class(TGLNodes)
  325. public
  326. constructor Create(AOwner: TComponent); overload;
  327. procedure NotifyChange; override;
  328. end;
  329. (* Base class for line objects. Introduces line style properties (width, color...) *)
  330. TGLLineBase = class(TGLImmaterialSceneObject)
  331. private
  332. FLineColor: TGLColor;
  333. FLinePattern: TGLushort;
  334. FLineWidth: Single;
  335. FAntiAliased: Boolean;
  336. protected
  337. procedure SetLineColor(const Value: TGLColor);
  338. procedure SetLinePattern(const Value: TGLushort);
  339. procedure SetLineWidth(const val: Single);
  340. function StoreLineWidth: Boolean; inline;
  341. procedure SetAntiAliased(const val: Boolean);
  342. (* Setup OpenGL states according to line style.
  343. You must call RestoreLineStyle after drawing your lines.
  344. You may use nested calls with SetupLineStyle/RestoreLineStyle *)
  345. procedure SetupLineStyle(var rci: TGLRenderContextInfo);
  346. public
  347. constructor Create(AOwner: TComponent); override;
  348. destructor Destroy; override;
  349. procedure Assign(Source: TPersistent); override;
  350. procedure NotifyChange(Sender: TObject); override;
  351. published
  352. (* Indicates if OpenGL should smooth line edges.
  353. Smoothed lines looks better but are poorly implemented in most OpenGL
  354. drivers and take *lots* of rendering time *)
  355. property AntiAliased: Boolean read FAntiAliased write SetAntiAliased
  356. default False;
  357. // Default color of the lines.
  358. property LineColor: TGLColor read FLineColor write SetLineColor;
  359. (* Bitwise line pattern.
  360. For instance $FFFF (65535) is a white line (stipple disabled), $0000
  361. is a black line, $CCCC is the stipple used in axes and dummycube, etc. *)
  362. property LinePattern: TGLushort read FLinePattern write SetLinePattern
  363. default $FFFF;
  364. // Default width of the lines.
  365. property LineWidth: Single read FLineWidth write SetLineWidth
  366. stored StoreLineWidth;
  367. property Visible;
  368. end;
  369. // Class that defines lines via a series of nodes. Base class, does not render anything
  370. TGLNodedLines = class(TGLLineBase)
  371. private
  372. FNodes: TGLLinesNodes;
  373. FNodesAspect: TGLLineNodesAspect;
  374. FNodeColor: TGLColor;
  375. FNodeSize: Single;
  376. FOldNodeColor: TColorVector;
  377. protected
  378. procedure SetNodesAspect(const Value: TGLLineNodesAspect);
  379. procedure SetNodeColor(const Value: TGLColor);
  380. procedure OnNodeColorChanged(Sender: TObject);
  381. procedure SetNodes(const aNodes: TGLLinesNodes);
  382. procedure SetNodeSize(const val: Single);
  383. function StoreNodeSize: Boolean;
  384. procedure DrawNode(var rci: TGLRenderContextInfo; X, Y, Z: Single;
  385. Color: TGLColor);
  386. public
  387. constructor Create(AOwner: TComponent); override;
  388. destructor Destroy; override;
  389. procedure Assign(Source: TPersistent); override;
  390. function AxisAlignedDimensionsUnscaled: TVector; override;
  391. procedure AddNode(const coords: TGLCoordinates); overload;
  392. procedure AddNode(const X, Y, Z: TGLFloat); overload;
  393. procedure AddNode(const Value: TVector); overload;
  394. procedure AddNode(const Value: TAffineVector); overload;
  395. published
  396. // Default color for nodes. lnaInvisible and lnaAxes ignore this setting
  397. property NodeColor: TGLColor read FNodeColor write SetNodeColor;
  398. // The nodes list.
  399. property Nodes: TGLLinesNodes read FNodes write SetNodes;
  400. (* Default aspect of line nodes.
  401. May help you materialize nodes, segments and control points. *)
  402. property NodesAspect: TGLLineNodesAspect read FNodesAspect
  403. write SetNodesAspect default lnaAxes;
  404. // Size for the various node aspects.
  405. property NodeSize: Single read FNodeSize write SetNodeSize
  406. stored StoreNodeSize;
  407. end;
  408. TGLLinesOption = (loUseNodeColorForLines, loColorLogicXor);
  409. TGLLinesOptions = set of TGLLinesOption;
  410. (* Set of 3D line segments.
  411. You define a 3D Line by adding its nodes in the "Nodes" property. The line
  412. may be rendered as a set of segment or as a curve (nodes then act as spline
  413. control points).
  414. Alternatively, you can also use it to render a set of spacial nodes (points
  415. in space), just make the lines transparent and the nodes visible by picking
  416. the node aspect that suits you. *)
  417. TGLLines = class(TGLNodedLines)
  418. private
  419. FDivision: Integer;
  420. FSplineMode: TGLLineSplineMode;
  421. FOptions: TGLLinesOptions;
  422. FNURBSOrder: Integer;
  423. FNURBSTolerance: Single;
  424. FNURBSKnots: TSingleList;
  425. protected
  426. procedure SetSplineMode(const val: TGLLineSplineMode);
  427. procedure SetDivision(const Value: Integer);
  428. procedure SetOptions(const val: TGLLinesOptions);
  429. procedure SetNURBSOrder(const val: Integer);
  430. procedure SetNURBSTolerance(const val: Single);
  431. public
  432. constructor Create(AOwner: TComponent); override;
  433. destructor Destroy; override;
  434. procedure Assign(Source: TPersistent); override;
  435. procedure BuildList(var rci: TGLRenderContextInfo); override;
  436. property NURBSKnots: TSingleList read FNURBSKnots;
  437. property NURBSOrder: Integer read FNURBSOrder write SetNURBSOrder;
  438. property NURBSTolerance: Single read FNURBSTolerance
  439. write SetNURBSTolerance;
  440. published
  441. (* Number of divisions for each segment in spline modes.
  442. Minimum 1 (disabled), ignored in lsmLines mode. *)
  443. property Division: Integer read FDivision write SetDivision default 10;
  444. // Default spline drawing mode.
  445. property SplineMode: TGLLineSplineMode read FSplineMode write SetSplineMode
  446. default lsmLines;
  447. (* Rendering options for the line.
  448. loUseNodeColorForLines: if set lines will be drawn using node
  449. colors (and color interpolation between nodes), if not, LineColor
  450. will be used (single color).
  451. loColorLogicXor: enable logic operation for color of XOR type. *)
  452. property Options: TGLLinesOptions read FOptions write SetOptions;
  453. end;
  454. TCubePart = (cpTop, cpBottom, cpFront, cpBack, cpLeft, cpRight);
  455. TCubeParts = set of TCubePart;
  456. (* A simple cube object.
  457. This cube use the same material for each of its faces, ie. all faces look
  458. the same. If you want a multi-material cube, use a mesh in conjunction
  459. with a TGLFreeForm and a material library. *)
  460. TGLCube = class(TGLSceneObject)
  461. private
  462. FCubeSize: TAffineVector;
  463. FParts: TCubeParts;
  464. FNormalDirection: TGLNormalDirection;
  465. function GetCubeWHD(const Index: Integer): TGLFloat; inline;
  466. procedure SetCubeWHD(Index: Integer; aValue: TGLFloat); inline;
  467. procedure SetParts(aValue: TCubeParts); inline;
  468. procedure SetNormalDirection(aValue: TGLNormalDirection); inline;
  469. protected
  470. procedure DefineProperties(Filer: TFiler); override;
  471. procedure ReadData(Stream: TStream); inline;
  472. procedure WriteData(Stream: TStream); inline;
  473. public
  474. constructor Create(AOwner: TComponent); override;
  475. function GenerateSilhouette(const silhouetteParameters
  476. : TGLSilhouetteParameters): TGLSilhouette; override;
  477. procedure BuildList(var rci: TGLRenderContextInfo); override;
  478. procedure Assign(Source: TPersistent); override;
  479. function AxisAlignedDimensionsUnscaled: TVector; override;
  480. function RayCastIntersect(const rayStart, rayVector: TVector;
  481. intersectPoint: PVector = nil; intersectNormal: PVector = nil)
  482. : Boolean; override;
  483. published
  484. property CubeWidth: TGLFloat index 0 read GetCubeWHD write SetCubeWHD
  485. stored False;
  486. property CubeHeight: TGLFloat index 1 read GetCubeWHD write SetCubeWHD
  487. stored False;
  488. property CubeDepth: TGLFloat index 2 read GetCubeWHD write SetCubeWHD
  489. stored False;
  490. property NormalDirection: TGLNormalDirection read FNormalDirection
  491. write SetNormalDirection default ndOutside;
  492. property Parts: TCubeParts read FParts write SetParts
  493. default [cpTop, cpBottom, cpFront, cpBack, cpLeft, cpRight];
  494. end;
  495. (* Determines how and if normals are smoothed.
  496. - nsFlat : facetted look
  497. - nsSmooth : smooth look
  498. - nsNone : unlighted rendering, usefull for decla texturing *)
  499. TGLNormalSmoothing = (nsFlat, nsSmooth, nsNone);
  500. (* Base class for quadric objects.
  501. Introduces some basic Quadric interaction functions (the actual quadric
  502. math is part of the GLU library). *)
  503. TGLQuadricObject = class(TGLSceneObject)
  504. private
  505. FNormals: TGLNormalSmoothing;
  506. FNormalDirection: TGLNormalDirection;
  507. protected
  508. procedure SetNormals(aValue: TGLNormalSmoothing);
  509. procedure SetNormalDirection(aValue: TGLNormalDirection);
  510. procedure SetupQuadricParams(quadric: PGLUquadricObj);
  511. procedure SetNormalQuadricOrientation(quadric: PGLUquadricObj);
  512. procedure SetInvertedQuadricOrientation(quadric: PGLUquadricObj);
  513. public
  514. constructor Create(AOwner: TComponent); override;
  515. procedure Assign(Source: TPersistent); override;
  516. published
  517. property Normals: TGLNormalSmoothing read FNormals write SetNormals
  518. default nsSmooth;
  519. property NormalDirection: TGLNormalDirection read FNormalDirection
  520. write SetNormalDirection default ndOutside;
  521. end;
  522. TAngleLimit1 = -90 .. 90;
  523. TAngleLimit2 = 0 .. 360;
  524. TGLCapType = (ctNone, ctCenter, ctFlat);
  525. (* A sphere object.
  526. The sphere can have to and bottom caps, as well as being just a slice
  527. of sphere. *)
  528. TGLSphere = class(TGLQuadricObject)
  529. private
  530. FRadius: TGLFloat;
  531. FSlices, FStacks: TGLInt;
  532. FTop: TAngleLimit1;
  533. FBottom: TAngleLimit1;
  534. FStart: TAngleLimit2;
  535. FStop: TAngleLimit2;
  536. FTopCap, FBottomCap: TGLCapType;
  537. procedure SetBottom(aValue: TAngleLimit1);
  538. procedure SetBottomCap(aValue: TGLCapType);
  539. procedure SetRadius(const aValue: TGLFloat);
  540. procedure SetSlices(aValue: TGLInt);
  541. procedure SetStart(aValue: TAngleLimit2);
  542. procedure SetStop(aValue: TAngleLimit2);
  543. procedure SetStacks(aValue: TGLInt);
  544. procedure SetTop(aValue: TAngleLimit1);
  545. procedure SetTopCap(aValue: TGLCapType);
  546. public
  547. constructor Create(AOwner: TComponent); override;
  548. procedure Assign(Source: TPersistent); override;
  549. procedure BuildList(var rci: TGLRenderContextInfo); override;
  550. function AxisAlignedDimensionsUnscaled: TVector; override;
  551. function RayCastIntersect(const rayStart, rayVector: TVector;
  552. intersectPoint: PVector = nil; intersectNormal: PVector = nil)
  553. : Boolean; override;
  554. function GenerateSilhouette(const silhouetteParameters
  555. : TGLSilhouetteParameters): TGLSilhouette; override;
  556. published
  557. property Bottom: TAngleLimit1 read FBottom write SetBottom default -90;
  558. property BottomCap: TGLCapType read FBottomCap write SetBottomCap
  559. default ctNone;
  560. property Radius: TGLFloat read FRadius write SetRadius;
  561. property Slices: TGLInt read FSlices write SetSlices default 16;
  562. property Stacks: TGLInt read FStacks write SetStacks default 16;
  563. property Start: TAngleLimit2 read FStart write SetStart default 0;
  564. property Stop: TAngleLimit2 read FStop write SetStop default 360;
  565. property Top: TAngleLimit1 read FTop write SetTop default 90;
  566. property TopCap: TGLCapType read FTopCap write SetTopCap default ctNone;
  567. end;
  568. (* Base class for objects based on a polygon. *)
  569. TGLPolygonBase = class(TGLSceneObject)
  570. private
  571. FDivision: Integer;
  572. FSplineMode: TGLLineSplineMode;
  573. protected
  574. FNodes: TGLNodes;
  575. procedure CreateNodes; dynamic;
  576. procedure SetSplineMode(const val: TGLLineSplineMode);
  577. procedure SetDivision(const Value: Integer);
  578. procedure SetNodes(const aNodes: TGLNodes);
  579. public
  580. constructor Create(AOwner: TComponent); override;
  581. destructor Destroy; override;
  582. procedure Assign(Source: TPersistent); override;
  583. procedure NotifyChange(Sender: TObject); override;
  584. procedure AddNode(const coords: TGLCoordinates); overload;
  585. procedure AddNode(const X, Y, Z: TGLFloat); overload;
  586. procedure AddNode(const Value: TVector); overload;
  587. procedure AddNode(const Value: TAffineVector); overload;
  588. published
  589. // The nodes list.
  590. property Nodes: TGLNodes read FNodes write SetNodes;
  591. (* Number of divisions for each segment in spline modes.
  592. Minimum 1 (disabled), ignored in lsmLines mode. *)
  593. property Division: Integer read FDivision write SetDivision default 10;
  594. (* Default spline drawing mode.
  595. This mode is used only for the curve, not for the rotation path. *)
  596. property SplineMode: TGLLineSplineMode read FSplineMode write SetSplineMode
  597. default lsmLines;
  598. end;
  599. (* A Superellipsoid object. The Superellipsoid can have top and bottom caps,
  600. as well as being just a slice of Superellipsoid. *)
  601. TGLSuperellipsoid = class(TGLQuadricObject)
  602. private
  603. FRadius, FVCurve, FHCurve: TGLFloat;
  604. FSlices, FStacks: TGLInt;
  605. FTop: TAngleLimit1;
  606. FBottom: TAngleLimit1;
  607. FStart: TAngleLimit2;
  608. FStop: TAngleLimit2;
  609. FTopCap, FBottomCap: TGLCapType;
  610. procedure SetBottom(aValue: TAngleLimit1);
  611. procedure SetBottomCap(aValue: TGLCapType);
  612. procedure SetRadius(const aValue: TGLFloat);
  613. procedure SetVCurve(const aValue: TGLFloat);
  614. procedure SetHCurve(const aValue: TGLFloat);
  615. procedure SetSlices(aValue: TGLInt);
  616. procedure SetStart(aValue: TAngleLimit2);
  617. procedure SetStop(aValue: TAngleLimit2);
  618. procedure SetStacks(aValue: TGLInt);
  619. procedure SetTop(aValue: TAngleLimit1);
  620. procedure SetTopCap(aValue: TGLCapType);
  621. public
  622. constructor Create(AOwner: TComponent); override;
  623. procedure Assign(Source: TPersistent); override;
  624. procedure BuildList(var rci: TGLRenderContextInfo); override;
  625. function AxisAlignedDimensionsUnscaled: TVector; override;
  626. function RayCastIntersect(const rayStart, rayVector: TVector;
  627. intersectPoint: PVector = nil; intersectNormal: PVector = nil)
  628. : Boolean; override;
  629. function GenerateSilhouette(const silhouetteParameters
  630. : TGLSilhouetteParameters): TGLSilhouette; override;
  631. published
  632. property Bottom: TAngleLimit1 read FBottom write SetBottom default -90;
  633. property BottomCap: TGLCapType read FBottomCap write SetBottomCap
  634. default ctNone;
  635. property Radius: TGLFloat read FRadius write SetRadius;
  636. property VCurve: TGLFloat read FVCurve write SetVCurve;
  637. property HCurve: TGLFloat read FHCurve write SetHCurve;
  638. property Slices: TGLInt read FSlices write SetSlices default 16;
  639. property Stacks: TGLInt read FStacks write SetStacks default 16;
  640. property Start: TAngleLimit2 read FStart write SetStart default 0;
  641. property Stop: TAngleLimit2 read FStop write SetStop default 360;
  642. property Top: TAngleLimit1 read FTop write SetTop default 90;
  643. property TopCap: TGLCapType read FTopCap write SetTopCap default ctNone;
  644. end;
  645. // Issues for a unit-size cube stippled wireframe
  646. procedure CubeWireframeBuildList(var rci: TGLRenderContextInfo; Size: TGLFloat;
  647. Stipple: Boolean; const Color: TColorVector);
  648. const
  649. TangentAttributeName: PAnsiChar = 'Tangent';
  650. BinormalAttributeName: PAnsiChar = 'Binormal';
  651. // -------------------------------------------------------------
  652. implementation
  653. // -------------------------------------------------------------
  654. procedure CubeWireframeBuildList(var rci: TGLRenderContextInfo; Size: TGLFloat;
  655. Stipple: Boolean; const Color: TColorVector);
  656. var
  657. mi, ma: Single;
  658. begin
  659. {$IFDEF USE_OPENGL_DEBUG}
  660. if GL.GREMEDY_string_marker then
  661. gl.StringMarkerGREMEDY(22, 'CubeWireframeBuildList');
  662. {$ENDIF}
  663. rci.GLStates.Disable(stLighting);
  664. rci.GLStates.Enable(stLineSmooth);
  665. if Stipple then
  666. begin
  667. rci.GLStates.Enable(stLineStipple);
  668. rci.GLStates.Enable(stBlend);
  669. rci.GLStates.SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
  670. rci.GLStates.LineStippleFactor := 1;
  671. rci.GLStates.LineStipplePattern := $CCCC;
  672. end;
  673. rci.GLStates.LineWidth := 1;
  674. ma := 0.5 * Size;
  675. mi := -ma;
  676. gl.Color4fv(@Color);
  677. gl.Begin_(GL_LINE_STRIP);
  678. // front face
  679. gl.Vertex3f(ma, mi, mi);
  680. gl.Vertex3f(ma, ma, mi);
  681. gl.Vertex3f(ma, ma, ma);
  682. gl.Vertex3f(ma, mi, ma);
  683. gl.Vertex3f(ma, mi, mi);
  684. // partial up back face
  685. gl.Vertex3f(mi, mi, mi);
  686. gl.Vertex3f(mi, mi, ma);
  687. gl.Vertex3f(mi, ma, ma);
  688. gl.Vertex3f(mi, ma, mi);
  689. // right side low
  690. gl.Vertex3f(ma, ma, mi);
  691. gl.End_;
  692. gl.Begin_(GL_LINES);
  693. // right high
  694. gl.Vertex3f(ma, ma, ma);
  695. gl.Vertex3f(mi, ma, ma);
  696. // back low
  697. gl.Vertex3f(mi, mi, mi);
  698. gl.Vertex3f(mi, ma, mi);
  699. // left high
  700. gl.Vertex3f(ma, mi, ma);
  701. gl.Vertex3f(mi, mi, ma);
  702. gl.End_;
  703. end;
  704. // ------------------
  705. // ------------------ TGLDummyCube ------------------
  706. // ------------------
  707. constructor TGLDummyCube.Create(AOwner: TComponent);
  708. begin
  709. inherited;
  710. ObjectStyle := ObjectStyle + [osDirectDraw];
  711. FCubeSize := 1;
  712. FEdgeColor := TGLColor.Create(Self);
  713. FEdgeColor.Initialize(clrWhite);
  714. FGroupList := TGLListHandle.Create;
  715. CamInvarianceMode := cimNone;
  716. end;
  717. destructor TGLDummyCube.Destroy;
  718. begin
  719. FGroupList.Free;
  720. FEdgeColor.Free;
  721. inherited;
  722. end;
  723. procedure TGLDummyCube.Assign(Source: TPersistent);
  724. begin
  725. if Source is TGLDummyCube then
  726. begin
  727. FCubeSize := TGLDummyCube(Source).FCubeSize;
  728. FEdgeColor.Color := TGLDummyCube(Source).FEdgeColor.Color;
  729. FVisibleAtRunTime := TGLDummyCube(Source).FVisibleAtRunTime;
  730. NotifyChange(Self);
  731. end;
  732. inherited Assign(Source);
  733. end;
  734. function TGLDummyCube.AxisAlignedDimensionsUnscaled: TVector;
  735. begin
  736. Result.X := 0.5 * Abs(FCubeSize);
  737. Result.Y := Result.X;
  738. Result.Z := Result.X;
  739. Result.W := 0;
  740. end;
  741. function TGLDummyCube.RayCastIntersect(const rayStart, rayVector: TVector;
  742. intersectPoint: PVector = nil; intersectNormal: PVector = nil): Boolean;
  743. begin
  744. Result := False;
  745. end;
  746. procedure TGLDummyCube.BuildList(var rci: TGLRenderContextInfo);
  747. begin
  748. if (csDesigning in ComponentState) or (FVisibleAtRunTime) then
  749. CubeWireframeBuildList(rci, FCubeSize, True, EdgeColor.Color);
  750. end;
  751. procedure TGLDummyCube.DoRender(var rci: TGLRenderContextInfo;
  752. renderSelf, renderChildren: Boolean);
  753. begin
  754. if Assigned(FOnVisibilityDetermination) then
  755. if not FOnVisibilityDetermination(Self, rci) then
  756. Exit;
  757. if FAmalgamate and (not rci.amalgamating) then
  758. begin
  759. if FGroupList.Handle = 0 then
  760. begin
  761. FGroupList.AllocateHandle;
  762. Assert(FGroupList.Handle <> 0, 'Handle=0 for ' + ClassName);
  763. rci.GLStates.NewList(FGroupList.Handle, GL_COMPILE);
  764. rci.amalgamating := True;
  765. // try
  766. inherited;
  767. // finally
  768. rci.amalgamating := False;
  769. rci.GLStates.EndList;
  770. // end;
  771. end;
  772. rci.GLStates.CallList(FGroupList.Handle);
  773. end
  774. else
  775. begin
  776. // proceed as usual
  777. inherited;
  778. end;
  779. end;
  780. procedure TGLDummyCube.StructureChanged;
  781. begin
  782. if FAmalgamate then
  783. FGroupList.DestroyHandle;
  784. inherited;
  785. end;
  786. function TGLDummyCube.BarycenterAbsolutePosition: TVector;
  787. var
  788. i: Integer;
  789. begin
  790. if Count > 0 then
  791. begin
  792. Result := Children[0].BarycenterAbsolutePosition;
  793. for i := 1 to Count - 1 do
  794. Result := VectorAdd(Result, Children[i].BarycenterAbsolutePosition);
  795. ScaleVector(Result, 1 / Count);
  796. end
  797. else
  798. Result := AbsolutePosition;
  799. end;
  800. procedure TGLDummyCube.SetCubeSize(const val: TGLFloat);
  801. begin
  802. if val <> FCubeSize then
  803. begin
  804. FCubeSize := val;
  805. StructureChanged;
  806. end;
  807. end;
  808. procedure TGLDummyCube.SetEdgeColor(const val: TGLColor);
  809. begin
  810. if val <> FEdgeColor then
  811. begin
  812. FEdgeColor.Assign(val);
  813. StructureChanged;
  814. end;
  815. end;
  816. procedure TGLDummyCube.SetVisibleAtRunTime(const val: Boolean);
  817. begin
  818. if val <> FVisibleAtRunTime then
  819. begin
  820. FVisibleAtRunTime := val;
  821. StructureChanged;
  822. end;
  823. end;
  824. procedure TGLDummyCube.SetAmalgamate(const val: Boolean);
  825. begin
  826. if val <> FAmalgamate then
  827. begin
  828. FAmalgamate := val;
  829. if not val then
  830. FGroupList.DestroyHandle;
  831. inherited StructureChanged;
  832. end;
  833. end;
  834. // ------------------
  835. // ------------------ TGLPlane ------------------
  836. // ------------------
  837. constructor TGLPlane.Create(AOwner: TComponent);
  838. begin
  839. inherited Create(AOwner);
  840. FWidth := 1;
  841. FHeight := 1;
  842. FXTiles := 1;
  843. FYTiles := 1;
  844. FXScope := 1;
  845. FYScope := 1;
  846. ObjectStyle := ObjectStyle + [osDirectDraw];
  847. FStyle := [psSingleQuad, psTileTexture];
  848. end;
  849. procedure TGLPlane.Assign(Source: TPersistent);
  850. begin
  851. if Assigned(Source) and (Source is TGLPlane) then
  852. begin
  853. FWidth := TGLPlane(Source).FWidth;
  854. FHeight := TGLPlane(Source).FHeight;
  855. FXOffset := TGLPlane(Source).FXOffset;
  856. FXScope := TGLPlane(Source).FXScope;
  857. FXTiles := TGLPlane(Source).FXTiles;
  858. FYOffset := TGLPlane(Source).FYOffset;
  859. FYScope := TGLPlane(Source).FYScope;
  860. FYTiles := TGLPlane(Source).FYTiles;
  861. FStyle := TGLPlane(Source).FStyle;
  862. StructureChanged;
  863. end;
  864. inherited Assign(Source);
  865. end;
  866. function TGLPlane.AxisAlignedDimensionsUnscaled: TVector;
  867. begin
  868. Result.X := 0.5 * Abs(FWidth);
  869. Result.Y := 0.5 * Abs(FHeight);
  870. Result.Z := 0;
  871. end;
  872. function TGLPlane.RayCastIntersect(const rayStart, rayVector: TVector;
  873. intersectPoint: PVector = nil; intersectNormal: PVector = nil): Boolean;
  874. var
  875. locRayStart, locRayVector, ip: TVector;
  876. t: Single;
  877. begin
  878. locRayStart := AbsoluteToLocal(rayStart);
  879. locRayVector := AbsoluteToLocal(rayVector);
  880. if locRayStart.Z >= 0 then
  881. begin
  882. // ray start over plane
  883. if locRayVector.Z < 0 then
  884. begin
  885. t := locRayStart.Z / locRayVector.Z;
  886. ip.X := locRayStart.X - t * locRayVector.X;
  887. ip.Y := locRayStart.Y - t * locRayVector.Y;
  888. if (Abs(ip.X) <= 0.5 * Width) and (Abs(ip.Y) <= 0.5 * Height) then
  889. begin
  890. Result := True;
  891. if Assigned(intersectNormal) then
  892. intersectNormal^ := AbsoluteDirection;
  893. end
  894. else
  895. Result := False;
  896. end
  897. else
  898. Result := False;
  899. end
  900. else
  901. begin
  902. // ray start below plane
  903. if locRayVector.Z > 0 then
  904. begin
  905. t := locRayStart.Z / locRayVector.Z;
  906. ip.X := locRayStart.X - t * locRayVector.X;
  907. ip.Y := locRayStart.Y - t * locRayVector.Y;
  908. if (Abs(ip.X) <= 0.5 * Width) and (Abs(ip.Y) <= 0.5 * Height) then
  909. begin
  910. Result := True;
  911. if Assigned(intersectNormal) then
  912. intersectNormal^ := VectorNegate(AbsoluteDirection);
  913. end
  914. else
  915. Result := False;
  916. end
  917. else
  918. Result := False;
  919. end;
  920. if Result and Assigned(intersectPoint) then
  921. begin
  922. ip.Z := 0;
  923. ip.W := 1;
  924. intersectPoint^ := LocalToAbsolute(ip);
  925. end;
  926. end;
  927. function TGLPlane.GenerateSilhouette(const silhouetteParameters
  928. : TGLSilhouetteParameters): TGLSilhouette;
  929. var
  930. hw, hh: Single;
  931. begin
  932. Result := TGLSilhouette.Create;
  933. hw := FWidth * 0.5;
  934. hh := FHeight * 0.5;
  935. with Result.vertices do
  936. begin
  937. AddPoint(hw, hh);
  938. AddPoint(hw, -hh);
  939. AddPoint(-hw, -hh);
  940. AddPoint(-hw, hh);
  941. end;
  942. with Result.Indices do
  943. begin
  944. Add(0, 1);
  945. Add(1, 2);
  946. Add(2, 3);
  947. Add(3, 0);
  948. end;
  949. if silhouetteParameters.CappingRequired then
  950. with Result.CapIndices do
  951. begin
  952. Add(0, 1, 2);
  953. Add(2, 3, 0);
  954. end;
  955. end;
  956. procedure TGLPlane.BuildList(var rci: TGLRenderContextInfo);
  957. procedure EmitVertex(ptr: PGLVertexRec); inline;
  958. begin
  959. xgl.TexCoord2fv(@ptr^.TexCoord);
  960. gl.Vertex3fv(@ptr^.Position);
  961. end;
  962. var
  963. hw, hh, posXFact, posYFact, pX, pY1: TGLFloat;
  964. tx0, tx1, ty0, ty1, texSFact, texTFact: TGLFloat;
  965. texS, texT1: TGLFloat;
  966. X, Y: Integer;
  967. TanLoc, BinLoc: Integer;
  968. pVertex: PGLVertexRec;
  969. begin
  970. hw := FWidth * 0.5;
  971. hh := FHeight * 0.5;
  972. gl.Normal3fv(@ZVector);
  973. if GL.ARB_shader_objects and (rci.GLStates.CurrentProgram > 0) then
  974. begin
  975. TanLoc := gl.GetAttribLocation(rci.GLStates.CurrentProgram,
  976. TangentAttributeName);
  977. BinLoc := gl.GetAttribLocation(rci.GLStates.CurrentProgram,
  978. BinormalAttributeName);
  979. if TanLoc > -1 then
  980. gl.VertexAttrib3fv(TanLoc, @XVector);
  981. if BinLoc > -1 then
  982. gl.VertexAttrib3fv(BinLoc, @YVector);
  983. end;
  984. // determine tex coords extents
  985. if psTileTexture in FStyle then
  986. begin
  987. tx0 := FXOffset;
  988. tx1 := FXTiles * FXScope + FXOffset;
  989. ty0 := FYOffset;
  990. ty1 := FYTiles * FYScope + FYOffset;
  991. end
  992. else
  993. begin
  994. tx0 := 0;
  995. ty0 := tx0;
  996. tx1 := FXScope;
  997. ty1 := FYScope;
  998. end;
  999. if psSingleQuad in FStyle then
  1000. begin
  1001. // single quad plane
  1002. gl.Begin_(GL_TRIANGLES);
  1003. xgl.TexCoord2f(tx1, ty1);
  1004. gl.Vertex2f(hw, hh);
  1005. xgl.TexCoord2f(tx0, ty1);
  1006. gl.Vertex2f(-hw, hh);
  1007. xgl.TexCoord2f(tx0, ty0);
  1008. gl.Vertex2f(-hw, -hh);
  1009. gl.Vertex2f(-hw, -hh);
  1010. xgl.TexCoord2f(tx1, ty0);
  1011. gl.Vertex2f(hw, -hh);
  1012. xgl.TexCoord2f(tx1, ty1);
  1013. gl.Vertex2f(hw, hh);
  1014. gl.End_;
  1015. Exit;
  1016. end
  1017. else
  1018. begin
  1019. // multi-quad plane (actually built from tri-strips)
  1020. texSFact := (tx1 - tx0) / FXTiles;
  1021. texTFact := (ty1 - ty0) / FYTiles;
  1022. posXFact := FWidth / FXTiles;
  1023. posYFact := FHeight / FYTiles;
  1024. if FMesh = nil then
  1025. begin
  1026. SetLength(FMesh, FYTiles + 1, FXTiles + 1);
  1027. for Y := 0 to FYTiles do
  1028. begin
  1029. texT1 := Y * texTFact;
  1030. pY1 := Y * posYFact - hh;
  1031. for X := 0 to FXTiles do
  1032. begin
  1033. texS := X * texSFact;
  1034. pX := X * posXFact - hw;
  1035. FMesh[Y][X].Position := Vector3fMake(pX, pY1, 0.0);
  1036. FMesh[Y][X].TexCoord := Vector2fMake(texS, texT1);
  1037. end;
  1038. end;
  1039. end;
  1040. end;
  1041. gl.Begin_(GL_TRIANGLES);
  1042. for Y := 0 to FYTiles - 1 do
  1043. begin
  1044. for X := 0 to FXTiles - 1 do
  1045. begin
  1046. pVertex := @FMesh[Y][X];
  1047. EmitVertex(pVertex);
  1048. pVertex := @FMesh[Y][X + 1];
  1049. EmitVertex(pVertex);
  1050. pVertex := @FMesh[Y + 1][X];
  1051. EmitVertex(pVertex);
  1052. pVertex := @FMesh[Y + 1][X + 1];
  1053. EmitVertex(pVertex);
  1054. pVertex := @FMesh[Y + 1][X];
  1055. EmitVertex(pVertex);
  1056. pVertex := @FMesh[Y][X + 1];
  1057. EmitVertex(pVertex);
  1058. end;
  1059. end;
  1060. gl.End_;
  1061. end;
  1062. procedure TGLPlane.SetWidth(const aValue: Single);
  1063. begin
  1064. if aValue <> FWidth then
  1065. begin
  1066. FWidth := aValue;
  1067. FMesh := nil;
  1068. StructureChanged;
  1069. end;
  1070. end;
  1071. function TGLPlane.ScreenRect(aBuffer: TGLSceneBuffer): TRect;
  1072. var
  1073. v: array [0 .. 3] of TVector;
  1074. buf: TGLSceneBuffer;
  1075. hw, hh: TGLFloat;
  1076. begin
  1077. buf := aBuffer;
  1078. if Assigned(buf) then
  1079. begin
  1080. hw := FWidth * 0.5;
  1081. hh := FHeight * 0.5;
  1082. v[0] := LocalToAbsolute(PointMake(-hw, -hh, 0));
  1083. v[1] := LocalToAbsolute(PointMake(hw, -hh, 0));
  1084. v[2] := LocalToAbsolute(PointMake(hw, hh, 0));
  1085. v[3] := LocalToAbsolute(PointMake(-hw, hh, 0));
  1086. buf.WorldToScreen(@v[0], 4);
  1087. Result.Left := Round(MinFloat([v[0].X, v[1].X, v[2].X, v[3].X]));
  1088. Result.Right := Round(MaxFloat([v[0].X, v[1].X, v[2].X, v[3].X]));
  1089. Result.Top := Round(MinFloat([v[0].Y, v[1].Y, v[2].Y, v[3].Y]));
  1090. Result.Bottom := Round(MaxFloat([v[0].Y, v[1].Y, v[2].Y, v[3].Y]));
  1091. end
  1092. else
  1093. FillChar(Result, SizeOf(TRect), 0);
  1094. end;
  1095. function TGLPlane.PointDistance(const aPoint: TVector): Single;
  1096. begin
  1097. Result := VectorDotProduct(VectorSubtract(aPoint, AbsolutePosition),
  1098. AbsoluteDirection);
  1099. end;
  1100. procedure TGLPlane.SetHeight(const aValue: Single);
  1101. begin
  1102. if aValue <> FHeight then
  1103. begin
  1104. FHeight := aValue;
  1105. FMesh := nil;
  1106. StructureChanged;
  1107. end;
  1108. end;
  1109. procedure TGLPlane.SetXOffset(const Value: TGLFloat);
  1110. begin
  1111. if Value <> FXOffset then
  1112. begin
  1113. FXOffset := Value;
  1114. FMesh := nil;
  1115. StructureChanged;
  1116. end;
  1117. end;
  1118. procedure TGLPlane.SetXScope(const Value: TGLFloat);
  1119. begin
  1120. if Value <> FXScope then
  1121. begin
  1122. FXScope := Value;
  1123. if FXScope > 1 then
  1124. FXScope := 1;
  1125. FMesh := nil;
  1126. StructureChanged;
  1127. end;
  1128. end;
  1129. function TGLPlane.StoreXScope: Boolean;
  1130. begin
  1131. Result := (FXScope <> 1);
  1132. end;
  1133. procedure TGLPlane.SetXTiles(const Value: Cardinal);
  1134. begin
  1135. if Value <> FXTiles then
  1136. begin
  1137. FXTiles := Value;
  1138. FMesh := nil;
  1139. StructureChanged;
  1140. end;
  1141. end;
  1142. procedure TGLPlane.SetYOffset(const Value: TGLFloat);
  1143. begin
  1144. if Value <> FYOffset then
  1145. begin
  1146. FYOffset := Value;
  1147. FMesh := nil;
  1148. StructureChanged;
  1149. end;
  1150. end;
  1151. procedure TGLPlane.SetYScope(const Value: TGLFloat);
  1152. begin
  1153. if Value <> FYScope then
  1154. begin
  1155. FYScope := Value;
  1156. if FYScope > 1 then
  1157. FYScope := 1;
  1158. FMesh := nil;
  1159. StructureChanged;
  1160. end;
  1161. end;
  1162. function TGLPlane.StoreYScope: Boolean;
  1163. begin
  1164. Result := (FYScope <> 1);
  1165. end;
  1166. procedure TGLPlane.SetYTiles(const Value: Cardinal);
  1167. begin
  1168. if Value <> FYTiles then
  1169. begin
  1170. FYTiles := Value;
  1171. FMesh := nil;
  1172. StructureChanged;
  1173. end;
  1174. end;
  1175. procedure TGLPlane.SetStyle(const val: TGLPlaneStyles);
  1176. begin
  1177. if val <> FStyle then
  1178. begin
  1179. FStyle := val;
  1180. StructureChanged;
  1181. end;
  1182. end;
  1183. // ------------------
  1184. // ------------------ TGLSprite ------------------
  1185. // ------------------
  1186. constructor TGLSprite.Create(AOwner: TComponent);
  1187. begin
  1188. inherited Create(AOwner);
  1189. ObjectStyle := ObjectStyle + [osDirectDraw, osNoVisibilityCulling];
  1190. FAlphaChannel := 1;
  1191. FWidth := 1;
  1192. FHeight := 1;
  1193. end;
  1194. procedure TGLSprite.Assign(Source: TPersistent);
  1195. begin
  1196. if Source is TGLSprite then
  1197. begin
  1198. FWidth := TGLSprite(Source).FWidth;
  1199. FHeight := TGLSprite(Source).FHeight;
  1200. FRotation := TGLSprite(Source).FRotation;
  1201. FAlphaChannel := TGLSprite(Source).FAlphaChannel;
  1202. end;
  1203. inherited Assign(Source);
  1204. end;
  1205. function TGLSprite.AxisAlignedDimensionsUnscaled: TVector;
  1206. begin
  1207. Result.X := 0.5 * Abs(FWidth);
  1208. Result.Y := 0.5 * Abs(FHeight);
  1209. // Sprites turn with the camera and can be considered to have the same depth
  1210. // as width
  1211. Result.Z := 0.5 * Abs(FWidth);
  1212. end;
  1213. procedure TGLSprite.BuildList(var rci: TGLRenderContextInfo);
  1214. var
  1215. vx, vy: TAffineVector;
  1216. W, h: Single;
  1217. mat: TMatrix;
  1218. u0, v0, u1, v1: Integer;
  1219. begin
  1220. if FAlphaChannel <> 1 then
  1221. rci.GLStates.SetGLMaterialAlphaChannel(GL_FRONT, FAlphaChannel);
  1222. mat := rci.PipelineTransformation.ModelViewMatrix^;
  1223. // extraction of the direction vectors of the matrix
  1224. W := FWidth * 0.5;
  1225. h := FHeight * 0.5;
  1226. vx.X := mat.v[0].X;
  1227. vy.X := mat.v[0].Y;
  1228. vx.Y := mat.v[1].X;
  1229. vy.Y := mat.v[1].Y;
  1230. vx.Z := mat.v[2].X;
  1231. vy.Z := mat.v[2].Y;
  1232. ScaleVector(vx, W / VectorLength(vx));
  1233. ScaleVector(vy, h / VectorLength(vy));
  1234. if FMirrorU then
  1235. begin
  1236. u0 := 1;
  1237. u1 := 0;
  1238. end
  1239. else
  1240. begin
  1241. u0 := 0;
  1242. u1 := 1;
  1243. end;
  1244. if FMirrorV then
  1245. begin
  1246. v0 := 1;
  1247. v1 := 0;
  1248. end
  1249. else
  1250. begin
  1251. v0 := 0;
  1252. v1 := 1;
  1253. end;
  1254. if FRotation <> 0 then
  1255. begin
  1256. gl.PushMatrix;
  1257. gl.Rotatef(FRotation, mat.v[0].Z, mat.v[1].Z, mat.v[2].Z);
  1258. end;
  1259. gl.Begin_(GL_QUADS);
  1260. xgl.TexCoord2f(u1, v1);
  1261. gl.Vertex3f(vx.X + vy.X, vx.Y + vy.Y, vx.Z + vy.Z);
  1262. xgl.TexCoord2f(u0, v1);
  1263. gl.Vertex3f(-vx.X + vy.X, -vx.Y + vy.Y, -vx.Z + vy.Z);
  1264. xgl.TexCoord2f(u0, v0);
  1265. gl.Vertex3f(-vx.X - vy.X, -vx.Y - vy.Y, -vx.Z - vy.Z);
  1266. xgl.TexCoord2f(u1, v0);
  1267. gl.Vertex3f(vx.X - vy.X, vx.Y - vy.Y, vx.Z - vy.Z);
  1268. gl.End_;
  1269. if FRotation <> 0 then
  1270. gl.PopMatrix;
  1271. end;
  1272. procedure TGLSprite.SetWidth(const val: TGLFloat);
  1273. begin
  1274. if FWidth <> val then
  1275. begin
  1276. FWidth := val;
  1277. NotifyChange(Self);
  1278. end;
  1279. end;
  1280. procedure TGLSprite.SetHeight(const val: TGLFloat);
  1281. begin
  1282. if FHeight <> val then
  1283. begin
  1284. FHeight := val;
  1285. NotifyChange(Self);
  1286. end;
  1287. end;
  1288. procedure TGLSprite.SetRotation(const val: TGLFloat);
  1289. begin
  1290. if FRotation <> val then
  1291. begin
  1292. FRotation := val;
  1293. NotifyChange(Self);
  1294. end;
  1295. end;
  1296. procedure TGLSprite.SetAlphaChannel(const val: Single);
  1297. begin
  1298. if val <> FAlphaChannel then
  1299. begin
  1300. if val < 0 then
  1301. FAlphaChannel := 0
  1302. else if val > 1 then
  1303. FAlphaChannel := 1
  1304. else
  1305. FAlphaChannel := val;
  1306. NotifyChange(Self);
  1307. end;
  1308. end;
  1309. function TGLSprite.StoreAlphaChannel: Boolean;
  1310. begin
  1311. Result := (FAlphaChannel <> 1);
  1312. end;
  1313. procedure TGLSprite.SetMirrorU(const val: Boolean);
  1314. begin
  1315. FMirrorU := val;
  1316. NotifyChange(Self);
  1317. end;
  1318. procedure TGLSprite.SetMirrorV(const val: Boolean);
  1319. begin
  1320. FMirrorV := val;
  1321. NotifyChange(Self);
  1322. end;
  1323. procedure TGLSprite.SetSize(const Width, Height: TGLFloat);
  1324. begin
  1325. FWidth := Width;
  1326. FHeight := Height;
  1327. NotifyChange(Self);
  1328. end;
  1329. procedure TGLSprite.SetSquareSize(const Size: TGLFloat);
  1330. begin
  1331. FWidth := Size;
  1332. FHeight := Size;
  1333. NotifyChange(Self);
  1334. end;
  1335. // ------------------
  1336. // ------------------ TGLPointParameters ------------------
  1337. // ------------------
  1338. constructor TGLPointParameters.Create(AOwner: TPersistent);
  1339. begin
  1340. inherited Create(AOwner);
  1341. FMinSize := 0;
  1342. FMaxSize := 128;
  1343. FFadeTresholdSize := 1;
  1344. FDistanceAttenuation := TGLCoordinates.CreateInitialized(Self, XHmgVector,
  1345. csVector);
  1346. end;
  1347. destructor TGLPointParameters.Destroy;
  1348. begin
  1349. FDistanceAttenuation.Free;
  1350. inherited;
  1351. end;
  1352. procedure TGLPointParameters.Assign(Source: TPersistent);
  1353. begin
  1354. if Source is TGLPointParameters then
  1355. begin
  1356. FMinSize := TGLPointParameters(Source).FMinSize;
  1357. FMaxSize := TGLPointParameters(Source).FMaxSize;
  1358. FFadeTresholdSize := TGLPointParameters(Source).FFadeTresholdSize;
  1359. FDistanceAttenuation.Assign(TGLPointParameters(Source).DistanceAttenuation);
  1360. end;
  1361. end;
  1362. procedure TGLPointParameters.DefineProperties(Filer: TFiler);
  1363. var
  1364. defaultParams: Boolean;
  1365. begin
  1366. inherited;
  1367. defaultParams := (FMaxSize = 128) and (FMinSize = 0) and
  1368. (FFadeTresholdSize = 1);
  1369. Filer.DefineBinaryProperty('PointParams', ReadData, WriteData,
  1370. not defaultParams);
  1371. end;
  1372. procedure TGLPointParameters.ReadData(Stream: TStream);
  1373. begin
  1374. with Stream do
  1375. begin
  1376. Read(FMinSize, SizeOf(Single));
  1377. Read(FMaxSize, SizeOf(Single));
  1378. Read(FFadeTresholdSize, SizeOf(Single));
  1379. end;
  1380. end;
  1381. procedure TGLPointParameters.WriteData(Stream: TStream);
  1382. begin
  1383. with Stream do
  1384. begin
  1385. Write(FMinSize, SizeOf(Single));
  1386. Write(FMaxSize, SizeOf(Single));
  1387. Write(FFadeTresholdSize, SizeOf(Single));
  1388. end;
  1389. end;
  1390. procedure TGLPointParameters.Apply;
  1391. begin
  1392. if Enabled and GL.ARB_point_parameters then
  1393. begin
  1394. gl.PointParameterf(GL_POINT_SIZE_MIN_ARB, FMinSize);
  1395. gl.PointParameterf(GL_POINT_SIZE_MAX_ARB, FMaxSize);
  1396. gl.PointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_ARB, FFadeTresholdSize);
  1397. gl.PointParameterfv(GL_DISTANCE_ATTENUATION_EXT,
  1398. FDistanceAttenuation.AsAddress);
  1399. end;
  1400. end;
  1401. procedure TGLPointParameters.UnApply;
  1402. begin
  1403. if Enabled and GL.ARB_point_parameters then
  1404. begin
  1405. gl.PointParameterf(GL_POINT_SIZE_MIN_ARB, 0);
  1406. gl.PointParameterf(GL_POINT_SIZE_MAX_ARB, 128);
  1407. gl.PointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 1);
  1408. gl.PointParameterfv(GL_DISTANCE_ATTENUATION_EXT, @XVector);
  1409. end;
  1410. end;
  1411. procedure TGLPointParameters.SetEnabled(const val: Boolean);
  1412. begin
  1413. if val <> FEnabled then
  1414. begin
  1415. FEnabled := val;
  1416. NotifyChange(Self);
  1417. end;
  1418. end;
  1419. procedure TGLPointParameters.SetMinSize(const val: Single);
  1420. begin
  1421. if val <> FMinSize then
  1422. begin
  1423. if val < 0 then
  1424. FMinSize := 0
  1425. else
  1426. FMinSize := val;
  1427. NotifyChange(Self);
  1428. end;
  1429. end;
  1430. procedure TGLPointParameters.SetMaxSize(const val: Single);
  1431. begin
  1432. if val <> FMaxSize then
  1433. begin
  1434. if val < 0 then
  1435. FMaxSize := 0
  1436. else
  1437. FMaxSize := val;
  1438. NotifyChange(Self);
  1439. end;
  1440. end;
  1441. procedure TGLPointParameters.SetFadeTresholdSize(const val: Single);
  1442. begin
  1443. if val <> FFadeTresholdSize then
  1444. begin
  1445. if val < 0 then
  1446. FFadeTresholdSize := 0
  1447. else
  1448. FFadeTresholdSize := val;
  1449. NotifyChange(Self);
  1450. end;
  1451. end;
  1452. procedure TGLPointParameters.SetDistanceAttenuation(const val: TGLCoordinates);
  1453. begin
  1454. FDistanceAttenuation.Assign(val);
  1455. end;
  1456. // ------------------
  1457. // ------------------ TGLPoints ------------------
  1458. // ------------------
  1459. constructor TGLPoints.Create(AOwner: TComponent);
  1460. begin
  1461. inherited Create(AOwner);
  1462. ObjectStyle := ObjectStyle + [osDirectDraw, osNoVisibilityCulling];
  1463. FStyle := psSquare;
  1464. FSize := cDefaultPointSize;
  1465. FPositions := TAffineVectorList.Create;
  1466. FPositions.Add(NullVector);
  1467. FColors := TVectorList.Create;
  1468. FPointParameters := TGLPointParameters.Create(Self);
  1469. end;
  1470. destructor TGLPoints.Destroy;
  1471. begin
  1472. FPointParameters.Free;
  1473. FColors.Free;
  1474. FPositions.Free;
  1475. inherited;
  1476. end;
  1477. procedure TGLPoints.Assign(Source: TPersistent);
  1478. begin
  1479. if Source is TGLPoints then
  1480. begin
  1481. FSize := TGLPoints(Source).FSize;
  1482. FStyle := TGLPoints(Source).FStyle;
  1483. FPositions.Assign(TGLPoints(Source).FPositions);
  1484. FColors.Assign(TGLPoints(Source).FColors);
  1485. StructureChanged
  1486. end;
  1487. inherited Assign(Source);
  1488. end;
  1489. procedure TGLPoints.BuildList(var rci: TGLRenderContextInfo);
  1490. var
  1491. n: Integer;
  1492. v: TVector;
  1493. begin
  1494. n := FPositions.Count;
  1495. if n = 0 then
  1496. Exit;
  1497. case FColors.Count of
  1498. 0:
  1499. gl.Color4f(1, 1, 1, 1);
  1500. 1:
  1501. gl.Color4fv(PGLFloat(FColors.List));
  1502. else
  1503. if FColors.Count < n then
  1504. n := FColors.Count;
  1505. gl.ColorPointer(4, GL_FLOAT, 0, FColors.List);
  1506. gl.EnableClientState(GL_COLOR_ARRAY);
  1507. end;
  1508. if FColors.Count < 2 then
  1509. gl.DisableClientState(GL_COLOR_ARRAY);
  1510. rci.GLStates.Disable(stLighting);
  1511. if n = 0 then
  1512. begin
  1513. v := NullHmgPoint;
  1514. gl.VertexPointer(3, GL_FLOAT, 0, @v);
  1515. n := 1;
  1516. end
  1517. else
  1518. gl.VertexPointer(3, GL_FLOAT, 0, FPositions.List);
  1519. gl.EnableClientState(GL_VERTEX_ARRAY);
  1520. if NoZWrite then
  1521. rci.GLStates.DepthWriteMask := False;
  1522. rci.GLStates.PointSize := FSize;
  1523. PointParameters.Apply;
  1524. if GL.EXT_compiled_vertex_array and (n > 64) then
  1525. gl.LockArrays(0, n);
  1526. case FStyle of
  1527. psSquare:
  1528. begin
  1529. // square point (simplest method, fastest)
  1530. rci.GLStates.Disable(stBlend);
  1531. end;
  1532. psRound:
  1533. begin
  1534. rci.GLStates.Enable(stPointSmooth);
  1535. rci.GLStates.Enable(stAlphaTest);
  1536. rci.GLStates.SetGLAlphaFunction(cfGreater, 0.5);
  1537. rci.GLStates.Disable(stBlend);
  1538. end;
  1539. psSmooth:
  1540. begin
  1541. rci.GLStates.Enable(stPointSmooth);
  1542. rci.GLStates.Enable(stAlphaTest);
  1543. rci.GLStates.SetGLAlphaFunction(cfNotEqual, 0.0);
  1544. rci.GLStates.Enable(stBlend);
  1545. rci.GLStates.SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
  1546. end;
  1547. psSmoothAdditive:
  1548. begin
  1549. rci.GLStates.Enable(stPointSmooth);
  1550. rci.GLStates.Enable(stAlphaTest);
  1551. rci.GLStates.SetGLAlphaFunction(cfNotEqual, 0.0);
  1552. rci.GLStates.Enable(stBlend);
  1553. rci.GLStates.SetBlendFunc(bfSrcAlpha, bfOne);
  1554. end;
  1555. psSquareAdditive:
  1556. begin
  1557. rci.GLStates.Enable(stBlend);
  1558. rci.GLStates.SetBlendFunc(bfSrcAlpha, bfOne);
  1559. end;
  1560. else
  1561. Assert(False);
  1562. end;
  1563. gl.DrawArrays(GL_POINTS, 0, n);
  1564. if GL.EXT_compiled_vertex_array and (n > 64) then
  1565. gl.UnlockArrays;
  1566. PointParameters.UnApply;
  1567. gl.DisableClientState(GL_VERTEX_ARRAY);
  1568. if FColors.Count > 1 then
  1569. gl.DisableClientState(GL_COLOR_ARRAY);
  1570. end;
  1571. function TGLPoints.StoreSize: Boolean;
  1572. begin
  1573. Result := (FSize <> cDefaultPointSize);
  1574. end;
  1575. procedure TGLPoints.SetNoZWrite(const val: Boolean);
  1576. begin
  1577. if FNoZWrite <> val then
  1578. begin
  1579. FNoZWrite := val;
  1580. StructureChanged;
  1581. end;
  1582. end;
  1583. procedure TGLPoints.SetStatic(const val: Boolean);
  1584. begin
  1585. if FStatic <> val then
  1586. begin
  1587. FStatic := val;
  1588. if val then
  1589. ObjectStyle := ObjectStyle - [osDirectDraw]
  1590. else
  1591. ObjectStyle := ObjectStyle + [osDirectDraw];
  1592. StructureChanged;
  1593. end;
  1594. end;
  1595. procedure TGLPoints.SetSize(const val: Single);
  1596. begin
  1597. if FSize <> val then
  1598. begin
  1599. FSize := val;
  1600. StructureChanged;
  1601. end;
  1602. end;
  1603. procedure TGLPoints.SetPositions(const val: TAffineVectorList);
  1604. begin
  1605. FPositions.Assign(val);
  1606. StructureChanged;
  1607. end;
  1608. procedure TGLPoints.SetColors(const val: TVectorList);
  1609. begin
  1610. FColors.Assign(val);
  1611. StructureChanged;
  1612. end;
  1613. procedure TGLPoints.SetStyle(const val: TGLPointStyle);
  1614. begin
  1615. if FStyle <> val then
  1616. begin
  1617. FStyle := val;
  1618. StructureChanged;
  1619. end;
  1620. end;
  1621. procedure TGLPoints.SetPointParameters(const val: TGLPointParameters);
  1622. begin
  1623. FPointParameters.Assign(val);
  1624. end;
  1625. // ------------------
  1626. // ------------------ TGLLineBase ------------------
  1627. // ------------------
  1628. constructor TGLLineBase.Create(AOwner: TComponent);
  1629. begin
  1630. inherited Create(AOwner);
  1631. FLineColor := TGLColor.Create(Self);
  1632. FLineColor.Initialize(clrWhite);
  1633. FLinePattern := $FFFF;
  1634. FAntiAliased := False;
  1635. FLineWidth := 1.0;
  1636. end;
  1637. destructor TGLLineBase.Destroy;
  1638. begin
  1639. FLineColor.Free;
  1640. inherited Destroy;
  1641. end;
  1642. procedure TGLLineBase.NotifyChange(Sender: TObject);
  1643. begin
  1644. if Sender = FLineColor then
  1645. StructureChanged;
  1646. inherited;
  1647. end;
  1648. procedure TGLLineBase.SetLineColor(const Value: TGLColor);
  1649. begin
  1650. FLineColor.Color := Value.Color;
  1651. StructureChanged;
  1652. end;
  1653. procedure TGLLineBase.SetLinePattern(const Value: TGLushort);
  1654. begin
  1655. if FLinePattern <> Value then
  1656. begin
  1657. FLinePattern := Value;
  1658. StructureChanged;
  1659. end;
  1660. end;
  1661. procedure TGLLineBase.SetLineWidth(const val: Single);
  1662. begin
  1663. if FLineWidth <> val then
  1664. begin
  1665. FLineWidth := val;
  1666. StructureChanged;
  1667. end;
  1668. end;
  1669. function TGLLineBase.StoreLineWidth: Boolean;
  1670. begin
  1671. Result := (FLineWidth <> 1.0);
  1672. end;
  1673. procedure TGLLineBase.SetAntiAliased(const val: Boolean);
  1674. begin
  1675. if FAntiAliased <> val then
  1676. begin
  1677. FAntiAliased := val;
  1678. StructureChanged;
  1679. end;
  1680. end;
  1681. procedure TGLLineBase.Assign(Source: TPersistent);
  1682. begin
  1683. if Source is TGLLineBase then
  1684. begin
  1685. LineColor := TGLLineBase(Source).FLineColor;
  1686. LinePattern := TGLLineBase(Source).FLinePattern;
  1687. LineWidth := TGLLineBase(Source).FLineWidth;
  1688. AntiAliased := TGLLineBase(Source).FAntiAliased;
  1689. end;
  1690. inherited Assign(Source);
  1691. end;
  1692. procedure TGLLineBase.SetupLineStyle(var rci: TGLRenderContextInfo);
  1693. begin
  1694. with rci.GLStates do
  1695. begin
  1696. Disable(stLighting);
  1697. if FLinePattern <> $FFFF then
  1698. begin
  1699. Enable(stLineStipple);
  1700. Enable(stBlend);
  1701. SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
  1702. LineStippleFactor := 1;
  1703. LineStipplePattern := FLinePattern;
  1704. end
  1705. else
  1706. Disable(stLineStipple);
  1707. if FAntiAliased then
  1708. begin
  1709. Enable(stLineSmooth);
  1710. Enable(stBlend);
  1711. SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
  1712. end
  1713. else
  1714. Disable(stLineSmooth);
  1715. LineWidth := FLineWidth;
  1716. if FLineColor.Alpha <> 1 then
  1717. begin
  1718. if not FAntiAliased then
  1719. begin
  1720. Enable(stBlend);
  1721. SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
  1722. end;
  1723. gl.Color4fv(FLineColor.AsAddress);
  1724. end
  1725. else
  1726. gl.Color3fv(FLineColor.AsAddress);
  1727. end;
  1728. end;
  1729. // ------------------
  1730. // ------------------ TGLLinesNode ------------------
  1731. // ------------------
  1732. constructor TGLLinesNode.Create(Collection: TCollection);
  1733. begin
  1734. inherited Create(Collection);
  1735. FColor := TGLColor.Create(Self);
  1736. FColor.Initialize((TGLLinesNodes(Collection).GetOwner as TGLLines)
  1737. .NodeColor.Color);
  1738. FColor.OnNotifyChange := OnColorChange;
  1739. end;
  1740. destructor TGLLinesNode.Destroy;
  1741. begin
  1742. FColor.Free;
  1743. inherited Destroy;
  1744. end;
  1745. procedure TGLLinesNode.Assign(Source: TPersistent);
  1746. begin
  1747. if Source is TGLLinesNode then
  1748. FColor.Assign(TGLLinesNode(Source).FColor);
  1749. inherited;
  1750. end;
  1751. procedure TGLLinesNode.SetColor(const val: TGLColor);
  1752. begin
  1753. FColor.Assign(val);
  1754. end;
  1755. procedure TGLLinesNode.OnColorChange(Sender: TObject);
  1756. begin
  1757. (Collection as TGLNodes).NotifyChange;
  1758. end;
  1759. function TGLLinesNode.StoreColor: Boolean;
  1760. begin
  1761. Result := not VectorEquals((TGLLinesNodes(Collection).GetOwner as TGLLines)
  1762. .NodeColor.Color, FColor.Color);
  1763. end;
  1764. // ------------------
  1765. // ------------------ TGLLinesNodes ------------------
  1766. // ------------------
  1767. constructor TGLLinesNodes.Create(AOwner: TComponent);
  1768. begin
  1769. inherited Create(AOwner, TGLLinesNode);
  1770. end;
  1771. procedure TGLLinesNodes.NotifyChange;
  1772. begin
  1773. if (GetOwner <> nil) then
  1774. (GetOwner as TGLBaseSceneObject).StructureChanged;
  1775. end;
  1776. // ------------------
  1777. // ------------------ TGLNodedLines ------------------
  1778. // ------------------
  1779. constructor TGLNodedLines.Create(AOwner: TComponent);
  1780. begin
  1781. inherited Create(AOwner);
  1782. FNodes := TGLLinesNodes.Create(Self);
  1783. FNodeColor := TGLColor.Create(Self);
  1784. FNodeColor.Initialize(clrBlue);
  1785. FNodeColor.OnNotifyChange := OnNodeColorChanged;
  1786. FOldNodeColor := clrBlue;
  1787. FNodesAspect := lnaAxes;
  1788. FNodeSize := 1;
  1789. end;
  1790. destructor TGLNodedLines.Destroy;
  1791. begin
  1792. FNodes.Free;
  1793. FNodeColor.Free;
  1794. inherited Destroy;
  1795. end;
  1796. procedure TGLNodedLines.SetNodesAspect(const Value: TGLLineNodesAspect);
  1797. begin
  1798. if Value <> FNodesAspect then
  1799. begin
  1800. FNodesAspect := Value;
  1801. StructureChanged;
  1802. end;
  1803. end;
  1804. procedure TGLNodedLines.SetNodeColor(const Value: TGLColor);
  1805. begin
  1806. FNodeColor.Color := Value.Color;
  1807. StructureChanged;
  1808. end;
  1809. procedure TGLNodedLines.OnNodeColorChanged(Sender: TObject);
  1810. var
  1811. i: Integer;
  1812. begin
  1813. // update color for nodes...
  1814. for i := 0 to Nodes.Count - 1 do
  1815. if VectorEquals(TGLLinesNode(Nodes[i]).Color.Color, FOldNodeColor) then
  1816. TGLLinesNode(Nodes[i]).Color.Assign(FNodeColor);
  1817. SetVector(FOldNodeColor, FNodeColor.Color);
  1818. end;
  1819. procedure TGLNodedLines.SetNodes(const aNodes: TGLLinesNodes);
  1820. begin
  1821. FNodes.Assign(aNodes);
  1822. StructureChanged;
  1823. end;
  1824. procedure TGLNodedLines.SetNodeSize(const val: Single);
  1825. begin
  1826. if val <= 0 then
  1827. FNodeSize := 1
  1828. else
  1829. FNodeSize := val;
  1830. StructureChanged;
  1831. end;
  1832. function TGLNodedLines.StoreNodeSize: Boolean;
  1833. begin
  1834. Result := FNodeSize <> 1;
  1835. end;
  1836. procedure TGLNodedLines.Assign(Source: TPersistent);
  1837. begin
  1838. if Source is TGLNodedLines then
  1839. begin
  1840. SetNodes(TGLNodedLines(Source).FNodes);
  1841. FNodesAspect := TGLNodedLines(Source).FNodesAspect;
  1842. FNodeColor.Color := TGLNodedLines(Source).FNodeColor.Color;
  1843. FNodeSize := TGLNodedLines(Source).FNodeSize;
  1844. end;
  1845. inherited Assign(Source);
  1846. end;
  1847. procedure TGLNodedLines.DrawNode(var rci: TGLRenderContextInfo; X, Y, Z: Single;
  1848. Color: TGLColor);
  1849. begin
  1850. gl.PushMatrix;
  1851. gl.Translatef(X, Y, Z);
  1852. case NodesAspect of
  1853. lnaAxes:
  1854. AxesBuildList(rci, $CCCC, FNodeSize * 0.5);
  1855. lnaCube:
  1856. CubeWireframeBuildList(rci, FNodeSize, False, Color.Color);
  1857. else
  1858. Assert(False)
  1859. end;
  1860. gl.PopMatrix;
  1861. end;
  1862. function TGLNodedLines.AxisAlignedDimensionsUnscaled: TVector;
  1863. var
  1864. i: Integer;
  1865. begin
  1866. RstVector(Result);
  1867. for i := 0 to Nodes.Count - 1 do
  1868. MaxVector(Result, VectorAbs(Nodes[i].AsVector));
  1869. // EG: commented out, line below looks suspicious, since scale isn't taken
  1870. // into account in previous loop, must have been hiding another bug... somewhere...
  1871. // DivideVector(Result, Scale.AsVector); //DanB ?
  1872. end;
  1873. procedure TGLNodedLines.AddNode(const coords: TGLCoordinates);
  1874. var
  1875. n: TGLNode;
  1876. begin
  1877. n := Nodes.Add;
  1878. if Assigned(coords) then
  1879. n.AsVector := coords.AsVector;
  1880. StructureChanged;
  1881. end;
  1882. procedure TGLNodedLines.AddNode(const X, Y, Z: TGLFloat);
  1883. var
  1884. n: TGLNode;
  1885. begin
  1886. n := Nodes.Add;
  1887. n.AsVector := VectorMake(X, Y, Z, 1);
  1888. StructureChanged;
  1889. end;
  1890. procedure TGLNodedLines.AddNode(const Value: TVector);
  1891. var
  1892. n: TGLNode;
  1893. begin
  1894. n := Nodes.Add;
  1895. n.AsVector := Value;
  1896. StructureChanged;
  1897. end;
  1898. procedure TGLNodedLines.AddNode(const Value: TAffineVector);
  1899. var
  1900. n: TGLNode;
  1901. begin
  1902. n := Nodes.Add;
  1903. n.AsVector := VectorMake(Value);
  1904. StructureChanged;
  1905. end;
  1906. // ------------------
  1907. // ------------------ TGLLines ------------------
  1908. // ------------------
  1909. constructor TGLLines.Create(AOwner: TComponent);
  1910. begin
  1911. inherited Create(AOwner);
  1912. FDivision := 10;
  1913. FSplineMode := lsmLines;
  1914. FNURBSKnots := TSingleList.Create;
  1915. FNURBSOrder := 0;
  1916. FNURBSTolerance := 50;
  1917. end;
  1918. destructor TGLLines.Destroy;
  1919. begin
  1920. FNURBSKnots.Free;
  1921. inherited Destroy;
  1922. end;
  1923. procedure TGLLines.SetDivision(const Value: Integer);
  1924. begin
  1925. if Value <> FDivision then
  1926. begin
  1927. if Value < 1 then
  1928. FDivision := 1
  1929. else
  1930. FDivision := Value;
  1931. StructureChanged;
  1932. end;
  1933. end;
  1934. procedure TGLLines.SetOptions(const val: TGLLinesOptions);
  1935. begin
  1936. FOptions := val;
  1937. StructureChanged;
  1938. end;
  1939. procedure TGLLines.SetSplineMode(const val: TGLLineSplineMode);
  1940. begin
  1941. if FSplineMode <> val then
  1942. begin
  1943. FSplineMode := val;
  1944. StructureChanged;
  1945. end;
  1946. end;
  1947. procedure TGLLines.SetNURBSOrder(const val: Integer);
  1948. begin
  1949. if val <> FNURBSOrder then
  1950. begin
  1951. FNURBSOrder := val;
  1952. StructureChanged;
  1953. end;
  1954. end;
  1955. procedure TGLLines.SetNURBSTolerance(const val: Single);
  1956. begin
  1957. if val <> FNURBSTolerance then
  1958. begin
  1959. FNURBSTolerance := val;
  1960. StructureChanged;
  1961. end;
  1962. end;
  1963. procedure TGLLines.Assign(Source: TPersistent);
  1964. begin
  1965. if Source is TGLLines then
  1966. begin
  1967. FDivision := TGLLines(Source).FDivision;
  1968. FSplineMode := TGLLines(Source).FSplineMode;
  1969. FOptions := TGLLines(Source).FOptions;
  1970. end;
  1971. inherited Assign(Source);
  1972. end;
  1973. procedure TGLLines.BuildList(var rci: TGLRenderContextInfo);
  1974. var
  1975. i, n: Integer;
  1976. A, B, C: TGLFloat;
  1977. f: Single;
  1978. Spline: TCubicSpline;
  1979. vertexColor: TVector;
  1980. nodeBuffer: array of TAffineVector;
  1981. colorBuffer: array of TVector;
  1982. nurbsRenderer: PGLUNurbs;
  1983. begin
  1984. if Nodes.Count > 1 then
  1985. begin
  1986. // first, we setup the line color & stippling styles
  1987. SetupLineStyle(rci);
  1988. if rci.bufferDepthTest then
  1989. rci.GLStates.Enable(stDepthTest);
  1990. if loColorLogicXor in Options then
  1991. begin
  1992. rci.GLStates.Enable(stColorLogicOp);
  1993. rci.GLStates.LogicOpMode := loXOr;
  1994. end;
  1995. // Set up the control point buffer for Bezier splines and NURBS curves.
  1996. // If required this could be optimized by storing a cached node buffer.
  1997. if (FSplineMode = lsmBezierSpline) or (FSplineMode = lsmNURBSCurve) then
  1998. begin
  1999. SetLength(nodeBuffer, Nodes.Count);
  2000. SetLength(colorBuffer, Nodes.Count);
  2001. for i := 0 to Nodes.Count - 1 do
  2002. with TGLLinesNode(Nodes[i]) do
  2003. begin
  2004. nodeBuffer[i] := AsAffineVector;
  2005. colorBuffer[i] := Color.Color;
  2006. end;
  2007. end;
  2008. if FSplineMode = lsmBezierSpline then
  2009. begin
  2010. // map evaluator
  2011. rci.GLStates.PushAttrib([sttEval]);
  2012. gl.Enable(GL_MAP1_VERTEX_3);
  2013. gl.Enable(GL_MAP1_COLOR_4);
  2014. gl.Map1f(GL_MAP1_VERTEX_3, 0, 1, 3, Nodes.Count, @nodeBuffer[0]);
  2015. gl.Map1f(GL_MAP1_COLOR_4, 0, 1, 4, Nodes.Count, @colorBuffer[0]);
  2016. end;
  2017. // start drawing the line
  2018. if (FSplineMode = lsmNURBSCurve) and (FDivision >= 2) then
  2019. begin
  2020. if (FNURBSOrder > 0) and (FNURBSKnots.Count > 0) then
  2021. begin
  2022. nurbsRenderer := gluNewNurbsRenderer;
  2023. // try
  2024. gluNurbsProperty(nurbsRenderer, GLU_SAMPLING_TOLERANCE,
  2025. FNURBSTolerance);
  2026. gluNurbsProperty(nurbsRenderer, GLU_DISPLAY_MODE, GLU_FILL);
  2027. gluBeginCurve(nurbsRenderer);
  2028. gluNurbsCurve(nurbsRenderer, FNURBSKnots.Count, @FNURBSKnots.List[0], 3,
  2029. @nodeBuffer[0], FNURBSOrder, GL_MAP1_VERTEX_3);
  2030. gluEndCurve(nurbsRenderer);
  2031. // finally
  2032. gluDeleteNurbsRenderer(nurbsRenderer);
  2033. // end;
  2034. end;
  2035. end
  2036. else
  2037. begin
  2038. // lines, cubic splines or bezier
  2039. if FSplineMode = lsmSegments then
  2040. gl.Begin_(GL_LINES)
  2041. else if FSplineMode = lsmLoop then
  2042. gl.Begin_(GL_LINE_LOOP)
  2043. else
  2044. gl.Begin_(GL_LINE_STRIP);
  2045. if (FDivision < 2) or (FSplineMode in [lsmLines, lsmSegments, lsmLoop])
  2046. then
  2047. begin
  2048. // standard line(s), draw directly
  2049. if loUseNodeColorForLines in Options then
  2050. begin
  2051. // node color interpolation
  2052. for i := 0 to Nodes.Count - 1 do
  2053. with TGLLinesNode(Nodes[i]) do
  2054. begin
  2055. gl.Color4fv(Color.AsAddress);
  2056. gl.Vertex3f(X, Y, Z);
  2057. end;
  2058. end
  2059. else
  2060. begin
  2061. // single color
  2062. for i := 0 to Nodes.Count - 1 do
  2063. with Nodes[i] do
  2064. gl.Vertex3f(X, Y, Z);
  2065. end;
  2066. end
  2067. else if FSplineMode = lsmCubicSpline then
  2068. begin
  2069. // cubic spline
  2070. Spline := Nodes.CreateNewCubicSpline;
  2071. // try
  2072. f := 1 / FDivision;
  2073. for i := 0 to (Nodes.Count - 1) * FDivision do
  2074. begin
  2075. Spline.SplineXYZ(i * f, A, B, C);
  2076. if loUseNodeColorForLines in Options then
  2077. begin
  2078. n := (i div FDivision);
  2079. if n < Nodes.Count - 1 then
  2080. VectorLerp(TGLLinesNode(Nodes[n]).Color.Color,
  2081. TGLLinesNode(Nodes[n + 1]).Color.Color, (i mod FDivision) * f,
  2082. vertexColor)
  2083. else
  2084. SetVector(vertexColor, TGLLinesNode(Nodes[Nodes.Count - 1])
  2085. .Color.Color);
  2086. gl.Color4fv(@vertexColor);
  2087. end;
  2088. gl.Vertex3f(A, B, C);
  2089. end;
  2090. // finally
  2091. Spline.Free;
  2092. // end;
  2093. end
  2094. else if FSplineMode = lsmBezierSpline then
  2095. begin
  2096. f := 1 / FDivision;
  2097. for i := 0 to FDivision do
  2098. gl.EvalCoord1f(i * f);
  2099. end;
  2100. gl.End_;
  2101. end;
  2102. rci.GLStates.Disable(stColorLogicOp);
  2103. if FSplineMode = lsmBezierSpline then
  2104. rci.GLStates.PopAttrib;
  2105. if Length(nodeBuffer) > 0 then
  2106. begin
  2107. SetLength(nodeBuffer, 0);
  2108. SetLength(colorBuffer, 0);
  2109. end;
  2110. if FNodesAspect <> lnaInvisible then
  2111. begin
  2112. if not rci.ignoreBlendingRequests then
  2113. begin
  2114. rci.GLStates.Enable(stBlend);
  2115. rci.GLStates.SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
  2116. end;
  2117. for i := 0 to Nodes.Count - 1 do
  2118. with TGLLinesNode(Nodes[i]) do
  2119. DrawNode(rci, X, Y, Z, Color);
  2120. end;
  2121. end;
  2122. end;
  2123. // ------------------
  2124. // ------------------ TGLCube ------------------
  2125. // ------------------
  2126. constructor TGLCube.Create(AOwner: TComponent);
  2127. begin
  2128. inherited Create(AOwner);
  2129. FCubeSize := XYZVector;
  2130. FParts := [cpTop, cpBottom, cpFront, cpBack, cpLeft, cpRight];
  2131. FNormalDirection := ndOutside;
  2132. ObjectStyle := ObjectStyle + [osDirectDraw];
  2133. end;
  2134. procedure TGLCube.BuildList(var rci: TGLRenderContextInfo);
  2135. var
  2136. v1: TAffineVector;
  2137. v2: TAffineVector;
  2138. v1d: TAffineVector;
  2139. v2d: TAffineVector;
  2140. nd: TGLFloat;
  2141. TanLoc, BinLoc: Integer;
  2142. begin
  2143. VectorScale(FCubeSize, 0.5, v2);
  2144. v1 := VectorNegate(v2);
  2145. if FNormalDirection = ndInside then
  2146. begin
  2147. v1d := v2;
  2148. v2d := v1;
  2149. nd := -1
  2150. end
  2151. else
  2152. begin
  2153. v1d := v1;
  2154. v2d := v2;
  2155. nd := 1;
  2156. end;
  2157. if GL.ARB_shader_objects and (rci.GLStates.CurrentProgram > 0) then
  2158. begin
  2159. TanLoc := gl.GetAttribLocation(rci.GLStates.CurrentProgram,
  2160. TangentAttributeName);
  2161. BinLoc := gl.GetAttribLocation(rci.GLStates.CurrentProgram,
  2162. BinormalAttributeName);
  2163. end
  2164. else
  2165. begin
  2166. TanLoc := -1;
  2167. BinLoc := -1;
  2168. end;
  2169. gl.Begin_(GL_QUADS);
  2170. if cpFront in FParts then
  2171. begin
  2172. gl.Normal3f(0, 0, nd);
  2173. if TanLoc > -1 then
  2174. gl.VertexAttrib3f(TanLoc, nd, 0, 0);
  2175. if BinLoc > -1 then
  2176. gl.VertexAttrib3f(BinLoc, 0, nd, 0);
  2177. xgl.TexCoord2fv(@XYTexPoint);
  2178. gl.Vertex3fv(@v2);
  2179. xgl.TexCoord2fv(@YTexPoint);
  2180. gl.Vertex3f(v1d.X, v2d.Y, v2.Z);
  2181. xgl.TexCoord2fv(@NullTexPoint);
  2182. gl.Vertex3f(v1.X, v1.Y, v2.Z);
  2183. xgl.TexCoord2fv(@XTexPoint);
  2184. gl.Vertex3f(v2d.X, v1d.Y, v2.Z);
  2185. end;
  2186. if cpBack in FParts then
  2187. begin
  2188. gl.Normal3f(0, 0, -nd);
  2189. if TanLoc > -1 then
  2190. gl.VertexAttrib3f(TanLoc, -nd, 0, 0);
  2191. if BinLoc > -1 then
  2192. gl.VertexAttrib3f(BinLoc, 0, nd, 0);
  2193. xgl.TexCoord2fv(@YTexPoint);
  2194. gl.Vertex3f(v2.X, v2.Y, v1.Z);
  2195. xgl.TexCoord2fv(@NullTexPoint);
  2196. gl.Vertex3f(v2d.X, v1d.Y, v1.Z);
  2197. xgl.TexCoord2fv(@XTexPoint);
  2198. gl.Vertex3fv(@v1);
  2199. xgl.TexCoord2fv(@XYTexPoint);
  2200. gl.Vertex3f(v1d.X, v2d.Y, v1.Z);
  2201. end;
  2202. if cpLeft in FParts then
  2203. begin
  2204. gl.Normal3f(-nd, 0, 0);
  2205. if TanLoc > -1 then
  2206. gl.VertexAttrib3f(TanLoc, 0, 0, nd);
  2207. if BinLoc > -1 then
  2208. gl.VertexAttrib3f(BinLoc, 0, nd, 0);
  2209. xgl.TexCoord2fv(@XYTexPoint);
  2210. gl.Vertex3f(v1.X, v2.Y, v2.Z);
  2211. xgl.TexCoord2fv(@YTexPoint);
  2212. gl.Vertex3f(v1.X, v2d.Y, v1d.Z);
  2213. xgl.TexCoord2fv(@NullTexPoint);
  2214. gl.Vertex3fv(@v1);
  2215. xgl.TexCoord2fv(@XTexPoint);
  2216. gl.Vertex3f(v1.X, v1d.Y, v2d.Z);
  2217. end;
  2218. if cpRight in FParts then
  2219. begin
  2220. gl.Normal3f(nd, 0, 0);
  2221. if TanLoc > -1 then
  2222. gl.VertexAttrib3f(TanLoc, 0, 0, -nd);
  2223. if BinLoc > -1 then
  2224. gl.VertexAttrib3f(BinLoc, 0, nd, 0);
  2225. xgl.TexCoord2fv(@YTexPoint);
  2226. gl.Vertex3fv(@v2);
  2227. xgl.TexCoord2fv(@NullTexPoint);
  2228. gl.Vertex3f(v2.X, v1d.Y, v2d.Z);
  2229. xgl.TexCoord2fv(@XTexPoint);
  2230. gl.Vertex3f(v2.X, v1.Y, v1.Z);
  2231. xgl.TexCoord2fv(@XYTexPoint);
  2232. gl.Vertex3f(v2.X, v2d.Y, v1d.Z);
  2233. end;
  2234. if cpTop in FParts then
  2235. begin
  2236. gl.Normal3f(0, nd, 0);
  2237. if TanLoc > -1 then
  2238. gl.VertexAttrib3f(TanLoc, nd, 0, 0);
  2239. if BinLoc > -1 then
  2240. gl.VertexAttrib3f(BinLoc, 0, 0, -nd);
  2241. xgl.TexCoord2fv(@YTexPoint);
  2242. gl.Vertex3f(v1.X, v2.Y, v1.Z);
  2243. xgl.TexCoord2fv(@NullTexPoint);
  2244. gl.Vertex3f(v1d.X, v2.Y, v2d.Z);
  2245. xgl.TexCoord2fv(@XTexPoint);
  2246. gl.Vertex3fv(@v2);
  2247. xgl.TexCoord2fv(@XYTexPoint);
  2248. gl.Vertex3f(v2d.X, v2.Y, v1d.Z);
  2249. end;
  2250. if cpBottom in FParts then
  2251. begin
  2252. gl.Normal3f(0, -nd, 0);
  2253. if TanLoc > -1 then
  2254. gl.VertexAttrib3f(TanLoc, -nd, 0, 0);
  2255. if BinLoc > -1 then
  2256. gl.VertexAttrib3f(BinLoc, 0, 0, nd);
  2257. xgl.TexCoord2fv(@NullTexPoint);
  2258. gl.Vertex3fv(@v1);
  2259. xgl.TexCoord2fv(@XTexPoint);
  2260. gl.Vertex3f(v2d.X, v1.Y, v1d.Z);
  2261. xgl.TexCoord2fv(@XYTexPoint);
  2262. gl.Vertex3f(v2.X, v1.Y, v2.Z);
  2263. xgl.TexCoord2fv(@YTexPoint);
  2264. gl.Vertex3f(v1d.X, v1.Y, v2d.Z);
  2265. end;
  2266. gl.End_;
  2267. end;
  2268. function TGLCube.GenerateSilhouette(const silhouetteParameters
  2269. : TGLSilhouetteParameters): TGLSilhouette;
  2270. var
  2271. hw, hh, hd: TGLFloat;
  2272. Connectivity: TGLConnectivity;
  2273. sil: TGLSilhouette;
  2274. begin
  2275. Connectivity := TGLConnectivity.Create(True);
  2276. hw := FCubeSize.X * 0.5;
  2277. hh := FCubeSize.Y * 0.5;
  2278. hd := FCubeSize.Z * 0.5;
  2279. if cpFront in FParts then
  2280. begin
  2281. Connectivity.AddQuad(AffineVectorMake(hw, hh, hd),
  2282. AffineVectorMake(-hw, hh, hd), AffineVectorMake(-hw, -hh, hd),
  2283. AffineVectorMake(hw, -hh, hd));
  2284. end;
  2285. if cpBack in FParts then
  2286. begin
  2287. Connectivity.AddQuad(AffineVectorMake(hw, hh, -hd),
  2288. AffineVectorMake(hw, -hh, -hd), AffineVectorMake(-hw, -hh, -hd),
  2289. AffineVectorMake(-hw, hh, -hd));
  2290. end;
  2291. if cpLeft in FParts then
  2292. begin
  2293. Connectivity.AddQuad(AffineVectorMake(-hw, hh, hd),
  2294. AffineVectorMake(-hw, hh, -hd), AffineVectorMake(-hw, -hh, -hd),
  2295. AffineVectorMake(-hw, -hh, hd));
  2296. end;
  2297. if cpRight in FParts then
  2298. begin
  2299. Connectivity.AddQuad(AffineVectorMake(hw, hh, hd),
  2300. AffineVectorMake(hw, -hh, hd), AffineVectorMake(hw, -hh, -hd),
  2301. AffineVectorMake(hw, hh, -hd));
  2302. end;
  2303. if cpTop in FParts then
  2304. begin
  2305. Connectivity.AddQuad(AffineVectorMake(-hw, hh, -hd),
  2306. AffineVectorMake(-hw, hh, hd), AffineVectorMake(hw, hh, hd),
  2307. AffineVectorMake(hw, hh, -hd));
  2308. end;
  2309. if cpBottom in FParts then
  2310. begin
  2311. Connectivity.AddQuad(AffineVectorMake(-hw, -hh, -hd),
  2312. AffineVectorMake(hw, -hh, -hd), AffineVectorMake(hw, -hh, hd),
  2313. AffineVectorMake(-hw, -hh, hd));
  2314. end;
  2315. sil := nil;
  2316. Connectivity.CreateSilhouette(silhouetteParameters, sil, False);
  2317. Result := sil;
  2318. Connectivity.Free;
  2319. end;
  2320. function TGLCube.GetCubeWHD(const Index: Integer): TGLFloat;
  2321. begin
  2322. Result := FCubeSize.v[index];
  2323. end;
  2324. procedure TGLCube.SetCubeWHD(Index: Integer; aValue: TGLFloat);
  2325. begin
  2326. if aValue <> FCubeSize.v[index] then
  2327. begin
  2328. FCubeSize.v[index] := aValue;
  2329. StructureChanged;
  2330. end;
  2331. end;
  2332. procedure TGLCube.SetParts(aValue: TCubeParts);
  2333. begin
  2334. if aValue <> FParts then
  2335. begin
  2336. FParts := aValue;
  2337. StructureChanged;
  2338. end;
  2339. end;
  2340. procedure TGLCube.SetNormalDirection(aValue: TGLNormalDirection);
  2341. begin
  2342. if aValue <> FNormalDirection then
  2343. begin
  2344. FNormalDirection := aValue;
  2345. StructureChanged;
  2346. end;
  2347. end;
  2348. procedure TGLCube.Assign(Source: TPersistent);
  2349. begin
  2350. if Assigned(Source) and (Source is TGLCube) then
  2351. begin
  2352. FCubeSize := TGLCube(Source).FCubeSize;
  2353. FParts := TGLCube(Source).FParts;
  2354. FNormalDirection := TGLCube(Source).FNormalDirection;
  2355. end;
  2356. inherited Assign(Source);
  2357. end;
  2358. function TGLCube.AxisAlignedDimensionsUnscaled: TVector;
  2359. begin
  2360. Result.X := FCubeSize.X * 0.5;
  2361. Result.Y := FCubeSize.Y * 0.5;
  2362. Result.Z := FCubeSize.Z * 0.5;
  2363. Result.W := 0;
  2364. end;
  2365. function TGLCube.RayCastIntersect(const rayStart, rayVector: TVector;
  2366. intersectPoint: PVector = nil; intersectNormal: PVector = nil): Boolean;
  2367. var
  2368. p: array [0 .. 5] of TVector;
  2369. rv: TVector;
  2370. rs, r: TVector;
  2371. i: Integer;
  2372. t: Single;
  2373. eSize: TAffineVector;
  2374. begin
  2375. rs := AbsoluteToLocal(rayStart);
  2376. SetVector(rv, VectorNormalize(AbsoluteToLocal(rayVector)));
  2377. eSize.X := FCubeSize.X * 0.5 + 0.0001;
  2378. eSize.Y := FCubeSize.Y * 0.5 + 0.0001;
  2379. eSize.Z := FCubeSize.Z * 0.5 + 0.0001;
  2380. p[0] := XHmgVector;
  2381. p[1] := YHmgVector;
  2382. p[2] := ZHmgVector;
  2383. SetVector(p[3], -1, 0, 0);
  2384. SetVector(p[4], 0, -1, 0);
  2385. SetVector(p[5], 0, 0, -1);
  2386. for i := 0 to 5 do
  2387. begin
  2388. if VectorDotProduct(p[i], rv) > 0 then
  2389. begin
  2390. t := -(p[i].X * rs.X + p[i].Y * rs.Y + p[i].Z * rs.Z + 0.5 * FCubeSize.v
  2391. [i mod 3]) / (p[i].X * rv.X + p[i].Y * rv.Y + p[i].Z * rv.Z);
  2392. MakePoint(r, rs.X + t * rv.X, rs.Y + t * rv.Y, rs.Z + t * rv.Z);
  2393. if (Abs(r.X) <= eSize.X) and (Abs(r.Y) <= eSize.Y) and
  2394. (Abs(r.Z) <= eSize.Z) and
  2395. (VectorDotProduct(VectorSubtract(r, rs), rv) > 0) then
  2396. begin
  2397. if Assigned(intersectPoint) then
  2398. MakePoint(intersectPoint^, LocalToAbsolute(r));
  2399. if Assigned(intersectNormal) then
  2400. MakeVector(intersectNormal^, LocalToAbsolute(VectorNegate(p[i])));
  2401. Result := True;
  2402. Exit;
  2403. end;
  2404. end;
  2405. end;
  2406. Result := False;
  2407. end;
  2408. procedure TGLCube.DefineProperties(Filer: TFiler);
  2409. begin
  2410. inherited;
  2411. Filer.DefineBinaryProperty('CubeSize', ReadData, WriteData,
  2412. (FCubeSize.X <> 1) or (FCubeSize.Y <> 1) or (FCubeSize.Z <> 1));
  2413. end;
  2414. procedure TGLCube.ReadData(Stream: TStream);
  2415. begin
  2416. with Stream do
  2417. begin
  2418. Read(FCubeSize, SizeOf(TAffineVector));
  2419. end;
  2420. end;
  2421. procedure TGLCube.WriteData(Stream: TStream);
  2422. begin
  2423. with Stream do
  2424. begin
  2425. Write(FCubeSize, SizeOf(TAffineVector));
  2426. end;
  2427. end;
  2428. // ------------------
  2429. // ------------------ TGLQuadricObject ------------------
  2430. // ------------------
  2431. constructor TGLQuadricObject.Create(AOwner: TComponent);
  2432. begin
  2433. inherited;
  2434. FNormals := nsSmooth;
  2435. FNormalDirection := ndOutside;
  2436. end;
  2437. procedure TGLQuadricObject.SetNormals(aValue: TGLNormalSmoothing);
  2438. begin
  2439. if aValue <> FNormals then
  2440. begin
  2441. FNormals := aValue;
  2442. StructureChanged;
  2443. end;
  2444. end;
  2445. procedure TGLQuadricObject.SetNormalDirection(aValue: TGLNormalDirection);
  2446. begin
  2447. if aValue <> FNormalDirection then
  2448. begin
  2449. FNormalDirection := aValue;
  2450. StructureChanged;
  2451. end;
  2452. end;
  2453. procedure TGLQuadricObject.SetupQuadricParams(quadric: PGLUquadricObj);
  2454. const
  2455. cNormalSmoothinToEnum: array [nsFlat .. nsNone] of Cardinal = (GLU_FLAT,
  2456. GLU_SMOOTH, GLU_NONE);
  2457. begin
  2458. gluQuadricDrawStyle(quadric, GLU_FILL);
  2459. gluQuadricNormals(quadric, cNormalSmoothinToEnum[FNormals]);
  2460. SetNormalQuadricOrientation(quadric);
  2461. gluQuadricTexture(quadric, True);
  2462. end;
  2463. procedure TGLQuadricObject.SetNormalQuadricOrientation(quadric: PGLUquadricObj);
  2464. const
  2465. cNormalDirectionToEnum: array [ndInside .. ndOutside] of Cardinal =
  2466. (GLU_INSIDE, GLU_OUTSIDE);
  2467. begin
  2468. gluQuadricOrientation(quadric, cNormalDirectionToEnum[FNormalDirection]);
  2469. end;
  2470. procedure TGLQuadricObject.SetInvertedQuadricOrientation
  2471. (quadric: PGLUquadricObj);
  2472. const
  2473. cNormalDirectionToEnum: array [ndInside .. ndOutside] of Cardinal =
  2474. (GLU_OUTSIDE, GLU_INSIDE);
  2475. begin
  2476. gluQuadricOrientation(quadric, cNormalDirectionToEnum[FNormalDirection]);
  2477. end;
  2478. procedure TGLQuadricObject.Assign(Source: TPersistent);
  2479. begin
  2480. if Assigned(Source) and (Source is TGLQuadricObject) then
  2481. begin
  2482. FNormals := TGLQuadricObject(Source).FNormals;
  2483. FNormalDirection := TGLQuadricObject(Source).FNormalDirection;
  2484. end;
  2485. inherited Assign(Source);
  2486. end;
  2487. // ------------------
  2488. // ------------------ TGLSphere ------------------
  2489. // ------------------
  2490. constructor TGLSphere.Create(AOwner: TComponent);
  2491. begin
  2492. inherited Create(AOwner);
  2493. FRadius := 0.5;
  2494. FSlices := 16;
  2495. FStacks := 16;
  2496. FTop := 90;
  2497. FBottom := -90;
  2498. FStart := 0;
  2499. FStop := 360;
  2500. end;
  2501. procedure TGLSphere.BuildList(var rci: TGLRenderContextInfo);
  2502. var
  2503. v1, v2, N1: TAffineVector;
  2504. AngTop, AngBottom, AngStart, AngStop, StepV, StepH: Double;
  2505. SinP, CosP, SinP2, CosP2, SinT, CosT, Phi, Phi2, Theta: Double;
  2506. uTexCoord, uTexFactor, vTexFactor, vTexCoord0, vTexCoord1: Single;
  2507. i, j: Integer;
  2508. DoReverse: Boolean;
  2509. begin
  2510. DoReverse := (FNormalDirection = ndInside);
  2511. rci.GLStates.PushAttrib([sttPolygon]);
  2512. if DoReverse then
  2513. rci.GLStates.InvertGLFrontFace;
  2514. // common settings
  2515. AngTop := DegToRad(1.0 * FTop);
  2516. AngBottom := DegToRad(1.0 * FBottom);
  2517. AngStart := DegToRad(1.0 * FStart);
  2518. AngStop := DegToRad(1.0 * FStop);
  2519. StepH := (AngStop - AngStart) / FSlices;
  2520. StepV := (AngTop - AngBottom) / FStacks;
  2521. gl.PushMatrix;
  2522. gl.Scalef(Radius, Radius, Radius);
  2523. // top cap
  2524. if (FTop < 90) and (FTopCap in [ctCenter, ctFlat]) then
  2525. begin
  2526. gl.Begin_(GL_TRIANGLE_FAN);
  2527. SinCosine(AngTop, SinP, CosP);
  2528. xgl.TexCoord2f(0.5, 0.5);
  2529. if DoReverse then
  2530. gl.Normal3f(0, -1, 0)
  2531. else
  2532. gl.Normal3f(0, 1, 0);
  2533. if FTopCap = ctCenter then
  2534. gl.Vertex3f(0, 0, 0)
  2535. else
  2536. begin
  2537. gl.Vertex3f(0, SinP, 0);
  2538. N1 := YVector;
  2539. if DoReverse then
  2540. N1.Y := -N1.Y;
  2541. end;
  2542. v1.Y := SinP;
  2543. Theta := AngStart;
  2544. for i := 0 to FSlices do
  2545. begin
  2546. SinCosine(Theta, SinT, CosT);
  2547. v1.X := CosP * SinT;
  2548. v1.Z := CosP * CosT;
  2549. if FTopCap = ctCenter then
  2550. begin
  2551. N1 := VectorPerpendicular(YVector, v1);
  2552. if DoReverse then
  2553. NegateVector(N1);
  2554. end;
  2555. xgl.TexCoord2f(SinT * 0.5 + 0.5, CosT * 0.5 + 0.5);
  2556. gl.Normal3fv(@N1);
  2557. gl.Vertex3fv(@v1);
  2558. Theta := Theta + StepH;
  2559. end;
  2560. gl.End_;
  2561. end;
  2562. // main body
  2563. Phi := AngTop;
  2564. Phi2 := Phi - StepV;
  2565. uTexFactor := 1 / FSlices;
  2566. vTexFactor := 1 / FStacks;
  2567. for j := 0 to FStacks - 1 do
  2568. begin
  2569. Theta := AngStart;
  2570. SinCos(Phi, SinP, CosP);
  2571. SinCos(Phi2, SinP2, CosP2);
  2572. v1.Y := SinP;
  2573. v2.Y := SinP2;
  2574. vTexCoord0 := 1 - j * vTexFactor;
  2575. vTexCoord1 := 1 - (j + 1) * vTexFactor;
  2576. gl.Begin_(GL_TRIANGLE_STRIP);
  2577. for i := 0 to FSlices do
  2578. begin
  2579. SinCos(Theta, SinT, CosT);
  2580. v1.X := CosP * SinT;
  2581. v2.X := CosP2 * SinT;
  2582. v1.Z := CosP * CosT;
  2583. v2.Z := CosP2 * CosT;
  2584. uTexCoord := i * uTexFactor;
  2585. xgl.TexCoord2f(uTexCoord, vTexCoord0);
  2586. if DoReverse then
  2587. begin
  2588. N1 := VectorNegate(v1);
  2589. gl.Normal3fv(@N1);
  2590. end
  2591. else
  2592. gl.Normal3fv(@v1);
  2593. gl.Vertex3fv(@v1);
  2594. xgl.TexCoord2f(uTexCoord, vTexCoord1);
  2595. if DoReverse then
  2596. begin
  2597. N1 := VectorNegate(v2);
  2598. gl.Normal3fv(@N1);
  2599. end
  2600. else
  2601. gl.Normal3fv(@v2);
  2602. gl.Vertex3fv(@v2);
  2603. Theta := Theta + StepH;
  2604. end;
  2605. gl.End_;
  2606. Phi := Phi2;
  2607. Phi2 := Phi2 - StepV;
  2608. end;
  2609. // bottom cap
  2610. if (FBottom > -90) and (FBottomCap in [ctCenter, ctFlat]) then
  2611. begin
  2612. gl.Begin_(GL_TRIANGLE_FAN);
  2613. SinCos(AngBottom, SinP, CosP);
  2614. xgl.TexCoord2f(0.5, 0.5);
  2615. if DoReverse then
  2616. gl.Normal3f(0, 1, 0)
  2617. else
  2618. gl.Normal3f(0, -1, 0);
  2619. if FBottomCap = ctCenter then
  2620. gl.Vertex3f(0, 0, 0)
  2621. else
  2622. begin
  2623. gl.Vertex3f(0, SinP, 0);
  2624. if DoReverse then
  2625. MakeVector(N1, 0, -1, 0)
  2626. else
  2627. begin
  2628. N1 := YVector;
  2629. NegateVector(N1);
  2630. end;
  2631. end;
  2632. v1.Y := SinP;
  2633. Theta := AngStop;
  2634. for i := 0 to FSlices do
  2635. begin
  2636. SinCos(Theta, SinT, CosT);
  2637. v1.X := CosP * SinT;
  2638. v1.Z := CosP * CosT;
  2639. if FBottomCap = ctCenter then
  2640. begin
  2641. N1 := VectorPerpendicular(AffineVectorMake(0, -1, 0), v1);
  2642. if DoReverse then
  2643. NegateVector(N1);
  2644. end;
  2645. xgl.TexCoord2f(SinT * 0.5 + 0.5, CosT * 0.5 + 0.5);
  2646. gl.Normal3fv(@N1);
  2647. gl.Vertex3fv(@v1);
  2648. Theta := Theta - StepH;
  2649. end;
  2650. gl.End_;
  2651. end;
  2652. if DoReverse then
  2653. rci.GLStates.InvertGLFrontFace;
  2654. gl.PopMatrix;
  2655. rci.GLStates.PopAttrib;
  2656. end;
  2657. function TGLSphere.RayCastIntersect(const rayStart, rayVector: TVector;
  2658. intersectPoint: PVector = nil; intersectNormal: PVector = nil): Boolean;
  2659. var
  2660. i1, i2: TVector;
  2661. localStart, localVector: TVector;
  2662. begin
  2663. // compute coefficients of quartic polynomial
  2664. SetVector(localStart, AbsoluteToLocal(rayStart));
  2665. SetVector(localVector, AbsoluteToLocal(rayVector));
  2666. NormalizeVector(localVector);
  2667. if RayCastSphereIntersect(localStart, localVector, NullHmgVector, Radius, i1,
  2668. i2) > 0 then
  2669. begin
  2670. Result := True;
  2671. if Assigned(intersectPoint) then
  2672. SetVector(intersectPoint^, LocalToAbsolute(i1));
  2673. if Assigned(intersectNormal) then
  2674. begin
  2675. i1.W := 0; // vector transform
  2676. SetVector(intersectNormal^, LocalToAbsolute(i1));
  2677. end;
  2678. end
  2679. else
  2680. Result := False;
  2681. end;
  2682. function TGLSphere.GenerateSilhouette(const silhouetteParameters
  2683. : TGLSilhouetteParameters): TGLSilhouette;
  2684. var
  2685. i, j: Integer;
  2686. s, C, angleFactor: Single;
  2687. sVec, tVec: TAffineVector;
  2688. Segments: Integer;
  2689. begin
  2690. Segments := MaxInteger(FStacks, FSlices);
  2691. // determine a local orthonormal matrix, viewer-oriented
  2692. sVec := VectorCrossProduct(silhouetteParameters.SeenFrom, XVector);
  2693. if VectorLength(sVec) < 1E-3 then
  2694. sVec := VectorCrossProduct(silhouetteParameters.SeenFrom, YVector);
  2695. tVec := VectorCrossProduct(silhouetteParameters.SeenFrom, sVec);
  2696. NormalizeVector(sVec);
  2697. NormalizeVector(tVec);
  2698. // generate the silhouette (outline and capping)
  2699. Result := TGLSilhouette.Create;
  2700. angleFactor := (2 * PI) / Segments;
  2701. for i := 0 to Segments - 1 do
  2702. begin
  2703. SinCosine(i * angleFactor, FRadius, s, C);
  2704. Result.vertices.AddPoint(VectorCombine(sVec, tVec, s, C));
  2705. j := (i + 1) mod Segments;
  2706. Result.Indices.Add(i, j);
  2707. if silhouetteParameters.CappingRequired then
  2708. Result.CapIndices.Add(Segments, i, j)
  2709. end;
  2710. if silhouetteParameters.CappingRequired then
  2711. Result.vertices.Add(NullHmgPoint);
  2712. end;
  2713. procedure TGLSphere.SetBottom(aValue: TAngleLimit1);
  2714. begin
  2715. if FBottom <> aValue then
  2716. begin
  2717. FBottom := aValue;
  2718. StructureChanged;
  2719. end;
  2720. end;
  2721. procedure TGLSphere.SetBottomCap(aValue: TGLCapType);
  2722. begin
  2723. if FBottomCap <> aValue then
  2724. begin
  2725. FBottomCap := aValue;
  2726. StructureChanged;
  2727. end;
  2728. end;
  2729. procedure TGLSphere.SetRadius(const aValue: TGLFloat);
  2730. begin
  2731. if aValue <> FRadius then
  2732. begin
  2733. FRadius := aValue;
  2734. StructureChanged;
  2735. end;
  2736. end;
  2737. procedure TGLSphere.SetSlices(aValue: Integer);
  2738. begin
  2739. if aValue <> FSlices then
  2740. begin
  2741. if aValue <= 0 then
  2742. FSlices := 1
  2743. else
  2744. FSlices := aValue;
  2745. StructureChanged;
  2746. end;
  2747. end;
  2748. procedure TGLSphere.SetStacks(aValue: TGLInt);
  2749. begin
  2750. if aValue <> FStacks then
  2751. begin
  2752. if aValue <= 0 then
  2753. FStacks := 1
  2754. else
  2755. FStacks := aValue;
  2756. StructureChanged;
  2757. end;
  2758. end;
  2759. procedure TGLSphere.SetStart(aValue: TAngleLimit2);
  2760. begin
  2761. if FStart <> aValue then
  2762. begin
  2763. Assert(aValue <= FStop);
  2764. FStart := aValue;
  2765. StructureChanged;
  2766. end;
  2767. end;
  2768. procedure TGLSphere.SetStop(aValue: TAngleLimit2);
  2769. begin
  2770. if FStop <> aValue then
  2771. begin
  2772. Assert(aValue >= FStart);
  2773. FStop := aValue;
  2774. StructureChanged;
  2775. end;
  2776. end;
  2777. procedure TGLSphere.SetTop(aValue: TAngleLimit1);
  2778. begin
  2779. if FTop <> aValue then
  2780. begin
  2781. FTop := aValue;
  2782. StructureChanged;
  2783. end;
  2784. end;
  2785. procedure TGLSphere.SetTopCap(aValue: TGLCapType);
  2786. begin
  2787. if FTopCap <> aValue then
  2788. begin
  2789. FTopCap := aValue;
  2790. StructureChanged;
  2791. end;
  2792. end;
  2793. procedure TGLSphere.Assign(Source: TPersistent);
  2794. begin
  2795. if Assigned(Source) and (Source is TGLSphere) then
  2796. begin
  2797. FRadius := TGLSphere(Source).FRadius;
  2798. FSlices := TGLSphere(Source).FSlices;
  2799. FStacks := TGLSphere(Source).FStacks;
  2800. FBottom := TGLSphere(Source).FBottom;
  2801. FTop := TGLSphere(Source).FTop;
  2802. FStart := TGLSphere(Source).FStart;
  2803. FStop := TGLSphere(Source).FStop;
  2804. end;
  2805. inherited Assign(Source);
  2806. end;
  2807. function TGLSphere.AxisAlignedDimensionsUnscaled: TVector;
  2808. begin
  2809. Result.X := Abs(FRadius);
  2810. Result.Y := Result.X;
  2811. Result.Z := Result.X;
  2812. Result.W := 0;
  2813. end;
  2814. // ------------------
  2815. // ------------------ TGLPolygonBase ------------------
  2816. // ------------------
  2817. constructor TGLPolygonBase.Create(AOwner: TComponent);
  2818. begin
  2819. inherited Create(AOwner);
  2820. CreateNodes;
  2821. FDivision := 10;
  2822. FSplineMode := lsmLines;
  2823. end;
  2824. procedure TGLPolygonBase.CreateNodes;
  2825. begin
  2826. FNodes := TGLNodes.Create(Self);
  2827. end;
  2828. destructor TGLPolygonBase.Destroy;
  2829. begin
  2830. FNodes.Free;
  2831. inherited Destroy;
  2832. end;
  2833. procedure TGLPolygonBase.Assign(Source: TPersistent);
  2834. begin
  2835. if Source is TGLPolygonBase then
  2836. begin
  2837. SetNodes(TGLPolygonBase(Source).FNodes);
  2838. FDivision := TGLPolygonBase(Source).FDivision;
  2839. FSplineMode := TGLPolygonBase(Source).FSplineMode;
  2840. end;
  2841. inherited Assign(Source);
  2842. end;
  2843. procedure TGLPolygonBase.NotifyChange(Sender: TObject);
  2844. begin
  2845. if Sender = Nodes then
  2846. StructureChanged;
  2847. inherited;
  2848. end;
  2849. procedure TGLPolygonBase.SetDivision(const Value: Integer);
  2850. begin
  2851. if Value <> FDivision then
  2852. begin
  2853. if Value < 1 then
  2854. FDivision := 1
  2855. else
  2856. FDivision := Value;
  2857. StructureChanged;
  2858. end;
  2859. end;
  2860. procedure TGLPolygonBase.SetNodes(const aNodes: TGLNodes);
  2861. begin
  2862. FNodes.Assign(aNodes);
  2863. StructureChanged;
  2864. end;
  2865. procedure TGLPolygonBase.SetSplineMode(const val: TGLLineSplineMode);
  2866. begin
  2867. if FSplineMode <> val then
  2868. begin
  2869. FSplineMode := val;
  2870. StructureChanged;
  2871. end;
  2872. end;
  2873. procedure TGLPolygonBase.AddNode(const coords: TGLCoordinates);
  2874. var
  2875. n: TGLNode;
  2876. begin
  2877. n := Nodes.Add;
  2878. if Assigned(coords) then
  2879. n.AsVector := coords.AsVector;
  2880. StructureChanged;
  2881. end;
  2882. procedure TGLPolygonBase.AddNode(const X, Y, Z: TGLFloat);
  2883. var
  2884. n: TGLNode;
  2885. begin
  2886. n := Nodes.Add;
  2887. n.AsVector := VectorMake(X, Y, Z, 1);
  2888. StructureChanged;
  2889. end;
  2890. procedure TGLPolygonBase.AddNode(const Value: TVector);
  2891. var
  2892. n: TGLNode;
  2893. begin
  2894. n := Nodes.Add;
  2895. n.AsVector := Value;
  2896. StructureChanged;
  2897. end;
  2898. procedure TGLPolygonBase.AddNode(const Value: TAffineVector);
  2899. var
  2900. n: TGLNode;
  2901. begin
  2902. n := Nodes.Add;
  2903. n.AsVector := VectorMake(Value);
  2904. StructureChanged;
  2905. end;
  2906. // ------------------
  2907. // ------------------ TGLSuperellipsoid ------------------
  2908. // ------------------
  2909. constructor TGLSuperellipsoid.Create(AOwner: TComponent);
  2910. begin
  2911. inherited Create(AOwner);
  2912. FRadius := 0.5;
  2913. FVCurve := 1.0;
  2914. FHCurve := 1.0;
  2915. FSlices := 16;
  2916. FStacks := 16;
  2917. FTop := 90;
  2918. FBottom := -90;
  2919. FStart := 0;
  2920. FStop := 360;
  2921. end;
  2922. procedure TGLSuperellipsoid.BuildList(var rci: TGLRenderContextInfo);
  2923. var
  2924. CosPc1, SinPc1, CosTc2, SinTc2: Double;
  2925. tc1, tc2: Integer;
  2926. v1, v2, vs, N1: TAffineVector;
  2927. AngTop, AngBottom, AngStart, AngStop, StepV, StepH: Double;
  2928. SinP, CosP, SinP2, CosP2, SinT, CosT, Phi, Phi2, Theta: Double;
  2929. uTexCoord, uTexFactor, vTexFactor, vTexCoord0, vTexCoord1: Double;
  2930. i, j: Integer;
  2931. DoReverse: Boolean;
  2932. begin
  2933. DoReverse := (FNormalDirection = ndInside);
  2934. if DoReverse then
  2935. rci.GLStates.InvertGLFrontFace;
  2936. // common settings
  2937. AngTop := DegToRad(1.0 * FTop);
  2938. AngBottom := DegToRad(1.0 * FBottom);
  2939. AngStart := DegToRad(1.0 * FStart);
  2940. AngStop := DegToRad(1.0 * FStop);
  2941. StepH := (AngStop - AngStart) / FSlices;
  2942. StepV := (AngTop - AngBottom) / FStacks;
  2943. { Even integer used with the Power function, only produce positive points }
  2944. tc1 := trunc(VCurve);
  2945. tc2 := trunc(HCurve);
  2946. if tc1 mod 2 = 0 then
  2947. VCurve := VCurve + 1E-6;
  2948. if tc2 mod 2 = 0 then
  2949. HCurve := HCurve - 1E-6;
  2950. // top cap
  2951. if (FTop < 90) and (FTopCap in [ctCenter, ctFlat]) then
  2952. begin
  2953. gl.Begin_(GL_TRIANGLE_FAN);
  2954. SinCos(AngTop, SinP, CosP);
  2955. xgl.TexCoord2f(0.5, 0.5);
  2956. if DoReverse then
  2957. gl.Normal3f(0, -1, 0)
  2958. else
  2959. gl.Normal3f(0, 1, 0);
  2960. if FTopCap = ctCenter then
  2961. gl.Vertex3f(0, 0, 0)
  2962. else
  2963. begin { FTopCap = ctFlat }
  2964. if (Sign(SinP) = 1) or (tc1 = VCurve) then
  2965. SinPc1 := Power(SinP, VCurve)
  2966. else
  2967. SinPc1 := -Power(-SinP, VCurve);
  2968. gl.Vertex3f(0, SinPc1 * Radius, 0);
  2969. N1 := YVector;
  2970. if DoReverse then
  2971. N1.Y := -N1.Y;
  2972. end; { FTopCap = ctFlat }
  2973. // v1.Y := SinP;
  2974. if (Sign(SinP) = 1) or (tc1 = VCurve) then
  2975. SinPc1 := Power(SinP, VCurve)
  2976. else
  2977. SinPc1 := -Power(-SinP, VCurve);
  2978. v1.Y := SinPc1;
  2979. Theta := AngStart;
  2980. for i := 0 to FSlices do
  2981. begin
  2982. SinCos(Theta, SinT, CosT);
  2983. // v1.X := CosP * SinT;
  2984. if (Sign(CosP) = 1) or (tc1 = VCurve) then
  2985. CosPc1 := Power(CosP, VCurve)
  2986. else
  2987. CosPc1 := -Power(-CosP, VCurve);
  2988. if (Sign(SinT) = 1) or (tc2 = HCurve) then
  2989. SinTc2 := Power(SinT, HCurve)
  2990. else
  2991. SinTc2 := -Power(-SinT, HCurve);
  2992. v1.X := CosPc1 * SinTc2;
  2993. // v1.Z := CosP * CosT;
  2994. if (Sign(CosT) = 1) or (tc2 = HCurve) then
  2995. CosTc2 := Power(CosT, HCurve)
  2996. else
  2997. CosTc2 := -Power(-CosT, HCurve);
  2998. v1.Z := CosPc1 * CosTc2;
  2999. if FTopCap = ctCenter then
  3000. begin
  3001. N1 := VectorPerpendicular(YVector, v1);
  3002. if DoReverse then
  3003. NegateVector(N1);
  3004. end;
  3005. // xgl.TexCoord2f(SinT * 0.5 + 0.5, CosT * 0.5 + 0.5);
  3006. xgl.TexCoord2f(SinTc2 * 0.5 + 0.5, CosTc2 * 0.5 + 0.5);
  3007. gl.Normal3fv(@N1);
  3008. vs := v1;
  3009. ScaleVector(vs, Radius);
  3010. gl.Vertex3fv(@vs);
  3011. Theta := Theta + StepH;
  3012. end;
  3013. gl.End_;
  3014. end;
  3015. // main body
  3016. Phi := AngTop;
  3017. Phi2 := Phi - StepV;
  3018. uTexFactor := 1 / FSlices;
  3019. vTexFactor := 1 / FStacks;
  3020. for j := 0 to FStacks - 1 do
  3021. begin
  3022. Theta := AngStart;
  3023. SinCos(Phi, SinP, CosP);
  3024. SinCos(Phi2, SinP2, CosP2);
  3025. if (Sign(SinP) = 1) or (tc1 = VCurve) then
  3026. SinPc1 := Power(SinP, VCurve)
  3027. else
  3028. SinPc1 := -Power(-SinP, VCurve);
  3029. v1.Y := SinPc1;
  3030. if (Sign(SinP2) = 1) or (tc1 = VCurve) then
  3031. SinPc1 := Power(SinP2, VCurve)
  3032. else
  3033. SinPc1 := -Power(-SinP2, VCurve);
  3034. v2.Y := SinPc1;
  3035. vTexCoord0 := 1 - j * vTexFactor;
  3036. vTexCoord1 := 1 - (j + 1) * vTexFactor;
  3037. gl.Begin_(GL_TRIANGLE_STRIP);
  3038. for i := 0 to FSlices do
  3039. begin
  3040. SinCos(Theta, SinT, CosT);
  3041. if (Sign(CosP) = 1) or (tc1 = VCurve) then
  3042. CosPc1 := Power(CosP, VCurve)
  3043. else
  3044. CosPc1 := -Power(-CosP, VCurve);
  3045. if (Sign(SinT) = 1) or (tc2 = HCurve) then
  3046. SinTc2 := Power(SinT, HCurve)
  3047. else
  3048. SinTc2 := -Power(-SinT, HCurve);
  3049. v1.X := CosPc1 * SinTc2;
  3050. if (Sign(CosP2) = 1) or (tc1 = VCurve) then
  3051. CosPc1 := Power(CosP2, VCurve)
  3052. else
  3053. CosPc1 := -Power(-CosP2, VCurve);
  3054. v2.X := CosPc1 * SinTc2;
  3055. if (Sign(CosP) = 1) or (tc1 = VCurve) then
  3056. CosPc1 := Power(CosP, VCurve)
  3057. else
  3058. CosPc1 := -Power(-CosP, VCurve);
  3059. if (Sign(CosT) = 1) or (tc2 = HCurve) then
  3060. CosTc2 := Power(CosT, HCurve)
  3061. else
  3062. CosTc2 := -Power(-CosT, HCurve);
  3063. v1.Z := CosPc1 * CosTc2;
  3064. if (Sign(CosP2) = 1) or (tc1 = VCurve) then
  3065. CosPc1 := Power(CosP2, VCurve)
  3066. else
  3067. CosPc1 := -Power(-CosP2, VCurve);
  3068. v2.Z := CosPc1 * CosTc2;
  3069. uTexCoord := i * uTexFactor;
  3070. xgl.TexCoord2f(uTexCoord, vTexCoord0);
  3071. if DoReverse then
  3072. begin
  3073. N1 := VectorNegate(v1);
  3074. gl.Normal3fv(@N1);
  3075. end
  3076. else
  3077. gl.Normal3fv(@v1);
  3078. vs := v1;
  3079. ScaleVector(vs, Radius);
  3080. gl.Vertex3fv(@vs);
  3081. xgl.TexCoord2f(uTexCoord, vTexCoord1);
  3082. if DoReverse then
  3083. begin
  3084. N1 := VectorNegate(v2);
  3085. gl.Normal3fv(@N1);
  3086. end
  3087. else
  3088. gl.Normal3fv(@v2);
  3089. vs := v2;
  3090. ScaleVector(vs, Radius);
  3091. gl.Vertex3fv(@vs);
  3092. Theta := Theta + StepH;
  3093. end;
  3094. gl.End_;
  3095. Phi := Phi2;
  3096. Phi2 := Phi2 - StepV;
  3097. end;
  3098. // bottom cap
  3099. if (FBottom > -90) and (FBottomCap in [ctCenter, ctFlat]) then
  3100. begin
  3101. gl.Begin_(GL_TRIANGLE_FAN);
  3102. SinCos(AngBottom, SinP, CosP);
  3103. xgl.TexCoord2f(0.5, 0.5);
  3104. if DoReverse then
  3105. gl.Normal3f(0, 1, 0)
  3106. else
  3107. gl.Normal3f(0, -1, 0);
  3108. if FBottomCap = ctCenter then
  3109. gl.Vertex3f(0, 0, 0)
  3110. else
  3111. begin { FTopCap = ctFlat }
  3112. if (Sign(SinP) = 1) or (tc1 = VCurve) then
  3113. SinPc1 := Power(SinP, VCurve)
  3114. else
  3115. SinPc1 := -Power(-SinP, VCurve);
  3116. gl.Vertex3f(0, SinPc1 * Radius, 0);
  3117. if DoReverse then
  3118. MakeVector(N1, 0, -1, 0)
  3119. else
  3120. N1 := YVector;
  3121. end;
  3122. // v1.Y := SinP;
  3123. if (Sign(SinP) = 1) or (tc1 = VCurve) then
  3124. SinPc1 := Power(SinP, VCurve)
  3125. else
  3126. SinPc1 := -Power(-SinP, VCurve);
  3127. v1.Y := SinPc1;
  3128. Theta := AngStop;
  3129. for i := 0 to FSlices do
  3130. begin
  3131. SinCos(Theta, SinT, CosT);
  3132. // v1.X := CosP * SinT;
  3133. if (Sign(CosP) = 1) or (tc1 = VCurve) then
  3134. CosPc1 := Power(CosP, VCurve)
  3135. else
  3136. CosPc1 := -Power(-CosP, VCurve);
  3137. if (Sign(SinT) = 1) or (tc2 = HCurve) then
  3138. SinTc2 := Power(SinT, HCurve)
  3139. else
  3140. SinTc2 := -Power(-SinT, HCurve);
  3141. v1.X := CosPc1 * SinTc2;
  3142. // v1.Z := CosP * CosT;
  3143. if (Sign(CosT) = 1) or (tc2 = HCurve) then
  3144. CosTc2 := Power(CosT, HCurve)
  3145. else
  3146. CosTc2 := -Power(-CosT, HCurve);
  3147. v1.Z := CosPc1 * CosTc2;
  3148. if FBottomCap = ctCenter then
  3149. begin
  3150. N1 := VectorPerpendicular(AffineVectorMake(0, -1, 0), v1);
  3151. if DoReverse then
  3152. NegateVector(N1);
  3153. gl.Normal3fv(@N1);
  3154. end;
  3155. // xgl.TexCoord2f(SinT * 0.5 + 0.5, CosT * 0.5 + 0.5);
  3156. xgl.TexCoord2f(SinTc2 * 0.5 + 0.5, CosTc2 * 0.5 + 0.5);
  3157. vs := v1;
  3158. ScaleVector(vs, Radius);
  3159. gl.Vertex3fv(@vs);
  3160. Theta := Theta - StepH;
  3161. end;
  3162. gl.End_;
  3163. end;
  3164. if DoReverse then
  3165. rci.GLStates.InvertGLFrontFace;
  3166. end;
  3167. // This will probably not work, karamba
  3168. // RayCastSphereIntersect -> RayCastSuperellipsoidIntersect ??????
  3169. function TGLSuperellipsoid.RayCastIntersect(const rayStart, rayVector: TVector;
  3170. intersectPoint: PVector = nil; intersectNormal: PVector = nil): Boolean;
  3171. var
  3172. i1, i2: TVector;
  3173. localStart, localVector: TVector;
  3174. begin
  3175. // compute coefficients of quartic polynomial
  3176. SetVector(localStart, AbsoluteToLocal(rayStart));
  3177. SetVector(localVector, AbsoluteToLocal(rayVector));
  3178. NormalizeVector(localVector);
  3179. if RayCastSphereIntersect(localStart, localVector, NullHmgVector, Radius, i1,
  3180. i2) > 0 then
  3181. begin
  3182. Result := True;
  3183. if Assigned(intersectPoint) then
  3184. SetVector(intersectPoint^, LocalToAbsolute(i1));
  3185. if Assigned(intersectNormal) then
  3186. begin
  3187. i1.W := 0; // vector transform
  3188. SetVector(intersectNormal^, LocalToAbsolute(i1));
  3189. end;
  3190. end
  3191. else
  3192. Result := False;
  3193. end;
  3194. // This will probably not work ?
  3195. function TGLSuperellipsoid.GenerateSilhouette(const silhouetteParameters
  3196. : TGLSilhouetteParameters): TGLSilhouette;
  3197. var
  3198. i, j: Integer;
  3199. s, C, angleFactor: Single;
  3200. sVec, tVec: TAffineVector;
  3201. Segments: Integer;
  3202. begin
  3203. Segments := MaxInteger(FStacks, FSlices);
  3204. // determine a local orthonormal matrix, viewer-oriented
  3205. sVec := VectorCrossProduct(silhouetteParameters.SeenFrom, XVector);
  3206. if VectorLength(sVec) < 1E-3 then
  3207. sVec := VectorCrossProduct(silhouetteParameters.SeenFrom, YVector);
  3208. tVec := VectorCrossProduct(silhouetteParameters.SeenFrom, sVec);
  3209. NormalizeVector(sVec);
  3210. NormalizeVector(tVec);
  3211. // generate the silhouette (outline and capping)
  3212. Result := TGLSilhouette.Create;
  3213. angleFactor := (2 * PI) / Segments;
  3214. for i := 0 to Segments - 1 do
  3215. begin
  3216. SinCosine(i * angleFactor, FRadius, s, C);
  3217. Result.vertices.AddPoint(VectorCombine(sVec, tVec, s, C));
  3218. j := (i + 1) mod Segments;
  3219. Result.Indices.Add(i, j);
  3220. if silhouetteParameters.CappingRequired then
  3221. Result.CapIndices.Add(Segments, i, j)
  3222. end;
  3223. if silhouetteParameters.CappingRequired then
  3224. Result.vertices.Add(NullHmgPoint);
  3225. end;
  3226. procedure TGLSuperellipsoid.SetBottom(aValue: TAngleLimit1);
  3227. begin
  3228. if FBottom <> aValue then
  3229. begin
  3230. FBottom := aValue;
  3231. StructureChanged;
  3232. end;
  3233. end;
  3234. procedure TGLSuperellipsoid.SetBottomCap(aValue: TGLCapType);
  3235. begin
  3236. if FBottomCap <> aValue then
  3237. begin
  3238. FBottomCap := aValue;
  3239. StructureChanged;
  3240. end;
  3241. end;
  3242. procedure TGLSuperellipsoid.SetHCurve(const aValue: TGLFloat);
  3243. begin
  3244. if aValue <> FHCurve then
  3245. begin
  3246. FHCurve := aValue;
  3247. StructureChanged;
  3248. end;
  3249. end;
  3250. procedure TGLSuperellipsoid.SetRadius(const aValue: TGLFloat);
  3251. begin
  3252. if aValue <> FRadius then
  3253. begin
  3254. FRadius := aValue;
  3255. StructureChanged;
  3256. end;
  3257. end;
  3258. procedure TGLSuperellipsoid.SetSlices(aValue: Integer);
  3259. begin
  3260. if aValue <> FSlices then
  3261. begin
  3262. if aValue <= 0 then
  3263. FSlices := 1
  3264. else
  3265. FSlices := aValue;
  3266. StructureChanged;
  3267. end;
  3268. end;
  3269. procedure TGLSuperellipsoid.SetStacks(aValue: TGLInt);
  3270. begin
  3271. if aValue <> FStacks then
  3272. begin
  3273. if aValue <= 0 then
  3274. FStacks := 1
  3275. else
  3276. FStacks := aValue;
  3277. StructureChanged;
  3278. end;
  3279. end;
  3280. procedure TGLSuperellipsoid.SetStart(aValue: TAngleLimit2);
  3281. begin
  3282. if FStart <> aValue then
  3283. begin
  3284. Assert(aValue <= FStop);
  3285. FStart := aValue;
  3286. StructureChanged;
  3287. end;
  3288. end;
  3289. procedure TGLSuperellipsoid.SetStop(aValue: TAngleLimit2);
  3290. begin
  3291. if FStop <> aValue then
  3292. begin
  3293. Assert(aValue >= FStart);
  3294. FStop := aValue;
  3295. StructureChanged;
  3296. end;
  3297. end;
  3298. procedure TGLSuperellipsoid.SetTop(aValue: TAngleLimit1);
  3299. begin
  3300. if FTop <> aValue then
  3301. begin
  3302. FTop := aValue;
  3303. StructureChanged;
  3304. end;
  3305. end;
  3306. procedure TGLSuperellipsoid.SetTopCap(aValue: TGLCapType);
  3307. begin
  3308. if FTopCap <> aValue then
  3309. begin
  3310. FTopCap := aValue;
  3311. StructureChanged;
  3312. end;
  3313. end;
  3314. procedure TGLSuperellipsoid.SetVCurve(const aValue: TGLFloat);
  3315. begin
  3316. if aValue <> FVCurve then
  3317. begin
  3318. FVCurve := aValue;
  3319. StructureChanged;
  3320. end;
  3321. end;
  3322. procedure TGLSuperellipsoid.Assign(Source: TPersistent);
  3323. begin
  3324. if Assigned(Source) and (Source is TGLSuperellipsoid) then
  3325. begin
  3326. FRadius := TGLSuperellipsoid(Source).FRadius;
  3327. FSlices := TGLSuperellipsoid(Source).FSlices;
  3328. FStacks := TGLSuperellipsoid(Source).FStacks;
  3329. FBottom := TGLSuperellipsoid(Source).FBottom;
  3330. FTop := TGLSuperellipsoid(Source).FTop;
  3331. FStart := TGLSuperellipsoid(Source).FStart;
  3332. FStop := TGLSuperellipsoid(Source).FStop;
  3333. end;
  3334. inherited Assign(Source);
  3335. end;
  3336. function TGLSuperellipsoid.AxisAlignedDimensionsUnscaled: TVector;
  3337. begin
  3338. Result.X := Abs(FRadius);
  3339. Result.Y := Result.X;
  3340. Result.Z := Result.X;
  3341. Result.W := 0;
  3342. end;
  3343. // -------------------------------------------------------------
  3344. initialization
  3345. // -------------------------------------------------------------
  3346. RegisterClasses([TGLSphere, TGLCube, TGLPlane, TGLSprite, TGLPoints,
  3347. TGLDummyCube, TGLLines, TGLSuperellipsoid]);
  3348. end.