foliage fix, first person view model, other fixes
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2024-05-24 22:52:42 -04:00
parent bd244b151d
commit 29f5496e23
42 changed files with 1076 additions and 164 deletions

View File

@ -134,16 +134,25 @@
"length" : 1,
"loops" : false
},
"animationFirstPersonStartup" : {
"name" : "Jog"
},
"animationLoop" : {
"name" : "Jog",
"length" : 1,
"loops" : false
},
"animationFirstPersonLoop" : {
"name" : "Jog"
},
"animationWindDown" : {
"name" : "Jog",
"length" : 1,
"loops" : false
},
"animationFirstPersonWindDown" : {
"name" : "Jog"
},
"sprintSystem" : {
"maxVelocity" : 0.058,
"staminaMax" : 500,
@ -167,6 +176,9 @@
"name" : "Jump",
"length" : 1,
"loops" : false
},
"animationFirstPersonJump" : {
"name" : "Jump"
}
},
{
@ -176,10 +188,16 @@
"length" : 1,
"loops" : true
},
"animationFirstPersonFall" : {
"name" : "Fall"
},
"animationLand" : {
"name" : "Land",
"length" : 1,
"loops" : true
},
"animationFirstPersonLand" : {
"name" : "Land"
}
}
],
@ -224,6 +242,7 @@
{
"equipPointId" : "handLeft",
"bone" : "MiddleLower.L",
"firstPersonBone" : "hand.L",
"offsetVector" : [],
"offsetRotation" : [],
"equipClassWhitelist" : [
@ -235,6 +254,7 @@
{
"equipPointId" : "handRight",
"bone" : "MiddleLower.R",
"firstPersonBone" : "hand.R",
"offsetVector" : [],
"offsetRotation" : [0.3057,0.2926,0.09933,0.9006],
"equipClassWhitelist" : [
@ -294,7 +314,16 @@
"driftGoal" : 0.02,
"driftFrameStart" : 7,
"driftFrameEnd" : 15,
"initialMove" : true
"initialMove" : true,
"animationFirstPersonWindup" : {
"name" : "Jump"
},
"animationFirstPersonHold" : {
"name" : "Jump"
},
"animationFirstPersonAttack" : {
"name" : "Jump"
}
},
{
"attackMoveId" : "Sword1HSlash2",
@ -310,7 +339,16 @@
"driftGoal" : 0.03,
"driftFrameStart" : 1,
"driftFrameEnd" : 10,
"initialMove" : false
"initialMove" : false,
"animationFirstPersonWindup" : {
"name" : "Jump"
},
"animationFirstPersonHold" : {
"name" : "Jump"
},
"animationFirstPersonAttack" : {
"name" : "Jump"
}
},
{
"attackMoveId" : "Bow2HFire",
@ -327,14 +365,33 @@
"movementStart" : 0,
"movementEnd" : 0,
"movementGoal" : 0,
"initialMove" : true
"initialMove" : true,
"animationFirstPersonWindup" : {
"name" : "Jump"
},
"animationFirstPersonHold" : {
"name" : "Jump"
},
"animationFirstPersonAttack" : {
"name" : "Jump"
}
}
],
"healthSystem" : {
"maxHealth" : 100,
"onDamageIFrames" : 30
},
"modelPath" : "Models/creatures/person2/person2_1.glb"
"idleData": {
"idleAnimation" : "Idle1",
"firstPersonIdleAnimation" : "Idle"
},
"modelPath" : "Models/creatures/person2/person2_1.glb",
"viewModelData" : {
"heightFromOrigin" : 0.8,
"cameraViewDirOffsetY" : -0.3,
"cameraViewDirOffsetZ" : 0.0,
"firstPersonModelPath" : "Models/creatures/viewmodel.glb"
}
}
],
"files" : []

Binary file not shown.

View File

@ -1,3 +1,3 @@
#maven.buildNumber.plugin properties file
#Thu May 02 18:40:02 EDT 2024
buildNumber=119
#Sun May 19 19:34:37 EDT 2024
buildNumber=132

View File

@ -273,23 +273,46 @@ Ground Texture Atlas system
First Person Camera
# TODO
(05/15/2024)
More consistent terrain editing
(05/16/2024)
Reintroduce strafing
(05/??/2024)
First person render pipeline
- Dedicated client scene
- Properly compositing onto main texture
- Potentially look at storing the framebuffer for the pipeline in the pipeline class itself
Overhaul of 'attach' semantics
- Having different types of attach tree propagation
- Ability to turn on/off combinations of models at will (already exists, but needs review)
(05/19/2024)
Character movement in particular feels off
- Bring back strafing
- Fix interaction with networking
- Potentially facing vector on server misaligned with client facing vector? - Nope! They're perfectly aligned
- May be in the ground move tree itself the hard setting velocity instead of applying a force is causing weirdness
(05/23/2024)
Viewmodel
- Fix hands placement
- Animations defined in data file
(05/24/2024)
Viewmodel
- Add animations queues in btrees
- idle
- jump
- ground movement
- land
- fall
- attack
Attaching items to hands in first person
Fix grass placement
# TODO
Fix being able to walk off far side of the world (ie in level editor)
Grass System properly LOD
@ -308,6 +331,13 @@ Data Cleanup
Clean up Material class
- fix storing textures in the mat class ( pain :c )
Clean up framebuffer class
- Comment everything
Overhaul of 'attach' semantics
- Having different types of attach tree propagation
- Ability to turn on/off combinations of models at will (already exists, but needs review)
More Debug menus
- Screen that shows the overall status of draw cell manager
- Screen that shows the overall status of fluid cell manager

View File

