Browse Source

load mesh data and structure meshes

mesh-colliders
FatBoy-DOTC 10 months ago
parent
commit
d53b5d03a4
  1. 10
      src/engine/collisionEngine/CollisionManager.java
  2. 125
      src/engine/collisionEngine/Mesh.java
  3. 23
      src/engine/collisionEngine/MeshData.java
  4. 20
      src/engine/collisionEngine/MeshTriangle.java
  5. 69
      src/engine/db/handlers/dbBuildingHandler.java
  6. 18
      src/engine/gameManager/BuildingManager.java
  7. 1
      src/engine/objects/AbstractCharacter.java
  8. 5
      src/engine/objects/Building.java
  9. 5
      src/engine/objects/PlayerCharacter.java
  10. 4
      src/engine/server/world/WorldServer.java

10
src/engine/collisionEngine/CollisionManager.java

@ -0,0 +1,10 @@
package engine.collisionEngine;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.HashMap;
public class CollisionManager {
public static HashMap<Integer, ArrayList<MeshTriangle>> mesh_triangles;
public static HashMap<Integer, ArrayList<MeshData>> structure_meshes;
}

125
src/engine/collisionEngine/Mesh.java

@ -0,0 +1,125 @@
package engine.collisionEngine;
import engine.gameManager.BuildingManager;
import engine.math.Vector3f;
import engine.math.Vector3fImmutable;
import engine.objects.AbstractCharacter;
import engine.objects.Building;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
public class Mesh {
public int parentUUID;
public MeshData meshData;
private int meshID;
private Rectangle2D.Float bounds;
private ArrayList<MeshTriangle> triangles;
private Vector3f mesh_loc;
private Vector3f mesh_ref;
private Vector3f mesh_end;
private float mesh_maxY;
private float mesh_minY;
public Mesh(MeshData data, int parentUUID){
this.meshData = data;
this.parentUUID = parentUUID;
this.meshID = data.meshID;
this.BakeTriangles();
this.BakeBounds();
}
public void BakeTriangles(){
if(CollisionManager.mesh_triangles.containsKey(this.meshID) == false)
return; // no triangle data to bake
this.triangles = new ArrayList<>();
Building building = BuildingManager.getBuilding(this.parentUUID);
if(building == null)
return; // can't continue without a building to base location offsets from
Vector3f adjustedBuildingLoc = new Vector3f(building.loc.x,building.loc.y, building.loc.z * -1);
int rotDegrees = (int)Math.toDegrees(building.getBounds().getQuaternion().angleY);
this.mesh_loc = Vector3f.rotateAroundPoint(adjustedBuildingLoc.add(meshData.mesh_loc),adjustedBuildingLoc,rotDegrees);
this.mesh_ref = Vector3f.rotateAroundPoint(adjustedBuildingLoc.add(meshData.mesh_ref),adjustedBuildingLoc,rotDegrees);
this.mesh_end = Vector3f.rotateAroundPoint(adjustedBuildingLoc.add(meshData.mesh_end),adjustedBuildingLoc,rotDegrees);
this.mesh_minY = adjustedBuildingLoc.y + this.meshData.mesh_minY;
this.mesh_maxY = adjustedBuildingLoc.y + this.meshData.mesh_maxY;
for(MeshTriangle tri : CollisionManager.mesh_triangles.get(this.meshID)){
Vector3f point1 = this.mesh_loc.add(new Vector3f(tri.point1.x,this.mesh_loc.y,tri.point1.y));
Vector3f point2 = this.mesh_loc.add(new Vector3f(tri.point2.x,this.mesh_loc.y,tri.point2.y));
Vector3f point3 = this.mesh_loc.add(new Vector3f(tri.point3.x,this.mesh_loc.y,tri.point3.y));
Vector3f rotatedPoint1 = Vector3f.rotateAroundPoint(point1,this.mesh_loc,rotDegrees);
Vector3f rotatedPoint2 = Vector3f.rotateAroundPoint(point2,this.mesh_loc,rotDegrees);
Vector3f rotatedPoint3 = Vector3f.rotateAroundPoint(point3,this.mesh_loc,rotDegrees);
MeshTriangle newTri = new MeshTriangle();
newTri.point1 = new Point2D.Float(rotatedPoint1.x,rotatedPoint1.z);
newTri.point2 = new Point2D.Float(rotatedPoint2.x,rotatedPoint2.z);
newTri.point3 = new Point2D.Float(rotatedPoint3.x,rotatedPoint3.z);
newTri.sides = new ArrayList<>();
newTri.sides.add(new Line2D.Float(newTri.point1,newTri.point2));
newTri.sides.add(new Line2D.Float(newTri.point2,newTri.point3));
newTri.sides.add(new Line2D.Float(newTri.point3,newTri.point1));
this.triangles.add(newTri);
}
}
public void BakeBounds(){
float width = this.mesh_ref.x - this.mesh_end.x;
float height = this.mesh_ref.z - this.mesh_end.z;
this.bounds = new Rectangle2D.Float(this.mesh_ref.x,this.mesh_ref.z,width,height);
}
public boolean collides(AbstractCharacter mover, Vector3fImmutable destination){
if(mover == null)
return false;
Line2D.Float line = new Line2D.Float(new Point2D.Float(mover.loc.x,mover.loc.z * -1),new Point2D.Float(destination.x,destination.z * -1));
float footHeight = mover.loc.y;
float headHeight = mover.loc.y + mover.characterHeight;
if(line.intersects(this.bounds) == false)
return false; // character path doesn't cross over this mesh
if(footHeight > this.mesh_maxY || headHeight < this.mesh_minY)
return false; //character is either above or below the bounds of this mesh
for(MeshTriangle tri : this.triangles)
if(tri.collides(line))
return true; //character's path directly hits part of this mesh
return false;
}
public boolean losBlocked(AbstractCharacter looker, Vector3fImmutable target){
float headHeight = looker.loc.y + looker.characterHeight;
float targetAlt = target.y;
Line2D.Float eyeLine = new Line2D.Float(new Point2D.Float(looker.loc.x,looker.loc.z * -1),new Point2D.Float(target.x,target.z * -1));
if(eyeLine.intersects(this.bounds) == false)
return false; // character eye-line doesn't cross over this mesh
if(targetAlt > this.mesh_maxY && headHeight > this.mesh_maxY)
return false; // both characters are above this mesh
if(targetAlt < this.mesh_maxY && headHeight < this.mesh_maxY)
return false; // both characters are below this mesh
return true;
}
}

