Move each application to its own submodule

Removed JOML and Bukkit depednencies for the standalone applications
This commit is contained in:
2026-03-15 15:16:42 -04:00
parent ce8165417b
commit c2aa41fe58
33 changed files with 1204 additions and 177 deletions

View File

@@ -1,194 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.util.Vector;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.ChunkLocation;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.Facet;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.MeshBuilder;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.Plane;
public class MeshTest {
private static final File BASE = new File( System.getProperty( "user.dir" ) );
private static final File CHUNK_DIR = new File( BASE, "chunks" );
public static void main( String[] args ) {
if ( CHUNK_DIR.exists() && CHUNK_DIR.isDirectory() ) {
System.out.println( "Found " + CHUNK_DIR.list().length + " files" );
for ( File file : CHUNK_DIR.listFiles() ) {
doStuff( file );
break;
}
} else {
System.err.println( "No such directory exists: " + CHUNK_DIR );
}
}
private static void doStuff( File file ) {
String name = file.getName();
String[] split = name.split( "," );
ChunkLocation location = new ChunkLocation( split[ 0 ], Integer.parseInt( split[ 1 ] ), Integer.parseInt( split[ 2 ] ) );
System.out.println( "Parsing chunk " + location );
// First parse the file to get a list of all bounding boxes that we can use
List< AABB > boxes = new ArrayList< AABB >();
try ( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
String line;
while ( ( line = reader.readLine() ) != null ) {
if ( !line.isEmpty() ) {
String[] values = line.split( "," );
double minX = Double.parseDouble( values[ 0 ] );
double minY = Double.parseDouble( values[ 1 ] );
double minZ = Double.parseDouble( values[ 2 ] );
double maxX = Double.parseDouble( values[ 3 ] );
double maxY = Double.parseDouble( values[ 4 ] );
double maxZ = Double.parseDouble( values[ 5 ] );
boxes.add( new AABB( minX, minY, minZ, maxX, maxY, maxZ ) );
}
}
} catch ( FileNotFoundException e ) {
e.printStackTrace();
return;
} catch ( IOException e ) {
e.printStackTrace();
return;
}
System.out.println( "Found " + boxes.size() + " boxes" );
// Now that we have a bunch of bounding boxes, do whatever
MeshBuilder builder = new MeshBuilder();
int i = 0;
for ( AABB box : boxes ) {
for ( Facet facet : generateFacetsFor( box ) ) {
builder.addFacet( facet );
}
}
System.out.println( "Planes: " + builder.planes.size() );
for ( Plane plane : builder.planes ) {
System.out.println( "Plane" );
System.out.println( "Norm:\t" + plane.normal );
System.out.println( "Ref:\t" + plane.point );
System.out.println( "Size:\t" + plane.polygons.size() );
}
/*
* The general plan is as follows:
* - Create a new mesh object
* - Insert faces one by one until we have all the shapes we want
* - In this case, it happens to be perfect AABB
* - Process the faces
* - Sort them into their correct plane of existence, along with their normal
* - In this case, their unique plane can be defined by their normal, and a point
* - Use the first point of the polygon to compare
* - Use the smallest point we can find as the reference point
* - O(1) operation per face, I suppose
* - Need to check point and normal with tolerance which is why
* - Now that we have faces each in their assorted group, we can start to tessellate each one
* - Generate even/odd regions and remove any colinear edges
* - Save this as the pre-mesh
* - Now trianglate each group and put that into a mesh collision shape or gimpact shape or whatnot
* - Use an IndexedMesh with the two array constructor
* - Put into game and test
*/
}
private static List< Facet > generateFacetsFor( AABB box ) {
List< Facet > facets = new ArrayList< Facet >();
Vector p1 = new Vector( box.xmin, box.ymin, box.zmin );
Vector p2 = new Vector( box.xmin, box.ymin, box.zmax );
Vector p3 = new Vector( box.xmin, box.ymax, box.zmin );
Vector p4 = new Vector( box.xmin, box.ymax, box.zmax );
Vector p5 = new Vector( box.xmax, box.ymin, box.zmin );
Vector p6 = new Vector( box.xmax, box.ymin, box.zmax );
Vector p7 = new Vector( box.xmax, box.ymax, box.zmin );
Vector p8 = new Vector( box.xmax, box.ymax, box.zmax );
{
Facet facet = new Facet();
facet.points.add( p1 );
facet.points.add( p2 );
facet.points.add( p4 );
facet.points.add( p3 );
facet.normal = new Vector( -1, 0, 0 );
facets.add( facet );
}
{
Facet facet = new Facet();
facet.points.add( p5 );
facet.points.add( p6 );
facet.points.add( p8 );
facet.points.add( p7 );
facet.normal = new Vector( 1, 0, 0 );
facets.add( facet );
}
{
Facet facet = new Facet();
facet.points.add( p1 );
facet.points.add( p2 );
facet.points.add( p6 );
facet.points.add( p5 );
facet.normal = new Vector( 0, -1, 0 );
facets.add( facet );
}
{
Facet facet = new Facet();
facet.points.add( p3 );
facet.points.add( p4 );
facet.points.add( p7 );
facet.points.add( p8 );
facet.normal = new Vector( 0, 1, 0 );
facets.add( facet );
}
{
Facet facet = new Facet();
facet.points.add( p1 );
facet.points.add( p3 );
facet.points.add( p7 );
facet.points.add( p5 );
facet.normal = new Vector( 0, 0, -1 );
facets.add( facet );
}
{
Facet facet = new Facet();
facet.points.add( p2 );
facet.points.add( p4 );
facet.points.add( p8 );
facet.points.add( p6 );
facet.normal = new Vector( 0, 0, 1 );
facets.add( facet );
}
return facets;
}
static class AABB {
double xmin, ymin, zmin;
double xmax, ymax, zmax;
AABB( double xmin, double ymin, double zmin, double xmax, double ymax, double zmax ) {
this.xmin = xmin;
this.ymax = ymin;
this.zmin = zmin;
this.xmax = xmax;
this.ymax = ymax;
this.zmax = zmax;
}
}
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,235 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.bukkit.util.Vector;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Mesh;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Polygon;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionRuleWinding;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionSimple;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionSimple.GluWindingRule;
import com.aaaaahhhhhhh.bananapuncher714.minietest.MeshingTest2.AABB;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.ChunkLocation;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.Facet;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.MeshBuilder;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.Plane;
/**
* Mesh speed test
*/
public class MeshingTest3 {
private static final File BASE = new File( System.getProperty( "user.dir" ) );
private static final File CHUNK_DIR = new File( BASE, "chunks" );
public static void main( String[] args ) {
if ( CHUNK_DIR.exists() && CHUNK_DIR.isDirectory() ) {
System.out.println( "Found " + CHUNK_DIR.list().length + " files" );
final long allStart = System.currentTimeMillis();
final AtomicInteger index = new AtomicInteger( 0 );
final Collection< File > files = Arrays.asList( CHUNK_DIR.listFiles() );
files.parallelStream().forEach( f -> {
final StringBuilder builder = new StringBuilder();
builder.append( "Meshing file: " + f + "\n" );
final long start = System.currentTimeMillis();
final List< Plane > planes = mesh( f, builder );
planes.parallelStream().forEach( p -> {
try {
process( p );
} catch ( IllegalStateException e ) {
e.printStackTrace();
System.exit( 1 );
}
} );
long time = System.currentTimeMillis() - start;
builder.append( "\tTook " + time + "ms\n" );
builder.append( "\tCompleted " + index.incrementAndGet() + "/" + files.size() );
System.out.println( builder.toString() );
} );
System.out.println( "Took a total of " + ( System.currentTimeMillis() - allStart ) + "ms" );
// for ( int i = 0; i < CHUNK_DIR.listFiles().length; ++i ) {
// final File file = CHUNK_DIR.listFiles()[ i ];
// System.out.println( ( i + 1 ) + "/" + CHUNK_DIR.listFiles().length + ":\tMeshing " + file );
// long start = System.currentTimeMillis();
// final List< Plane > planes = mesh( file, null );
// planes.parallelStream().forEach( p -> {
// try {
// process( p );
// } catch ( IllegalStateException e ) {
// e.printStackTrace();
//
// System.exit( 1 );
// }
// } );
//
// long time = System.currentTimeMillis() - start;
//
// System.out.println( "\tTook " + time + "ms" );
// }
// final List< Plane > planes = mesh( new File( CHUNK_DIR, "world,-10,-10" ) ); // 25
// for ( int i = 0; i < planes.size(); ++i ) {
// System.out.println( "Meshing plane " + i );
// process( planes.get( i ) );
// }
// process( planes.get( 27 ) );
} else {
System.err.println( "No such directory exists: " + CHUNK_DIR );
}
}
private static void process( final Plane plane ) {
if ( plane != null ) {
Mesh< RegionSimple > mesh = new Mesh< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } );
for ( Polygon poly : plane.polygons ) {
mesh.addPolygon( poly, RegionRuleWinding.CLOCKWISE );
}
mesh.meshify();
} else {
System.out.println( "No data!" );
}
}
private static List< Plane > mesh( File file, final StringBuilder stringBuilder ) {
String name = file.getName();
String[] split = name.split( "," );
ChunkLocation location = new ChunkLocation( split[ 0 ], Integer.parseInt( split[ 1 ] ), Integer.parseInt( split[ 2 ] ) );
// First parse the file to get a list of all bounding boxes that we can use
List< AABB > boxes = new ArrayList< AABB >();
try ( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
String line;
while ( ( line = reader.readLine() ) != null ) {
if ( !line.isEmpty() ) {
String[] values = line.split( "," );
double minX = Double.parseDouble( values[ 0 ] );
double minY = Double.parseDouble( values[ 1 ] );
double minZ = Double.parseDouble( values[ 2 ] );
double maxX = Double.parseDouble( values[ 3 ] );
double maxY = Double.parseDouble( values[ 4 ] );
double maxZ = Double.parseDouble( values[ 5 ] );
boxes.add( new AABB( minX, minY, minZ, maxX, maxY, maxZ ) );
}
}
} catch ( FileNotFoundException e ) {
e.printStackTrace();
return null;
} catch ( IOException e ) {
e.printStackTrace();
return null;
}
if ( stringBuilder != null ) {
stringBuilder.append( "\tParsing chunk " + location + "\n" );
stringBuilder.append( "\tFound " + boxes.size() + " boxes\n" );
} else {
System.out.println( "\tParsing chunk " + location );
System.out.println( "\tFound " + boxes.size() + " boxes" );
}
// Now that we have a bunch of bounding boxes, do whatever
MeshBuilder builder = new MeshBuilder();
for ( AABB box : boxes ) {
for ( Facet facet : generateFacetsFor( box ) ) {
builder.addFacet( facet );
}
}
return builder.planes;
}
private static List< Facet > generateFacetsFor( AABB box ) {
List< Facet > facets = new ArrayList< Facet >();
Vector p1 = new Vector( box.xmin, box.ymin, box.zmin );
Vector p2 = new Vector( box.xmin, box.ymin, box.zmax );
Vector p3 = new Vector( box.xmin, box.ymax, box.zmin );
Vector p4 = new Vector( box.xmin, box.ymax, box.zmax );
Vector p5 = new Vector( box.xmax, box.ymin, box.zmin );
Vector p6 = new Vector( box.xmax, box.ymin, box.zmax );
Vector p7 = new Vector( box.xmax, box.ymax, box.zmin );
Vector p8 = new Vector( box.xmax, box.ymax, box.zmax );
{
Facet facet = new Facet();
facet.points.add( p1 );
facet.points.add( p2 );
facet.points.add( p4 );
facet.points.add( p3 );
facet.normal = new Vector( -1, 0, 0 );
facets.add( facet );
}
{
Facet facet = new Facet();
facet.points.add( p5 );
facet.points.add( p6 );
facet.points.add( p8 );
facet.points.add( p7 );
facet.normal = new Vector( 1, 0, 0 );
facets.add( facet );
}
{
Facet facet = new Facet();
facet.points.add( p1 );
facet.points.add( p2 );
facet.points.add( p6 );
facet.points.add( p5 );
facet.normal = new Vector( 0, -1, 0 );
facets.add( facet );
}
{
Facet facet = new Facet();
facet.points.add( p3 );
facet.points.add( p4 );
facet.points.add( p8 );
facet.points.add( p7 );
facet.normal = new Vector( 0, 1, 0 );
facets.add( facet );
}
{
Facet facet = new Facet();
facet.points.add( p1 );
facet.points.add( p3 );
facet.points.add( p7 );
facet.points.add( p5 );
facet.normal = new Vector( 0, 0, -1 );
facets.add( facet );
}
{
Facet facet = new Facet();
facet.points.add( p2 );
facet.points.add( p4 );
facet.points.add( p8 );
facet.points.add( p6 );
facet.normal = new Vector( 0, 0, 1 );
facets.add( facet );
}
return facets;
}
}

