RosettaCodeData/Task/Death-Star/FreeBASIC/death-star-2.basic

101 lines
2.6 KiB
Plaintext

Type vector
v(2) As Double
End Type
Type sphere
cx As Integer
cy As Integer
cz As Integer
r As Integer
End Type
Function dot(x As vector, y As vector) As Double
Return x.v(0)*y.v(0) + x.v(1)*y.v(1) + x.v(2)*y.v(2)
End Function
Sub normalizeVector(v As vector)
Dim invLen As Double = 1.0 / Sqr(dot(v, v))
v.v(0) *= invLen
v.v(1) *= invLen
v.v(2) *= invLen
End Sub
Function hitSphere(s As sphere, x As Integer, y As Integer, z1 As Double Ptr, z2 As Double Ptr) As Boolean
Dim xx As Integer = x - s.cx
Dim yy As Integer = y - s.cy
Dim zsq As Integer = s.r*s.r - (xx*xx + yy*yy)
If zsq >= 0 Then
Dim zsqrt As Double = Sqr(zsq)
*z1 = s.cz - zsqrt
*z2 = s.cz + zsqrt
Return True
End If
Return False
End Function
Function createDeathStar(posic As sphere, neg As sphere, k As Double, amb As Double, direc As vector) As Any Ptr
Dim As Integer w = posic.r * 4
Dim As Integer h = posic.r * 3
Dim As Any Ptr img = Imagecreate(w, h, Rgb(0,0,0))
Dim vec As vector
Dim As Double z1, z2, zs1, zs2
For y As Integer = posic.cy - posic.r To posic.cy + posic.r
For x As Integer = posic.cx - posic.r To posic.cx + posic.r
If hitSphere(posic, x, y, @z1, @z2) Then
Dim hit As Boolean = hitSphere(neg, x, y, @zs1, @zs2)
If hit Then
If zs1 > z1 Then hit = False
If zs2 > z2 Then Continue For
End If
If hit Then
vec.v(0) = neg.cx - x
vec.v(1) = neg.cy - y
vec.v(2) = neg.cz - zs2
Else
vec.v(0) = x - posic.cx
vec.v(1) = y - posic.cy
vec.v(2) = z1 - posic.cz
End If
normalizeVector(vec)
Dim s As Double = dot(direc, vec)
If s < 0 Then s = 0
Dim lum As Double = 255 * (s^k + amb) / (1 + amb)
If lum < 0 Then lum = 0
If lum > 255 Then lum = 255
Dim shade As Integer = lum
Pset img, (x + w\2, y + h\2), Rgb(shade, shade, shade)
End If
Next x
Next y
Return img
End Function
' Main program
Screenres 500, 400, 32
Windowtitle "Death Star FreeBASIC"
Dim direct As vector
direct.v(0) = 20
direct.v(1) = -40
direct.v(2) = -10
normalizeVector(direct)
Dim posic As sphere = Type(0, 0, 0, 120)
Dim neg As sphere = Type(-50, -50, -30, 75)
Dim img As Any Ptr = createDeathStar(posic, neg, 1.5, 0.2, direct)
Put (0, 0), img
Imagedestroy(img)
Sleep