23
src/engine/collisionEngine/MeshData.java

@ -0,0 +1,23 @@
package engine.collisionEngine;
import engine.math.Vector3f;
public class MeshData {
public int propID;
public int meshID;
public Vector3f mesh_loc;
public Vector3f mesh_ref;
public Vector3f mesh_end;
public float mesh_maxY;
public float mesh_minY;
public MeshData(int propID,int meshID, Vector3f meshLoc, Vector3f meshRef, Vector3f meshEnd, float maxY, float minY){
this.propID = propID;
this.meshID = meshID;
this.mesh_loc = meshLoc;
this.mesh_ref = meshRef;
this.mesh_end = meshEnd;
this.mesh_maxY = maxY;
this.mesh_minY = minY;
}
}

20
src/engine/collisionEngine/MeshTriangle.java

@ -0,0 +1,20 @@
package engine.collisionEngine;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
public class MeshTriangle {
public Point2D.Float point1;
public Point2D.Float point2;
public Point2D.Float point3;
public ArrayList<Line2D.Float> sides;
public boolean collides(Line2D.Float line){
for(Line2D.Float side : sides)
if(line.intersectsLine(side))
return true;
return false;
}
}

69
src/engine/db/handlers/dbBuildingHandler.java

@ -13,13 +13,18 @@ import engine.Enum;
import engine.Enum.DbObjectType; import engine.Enum.DbObjectType;
import engine.Enum.ProtectionState; import engine.Enum.ProtectionState;
import engine.Enum.TaxType; import engine.Enum.TaxType;
import engine.collisionEngine.CollisionManager;
import engine.collisionEngine.MeshData;
import engine.collisionEngine.MeshTriangle;
import engine.gameManager.BuildingManager; import engine.gameManager.BuildingManager;
import engine.gameManager.DbManager; import engine.gameManager.DbManager;
import engine.math.Vector3f;
import engine.math.Vector3fImmutable; import engine.math.Vector3fImmutable;
import engine.objects.*; import engine.objects.*;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.awt.geom.Point2D;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
@ -848,5 +853,69 @@ public class dbBuildingHandler extends dbHandlerBase {
} }
return false; return false;
} }
public boolean LOAD_STRUCTURE_MESHES() {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `final_structure_meshes`;")) {
ResultSet rs = preparedStatement.executeQuery();
CollisionManager.structure_meshes = new HashMap<>();
while (rs.next()) {
int propId = rs.getInt("propID");
int meshId = rs.getInt("meshID");
Vector3f meshLoc = new Vector3f(rs.getFloat("locX"),rs.getFloat("locY"),rs.getFloat("locZ"));
Vector3f meshRef = new Vector3f(rs.getFloat("refX"),rs.getFloat("refY"),rs.getFloat("refZ"));
Vector3f meshEnd = new Vector3f(rs.getFloat("endX"),rs.getFloat("endY"),rs.getFloat("endZ"));
float maxY = rs.getFloat("maxY");
float minY = rs.getFloat("minY");
MeshData data = new MeshData(propId,meshId,meshLoc,meshRef,meshEnd,maxY,minY);
if(CollisionManager.structure_meshes.containsKey(propId)){
CollisionManager.structure_meshes.get(propId).add(data);
} else{
ArrayList<MeshData> addList = new ArrayList<>();
addList.add(data);
CollisionManager.structure_meshes.put(propId,addList);
}
}
return (preparedStatement.executeUpdate() > 0);
} catch (SQLException e) {
Logger.error(e);
}
return false;
}
public boolean LOAD_MESH_TRIANGLES() {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `final_mesh_triangles`;")) {
ResultSet rs = preparedStatement.executeQuery();
CollisionManager.mesh_triangles = new HashMap<>();
while (rs.next()) {
int meshId = rs.getInt("meshID");
Point2D.Float point1 = new Point2D.Float(rs.getFloat("P1X"), rs.getFloat("P1Z"));
Point2D.Float point2 = new Point2D.Float(rs.getFloat("P2X"), rs.getFloat("P2Z"));
Point2D.Float point3 = new Point2D.Float(rs.getFloat("P3X"), rs.getFloat("P3Z"));
MeshTriangle newTri = new MeshTriangle();
newTri.point1 = point1;
newTri.point2 = point2;
newTri.point3 = point3;
if(CollisionManager.mesh_triangles.containsKey(meshId)){
CollisionManager.mesh_triangles.get(meshId).add(newTri);
} else{
ArrayList<MeshTriangle> addList = new ArrayList<>();
addList.add(newTri);
CollisionManager.mesh_triangles.put(meshId,addList);
}
}
return (preparedStatement.executeUpdate() > 0);
} catch (SQLException e) {
Logger.error(e);
}
return false;
}
} }