View File

@@ -1,392 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.bukkit.util.Vector;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Mesh;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Polygon;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionRuleWinding;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionSimple;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionSimple.GluWindingRule;
import com.aaaaahhhhhhh.bananapuncher714.minietest.MeshingTest2.AABB;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.ChunkLocation;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.Facet;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.MeshBuilder;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.Plane;
/**
* Mesh chunk data to ply2 format
*/
public class MeshingTest4 {
private static final File BASE = new File( System.getProperty( "user.dir" ) );
private static final File CHUNK_DIR = new File( BASE, "chunks" );
private static final File MODEL_DIR = new File( BASE, "chunk_models" );
public static void main( String[] args ) {
if ( CHUNK_DIR.exists() && CHUNK_DIR.isDirectory() ) {
System.out.println( "Found " + CHUNK_DIR.list().length + " files" );
// Omega mesh time
// omegaMesh( CHUNK_DIR, new File( MODEL_DIR, "omega.ply" ) );
final long allStart = System.currentTimeMillis();
final AtomicInteger index = new AtomicInteger( 0 );
final Collection< File > files = Arrays.asList( CHUNK_DIR.listFiles() );
files.parallelStream().forEach( f -> {
final StringBuilder builder = new StringBuilder();
builder.append( "Meshing file: " + f + "\n" );
final long start = System.currentTimeMillis();
final List< Plane > planes = mesh( f, builder );
savePly2( new File( MODEL_DIR, f.getName() + ".ply" ), planes.parallelStream().flatMap( p -> process( p ).parallelStream().map( p::convert ) ).collect( Collectors.toSet() ) );
final long time = System.currentTimeMillis() - start;
builder.append( "\tTook " + time + "ms\n" );
builder.append( "\tCompleted " + index.incrementAndGet() + "/" + files.size() );
System.out.println( builder.toString() );
} );
System.out.println( "Took a total of " + ( System.currentTimeMillis() - allStart ) );
// for ( int i = 0; i < CHUNK_DIR.listFiles().length; ++i ) {
// final File file = CHUNK_DIR.listFiles()[ i ];
// System.out.println( ( i + 1 ) + "/" + CHUNK_DIR.listFiles().length + ":\tMeshing " + file );
// final long start = System.currentTimeMillis();
// final List< Plane > planes = mesh( file );
// savePly2( new File( MODEL_DIR, file.getName() + ".ply" ), planes.parallelStream().flatMap( p -> process( p ).parallelStream().map( p::convert ) ).collect( Collectors.toSet() ) );
// long time = System.currentTimeMillis() - start;
//
// System.out.println( "\tTook " + time + "ms" );
// }
} else {
System.err.println( "No such directory exists: " + CHUNK_DIR );
}
}
private static void savePly2( final File file, Collection< Facet > facets ) {
file.getParentFile().mkdirs();
if ( file.exists() ) {
file.delete();
}
class VectorRef {
int index;
}
class Triangle {
List< VectorRef > refs = new ArrayList< VectorRef >();
}
Map< Vector, VectorRef > vertices = new HashMap< Vector, VectorRef >();
Collection< Triangle > triangles = new HashSet< Triangle >();
// Convert each facet to a triangle
for ( final Facet facet : facets ) {
if ( facet.points.size() != 3 ) {
System.out.println( "Warning: Facet is not a triangle!" );
}
final Triangle triangle = new Triangle();
for ( final Vector vec : facet.points ) {
VectorRef ref = null;
for ( final Entry< Vector, VectorRef > entry : vertices.entrySet() ) {
final Vector existingVec = entry.getKey();
if ( existingVec.distanceSquared( vec ) < 1e-8 ) {
ref = entry.getValue();
break;
}
}
if ( ref == null ) {
ref = new VectorRef();
vertices.put( vec, ref );
}
triangle.refs.add( ref );
}
triangles.add( triangle );
}
// Sort the vertices
final List< Entry< Vector, VectorRef > > sorted = new ArrayList< Entry< Vector, VectorRef > >( vertices.entrySet() );
Collections.sort( sorted, ( aEntry, bEntry ) -> {
final Vector a = aEntry.getKey();
final Vector b = bEntry.getKey();
final double xDiff = a.getX() - b.getX();
if ( xDiff == 0 ) {
final double yDiff = a.getY() - b.getY();
if ( yDiff == 0 ) {
return Double.compare( a.getZ(), b.getZ() );
} else {
return Double.compare( yDiff, 0 );
}
} else {
return Double.compare( xDiff, 0 );
}
} );
try ( PrintWriter writer = new PrintWriter( file ) ) {
writer.println( "ply" );
writer.println( "format ascii 1.0" );
writer.println( "comment Created by java tess" );
writer.println( "element vertex " + sorted.size() );
writer.println( "property float x" );
writer.println( "property float y" );
writer.println( "property float z" );
writer.println( "element face " + triangles.size() );
writer.println( "element property list uchar uint vertex_indices" );
writer.println( "end_header" );
// Write vertices
for ( int i = 0; i < sorted.size(); ++i ) {
final Entry< Vector, VectorRef > entry = sorted.get( i );
entry.getValue().index = i;
final Vector vector = entry.getKey();
writer.println( String.format( "%f %f %f", vector.getX(), vector.getY(), vector.getZ() ) );
}
for ( final Triangle triangle : triangles ) {
final StringBuilder builder = new StringBuilder();
builder.append( triangle.refs.size() );
for ( final VectorRef ref : triangle.refs ) {
builder.append( " " );
builder.append( ref.index );
}
writer.println( builder.toString() );
}
System.out.println( "\tWriting " + triangles.size() + " triangles and " + sorted.size() + " vertices to " + file );
} catch ( FileNotFoundException e ) {
e.printStackTrace();
}
}
private static void omegaMesh( final File directory, final File output ) {
final List< AABB > allBoxes = new ArrayList< AABB >();
for ( int i = 0; i < directory.listFiles().length; ++i ) {
final File file = directory.listFiles()[ i ];
System.out.println( ( i + 1 ) + "/" + directory.listFiles().length + ": Getting meshes for: " + file );
allBoxes.addAll( getBoxes( file ) );
}
System.out.println( "Gathered " + allBoxes.size() + " boxes" );
final MeshBuilder builder = new MeshBuilder();
int boxCount = 0;
for ( final AABB box : allBoxes ) {
for ( final Facet facet : generateFacetsFor( box ) ) {
builder.addFacet( facet );
}
if ( ++boxCount % 100_000 == 0 ) {
System.out.println( "Added box " + boxCount + "/" + allBoxes.size() + "\t" + ( boxCount / ( double ) allBoxes.size() ) + "%" );
}
}
System.out.println( "Starting to mesh " + builder.planes.size() + " planes" );
final long start = System.currentTimeMillis();
final AtomicInteger counter = new AtomicInteger();
savePly2( output, builder.planes.parallelStream().flatMap( p -> {
final Stream< Facet > facets = process( p ).parallelStream().map( p::convert );
System.out.println( "Finished " + counter.incrementAndGet() + "/" + builder.planes.size() );
return facets;
} ).collect( Collectors.toSet() ) );
System.out.println( "\tTook " + ( System.currentTimeMillis() - start ) + "ms" );
}
private static Collection< Polygon > process( final Plane plane ) {
if ( plane != null ) {
Mesh< RegionSimple > mesh = new Mesh< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } );
for ( Polygon poly : plane.polygons ) {
mesh.addPolygon( poly, RegionRuleWinding.CLOCKWISE );
}
return mesh.meshify();
} else {
System.out.println( "No data!" );
return Collections.emptySet();
}
}
private static List< Plane > mesh( File file, final StringBuilder stringBuilder ) {
String name = file.getName();
String[] split = name.split( "," );
ChunkLocation location = new ChunkLocation( split[ 0 ], Integer.parseInt( split[ 1 ] ), Integer.parseInt( split[ 2 ] ) );
// First parse the file to get a list of all bounding boxes that we can use
List< AABB > boxes = new ArrayList< AABB >();
try ( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
String line;
while ( ( line = reader.readLine() ) != null ) {
if ( !line.isEmpty() ) {
String[] values = line.split( "," );
double minX = Double.parseDouble( values[ 0 ] );
double minY = Double.parseDouble( values[ 1 ] );
double minZ = Double.parseDouble( values[ 2 ] );
double maxX = Double.parseDouble( values[ 3 ] );
double maxY = Double.parseDouble( values[ 4 ] );
double maxZ = Double.parseDouble( values[ 5 ] );
boxes.add( new AABB( minX, minY, minZ, maxX, maxY, maxZ ) );
}
}
} catch ( FileNotFoundException e ) {
e.printStackTrace();
return null;
} catch ( IOException e ) {
e.printStackTrace();
return null;
}
// Now that we have a bunch of bounding boxes, do whatever
MeshBuilder builder = new MeshBuilder();
for ( AABB box : boxes ) {
for ( Facet facet : generateFacetsFor( box ) ) {
builder.addFacet( facet );
}
}
if ( stringBuilder != null ) {
stringBuilder.append( "\tParsing chunk " + location + "\n" );
stringBuilder.append( "\tFound " + boxes.size() + " boxes and " + builder.planes.size() + " planes\n" );
} else {
System.out.println( "\tParsing chunk " + location );
System.out.println( "\tFound " + boxes.size() + " boxes and " + builder.planes.size() + " planes" );
}
return builder.planes;
}
private static List< AABB > getBoxes( final File file ) {
final String name = file.getName();
final String[] split = name.split( "," );
final int chunkX = Integer.parseInt( split[ 1 ] );
final int chunkZ = Integer.parseInt( split[ 2 ] );
final int blockX = chunkX << 4;
final int blockZ = chunkZ << 4;
// First parse the file to get a list of all bounding boxes that we can use
final List< AABB > boxes = new ArrayList< AABB >();
try ( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
String line;
while ( ( line = reader.readLine() ) != null ) {
if ( !line.isEmpty() ) {
String[] values = line.split( "," );
double minX = Double.parseDouble( values[ 0 ] );
double minY = Double.parseDouble( values[ 1 ] );
double minZ = Double.parseDouble( values[ 2 ] );
double maxX = Double.parseDouble( values[ 3 ] );
double maxY = Double.parseDouble( values[ 4 ] );
double maxZ = Double.parseDouble( values[ 5 ] );
boxes.add( new AABB( minX + blockX, minY, minZ + blockZ, maxX + blockX, maxY, maxZ + blockZ ) );
}
}
} catch ( FileNotFoundException e ) {
e.printStackTrace();
return Collections.emptyList();
} catch ( IOException e ) {
e.printStackTrace();
return Collections.emptyList();
}
return boxes;
}
private static List< Facet > generateFacetsFor( AABB box ) {
List< Facet > facets = new ArrayList< Facet >();
Vector p1 = new Vector( box.xmin, box.ymin, box.zmin );
Vector p2 = new Vector( box.xmin, box.ymin, box.zmax );
Vector p3 = new Vector( box.xmin, box.ymax, box.zmin );
Vector p4 = new Vector( box.xmin, box.ymax, box.zmax );
Vector p5 = new Vector( box.xmax, box.ymin, box.zmin );
Vector p6 = new Vector( box.xmax, box.ymin, box.zmax );
Vector p7 = new Vector( box.xmax, box.ymax, box.zmin );
Vector p8 = new Vector( box.xmax, box.ymax, box.zmax );
{
Facet facet = new Facet();
facet.points.add( p1 );
facet.points.add( p2 );
facet.points.add( p4 );
facet.points.add( p3 );
facet.normal = new Vector( -1, 0, 0 );
facets.add( facet );
}
{
Facet facet = new Facet();
facet.points.add( p5 );
facet.points.add( p6 );
facet.points.add( p8 );
facet.points.add( p7 );
facet.normal = new Vector( 1, 0, 0 );
facets.add( facet );
}
{
Facet facet = new Facet();
facet.points.add( p1 );
facet.points.add( p2 );
facet.points.add( p6 );
facet.points.add( p5 );
facet.normal = new Vector( 0, -1, 0 );
facets.add( facet );
}
{
Facet facet = new Facet();
facet.points.add( p3 );
facet.points.add( p4 );
facet.points.add( p8 );
facet.points.add( p7 );
facet.normal = new Vector( 0, 1, 0 );
facets.add( facet );
}
{
Facet facet = new Facet();
facet.points.add( p1 );
facet.points.add( p3 );
facet.points.add( p7 );
facet.points.add( p5 );
facet.normal = new Vector( 0, 0, -1 );
facets.add( facet );
}
{
Facet facet = new Facet();
facet.points.add( p2 );
facet.points.add( p4 );
facet.points.add( p8 );
facet.points.add( p6 );
facet.normal = new Vector( 0, 0, 1 );
facets.add( facet );
}
return facets;
}
}

