require 'propane'

# Example to show how to use the VecMath library.
# ruby replacement for PVector. Also features
# the use each_cons, possibly a rare use for this
# ruby Enumerable method?
# 2010-03-22 - fjenett (last revised by monkstone 2016-03-26)
# now uses 'zip' and 'each', in place of a custom Array object
# with a 'one_of_each' method
# Drawolver: draw 2D & revolve 3D
class Drawolver < Propane::App
  attr_reader :drawing_mode, :points, :rot_x, :rot_y, :vertices

  def setup
    size 1024, 768, P3D
    frame_rate 30
    reset_scene
  end

  def draw
    background 0
    unless drawing_mode
      translate(width / 2, height / 2)
      rotate_x rot_x
      rotate_y rot_y
      @rot_x += 0.01
      @rot_y += 0.02
      translate(-width / 2, -height / 2)
    end
    no_fill
    stroke 255
    points.each_cons(2) { |ps, pe| line ps.x, ps.y, pe.x, pe.y }
    return if drawing_mode
    stroke 125
    fill 120
    lights
    ambient_light 120, 120, 120
    vertices.each_cons(2) do |r1, r2|
      begin_shape(TRIANGLE_STRIP)
      r1.zip(r2).each do |v1, v2|
        vertex v1.x, v1.y, v1.z
        vertex v2.x, v2.y, v2.z
      end
      end_shape
    end
  end

  def reset_scene
    @drawing_mode = true
    @points = []
    @rot_x = 0.0
    @rot_y = 0.0
  end

  def mouse_pressed
    reset_scene
    points << Vec3D.new(mouse_x, mouse_y)
  end

  def mouse_dragged
    points << Vec3D.new(mouse_x, mouse_y)
  end

  def mouse_released
    points << Vec3D.new(mouse_x, mouse_y)
    recalculate_shape
  end

  def recalculate_shape
    @vertices = []
    points.each_cons(2) do |ps, _pe|
      b = points.last - points.first
      # len = b.mag
      b.normalize!
      a = ps - points.first
      dot = a.dot b
      b *= dot
      normal = points.first + b
      c = ps - normal
      # nlen = c.mag
      vertices << []
      (0..TAU).step(PI / 15) do |ang|
        e = normal + c * cos(ang)
        e.z = c.mag * sin(ang)
        vertices.last << e
      end
    end
    @drawing_mode = false
  end
end

Drawolver.new title: 'Drawolver'