From 58c5ac05121089e52a05155e24f70d1860f4ed3d Mon Sep 17 00:00:00 2001 From: austin Date: Wed, 24 Jul 2024 13:30:06 -0400 Subject: [PATCH] POV switching --- assets/Data/creatures/human.json | 4 +- docs/src/progress/renderertodo.md | 4 ++ .../controls/ControlHandler.java | 14 +++++++ src/main/java/electrosphere/engine/Main.java | 42 +++++++++---------- .../engine/loadingthreads/ClientLoading.java | 7 +--- .../entity/state/equip/ClientEquipState.java | 28 +++++++++++++ .../entity/types/attach/AttachUtils.java | 11 +++-- .../types/camera/CameraEntityUtils.java | 17 ++++++++ .../menu/debug/ImGuiWindowMacros.java | 3 ++ .../net/client/protocol/EntityProtocol.java | 14 ++----- .../ClientSynchronizationManager.java | 6 ++- .../pipelines/MainContentPipeline.java | 11 ++++- .../pipelines/NormalsForOutlinePipeline.java | 42 ++++++++++++++++--- 13 files changed, 154 insertions(+), 49 deletions(-) diff --git a/assets/Data/creatures/human.json b/assets/Data/creatures/human.json index fa3dfcfa..1ae58a3c 100644 --- a/assets/Data/creatures/human.json +++ b/assets/Data/creatures/human.json @@ -339,7 +339,7 @@ "name" : "Jump" }, "animationFirstPersonAttack" : { - "name" : "Jump" + "name" : "Sword1HSlash1" } }, { @@ -364,7 +364,7 @@ "name" : "Jump" }, "animationFirstPersonAttack" : { - "name" : "Jump" + "name" : "Sword1HSlash2" } }, { diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 0c78e59d..380a51e8 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -447,6 +447,10 @@ Overflow handling AI scaffolding Attacker ai tree +(07/24/2024) +2 Hand katana +Switching between first and third person + # TODO diff --git a/src/main/java/electrosphere/controls/ControlHandler.java b/src/main/java/electrosphere/controls/ControlHandler.java index aa670734..8419e019 100644 --- a/src/main/java/electrosphere/controls/ControlHandler.java +++ b/src/main/java/electrosphere/controls/ControlHandler.java @@ -92,6 +92,7 @@ import electrosphere.entity.state.movement.SprintTree; import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree; import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree.MovementRelativeFacing; import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree.MovementTreeState; +import electrosphere.entity.types.attach.AttachUtils; import electrosphere.entity.types.camera.CameraEntityUtils; import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.logger.LoggerInterface; @@ -1857,6 +1858,19 @@ public class ControlHandler { public boolean cameraIsThirdPerson(){ return cameraIsThirdPerson; } + + /** + * Sets the 1st/3rd person status of the camera + * @param isThirdPerson True for 3rd person, false for 1st person + */ + public void setIsThirdPerson(boolean isThirdPerson){ + this.cameraIsThirdPerson = isThirdPerson; + CameraEntityUtils.initCamera(); + ClientEquipState playerEquipState = ClientEquipState.getClientEquipState(Globals.playerEntity); + if(playerEquipState != null){ + playerEquipState.evaluatePlayerAttachments(); + } + } } diff --git a/src/main/java/electrosphere/engine/Main.java b/src/main/java/electrosphere/engine/Main.java index b249b285..93e958fb 100644 --- a/src/main/java/electrosphere/engine/Main.java +++ b/src/main/java/electrosphere/engine/Main.java @@ -163,27 +163,27 @@ public class Main { })); //uncomment to test loading a model into engine - // if(1==1){ - // Globals.assetManager.addModelPathToQueue("/Models/creatures/viewmodel.glb"); - // Globals.assetManager.loadAssetsInQueue(); - // electrosphere.renderer.model.Model model = Globals.assetManager.fetchModel("/Models/creatures/viewmodel.glb"); - // // for(electrosphere.renderer.anim.Animation anim : model.getAnimations()){ - // // if(anim.name.equals("Armature|Idle1")){ - // // System.out.println(anim.duration); - // // for(electrosphere.renderer.anim.AnimChannel channel : anim.channels){ - // // if(channel.getNodeID().equals("Torso")){ - // // channel.fullDescribeChannel(); - // // } - // // // System.out.println("CHannel: " + channel.getNodeID()); - // // } - // // break; - // // } - // // } - // model.describeHighLevel(); - // // model.animations.get(0).fullDescribeAnimation(); - // // model.describeHighLevel(); - // System.exit(0); - // } + // if(1==1){ + // Globals.assetManager.addModelPathToQueue("/Models/creatures/viewmodel.glb"); + // Globals.assetManager.loadAssetsInQueue(); + // electrosphere.renderer.model.Model model = Globals.assetManager.fetchModel("/Models/creatures/viewmodel.glb"); + // // for(electrosphere.renderer.anim.Animation anim : model.getAnimations()){ + // // if(anim.name.equals("Armature|Idle1")){ + // // System.out.println(anim.duration); + // // for(electrosphere.renderer.anim.AnimChannel channel : anim.channels){ + // // if(channel.getNodeID().equals("Torso")){ + // // channel.fullDescribeChannel(); + // // } + // // // System.out.println("CHannel: " + channel.getNodeID()); + // // } + // // break; + // // } + // // } + // model.describeHighLevel(); + // // model.animations.get(0).fullDescribeAnimation(); + // // model.describeHighLevel(); + // System.exit(0); + // } //create the audio context if(Globals.RUN_CLIENT && !Globals.HEADLESS && Globals.RUN_AUDIO){ diff --git a/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java b/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java index 5532d128..59912e01 100644 --- a/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java +++ b/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java @@ -26,7 +26,6 @@ import electrosphere.menu.mainmenu.MenuGeneratorsMultiplayer; import electrosphere.net.NetUtils; import electrosphere.net.client.ClientNetworking; import electrosphere.renderer.ui.elements.Window; -import electrosphere.util.MathUtils; public class ClientLoading { @@ -161,11 +160,7 @@ public class ClientLoading { Player Camera */ - if(Globals.controlHandler.cameraIsThirdPerson()){ - Globals.playerCamera = CameraEntityUtils.spawnPlayerEntityTrackingCameraEntity(new Vector3f(1,0,1), MathUtils.getOriginVectorf()); - } else { - Globals.playerCamera = CameraEntityUtils.spawnPlayerEntityTrackingCameraFirstPersonEntity(new Vector3f(1,0,1), MathUtils.getOriginVectorf()); - } + CameraEntityUtils.initCamera(); /* diff --git a/src/main/java/electrosphere/entity/state/equip/ClientEquipState.java b/src/main/java/electrosphere/entity/state/equip/ClientEquipState.java index 15663018..f8e0f8f4 100644 --- a/src/main/java/electrosphere/entity/state/equip/ClientEquipState.java +++ b/src/main/java/electrosphere/entity/state/equip/ClientEquipState.java @@ -22,6 +22,7 @@ import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.item.ItemUtils; import electrosphere.game.data.creature.type.equip.EquipPoint; import electrosphere.game.data.item.type.EquipWhitelist; +import electrosphere.logger.LoggerInterface; import electrosphere.net.parser.net.message.InventoryMessage; import electrosphere.net.parser.net.message.NetworkMessage; import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree; @@ -326,6 +327,33 @@ public class ClientEquipState implements BehaviorTree { return equipMap.containsKey(point); } + + /** + * Checks if the player has any attached entities, and if so, makes sure they're attached to the right model + * This should be used when we change the camera of the player (IE from first to third person or vice versa) + */ + public void evaluatePlayerAttachments(){ + if(this.parent != Globals.playerEntity){ + LoggerInterface.loggerEngine.ERROR(new IllegalStateException("Re-evaluating client attachments on non-player entity! This should only be called for the player's entity!")); + } + if(Globals.controlHandler.cameraIsThirdPerson()){ + for(String occupiedPoint : this.getEquippedPoints()){ + EquipPoint point = this.getEquipPoint(occupiedPoint); + Entity toEquip = this.equipMap.get(point.getEquipPointId()); + AttachUtils.clientDetatchEntityFromEntityAtBone(Globals.firstPersonEntity, toEquip); + AttachUtils.clientAttachEntityToEntityAtBone(Globals.playerEntity, toEquip, point.getBone(), AttachUtils.getEquipPointRotationOffset(point.getOffsetRotation())); + } + } else { + for(String occupiedPoint : this.getEquippedPoints()){ + EquipPoint point = this.getEquipPoint(occupiedPoint); + Entity toEquip = this.equipMap.get(point.getEquipPointId()); + AttachUtils.clientDetatchEntityFromEntityAtBone(Globals.playerEntity, toEquip); + AttachUtils.clientAttachEntityToEntityAtBone(Globals.firstPersonEntity, toEquip, point.getFirstPersonBone(), AttachUtils.getEquipPointRotationOffset(point.getOffsetRotation())); + } + } + } + + @Override public void simulate(float deltaTime) { } diff --git a/src/main/java/electrosphere/entity/types/attach/AttachUtils.java b/src/main/java/electrosphere/entity/types/attach/AttachUtils.java index 07c34f89..65766f82 100644 --- a/src/main/java/electrosphere/entity/types/attach/AttachUtils.java +++ b/src/main/java/electrosphere/entity/types/attach/AttachUtils.java @@ -281,7 +281,6 @@ public class AttachUtils { - // @@ -439,8 +438,10 @@ public class AttachUtils { * Detatches an entity on the server * @param parent The parent entity * @param toAttach The attached entity + * @return The bone the entity was attached to */ - public static void serverDetatchEntityFromEntityAtBone(Entity parent, Entity toAttach){ + public static String serverDetatchEntityFromEntityAtBone(Entity parent, Entity toAttach){ + String bone = getTargetBone(toAttach); ServerEntityTagUtils.removeTagFromEntity(toAttach, EntityTags.BONE_ATTACHED); toAttach.removeData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED); toAttach.removeData(EntityDataStrings.ATTACH_PARENT); @@ -448,14 +449,17 @@ public class AttachUtils { if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){ getChildrenList(parent).remove(toAttach); } + return bone; } /** * Detatches an entity on the client * @param parent The parent entity * @param toAttach The attached entity + * @return The bone the entity was attached to */ - public static void clientDetatchEntityFromEntityAtBone(Entity parent, Entity toAttach){ + public static String clientDetatchEntityFromEntityAtBone(Entity parent, Entity toAttach){ + String bone = getTargetBone(toAttach); Globals.clientSceneWrapper.getScene().removeEntityFromTag(toAttach, EntityTags.BONE_ATTACHED); toAttach.removeData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED); toAttach.removeData(EntityDataStrings.ATTACH_PARENT); @@ -463,6 +467,7 @@ public class AttachUtils { if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){ getChildrenList(parent).remove(toAttach); } + return bone; } diff --git a/src/main/java/electrosphere/entity/types/camera/CameraEntityUtils.java b/src/main/java/electrosphere/entity/types/camera/CameraEntityUtils.java index ee1c8d0d..025ea664 100644 --- a/src/main/java/electrosphere/entity/types/camera/CameraEntityUtils.java +++ b/src/main/java/electrosphere/entity/types/camera/CameraEntityUtils.java @@ -6,6 +6,7 @@ import electrosphere.entity.EntityCreationUtils; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; import electrosphere.entity.btree.BehaviorTree; +import electrosphere.util.MathUtils; import org.joml.Matrix4f; import org.joml.Quaternionf; @@ -105,6 +106,22 @@ public class CameraEntityUtils { Globals.clientScene.registerBehaviorTree(entityTrackingTree); return rVal; } + + /** + * Initializes the camera + */ + public static void initCamera(){ + //destroy if it already exists + if(Globals.playerCamera != null){ + Globals.clientSceneWrapper.getScene().deregisterEntity(Globals.playerCamera); + } + //create + if(Globals.controlHandler.cameraIsThirdPerson()){ + Globals.playerCamera = CameraEntityUtils.spawnPlayerEntityTrackingCameraEntity(new Vector3f(1,0,1), MathUtils.getOriginVectorf()); + } else { + Globals.playerCamera = CameraEntityUtils.spawnPlayerEntityTrackingCameraFirstPersonEntity(new Vector3f(1,0,1), MathUtils.getOriginVectorf()); + } + } public static Entity getOrbitalCameraTarget(Entity camera){ return (Entity)camera.getData(EntityDataStrings.DATA_STRING_CAMERA_ORBIT_TARGET); diff --git a/src/main/java/electrosphere/menu/debug/ImGuiWindowMacros.java b/src/main/java/electrosphere/menu/debug/ImGuiWindowMacros.java index 123de70e..55a9ee09 100644 --- a/src/main/java/electrosphere/menu/debug/ImGuiWindowMacros.java +++ b/src/main/java/electrosphere/menu/debug/ImGuiWindowMacros.java @@ -221,6 +221,9 @@ public class ImGuiWindowMacros { if(ImGui.button("Toggle Player Camera Lock")){ Globals.cameraHandler.setTrackPlayerEntity(!Globals.cameraHandler.getTrackPlayerEntity()); } + if(ImGui.button("Toggle 1st/3rd Person")){ + Globals.controlHandler.setIsThirdPerson(!Globals.controlHandler.cameraIsThirdPerson()); + } } }); playerEntityWindow.setOpen(false); diff --git a/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java b/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java index ba05b7d1..6efa3ca8 100644 --- a/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java +++ b/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java @@ -8,7 +8,6 @@ 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.client.firstPerson.FirstPersonTree; @@ -160,15 +159,10 @@ public class EntityProtocol { 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()); - } + 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()); } } } diff --git a/src/main/java/electrosphere/net/synchronization/ClientSynchronizationManager.java b/src/main/java/electrosphere/net/synchronization/ClientSynchronizationManager.java index 29dce73b..f2a7f616 100644 --- a/src/main/java/electrosphere/net/synchronization/ClientSynchronizationManager.java +++ b/src/main/java/electrosphere/net/synchronization/ClientSynchronizationManager.java @@ -72,7 +72,11 @@ public class ClientSynchronizationManager { } break; } } else if(Globals.clientSceneWrapper.getEntityFromServerId(message.getentityId()) == null){ - LoggerInterface.loggerNetworking.WARNING("Client received synchronization packet for entity that no longer exists on client!"); + String errorMessage = + "Client received synchronization packet for entity that does not exists on client!\n" + + "Entity id in network message: " + message.getentityId() + ; + LoggerInterface.loggerNetworking.ERROR(new IllegalStateException(errorMessage)); } } for(SynchronizationMessage message : messagesToClear){ diff --git a/src/main/java/electrosphere/renderer/pipelines/MainContentPipeline.java b/src/main/java/electrosphere/renderer/pipelines/MainContentPipeline.java index b83257e0..c3edd591 100644 --- a/src/main/java/electrosphere/renderer/pipelines/MainContentPipeline.java +++ b/src/main/java/electrosphere/renderer/pipelines/MainContentPipeline.java @@ -247,7 +247,16 @@ public class MainContentPipeline implements RenderPipeline { * @return True if in blacklist, false otherwise */ static boolean entityBlacklist(Entity entity){ - return entity == Globals.firstPersonEntity; + return + //don't draw first person view in this pipeline ever + entity == Globals.firstPersonEntity || + + //don't draw third person view if camera is first person + ( + !Globals.controlHandler.cameraIsThirdPerson() && + entity == Globals.playerEntity + ) + ; } } diff --git a/src/main/java/electrosphere/renderer/pipelines/NormalsForOutlinePipeline.java b/src/main/java/electrosphere/renderer/pipelines/NormalsForOutlinePipeline.java index 9cb012d1..5ab78630 100644 --- a/src/main/java/electrosphere/renderer/pipelines/NormalsForOutlinePipeline.java +++ b/src/main/java/electrosphere/renderer/pipelines/NormalsForOutlinePipeline.java @@ -65,11 +65,7 @@ public class NormalsForOutlinePipeline implements RenderPipeline { for(Entity currentEntity : Globals.clientScene.getEntitiesWithTag(EntityTags.DRAWABLE)){ Vector3d position = EntityUtils.getPosition(currentEntity); - if( - (boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) && - currentEntity.getData(EntityDataStrings.DRAW_SOLID_PASS) != null && - currentEntity.getData(EntityDataStrings.DRAW_OUTLINE) != null - ){ + if(shouldDraw(currentEntity)){ //fetch actor Actor currentActor = EntityUtils.getActor(currentEntity); //calculate camera-modified vector3f @@ -87,5 +83,41 @@ public class NormalsForOutlinePipeline implements RenderPipeline { Globals.profiler.endCpuSample(); } + + /** + * Checks if the entity should be drawn + * @param entity The entity + * @return true if should draw, false otherwise + */ + static boolean shouldDraw(Entity entity){ + return + ( + (boolean)entity.getData(EntityDataStrings.DATA_STRING_DRAW) && + entity.getData(EntityDataStrings.DRAW_SOLID_PASS) != null && + entity.getData(EntityDataStrings.DRAW_OUTLINE) != null + ) && + ( + !entityBlacklist(entity) + ) + ; + } + + /** + * Checks whether the entity is on the blacklist for drawing in main pipeline or not + * @param entity The entity + * @return True if in blacklist, false otherwise + */ + static boolean entityBlacklist(Entity entity){ + return + //don't draw first person view in this pipeline ever + entity == Globals.firstPersonEntity || + + //don't draw third person view if camera is first person + ( + !Globals.controlHandler.cameraIsThirdPerson() && + entity == Globals.playerEntity + ) + ; + } }