View File

@@ -1,178 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import org.bukkit.util.Vector;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Mesh;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Polygon;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionRuleWinding;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionSimple;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionSimple.GluWindingRule;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.ChunkLocation;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.Facet;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.MeshBuilder;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.Plane;
/**
* Mesh speed test for facets
*/
public class MeshingTest5 {
private static final File BASE = new File( System.getProperty( "user.dir" ) );
private static final File FACET_DIR = new File( BASE, "facets" );
private static Collection< Facet > facets = Collections.synchronizedCollection( new LinkedHashSet< Facet >() );
public static void main( String[] args ) {
if ( FACET_DIR.exists() && FACET_DIR.isDirectory() ) {
System.out.println( "Found " + FACET_DIR.list().length + " files" );
final long allStart = System.currentTimeMillis();
final AtomicInteger index = new AtomicInteger( 0 );
final Collection< File > files = Arrays.asList( FACET_DIR.listFiles() );
files.parallelStream().forEach( f -> {
final StringBuilder builder = new StringBuilder();
builder.append( "Meshing file: " + f + "\n" );
final long start = System.currentTimeMillis();
final List< Plane > planes = mesh( f, builder );
planes.parallelStream().forEach( p -> {
try {
process( p );
} catch ( IllegalStateException e ) {
e.printStackTrace();
System.exit( 1 );
}
} );
long time = System.currentTimeMillis() - start;
builder.append( "\tTook " + time + "ms\n" );
builder.append( "\tCompleted " + index.incrementAndGet() + "/" + files.size() );
System.out.println( builder.toString() );
} );
System.out.println( "Took a total of " + ( System.currentTimeMillis() - allStart ) + "ms" );
// for ( int i = 0; i < FACET_DIR.listFiles().length; ++i ) {
// final File file = FACET_DIR.listFiles()[ i ];
// System.out.println( ( i + 1 ) + "/" + FACET_DIR.listFiles().length + ":\tMeshing " + file );
// long start = System.currentTimeMillis();
// final List< Plane > planes = mesh( file, null );
// planes.parallelStream().forEach( p -> {
// try {
// process( p );
// } catch ( IllegalStateException e ) {
// e.printStackTrace();
//
// System.exit( 1 );
// }
// } );
//
// long time = System.currentTimeMillis() - start;
//
// System.out.println( "\tTook " + time + "ms" );
// }
// final List< Plane > planes = mesh( new File( FACET_DIR, "world,-1,2.facet" ), null ); // 25
// for ( int i = 0; i < planes.size(); ++i ) {
// System.out.println( "Meshing plane " + i );
// process( planes.get( i ) );
// }
// process( planes.get( 73 ) );
} else {
System.err.println( "No such directory exists: " + FACET_DIR );
}
}
private static void process( final Plane plane ) {
if ( plane != null ) {
Mesh< RegionSimple > mesh = new Mesh< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } );
for ( Polygon poly : plane.polygons ) {
mesh.addPolygon( poly, RegionRuleWinding.CLOCKWISE );
}
synchronized( facets ) {
facets.addAll( plane.convert( mesh.meshify() ) );
}
} else {
System.out.println( "No data!" );
}
}
private static List< Plane > mesh( File file, final StringBuilder stringBuilder ) {
final String name = file.getName().substring( 0, file.getName().indexOf( '.' ) );
final String[] split = name.split( "," );
final ChunkLocation location = new ChunkLocation( split[ 0 ], Integer.parseInt( split[ 1 ] ), Integer.parseInt( split[ 2 ] ) );
// First parse the file to get a list of all facets
final List< Facet > facets = new ArrayList< Facet >();
try ( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
String line;
while ( ( line = reader.readLine() ) != null ) {
if ( !line.isEmpty() ) {
String[] values = line.split( " " );
final int facetCount = Integer.parseInt( values[ 0 ] );
final double nx = Double.parseDouble( values[ 1 ] );
final double ny = Double.parseDouble( values[ 2 ] );
final double nz = Double.parseDouble( values[ 3 ] );
final Facet facet = new Facet();
facet.normal = new Vector( nx, ny, nz );
int point = 0;
while ( point < facetCount && ( line = reader.readLine() ) != null ) {
if ( !line.isEmpty() ) {
String[] values2 = line.split( " " );
final double px = Double.parseDouble( values2[ 0 ] );
final double py = Double.parseDouble( values2[ 1 ] );
final double pz = Double.parseDouble( values2[ 2 ] );
facet.points.add( new Vector( px, py, pz ) );
++point;
}
}
facets.add( facet );
}
}
} catch ( FileNotFoundException e ) {
e.printStackTrace();
return null;
} catch ( IOException e ) {
e.printStackTrace();
return null;
}
if ( stringBuilder != null ) {
stringBuilder.append( "\tParsing chunk " + location + "\n" );
stringBuilder.append( "\tFound " + facets.size() + " facets\n" );
} else {
System.out.println( "\tParsing chunk " + location );
System.out.println( "\tFound " + facets.size() + " facets" );
}
// Now that we have a bunch of bounding boxes, do whatever
MeshBuilder builder = new MeshBuilder();
for ( Facet facet : facets ) {
builder.addFacet( facet );
}
return builder.planes;
}
}

