Re: Drawing3D - Draw-Befehle für 3D-Szenen
Verfasst: 21.08.2014 12:08
Ich habe es jetzt nicht überprüft, aber kann es sein, dass einer von euch von einer globalen Rotation spricht und der andere von einer lokalen?
Das deutsche PureBasic-Forum
https://www.purebasic.fr/german/
Die zusammensetzung ist einfach falsch. Die Rotation um alle 3 möglichen Achsen ist nicht nur die Multiplikation der einzelnen Komponenten.silbersurfer hat geschrieben:ja aber was genau mache Ich da Falsch?
Da der Fehler ja schon in der Matrix liegt, will ich deine falsche Matrix ungern analysieren.silbersurfer hat geschrieben:Mir ist auch aufgefallen das es nur zu fehlern kommt wenn Ich X und Y Achse Rotiere X-Z oder Y-Z ergeben in meinen Augen keine fehler zumindest Rotieren Sie wie Ich mir das gedacht hatte
Code: Alles auswählen
; Image3D
;---------
; Disable the debugger !
XIncludeFile "Drawing3D.pbi"
Enumeration
#Window
#Gadget
#Image
#Image3D
EndEnumeration
UsePNGImageDecoder()
UseJPEGImageDecoder()
LoadImage(#Image, "Image.png")
CreateImage3D(#Image3D, #Image)
OpenWindow(#Window, 0, 0, 500, 500, "Image3D", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
CanvasGadget(#Gadget, 0, 0, WindowWidth(#Window), WindowHeight(#Window))
If StartDrawing3D(CanvasOutput(#Gadget))
Drawing3DMode(#Drawing3D_Outline)
DrawImage3D(#Image3D, 0, 0, 0, 400, 400, 0, 0, -30)
DrawImage3D(#Image3D, 0, 0, 0, 400, 400, 0, 0, 15)
DrawImage3D(#Image3D, 0, 0, 0, 400, 400, 0, 0, 45)
StopDrawing3D()
EndIf
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
EndSelect
ForEver
Code: Alles auswählen
Procedure.i Drawing3D_ImageColor(*Color.Drawing3D_Color, X.f, Y.f)
Protected *Image3D.Drawing3D_Image = Drawing3DInclude\CurrentImage3D
Protected Null.Drawing3D_Color
Protected FX.f = Mod(X**Image3D\Width+0.5, 1.0)
Protected FY.f = Mod(Y**Image3D\Height+0.5, 1.0)
Protected PixelX0.i = X * (*Image3D\Width+2) - 1.5 - FX
Protected PixelY0.i = Y * (*Image3D\Height+2) - 1.5 - FY
Protected PixelX1.i = X * (*Image3D\Width+2) - 0.5 - FX
Protected PixelY1.i = Y * (*Image3D\Height+2) - 0.5 - FY
; If PixelX0 < 0 : PixelX0 = 0 : EndIf
; If PixelY0 < 0 : PixelY0 = 0 : EndIf
; If PixelX1 > *Image3D\Width-1 : PixelX1 = *Image3D\Width-1 : EndIf
; If PixelY1 > *Image3D\Height-1 : PixelY1 = *Image3D\Height-1 : EndIf
; Protected *C00.Drawing3D_Color = *Image3D\Pixel(PixelX0, PixelY0)
; Protected *C10.Drawing3D_Color = *Image3D\Pixel(PixelX1, PixelY0)
; Protected *C01.Drawing3D_Color = *Image3D\Pixel(PixelX0, PixelY1)
; Protected *C11.Drawing3D_Color = *Image3D\Pixel(PixelX1, PixelY1)
Protected.Drawing3D_Color *C00 = @Null, *C10 = @Null, *C01 = @Null, *C11 = @Null
If PixelX0 >= 0 And PixelX0 < *Image3D\Width And PixelY0 >= 0 And PixelY0 < *Image3D\Height : *C00 = *Image3D\Pixel(PixelX0, PixelY0) : EndIf
If PixelX1 >= 0 And PixelX1 < *Image3D\Width And PixelY0 >= 0 And PixelY0 < *Image3D\Height : *C10 = *Image3D\Pixel(PixelX1, PixelY0) : EndIf
If PixelX0 >= 0 And PixelX0 < *Image3D\Width And PixelY1 >= 0 And PixelY1 < *Image3D\Height : *C01 = *Image3D\Pixel(PixelX0, PixelY1) : EndIf
If PixelX1 >= 0 And PixelX1 < *Image3D\Width And PixelY1 >= 0 And PixelY1 < *Image3D\Height : *C11 = *Image3D\Pixel(PixelX1, PixelY1) : EndIf
*Color\Alpha = *C00\Alpha*(1-FX)*(1-FY) + *C10\Alpha*(FX)*(1-FY) + *C01\Alpha*(1-FX)*(FY) + *C11\Alpha*(FX)*(FY)
*Color\Red = *C00\Red *(1-FX)*(1-FY) + *C10\Red *(FX)*(1-FY) + *C01\Red *(1-FX)*(FY) + *C11\Red *(FX)*(FY)
*Color\Green = *C00\Green*(1-FX)*(1-FY) + *C10\Green*(FX)*(1-FY) + *C01\Green*(1-FX)*(FY) + *C11\Green*(FX)*(FY)
*Color\Blue = *C00\Blue *(1-FX)*(1-FY) + *C10\Blue *(FX)*(1-FY) + *C01\Blue *(1-FX)*(FY) + *C11\Blue *(FX)*(FY)
EndProcedure
Code: Alles auswählen
XIncludeFile "Drawing3D.pbi"
Enumeration
#Window
#Gadget
#Image
#Image3D
EndEnumeration
UsePNGImageDecoder()
OpenWindow(#Window, 0, 0, 500, 500, "Image3D", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
CanvasGadget(#Gadget, 0, 0, WindowWidth(#Window), WindowHeight(#Window))
For n = 1 To 10
; Nächstes Bild laden
LoadImage(#Image, "Image.png")
CreateImage3D(#Image3D, #Image)
If StartDrawing3D(CanvasOutput(#Gadget))
Drawing3DMode(#Drawing3D_Default)
Drawing3DBackground($FFFFFFFF)
DrawImage3D(#Image3D, Random(20), Random(20), 0, ImageWidth(#Image), ImageHeight(#Image), 0, 0, Random(60)-30)
StopDrawing3D()
EndIf
FreeImage3D(#Image3D)
Next
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
EndSelect
ForEver
Code: Alles auswählen
; Schließt eine Drawing3D-Umgebung und rendert die Szene
Procedure StopDrawing3D()
Protected *Pixel.Drawing3D_Pixel, *PreviousPixel.Drawing3D_Pixel
Protected Color.Drawing3D_Color
Protected X.i, Y.i
;DrawingMode(#PB_2DDrawing_AllChannels)
DrawingMode(#PB_2DDrawing_AlphaBlend)
For Y = 0 To Drawing3DInclude\MaxY
For X = 0 To Drawing3DInclude\MaxX
*Pixel = Drawing3DInclude\PixelIndex(X, Y)
If *Pixel
While *Pixel\PreviousPixel
Drawing3D_AlphaBlend(*Pixel\PreviousPixel\Color, *Pixel\Color)
*Pixel = *Pixel\PreviousPixel
Wend
;Color = Drawing3DInclude\Background
;Plot(X, Y, Drawing3D_GetColor(Drawing3D_AlphaBlend(Color, *Pixel)))
Plot(X, Y, Drawing3D_GetColor(*Pixel\Color))
EndIf
Next
Next
StopDrawing()
EndProcedure
Code: Alles auswählen
; wenn Deine Drehmatrix nicht stimmt, so setze Deine Matrix doch einfach aus den Einzelmatrizen (die ja stimmen) zusammen,
; indem Du sie nacheinander durchmultiplizierst:
Procedure MatrixMult3x3(*m1.Matrix3D,*m2.Matrix3D,*m3.Matrix3D)
*m3\p11 = *m1\p11 * *m2\p11 + *m1\p21 * *m2\p12 + *m1\p31 * *m2\p13
*m3\p12 = *m1\p11 * *m2\p21 + *m1\p21 * *m2\p22 + *m1\p31 * *m2\p23
*m3\p13 = *m1\p11 * *m2\p31 + *m1\p21 * *m2\p32 + *m1\p31 * *m2\p33
*m3\p21 = *m1\p12 * *m2\p11 + *m1\p22 * *m2\p12 + *m1\p32 * *m2\p13
*m3\p22 = *m1\p12 * *m2\p21 + *m1\p22 * *m2\p22 + *m1\p32 * *m2\p23
*m3\p23 = *m1\p12 * *m2\p31 + *m1\p22 * *m2\p32 + *m1\p32 * *m2\p33
*m3\p31 = *m1\p13 * *m2\p11 + *m1\p23 * *m2\p12 + *m1\p33 * *m2\p13
*m3\p32 = *m1\p13 * *m2\p21 + *m1\p23 * *m2\p22 + *m1\p33 * *m2\p23
*m3\p33 = *m1\p13 * *m2\p31 + *m1\p23 * *m2\p32 + *m1\p33 * *m2\p33
EndProcedure
; Du kannst natürlich auch die von Stargate erwähnten Quaternions benutzen. Der Vorteil : alle Transformationen
; können durch eine Matrixform dargestellt werden z.B. :
Structure Matrix4 ; Drehmatrix Verschiebematrix Skalierungsmatrix
p11.f : p21.f : p31.f : p41.f ; d d d 0 1 0 0 v s 0 0 0
p12.f : p22.f : p32.f : p42.f ; d d d 0 0 1 0 v 0 s 0 0
p13.f : p23.f : p33.f : p43.f ; d d d 0 0 0 1 v 0 0 s 0
p14.f : p24.f : p34.f : p44.f ; 0 0 0 1 0 0 0 1 0 0 0 1
EndStructure
; die gesamte Transformation mit verdrehen, verschieben, skalieren kann durch Multiplizieren der entsprechenden
; Matrizen auf eine Matrix-Vektor-Multiplikation zurückgeführt werden, was bei großen Datenmengen natürlich von
; Vorteil ist (z.B. OpenGL arbeitet so)
; Punkte und Vektoren werden dabei so dargestellt:
Structure Vector4 ; Punkt Vektor
p1.f : p2.f : p3.f : p4.f ; x y z 1 x y z 0
EndStructure
; orthogonal :
; Eine Drehmatrix ist immer orthogonal d.h. die Determinante ist 1.
; Wenn orthogonale Matrizen multipliziert werden, ist das Ergebnis wieder orthogonal.
; Die Drehmatrix kann man sich als Koordinatensystemachsen vorstellen (jede Achse steht senkrecht auf den anderen
; beiden Achsen -> deswegen orthogonal). Wenn Matrizen sehr oft miteinander multipliziert werden, (und nicht immer
; wieder initialisiert werden z.B. durch Neuberechnung aus Winkeln) kann durch die Fehlerfortpflanzung die
; Drehmatrix nicht mehr orthogonal sein. Das kann man durch die Berechnung der Determinante der Drehmatrix
; prüfen (der Skalierungsfaktor ist hierbei zu beachten!!!). Wenn die Determinante sehr von 1 abweicht, dann
; sollte man die Drehmatrix wieder orthogonalisieren, sonst ist die Darstellung verzerrt.
Structure Vector3
p1.f : p2.f : p3.f
EndStructure
Procedure.f Determinante(*m.Matrix3D)
Protected D.f = *m\p11 * *m\p22 * *m\p33 + *m\p21 * *m\p32 * *m\p13 + *m\p31 * *m\p12 * *m\p23
D - *m\p11 * *m\p32 * *m\p23 + *m\p21 * *m\p12 * *m\p33 + *m\p31 * *m\p22 * *m\p13
ProcedureReturn D
EndProcedure
Procedure VektorProduct(*v1.Vektor3,*v2.Vector3,*v3.Vector3)
*v3\p1 = *v1\p2 * *v2\p3 - *v1\p3 * *v2\p2
*v3\p2 = *v1\p3 * *v2\p1 - *v1\p1 * *v2\p3
*v3\p3 = *v1\p1 * *v2\p2 - *v1\p2 * *v2\p1
EndProcedure
Procedure VektorNorm(*v.Vector3)
Protected L.f = *v\p1 * *v\p1 + *v\p2 * *v\p2 + *v\p3 * *v\p3
L = Sqr(L)
*v\p1 * L
*v\p2 * L
*v\p3 * L
EndProcedure
Procedure OrthoMatrix(*m.Matrix3D)
Protected v1.Vector3,v2.Vektor3,v3.Vektor3,vh2.Vector3,vh3.Vector3
v1\p1 = *m\p11 : v1\p2 = *m\p12 : v1\p3 = *m\p13
v2\p1 = *m\p21 : v2\p2 = *m\p22 : v2\p3 = *m\p23
v3\p1 = *m\p31 : v3\p2 = *m\p32 : v3\p3 = *m\p33
VectorProduct(@v1,@v2,@vh3)
VectorProduct(@vh3,@v1,@vh2)
VectorNorm(@v1)
VectorNorm(@vh2)
VectorNorm(@vh3)
*m\p11 = v1\p1 : *m\p12 = v1\p2 : *m\p13 = v1\p3
*m\p21 = vh2\p1 : *m\p22 = vh2\p2 : *m\p23 = vh2\p3
*m\p31 = vh3\p1 : *m\p32 = vh3\p2 : *m\p33 = vh3\p3
EndProcedure
Yap, sieht gut aus! Danke!STARGÅTE hat geschrieben: Lieber selber den Background setzen mit normalen 2D-Drawing am anfang.
Code: Alles auswählen
XIncludeFile "Drawing3D.pbi"
Enumeration
#Window
#Gadget
#Image
#Image3D
EndEnumeration
UsePNGImageDecoder()
OpenWindow(#Window, 0, 0, 1024, 768, "Image3D", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
CanvasGadget(#Gadget, 0, 0, WindowWidth(#Window), WindowHeight(#Window))
For n = 1 To 10
; Nächstes Bild laden
CreateImage(#Image, 160, 120, 32, #PB_Image_Transparent )
If StartDrawing(ImageOutput(#Image))
DrawingMode(#PB_2DDrawing_AllChannels )
RoundBox(0, 0, ImageWidth(#Image), ImageHeight(#Image), 3, 3, RGBA(128, 128, 128, 100)) ; Schatten
RoundBox(4, 4, ImageWidth(#Image) - 8, ImageHeight(#Image) - 8, 3, 3, RGBA(255, 255, 255, 255)) ; BildRahmen
DrawText(20, 20, Str(n))
StopDrawing()
EndIf
; LoadImage(#Image, "Image.png")
CreateImage3D(#Image3D, #Image)
If StartDrawing3D(CanvasOutput(#Gadget))
Drawing3DMode(#Drawing3D_Default)
x = Random(WindowWidth(#Window) - ImageWidth(#Image))
y = Random(WindowHeight(#Window) - ImageHeight(#Image))
DrawImage3D(#Image3D, x, y, 0, ImageWidth(#Image), ImageHeight(#Image), 0, 0, Random(60)-30)
; DrawImage(ImageID(#Image), x, y)
DrawText( x, y, "Bild: " + Str(n) + " | " + Str(x) + ", " + Str(y))
StopDrawing3D()
EndIf
FreeImage3D(#Image3D)
Next
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
EndSelect
ForEver