bone debug rendering
This commit is contained in:
parent
41a145a5bd
commit
abfafe13b9
@ -1,3 +1,3 @@
|
||||
#maven.buildNumber.plugin properties file
|
||||
#Thu Aug 01 17:36:27 EDT 2024
|
||||
buildNumber=198
|
||||
#Thu Aug 01 18:31:38 EDT 2024
|
||||
buildNumber=199
|
||||
|
||||
@ -15,5 +15,8 @@ Things that feel bad:
|
||||
First person blocking angle doesn't line up
|
||||
Can't instantly start/stop blocking
|
||||
Attack animation feels slow
|
||||
Hands don't align with blade
|
||||
Need to be able to visualize bones
|
||||
No audio
|
||||
Short movement bursts feel jittery
|
||||
Part of this may be cylinder collidable instead of capsule
|
||||
|
||||
@ -178,6 +178,11 @@ public class ImGuiEntityMacros {
|
||||
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")){
|
||||
|
||||
@ -27,6 +27,15 @@ public class OpenGLState {
|
||||
//the current depth function
|
||||
int depthFunction = -1;
|
||||
|
||||
//whether to blend or nit
|
||||
boolean blendTest = false;
|
||||
|
||||
//the current blend func
|
||||
//map is (texture unit) -> [sfactor,dfactor]
|
||||
Map<Integer,int[]> blendFuncMap = new HashMap<Integer,int[]>();
|
||||
//the key that contains the value of glBlendFunc (which would affect all buffers)
|
||||
static final int ALL_BUFFERS_KEY = -1;
|
||||
|
||||
//the currently bound texture
|
||||
int boundTexturePointer = 0;
|
||||
int boundTextureType = 0;
|
||||
@ -204,4 +213,59 @@ public class OpenGLState {
|
||||
return MAX_TEXTURE_WIDTH;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param sfactor
|
||||
* @param dfactor
|
||||
*/
|
||||
public void glBlendFunc(int sfactor, int dfactor){
|
||||
GL40.glBlendFunc(sfactor, dfactor);
|
||||
//set all other keys
|
||||
for(int keyCurrent : this.blendFuncMap.keySet()){
|
||||
if(keyCurrent != ALL_BUFFERS_KEY){
|
||||
int[] funcs = this.blendFuncMap.get(keyCurrent);
|
||||
funcs[0] = sfactor;
|
||||
funcs[1] = dfactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the blend function for opengl
|
||||
* @param drawBufferIndex The draw buffer index that will have this function set
|
||||
* @param sfactor The source factor
|
||||
* @param dfactor The destination factor
|
||||
*/
|
||||
public void glBlendFunci(int drawBufferIndex, int sfactor, int dfactor){
|
||||
if(this.blendFuncMap.containsKey(drawBufferIndex)){
|
||||
int[] funcs = this.blendFuncMap.get(drawBufferIndex);
|
||||
int sFactorCurr = funcs[0];
|
||||
int dFactorCurr = funcs[1];
|
||||
if(sfactor != sFactorCurr || dfactor != dFactorCurr){
|
||||
funcs[0] = sfactor;
|
||||
funcs[1] = dfactor;
|
||||
this.blendFuncMap.put(drawBufferIndex,funcs);
|
||||
GL40.glBlendFunci(drawBufferIndex, sfactor, dfactor);
|
||||
}
|
||||
} else {
|
||||
int[] funcs = new int[]{
|
||||
sfactor, dfactor
|
||||
};
|
||||
this.blendFuncMap.put(drawBufferIndex,funcs);
|
||||
GL40.glBlendFunci(drawBufferIndex, sfactor, dfactor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void glBlend(boolean blend){
|
||||
// if(this.blendTest != blend){
|
||||
this.blendTest = blend;
|
||||
if(this.blendTest){
|
||||
GL40.glEnable(GL40.GL_BLEND);
|
||||
} else {
|
||||
GL40.glDisable(GL40.GL_BLEND);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -89,7 +89,6 @@ import electrosphere.renderer.framebuffer.Renderbuffer;
|
||||
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.ImGuiPipeline;
|
||||
import electrosphere.renderer.pipelines.MainContentNoOITPipeline;
|
||||
@ -100,6 +99,7 @@ import electrosphere.renderer.pipelines.RenderScreenPipeline;
|
||||
import electrosphere.renderer.pipelines.ShadowMapPipeline;
|
||||
import electrosphere.renderer.pipelines.UIPipeline;
|
||||
import electrosphere.renderer.pipelines.VolumeBufferPipeline;
|
||||
import electrosphere.renderer.pipelines.debug.DebugContentPipeline;
|
||||
import electrosphere.renderer.shader.ShaderProgram;
|
||||
import electrosphere.renderer.texture.Texture;
|
||||
|
||||
@ -303,8 +303,8 @@ public class RenderingEngine {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// Support for transparency
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
openGLState.glBlend(true);
|
||||
openGLState.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
//this disables vsync to make game run faster
|
||||
//https://stackoverflow.com/questions/55598376/glfwswapbuffers-is-slow
|
||||
@ -597,6 +597,14 @@ public class RenderingEngine {
|
||||
return this.imGuiPipeline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the debug content pipeline
|
||||
* @return The debug content pipeline
|
||||
*/
|
||||
public DebugContentPipeline getDebugContentPipeline(){
|
||||
return this.debugContentPipeline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current render pipeline state
|
||||
* @return The current render pipeline state
|
||||
|
||||
@ -402,7 +402,7 @@ public class Actor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the position of a bone
|
||||
* Gets the position of a bone in local space
|
||||
* @param boneName The name of the bone
|
||||
* @return The vector3f containing the position of the bone, or a vector of (0,0,0) if the model lookup fails
|
||||
* //TODO: refactor to make failure more transparent (both for model not existing and bone not existing)
|
||||
@ -431,6 +431,11 @@ public class Actor {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rotation of a bone in local space
|
||||
* @param boneName The name of the bone
|
||||
* @return The Quaterniond containing the rotation of the bone, or an identity Quaterniond if the lookup fails
|
||||
*/
|
||||
public Quaterniond getBoneRotation(String boneName){
|
||||
Quaterniond rVal = new Quaterniond();
|
||||
Model model = Globals.assetManager.fetchModel(modelPath);
|
||||
|
||||
@ -1,8 +1,13 @@
|
||||
package electrosphere.renderer.actor;
|
||||
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.util.MathUtils;
|
||||
|
||||
/**
|
||||
* Utils for dealing with actors
|
||||
@ -39,6 +44,46 @@ public class ActorUtils {
|
||||
Actor entityActor = EntityUtils.getActor(actorEntity);
|
||||
return entityActor.getStaticMorph();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the world position of a bone
|
||||
* @param actorEntity The entity that has a bone
|
||||
* @param boneName The name of the bone
|
||||
*/
|
||||
public static Vector3d getBoneWorldPosition(Entity actorEntity, String boneName){
|
||||
Actor actor = EntityUtils.getActor(actorEntity);
|
||||
Vector3d localPos = new Vector3d(actor.getBonePosition(boneName));
|
||||
|
||||
//transform bone space
|
||||
Vector3d position = new Vector3d(localPos);
|
||||
position = position.mul(EntityUtils.getScale(actorEntity));
|
||||
position = position.rotate(new Quaterniond(EntityUtils.getRotation(actorEntity)));
|
||||
//transform worldspace
|
||||
position.add(new Vector3d(EntityUtils.getPosition(actorEntity)));
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the global rotation of the bone
|
||||
* @param actorEntity The entity with the bone
|
||||
* @param boneName The name of the bone
|
||||
* @return The global rotation of the bone
|
||||
*/
|
||||
public static Quaterniond getBoneWorldRotation(Entity actorEntity, String boneName){
|
||||
Actor actor = EntityUtils.getActor(actorEntity);
|
||||
Quaterniond localRot = actor.getBoneRotation(boneName);
|
||||
|
||||
Vector3d facingAngle = CreatureUtils.getFacingVector(actorEntity);
|
||||
if(facingAngle == null){
|
||||
facingAngle = MathUtils.getOriginVector();
|
||||
}
|
||||
//calculate rotation of model
|
||||
return new Quaterniond()
|
||||
.rotationTo(MathUtils.getOriginVector(), new Vector3d(facingAngle.x,facingAngle.y,facingAngle.z))
|
||||
.mul(localRot)
|
||||
.normalize();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -17,8 +17,8 @@ public class CompositePipeline implements RenderPipeline {
|
||||
//
|
||||
openGLState.glDepthFunc(GL40.GL_ALWAYS);
|
||||
// glDepthMask(false);
|
||||
GL40.glEnable(GL40.GL_BLEND);
|
||||
GL40.glBlendFunc(GL40.GL_SRC_ALPHA, GL40.GL_ONE_MINUS_SRC_ALPHA);
|
||||
openGLState.glBlend(true);
|
||||
openGLState.glBlendFunc(GL40.GL_SRC_ALPHA, GL40.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
RenderingEngine.screenFramebuffer.bind(openGLState);
|
||||
|
||||
|
||||
@ -30,7 +30,9 @@ public class FirstPersonItemsPipeline implements RenderPipeline {
|
||||
|
||||
if(Globals.firstPersonEntity != null && !Globals.controlHandler.cameraIsThirdPerson()){
|
||||
//update logic
|
||||
updateFirstPersonModelPosition(Globals.firstPersonEntity);
|
||||
if(Globals.cameraHandler.getTrackPlayerEntity()){
|
||||
updateFirstPersonModelPosition(Globals.firstPersonEntity);
|
||||
}
|
||||
|
||||
//setup opengl state
|
||||
renderPipelineState.setUseBones(true);
|
||||
|
||||
@ -31,7 +31,9 @@ public class MainContentNoOITPipeline implements RenderPipeline {
|
||||
GL40.glDepthMask(true);
|
||||
openGLState.glViewport(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
|
||||
|
||||
GL40.glEnable(GL40.GL_BLEND);
|
||||
openGLState.glBlend(true);
|
||||
openGLState.glBlendFunci(0, GL40.GL_ONE, GL40.GL_ONE);
|
||||
openGLState.glBlendFunci(1, GL40.GL_ZERO, GL40.GL_ONE_MINUS_SRC_COLOR);
|
||||
GL40.glBlendFunci(0, GL40.GL_ONE, GL40.GL_ONE);
|
||||
GL40.glBlendFunci(1, GL40.GL_ZERO, GL40.GL_ONE_MINUS_SRC_COLOR);
|
||||
GL40.glBlendEquation(GL40.GL_FUNC_ADD);
|
||||
|
||||
@ -125,7 +125,7 @@ public class MainContentPipeline implements RenderPipeline {
|
||||
//
|
||||
// glDisable(GL_DEPTH_TEST);
|
||||
GL40.glDepthMask(false);
|
||||
GL40.glEnable(GL40.GL_BLEND);
|
||||
openGLState.glBlend(true);
|
||||
GL40.glBlendFunci(0, GL40.GL_ONE, GL40.GL_ONE);
|
||||
GL40.glBlendFunci(1, GL40.GL_ZERO, GL40.GL_ONE_MINUS_SRC_COLOR);
|
||||
GL40.glBlendEquation(GL40.GL_FUNC_ADD);
|
||||
|
||||
@ -30,8 +30,8 @@ public class NormalsForOutlinePipeline implements RenderPipeline {
|
||||
//bind screen fbo
|
||||
RenderingEngine.gameImageNormalsFramebuffer.bind(openGLState);
|
||||
openGLState.glDepthTest(true);
|
||||
GL40.glDisable(GL40.GL_BLEND);
|
||||
GL40.glBlendFunc(GL40.GL_SRC_ALPHA, GL40.GL_ONE_MINUS_SRC_ALPHA);
|
||||
openGLState.glBlend(false);
|
||||
openGLState.glBlendFunc(GL40.GL_SRC_ALPHA, GL40.GL_ONE_MINUS_SRC_ALPHA);
|
||||
openGLState.glDepthFunc(GL40.GL_LESS);
|
||||
GL40.glDepthMask(true);
|
||||
|
||||
|
||||
@ -69,6 +69,7 @@ public class UIPipeline implements RenderPipeline {
|
||||
|
||||
//set opengl state
|
||||
openGLState.glDepthTest(false);
|
||||
openGLState.glBlend(true);
|
||||
|
||||
for(Element currentElement : Globals.elementManager.getWindowList()){
|
||||
if(currentElement instanceof DrawableElement){
|
||||
|
||||
@ -0,0 +1,102 @@
|
||||
package electrosphere.renderer.pipelines.debug;
|
||||
|
||||
import org.joml.Matrix4d;
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.lwjgl.opengl.GL40;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.types.camera.CameraEntityUtils;
|
||||
import electrosphere.renderer.OpenGLState;
|
||||
import electrosphere.renderer.RenderPipelineState;
|
||||
import electrosphere.renderer.RenderingEngine;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
import electrosphere.renderer.actor.ActorUtils;
|
||||
import electrosphere.renderer.model.Bone;
|
||||
import electrosphere.renderer.model.Model;
|
||||
import electrosphere.renderer.pipelines.RenderPipeline;
|
||||
|
||||
/**
|
||||
* Renders the bones for a given mesh
|
||||
*/
|
||||
public class DebugBonesPipeline implements RenderPipeline {
|
||||
|
||||
//The scale vector
|
||||
static final Vector3d scale = new Vector3d(1);
|
||||
|
||||
/**
|
||||
* The entity to render bones for
|
||||
*/
|
||||
Entity targetEntity;
|
||||
|
||||
@Override
|
||||
public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) {
|
||||
Globals.profiler.beginCpuSample("DebugBonesPipeline.render");
|
||||
|
||||
if(targetEntity != null){
|
||||
//bind screen fbo
|
||||
RenderingEngine.screenFramebuffer.bind(openGLState);
|
||||
openGLState.glDepthTest(true);
|
||||
openGLState.glDepthFunc(GL40.GL_LESS);
|
||||
GL40.glDepthMask(true);
|
||||
openGLState.glBlend(false);
|
||||
openGLState.glViewport(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
|
||||
|
||||
///
|
||||
/// R E N D E R I N G S T U F F
|
||||
///
|
||||
//Sets the background color.
|
||||
|
||||
|
||||
//
|
||||
// Set render pipeline state
|
||||
//
|
||||
renderPipelineState.setUseMeshShader(false);
|
||||
renderPipelineState.setBufferStandardUniforms(true);
|
||||
renderPipelineState.setBufferNonStandardUniforms(false);
|
||||
renderPipelineState.setUseMaterial(true);
|
||||
renderPipelineState.setUseShadowMap(true);
|
||||
renderPipelineState.setUseBones(true);
|
||||
renderPipelineState.setUseLight(true);
|
||||
|
||||
Matrix4d modelTransformMatrix = new Matrix4d();
|
||||
|
||||
//
|
||||
//Get target data
|
||||
//
|
||||
Actor targetActor = EntityUtils.getActor(targetEntity);
|
||||
Model boneModel = Globals.assetManager.fetchModel("Models/basic/geometry/unitcylinder.fbx");
|
||||
boneModel.getMaterials().get(0).set_diffuse(Globals.textureDiffuseDefault);
|
||||
for(Bone bone : targetActor.getBoneValues()){
|
||||
Vector3d bonePos = ActorUtils.getBoneWorldPosition(targetEntity, bone.boneID);
|
||||
Quaterniond boneRot = ActorUtils.getBoneWorldRotation(targetEntity, bone.boneID);
|
||||
|
||||
//put pos + rot into model
|
||||
Vector3f cameraModifiedPosition = new Vector3f((float)bonePos.x,(float)bonePos.y,(float)bonePos.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
|
||||
modelTransformMatrix.identity();
|
||||
modelTransformMatrix.translate(cameraModifiedPosition);
|
||||
modelTransformMatrix.rotate(boneRot);
|
||||
modelTransformMatrix.scale(scale);
|
||||
boneModel.setModelMatrix(modelTransformMatrix);
|
||||
|
||||
//draw
|
||||
boneModel.draw(renderPipelineState,openGLState);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Globals.profiler.endCpuSample();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entity that should be drawn in this pipeline
|
||||
* @param entity The entity to draw bones for
|
||||
*/
|
||||
public void setEntity(Entity entity){
|
||||
this.targetEntity = entity;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package electrosphere.renderer.pipelines;
|
||||
package electrosphere.renderer.pipelines.debug;
|
||||
|
||||
import org.joml.Matrix4d;
|
||||
import org.joml.Quaterniond;
|
||||
@ -25,6 +25,7 @@ import electrosphere.renderer.OpenGLState;
|
||||
import electrosphere.renderer.RenderPipelineState;
|
||||
import electrosphere.renderer.RenderingEngine;
|
||||
import electrosphere.renderer.model.Model;
|
||||
import electrosphere.renderer.pipelines.RenderPipeline;
|
||||
import electrosphere.renderer.texture.Texture;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
import electrosphere.server.datacell.utils.EntityLookupUtils;
|
||||
@ -37,6 +38,9 @@ import electrosphere.server.pathfinding.navmesh.NavShape;
|
||||
*/
|
||||
public class DebugContentPipeline implements RenderPipeline {
|
||||
|
||||
//The bone debugging pipeline
|
||||
DebugBonesPipeline debugBonesPipeline = new DebugBonesPipeline();
|
||||
|
||||
@Override
|
||||
public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) {
|
||||
Globals.profiler.beginCpuSample("DebugContentPipeline.render");
|
||||
@ -326,6 +330,8 @@ public class DebugContentPipeline implements RenderPipeline {
|
||||
}
|
||||
}
|
||||
|
||||
debugBonesPipeline.render(openGLState, renderPipelineState);
|
||||
|
||||
Globals.profiler.endCpuSample();
|
||||
}
|
||||
|
||||
@ -366,5 +372,13 @@ public class DebugContentPipeline implements RenderPipeline {
|
||||
}
|
||||
return "Textures/transparent_grey.png";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bone debugging pipeline
|
||||
* @return The bone debugging pipeline
|
||||
*/
|
||||
public DebugBonesPipeline getDebugBonesPipeline(){
|
||||
return this.debugBonesPipeline;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user