View File

@@ -1,991 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.MouseInfo;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.concurrent.locks.ReentrantLock;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import org.bukkit.util.Vector;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Chain;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Mesh;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Mesh.MeshChainEventHandler;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Mesh.MeshPartitionEventHandler;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Point;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Polygon;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Segment;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Vector2d;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionRuleWinding;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionSimple;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionSimple.GluWindingRule;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.ChunkLocation;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.Facet;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.MeshBuilder;
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.Plane;
/**
* Facet meshing visualizer
*/
public class MeshingTest6 extends JPanel {
private static final File BASE = new File( System.getProperty( "user.dir" ) );
private static final File FACET_DIR = new File( BASE, "facets" );
JFrame f;
// private int windowWidth = 1200;
// private int windowHeight = 1000;
private int windowWidth = 1200;
private int windowHeight = 800;
// private int centerX = 600;
// private int centerY = 400;
private int offsetX = windowWidth >> 1;
private int offsetY = windowHeight >> 1;
private double centerX = 0;
private double centerY = 0;
private double scale = 8;
private int stringBoardX = -100;
private int stringBoardY = 20;
final private List< Plane > planes;
final private PlaneData[] data;
int index = -1;
private JLabel statusBar;
private JComboBox< String > selectionBox;
private ReentrantLock lock = new ReentrantLock();
public static void main( String[] args ) {
if ( FACET_DIR.exists() && FACET_DIR.isDirectory() ) {
System.out.println( "Found " + FACET_DIR.list().length + " files" );
// for ( File file : FACET_DIR.listFiles() ) {
// List< Plane > planes = mesh( file );
// Plane draw = null;
// System.out.println( "Planes: " + planes.size() );
// int planeIndex = 0;
// for ( planeIndex = 0; planeIndex < planes.size(); ++planeIndex ) {
// if ( planes.get( planeIndex ).polygons.size() > 100 ) {
// break;
// }
// }
// Collections.sort( planes, ( a, b ) -> Integer.compare( b.polygons.size(), a.polygons.size() ) );
// draw = planes.get( 4 );
// Select a random plane to draw
// draw = planes.get( new Random().nextInt( planes.size() ) );
// System.out.println( "Draw is " + draw );
// Attempt to mesh all planes
// try {
// test( planes );
// } catch ( PolygonException e ) {
// draw = e.getPlane();
// System.out.println( "Draw is now " + draw );
// }
// final PlaneData data = process( draw );
// final Collection< Polygon > polys = triangulate( draw );
// final Collection< Polygon > polys = test();
// System.out.println( "Polygon count: " + data.polygons.size() );
// final int startingIndex = planeIndex;
// SwingUtilities.invokeLater( new Runnable() {
// @Override
// public void run() {
// new MeshingTest2( planes ).setIndex( startingIndex ).start();;
// }
// } );
// break;
// }
final List< Plane > masterPlanes = new ArrayList< Plane >();
System.out.println( "Facet files: " + FACET_DIR.listFiles().length );
int limit = 1;
for ( File file : FACET_DIR.listFiles() ) {
masterPlanes.addAll( mesh( file ) );
if ( --limit <= 0 ) {
break;
} else {
System.out.println( "Remaining: " + limit );
}
}
// final List< Plane > planes = mesh( new File( FACET_DIR, "world,-1,2.facet" ) );
// masterPlanes.add( planes.get( 73 ) );
// masterPlanes.addAll( planes );
System.out.println( "Adding test plane" );
masterPlanes.add( getTestPlane() );
SwingUtilities.invokeLater( new Runnable() {
@Override
public void run() {
new MeshingTest6( masterPlanes ).start();
}
} );
} else {
System.err.println( "No such directory exists: " + FACET_DIR );
}
}
private static List< Plane > mesh( File file ) {
final String name = file.getName().substring( 0, file.getName().indexOf( '.' ) );
final String[] split = name.split( "," );
final ChunkLocation location = new ChunkLocation( split[ 0 ], Integer.parseInt( split[ 1 ] ), Integer.parseInt( split[ 2 ] ) );
System.out.println( "Parsing chunk " + location );
// First parse the file to get a list of all facets
final List< Facet > facets = new ArrayList< Facet >();
try ( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
String line;
while ( ( line = reader.readLine() ) != null ) {
if ( !line.isEmpty() ) {
String[] values = line.split( " " );
final int facetCount = Integer.parseInt( values[ 0 ] );
final double nx = Double.parseDouble( values[ 1 ] );
final double ny = Double.parseDouble( values[ 2 ] );
final double nz = Double.parseDouble( values[ 3 ] );
final Facet facet = new Facet();
facet.normal = new Vector( nx, ny, nz );
int point = 0;
while ( point < facetCount && ( line = reader.readLine() ) != null ) {
if ( !line.isEmpty() ) {
String[] values2 = line.split( " " );
final double px = Double.parseDouble( values2[ 0 ] );
final double py = Double.parseDouble( values2[ 1 ] );
final double pz = Double.parseDouble( values2[ 2 ] );
facet.points.add( new Vector( px, py, pz ) );
++point;
}
}
facets.add( facet );
}
}
} catch ( FileNotFoundException e ) {
e.printStackTrace();
return null;
} catch ( IOException e ) {
e.printStackTrace();
return null;
}
// Now that we have a bunch of facets, do whatever
System.out.println( "Found " + facets.size() + " facets" );
MeshBuilder builder = new MeshBuilder();
for ( Facet facet : facets ) {
builder.addFacet( facet );
}
return builder.planes;
}
public static class PolygonException extends RuntimeException {
Plane plane;
PolygonException( Plane plane ) {
this.plane = plane;
}
Plane getPlane() {
return plane;
}
}
private static void test( final Collection< Plane > planes ) {
final long processAllStart = System.currentTimeMillis();
planes.parallelStream().forEach( plane -> {
try {
Mesh< RegionSimple > mesh = new Mesh< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } );
for ( Polygon poly : plane.polygons ) {
mesh.addPolygon( poly, RegionRuleWinding.CLOCKWISE );
}
long start = System.currentTimeMillis();
mesh.simplify();
mesh.generateRegions();
final Collection< Polygon > polys = mesh.copyOf().mesh();
long end = System.currentTimeMillis();
System.out.println( plane.polygons.size() + " to " + polys.size() + ":\t " + ( end - start ) + "ms" );
} catch ( IllegalStateException e ) {
e.printStackTrace();
throw new PolygonException( plane );
}
} );
final long processAllEnd = System.currentTimeMillis();
System.out.println( "Took " + ( processAllEnd - processAllStart ) + "ms to process " + planes.size() + " planes" );
}
private static PlaneData process( final Plane plane ) {
if ( plane != null ) {
final PlaneData data = new PlaneData();
System.out.println( "Norm:\t" + plane.normal );
System.out.println( "Ref:\t" + plane.point );
System.out.println( "Size:\t" + plane.polygons.size() );
Mesh< RegionSimple > mesh = new Mesh< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } );
for ( Polygon poly : plane.polygons ) {
mesh.addPolygon( poly, RegionRuleWinding.CLOCKWISE );
}
System.out.println( "Initial vertex count: " + mesh.getVertices().size() );
System.out.println( "Initial edge count: " + ( mesh.getEdgeCount() / 2 ) );
long start = System.currentTimeMillis();
mesh.simplify();
System.out.println( "After simplify vertex count: " + mesh.getVertices().size() );
System.out.println( "After simplify edge count: " + ( mesh.getEdgeCount() / 2 ) );
data.vertices = mesh.getVertices();
data.edges = mesh.getEdges();
try {
mesh.generateRegions();
data.vertices = mesh.getVertices();
data.edges = mesh.getEdges();
} catch ( Exception e ) {
e.printStackTrace();
return data;
}
long end = System.currentTimeMillis();
System.out.println( "After generating regions vertex count: " + mesh.getVertices().size() );
System.out.println( "After generating regions edge count: " + ( mesh.getEdgeCount() / 2 ) );
mesh.addChainHandler( new MeshChainEventHandler() {
@Override
public void onChainGenerationEvent( Collection< Chain > chains ) {
data.chains = chains;
}
@Override
public void onPreChainMergeEvent( Collection< Chain > chains ) {
data.selectedChains = chains;
final List< Chain > sorted = new ArrayList< Chain >( chains );
Collections.sort( sorted, ( a, b ) -> {
final double diff = a.getStart().getX() - b.getStart().getX();
if ( Math.abs( diff ) < 1e-7 ) {
return Double.compare( a.getStart().getY(), b.getStart().getY() );
}
return Double.compare( diff, 0 );
} );
for ( Chain chain : sorted ) {
System.out.println( "c: " + chain.getPoints() );
}
final Collection< Point > points = new HashSet< Point >();
for ( Chain chain : chains ) {
for ( int i = 1; i < chain.getPoints().size() - 1; ++i ) {
if ( !points.add( chain.getPoints().get( i ) ) ) {
System.out.println( "Intersection at " + chain.getPoints().get( i ) );
}
}
}
}
} );
mesh.addPartitionHandler( new MeshPartitionEventHandler() {
@Override
public void onPartitionEvent( Collection< Polygon > polygons ) {
data.polygons = polygons;
}
} );
try {
// If the chains are the issue, set this to false and see if it still meshes
mesh.setMergeChains( true );
final Collection< Polygon > triangles = mesh.mesh();
if ( !triangles.isEmpty() ) {
data.polygons = triangles;
}
} catch ( IllegalStateException e ) {
e.printStackTrace();
}
// final List< Point > points = new ArrayList< Point >( data.vertices );
// Collections.sort( points, ( a, b ) -> {
// final int x = Double.compare( a.getX(), b.getX() );
// if ( x == 0 ) {
// return Double.compare( a.getY(), b.getY() );
// }
// return x;
// } );
// for ( Point v : points ) {
// System.out.println( v.getX() + ", " + v.getY() );
// }
System.out.println( "Took " + ( end - start ) + "ms" );
return data;
} else {
System.out.println( "No data!" );
return null;
}
}
private static Collection< Polygon > triangulate( final Plane plane ) {
if ( plane != null ) {
System.out.println( "Norm:\t" + plane.normal );
System.out.println( "Ref:\t" + plane.point );
System.out.println( "Size:\t" + plane.polygons.size() );
Mesh< RegionSimple > mesh = new Mesh< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } );
for ( Polygon poly : plane.polygons ) {
mesh.addPolygon( poly, RegionRuleWinding.CLOCKWISE );
}
System.out.println( "Initial vertex count: " + mesh.getVertices().size() );
System.out.println( "Initial edge count: " + ( mesh.getEdgeCount() / 2 ) );
long start = System.currentTimeMillis();
mesh.simplify();
System.out.println( "After simplify vertex count: " + mesh.getVertices().size() );
System.out.println( "After simplify edge count: " + ( mesh.getEdgeCount() / 2 ) );
mesh.generateRegions();
System.out.println( "After generating regions vertex count: " + mesh.getVertices().size() );
System.out.println( "After generating regions edge count: " + ( mesh.getEdgeCount() / 2 ) );
// Make sure this works
mesh = mesh.copyOf();
Collection< Polygon > polys = new HashSet< Polygon >();
try {
polys = mesh.mesh();
} catch ( IllegalStateException e ) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println( "Took " + ( end - start ) + "ms" );
return polys;
} else {
System.out.println( "No data!" );
return Collections.emptySet();
}
}
private static PlaneData test() {
final PlaneData data = new PlaneData();
final Mesh< RegionSimple > mesh = new Mesh< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } );
mesh.addChainHandler( new MeshChainEventHandler() {
@Override
public void onChainGenerationEvent( Collection< Chain > chains ) {
data.chains = chains;
}
@Override
public void onPreChainMergeEvent( Collection< Chain > chains ) {
data.selectedChains = chains;
for ( Chain chain : chains ) {
System.out.println( "c: " + chain.getPoints() );
}
}
} );
// mesh.addPolygon( new Polygon( Arrays.asList(
// new Point( -1, 0 ),
// new Point( 1, -2 ),
// new Point( 1, -1 ),
// new Point( 2, -1 ),
// new Point( 1, 0 ),
// new Point( 1, 1 )
// ) ), RegionRuleWinding.CLOCKWISE );
// mesh.addPolygon( new Polygon( Arrays.asList(
// new Point( 0, 0 ),
// new Point( 5, 0 ),
// new Point( 5, 1 ),
// new Point( 4, 1 ),
// new Point( 4, 2 ),
// new Point( 3, 2 ),
// new Point( 3, 3 ),
// new Point( 2, 3 ),
// new Point( 2, 4 ),
// new Point( 0, 4 )
// ) ), RegionRuleWinding.CLOCKWISE );
// mesh.addPolygon( new Polygon( Arrays.asList(
// new Point( 0, 0 ),
// new Point( 2, 0 ),
// new Point( 2, 1 ),
// new Point( 1, 1 ),
// new Point( 1, 2 ),
// new Point( 2, 2 ),
// new Point( 2, 4 ),
// new Point( 1, 4 ),
// new Point( 1, 3 ),
// new Point( 0, 3 )
// ) ), RegionRuleWinding.CLOCKWISE );
// mesh.addPolygon( new Polygon( Arrays.asList(
// new Point( 0, 0 ),
// new Point( 3, 0 ),
// new Point( 3, 1 ),
// new Point( 4, 1 ),
// new Point( 4, 2 ),
// new Point( 2, 2 ),
// new Point( 2, 1 ),
// new Point( 1, 1 ),
// new Point( 0, 1 )
// ) ), RegionRuleWinding.CLOCKWISE );
// mesh.addPolygon( new Polygon( Arrays.asList(
// new Point( 0, 0 ),
// new Point( 2, 0 ),
// new Point( 2, 1 ),
// new Point( 3, 1 ),
// new Point( 3, 2 ),
// new Point( 2, 2 ),
// new Point( 2, 5 ),
// new Point( 1, 5 ),
// new Point( 1, 7 ),
// new Point( 0, 7 ),
// new Point( 0, 4 ),
// new Point( 1, 4 ),
// new Point( 1, 1 ),
// new Point( 0, 1 )
// ) ), RegionRuleWinding.CLOCKWISE );
// mesh.addPolygon( new Polygon( Arrays.asList(
// new Point( 1, 0 ),
// new Point( 6, 0 ),
// new Point( 6, 1 ),
// new Point( 4, 1 ),
// new Point( 4, 2 ),
// new Point( 2, 2 ),
// new Point( 2, 3 ),
// new Point( 0, 3 ),
// new Point( 0, 1 ),
// new Point( 1, 1 )
// ) ), RegionRuleWinding.CLOCKWISE );
// mesh.addPolygon( new Polygon( Arrays.asList(
// new Point( 3, 1 ),
// new Point( 3, 0 ),
// new Point( 10, 0 ),
// new Point( 10, 6 ),
// new Point( 9, 6 ),
// new Point( 9, 4 ),
// new Point( 8, 4 ),
// new Point( 8, 3 ),
// new Point( 5, 3 ),
// new Point( 5, 2 ),
// new Point( 0, 2 ),
// new Point( 0, 1 )
// ) ), RegionRuleWinding.CLOCKWISE );
// mesh.addPolygon( new Polygon( Arrays.asList(
// new Point( 7, 2 ),
// new Point( 9, 2 ),
// new Point( 9, 3 ),
// new Point( 7, 3 )
// ) ), RegionRuleWinding.CLOCKWISE );
// mesh.addPolygon( new Polygon( Arrays.asList(
// new Point( 0, 0 ),
// new Point( 6, 1 ),
// new Point( 7, 2 ),
// new Point( 1, 1 )
// ) ), RegionRuleWinding.CLOCKWISE );
// mesh.addPolygon( new Polygon( Arrays.asList(
// new Point( 2, 2 ),
// new Point( 8, 3 ),
// new Point( 9, 4 ),
// new Point( 3, 3 )
// ) ), RegionRuleWinding.CLOCKWISE );
// mesh.addPolygon( new Polygon( Arrays.asList(
// new Point( 2.816104467407629, -3.7472939407853763 ),
// new Point( 2.815383313894849, -2.9972942874937156 ),
// new Point( 2.0028836894955497, -2.9980755371325607 ),
// new Point( 2.0036048430083304, -3.7480751904242213 )
// ) ), RegionRuleWinding.CLOCKWISE );
// mesh.addPolygon( new Polygon( Arrays.asList(
// new Point( 2.8144217758778085, -1.9972947497715015 ),
// new Point( 2.0019221514785093, -1.998075999410347 ),
// new Point( 2.00264330499129, -2.748075652702007 ),
// new Point( 2.8151429293905887, -2.747294403063162 )
// ) ), RegionRuleWinding.CLOCKWISE );
// mesh.addPolygon( new Polygon( Arrays.asList(
// new Point( 0, 0 ),
// new Point( 1, 0 ),
// new Point( 1, 1 ),
// new Point( 0, 1 )
// ) ), RegionRuleWinding.CLOCKWISE );
// mesh.addPolygon( new Polygon( Arrays.asList(
// new Point( 0, 2 ),
// new Point( 1, 2 ),
// new Point( 1, 3 ),
// new Point( 0, 3 )
// ) ), RegionRuleWinding.CLOCKWISE );
// mesh.addPolygon( new Polygon( Arrays.asList(
// new Point( -1, -1 ),
// new Point( 2, -1 ),
// new Point( 2, 4 ),
// new Point( -1, 4 )
// ) ), RegionRuleWinding.CLOCKWISE );
data.polygons = mesh.mesh();
data.vertices = mesh.getVertices();
data.edges = mesh.getEdges();
return data;
}
private static Plane getTestPlane() {
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(
// 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, 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(
new Point( 1, 0 ),
new Point( 0, -2 ),
new Point( -1, 0 )
) ) );
return plane;
}
public MeshingTest6( List< Plane > data ) {
this.planes = data;
this.data = new PlaneData[ data.size() ];
}
private MeshingTest6 setIndex( final int index ) {
final int planeCount = planes.size();
final int newIndex = ( ( ( index % planeCount ) + planeCount ) % planeCount );
lock.lock();
if ( this.index != newIndex ) {
this.index = newIndex;
if ( selectionBox != null ) {
selectionBox.setSelectedIndex( newIndex );
}
new Thread( () -> { getData( this.index, this::repaint ); } ).start();
}
lock.unlock();
return this;
}
private PlaneData getData( final int index, final Runnable callback ) {
if ( data[ index ] != null ) {
callback.run();
return data[ index ];
} else {
setStatus( "Loading..." );
final PlaneData data = process( planes.set( index, null ) );
setStatus( "Done!" );
this.data[ index ] = data;
callback.run();
return data;
}
}
private void setStatus( final String status ) {
if ( statusBar != null ) {
statusBar.setText( status );
}
}
private MeshingTest6 preMesh() {
for ( int i = 0; i < planes.size(); ++i ) {
this.data[ i ] = process( planes.set( i, null ) );
}
return this;
}
private void start() {
if ( index == -1 ) {
setIndex( 0 );
}
f = new JFrame( "Drawing Board" );
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
final MouseAdapter adapter = new MouseAdapter() {
private boolean dragging = false;
private double initX, initY;
private int dragX, dragY;
private double scroll = Math.log( scale );
@Override
public void mousePressed( MouseEvent e ) {
dragging = true;
initX = centerX;
initY = centerY;
dragX = e.getXOnScreen();
dragY = e.getYOnScreen();
}
@Override
public void mouseReleased( MouseEvent e ) {
dragging = false;
}
@Override
public void mouseDragged( MouseEvent e ) {
if ( dragging ) {
centerX = initX + ( ( e.getXOnScreen() - dragX ) / scale );
centerY = initY + ( ( e.getYOnScreen() - dragY ) / scale );
repaint();
}
}
@Override
public void mouseWheelMoved( MouseWheelEvent e ) {
if ( e.getWheelRotation() < 0 ) {
scroll += e.isControlDown() ? 0.1 : 0.5;
} else {
scroll -= e.isControlDown() ? 0.1 : 0.5;
}
scale = Math.exp( scroll );
repaint();
}
@Override
public void mouseMoved( MouseEvent e ) {
super.mouseMoved( e );
repaint();
}
};
addMouseListener( adapter );
addMouseMotionListener( adapter );
addMouseWheelListener( adapter );
f.addComponentListener( new ComponentAdapter() {
public void componentResized( ComponentEvent e ) {
offsetX = getWidth() >> 1;
offsetY = getHeight() >> 1;
};
} );
final JPanel taskbar = new JPanel();
taskbar.setLayout( new FlowLayout() );
{
final JComboBox< String > data = new JComboBox< String >();
for ( int i = 0; i < planes.size(); ++i ) {
data.addItem( "Plane " + i );
}
data.addActionListener( e -> {
setIndex( data.getSelectedIndex() );
} );
taskbar.add( data );
selectionBox = data;
}
{
final JLabel label = new JLabel();
label.setPreferredSize( new Dimension( 100, 16 ) );
label.setHorizontalAlignment( SwingConstants.LEFT );
taskbar.add( label );
statusBar = label;
}
{
final JButton prev = new JButton( "Previous" );
prev.addActionListener( e -> { setIndex( index - 1 ); } );
taskbar.add( prev );
}
{
final JButton prev = new JButton( "Next" );
prev.addActionListener( e -> { setIndex( index + 1 ); } );
taskbar.add( prev );
}
f.add( taskbar, BorderLayout.NORTH );
f.add( this );
f.setSize( windowWidth, windowHeight );
f.setVisible( true );
f.setResizable( true );
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
private static Vector2d rotate( Vector2d a, double angle ) {
double cos = Math.cos( angle );
double sin = Math.sin( angle );
double ax = a.getX() * cos - a.getY() * sin;
double ay = a.getX() * sin + a.getY() * cos;
return new Vector2d( ax, ay );
}
private void drawOnBoard( Graphics g, String str, int x, int y ) {
g.setFont( new Font( Font.MONOSPACED, Font.BOLD, ( int ) scale * 5 ) );
g.drawString( str, ( int ) ( ( centerX + x + stringBoardX ) * scale ) + offsetX, ( int ) ( ( centerY - y + stringBoardY ) * scale ) + offsetY );
}
@Override
public void paintComponent( Graphics g ) {
super.paintComponent( g );
final PlaneData data = this.data[ index ];
g.setColor( new Color( 200, 200, 200 ) );
g.drawLine( ( int ) ( scale * centerX ) + offsetX, 0, ( int ) ( scale * centerX ) + offsetX, getHeight() );
g.drawLine( 0, ( int ) ( scale * centerY ) + offsetY, getWidth(), ( int ) ( scale * centerY ) + offsetY );
g.setColor( Color.BLACK );
if ( data != null ) {
int highestX = 40;
if ( !data.edges.isEmpty() ) {
Collection< Point > points = data.vertices;
if ( !data.polygons.isEmpty() ) {
highestX = ( int ) ( points.parallelStream()
.max( ( a, b ) -> { return Double.compare( a.getX(), b.getX() ); } ).get().getX() + 40.5 );
} else {
highestX = 0;
}
g.setColor( Color.BLACK );
for ( final Segment segment : data.edges ) {
Point p1 = segment.getStart();
Point p2 = segment.getEnd();
g.drawLine(
( int ) ( ( centerX + p1.getX() + highestX ) * scale ) + offsetX,
( int ) ( ( centerY - p1.getY() ) * scale ) + offsetY,
( int ) ( ( centerX + p2.getX() + highestX ) * scale ) + offsetX,
( int ) ( ( centerY - p2.getY() ) * scale ) + offsetY
);
}
for ( final Point point : points ) {
final double diff = scale * 0.15;
g.drawRect( ( int ) ( ( centerX + point.getX() + highestX ) * scale ) - ( int ) diff + offsetX, ( int ) ( ( centerY - point.getY() ) * scale ) - ( int ) diff + offsetY, ( int ) ( diff * 2 ), ( int ) ( diff * 2 ) );
}
}
{
int count = 2;
Random random = new Random( hashCode() );
final int spacing = 25;
for ( final Polygon p : data.polygons ) {
final List< Point > points = p.getPoints();
final int[] x = new int[ points.size() ];
final int[] y = new int[ points.size() ];
final int[] xOffset = new int[ points.size() ];
final int[] yOffset = new int[ points.size() ];
final int[] filledX = new int[ points.size() ];
final int[] filledY = new int[ points.size() ];
for ( int i = 0; i < points.size(); ++i ) {
final Point point = points.get( i );
x[ i ] = ( int ) ( ( centerX + point.getX() ) * scale ) + offsetX;
y[ i ] = ( int ) ( ( centerY - point.getY() - 150 ) * scale ) + offsetY;
xOffset[ i ] = ( int ) ( ( centerX + point.getX() + count * spacing ) * scale ) + offsetX;
yOffset[ i ] = ( int ) ( ( centerY - point.getY() - 150 ) * scale ) + offsetY;
filledX[ i ] = ( int ) ( ( centerX + point.getX() ) * scale ) + offsetX;
filledY[ i ] = ( int ) ( ( centerY - point.getY() ) * scale ) + offsetY;
}
g.setColor( Color.BLACK );
g.drawPolygon( x, y, points.size() );
g.drawPolygon( xOffset, yOffset, points.size() );
g.setColor( new Color( random.nextInt( 0x1000000 ) ) );
g.fillPolygon( filledX, filledY, points.size() );
++count;
}
}
{
g.setColor( Color.RED );
for ( final Chain chain : data.chains ) {
final Point p1 = chain.getStart();
final Point p2 = chain.getEnd();
g.drawLine(
( int ) ( ( centerX + p1.getX() + highestX ) * scale ) + offsetX,
( int ) ( ( centerY - p1.getY() ) * scale ) + offsetY,
( int ) ( ( centerX + p2.getX() + highestX ) * scale ) + offsetX,
( int ) ( ( centerY - p2.getY() ) * scale ) + offsetY
);
}
}
{
g.setColor( Color.BLUE );
for ( final Chain chain : data.selectedChains ) {
final Point p1 = chain.getStart();
final Point p2 = chain.getEnd();
g.drawLine(
( int ) ( ( centerX + p1.getX() + highestX ) * scale ) + offsetX,
( int ) ( ( centerY - p1.getY() ) * scale ) + offsetY,
( int ) ( ( centerX + p2.getX() + highestX ) * scale ) + offsetX,
( int ) ( ( centerY - p2.getY() ) * scale ) + offsetY
);
}
}
g.setColor( Color.BLACK );
drawOnBoard( g, "Plane index: " + index, 0, 10 );
g.setColor( Color.CYAN );
drawOnBoard( g, "Edge count: " + data.edges.size(), 0, 0 );
g.setColor( Color.GREEN );
drawOnBoard( g, "Vertex count: " + data.vertices.size(), 0, -5 );
g.setColor( Color.MAGENTA );
drawOnBoard( g, "Triangle count: " + data.polygons.size(), 0, -10 );
g.setColor( Color.RED );
drawOnBoard( g, "Total chain count: " + data.chains.size(), 0, -15 );
g.setColor( Color.BLUE );
drawOnBoard( g, "Optimal chain count: " + data.selectedChains.size(), 0, -20 );
}
java.awt.Point p = MouseInfo.getPointerInfo().getLocation();
java.awt.Point componentLocation = getLocationOnScreen();
p = new java.awt.Point( p.x - componentLocation.x, p.y - componentLocation.y );
g.setColor( Color.RED );
g.setFont( new Font( Font.MONOSPACED, Font.BOLD, 30 ) );
g.drawString( "X: " + ( ( p.x - offsetX ) / scale - centerX ), 10, 30 );
g.drawString( "Y: " + ( - ( ( p.y - offsetY ) / scale - centerY ) ), 10, 60 );
}
private static class PlaneData {
Collection< Point > vertices = new HashSet< Point >();
Collection< Segment > edges = new HashSet< Segment >();
Collection< Chain > chains = new HashSet< Chain >();
Collection< Chain > selectedChains = new HashSet< Chain >();
Collection< Polygon > polygons = new HashSet< Polygon >();
}
}

