GLObjects.pas 102 KB

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