Create standalone physics plugin

This commit is contained in:
2026-03-18 01:03:39 -04:00
parent 70049922c5
commit 3f4b4c6975
10 changed files with 883 additions and 444 deletions

View File

@@ -66,19 +66,6 @@
<release>21</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.aaaaahhhhhhh.bananapuncher714.minietest.MeshingTest6</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,10 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.ChunkLocation;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.ChunkMesh;
public interface EnvironmentHandler {
public void onMeshLoad( ChunkLocation location, ChunkMesh mesh );
public void onMeshUnload( ChunkLocation location, ChunkMesh mesh );
public void onMeshUpdate( ChunkLocation location, ChunkMesh mesh );
}

View File

@@ -69,26 +69,24 @@ public class MeshEnvironment {
private ChunkMeshCache cache;
private EnvironmentHandler handler;
private ReentrantLock lock = new ReentrantLock();
final BukkitTask task = Bukkit.getScheduler().runTaskTimer( plugin, () -> {
// final Collection< ChunkLocation > locations = new ArrayDeque< ChunkLocation >();
lock.lock();
updateLocations.entrySet().stream().forEach( e -> {
ChunkMesh mesh = chunkMeshes.get( e.getKey() );
if ( mesh != null ) {
final Collection< Location > locs = update( mesh, e.getValue() );
e.getValue().removeAll( locs );
// if ( !locs.isEmpty() ) {
// locations.add( e.getKey() );
// }
if ( handler != null && !locs.isEmpty() ) {
handler.onMeshUpdate( e.getKey(), mesh );
}
}
} );
// if ( !locations.isEmpty() ) {
// space.activateAll( true );
// }
updateLocations.values().removeIf( c -> c.isEmpty() );
lock.unlock();
}, 1, 1 );
@@ -204,11 +202,20 @@ public class MeshEnvironment {
HandlerList.unregisterAll( eventListener );
}
public void load( ChunkLocation location ) {
loadMesh( location );
}
public void setHandler( EnvironmentHandler handler ) {
this.handler = handler;
}
private void completeTask( ChunkLocation location ) {
lock.lock();
try {
final ChunkTask task = tasks.remove( location );
if ( task.type == ChunkTaskType.LOAD ) {
handler.onMeshLoad( location, chunkMeshes.get( location ) );
if ( !location.isLoaded() ) {
// Update all and unload
unloadMesh( location );
@@ -223,7 +230,11 @@ public class MeshEnvironment {
if ( updateLocations.containsKey( location ) ) {
unloadMesh( location );
} else {
chunkMeshes.remove( location );
final ChunkMesh mesh = chunkMeshes.remove( location );
if ( handler != null ) {
handler.onMeshUnload( location, mesh );
}
}
} else {
// Chunk is loaded, but we saved. Do nothing
@@ -315,7 +326,12 @@ public class MeshEnvironment {
final ChunkMesh mesh = chunkMeshes.get( location );
if ( locations != null && !locations.isEmpty() && mesh != null ) {
locations.removeAll( update( mesh, locations ) );
final Collection< Location > removed = update( mesh, locations );
locations.removeAll( removed );
if ( handler != null && !removed.isEmpty() ) {
handler.onMeshUpdate( location, mesh );
}
return locations.isEmpty();
}
@@ -326,7 +342,7 @@ public class MeshEnvironment {
return true;
}
private static void generateSpareMesh( JavaPlugin plugin, World world, Collection< Vector > locations, Consumer< SparseMesh > callback ) {
public static void generateSpareMesh( JavaPlugin plugin, World world, Collection< Vector > locations, Consumer< SparseMesh > callback ) {
if ( locations.isEmpty() ) {
return;
}
@@ -492,7 +508,7 @@ public class MeshEnvironment {
}
// TODO Use ChunkSnapshot in the future
private static void generateMesh( JavaPlugin plugin, World world, final Chunk chunk, Consumer< ChunkMesh > callback ) {
public static void generateMesh( JavaPlugin plugin, World world, final Chunk chunk, Consumer< ChunkMesh > callback ) {
final int worldMinHeight = world.getMinHeight();
final int worldMaxHeight = world.getMaxHeight();
final int worldHeight = worldMaxHeight - worldMinHeight;
@@ -654,7 +670,7 @@ public class MeshEnvironment {
} );
}
private static Collection< Location > update( final AbstractMesh mesh, final Collection< Location > locations ) {
public static Collection< Location > update( final AbstractMesh mesh, final Collection< Location > locations ) {
if ( locations.isEmpty() ) {
return Collections.emptySet();
}
@@ -891,7 +907,7 @@ public class MeshEnvironment {
return canRemove;
}
private static MeshResult generateMeshFrom( final Map< MinecraftPlane, Collection< Polygon > > polygons ) {
public static MeshResult generateMeshFrom( final Map< MinecraftPlane, Collection< Polygon > > polygons ) {
final Map< MinecraftPlane, Mesh< RegionSimple > > meshMap = new HashMap< MinecraftPlane, Mesh< RegionSimple > >();
for ( final Entry< MinecraftPlane, Collection< Polygon > > entry : polygons.entrySet() ) {
final MinecraftPlane plane = entry.getKey();
@@ -989,7 +1005,7 @@ public class MeshEnvironment {
}
}
private static class MeshResult {
public static class MeshResult {
Map< MinecraftPlane, PlaneMesh > meshes;
TreeSet< VectorReference > points;
}

View File

@@ -1,14 +1,6 @@
name: MC-Mesh-Environment
main: com.aaaaahhhhhhh.bananapuncher714.minietest.MiniePlugin
main: com.aaaaahhhhhhh.bananapuncher714.mesh.environment.McMeshEnvironmentPlugin
version: 0.0.1
description: BulletJME and MC-Mesh integration
author: BananaPuncher714
api-version: 1.13
#libraries:
#- com.github.stephengold:Minie:7.5.0
commands:
minie:
description: Main Minie command
aliases: []
permission: minie

53
plugin/physics/pom.xml Normal file
View File

@@ -0,0 +1,53 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.aaaaahhhhhhh.bananapuncher714</groupId>
<artifactId>mc-mesh-plugin</artifactId>
<version>0.0.1</version>
</parent>
<artifactId>mc-mesh-plugin-physics</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.21.10-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.aaaaahhhhhhh.bananapuncher714</groupId>
<artifactId>mc-mesh-plugin-environment</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.14.1</version>
<configuration>
<release>21</release>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,22 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.physics;
import org.bukkit.entity.Display;
import org.bukkit.util.Vector;
class AuxiliaryDisplayStruct {
Display display;
Vector offset;
Vector scale;
AuxiliaryDisplayStruct( Display display, Vector offset ) {
this.display = display;
this.offset = offset.clone();
this.scale = new Vector( 1, 1, 1 );
}
AuxiliaryDisplayStruct setScale( Vector scale ) {
this.scale = scale.clone();
return this;
}
}

View File

@@ -0,0 +1,342 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.physics;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.BlockDisplay;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.Transformation;
import org.bukkit.util.Vector;
import org.joml.Matrix4f;
import org.joml.Quaternionf;
import com.aaaaahhhhhhh.bananapuncher714.mesh.command.CommandParameters;
import com.aaaaahhhhhhh.bananapuncher714.mesh.command.SubCommand;
import com.aaaaahhhhhhh.bananapuncher714.mesh.command.executor.CommandExecutableMessage;
import com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.InputValidatorDouble;
import com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.InputValidatorInt;
import com.aaaaahhhhhhh.bananapuncher714.mesh.command.validator.sender.SenderValidatorPlayer;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.EnvironmentHandler;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.MeshEnvironment;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.ChunkLocation;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.ChunkMesh;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.util.NmsUtil;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.util.NmsUtil.BlockShapeType;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.PhysicsSpace.BroadphaseType;
import com.jme3.bullet.collision.PhysicsCollisionEvent;
import com.jme3.bullet.collision.PhysicsCollisionListener;
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.SphereCollisionShape;
import com.jme3.bullet.collision.shapes.infos.IndexedMesh;
import com.jme3.bullet.objects.PhysicsBody;
import com.jme3.bullet.objects.PhysicsRigidBody;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
public class McMeshPhysicsPlugin extends JavaPlugin {
private static final int TIME_STEPS = 5;
private static final float SIMULATION_SPEED = 1f;
private MeshEnvironment environment;
private PhysicsSpace space;
private boolean paused = false;
private boolean teleportOnDeactivate = false;
private float tick = 0;
private Map< PhysicsCollisionObject, AuxiliaryDisplayStruct > linkedDisplays = new HashMap< PhysicsCollisionObject, AuxiliaryDisplayStruct >();
private Set< PhysicsCollisionObject > active = new HashSet< PhysicsCollisionObject >();
private Map< ChunkLocation, PhysicsRigidBody > chunks = new HashMap< ChunkLocation, PhysicsRigidBody >();
@Override
public void onEnable() {
registerCommands();
space = new PhysicsSpace( BroadphaseType.DBVT );
space.setAccuracy( 1f / ( TIME_STEPS * 20f ) );
environment = new MeshEnvironment( this, new File( getDataFolder(), "environment" ) );
environment.setHandler( new EnvironmentHandler() {
@Override
public void onMeshLoad( ChunkLocation location, ChunkMesh mesh ) {
// Now, create a physics object from the chunk mesh
final IndexedMesh nativeMesh = mesh.toIndexedMesh();
// Enable quantized AABB compression... hopefully that doesn't mess with the accuracy or anything...
final MeshCollisionShape meshCollision = new MeshCollisionShape( true, nativeMesh );
// Create a rigid body
PhysicsRigidBody rigid = new PhysicsRigidBody( meshCollision, PhysicsBody.massForStatic );
rigid.setPhysicsLocation( new Vector3f( location.getX() << 4, location.getWorld().getMinHeight(), location.getZ() << 4 ) );
rigid.setPhysicsRotation( new Quaternion( 0, 0, 0, 1 ) );
rigid.setKinematic( false );
Bukkit.getScheduler().runTask( McMeshPhysicsPlugin.this, () -> {
space.addCollisionObject( rigid );
PhysicsRigidBody old = chunks.put( location, rigid );
if ( old != null ) {
space.remove( old );
}
} );
}
@Override
public void onMeshUnload( ChunkLocation location, ChunkMesh mesh ) {
space.removeCollisionObject( chunks.get( location ) );
}
@Override
public void onMeshUpdate( ChunkLocation location, ChunkMesh mesh ) {
// Now, create a physics object from the chunk mesh
final IndexedMesh nativeMesh = mesh.toIndexedMesh();
// Enable quantized AABB compression... hopefully that doesn't mess with the accuracy or anything...
final MeshCollisionShape meshCollision = new MeshCollisionShape( true, nativeMesh );
// Create a rigid body
PhysicsRigidBody rigid = new PhysicsRigidBody( meshCollision, PhysicsBody.massForStatic );
rigid.setPhysicsLocation( new Vector3f( location.getX() << 4, location.getWorld().getMinHeight(), location.getZ() << 4 ) );
rigid.setPhysicsRotation( new Quaternion( 0, 0, 0, 1 ) );
rigid.setKinematic( false );
Bukkit.getScheduler().runTask( McMeshPhysicsPlugin.this, () -> {
space.addCollisionObject( rigid );
PhysicsRigidBody old = chunks.put( location, rigid );
if ( old != null ) {
space.remove( old );
}
} );
space.activateAll( true );
}
} );
Bukkit.getScheduler().runTaskTimer( this, () -> {
if ( !paused ) {
// Update the real world with the physics space objects
space.distributeEvents();
space.update( tick, TIME_STEPS );
for ( Iterator< Entry< PhysicsCollisionObject, AuxiliaryDisplayStruct > > it = linkedDisplays.entrySet().iterator(); it.hasNext(); ) {
Entry< PhysicsCollisionObject, AuxiliaryDisplayStruct > entry = it.next();
PhysicsCollisionObject obj = entry.getKey();
AuxiliaryDisplayStruct disp = entry.getValue();
if ( !disp.display.isValid() ) {
it.remove();
space.removeCollisionObject( obj );
continue;
}
Location displayLocation = disp.display.getLocation();
// Do not calculate for this object if it is inactive
if ( !obj.isActive() ) {
if ( teleportOnDeactivate && active.remove( obj ) ) {
// Newly deactivated object, teleport the display to the actual position to prevent the translation from getting too large
Transformation currentTransformation = disp.display.getTransformation();
org.joml.Vector3f trans = currentTransformation.getTranslation();
displayLocation.add( trans.x(), trans.y(), trans.z() );
disp.display.teleport( displayLocation );
Transformation newTrans = new Transformation( new org.joml.Vector3f( 0, 0, 0 ), currentTransformation.getLeftRotation(), currentTransformation.getScale(), currentTransformation.getRightRotation() );
disp.display.setInterpolationDelay( 0 );
disp.display.setInterpolationDuration( 0 );
disp.display.setTransformation( newTrans );
}
continue;
} else {
active.add( obj );
}
Vector3f location = obj.getPhysicsLocation();
Quaternion rotation = new Quaternion();
obj.getPhysicsRotation( rotation );
Vector offsetVec = disp.offset;
Vector scale = disp.scale;
Matrix4f transformRot = new Matrix4f();
transformRot.set( new Quaternionf( rotation.getX(), rotation.getY(), rotation.getZ(), rotation.getW() ) );
transformRot.mul( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, - ( float ) offsetVec.getX(), - ( float ) offsetVec.getY(), - ( float ) offsetVec.getZ(), 1 );
transformRot.mul( ( float ) scale.getX(), 0, 0, 0, 0, ( float ) scale.getY(), 0, 0, 0, 0, ( float ) scale.getZ(), 0, 0, 0, 0, 1 );
Matrix4f transMat = new Matrix4f( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ( float ) ( location.getX() - displayLocation.getX() ), ( float ) ( location.getY() - displayLocation.getY() ), ( float ) ( location.getZ() - displayLocation.getZ() ), 1 );
disp.display.setInterpolationDelay( 0 );
disp.display.setInterpolationDuration( 2 );
disp.display.setTransformationMatrix( transMat.mul( transformRot ) );
}
tick += SIMULATION_SPEED / 20f;
}
}, 0, 1 );
}
private void registerCommands() {
new SubCommand( "minie" )
.addSenderValidator( new SenderValidatorPlayer() )
.add( new SubCommand( "spawn" )
.add( new SubCommand( new InputValidatorDouble( 0.01, 100 ) )
.defaultTo( this::spawnBlock ) )
.defaultTo( this::spawnBlock ) )
.add( new SubCommand( "toggle" )
.defaultTo( ( sender, args, params ) -> {
paused = !paused;
} ) )
.add( new SubCommand( "teleport" )
.defaultTo( ( sender, args, params ) -> {
teleportOnDeactivate = !teleportOnDeactivate;
} ) )
.add( new SubCommand( "impulse" )
.add( new SubCommand( new InputValidatorInt() )
.defaultTo( ( sender, args, params ) -> {
Player player = ( Player ) sender;
Location loc = player.getLocation();
impulse( new Vector3f( ( float ) loc.getX(), ( float ) loc.getY(), ( float ) loc.getZ() ), params.getLast( int.class ) );
} ) )
.defaultTo( ( sender, args, params ) -> {
Player player = ( Player ) sender;
Location loc = player.getLocation();
impulse( new Vector3f( ( float ) loc.getX(), ( float ) loc.getY(), ( float ) loc.getZ() ), 15f );
} ) )
.defaultTo( new CommandExecutableMessage( "An argument must be provided" ) )
.whenUnknown( new CommandExecutableMessage( "Unknown argument" ) )
.applyTo( getCommand( "minie" ) );
}
private void impulse( Vector3f location, float power ) {
PhysicsRigidBody rigid = new PhysicsRigidBody( new SphereCollisionShape( 20 ), 1f );
rigid.setPhysicsLocation( location );
space.contactTest( rigid, new PhysicsCollisionListener() {
@Override
public void collision( PhysicsCollisionEvent event ) {
if ( event.getObjectB() instanceof PhysicsRigidBody ) {
PhysicsRigidBody objB = ( PhysicsRigidBody ) event.getObjectB();
Vector3f rLoc = objB.getPhysicsLocation();
Vector3f to = rLoc.subtract( ( float ) location.getX(), ( float ) location.getY(), ( float ) location.getZ() );
float distSq = to.lengthSquared();
if ( distSq != 0 ) {
if ( power / distSq > 1 ) {
objB.applyCentralImpulse( to.normalize().mult( power / distSq ) );
}
}
}
}
} );
}
private void spawnBlock( final CommandSender sender, final String[] args, final CommandParameters params ) {
Player player = ( Player ) sender;
Location loc = player.getLocation();
// Optional scale
double scale = 1;
if ( params.size() > 2 ) {
scale = params.getFirst( double.class );
}
loc.setPitch( 0 );
loc.setDirection( new Vector( 0, 0, 0 ) );
BlockData displayData;
ItemStack item = player.getInventory().getItemInMainHand();
if ( item != null && item.getType() != Material.AIR && item.getType().isBlock() ) {
displayData = item.getType().createBlockData();
} else {
displayData = Material.TNT.createBlockData();
}
BoundingBox[] boxes = NmsUtil.convertFrom( NmsUtil.getShape( displayData, null, BlockShapeType.SHAPE ) );
Vector blockCenter = calculateCenter( boxes );
CollisionShape box;
if ( boxes.length == 0 ) {
player.sendMessage( "No bounding box detected! Wrong method?" );
return;
}
if ( boxes.length == 1 ) {
Vector min = boxes[ 0 ].getMin();
Vector center = boxes[ 0 ].getCenter().subtract( min );
box = new BoxCollisionShape( ( float ) center.getX(), ( float ) center.getY(), ( float ) center.getZ() );
} else {
CompoundCollisionShape compound = new CompoundCollisionShape();
for ( BoundingBox aabb : boxes ) {
Vector min = aabb.getMin();
Vector center = aabb.getCenter();
Vector half = center.clone().subtract( min );
center.subtract( blockCenter );
CollisionShape subShape = new BoxCollisionShape( ( float ) half.getX(), ( float ) half.getY(), ( float ) half.getZ() );
compound.addChildShape( subShape, ( float ) center.getX(), ( float ) center.getY(), ( float ) center.getZ() );
}
box = compound;
}
box.setScale( ( float ) scale );
PhysicsRigidBody rigid = new PhysicsRigidBody( box, 1f );
// Since the center of the rigid body and the box shape are different, we need to offset the location
rigid.setPhysicsLocation( new Vector3f( ( float ) ( loc.getX() + blockCenter.getX() ), ( float ) ( loc.getY() + blockCenter.getY() ), ( float ) ( loc.getZ() + blockCenter.getZ() ) ) );
// Convert the display direction vector to a quaternion
rigid.setPhysicsRotation( new Quaternion( 0, 0, 0, 1 ) );
rigid.setMass( rigid.getMass() * ( float ) ( scale * scale ) );
space.addCollisionObject( rigid );
// Create the display
BlockDisplay display = loc.getWorld().spawn( loc, BlockDisplay.class, d -> {
d.setBlock( displayData );
d.setViewRange( 1000 );
} );
linkedDisplays.put( rigid, new AuxiliaryDisplayStruct( display, blockCenter.multiply( scale ) ).setScale( new Vector( scale, scale, scale ) ) );
player.sendMessage( "Created display" );
}
private static Vector calculateCenter( BoundingBox[] boxes ) {
Vector center = new Vector( 0, 0, 0 );
// TODO Throw error, probably
if ( boxes.length == 0 ) {
return center;
}
double totalVolume = 0;
for ( BoundingBox box : boxes ) {
Vector mid = box.getCenter();
center.add( mid.multiply( box.getVolume() ) );
totalVolume += box.getVolume();
}
return center.multiply( 1 / totalVolume );
}
}

View File

@@ -1,4 +1,4 @@
package com.aaaaahhhhhhh.bananapuncher714.mesh.environment;
package com.aaaaahhhhhhh.bananapuncher714.mesh.physics;
import java.io.File;
import java.io.FileWriter;
@@ -75,6 +75,7 @@ import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.BlockDataType;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.ChunkLocation;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.ChunkMesh;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.IndexedPolygon;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.IndexedTriangle;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.MinecraftPlane;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.PlaneMesh;
import com.aaaaahhhhhhh.bananapuncher714.mesh.environment.objects.VectorReference;
@@ -1050,7 +1051,7 @@ public class MiniePlugin extends JavaPlugin {
for ( final Entry< Vector, VectorRef > entry : vertices.entrySet() ) {
final Vector existingVec = entry.getKey();
if ( existingVec.distanceSquared( vec ) < 1e-8 ) {
if ( existingVec.distanceSquared( new Vector( vec.getX(), vec.getY(), vec.getZ() ) ) < 1e-8 ) {
ref = entry.getValue();
break;
}
@@ -1058,7 +1059,7 @@ public class MiniePlugin extends JavaPlugin {
if ( ref == null ) {
ref = new VectorRef();
vertices.put( vec, ref );
vertices.put( new Vector( vec.getX(), vec.getY(), vec.getZ() ), ref );
}
triangle.refs.add( ref );
@@ -1313,9 +1314,9 @@ public class MiniePlugin extends JavaPlugin {
// Ignore any planes that are empty
if ( !tris.isEmpty() ) {
final PlaneMesh newMesh = new PlaneMesh();
newMesh.completedPolygons = new ArrayList< IndexedPolygon >();
newMesh.completedPolygons = new ArrayList< IndexedTriangle >();
for ( final Polygon tri : tris ) {
final IndexedPolygon newPoly = new IndexedPolygon();
final IndexedTriangle newPoly = new IndexedTriangle();
for ( final Point point : tri.getPoints() ) {
final Vector vert = plane.convert( point );
@@ -1342,7 +1343,7 @@ public class MiniePlugin extends JavaPlugin {
++ref.referenceCount;
}
newPoly.points.add( ref );
// newPoly.points.add( ref );
}
newMesh.completedPolygons.add( newPoly );
}
@@ -1536,7 +1537,7 @@ public class MiniePlugin extends JavaPlugin {
if ( planeMesh != null ) {
// Reset all indexed polygons(triangles) for this plane
for ( final IndexedPolygon poly : planeMesh.completedPolygons ) {
poly.points.parallelStream().forEach( p -> --p.referenceCount );
// poly.points.parallelStream().forEach( p -> --p.referenceCount );
}
// Add all polygons that were previously generated
@@ -1563,9 +1564,9 @@ public class MiniePlugin extends JavaPlugin {
// Ignore any planes that are empty
if ( !tris.isEmpty() ) {
final PlaneMesh newMesh = new PlaneMesh();
newMesh.completedPolygons = new ArrayList< IndexedPolygon >();
newMesh.completedPolygons = new ArrayList< IndexedTriangle >();
for ( final Polygon tri : tris ) {
final IndexedPolygon newPoly = new IndexedPolygon();
final IndexedTriangle newPoly = new IndexedTriangle();
for ( final Point point : tri.getPoints() ) {
final Vector vert = plane.convert( point );
@@ -1591,7 +1592,7 @@ public class MiniePlugin extends JavaPlugin {
++ref.referenceCount;
}
newPoly.points.add( ref );
// newPoly.points.add( ref );
}
newMesh.completedPolygons.add( newPoly );
}
@@ -1667,12 +1668,12 @@ public class MiniePlugin extends JavaPlugin {
}
final Triangle triangle = new Triangle();
for ( final Vector vec : facet.points ) {
for ( final Vector3d 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 ) {
if ( existingVec.distanceSquared( new Vector( vec.getX(), vec.getY(), vec.getZ() ) ) < 1e-8 ) {
ref = entry.getValue();
break;
}
@@ -1680,7 +1681,7 @@ public class MiniePlugin extends JavaPlugin {
if ( ref == null ) {
ref = new VectorRef();
vertices.put( vec, ref );
vertices.put( new Vector( vec.getX(), vec.getY(), vec.getZ() ), ref );
}
triangle.refs.add( ref );
@@ -1765,10 +1766,10 @@ public class MiniePlugin extends JavaPlugin {
try ( FileWriter writer = new FileWriter( file ) ) {
for ( final Facet facet : facets ) {
final Vector normal = facet.normal;
final Vector3d normal = facet.normal;
writer.write( facet.points.size() + " " + normal.getX() + " " + normal.getY() + " " + normal.getZ() + "\n" );
for ( final Vector point : facet.points ) {
for ( final Vector3d point : facet.points ) {
writer.write( point.getX() + " " + point.getY() + " " + point.getZ() + "\n" );
}
}

View File

@@ -0,0 +1,15 @@
name: MC-Mesh-Physics
main: com.aaaaahhhhhhh.bananapuncher714.mesh.physics.McMeshPhysicsPlugin
version: 0.0.1
description: BulletJME and MC-Mesh integration
author: BananaPuncher714
api-version: 1.13
depend: [ "Mc-Mesh-Environment" ]
#libraries:
#- com.github.stephengold:Minie:7.5.0
commands:
minie:
description: Main Minie command
aliases: []
permission: minie

View File

@@ -13,5 +13,6 @@
<modules>
<module>environment</module>
<module>physics</module>
</modules>
</project>