support for low lod models definitions and pipe
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
This commit is contained in:
parent
6e55b7ee18
commit
ae72912649
@ -588,7 +588,8 @@
|
||||
"priorityCategory" : "IDLE"
|
||||
}
|
||||
},
|
||||
"path" : "Models/creatures/person2/person2_1.glb"
|
||||
"path" : "Models/creatures/person2/person2_1.glb",
|
||||
"lodPath": "Models/creatures/person2/person2_1_lod.glb"
|
||||
}
|
||||
},
|
||||
"viewModelData" : {
|
||||
|
||||
BIN
assets/Models/creatures/person2/person2_1_lod.glb
Normal file
BIN
assets/Models/creatures/person2/person2_1_lod.glb
Normal file
Binary file not shown.
@ -68,6 +68,7 @@ public class PhysicsEntityUtils {
|
||||
if(physicsTemplate.getKinematic()){
|
||||
categoryBit = Collidable.TYPE_STATIC_BIT;
|
||||
}
|
||||
CollisionEngine.lockOde();
|
||||
if(physicsTemplate.getKinematic()){
|
||||
DGeom geom = null;
|
||||
switch(physicsTemplate.getType()){
|
||||
@ -364,6 +365,7 @@ public class PhysicsEntityUtils {
|
||||
ClientPhysicsSyncTree.attachTree(rVal);
|
||||
}
|
||||
}
|
||||
CollisionEngine.unlockOde();
|
||||
}
|
||||
|
||||
|
||||
@ -383,6 +385,7 @@ public class PhysicsEntityUtils {
|
||||
if(physicsTemplate.getKinematic()){
|
||||
categoryBit = Collidable.TYPE_STATIC_BIT;
|
||||
}
|
||||
CollisionEngine.lockOde();
|
||||
if(physicsTemplate.getKinematic()){
|
||||
DGeom geom = null;
|
||||
switch(physicsTemplate.getType()){
|
||||
@ -686,6 +689,7 @@ public class PhysicsEntityUtils {
|
||||
ServerPhysicsSyncTree.attachTree(rVal);
|
||||
}
|
||||
}
|
||||
CollisionEngine.unlockOde();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -31,6 +31,11 @@ public class NonproceduralModel {
|
||||
*/
|
||||
private Map<String,Vector3f> meshColorMap;
|
||||
|
||||
/**
|
||||
* The path to the lower-resolution model
|
||||
*/
|
||||
private String lodPath;
|
||||
|
||||
/**
|
||||
* Gets the path of the model
|
||||
* @return The path of the model
|
||||
@ -94,6 +99,22 @@ public class NonproceduralModel {
|
||||
public void setMeshColorMap(Map<String,Vector3f> meshColorMap) {
|
||||
this.meshColorMap = meshColorMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path to the lower resolution model
|
||||
* @return The path to the lower resolution model
|
||||
*/
|
||||
public String getLODPath(){
|
||||
return lodPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the path to the lower resolution model
|
||||
* @param lodPath The path to the lower resolution model
|
||||
*/
|
||||
public void setLODPath(String lodPath){
|
||||
this.lodPath = lodPath;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,14 @@
|
||||
package electrosphere.entity;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import electrosphere.data.entity.graphics.NonproceduralModel;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.state.idle.ClientIdleTree;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
|
||||
/**
|
||||
@ -36,4 +45,55 @@ public class DrawableUtils {
|
||||
return entity.containsKey(EntityDataStrings.HAS_UNIQUE_MODEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies non-procedural model data to the entity
|
||||
* @param entity The entity
|
||||
* @param modelData The model data
|
||||
*/
|
||||
public static void applyNonproceduralModel(Entity entity, NonproceduralModel modelData){
|
||||
if(modelData == null){
|
||||
throw new Error("Null model data!");
|
||||
}
|
||||
if(modelData.getPath() == null){
|
||||
throw new Error("Path undefined!");
|
||||
}
|
||||
//make the entity drawable
|
||||
EntityCreationUtils.makeEntityDrawable(entity, modelData.getPath());
|
||||
Actor creatureActor = EntityUtils.getActor(entity);
|
||||
|
||||
//add low-res model path to actor if present
|
||||
if(modelData.getLODPath() != null){
|
||||
creatureActor.setLowResPath(modelData.getLODPath());
|
||||
Globals.assetManager.addModelPathToQueue(modelData.getLODPath());
|
||||
}
|
||||
|
||||
|
||||
//idle tree & generic stuff all entities have
|
||||
if(modelData.getIdleData() != null){
|
||||
ClientIdleTree.attachTree(entity, modelData.getIdleData());
|
||||
}
|
||||
|
||||
//apply uniforms
|
||||
if(modelData.getUniforms() != null){
|
||||
Map<String,Map<String,Object>> meshUniformMap = modelData.getUniforms();
|
||||
Set<String> meshNames = meshUniformMap.keySet();
|
||||
for(String meshName : meshNames){
|
||||
Map<String,Object> uniforms = meshUniformMap.get(meshName);
|
||||
Set<String> uniformNames = uniforms.keySet();
|
||||
for(String uniformName : uniformNames){
|
||||
Object value = uniforms.get(uniformName);
|
||||
creatureActor.setUniformOnMesh(meshName, uniformName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//apply mesh color map
|
||||
if(modelData.getMeshColorMap() != null){
|
||||
Map<String,Vector3f> meshColorMap = modelData.getMeshColorMap();
|
||||
for(Entry<String,Vector3f> entry : meshColorMap.entrySet()){
|
||||
creatureActor.setUniformOnMesh(entry.getKey(), "color", entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,12 +1,7 @@
|
||||
package electrosphere.entity.types.common;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.ode4j.ode.DBody;
|
||||
|
||||
import electrosphere.client.interact.ClientInteractionEngine;
|
||||
@ -31,6 +26,7 @@ import electrosphere.data.entity.graphics.GraphicsTemplate;
|
||||
import electrosphere.data.entity.item.Item;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.engine.assetmanager.PhysicsMeshQueueItem;
|
||||
import electrosphere.entity.DrawableUtils;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityCreationUtils;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
@ -55,7 +51,6 @@ import electrosphere.entity.state.gravity.ServerGravityTree;
|
||||
import electrosphere.entity.state.growth.ClientGrowthComponent;
|
||||
import electrosphere.entity.state.growth.ServerGrowthComponent;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||
import electrosphere.entity.state.idle.ClientIdleTree;
|
||||
import electrosphere.entity.state.idle.ServerIdleTree;
|
||||
import electrosphere.entity.state.inventory.ClientInventoryState;
|
||||
import electrosphere.entity.state.inventory.InventoryUtils;
|
||||
@ -169,32 +164,8 @@ public class CommonEntityUtils {
|
||||
//
|
||||
if(rawType.getGraphicsTemplate() != null){
|
||||
GraphicsTemplate graphicsTemplate = rawType.getGraphicsTemplate();
|
||||
if(graphicsTemplate.getModel() != null && graphicsTemplate.getModel().getPath() != null && EntityUtils.getActor(entity) == null && generateDrawable == true){
|
||||
EntityCreationUtils.makeEntityDrawable(entity, graphicsTemplate.getModel().getPath());
|
||||
}
|
||||
//idle tree & generic stuff all entities have
|
||||
if(graphicsTemplate.getModel() != null && graphicsTemplate.getModel().getIdleData() != null){
|
||||
ClientIdleTree.attachTree(entity, graphicsTemplate.getModel().getIdleData());
|
||||
}
|
||||
if(graphicsTemplate.getModel() != null && graphicsTemplate.getModel().getUniforms() != null){
|
||||
Actor creatureActor = EntityUtils.getActor(entity);
|
||||
Map<String,Map<String,Object>> meshUniformMap = graphicsTemplate.getModel().getUniforms();
|
||||
Set<String> meshNames = meshUniformMap.keySet();
|
||||
for(String meshName : meshNames){
|
||||
Map<String,Object> uniforms = meshUniformMap.get(meshName);
|
||||
Set<String> uniformNames = uniforms.keySet();
|
||||
for(String uniformName : uniformNames){
|
||||
Object value = uniforms.get(uniformName);
|
||||
creatureActor.setUniformOnMesh(meshName, uniformName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(graphicsTemplate.getModel() != null && graphicsTemplate.getModel().getMeshColorMap() != null){
|
||||
Actor creatureActor = EntityUtils.getActor(entity);
|
||||
Map<String,Vector3f> meshColorMap = graphicsTemplate.getModel().getMeshColorMap();
|
||||
for(Entry<String,Vector3f> entry : meshColorMap.entrySet()){
|
||||
creatureActor.setUniformOnMesh(entry.getKey(), "color", entry.getValue());
|
||||
}
|
||||
if(graphicsTemplate.getModel() != null && EntityUtils.getActor(entity) == null && generateDrawable == true){
|
||||
DrawableUtils.applyNonproceduralModel(entity, graphicsTemplate.getModel());
|
||||
}
|
||||
}
|
||||
Actor creatureActor = EntityUtils.getActor(entity);
|
||||
|
||||
@ -44,11 +44,32 @@ public class Actor {
|
||||
*/
|
||||
public static final int INVALID_ANIMATION = -1;
|
||||
|
||||
/**
|
||||
* full-resolution lod level
|
||||
*/
|
||||
public static final int LOD_LEVEL_FULL = 1;
|
||||
|
||||
/**
|
||||
* lower-resolution lod level
|
||||
*/
|
||||
public static final int LOD_LEVEL_LOWER = 0;
|
||||
|
||||
|
||||
/**
|
||||
* the model path of the model backing the actor
|
||||
*/
|
||||
private String modelPath;
|
||||
|
||||
/**
|
||||
* Path to the low res model
|
||||
*/
|
||||
private String lowResPath;
|
||||
|
||||
/**
|
||||
* The LOD level of the actor
|
||||
*/
|
||||
private int lodLevel = Actor.LOD_LEVEL_FULL;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -124,6 +145,16 @@ public class Actor {
|
||||
* Sets scaling applied at the actor level
|
||||
*/
|
||||
private float scale = 1.0f;
|
||||
|
||||
/**
|
||||
* The transform matrix
|
||||
*/
|
||||
private Matrix4d modelMatrix = new Matrix4d();
|
||||
|
||||
/**
|
||||
* The world position vector
|
||||
*/
|
||||
private Vector3d worldPos = new Vector3d();
|
||||
|
||||
/**
|
||||
* Creates an achor
|
||||
@ -438,7 +469,7 @@ public class Actor {
|
||||
* Calculates the node transforms for the actor
|
||||
* @param model The model that backs the actor
|
||||
*/
|
||||
void calculateNodeTransforms(Model model){
|
||||
private void calculateNodeTransforms(Model model){
|
||||
model.updateNodeTransform(boneRotators,staticMorph);
|
||||
for(Bone bone : model.getBones()){
|
||||
//store position
|
||||
@ -478,8 +509,8 @@ public class Actor {
|
||||
public void applySpatialData(Matrix4d modelMatrix, Vector3d worldPos){
|
||||
Model model = Globals.assetManager.fetchModel(modelPath);
|
||||
if(model != null){
|
||||
model.setModelMatrix(modelMatrix);
|
||||
model.setWorldPos(worldPos);
|
||||
this.modelMatrix.set(modelMatrix);
|
||||
this.worldPos.set(worldPos);
|
||||
}
|
||||
}
|
||||
|
||||
@ -489,14 +520,29 @@ public class Actor {
|
||||
*/
|
||||
public void draw(RenderPipelineState renderPipelineState, OpenGLState openGLState){
|
||||
Globals.profiler.beginAggregateCpuSample("Actor.draw");
|
||||
Model model = Globals.assetManager.fetchModel(modelPath);
|
||||
if(model != null && Actor.isWithinFrustumBox(renderPipelineState,model,frustumCull)){
|
||||
|
||||
//fetch the model
|
||||
String pathToFetch = this.modelPath;
|
||||
if(this.lodLevel == Actor.LOD_LEVEL_LOWER && this.lowResPath != null){
|
||||
pathToFetch = this.lowResPath;
|
||||
}
|
||||
Model model = Globals.assetManager.fetchModel(pathToFetch);
|
||||
|
||||
if(model == null){
|
||||
Globals.profiler.endCpuSample();
|
||||
return;
|
||||
}
|
||||
model.setModelMatrix(this.modelMatrix);
|
||||
model.setWorldPos(this.worldPos);
|
||||
|
||||
//frustum cull then draw
|
||||
if(Actor.isWithinFrustumBox(renderPipelineState,model,frustumCull)){
|
||||
this.applyAnimationMasks(model);
|
||||
meshMask.processMeshMaskQueue();
|
||||
model.setMeshMask(meshMask);
|
||||
model.setTextureMask(textureMap);
|
||||
for(ActorShaderMask shaderMask : shaderMasks){
|
||||
if(shaderMask.getModelName().equals(modelPath)){
|
||||
if(shaderMask.getModelName().equals(pathToFetch)){
|
||||
model.getShaderMask().put(shaderMask.getMeshName(),shaderMask);
|
||||
}
|
||||
}
|
||||
@ -534,13 +580,18 @@ public class Actor {
|
||||
*/
|
||||
public boolean isStaticDrawCall(){
|
||||
return
|
||||
this.animationQueue.size() == 0 &&
|
||||
this.meshMask.getBlockedMeshes().size() == 0 &&
|
||||
this.textureMap == null &&
|
||||
this.shaderMasks.size() == 0 &&
|
||||
this.textureOverride == null &&
|
||||
this.uniformMap.isEmpty() &&
|
||||
this.staticMorph == null
|
||||
//is low lod level
|
||||
this.lodLevel == Actor.LOD_LEVEL_LOWER ||
|
||||
//actor doesn't have anything complicated render-wise (animations, custom textures, etc)
|
||||
(
|
||||
this.animationQueue.size() == 0 &&
|
||||
this.meshMask.getBlockedMeshes().size() == 0 &&
|
||||
this.textureMap == null &&
|
||||
this.shaderMasks.size() == 0 &&
|
||||
this.textureOverride == null &&
|
||||
this.uniformMap.isEmpty() &&
|
||||
this.staticMorph == null
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
@ -873,4 +924,37 @@ public class Actor {
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path to the low res model
|
||||
* @return Path to the low res model
|
||||
*/
|
||||
public String getLowResPath() {
|
||||
return lowResPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the path to the low res model
|
||||
* @param lowResPath The path to the low res model
|
||||
*/
|
||||
public void setLowResPath(String lowResPath) {
|
||||
this.lowResPath = lowResPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the lod level
|
||||
* @return The lod level
|
||||
*/
|
||||
public int getLodLevel(){
|
||||
return this.lodLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lod level of the actor
|
||||
* @param lodLevel The lod level
|
||||
*/
|
||||
public void setLodLevel(int lodLevel){
|
||||
this.lodLevel = lodLevel;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -19,6 +19,12 @@ import electrosphere.renderer.pipelines.MainContentPipeline;
|
||||
* Evaluates the draw targets
|
||||
*/
|
||||
public class DrawTargetEvaluator {
|
||||
|
||||
|
||||
/**
|
||||
* Cutoff after which we start using LOD models
|
||||
*/
|
||||
public static final int LOD_CUTOFF = 100;
|
||||
|
||||
/**
|
||||
* Evaluates the draw targets
|
||||
@ -54,6 +60,19 @@ public class DrawTargetEvaluator {
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
//fetch actor
|
||||
Actor currentActor = EntityUtils.getActor(currentEntity);
|
||||
|
||||
//evaluate LOD level
|
||||
if(currentActor.getLowResPath() != null){
|
||||
posVec.set(position);
|
||||
double dist = posVec.distance(cameraCenter);
|
||||
if(dist < LOD_CUTOFF){
|
||||
currentActor.setLodLevel(Actor.LOD_LEVEL_FULL);
|
||||
} else {
|
||||
currentActor.setLodLevel(Actor.LOD_LEVEL_LOWER);
|
||||
}
|
||||
}
|
||||
|
||||
//queue calls accordingly
|
||||
if(!DrawableUtils.hasUniqueModel(currentEntity) && currentActor.isStaticDrawCall()){
|
||||
//calculate camera-modified vector3d
|
||||
Vector3d cameraModifiedPosition = positionVec.set(position).sub(cameraCenter);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user