Browse Source

playing around with shapes

Sebastian Kreisel 4 years ago
parent
commit
bdb7f4d81c
7 changed files with 304 additions and 31 deletions
  1. 2 2
      README
  2. 5 4
      TODO.txt
  3. 4 2
      run_compile.sh
  4. 27 22
      src/polygon.coffee
  5. 258 0
      src/test/grow/testgrowing.coffee
  6. 4 1
      src/test/spikyscene.coffee
  7. 4 0
      src/utils.coffee

+ 2 - 2
README

@@ -5,5 +5,5 @@ WHYILIKETREES
 -------------------------------------------------------------------------------
 (*) why i do like trees
 (*) not quite recent versions might be hosted on
-    http://elfeck.com/playwhyiliketrees but no guarantee
-(*) once in a while I might stream programming on https://twitch.tv/elfeck
+    http://elfeck.com/games/whyiliketrees but no guarantee
+(*) once in a while I might stream programming on https://twitch.tv/elfeck

+ 5 - 4
TODO.txt

@@ -1,10 +1,6 @@
 TODO
 =======================================
 
-(*) Fix the problem that after one call in moveOntoCircle the dir-vec
-    gets changed because the point moves from the line hence not going into if
-(*) Figure out why order is important for scaling: rotate then translate
-
 --
 Geometry
 --
@@ -27,3 +23,8 @@ Other
 --
 (*) Fonts and text rendering
 (*) Dependend Planes see Polygon.getPlane and stuff
+
+--
+Minor
+--
+(*) Figure out why order is important for scaling: rotate then translate

+ 4 - 2
run_compile.sh