18
src/engine/gameManager/BuildingManager.java

@ -14,6 +14,9 @@ import engine.Enum.BuildingGroup;
import engine.Enum.GameObjectType; import engine.Enum.GameObjectType;
import engine.InterestManagement.InterestManager; import engine.InterestManagement.InterestManager;
import engine.InterestManagement.WorldGrid; import engine.InterestManagement.WorldGrid;
import engine.collisionEngine.CollisionManager;
import engine.collisionEngine.Mesh;
import engine.collisionEngine.MeshData;
import engine.job.JobContainer; import engine.job.JobContainer;
import engine.job.JobScheduler; import engine.job.JobScheduler;
import engine.jobs.UpgradeBuildingJob; import engine.jobs.UpgradeBuildingJob;
@ -943,6 +946,8 @@ public enum BuildingManager {
cleanupHirelings(building); cleanupHirelings(building);
building.isDeranking.compareAndSet(true, false); building.isDeranking.compareAndSet(true, false);
BakeColliders(building);
} }
public static Building getBuildingAtLocation(Vector3fImmutable loc) { public static Building getBuildingAtLocation(Vector3fImmutable loc) {
@ -960,4 +965,17 @@ public enum BuildingManager {
return null; return null;
} }
public static void BakeColliders(Building building){
int propID = building.meshUUID;
if(CollisionManager.structure_meshes.containsKey(propID) == false) {
Logger.error("Bake for PropID: " + propID + " Failed");
return;
}
building.buildingMeshes = new ArrayList<>();
for(MeshData data : CollisionManager.structure_meshes.get(propID)){
building.buildingMeshes.add(new Mesh(data,building.getObjectUUID()));
}
}
} }

