hitbox offsets
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
902680ad16
commit
06b068643e
@ -46,7 +46,8 @@
|
|||||||
{
|
{
|
||||||
"type": "hurt",
|
"type": "hurt",
|
||||||
"bone": "Head",
|
"bone": "Head",
|
||||||
"radius": 0.06
|
"radius": 0.06,
|
||||||
|
"offset": [0.0,3.0,0.0]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tokens" : [
|
"tokens" : [
|
||||||
|
|||||||
@ -72,7 +72,8 @@
|
|||||||
{
|
{
|
||||||
"type": "hit_connected",
|
"type": "hit_connected",
|
||||||
"bone": "Blade3",
|
"bone": "Blade3",
|
||||||
"radius": 0.04
|
"radius": 0.04,
|
||||||
|
"offset": [0, 0, 0.15]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -5,4 +5,5 @@
|
|||||||
- @subpage largelocationideas
|
- @subpage largelocationideas
|
||||||
- @subpage macrolocationideas
|
- @subpage macrolocationideas
|
||||||
- @subpage smalllocations
|
- @subpage smalllocations
|
||||||
- @subpage minidungeons
|
- @subpage minidungeons
|
||||||
|
- @subpage zones
|
||||||
1
docs/src/highlevel-design/locations/zones.md
Normal file
1
docs/src/highlevel-design/locations/zones.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
@page zones Zones
|
||||||
@ -549,6 +549,9 @@ Always upright tree
|
|||||||
Fix upright tree clearing linear force/velocity
|
Fix upright tree clearing linear force/velocity
|
||||||
Movement tweaks
|
Movement tweaks
|
||||||
|
|
||||||
|
(08/13/2024)
|
||||||
|
Hitbox support offsets now
|
||||||
|
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
|
|||||||
@ -3,16 +3,13 @@ package electrosphere.collision.hitbox;
|
|||||||
import electrosphere.collision.collidable.Collidable;
|
import electrosphere.collision.collidable.Collidable;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.entity.EntityDataStrings;
|
import electrosphere.entity.EntityDataStrings;
|
||||||
import electrosphere.entity.EntityUtils;
|
|
||||||
import electrosphere.entity.types.attach.AttachUtils;
|
import electrosphere.entity.types.attach.AttachUtils;
|
||||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState;
|
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState;
|
||||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxType;
|
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxType;
|
||||||
import electrosphere.game.data.collidable.HitboxData;
|
import electrosphere.game.data.collidable.HitboxData;
|
||||||
|
|
||||||
import org.joml.Quaterniond;
|
|
||||||
import org.joml.Vector3d;
|
import org.joml.Vector3d;
|
||||||
import org.joml.Vector3f;
|
|
||||||
import org.ode4j.ode.DContactGeom;
|
import org.ode4j.ode.DContactGeom;
|
||||||
import org.ode4j.ode.DGeom;
|
import org.ode4j.ode.DGeom;
|
||||||
|
|
||||||
@ -21,211 +18,6 @@ import org.ode4j.ode.DGeom;
|
|||||||
*/
|
*/
|
||||||
public class HitboxUtils {
|
public class HitboxUtils {
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Spawns a hitbox entity on the client
|
|
||||||
// * @param parent The parent entity to attach the hitbox to
|
|
||||||
// * @param bone The bone on the parent to attach to
|
|
||||||
// * @param size The radius of the hitsphere
|
|
||||||
// * @return The hitbox entity
|
|
||||||
// */
|
|
||||||
// public static Entity clientSpawnRegularHitbox(Entity parent, String bone, float size){
|
|
||||||
// Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
|
||||||
// HitboxData data = new HitboxData();
|
|
||||||
// data.setActive(false);
|
|
||||||
// data.setBone(bone);
|
|
||||||
// data.setRadius(size);
|
|
||||||
// data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT);
|
|
||||||
// rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent);
|
|
||||||
// rVal.putData(EntityDataStrings.HITBOX_DATA, data);
|
|
||||||
// rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
|
||||||
// rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true);
|
|
||||||
// Globals.clientHitboxManager.registerHitbox(rVal);
|
|
||||||
// return rVal;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Spawns a hitbox entity on the server
|
|
||||||
// * @param parent The parent entity to attach the hitbox to
|
|
||||||
// * @param bone The bone to attach to the hitbox to
|
|
||||||
// * @param size The radius of the hitsphere
|
|
||||||
// * @return The hitbox entity
|
|
||||||
// */
|
|
||||||
// public static Entity serverSpawnRegularHitbox(Entity parent, String bone, float size){
|
|
||||||
// Entity rVal = EntityCreationUtils.createServerEntity(Globals.realmManager.getEntityRealm(parent), new Vector3d(0,0,0));
|
|
||||||
// HitboxData data = new HitboxData();
|
|
||||||
// data.setActive(false);
|
|
||||||
// data.setBone(bone);
|
|
||||||
// data.setRadius(size);
|
|
||||||
// data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT);
|
|
||||||
// rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent);
|
|
||||||
// rVal.putData(EntityDataStrings.HITBOX_DATA, data);
|
|
||||||
// rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
|
||||||
// rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true);
|
|
||||||
// Globals.realmManager.getEntityRealm(parent).getHitboxManager().registerHitbox(rVal);
|
|
||||||
// return rVal;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Spawns a hurtbox on the client
|
|
||||||
// * @param parent The parent entity of the hurtbox
|
|
||||||
// * @param bone The bone on the parent to attach the hurtbox to
|
|
||||||
// * @param size The radius of the hurtsphere
|
|
||||||
// * @return The hurtbox entity
|
|
||||||
// */
|
|
||||||
// public static Entity clientSpawnRegularHurtbox(Entity parent, String bone, float size){
|
|
||||||
// Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
|
||||||
// HitboxData data = new HitboxData();
|
|
||||||
// data.setActive(true);
|
|
||||||
// data.setBone(bone);
|
|
||||||
// data.setRadius(size);
|
|
||||||
// data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT);
|
|
||||||
// rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent);
|
|
||||||
// rVal.putData(EntityDataStrings.HITBOX_DATA, data);
|
|
||||||
// rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
|
||||||
// rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true);
|
|
||||||
// Globals.clientHitboxManager.registerHitbox(rVal);
|
|
||||||
// return rVal;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Spawns a hurtbox on the server
|
|
||||||
// * @param parent The parent entity of the hurtbox
|
|
||||||
// * @param bone The bone on the parent to attach the hurtbox to
|
|
||||||
// * @param size The radius of the hurtsphere
|
|
||||||
// * @return The hurtbox entity
|
|
||||||
// */
|
|
||||||
// public static Entity serverSpawnRegularHurtbox(Entity parent, String bone, float size){
|
|
||||||
// Entity rVal = EntityCreationUtils.createServerEntity(Globals.realmManager.getEntityRealm(parent), new Vector3d(0,0,0));
|
|
||||||
// HitboxData data = new HitboxData();
|
|
||||||
// data.setActive(true);
|
|
||||||
// data.setBone(bone);
|
|
||||||
// data.setRadius(size);
|
|
||||||
// data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT);
|
|
||||||
// rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent);
|
|
||||||
// rVal.putData(EntityDataStrings.HITBOX_DATA, data);
|
|
||||||
// rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
|
||||||
// rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true);
|
|
||||||
// Globals.realmManager.getEntityRealm(parent).getHitboxManager().registerHitbox(rVal);
|
|
||||||
// return rVal;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * More sophisticated function for spawning in hitboxes. Takes a position callback so it's not tied to a bone
|
|
||||||
// * @param parent The parent entity of the hitbox
|
|
||||||
// * @param positionCallback The position callback for keeping hitbox entity position up to date
|
|
||||||
// * @param size The size of the hitbox
|
|
||||||
// * @param hurtbox If true, it will instead be a hurtbox
|
|
||||||
// * @param filter an optional list of parent entities to not colide with
|
|
||||||
// * @return The hitbox entity
|
|
||||||
// */
|
|
||||||
// public static Entity clientSpawnRegularHitbox(Entity parent, HitboxPositionCallback positionCallback, float size, boolean hurtbox, List<Entity> filter){
|
|
||||||
// Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
|
||||||
// HitboxData data = new HitboxData();
|
|
||||||
// data.setActive(true);
|
|
||||||
// data.setPositionCallback(positionCallback);
|
|
||||||
// data.setRadius(size);
|
|
||||||
// data.setEntityFilter(filter);
|
|
||||||
// if(hurtbox){
|
|
||||||
// data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT);
|
|
||||||
// } else {
|
|
||||||
// data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT);
|
|
||||||
// }
|
|
||||||
// rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent);
|
|
||||||
// rVal.putData(EntityDataStrings.HITBOX_DATA, data);
|
|
||||||
// rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
|
||||||
// rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true);
|
|
||||||
// Globals.clientHitboxManager.registerHitbox(rVal);
|
|
||||||
// return rVal;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * More sophisticated function for spawning in hitboxes. Takes a position callback so it's not tied to a bone
|
|
||||||
// * @param parent The parent entity of the hitbox
|
|
||||||
// * @param positionCallback The position callback for keeping hitbox entity position up to date
|
|
||||||
// * @param size The size of the hitbox
|
|
||||||
// * @param hurtbox If true, it will instead be a hurtbox
|
|
||||||
// * @param filter an optional list of parent entities to not colide with
|
|
||||||
// * @return The hitbox entity
|
|
||||||
// */
|
|
||||||
// public static Entity serverSpawnRegularHitbox(Entity parent, HitboxPositionCallback positionCallback, float size, boolean hurtbox, List<Entity> filter){
|
|
||||||
// Entity rVal = EntityCreationUtils.createServerEntity(Globals.realmManager.getEntityRealm(parent), new Vector3d(0,0,0));
|
|
||||||
// HitboxData data = new HitboxData();
|
|
||||||
// data.setActive(true);
|
|
||||||
// data.setPositionCallback(positionCallback);
|
|
||||||
// data.setRadius(size);
|
|
||||||
// data.setEntityFilter(filter);
|
|
||||||
// if(hurtbox){
|
|
||||||
// data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT);
|
|
||||||
// } else {
|
|
||||||
// data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT);
|
|
||||||
// }
|
|
||||||
// rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent);
|
|
||||||
// rVal.putData(EntityDataStrings.HITBOX_DATA, data);
|
|
||||||
// rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
|
||||||
// rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true);
|
|
||||||
// Globals.realmManager.getEntityRealm(parent).getHitboxManager().registerHitbox(rVal);
|
|
||||||
// return rVal;
|
|
||||||
// }
|
|
||||||
|
|
||||||
public static void clientUpdatePosition(Entity hitbox){
|
|
||||||
Entity parent = ((Entity)hitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT));
|
|
||||||
HitboxData hitboxData = getHitboxData(hitbox);
|
|
||||||
String boneName = hitboxData.getBone();
|
|
||||||
if(boneName != null){
|
|
||||||
Quaterniond parentRotation = EntityUtils.getRotation(parent);
|
|
||||||
Vector3f positionScale = EntityUtils.getScale(parent);
|
|
||||||
Vector3d worldPosition = new Vector3d();
|
|
||||||
Vector3f bonePosition = EntityUtils.getActor(parent).getBonePosition(boneName);
|
|
||||||
Vector3d parentPos = EntityUtils.getPosition(parent);
|
|
||||||
worldPosition.set(bonePosition.x,bonePosition.y,bonePosition.z);
|
|
||||||
Quaterniond rotation = new Quaterniond(parentRotation);
|
|
||||||
|
|
||||||
worldPosition = worldPosition.mul(positionScale);
|
|
||||||
|
|
||||||
worldPosition = worldPosition.rotate(rotation);
|
|
||||||
|
|
||||||
|
|
||||||
worldPosition.add(new Vector3f((float)parentPos.x,(float)parentPos.y,(float)parentPos.z));
|
|
||||||
|
|
||||||
EntityUtils.getPosition(hitbox).set(worldPosition);
|
|
||||||
} else {
|
|
||||||
HitboxPositionCallback positionCallback = hitboxData.getPositionCallback();
|
|
||||||
EntityUtils.getPosition(hitbox).set(positionCallback.getPosition());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the position of a hitbox
|
|
||||||
* @param hitbox the hitbox to update
|
|
||||||
*/
|
|
||||||
public static void serverUpdatePosition(Entity hitbox){
|
|
||||||
Entity parent = ((Entity)hitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT));
|
|
||||||
HitboxData hitboxData = getHitboxData(hitbox);
|
|
||||||
String boneName = hitboxData.getBone();
|
|
||||||
if(boneName != null){
|
|
||||||
Quaterniond parentRotation = EntityUtils.getRotation(parent);
|
|
||||||
Vector3f positionScale = EntityUtils.getScale(parent);
|
|
||||||
Vector3d worldPosition = new Vector3d();
|
|
||||||
Vector3f bonePosition = EntityUtils.getPoseActor(parent).getBonePosition(boneName);
|
|
||||||
Vector3d parentPos = EntityUtils.getPosition(parent);
|
|
||||||
worldPosition.set(bonePosition.x,bonePosition.y,bonePosition.z);
|
|
||||||
Quaterniond rotation = new Quaterniond(parentRotation);
|
|
||||||
|
|
||||||
worldPosition = worldPosition.mul(positionScale);
|
|
||||||
|
|
||||||
worldPosition = worldPosition.rotate(rotation);
|
|
||||||
|
|
||||||
|
|
||||||
worldPosition.add(new Vector3d(parentPos.x,parentPos.y,parentPos.z));
|
|
||||||
|
|
||||||
EntityUtils.getPosition(hitbox).set(worldPosition);
|
|
||||||
} else {
|
|
||||||
HitboxPositionCallback positionCallback = hitboxData.getPositionCallback();
|
|
||||||
EntityUtils.getPosition(hitbox).set(positionCallback.getPosition());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a damage collision on the client
|
* Handles a damage collision on the client
|
||||||
|
|||||||
@ -23,7 +23,9 @@ import electrosphere.entity.Entity;
|
|||||||
import electrosphere.entity.EntityDataStrings;
|
import electrosphere.entity.EntityDataStrings;
|
||||||
import electrosphere.entity.EntityUtils;
|
import electrosphere.entity.EntityUtils;
|
||||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState.HitboxShapeType;
|
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState.HitboxShapeType;
|
||||||
|
import electrosphere.entity.types.attach.AttachUtils;
|
||||||
import electrosphere.game.data.collidable.HitboxData;
|
import electrosphere.game.data.collidable.HitboxData;
|
||||||
|
import electrosphere.game.data.utils.DataFormatUtil;
|
||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
import electrosphere.util.math.MathUtils;
|
import electrosphere.util.math.MathUtils;
|
||||||
|
|
||||||
@ -235,10 +237,10 @@ public class HitboxCollectionState {
|
|||||||
HitboxState shapeStatus = this.geomStateMap.get(geom);
|
HitboxState shapeStatus = this.geomStateMap.get(geom);
|
||||||
switch(shapeStatus.shapeType){
|
switch(shapeStatus.shapeType){
|
||||||
case SPHERE: {
|
case SPHERE: {
|
||||||
this.updateSphereShapePosition(collisionEngine,boneName,bonePosition);
|
this.updateSphereShapePosition(collisionEngine,boneName,shapeStatus,bonePosition);
|
||||||
} break;
|
} break;
|
||||||
case CAPSULE: {
|
case CAPSULE: {
|
||||||
this.updateCapsuleShapePosition(collisionEngine,boneName,bonePosition);
|
this.updateCapsuleShapePosition(collisionEngine,boneName,shapeStatus,bonePosition);
|
||||||
} break;
|
} break;
|
||||||
case STATIC_CAPSULE: {
|
case STATIC_CAPSULE: {
|
||||||
} break;
|
} break;
|
||||||
@ -261,10 +263,10 @@ public class HitboxCollectionState {
|
|||||||
HitboxState shapeStatus = this.geomStateMap.get(geom);
|
HitboxState shapeStatus = this.geomStateMap.get(geom);
|
||||||
switch(shapeStatus.shapeType){
|
switch(shapeStatus.shapeType){
|
||||||
case SPHERE: {
|
case SPHERE: {
|
||||||
this.updateSphereShapePosition(collisionEngine,boneName,bonePosition);
|
this.updateSphereShapePosition(collisionEngine,boneName,shapeStatus,bonePosition);
|
||||||
} break;
|
} break;
|
||||||
case CAPSULE: {
|
case CAPSULE: {
|
||||||
this.updateCapsuleShapePosition(collisionEngine,boneName,bonePosition);
|
this.updateCapsuleShapePosition(collisionEngine,boneName,shapeStatus,bonePosition);
|
||||||
} break;
|
} break;
|
||||||
case STATIC_CAPSULE: {
|
case STATIC_CAPSULE: {
|
||||||
} break;
|
} break;
|
||||||
@ -310,21 +312,27 @@ public class HitboxCollectionState {
|
|||||||
* @param boneName The name of the bone
|
* @param boneName The name of the bone
|
||||||
* @param bonePosition the position of the bone
|
* @param bonePosition the position of the bone
|
||||||
*/
|
*/
|
||||||
private void updateSphereShapePosition(CollisionEngine collisionEngine, String boneName, Vector3f bonePosition){
|
private void updateSphereShapePosition(CollisionEngine collisionEngine, String boneName, HitboxState hitboxState, Vector3f bonePosition){
|
||||||
DGeom geom = this.hitboxGeomMap.get(boneName);
|
DGeom geom = this.hitboxGeomMap.get(boneName);
|
||||||
|
|
||||||
|
//get offset's transform
|
||||||
|
Vector3d offsetPosition = DataFormatUtil.getDoubleListAsVector(hitboxState.getHitboxData().getOffset());
|
||||||
|
Quaterniond offsetRotation = new Quaterniond();
|
||||||
|
|
||||||
|
//the bone's transform
|
||||||
|
Vector3d bonePositionD = new Vector3d(bonePosition);
|
||||||
|
Quaterniond boneRotation = new Quaterniond();
|
||||||
|
|
||||||
|
//the parent's transform
|
||||||
|
Vector3d parentPosition = EntityUtils.getPosition(parent);
|
||||||
Quaterniond parentRotation = EntityUtils.getRotation(parent);
|
Quaterniond parentRotation = EntityUtils.getRotation(parent);
|
||||||
Vector3f positionScale = EntityUtils.getScale(parent);
|
Vector3d parentScale = new Vector3d(EntityUtils.getScale(parent));
|
||||||
Vector3d worldPosition = new Vector3d();
|
|
||||||
Vector3d parentPos = EntityUtils.getPosition(parent);
|
|
||||||
Quaterniond rotation = new Quaterniond(parentRotation);
|
|
||||||
|
|
||||||
//calculate new world pos
|
//calculate
|
||||||
worldPosition.set(bonePosition.x,bonePosition.y,bonePosition.z);
|
Vector3d hitboxPos = AttachUtils.calculateBoneAttachmentPosition(offsetPosition, offsetRotation, bonePositionD, boneRotation, parentPosition, parentRotation, parentScale);
|
||||||
worldPosition = worldPosition.mul(positionScale);
|
|
||||||
worldPosition = worldPosition.rotate(rotation);
|
|
||||||
worldPosition.add(new Vector3f((float)parentPos.x,(float)parentPos.y,(float)parentPos.z));
|
|
||||||
|
|
||||||
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, worldPosition, rotation);
|
|
||||||
|
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, hitboxPos, new Quaterniond());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -333,23 +341,30 @@ public class HitboxCollectionState {
|
|||||||
* @param boneName
|
* @param boneName
|
||||||
* @param bonePosition
|
* @param bonePosition
|
||||||
*/
|
*/
|
||||||
private void updateCapsuleShapePosition(CollisionEngine collisionEngine, String boneName, Vector3f bonePosition){
|
private void updateCapsuleShapePosition(CollisionEngine collisionEngine, String boneName, HitboxState hitboxState, Vector3f bonePosition){
|
||||||
DGeom geom = this.hitboxGeomMap.get(boneName);
|
|
||||||
HitboxState shapeStatus = this.geomStateMap.get(geom);
|
|
||||||
Quaterniond parentRotation = EntityUtils.getRotation(parent);
|
|
||||||
Vector3f positionScale = EntityUtils.getScale(parent);
|
|
||||||
Vector3d worldPosition = new Vector3d();
|
|
||||||
Vector3d parentPos = EntityUtils.getPosition(parent);
|
|
||||||
Quaterniond rotation = new Quaterniond(parentRotation);
|
|
||||||
Vector3d previousWorldPos = shapeStatus.getPreviousWorldPos();
|
|
||||||
|
|
||||||
//calculate new world pos
|
//get data about the hitbox
|
||||||
worldPosition.set(bonePosition.x,bonePosition.y,bonePosition.z);
|
DGeom geom = this.hitboxGeomMap.get(boneName);
|
||||||
worldPosition = worldPosition.mul(positionScale);
|
Vector3d previousWorldPos = hitboxState.getPreviousWorldPos();
|
||||||
worldPosition = worldPosition.rotate(rotation);
|
double length = hitboxState.getHitboxData().getRadius();
|
||||||
worldPosition.add(new Vector3f((float)parentPos.x,(float)parentPos.y,(float)parentPos.z));
|
|
||||||
double length = shapeStatus.getHitboxData().getRadius();
|
|
||||||
// double radius = shapeStatus.getHitboxData().getRadius();
|
//get offset's transform
|
||||||
|
Vector3d offsetPosition = DataFormatUtil.getDoubleListAsVector(hitboxState.getHitboxData().getOffset());
|
||||||
|
Quaterniond offsetRotation = new Quaterniond();
|
||||||
|
|
||||||
|
//the bone's transform
|
||||||
|
Vector3d bonePositionD = new Vector3d(bonePosition);
|
||||||
|
Quaterniond boneRotation = new Quaterniond();
|
||||||
|
|
||||||
|
//the parent's transform
|
||||||
|
Vector3d parentPosition = EntityUtils.getPosition(parent);
|
||||||
|
Quaterniond parentRotation = EntityUtils.getRotation(parent);
|
||||||
|
Vector3d parentScale = new Vector3d(EntityUtils.getScale(parent));
|
||||||
|
|
||||||
|
//calculate
|
||||||
|
Vector3d worldPosition = AttachUtils.calculateBoneAttachmentPosition(offsetPosition, offsetRotation, bonePositionD, boneRotation, parentPosition, parentRotation, parentScale);
|
||||||
|
Quaterniond worldRotation = new Quaterniond();
|
||||||
|
|
||||||
if(previousWorldPos != null){
|
if(previousWorldPos != null){
|
||||||
//called all subsequent updates to hitbox position
|
//called all subsequent updates to hitbox position
|
||||||
@ -366,7 +381,7 @@ public class HitboxCollectionState {
|
|||||||
//the second quaternion is a rotation along the x axis. This is used to put the hitbox rotation into ode's space
|
//the second quaternion is a rotation along the x axis. This is used to put the hitbox rotation into ode's space
|
||||||
//ode is Z-axis-up
|
//ode is Z-axis-up
|
||||||
if(previousWorldPos.distance(worldPosition) > 0.0){
|
if(previousWorldPos.distance(worldPosition) > 0.0){
|
||||||
rotation = MathUtils.calculateRotationFromPointToPoint(previousWorldPos,worldPosition).mul(new Quaterniond(0,0.707,0,0.707));
|
worldRotation = MathUtils.calculateRotationFromPointToPoint(previousWorldPos,worldPosition).mul(new Quaterniond(0,0.707,0,0.707));
|
||||||
}
|
}
|
||||||
|
|
||||||
//create new capsule
|
//create new capsule
|
||||||
@ -389,9 +404,9 @@ public class HitboxCollectionState {
|
|||||||
}
|
}
|
||||||
length = 0.1;
|
length = 0.1;
|
||||||
}
|
}
|
||||||
geom = CollisionBodyCreation.createCapsuleShape(manager.getCollisionEngine(), shapeStatus.getHitboxData().getRadius(), length, Collidable.TYPE_OBJECT_BIT);
|
geom = CollisionBodyCreation.createCapsuleShape(manager.getCollisionEngine(), hitboxState.getHitboxData().getRadius(), length, Collidable.TYPE_OBJECT_BIT);
|
||||||
CollisionBodyCreation.attachGeomToBody(collisionEngine,body,geom);
|
CollisionBodyCreation.attachGeomToBody(collisionEngine,body,geom);
|
||||||
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, bodyPosition, rotation);
|
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, bodyPosition, worldRotation);
|
||||||
} else {
|
} else {
|
||||||
//called first time the hitbox updates position
|
//called first time the hitbox updates position
|
||||||
this.geomStateMap.remove(geom);
|
this.geomStateMap.remove(geom);
|
||||||
@ -399,14 +414,14 @@ public class HitboxCollectionState {
|
|||||||
CollisionBodyCreation.destroyShape(collisionEngine, geom);
|
CollisionBodyCreation.destroyShape(collisionEngine, geom);
|
||||||
|
|
||||||
//create new capsule
|
//create new capsule
|
||||||
geom = CollisionBodyCreation.createCapsuleShape(manager.getCollisionEngine(), shapeStatus.getHitboxData().getRadius(), length, Collidable.TYPE_OBJECT_BIT);
|
geom = CollisionBodyCreation.createCapsuleShape(manager.getCollisionEngine(), hitboxState.getHitboxData().getRadius(), length, Collidable.TYPE_OBJECT_BIT);
|
||||||
CollisionBodyCreation.attachGeomToBody(collisionEngine,body,geom);
|
CollisionBodyCreation.attachGeomToBody(collisionEngine,body,geom);
|
||||||
}
|
}
|
||||||
//update maps and other variables for next frame
|
//update maps and other variables for next frame
|
||||||
this.hitboxGeomMap.put(boneName,geom);
|
this.hitboxGeomMap.put(boneName,geom);
|
||||||
this.geomStateMap.put(geom,shapeStatus);
|
this.geomStateMap.put(geom,hitboxState);
|
||||||
this.geoms.add(geom);
|
this.geoms.add(geom);
|
||||||
shapeStatus.setPreviousWorldPos(worldPosition);
|
hitboxState.setPreviousWorldPos(worldPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -289,6 +289,58 @@ public class AttachUtils {
|
|||||||
Vector3d bonePosition,
|
Vector3d bonePosition,
|
||||||
Quaterniond boneRotation,
|
Quaterniond boneRotation,
|
||||||
|
|
||||||
|
//parent transforms
|
||||||
|
Vector3d parentPosition,
|
||||||
|
Quaterniond parentRotation,
|
||||||
|
Vector3d parentScale
|
||||||
|
){
|
||||||
|
//transform bone space
|
||||||
|
Vector3d position = AttachUtils.calculateBoneAttachmentPosition(
|
||||||
|
offsetVector,
|
||||||
|
offsetRotation,
|
||||||
|
bonePosition,
|
||||||
|
boneRotation,
|
||||||
|
parentPosition,
|
||||||
|
parentRotation,
|
||||||
|
parentScale
|
||||||
|
);
|
||||||
|
//set
|
||||||
|
EntityUtils.getPosition(child).set(position);
|
||||||
|
|
||||||
|
|
||||||
|
//calculate and apply rotation
|
||||||
|
Quaterniond rotation = AttachUtils.calculateBoneAttachmentRotation(
|
||||||
|
offsetVector,
|
||||||
|
offsetRotation,
|
||||||
|
bonePosition,
|
||||||
|
boneRotation,
|
||||||
|
parentPosition,
|
||||||
|
parentRotation,
|
||||||
|
parentScale
|
||||||
|
);
|
||||||
|
EntityUtils.getRotation(child).set(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the position of an entity attached to a bone
|
||||||
|
* @param offsetVector The offset position
|
||||||
|
* @param offsetRotation The offset rotation
|
||||||
|
* @param bonePosition The bone's position
|
||||||
|
* @param boneRotation The bone's rotation
|
||||||
|
* @param parentPosition The parent's position
|
||||||
|
* @param parentRotation The parent's rotation
|
||||||
|
* @param parentScale The parent's scale
|
||||||
|
* @return The position of the attached/child entity
|
||||||
|
*/
|
||||||
|
public static Vector3d calculateBoneAttachmentPosition(
|
||||||
|
//optional offsets
|
||||||
|
Vector3d offsetVector,
|
||||||
|
Quaterniond offsetRotation,
|
||||||
|
|
||||||
|
//current bone transform
|
||||||
|
Vector3d bonePosition,
|
||||||
|
Quaterniond boneRotation,
|
||||||
|
|
||||||
//parent transforms
|
//parent transforms
|
||||||
Vector3d parentPosition,
|
Vector3d parentPosition,
|
||||||
Quaterniond parentRotation,
|
Quaterniond parentRotation,
|
||||||
@ -302,11 +354,36 @@ public class AttachUtils {
|
|||||||
position = position.rotate(new Quaterniond(parentRotation));
|
position = position.rotate(new Quaterniond(parentRotation));
|
||||||
//transform worldspace
|
//transform worldspace
|
||||||
position.add(parentPosition);
|
position.add(parentPosition);
|
||||||
//set
|
|
||||||
EntityUtils.getPosition(child).set(position);
|
return position;
|
||||||
//calculate rotation of model
|
}
|
||||||
EntityUtils.getRotation(child)
|
|
||||||
.identity()
|
/**
|
||||||
|
* Calculates the rotation of a child that is attached to a bone on an entity
|
||||||
|
* @param offsetVector The offset vector
|
||||||
|
* @param offsetRotation The offset rotation
|
||||||
|
* @param bonePosition The position of the bone
|
||||||
|
* @param boneRotation The rotation of the bone
|
||||||
|
* @param parentPosition The position of the parent
|
||||||
|
* @param parentRotation The rotation of the parent
|
||||||
|
* @param parentScale The scale of the parent
|
||||||
|
* @return The rotation of the child
|
||||||
|
*/
|
||||||
|
public static Quaterniond calculateBoneAttachmentRotation(
|
||||||
|
//optional offsets
|
||||||
|
Vector3d offsetVector,
|
||||||
|
Quaterniond offsetRotation,
|
||||||
|
|
||||||
|
//current bone transform
|
||||||
|
Vector3d bonePosition,
|
||||||
|
Quaterniond boneRotation,
|
||||||
|
|
||||||
|
//parent transforms
|
||||||
|
Vector3d parentPosition,
|
||||||
|
Quaterniond parentRotation,
|
||||||
|
Vector3d parentScale
|
||||||
|
){
|
||||||
|
return new Quaterniond()
|
||||||
.mul(parentRotation)
|
.mul(parentRotation)
|
||||||
.mul(boneRotation)
|
.mul(boneRotation)
|
||||||
.mul(offsetRotation)
|
.mul(offsetRotation)
|
||||||
@ -649,7 +726,6 @@ public class AttachUtils {
|
|||||||
* @param parentEntity
|
* @param parentEntity
|
||||||
* @return The list of entities that are attached to this parent entity, or null if undefined
|
* @return The list of entities that are attached to this parent entity, or null if undefined
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked") //as long as we only ever access this value via the getters and setters in this class, this assumption should always be correct
|
|
||||||
public static List<Entity> getChildrenList(Entity parentEntity){
|
public static List<Entity> getChildrenList(Entity parentEntity){
|
||||||
return (List<Entity>)parentEntity.getData(EntityDataStrings.ATTACH_CHILDREN_LIST);
|
return (List<Entity>)parentEntity.getData(EntityDataStrings.ATTACH_CHILDREN_LIST);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,6 +59,9 @@ public class HitboxData {
|
|||||||
//used to filter this hitbox to hitting only certain parent entities
|
//used to filter this hitbox to hitting only certain parent entities
|
||||||
List<Entity> filter;
|
List<Entity> filter;
|
||||||
|
|
||||||
|
//The offset from the bone
|
||||||
|
List<Double> offset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the type of hitbox
|
* Gets the type of hitbox
|
||||||
* @return the type of hitbox
|
* @return the type of hitbox
|
||||||
@ -194,6 +197,22 @@ public class HitboxData {
|
|||||||
public List<Entity> getEntityFilter(){
|
public List<Entity> getEntityFilter(){
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the offset for the hitbox
|
||||||
|
* @return The offset
|
||||||
|
*/
|
||||||
|
public List<Double> getOffset(){
|
||||||
|
return this.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the offset for the hitbox
|
||||||
|
* @param offset The offset
|
||||||
|
*/
|
||||||
|
public void setOffset(List<Double> offset){
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,64 @@
|
|||||||
|
package electrosphere.game.data.utils;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.joml.Quaterniond;
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts data structures between formats saved to disk vs formats used in engine
|
||||||
|
*/
|
||||||
|
public class DataFormatUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the rotation in quaterniond form
|
||||||
|
* @param values The list of raw float values
|
||||||
|
* @return The quaterniond containing those values or an identity quaterniond if no such values exist
|
||||||
|
*/
|
||||||
|
public static Quaterniond getDoubleListAsQuaternion(List<Double> values){
|
||||||
|
if(values == null){
|
||||||
|
return new Quaterniond();
|
||||||
|
}
|
||||||
|
if(values.size() > 0){
|
||||||
|
return new Quaterniond(values.get(0),values.get(1),values.get(2),values.get(3));
|
||||||
|
} else {
|
||||||
|
return new Quaterniond();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a quaterniond as a list of doubles
|
||||||
|
* @param quat The quaternion
|
||||||
|
* @return The list of doubles
|
||||||
|
*/
|
||||||
|
public static List<Double> getQuatAsDoubleList(Quaterniond quat){
|
||||||
|
return Arrays.asList((Double)quat.x,(Double)quat.y,(Double)quat.z,(Double)quat.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the vector in vector3d form
|
||||||
|
* @param values The list of raw float values
|
||||||
|
* @return The vector containing those values or an identity vector if no such values exist
|
||||||
|
*/
|
||||||
|
public static Vector3d getDoubleListAsVector(List<Double> values){
|
||||||
|
if(values == null){
|
||||||
|
return new Vector3d();
|
||||||
|
}
|
||||||
|
if(values.size() > 0){
|
||||||
|
return new Vector3d(values.get(0),values.get(1),values.get(2));
|
||||||
|
} else {
|
||||||
|
return new Vector3d();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a vector as a list of doubles
|
||||||
|
* @param vec The vector
|
||||||
|
* @return The list of doubles
|
||||||
|
*/
|
||||||
|
public static List<Double> getVectorAsDoubleList(Vector3d vec){
|
||||||
|
return Arrays.asList((Double)vec.x,(Double)vec.y,(Double)vec.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user