From de77ead36ea84bfcd4fd5cb216e95f18337337c3 Mon Sep 17 00:00:00 2001 From: austin Date: Sat, 2 Apr 2022 22:27:34 -0400 Subject: [PATCH] rotator system --- assets/Data/creatures/human.json | 6 +-- build.sh | 3 +- .../electrosphere/controls/CameraHandler.java | 8 +++ .../java/electrosphere/entity/Entity.java | 4 ++ .../entity/EntityDataStrings.java | 5 ++ .../entity/state/AttackTree.java | 21 +++++--- .../state/rotator/RotatorConstraint.java | 8 +++ .../state/rotator/RotatorHierarchyNode.java | 12 +---- .../entity/state/rotator/RotatorTree.java | 52 ++++++++++++++++--- .../entity/state/view/ViewUtils.java | 20 +++++++ .../entity/types/creature/CreatureUtils.java | 15 +++++- 11 files changed, 125 insertions(+), 29 deletions(-) create mode 100644 src/main/java/electrosphere/entity/state/view/ViewUtils.java diff --git a/assets/Data/creatures/human.json b/assets/Data/creatures/human.json index f16e5662..6d720a8a 100644 --- a/assets/Data/creatures/human.json +++ b/assets/Data/creatures/human.json @@ -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 } ] } diff --git a/build.sh b/build.sh index 4433f6d6..a13852e4 100755 --- a/build.sh +++ b/build.sh @@ -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 diff --git a/src/main/java/electrosphere/controls/CameraHandler.java b/src/main/java/electrosphere/controls/CameraHandler.java index b49af49b..e2aaba92 100644 --- a/src/main/java/electrosphere/controls/CameraHandler.java +++ b/src/main/java/electrosphere/controls/CameraHandler.java @@ -87,4 +87,12 @@ public class CameraHandler { Globals.viewMatrix = CameraEntityUtils.getCameraViewMatrix(Globals.playerCamera); } + public float getYaw(){ + return yaw; + } + + public float getPitch(){ + return pitch; + } + } diff --git a/src/main/java/electrosphere/entity/Entity.java b/src/main/java/electrosphere/entity/Entity.java index f3988d08..f746175d 100644 --- a/src/main/java/electrosphere/entity/Entity.java +++ b/src/main/java/electrosphere/entity/Entity.java @@ -44,6 +44,10 @@ public class Entity { public List getDataKeys(){ return dataKeys; } + + public boolean containsKey(String key){ + return data.containsKey(key); + } public Object getData(String key){ return data.get(key); diff --git a/src/main/java/electrosphere/entity/EntityDataStrings.java b/src/main/java/electrosphere/entity/EntityDataStrings.java index 84aa6892..5528e86f 100644 --- a/src/main/java/electrosphere/entity/EntityDataStrings.java +++ b/src/main/java/electrosphere/entity/EntityDataStrings.java @@ -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 diff --git a/src/main/java/electrosphere/entity/state/AttackTree.java b/src/main/java/electrosphere/entity/state/AttackTree.java index 828cefbf..29dc202a 100644 --- a/src/main/java/electrosphere/entity/state/AttackTree.java +++ b/src/main/java/electrosphere/entity/state/AttackTree.java @@ -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 attachedEntities = (List)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 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 attachedEntities = (List)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 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){ diff --git a/src/main/java/electrosphere/entity/state/rotator/RotatorConstraint.java b/src/main/java/electrosphere/entity/state/rotator/RotatorConstraint.java index 8d427eec..39a18449 100644 --- a/src/main/java/electrosphere/entity/state/rotator/RotatorConstraint.java +++ b/src/main/java/electrosphere/entity/state/rotator/RotatorConstraint.java @@ -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; } diff --git a/src/main/java/electrosphere/entity/state/rotator/RotatorHierarchyNode.java b/src/main/java/electrosphere/entity/state/rotator/RotatorHierarchyNode.java index 2bc3a72d..2242d56f 100644 --- a/src/main/java/electrosphere/entity/state/rotator/RotatorHierarchyNode.java +++ b/src/main/java/electrosphere/entity/state/rotator/RotatorHierarchyNode.java @@ -1,12 +1,12 @@ package electrosphere.entity.state.rotator; +import java.util.LinkedList; import java.util.List; public class RotatorHierarchyNode { String bone; - List rotatorConstraints; - List children; + List rotatorConstraints = new LinkedList(); public String getBone(){ return bone; @@ -16,14 +16,6 @@ public class RotatorHierarchyNode { return rotatorConstraints; } - public List getChildren(){ - return children; - } - - public void addChild(RotatorHierarchyNode child){ - this.children.add(child); - } - public void addRotatorConstraint(RotatorConstraint contraint){ this.rotatorConstraints.add(contraint); } diff --git a/src/main/java/electrosphere/entity/state/rotator/RotatorTree.java b/src/main/java/electrosphere/entity/state/rotator/RotatorTree.java index 0aaee507..7e03fc1b 100644 --- a/src/main/java/electrosphere/entity/state/rotator/RotatorTree.java +++ b/src/main/java/electrosphere/entity/state/rotator/RotatorTree.java @@ -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 rootNodes; + List nodes = new LinkedList(); 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); + } } diff --git a/src/main/java/electrosphere/entity/state/view/ViewUtils.java b/src/main/java/electrosphere/entity/state/view/ViewUtils.java new file mode 100644 index 00000000..34bc0f9c --- /dev/null +++ b/src/main/java/electrosphere/entity/state/view/ViewUtils.java @@ -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; + } + } + +} diff --git a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java index a7180f77..aa6f69df 100644 --- a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java +++ b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java @@ -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()));