1
src/engine/objects/AbstractCharacter.java

@ -45,6 +45,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
public abstract class AbstractCharacter extends AbstractWorldObject { public abstract class AbstractCharacter extends AbstractWorldObject {
public float characterHeight = 0;
protected CharacterItemManager charItemManager; protected CharacterItemManager charItemManager;
private final ReentrantReadWriteLock healthLock = new ReentrantReadWriteLock(); private final ReentrantReadWriteLock healthLock = new ReentrantReadWriteLock();
public short level; public short level;

5
src/engine/objects/Building.java

@ -14,6 +14,7 @@ import engine.Enum.*;
import engine.InterestManagement.RealmMap; import engine.InterestManagement.RealmMap;
import engine.InterestManagement.Terrain; import engine.InterestManagement.Terrain;
import engine.InterestManagement.WorldGrid; import engine.InterestManagement.WorldGrid;
import engine.collisionEngine.Mesh;
import engine.db.archive.CityRecord; import engine.db.archive.CityRecord;
import engine.db.archive.DataWarehouse; import engine.db.archive.DataWarehouse;
import engine.db.archive.MineRecord; import engine.db.archive.MineRecord;
@ -99,6 +100,8 @@ public class Building extends AbstractWorldObject {
private ConcurrentHashMap<Integer, Condemned> condemned; private ConcurrentHashMap<Integer, Condemned> condemned;
private ArrayList<Building> children = null; private ArrayList<Building> children = null;
public ArrayList<Mesh> buildingMeshes;
/** /**
* ResultSet Constructor * ResultSet Constructor
*/ */
@ -1003,6 +1006,8 @@ public class Building extends AbstractWorldObject {
if (this.upgradeDateTime != null) if (this.upgradeDateTime != null)
BuildingManager.submitUpgradeJob(this); BuildingManager.submitUpgradeJob(this);
BuildingManager.BakeColliders(this);
} }
public synchronized boolean setOwner(AbstractCharacter newOwner) { public synchronized boolean setOwner(AbstractCharacter newOwner) {

5
src/engine/objects/PlayerCharacter.java

@ -165,7 +165,6 @@ public class PlayerCharacter extends AbstractCharacter {
private boolean wasTripped75 = false; private boolean wasTripped75 = false;
private boolean wasTripped50 = false; private boolean wasTripped50 = false;
private boolean wasTripped25 = false; private boolean wasTripped25 = false;
private float characterHeight = 0;
private boolean lastSwimming = false; private boolean lastSwimming = false;
private boolean isTeleporting = false; private boolean isTeleporting = false;
private boolean dirtyLoad = true; private boolean dirtyLoad = true;
@ -5427,10 +5426,6 @@ public class PlayerCharacter extends AbstractCharacter {
this.lastStamUpdateTime = System.currentTimeMillis(); this.lastStamUpdateTime = System.currentTimeMillis();
} }
public float getCharacterHeight() {
return characterHeight;
}
public boolean isEnteredWorld() { public boolean isEnteredWorld() {
return enteredWorld; return enteredWorld;
} }

4
src/engine/server/world/WorldServer.java

@ -315,6 +315,10 @@ public class WorldServer {
Logger.info("Initializing PowersManager."); Logger.info("Initializing PowersManager.");
PowersManager.initPowersManager(true); PowersManager.initPowersManager(true);
Logger.info("Loading Collider Data");
DbManager.BuildingQueries.LOAD_MESH_TRIANGLES();
DbManager.BuildingQueries.LOAD_STRUCTURE_MESHES();
Logger.info("Loading granted Skills for Runes"); Logger.info("Loading granted Skills for Runes");
DbManager.SkillsBaseQueries.LOAD_ALL_RUNE_SKILLS(); DbManager.SkillsBaseQueries.LOAD_ALL_RUNE_SKILLS();

Loading…
Cancel
Save