Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
90
Task/Death-Star/Nim/death-star.nim
Normal file
90
Task/Death-Star/Nim/death-star.nim
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
import math
|
||||
|
||||
import bitmap, grayscale_image, nimPNG
|
||||
|
||||
type
|
||||
|
||||
Vector = array[3, float]
|
||||
|
||||
Sphere = object
|
||||
cx, cy, cz: int
|
||||
r: int
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
func dot(x, y: Vector): float {.inline.} =
|
||||
x[0] * y[0] + x[1] * y[1] + x[2] * y[2]
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
func normalize(v: var Vector) =
|
||||
let invLen = 1 / sqrt(dot(v, v))
|
||||
v[0] *= invLen
|
||||
v[1] *= invLen
|
||||
v[2] *= invLen
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
func hit(s: Sphere; x, y: int): tuple[z1, z2: float; hit: bool] =
|
||||
let x = x - s.cx
|
||||
let y = y - s.cy
|
||||
let zsq = s.r * s.r - (x * x + y * y)
|
||||
if zsq >= 0:
|
||||
let zsqrt = sqrt(zsq.toFloat)
|
||||
result = (s.cz.toFloat - zsqrt, s.cz.toFloat, true)
|
||||
else:
|
||||
result = (0.0, 0.0, false)
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
func deathStar(pos, neg: Sphere; k, amb: float; dir: Vector): GrayImage =
|
||||
|
||||
let w = pos.r * 4
|
||||
let h = pos.r * 3
|
||||
result = newGrayImage(w, h)
|
||||
var vect: Vector
|
||||
let deltaX = pos.cx - w div 2
|
||||
let deltaY = pos.cy - h div 2
|
||||
|
||||
let xMax = pos.cx + pos.r
|
||||
let yMax = pos.cy + pos.r
|
||||
for y in (pos.cy - pos.r)..yMax:
|
||||
for x in (pos.cx - pos.r)..xMax:
|
||||
let (zb1, zb2, posHit) = pos.hit(x, y)
|
||||
if not posHit: continue
|
||||
var (zs1, zs2, negHit) = neg.hit(x, y)
|
||||
if negHit:
|
||||
if zs1 > zb1: negHit = false
|
||||
elif zs2 > zb2: continue
|
||||
if negHit:
|
||||
vect[0] = (neg.cx - x).toFloat
|
||||
vect[1] = (neg.cy - y).toFloat
|
||||
vect[2] = neg.cz.toFloat - zs2
|
||||
else:
|
||||
vect[0] = (x - pos.cx).toFloat
|
||||
vect[1] = (y - pos.cy).toFloat
|
||||
vect[2] = zb1 - pos.cz.toFloat
|
||||
vect.normalize()
|
||||
var s = dot(dir, vect)
|
||||
if s < 0: s = 0
|
||||
var lum = (255 * (s.pow(k) + amb) / (1 + amb)).toInt
|
||||
if lum < 0: lum = 0
|
||||
elif lum > 255: lum = 255
|
||||
result[x - deltaX, y - deltaY] = Luminance(lum)
|
||||
|
||||
#———————————————————————————————————————————————————————————————————————————————————————————————————
|
||||
|
||||
var dir: Vector = [float 20, -40, -10]
|
||||
dir.normalize()
|
||||
let pos = Sphere(cx: 0, cy: 0, cz: 0, r: 120)
|
||||
let neg = Sphere(cx: -90, cy: -90, cz: -30, r: 100)
|
||||
|
||||
let grayImage = deathStar(pos, neg, 1.5, 0.2, dir)
|
||||
|
||||
# Save to PNG. We convert to an RGB image then transform the pixels
|
||||
# in a sequence of bytes (actually a copy) in order to call "savePNG24".
|
||||
let rgbImage = grayImage.toImage
|
||||
var data = newSeqOfCap[byte](rgbImage.pixels.len * 3)
|
||||
for color in rgbImage.pixels:
|
||||
data.add([color.r, color.g, color.b])
|
||||
echo savePNG24("death_star.png", data, rgbImage.w, rgbImage.h)
|
||||
Loading…
Add table
Add a link
Reference in a new issue