server anim time scale fix
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
9d7ab27da7
commit
8e48250013
@ -1,4 +1,12 @@
|
|||||||
@page creatureideas Creature Ideas
|
@page creatureideas Creature Ideas
|
||||||
|
|
||||||
Leaf Sheep
|
Leaf Sheep
|
||||||
Jellyfish
|
Jellyfish
|
||||||
|
Mushroom-men
|
||||||
|
|
||||||
|
|
||||||
|
Ogres
|
||||||
|
Troll-men
|
||||||
|
Goblins
|
||||||
|
Demons/Devils
|
||||||
|
|
||||||
|
|||||||
@ -537,6 +537,9 @@ Ability to serialize/deserialize a creature with equipped items
|
|||||||
Sending initial synchronized state on player connect to chunk
|
Sending initial synchronized state on player connect to chunk
|
||||||
Pass at client-server physics synchronization
|
Pass at client-server physics synchronization
|
||||||
|
|
||||||
|
(08/12/2024)
|
||||||
|
Fix server animation playing at reduced timescale
|
||||||
|
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,8 @@ import electrosphere.renderer.model.Model;
|
|||||||
import electrosphere.renderer.ui.imgui.ImGuiWindow;
|
import electrosphere.renderer.ui.imgui.ImGuiWindow;
|
||||||
import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback;
|
import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback;
|
||||||
import electrosphere.server.datacell.utils.EntityLookupUtils;
|
import electrosphere.server.datacell.utils.EntityLookupUtils;
|
||||||
|
import electrosphere.server.poseactor.PoseActor;
|
||||||
|
import electrosphere.server.poseactor.PoseModel;
|
||||||
import imgui.ImGui;
|
import imgui.ImGui;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,6 +52,7 @@ public class ImGuiEntityMacros {
|
|||||||
|
|
||||||
//tree node values
|
//tree node values
|
||||||
private static boolean showActorTab = false; //show the actor tab
|
private static boolean showActorTab = false; //show the actor tab
|
||||||
|
private static boolean showPoseActorTab = false; //show the pose actor tab
|
||||||
private static boolean showEquipStateTab = false; //actor details
|
private static boolean showEquipStateTab = false; //actor details
|
||||||
private static boolean showFirstPersonTab = false; //first person tab
|
private static boolean showFirstPersonTab = false; //first person tab
|
||||||
private static boolean showLinkedEntitiesTab = false;//show linked entities
|
private static boolean showLinkedEntitiesTab = false;//show linked entities
|
||||||
@ -111,6 +114,9 @@ public class ImGuiEntityMacros {
|
|||||||
if(EntityUtils.getActor(detailViewEntity) != null && ImGui.checkbox("Actor Details", showActorTab)){
|
if(EntityUtils.getActor(detailViewEntity) != null && ImGui.checkbox("Actor Details", showActorTab)){
|
||||||
showActorTab = !showActorTab;
|
showActorTab = !showActorTab;
|
||||||
}
|
}
|
||||||
|
if(EntityUtils.getPoseActor(detailViewEntity) != null && ImGui.checkbox("Pose Actor Details", showPoseActorTab)){
|
||||||
|
showPoseActorTab = !showPoseActorTab;
|
||||||
|
}
|
||||||
if(ClientEquipState.hasEquipState(detailViewEntity) && ImGui.checkbox("Equip State", showEquipStateTab)){
|
if(ClientEquipState.hasEquipState(detailViewEntity) && ImGui.checkbox("Equip State", showEquipStateTab)){
|
||||||
showEquipStateTab = !showEquipStateTab;
|
showEquipStateTab = !showEquipStateTab;
|
||||||
}
|
}
|
||||||
@ -133,6 +139,7 @@ public class ImGuiEntityMacros {
|
|||||||
}
|
}
|
||||||
ImGui.nextColumn();
|
ImGui.nextColumn();
|
||||||
drawActorView();
|
drawActorView();
|
||||||
|
drawPoseActor();
|
||||||
drawEquipState();
|
drawEquipState();
|
||||||
drawFirstPersonView();
|
drawFirstPersonView();
|
||||||
drawLinkedEntities();
|
drawLinkedEntities();
|
||||||
@ -242,6 +249,82 @@ public class ImGuiEntityMacros {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws pose actor
|
||||||
|
*/
|
||||||
|
protected static void drawPoseActor(){
|
||||||
|
if(showPoseActorTab && ImGui.collapsingHeader("Pose Actor Details")){
|
||||||
|
ImGui.indent();
|
||||||
|
if(detailViewEntity != null && EntityUtils.getPoseActor(detailViewEntity) != null){
|
||||||
|
PoseActor poseActor = EntityUtils.getPoseActor(detailViewEntity);
|
||||||
|
|
||||||
|
//animation queue
|
||||||
|
if(ImGui.collapsingHeader("Animation Queue")){
|
||||||
|
Set<ActorAnimationMask> animationQueue = poseActor.getAnimationQueue();
|
||||||
|
for(ActorAnimationMask mask : animationQueue){
|
||||||
|
ImGui.text(mask.getAnimationName() + " - " + mask.getPriority());
|
||||||
|
ImGui.text(mask.getDuration() + " " + mask.getTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//bone values
|
||||||
|
if(ImGui.collapsingHeader("Bone Values")){
|
||||||
|
for(Bone bone : poseActor.getBoneValues()){
|
||||||
|
ImGui.text(bone.boneID);
|
||||||
|
ImGui.text("Position: " + poseActor.getBonePosition(bone.boneID));
|
||||||
|
ImGui.text("Rotation: " + poseActor.getBoneRotation(bone.boneID));
|
||||||
|
ImGui.text(bone.getFinalTransform() + "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Draws all the bones in the world
|
||||||
|
if(ImGui.button("Draw Bones")){
|
||||||
|
Globals.renderingEngine.getDebugContentPipeline().getDebugBonesPipeline().setEntity(detailViewEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Browsable list of all animations with their data
|
||||||
|
if(ImGui.collapsingHeader("Animation Channel Data")){
|
||||||
|
Model model = Globals.assetManager.fetchModel(poseActor.getModelPath());
|
||||||
|
ImGui.indent();
|
||||||
|
for(Animation animation : model.getAnimations()){
|
||||||
|
if(ImGui.collapsingHeader(animation.name)){
|
||||||
|
for(AnimChannel channel : animation.channels){
|
||||||
|
ImGui.pushID(channel.getNodeID());
|
||||||
|
if(ImGui.button("Fully describe")){
|
||||||
|
channel.fullDescribeChannel();
|
||||||
|
}
|
||||||
|
ImGui.text("=" + channel.getNodeID() + "=");
|
||||||
|
ImGui.text("" + channel.getCurrentPosition());
|
||||||
|
ImGui.text("" + channel.getCurrentRotation());
|
||||||
|
ImGui.text("" + channel.getCurrentScale());
|
||||||
|
ImGui.popID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui.unindent();
|
||||||
|
}
|
||||||
|
|
||||||
|
//print data macros
|
||||||
|
if(ImGui.collapsingHeader("Print Data")){
|
||||||
|
//print bone values
|
||||||
|
if(ImGui.button("Print current bone values")){
|
||||||
|
for(Bone bone : poseActor.getBoneValues()){
|
||||||
|
LoggerInterface.loggerRenderer.DEBUG(bone.boneID);
|
||||||
|
LoggerInterface.loggerRenderer.DEBUG("" + bone.getFinalTransform());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//print animation keys
|
||||||
|
if(ImGui.button("Print animation keys")){
|
||||||
|
PoseModel model = Globals.assetManager.fetchPoseModel(poseActor.getModelPath());
|
||||||
|
model.describeAllAnimations();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui.unindent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* First person data
|
* First person data
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -4,7 +4,8 @@ import java.util.HashMap;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.PriorityQueue;
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import org.joml.AxisAngle4f;
|
import org.joml.AxisAngle4f;
|
||||||
import org.joml.Matrix4d;
|
import org.joml.Matrix4d;
|
||||||
@ -32,7 +33,7 @@ public class PoseActor {
|
|||||||
//scalar on the speed of animation playback
|
//scalar on the speed of animation playback
|
||||||
float animationScalar = 1.0f;
|
float animationScalar = 1.0f;
|
||||||
//priority queue of animations to play. Allows masking a higher priority animation over a lower priority one.
|
//priority queue of animations to play. Allows masking a higher priority animation over a lower priority one.
|
||||||
PriorityQueue<ActorAnimationMask> animationQueue = new PriorityQueue<ActorAnimationMask>();
|
Set<ActorAnimationMask> animationQueue = new TreeSet<ActorAnimationMask>();
|
||||||
//bone rotation map. Used to apply rotator functionality to bones (think hair, cloth, and camera rotation on looking)
|
//bone rotation map. Used to apply rotator functionality to bones (think hair, cloth, and camera rotation on looking)
|
||||||
Map<String,ActorBoneRotator> boneRotators = new HashMap<String,ActorBoneRotator>();
|
Map<String,ActorBoneRotator> boneRotators = new HashMap<String,ActorBoneRotator>();
|
||||||
//static morph used to apply an initial, static modification to the layout of bones in the pose model
|
//static morph used to apply an initial, static modification to the layout of bones in the pose model
|
||||||
@ -332,6 +333,14 @@ public class PoseActor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the animation queue
|
||||||
|
* @return The animation queue
|
||||||
|
*/
|
||||||
|
public Set<ActorAnimationMask> getAnimationQueue(){
|
||||||
|
return animationQueue;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates all node transforms for the PoseModel based on bone rotators and the static morph of this PoseActor
|
* Calculates all node transforms for the PoseModel based on bone rotators and the static morph of this PoseActor
|
||||||
* @param model The PoseModel to calculate transforms for
|
* @param model The PoseModel to calculate transforms for
|
||||||
@ -396,6 +405,14 @@ public class PoseActor {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the model path associated with the pose actor
|
||||||
|
* @return The model path
|
||||||
|
*/
|
||||||
|
public String getModelPath(){
|
||||||
|
return modelPath;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the position of a bone currently
|
* Gets the position of a bone currently
|
||||||
* @param boneName
|
* @param boneName
|
||||||
@ -407,23 +424,62 @@ public class PoseActor {
|
|||||||
if(model != null){
|
if(model != null){
|
||||||
applyAnimationMasks(model);
|
applyAnimationMasks(model);
|
||||||
calculateNodeTransforms(model);
|
calculateNodeTransforms(model);
|
||||||
// if(animation != null){
|
Bone currentBone = model.boneMap.get(boneName);
|
||||||
// model.playAnimation(animation);
|
if(currentBone != null){
|
||||||
// model.incrementTime(animationTime);
|
Vector4d result = new Matrix4d(currentBone.getFinalTransform()).transform(currentBone.getMOffset().invert().transform(new Vector4d(rVal.x,rVal.y,rVal.z,1)));
|
||||||
// model.updateNodeTransform();
|
rVal.x = (float)result.x;
|
||||||
Bone currentBone = model.boneMap.get(boneName);
|
rVal.y = (float)result.y;
|
||||||
if(currentBone != null){
|
rVal.z = (float)result.z;
|
||||||
Vector4d result = new Matrix4d(currentBone.getFinalTransform()).transform(currentBone.getMOffset().invert().transform(new Vector4d(rVal.x,rVal.y,rVal.z,1)));
|
} else {
|
||||||
// currentBone.inverseBindPoseMatrix
|
String message = "Trying to get position of bone that does not exist on model!\n" +
|
||||||
rVal.x = (float)result.x;
|
"boneName: " + boneName;
|
||||||
rVal.y = (float)result.y;
|
throw new IllegalArgumentException(message);
|
||||||
rVal.z = (float)result.z;
|
}
|
||||||
}
|
}
|
||||||
// }
|
if(!Double.isFinite(rVal.x)){
|
||||||
|
throw new IllegalStateException("Bone position that is not finite!");
|
||||||
}
|
}
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the transform of a given bone
|
||||||
|
* @param boneName The name of the bone
|
||||||
|
* @return The transform
|
||||||
|
*/
|
||||||
|
public Matrix4d getBoneTransform(String boneName){
|
||||||
|
Matrix4d rVal = new Matrix4d();
|
||||||
|
PoseModel model = Globals.assetManager.fetchPoseModel(modelPath);
|
||||||
|
if(model != null){
|
||||||
|
applyAnimationMasks(model);
|
||||||
|
calculateNodeTransforms(model);
|
||||||
|
Bone currentBone = model.getBoneMap().get(boneName);
|
||||||
|
if(currentBone != null){
|
||||||
|
rVal = currentBone.getFinalTransform();
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Trying to get rotation of bone that does not exist on model!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!Double.isFinite(rVal.m00())){
|
||||||
|
throw new IllegalStateException("Bone rotation that is not finite!");
|
||||||
|
}
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of all bones
|
||||||
|
* @return the list of all bones
|
||||||
|
*/
|
||||||
|
public List<Bone> getBoneValues(){
|
||||||
|
PoseModel model = Globals.assetManager.fetchPoseModel(modelPath);
|
||||||
|
if(model != null){
|
||||||
|
applyAnimationMasks(model);
|
||||||
|
calculateNodeTransforms(model);
|
||||||
|
return model.getBones();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the bone groups
|
* Sets the bone groups
|
||||||
* @param boneGroups The bone groups
|
* @param boneGroups The bone groups
|
||||||
|
|||||||
@ -161,6 +161,14 @@ public class PoseModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the map of bone name -> bone
|
||||||
|
* @return the map
|
||||||
|
*/
|
||||||
|
public Map<String,Bone> getBoneMap(){
|
||||||
|
return boneMap;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal recursive method behind the public updateNodeTransform
|
* Internal recursive method behind the public updateNodeTransform
|
||||||
* @param boneRotators The bone rotators
|
* @param boneRotators The bone rotators
|
||||||
@ -211,6 +219,21 @@ public class PoseModel {
|
|||||||
return animMap.get(animName);
|
return animMap.get(animName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs all animations for a given model
|
||||||
|
*/
|
||||||
|
public void describeAllAnimations(){
|
||||||
|
if(animations.size() > 0){
|
||||||
|
LoggerInterface.loggerRenderer.DEBUG("=====================");
|
||||||
|
LoggerInterface.loggerRenderer.DEBUG(animations.size() + " animations available in model!");
|
||||||
|
Iterator<Animation> animIterator = animations.iterator();
|
||||||
|
while(animIterator.hasNext()){
|
||||||
|
Animation currentAnim = animIterator.next();
|
||||||
|
currentAnim.describeAnimation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the list of bones in this pose model
|
* Gets the list of bones in this pose model
|
||||||
* @return The list of bones
|
* @return The list of bones
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import electrosphere.entity.types.attach.AttachUtils;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.engine.Main;
|
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.entity.EntityTags;
|
import electrosphere.entity.EntityTags;
|
||||||
import electrosphere.entity.EntityUtils;
|
import electrosphere.entity.EntityUtils;
|
||||||
@ -42,7 +41,7 @@ public class MicroSimulation {
|
|||||||
PoseActor currentPoseActor = EntityUtils.getPoseActor(currentEntity);
|
PoseActor currentPoseActor = EntityUtils.getPoseActor(currentEntity);
|
||||||
//increment animations
|
//increment animations
|
||||||
if(currentPoseActor.isPlayingAnimation()){
|
if(currentPoseActor.isPlayingAnimation()){
|
||||||
currentPoseActor.incrementAnimationTime(Globals.timekeeper.getSimFrameTime() / Main.targetFrameRate);
|
currentPoseActor.incrementAnimationTime(Globals.timekeeper.getSimFrameTime());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user