@ -1,7 +1,6 @@
package electrosphere.client.foliagemanager;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.HashMap;
@ -18,7 +17,6 @@ import org.joml.Vector3d;
import org.joml.Vector3f;
import org.joml.Vector3i;
import org.lwjgl.BufferUtils;
import org.lwjgl.system.MemoryUtil;
import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.engine.Globals;
@ -395,17 +393,20 @@ public class ClientFoliageManager {
//get position to place
double rand1 = placementRandomizer.nextDouble();
double rand2 = placementRandomizer.nextDouble();
double relativePositionOnGridX = x / (1.0 * TARGET_FOLIAGE_SPACING) - 0.5 + rand1 / TARGET_FOLIAGE_SPACING;
double relativePositionOnGridZ = z / (1.0 * TARGET_FOLIAGE_SPACING) - 0.5 + rand2 / TARGET_FOLIAGE_SPACING;
double offsetX = relativePositionOnGridX;
double offsetZ = relativePositionOnGridZ;
double relativePositionOnGridX = x / (1.0 * TARGET_FOLIAGE_SPACING) + rand1 / TARGET_FOLIAGE_SPACING;
double relativePositionOnGridZ = z / (1.0 * TARGET_FOLIAGE_SPACING) + rand2 / TARGET_FOLIAGE_SPACING;
double offsetX = relativePositionOnGridX - 0.5;
double offsetZ = relativePositionOnGridZ - 0.5;
//determine quadrant we're placing in
double offsetY = 0;
boolean addBlade = false;
if(relativePositionOnGridX >=0){
if(relativePositionOnGridZ >= 0){
relativePositionOnGridX += 0.5;
relativePositionOnGridZ += 0.5;
if(relativePositionOnGridX >=0.5){
if(relativePositionOnGridZ >= 0.5){
relativePositionOnGridX = relativePositionOnGridX - 0.5;
relativePositionOnGridZ = relativePositionOnGridZ - 0.5;
relativePositionOnGridX /= 0.5;
relativePositionOnGridZ /= 0.5;
// System.out.println(relativePositionOnGridX + " " + relativePositionOnGridZ);
//if we have heights for all four surrounding spots, interpolate for y value
if(sample_11 != null && sample_12 != null && sample_21 != null && sample_22 != null){
offsetY =
@ -416,8 +417,9 @@ public class ClientFoliageManager {
addBlade = true;
}
} else {
relativePositionOnGridX += 0.5;
relativePositionOnGridZ += 0.5;
relativePositionOnGridX = relativePositionOnGridX - 0.5;
relativePositionOnGridX /= 0.5;
relativePositionOnGridZ /= 0.5;
//if we have heights for all four surrounding spots, interpolate for y value
if(sample_10 != null && sample_11 != null && sample_20 != null && sample_21 != null){
offsetY =
@ -429,9 +431,10 @@ public class ClientFoliageManager {
}
}
} else {
if(relativePositionOnGridZ >= 0){
relativePositionOnGridX += 0.5;
relativePositionOnGridZ += 0.5;
if(relativePositionOnGridZ >= 0.5){
relativePositionOnGridZ = relativePositionOnGridZ - 0.5;
relativePositionOnGridX /= 0.5;
relativePositionOnGridZ /= 0.5;
//if we have heights for all four surrounding spots, interpolate for y value
if(sample_01 != null && sample_02 != null && sample_11 != null && sample_12 != null){
offsetY =
@ -442,8 +445,8 @@ public class ClientFoliageManager {
addBlade = true;
}
} else {
relativePositionOnGridX += 0.5;
relativePositionOnGridZ += 0.5;
relativePositionOnGridX /= 0.5;
relativePositionOnGridZ /= 0.5;
//if we have heights for all four surrounding spots, interpolate for y value
if(sample_00 != null && sample_01 != null && sample_10 != null && sample_11 != null){
offsetY =

View File

@ -475,14 +475,14 @@ public class ControlHandler {
if(movementTree instanceof ClientGroundMovementTree){
ClientGroundMovementTree groundTree = (ClientGroundMovementTree) movementTree;
Vector3f cameraEyeVector = CameraEntityUtils.getCameraEye(Globals.playerCamera);
if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_LEFT).isState()){
if(controls.get(DATA_STRING_INPUT_CODE_STRAFE_LEFT).isState()){
Vector3d newFacingVector = new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(Math.PI/4.0).normalize();
CreatureUtils.setFacingVector(Globals.playerEntity, newFacingVector);
groundTree.start(MovementRelativeFacing.FORWARD);
} else if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_RIGHT).isState()){
groundTree.start(MovementRelativeFacing.FORWARD_LEFT);
} else if(controls.get(DATA_STRING_INPUT_CODE_STRAFE_RIGHT).isState()){
Vector3d newFacingVector = new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(-Math.PI/4.0).normalize();
CreatureUtils.setFacingVector(Globals.playerEntity, newFacingVector);
groundTree.start(MovementRelativeFacing.FORWARD);
groundTree.start(MovementRelativeFacing.FORWARD_RIGHT);
} else {
Vector3d newFacingVector = new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).normalize();
CreatureUtils.setFacingVector(Globals.playerEntity, newFacingVector);
@ -497,14 +497,14 @@ public class ControlHandler {
if(movementTree instanceof ClientGroundMovementTree){
ClientGroundMovementTree groundTree = (ClientGroundMovementTree) movementTree;
Vector3f cameraEyeVector = CameraEntityUtils.getCameraEye(Globals.playerCamera);
if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_LEFT).isState()){
if(controls.get(DATA_STRING_INPUT_CODE_STRAFE_LEFT).isState()){
Vector3d newFacingVector = new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(Math.PI/4.0).normalize();
CreatureUtils.setFacingVector(Globals.playerEntity, newFacingVector);
groundTree.start(MovementRelativeFacing.FORWARD);
} else if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_RIGHT).isState()){
groundTree.start(MovementRelativeFacing.FORWARD_LEFT);
} else if(controls.get(DATA_STRING_INPUT_CODE_STRAFE_RIGHT).isState()){
Vector3d newFacingVector = new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(-Math.PI/4.0).normalize();
CreatureUtils.setFacingVector(Globals.playerEntity, newFacingVector);
groundTree.start(MovementRelativeFacing.FORWARD);
groundTree.start(MovementRelativeFacing.FORWARD_RIGHT);
} else {
Vector3d newFacingVector = new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).normalize();
CreatureUtils.setFacingVector(Globals.playerEntity, newFacingVector);
@ -532,15 +532,15 @@ public class ControlHandler {
if(movementTree instanceof ClientGroundMovementTree){
ClientGroundMovementTree groundTree = (ClientGroundMovementTree) movementTree;
Vector3f cameraEyeVector = CameraEntityUtils.getCameraEye(Globals.playerCamera);
if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_LEFT).isState()){
if(controls.get(DATA_STRING_INPUT_CODE_STRAFE_LEFT).isState()){
CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(3.0/4.0*Math.PI).normalize());
groundTree.start(MovementRelativeFacing.FORWARD);
} else if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_RIGHT).isState()){
groundTree.start(MovementRelativeFacing.BACKWARD_LEFT);
} else if(controls.get(DATA_STRING_INPUT_CODE_STRAFE_RIGHT).isState()){
CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(5.0/4.0*Math.PI).normalize());
groundTree.start(MovementRelativeFacing.FORWARD);
groundTree.start(MovementRelativeFacing.BACKWARD_RIGHT);
} else {
CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(Math.PI).normalize());
groundTree.start(MovementRelativeFacing.FORWARD);
CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).normalize());
groundTree.start(MovementRelativeFacing.BACKWARD);
}
}
}
@ -551,15 +551,15 @@ public class ControlHandler {
if(movementTree instanceof ClientGroundMovementTree){
ClientGroundMovementTree groundTree = (ClientGroundMovementTree) movementTree;
Vector3f cameraEyeVector = CameraEntityUtils.getCameraEye(Globals.playerCamera);
if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_LEFT).isState()){
if(controls.get(DATA_STRING_INPUT_CODE_STRAFE_LEFT).isState()){
CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(3.0/4.0*Math.PI).normalize());
groundTree.start(MovementRelativeFacing.FORWARD);
} else if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_RIGHT).isState()){
groundTree.start(MovementRelativeFacing.BACKWARD_LEFT);
} else if(controls.get(DATA_STRING_INPUT_CODE_STRAFE_RIGHT).isState()){
CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(5.0/4.0*Math.PI).normalize());
groundTree.start(MovementRelativeFacing.FORWARD);
groundTree.start(MovementRelativeFacing.BACKWARD_RIGHT);
} else {
CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(Math.PI).normalize());
groundTree.start(MovementRelativeFacing.FORWARD);
CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).normalize());
groundTree.start(MovementRelativeFacing.BACKWARD);
}
}
}

View File

