Um mal meine Ausführungen zu visualisieren, hab ich mal einen kleinen Beispielcode geschrieben, wie das mit den Dreiecken funktionieren könnte.
DisplayLightCone() zeichnet ein Dreieck-Sprite3D mit den Koordianten X,Y und die beiden Polarkoordinaten 1 und 2
DisplayLight() verlangt hier die Koordianten des Lichtzentrums und ein Array aus Ecken, an denen "sich etwas ändert" (was du vermutlich eh hast).
Außerdem hab ich unten noch etwas bewegung hineingebracht.
Wie man/du siehst, wird das ganze Licht "perfekt" dargestellt, obwohl aus aus vielen Dreiecken besteht.
Die Berechnungen (Sin, Cos) könnne natürlich noch ausgelagert werden, um es zu beschleunigen.
Code: Alles auswählen
Structure DX9Vertex
X.f
Y.f
Z.f
Rhw.f
Color.l
Tu.f
Tv.f
EndStructure
Structure DX9
TexRes.i
Vertice.DX9Vertex[4]
TmpVertice.DX9Vertex[4]
Width.l
Height.l
RealWidth.l
RealHeight.l
Angle.f
Transformed.l
EndStructure
Structure Corner
Radius1.f
Radius2.f
Angle.f
EndStructure
Procedure DisplayLightCone(Sprite3D.i, X.f, Y.f, Angle1.f, Length1.f, Angle2.f, Length2.f, MaxLength.f=386.0)
Protected *DX9.DX9 = IsSprite3D(Sprite3D)
Protected I1=1, I2=2
With *DX9
\Transformed = 1
\Vertice[0]\X = X
\Vertice[0]\Y = Y
\Vertice[0]\Tu = 0.5
\Vertice[0]\Tv = 0.5
\Vertice[3]\X = X
\Vertice[3]\Y = Y
\Vertice[3]\Tu = 0.5
\Vertice[3]\Tv = 0.5
If Angle1 > Angle2
Swap I1, I2
EndIf
\Vertice[I1]\X = X+Cos(Angle1)*Length1
\Vertice[I1]\Y = Y+Sin(Angle1)*Length1
\Vertice[I2]\X = X+Cos(Angle2)*Length2
\Vertice[I2]\Y = Y+Sin(Angle2)*Length2
\Vertice[I1]\Tu = 0.5+Cos(Angle1)*Length1/MaxLength*0.5
\Vertice[I1]\Tv = 0.5+Sin(Angle1)*Length1/MaxLength*0.5
\Vertice[I2]\Tu = 0.5+Cos(Angle2)*Length2/MaxLength*0.5
\Vertice[I2]\Tv = 0.5+Sin(Angle2)*Length2/MaxLength*0.5
DisplaySprite3D(Sprite3D, 0, 0)
EndWith
EndProcedure
Procedure DisplayLight(Sprite3D.i, X.f, Y.f, Array Corner.Corner(1), MaxLength.f=386.0)
Protected Size.i = ArraySize(Corner())
Protected I.i
For I = 0 To Size
DisplayLightCone(Sprite3D, X, Y, Corner(I)\Angle, Corner(I)\Radius1, Corner((I+1)%(Size+1))\Angle, Corner(I)\Radius2, MaxLength)
Next
EndProcedure
InitSprite()
InitSprite3D()
Enumeration
#Window
#Sprite
#Sprite3D
EndEnumeration
OpenWindow(#Window, 0, 0, 800, 600, "ScreenTitle", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(#Window), 0, 0, WindowWidth(#Window), WindowHeight(#Window), 0, 0, 0)
CreateSprite(#Sprite, 256, 256, #PB_Sprite_Texture)
StartDrawing(SpriteOutput(#Sprite))
For R = 127 To 1 Step -1
Gray = Pow(1-r/127.0, 2)*255
Circle(128, 128, R, RGB(Gray, Gray, Gray))
Next
StopDrawing()
CreateSprite3D(#Sprite3D, #Sprite)
Dim Corner.Corner(10)
RandomSeed(5)
For I = 0 To 10
Corner(I)\Angle = Radian(I*36)
Corner(I)\Radius1 = Random(256)+128
Corner(I)\Radius2 = Random(256)+128
Next
Repeat
Repeat
Select WindowEvent()
Case #PB_Event_CloseWindow
End
Case #Null
Break
EndSelect
ForEver
ClearScreen(0)
StartDrawing(ScreenOutput())
For X = 0 To 799
Line(X,0,1,600,RGB(X*128/799,0,128-X*128/799))
Next
StopDrawing()
If Start3D()
Sprite3DBlendingMode(5,2)
Corner(3)\Radius1 = 256+Sin(ElapsedMilliseconds()*0.001)*128
Corner(4)\Angle = Radian(4*36+Sin(ElapsedMilliseconds()*0.001)*18)
DisplayLight(#Sprite3D, 400, 300, Corner())
Stop3D()
EndIf
FlipBuffers()
Until WindowEvent() = #PB_Event_CloseWindow
PS: Ich könnte ja gleich mal eine Prozedur schreiben wie DisplayPolygonSprite3D() bei der ein Sprite3D mit der angegebenen Polygon-Maske gezeichnet wird.