actor code cleanup

This commit is contained in:
austin 2025-05-29 15:30:54 -04:00
parent 083198e5e5
commit e9067af287
18 changed files with 314 additions and 152 deletions

View File

@ -2059,6 +2059,7 @@ Logging for loading thread failure
Code cleanup Code cleanup
More tests More tests
Move actor masks into dedicated package Move actor masks into dedicated package
Actor code cleanup

View File

@ -55,8 +55,8 @@ public class ImGuiEntityActorTab {
} }
} }
} else { } else {
ImGui.text("Model path: " + actor.getModelPath()); ImGui.text("Model path: " + actor.getBaseModelPath());
Model loadedModel = Globals.assetManager.fetchModel(actor.getModelPath()); Model loadedModel = Globals.assetManager.fetchModel(actor.getBaseModelPath());
ImGui.text("Model is loaded: " + (loadedModel != null)); ImGui.text("Model is loaded: " + (loadedModel != null));
} }
@ -99,7 +99,7 @@ public class ImGuiEntityActorTab {
//Browsable list of all animations with their data //Browsable list of all animations with their data
if(ImGui.collapsingHeader("Animation Channel Data")){ if(ImGui.collapsingHeader("Animation Channel Data")){
Model model = Globals.assetManager.fetchModel(actor.getModelPath()); Model model = Globals.assetManager.fetchModel(actor.getBaseModelPath());
ImGui.indent(); ImGui.indent();
for(Animation animation : model.getAnimations()){ for(Animation animation : model.getAnimations()){
if(ImGui.collapsingHeader(animation.name)){ if(ImGui.collapsingHeader(animation.name)){
@ -139,7 +139,7 @@ public class ImGuiEntityActorTab {
//print animation keys //print animation keys
if(ImGui.button("Print animation keys")){ if(ImGui.button("Print animation keys")){
Model model = Globals.assetManager.fetchModel(actor.getModelPath()); Model model = Globals.assetManager.fetchModel(actor.getBaseModelPath());
model.describeAllAnimations(); model.describeAllAnimations();
} }
} }

View File

@ -70,7 +70,7 @@ public class DrawableUtils {
//add low-res model path to actor if present //add low-res model path to actor if present
if(modelData.getLODPath() != null){ if(modelData.getLODPath() != null){
creatureActor.setLowResPath(modelData.getLODPath()); creatureActor.setLowResBaseModelPath(modelData.getLODPath());
Globals.assetManager.addModelPathToQueue(modelData.getLODPath()); Globals.assetManager.addModelPathToQueue(modelData.getLODPath());
} }

View File

@ -107,7 +107,7 @@ public class FirstPersonTree implements BehaviorTree {
Actor actor = EntityUtils.getActor(Globals.clientState.firstPersonEntity); Actor actor = EntityUtils.getActor(Globals.clientState.firstPersonEntity);
if( if(
(!actor.isPlayingAnimation() || !actor.isPlayingAnimation(animationName)) && (!actor.isPlayingAnimation() || !actor.isPlayingAnimation(animationName)) &&
(Globals.assetManager.fetchModel(actor.getModelPath()) != null && Globals.assetManager.fetchModel(actor.getModelPath()).getAnimation(animationName) != null) (Globals.assetManager.fetchModel(actor.getBaseModelPath()) != null && Globals.assetManager.fetchModel(actor.getBaseModelPath()).getAnimation(animationName) != null)
){ ){
actor.playAnimation(animationName,priority); actor.playAnimation(animationName,priority);
actor.incrementAnimationTime(offset); actor.incrementAnimationTime(offset);
@ -133,7 +133,7 @@ public class FirstPersonTree implements BehaviorTree {
Actor actor = EntityUtils.getActor(Globals.clientState.firstPersonEntity); Actor actor = EntityUtils.getActor(Globals.clientState.firstPersonEntity);
if( if(
(!actor.isPlayingAnimation() || !actor.isPlayingAnimation(animation.getNameFirstPerson())) && (!actor.isPlayingAnimation() || !actor.isPlayingAnimation(animation.getNameFirstPerson())) &&
(Globals.assetManager.fetchModel(actor.getModelPath()) != null && Globals.assetManager.fetchModel(actor.getModelPath()).getAnimation(animation.getNameFirstPerson()) != null) (Globals.assetManager.fetchModel(actor.getBaseModelPath()) != null && Globals.assetManager.fetchModel(actor.getBaseModelPath()).getAnimation(animation.getNameFirstPerson()) != null)
){ ){
actor.playAnimation(animation, false); actor.playAnimation(animation, false);
actor.incrementAnimationTime(offset); actor.incrementAnimationTime(offset);
@ -150,7 +150,7 @@ public class FirstPersonTree implements BehaviorTree {
Actor actor = EntityUtils.getActor(Globals.clientState.firstPersonEntity); Actor actor = EntityUtils.getActor(Globals.clientState.firstPersonEntity);
if( if(
(actor.isPlayingAnimation() || actor.isPlayingAnimation(animation.getNameFirstPerson())) && (actor.isPlayingAnimation() || actor.isPlayingAnimation(animation.getNameFirstPerson())) &&
(Globals.assetManager.fetchModel(actor.getModelPath()) != null && Globals.assetManager.fetchModel(actor.getModelPath()).getAnimation(animation.getNameFirstPerson()) != null) (Globals.assetManager.fetchModel(actor.getBaseModelPath()) != null && Globals.assetManager.fetchModel(actor.getBaseModelPath()).getAnimation(animation.getNameFirstPerson()) != null)
){ ){
actor.interruptAnimation(animation, false); actor.interruptAnimation(animation, false);
} }

View File

@ -80,8 +80,8 @@ public class ClientIdleTree implements BehaviorTree {
idleData != null && idleData != null &&
(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(idleData.getAnimation())) && (!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(idleData.getAnimation())) &&
( (
Globals.assetManager.fetchModel(entityActor.getModelPath()) != null && Globals.assetManager.fetchModel(entityActor.getBaseModelPath()) != null &&
Globals.assetManager.fetchModel(entityActor.getModelPath()).getAnimation(idleData.getAnimation().getNameThirdPerson()) != null Globals.assetManager.fetchModel(entityActor.getBaseModelPath()).getAnimation(idleData.getAnimation().getNameThirdPerson()) != null
) )
){ ){

View File

@ -93,7 +93,6 @@ import electrosphere.net.server.player.Player;
import electrosphere.net.synchronization.transport.StateCollection; import electrosphere.net.synchronization.transport.StateCollection;
import electrosphere.renderer.actor.Actor; import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.actor.ActorBoneRotator; import electrosphere.renderer.actor.ActorBoneRotator;
import electrosphere.renderer.actor.ActorUtils;
import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils; import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
import electrosphere.server.datacell.utils.ServerEntityTagUtils; import electrosphere.server.datacell.utils.ServerEntityTagUtils;
@ -368,9 +367,6 @@ public class CommonEntityUtils {
ClientAlwaysUprightTree.attachTree(entity); ClientAlwaysUprightTree.attachTree(entity);
CreatureUtils.setFacingVector(entity, SpatialMathUtils.getOriginVector()); CreatureUtils.setFacingVector(entity, SpatialMathUtils.getOriginVector());
} break; } break;
case "BLENDER_ROTATION": {
ActorUtils.applyBlenderRotation(entity);
} break;
case "SPAWNPOINT": { case "SPAWNPOINT": {
//ignore on client //ignore on client
} break; } break;
@ -684,9 +680,6 @@ public class CommonEntityUtils {
ServerAlwaysUprightTree.attachTree(entity); ServerAlwaysUprightTree.attachTree(entity);
CreatureUtils.setFacingVector(entity, SpatialMathUtils.getOriginVector()); CreatureUtils.setFacingVector(entity, SpatialMathUtils.getOriginVector());
} break; } break;
case "BLENDER_ROTATION": {
ActorUtils.applyBlenderRotation(entity);
} break;
case "SPAWNPOINT": { case "SPAWNPOINT": {
realm.registerSpawnPoint(position); realm.registerSpawnPoint(position);
} break; } break;

View File

@ -8,14 +8,14 @@ import electrosphere.logger.LoggerInterface;
import electrosphere.mem.JomlPool; import electrosphere.mem.JomlPool;
import electrosphere.renderer.OpenGLState; import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderPipelineState; import electrosphere.renderer.RenderPipelineState;
import electrosphere.renderer.actor.ActorUniformMap.UniformValue;
import electrosphere.renderer.actor.mask.ActorAnimationMask; import electrosphere.renderer.actor.mask.ActorAnimationMask;
import electrosphere.renderer.actor.mask.ActorMeshMask; import electrosphere.renderer.actor.mask.ActorMeshMask;
import electrosphere.renderer.actor.mask.ActorShaderMask; import electrosphere.renderer.actor.mask.ActorShaderMask;
import electrosphere.renderer.actor.mask.ActorTextureMask; import electrosphere.renderer.actor.mask.ActorTextureMask;
import electrosphere.renderer.actor.mask.ActorUniformMap;
import electrosphere.renderer.actor.mask.ActorUniformMap.UniformValue;
import electrosphere.renderer.model.Bone; import electrosphere.renderer.model.Bone;
import electrosphere.renderer.model.Model; import electrosphere.renderer.model.Model;
import electrosphere.renderer.texture.Texture;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
@ -64,15 +64,14 @@ public class Actor {
public static final int LOD_LEVEL_STATIC = 0; public static final int LOD_LEVEL_STATIC = 0;
/**
* the model path of the model backing the actor
*/
private String modelPath;
/**
* Path to the low res model
*/ //
private String lowResPath; //
// CORE RENDER VARS
//
//
/** /**
* The LOD level of the actor * The LOD level of the actor
@ -80,16 +79,55 @@ public class Actor {
private int lodLevel = Actor.LOD_LEVEL_FULL; private int lodLevel = Actor.LOD_LEVEL_FULL;
/** /**
* used for statically binding textures in pipelines that dont bind textures on a per-mesh level * Controls whether the actor should obey frustum culling
* ie when in the ui, this can be set to bind a texture at the actor level
*/ */
private String textureOverride; private boolean frustumCull = true;
/** /**
* scales the time that animations are played at * scales the time that animations are played at
*/ */
private float animationScalar = 1.0f; private float animationScalar = 1.0f;
/**
* Sets scaling applied at the actor level
*/
private float scale = 1.0f;
/**
* The transform matrix
*/
private Matrix4d modelMatrix = new Matrix4d();
/**
* The world position vector
*/
private Vector3d worldPos = new Vector3d();
//
//
// MODEL AND MESH DATA
//
//
/**
* the model path of the model backing the actor
*/
private String baseModelPath;
/**
* Path to the low res model
*/
private String lowResBaseModelPath;
/** /**
* The stack of animations being applied to a given actor * The stack of animations being applied to a given actor
*/ */
@ -130,16 +168,20 @@ public class Actor {
*/ */
private ActorUniformMap uniformMap = new ActorUniformMap(); private ActorUniformMap uniformMap = new ActorUniformMap();
/**
* Controls whether the actor should obey frustum culling
*/
private boolean frustumCull = true;
/** /**
* Used for caching animation masks that should be removed * Used for caching animation masks that should be removed
*/ */
private List<ActorAnimationMask> toRemoveMasks = new LinkedList<ActorAnimationMask>(); private List<ActorAnimationMask> toRemoveMasks = new LinkedList<ActorAnimationMask>();
//
//
// DATA CACHING
//
//
/** /**
* Stores the positions of bones as they are updated * Stores the positions of bones as they are updated
*/ */
@ -149,28 +191,23 @@ public class Actor {
* Stores the rotations of bones as they are updated * Stores the rotations of bones as they are updated
*/ */
private Map<String,Quaterniond> boneRotationMap = new HashMap<String,Quaterniond>(); private Map<String,Quaterniond> boneRotationMap = new HashMap<String,Quaterniond>();
/**
* Sets scaling applied at the actor level
*/
private float scale = 1.0f;
/**
* The transform matrix
*/
private Matrix4d modelMatrix = new Matrix4d();
/**
* The world position vector
*/
private Vector3d worldPos = new Vector3d();
/** /**
* Creates an achor * Creates an achor
* @param modelPath The path of the model associated with the actor * @param modelPath The path of the model associated with the actor
*/ */
public Actor(String modelPath){ public Actor(String modelPath){
this.modelPath = modelPath; this.baseModelPath = modelPath;
} }
/** /**
@ -266,7 +303,7 @@ public class Actor {
* @param priority The priority of the animation * @param priority The priority of the animation
*/ */
public void playAnimation(String animationName, int priority){ public void playAnimation(String animationName, int priority){
Model model = Globals.assetManager.fetchModel(modelPath); Model model = Globals.assetManager.fetchModel(baseModelPath);
if(model != null && model.getAnimation(animationName) != null){ if(model != null && model.getAnimation(animationName) != null){
double length = model.getAnimation(animationName).duration; double length = model.getAnimation(animationName).duration;
ActorAnimationMask animMask = new ActorAnimationMask(priority, animationName, 0, length); ActorAnimationMask animMask = new ActorAnimationMask(priority, animationName, 0, length);
@ -335,11 +372,11 @@ public class Actor {
} else if(animation.getBoneGroups() != null && this.boneGroups == null){ } else if(animation.getBoneGroups() != null && this.boneGroups == null){
LoggerInterface.loggerRenderer.WARNING( LoggerInterface.loggerRenderer.WARNING(
"Trying to play animation on Actor that uses bone groups, but the Actor's bone group isn't defined!\n" + "Trying to play animation on Actor that uses bone groups, but the Actor's bone group isn't defined!\n" +
"Model path: " + modelPath + "\n" + "Model path: " + baseModelPath + "\n" +
"Animation name: " + animationName + "\n" "Animation name: " + animationName + "\n"
); );
} else if(animation.getBoneGroups() == null){ } else if(animation.getBoneGroups() == null){
Model model = Globals.assetManager.fetchModel(this.modelPath); Model model = Globals.assetManager.fetchModel(this.baseModelPath);
if(model != null){ if(model != null){
boneMask = new LinkedList<String>(); boneMask = new LinkedList<String>();
for(Bone bone : model.getBones()){ for(Bone bone : model.getBones()){
@ -349,7 +386,7 @@ public class Actor {
} }
Model model = Globals.assetManager.fetchModel(modelPath); Model model = Globals.assetManager.fetchModel(baseModelPath);
if(model != null && model.getAnimation(animationName) != null){ if(model != null && model.getAnimation(animationName) != null){
//get data from the actual animation in the model //get data from the actual animation in the model
@ -429,7 +466,7 @@ public class Actor {
} }
public void playAnimationWithMask(String animationName, int priority, List<String> boneMask){ public void playAnimationWithMask(String animationName, int priority, List<String> boneMask){
Model model = Globals.assetManager.fetchModel(modelPath); Model model = Globals.assetManager.fetchModel(baseModelPath);
if(model != null){ if(model != null){
double length = model.getAnimation(animationName).duration; double length = model.getAnimation(animationName).duration;
ActorAnimationMask animMask = new ActorAnimationMask(priority, animationName, 0, length, boneMask); ActorAnimationMask animMask = new ActorAnimationMask(priority, animationName, 0, length, boneMask);
@ -519,7 +556,7 @@ public class Actor {
* @param worldPos The world position of the model * @param worldPos The world position of the model
*/ */
public void applySpatialData(Matrix4d modelMatrix, Vector3d worldPos){ public void applySpatialData(Matrix4d modelMatrix, Vector3d worldPos){
Model model = Globals.assetManager.fetchModel(modelPath); Model model = Globals.assetManager.fetchModel(baseModelPath);
if(model != null){ if(model != null){
this.modelMatrix.set(modelMatrix); this.modelMatrix.set(modelMatrix);
this.worldPos.set(worldPos); this.worldPos.set(worldPos);
@ -534,9 +571,9 @@ public class Actor {
Globals.profiler.beginAggregateCpuSample("Actor.draw"); Globals.profiler.beginAggregateCpuSample("Actor.draw");
//fetch the model //fetch the model
String pathToFetch = this.modelPath; String pathToFetch = this.baseModelPath;
if(this.lodLevel <= Actor.LOD_LEVEL_LOWER && this.lowResPath != null){ if(this.lodLevel <= Actor.LOD_LEVEL_LOWER && this.lowResBaseModelPath != null){
pathToFetch = this.lowResPath; pathToFetch = this.lowResBaseModelPath;
} }
Model model = Globals.assetManager.fetchModel(pathToFetch); Model model = Globals.assetManager.fetchModel(pathToFetch);
@ -559,12 +596,6 @@ public class Actor {
} }
} }
this.calculateNodeTransforms(model); this.calculateNodeTransforms(model);
if(textureOverride != null){
Texture overrideTextureObject = Globals.assetManager.fetchTexture(textureOverride);
if(overrideTextureObject != null){
overrideTextureObject.bind(openGLState);
}
}
//apply uniform overrides //apply uniform overrides
if(this.uniformMap.getMeshes() != null && this.uniformMap.getMeshes().size() > 0){ if(this.uniformMap.getMeshes() != null && this.uniformMap.getMeshes().size() > 0){
for(String meshName : this.uniformMap.getMeshes()){ for(String meshName : this.uniformMap.getMeshes()){
@ -600,7 +631,6 @@ public class Actor {
this.meshMask.getBlockedMeshes().size() == 0 && this.meshMask.getBlockedMeshes().size() == 0 &&
this.textureMap == null && this.textureMap == null &&
this.shaderMasks.size() == 0 && this.shaderMasks.size() == 0 &&
this.textureOverride == null &&
this.uniformMap.isEmpty() && this.uniformMap.isEmpty() &&
this.staticMorph == null this.staticMorph == null
) )
@ -623,7 +653,6 @@ public class Actor {
rVal = rVal + (this.meshMask.getBlockedMeshes().size() == 0) + "\n"; rVal = rVal + (this.meshMask.getBlockedMeshes().size() == 0) + "\n";
rVal = rVal + (this.textureMap == null) + "\n"; rVal = rVal + (this.textureMap == null) + "\n";
rVal = rVal + (this.shaderMasks.size() == 0) + "\n"; rVal = rVal + (this.shaderMasks.size() == 0) + "\n";
rVal = rVal + (this.textureOverride == null) + "\n";
rVal = rVal + this.uniformMap.isEmpty() + "\n"; rVal = rVal + this.uniformMap.isEmpty() + "\n";
rVal = rVal + (this.staticMorph == null) + "\n"; rVal = rVal + (this.staticMorph == null) + "\n";
return rVal; return rVal;
@ -636,22 +665,29 @@ public class Actor {
* @return true if it should draw, false otherwise * @return true if it should draw, false otherwise
*/ */
public boolean frustumTest(RenderPipelineState renderPipelineState, Vector3d position){ public boolean frustumTest(RenderPipelineState renderPipelineState, Vector3d position){
Model model = Globals.assetManager.fetchModel(modelPath); Model model = Globals.assetManager.fetchModel(baseModelPath);
if(model != null && Actor.isWithinFrustumBox(renderPipelineState,model,position,frustumCull)){ if(model != null && Actor.isWithinFrustumBox(renderPipelineState,model,position,frustumCull)){
return true; return true;
} }
return false; return false;
} }
/**
* Draws this actor in the ui pipeline
*/
public void drawUI(){ public void drawUI(){
Model model = Globals.assetManager.fetchModel(modelPath); Model model = Globals.assetManager.fetchModel(baseModelPath);
if(model != null){ if(model != null){
model.drawUI(); model.drawUI();
} }
} }
public String getModelPath(){ /**
return modelPath; * Gets the base model's path
* @return The base model's path
*/
public String getBaseModelPath(){
return baseModelPath;
} }
/** /**
@ -665,7 +701,7 @@ public class Actor {
return bonePositionMap.get(boneName); return bonePositionMap.get(boneName);
} }
Vector3d rVal = new Vector3d(); Vector3d rVal = new Vector3d();
Model model = Globals.assetManager.fetchModel(modelPath); Model model = Globals.assetManager.fetchModel(baseModelPath);
if(model != null){ if(model != null){
this.applyAnimationMasks(model); this.applyAnimationMasks(model);
this.calculateNodeTransforms(model); this.calculateNodeTransforms(model);
@ -700,7 +736,7 @@ public class Actor {
return boneRotationMap.get(boneName); return boneRotationMap.get(boneName);
} }
Quaterniond rVal = new Quaterniond(); Quaterniond rVal = new Quaterniond();
Model model = Globals.assetManager.fetchModel(modelPath); Model model = Globals.assetManager.fetchModel(baseModelPath);
if(model != null){ if(model != null){
this.applyAnimationMasks(model); this.applyAnimationMasks(model);
this.calculateNodeTransforms(model); this.calculateNodeTransforms(model);
@ -722,7 +758,7 @@ public class Actor {
public Matrix4d getBoneTransform(String boneName){ public Matrix4d getBoneTransform(String boneName){
Matrix4d rVal = new Matrix4d(); Matrix4d rVal = new Matrix4d();
Model model = Globals.assetManager.fetchModel(modelPath); Model model = Globals.assetManager.fetchModel(baseModelPath);
if(model != null){ if(model != null){
applyAnimationMasks(model); applyAnimationMasks(model);
calculateNodeTransforms(model); calculateNodeTransforms(model);
@ -744,7 +780,7 @@ public class Actor {
* @return the list of all bones * @return the list of all bones
*/ */
public List<Bone> getBoneValues(){ public List<Bone> getBoneValues(){
Model model = Globals.assetManager.fetchModel(modelPath); Model model = Globals.assetManager.fetchModel(baseModelPath);
if(model != null){ if(model != null){
applyAnimationMasks(model); applyAnimationMasks(model);
calculateNodeTransforms(model); calculateNodeTransforms(model);
@ -758,7 +794,7 @@ public class Actor {
* @return the bone * @return the bone
*/ */
public Bone getBone(String boneName){ public Bone getBone(String boneName){
Model model = Globals.assetManager.fetchModel(modelPath); Model model = Globals.assetManager.fetchModel(baseModelPath);
if(model != null){ if(model != null){
return model.getBoneMap().get(boneName); return model.getBoneMap().get(boneName);
} }
@ -771,26 +807,30 @@ public class Actor {
* @return true if it exists, false otherwise * @return true if it exists, false otherwise
*/ */
public boolean containsBone(String boneName){ public boolean containsBone(String boneName){
Model model = Globals.assetManager.fetchModel(modelPath); Model model = Globals.assetManager.fetchModel(baseModelPath);
if(model != null){ if(model != null){
return model.getBoneMap().containsKey(boneName); return model.getBoneMap().containsKey(boneName);
} }
return false; return false;
} }
/**
* Checks if the model is loaded for this actor
* @return true if it is loaded, false otherwise
*/
public boolean modelIsLoaded(){ public boolean modelIsLoaded(){
Model model = Globals.assetManager.fetchModel(modelPath); Model model = Globals.assetManager.fetchModel(baseModelPath);
if(model != null){ if(model != null){
return true; return true;
} else { } else {
return false; return false;
} }
} }
public void setTextureOverride(String override){ /**
textureOverride = override; * Gets the mesh mask for this actor
} * @return The mesh mask
*/
public ActorMeshMask getMeshMask(){ public ActorMeshMask getMeshMask(){
return meshMask; return meshMask;
} }
@ -802,7 +842,7 @@ public class Actor {
* @param fragmentShader the fragment shader to apply * @param fragmentShader the fragment shader to apply
*/ */
public void maskShader(String mesh, String vertexShader, String fragmentShader){ public void maskShader(String mesh, String vertexShader, String fragmentShader){
shaderMasks.add(new ActorShaderMask(this.modelPath, mesh, vertexShader, fragmentShader)); shaderMasks.add(new ActorShaderMask(this.baseModelPath, mesh, vertexShader, fragmentShader));
} }
/** /**
@ -813,6 +853,10 @@ public class Actor {
throw new UnsupportedOperationException("Not implemented yet"); throw new UnsupportedOperationException("Not implemented yet");
} }
/**
* Adds a texture mask to this actor
* @param textureMask The texture mask
*/
public void addTextureMask(ActorTextureMask textureMask){ public void addTextureMask(ActorTextureMask textureMask){
if(textureMap == null){ if(textureMap == null){
textureMap = new HashMap<String,ActorTextureMask>(); textureMap = new HashMap<String,ActorTextureMask>();
@ -821,10 +865,20 @@ public class Actor {
} }
/**
* Adds a rotator to a bone on this actor
* @param bone The name of the bone
* @param rotator The rotator
*/
public void addBoneRotator(String bone, ActorBoneRotator rotator){ public void addBoneRotator(String bone, ActorBoneRotator rotator){
boneRotators.put(bone, rotator); boneRotators.put(bone, rotator);
} }
/**
* Gets the rotator to apply to a bone
* @param bone The name of the bone
* @return The rotator to apply to that bone if it exists, null otherwise
*/
public ActorBoneRotator getBoneRotator(String bone){ public ActorBoneRotator getBoneRotator(String bone){
return boneRotators.get(bone); return boneRotators.get(bone);
} }
@ -839,20 +893,34 @@ public class Actor {
this.uniformMap.setUniform(meshName, uniformName, value); this.uniformMap.setUniform(meshName, uniformName, value);
} }
/**
* Sets the static morph for this actor
* @param staticMorph The static morph
*/
public void setActorStaticMorph(ActorStaticMorph staticMorph){ public void setActorStaticMorph(ActorStaticMorph staticMorph){
this.staticMorph = staticMorph; this.staticMorph = staticMorph;
} }
/**
* Gets the static morph for this actor
* @return The static morph for this actor
*/
public ActorStaticMorph getStaticMorph(){ public ActorStaticMorph getStaticMorph(){
return this.staticMorph; return this.staticMorph;
} }
//set should frustum cull /**
* Sets whether this actor should frustum cull or not
* @param frustumCull true to frustum cull, false to skip frustum culling
*/
public void setFrustumCull(boolean frustumCull){ public void setFrustumCull(boolean frustumCull){
this.frustumCull = frustumCull; this.frustumCull = frustumCull;
} }
//get should frustum cull /**
* Gets whether this actor should frustum cull or not
* @return true to frustum cull, false otherwise
*/
public boolean getFrustumCull(){ public boolean getFrustumCull(){
return frustumCull; return frustumCull;
} }
@ -943,16 +1011,16 @@ public class Actor {
* Gets the path to the low res model * Gets the path to the low res model
* @return Path to the low res model * @return Path to the low res model
*/ */
public String getLowResPath() { public String getLowResBaseModelPath() {
return lowResPath; return lowResBaseModelPath;
} }
/** /**
* Sets the path to the low res model * Sets the path to the low res model
* @param lowResPath The path to the low res model * @param lowResPath The path to the low res model
*/ */
public void setLowResPath(String lowResPath) { public void setLowResBaseModelPath(String lowResPath) {
this.lowResPath = lowResPath; this.lowResBaseModelPath = lowResPath;
} }
/** /**

View File

@ -8,8 +8,15 @@ import org.joml.Quaternionf;
*/ */
public class ActorBoneRotator { public class ActorBoneRotator {
/**
* The rotation to apply
*/
Quaternionf rotation = new Quaternionf().identity(); Quaternionf rotation = new Quaternionf().identity();
/**
* Gets the rotation to apply
* @return The rotation to apply
*/
public Quaternionf getRotation(){ public Quaternionf getRotation(){
return rotation; return rotation;
} }

View File

@ -29,17 +29,12 @@ public class ActorUtils {
Actor rVal = new Actor(modelPath); Actor rVal = new Actor(modelPath);
return rVal; return rVal;
} }
@Deprecated
public static void applyBlenderTransformer(Entity actorEntity){
// Actor entityActor = EntityUtils.getActor(actorEntity);
// entityActor.setAnimationScalar(60f); //should be the value of the fps i think
}
public static void applyBlenderRotation(Entity actorEntity){
EntityUtils.getRotation(actorEntity).rotateLocalX((float)-Math.PI/2);
}
/**
* Gets the static morph of the actor on the entity
* @param actorEntity The entity
* @return The static morph if it exists, null otherwise
*/
public static ActorStaticMorph getStaticMorph(Entity actorEntity){ public static ActorStaticMorph getStaticMorph(Entity actorEntity){
Actor entityActor = EntityUtils.getActor(actorEntity); Actor entityActor = EntityUtils.getActor(actorEntity);
return entityActor.getStaticMorph(); return entityActor.getStaticMorph();
@ -51,7 +46,7 @@ public class ActorUtils {
*/ */
public static void queueActorForDeletion(Entity actorEntity){ public static void queueActorForDeletion(Entity actorEntity){
Actor actor = EntityUtils.getActor(actorEntity); Actor actor = EntityUtils.getActor(actorEntity);
Globals.assetManager.queueModelForDeletion(actor.getModelPath()); Globals.assetManager.queueModelForDeletion(actor.getBaseModelPath());
} }
} }

View File

@ -11,8 +11,8 @@ import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
import electrosphere.renderer.OpenGLState; import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderPipelineState; import electrosphere.renderer.RenderPipelineState;
import electrosphere.renderer.actor.ActorUniformMap; import electrosphere.renderer.actor.mask.ActorUniformMap;
import electrosphere.renderer.actor.ActorUniformMap.UniformValue; import electrosphere.renderer.actor.mask.ActorUniformMap.UniformValue;
import electrosphere.renderer.model.Material; import electrosphere.renderer.model.Material;
import electrosphere.renderer.model.Model; import electrosphere.renderer.model.Model;
import electrosphere.renderer.shader.VisualShader; import electrosphere.renderer.shader.VisualShader;

View File

@ -8,25 +8,35 @@ import java.util.List;
*/ */
public class ActorAnimationMask implements Comparable<ActorAnimationMask> { public class ActorAnimationMask implements Comparable<ActorAnimationMask> {
//The priority of the mask /**
int priority; * The priority of the mask
*/
private int priority;
//The name of the animation /**
String animationName; * The name of the animation
*/
private String animationName;
//The current time of this mask /**
double time; * The current time of this mask
*/
private double time;
//The maximum time to play this mask for /**
double timeMax; * The maximum time to play this mask for
*/
private double timeMax;
//The mask of bones to apply this animation to /**
List<String> boneMask; * The mask of bones to apply this animation to
*/
private List<String> boneMask;
/** /**
* The number of frames to freeze this animation mask for * The number of frames to freeze this animation mask for
*/ */
int freezeFrames = 0; private int freezeFrames = 0;
/** /**
* Constructor * Constructor

View File

@ -19,30 +19,51 @@ public class ActorMeshMask {
//The map of base mesh name -> blocked status /**
//Ie "feet" -> true would mean that the base model feet should not be drawn * The map of base mesh name -> blocked status
Map<String,Boolean> meshBlockerList = new HashMap<String,Boolean>(); * <p>
//the list of meshes to draw that are stored in this object * Ie "feet" -> true would mean that the base model feet should not be drawn
//ie this would contain a mesh for boots */
Map<String,Mesh> toDrawMesh = new HashMap<String,Mesh>(); private Map<String,Boolean> meshBlockerList = new HashMap<String,Boolean>();
//lock for queueing blockers /**
Semaphore queueLock = new Semaphore(1); * the list of meshes to draw that are stored in this object
List<MeshDrawQueueItem> queuedMeshes = new LinkedList<MeshDrawQueueItem>(); * <p>
List<MeshDrawQueueItem> queuedBlockers = new LinkedList<MeshDrawQueueItem>(); * ie this would contain a mesh for boots
*/
private Map<String,Mesh> toDrawMesh = new HashMap<String,Mesh>();
/**
* lock for queueing blockers
*/
private Semaphore queueLock = new Semaphore(1);
/**
* The set of queued meshes
*/
private List<MeshDrawQueueItem> queuedMeshes = new LinkedList<MeshDrawQueueItem>();
/**
* The set of queued blockers
*/
private List<MeshDrawQueueItem> queuedBlockers = new LinkedList<MeshDrawQueueItem>();
public ActorMeshMask(){ /**
* Quques a mesh
} * @param modelName The model's name
* @param meshName The mesh's name
*/
public void queueMesh(String modelName, String meshName){ public void queueMesh(String modelName, String meshName){
queueLock.acquireUninterruptibly(); queueLock.acquireUninterruptibly();
queuedMeshes.add(new MeshDrawQueueItem(modelName, meshName)); queuedMeshes.add(new MeshDrawQueueItem(modelName, meshName));
queueLock.release(); queueLock.release();
} }
/**
* Processes all items in the mesh mask queue
*/
public void processMeshMaskQueue(){ public void processMeshMaskQueue(){
Model model; Model model;
Mesh mesh; Mesh mesh;
@ -79,14 +100,26 @@ public class ActorMeshMask {
} }
} }
/**
* Gets the list of meshes to draw
* @return The list of meshes to draw
*/
public List<Mesh> getToDrawMeshes(){ public List<Mesh> getToDrawMeshes(){
return toDrawMesh.values().stream().collect(Collectors.toList()); return toDrawMesh.values().stream().collect(Collectors.toList());
} }
/**
* Ejects a mesh to draw
* @param name The mesh's name
*/
public void ejectMeshToDraw(String name){ public void ejectMeshToDraw(String name){
toDrawMesh.remove(name); toDrawMesh.remove(name);
} }
/**
* Checks if the mesh mask is empty
* @return true if it is empty, false otherwise
*/
public boolean isEmpty(){ public boolean isEmpty(){
return toDrawMesh.size() > 0; return toDrawMesh.size() > 0;
} }
@ -103,24 +136,48 @@ public class ActorMeshMask {
// //
//blocking interactions //blocking interactions
// //
/**
* Checks if this mesh mask contains a mesh by a given name which it should draw
* @param name The name of the mesh
* @return true if it should draw, false otherwise
*/
public boolean containsMeshToDraw(String name){ public boolean containsMeshToDraw(String name){
return toDrawMesh.containsKey(name); return toDrawMesh.containsKey(name);
} }
/**
* Blocks a mesh from rendering
* @param modelName The name of the model
* @param meshName The name of the mesh
*/
public void blockMesh(String modelName, String meshName){ public void blockMesh(String modelName, String meshName){
queueLock.acquireUninterruptibly(); queueLock.acquireUninterruptibly();
queuedBlockers.add(new MeshDrawQueueItem(modelName, meshName)); queuedBlockers.add(new MeshDrawQueueItem(modelName, meshName));
queueLock.release(); queueLock.release();
} }
/**
* Checks if a mesh is blocked from rendering
* @param name The name of the mesh
* @return true if it is blocked, false otherwise
*/
public boolean isBlockedMesh(String name){ public boolean isBlockedMesh(String name){
return meshBlockerList.containsKey(name); return meshBlockerList.containsKey(name);
} }
/**
* Unblocks a mesh from rendering
* @param name The name of the mesh
*/
public void unblockMesh(String name){ public void unblockMesh(String name){
meshBlockerList.remove(name); meshBlockerList.remove(name);
} }
/**
* Gets the list of all meshes that are blocked
* @return The list of all meshes that are blocked
*/
public List<String> getBlockedMeshes(){ public List<String> getBlockedMeshes(){
return meshBlockerList.keySet().stream().collect(Collectors.toList()); return meshBlockerList.keySet().stream().collect(Collectors.toList());
} }
@ -132,21 +189,41 @@ public class ActorMeshMask {
* When a creature equips an item that would block a mesh, the mesh may not have already been loaded into memory. * When a creature equips an item that would block a mesh, the mesh may not have already been loaded into memory.
* This represents an item in a queue that contains a mesh that should be eventually used to block a mesh on the parent actor. * This represents an item in a queue that contains a mesh that should be eventually used to block a mesh on the parent actor.
*/ */
class MeshDrawQueueItem { private class MeshDrawQueueItem {
String modelName; /**
String meshName; * The name of the model
*/
private String modelName;
MeshDrawQueueItem(String modelName, String meshName){ /**
* The name of the mesh
*/
private String meshName;
/**
* Constructor
* @param modelName Model name
* @param meshName Mesh name
*/
protected MeshDrawQueueItem(String modelName, String meshName){
this.modelName = modelName; this.modelName = modelName;
this.meshName = meshName; this.meshName = meshName;
} }
/**
* Gets the name of the model
* @return The name of the model
*/
public String getModelName(){ public String getModelName(){
return modelName; return modelName;
} }
/**
* Gets the name of the mesh
* @return The name of the mesh
*/
public String getMeshName(){ public String getMeshName(){
return meshName; return meshName;
} }

View File

@ -5,14 +5,25 @@ package electrosphere.renderer.actor.mask;
*/ */
public class ActorShaderMask { public class ActorShaderMask {
//the model name /**
String modelName; * The name of the model
//the mesh name */
String meshName; private String modelName;
//the vertex shader
String vertexShaderPath; /**
//the fragment shader * The name of the mesh to apply the shader to
String fragmentShaderPath; */
private String meshName;
/**
* The vertex shader's path
*/
private String vertexShaderPath;
/**
* The fragment shader's path
*/
private String fragmentShaderPath;
/** /**
* Constructor * Constructor

View File

@ -12,22 +12,22 @@ public class ActorTextureMask {
/** /**
* The mesh this mask is overwriting * The mesh this mask is overwriting
*/ */
String meshName; private String meshName;
/** /**
* The texture objects used for this mask * The texture objects used for this mask
*/ */
List<Texture> textures; private List<Texture> textures;
/** /**
* The paths to textures to be used for this mask * The paths to textures to be used for this mask
*/ */
List<String> texturePaths; private List<String> texturePaths;
/** /**
* The uniform names used for this mask * The uniform names used for this mask
*/ */
List<String> uniformNames; private List<String> uniformNames;
/** /**
* Constructor * Constructor

View File

@ -1,4 +1,4 @@
package electrosphere.renderer.actor; package electrosphere.renderer.actor.mask;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;

View File

@ -85,6 +85,7 @@ public class Model {
* The root animation node * The root animation node
*/ */
private AnimNode rootAnimNode; private AnimNode rootAnimNode;
/** /**
* The map of animation node name -> node * The map of animation node name -> node
*/ */
@ -100,7 +101,6 @@ public class Model {
*/ */
private Map<String,Animation> animMap = new HashMap<String,Animation>(); private Map<String,Animation> animMap = new HashMap<String,Animation>();
/** /**
* A mask that overwrites meshes themsselves * A mask that overwrites meshes themsselves
*/ */

View File

@ -80,7 +80,7 @@ public class DrawTargetEvaluator {
double dist = posVec.distance(cameraCenter); double dist = posVec.distance(cameraCenter);
//evaluate LOD level //evaluate LOD level
if(currentActor.getLowResPath() != null){ if(currentActor.getLowResBaseModelPath() != null){
if(dist < LOD_LOWER_CUTOFF){ if(dist < LOD_LOWER_CUTOFF){
currentActor.setLodLevel(Actor.LOD_LEVEL_FULL); currentActor.setLodLevel(Actor.LOD_LEVEL_FULL);
} else if(dist < LOD_STATIC_CUTOFF) { } else if(dist < LOD_STATIC_CUTOFF) {
@ -104,13 +104,13 @@ public class DrawTargetEvaluator {
if(currentActor.frustumTest(Globals.renderingEngine.getRenderPipelineState(), modelTransformMatrix.getTranslation(posVec))){ if(currentActor.frustumTest(Globals.renderingEngine.getRenderPipelineState(), modelTransformMatrix.getTranslation(posVec))){
//queue for batching //queue for batching
if(MainContentPipeline.shouldDrawSolidPass(currentEntity)){ if(MainContentPipeline.shouldDrawSolidPass(currentEntity)){
mainAccumulator.addCall(currentActor.getModelPath(), position, modelTransformMatrix); mainAccumulator.addCall(currentActor.getBaseModelPath(), position, modelTransformMatrix);
} }
if(dist < ShadowMapPipeline.DRAW_CUTOFF_DIST && shadowList.contains(currentEntity)){ if(dist < ShadowMapPipeline.DRAW_CUTOFF_DIST && shadowList.contains(currentEntity)){
shadowAccumulator.addCall(currentActor.getModelPath(), position, modelTransformMatrix); shadowAccumulator.addCall(currentActor.getBaseModelPath(), position, modelTransformMatrix);
} }
if(dist < NormalsForOutlinePipeline.DRAW_CUTOFF_DIST && NormalsForOutlinePipeline.shouldDraw(currentEntity)){ if(dist < NormalsForOutlinePipeline.DRAW_CUTOFF_DIST && NormalsForOutlinePipeline.shouldDraw(currentEntity)){
normalAccumulator.addCall(currentActor.getModelPath(), position, modelTransformMatrix); normalAccumulator.addCall(currentActor.getBaseModelPath(), position, modelTransformMatrix);
} }
} }
} else if(TerrainChunk.isBlockEntity(currentEntity)){ } else if(TerrainChunk.isBlockEntity(currentEntity)){

View File

@ -224,7 +224,7 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme
GL40.glClear(GL40.GL_COLOR_BUFFER_BIT | GL40.GL_DEPTH_BUFFER_BIT); GL40.glClear(GL40.GL_COLOR_BUFFER_BIT | GL40.GL_DEPTH_BUFFER_BIT);
Model actorModel = Globals.assetManager.fetchModel(actor.getModelPath()); Model actorModel = Globals.assetManager.fetchModel(actor.getBaseModelPath());
if(currentAnim != null){ if(currentAnim != null){
if((!actor.isPlayingAnimation() || !actor.isPlayingAnimation(currentAnim)) && if((!actor.isPlayingAnimation() || !actor.isPlayingAnimation(currentAnim)) &&
actorModel != null && actorModel != null &&