@ -369,6 +369,8 @@ public class Globals {
//the creature the player camera will orbit and will receive controlHandler movementTree updates
public static Entity playerEntity;
//the entity for the first person modal (view model)
public static Entity firstPersonEntity;
//client current selected voxel type
public static VoxelType clientSelectedVoxelType = null;

View File

@ -182,7 +182,7 @@ public class ClientLoading {
Globals.playerCamera = CameraEntityUtils.spawnPlayerEntityTrackingCameraFirstPersonEntity(new Vector3f(1,0,1), new Vector3f(0,0,1));
}
/*
Targeting crosshair

View File

@ -70,6 +70,7 @@ public class EntityDataStrings {
public static final String SERVER_JUMP_TREE = "serverJumpTree";
public static final String FALL_TREE = "fallTree";
public static final String CREATURE_TEMPLATE = "creatureTemplate";
public static final String FIRST_PERSON_TREE = "firstPersonTree";
/*

View File

@ -11,6 +11,7 @@ import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.state.client.firstPerson.FirstPersonTree;
import electrosphere.entity.state.collidable.Impulse;
import electrosphere.entity.state.equip.ClientEquipState;
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree;
@ -48,6 +49,9 @@ import org.joml.Vector3f;
public class ClientAttackTree implements BehaviorTree {
@SynchronizableEnum
/**
* States available to the attack tree
*/
public static enum AttackTreeState {
WINDUP,
HOLD,
@ -56,29 +60,39 @@ public class ClientAttackTree implements BehaviorTree {
IDLE,
}
//the state of drifting forward during the attack
@SynchronizableEnum
/**
* The state of drifting forward during the attack
*/
public static enum AttackTreeDriftState {
DRIFT,
NO_DRIFT,
}
//the current state of the tree
@SyncedField
AttackTreeState state;
//the current state of drifting caused by the tree
@SyncedField
AttackTreeDriftState driftState;
//the parent entity of this attack tree
Entity parent;
//the queue of network messages to process
CopyOnWriteArrayList<EntityMessage> networkMessageQueue = new CopyOnWriteArrayList<EntityMessage>();
//the last time this tree was updated by server
long lastUpdateTime = 0;
//the current frame of the current animation/move
float frameCurrent;
//the name of the current animation
String animationName = "SwingWeapon";
//the max frame
int maxFrame = 60;
List<AttackMove> currentMoveset = null;
@ -239,13 +253,14 @@ public class ClientAttackTree implements BehaviorTree {
if(parent.containsKey(EntityDataStrings.CLIENT_ROTATOR_TREE)){
RotatorTree.getClientRotatorTree(parent).setActive(true);
}
if(entityActor != null){
if(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(animationName)){
entityActor.playAnimation(animationName,1);
entityActor.incrementAnimationTime(0.0001);
}
}
if(currentMove != null && frameCurrent > currentMove.getWindupFrames()){
if(entityActor != null){
if(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(currentMove.getWindupAnimationName())){
entityActor.playAnimation(currentMove.getWindupAnimationName(),1);
entityActor.incrementAnimationTime(0.0001);
}
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonWindup().getName());
}
if(currentMoveCanHold && stillHold){
state = AttackTreeState.HOLD;
} else {
@ -259,6 +274,7 @@ public class ClientAttackTree implements BehaviorTree {
entityActor.playAnimation(animationName,1);
entityActor.incrementAnimationTime(0.0001);
}
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonHold().getName());
}
if(!stillHold){
state = AttackTreeState.ATTACK;

View File

@ -1,4 +1,4 @@
package electrosphere.entity.state.ambientaudio;
package electrosphere.entity.state.client.ambientaudio;
import org.joml.Vector3d;

View File

@ -0,0 +1,123 @@
package electrosphere.entity.state.client.firstPerson;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.renderer.actor.Actor;
/**
* Manages the animations for the first person view model
*/
public class FirstPersonTree implements BehaviorTree {
//the offset from the origin to place the viewmodel
double heightFromOrigin;
//the amount to pull below the camera
double cameraViewDirOffsetY;
//the amount to pull behind the camera
double cameraViewDirOffsetZ;
//the animation to play currently
String currentAnimation = "Idle";
@Override
public void simulate(float deltaTime) {
if(Globals.firstPersonEntity != null){
Actor actor = EntityUtils.getActor(Globals.firstPersonEntity);
if(
(!actor.isPlayingAnimation() || !actor.isPlayingAnimation(currentAnimation)) &&
(Globals.assetManager.fetchModel(actor.getModelPath()) != null && Globals.assetManager.fetchModel(actor.getModelPath()).getAnimation(currentAnimation) != null)
){
actor.playAnimation(currentAnimation,3);
actor.incrementAnimationTime(0.0001);
}
}
}
/**
* Attaches this tree to the entity.
* @param entity The entity to attach to
* @param heightFromOrigin How far from the origin of the creature to place the viewmodel
* @param cameraViewDirOffset How far to pull the view model behind the camera
*/
public static FirstPersonTree attachTree(Entity parent, double heightFromOrigin, double cameraViewDirOffsetY, double cameraViewDirOffsetZ){
FirstPersonTree rVal = new FirstPersonTree();
rVal.heightFromOrigin = heightFromOrigin;
rVal.cameraViewDirOffsetY = cameraViewDirOffsetY;
rVal.cameraViewDirOffsetZ = cameraViewDirOffsetZ;
//!!WARNING!! THIS WAS MANUALLY MODIFIED OH GOD
parent.putData(EntityDataStrings.FIRST_PERSON_TREE, rVal);
Globals.clientScene.registerBehaviorTree(rVal);
return rVal;
}
/**
* Gets the tree on the entity
* @param target the entity
* @return The tree
*/
public static FirstPersonTree getTree(Entity target){
return (FirstPersonTree)target.getData(EntityDataStrings.FIRST_PERSON_TREE);
}
/**
* Checks if the provided entity has the tree
* @param target the provided entity
* @return true if the entity has a FirstPersonTree, false otherwise
*/
public static boolean hasTree(Entity target){
return target.containsKey(EntityDataStrings.FIRST_PERSON_TREE);
}
/**
* the offset from the origin to place the viewmodel
* @return
*/
public double getHeightFromOrigin(){
return heightFromOrigin;
}
/**
* the amount to pull below the camera
* @return
*/
public double getCameraViewDirOffsetY(){
return cameraViewDirOffsetY;
}
/**
* the amount to pull behind the camera
* @return
*/
public double getCameraViewDirOffsetZ(){
return cameraViewDirOffsetZ;
}
/**
* Plays an animation if it exists
* @param animationName the name of the animation
*/
public void playAnimation(String animationName){
this.currentAnimation = animationName;
}
/**
* If the entity has a first person tree, plays the provided animation
* @param entity The entity
* @param animationName the name of the animation
*/
public static void conditionallyPlayAnimation(Entity entity, String animationName){
if(hasTree(entity)){
getTree(entity).playAnimation(animationName);
}
}
}

View File

@ -34,11 +34,20 @@ import electrosphere.renderer.actor.ActorMeshMask;
*/
public class ClientEquipState implements BehaviorTree {
//the parent entity of the btree
Entity parent;
//the list of available equip points
List<EquipPoint> equipPoints = new LinkedList<EquipPoint>();
//the map of point to the equipped entity
Map<String,Entity> equipMap = new HashMap<String,Entity>();
/**
* Creates the tree
* @param parent the entity this is attached to
* @param equipPoints the list of available points
*/
public ClientEquipState(Entity parent, List<EquipPoint> equipPoints){
this.parent = parent;
for(EquipPoint point : equipPoints){
@ -46,10 +55,19 @@ public class ClientEquipState implements BehaviorTree {
}
}
/**
* Gets the list of equipped points
* @return the list
*/
public List<String> equippedPoints(){
return new LinkedList<String>(equipMap.keySet());
}
/**
* Attempts to equip the item
* @param toEquip the item to equip
* @param point the point to equip to
*/
public void commandAttemptEquip(Entity toEquip, EquipPoint point){
boolean hasEquipped = hasEquippedAtPoint(point.getEquipPointId());
boolean targetIsItem = ItemUtils.isItem(toEquip);
@ -117,7 +135,11 @@ public class ClientEquipState implements BehaviorTree {
} else {
//since we're not replacing meshes we must be attaching to a bone
equipMap.put(point.getEquipPointId(),toEquip);
AttachUtils.clientAttachEntityToEntityAtBone(parent, toEquip, point.getBone(), AttachUtils.getEquipPointRotationOffset(point.getOffsetRotation()));
if(Globals.controlHandler.cameraIsThirdPerson()){
AttachUtils.clientAttachEntityToEntityAtBone(parent, toEquip, point.getBone(), AttachUtils.getEquipPointRotationOffset(point.getOffsetRotation()));
} else {
AttachUtils.clientAttachEntityToEntityAtBone(Globals.firstPersonEntity, toEquip, point.getFirstPersonBone(), AttachUtils.getEquipPointRotationOffset(point.getOffsetRotation()));
}
if(toEquip.containsKey(EntityDataStrings.PHYSICS_COLLISION_BODY) && toEquip.containsKey(EntityDataStrings.PHYSICS_COLLIDABLE)){
DBody rigidBody = (DBody)toEquip.getData(EntityDataStrings.PHYSICS_COLLISION_BODY);
Globals.clientSceneWrapper.getCollisionEngine().deregisterPhysicsObject(rigidBody);
@ -171,6 +193,11 @@ public class ClientEquipState implements BehaviorTree {
// }
}
/**
* Gets the equip point by its name
* @param name the name of the equip point
* @return the equip point object if it exists, otherwise null
*/
public EquipPoint getEquipPoint(String name){
for(EquipPoint point : equipPoints){
if(point.getEquipPointId().equals(name)){
@ -180,6 +207,11 @@ public class ClientEquipState implements BehaviorTree {
return null;
}
/**
* Gets the item equipped at a point
* @param point the point's name
* @return the item entity
*/
public Entity getEquippedItemAtPoint(String point){
return equipMap.get(point);
}
@ -223,6 +255,10 @@ public class ClientEquipState implements BehaviorTree {
// }
// }
/**
* Attempts to unequip the item at a given point
* @param pointId the id of the point
*/
public void commandAttemptUnequip(String pointId){
boolean hasEquipped = hasEquippedAtPoint(pointId);
if(hasEquipped){
@ -266,6 +302,11 @@ public class ClientEquipState implements BehaviorTree {
}
}
/**
* Checks if a point has an item equipped
* @param point the equip point
* @return true if there is an item equipped, false otherwise
*/
public boolean hasEquippedAtPoint(String point){
return equipMap.containsKey(point);
}

View File

@ -3,6 +3,7 @@ package electrosphere.entity.state.idle;
import electrosphere.net.synchronization.BehaviorTreeIdEnums;
import electrosphere.entity.state.attack.ClientAttackTree;
import electrosphere.entity.state.client.firstPerson.FirstPersonTree;
import electrosphere.entity.state.movement.AirplaneMovementTree;
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree;
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree.MovementTreeState;
@ -13,6 +14,8 @@ import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.IdleData;
import electrosphere.net.synchronization.annotation.SyncedField;
import electrosphere.net.synchronization.annotation.SynchronizableEnum;
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
@ -37,10 +40,13 @@ public class IdleTree implements BehaviorTree {
private IdleTreeState state;
Entity parent;
IdleData idleData;
public IdleTree(Entity e){
state = IdleTreeState.IDLE;
parent = e;
CreatureType creatureType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(CreatureUtils.getType(parent));
idleData = creatureType.getIdleData();
}
/**
@ -80,12 +86,14 @@ public class IdleTree implements BehaviorTree {
case IDLE:
if(entityActor != null){
if(
(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(Animation.ANIMATION_IDLE_1)) &&
(Globals.assetManager.fetchModel(entityActor.getModelPath()) != null && Globals.assetManager.fetchModel(entityActor.getModelPath()).getAnimation(Animation.ANIMATION_IDLE_1) != null)
idleData != null &&
(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(idleData.getIdleAnimation())) &&
(Globals.assetManager.fetchModel(entityActor.getModelPath()) != null && Globals.assetManager.fetchModel(entityActor.getModelPath()).getAnimation(idleData.getIdleAnimation()) != null)
){
entityActor.playAnimation(Animation.ANIMATION_IDLE_1,3);
entityActor.playAnimation(idleData.getIdleAnimation(),3);
entityActor.incrementAnimationTime(0.0001);
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, idleData.getFirstPersonIdleAnimation());
}
}
break;

View File

@ -1,29 +1,42 @@
package electrosphere.entity.state.movement;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.state.client.firstPerson.FirstPersonTree;
import electrosphere.game.data.creature.type.movement.FallMovementSystem;
import electrosphere.renderer.actor.Actor;
/**
* Behavior tree for playing animations when an entity is falling/landing
*/
public class FallTree implements BehaviorTree {
/**
* The state of the fall tree
*/
static enum FallState {
ACTIVE,
INACTIVE,
}
//the raw data from disk
FallMovementSystem fallMovementSystem;
//current state
FallState state = FallState.INACTIVE;
String animationFall = "Armature|Fall";
String animationLand = "Armature|Land";
//the entity this is attached to
Entity parent;
//the related jump tree
JumpTree jumpTree;
public FallTree(Entity parent){
public FallTree(Entity parent, FallMovementSystem fallMovementSystem){
this.parent = parent;
this.fallMovementSystem = fallMovementSystem;
}
@Override
@ -32,13 +45,13 @@ public class FallTree implements BehaviorTree {
switch(state){
case ACTIVE:
if(entityActor != null){
String animationToPlay = determineCorrectAnimation();
if(
!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(animationToPlay) &&
!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(fallMovementSystem.getAnimationFall().getName()) &&
(jumpTree == null || !jumpTree.isJumping())
){
entityActor.playAnimation(animationToPlay,1);
entityActor.playAnimation(fallMovementSystem.getAnimationFall().getName(),1);
entityActor.incrementAnimationTime(0.0001);
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, fallMovementSystem.getAnimationFirstPersonFall().getName());
}
}
break;
@ -47,55 +60,55 @@ public class FallTree implements BehaviorTree {
}
}
/**
* Starts the falling tree
*/
public void start(){
state = FallState.ACTIVE;
}
/**
* Returns the status of the fall tree
* @return true if falling, false otherwise
*/
public boolean isFalling(){
return state == FallState.ACTIVE;
}
/**
* Triggers the falling tree to land
*/
public void land(){
if(state != FallState.INACTIVE){
state = FallState.INACTIVE;
Actor entityActor = EntityUtils.getActor(parent);
if(entityActor != null){
String animationToPlay = determineCorrectAnimation();
if(
!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(animationToPlay)
!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(fallMovementSystem.getAnimationLand().getName())
){
entityActor.playAnimation(animationToPlay,1);
entityActor.playAnimation(fallMovementSystem.getAnimationLand().getName(),1);
entityActor.incrementAnimationTime(0.0001);
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, fallMovementSystem.getAnimationFirstPersonLand().getName());
}
}
}
}
/**
* Gets the falling tree state of an entity
* @param parent the entity
* @return the state
*/
public static FallTree getFallTree(Entity parent){
return (FallTree)parent.getData(EntityDataStrings.FALL_TREE);
}
String determineCorrectAnimation(){
switch(state){
case ACTIVE:
return animationFall;
case INACTIVE:
return animationLand;
default:
return animationLand;
}
}
/**
* Sets the related jump tree
* @param jumpTree the jump tree that is related to this fall tree (on the same entity)
*/
public void setJumpTree(JumpTree jumpTree){
this.jumpTree = jumpTree;
}
public void setAnimationFall(String animationName){
animationFall = animationName;
}
public void setAnimationLand(String animationName){
animationLand = animationName;
}
}

View File

@ -7,13 +7,16 @@ import org.ode4j.ode.DBody;
import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.collidable.Collidable;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.state.client.firstPerson.FirstPersonTree;
import electrosphere.entity.state.collidable.Impulse;
import electrosphere.entity.state.gravity.GravityUtils;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.game.data.creature.type.movement.JumpMovementSystem;
import electrosphere.renderer.actor.Actor;
public class JumpTree implements BehaviorTree {
@ -28,6 +31,8 @@ public class JumpTree implements BehaviorTree {
String animationJump = "Armature|Jump";
JumpMovementSystem jumpData;
Entity parent;
int jumpFrames = 0;
@ -37,10 +42,11 @@ public class JumpTree implements BehaviorTree {
static final float jumpFalloff = 0.99f;
public JumpTree(Entity parent, int jumpFrames, float jumpForce){
public JumpTree(Entity parent, int jumpFrames, float jumpForce, JumpMovementSystem jumpData){
this.parent = parent;
this.jumpFrames = jumpFrames;
this.jumpForce = jumpForce;
this.jumpData = jumpData;
}
public void start(){
@ -58,10 +64,10 @@ public class JumpTree implements BehaviorTree {
switch(state){
case ACTIVE:
if(entityActor != null){
String animationToPlay = determineCorrectAnimation();
if(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(animationToPlay)){
entityActor.playAnimation(animationToPlay,1);
if(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(jumpData.getAnimationJump().getName())){
entityActor.playAnimation(jumpData.getAnimationJump().getName(),1);
entityActor.incrementAnimationTime(0.0001);
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, jumpData.getAnimationFirstPersonJump().getName());
}
}
currentFrame++;

View File

@ -15,6 +15,7 @@ import electrosphere.engine.Main;
import electrosphere.entity.types.camera.CameraEntityUtils;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.game.data.creature.type.movement.GroundMovementSystem;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
@ -22,6 +23,7 @@ import electrosphere.entity.EntityUtils;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.state.attack.ClientAttackTree;
import electrosphere.entity.state.attack.ClientAttackTree.AttackTreeState;
import electrosphere.entity.state.client.firstPerson.FirstPersonTree;
import electrosphere.entity.state.movement.FallTree;
import electrosphere.entity.state.movement.JumpTree;
import electrosphere.entity.state.movement.SprintTree;
@ -96,6 +98,8 @@ public class ClientGroundMovementTree implements BehaviorTree {
SprintTree sprintTree;
JumpTree jumpTree;
FallTree fallTree;
GroundMovementSystem groundMovementData;
Entity parent;
@ -288,6 +292,7 @@ public class ClientGroundMovementTree implements BehaviorTree {
){
entityActor.playAnimation(animationToPlay,1);
entityActor.incrementAnimationTime(0.0001);
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, groundMovementData.getAnimationFirstPersonStartup().getName());
}
}
//run startup code
@ -322,6 +327,7 @@ public class ClientGroundMovementTree implements BehaviorTree {
){
entityActor.playAnimation(animationToPlay,1);
entityActor.incrementAnimationTime(0.0001);
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, groundMovementData.getAnimationFirstPersonLoop().getName());
}
}
if(velocity != maxNaturalVelocity){
@ -350,6 +356,7 @@ public class ClientGroundMovementTree implements BehaviorTree {
){
entityActor.playAnimation(animationToPlay,1);
entityActor.incrementAnimationTime(0.0001);
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, groundMovementData.getAnimationFirstPersonWindDown().getName());
}
}
//velocity stuff
@ -665,11 +672,12 @@ public class ClientGroundMovementTree implements BehaviorTree {
* @param entity The entity to attach to
* @param tree The behavior tree to attach
*/
public static ClientGroundMovementTree attachTree(Entity parent, Collidable collidable){
public static ClientGroundMovementTree attachTree(Entity parent, Collidable collidable, GroundMovementSystem groundMovementData){
ClientGroundMovementTree rVal = new ClientGroundMovementTree(parent);
//put manual code here (setting params, etc)
rVal.collidable = collidable;
rVal.groundMovementData = groundMovementData;
//!!WARNING!! from here below should not be touched
//This was generated automatically to properly alert various systems that the btree exists and should be tracked

View File

@ -148,9 +148,14 @@ public class ServerGroundMovementTree implements BehaviorTree {
}
public void simulate(float deltaTime){
float velocity = CreatureUtils.getVelocity(parent);
float acceleration = CreatureUtils.getAcceleration(parent);
float maxNaturalVelocity = sprintTree != null && sprintTree.getState() == SprintTreeState.SPRINTING ? sprintTree.getMaxVelocity() : CreatureUtils.getMaxNaturalVelocity(parent);
float velocity = 0;
float acceleration = 0;
float maxNaturalVelocity = 0;
if(CreatureUtils.hasVelocity(parent)){
velocity = CreatureUtils.getVelocity(parent);
acceleration = CreatureUtils.getAcceleration(parent);
maxNaturalVelocity = sprintTree != null && sprintTree.getState() == SprintTreeState.SPRINTING ? sprintTree.getMaxVelocity() : CreatureUtils.getMaxNaturalVelocity(parent);
}
PoseActor entityPoseActor = EntityUtils.getPoseActor(parent);
// Model entityModel = Globals.assetManager.fetchModel(EntityUtils.getEntityModelPath(parent));
Vector3d position = EntityUtils.getPosition(parent);
@ -208,27 +213,6 @@ public class ServerGroundMovementTree implements BehaviorTree {
case MOVEUPDATE: {
if(updateTime >= lastUpdateTime){
lastUpdateTime = updateTime;
switch(message.gettreeState()){
case 0:
state = MovementTreeState.STARTUP;
// System.out.println("Set state STARTUP");
GravityUtils.serverAttemptActivateGravity(parent);
break;
case 1:
state = MovementTreeState.MOVE;
// System.out.println("Set state MOVE");
GravityUtils.serverAttemptActivateGravity(parent);
break;
case 2:
state = MovementTreeState.SLOWDOWN;
// System.out.println("Set state SLOWDOWN");
GravityUtils.serverAttemptActivateGravity(parent);
break;
case 3:
state = MovementTreeState.IDLE;
// System.out.println("Set state IDLE");
break;
}
//we want to always update the server facing vector with where the client says they're facing
EntityUtils.getRotation(parent).set(message.getrotationX(),message.getrotationY(),message.getrotationZ(),message.getrotationW());
CreatureUtils.setFacingVector(parent, new Vector3d(0,0,1).rotate(EntityUtils.getRotation(parent)));

View File

@ -24,8 +24,7 @@ import org.joml.Vector3f;
import org.joml.Vector4d;
/**
*
* @author amaterasu
* Utilities for attaching entities to entities
*/
public class AttachUtils {
@ -110,6 +109,9 @@ public class AttachUtils {
// Quaternionf rotation = parentActor.getBoneRotation(targetBone);
// EntityUtils.getRotation(currentEntity).set(rotation).normalize();
Vector3d facingAngle = CreatureUtils.getFacingVector(parent);
if(facingAngle == null){
facingAngle = new Vector3d(0,0,1);
}
//calculate rotation of model
EntityUtils.getRotation(currentEntity)
.rotationTo(new Vector3d(0,0,1), new Vector3d(facingAngle.x,facingAngle.y,facingAngle.z))

View File

@ -158,6 +158,26 @@ public class CameraEntityUtils {
public static float getCameraYaw(Entity camera){
return (float)camera.getData(EntityDataStrings.CAMERA_YAW);
}
/**
* Gets the quaternion containing the camera pitch
* @param camera
* @return
*/
public static Quaternionf getPitchQuat(Entity camera){
Quaternionf pitchQuat = new Quaternionf().fromAxisAngleDeg(new Vector3f(1,0,0), -getCameraPitch(camera));
return pitchQuat;
}
/**
* Gets the quaternion containing the camera yaw
* @param camera
* @return
*/
public static Quaternionf getYawQuat(Entity camera){
Quaternionf yawQuat = new Quaternionf().fromAxisAngleDeg(new Vector3f(0,1,0), -getCameraYaw(camera));
return yawQuat;
}
public static void destroyCameraEntity(Entity e){
if(e != null){

View File

@ -101,6 +101,8 @@ public class CreatureUtils {
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
EntityCreationUtils.makeEntityDrawable(rVal, rawType.getModelPath());
Actor creatureActor = EntityUtils.getActor(rVal);
EntityUtils.setEntityType(rVal, ENTITY_TYPE_CREATURE);
EntityUtils.setEntitySubtype(rVal, type);
for(HitboxData hitboxdata : rawType.getHitboxes()){
List<Entity> hitboxList = new LinkedList<Entity>();
List<Entity> hurtboxList = new LinkedList<Entity>();
@ -132,7 +134,7 @@ public class CreatureUtils {
// Generic ground
case GroundMovementSystem.GROUND_MOVEMENT_SYSTEM:
GroundMovementSystem groundMovementSystem = (GroundMovementSystem)movementSystem;
ClientGroundMovementTree moveTree = ClientGroundMovementTree.attachTree(rVal, CollisionObjUtils.getCollidable(rVal));
ClientGroundMovementTree moveTree = ClientGroundMovementTree.attachTree(rVal, CollisionObjUtils.getCollidable(rVal), groundMovementSystem);
if(groundMovementSystem.getAnimationStartup() != null){
moveTree.setAnimationStartUp(groundMovementSystem.getAnimationStartup().getName());
}
@ -174,7 +176,7 @@ public class CreatureUtils {
// Jump
case JumpMovementSystem.JUMP_MOVEMENT_SYSTEM:
JumpMovementSystem jumpMovementSystem = (JumpMovementSystem)movementSystem;
JumpTree jumpTree = new JumpTree(rVal, jumpMovementSystem.getJumpFrames(), jumpMovementSystem.getJumpForce());
JumpTree jumpTree = new JumpTree(rVal, jumpMovementSystem.getJumpFrames(), jumpMovementSystem.getJumpForce(), jumpMovementSystem);
if(jumpMovementSystem.getAnimationJump() != null){
jumpTree.setAnimationJump(jumpMovementSystem.getAnimationJump().getName());
}
@ -191,13 +193,7 @@ public class CreatureUtils {
// Falling
case FallMovementSystem.FALL_MOVEMENT_SYSTEM:
FallMovementSystem fallMovementSystem = (FallMovementSystem)movementSystem;
FallTree fallTree = new FallTree(rVal);
if(fallMovementSystem.getAnimationFall()!=null){
fallTree.setAnimationFall(fallMovementSystem.getAnimationFall().getName());
}
if(fallMovementSystem.getAnimationLand()!=null){
fallTree.setAnimationLand(fallMovementSystem.getAnimationLand().getName());
}
FallTree fallTree = new FallTree(rVal, fallMovementSystem);
if(CreatureUtils.clientGetEntityMovementTree(rVal) != null && CreatureUtils.clientGetEntityMovementTree(rVal) instanceof ClientGroundMovementTree){
((ClientGroundMovementTree)CreatureUtils.clientGetEntityMovementTree(rVal)).setClientFallTree(fallTree);
}
@ -374,8 +370,6 @@ public class CreatureUtils {
rVal.putData(EntityDataStrings.TREE_IDLE, idleTree);
Globals.clientScene.registerBehaviorTree(idleTree);
Globals.clientScene.registerEntityToTag(rVal, EntityTags.CREATURE);
EntityUtils.setEntityType(rVal, ENTITY_TYPE_CREATURE);
EntityUtils.setEntitySubtype(rVal, type);
CreatureUtils.setFacingVector(rVal, new Vector3d(0,0,1));
rVal.putData(EntityDataStrings.DRAW_CAST_SHADOW, true);
return rVal;
@ -717,6 +711,10 @@ public class CreatureUtils {
public static void setAcceleration(Entity e, float scalar){
e.putData(EntityDataStrings.DATA_STRING_ACCELERATION, scalar);
}
public static boolean hasVelocity(Entity e){
return e.containsKey(EntityDataStrings.DATA_STRING_VELOCITY);
}
public static float getVelocity(Entity e){
return (float)e.getData(EntityDataStrings.DATA_STRING_VELOCITY);

View File

@ -11,7 +11,7 @@ import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityTags;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.state.ambientaudio.ClientAmbientAudioTree;
import electrosphere.entity.state.client.ambientaudio.ClientAmbientAudioTree;
import electrosphere.entity.state.idle.IdleTree;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.entity.types.tree.ProceduralTree;

View File

@ -11,6 +11,9 @@ import electrosphere.game.data.creature.type.visualattribute.VisualAttribute;
import java.util.List;
/**
* A given type of creature
*/
public class CreatureType {
String creatureId;
List<HitboxData> hitboxes;
@ -24,6 +27,8 @@ public class CreatureType {
HealthSystem healthSystem;
LookAtSystem lookAtSystem;
String modelPath;
ViewModelData viewModelData;
IdleData idleData;
AttackMoveResolver attackMoveResolver;
@ -82,6 +87,14 @@ public class CreatureType {
public AttackMoveResolver getAttackMoveResolver(){
return attackMoveResolver;
}
public ViewModelData getViewModelData(){
return viewModelData;
}
public IdleData getIdleData(){
return idleData;
}
}

View File

@ -0,0 +1,30 @@
package electrosphere.game.data.creature.type;
/**
* Data about how the creature will behave when in idle state
*/
public class IdleData {
//the animation that plays when the creature is idle
String idleAnimation;
//the animation that plays when the creature idles in first person
String firstPersonIdleAnimation;
/**
* the animation that plays when the creature is idle
* @return
*/
public String getIdleAnimation(){
return idleAnimation;
}
/**
* the animation that plays when the creature idles in first person
* @return
*/
public String getFirstPersonIdleAnimation(){
return firstPersonIdleAnimation;
}
}

View File

@ -0,0 +1,54 @@
package electrosphere.game.data.creature.type;
/**
* Data about the first person view model for this creature type
*/
public class ViewModelData {
//How far from the origin of the creature to place the viewmodel
double heightFromOrigin;
//How far to pull the view model below the camera
double cameraViewDirOffsetY;
//How far to pull the view model behind the camera
double cameraViewDirOffsetZ;
//the actual model
String firstPersonModelPath;
/**
* How far from the origin of the creature to place the viewmodel
* @return
*/
public double getHeightFromOrigin(){
return heightFromOrigin;
}
/**
* How far to pull the view model below the camera
* @return
*/
public double getCameraViewDirOffsetY(){
return cameraViewDirOffsetY;
}
/**
* How far to pull the view model behind the camera
* @return
*/
public double getCameraViewDirOffsetZ(){
return cameraViewDirOffsetZ;
}
/**
* the actual model
* @return
*/
public String getFirstPersonModelPath(){
return firstPersonModelPath;
}
}

View File

@ -1,15 +1,14 @@
package electrosphere.game.data.creature.type.attack;
import java.util.List;
import electrosphere.game.data.creature.type.Animation;
/**
*
* @author amaterasu
* Data about a single attack move this creature is capable of
*/
public class AttackMove {
/*
Base data
*/
String attackMoveId;
String type;
@ -21,6 +20,10 @@ public class AttackMove {
String holdAnimationName;
String attackAnimationName;
Animation animationFirstPersonWindup;
Animation animationFirstPersonHold;
Animation animationFirstPersonAttack;
/*
Damage stuff
*/
@ -45,66 +48,154 @@ public class AttackMove {
int driftFrameStart; //when do we start drifting
int driftFrameEnd; //when do we stop drifting
/**
* Gets the id of the attack move
* @return the id of the attack move
*/
public String getAttackMoveId(){
return attackMoveId;
}
/**
* Gets the type of attack move
* @return the attack move type
*/
public String getType() {
return type;
}
/**
* Gets the name of the animation to play in 3rd person for the windup
* @return the animation name
*/
public String getWindupAnimationName() {
return windupAnimationName;
}
/**
* Gets the name of the animation to play in 3rd person for the hold
* @return the animation name
*/
public String getHoldAnimationName() {
return holdAnimationName;
}
/**
* Gets the name of the animation to play in 3rd person for the attack
* @return the animation name
*/
public String getAttackAnimationName() {
return attackAnimationName;
}
/**
* Gets the animation data for the 1st person windup
* @return the animation data
*/
public Animation getAnimationFirstPersonWindup(){
return animationFirstPersonWindup;
}
/**
* Gets the animation data for the 1st person hold
* @return the animation data
*/
public Animation getAnimationFirstPersonHold(){
return animationFirstPersonHold;
}
/**
* Gets the animation data for the 1st person attack
* @return the animation data
*/
public Animation getAnimationFirstPersonAttack(){
return animationFirstPersonAttack;
}
/**
* Gets the number of frames to windup for
* @return the number of frames
*/
public int getWindupFrames() {
return windupFrames;
}
/**
* Gets the number of frames to attack for
* @return the number of frames
*/
public int getAttackFrames() {
return attackFrames;
}
/**
* Gets the number of frames to cooldown for
* @return the number of frames
*/
public int getCooldownFrames(){
return cooldownFrames;
}
/**
* Gets the id of the next attack move
* @return the id of the next attack move
*/
public String getNextMoveId() {
return nextMoveId;
}
/**
* Gets the frame number where the window to chain the next attack starts
* @return the frame number
*/
public int getMoveChainWindowStart(){
return moveChainWindowStart;
}
/**
* Gets the frame number where the window to chain the next attack ends
* @return the frame number
*/
public int getMoveChainWindowEnd(){
return moveChainWindowEnd;
}
/**
* Gets the amount we want the animation to push the creature forward
* @return the amount to push forward
*/
public float getDriftGoal(){
return driftGoal;
}
/**
* Gets the frame number where the drift starts
* @return the frame number
*/
public int getDriftFrameStart(){
return driftFrameStart;
}
/**
* Gets the frame number where the drift starts
* @return the frame number
*/
public int getDriftFrameEnd(){
return driftFrameEnd;
}
/**
* Returns if the move is the initial move in the attack chain
* @return true if the initial move, false otherwise
*/
public boolean isInitialMove(){
return initialMove;
}
/**
* Returns if it fires a projectile
* @return true if it fires a projectile, false otherwise
*/
public boolean getFiresProjectile(){
return firesProjectile;
}

View File

@ -2,30 +2,68 @@ package electrosphere.game.data.creature.type.equip;
import java.util.List;
/**
* A portion of the creature that can have an item attached to it
*/
public class EquipPoint {
//the id of the equip point
String equipPointId;
//the bone that can have the item attached to it (may not be defined depending on the type of equip point (think legs))
String bone;
//the bone to attach items to for the first person viewmodel (may not be defined based on the viewmodel)
String firstPersonBone;
//the offset to apply to items that are attached to the bone
List<Float> offsetVector;
//the rotation to apply to the items that are attached to the bone
List<Float> offsetRotation;
//the equip classes that are whitelisted for this equip point
List<String> equipClassWhitelist;
/**
* Gets the equip point id
* @return the id of the equip point
*/
public String getEquipPointId(){
return equipPointId;
}
/**
* Gets the bone that can have the item attached to it (may not be defined depending on the type of equip point (think legs))
* @return the bone
*/
public String getBone(){
return bone;
}
/**
* Gets the bone to attach items to for the first person viewmodel (may not be defined based on the viewmodel)
* @return the bone
*/
public String getFirstPersonBone(){
return firstPersonBone;
}
/**
* Gets the offset to apply to items that are attached to the bone
* @return the offset
*/
public List<Float> getOffsetVector(){
return offsetVector;
}
/**
* Gets the rotation to apply to the items that are attached to the bone
* @return the rotation
*/
public List<Float> getOffsetRotation(){
return offsetRotation;
}
/**
* Gets the equip classes that are whitelisted for this equip point
* @return the classes
*/
public List<String> getEquipClassWhitelist(){
return equipClassWhitelist;
}

View File

@ -2,23 +2,55 @@ package electrosphere.game.data.creature.type.movement;
import electrosphere.game.data.creature.type.Animation;
/**
* Data about a falling movement system
*/
public class FallMovementSystem implements MovementSystem {
public static final String FALL_MOVEMENT_SYSTEM = "FALL";
String type;
//Fall data
Animation animationFall;
Animation animationLand;
Animation animationFirstPersonFall;
//landing data
Animation animationLand;
Animation animationFirstPersonLand;
/**
* Gets the animation to play in 3rd person when the creature is falling
* @return the animation data
*/
public Animation getAnimationFall(){
return animationFall;
}
/**
* Gets the animation to play in 1st person when the creature is falling
* @return the animation data
*/
public Animation getAnimationFirstPersonFall(){
return animationFirstPersonFall;
}
/**
* Gets the animation to play in 3rd person when the creature is landing
* @return the animation data
*/
public Animation getAnimationLand(){
return animationLand;
}
/**
* Gets the animation to play in 1st person when the creature is landing
* @return the animation data
*/
public Animation getAnimationFirstPersonLand(){
return animationFirstPersonLand;
}
@Override
public String getType() {
return type;

View File

@ -3,40 +3,105 @@ package electrosphere.game.data.creature.type.movement;
import electrosphere.game.data.creature.type.Animation;
import electrosphere.game.data.creature.type.SprintSystem;
/**
* A ground movement system's data
*/
public class GroundMovementSystem implements MovementSystem {
//move system type string
public static final String GROUND_MOVEMENT_SYSTEM = "GROUND";
//type of move system
String type;
//core physics numbers
float acceleration;
float maxVelocity;
//startup data
Animation animationStartup;
Animation animationFirstPersonStartup;
//loop data
Animation animationLoop;
Animation animationFirstPersonLoop;
//wind down data
Animation animationWindDown;
Animation animationFirstPersonWindDown;
//sprint data
SprintSystem sprintSystem;
/**
* Gets the acceleration factor for this creature
* @return the acceleration factor
*/
public float getAcceleration() {
return acceleration;
}
/**
* Gets the maximum velocity the creature can move at with this system
* @return the max velocity
*/
public float getMaxVelocity() {
return maxVelocity;
}
/**
* Gets the animation to play in 3rd person for startup
* @return The animation data
*/
public Animation getAnimationStartup() {
return animationStartup;
}
/**
* Gets the animation to play in 1st person for startup
* @return The animation data
*/
public Animation getAnimationFirstPersonStartup(){
return animationFirstPersonStartup;
}
/**
* Gets the animation to loop in 3rd person
* @return The animation data
*/
public Animation getAnimationLoop() {
return animationLoop;
}
/**
* Gets the animation to loop in 1st person
* @return The animation data
*/
public Animation getAnimationFirstPersonLoop(){
return animationFirstPersonLoop;
}
/**
* Gets the animation to play in 3rd person to wind down
* @return The animation data
*/
public Animation getAnimationWindDown() {
return animationWindDown;
}
/**
* Gets the animation to play in 1st person to wind down
* @return The animation data
*/
public Animation getAnimationFirstPersonWindDown(){
return animationFirstPersonWindDown;
}
/**
* Gets the sprint system data
* @return The sprint system data
*/
public SprintSystem getSprintSystem() {
return sprintSystem;
}

View File

@ -9,7 +9,8 @@ public class JumpMovementSystem implements MovementSystem {
String type;
Animation animationJump;
Animation animationFirstPersonJump;
int jumpFrames;
float jumpForce;
@ -25,6 +26,10 @@ public class JumpMovementSystem implements MovementSystem {
return animationJump;
}
public Animation getAnimationFirstPersonJump(){
return animationFirstPersonJump;
}
@Override
public String getType() {
return type;

View File

@ -99,6 +99,12 @@ public class TreeModel {
//The maximum scalar of a branch to generate a sway behavior tree
float maximumScalarToGenerateSwayTree;
//The model for the trunk of the tree
String trunkModelPath;
//the model for a leaf blob
String leafModelPath;
/**
* how quickly do the limbs shrink
* @return
@ -332,4 +338,20 @@ public class TreeModel {
return this.physicsBody;
}
/**
* The model for the trunk of the tree
* @return
*/
public String getTrunkModelPath(){
return trunkModelPath;
}
/**
* the model for a leaf blob
* @return
*/
public String getLeafModelPath(){
return leafModelPath;
}
}

View File

@ -26,7 +26,7 @@ public class LoggerInterface {
*/
public static void initLoggers(){
loggerStartup = new Logger(LogLevel.WARNING);
loggerNetworking = new Logger(LogLevel.DEBUG);
loggerNetworking = new Logger(LogLevel.WARNING);
loggerFileIO = new Logger(LogLevel.WARNING);
loggerGameLogic = new Logger(LogLevel.WARNING);
loggerRenderer = new Logger(LogLevel.WARNING);

View File

@ -6,15 +6,20 @@ import org.joml.Vector3d;
import electrosphere.engine.Globals;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityTags;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.attack.ClientAttackTree;
import electrosphere.entity.state.attack.ServerAttackTree;
import electrosphere.entity.state.client.firstPerson.FirstPersonTree;
import electrosphere.entity.types.attach.AttachUtils;
import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.foliage.FoliageUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.ViewModelData;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.util.Utilities;
@ -101,19 +106,7 @@ public class EntityProtocol {
case SETPROPERTY: {
if(Globals.clientSceneWrapper.serverToClientMapContainsId(message.getentityID())){
if(message.getpropertyType() == 0){
Entity target = Globals.clientSceneWrapper.getEntityFromServerId(message.getentityID());
if(target != null){
CreatureUtils.setControllerPlayerId(target, message.getpropertyValue());
if(Globals.clientPlayer != null && message.getpropertyValue() == Globals.clientPlayer.getId()){
Globals.clientCharacterID = message.getentityID();
Globals.playerEntity = target;
if(Globals.controlHandler.cameraIsThirdPerson()){
Globals.playerEntity.putData(EntityDataStrings.DATA_STRING_DRAW, true);
} else {
Globals.playerEntity.putData(EntityDataStrings.DATA_STRING_DRAW, false);
}
}
}
setPlayerEntity(message);
}
} else {
//TODO: bounce message
@ -168,4 +161,33 @@ public class EntityProtocol {
Globals.profiler.endCpuSample();
}
/**
* Sets the player's entity
* @param message the network message to parse
*/
static void setPlayerEntity(EntityMessage message){
Entity target = Globals.clientSceneWrapper.getEntityFromServerId(message.getentityID());
if(target != null){
CreatureUtils.setControllerPlayerId(target, message.getpropertyValue());
String creatureTypeRaw = CreatureUtils.getType(target);
CreatureType creatureType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(creatureTypeRaw);
ViewModelData viewModelData = creatureType.getViewModelData();
if(Globals.clientPlayer != null && message.getpropertyValue() == Globals.clientPlayer.getId()){
Globals.clientCharacterID = message.getentityID();
Globals.playerEntity = target;
if(Globals.controlHandler.cameraIsThirdPerson()){
Globals.playerEntity.putData(EntityDataStrings.DATA_STRING_DRAW, true);
} else {
Globals.playerEntity.putData(EntityDataStrings.DATA_STRING_DRAW, false);
if(viewModelData != null && viewModelData.getFirstPersonModelPath() != null){
Globals.firstPersonEntity = EntityCreationUtils.createClientSpatialEntity();
EntityCreationUtils.makeEntityDrawable(Globals.firstPersonEntity, viewModelData.getFirstPersonModelPath());
FirstPersonTree.attachTree(Globals.firstPersonEntity, viewModelData.getHeightFromOrigin(), viewModelData.getCameraViewDirOffsetY(), viewModelData.getCameraViewDirOffsetZ());
Globals.clientSceneWrapper.getScene().removeEntityFromTag(Globals.firstPersonEntity,EntityTags.DRAWABLE);
}
}
}
}
}
}

View File

@ -103,6 +103,7 @@ import electrosphere.renderer.light.LightManager;
import electrosphere.renderer.model.Model;
import electrosphere.renderer.pipelines.CompositePipeline;
import electrosphere.renderer.pipelines.DebugContentPipeline;
import electrosphere.renderer.pipelines.FirstPersonItemsPipeline;
import electrosphere.renderer.pipelines.MainContentNoOITPipeline;
import electrosphere.renderer.pipelines.MainContentPipeline;
import electrosphere.renderer.pipelines.NormalsForOutlinePipeline;
@ -244,6 +245,7 @@ public class RenderingEngine {
MainContentPipeline mainContentPipeline = new MainContentPipeline();
MainContentNoOITPipeline mainContentNoOITPipeline = new MainContentNoOITPipeline();
DebugContentPipeline debugContentPipeline = new DebugContentPipeline();
FirstPersonItemsPipeline firstPersonItemsPipeline = new FirstPersonItemsPipeline();
ShadowMapPipeline shadowMapPipeline = new ShadowMapPipeline();
VolumeBufferPipeline volumeBufferPipeline = new VolumeBufferPipeline();
NormalsForOutlinePipeline normalsForOutlinePipeline = new NormalsForOutlinePipeline();
@ -448,6 +450,12 @@ public class RenderingEngine {
// fogColor.put(1.0f);
// fogColor.flip();
// GL11.glFogfv(GL_FOG_COLOR, fogColor);
//
//Init pipelines
//
firstPersonItemsPipeline.init();
compositePipeline.setFirstPersonPipeline(firstPersonItemsPipeline);
//
// Projection and View matrix creation
@ -496,6 +504,7 @@ public class RenderingEngine {
}
debugContentPipeline.render(openGLState, renderPipelineState);
normalsForOutlinePipeline.render(openGLState, renderPipelineState);
firstPersonItemsPipeline.render(openGLState, renderPipelineState);
postProcessingPipeline.render(openGLState, renderPipelineState);
compositePipeline.render(openGLState, renderPipelineState);
}

View File

@ -336,14 +336,31 @@ public class Actor {
return meshMask;
}
/**
* Masks a shader with another shader
* @param mesh The mesh to apply the mask on
* @param vertexShader the vertex shader to apply
* @param fragmentShader the fragment shader to apply
*/
public void maskShader(String mesh, String vertexShader, String fragmentShader){
shaderMasks.add(new ActorShaderMask(this.modelPath, mesh, vertexShader, null, fragmentShader));
}
/**
* Masks a shader with another shader
* @param mesh the mesh to apply the mask on
* @param vertexShader the vertex shader to apply
* @param geometryShader the geometry shader to apply
* @param fragmentShader the fragment shader to apply
*/
public void maskShader(String mesh, String vertexShader, String geometryShader, String fragmentShader){
shaderMasks.add(new ActorShaderMask(this.modelPath, mesh, vertexShader, geometryShader, fragmentShader));
}
/**
* Unmasks a shader
* @param mesh the mesh to unmask
*/
public void unmaskShader(String mesh){
throw new UnsupportedOperationException("Not implemented yet");
}

View File

@ -1,13 +1,29 @@
package electrosphere.renderer.actor;
/**
* Masks a shader on a mesh with another shader
*/
public class ActorShaderMask {
//the model name
String modelName;
//the mesh name
String meshName;
//the vertex shader
String vertexShaderPath;
//the geometry shader
String geometryShaderPath;
//the fragment shader
String fragmentShaderPath;
/**
* Constructor
* @param modelName
* @param meshName
* @param vertexShaderPath
* @param geometryShaderPath
* @param fragmentShaderPath
*/
public ActorShaderMask(String modelName, String meshName, String vertexShaderPath, String geometryShaderPath, String fragmentShaderPath){
this.modelName = modelName;
this.meshName = meshName;
@ -16,22 +32,42 @@ public class ActorShaderMask {
this.fragmentShaderPath = fragmentShaderPath;
}
/**
* Gets the model name
* @return the model name
*/
public String getModelName(){
return modelName;
}
/**
* Gets the mesh name
* @return the mesh name
*/
public String getMeshName(){
return meshName;
}
/**
* Gets the vertex shader path
* @return the vertex shader path
*/
public String getVertexShaderPath(){
return vertexShaderPath;
}
/**
* Gets the geometry shader path
* @return the geometry shader path
*/
public String getGeometryShaderPath(){
return geometryShaderPath;
}
/**
* Gets the fragment shader path
* @return the fragment shader path
*/
public String getFragmentShaderPath(){
return fragmentShaderPath;
}

View File

@ -58,8 +58,7 @@ import static org.lwjgl.opengl.GL30.glRenderbufferStorage;
import static org.lwjgl.system.MemoryUtil.NULL;
/**
*
* @author amaterasu
* Utilities for framebuffer creation
*/
public class FramebufferUtils {

View File

@ -436,17 +436,17 @@ public class Model {
* Describes the model at a high level
*/
public void describeHighLevel(){
LoggerInterface.loggerRenderer.DEBUG("Meshes: ");
LoggerInterface.loggerRenderer.WARNING("Meshes: ");
for(Mesh mesh : meshes){
LoggerInterface.loggerRenderer.DEBUG(mesh.getMeshName());
LoggerInterface.loggerRenderer.WARNING(mesh.getMeshName());
}
LoggerInterface.loggerRenderer.DEBUG("Animations: ");
LoggerInterface.loggerRenderer.WARNING("Animations: ");
for(Animation anim : animations){
LoggerInterface.loggerRenderer.DEBUG(anim.name);
LoggerInterface.loggerRenderer.WARNING(anim.name);
}
LoggerInterface.loggerRenderer.DEBUG("Bones:");
LoggerInterface.loggerRenderer.WARNING("Bones:");
for(Bone bone : bones){
LoggerInterface.loggerRenderer.DEBUG(bone.boneID);
LoggerInterface.loggerRenderer.WARNING(bone.boneID);
}
}

View File

@ -9,6 +9,9 @@ import electrosphere.renderer.RenderingEngine;
public class CompositePipeline implements RenderPipeline {
//the pipeline for the first person render items
FirstPersonItemsPipeline firstPersonItemsPipeline;
@Override
public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) {
Globals.profiler.beginCpuSample("CompositePipeline.render");
@ -60,12 +63,55 @@ public class CompositePipeline implements RenderPipeline {
openGLState.glBindTexture(GL40.GL_TEXTURE_2D, RenderingEngine.transparencyAccumulatorTexture.getTexturePointer());
openGLState.glActiveTexture(GL40.GL_TEXTURE1);
openGLState.glBindTexture(GL40.GL_TEXTURE_2D, RenderingEngine.transparencyRevealageTexture.getTexturePointer());
openGLState.glActiveTexture(GL40.GL_TEXTURE2);
openGLState.glBindTexture(GL40.GL_TEXTURE_2D, firstPersonItemsPipeline.getFramebuffer().getTexturePointer());
GL40.glDrawArrays(GL40.GL_TRIANGLES, 0, 6);
//
//Draw the first person texture on top of the other textures
//
openGLState.setActiveShader(renderPipelineState, RenderingEngine.screenTextureShaders);
openGLState.glActiveTexture(GL40.GL_TEXTURE0);
openGLState.glBindTexture(GL40.GL_TEXTURE_2D, 0);
openGLState.glActiveTexture(GL40.GL_TEXTURE1);
openGLState.glBindTexture(GL40.GL_TEXTURE_2D, 0);
openGLState.glActiveTexture(GL40.GL_TEXTURE2);
openGLState.glBindTexture(GL40.GL_TEXTURE_2D, 0);
openGLState.glActiveTexture(GL40.GL_TEXTURE3);
openGLState.glBindTexture(GL40.GL_TEXTURE_2D, 0);
openGLState.glActiveTexture(GL40.GL_TEXTURE0);
openGLState.glBindTexture(GL40.GL_TEXTURE_2D, firstPersonItemsPipeline.getFramebuffer().getTexturePointer());
openGLState.glActiveTexture(GL40.GL_TEXTURE1);
GL40.glDrawArrays(GL40.GL_TRIANGLES, 0, 6);
//
//Close down pipeline
//
GL40.glBindVertexArray(0);
Globals.profiler.endCpuSample();
}
/**
* Get the first person pipeline
* @param firstPersonItemsPipeline the first person pipeline
*/
public void setFirstPersonPipeline(FirstPersonItemsPipeline firstPersonItemsPipeline){
this.firstPersonItemsPipeline = firstPersonItemsPipeline;
}
}

View File

@ -1,13 +1,119 @@
package electrosphere.renderer.pipelines;
import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER;
import org.joml.Matrix4d;
import org.joml.Quaterniond;
import org.joml.Quaternionf;
import org.joml.Vector3d;
import org.joml.Vector3f;
import org.joml.Vector4d;
import org.lwjgl.opengl.GL40;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.client.firstPerson.FirstPersonTree;
import electrosphere.entity.types.camera.CameraEntityUtils;
import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderPipelineState;
import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.framebuffer.Framebuffer;
import electrosphere.renderer.framebuffer.FramebufferUtils;
/**
* Renders content that should only be rendered in first person (ie the view model/hands/whatever)
*/
public class FirstPersonItemsPipeline implements RenderPipeline {
//framebuffer to store what is rendered in this pass
Framebuffer firstPersonFramebuffer;
//internal model matrix
Matrix4d modelTransformMatrix = new Matrix4d();
/**
* Initializes the pipeline
*/
public void init(){
this.firstPersonFramebuffer = FramebufferUtils.generateTextureFramebuffer(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT);
}
@Override
public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) {
//todo, render hands to a screenbuffer
//update logic
updateFirstPersonModelPosition(Globals.firstPersonEntity);
//setup opengl state
this.firstPersonFramebuffer.bind();
renderPipelineState.setUseBones(true);
renderPipelineState.setUseLight(false);
renderPipelineState.setUseMaterial(true);
renderPipelineState.setUseMeshShader(true);
renderPipelineState.setUseShadowMap(false);
renderPipelineState.setBufferStandardUniforms(true);
renderPipelineState.setFrustumCheck(false);
openGLState.glDepthTest(true);
openGLState.glDepthFunc(GL40.GL_LESS);
GL40.glDepthMask(true);
//clear
GL40.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL40.glClear(GL40.GL_COLOR_BUFFER_BIT);
GL40.glClear(GL40.GL_DEPTH_BUFFER_BIT);
//render
if(
!Globals.controlHandler.cameraIsThirdPerson() &&
Globals.firstPersonEntity != null
){
Vector3d position = EntityUtils.getPosition(Globals.firstPersonEntity);
Actor actor = EntityUtils.getActor(Globals.firstPersonEntity);
//calculate camera-modified vector3f
Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
//calculate and apply model transform
modelTransformMatrix.identity();
modelTransformMatrix.translate(cameraModifiedPosition);
modelTransformMatrix.rotate(EntityUtils.getRotation(Globals.firstPersonEntity));
modelTransformMatrix.scale(new Vector3d(EntityUtils.getScale(Globals.firstPersonEntity)));
actor.applySpatialData(modelTransformMatrix,position);
//draw
actor.draw(renderPipelineState, openGLState);
}
//finish up
openGLState.glBindFramebuffer(GL_FRAMEBUFFER,0);
}
/**
* Gets the framebuffer of the pipeline
* @return the framebuffer
*/
public Framebuffer getFramebuffer(){
return this.firstPersonFramebuffer;
}
/**
* Updates the position and rotation of the first person model
*/
private void updateFirstPersonModelPosition(Entity target){
FirstPersonTree tree = FirstPersonTree.getTree(target);
Quaternionf quatRaw = CameraEntityUtils.getYawQuat(Globals.playerCamera).mul(CameraEntityUtils.getPitchQuat(Globals.playerCamera));
Quaterniond quatd = new Quaterniond(quatRaw).normalize();
EntityUtils.getRotation(Globals.firstPersonEntity).set(quatd);
Matrix4d rotationMat = new Matrix4d().rotate(quatd);
Vector3d playerPos = EntityUtils.getPosition(Globals.playerEntity);
Vector4d behindCameraOffsetRaw = rotationMat.transform(new Vector4d(0,tree.getCameraViewDirOffsetY(),tree.getCameraViewDirOffsetZ(),1)); //pushes the model behind the camera
Vector3d behindCameraOffset = new Vector3d(behindCameraOffsetRaw.x,behindCameraOffsetRaw.y,behindCameraOffsetRaw.z);
EntityUtils.getPosition(Globals.firstPersonEntity).set(playerPos).add(0.0f,tree.getHeightFromOrigin(),0.0f).add(behindCameraOffset);
}
}

View File

@ -58,6 +58,15 @@ public class MicroSimulation {
currentActor.incrementAnimationTime(Globals.timekeeper.getSimFrameTime() / Main.targetFrameRate);
}
}
//update first person model animations
if(Globals.firstPersonEntity != null){
//fetch actor
Actor currentActor = EntityUtils.getActor(Globals.firstPersonEntity);
//increment animations
if(currentActor.isPlayingAnimation()){
currentActor.incrementAnimationTime(Globals.timekeeper.getSimFrameTime() / Main.targetFrameRate);
}
}
//make items play idle animation
for(Entity item : dataCell.getScene().getEntitiesWithTag(EntityTags.ITEM)){
ItemUtils.updateItemActorAnimation(item);

View File

@ -12,6 +12,9 @@ import electrosphere.server.terrain.manager.ServerTerrainChunk;
* Provides utilities for editing terrain (particularly brushes, etc)
*/
public class TerrainEditing {
//the minimum value before hard setting to 0
static final float MINIMUM_FULL_VALUE = 0.01f;
/**
* Performs a terrain chunk edit. Basically has a sphere around the provided position that it attempts to add value to.
@ -62,7 +65,10 @@ public class TerrainEditing {
){
float current = data.getWeights()[voxelPos.x][voxelPos.y][voxelPos.z];
//hard clamp so it doesn't go over 1
float finalValue = Math.max(Math.min(current + weight * distance,1),-1);
float finalValue = Math.max(Math.min(current + weight / distance,1),-1);
if(finalValue < MINIMUM_FULL_VALUE && current > MINIMUM_FULL_VALUE){
finalValue = -1;
}
voxelCellManager.editChunk(chunkPos, voxelPos, finalValue, type);
}
}