dynamic Lightning

Spiele, Demos, Grafikzeug und anderes unterhaltendes.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: dynamic Lightning

Beitrag von STARGÅTE »

Sry für Doppelpost, aber hier mal die Variante mit X,Y und Liste:

Die Liste enthält nun die relativen Koordinaten zur Lichtquelle wo eine Ecke ist.
Ich weiß leider nicht genau wie du die "Ecken hinter den Ecken" bestimmst, sodass alles glatt liegt, aber ich denke mal mit dem neuen Code kannst du mehr anfangen:

DisplayLight() nimmt nun die Ecken-Liste und sortiert sie nach Winkeln.
Damit alles gedeckt ist, sollten dann immer zwei gleiche Winkel als doppelpack kommen, sodass dann die Liste um 1 verschoben wird sodass die Dreicke entstehen.
Was noch zu beachten wäre, wäre wenn es zu wenige Ecken gibt, dass dann die Dreicke zu "flach" sind, sodass du selbst noch Ecken "im Unendlichen" hinzufügen musst. Ich vermute mal, auf dieses Problem bist du auch bei deinen Schatten schon gestoßen, wenn die Lichtquelle zu dicht am Objekt liegt richtig ?^^

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
	X.f
	Y.f
EndStructure

Structure CornerSort
	*Corner.Corner
	Angle.f
EndStructure

Procedure DisplayLightCone(Sprite3D.i, X.f, Y.f, X1.f, Y1.f, X2.f, Y2.f, MaxLength.f=386.0)
	Protected *DX9.DX9 = IsSprite3D(Sprite3D)
	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
		\Vertice[1]\X = X+X1
		\Vertice[1]\Y = Y+Y1
		\Vertice[2]\X = X+X2
		\Vertice[2]\Y = Y+Y2
		\Vertice[1]\Tu = 0.5+X1/MaxLength*0.5
		\Vertice[1]\Tv = 0.5+Y1/MaxLength*0.5
		\Vertice[2]\Tu = 0.5+X2/MaxLength*0.5
		\Vertice[2]\Tv = 0.5+Y2/MaxLength*0.5
		DisplaySprite3D(Sprite3D, 0, 0)
	EndWith
EndProcedure

Procedure DisplayLight(Sprite3D.i, X.f, Y.f, List Corner.Corner(), MaxLength.f=386.0)
	Protected *Corner1.Corner, *Corner2.Corner
	Protected NewList CornerSort.CornerSort()
	; Allen Ecken einen Winkel geben
	ForEach Corner()
		AddElement(CornerSort())
		CornerSort()\Corner = @Corner()
		CornerSort()\Angle = ATan2(Corner()\X, Corner()\Y)
	Next
	; Sortieren
	SortStructuredList(CornerSort(), #PB_Sort_Ascending, OffsetOf(CornerSort\Angle), #PB_Sort_Float)
	; Verschieben und Anzeigen
	LastElement(CornerSort())
	*Corner1 = CornerSort()\Corner
	ResetList(CornerSort())
	While NextElement(CornerSort())
		*Corner2 = CornerSort()\Corner
		DisplayLightCone(Sprite3D, X, Y, *Corner1\X, *Corner1\Y, *Corner2\X, *Corner2\Y, MaxLength)
		NextElement(CornerSort())
		*Corner1 = CornerSort()\Corner
	Wend
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)

