diff --git a/.gitignore b/.gitignore index 65dcd5c..d3f0f49 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,6 @@ chunks new_chunks images chunk_models -chunk_models_new \ No newline at end of file +chunk_models_new +chunks_test +chunk_models_test \ No newline at end of file diff --git a/src/main/java/com/aaaaahhhhhhh/bananapuncher714/minietest/MiniePlugin.java b/src/main/java/com/aaaaahhhhhhh/bananapuncher714/minietest/MiniePlugin.java index b2699bc..db681da 100644 --- a/src/main/java/com/aaaaahhhhhhh/bananapuncher714/minietest/MiniePlugin.java +++ b/src/main/java/com/aaaaahhhhhhh/bananapuncher714/minietest/MiniePlugin.java @@ -3,11 +3,17 @@ package com.aaaaahhhhhhh.bananapuncher714.minietest; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.stream.Collectors; import java.util.Set; import org.apache.commons.lang.SystemUtils; @@ -36,11 +42,18 @@ import org.bukkit.util.Vector; import org.joml.Matrix4f; import org.joml.Quaternionf; +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.command.SubCommand; import com.aaaaahhhhhhh.bananapuncher714.minietest.command.executor.CommandExecutableMessage; import com.aaaaahhhhhhh.bananapuncher714.minietest.command.validator.InputValidatorInt; import com.aaaaahhhhhhh.bananapuncher714.minietest.command.validator.sender.SenderValidatorPlayer; 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.util.FileUtil; import com.jme3.bullet.PhysicsSpace; import com.jme3.bullet.PhysicsSpace.BroadphaseType; @@ -52,8 +65,10 @@ import com.jme3.bullet.collision.PhysicsCollisionObject; import com.jme3.bullet.collision.shapes.BoxCollisionShape; import com.jme3.bullet.collision.shapes.CollisionShape; import com.jme3.bullet.collision.shapes.CompoundCollisionShape; +import com.jme3.bullet.collision.shapes.MeshCollisionShape; import com.jme3.bullet.collision.shapes.PlaneCollisionShape; import com.jme3.bullet.collision.shapes.SphereCollisionShape; +import com.jme3.bullet.collision.shapes.infos.IndexedMesh; import com.jme3.bullet.joints.New6Dof; import com.jme3.bullet.joints.PhysicsJoint; import com.jme3.bullet.joints.motors.MotorParam; @@ -65,7 +80,9 @@ import com.jme3.math.Quaternion; import com.jme3.math.Vector3f; import net.minecraft.core.BlockPosition; +import net.minecraft.server.level.WorldServer; import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraft.world.phys.shapes.VoxelShapeCollision; public class MiniePlugin extends JavaPlugin { private static final int TIME_STEPS = 5; @@ -77,6 +94,8 @@ public class MiniePlugin extends JavaPlugin { private float tick = 0; private Map< PhysicsCollisionObject, AuxiliaryDisplayStruct > linkedDisplays = new HashMap< PhysicsCollisionObject, AuxiliaryDisplayStruct >(); + private PhysicsRigidBody planeBody; + private Set< PhysicsCollisionObject > active = new HashSet< PhysicsCollisionObject >(); private Set< PhysicsCollisionObject > isTnt = new HashSet< PhysicsCollisionObject >(); @@ -101,9 +120,9 @@ public class MiniePlugin extends JavaPlugin { space = new PhysicsSpace( BroadphaseType.DBVT ); PlaneCollisionShape plane = new PlaneCollisionShape( new Plane( new Vector3f( 0, 1, 0 ), 0 ) ); - PhysicsRigidBody planeBody = new PhysicsRigidBody( plane, PhysicsBody.massForStatic ); + planeBody = new PhysicsRigidBody( plane, PhysicsBody.massForStatic ); planeBody.setPhysicsLocation( new Vector3f( 0, 128, 0 ) ); - space.addCollisionObject( planeBody ); +// space.addCollisionObject( planeBody ); space.setAccuracy( 1f / ( TIME_STEPS * 20f ) ); space.addContactListener( new ContactListener() { @@ -139,9 +158,9 @@ public class MiniePlugin extends JavaPlugin { @EventHandler private void onChunkLoad( ChunkLoadEvent event ) { if ( event.getWorld().getName().equalsIgnoreCase( "world" ) ) { - getLogger().info( "Loading chunk..." ); +// getLogger().info( "Loading chunk..." ); // scanAndGenerate( event.getChunk() ); - saveChunk( event.getChunk() ); +// saveChunk( event.getChunk() ); } } @@ -158,8 +177,8 @@ public class MiniePlugin extends JavaPlugin { }, this ); - getLogger().info( "There are " + Bukkit.getWorld( "world" ).getLoadedChunks().length + " chunks" ); - getLogger().info( "Converted " + saveAllChunks( Bukkit.getWorld( "world" ) ) ); +// getLogger().info( "There are " + Bukkit.getWorld( "world" ).getLoadedChunks().length + " chunks" ); +// getLogger().info( "Converted " + saveAllChunks( Bukkit.getWorld( "world" ) ) ); Bukkit.getScheduler().runTaskTimer( this, () -> { if ( !paused ) { @@ -279,9 +298,7 @@ public class MiniePlugin extends JavaPlugin { displayData = Material.TNT.createBlockData(); } - CraftBlockData data = ( CraftBlockData ) displayData; - - BoundingBox[] boxes = convertFrom( data.getState().f( null, null ) ); + BoundingBox[] boxes = convertFrom( getShape( displayData, null, BlockShapeType.VISUAL_SHAPE ) ); Vector blockCenter = calculateCenter( boxes ); CollisionShape box; @@ -338,12 +355,10 @@ public class MiniePlugin extends JavaPlugin { loc.setDirection( new Vector( 0, 0, 0 ) ); BlockData displayData = Material.IRON_TRAPDOOR.createBlockData(); - CraftBlockData data = ( CraftBlockData ) displayData; final Vector scale = new Vector( 5, 2, 5 ); - BlockPosition pos = new BlockPosition( loc.getBlockX(), loc.getBlockY(), loc.getBlockZ() ); - BoundingBox[] boxes = convertFrom( data.getState().f( ( ( CraftWorld ) loc.getWorld() ).getHandle(), pos ) ); + BoundingBox[] boxes = convertFrom( getShape( displayData, loc, BlockShapeType.VISUAL_SHAPE ) ); for ( BoundingBox box : boxes ) { Vector min = box.getMin().multiply( scale ); Vector max = box.getMax().multiply( scale ); @@ -419,7 +434,30 @@ public class MiniePlugin extends JavaPlugin { Player player = ( Player ) sender; player.sendMessage( "Registering chunk..." ); - player.sendMessage( "Registered " + scanAndGenerate( player.getLocation().getChunk() ) ); + scanAndGenerate( player.getLocation().getChunk() ); + } ) ) + .add( new SubCommand( "plane" ) + .defaultTo( ( sender, args, params ) -> { + Player player = ( Player ) sender; + + if ( planeBody != null ) { + if ( planeBody.getCollisionGroup() == PhysicsCollisionObject.COLLISION_GROUP_01 ) { + player.sendMessage( "Disabling plane" ); + planeBody.setCollisionGroup( PhysicsCollisionObject.COLLISION_GROUP_02 ); + } else { + player.sendMessage( "Enabling plane" ); + planeBody.setCollisionGroup( PhysicsCollisionObject.COLLISION_GROUP_01 ); + } + } else { + player.sendMessage( "Plane does not exist!" ); + } + } ) ) + .add( new SubCommand( "save" ) + .defaultTo( ( sender, args, params ) -> { + Player player = ( Player ) sender; + + player.sendMessage( "Saving chunk..." ); + player.sendMessage( "Saved " + saveChunk( player.getLocation().getChunk() ) + " boxes" ); } ) ) .add( new SubCommand( "toggle" ) .defaultTo( ( sender, args, params ) -> { @@ -485,22 +523,20 @@ public class MiniePlugin extends JavaPlugin { File saveFile = new File( getDataFolder() + "/chunks", chunk.getWorld().getName() + "," + chunk.getX() + "," + chunk.getZ() ); saveFile.getParentFile().mkdirs(); saveFile.delete(); - + int count = 0; try ( FileWriter writer = new FileWriter( saveFile ) ) { World world = chunk.getWorld(); - for ( int y = world.getMinHeight(); y < world.getMaxHeight(); y++ ) { - for ( int z = 0; z < 16; z++ ) { - for ( int x = 0; x < 16; x++ ) { + for ( int y = world.getMinHeight(); y < world.getMaxHeight(); ++y ) { + for ( int z = 0; z < 16; ++z ) { + for ( int x = 0; x < 16; ++x ) { Block block = chunk.getBlock( x, y, z ); if ( !( block.isEmpty() && block.isLiquid() ) ) { BlockState state = block.getState(); - BlockData displayData = state.getBlockData(); + BlockData data = state.getBlockData(); Location loc = block.getLocation(); - CraftBlockData data = ( CraftBlockData ) displayData; - BlockPosition pos = new BlockPosition( loc.getBlockX(), loc.getBlockY(), loc.getBlockZ() ); - BoundingBox[] boxes = convertFrom( data.getState().f( ( ( CraftWorld ) world ).getHandle(), pos ) ); + BoundingBox[] boxes = convertFrom( getShape( data, loc, BlockShapeType.VISUAL_SHAPE ) ); if ( boxes.length > 0 ) { // Save this block @@ -524,130 +560,168 @@ public class MiniePlugin extends JavaPlugin { return count; } - private int scanAndGenerate( World world ) { - int total = 0; + private void scanAndGenerate( World world ) { for ( Chunk chunk : world.getLoadedChunks() ) { - total += scanAndGenerate( chunk ); + scanAndGenerate( chunk ); } - return total; } - private int scanAndGenerate( Chunk chunk ) { - World world = chunk.getWorld(); - CompoundCollisionShape compound = new CompoundCollisionShape(); - int worldHeight = world.getMaxHeight() - world.getMinHeight(); - boolean[][][] isSolid = new boolean[ worldHeight ][ 16 ][ 16 ]; - for ( int y = 0; y < worldHeight; y++ ) { - for ( int z = 0; z < 16; z++ ) { - for ( int x = 0; x < 16; x++ ) { - Block block = chunk.getBlock( x, y + world.getMinHeight(), z ); + private void scanAndGenerate( final Chunk chunk ) { + final long start = System.currentTimeMillis(); + + final World world = chunk.getWorld(); + final int worldMinHeight = world.getMinHeight(); + final int worldMaxHeight = world.getMaxHeight(); + final Collection< BoundingBox > boxes = new ArrayDeque< BoundingBox >(); + getLogger().info( "Gathering bounding boxes..." ); + for ( int y = worldMinHeight; y < worldMaxHeight; ++y ) { + for ( int z = 0; z < 16; ++z ) { + for ( int x = 0; x < 16; ++x ) { + Block block = chunk.getBlock( x, y, z ); if ( !( block.isEmpty() && block.isLiquid() ) ) { - BlockState state = block.getState(); - BlockData displayData = state.getBlockData(); - Location loc = block.getLocation(); - CraftBlockData data = ( CraftBlockData ) displayData; + final BlockData data = block.getBlockData(); + final Location loc = block.getLocation(); - BlockPosition pos = new BlockPosition( loc.getBlockX(), loc.getBlockY(), loc.getBlockZ() ); - BoundingBox[] boxes = convertFrom( data.getState().f( ( ( CraftWorld ) world ).getHandle(), pos ) ); - - if ( boxes.length == 1 && boxes[ 0 ].getVolume() == 1 ) { - isSolid[ y ][ z ][ x ] = true; + // Start the box at 0, 0, 0 + final BoundingBox[] boundingBoxes = convertFrom( getShape( data, loc, BlockShapeType.VISUAL_SHAPE ), new Vector( x, y - worldMinHeight, z ) ); + + for ( BoundingBox box : boundingBoxes ) { + boxes.add( box ); } } } } } - for ( int y = 0; y < worldHeight; y++ ) { - for ( int z = 0; z < 16; z++ ) { - for ( int x = 0; x < 16; x++ ) { - if ( x > 0 && x < 15 && z > 0 && z < 15 && y > 0 && y < worldHeight - 1 ) { - // Figure out if this block is surrounded by solid blocks to avoid having to add this block - if ( isSolid[ y - 1 ][ z ][ x ] - && isSolid[ y + 1 ][ z ][ x ] - && isSolid[ y ][ z - 1 ][ x ] - && isSolid[ y ][ z + 1 ][ x ] - && isSolid[ y ][ z ][ x - 1 ] - && isSolid[ y ][ z ][ x + 1 ] ) { - continue; - } - - } - - Block block = chunk.getBlock( x, y + world.getMinHeight(), z ); - - if ( !( block.isEmpty() && block.isLiquid() ) ) { - BlockState state = block.getState(); - BlockData displayData = state.getBlockData(); - Location loc = block.getLocation(); - CraftBlockData data = ( CraftBlockData ) displayData; - - BlockPosition pos = new BlockPosition( loc.getBlockX(), loc.getBlockY(), loc.getBlockZ() ); - BoundingBox[] boxes = convertFrom( data.getState().f( ( ( CraftWorld ) world ).getHandle(), pos ) ); - - if ( boxes.length == 0 ) { - continue; - } - - if ( boxes.length == 1 ) { - Vector min = boxes[ 0 ].getMin(); - Vector center = boxes[ 0 ].getCenter().subtract( min ); - Vector3f halfExtents = new Vector3f( ( float ) center.getX(), ( float ) center.getY(), ( float ) center.getZ() ); - - CollisionShape shape = collisionShapes.get( halfExtents ); - if ( shape == null ) { - shape = new BoxCollisionShape( halfExtents ); - collisionShapes.put( halfExtents, shape ); - } - Vector3f shapeCenter = new Vector3f( ( float ) boxes[ 0 ].getCenterX() + x, ( float ) boxes[ 0 ].getCenterY() + y, ( float ) boxes[ 0 ].getCenterZ() + z ); - compound.addChildShape( shape, shapeCenter ); - } else { - for ( BoundingBox aabb : boxes ) { - Vector min = aabb.getMin(); - Vector center = aabb.getCenter(); - Vector half = center.clone().subtract( min ); - Vector3f halfExtents = new Vector3f( ( float ) half.getX(), ( float ) half.getY(), ( float ) half.getZ() ); - - CollisionShape shape = collisionShapes.get( halfExtents ); - if ( shape == null ) { - shape = new BoxCollisionShape( halfExtents ); - collisionShapes.put( halfExtents, shape ); - } - compound.addChildShape( shape, ( float ) center.getX() + x, ( float ) center.getY() + y, ( float ) center.getZ() + z ); - } - } - } + Bukkit.getScheduler().runTaskAsynchronously( this, () -> { + getLogger().info( "Building planes..." ); + final MeshBuilder builder = new MeshBuilder(); + for ( final BoundingBox box : boxes ) { + for ( final Facet facet : generateFacetsFor( box ) ) { + builder.addFacet( facet ); } } - } - - getLogger().info( "Chunk has " + compound.countChildren() ); - - // Create a rigid body - PhysicsRigidBody rigid = new PhysicsRigidBody( compound, PhysicsBody.massForStatic ); - rigid.setPhysicsLocation( new Vector3f( chunk.getX() << 4, world.getMinHeight(), chunk.getZ() << 4 ) ); - rigid.setPhysicsRotation( new Quaternion( 0, 0, 0, 1 ) ); - - space.addCollisionObject( rigid ); - - PhysicsRigidBody old = chunks.put( new ChunkLocation( chunk ), rigid ); - if ( old != null ) { - getLogger().warning( "Old rigid body found!" ); - space.remove( old ); - } - - return compound.countChildren(); + + getLogger().info( "Meshing planes..." ); + Collection< Facet > facets = builder.planes.parallelStream().flatMap( p -> process( p ).parallelStream().map( p::convert ) ).collect( Collectors.toSet() ); + + final class VectorRef { + int index; + } + + final class Triangle { + List< VectorRef > refs = new ArrayList< VectorRef >(); + } + + final Map< Vector, VectorRef > vertices = new HashMap< Vector, VectorRef >(); + final List< Triangle > triangles = new ArrayList< Triangle >(); + + getLogger().info( "Generating triangles..." ); + // 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 ); + } + } ); + + getLogger().info( "Creating buffers..." ); + final Vector3f[] positionArray = new Vector3f[ sorted.size() ]; + 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(); + + positionArray[ i ] = new Vector3f( ( float ) vector.getX(), ( float ) vector.getY(), ( float ) vector.getZ() ); + } + + final int[] indexArray = new int[ triangles.size() * 3 ]; + for ( int i = 0; i < triangles.size(); ++i ) { + final Triangle triangle = triangles.get( i ); + if ( triangle.refs.size() != 3 ) { + throw new IllegalStateException( "Triangle does not have exactly 3 vertices!" ); + } + + final int indexArrayStart = i * 3; + indexArray[ indexArrayStart ] = triangle.refs.get( 0 ).index; + indexArray[ indexArrayStart + 1 ] = triangle.refs.get( 1 ).index; + indexArray[ indexArrayStart + 2 ] = triangle.refs.get( 2 ).index; + } + + getLogger().info( "Adding mesh collision shape..." ); + final IndexedMesh nativeMesh = new IndexedMesh( positionArray, indexArray ); + // Enable quantized AABB compression... hopefully that doesn't mess with the accuracy or anything... + final MeshCollisionShape mesh = new MeshCollisionShape( true, nativeMesh ); + + getLogger().info( "Mesh has " + mesh.countMeshVertices() + " vertices and " + mesh.countMeshTriangles() + " triangles" ); + + // Create a rigid body + PhysicsRigidBody rigid = new PhysicsRigidBody( mesh, PhysicsBody.massForStatic ); + rigid.setPhysicsLocation( new Vector3f( chunk.getX() << 4, world.getMinHeight(), chunk.getZ() << 4 ) ); + rigid.setPhysicsRotation( new Quaternion( 0, 0, 0, 1 ) ); + rigid.setKinematic( false ); + + Bukkit.getScheduler().runTask( this, () -> { + space.addCollisionObject( rigid ); + + PhysicsRigidBody old = chunks.put( new ChunkLocation( chunk ), rigid ); + if ( old != null ) { + getLogger().warning( "Old rigid body found!" ); + space.remove( old ); + } + getLogger().info( "Done!" ); + final long time = System.currentTimeMillis() - start; + getLogger().info( "Took " + time + "ms" ); + } ); + } ); } private boolean convert( Block block ) { BlockState state = block.getState(); - BlockData displayData = state.getBlockData(); + BlockData data = state.getBlockData(); Location loc = block.getLocation(); - CraftBlockData data = ( CraftBlockData ) displayData; - - BlockPosition pos = new BlockPosition( loc.getBlockX(), loc.getBlockY(), loc.getBlockZ() ); - BoundingBox[] boxes = convertFrom( data.getState().f( ( ( CraftWorld ) loc.getWorld() ).getHandle(), pos ) ); + BoundingBox[] boxes = convertFrom( getShape( data, loc, BlockShapeType.VISUAL_SHAPE ) ); Vector blockCenter = calculateCenter( boxes ); CollisionShape box; @@ -714,6 +788,15 @@ public class MiniePlugin extends JavaPlugin { return true; } + private static Collection< Polygon > process( final com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.Plane plane ) { + final Mesh< RegionSimple > mesh = new Mesh< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } ); + for ( Polygon poly : plane.polygons ) { + mesh.addPolygon( poly, RegionRuleWinding.CLOCKWISE ); + } + + return mesh.meshify(); + } + private static Vector calculateCenter( BoundingBox[] boxes ) { Vector center = new Vector( 0, 0, 0 ); // TODO Throw error, probably @@ -730,12 +813,117 @@ public class MiniePlugin extends JavaPlugin { return center.multiply( 1 / totalVolume ); } - private static BoundingBox[] convertFrom( VoxelShape shape ) { + // 1.21.5 + private static VoxelShape getShape( BlockData blockData, Location location, BlockShapeType type ) { + final CraftBlockData data = ( CraftBlockData ) blockData; + + WorldServer server = null; + BlockPosition pos = null; + if ( location != null ) { + server = ( ( CraftWorld ) location.getWorld() ).getHandle(); + pos = new BlockPosition( location.getBlockX(), location.getBlockY(), location.getBlockZ() ); + } + + switch ( type ) { + default: + case SHAPE: + return data.getState().f( server, pos ); + case COLLISION_SHAPE: + return data.getState().g( server, pos ); + case VISUAL_SHAPE: + return data.getState().c( server, pos, VoxelShapeCollision.a() ); + case INTERACTION_SHAPE: + return data.getState().i( server, pos ); + case BLOCK_SUPPORT_SHAPE: + return data.getState().h( server, pos ); + } + } + + private static BoundingBox[] convertFrom( final VoxelShape shape ) { + return convertFrom( shape, new Vector() ); + } + + private static BoundingBox[] convertFrom( final VoxelShape shape, final Vector offset ) { return shape.e().stream() - .map( aabb -> { return new BoundingBox( aabb.a, aabb.b, aabb.c, aabb.d, aabb.e, aabb.f ); } ) + .map( aabb -> { return new BoundingBox( aabb.a, aabb.b, aabb.c, aabb.d, aabb.e, aabb.f ).shift( offset ); } ) .toArray( BoundingBox[]::new ); } + private static List< Facet > generateFacetsFor( BoundingBox box ) { + List< Facet > facets = new ArrayList< Facet >(); + + Vector p1 = new Vector( box.getMinX(), box.getMinY(), box.getMinZ() ); + Vector p2 = new Vector( box.getMinX(), box.getMinY(), box.getMaxZ() ); + Vector p3 = new Vector( box.getMinX(), box.getMaxY(), box.getMinZ() ); + Vector p4 = new Vector( box.getMinX(), box.getMaxY(), box.getMaxZ() ); + Vector p5 = new Vector( box.getMaxX(), box.getMinY(), box.getMinZ() ); + Vector p6 = new Vector( box.getMaxX(), box.getMinY(), box.getMaxZ() ); + Vector p7 = new Vector( box.getMaxX(), box.getMaxY(), box.getMinZ() ); + Vector p8 = new Vector( box.getMaxX(), box.getMaxY(), box.getMaxZ() ); + + { + 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; + } + private class JointStruct { BlockState state; PhysicsRigidBody object; @@ -765,4 +953,13 @@ public class MiniePlugin extends JavaPlugin { Vector offset; Vector scale; } + + private enum BlockShapeType { + SHAPE, + COLLISION_SHAPE, + VISUAL_SHAPE, + INTERACTION_SHAPE, + BLOCK_SUPPORT_SHAPE + + } }