rotator system

This commit is contained in:
austin 2022-04-02 22:27:34 -04:00
parent c461f75480
commit de77ead36e
11 changed files with 125 additions and 29 deletions

View File

@ -128,7 +128,7 @@
"followsView" : true,
"followsBone" : false,
"parentBone" : "",
"allowedMargin" : 0.2
"allowedMarginPitch" : 0.2
}
]
},
@ -139,7 +139,7 @@
"followsView" : false,
"followsBone" : true,
"parentBone" : "myTorsoBone",
"allowedMargin" : 0.2
"allowedMarginYaw" : 0.2
}
]
},
@ -150,7 +150,7 @@
"followsView" : false,
"followsBone" : true,
"parentBone" : "myTorsoBone",
"allowedMargin" : 0.2
"allowedMarginYaw" : 0.2
}
]
}

View File

@ -1,5 +1,6 @@
#DEPENDENCIES
#Windows, JDK17, Maven, GitBash, 7zip, MinGW, GCC, Make
#Windows: JDK17, Maven, GitBash, 7zip, MinGW, GCC, Make
#Linux: JDK17, Maven, git, bash, unzip, GCC, Make
#completely clear build directory
rm -rf ./build

View File

@ -87,4 +87,12 @@ public class CameraHandler {
Globals.viewMatrix = CameraEntityUtils.getCameraViewMatrix(Globals.playerCamera);
}
public float getYaw(){
return yaw;
}
public float getPitch(){
return pitch;
}
}

View File

