Files
mc-mesh/src/main/java/com/aaaaahhhhhhh/bananapuncher714/tess4j/Tess4jTest.java
BananaPuncher714 d16041f977 Improve tessellation algorithm
Added new mesh class
Rewrite mesh algorithms to be less error prone
Make code more concise
Tried to add some documentation
Added half edge set
2025-05-04 00:04:22 -04:00

266 lines
10 KiB
Java

package com.aaaaahhhhhhh.bananapuncher714.tess4j;
import java.awt.Color;
import java.awt.Graphics;
import java.util.Arrays;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Point;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Polygon;
import com.aaaaahhhhhhh.bananapuncher714.mesh.Vector2d;
import com.aaaaahhhhhhh.bananapuncher714.tess4j.region.RegionSimple;
import com.aaaaahhhhhhh.bananapuncher714.tess4j.region.RegionSimple.GluWindingRule;
import com.aaaaahhhhhhh.bananapuncher714.tess4j.region.WindingRuleSimple;
public class Tess4jTest extends JPanel {
JFrame f;
private int windowWidth = 1200;
private int windowHeight = 1000;
private int centerX = 600;
private int centerY = 400;
private Graphics g;
private int scale = 100;
public static void main( String[] args ) {
SwingUtilities.invokeLater( new Runnable() {
@Override
public void run() {
new Tess4jTest();
}
} );
}
public Tess4jTest() {
f = new JFrame( "Drawing Board" );
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
f.add( this );
f.setSize( windowWidth, windowHeight );
f.setVisible( true );
f.setResizable( true );
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
public void drawPoint( double x, double y ) {
g.fillRect( ( int ) x * scale, ( int ) y * scale, scale, scale );
}
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 );
}
@Override
public void paintComponent( Graphics g ) {
super.paintComponent( g );
this.g = g;
// Vertex v = null;
// for ( int i = 0; i < 100; i++ ) {
// double deg = Math.random() * 360;
// double dist = Math.random() * 100 + 100;
// double x = dist * Math.cos( Math.toRadians( deg ) );
// double y = dist * Math.sin( Math.toRadians( deg ) );
// HalfWing edge = new HalfWing();
// edge.getDest().setPosition( new Vector2d( x, y ) );
// if ( v == null ) {
// v = edge.getOrigin();
// } else {
// HalfWing.splice( edge, v.getWing() );
// }
// }
// v.update();
//
// HalfWing edge = v.getWing();
// int i = 0;
// double ic = 0;
// do {
// Vector2d dest = edge.getDest().getPosition();
// g.drawLine( centerX, centerY, ( int ) dest.getX() + centerX, ( int ) dest.getY() + centerY );
// dest = dest.normalized();
// g.drawString( i++ + "", ( int ) ( dest.x * 200 * ( ic + 1.1 ) ) + centerX, ( int ) ( dest.y * 200 * ( ic + 1.1 ) ) + centerY );
// ic = ( ic + 0.07 ) % .7;
// edge = edge.getPrev();
// } while ( edge != v.getWing() );
//
// v.sort();
//
// g.drawLine( centerX + 700, centerY, centerX + 700, centerY - 400 );
// edge = v.getWing();
// i = 0;
// ic = 0;
// do {
// Vector2d dest = edge.getDest().getPosition();
// g.drawLine( centerX + 700, centerY, ( int ) dest.getX() + centerX + 700, ( int ) dest.y + centerY );
// dest = dest.normalized();
// g.drawString( i++ + "", ( int ) ( dest.x * 200 * ( ic + 1.1 ) ) + centerX + 700, ( int ) ( dest.y * 200 * ( ic + 1.1 ) ) + centerY );
// ic = ( ic + 0.07 ) % .7;
// edge = edge.getPrev();
// } while ( edge != v.getWing() );
// Tess4j< RegionSimple > tess4j = new Tess4j< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } );
Tess4j< RegionSimple > tess4j = new Tess4j< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); }, new Vector2dComparator() {
@Override
public double compareX( Vector2d a, Vector2d b ) {
a = rotate( a, 128 );
b = rotate( b, 128 );
return a.getX() - b.getX();
}
@Override
public double compareY(Vector2d a, Vector2d b ) {
a = rotate( a, 128 );
b = rotate( b, 128 );
return b.getY() - a.getY();
}
} );
// tess4j.addPolygon( new Polygon( Arrays.asList(
// new Point( -1, -1 ),
// new Point( 1, -1 ),
// new Point( 1, 1 ),
// new Point( -1, 1 )
// ) ), new WindingRuleSimple() );
// tess4j.addPolygon( new Polygon( Arrays.asList(
// new Point( -1, 1 ),
// new Point( 1, 1 ),
// new Point( 1, 3 ),
// new Point( -1, 3 )
// ) ), new WindingRuleSimple() );
// tess4j.addPolygon( new Polygon( Arrays.asList(
// new Point( -2, -1 ),
// new Point( -1, -1 ),
// new Point( -1, 2 ),
// new Point( -2, 2 )
// ) ), new WindingRuleSimple() );
// tess4j.addPolygon( new Polygon( Arrays.asList(
// new Point( -5, 0 ),
// new Point( -2, 0 ),
// new Point( -2, 1 ),
// new Point( -5, 1 )
// ) ), new WindingRuleSimple() );
// tess4j.addPolygon( new Polygon( Arrays.asList(
// new Point( -1.75, .5 ),
// new Point( 4.25, .5 ),
// new Point( -0.25, -2.5 ),
// new Point( 1.25, 2 ),
// new Point( 2.75, -2.5 )
// ) ), new WindingRuleSimple() );
// tess4j.addPolygon( new Polygon( Arrays.asList(
// new Point( -4, -2 ),
// new Point( -1, -2 ),
// new Point( -1, 1.5 ),
// new Point( -4, 1.5 )
// ) ), new WindingRuleSimple() );
// tess4j.addPolygon( new Polygon( Arrays.asList(
// new Point( -1, 0 ),
// new Point( 0, 1.5 ),
// new Point( 1, 0 )
// ) ), new WindingRuleSimple() );
// tess4j.addPolygon( new Polygon( Arrays.asList(
// new Point( 1, 0 ),
// new Point( 0, -2 ),
// new Point( -1, 0 )
// ) ), new WindingRuleSimple() );
for ( int i = 0; i < 4; i++ ) {
for ( int j = 0; j < 4; j++ ) {
tess4j.addPolygon( new Polygon( Arrays.asList(
new Point( i, j ),
new Point( i, j + 1 ),
new Point( i + 1, j + 1 ),
new Point( i + 1, j )
) ), new WindingRuleSimple() );
// tess4j.addPolygon( new Polygon( Arrays.asList(
// new Point( i, j ),
// new Point( i, j + 1 ),
// new Point( i + 1, j ),
// new Point( i + 1, j + 1 )
// ) ), new WindingRuleSimple() );
}
}
tess4j.tessellate();
List< Polygon > polygons = tess4j.getPolygons();
System.out.println( "Polygon count" );
System.out.println( polygons.size() );
for ( Polygon p : polygons ) {
System.out.println( p.getPoints().size() );
int size = p.getPoints().size();
int[] xPoints = new int[ size ];
int[] yPoints = new int[ size ];
for ( int i = 0; i < p.getPoints().size(); i++ ) {
Point point = p.getPoints().get( i );
System.out.println( point.getX() + ", " + point.getY() );
Vector2d pVec = new Vector2d( point.getX(), point.getY() );
pVec = rotate( pVec, 0 );
point = new Point( pVec.getX(), pVec.getY() );
xPoints[ i ] = ( int ) ( point.getX() * scale ) + centerX;
yPoints[ i ] = 100 - ( int ) ( point.getY() * scale ) + centerY;
}
g.setColor( new Color( ( int ) ( Math.random() * 0xFFFFFF ) ) );
g.fillPolygon( xPoints, yPoints, size );
}
g.setColor( Color.BLACK );
for ( Polygon p : polygons ) {
for ( Point point : p.getPoints() ) {
Vector2d pVec = new Vector2d( point.getX(), point.getY() );
pVec = rotate( pVec, 0 );
point = new Point( pVec.getX(), pVec.getY() );
double diff = scale * .05;
g.drawRect( ( int ) ( point.getX() * scale ) + centerX - ( int ) diff, 100 - ( int ) ( point.getY() * scale ) + centerY - ( int ) diff, ( int ) ( diff * 2 ), ( int ) ( diff * 2 ) );
}
}
g.drawLine( centerX, 0, centerX, 2000 );
g.drawLine( 0, centerY + 100, 2000, centerY + 100 );
// Point[] points = {
// new Point( 0, -2 ),
// new Point( 1.5, -3.0 ),
// new Point( 0.0, -2.0 ),
// new Point( 0.9545454545454546, -1.3636363636363638 ),
// new Point( -0.8333333333333334, -1.0 ),
// new Point( 0.8333333333333334, -1.0 ),
// new Point( -0.5, 0.0 ),
// new Point( 0.5, 0.0 ),
// new Point( -0.16666666666666669, 1.0 ),
// new Point( 0.16666666666666669, 1.0 ),
// new Point( -0.16666666666666669, 1.0 ),
// new Point( 1, 1 ),
// new Point( -0.16666666666666669, 1.0 ),
// new Point( 0, 1.5 ),
// new Point( 0, 1.5 ),
// new Point( 0.16666666666666669, 1.0 ),
// new Point( -1, 2 ),
// new Point( 1, 2 ),
// };
//
// int size = points.length >> 1;
// for ( int i = 0; i < size;i++ ) {
// Point a = points[ i << 1 ];
// Point b = points[ ( i << 1 ) + 1 ];
//
// g.drawLine( ( int ) ( a.x * scale ) + centerX, ( int ) ( a.y * scale ) + centerY, ( int ) ( b.x * scale ) + centerX, ( int ) ( b.y * scale ) + centerY );
// }
}
}