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
|
||||
|
||||
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
|
||||
Pass at client-server physics synchronization
|
||||
|
||||
(08/12/2024)
|
||||
Fix server animation playing at reduced timescale
|
||||
|
||||
|
||||
# TODO
|
||||
|
||||
|
||||
@ -33,6 +33,8 @@ import electrosphere.renderer.model.Model;
|
||||
import electrosphere.renderer.ui.imgui.ImGuiWindow;
|
||||
import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback;
|
||||
import electrosphere.server.datacell.utils.EntityLookupUtils;
|
||||
import electrosphere.server.poseactor.PoseActor;
|
||||
import electrosphere.server.poseactor.PoseModel;
|
||||
import imgui.ImGui;
|
||||
|
||||
/**
|
||||
@ -50,6 +52,7 @@ public class ImGuiEntityMacros {
|
||||
|
||||
//tree node values
|
||||
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 showFirstPersonTab = false; //first person tab
|
||||
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)){
|
||||
showActorTab = !showActorTab;
|
||||
}
|
||||
if(EntityUtils.getPoseActor(detailViewEntity) != null && ImGui.checkbox("Pose Actor Details", showPoseActorTab)){
|
||||
showPoseActorTab = !showPoseActorTab;
|
||||
}
|
||||
if(ClientEquipState.hasEquipState(detailViewEntity) && ImGui.checkbox("Equip State", showEquipStateTab)){
|
||||
showEquipStateTab = !showEquipStateTab;
|
||||
}
|
||||
@ -133,6 +139,7 @@ public class ImGuiEntityMacros {
|
||||
}
|
||||
ImGui.nextColumn();
|
||||
drawActorView();
|
||||
drawPoseActor();
|
||||
drawEquipState();
|
||||
drawFirstPersonView();
|
||||
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
|
||||
*/
|
||||
|
||||
@ -4,7 +4,8 @@ import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.joml.AxisAngle4f;
|
||||
import org.joml.Matrix4d;
|
||||
@ -32,7 +33,7 @@ public class PoseActor {
|
||||
//scalar on the speed of animation playback
|
||||
float animationScalar = 1.0f;
|
||||
//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)
|
||||
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
|
||||
@ -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
|
||||
* @param model The PoseModel to calculate transforms for
|
||||
@ -396,6 +405,14 @@ public class PoseActor {
|
||||
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
|
||||
* @param boneName
|
||||
@ -407,23 +424,62 @@ public class PoseActor {
|
||||
if(model != null){
|
||||
applyAnimationMasks(model);
|
||||
calculateNodeTransforms(model);
|
||||
// if(animation != null){
|
||||
// model.playAnimation(animation);
|
||||
// model.incrementTime(animationTime);
|
||||
// model.updateNodeTransform();
|
||||
Bone currentBone = model.boneMap.get(boneName);
|
||||
if(currentBone != null){
|
||||
Vector4d result = new Matrix4d(currentBone.getFinalTransform()).transform(currentBone.getMOffset().invert().transform(new Vector4d(rVal.x,rVal.y,rVal.z,1)));
|
||||
// currentBone.inverseBindPoseMatrix
|
||||
rVal.x = (float)result.x;
|
||||
rVal.y = (float)result.y;
|
||||
rVal.z = (float)result.z;
|
||||
}
|
||||
// }
|
||||
Bone currentBone = model.boneMap.get(boneName);
|
||||
if(currentBone != null){
|
||||
Vector4d result = new Matrix4d(currentBone.getFinalTransform()).transform(currentBone.getMOffset().invert().transform(new Vector4d(rVal.x,rVal.y,rVal.z,1)));
|
||||
rVal.x = (float)result.x;
|
||||
rVal.y = (float)result.y;
|
||||
rVal.z = (float)result.z;
|
||||
} else {
|
||||
String message = "Trying to get position of bone that does not exist on model!\n" +
|
||||
"boneName: " + boneName;
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
if(!Double.isFinite(rVal.x)){
|
||||
throw new IllegalStateException("Bone position that is not finite!");
|
||||
}
|
||||
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
|
||||
* @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
|
||||
* @param boneRotators The bone rotators
|
||||
@ -211,6 +219,21 @@ public class PoseModel {
|
||||
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
|
||||
* @return The list of bones
|
||||
|
||||
@ -5,7 +5,6 @@ import electrosphere.entity.types.attach.AttachUtils;
|
||||
import java.util.Set;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.engine.Main;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityTags;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
@ -42,7 +41,7 @@ public class MicroSimulation {
|
||||
PoseActor currentPoseActor = EntityUtils.getPoseActor(currentEntity);
|
||||
//increment animations
|
||||
if(currentPoseActor.isPlayingAnimation()){
|
||||
currentPoseActor.incrementAnimationTime(Globals.timekeeper.getSimFrameTime() / Main.targetFrameRate);
|
||||
currentPoseActor.incrementAnimationTime(Globals.timekeeper.getSimFrameTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user