Speedup the mesh simplification
Change EdgeSet to use LinkedHashSet for better iteration, potentially. Map polygon points to existing vertices to reduce unnecessary vertex duplication Attempt to merge overlapping edges initially before doing anything else when simplifying Use tree sets instead of priority queues for constant time poll Split intersection calculation method into two separate methods Rework which edges are actively within the scan zone to reduce the amount of edges to check when looking for intersections. This should help make the entire algorithm closer to O(nlogn) Removed intersection classes Added method to resolve only collinear edges around a vertex Added method to resolve edge intersections directly from the edge, rather than the positive side Added simple Y check to see if two edges can even intersect Added method to calculate absolute vector Added test plane by default to MeshingTest2(the plane viewer)
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
package com.aaaaahhhhhhh.bananapuncher714.mesh;
|
package com.aaaaahhhhhhh.bananapuncher714.mesh;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A set for easily checking if a set contains/does not contain a half-edge or its sym.
|
* A set for easily checking if a set contains/does not contain a half-edge or its sym.
|
||||||
*
|
*
|
||||||
* @author BananaPuncher714
|
* @author BananaPuncher714
|
||||||
*/
|
*/
|
||||||
public class EdgeSet extends HashSet< HalfEdge > {
|
public class EdgeSet extends LinkedHashSet< HalfEdge > {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -9,12 +9,9 @@ import java.util.HashMap;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.PriorityQueue;
|
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
@@ -81,6 +78,9 @@ public class Mesh< T extends Region > {
|
|||||||
public static final double ANGLE_TOLERANCE = Math.toRadians( 1e-10 );
|
public static final double ANGLE_TOLERANCE = Math.toRadians( 1e-10 );
|
||||||
public static final double CROSS_TOLERANCE = Math.sin( ANGLE_TOLERANCE );
|
public static final double CROSS_TOLERANCE = Math.sin( ANGLE_TOLERANCE );
|
||||||
|
|
||||||
|
// Point to vertex map, to avoid duplicating vertices when inserting polygons
|
||||||
|
protected Map< Point, Vertex > vertexMap = new HashMap< Point, Vertex >();
|
||||||
|
|
||||||
// All points in the graph
|
// All points in the graph
|
||||||
protected Collection< Vertex > vertices = new ArrayDeque< Vertex >();
|
protected Collection< Vertex > vertices = new ArrayDeque< Vertex >();
|
||||||
// All rules associated with a given half edge
|
// All rules associated with a given half edge
|
||||||
@@ -121,14 +121,19 @@ public class Mesh< T extends Region > {
|
|||||||
} else {
|
} else {
|
||||||
edge = edge.split();
|
edge = edge.split();
|
||||||
}
|
}
|
||||||
|
|
||||||
edge.getOrigin().setPosition( new Vector2d( point ) );
|
final Vertex vertex = vertexMap.get( point );
|
||||||
|
if ( vertex != null ) {
|
||||||
|
HalfEdge.splice( edge.getPrev(), vertex.getEdge() );
|
||||||
|
} else {
|
||||||
|
edge.getOrigin().setPosition( new Vector2d( point ) );
|
||||||
|
|
||||||
|
vertices.add( edge.getOrigin() );
|
||||||
|
}
|
||||||
|
|
||||||
rules.put( edge, rule );
|
rules.put( edge, rule );
|
||||||
rules.put( edge.getSym(), rule.inverse() );
|
rules.put( edge.getSym(), rule.inverse() );
|
||||||
|
|
||||||
vertices.add( edge.getOrigin() );
|
|
||||||
|
|
||||||
state = MeshState.DIRTY;
|
state = MeshState.DIRTY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,6 +184,7 @@ public class Mesh< T extends Region > {
|
|||||||
vertices.clear();
|
vertices.clear();
|
||||||
rules.clear();
|
rules.clear();
|
||||||
interiorEdges.clear();
|
interiorEdges.clear();
|
||||||
|
vertexMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mesh< T > copyOf() {
|
public Mesh< T > copyOf() {
|
||||||
@@ -244,7 +250,7 @@ public class Mesh< T extends Region > {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
copy.vertices.parallelStream().forEach( v -> sort( v ) );
|
copy.vertices.parallelStream().forEach( v -> { sort( v ); copy.vertexMap.put( v.getPosition(), v ); } );
|
||||||
copy.state = state;
|
copy.state = state;
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
@@ -282,9 +288,24 @@ public class Mesh< T extends Region > {
|
|||||||
* will be simple, since there can be holes.
|
* will be simple, since there can be holes.
|
||||||
*/
|
*/
|
||||||
public void simplify() {
|
public void simplify() {
|
||||||
// Create a queue and insert all vertices in O(nlogn) time.
|
// Create a sorted set with duplicate vertices allowed
|
||||||
final Queue< Vertex > queue = new PriorityQueue< Vertex >( Mesh::compare );
|
// Insert all vertices in O(nlogn) time.
|
||||||
queue.addAll( vertices );
|
// Use a treeset instead of a priority queue for constant time poll first
|
||||||
|
final TreeSet< Vertex > vertexSet = new TreeSet< Vertex >( ( a, b ) -> {
|
||||||
|
final int compare = compare( a, b );
|
||||||
|
if ( compare == 0 ) {
|
||||||
|
return Integer.compare( a.hashCode(), b.hashCode() );
|
||||||
|
} else {
|
||||||
|
return compare;
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
vertexSet.addAll( vertices );
|
||||||
|
|
||||||
|
// Need to update vertices if using the vertex map when inserting polygons
|
||||||
|
vertexSet.parallelStream().forEach( Vertex::update );
|
||||||
|
|
||||||
|
// Do a quick merging of edges so we don't have to deal with them later
|
||||||
|
mergeOverlappingEdges( vertexSet );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* As we iterate through each vertex, there are certain operations
|
* As we iterate through each vertex, there are certain operations
|
||||||
@@ -299,35 +320,31 @@ public class Mesh< T extends Region > {
|
|||||||
// This set contains the non-redundant vertices.
|
// This set contains the non-redundant vertices.
|
||||||
final Set< Vertex > scannedVertices = new HashSet< Vertex >();
|
final Set< Vertex > scannedVertices = new HashSet< Vertex >();
|
||||||
|
|
||||||
Vertex vertex;
|
while ( !vertexSet.isEmpty() ) {
|
||||||
while ( ( vertex = queue.poll() ) != null ) {
|
final Vertex vertex = vertexSet.pollFirst();
|
||||||
final Vector2d pos = vertex.getPosition();
|
final Vector2d pos = vertex.getPosition();
|
||||||
{
|
|
||||||
final List< Vertex > addBack = new LinkedList< Vertex >();
|
// We must poll and add back later since priority queues are not
|
||||||
Vertex other;
|
// sorted, so an iterator over its elements would not guarantee
|
||||||
// We must poll and add back later since priority queues are not
|
// the correct ordering unless we poll it.
|
||||||
// sorted, so an iterator over its elements would not guarantee
|
for ( final Iterator< Vertex > it = vertexSet.iterator(); it.hasNext(); ) {
|
||||||
// the correct ordering unless we poll it.
|
final Vertex other = it.next();
|
||||||
while ( ( other = queue.poll() ) != null ) {
|
final Vector2d otherPos = other.getPosition();
|
||||||
final Vector2d otherPos = other.getPosition();
|
|
||||||
|
// Once the vertex scanned is past the tolerance in the X direction,
|
||||||
// Once the vertex scanned is past the tolerance in the X direction,
|
// we know there are no more vertices which can be merged with the
|
||||||
// we know there are no more vertices which can be merged with the
|
// current vertex.
|
||||||
// current vertex.
|
if ( compareX( otherPos, pos ) > VERTEX_TOLERANCE ) {
|
||||||
if ( compareX( otherPos, pos ) > VERTEX_TOLERANCE ) {
|
break;
|
||||||
addBack.add( other );
|
}
|
||||||
break;
|
|
||||||
}
|
// Check if the vertices are close enough that they can
|
||||||
|
// be considered "the same"
|
||||||
// Check if the vertices are close enough that they can
|
if ( isSimilar( pos, otherPos ) ) {
|
||||||
// be considered "the same"
|
HalfEdge.splice( vertex.getEdge(), other.getEdge() );
|
||||||
if ( isSimilar( pos, otherPos ) ) {
|
|
||||||
HalfEdge.splice( vertex.getEdge(), other.getEdge() );
|
it.remove();
|
||||||
} else {
|
|
||||||
addBack.add( other );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
queue.addAll( addBack );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -358,14 +375,8 @@ public class Mesh< T extends Region > {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all edges from this vertex if they do not already exist in
|
|
||||||
// the set of scanned edges
|
|
||||||
for ( final HalfEdge edge : vertex ) {
|
|
||||||
scannedEdges.add( edge );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add edges that belong to vertices up to VERTEX_TOLERANCE away in the X direction
|
// Add edges that belong to vertices up to VERTEX_TOLERANCE away in the X direction
|
||||||
for ( final Iterator< Vertex > it = queue.iterator(); it.hasNext(); ) {
|
for ( final Iterator< Vertex > it = vertexSet.iterator(); it.hasNext(); ) {
|
||||||
final Vertex other = it.next();
|
final Vertex other = it.next();
|
||||||
final Vector2d otherPos = other.getPosition();
|
final Vector2d otherPos = other.getPosition();
|
||||||
|
|
||||||
@@ -377,28 +388,36 @@ public class Mesh< T extends Region > {
|
|||||||
// horizontally onto the exact same x position as this vertex.
|
// horizontally onto the exact same x position as this vertex.
|
||||||
// It saves us from having fuzzy errors in the future.
|
// It saves us from having fuzzy errors in the future.
|
||||||
otherPos.setX( pos.getX() );
|
otherPos.setX( pos.getX() );
|
||||||
|
|
||||||
for ( final HalfEdge edge : other ) {
|
|
||||||
scannedEdges.add( edge );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update all edges this vertex is connected to for consistency
|
// Update all edges this vertex is connected to for consistency
|
||||||
vertex.update();
|
vertex.update();
|
||||||
|
|
||||||
// Merge any vertices with edges that they may be on
|
// Merge any vertices that are on edges
|
||||||
resolveVertexIntersections( scannedEdges, vertex );
|
resolveVertexIntersections( scannedEdges, vertex );
|
||||||
|
|
||||||
|
// Remove any collinear edges attached to this vertex
|
||||||
|
resolveCollinearEdges( scannedEdges, vertex );
|
||||||
|
|
||||||
|
// Remove any intersections with edges from other vertices
|
||||||
for ( final HalfEdge edge : vertex ) {
|
for ( final HalfEdge edge : vertex ) {
|
||||||
// Resolve any intersections belonging to this edge which are still
|
// Resolve any intersections belonging to this edge which are still
|
||||||
// being scanned
|
// being scanned, but only if it's a new edge
|
||||||
if ( scannedEdges.contains( edge ) ) {
|
if ( !scannedEdges.contains( edge ) && !scannedVertices.contains( edge.getDest() ) ) {
|
||||||
resolveEdgeIntersections( queue, scannedEdges, edge );
|
resolveEdgeIntersections( vertexSet, scannedEdges, edge );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Consider this vertex "scanned"
|
||||||
|
scannedVertices.add( vertex );
|
||||||
|
|
||||||
// Remove all edges from previously scanned vertices that are no longer useful
|
// Remove all edges from previously scanned vertices that are no longer useful
|
||||||
for ( final HalfEdge edge : vertex ) {
|
for ( final HalfEdge edge : vertex ) {
|
||||||
|
if ( vertex == edge.getDest() ) {
|
||||||
|
// TODO Remove this
|
||||||
|
throw new IllegalStateException( "Zero length edge!" );
|
||||||
|
}
|
||||||
|
|
||||||
if ( scannedVertices.contains( edge.getDest() ) ) {
|
if ( scannedVertices.contains( edge.getDest() ) ) {
|
||||||
/*
|
/*
|
||||||
* Remove the half edge and it's sym if the destination
|
* Remove the half edge and it's sym if the destination
|
||||||
@@ -412,13 +431,16 @@ public class Mesh< T extends Region > {
|
|||||||
// TODO Remove this
|
// TODO Remove this
|
||||||
throw new IllegalStateException( "Tried to remove an invalid edge!" );
|
throw new IllegalStateException( "Tried to remove an invalid edge!" );
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
scannedEdges.add( edge );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scannedVertices.add( vertex );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mergeOverlappingEdges( scannedVertices );
|
mergeOverlappingEdges( scannedVertices );
|
||||||
|
|
||||||
|
scannedVertices.parallelStream().forEach( Mesh::sort );
|
||||||
|
|
||||||
// Update the list of vertices with our new updated list of vertices
|
// Update the list of vertices with our new updated list of vertices
|
||||||
vertices = scannedVertices;
|
vertices = scannedVertices;
|
||||||
|
|
||||||
@@ -446,7 +468,7 @@ public class Mesh< T extends Region > {
|
|||||||
* @param scannedEdges
|
* @param scannedEdges
|
||||||
* @param vertex
|
* @param vertex
|
||||||
*/
|
*/
|
||||||
private void resolveVertexIntersections( final EdgeSet scannedEdges, final Vertex vertex ) {
|
private Collection< HalfEdge > resolveVertexIntersections( final EdgeSet scannedEdges, final Vertex vertex ) {
|
||||||
// Split any edges passing through vertex, which do not include
|
// Split any edges passing through vertex, which do not include
|
||||||
// the vertex as the origin or destination
|
// the vertex as the origin or destination
|
||||||
final Vector2d v = vertex.getPosition();
|
final Vector2d v = vertex.getPosition();
|
||||||
@@ -455,6 +477,8 @@ public class Mesh< T extends Region > {
|
|||||||
final Vector2d a = edge.getOrigin().getPosition();
|
final Vector2d a = edge.getOrigin().getPosition();
|
||||||
final Vector2d b = edge.getDest().getPosition();
|
final Vector2d b = edge.getDest().getPosition();
|
||||||
|
|
||||||
|
// TODO Can parallelize finding the edges, then do the merging sequentially afterwards
|
||||||
|
|
||||||
if ( v == a || v == b ) {
|
if ( v == a || v == b ) {
|
||||||
// Skip if this edge
|
// Skip if this edge
|
||||||
continue;
|
continue;
|
||||||
@@ -497,7 +521,67 @@ public class Mesh< T extends Region > {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scannedEdges.addAll( toInsert );
|
|
||||||
|
return toInsert;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resolveCollinearEdges( final EdgeSet scannedEdges, final Vertex vertex ) {
|
||||||
|
final Collection< HalfEdge > checked = new HashSet< HalfEdge >();
|
||||||
|
for ( final HalfEdge edge : vertex ) {
|
||||||
|
if ( scannedEdges.contains( edge ) ) {
|
||||||
|
checked.add( edge );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assume a and b are both positive
|
||||||
|
// This assumes that if a and b are collinear, then they _must_ share
|
||||||
|
// the same origin, since we are traversing through the vertices
|
||||||
|
// starting with the smallest.
|
||||||
|
for ( final HalfEdge edge : vertex ) {
|
||||||
|
// Only check this edge if it is not already scanned
|
||||||
|
if ( checked.add( edge ) ) {
|
||||||
|
final Vector2d r = edge.toVector2d().normalize();
|
||||||
|
for ( final HalfEdge other : vertex ) {
|
||||||
|
if ( !checked.contains( other ) ) {
|
||||||
|
// Do not split edges that are pretty much equal, since they will get merged later
|
||||||
|
if ( !isSimilar( edge.getDest(), other.getDest() ) ) {
|
||||||
|
final Vector2d s = other.toVector2d().normalize();
|
||||||
|
final double angle = r.cross( s );
|
||||||
|
|
||||||
|
// Ignore edges that are not collinear
|
||||||
|
if ( Math.abs( angle ) <= CROSS_TOLERANCE ) {
|
||||||
|
|
||||||
|
HalfEdge shorter;
|
||||||
|
HalfEdge longer;
|
||||||
|
|
||||||
|
// Compare which edge is shorter
|
||||||
|
if ( r.lengthSquared() < s.lengthSquared() ) {
|
||||||
|
shorter = edge;
|
||||||
|
longer = other;
|
||||||
|
} else {
|
||||||
|
shorter = other;
|
||||||
|
longer = edge;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the winding rule for the split
|
||||||
|
final HalfEdge split = longer.split();
|
||||||
|
RegionRule< T > rule = rules.get( longer );
|
||||||
|
rules.put( split, rule );
|
||||||
|
rules.put( split.getSym(), rule.inverse() );
|
||||||
|
|
||||||
|
// Update the vertex for the split
|
||||||
|
final Vertex vert = shorter.getDest();
|
||||||
|
split.setOrigin( vert );
|
||||||
|
longer.getSym().setOrigin( vert );
|
||||||
|
|
||||||
|
// Splice the two together
|
||||||
|
HalfEdge.splice( shorter.getSym(), split );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -508,150 +592,93 @@ public class Mesh< T extends Region > {
|
|||||||
* @param edge
|
* @param edge
|
||||||
*/
|
*/
|
||||||
private void resolveEdgeIntersections( final Collection< Vertex > vertices, final EdgeSet scannedEdges, final HalfEdge edge ) {
|
private void resolveEdgeIntersections( final Collection< Vertex > vertices, final EdgeSet scannedEdges, final HalfEdge edge ) {
|
||||||
|
final Vector2d p = edge.getOrigin().getPosition();
|
||||||
|
final double edgeOriginY = p.getY();
|
||||||
|
|
||||||
|
// Recalculate these if the edge is split
|
||||||
|
double edgeDestY = edge.getDest().getPosition().getY();
|
||||||
|
Vector2d r = edge.toVector2d();
|
||||||
|
|
||||||
|
double edgeUpperY = Math.max( edgeOriginY, edgeDestY );
|
||||||
|
double edgeLowerY = Math.min( edgeOriginY, edgeDestY );
|
||||||
|
|
||||||
// Use the positive edge for finding the intersection
|
// Use the positive edge for finding the intersection
|
||||||
final HalfEdge positiveEdge = isPositive( edge ) ? edge : edge.getSym();
|
|
||||||
for ( HalfEdge other : scannedEdges ) {
|
for ( HalfEdge other : scannedEdges ) {
|
||||||
if ( !isPositive( other ) ) {
|
if ( edge == other || edge == other.getSym() ) {
|
||||||
other = other.getSym();
|
continue;
|
||||||
}
|
}
|
||||||
final Optional< Intersection > optInt = getIntersection( positiveEdge, other );
|
|
||||||
if ( optInt.isPresent() ) {
|
// Do simple Y axis check between the two edges to see if they overlap
|
||||||
final Intersection intersection = optInt.get();
|
{
|
||||||
if ( intersection instanceof IntersectionEdgeToEdge ) {
|
final double otherOriginY = other.getOrigin().getPosition().getY();
|
||||||
final IntersectionEdgeToEdge intEdge = ( IntersectionEdgeToEdge ) intersection;
|
final double otherDestY = other.getDest().getPosition().getY();
|
||||||
|
|
||||||
|
final double otherUpperY = Math.max( otherOriginY, otherDestY );
|
||||||
|
final double otherLowerY = Math.min( otherOriginY, otherDestY );
|
||||||
|
|
||||||
|
if ( !( edgeLowerY < otherUpperY && otherLowerY < edgeUpperY ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( edge.getOrigin() != other.getOrigin() && edge.getOrigin() != other.getDest() && !isSimilar( edge.getDest(), other.getDest() ) ) {
|
||||||
|
// Both edges may intersect somewhere in the middle
|
||||||
|
final Vector2d q = other.getOrigin().getPosition();
|
||||||
|
final Vector2d s = other.toVector2d();
|
||||||
|
|
||||||
|
final Vector2d pq = q.subtracted( p );
|
||||||
|
final double rs = r.cross( s );
|
||||||
|
final double pqr = pq.cross( r );
|
||||||
|
|
||||||
|
// Check if parallel
|
||||||
|
if ( rs != 0 ) {
|
||||||
|
// Calculate t and u
|
||||||
|
final double t = pq.cross( s ) / rs;
|
||||||
|
final double u = pqr / rs;
|
||||||
|
|
||||||
|
final double tTol = VERTEX_TOLERANCE / r.length();
|
||||||
|
final double uTol = VERTEX_TOLERANCE / s.length();
|
||||||
|
|
||||||
if ( positiveEdge.getDest() == other.getDest() ) {
|
// Do the line segments intersect
|
||||||
// TODO Remove this
|
// They should NOT intersect at their endpoints
|
||||||
throw new IllegalStateException( "Invalid intersection" );
|
if ( t > tTol && t < ( 1 - tTol ) && u > uTol && u < ( 1 - uTol ) ) {
|
||||||
|
// Calculate the point of intersection
|
||||||
|
final Vector2d intersection = r.multiplied( t ).add( p );
|
||||||
|
|
||||||
|
// Split the first edge
|
||||||
|
HalfEdge aSplit = edge.split();
|
||||||
|
RegionRule< T > aRule = rules.get( edge );
|
||||||
|
rules.put( aSplit, aRule );
|
||||||
|
rules.put( aSplit.getSym(), aRule.inverse() );
|
||||||
|
|
||||||
|
// Update the position
|
||||||
|
final Vertex aSplitOrigin = aSplit.getOrigin();
|
||||||
|
aSplitOrigin.setPosition( intersection );
|
||||||
|
|
||||||
|
// Split the other edge
|
||||||
|
HalfEdge bSplit = other.split();
|
||||||
|
RegionRule< T > bRule = rules.get( other );
|
||||||
|
rules.put( bSplit, bRule );
|
||||||
|
rules.put( bSplit.getSym(), bRule.inverse() );
|
||||||
|
|
||||||
|
// Splice the edges together into the same vertex
|
||||||
|
HalfEdge.splice( bSplit, aSplit );
|
||||||
|
|
||||||
|
aSplitOrigin.update();
|
||||||
|
|
||||||
|
vertices.add( aSplitOrigin );
|
||||||
|
|
||||||
|
// Recalculate the edge values
|
||||||
|
edgeDestY = intersection.getY();
|
||||||
|
r = edge.toVector2d();
|
||||||
|
edgeUpperY = Math.max( edgeOriginY, edgeDestY );
|
||||||
|
edgeLowerY = Math.min( edgeOriginY, edgeDestY );
|
||||||
}
|
}
|
||||||
|
|
||||||
final Vector2d point = intEdge.getPoint();
|
|
||||||
if ( isSimilar( point, other.getDest().getPosition() ) || isSimilar( point, positiveEdge.getDest().getPosition() ) ) {
|
|
||||||
// TODO Remove this
|
|
||||||
throw new IllegalStateException( "Invalid intersection point" );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split the first edge
|
|
||||||
HalfEdge aSplit = edge.split();
|
|
||||||
RegionRule< T > aRule = rules.get( edge );
|
|
||||||
rules.put( aSplit, aRule );
|
|
||||||
rules.put( aSplit.getSym(), aRule.inverse() );
|
|
||||||
|
|
||||||
// Update the position
|
|
||||||
final Vertex origin = aSplit.getOrigin();
|
|
||||||
origin.setPosition( point );
|
|
||||||
|
|
||||||
// Split the other edge
|
|
||||||
HalfEdge bSplit = other.split();
|
|
||||||
RegionRule< T > bRule = rules.get( other );
|
|
||||||
rules.put( bSplit, bRule );
|
|
||||||
rules.put( bSplit.getSym(), bRule.inverse() );
|
|
||||||
|
|
||||||
// Splice the edges together into the same vertex
|
|
||||||
HalfEdge.splice( bSplit, aSplit );
|
|
||||||
|
|
||||||
origin.update();
|
|
||||||
|
|
||||||
vertices.add( origin );
|
|
||||||
} else if ( intersection instanceof IntersectionCollinear ) {
|
|
||||||
final IntersectionCollinear intCol = ( IntersectionCollinear ) intersection;
|
|
||||||
|
|
||||||
final HalfEdge shorter = intCol.getShorterEdge();
|
|
||||||
HalfEdge longer = intCol.getLongerEdge();
|
|
||||||
|
|
||||||
// Use the original edge for splitting to preserve the order of
|
|
||||||
// edges around the current vertex
|
|
||||||
if ( longer == positiveEdge ) {
|
|
||||||
longer = edge;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the winding rule for the split
|
|
||||||
final HalfEdge split = longer.split();
|
|
||||||
RegionRule< T > rule = rules.get( longer );
|
|
||||||
rules.put( split, rule );
|
|
||||||
rules.put( split.getSym(), rule.inverse() );
|
|
||||||
|
|
||||||
// Update the vertex for the split
|
|
||||||
final Vertex vert = shorter.getDest();
|
|
||||||
split.setOrigin( vert );
|
|
||||||
longer.getSym().setOrigin( vert );
|
|
||||||
|
|
||||||
// Splice the two together
|
|
||||||
HalfEdge.splice( shorter.getSym(), split );
|
|
||||||
} else {
|
|
||||||
// TODO Remove this
|
|
||||||
throw new IllegalStateException( "Unknown intersection type" );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate the intersection for two edges
|
|
||||||
*
|
|
||||||
* @param a
|
|
||||||
* @param b
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static Optional< Intersection > getIntersection( HalfEdge a, HalfEdge b ) {
|
|
||||||
// Assume a and b are both positive
|
|
||||||
// This assumes that if a and b are collinear, then they _must_ share
|
|
||||||
// the same origin, since we are traversing through the vertices
|
|
||||||
// starting with the smallest.
|
|
||||||
if ( a.getOrigin() == b.getOrigin() ) {
|
|
||||||
// Do not split edges that are pretty much equal, since they will get merged later
|
|
||||||
if ( !isSimilar( a.getDest(), b.getDest() ) ) {
|
|
||||||
final Vector2d r = a.toVector2d().normalize();
|
|
||||||
final Vector2d s = b.toVector2d().normalize();
|
|
||||||
final double angle = r.cross( s );
|
|
||||||
|
|
||||||
// Ignore edges that are not collinear
|
|
||||||
if ( Math.abs( angle ) <= CROSS_TOLERANCE ) {
|
|
||||||
|
|
||||||
// Compare which edge is shorter
|
|
||||||
if ( r.lengthSquared() < s.lengthSquared() ) {
|
|
||||||
return Optional.of( new IntersectionCollinear( a, b ) );
|
|
||||||
} else {
|
|
||||||
return Optional.of( new IntersectionCollinear( b, a ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ( isSimilar( a.getOrigin(), b.getOrigin() ) ) {
|
|
||||||
// TODO Remove this
|
|
||||||
throw new IllegalArgumentException( "Vertex not merged!" );
|
|
||||||
} else if ( !isSimilar( a.getDest(), b.getDest() ) ) {
|
|
||||||
// Both edges may intersect somewhere in the middle
|
|
||||||
final Vector2d p = a.getOrigin().getPosition();
|
|
||||||
final Vector2d r = a.toVector2d();
|
|
||||||
final Vector2d q = b.getOrigin().getPosition();
|
|
||||||
final Vector2d s = b.toVector2d();
|
|
||||||
|
|
||||||
final Vector2d pq = q.subtracted( p );
|
|
||||||
final double pqr = pq.cross( r );
|
|
||||||
final double rs = r.cross( s );
|
|
||||||
|
|
||||||
// Check if parallel
|
|
||||||
if ( rs != 0 ) {
|
|
||||||
// Calculate t and u
|
|
||||||
final double t = pq.cross( s ) / rs;
|
|
||||||
final double u = pqr / rs;
|
|
||||||
|
|
||||||
final double tTol = VERTEX_TOLERANCE / r.length();
|
|
||||||
final double uTol = VERTEX_TOLERANCE / s.length();
|
|
||||||
|
|
||||||
// Do the line segments intersect
|
|
||||||
// They should NOT intersect at their endpoints
|
|
||||||
if ( t > tTol && t < ( 1 - tTol ) && u > uTol && u < ( 1 - uTol ) ) {
|
|
||||||
// Calculate the point of intersection
|
|
||||||
final Vector2d intersection = r.multiply( t ).add( p );
|
|
||||||
|
|
||||||
return Optional.of( new IntersectionEdgeToEdge( intersection ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The goal for this method is to sort vertices
|
* The goal for this method is to sort vertices
|
||||||
* and to ensure that edges with the same endpoint and
|
* and to ensure that edges with the same endpoint and
|
||||||
@@ -659,8 +686,6 @@ public class Mesh< T extends Region > {
|
|||||||
*/
|
*/
|
||||||
private void mergeOverlappingEdges( final Collection< Vertex > vertices ) {
|
private void mergeOverlappingEdges( final Collection< Vertex > vertices ) {
|
||||||
for ( final Vertex vertex : vertices ) {
|
for ( final Vertex vertex : vertices ) {
|
||||||
sort( vertex );
|
|
||||||
|
|
||||||
// Keep track of which ranges of edges are attached to which
|
// Keep track of which ranges of edges are attached to which
|
||||||
final Map< Vertex, Queue< HalfEdge > > ranges = new HashMap< Vertex, Queue< HalfEdge > >();
|
final Map< Vertex, Queue< HalfEdge > > ranges = new HashMap< Vertex, Queue< HalfEdge > >();
|
||||||
|
|
||||||
@@ -729,8 +754,15 @@ public class Mesh< T extends Region > {
|
|||||||
throw new IllegalStateException( "Mesh is not simplified!" );
|
throw new IllegalStateException( "Mesh is not simplified!" );
|
||||||
}
|
}
|
||||||
|
|
||||||
final Queue< Vertex > queue = new PriorityQueue< Vertex >( Mesh::compare );
|
final Collection< Vertex > vertexSet = new TreeSet< Vertex >( ( a, b ) -> {
|
||||||
queue.addAll( vertices );
|
final int compare = compare( a, b );
|
||||||
|
if ( compare == 0 ) {
|
||||||
|
return Integer.compare( a.hashCode(), b.hashCode() );
|
||||||
|
} else {
|
||||||
|
return compare;
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
vertexSet.addAll( vertices );
|
||||||
|
|
||||||
// Keep track of what regions belong to what edge
|
// Keep track of what regions belong to what edge
|
||||||
final Map< HalfEdge, T > regions = new HashMap< HalfEdge, T >();
|
final Map< HalfEdge, T > regions = new HashMap< HalfEdge, T >();
|
||||||
@@ -747,8 +779,7 @@ public class Mesh< T extends Region > {
|
|||||||
final Set< HalfEdge > toRemove = new HashSet< HalfEdge >();
|
final Set< HalfEdge > toRemove = new HashSet< HalfEdge >();
|
||||||
|
|
||||||
// Assume the edges on each vertex is already sorted
|
// Assume the edges on each vertex is already sorted
|
||||||
Vertex vertex;
|
for ( Vertex vertex : vertexSet ) {
|
||||||
while ( ( vertex = queue.poll() ) != null ) {
|
|
||||||
// Insert all edges into the edge set
|
// Insert all edges into the edge set
|
||||||
for ( final HalfEdge edge : vertex ) {
|
for ( final HalfEdge edge : vertex ) {
|
||||||
if ( !isPositive( edge ) ) {
|
if ( !isPositive( edge ) ) {
|
||||||
@@ -853,6 +884,9 @@ public class Mesh< T extends Region > {
|
|||||||
interiorEdges.addAll( interiorAboveEdges );
|
interiorEdges.addAll( interiorAboveEdges );
|
||||||
|
|
||||||
vertices = keep;
|
vertices = keep;
|
||||||
|
|
||||||
|
vertexMap.clear();
|
||||||
|
vertices.forEach( v -> vertexMap.put( v.getPosition(), v ) );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invariants:
|
* Invariants:
|
||||||
@@ -2760,7 +2794,7 @@ public class Mesh< T extends Region > {
|
|||||||
|
|
||||||
// Keep track of which edge to insert new edges for the given vertex
|
// Keep track of which edge to insert new edges for the given vertex
|
||||||
final Map< Vertex, HalfEdge > insertEdges = new HashMap< Vertex, HalfEdge >();
|
final Map< Vertex, HalfEdge > insertEdges = new HashMap< Vertex, HalfEdge >();
|
||||||
final Queue< HalfEdge > edges = new PriorityQueue< HalfEdge >( ( a, b ) -> {
|
final TreeSet< HalfEdge > edges = new TreeSet< HalfEdge >( ( a, b ) -> {
|
||||||
return compare( a.getOrigin(), b.getOrigin() );
|
return compare( a.getOrigin(), b.getOrigin() );
|
||||||
} );
|
} );
|
||||||
edges.addAll( polygon.getEdges() );
|
edges.addAll( polygon.getEdges() );
|
||||||
@@ -2768,12 +2802,12 @@ public class Mesh< T extends Region > {
|
|||||||
|
|
||||||
final Stack< HalfEdge > stack = new Stack< HalfEdge >();
|
final Stack< HalfEdge > stack = new Stack< HalfEdge >();
|
||||||
// Add the first two vertices/edges
|
// Add the first two vertices/edges
|
||||||
stack.add( edges.poll() );
|
stack.add( edges.pollFirst() );
|
||||||
stack.add( edges.poll() );
|
stack.add( edges.pollFirst() );
|
||||||
|
|
||||||
HalfEdge prev = stack.peek();
|
HalfEdge prev = stack.peek();
|
||||||
while ( edges.size() > 1 ) {
|
while ( edges.size() > 1 ) {
|
||||||
final HalfEdge edge = edges.poll();
|
final HalfEdge edge = edges.pollFirst();
|
||||||
|
|
||||||
final boolean isEdgePositive = isPositive( edge );
|
final boolean isEdgePositive = isPositive( edge );
|
||||||
if ( isEdgePositive ^ isPositive( stack.peek() ) ) {
|
if ( isEdgePositive ^ isPositive( stack.peek() ) ) {
|
||||||
@@ -2865,7 +2899,7 @@ public class Mesh< T extends Region > {
|
|||||||
// The last edge must be a negative edge, since
|
// The last edge must be a negative edge, since
|
||||||
// the last vertex must terminate the polygon and
|
// the last vertex must terminate the polygon and
|
||||||
// therefore have no right-going edges.
|
// therefore have no right-going edges.
|
||||||
final HalfEdge last = edges.poll();
|
final HalfEdge last = edges.pollFirst();
|
||||||
stack.pop();
|
stack.pop();
|
||||||
final boolean isPositive = isPositive( stack.peek() );
|
final boolean isPositive = isPositive( stack.peek() );
|
||||||
HalfEdge insertEdge = last;
|
HalfEdge insertEdge = last;
|
||||||
@@ -2999,48 +3033,6 @@ public class Mesh< T extends Region > {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Represents an intersection
|
|
||||||
*/
|
|
||||||
private static abstract class Intersection {
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When 2 edges both intersect somewhere in the middle
|
|
||||||
*/
|
|
||||||
private static class IntersectionEdgeToEdge extends Intersection {
|
|
||||||
private final Vector2d point;
|
|
||||||
|
|
||||||
IntersectionEdgeToEdge( Vector2d point ) {
|
|
||||||
this.point = point;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2d getPoint() {
|
|
||||||
return point;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When 2 edges are collinear, and do not share the same endpoint
|
|
||||||
*/
|
|
||||||
private static class IntersectionCollinear extends Intersection {
|
|
||||||
private final HalfEdge shorter;
|
|
||||||
private final HalfEdge longer;
|
|
||||||
|
|
||||||
IntersectionCollinear( HalfEdge shorter, HalfEdge longer ) {
|
|
||||||
this.shorter = shorter;
|
|
||||||
this.longer = longer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HalfEdge getShorterEdge() {
|
|
||||||
return shorter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HalfEdge getLongerEdge() {
|
|
||||||
return longer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class EdgePolygon {
|
private static class EdgePolygon {
|
||||||
private Set< HalfEdge > edges = new HashSet< HalfEdge >();
|
private Set< HalfEdge > edges = new HashSet< HalfEdge >();
|
||||||
private Set< Vertex > vertices = new HashSet< Vertex >();
|
private Set< Vertex > vertices = new HashSet< Vertex >();
|
||||||
|
|||||||
@@ -66,6 +66,17 @@ public class Vector2d extends Point {
|
|||||||
return add( this, o );
|
return add( this, o );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector2d absolute() {
|
||||||
|
x = Math.abs( x );
|
||||||
|
y = Math.abs( y );
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2d absoluteOf() {
|
||||||
|
return new Vector2d( Math.abs( x ), Math.abs( y ) );
|
||||||
|
}
|
||||||
|
|
||||||
public Vector2d subtract( double v ) {
|
public Vector2d subtract( double v ) {
|
||||||
x -= v;
|
x -= v;
|
||||||
y -= v;
|
y -= v;
|
||||||
|
|||||||
@@ -133,6 +133,9 @@ public class MeshingTest2 extends JPanel {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
final List< Plane > masterPlanes = new ArrayList< Plane >();
|
final List< Plane > masterPlanes = new ArrayList< Plane >();
|
||||||
|
System.out.println( "Adding test plane" );
|
||||||
|
masterPlanes.add( getTestPlane() );
|
||||||
|
|
||||||
System.out.println( "Chunk files: " + CHUNK_DIR.listFiles().length );
|
System.out.println( "Chunk files: " + CHUNK_DIR.listFiles().length );
|
||||||
int limit = 1;
|
int limit = 1;
|
||||||
for ( File file : CHUNK_DIR.listFiles() ) {
|
for ( File file : CHUNK_DIR.listFiles() ) {
|
||||||
@@ -144,12 +147,10 @@ public class MeshingTest2 extends JPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// final List< Plane > planes = mesh( new File( CHUNK_DIR, "world,-1,-1" ) );
|
// final List< Plane > planes = mesh( new File( CHUNK_DIR, "world,-10,-10" ) );
|
||||||
// masterPlanes.add( planes.get( 20 ) );
|
// masterPlanes.add( planes.get( 27 ) );
|
||||||
// masterPlanes.addAll( planes );
|
// masterPlanes.addAll( planes );
|
||||||
|
|
||||||
// masterPlanes.add( getTestPlane() );
|
|
||||||
|
|
||||||
SwingUtilities.invokeLater( new Runnable() {
|
SwingUtilities.invokeLater( new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -262,12 +263,19 @@ public class MeshingTest2 extends JPanel {
|
|||||||
System.out.println( "After simplify vertex count: " + mesh.getVertices().size() );
|
System.out.println( "After simplify vertex count: " + mesh.getVertices().size() );
|
||||||
System.out.println( "After simplify edge count: " + ( mesh.getEdgeCount() / 2 ) );
|
System.out.println( "After simplify edge count: " + ( mesh.getEdgeCount() / 2 ) );
|
||||||
|
|
||||||
mesh.generateRegions();
|
|
||||||
long end = System.currentTimeMillis();
|
|
||||||
|
|
||||||
data.vertices = mesh.getVertices();
|
data.vertices = mesh.getVertices();
|
||||||
data.edges = mesh.getEdges();
|
data.edges = mesh.getEdges();
|
||||||
|
|
||||||
|
try {
|
||||||
|
mesh.generateRegions();
|
||||||
|
|
||||||
|
data.vertices = mesh.getVertices();
|
||||||
|
data.edges = mesh.getEdges();
|
||||||
|
} catch ( Exception e ) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
long end = System.currentTimeMillis();
|
||||||
|
|
||||||
System.out.println( "After generating regions vertex count: " + mesh.getVertices().size() );
|
System.out.println( "After generating regions vertex count: " + mesh.getVertices().size() );
|
||||||
System.out.println( "After generating regions edge count: " + ( mesh.getEdgeCount() / 2 ) );
|
System.out.println( "After generating regions edge count: " + ( mesh.getEdgeCount() / 2 ) );
|
||||||
|
|
||||||
@@ -547,6 +555,9 @@ public class MeshingTest2 extends JPanel {
|
|||||||
private static Plane getTestPlane() {
|
private static Plane getTestPlane() {
|
||||||
final Plane plane = new Plane();
|
final Plane plane = new Plane();
|
||||||
|
|
||||||
|
plane.normal = new Vector( 0, 0, 1 );
|
||||||
|
plane.point = new Vector( 1, 0, 0 );
|
||||||
|
|
||||||
// plane.polygons.add( new Polygon( Arrays.asList(
|
// plane.polygons.add( new Polygon( Arrays.asList(
|
||||||
// new Point( 1, 0 ),
|
// new Point( 1, 0 ),
|
||||||
// new Point( 2, 1 ),
|
// new Point( 2, 1 ),
|
||||||
@@ -560,20 +571,75 @@ public class MeshingTest2 extends JPanel {
|
|||||||
// new Point( 0, 3 ),
|
// new Point( 0, 3 ),
|
||||||
// new Point( 1, 2 ),
|
// new Point( 1, 2 ),
|
||||||
// new Point( 0, 1 )
|
// new Point( 0, 1 )
|
||||||
|
// plane.polygons.add( new Polygon( Arrays.asList(
|
||||||
|
// new Point( 1, 0 ),
|
||||||
|
// new Point( 2, 1 ),
|
||||||
|
// new Point( 3, 0 ),
|
||||||
|
// new Point( 4, 1 ),
|
||||||
|
// new Point( 3, 2 ),
|
||||||
|
// new Point( 4, 3 ),
|
||||||
|
// new Point( 3, 4 ),
|
||||||
|
// new Point( 2, 3 ),
|
||||||
|
// new Point( 1, 4 ),
|
||||||
|
// new Point( 0, 3 ),
|
||||||
|
// new Point( 1, 2 ),
|
||||||
|
// new Point( 0, 1 )
|
||||||
|
// ) ) );
|
||||||
|
|
||||||
|
plane.polygons.add( new Polygon( Arrays.asList(
|
||||||
|
new Point( -1, -1 ),
|
||||||
|
new Point( 1, -1 ),
|
||||||
|
new Point( 1, 1 ),
|
||||||
|
new Point( -1, 1 )
|
||||||
|
) ) );
|
||||||
|
plane.polygons.add( new Polygon( Arrays.asList(
|
||||||
|
new Point( -1, -1 ),
|
||||||
|
new Point( 1, -1 ),
|
||||||
|
new Point( 1, 1 ),
|
||||||
|
new Point( -1, 1 )
|
||||||
|
) ) );
|
||||||
|
|
||||||
|
plane.polygons.add( new Polygon( Arrays.asList(
|
||||||
|
new Point( -1, -1 ),
|
||||||
|
new Point( 1, -1 ),
|
||||||
|
new Point( 1, 1 ),
|
||||||
|
new Point( -1, 1 )
|
||||||
|
) ) );
|
||||||
|
plane.polygons.add( new Polygon( Arrays.asList(
|
||||||
|
new Point( -1, 1 ),
|
||||||
|
new Point( 1, 1 ),
|
||||||
|
new Point( 1, 3 ),
|
||||||
|
new Point( -1, 3 )
|
||||||
|
) ) );
|
||||||
|
plane.polygons.add( new Polygon( Arrays.asList(
|
||||||
|
new Point( -2, -1 ),
|
||||||
|
new Point( -1, -1 ),
|
||||||
|
new Point( -1, 2 ),
|
||||||
|
new Point( -2, 2 )
|
||||||
|
) ) );
|
||||||
|
plane.polygons.add( new Polygon( Arrays.asList(
|
||||||
|
new Point( -4, -2 ),
|
||||||
|
new Point( -1, -2 ),
|
||||||
|
new Point( -1, 1.5 ),
|
||||||
|
new Point( -4, 1.5 )
|
||||||
|
) ) );
|
||||||
|
plane.polygons.add( new Polygon( Arrays.asList(
|
||||||
|
new Point( -3, 0 ),
|
||||||
|
new Point( 3, 0 ),
|
||||||
|
new Point( -1.5, -3 ),
|
||||||
|
new Point( 0, 1.5 ),
|
||||||
|
new Point( 1.5, -3 )
|
||||||
|
) ) );
|
||||||
|
plane.polygons.add( new Polygon( Arrays.asList(
|
||||||
|
new Point( -1, 0 ),
|
||||||
|
new Point( 0, 1.5 ),
|
||||||
|
new Point( 1, 0 )
|
||||||
|
) ) );
|
||||||
plane.polygons.add( new Polygon( Arrays.asList(
|
plane.polygons.add( new Polygon( Arrays.asList(
|
||||||
new Point( 1, 0 ),
|
new Point( 1, 0 ),
|
||||||
new Point( 2, 1 ),
|
new Point( 0, -2 ),
|
||||||
new Point( 3, 0 ),
|
new Point( -1, 0 )
|
||||||
new Point( 4, 1 ),
|
) ) );
|
||||||
new Point( 3, 2 ),
|
|
||||||
new Point( 4, 3 ),
|
|
||||||
new Point( 3, 4 ),
|
|
||||||
new Point( 2, 3 ),
|
|
||||||
new Point( 1, 4 ),
|
|
||||||
new Point( 0, 3 ),
|
|
||||||
new Point( 1, 2 ),
|
|
||||||
new Point( 0, 1 )
|
|
||||||
) ) );
|
|
||||||
|
|
||||||
return plane;
|
return plane;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,13 +48,13 @@ public class MeshingTest3 {
|
|||||||
System.out.println( "\tTook " + time + "ms" );
|
System.out.println( "\tTook " + time + "ms" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// final List< Plane > planes = mesh( new File( CHUNK_DIR, "world,-1,-1" ) ); // 123
|
// final List< Plane > planes = mesh( new File( CHUNK_DIR, "world,-10,-10" ) ); // 25
|
||||||
// for ( int i = 0; i < planes.size(); ++i ) {
|
// for ( int i = 0; i < planes.size(); ++i ) {
|
||||||
// System.out.println( "Meshing plane " + i );
|
// System.out.println( "Meshing plane " + i );
|
||||||
// process( planes.get( i ) );
|
// process( planes.get( i ) );
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// process( planes.get( 20 ) );
|
// process( planes.get( 27 ) );
|
||||||
} else {
|
} else {
|
||||||
System.err.println( "No such directory exists: " + CHUNK_DIR );
|
System.err.println( "No such directory exists: " + CHUNK_DIR );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -583,7 +583,7 @@ public class MiniePlugin extends JavaPlugin {
|
|||||||
final Location loc = block.getLocation();
|
final Location loc = block.getLocation();
|
||||||
|
|
||||||
// Start the box at 0, 0, 0
|
// Start the box at 0, 0, 0
|
||||||
final BoundingBox[] boundingBoxes = convertFrom( getShape( data, loc, BlockShapeType.VISUAL_SHAPE ), new Vector( x, y - worldMinHeight, z ) );
|
final BoundingBox[] boundingBoxes = convertFrom( getShape( data, loc, BlockShapeType.COLLISION_SHAPE ), new Vector( x, y - worldMinHeight, z ) );
|
||||||
|
|
||||||
for ( BoundingBox box : boundingBoxes ) {
|
for ( BoundingBox box : boundingBoxes ) {
|
||||||
boxes.add( box );
|
boxes.add( box );
|
||||||
|
|||||||
Reference in New Issue
Block a user