GLS.Objects.pas 99 KB

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