View File

@@ -1,98 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Mesh;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Point;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Polygon;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionRuleWinding;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionSimple;
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionSimple.GluWindingRule;
/**
* Mesh speed test for polygons
*/
public class MeshingTest7 {
private static final File BASE = new File( System.getProperty( "user.dir" ) );
private static final File POLYGON_DIR = new File( BASE, "polygons" );
public static void main( String[] args ) {
if ( POLYGON_DIR.exists() && POLYGON_DIR.isDirectory() ) {
System.out.println( "Found " + POLYGON_DIR.list().length + " files" );
final long allStart = System.currentTimeMillis();
final AtomicInteger index = new AtomicInteger( 0 );
final Collection< File > files = Arrays.asList( POLYGON_DIR.listFiles() );
files.parallelStream().forEach( f -> {
final StringBuilder builder = new StringBuilder();
builder.append( "Meshing file: " + f + "\n" );
final long start = System.currentTimeMillis();
final List< Polygon > polygons = mesh( f, builder );
Mesh< RegionSimple > mesh = new Mesh< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } );
for ( Polygon poly : polygons ) {
mesh.addPolygon( poly, RegionRuleWinding.CLOCKWISE );
}
mesh.meshify();
long time = System.currentTimeMillis() - start;
builder.append( "\tTook " + time + "ms\n" );
builder.append( "\tCompleted " + index.incrementAndGet() + "/" + files.size() );
System.out.println( builder.toString() );
} );
System.out.println( "Took a total of " + ( System.currentTimeMillis() - allStart ) + "ms" );
} else {
System.err.println( "No such directory exists: " + POLYGON_DIR );
}
}
private static List< Polygon > mesh( File file, final StringBuilder stringBuilder ) {
// First parse the file to get a list of all polygons
final List< Polygon > polys = new ArrayList< Polygon >();
try ( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
String line;
while ( ( line = reader.readLine() ) != null ) {
if ( !line.isEmpty() ) {
final int pointCount = Integer.parseInt( line );
List< Point > points = new ArrayList< Point >( pointCount );
int point = 0;
while ( point < pointCount && ( line = reader.readLine() ) != null ) {
if ( !line.isEmpty() ) {
String[] values2 = line.split( " " );
final double px = Double.parseDouble( values2[ 0 ] );
final double py = Double.parseDouble( values2[ 1 ] );
points.add( new Point( px, py ) );
++point;
}
}
polys.add( new Polygon( points ) ) ;
}
}
} catch ( FileNotFoundException e ) {
e.printStackTrace();
return null;
} catch ( IOException e ) {
e.printStackTrace();
return null;
}
return polys;
}
}

