added slick2D rendering

This commit is contained in:
masongreen 2009-07-13 22:34:59 -04:00
parent 236155e6ed
commit 89866779da
4 changed files with 89 additions and 117 deletions

View File

@ -30,9 +30,93 @@
*/ */
package org.poly2tri package org.poly2tri
// Based on Raimund Seidel's paper "A simple and fast incremental randomized
// algorithm for computing trapezoidal decompositions and for triangulating polygons"
// See also: "Computational Geometry", 3rd edition, by Mark de Berg et al, Chapter 6.2
// "Computational Geometry in C", 2nd edition, by Joseph O'Rourke
import org.newdawn.slick.{BasicGame, GameContainer, Graphics, Color, AppGameContainer}
import org.newdawn.slick.geom.Polygon
import collection.jcl.ArrayList
// TODO: Lots of documentation!
object Poly2Tri { object Poly2Tri {
def main(args: Array[String]) { def main(args: Array[String]) {
val container = new AppGameContainer(new Poly2TriDemo())
container.setDisplayMode(800,600,false)
container.start()
} }
}
class Poly2TriDemo extends BasicGame("Poly2Tri") {
var tesselator: Triangulator = null
var quit = false
def init(container: GameContainer) {
testTesselator
}
def update(gc: GameContainer, delta: Int) {
if(quit) gc exit
}
def render(container: GameContainer, g: Graphics) {
val red = new Color(1f,0.0f,0.0f)
val blue = new Color(0f, 0f, 1f)
val green = new Color(0f, 1f, 0f)
//for(t <- tesselator.allTrapezoids) {
for(t <- tesselator.trapezoids) {
val polygon = new Polygon()
for(v <- t.vertices) {
polygon.addPoint(v.x, v.y)
}
//g.setColor(red)
//g.draw(polygon)
}
for(x <- tesselator.xMonoPoly) {
var t = x.triangles
for(t <- x.triangles) {
val triangle = new Polygon()
t.foreach(p => triangle.addPoint(p.x, p.y))
g.setColor(green)
g.draw(triangle)
}
}
}
override def keyPressed(key:Int, c:Char) {
if(key == 1) quit = true
}
def testTesselator {
val scale = 1.0f
val p1 = new Point(100,300)*scale
val p2 = new Point(400,500)*scale
val p3 = new Point(260,200)*scale
val p4 = new Point(600,175)*scale
val p5 = new Point(400,300)*scale
val p6 = new Point(650,250)*scale
val segments = new ArrayList[Segment]
segments += new Segment(p1, p2)
segments += new Segment(p3, p4)
segments += new Segment(p1, p3)
segments += new Segment(p5, p2)
segments += new Segment(p5, p6)
segments += new Segment(p4, p6)
tesselator = new Triangulator(segments)
tesselator.process
}
} }

View File

@ -40,7 +40,7 @@ class TrapezoidalMap {
// Trapezoid associated array // Trapezoid associated array
val map = HashSet.empty[Trapezoid] val map = HashSet.empty[Trapezoid]
// AABB margin // AABB margin
var margin = 2f var margin = 20f
// Bottom segment that spans multiple trapezoids // Bottom segment that spans multiple trapezoids
private var bCross: Segment = null private var bCross: Segment = null

View File

@ -33,8 +33,6 @@ package org.poly2tri
import collection.jcl.ArrayList import collection.jcl.ArrayList
import scala.collection.mutable.{HashSet, Map, Stack, ListBuffer} import scala.collection.mutable.{HashSet, Map, Stack, ListBuffer}
import utils.Random
// Based on Raimund Seidel's paper "A simple and fast incremental randomized // Based on Raimund Seidel's paper "A simple and fast incremental randomized
// algorithm for computing trapezoidal decompositions and for triangulating polygons" // algorithm for computing trapezoidal decompositions and for triangulating polygons"
class Triangulator(var segments: ArrayList[Segment]) { class Triangulator(var segments: ArrayList[Segment]) {
@ -144,6 +142,7 @@ class Triangulator(var segments: ArrayList[Segment]) {
segs += s segs += s
} }
} }
// This is actually important: See Seidel's paper
Random.shuffle(segs) Random.shuffle(segs)
} }
} }

View File

@ -1,124 +1,13 @@
/* Poly2Tri
* Copyright (c) 2009, Mason Green
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.poly2tri package org.poly2tri
import collection.jcl.ArrayList import collection.jcl.ArrayList
import org.villane.vecmath.Vector2
object Util {
final def rotateLeft90(v:Vector2) = new Vector2( -v.y, v.x )
final def rotateRight90(v:Vector2) = new Vector2(v.y, -v.x )
final def rotate(v:Vector2, angle:Float) = {
val cos = Math.cos(angle).asInstanceOf[Float]
val sin = Math.sin(angle).asInstanceOf[Float]
val u = new Vector2((cos * v.x) - (sin * v.y), (cos * v.y) + (sin * v.x))
u
}
final def clamp(a: Float, low: Float, high: Float) =
if (a < low) low
else if (a > high) high
else a
final def left(a: Vector2, b: Vector2, c: Vector2) =
((b.x - a.x)*(c.y - a.y) - (c.x - a.x)*(b.y - a.y) > 0)
/** Melkman's Algorithm
* www.ams.sunysb.edu/~jsbm/courses/345/melkman.pdf
* Return a convex hull in ccw order
*/
def hull(V: Array[Vector2]) = {
val n = V.length
val D = new Array[Vector2](2 * n + 1)
var bot = n - 2
var top = bot + 3
D(bot) = V(2)
D(top) = V(2)
if (left(V(0), V(1), V(2))) {
D(bot+1) = V(0)
D(bot+2) = V(1)
} else {
D(bot+1) = V(1)
D(bot+2) = V(0)
}
var i = 3
while(i < n) {
while (left(D(bot), D(bot+1), V(i)) && left(D(top-1), D(top), V(i))) {
i += 1
}
while (!left(D(top-1), D(top), V(i))) top -= 1
top += 1; D(top) = V(i)
while (!left(D(bot), D(bot+1), V(i))) bot += 1
bot -= 1; D(bot) = V(i)
i += 1
}
val H = new Array[Vector2](top - bot)
var h = 0
while(h < (top - bot)) {
H(h) = D(bot + h)
h += 1
}
H
}
def svgToWorld(points: Array[Float], scale: Float) = {
val verts = new Array[Vector2](points.length/2)
var i = 0
while(i < verts.length) {
verts(i) = worldPoint(points(i*2), points(i*2+1), scale)
i += 1
}
verts
}
def worldPoint(x: Float, y: Float, scale: Float) = {
val p = Vector2(x*scale, y*scale)
p
}
}
/** The object <code>Random</code> offers a default implementation /** The object <code>Random</code> offers a default implementation
* of scala.util.Random and random-related convenience methods. * of scala.util.Random and random-related convenience methods.
* *
* @since 2.8 * @since 2.8
* From Scala 2.8 standard library
*/ */
object Random extends scala.util.Random { object Random extends scala.util.Random {