Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 12th, 2012  |  syntax: None  |  size: 2.63 KB  |  hits: 12  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. package main
  2.  
  3. import (
  4.         "fmt"
  5.         "math/rand"
  6.         "math"
  7.         "bufio"
  8.         "os"
  9. )
  10.  
  11. const PI = 3.1415926535
  12.  
  13. type Vec2 struct {
  14.         X, Y float32
  15. }
  16.  
  17. func lerp(a, b, v float32) float32 {
  18.         return a * (1 - v) + b * v
  19. }
  20.  
  21. func smooth(v float32) float32 {
  22.         return v * v * (3 - 2 * v)
  23. }
  24.  
  25. func random_gradient(r *rand.Rand) Vec2 {
  26.         v := r.Float64() * PI * 2
  27.         return Vec2{
  28.                 float32(math.Cos(v)),
  29.                 float32(math.Sin(v)),
  30.         }
  31. }
  32.  
  33. func gradient(orig, grad, p Vec2) float32 {
  34.         sp := Vec2{p.X - orig.X, p.Y - orig.Y}
  35.         return grad.X * sp.X + grad.Y * sp.Y
  36. }
  37.  
  38. type Noise2DContext struct {
  39.         rgradients []Vec2
  40.         permutations []int
  41.         gradients [4]Vec2
  42.         origins [4]Vec2
  43. }
  44.  
  45. func NewNoise2DContext(seed int) *Noise2DContext {
  46.         rnd := rand.New(rand.NewSource(int64(seed)))
  47.  
  48.         n2d := new(Noise2DContext)
  49.         n2d.rgradients = make([]Vec2, 256)
  50.         n2d.permutations = rand.Perm(256)
  51.         for i := range n2d.rgradients {
  52.                 n2d.rgradients[i] = random_gradient(rnd)
  53.         }
  54.  
  55.         return n2d
  56. }
  57.  
  58. func (n2d *Noise2DContext) get_gradient(x, y int) Vec2 {
  59.         idx := n2d.permutations[x & 255] + n2d.permutations[y & 255]
  60.         return n2d.rgradients[idx & 255]
  61. }
  62.  
  63. func (n2d *Noise2DContext) get_gradients(x, y float32) {
  64.         x0f := math.Floor(float64(x))
  65.         y0f := math.Floor(float64(y))
  66.         x0 := int(x0f)
  67.         y0 := int(y0f)
  68.         x1 := x0 + 1
  69.         y1 := y0 + 1
  70.  
  71.         n2d.gradients[0] = n2d.get_gradient(x0, y0)
  72.         n2d.gradients[1] = n2d.get_gradient(x1, y0)
  73.         n2d.gradients[2] = n2d.get_gradient(x0, y1)
  74.         n2d.gradients[3] = n2d.get_gradient(x1, y1)
  75.  
  76.         n2d.origins[0] = Vec2{float32(x0f + 0.0), float32(y0f + 0.0)}
  77.         n2d.origins[1] = Vec2{float32(x0f + 1.0), float32(y0f + 0.0)}
  78.         n2d.origins[2] = Vec2{float32(x0f + 0.0), float32(y0f + 1.0)}
  79.         n2d.origins[3] = Vec2{float32(x0f + 1.0), float32(y0f + 1.0)}
  80. }
  81.  
  82. func (n2d *Noise2DContext) Get(x, y float32) float32 {
  83.         p := Vec2{x, y}
  84.         n2d.get_gradients(x, y)
  85.         v0 := gradient(n2d.origins[0], n2d.gradients[0], p)
  86.         v1 := gradient(n2d.origins[1], n2d.gradients[1], p)
  87.         v2 := gradient(n2d.origins[2], n2d.gradients[2], p)
  88.         v3 := gradient(n2d.origins[3], n2d.gradients[3], p)
  89.         fx := smooth(x - n2d.origins[0].X)
  90.         vx0 := lerp(v0, v1, fx)
  91.         vx1 := lerp(v2, v3, fx)
  92.         fy := smooth(y - n2d.origins[0].Y)
  93.         return lerp(vx0, vx1, fy)
  94. }
  95.  
  96. func main() {
  97.         symbols := []string{" ", "░", "▒", "▓", "█", "█"}
  98.         pixels := make([]float32, 256*256)
  99.         n2d := NewNoise2DContext(0)
  100.         for i := 0; i < 100; i++ {
  101.                 for y := 0; y < 256; y++ {
  102.                         for x := 0; x < 256; x++ {
  103.                                 v := n2d.Get(float32(x) * 0.1,
  104.                                              float32(y) * 0.1)
  105.                                 v = v * 0.5 + 0.5
  106.                                 pixels[y*256+x] = v
  107.                         }
  108.                 }
  109.         }
  110.  
  111.         out := bufio.NewWriter(os.Stdout)
  112.         for y := 0; y < 256; y++ {
  113.                 for x := 0; x < 256; x++ {
  114.                         fmt.Fprint(out, symbols[int(pixels[y*256+x] / 0.2)])
  115.                 }
  116.                 fmt.Fprintln(out)
  117.         }
  118.         out.Flush()
  119. }