View File

@@ -1,11 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.util.Vector;
public class Facet {
public Vector normal;
public List< Vector > points = new ArrayList< Vector >();
}

View File

@@ -1,45 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh;
import org.bukkit.util.Vector;
public class LineSegment {
public Vector point1, point2;
public LineSegment( Vector point1, Vector point2 ) {
if ( point1.getX() < point2.getX() ) {
this.point1 = point1;
this.point2 = point2;
} else if ( point1.getX() > point2.getX() ) {
this.point1 = point2;
this.point2 = point1;
} else if ( point1.getY() < point2.getY() ) {
this.point1 = point1;
this.point2 = point2;
} else if ( point1.getY() > point2.getY() ) {
this.point1 = point2;
this.point2 = point1;
} else if ( point1.getZ() < point2.getZ() ) {
this.point1 = point1;
this.point2 = point2;
} else if ( point1.getZ() > point2.getZ() ) {
this.point1 = point2;
this.point2 = point1;
} else {
// point 1 and 2 are the same, I guess...
this.point1 = point1;
this.point2 = point2;
}
}
public boolean isPoint() {
return point1.equals( point2 );
}
public double length() {
return point1.distance( point2 );
}
public Vector getVector() {
return point2.clone().subtract( point1 );
}
}

View File

@@ -1,30 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.bukkit.util.Vector;
public class MeshBuilder {
public List< Plane > planes = new ArrayList< Plane >();
public Plane addFacet( Facet facet ) {
final Optional< Plane > opt = planes.stream().filter( p -> p.matches( facet.normal, facet.points.get( 0 ) ) ).findAny();
if ( opt.isPresent() ) {
final Plane plane = opt.get();
plane.addShape( facet );
return plane;
}
Plane plane = new Plane();
plane.normal = facet.normal;
Optional< Vector > ref = facet.points.stream().filter( v -> v.lengthSquared() > 0.001 && Math.abs( v.clone().normalize().dot( facet.normal ) ) < .999999 ).findAny();
if ( ref.isPresent() ) {
plane.point = ref.get();
}
plane.addShape( facet );
planes.add( plane );
return plane;
}
}

