Verfasst: 21.09.2007 23:23
Was der resultierende Wert Ausdrückt ist ja ganz alleine davon abhängig als was du ihn interpretierst. Du kannst also eine Splinelinie als Pfad und eine weitere als höhe nutzen.
Code: Alles auswählen
z.Achse
|
C=(0,100) D=(100,100)
P=(25,10)
A=(0,0) B=(100,0) ---> x-Achse
Code: Alles auswählen
Py = (dab*sab+dac*sac+dcd*scd+sbd*dbd) / 4
Code: Alles auswählen
;EnableExplicit
;Erstellt eine Kamera, die 3D-Koordinaten in 2D-Koordinaten umrechnet
CompilerIf Defined(PI, #PB_Constant) = #False
#PI = 3.141592653589793238
CompilerEndIf
#DEG2RAD = #PI / 180
Structure V3D
x.d
y.d
z.d
EndStructure
Structure Camera
p.V3D
a.V3D
x.V3D
y.V3D
z.V3D ;Zeigt in Blickrichtung
FOV.d
tFOV.d
MinX.d
MaxX.d
MinY.d
MaxY.d
AspX.d
AspY.d
EndStructure
Procedure LimitVar(Var, Min, Max)
If Var < Min
Var = Min
ElseIf Var > Max
Var = Max
EndIf
ProcedureReturn Var
EndProcedure
Procedure Camera_Calc(*Camera.Camera) ;Wird intern aufgerufen
Protected a_1.d, a_2.d, a_3.d, a_4.d, a_5.d, a_6.d, v_x.V3D, v_y.V3D
Static Pi2.d = #PI / 2
a_1 = Sin(*Camera\a\y)
a_2 = Cos(*Camera\a\x)
a_3 = Cos(*Camera\a\y)
a_4 = Sin(*Camera\a\x)
a_5 = Cos(*Camera\a\z)
a_6 = Sin(*Camera\a\z)
;Z-Achse
*Camera\z\x = a_1 * a_2 ; Sin(y) * Cos(x) 0
*Camera\z\y = a_4 ; Sin(x) 0
*Camera\z\z = a_2 * a_3 ; Cos(x) * Cos(y) 1
;Y-Achse
v_y\x = -a_1 * a_4 ; -Sin(y) * Sin(x) 0
v_y\y = a_2 ; Cos(x) 1
v_y\z = -a_4 * a_3 ; -Sin(x) * Cos(y) 0
v_x\x = -*Camera\z\y * v_y\z + *Camera\z\z * v_y\y
v_x\y = -*Camera\z\z * v_y\x + *Camera\z\x * v_y\z
v_x\z = -*Camera\z\x * v_y\y + *Camera\z\y * v_y\x
;Einberechnung des Z-Winkels
*Camera\x\x = v_x\x * a_5 + v_y\x * a_6
*Camera\x\y = v_x\y * a_5 + v_y\y * a_6
*Camera\x\z = v_x\z * a_5 + v_y\z * a_6
*Camera\y\x = v_y\x * a_5 - v_x\x * a_6
*Camera\y\y = v_y\y * a_5 - v_x\y * a_6
*Camera\y\z = v_y\z * a_5 - v_x\z * a_6
EndProcedure
Procedure Camera_New() ;Erstellt eine neue Kamera
Protected *Camera.Camera
*Camera = AllocateMemory(SizeOf(Camera))
If *Camera = 0 : ProcedureReturn #False : EndIf
Camera_Calc(*Camera)
With *Camera
\MinX = -1
\MaxX = 1
\MinY = -1
\MaxY = 1
\AspX = 1
\AspY = 1
EndWith
ProcedureReturn *Camera
EndProcedure
Procedure Camera_Set(*Camera.Camera, *Position.V3D, *Angle.V3D) ;Setzt Position und Winkel der Kamera
If *Position
*Camera\p\x = *Position\x
*Camera\p\y = *Position\y
*Camera\p\z = *Position\z
EndIf
If *Angle
*Camera\a\x = *Angle\x * #DEG2RAD
*Camera\a\y = *Angle\y * #DEG2RAD
*Camera\a\z = *Angle\z * #DEG2RAD
Camera_Calc(*Camera)
EndIf
EndProcedure
Procedure Camera_Add(*Camera.Camera, *Position.V3D, *Angle.V3D) ;Addiert Position und Winkel zur Kamera
If *Position
*Camera\p\x + *Position\x
*Camera\p\y + *Position\y
*Camera\p\z + *Position\z
EndIf
If *Angle
*Camera\a\x + *Angle\x * #DEG2RAD
*Camera\a\y + *Angle\y * #DEG2RAD
*Camera\a\z + *Angle\z * #DEG2RAD
Camera_Calc(*Camera)
EndIf
EndProcedure
Procedure.d Camera_FOV(*Camera.Camera, FOV.d = -1) ;Setzt "Field of view" der Kamera in Grad (0 < FOV < 180) oder gibt es zurück
If FOV = -1
ProcedureReturn *Camera\FOV
ElseIf FOV > 0 And FOV < 180
*Camera\FOV = FOV * #DEG2RAD
*Camera\tFOV = Tan(*Camera\FOV)
EndIf
EndProcedure
Procedure Camera_Size(*Camera.Camera, MinX.d, MaxX.d, MinY.d, MaxY.d) ;Setzt die maximalen Ausgabekoordinaten
With *Camera
\MinX = MinX
\MaxX = MaxX
\MinY = MinY
\MaxY = MaxY
If \MaxX - \MinX > \MaxY - \MinY
\AspX = 1
\AspY = (\MaxY - \MinY) / (\MaxX - \MinX)
ElseIf \MaxX - \MinX = \MaxY - \MinY
\AspX = 1
\AspY = 1
Else
\AspY = 1
\AspX = (\MaxX - \MinX) / (\MaxY - \MinY)
EndIf
EndWith
EndProcedure
Procedure Camera_Move(*Camera.Camera, *Position.V3D, *Angle.V3D) ;Bewegt die Kamera relativ zu Position und Drehung
Protected CosZ.d, SinZ.d
If *Position
*Camera\p\x + *Position\x * *Camera\x\x + *Position\y * *Camera\y\x + *Position\z * *Camera\z\x
*Camera\p\y + *Position\x * *Camera\x\y + *Position\y * *Camera\y\y + *Position\z * *Camera\z\y
*Camera\p\z + *Position\x * *Camera\x\z + *Position\y * *Camera\y\z + *Position\z * *Camera\z\z
EndIf
If *Angle
*Camera\a\z + *Angle\z * #DEG2RAD
CosZ = Cos(*Camera\a\z)
SinZ = Sin(*Camera\a\z)
*Camera\a\x + (*Angle\x * CosZ + *Angle\y * SinZ) * #DEG2RAD
*Camera\a\y + (*Angle\y * CosZ - *Angle\x * SinZ) * #DEG2RAD
Camera_Calc(*Camera)
EndIf
EndProcedure
Procedure Camera_3Dto2D(*Camera.Camera, *p3d.V3D, *p2d.V3D, *c3d.V3D = 0) ;Rechnet 3D-Punkt in 2D-Punkt um
Protected v_x.V3D, v_y.V3D, v.V3D, cx.d, cy.d, cz.d
;Vektor von Kamera zu Punkt
v\x = *p3d\x - *Camera\p\x
v\y = *p3d\y - *Camera\p\y
v\z = *p3d\z - *Camera\p\z
;Abstand von Kamera auf Z-Achse
cz = v\x * *Camera\z\x + v\y * *Camera\z\y + v\z * *Camera\z\z
If cz = 0
cx = 0
cy = 0
*p2d\x = 0
*p2d\y = 0
Else
;Abstand von Kamera auf X- und Y-Achse
cx = v\x * *Camera\x\x + v\y * *Camera\x\y + v\z * *Camera\x\z
cy = v\x * *Camera\y\x + v\y * *Camera\y\y + v\z * *Camera\y\z
;Berechnung des 2D-Punktes auf X- und Y-Achse im Bereich -1 bis 1
*p2d\x = cx / (cz * *Camera\tFOV) / *Camera\AspX
*p2d\y = cy / (cz * *Camera\tFOV) / *Camera\AspY
;Umrechnung des Bereichs auf die maximalen Ausgabekoordinaten
*p2d\x = *Camera\MinX + (*p2d\x + 1) * 0.5 * (*Camera\MaxX - *Camera\MinX)
*p2d\y = *Camera\MinY + (*p2d\y + 1) * 0.5 * (*Camera\MaxY - *Camera\MinY)
EndIf
If *c3d
*c3d\x = cx
*c3d\y = cy
*c3d\z = cz
EndIf
;Wenn Punkt hinter Kamera war
If cz <= 0 : ProcedureReturn #False : EndIf
;Wenn Punkt außerhalb maximalen Ausgabekoordinaten war
If *p2d\x < *Camera\MinX Or *p2d\x > *Camera\MaxX : ProcedureReturn #False : EndIf
If *p2d\y < *Camera\MinY Or *p2d\y > *Camera\MaxY : ProcedureReturn #False : EndIf
;Wenn Punkt im sichtbaren Bereich
ProcedureReturn #True
EndProcedure
Structure Dots
p.V3D
c.l
EndStructure
Global Width.l = 800, Height.l = 600
Define x.l, y.l, z.l, i.l, d.d, m.l, n.l, o.l, R.l, c
Define scaley.f
Define temp.V3D
Global NewList Dots.Dots()
InitSprite()
InitKeyboard()
InitMouse()
If OpenWindow(0, 0, 0, Width, Height, "3D-to-2D") = 0 : End : EndIf
If OpenWindowedScreen(WindowID(0), 0, 0, Width, Height, 0, 0, 0) = 0 : End : EndIf
UsePNGImageDecoder()
If LoadImage(1, #PB_Compiler_Home+"Examples\Sources\Data\Terrain.png")
StartDrawing(ImageOutput(1))
w = ImageWidth(1)/4
h = ImageHeight(1)/4
Dim dotar.V3D(w,h)
Dim temp.V3D(w,h)
For x = 0 To w
For y = 0 To h
dotar(x,y)\x = x
dotar(x,y)\y = 255-Red(Point(x,y))
dotar(x,y)\z = y
Next
Next
StopDrawing()
EndIf
Define p.V3D, a.V3D, p2d.V3D, p2d.V3D
Define p_add.d, a_add.d, FOV.d
p_add.d = 1
a_add.d = 1
FOV.d = 45
scaley = 4
#maxdif = 0
Define *Camera.Camera
*Camera.Camera = Camera_New()
Camera_Size(*Camera, 0, Width - 1, 0, Height - 1)
Repeat
ClearScreen(0)
ExamineKeyboard()
ExamineMouse()
p\x = 0 : p\y = 0 : p\z = 0
a\x = 0 : a\y = 0 : a\z = 0
If KeyboardPushed(#PB_Key_Up) : p\z + p_add : EndIf
If KeyboardPushed(#PB_Key_Down) : p\z - p_add : EndIf
If KeyboardPushed(#PB_Key_Left) : p\x - p_add : EndIf
If KeyboardPushed(#PB_Key_Right) : p\x + p_add : EndIf
a\x + MouseDeltaY() * 0.5
a\y + MouseDeltaX() * 0.5
If KeyboardReleased(#PB_Key_A) : scaley/2 : EndIf
If KeyboardReleased(#PB_Key_Z) : scaley*2 : EndIf
If KeyboardPushed(#PB_Key_S) : a\z + a_add : EndIf
If KeyboardPushed(#PB_Key_X) : a\z - a_add : EndIf
If KeyboardPushed(#PB_Key_D) : FOV - 0.25 : EndIf
If KeyboardPushed(#PB_Key_C) : FOV + 0.25 : EndIf
Camera_FOV(*Camera, FOV)
; t.V3D\x = LimitVar(*Camera\p\x+p\x, 0, w)
; t.V3D\z = LimitVar(*Camera\p\z+p\z, 0, h)
; t.V3D\y = Dotar(Int(*Camera\p\x),Int(*Camera\p\z))\y/scaley-5
; Camera_Set(*Camera, t, 0)
; Camera_Move(*Camera, 0, a)
Camera_Move(*Camera, p, a)
StartDrawing(ScreenOutput())
For x = 0 To w
For y = 0 To h
temp.V3D\x = Dotar(x,y)\x
temp.V3D\y = Dotar(x,y)\y/scaley
temp.V3D\z = Dotar(x,y)\z
If Camera_3Dto2D(*Camera, temp, temp(x,y))
; Circle(temp(x,y)\x, temp(x,y)\y, 2, #White)
; Else
; temp(x,y)\x = -1
; temp(x,y)\y = -1
EndIf
Next
Next
For x = 0 To w-1
For y = 0 To h-1
; If temp(x,y)\x > 0-#maxdif And temp(x,y)\x < Width+#maxdif And temp(x,y)\y > 0-#maxdif And temp(x,y)\y < Height+#maxdif
; If temp(x+1,y)\x > 0-#maxdif And temp(x+1,y)\x < Width+#maxdif And temp(x+1,y)\y > 0-#maxdif And temp(x+1,y)\y < Height+#maxdif
LineXY(temp(x,y)\x, temp(x,y)\y, temp(x+1,y)\x, temp(x+1,y)\y, #Gray)
; EndIf
; If temp(x,y+1)\x > 0-#maxdif And temp(x,y+1)\x < Width+#maxdif And temp(x,y+1)\y > 0-#maxdif And temp(x,y+1)\y < Height+#maxdif
LineXY(temp(x,y)\x, temp(x,y)\y, temp(x,y+1)\x, temp(x,y+1)\y, #Gray)
; EndIf
; EndIf
Next
Next
StopDrawing()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)