NewList Corner.Corner()
RandomSeed(15)
For I = 0 To 9
	Angle.f = Radian(Random(359))
	AddElement(Corner())
	Radius1.f = Random(256)+128
	Corner()\X = Cos(Angle)*Radius1
	Corner()\Y = Sin(Angle)*Radius1
	AddElement(Corner())
	Radius2.f = Random(256)+128
	Corner()\X = Cos(Angle)*Radius2
	Corner()\Y = Sin(Angle)*Radius2
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)
		DisplayLight(#Sprite3D, 400, 300, Corner())
		Stop3D()
	EndIf
	
	FlipBuffers()
	
Until WindowEvent() = #PB_Event_CloseWindow 
Info: SortStructuredList() ist nicht das schnellste der Welt, daher vermute ich, der Code wird mit zunahme der Lichter und Ecken schnell langsam.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
oh... well?!
Beiträge: 98
Registriert: 21.07.2010 10:46
Computerausstattung: Intel Pentium D 2,8 GHz
2 GB RAM
ATI RADEON X700 SE

Zweitrechner :
Intel Pentium M 1,6 GHz
1 GB RAM
Intel 82852/82855 GM/GME Graphics Controller (64 MB)

Re: dynamic Lightning

Beitrag von oh... well?! »

oh... was macht die Procedure "ATan2()"? Die is bei mir irgendwie nich definiert.
Und ja, auf das Problem mit dem Ecken im Unendlichen hab ich auch und noch nicht wirklich gelöst, aber da bin ich zuversichtlich.
Bild it's Monkey Buissness
Homepage
facebook
Lord
Beiträge: 313
Registriert: 21.01.2008 19:11

Re: dynamic Lightning

Beitrag von Lord »

PureBasic-Geschichte hat geschrieben:7. Juni 2010 : Version 4.50
- Hinzugefügt: Viele Mathe-Funktionen: Exp(), ATan2(), Radian(), Degree(), [A]CosH(), [A]SinH(), [A]TanH(), IsNaN(), IsInfinity(), NaN(), Infinity(), Sign()
PureBasic Hilfe hat geschrieben:ATan2()

Syntax

Ergebnis.f = ATan2(x.f, y.f)

Beschreibung

Berechnet den Winkel im Bogenmaß (Radiant) zwischen der X-Achse und einer Linie, welche in der von 'x' und 'y' definierten Richtung gezeichnet wird. Der Winkel kann zum Berechnen von Winkeln zwischen Linien in 2D verwendet werden, oder zum Umwandeln rechtwinkeliger Koordinaten in Polarkoordinaten.
Alles klar?
Bild
Benutzeravatar
oh... well?!
Beiträge: 98
Registriert: 21.07.2010 10:46
Computerausstattung: Intel Pentium D 2,8 GHz
2 GB RAM
ATI RADEON X700 SE

Zweitrechner :
Intel Pentium M 1,6 GHz
1 GB RAM
Intel 82852/82855 GM/GME Graphics Controller (64 MB)

Re: dynamic Lightning

Beitrag von oh... well?! »

^^jop, danke. Hab die Procedure mal wie folgt implementiert:

Code: Alles auswählen

Procedure.f ATan2(x.f, y.f)
   Protected Angle.f
   Angle = ATan(y/x)
   If x < 0 : Angle + #PI : EndIf
   ProcedureReturn Angle
EndProcedure
Bis jetzt scheints zu funktionieren.

Jetzt hab ich denk ich mal alle notwendigen Informationen zusammen. Könnte aber noch bisschen dauern bis ihr was zu sehen bekommt. Muss nebenbei noch studieren.
Bild it's Monkey Buissness
Homepage
facebook
DarkDragon
Beiträge: 6267
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Re: dynamic Lightning

Beitrag von DarkDragon »

Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: dynamic Lightning

Beitrag von NicTheQuick »

Doch, seine Procedure ist richtig. Lediglich für den Fall y < 0 und x < 0 hat er eine 2*Pi-Verschiebung drin, was aber ja bekanntlich kein Problem ist. Was vielleicht nicht jeder weiß ist, dass ATan() mit - und + Unendlich zurecht kommt. Fall 4 und 5, wo x = 0 ist, sind somit automatisch abgedeckt.
Man sieht sogar, dass die in PB eingebaut Funktion ATan2 für den Fall x = 0 und y = 0 falsch rechnet. Man erhält dann nämlich 0.0 statt NaN.

Hier mein Testcode dazu:

Code: Alles auswählen

Procedure.d ATan2b(x.d, y.d)
   Protected angle.d
   angle = ATan(y / x)
   If x < 0 : angle + #PI : EndIf
   ProcedureReturn angle
EndProcedure

Debug "Case 1"
Debug ATan(1. / 1.)
Debug ATan2b(1, 1)
Debug ATan2(1, 1)
Debug "Case 2a"
Debug ATan(0.0 / -1.0) + #PI
Debug ATan2b(-1, 0)
Debug ATan2(-1, 0)
Debug "Case 2b"
Debug ATan(1.0 / -1.0) + #PI
Debug ATan2b(-1, 1)
Debug ATan2(-1, 1)
Debug "Case 3 (2*Pi-Verschiebung)"
Debug ATan(-1.0 / -1.0) - #PI
Debug ATan2b(-1, -1)
Debug ATan2(-1, -1)
Debug "Case 4"
Debug #PI / 2.
Debug ATan2b(0.0, 1.0)
Debug ATan2(0.0, 1.0)
Debug "Case 5"
Debug - #PI / 2.
Debug ATan2b(0.0, -1.0)
Debug ATan2(0.0, -1.0)
Debug "Case 6"
Debug "NaN"
Debug ATan2b(0, 0)
Debug ATan2(0, 0)
Bild
Antworten