View File

@@ -1,98 +0,0 @@
package com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.bukkit.util.Vector;
import org.joml.Matrix3d;
import org.joml.Vector3d;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Point;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Polygon;
public class Plane {
public Vector normal;
public Vector point;
public double distance;
private boolean set = false;
public List< Polygon > polygons = new ArrayList< Polygon >();
private Matrix3d mat;
private Matrix3d transpose;
public void addShape( Facet facet ) {
final Matrix3d mat = getProjectionMatrix();
List< Point > polygon = new ArrayList< Point >();
for ( Vector p : facet.points ) {
double t = point.clone().subtract( p ).dot( normal );
Vector i = normal.clone().multiply( t ).add( p );
Vector3d v = new Vector3d( i.getX(), i.getY(), i.getZ() );
Vector3d r = v.mul( mat );
polygon.add( new Point( r.x(), r.y() ) );
if ( !set ) {
distance = r.z();
set = true;
} else if ( Math.abs( r.z() - distance ) > 1e-7 ) {
throw new IllegalStateException( "Bad point in facet!" );
}
}
polygons.add( new Polygon( polygon ) );
}
public Vector convert( final Point p ) {
final Vector3d plane = new Vector3d( p.getX(), p.getY(), distance );
final Vector3d res = plane.mul( getInverseProjectionMatrix() );
return new Vector( res.x(), res.y(), res.z() );
}
public Facet convert( final Polygon polygon ) {
final Facet facet = new Facet();
facet.normal = normal;
for ( final Point p : polygon.getPoints() ) {
facet.points.add( convert( p ) );
}
return facet;
}
public Collection< Facet > convert( final Collection< Polygon > polygons ) {
return polygons.parallelStream().map( this::convert ).collect( Collectors.toSet() );
}
public boolean matches( Vector normal, Vector point ) {
return Math.abs( this.normal.dot( normal ) ) > 0.99 && Math.abs( this.point.clone().subtract( point ).dot( normal ) ) < 0.01;
}
private Matrix3d getProjectionMatrix() {
if ( mat == null ) {
final Vector basis1 = normal.clone().multiply( point.clone().multiply( -1 ).dot( normal ) ).add( point ).normalize();
final Vector3d b1 = new Vector3d( basis1.getX(), basis1.getY(), basis1.getZ() );
final Vector3d b3 = new Vector3d( normal.getX(), normal.getY(), normal.getZ() );
final Vector3d b2 = new Vector3d( b1 ).cross( b3 ).normalize();
mat = new Matrix3d( b1, b2, b3 ).transpose();
}
return mat;
}
private Matrix3d getInverseProjectionMatrix() {
if ( transpose == null ) {
transpose = getProjectionMatrix().transpose();
}
return transpose;
}
}

View File

@@ -2,7 +2,6 @@ package com.aaaaahhhhhhh.bananapuncher714.minietest.util;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
/**
* Big/little endian binary writer