fix block mesh ray cast bug
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
355abd0991
commit
fcd2f1e0a7
@ -1353,6 +1353,7 @@ Fix TextureInstancedActor packing data texture incorrectly (column major instead
|
||||
|
||||
(03/28/2025)
|
||||
Grass height variance with control from ui + file
|
||||
Fix block mesh ray casting bug due to trimesh overlap
|
||||
|
||||
|
||||
# TODO
|
||||
|
||||
@ -23,7 +23,12 @@ import electrosphere.renderer.meshgen.BlockMeshgen.BlockMeshData;
|
||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||
import electrosphere.server.terrain.manager.ServerTerrainManager;
|
||||
|
||||
|
||||
/**
|
||||
* Handles networking for block-related messages on client
|
||||
*/
|
||||
public class ClientBlockManager {
|
||||
|
||||
//queues messages from server
|
||||
List<TerrainMessage> messageQueue = new LinkedList<TerrainMessage>();
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ import org.ode4j.ode.DMass;
|
||||
import org.ode4j.ode.DSphere;
|
||||
import org.ode4j.ode.DTriMesh;
|
||||
|
||||
import electrosphere.entity.state.collidable.MultiShapeTriGeomData;
|
||||
import electrosphere.entity.state.collidable.TriGeomData;
|
||||
|
||||
/**
|
||||
@ -270,6 +271,35 @@ public class CollisionBodyCreation {
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ode DBody from a mesh data set containing multiple shapes
|
||||
* @param data The mesh data data
|
||||
* @return The DBody
|
||||
*/
|
||||
public static DBody generateBodyFromMultiShapeMeshData(CollisionEngine collisionEngine, MultiShapeTriGeomData data, long categoryBits){
|
||||
DBody body = null;
|
||||
|
||||
DGeom[] geoms = new DGeom[data.getData().size()];
|
||||
|
||||
//create trimeshes
|
||||
int i = 0;
|
||||
for(TriGeomData shapeData : data.getData()){
|
||||
if(shapeData.getFaceElements().length > 0){
|
||||
DTriMesh triMesh = collisionEngine.createTrimeshGeom(shapeData.getVertices(),shapeData.getFaceElements(),categoryBits);
|
||||
geoms[i] = triMesh;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
//create body from shapes
|
||||
body = collisionEngine.createDBody(geoms);
|
||||
collisionEngine.setKinematic(body);
|
||||
collisionEngine.setGravityMode(body, false);
|
||||
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a body from an AIScene
|
||||
* @param scene The AIScene to generate a rigid body off of
|
||||
|
||||
@ -17,6 +17,7 @@ import electrosphere.entity.EntityTags;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.ServerEntityUtils;
|
||||
import electrosphere.entity.state.collidable.ClientCollidableTree;
|
||||
import electrosphere.entity.state.collidable.MultiShapeTriGeomData;
|
||||
import electrosphere.entity.state.collidable.ServerCollidableTree;
|
||||
import electrosphere.entity.state.collidable.TriGeomData;
|
||||
import electrosphere.entity.state.physicssync.ClientPhysicsSyncTree;
|
||||
@ -504,6 +505,21 @@ public class PhysicsEntityUtils {
|
||||
terrain.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
|
||||
}
|
||||
|
||||
/**
|
||||
* [CLIENT ONLY] Given an entity and a multi-shape trimesh description, create physics for the shapes and attach it to the entity
|
||||
* @param terrain The entity
|
||||
* @param data The trimesh description
|
||||
* @return The rigid body created (note, attachment has already been performed)
|
||||
*/
|
||||
public static void clientAttachMultiShapeTriGeomRigidBody(Entity terrain, MultiShapeTriGeomData data){
|
||||
DBody terrainBody = CollisionBodyCreation.generateBodyFromMultiShapeMeshData(Globals.clientSceneWrapper.getCollisionEngine(), data, Collidable.TYPE_STATIC_BIT);
|
||||
CollisionBodyCreation.setAutoDisable(Globals.clientSceneWrapper.getCollisionEngine(), terrainBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD);
|
||||
Collidable collidable = new Collidable(terrain,Collidable.TYPE_STATIC, false);
|
||||
Globals.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, collidable);
|
||||
PhysicsEntityUtils.setDBody(terrain,terrainBody);
|
||||
terrain.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* [SERVER ONLY] Given an entity and a terrain chunk description, create physics for the chunk and attach it to the entity
|
||||
@ -522,6 +538,23 @@ public class PhysicsEntityUtils {
|
||||
return terrainBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* [SERVER ONLY] Given an entity and a multi-shape trimesh description, create physics for the shapes and attach it to the entity
|
||||
* @param terrain The entity
|
||||
* @param data The trimesh description
|
||||
* @return The rigid body created (note, attachment has already been performed)
|
||||
*/
|
||||
public static DBody serverAttachMultiShapeTriGeomRigidBody(Entity terrain, MultiShapeTriGeomData data){
|
||||
Realm realm = Globals.realmManager.getEntityRealm(terrain);
|
||||
DBody terrainBody = CollisionBodyCreation.generateBodyFromMultiShapeMeshData(realm.getCollisionEngine(),data,Collidable.TYPE_STATIC_BIT);
|
||||
CollisionBodyCreation.setAutoDisable(realm.getCollisionEngine(), terrainBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD);
|
||||
|
||||
realm.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_STATIC, false));
|
||||
PhysicsEntityUtils.setDBody(terrain,terrainBody);
|
||||
|
||||
return terrainBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* Repositions all active physics-scoped entities on a given realm
|
||||
* @param collisionEngine The realm's collision engine
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
package electrosphere.entity.state.collidable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A tri geom data set that contains multiple shapes
|
||||
*/
|
||||
public interface MultiShapeTriGeomData {
|
||||
|
||||
/**
|
||||
* Gets the data for the tri geom shapes
|
||||
* @return The data
|
||||
*/
|
||||
public Collection<TriGeomData> getData();
|
||||
|
||||
}
|
||||
@ -67,7 +67,7 @@ public class BlockChunkEntity {
|
||||
}));
|
||||
EntityCreationUtils.makeEntityDrawablePreexistingModel(rVal, modelPath);
|
||||
if(levelOfDetail == BlockChunkData.LOD_FULL_RES){
|
||||
PhysicsEntityUtils.clientAttachTriGeomRigidBody(rVal, data);
|
||||
PhysicsEntityUtils.clientAttachMultiShapeTriGeomRigidBody(rVal, data);
|
||||
CollisionObjUtils.clientPositionCharacter(rVal, new Vector3d(EntityUtils.getPosition(rVal)), new Quaterniond());
|
||||
} else {
|
||||
EntityCreationUtils.bypassShadowPass(rVal);
|
||||
@ -112,7 +112,7 @@ public class BlockChunkEntity {
|
||||
*/
|
||||
public static void serverCreateBlockChunkEntity(Entity entity, BlockMeshData blockChunkData){
|
||||
if(blockChunkData.getVertices().length > 0){
|
||||
PhysicsEntityUtils.serverAttachTriGeomRigidBody(entity, blockChunkData);
|
||||
PhysicsEntityUtils.serverAttachMultiShapeTriGeomRigidBody(entity, blockChunkData);
|
||||
Realm realm = Globals.realmManager.getEntityRealm(entity);
|
||||
DBody terrainBody = PhysicsEntityUtils.getDBody(entity);
|
||||
Vector3d entityPos = EntityUtils.getPosition(entity);
|
||||
|
||||
@ -208,6 +208,7 @@ public class TerrainProtocol implements ClientProtocolTemplate<TerrainMessage> {
|
||||
if(Globals.clientBlockManager.containsChunkDataAtWorldPoint(worldPos.x, worldPos.y, worldPos.z, ChunkData.NO_STRIDE)){
|
||||
BlockChunkData data = Globals.clientBlockManager.getChunkDataAtWorldPoint(worldPos.x, worldPos.y, worldPos.z, ChunkData.NO_STRIDE);
|
||||
if(data != null){
|
||||
System.out.println("Set " + message.getvoxelX() + " " + message.getvoxelY() + " " + message.getvoxelZ() + " to " + message.getblockType());
|
||||
data.setType(
|
||||
message.getvoxelX(),
|
||||
message.getvoxelY(),
|
||||
|
||||
@ -2,6 +2,7 @@ package electrosphere.renderer.meshgen;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -13,6 +14,7 @@ import org.lwjgl.opengl.GL40;
|
||||
|
||||
import electrosphere.client.block.BlockChunkData;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.state.collidable.MultiShapeTriGeomData;
|
||||
import electrosphere.entity.state.collidable.TriGeomData;
|
||||
import electrosphere.renderer.model.Material;
|
||||
import electrosphere.renderer.model.Mesh;
|
||||
@ -311,6 +313,9 @@ public class BlockMeshgen {
|
||||
//sort
|
||||
Collections.sort(quadMeshes);
|
||||
|
||||
int lastVertexCount = 0;
|
||||
int lastFaceCount = 0;
|
||||
|
||||
//generate volumes
|
||||
QuadMesh quad1 = null;
|
||||
QuadMesh quad2 = null;
|
||||
@ -325,6 +330,11 @@ public class BlockMeshgen {
|
||||
} else {
|
||||
BlockMeshgen.meshifyBox(verts,normals,uvs,indices,samplers,quad1,zEnd,quad1.type,verts.size());
|
||||
quad1 = quad2;
|
||||
|
||||
BlockSingleShape blockSingleShape = BlockMeshgen.copyDataToShape(verts,indices,lastVertexCount,lastFaceCount);
|
||||
lastVertexCount = verts.size();
|
||||
lastFaceCount = indices.size();
|
||||
rVal.shapeData.add(blockSingleShape);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -332,6 +342,10 @@ public class BlockMeshgen {
|
||||
}
|
||||
if(quad1 != null){
|
||||
BlockMeshgen.meshifyBox(verts,normals,uvs,indices,samplers,quad1,zEnd,quad1.type,verts.size());
|
||||
BlockSingleShape blockSingleShape = BlockMeshgen.copyDataToShape(verts,indices,lastVertexCount,lastFaceCount);
|
||||
lastVertexCount = verts.size();
|
||||
lastFaceCount = indices.size();
|
||||
rVal.shapeData.add(blockSingleShape);
|
||||
}
|
||||
|
||||
//
|
||||
@ -389,6 +403,28 @@ public class BlockMeshgen {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies vertex and index data from the combined array into a single shape
|
||||
* @param verts The list of vertices
|
||||
* @param indices The list of indices
|
||||
* @param lastVertCount The last vertex position that was copied
|
||||
* @param lastFaceCount The last index position that was copied
|
||||
* @return The data containing a single shape's worth of geometry data
|
||||
*/
|
||||
private static BlockSingleShape copyDataToShape(List<Vector3f> verts, List<Integer> indices, int lastVertCount, int lastFaceCount){
|
||||
BlockSingleShape blockSingleShape = new BlockSingleShape((verts.size() - lastVertCount),(indices.size() - lastFaceCount));
|
||||
for(int i = lastVertCount; i < verts.size(); i++){
|
||||
Vector3f vert = verts.get(i);
|
||||
blockSingleShape.vertices[(i - lastVertCount) * 3 + 0] = vert.x;
|
||||
blockSingleShape.vertices[(i - lastVertCount) * 3 + 1] = vert.y;
|
||||
blockSingleShape.vertices[(i - lastVertCount) * 3 + 2] = vert.z;
|
||||
}
|
||||
for(int i = lastFaceCount; i < indices.size(); i++){
|
||||
blockSingleShape.faceElements[i - lastFaceCount] = indices.get(i) - lastVertCount;
|
||||
}
|
||||
return blockSingleShape;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a mesh based on a block mesh data object
|
||||
* @param data The block mesh data object
|
||||
@ -492,36 +528,117 @@ public class BlockMeshgen {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains the geom data for a single shape in the block mesh
|
||||
*/
|
||||
public static class BlockSingleShape implements TriGeomData {
|
||||
|
||||
/**
|
||||
* The verts
|
||||
*/
|
||||
float[] vertices;
|
||||
|
||||
/**
|
||||
* The faces
|
||||
*/
|
||||
int[] faceElements;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param vertCount The number of verts
|
||||
* @param faceCount The number of faces
|
||||
*/
|
||||
public BlockSingleShape(int vertCount, int faceCount){
|
||||
vertices = new float[vertCount * 3];
|
||||
faceElements = new int[faceCount];
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getVertices() {
|
||||
return vertices;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getFaceElements() {
|
||||
return faceElements;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The final rasterization data that is emitted
|
||||
*/
|
||||
public static class BlockMeshData implements TriGeomData {
|
||||
//the verts
|
||||
public static class BlockMeshData implements TriGeomData, MultiShapeTriGeomData {
|
||||
|
||||
/**
|
||||
* Vertex data in array form
|
||||
*/
|
||||
float[] vertices;
|
||||
//normals
|
||||
|
||||
/**
|
||||
* Normal data in array form
|
||||
*/
|
||||
float[] normals;
|
||||
//faces
|
||||
|
||||
/**
|
||||
* Face data in array form
|
||||
*/
|
||||
int[] faceElements;
|
||||
//UVs
|
||||
|
||||
/**
|
||||
* UV data in array form
|
||||
*/
|
||||
float[] uvs;
|
||||
//The samplers for each quad
|
||||
|
||||
/**
|
||||
* Sampler data in array form
|
||||
*/
|
||||
int[] samplers;
|
||||
|
||||
/**
|
||||
* Data broken out by each shape
|
||||
*/
|
||||
List<TriGeomData> shapeData = new LinkedList<TriGeomData>();
|
||||
|
||||
/**
|
||||
* Buffer of vertex data
|
||||
*/
|
||||
FloatBuffer vertBuffer;
|
||||
|
||||
/**
|
||||
* Buffer of normal data
|
||||
*/
|
||||
FloatBuffer normalBuffer;
|
||||
|
||||
/**
|
||||
* Buffer of face data
|
||||
*/
|
||||
IntBuffer faceBuffer;
|
||||
|
||||
/**
|
||||
* Buffer of UV data
|
||||
*/
|
||||
FloatBuffer uvBuffer;
|
||||
|
||||
/**
|
||||
* Buffer of sampler data
|
||||
*/
|
||||
IntBuffer samplerBuffer;
|
||||
|
||||
@Override
|
||||
public float[] getVertices() {
|
||||
return vertices;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getFaceElements() {
|
||||
return faceElements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<TriGeomData> getData() {
|
||||
return shapeData;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user