@@ -3,9 +3,11 @@ if [ "$1" == "join" ]
 then
     coffee -j js/wilt.js -w -c \
 	   src/*.coffee \
-	   src/test/*.coffee
+	   src/test/*.coffee \
+	   src/test/grow/*.coffee
 else
     coffee -w -c -o js \
 	   src/*.coffee \
-	   src/test/*.coffee
+	   src/test/*.coffee \
+	   src/test/grow/*.coffee
 fi

+ 27 - 22
src/polygon.coffee

@@ -57,8 +57,6 @@ class window.Polygon
 
   rotateAroundLine: (line, angle) ->
     line.rotatePoint p, angle for p in @points
-    #@updateNormal()
-    #@updateConnNormals()
     return
 
   rotateAroundCentroid: (angle) ->
@@ -67,8 +65,6 @@ class window.Polygon
 
   translatePoints: (dir) ->
     p.addVec dir for p in @points
-    #@updateNormal()
-    #@updateConnNormals()
     return
 
   translateAlongNormal: (offset) ->
@@ -198,27 +194,39 @@ class window.Polygon
       diff = perc * (regu - distri[i])
       circle.baseline.rotatePoint(@points[i + 1], diff)
       distri[i + 1] -= diff
-    @updateConnNormals()
     return
 
-  movePointsOntoCircleAbs: (circle, offs) ->
+  #http://math.stackexchange.com/questions/1387507/
+  #move-point-onto-circle-outline-in-r3/1387554#1387554
+  movePointsOntoCircleAbs: (circle, offs, dir = null) ->
     for p in @points
       if not circle.isPointOn p
-        dir = p.subVecC(circle.baseline.base)
-        pp = null
-        if dir.isZeroVec() || Line.onLine @points
-          for q in @points
-            if not isFloatZero(q.distance(circle.baseline.base))
-              pp = q
-          v = pp.subVecC(circle.baseline.base)
-          plane = @getPlane()
-          dir = plane.orthogonalInPlane(v)
-        dir.normalize()
-        dist = circle.radius - p.subVecC(circle.baseline.base).length()
+        if dir == null
+          dir = p.subVecC(circle.baseline.base)
+          pp = null
+          if dir.isZeroVec() || Line.onLine @points
+            for q in @points
+              if not isFloatZero(q.distance(circle.baseline.base))
+                pp = q
+            v = pp.subVecC(circle.baseline.base)
+            plane = @getPlane()
+            dir = plane.orthogonalInPlane(v)
+          dir.normalize()
+          dist = circle.radius - p.subVecC(circle.baseline.base).length()
+        else
+          dir = dir.normalizeC()
+          if isFloatZero(circle.baseline.base.distance(p))
+            dist = circle.radius
+          else
+            l = circle.baseline.base.distance(p)
+            r = circle.radius
+            theta = Vec.angleBetween circle.baseline.base.subVecC(p), dir
+            #console.log "t: " + theta
+            #console.log "sin(t): " + Math.cos(theta)
+            dist = Math.sqrt(r * r - l * l * Math.pow(Math.sin(theta), 2)) +
+              l * Math.cos(theta)
         dist = Math.min dist, offs
         p.addVec(dir.multScalarC(dist))
-    @updateNormal()
-    @updateConnNormals()
     return
 
   regularizeAbs: (angle) ->
@@ -237,7 +245,6 @@ class window.Polygon
       diff = Math.max a, total if total <= 0
       circle.baseline.rotatePoint(@points[i + 1], diff)
       distri[i + 1] -= diff
-    @updateConnNormals()
     return
 
   movePointAlongCircleRel: (index, perc) ->
@@ -248,7 +255,6 @@ class window.Polygon
     circle = @getMinimalOutcircle()
     angle = distri[index] * perc
     circle.baseline.rotatePoint(@points[index], angle)
-    @updateConnNormals()
     return
 
   movePointAlongCircleAbs: (index, angle) ->
@@ -259,7 +265,6 @@ class window.Polygon
     circle = @getMinimalOutcircle()
     angle = Math.min(distri[index], angle)
     circle.baseline.rotatePoint(@points[index], angle)
-    @updateConnNormals()
     return
 
   getCircularAngleDistribution: () ->

+ 258 - 0
src/test/grow/testgrowing.coffee

@@ -0,0 +1,258 @@
+class window.TestGrowing
+
+  constructor: (@scene) ->
+    @uid = getuid()
+    @fillshader = @scene.fillshader
+    @lineshader = @scene.lineshader
+
+    @color = new Vec [1.0, 0.3, 0.3]
+    @offs = Vec.zeros 3
+
+    @n = 5
+
+  initGfx: ->
+    @scene.lineshader.addUniformGL @uid, "offs", @offs
+    window.camera.addToProgram @lineshader, @uid
+
+    @fillshader.addUniformGL @uid, "offs", @offs
+    @fillshader.addUniformGL @uid, "num_lights", new Vec([2])
+    window.camera.addToProgram @fillshader, @uid
+    @scene.attenuLight.addToProgram @fillshader, @uid
+    pl.addToProgram @fillshader, @uid for pl in @scene.plights
+
+
+class window.Simple extends TestGrowing
+
+  constructor: (scene) ->
+    super scene
+
+    @initGeom()
+    @initGfx()
+
+  initGeom: ->
+    @n = 10
+    @h = 15.0
+    @step = @h / @n
+    points = []
+    points.push new Vec([0, 0.01, 0], true)
+    points.push new Vec([rndBetween(-1, 1), @step, rndBetween(-1, 1)], true)
+    for i in [1..@n]
+      points.push @angledRndPoint(points[i])
+    @segs = LineSegment.connectPoints points
+    lines = []
+    lines.push s.getLine() for s in @segs
+    @polys = []
+    @polys.push Polygon.regularFromLine(new Line(
+      new Vec([0, 0.01, 0]),
+      new Vec([0, 1, 0])), @widthFun(0), 5)
+    for i in [1..lines.length-1]
+      @polys.push Polygon.regularFromLine lines[i], @widthFun(i), 5
+
+    @connpolys = []
+    for i in [0..@polys.length-2]
+      @connpolys = @connpolys.concat(
+        Polygon.connectPolygons @polys[i], @polys[i+1])
+    return
+
+  widthFun: (x) ->
+    yi = 2.5
+    a = yi / (@h * @h)
+    return a * Math.pow((x - @h), 2)
+
+  angleConstraint: (tangle, p1, p2) ->
+    return Vec.angleBetween(p1, p2) < tangle
+
+  angledRndPoint: (p1) ->
+    y = p1.y() + @step
+    okay = false
+    count = 0
+    vmax = new Vec [p1.x() + 1, p1.y(), p1.z() + 1]
+    tangle = 0.2 * Vec.angleBetween(p1, vmax)
+    #console.log "max angle: " + tangle
+    while not okay
+      x = rndBetween p1.x() - 1, p1.x() + 1
+      z = rndBetween p1.z() - 1, p1.z() + 1
+      p2 = new Vec [x, y, z], true
+      okay = @angleConstraint tangle, p1, p2
+      count++
+      if count > 100
+        okay = true
+        console.log "could not find point"
+    #console.log "found point after " + count
+    return p2
+
+  initGfx: ->
+    super()
+    lprims = []
+    lprims = lprims.concat s.gfxAddLineSeg @color for s in @segs
+
+    pprims = []
+    pprims = pprims.concat p.gfxAddFill @color for p in @polys
+
+    cprims = []
+    cprims = cprims.concat c.gfxAddFill @color for c in @connpolys
+
+    lds = new GeomData @uid, @lineshader, lprims, GL.LINES
+    #@scene.lineGeom.addData lds
+
+    pds = new GeomData @uid, @fillshader, pprims
+    #@scene.fillGeom.addData pds
+
+    cds = new GeomData @uid, @fillshader, cprims
+    @scene.fillGeom.addData cds
+    return
+
+  doLogic: (delta) ->
+    return
+
+#
+#
+# 
+class window.Circling extends TestGrowing
+
+  constructor: (scene) ->
+    super scene
+
+    @state = 0
+    @tacc = 0
+    @once = false
+
+    @initGeom()
+    @initGfx()
+
+  initGeom: ->
+    @baseline = new Line(new Vec([0, 0, 0]), new Vec([0, 0, 1]))
+    @basepoly = new Polygon([
+      new Vec([-3, 0, 0], true),
+      new Vec([3, 0, 0], true)])
+    @basepoly.normal = @baseline.dir.copy()
+
+  initGfx: ->
+    super()
+
+  updateGfx: ->
+    if not @baseds?
+      @baseprims = @basepoly.gfxAddFill @color
+      @baseds = new GeomData @uid, @fillshader, @baseprims
+      @scene.fillGeom.addData @baseds
+    else
+      @baseprims = @basepoly.gfxAddFill @color
+      @baseds.prims = @baseprims
+      @baseds.setModified()
+
+  doLogic: (delta) ->
+    @tacc += delta * 0.001
+    if @tacc > 1
+      @tacc = 0
+      @state++
+      @once = true
+
+    if @state == 1 && @once
+      @once = false
+      @basepoly.replicatePoint 0
+      ldir = @basepoly.points[0].subVecC(@basepoly.points[2])
+      @basepoly.points[1].addVec ldir.multScalar -0.1
+      @circ = @basepoly.getMinimalOutcircle()
+
+      cprims = @circ.gfxAddOutline 30, Vec.green()
+      cds = new GeomData @uid, @lineshader, cprims, GL.LINES
+      @scene.lineGeom.addData cds
+
+    if @state == 3 && @once
+      @once = false
+      @basepoly.replicatePoint 0
+      @updateGfx()
+
+    if @state == 1
+      @basepoly.movePointsOntoCircleAbs @circ, 0.123, new Vec([1, -1, 0])
+      circ = @basepoly.getMinimalOutcircle()
+      @updateGfx()
+
+    if @state >= 2
+      @basepoly.regularizeAbs 0.1 * Math.PI * 0.001 * delta
+      @baseds.setModified()
+
+#
+#
+# 
+class window.Spike extends TestGrowing
+
+  constructor: (scene) ->
+    super scene
+
+    @height = 15
+
+    @tacc = 0
+    @state = 0
+
+    @initGeom()
+    @initGfx()
+
+  initGeom: ->
+    @baseline = new Line(new Vec([0, 0.1, 0]), new Vec([0, 1, 0]))
+
+    @basepoly = Polygon.regularFromLine @baseline, @widthFun(@state), @n
+    @toppoly = new Polygon([new Vec([0, 0.1, 0], true)])
+
+    @intermPolys = [@basepoly, @toppoly]
+
+    @connpolys = []
+    return
+
+  initGfx: ->
+    super()
+
+    @baseprims = []
+    @baseprims = @baseprims.concat @basepoly.gfxAddFill @color
+
+    @baseds = new GeomData @uid, @fillshader, @baseprims
+    @connds = new GeomData @uid, @fillshader, @connprims
+
+    @reconnect()
+
+    @scene.fillGeom.addData @baseds
+    @scene.fillGeom.addData @connds
+    return
+
+  reconnect: ->
+    @connpolys = []
+    for i in [0..@intermPolys.length-2]
+      @connpolys = @connpolys.concat Polygon.connectPolygons(
+        @intermPolys[i], @intermPolys[i+1], -1)
+    @connprims = []
+    @connprims = @connprims.concat p.gfxAddFill @color for p in @connpolys
+    @connds.prims = @connprims
+    @connds.setModified()
+    return
+
+  angle = (Math.PI * 2) / (20 * 7)
+  doLogic: (delta) ->
+    @tacc += delta * 0.001
+    return if @state > @height
+    if @tacc > 1
+      @tacc = 0
+      @state++
+
+      newpoly = Polygon.regularFromLine(@baseline.shiftBaseC(@state),
+        @widthFun(@state), @n)
+      console.log @widthFun @state
+      newpoly.rotateAroundLine @baseline, angle * @state
+      @intermPolys.splice @intermPolys.length-1, 0, newpoly
+      @reconnect()
+
+    @toppoly.translatePoints @baseline.dir.multScalarC(delta * 0.001)
+    @toppoly.updateConnNormals()
+
+    #for p in @intermPolys
+      #p.rotateAroundLine @baseline, -0.001 * delta * Math.PI * 0.025
+      #p.updateNormal()
+    #for c in @connpolys
+      #c.rotateAroundLine @baseline, -0.001 * delta * Math.PI * 0.025
+      #c.updateNormal()
+    @baseds.setModified()
+    @connds.setModified()
+    return
+
+  widthFun: (x) ->
+    #return 1 + Math.pow(Math.E, -(x-2.1))
+    return 0.025 * Math.pow((x - 20), 2)

+ 4 - 1
src/test/spikyscene.coffee

@@ -28,10 +28,13 @@ class window.SpikyScene
     @entities = [
       new SpikyFloor(this),
       #new Spiky(this, new Vec([0, 0, 0]))
-      new Curly(this)
+      #new Curly(this)
       #new Growing(this)
       #new TestSpiky(this)
       #new SimpleTest(this)
+      new Spike(this)
+      #new Circling(this)
+      #new Simple(this)
     ]
 
   delegateDrawGL: ->

+ 4 - 0
src/utils.coffee

@@ -63,3 +63,7 @@ window.getShaderAttributes = (vertSrc) ->
 
 window.arrayEqual = (a, b) ->
   a.length is b.length and a.every (elem, i) -> elem is b[i]
+
+window.rndBetween = (a, b) ->
+  r = Math.random() * (b - a)
+  return r + a