Proper frustum culling
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
1883ffddf3
commit
5356b3e325
@ -1,3 +1,3 @@
|
||||
#maven.buildNumber.plugin properties file
|
||||
#Thu Feb 29 11:18:06 EST 2024
|
||||
buildNumber=29
|
||||
#Thu Feb 29 18:57:13 EST 2024
|
||||
buildNumber=30
|
||||
|
||||
9
docs/src/rendering/actors/actorsindex.md
Normal file
9
docs/src/rendering/actors/actorsindex.md
Normal file
@ -0,0 +1,9 @@
|
||||
@page actorsindex Actors
|
||||
|
||||
[TOC]
|
||||
- @subpage texturemask
|
||||
- @subpage bonerotators
|
||||
- @subpage staticmorph
|
||||
- @subpage shadermask
|
||||
- @subpage animationmask
|
||||
- @subpage meshmask
|
||||
5
docs/src/rendering/actors/animationmask.md
Normal file
5
docs/src/rendering/actors/animationmask.md
Normal file
@ -0,0 +1,5 @@
|
||||
@page animationmask Animation Mask
|
||||
|
||||
TODO
|
||||
|
||||
use example: play running animation for whole actor, but then mask crafting animation on top of bones from torso up
|
||||
5
docs/src/rendering/actors/bonerotators.md
Normal file
5
docs/src/rendering/actors/bonerotators.md
Normal file
@ -0,0 +1,5 @@
|
||||
@page bonerotators Actor Bone Rotators
|
||||
|
||||
TODO
|
||||
|
||||
use example: rotate torso to tilt based on whatever the player is locked on to, so that they swing at goblins below them and harpies above them
|
||||
5
docs/src/rendering/actors/meshmask.md
Normal file
5
docs/src/rendering/actors/meshmask.md
Normal file
@ -0,0 +1,5 @@
|
||||
@page meshmask Mesh Mask
|
||||
|
||||
TODO
|
||||
|
||||
use example: overwriting a mesh without clothing to one with clothing
|
||||
5
docs/src/rendering/actors/shadermask.md
Normal file
5
docs/src/rendering/actors/shadermask.md
Normal file
@ -0,0 +1,5 @@
|
||||
@page shadermask Shader Mask
|
||||
|
||||
TODO
|
||||
|
||||
use example: override default cube shader to use a shader that does raymarching
|
||||
5
docs/src/rendering/actors/staticmorph.md
Normal file
5
docs/src/rendering/actors/staticmorph.md
Normal file
@ -0,0 +1,5 @@
|
||||
@page staticmorph Actor Static Morph
|
||||
|
||||
TODO
|
||||
|
||||
use example: scale something that was exported from blender waayyyyyy too large
|
||||
3
docs/src/rendering/actors/texturemask.md
Normal file
3
docs/src/rendering/actors/texturemask.md
Normal file
@ -0,0 +1,3 @@
|
||||
@page texturemask Actor Texture Mask
|
||||
|
||||
TODO
|
||||
@ -90,7 +90,7 @@ public class FoliageCell {
|
||||
instancedActor.setPriority((int)grassPosition.distance(playerPosition));
|
||||
|
||||
//draw
|
||||
instancedActor.draw(Globals.renderingEngine.getRenderPipelineState());
|
||||
instancedActor.draw(Globals.renderingEngine.getRenderPipelineState(), new Vector3d(cameraModifiedPosition));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
package electrosphere.client.instancing;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityTags;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.types.camera.CameraEntityUtils;
|
||||
import electrosphere.renderer.actor.instance.InstancedActor;
|
||||
|
||||
/**
|
||||
* Used for updating instance priority
|
||||
*/
|
||||
public class InstanceUpdater {
|
||||
|
||||
/**
|
||||
* Updates all instanced actors to have priority based on distance from camera
|
||||
*/
|
||||
public static void updateInstancedActorPriority(){
|
||||
Vector3d eyePosition = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera));
|
||||
for(Entity entity : Globals.clientScene.getEntitiesWithTag(EntityTags.DRAW_INSTANCED)){
|
||||
//set priority equal to distance
|
||||
Vector3d entityPosition = EntityUtils.getPosition(entity);
|
||||
InstancedActor.getInstancedActor(entity).setPriority((int)entityPosition.distance(eyePosition));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package electrosphere.client.sim;
|
||||
|
||||
import electrosphere.client.instancing.InstanceUpdater;
|
||||
import electrosphere.client.terrain.manager.ClientTerrainManager;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
@ -28,6 +29,7 @@ public class ClientFunctions {
|
||||
ClientTerrainManager.generateTerrainChunkGeometry();
|
||||
updateSkyboxPos();
|
||||
Globals.clientSceneWrapper.destroyEntitiesOutsideSimRange();
|
||||
InstanceUpdater.updateInstancedActorPriority();
|
||||
// updateCellManager();
|
||||
}
|
||||
|
||||
|
||||
@ -74,10 +74,6 @@ public class ClientSimulation {
|
||||
}
|
||||
//clear collidable impulse lists
|
||||
Globals.clientSceneWrapper.getCollisionEngine().clearCollidableImpulseLists();
|
||||
//delete all client side entities that aren't in visible chunks
|
||||
if(Globals.clientEntityCullingManager != null){
|
||||
Globals.clientEntityCullingManager.clearOutOfBoundsEntities();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -23,7 +23,7 @@ import electrosphere.entity.types.terrain.TerrainChunkData;
|
||||
public class CollisionBodyCreation {
|
||||
|
||||
//Matrix for correcting initial axis of eg cylinders or capsules
|
||||
static final DMatrix3 AXIS_CORRECTION_MATRIX = new DMatrix3(
|
||||
public static final DMatrix3 AXIS_CORRECTION_MATRIX = new DMatrix3(
|
||||
1.0000000, 0.0000000, 0.0000000,
|
||||
0.0000000, 0.0000000, -1.0000000,
|
||||
0.0000000, 1.0000000, 0.0000000
|
||||
@ -65,7 +65,7 @@ public class CollisionBodyCreation {
|
||||
public static DBody createCylinderBody(CollisionEngine collisionEngine, double radius, double length){
|
||||
DCylinder geom = collisionEngine.createCylinderGeom(radius,length);
|
||||
DBody returnBody = collisionEngine.createDBody(geom);
|
||||
geom.setOffsetRotation(AXIS_CORRECTION_MATRIX); //ode4j required geom to already be on body before rotating for some reason
|
||||
collisionEngine.setOffsetRotation(geom); //ode4j required geom to already be on body before rotating for some reason
|
||||
return returnBody;
|
||||
}
|
||||
|
||||
|
||||
@ -671,6 +671,16 @@ public class CollisionEngine {
|
||||
spaceLock.release();
|
||||
}
|
||||
|
||||
/**
|
||||
* Corrects the initial axis of eg cylinders or capsules
|
||||
* @param geom the geometry to correct
|
||||
*/
|
||||
protected void setOffsetRotation(DGeom geom){
|
||||
spaceLock.acquireUninterruptibly();
|
||||
geom.setOffsetRotation(CollisionBodyCreation.AXIS_CORRECTION_MATRIX);
|
||||
spaceLock.release();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the position of the body in a thread-safe way
|
||||
* @param body The body to get the position of
|
||||
|
||||
@ -25,6 +25,7 @@ import java.util.Map;
|
||||
import org.joml.Matrix4d;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Sphered;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4d;
|
||||
@ -114,6 +115,9 @@ public class Mesh {
|
||||
|
||||
Material material;
|
||||
|
||||
//the bounding sphere for this mesh
|
||||
Sphered boundingSphere;
|
||||
|
||||
public static Mesh create_mesh_from_aimesh(AIMesh mesh, ModelPretransforms.MeshMetadata metadata){
|
||||
boolean has_bones = false;
|
||||
boolean apply_lighting = true;
|
||||
@ -184,6 +188,7 @@ public class Mesh {
|
||||
float x = vertex.x();
|
||||
float y = vertex.y();
|
||||
float z = vertex.z();
|
||||
//store dimensions of the model
|
||||
if(definedDimensions){
|
||||
if(x < minX){ minX = x; }
|
||||
if(x > maxX){ maxX = x; }
|
||||
@ -197,6 +202,12 @@ public class Mesh {
|
||||
minY = maxY = y;
|
||||
minZ = maxZ = z;
|
||||
}
|
||||
//update bounding sphere
|
||||
double dist = Math.sqrt(x*x+y*y+z*z);
|
||||
if(dist > rVal.boundingSphere.r){
|
||||
rVal.boundingSphere.r = dist;
|
||||
}
|
||||
//store vertex data
|
||||
Vector4d transformedVertex = vertexPretransform.transform(new Vector4d(x,y,z,1.0));
|
||||
transformedVertex.w = 1.0;
|
||||
temp[0] = (float)transformedVertex.x;
|
||||
@ -456,7 +467,7 @@ public class Mesh {
|
||||
|
||||
|
||||
public Mesh(){
|
||||
|
||||
this.boundingSphere = new Sphered();
|
||||
}
|
||||
|
||||
|
||||
@ -745,4 +756,26 @@ public class Mesh {
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the bounding sphere of the mesh
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param r
|
||||
*/
|
||||
public void updateBoundingSphere(float x, float y, float z, float r){
|
||||
this.boundingSphere.x = x;
|
||||
this.boundingSphere.y = y;
|
||||
this.boundingSphere.z = z;
|
||||
this.boundingSphere.r = r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bounding sphere of this mesh
|
||||
* @return The bounding sphere
|
||||
*/
|
||||
public Sphered getBoundingSphere(){
|
||||
return this.boundingSphere;
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Sphered;
|
||||
import org.joml.Vector3d;
|
||||
import org.lwjgl.assimp.AIAnimation;
|
||||
import org.lwjgl.assimp.AIBone;
|
||||
@ -72,6 +73,15 @@ public class Model {
|
||||
Map<String,ActorShaderMask> shaderMask = new HashMap<String,ActorShaderMask>();
|
||||
Map<String,ActorTextureMask> textureMap = null;
|
||||
|
||||
//The bounding sphere for this particular model
|
||||
Sphered boundingSphere;
|
||||
|
||||
/**
|
||||
* Loads a model from an ai scene object
|
||||
* @param path The path of the model
|
||||
* @param s the ai scene
|
||||
* @return The model object
|
||||
*/
|
||||
public static Model createModelFromAiscene(String path, AIScene s){
|
||||
Model rVal = new Model();
|
||||
//
|
||||
@ -100,6 +110,10 @@ public class Model {
|
||||
Mesh currentMesh = Mesh.create_mesh_from_aimesh(aiMesh, meshMetadata);
|
||||
rVal.meshes.add(currentMesh);
|
||||
currentMesh.parent = rVal;
|
||||
//update model bounding sphere
|
||||
if(currentMesh.boundingSphere.r > rVal.boundingSphere.r){
|
||||
rVal.boundingSphere.r = currentMesh.boundingSphere.r;
|
||||
}
|
||||
}
|
||||
//
|
||||
//register bones
|
||||
@ -211,6 +225,7 @@ public class Model {
|
||||
modelMatrix = new Matrix4d();
|
||||
program = null;
|
||||
globalInverseTransform = null;
|
||||
this.boundingSphere = new Sphered();
|
||||
}
|
||||
|
||||
public void free() {
|
||||
@ -532,4 +547,20 @@ public class Model {
|
||||
mesh.setMaterial(material);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bounding sphere for this model
|
||||
* @return The bounding sphere
|
||||
*/
|
||||
public Sphered getBoundingSphere(){
|
||||
return boundingSphere;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bounding sphere
|
||||
* @param boundingSphere The bounding sphere to be stored
|
||||
*/
|
||||
public void setBoundingSphere(Sphered boundingSphere){
|
||||
this.boundingSphere = boundingSphere;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
package electrosphere.renderer;
|
||||
|
||||
import org.joml.FrustumIntersection;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
import electrosphere.renderer.actor.instance.InstanceData;
|
||||
|
||||
/**
|
||||
@ -53,6 +56,9 @@ public class RenderPipelineState {
|
||||
//The pointer to the current shader program bound
|
||||
int currentShaderPointer;
|
||||
|
||||
//JOML-provided object to perform frustum culling
|
||||
FrustumIntersection frustumInt = new FrustumIntersection();
|
||||
|
||||
public boolean getUseMeshShader(){
|
||||
return this.useMeshShader;
|
||||
}
|
||||
@ -141,4 +147,24 @@ public class RenderPipelineState {
|
||||
this.currentShaderPointer = currentShaderPointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the frustum intersection with the provided projection and view matrices
|
||||
* @param projectionMatrix the projection matrix
|
||||
* @param viewMatrix the view matrix
|
||||
*/
|
||||
public void updateFrustumIntersection(Matrix4f projectionMatrix, Matrix4f viewMatrix){
|
||||
Matrix4f projectionViewMatrix = new Matrix4f();
|
||||
projectionViewMatrix.set(projectionMatrix);
|
||||
projectionViewMatrix.mul(viewMatrix);
|
||||
this.frustumInt.set(projectionViewMatrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current render pipeline's frustum intersection object
|
||||
* @return The frustum intersection object
|
||||
*/
|
||||
public FrustumIntersection getFrustumIntersection(){
|
||||
return frustumInt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -65,6 +65,7 @@ import org.joml.Matrix4d;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Sphered;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.lwjgl.BufferUtils;
|
||||
@ -182,8 +183,6 @@ public class RenderingEngine {
|
||||
|
||||
LightManager lightManager;
|
||||
|
||||
static float currentViewPlanarAngle;
|
||||
|
||||
ShaderProgram activeProgram;
|
||||
|
||||
static int outputFramebuffer = 0;
|
||||
@ -192,6 +191,7 @@ public class RenderingEngine {
|
||||
static float aspectRatio = 1.0f;
|
||||
static float verticalFOV = 90.0f;
|
||||
|
||||
//the current state of the rendering pipeline
|
||||
static RenderPipelineState renderPipelineState = new RenderPipelineState();
|
||||
|
||||
|
||||
@ -409,32 +409,22 @@ public class RenderingEngine {
|
||||
return origin.distance(target);
|
||||
}
|
||||
|
||||
|
||||
static boolean drawPoint(Vector3f cameraPos, Vector3f position){
|
||||
boolean rVal = true;
|
||||
float phi = (float)Math.abs((calculateAngle(cameraPos,position) - currentViewPlanarAngle) % (Math.PI * 2.0f));
|
||||
if(phi > Math.PI){
|
||||
phi = (float)(Math.PI * 2) - phi;
|
||||
}
|
||||
float rotationalDiff = phi;
|
||||
float dist = calculateDist(new Vector3f(cameraPos.x,0,cameraPos.z), new Vector3f(position.x,0,position.z));
|
||||
if(rotationalDiff > (Globals.verticalFOV / 180 * Math.PI) && dist > 300){
|
||||
rVal = false;
|
||||
}
|
||||
return rVal;
|
||||
}
|
||||
|
||||
void calculateRenderingAngle(){
|
||||
currentViewPlanarAngle = calculateAngle(CameraEntityUtils.getCameraEye(Globals.playerCamera), new Vector3f(0,0,0));
|
||||
// System.out.println(currentViewPlanarAngle);
|
||||
/**
|
||||
* Updates the frustum box of the render pipeline
|
||||
*/
|
||||
void updateFrustumBox(){
|
||||
renderPipelineState.updateFrustumIntersection(Globals.projectionMatrix, Globals.viewMatrix);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Main function to draw the screen
|
||||
*/
|
||||
public void drawScreen(){
|
||||
|
||||
//calculate render angle for frustum culling
|
||||
if(Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT){
|
||||
calculateRenderingAngle();
|
||||
updateFrustumBox();
|
||||
}
|
||||
|
||||
//
|
||||
@ -581,7 +571,6 @@ public class RenderingEngine {
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
if(
|
||||
(boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) &&
|
||||
drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z)) &&
|
||||
currentEntity.containsKey(EntityDataStrings.DRAW_CAST_SHADOW)
|
||||
){
|
||||
//fetch actor
|
||||
@ -658,8 +647,7 @@ public class RenderingEngine {
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
if(
|
||||
(boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) &&
|
||||
currentEntity.getData(EntityDataStrings.DRAW_SOLID_PASS) != null &&
|
||||
drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z))
|
||||
currentEntity.getData(EntityDataStrings.DRAW_SOLID_PASS) != null
|
||||
){
|
||||
//fetch actor
|
||||
Actor currentActor = EntityUtils.getActor(currentEntity);
|
||||
@ -679,8 +667,7 @@ public class RenderingEngine {
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
if(
|
||||
currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) != null &&
|
||||
currentEntity.getData(EntityDataStrings.DRAW_SOLID_PASS) != null &&
|
||||
drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z))
|
||||
currentEntity.getData(EntityDataStrings.DRAW_SOLID_PASS) != null
|
||||
){
|
||||
//fetch actor
|
||||
InstancedActor currentActor = InstancedActor.getInstancedActor(currentEntity);
|
||||
@ -696,15 +683,13 @@ public class RenderingEngine {
|
||||
new Quaternionf((float)rotation.x,(float)rotation.y,(float)rotation.z,(float)rotation.w),
|
||||
new Vector3f(EntityUtils.getScale(currentEntity))
|
||||
);
|
||||
// modelTransformMatrix.translate(cameraModifiedPosition);
|
||||
// modelTransformMatrix.rotate(rotation);
|
||||
// modelTransformMatrix.scale(new Vector3d(EntityUtils.getScale(currentEntity)));
|
||||
//set actor value
|
||||
currentActor.setAttribute(modelAttribute, new Matrix4f(modelTransformMatrix));
|
||||
// ((Matrix4f)currentActor.getAttributeValue(modelAttribute)).set(modelTransformMatrix);
|
||||
//draw
|
||||
currentActor.draw(renderPipelineState, new Vector3d(cameraModifiedPosition));
|
||||
} else {
|
||||
currentActor.draw(renderPipelineState);
|
||||
}
|
||||
//draw
|
||||
currentActor.draw(renderPipelineState);
|
||||
}
|
||||
}
|
||||
//draw all instanced models
|
||||
@ -747,8 +732,7 @@ public class RenderingEngine {
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
if(
|
||||
(boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) &&
|
||||
currentEntity.getData(EntityDataStrings.DRAW_TRANSPARENT_PASS) != null &&
|
||||
drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z))
|
||||
currentEntity.getData(EntityDataStrings.DRAW_TRANSPARENT_PASS) != null
|
||||
){
|
||||
//fetch actor
|
||||
Actor currentActor = EntityUtils.getActor(currentEntity);
|
||||
@ -768,13 +752,27 @@ public class RenderingEngine {
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
if(
|
||||
currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) != null &&
|
||||
currentEntity.getData(EntityDataStrings.DRAW_TRANSPARENT_PASS) != null &&
|
||||
drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z))
|
||||
currentEntity.getData(EntityDataStrings.DRAW_TRANSPARENT_PASS) != null
|
||||
){
|
||||
//fetch actor
|
||||
InstancedActor currentActor = InstancedActor.getInstancedActor(currentEntity);
|
||||
//draw
|
||||
if(currentActor != null){
|
||||
//if the shader attribute for model matrix exists, calculate the model matrix and apply
|
||||
if(InstancedActor.getInstanceModelAttribute(currentEntity) != null){
|
||||
ShaderAttribute modelAttribute = InstancedActor.getInstanceModelAttribute(currentEntity);
|
||||
//calculate model matrix
|
||||
Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
|
||||
Quaterniond rotation = EntityUtils.getRotation(currentEntity);
|
||||
// modelTransformMatrix.identity();
|
||||
modelTransformMatrix.identity().translationRotateScale(
|
||||
cameraModifiedPosition,
|
||||
new Quaternionf((float)rotation.x,(float)rotation.y,(float)rotation.z,(float)rotation.w),
|
||||
new Vector3f(EntityUtils.getScale(currentEntity))
|
||||
);
|
||||
//set actor value
|
||||
currentActor.setAttribute(modelAttribute, new Matrix4f(modelTransformMatrix));
|
||||
//draw
|
||||
currentActor.draw(renderPipelineState, new Vector3d(cameraModifiedPosition));
|
||||
} else {
|
||||
currentActor.draw(renderPipelineState);
|
||||
}
|
||||
}
|
||||
@ -833,8 +831,7 @@ public class RenderingEngine {
|
||||
for(Entity currentEntity : Globals.clientScene.getEntitiesWithTag(EntityTags.DRAWABLE)){
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
if(
|
||||
(boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) &&
|
||||
drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z))
|
||||
(boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW)
|
||||
){
|
||||
//fetch actor
|
||||
Actor currentActor = EntityUtils.getActor(currentEntity);
|
||||
@ -1080,8 +1077,7 @@ public class RenderingEngine {
|
||||
if(
|
||||
(boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) &&
|
||||
currentEntity.getData(EntityDataStrings.DRAW_SOLID_PASS) != null &&
|
||||
currentEntity.getData(EntityDataStrings.DRAW_OUTLINE) != null &&
|
||||
drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z))
|
||||
currentEntity.getData(EntityDataStrings.DRAW_OUTLINE) != null
|
||||
){
|
||||
//fetch actor
|
||||
Actor currentActor = EntityUtils.getActor(currentEntity);
|
||||
@ -1334,7 +1330,6 @@ public class RenderingEngine {
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
if(
|
||||
(boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) &&
|
||||
drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z)) &&
|
||||
currentEntity.containsKey(EntityDataStrings.DRAW_VOLUMETRIC)
|
||||
){
|
||||
//fetch actor
|
||||
@ -1372,7 +1367,6 @@ public class RenderingEngine {
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
if(
|
||||
(boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) &&
|
||||
drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z)) &&
|
||||
!currentEntity.containsKey(EntityDataStrings.DRAW_VOLUMETRIC)
|
||||
){
|
||||
//fetch actor
|
||||
@ -1421,7 +1415,6 @@ public class RenderingEngine {
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
if(
|
||||
(boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) &&
|
||||
drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z)) &&
|
||||
currentEntity.containsKey(EntityDataStrings.DRAW_VOLUMETRIC)
|
||||
){
|
||||
//fetch actor
|
||||
|
||||
@ -17,23 +17,50 @@ import org.joml.Matrix4d;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Sphered;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4d;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author amaterasu
|
||||
* An actor
|
||||
* Container for a model that keeps track of:
|
||||
* - Animation state
|
||||
* - Mesh overrides
|
||||
* - Shader overrides
|
||||
* - Texture overrides
|
||||
* - Bone overrides
|
||||
* - Static Morphs (think scaling something, but from creatures.json)
|
||||
*/
|
||||
public class Actor {
|
||||
|
||||
//the model path of the model backing the actor
|
||||
String modelPath;
|
||||
|
||||
//used for statically binding textures in pipelines that dont bind textures on a per-mesh level
|
||||
//ie when in the ui, this can be set to bind a texture at the actor level
|
||||
String textureOverride;
|
||||
|
||||
//scales the time that animations are played at
|
||||
float animationScalar = 1.0f;
|
||||
|
||||
//The stack of animations being applied to a given actor
|
||||
PriorityQueue<ActorAnimationMask> animationQueue = new PriorityQueue<ActorAnimationMask>();
|
||||
|
||||
//Mask for overwriting meshes in a given actor
|
||||
ActorMeshMask meshMask = new ActorMeshMask();
|
||||
|
||||
//optional overrides for specific shaders
|
||||
List<ActorShaderMask> shaderMasks = new LinkedList<ActorShaderMask>();
|
||||
|
||||
//optional overrides for textures
|
||||
Map<String,ActorTextureMask> textureMap = null;
|
||||
|
||||
//bone rotators
|
||||
Map<String,ActorBoneRotator> boneRotators = new HashMap<String,ActorBoneRotator>();
|
||||
|
||||
//static morph for this specific actor
|
||||
ActorStaticMorph staticMorph;
|
||||
|
||||
public Actor(String modelPath){
|
||||
@ -52,18 +79,6 @@ public class Actor {
|
||||
for(ActorAnimationMask mask : toRemoveMasks){
|
||||
animationQueue.remove(mask);
|
||||
}
|
||||
// if(playingAnimation){
|
||||
// animationTime = animationTime + deltaTime * animationScalar;
|
||||
// }
|
||||
// if(model != null){
|
||||
// if(animation != null){
|
||||
// model.playAnimation(animation);
|
||||
// model.incrementTime(animationTime);
|
||||
// if(model.currentAnimation == null){
|
||||
// playingAnimation = false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
public double getAnimationTime(String animationName){
|
||||
@ -100,10 +115,6 @@ public class Actor {
|
||||
}
|
||||
}
|
||||
|
||||
// public String getCurrentAnimation(){
|
||||
// return animation;
|
||||
// }
|
||||
|
||||
public void playAnimation(String animationName, int priority){
|
||||
// animationTime = 0;
|
||||
// playingAnimation = true;
|
||||
@ -170,10 +181,6 @@ public class Actor {
|
||||
model.updateNodeTransform(boneRotators,staticMorph);
|
||||
}
|
||||
|
||||
// public boolean isPlayingAnimation(){
|
||||
// return playingAnimation;
|
||||
// }
|
||||
|
||||
public void setAnimationScalar(float animationScalar) {
|
||||
this.animationScalar = animationScalar;
|
||||
}
|
||||
@ -185,10 +192,14 @@ public class Actor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws an actor
|
||||
* @param renderPipelineState The render pipeline state to draw within
|
||||
*/
|
||||
public void draw(RenderPipelineState renderPipelineState){
|
||||
Model model = Globals.assetManager.fetchModel(modelPath);
|
||||
boolean hasDrawn = false;
|
||||
if(model != null){
|
||||
if(model != null && isWithinFrustumBox(renderPipelineState,model)){
|
||||
applyAnimationMasks(model);
|
||||
meshMask.processMeshMaskQueue();
|
||||
model.setMeshMask(meshMask);
|
||||
@ -353,5 +364,17 @@ public class Actor {
|
||||
return this.staticMorph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given model is within the render pipeline state's frustum box
|
||||
* @param renderPipelineState The render pipeline state
|
||||
* @param model The model
|
||||
* @return true if it is within the box, false otherwise
|
||||
*/
|
||||
static boolean isWithinFrustumBox(RenderPipelineState renderPipelineState, Model model){
|
||||
Sphered sphere = model.getBoundingSphere();
|
||||
Vector3d modelPosition = model.modelMatrix.getTranslation(new Vector3d());
|
||||
return renderPipelineState.getFrustumIntersection().testSphere((float)(sphere.x + modelPosition.x), (float)(sphere.y + modelPosition.y), (float)(sphere.z + modelPosition.z), (float)sphere.r);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,10 @@ package electrosphere.renderer.actor;
|
||||
|
||||
import org.joml.Quaternionf;
|
||||
|
||||
/**
|
||||
* Optional rotation to be applied to a bone that can be programmatically controlled and applied alongside another animation.
|
||||
* For instance, having a character look at something, turn their torso mid animation, or hair rotating around.
|
||||
*/
|
||||
public class ActorBoneRotator {
|
||||
|
||||
Quaternionf rotation = new Quaternionf().identity();
|
||||
|
||||
@ -7,6 +7,10 @@ import org.joml.Matrix4f;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
/**
|
||||
* A static morph that is applied to an actor if it is defined in a pipeline creating an actor.
|
||||
* For instance, if you provide a static morph for the model in an item in creatures.json, this is the structure that will actually hold that data
|
||||
*/
|
||||
public class ActorStaticMorph {
|
||||
|
||||
Map<String,StaticMorphTransforms> boneTransformMap = new HashMap<String,StaticMorphTransforms>();
|
||||
|
||||
@ -3,11 +3,15 @@ package electrosphere.renderer.actor.instance;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
|
||||
import org.joml.Matrix4d;
|
||||
import org.joml.Matrix4f;
|
||||
@ -37,8 +41,8 @@ public class InstanceData {
|
||||
//the number of draw calls since the last clear operation
|
||||
int drawCalls = 0;
|
||||
|
||||
//The priority queue of instanced actors to draw
|
||||
PriorityQueue<InstancedActor> actorQueue = null;
|
||||
//The set of instanced actors to draw
|
||||
List<InstancedActor> actorQueue = null;
|
||||
//Map of actor to index in the buffers that are emitted
|
||||
Map<InstancedActor,Integer> actorIndexMap = new HashMap<InstancedActor,Integer>();
|
||||
//Map of index -> actor used for buffer evictions
|
||||
@ -60,7 +64,7 @@ public class InstanceData {
|
||||
this.capacity = capacity;
|
||||
this.vertexShaderPath = vertexPath;
|
||||
this.fragmentShaderPath = fragmentPath;
|
||||
actorQueue = new PriorityQueue<InstancedActor>(this.capacity);
|
||||
actorQueue = new LinkedList<InstancedActor>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -179,6 +183,7 @@ public class InstanceData {
|
||||
} break;
|
||||
}
|
||||
}
|
||||
actorQueue.sort(Comparator.naturalOrder());
|
||||
//buffer data
|
||||
for(InstancedActor actor : actorQueue){
|
||||
//push values to attribute buffers
|
||||
|
||||
@ -6,11 +6,14 @@ import java.util.Map;
|
||||
|
||||
import org.joml.Matrix4d;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Sphered;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.renderer.Model;
|
||||
import electrosphere.renderer.RenderPipelineState;
|
||||
@ -41,6 +44,23 @@ public class InstancedActor implements Comparable<InstancedActor> {
|
||||
/**
|
||||
* Draws the instanced actor. Should be called normally in a loop as if this was a regular actor.
|
||||
* @param renderPipelineState The pipeline state of the instanced actor
|
||||
* @param position The position used for frustum checking
|
||||
*/
|
||||
public void draw(RenderPipelineState renderPipelineState, Vector3d position){
|
||||
Model model = Globals.assetManager.fetchModel(modelPath);
|
||||
if(model != null){
|
||||
Sphered boundingSphere = model.getBoundingSphere();
|
||||
//frustum check if the model matrix exists (and we therefore can get position)
|
||||
boolean frustumCheck = renderPipelineState.getFrustumIntersection().testSphere((float)(position.x + boundingSphere.x), (float)(position.y + boundingSphere.y), (float)(position.z + boundingSphere.z), (float)boundingSphere.r);
|
||||
if(frustumCheck){
|
||||
Globals.clientInstanceManager.addToQueue(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the instanced actor WITHOUT frustum checking. Otherwise identical to the call with frustum checking
|
||||
* @param renderPipelineState
|
||||
*/
|
||||
public void draw(RenderPipelineState renderPipelineState){
|
||||
Model model = Globals.assetManager.fetchModel(modelPath);
|
||||
|
||||
@ -25,6 +25,7 @@ import electrosphere.renderer.Material;
|
||||
import electrosphere.renderer.Mesh;
|
||||
import electrosphere.renderer.Model;
|
||||
import electrosphere.renderer.ShaderProgram;
|
||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||
|
||||
public class TerrainChunkModelGeneration {
|
||||
|
||||
@ -775,6 +776,13 @@ public class TerrainChunkModelGeneration {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
float halfChunk = ServerTerrainChunk.CHUNK_DIMENSION / 2.0f;
|
||||
mesh.updateBoundingSphere(
|
||||
halfChunk,
|
||||
halfChunk,
|
||||
halfChunk,
|
||||
(float)Math.sqrt(halfChunk * halfChunk + halfChunk * halfChunk + halfChunk * halfChunk)
|
||||
);
|
||||
|
||||
|
||||
|
||||
@ -805,6 +813,7 @@ public class TerrainChunkModelGeneration {
|
||||
m.parent = rVal;
|
||||
|
||||
rVal.meshes.add(m);
|
||||
rVal.setBoundingSphere(m.getBoundingSphere());
|
||||
|
||||
return rVal;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user