From 9c672af15f3261e2b04992f08c2ea125d38babfe Mon Sep 17 00:00:00 2001 From: austin Date: Fri, 29 Nov 2024 19:05:14 -0500 Subject: [PATCH] character creation menu work --- docs/src/progress/renderertodo.md | 5 + .../entity/camera/CameraEntityUtils.java | 5 + .../ui/components/CharacterCustomizer.java | 49 ++- .../electrosphere/controls/CameraHandler.java | 20 +- .../categories/ControlCategoryMenuNav.java | 2 +- .../engine/assetmanager/AssetManager.java | 6 +- .../electrosphere/renderer/actor/Actor.java | 21 +- .../renderer/loading/ModelLoader.java | 12 +- .../renderer/meshgen/MeshLoader.java | 16 +- .../electrosphere/renderer/model/Mesh.java | 6 +- .../electrosphere/renderer/model/Model.java | 26 +- .../renderer/ui/ElementService.java | 6 + .../renderer/ui/elements/ActorPanel.java | 290 +++++++++++++++--- .../renderer/ui/events/ScrollEvent.java | 21 ++ 14 files changed, 390 insertions(+), 95 deletions(-) diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 588745c2..b28c75e0 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1179,6 +1179,10 @@ Nearest biome sampling for content generation Fix recursive delete not actually recursing Add floor voxel type 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 @@ -1215,6 +1219,7 @@ Bug Fixes - Fix virtual scrollables not working - Fix foliage flickering on edit - Fix single blades of grass generating in bad locations + - Fix falling tree not stopping when hitting static collidables Startup Performance - Allow texture map to bind multiple model paths to a single set of mesh->textures diff --git a/src/main/java/electrosphere/client/entity/camera/CameraEntityUtils.java b/src/main/java/electrosphere/client/entity/camera/CameraEntityUtils.java index 437acafd..d7fc05a8 100644 --- a/src/main/java/electrosphere/client/entity/camera/CameraEntityUtils.java +++ b/src/main/java/electrosphere/client/entity/camera/CameraEntityUtils.java @@ -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){ Vector3f cameraCenter = new Vector3f(0,0,0);//getViewMatrixCenterOffset(camera); Vector3f cameraEye = new Vector3f(cameraCenter).add(getCameraEye(camera)); diff --git a/src/main/java/electrosphere/client/ui/components/CharacterCustomizer.java b/src/main/java/electrosphere/client/ui/components/CharacterCustomizer.java index 31db0641..7d0364a4 100644 --- a/src/main/java/electrosphere/client/ui/components/CharacterCustomizer.java +++ b/src/main/java/electrosphere/client/ui/components/CharacterCustomizer.java @@ -4,6 +4,7 @@ import java.util.function.Consumer; import java.util.stream.Collectors; import org.joml.Vector3f; +import org.joml.Vector4d; import electrosphere.client.entity.camera.CameraEntityUtils; import electrosphere.engine.Globals; @@ -15,6 +16,7 @@ import electrosphere.net.parser.net.message.CharacterMessage; import electrosphere.renderer.actor.Actor; import electrosphere.renderer.actor.ActorStaticMorph; import electrosphere.renderer.actor.ActorUtils; +import electrosphere.renderer.light.DirectionalLight; import electrosphere.renderer.ui.elements.ActorPanel; import electrosphere.renderer.ui.elements.Button; import electrosphere.renderer.ui.elements.Div; @@ -40,6 +42,16 @@ public class CharacterCustomizer { * Minimum height of the component */ 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 @@ -58,8 +70,13 @@ public class CharacterCustomizer { Actor characterActor = ActorUtils.createActorFromModelPath(selectedRaceType.getGraphicsTemplate().getModel().getPath()); ActorPanel actorPanel = ActorPanel.create(characterActor); 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.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 ActorStaticMorph staticMorph = new ActorStaticMorph(); @@ -105,7 +122,12 @@ public class CharacterCustomizer { //add attribute to creature template 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)){ //add label for carousel Label scrollableName = Label.createLabel(attribute.getAttributeId()); @@ -136,22 +158,35 @@ public class CharacterCustomizer { //set the current attrib for the template 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 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 Div rVal = Div.createCol( Div.createRow( scrollable, actorPanel ), - Button.createButton("Create", () -> { - Globals.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestCreateCharacterMessage(Utilities.stringify(template))); - onConfirm.accept(template); - }) + createButtonContainer ); return rVal; diff --git a/src/main/java/electrosphere/controls/CameraHandler.java b/src/main/java/electrosphere/controls/CameraHandler.java index c98e5007..fa1123c2 100644 --- a/src/main/java/electrosphere/controls/CameraHandler.java +++ b/src/main/java/electrosphere/controls/CameraHandler.java @@ -62,7 +62,7 @@ public class CameraHandler { } } - updateGlobalCamera(); + this.updateGlobalCamera(); } /** @@ -160,7 +160,7 @@ public class CameraHandler { Globals.viewMatrix = CameraEntityUtils.getCameraViewMatrix(Globals.playerCamera); //update the cursor on client side - updatePlayerCursor(); + this.updatePlayerCursor(); } } Globals.profiler.endCpuSample(); @@ -196,6 +196,14 @@ public class CameraHandler { 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 * @return the pitch @@ -204,6 +212,14 @@ public class CameraHandler { 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 public void setTrackPlayerEntity(boolean track){ trackPlayerEntity = track; diff --git a/src/main/java/electrosphere/controls/categories/ControlCategoryMenuNav.java b/src/main/java/electrosphere/controls/categories/ControlCategoryMenuNav.java index 17c64032..cfce3264 100644 --- a/src/main/java/electrosphere/controls/categories/ControlCategoryMenuNav.java +++ b/src/main/java/electrosphere/controls/categories/ControlCategoryMenuNav.java @@ -105,7 +105,7 @@ public class ControlCategoryMenuNav { //scrolling the mouse menuNavigationControlList.add(controlMap.get(MENU_SCROLL)); 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 diff --git a/src/main/java/electrosphere/engine/assetmanager/AssetManager.java b/src/main/java/electrosphere/engine/assetmanager/AssetManager.java index e529406f..db5e3abd 100644 --- a/src/main/java/electrosphere/engine/assetmanager/AssetManager.java +++ b/src/main/java/electrosphere/engine/assetmanager/AssetManager.java @@ -95,8 +95,8 @@ public class AssetManager { modelsInQueue.remove(currentPath); AIScene aiScene = ModelLoader.loadAIScene(currentPath); TextureMap textureMap = null; - if(getLocalTextureMapPath(currentPath) != null){ - textureMap = TextureMap.construct(getLocalTextureMapPath(currentPath)); + if(this.getLocalTextureMapPath(currentPath) != null){ + textureMap = TextureMap.construct(this.getLocalTextureMapPath(currentPath)); } if(aiScene != null){ modelsLoadedIntoMemory.put(currentPath, ModelLoader.createModelFromAiScene(aiScene,textureMap,currentPath)); @@ -105,7 +105,7 @@ public class AssetManager { //create physics physicsMeshesToLoad.remove(physicsMeshQueueItem); physicsMeshesLoadedIntoMemory.put( - getCollisionMeshMapKey(physicsMeshQueueItem.collisionEngine,currentPath), + this.getCollisionMeshMapKey(physicsMeshQueueItem.collisionEngine,currentPath), CollisionBodyCreation.generateRigidBodyFromAIScene(physicsMeshQueueItem.collisionEngine,aiScene,Collidable.TYPE_STATIC_BIT) ); } diff --git a/src/main/java/electrosphere/renderer/actor/Actor.java b/src/main/java/electrosphere/renderer/actor/Actor.java index 93ff80e7..ca7501d6 100644 --- a/src/main/java/electrosphere/renderer/actor/Actor.java +++ b/src/main/java/electrosphere/renderer/actor/Actor.java @@ -427,39 +427,24 @@ public class Actor { */ public void draw(RenderPipelineState renderPipelineState, OpenGLState openGLState){ Model model = Globals.assetManager.fetchModel(modelPath); - boolean hasDrawn = false; if(model != null && isWithinFrustumBox(renderPipelineState,model,frustumCull)){ - applyAnimationMasks(model); + this.applyAnimationMasks(model); meshMask.processMeshMaskQueue(); model.setMeshMask(meshMask); 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){ if(shaderMask.getModelName().equals(modelPath)){ model.getShaderMask().put(shaderMask.getMeshName(),shaderMask); } } - calculateNodeTransforms(model); + this.calculateNodeTransforms(model); if(textureOverride != null){ Texture overrideTextureObject = Globals.assetManager.fetchTexture(textureOverride); if(overrideTextureObject != null){ overrideTextureObject.bind(openGLState); - hasDrawn = true; - model.draw(renderPipelineState,openGLState); } } - if(!hasDrawn){ - model.draw(renderPipelineState,openGLState); - } + model.draw(renderPipelineState,openGLState); model.getShaderMask().clear(); model.setTextureMask(null); } diff --git a/src/main/java/electrosphere/renderer/loading/ModelLoader.java b/src/main/java/electrosphere/renderer/loading/ModelLoader.java index d212659e..a9a11e7e 100644 --- a/src/main/java/electrosphere/renderer/loading/ModelLoader.java +++ b/src/main/java/electrosphere/renderer/loading/ModelLoader.java @@ -32,7 +32,8 @@ public class ModelLoader { Assimp.aiProcess_Triangulate | Assimp.aiProcess_FixInfacingNormals | Assimp.aiProcess_LimitBoneWeights | - Assimp.aiProcess_GlobalScale + Assimp.aiProcess_GlobalScale | + Assimp.aiProcess_GenBoundingBoxes ); if(rVal == null){ LoggerInterface.loggerRenderer.ERROR(new IllegalStateException(Assimp.aiGetErrorString())); @@ -40,11 +41,18 @@ public class ModelLoader { 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){ Model rVal = null; if(scene != null){ rVal = Model.createModelFromAiscene(path, scene); - attemptAddTexturesFromPathname(path, localTextureMap, rVal); + ModelLoader.attemptAddTexturesFromPathname(path, localTextureMap, rVal); LoggerInterface.loggerRenderer.DEBUG("Finished loading model " + path); } return rVal; diff --git a/src/main/java/electrosphere/renderer/meshgen/MeshLoader.java b/src/main/java/electrosphere/renderer/meshgen/MeshLoader.java index 28277ba1..230ecd92 100644 --- a/src/main/java/electrosphere/renderer/meshgen/MeshLoader.java +++ b/src/main/java/electrosphere/renderer/meshgen/MeshLoader.java @@ -6,8 +6,10 @@ import java.util.Iterator; import org.joml.Matrix4d; import org.joml.Vector4d; +import org.joml.Vector3d; import org.lwjgl.BufferUtils; import org.lwjgl.PointerBuffer; +import org.lwjgl.assimp.AIAABB; import org.lwjgl.assimp.AIBone; import org.lwjgl.assimp.AIFace; import org.lwjgl.assimp.AIMesh; @@ -109,11 +111,6 @@ public class MeshLoader { minY = maxY = y; 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 Vector4d transformedVertex = vertexPretransform.transform(new Vector4d(x,y,z,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; + } diff --git a/src/main/java/electrosphere/renderer/model/Mesh.java b/src/main/java/electrosphere/renderer/model/Mesh.java index de6148ed..7469d6ce 100644 --- a/src/main/java/electrosphere/renderer/model/Mesh.java +++ b/src/main/java/electrosphere/renderer/model/Mesh.java @@ -344,7 +344,7 @@ public class Mesh { public void complexDraw(RenderPipelineState renderPipelineState, OpenGLState openGLState){ //bind vao off the rip - glBindVertexArray(vertexArrayObject); + GL40.glBindVertexArray(vertexArrayObject); Globals.renderingEngine.checkError(); if(renderPipelineState.getUseMeshShader()){ @@ -489,7 +489,7 @@ public class Mesh { } if(renderPipelineState.getBufferNonStandardUniforms()){ - bufferAllUniforms(openGLState); + this.bufferAllUniforms(openGLState); Globals.renderingEngine.checkError(); } @@ -519,7 +519,7 @@ public class Mesh { } } } - glBindVertexArray(0); + GL40.glBindVertexArray(0); Globals.renderingEngine.checkError(); } diff --git a/src/main/java/electrosphere/renderer/model/Model.java b/src/main/java/electrosphere/renderer/model/Model.java index 8f571067..1f5f4dfb 100644 --- a/src/main/java/electrosphere/renderer/model/Model.java +++ b/src/main/java/electrosphere/renderer/model/Model.java @@ -27,6 +27,7 @@ import org.lwjgl.assimp.AIScene; import java.util.HashMap; import java.util.Iterator; import java.util.Map; + import org.joml.Sphered; import org.joml.Vector3d; import org.lwjgl.assimp.AIAnimation; @@ -89,10 +90,10 @@ public class Model { /** * Loads a model from an ai scene object * @param path The path of the model - * @param s the ai scene + * @param scene the ai scene * @return The model object */ - public static Model createModelFromAiscene(String path, AIScene s){ + public static Model createModelFromAiscene(String path, AIScene scene){ Model rVal = new Model(); ModelPretransforms.ModelMetadata modelMetadata = Globals.modelPretransforms.getModel(path); @@ -104,7 +105,7 @@ public class Model { // //load meshes // - PointerBuffer meshesBuffer = s.mMeshes(); + PointerBuffer meshesBuffer = scene.mMeshes(); rVal.meshes = new ArrayList(); while(meshesBuffer.hasRemaining()){ AIMesh aiMesh = AIMesh.create(meshesBuffer.get()); @@ -120,6 +121,7 @@ public class Model { rVal.boundingSphere.r = currentMesh.getBoundingSphere().r; } } + // //register bones // @@ -165,10 +167,11 @@ public class Model { currentMesh.getBones().add(boneIterator.next()); } } + // //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 //This version of assimp doesn't support it, unfortunately rVal.rootTransform = electrosphere.util.Utilities.convertAIMatrixd(rootNode.mTransformation()); @@ -178,12 +181,13 @@ public class Model { } LoggerInterface.loggerRenderer.DEBUG("Global Inverse Transform"); LoggerInterface.loggerRenderer.DEBUG(rVal.rootTransform + ""); - rVal.rootAnimNode = rVal.buildAnimNodeMap(s.mRootNode(),null); + rVal.rootAnimNode = rVal.buildAnimNodeMap(scene.mRootNode(),null); + // //load animations // - int animCount = s.mNumAnimations(); - PointerBuffer animBuffer = s.mAnimations(); + int animCount = scene.mNumAnimations(); + PointerBuffer animBuffer = scene.mAnimations(); rVal.animations = new ArrayList(); rVal.animMap = new HashMap(); for(int i = 0; i < animCount; i++){ @@ -191,18 +195,18 @@ public class Model { rVal.animations.add(newAnim); rVal.animMap.put(newAnim.name,newAnim); } + // //Load materials // - if(s.mNumMaterials() > 0){ + if(scene.mNumMaterials() > 0){ rVal.materials = new ArrayList(); - PointerBuffer material_buffer = s.mMaterials(); + PointerBuffer material_buffer = scene.mMaterials(); while(material_buffer.hasRemaining()){ rVal.materials.add(Material.load_material_from_aimaterial(AIMaterial.create(material_buffer.get()))); } } - //garbage collect - System.gc(); + return rVal; } diff --git a/src/main/java/electrosphere/renderer/ui/ElementService.java b/src/main/java/electrosphere/renderer/ui/ElementService.java index 08cf9a14..9b2d93e6 100644 --- a/src/main/java/electrosphere/renderer/ui/ElementService.java +++ b/src/main/java/electrosphere/renderer/ui/ElementService.java @@ -27,6 +27,7 @@ import electrosphere.renderer.ui.events.Event; import electrosphere.renderer.ui.events.FocusEvent; import electrosphere.renderer.ui.events.HoverEvent; import electrosphere.renderer.ui.events.NavigationEvent; +import electrosphere.renderer.ui.events.ScrollEvent; import electrosphere.renderer.ui.events.DragEvent.DragEventType; import electrosphere.renderer.ui.events.NavigationEvent.NavigationEventType; @@ -246,6 +247,11 @@ public class ElementService extends SignalServiceImpl { Vector2i absPos = getAbsolutePosition(currentElement); dragEvent.setRelativeX(dragEvent.getCurrentX() - absPos.x); 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); } diff --git a/src/main/java/electrosphere/renderer/ui/elements/ActorPanel.java b/src/main/java/electrosphere/renderer/ui/elements/ActorPanel.java index 54eee199..c29f4f9d 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/ActorPanel.java +++ b/src/main/java/electrosphere/renderer/ui/elements/ActorPanel.java @@ -1,32 +1,32 @@ 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.Quaterniond; import org.joml.Vector3d; 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.logger.LoggerInterface; import electrosphere.renderer.OpenGLState; import electrosphere.renderer.RenderPipelineState; import electrosphere.renderer.RenderingEngine; import electrosphere.renderer.actor.Actor; -import electrosphere.renderer.debug.DebugRendering; import electrosphere.renderer.framebuffer.Framebuffer; import electrosphere.renderer.model.Model; import electrosphere.renderer.ui.elementtypes.DraggableElement; +import electrosphere.renderer.ui.elementtypes.ScrollableElement; import electrosphere.renderer.ui.events.DragEvent; import electrosphere.renderer.ui.events.DragEvent.DragEventType; 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 @@ -38,37 +38,138 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme */ 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); + /** + * Color to clear the panel with + */ + Vector4d clearColor = new Vector4d(1.0); + + /** + * The actor to draw + */ Actor actor; + + /** + * The model matrix for the actor panel + */ Matrix4d modelMatrix = new Matrix4d(); + + /** + * The current animation to play + */ String currentAnim; + + /** + * The position of the actor + */ Vector3f actorPosition = new Vector3f(0,0,0); + + /** + * The rotation of the actor + */ Quaterniond actorRotation = new Quaterniond(); + + /** + * The scale of the actor + */ Vector3f actorScale = new Vector3f(1,1,1); + + /** + * The FOV of the panel + */ float FOV = 50.0f; + + /** + * The aspec ratio of the panel + */ float aspectRatio = 1.9f; - + /** + * Used for calculating drawing the panel + */ Vector3f texPosition = new Vector3f(0,0,0); + + /** + * Used for calculating drawing the panel + */ 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 + *

+ * This must be done during draw-phase instead of creation-phase because the model may not exist when creating + *

+ */ + 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; + + /** + * Fires on dragging the panel + */ DragEventCallback onDrag; + + /** + * Fires on releasing dragging thep anel + */ DragEventCallback onDragRelease; - static final Vector3f windowDrawDebugColor = new Vector3f(0.0f,0.0f,1.0f); - - @Deprecated - public ActorPanel(OpenGLState openGLState, int x, int y, int width, int height, Actor actor){ - super(); - - this.actor = actor; - this.setWidth(width); - this.setHeight(height); - this.aspectRatio = (float)width / (float)height; - recalculateModelMatrix(); - } + /** + * Fires when a scrollable event occurs + */ + ScrollEventCallback onScroll; /** * Constructor @@ -113,14 +214,14 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme RenderingEngine.setAspectRatio(aspectRatio); openGLState.glDepthTest(true); - openGLState.glDepthFunc(GL_LESS); - glDepthMask(true); + openGLState.glDepthFunc(GL40.GL_LESS); + GL40.glDepthMask(true); - glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GL40.glClearColor((float)clearColor.x, (float)clearColor.y, (float)clearColor.z, (float)clearColor.w); + GL40.glClear(GL40.GL_COLOR_BUFFER_BIT | GL40.GL_DEPTH_BUFFER_BIT); + Model actorModel = Globals.assetManager.fetchModel(actor.getModelPath()); - if(currentAnim != null){ if((!actor.isPlayingAnimation() || !actor.isPlayingAnimation(currentAnim)) && actorModel != null && @@ -130,6 +231,24 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme 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 @@ -138,7 +257,7 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme renderPipelineState.setBufferStandardUniforms(true); renderPipelineState.setBufferNonStandardUniforms(true); renderPipelineState.setUseMaterial(true); - renderPipelineState.setUseShadowMap(true); + renderPipelineState.setUseShadowMap(false); renderPipelineState.setUseBones(true); renderPipelineState.setUseLight(true); @@ -146,7 +265,6 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme - actor.applySpatialData(modelMatrix,new Vector3d(actorPosition)); actor.draw(renderPipelineState,openGLState); @@ -201,58 +319,141 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme } else { 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){ currentAnim = animation; } + /** + * Sets the position of the actor panel's actor + * @param position The position + */ public void setPosition(Vector3f position){ this.actorPosition.set(position); recalculateModelMatrix(); } + /** + * Sets the rotation of the actor panel's actor + * @param rotation The rotation + */ public void setRotation(Quaterniond rotation){ this.actorRotation.set(rotation); recalculateModelMatrix(); } + /** + * Sets the scale of the actor panel's actor + * @param scale The scale + */ public void setScale(Vector3f scale){ this.actorScale.set(scale); recalculateModelMatrix(); } - void recalculateModelMatrix(){ + /** + * Recalculates the model matrix + */ + private void recalculateModelMatrix(){ modelMatrix.identity(); - modelMatrix.translate(actorPosition); + modelMatrix.translate(new Vector3d(actorPosition).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera))); modelMatrix.rotate(actorRotation); modelMatrix.scale(new Vector3d(actorScale)); 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){ boolean propagate = true; if(event instanceof DragEvent){ - if(onDragStart != null && ((DragEvent)event).getType() == DragEventType.START){ - if(!onDragStart.execute((DragEvent)event)){ + DragEvent dragEvent = (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; } } - if(onDrag != null && ((DragEvent)event).getType() == DragEventType.DRAG){ - if(!onDrag.execute((DragEvent)event)){ - propagate = false; + if(dragEvent.getType() == DragEventType.RELEASE){ + if(onDragRelease != null){ + 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; } + } 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; @@ -272,6 +473,11 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme public void setOnDragRelease(DragEventCallback callback) { onDragRelease = callback; } + + @Override + public void setOnScrollCallback(ScrollEventCallback callback) { + onScroll = callback; + } diff --git a/src/main/java/electrosphere/renderer/ui/events/ScrollEvent.java b/src/main/java/electrosphere/renderer/ui/events/ScrollEvent.java index b7a22a33..dee09abb 100644 --- a/src/main/java/electrosphere/renderer/ui/events/ScrollEvent.java +++ b/src/main/java/electrosphere/renderer/ui/events/ScrollEvent.java @@ -11,6 +11,9 @@ public class ScrollEvent implements Event { double mouseX; double mouseY; + int relativeX; + int relativeY; + /** * Constructor * @param scrollAmount @@ -19,6 +22,8 @@ public class ScrollEvent implements Event { this.scrollAmount = scrollAmount; this.mouseX = mouseX; this.mouseY = mouseY; + this.relativeX = (int)mouseX; + this.relativeY = (int)mouseY; } /** @@ -45,5 +50,21 @@ public class ScrollEvent implements Event { 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; + } + }