Um vielleicht doch ein eventuelles Missverständnis auszuschließen, habe ich nun meinen Code für PureBasic umgeschrieben:
Code: Alles auswählen
Structure Dots3D
dx.f
dy.f
dz.f
EndStructure
Structure Dots2D
da.l
dx.l
dy.l
EndStructure
Structure Lines
d1.l
d2.l
cl.l
EndStructure
Global Dim Dots3D.Dots3D(0)
Global Dim Dots2D.Dots2D(0)
Global Dim Lines.Lines(0)
Global CamDist, ScreenW, ScreenH, Zoom, NrOfDots, NrOfLines
Procedure Convert3Dto2D()
For i = 0 To NrOfDots
Dots2D(i)\da = 0
If Dots3D(i)\dz - CamDist > -200
Dots2D(i)\da = 1
Dots2D(i)\dx = ScreenW / 2 + Dots3D(i)\dx * Zoom / (-Dots3D(i)\dz - CamDist)
Dots2D(i)\dy = ScreenH / 2 + Dots3D(i)\dy * Zoom / (-Dots3D(i)\dz - CamDist)
Else
;Hier muss die Formel für die Berechnung des 2D Punktes hinter dem Betrachter rein!
EndIf
Next
EndProcedure
Procedure DrawObject(Mode)
StartDrawing(ScreenOutput())
If Mode = 1 Or Mode = 3
For i = 0 To NrOfLines
If Dots2D(Lines(i)\d1)\da And Dots2D(Lines(i)\d2)\da
LineXY(Dots2D(Lines(i)\d1)\dx, Dots2D(Lines(i)\d1)\dy, Dots2D(Lines(i)\d2)\dx, Dots2D(Lines(i)\d2)\dy, Lines(i)\cl)
EndIf
Next
EndIf
If Mode > 1
For i = 0 To NrOfDots
If Dots2D(i)\da
If Dots2D(i)\dx > 0 And Dots2D(i)\dx < ScreenW And Dots2D(i)\dy > 0 And Dots2D(i)\dy < ScreenH
Plot(Dots2D(i)\dx, Dots2D(i)\dy, $ffffff)
EndIf
EndIf
Next
EndIf
StopDrawing()
EndProcedure
Procedure MoveObject(mx, my, mz)
For i = 0 To NrOfDots
With Dots3D(i)
\dx + mx
\dy + my
\dz + mz
EndWith
Next
EndProcedure
Procedure RotateObject(rx, ry, rz)
Protected dist, angle
For i = 0 To NrOfDots
; If rx
; dist = Sqr(Pow(Dots3D(i)\dy, 2) + Pow(Dots3D(i)\dz + CamDist, 2))
; angle = ATan(Dots3D(i)\dy, Dots3D(i)\dz + CamDist)
; angle - rx
; Dots3D(i)\dy = Sin(angle) * dist
; Dots3D(i)\dz = Cos(angle) * dist - CamDist
; EndIf
;
; If ry
; dist = Sqr(Pow(Dots3D(i)\dx, 2) + Pow(Dots3D(i)\dz + CamDist, 2))
; angle = ATan(Dots3D(i)\dz + CamDist, Dots3D(i)\dx)
; EndIf
; angle + ry
; Dots3D(i)\dx = Sin(angle) * dist
; Dots3D(i)\dz = Cos(angle) * dist - CamDist
; EndIf
;
; If rz
; dist = Sqr(Pow(Dots3D(i)\dx, 2) + Pow(Dots3D(i)\dy, 2))
; If Dots3D(i)\dx < Dots3D(i)\dy
; angle = ATan(Dots3D(i)\dx, Dots3D(i)\dy)
; angle + rz
; Dots3D(i)\dx = Sin(angle) * dist
; Dots3D(i)\dy = Cos(angle) * dist
; EndIf
Next
EndProcedure
;Set initial values
ScreenW = 640
ScreenH = 480
CamDist = 100
Zoom = 512
;Create object
NrOfDots = 120
NrOfLines = 21
ReDim Dots3D.Dots3D(NrOfDots)
ReDim Dots2D.Dots2D(NrOfDots)
ReDim Lines.Lines(NrOfLines)
i = 0
For z = -50 To 50 Step 10
For x = -50 To 50 Step 10
With Dots3D(i)
\dx = x
\dy = -20
\dz = z
EndWith
i + 1
Next
Next
For i = 0 To 10
Lines(i)\d1 = i
Lines(i)\d2 = i + 1 * 110
Lines(i)\cl = $ff0000
Lines(i + 11)\d1 = i * 11
Lines(i + 11)\d2 = i * 11 + 10
Lines(i + 11)\cl = $ff0000
Next
InitKeyboard()
InitSprite()
If OpenWindow(0, 0, 0, ScreenW, ScreenH, "3D Wireframe")
If OpenWindowedScreen(WindowID(0), 0, 0, ScreenW, ScreenH, 0, 0, 0)
Repeat
Event = WindowEvent()
ClearScreen(0)
ExamineKeyboard()
If KeyboardPushed(#PB_Key_W): RotateObject(1, 0, 0): EndIf
If KeyboardPushed(#PB_Key_S): RotateObject(-1, 0, 0): EndIf
If KeyboardPushed(#PB_Key_Left): MoveObject(-1, 0, 0): EndIf
If KeyboardPushed(#PB_Key_Right): MoveObject(1, 0, 0): EndIf
If KeyboardPushed(#PB_Key_LeftControl) Or KeyboardPushed(#PB_Key_RightControl)
If KeyboardPushed(#PB_Key_A): RotateObject(0, 0, -1): EndIf
If KeyboardPushed(#PB_Key_D): RotateObject(0, 0, 1): EndIf
If KeyboardPushed(#PB_Key_Up): MoveObject(0, -1, 0): EndIf
If KeyboardPushed(#PB_Key_Down): MoveObject(0, 1, 0): EndIf
Else
If KeyboardPushed(#PB_Key_A): RotateObject(0, -1, 0): EndIf
If KeyboardPushed(#PB_Key_D): RotateObject(0, 1, 0): EndIf
If KeyboardPushed(#PB_Key_Up): MoveObject(0, 0, -1): EndIf
If KeyboardPushed(#PB_Key_Down): MoveObject(0, 0, 1): EndIf
EndIf
Convert3Dto2D()
DrawObject(1)
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
EndIf
EndIf
Leider funktionieren die Rotationen hier in PureBasic nicht, da die Funktionen ATAN(), SIN() und COS() anders arbeiten als bei GLBasic. Da konnte der Winkel im DEG-Format angegeben werden und ATAN() akzeptierte die Angabe des X- und Y-Anstiegs. Ich habe zwar schon probiert in Radiant umzurechnen aber das klappte dann alles vorne und hinten nicht.
Aber egal, es geht ja hier nur mal darum, wie ich das gemacht habe. Wie schon erwähnt, verschiebe ich immer die 3D-Punkte und erreiche damit denselben Effekt.
So, und jetzt habe ich bei obigem Code die Stelle kommentiert, wo die Formel rein müsste für Z<=0. Da muss jetzt nichts gefiltert werden, es geht immer nur um die Berechnung eines einzigen 2D-Punktes bei jedem Schleifendurchlauf. Es muss ganz einfach sein - irgendwie muss die Formal nur umgekehrt werden aber ich weiß eben nicht, wie. Momentan werden eben die Linien einfach ausgeblendet, so bald einer der beiden Endpunkte nicht mehr korrekt berechnet werden kann.