@ -44,6 +44,10 @@ public class Entity {
public List<String> getDataKeys(){
return dataKeys;
}
public boolean containsKey(String key){
return data.containsKey(key);
}
public Object getData(String key){
return data.get(key);

View File

@ -216,6 +216,11 @@ public class EntityDataStrings {
Iron sight
*/
public static final String IRON_SIGHT_TREE = "ironSightTree";
/*
AI stuff
*/
public static final String VIEW_PITCH = "aiViewPitch";
/*
Entity categories

View File

@ -5,6 +5,7 @@ import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.collidable.Impulse;
import electrosphere.entity.state.equip.EquipState;
import electrosphere.entity.state.rotator.RotatorTree;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.hitbox.HitboxUtils;
@ -109,7 +110,7 @@ public class AttackTree {
//intuit can hold from presence of windup anim
currentMoveCanHold = currentMove.getHoldAnimationName() != null;
//stop movement tree
if(parent.getDataKeys().contains(EntityDataStrings.DATA_STRING_MOVEMENT_BT)){
if(parent.containsKey(EntityDataStrings.DATA_STRING_MOVEMENT_BT)){
CreatureUtils.getEntityMovementTree(parent).interrupt();
}
Vector3d movementVector = CreatureUtils.getFacingVector(parent);
@ -183,6 +184,9 @@ public class AttackTree {
//state machine
switch(state){
case WINDUP:
if(parent.containsKey(EntityDataStrings.ROTATOR_TREE)){
RotatorTree.getRotatorTree(parent).setActive(true);
}
if(entityActor != null){
if(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(animationName)){
entityActor.playAnimation(animationName,1);
@ -272,10 +276,10 @@ public class AttackTree {
// }
break;
case ATTACK:
if(parent.getDataKeys().contains(EntityDataStrings.ATTACH_CHILDREN_LIST)){
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){
List<Entity> attachedEntities = (List<Entity>)parent.getData(EntityDataStrings.ATTACH_CHILDREN_LIST);
for(Entity currentAttached : attachedEntities){
if(currentAttached.getDataKeys().contains(EntityDataStrings.HITBOX_ASSOCIATED_LIST)){
if(currentAttached.containsKey(EntityDataStrings.HITBOX_ASSOCIATED_LIST)){
List<Entity> hitboxes = HitboxUtils.getHitboxAssociatedList(currentAttached);
for(Entity hitbox : hitboxes){
HitboxUtils.getHitboxData(hitbox).setActive(true);
@ -353,10 +357,10 @@ public class AttackTree {
}
break;
case COOLDOWN:
if(parent.getDataKeys().contains(EntityDataStrings.ATTACH_CHILDREN_LIST)){
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){
List<Entity> attachedEntities = (List<Entity>)parent.getData(EntityDataStrings.ATTACH_CHILDREN_LIST);
for(Entity currentAttached : attachedEntities){
if(currentAttached.getDataKeys().contains(EntityDataStrings.HITBOX_ASSOCIATED_LIST)){
if(currentAttached.containsKey(EntityDataStrings.HITBOX_ASSOCIATED_LIST)){
List<Entity> hitboxes = HitboxUtils.getHitboxAssociatedList(currentAttached);
for(Entity hitbox : hitboxes){
HitboxUtils.getHitboxData(hitbox).setActive(false);
@ -368,6 +372,9 @@ public class AttackTree {
if(frameCurrent > 60){
state = AttackTreeState.IDLE;
frameCurrent = 0;
if(parent.containsKey(EntityDataStrings.ROTATOR_TREE)){
RotatorTree.getRotatorTree(parent).setActive(false);
}
}
if(Globals.RUN_SERVER){
Globals.server.broadcastMessage(
@ -414,7 +421,7 @@ public class AttackTree {
String getAttackType(){
String rVal = null;
if(parent.getDataKeys().contains(EntityDataStrings.EQUIP_STATE)){
if(parent.containsKey(EntityDataStrings.EQUIP_STATE)){
EquipState equipState = (EquipState)parent.getData(EntityDataStrings.EQUIP_STATE);
for(String point : equipState.equippedPoints()){
Entity item = equipState.getEquippedItemAtPoint(point);
@ -444,7 +451,7 @@ public class AttackTree {
rVal = true;
}
} else {
if(parent.getDataKeys().contains(EntityDataStrings.EQUIP_STATE)){
if(parent.containsKey(EntityDataStrings.EQUIP_STATE)){
EquipState equipState = (EquipState)parent.getData(EntityDataStrings.EQUIP_STATE);
// if(equipState.hasEquipPrimary()){
// switch(attackType){

View File

@ -8,6 +8,14 @@ public class RotatorConstraint {
float allowedMarginPitch;
float allowedMarginYaw;
public RotatorConstraint(electrosphere.game.data.creature.type.rotator.RotatorConstraint data){
followsBone = data.getFollowsBone();
followsView = data.getFollowsView();
parentBone = data.getParentBone();
allowedMarginPitch = data.getAllowedMarginPitch();
allowedMarginYaw = data.getAllowedMarginYaw();
}
public boolean getFollowsView(){
return followsView;
}

View File

@ -1,12 +1,12 @@
package electrosphere.entity.state.rotator;
import java.util.LinkedList;
import java.util.List;
public class RotatorHierarchyNode {
String bone;
List<RotatorConstraint> rotatorConstraints;
List<RotatorHierarchyNode> children;
List<RotatorConstraint> rotatorConstraints = new LinkedList<RotatorConstraint>();
public String getBone(){
return bone;
@ -16,14 +16,6 @@ public class RotatorHierarchyNode {
return rotatorConstraints;
}
public List<RotatorHierarchyNode> getChildren(){
return children;
}
public void addChild(RotatorHierarchyNode child){
this.children.add(child);
}
public void addRotatorConstraint(RotatorConstraint contraint){
this.rotatorConstraints.add(contraint);
}

View File

@ -1,14 +1,23 @@
package electrosphere.entity.state.rotator;
import java.util.LinkedList;
import java.util.List;
import org.joml.Quaternionf;
import org.joml.Vector3d;
import org.joml.Vector3f;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.BehaviorTree;
import electrosphere.entity.state.view.ViewUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.main.Globals;
import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.actor.ActorBoneRotator;
public class RotatorTree {
public class RotatorTree implements BehaviorTree{
public static enum RotatorTreeState {
ACTIVE,
@ -20,9 +29,10 @@ public class RotatorTree {
Entity parent;
Actor entityActor;
List<RotatorHierarchyNode> rootNodes;
List<RotatorHierarchyNode> nodes = new LinkedList<RotatorHierarchyNode>();
public RotatorTree(Entity parent){
this.parent = parent;
entityActor = EntityUtils.getActor(parent);
state = RotatorTreeState.INACTIVE;
}
@ -32,12 +42,16 @@ public class RotatorTree {
state = RotatorTreeState.ACTIVE;
} else {
state = RotatorTreeState.INACTIVE;
//clear all modifications we've made up to this point
for(RotatorHierarchyNode node : nodes){
entityActor.getBoneRotator(node.getBone()).getRotation().identity();
}
}
}
public void simulate(){
if(entityActor.modelIsLoaded() && this.state == RotatorTreeState.ACTIVE){
for(RotatorHierarchyNode node : rootNodes){
for(RotatorHierarchyNode node : nodes){
applyRotatorNode(node);
}
}
@ -58,13 +72,33 @@ public class RotatorTree {
// currentRotation.
}
if(followsView){
// Quaternionf currentRotation = entityActor.getBoneRotation(parentBone);
ActorBoneRotator currentRotator = entityActor.getBoneRotator(node.getBone());
//apparently this isn't needed?
//not sure I understand the math on this one
// Vector3d facingVector = CreatureUtils.getFacingVector(parent);
// Vector3f rotationAxis = new Vector3f((float)facingVector.x,(float)facingVector.y,(float)facingVector.z).rotateY((float)Math.PI/2.0f).normalize();
Vector3f rotationAxis = new Vector3f(1,0,0);
float rotationRaw = 0.0f;
if(parent == Globals.playerCharacter){
rotationRaw = Globals.cameraHandler.getPitch();
} else {
rotationRaw = ViewUtils.getPitch(parent);
}
float rotation = (float)(rotationRaw * Math.PI / 180.0f);
if(Math.abs(rotation) > constraint.getAllowedMarginPitch()){
rotation = (float)Math.copySign(constraint.allowedMarginPitch, rotation);
}
currentRotator.getRotation().identity().rotationAxis(rotation, rotationAxis);
}
}
//recurse to children
for(RotatorHierarchyNode child : node.getChildren()){
applyRotatorNode(child);
}
// for(RotatorHierarchyNode child : node.getChildren()){
// applyRotatorNode(child);
// }
}
public void addRotatorNode(RotatorHierarchyNode node){
nodes.add(node);
}
public float calculateYawOfQuat(Quaternionf quat){
@ -74,5 +108,9 @@ public class RotatorTree {
public float calculatePitchOfQuat(Quaternionf quat){
return (float)Math.asin(-2.0*(quat.x*quat.z - quat.w*quat.y));
}
public static RotatorTree getRotatorTree(Entity parent){
return (RotatorTree)parent.getData(EntityDataStrings.ROTATOR_TREE);
}
}

View File

@ -0,0 +1,20 @@
package electrosphere.entity.state.view;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
public class ViewUtils {
public static void setPitch(Entity parent, float pitch){
parent.putData(EntityDataStrings.VIEW_PITCH, pitch);
}
public static float getPitch(Entity parent){
if(parent.containsKey(EntityDataStrings.VIEW_PITCH)){
return (float)parent.getData(EntityDataStrings.VIEW_PITCH);
} else {
return 0;
}
}
}

View File

@ -22,6 +22,8 @@ import electrosphere.entity.state.inventory.UnrelationalInventoryState;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.entity.state.life.LifeState;
import electrosphere.entity.state.movement.SprintTree;
import electrosphere.entity.state.rotator.RotatorHierarchyNode;
import electrosphere.entity.state.rotator.RotatorTree;
import electrosphere.game.collision.PhysicsUtils;
import electrosphere.game.collision.collidable.Collidable;
import electrosphere.game.data.creature.type.CollidableTemplate;
@ -32,6 +34,7 @@ import electrosphere.game.data.creature.type.movement.FallMovementSystem;
import electrosphere.game.data.creature.type.movement.GroundMovementSystem;
import electrosphere.game.data.creature.type.movement.JumpMovementSystem;
import electrosphere.game.data.creature.type.movement.MovementSystem;
import electrosphere.game.data.creature.type.rotator.RotatorConstraint;
import electrosphere.game.data.creature.type.rotator.RotatorItem;
import electrosphere.game.data.creature.type.rotator.RotatorSystem;
import electrosphere.game.data.creature.type.visualattribute.AttributeVariant;
@ -301,11 +304,21 @@ public class CreatureUtils {
//rotator system
if(rawType.getRotatorSystem() != null){
RotatorSystem system = rawType.getRotatorSystem();
RotatorTree rotatorTree = new RotatorTree(rVal);
for(RotatorItem item : system.getRotatorItems()){
//put actor rotator
ActorBoneRotator newRotator = new ActorBoneRotator();
newRotator.getRotation().rotationAxis((float)Math.PI/2.0f, new Vector3f(1,0,0));
creatureActor.addBoneRotator(item.getBoneName(), newRotator);
//construct node for tree
RotatorHierarchyNode hierarchyNode = new RotatorHierarchyNode();
hierarchyNode.setBone(item.getBoneName());
for(RotatorConstraint constraint : item.getConstraints()){
hierarchyNode.addRotatorConstraint(new electrosphere.entity.state.rotator.RotatorConstraint(constraint));
}
rotatorTree.addRotatorNode(hierarchyNode);
}
rVal.putData(EntityDataStrings.ROTATOR_TREE, rotatorTree);
Globals.entityManager.registerBehaviorTree(rotatorTree);
}
//add health system
rVal.putData(EntityDataStrings.LIFE_STATE, new LifeState(rVal, rawType.getHealthSystem()));