character creation menu work
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2024-11-29 19:05:14 -05:00
parent 86fbaa8aa4
commit 9c672af15f
14 changed files with 390 additions and 95 deletions

View File

@ -1179,6 +1179,10 @@ Nearest biome sampling for content generation
Fix recursive delete not actually recursing Fix recursive delete not actually recursing
Add floor voxel type Add floor voxel type
Singleplayer menu layout work Singleplayer menu layout work
Remove explicit garbage collection call
Actor panel additional functionality
Better style for character creation menu
Fix AABB calculation from assimp-loaded models
# TODO # TODO
@ -1215,6 +1219,7 @@ Bug Fixes
- Fix virtual scrollables not working - Fix virtual scrollables not working
- Fix foliage flickering on edit - Fix foliage flickering on edit
- Fix single blades of grass generating in bad locations - Fix single blades of grass generating in bad locations
- Fix falling tree not stopping when hitting static collidables
Startup Performance Startup Performance
- Allow texture map to bind multiple model paths to a single set of mesh->textures - Allow texture map to bind multiple model paths to a single set of mesh->textures

View File

@ -216,6 +216,11 @@ public class CameraEntityUtils {
} }
} }
/**
* Gets the camera view matrix for a given camera entity
* @param camera The camera
* @return The view matrix for the camera
*/
public static Matrix4f getCameraViewMatrix(Entity camera){ public static Matrix4f getCameraViewMatrix(Entity camera){
Vector3f cameraCenter = new Vector3f(0,0,0);//getViewMatrixCenterOffset(camera); Vector3f cameraCenter = new Vector3f(0,0,0);//getViewMatrixCenterOffset(camera);
Vector3f cameraEye = new Vector3f(cameraCenter).add(getCameraEye(camera)); Vector3f cameraEye = new Vector3f(cameraCenter).add(getCameraEye(camera));

View File

@ -4,6 +4,7 @@ import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.Vector4d;
import electrosphere.client.entity.camera.CameraEntityUtils; import electrosphere.client.entity.camera.CameraEntityUtils;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
@ -15,6 +16,7 @@ import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.renderer.actor.Actor; import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.actor.ActorStaticMorph; import electrosphere.renderer.actor.ActorStaticMorph;
import electrosphere.renderer.actor.ActorUtils; import electrosphere.renderer.actor.ActorUtils;
import electrosphere.renderer.light.DirectionalLight;
import electrosphere.renderer.ui.elements.ActorPanel; import electrosphere.renderer.ui.elements.ActorPanel;
import electrosphere.renderer.ui.elements.Button; import electrosphere.renderer.ui.elements.Button;
import electrosphere.renderer.ui.elements.Div; import electrosphere.renderer.ui.elements.Div;
@ -40,6 +42,16 @@ public class CharacterCustomizer {
* Minimum height of the component * Minimum height of the component
*/ */
public static final int MIN_HEIGHT = 500; public static final int MIN_HEIGHT = 500;
/**
* The direction of the light in the actor panel
*/
static final Vector3f LIGHT_DIRECTION = new Vector3f(-0.2f,-0.8f,-0.2f).normalize();
/**
* Margin around each control container
*/
static final int CONTROL_CONTAINER_MARGIN = 15;
/** /**
* Creates a character customizer panel * Creates a character customizer panel
@ -58,8 +70,13 @@ public class CharacterCustomizer {
Actor characterActor = ActorUtils.createActorFromModelPath(selectedRaceType.getGraphicsTemplate().getModel().getPath()); Actor characterActor = ActorUtils.createActorFromModelPath(selectedRaceType.getGraphicsTemplate().getModel().getPath());
ActorPanel actorPanel = ActorPanel.create(characterActor); ActorPanel actorPanel = ActorPanel.create(characterActor);
actorPanel.setAnimation(selectedRaceType.getGraphicsTemplate().getModel().getIdleData().getAnimation().getNameThirdPerson()); actorPanel.setAnimation(selectedRaceType.getGraphicsTemplate().getModel().getIdleData().getAnimation().getNameThirdPerson());
actorPanel.setPosition(new Vector3f(0,-0.5f,-0.6f)); actorPanel.setPosition(new Vector3f(0));
actorPanel.setScale(new Vector3f(1.0f)); actorPanel.setScale(new Vector3f(1.0f));
actorPanel.setClearColor(new Vector4d(0));
//Set lighting
DirectionalLight directionalLight = Globals.renderingEngine.getLightManager().getDirectionalLight();
directionalLight.setDirection(LIGHT_DIRECTION);
//have to build static morph while looping through attributes //have to build static morph while looping through attributes
ActorStaticMorph staticMorph = new ActorStaticMorph(); ActorStaticMorph staticMorph = new ActorStaticMorph();
@ -105,7 +122,12 @@ public class CharacterCustomizer {
//add attribute to creature template //add attribute to creature template
template.putAttributeValue(attribute.getAttributeId(), defaultValue); template.putAttributeValue(attribute.getAttributeId(), defaultValue);
scrollable.addChild(Div.createRow(sliderName,boneSlider)); Div controlContainer = Div.createRow(sliderName,boneSlider);
controlContainer.setMarginTop(CONTROL_CONTAINER_MARGIN);
controlContainer.setMarginBottom(CONTROL_CONTAINER_MARGIN);
controlContainer.setMarginLeft(CONTROL_CONTAINER_MARGIN);
controlContainer.setMarginRight(CONTROL_CONTAINER_MARGIN);
scrollable.addChild(controlContainer);
} else if(attribute.getType().equals(VisualAttribute.TYPE_REMESH)){ } else if(attribute.getType().equals(VisualAttribute.TYPE_REMESH)){
//add label for carousel //add label for carousel
Label scrollableName = Label.createLabel(attribute.getAttributeId()); Label scrollableName = Label.createLabel(attribute.getAttributeId());
@ -136,22 +158,35 @@ public class CharacterCustomizer {
//set the current attrib for the template //set the current attrib for the template
template.putAttributeValue(attribute.getAttributeId(), attribute.getVariants().get(0).getId()); template.putAttributeValue(attribute.getAttributeId(), attribute.getVariants().get(0).getId());
scrollable.addChild(Div.createRow(scrollableName,variantCarousel)); Div controlContainer = Div.createRow(scrollableName,variantCarousel);
controlContainer.setMarginTop(CONTROL_CONTAINER_MARGIN);
controlContainer.setMarginBottom(CONTROL_CONTAINER_MARGIN);
controlContainer.setMarginLeft(CONTROL_CONTAINER_MARGIN);
controlContainer.setMarginRight(CONTROL_CONTAINER_MARGIN);
scrollable.addChild(controlContainer);
} }
} }
//finally set static morph //finally set static morph
characterActor.setActorStaticMorph(staticMorph); characterActor.setActorStaticMorph(staticMorph);
//character create button
Div createButtonContainer = Div.createDiv();
createButtonContainer.setMarginTop(CONTROL_CONTAINER_MARGIN);
createButtonContainer.setMarginBottom(CONTROL_CONTAINER_MARGIN);
createButtonContainer.setMarginLeft(CONTROL_CONTAINER_MARGIN);
createButtonContainer.setMarginRight(CONTROL_CONTAINER_MARGIN);
createButtonContainer.addChild(Button.createButton("Create", () -> {
Globals.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestCreateCharacterMessage(Utilities.stringify(template)));
onConfirm.accept(template);
}));
//create layout //create layout
Div rVal = Div.createCol( Div rVal = Div.createCol(
Div.createRow( Div.createRow(
scrollable, scrollable,
actorPanel actorPanel
), ),
Button.createButton("Create", () -> { createButtonContainer
Globals.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestCreateCharacterMessage(Utilities.stringify(template)));
onConfirm.accept(template);
})
); );
return rVal; return rVal;

View File

@ -62,7 +62,7 @@ public class CameraHandler {
} }
} }
updateGlobalCamera(); this.updateGlobalCamera();
} }
/** /**
@ -160,7 +160,7 @@ public class CameraHandler {
Globals.viewMatrix = CameraEntityUtils.getCameraViewMatrix(Globals.playerCamera); Globals.viewMatrix = CameraEntityUtils.getCameraViewMatrix(Globals.playerCamera);
//update the cursor on client side //update the cursor on client side
updatePlayerCursor(); this.updatePlayerCursor();
} }
} }
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
@ -196,6 +196,14 @@ public class CameraHandler {
return yaw; return yaw;
} }
/**
* Sets the yaw of the camera handler
* @param yaw The yaw
*/
public void setYaw(double yaw){
this.yaw = (float)yaw;
}
/** /**
* Gets the pitch of the camera handler * Gets the pitch of the camera handler
* @return the pitch * @return the pitch
@ -204,6 +212,14 @@ public class CameraHandler {
return pitch; return pitch;
} }
/**
* Sets the pitch of the camera handler
* @param pitch The pitch
*/
public void setPitch(double pitch){
this.pitch = (float)pitch;
}
//set player tracking //set player tracking
public void setTrackPlayerEntity(boolean track){ public void setTrackPlayerEntity(boolean track){
trackPlayerEntity = track; trackPlayerEntity = track;

View File

@ -105,7 +105,7 @@ public class ControlCategoryMenuNav {
//scrolling the mouse //scrolling the mouse
menuNavigationControlList.add(controlMap.get(MENU_SCROLL)); menuNavigationControlList.add(controlMap.get(MENU_SCROLL));
controlMap.get(MENU_SCROLL).setOnScroll(new Control.ScrollCallback() {public void execute(MouseState mouseState, ScrollEvent scrollEvent){ controlMap.get(MENU_SCROLL).setOnScroll(new Control.ScrollCallback() {public void execute(MouseState mouseState, ScrollEvent scrollEvent){
Globals.elementService.fireEvent(scrollEvent, GLFW.GLFW_KEY_X, GLFW.GLFW_KEY_Z); Globals.elementService.fireEvent(scrollEvent, (int)scrollEvent.getMouseX(), (int)scrollEvent.getMouseY());
}}); }});
//dragging the cursor //dragging the cursor

View File

@ -95,8 +95,8 @@ public class AssetManager {
modelsInQueue.remove(currentPath); modelsInQueue.remove(currentPath);
AIScene aiScene = ModelLoader.loadAIScene(currentPath); AIScene aiScene = ModelLoader.loadAIScene(currentPath);
TextureMap textureMap = null; TextureMap textureMap = null;
if(getLocalTextureMapPath(currentPath) != null){ if(this.getLocalTextureMapPath(currentPath) != null){
textureMap = TextureMap.construct(getLocalTextureMapPath(currentPath)); textureMap = TextureMap.construct(this.getLocalTextureMapPath(currentPath));
} }
if(aiScene != null){ if(aiScene != null){
modelsLoadedIntoMemory.put(currentPath, ModelLoader.createModelFromAiScene(aiScene,textureMap,currentPath)); modelsLoadedIntoMemory.put(currentPath, ModelLoader.createModelFromAiScene(aiScene,textureMap,currentPath));
@ -105,7 +105,7 @@ public class AssetManager {
//create physics //create physics
physicsMeshesToLoad.remove(physicsMeshQueueItem); physicsMeshesToLoad.remove(physicsMeshQueueItem);
physicsMeshesLoadedIntoMemory.put( physicsMeshesLoadedIntoMemory.put(
getCollisionMeshMapKey(physicsMeshQueueItem.collisionEngine,currentPath), this.getCollisionMeshMapKey(physicsMeshQueueItem.collisionEngine,currentPath),
CollisionBodyCreation.generateRigidBodyFromAIScene(physicsMeshQueueItem.collisionEngine,aiScene,Collidable.TYPE_STATIC_BIT) CollisionBodyCreation.generateRigidBodyFromAIScene(physicsMeshQueueItem.collisionEngine,aiScene,Collidable.TYPE_STATIC_BIT)
); );
} }

View File

@ -427,39 +427,24 @@ public class Actor {
*/ */
public void draw(RenderPipelineState renderPipelineState, OpenGLState openGLState){ public void draw(RenderPipelineState renderPipelineState, OpenGLState openGLState){
Model model = Globals.assetManager.fetchModel(modelPath); Model model = Globals.assetManager.fetchModel(modelPath);
boolean hasDrawn = false;
if(model != null && isWithinFrustumBox(renderPipelineState,model,frustumCull)){ if(model != null && isWithinFrustumBox(renderPipelineState,model,frustumCull)){
applyAnimationMasks(model); this.applyAnimationMasks(model);
meshMask.processMeshMaskQueue(); meshMask.processMeshMaskQueue();
model.setMeshMask(meshMask); model.setMeshMask(meshMask);
model.setTextureMask(textureMap); model.setTextureMask(textureMap);
// if(!meshMask.isEmpty()){
// }
// if(animation != null){
// model.playAnimation(animation);
// model.incrementTime(0.001);
// model.incrementTime(animationTime);
// if(model.currentAnimation == null){
// playingAnimation = false;
// }
// }
for(ActorShaderMask shaderMask : shaderMasks){ for(ActorShaderMask shaderMask : shaderMasks){
if(shaderMask.getModelName().equals(modelPath)){ if(shaderMask.getModelName().equals(modelPath)){
model.getShaderMask().put(shaderMask.getMeshName(),shaderMask); model.getShaderMask().put(shaderMask.getMeshName(),shaderMask);
} }
} }
calculateNodeTransforms(model); this.calculateNodeTransforms(model);
if(textureOverride != null){ if(textureOverride != null){
Texture overrideTextureObject = Globals.assetManager.fetchTexture(textureOverride); Texture overrideTextureObject = Globals.assetManager.fetchTexture(textureOverride);
if(overrideTextureObject != null){ if(overrideTextureObject != null){
overrideTextureObject.bind(openGLState); overrideTextureObject.bind(openGLState);
hasDrawn = true;
model.draw(renderPipelineState,openGLState);
} }
} }
if(!hasDrawn){ model.draw(renderPipelineState,openGLState);
model.draw(renderPipelineState,openGLState);
}
model.getShaderMask().clear(); model.getShaderMask().clear();
model.setTextureMask(null); model.setTextureMask(null);
} }

View File

@ -32,7 +32,8 @@ public class ModelLoader {
Assimp.aiProcess_Triangulate | Assimp.aiProcess_Triangulate |
Assimp.aiProcess_FixInfacingNormals | Assimp.aiProcess_FixInfacingNormals |
Assimp.aiProcess_LimitBoneWeights | Assimp.aiProcess_LimitBoneWeights |
Assimp.aiProcess_GlobalScale Assimp.aiProcess_GlobalScale |
Assimp.aiProcess_GenBoundingBoxes
); );
if(rVal == null){ if(rVal == null){
LoggerInterface.loggerRenderer.ERROR(new IllegalStateException(Assimp.aiGetErrorString())); LoggerInterface.loggerRenderer.ERROR(new IllegalStateException(Assimp.aiGetErrorString()));
@ -40,11 +41,18 @@ public class ModelLoader {
return rVal; return rVal;
} }
/**
* Creates a model object from an ai scene
* @param scene The ai scene
* @param localTextureMap The local texture map stored next to the model file
* @param path The path to the model
* @return The model object
*/
public static Model createModelFromAiScene(AIScene scene, TextureMap localTextureMap, String path){ public static Model createModelFromAiScene(AIScene scene, TextureMap localTextureMap, String path){
Model rVal = null; Model rVal = null;
if(scene != null){ if(scene != null){
rVal = Model.createModelFromAiscene(path, scene); rVal = Model.createModelFromAiscene(path, scene);
attemptAddTexturesFromPathname(path, localTextureMap, rVal); ModelLoader.attemptAddTexturesFromPathname(path, localTextureMap, rVal);
LoggerInterface.loggerRenderer.DEBUG("Finished loading model " + path); LoggerInterface.loggerRenderer.DEBUG("Finished loading model " + path);
} }
return rVal; return rVal;

View File

@ -6,8 +6,10 @@ import java.util.Iterator;
import org.joml.Matrix4d; import org.joml.Matrix4d;
import org.joml.Vector4d; import org.joml.Vector4d;
import org.joml.Vector3d;
import org.lwjgl.BufferUtils; import org.lwjgl.BufferUtils;
import org.lwjgl.PointerBuffer; import org.lwjgl.PointerBuffer;
import org.lwjgl.assimp.AIAABB;
import org.lwjgl.assimp.AIBone; import org.lwjgl.assimp.AIBone;
import org.lwjgl.assimp.AIFace; import org.lwjgl.assimp.AIFace;
import org.lwjgl.assimp.AIMesh; import org.lwjgl.assimp.AIMesh;
@ -109,11 +111,6 @@ public class MeshLoader {
minY = maxY = y; minY = maxY = y;
minZ = maxZ = z; minZ = maxZ = z;
} }
//update bounding sphere
double dist = Math.sqrt(x*x+y*y+z*z);
if(dist > rVal.getBoundingSphere().r){
rVal.getBoundingSphere().r = dist;
}
//store vertex data //store vertex data
Vector4d transformedVertex = vertexPretransform.transform(new Vector4d(x,y,z,1.0)); Vector4d transformedVertex = vertexPretransform.transform(new Vector4d(x,y,z,1.0));
transformedVertex.w = 1.0; transformedVertex.w = 1.0;
@ -324,7 +321,14 @@ public class MeshLoader {
//bounding sphere work
{
AIAABB aabbData = mesh.mAABB();
AIVector3D max = aabbData.mMax();
AIVector3D min = aabbData.mMin();
double dist = new Vector3d(max.x(),max.y(),max.z()).distance(new Vector3d(min.x(),min.y(),min.z()));
rVal.getBoundingSphere().r = dist / 2.0;
}

View File

@ -344,7 +344,7 @@ public class Mesh {
public void complexDraw(RenderPipelineState renderPipelineState, OpenGLState openGLState){ public void complexDraw(RenderPipelineState renderPipelineState, OpenGLState openGLState){
//bind vao off the rip //bind vao off the rip
glBindVertexArray(vertexArrayObject); GL40.glBindVertexArray(vertexArrayObject);
Globals.renderingEngine.checkError(); Globals.renderingEngine.checkError();
if(renderPipelineState.getUseMeshShader()){ if(renderPipelineState.getUseMeshShader()){
@ -489,7 +489,7 @@ public class Mesh {
} }
if(renderPipelineState.getBufferNonStandardUniforms()){ if(renderPipelineState.getBufferNonStandardUniforms()){
bufferAllUniforms(openGLState); this.bufferAllUniforms(openGLState);
Globals.renderingEngine.checkError(); Globals.renderingEngine.checkError();
} }
@ -519,7 +519,7 @@ public class Mesh {
} }
} }
} }
glBindVertexArray(0); GL40.glBindVertexArray(0);
Globals.renderingEngine.checkError(); Globals.renderingEngine.checkError();
} }

View File

@ -27,6 +27,7 @@ import org.lwjgl.assimp.AIScene;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import org.joml.Sphered; import org.joml.Sphered;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.lwjgl.assimp.AIAnimation; import org.lwjgl.assimp.AIAnimation;
@ -89,10 +90,10 @@ public class Model {
/** /**
* Loads a model from an ai scene object * Loads a model from an ai scene object
* @param path The path of the model * @param path The path of the model
* @param s the ai scene * @param scene the ai scene
* @return The model object * @return The model object
*/ */
public static Model createModelFromAiscene(String path, AIScene s){ public static Model createModelFromAiscene(String path, AIScene scene){
Model rVal = new Model(); Model rVal = new Model();
ModelPretransforms.ModelMetadata modelMetadata = Globals.modelPretransforms.getModel(path); ModelPretransforms.ModelMetadata modelMetadata = Globals.modelPretransforms.getModel(path);
@ -104,7 +105,7 @@ public class Model {
// //
//load meshes //load meshes
// //
PointerBuffer meshesBuffer = s.mMeshes(); PointerBuffer meshesBuffer = scene.mMeshes();
rVal.meshes = new ArrayList<Mesh>(); rVal.meshes = new ArrayList<Mesh>();
while(meshesBuffer.hasRemaining()){ while(meshesBuffer.hasRemaining()){
AIMesh aiMesh = AIMesh.create(meshesBuffer.get()); AIMesh aiMesh = AIMesh.create(meshesBuffer.get());
@ -120,6 +121,7 @@ public class Model {
rVal.boundingSphere.r = currentMesh.getBoundingSphere().r; rVal.boundingSphere.r = currentMesh.getBoundingSphere().r;
} }
} }
// //
//register bones //register bones
// //
@ -165,10 +167,11 @@ public class Model {
currentMesh.getBones().add(boneIterator.next()); currentMesh.getBones().add(boneIterator.next());
} }
} }
// //
//parse animation nodes and form hierarchy //parse animation nodes and form hierarchy
// //
AINode rootNode = s.mRootNode(); AINode rootNode = scene.mRootNode();
//The mOffsetMatrix, inverted, is the bind pose matrix that we want to apply at the top of all anims: https://github.com/assimp/assimp/issues/4364 //The mOffsetMatrix, inverted, is the bind pose matrix that we want to apply at the top of all anims: https://github.com/assimp/assimp/issues/4364
//This version of assimp doesn't support it, unfortunately //This version of assimp doesn't support it, unfortunately
rVal.rootTransform = electrosphere.util.Utilities.convertAIMatrixd(rootNode.mTransformation()); rVal.rootTransform = electrosphere.util.Utilities.convertAIMatrixd(rootNode.mTransformation());
@ -178,12 +181,13 @@ public class Model {
} }
LoggerInterface.loggerRenderer.DEBUG("Global Inverse Transform"); LoggerInterface.loggerRenderer.DEBUG("Global Inverse Transform");
LoggerInterface.loggerRenderer.DEBUG(rVal.rootTransform + ""); LoggerInterface.loggerRenderer.DEBUG(rVal.rootTransform + "");
rVal.rootAnimNode = rVal.buildAnimNodeMap(s.mRootNode(),null); rVal.rootAnimNode = rVal.buildAnimNodeMap(scene.mRootNode(),null);
// //
//load animations //load animations
// //
int animCount = s.mNumAnimations(); int animCount = scene.mNumAnimations();
PointerBuffer animBuffer = s.mAnimations(); PointerBuffer animBuffer = scene.mAnimations();
rVal.animations = new ArrayList<Animation>(); rVal.animations = new ArrayList<Animation>();
rVal.animMap = new HashMap<String,Animation>(); rVal.animMap = new HashMap<String,Animation>();
for(int i = 0; i < animCount; i++){ for(int i = 0; i < animCount; i++){
@ -191,18 +195,18 @@ public class Model {
rVal.animations.add(newAnim); rVal.animations.add(newAnim);
rVal.animMap.put(newAnim.name,newAnim); rVal.animMap.put(newAnim.name,newAnim);
} }
// //
//Load materials //Load materials
// //
if(s.mNumMaterials() > 0){ if(scene.mNumMaterials() > 0){
rVal.materials = new ArrayList<Material>(); rVal.materials = new ArrayList<Material>();
PointerBuffer material_buffer = s.mMaterials(); PointerBuffer material_buffer = scene.mMaterials();
while(material_buffer.hasRemaining()){ while(material_buffer.hasRemaining()){
rVal.materials.add(Material.load_material_from_aimaterial(AIMaterial.create(material_buffer.get()))); rVal.materials.add(Material.load_material_from_aimaterial(AIMaterial.create(material_buffer.get())));
} }
} }
//garbage collect
System.gc();
return rVal; return rVal;
} }

View File

@ -27,6 +27,7 @@ import electrosphere.renderer.ui.events.Event;
import electrosphere.renderer.ui.events.FocusEvent; import electrosphere.renderer.ui.events.FocusEvent;
import electrosphere.renderer.ui.events.HoverEvent; import electrosphere.renderer.ui.events.HoverEvent;
import electrosphere.renderer.ui.events.NavigationEvent; import electrosphere.renderer.ui.events.NavigationEvent;
import electrosphere.renderer.ui.events.ScrollEvent;
import electrosphere.renderer.ui.events.DragEvent.DragEventType; import electrosphere.renderer.ui.events.DragEvent.DragEventType;
import electrosphere.renderer.ui.events.NavigationEvent.NavigationEventType; import electrosphere.renderer.ui.events.NavigationEvent.NavigationEventType;
@ -246,6 +247,11 @@ public class ElementService extends SignalServiceImpl {
Vector2i absPos = getAbsolutePosition(currentElement); Vector2i absPos = getAbsolutePosition(currentElement);
dragEvent.setRelativeX(dragEvent.getCurrentX() - absPos.x); dragEvent.setRelativeX(dragEvent.getCurrentX() - absPos.x);
dragEvent.setRelativeY(dragEvent.getCurrentY() - absPos.y); dragEvent.setRelativeY(dragEvent.getCurrentY() - absPos.y);
} else if(event instanceof ScrollEvent){
ScrollEvent scrollEvent = (ScrollEvent)event;
Vector2i absPos = getAbsolutePosition(currentElement);
scrollEvent.setRelativeX((int)(scrollEvent.getMouseX() - absPos.x));
scrollEvent.setRelativeY((int)(scrollEvent.getMouseY() - absPos.y));
} }
propagate = currentElement.handleEvent(event); propagate = currentElement.handleEvent(event);
} }

View File

@ -1,32 +1,32 @@
package electrosphere.renderer.ui.elements; package electrosphere.renderer.ui.elements;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_LESS;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glClearColor;
import static org.lwjgl.opengl.GL11.glDepthMask;
import org.joml.Matrix4d; import org.joml.Matrix4d;
import org.joml.Quaterniond; import org.joml.Quaterniond;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.Vector4d;
import org.lwjgl.opengl.GL40;
import electrosphere.client.entity.camera.CameraEntityUtils;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.OpenGLState; import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderPipelineState; import electrosphere.renderer.RenderPipelineState;
import electrosphere.renderer.RenderingEngine; import electrosphere.renderer.RenderingEngine;
import electrosphere.renderer.actor.Actor; import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.debug.DebugRendering;
import electrosphere.renderer.framebuffer.Framebuffer; import electrosphere.renderer.framebuffer.Framebuffer;
import electrosphere.renderer.model.Model; import electrosphere.renderer.model.Model;
import electrosphere.renderer.ui.elementtypes.DraggableElement; import electrosphere.renderer.ui.elementtypes.DraggableElement;
import electrosphere.renderer.ui.elementtypes.ScrollableElement;
import electrosphere.renderer.ui.events.DragEvent; import electrosphere.renderer.ui.events.DragEvent;
import electrosphere.renderer.ui.events.DragEvent.DragEventType; import electrosphere.renderer.ui.events.DragEvent.DragEventType;
import electrosphere.renderer.ui.events.Event; import electrosphere.renderer.ui.events.Event;
import electrosphere.renderer.ui.events.ScrollEvent;
public class ActorPanel extends BufferedStandardDrawableContainerElement implements DraggableElement { /**
* Draws a 3d scene inside a panel
*/
public class ActorPanel extends BufferedStandardDrawableContainerElement implements DraggableElement, ScrollableElement {
/** /**
* The default width of an actor panel * The default width of an actor panel
@ -38,37 +38,138 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme
*/ */
public static final int DEFAULT_HEIGHT = 500; public static final int DEFAULT_HEIGHT = 500;
/**
* Default distance to move the camera back from the actor
*/
static final double DEFAULT_STANDOFF_DIST = 1.0;
/**
* Default amount to increment the yaw by
*/
static final double DEFAULT_YAW_INCREMENT = 0.03;
/**
* Multiplier applied to drag events to scale how fast the camera rotates
*/
static final double DRAG_MULTIPLIER = 0.5;
/**
* The minimum zoom
*/
static final double MIN_ZOOM = 0.1;
/**
* The maximum zoom
*/
static final double MAX_ZOOM = 10.0;
/**
* Multiplier applied to scroll events to scale how fast the camera zooms
*/
static final double SCROLL_MULTIPLIER = 0.1;
/**
* Color to clear the background with
*/
static Vector3f color = new Vector3f(1.0f); static Vector3f color = new Vector3f(1.0f);
/**
* Color to clear the panel with
*/
Vector4d clearColor = new Vector4d(1.0);
/**
* The actor to draw
*/
Actor actor; Actor actor;
/**
* The model matrix for the actor panel
*/
Matrix4d modelMatrix = new Matrix4d(); Matrix4d modelMatrix = new Matrix4d();
/**
* The current animation to play
*/
String currentAnim; String currentAnim;
/**
* The position of the actor
*/
Vector3f actorPosition = new Vector3f(0,0,0); Vector3f actorPosition = new Vector3f(0,0,0);
/**
* The rotation of the actor
*/
Quaterniond actorRotation = new Quaterniond(); Quaterniond actorRotation = new Quaterniond();
/**
* The scale of the actor
*/
Vector3f actorScale = new Vector3f(1,1,1); Vector3f actorScale = new Vector3f(1,1,1);
/**
* The FOV of the panel
*/
float FOV = 50.0f; float FOV = 50.0f;
/**
* The aspec ratio of the panel
*/
float aspectRatio = 1.9f; float aspectRatio = 1.9f;
/**
* Used for calculating drawing the panel
*/
Vector3f texPosition = new Vector3f(0,0,0); Vector3f texPosition = new Vector3f(0,0,0);
/**
* Used for calculating drawing the panel
*/
Vector3f texScale = new Vector3f(1,1,0); Vector3f texScale = new Vector3f(1,1,0);
/**
* Tracks whether this actor panel has pulled the camera back based on the bounding sphere of the model or not
* <p>
* This must be done during draw-phase instead of creation-phase because the model may not exist when creating
* </p>
*/
boolean hasOffsetFromBoundingSphere = false;
/**
* The yaw of the camera
*/
double yaw = 0;
/**
* The pitch of the camera
*/
double pitch = 0;
/**
* The radius of the camera
*/
double cameraRadius = 1.0;
/**
* Fires on starting dragging the panel
*/
DragEventCallback onDragStart; DragEventCallback onDragStart;
/**
* Fires on dragging the panel
*/
DragEventCallback onDrag; DragEventCallback onDrag;
/**
* Fires on releasing dragging thep anel
*/
DragEventCallback onDragRelease; DragEventCallback onDragRelease;
static final Vector3f windowDrawDebugColor = new Vector3f(0.0f,0.0f,1.0f); /**
* Fires when a scrollable event occurs
@Deprecated */
public ActorPanel(OpenGLState openGLState, int x, int y, int width, int height, Actor actor){ ScrollEventCallback onScroll;
super();
this.actor = actor;
this.setWidth(width);
this.setHeight(height);
this.aspectRatio = (float)width / (float)height;
recalculateModelMatrix();
}
/** /**
* Constructor * Constructor
@ -113,14 +214,14 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme
RenderingEngine.setAspectRatio(aspectRatio); RenderingEngine.setAspectRatio(aspectRatio);
openGLState.glDepthTest(true); openGLState.glDepthTest(true);
openGLState.glDepthFunc(GL_LESS); openGLState.glDepthFunc(GL40.GL_LESS);
glDepthMask(true); GL40.glDepthMask(true);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); GL40.glClearColor((float)clearColor.x, (float)clearColor.y, (float)clearColor.z, (float)clearColor.w);
glClear(GL_COLOR_BUFFER_BIT | 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.getModelPath());
if(currentAnim != null){ if(currentAnim != null){
if((!actor.isPlayingAnimation() || !actor.isPlayingAnimation(currentAnim)) && if((!actor.isPlayingAnimation() || !actor.isPlayingAnimation(currentAnim)) &&
actorModel != null && actorModel != null &&
@ -130,6 +231,24 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme
actor.incrementAnimationTime(0.0001); actor.incrementAnimationTime(0.0001);
} }
} }
if(!hasOffsetFromBoundingSphere && actorModel != null){
Globals.cameraHandler.updateRadialOffset(actorPosition);
double radius = actorModel.getBoundingSphere().r;
this.cameraRadius = radius + DEFAULT_STANDOFF_DIST;
CameraEntityUtils.setOrbitalCameraDistance(Globals.playerCamera, (float)(this.cameraRadius));
CameraEntityUtils.setCameraCenter(Globals.playerCamera, new Vector3f(0,(float)(this.cameraRadius - DEFAULT_STANDOFF_DIST),0));
hasOffsetFromBoundingSphere = true;
}
//
//Setup camera
//
yaw = yaw + DEFAULT_YAW_INCREMENT;
this.clampYaw();
Globals.cameraHandler.setYaw(yaw);
Globals.cameraHandler.setPitch(pitch);
Globals.cameraHandler.updateGlobalCamera();
this.recalculateModelMatrix();
// //
// Set rendering engine state // Set rendering engine state
@ -138,7 +257,7 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme
renderPipelineState.setBufferStandardUniforms(true); renderPipelineState.setBufferStandardUniforms(true);
renderPipelineState.setBufferNonStandardUniforms(true); renderPipelineState.setBufferNonStandardUniforms(true);
renderPipelineState.setUseMaterial(true); renderPipelineState.setUseMaterial(true);
renderPipelineState.setUseShadowMap(true); renderPipelineState.setUseShadowMap(false);
renderPipelineState.setUseBones(true); renderPipelineState.setUseBones(true);
renderPipelineState.setUseLight(true); renderPipelineState.setUseLight(true);
@ -146,7 +265,6 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme
actor.applySpatialData(modelMatrix,new Vector3d(actorPosition)); actor.applySpatialData(modelMatrix,new Vector3d(actorPosition));
actor.draw(renderPipelineState,openGLState); actor.draw(renderPipelineState,openGLState);
@ -201,58 +319,141 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme
} else { } else {
LoggerInterface.loggerRenderer.ERROR("Actor Panel unable to find plane model!!", new Exception()); LoggerInterface.loggerRenderer.ERROR("Actor Panel unable to find plane model!!", new Exception());
} }
if(Globals.RENDER_FLAG_RENDER_UI_BOUNDS && DebugRendering.RENDER_DEBUG_OUTLINE_ACTOR_PANEL){
DebugRendering.drawUIBounds(framebuffer, boxPosition, boxDimensions, windowDrawDebugColor);
}
} }
} }
/**
* Sets the animation of the actor panel's actor
* @param animation The animation
*/
public void setAnimation(String animation){ public void setAnimation(String animation){
currentAnim = animation; currentAnim = animation;
} }
/**
* Sets the position of the actor panel's actor
* @param position The position
*/
public void setPosition(Vector3f position){ public void setPosition(Vector3f position){
this.actorPosition.set(position); this.actorPosition.set(position);
recalculateModelMatrix(); recalculateModelMatrix();
} }
/**
* Sets the rotation of the actor panel's actor
* @param rotation The rotation
*/
public void setRotation(Quaterniond rotation){ public void setRotation(Quaterniond rotation){
this.actorRotation.set(rotation); this.actorRotation.set(rotation);
recalculateModelMatrix(); recalculateModelMatrix();
} }
/**
* Sets the scale of the actor panel's actor
* @param scale The scale
*/
public void setScale(Vector3f scale){ public void setScale(Vector3f scale){
this.actorScale.set(scale); this.actorScale.set(scale);
recalculateModelMatrix(); recalculateModelMatrix();
} }
void recalculateModelMatrix(){ /**
* Recalculates the model matrix
*/
private void recalculateModelMatrix(){
modelMatrix.identity(); modelMatrix.identity();
modelMatrix.translate(actorPosition); modelMatrix.translate(new Vector3d(actorPosition).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)));
modelMatrix.rotate(actorRotation); modelMatrix.rotate(actorRotation);
modelMatrix.scale(new Vector3d(actorScale)); modelMatrix.scale(new Vector3d(actorScale));
actor.applySpatialData(modelMatrix,new Vector3d(actorPosition)); actor.applySpatialData(modelMatrix,new Vector3d(actorPosition));
} }
/**
* Sets the clear color of this panel
* @param color The clear color
*/
public void setClearColor(Vector4d color){
this.clearColor.set(color);
}
/**
* Clamps the yaw value
*/
private void clampYaw(){
while(yaw > 360){
yaw = yaw - 360;
}
while(yaw < 0){
yaw = yaw + 360;
}
}
/**
* Clamps the pitch value
*/
private void clampPitch(){
if(pitch >= 90){
pitch = 89.99;
}
if(pitch <= -90){
pitch = -89.99;
}
}
/**
* Handles any events applied to this actor panel
*/
public boolean handleEvent(Event event){ public boolean handleEvent(Event event){
boolean propagate = true; boolean propagate = true;
if(event instanceof DragEvent){ if(event instanceof DragEvent){
if(onDragStart != null && ((DragEvent)event).getType() == DragEventType.START){ DragEvent dragEvent = (DragEvent)event;
if(!onDragStart.execute((DragEvent)event)){ if(dragEvent.getType() == DragEventType.START){
if(onDragStart != null){
if(!onDragStart.execute(dragEvent)){
propagate = false;
}
} else {
}
}
if(dragEvent.getType() == DragEventType.DRAG){
if(onDrag != null){
if(!onDrag.execute(dragEvent)){
propagate = false;
}
} else {
yaw = yaw + dragEvent.getDeltaX() * DRAG_MULTIPLIER;
this.clampYaw();
pitch = pitch + dragEvent.getDeltaY() * DRAG_MULTIPLIER;
this.clampPitch();
propagate = false; propagate = false;
} }
} }
if(onDrag != null && ((DragEvent)event).getType() == DragEventType.DRAG){ if(dragEvent.getType() == DragEventType.RELEASE){
if(!onDrag.execute((DragEvent)event)){ if(onDragRelease != null){
propagate = false; if(!onDragRelease.execute(dragEvent)){
propagate = false;
}
} }
} }
if(onDragRelease != null && ((DragEvent)event).getType() == DragEventType.RELEASE){ }
if(!onDragRelease.execute((DragEvent)event)){ if(event instanceof ScrollEvent){
ScrollEvent scrollEvent = (ScrollEvent)event;
if(onScroll != null){
if(!onScroll.execute(scrollEvent)){
propagate = false; propagate = false;
} }
} else {
this.cameraRadius = this.cameraRadius - scrollEvent.getScrollAmount() * SCROLL_MULTIPLIER;
if(this.cameraRadius > MAX_ZOOM){
this.cameraRadius = MAX_ZOOM;
}
if(this.cameraRadius < MIN_ZOOM){
this.cameraRadius = MIN_ZOOM;
}
CameraEntityUtils.setOrbitalCameraDistance(Globals.playerCamera, (float)cameraRadius);
propagate = false;
} }
} }
return propagate; return propagate;
@ -272,6 +473,11 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme
public void setOnDragRelease(DragEventCallback callback) { public void setOnDragRelease(DragEventCallback callback) {
onDragRelease = callback; onDragRelease = callback;
} }
@Override
public void setOnScrollCallback(ScrollEventCallback callback) {
onScroll = callback;
}

View File

@ -11,6 +11,9 @@ public class ScrollEvent implements Event {
double mouseX; double mouseX;
double mouseY; double mouseY;
int relativeX;
int relativeY;
/** /**
* Constructor * Constructor
* @param scrollAmount * @param scrollAmount
@ -19,6 +22,8 @@ public class ScrollEvent implements Event {
this.scrollAmount = scrollAmount; this.scrollAmount = scrollAmount;
this.mouseX = mouseX; this.mouseX = mouseX;
this.mouseY = mouseY; this.mouseY = mouseY;
this.relativeX = (int)mouseX;
this.relativeY = (int)mouseY;
} }
/** /**
@ -45,5 +50,21 @@ public class ScrollEvent implements Event {
return mouseY; return mouseY;
} }
public int getRelativeX(){
return relativeX;
}
public int getRelativeY(){
return relativeY;
}
public void setRelativeX(int relX){
this.relativeX = relX;
}
public void setRelativeY(int relY){
this.relativeY = relY;
}
} }