more allocation work
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2025-06-08 21:31:19 -04:00
parent cacb20cf49
commit b11aa149d5
15 changed files with 196 additions and 42 deletions

View File

@ -2138,6 +2138,7 @@ Fix many places where entity position being set on vector fetched from getPositi
Undo getPosition new alloc to lower memory footprint
Work to reduce allocations
Prevent mouse event re-allocation every frame
More allocation work

View File

@ -1,5 +1,7 @@
package electrosphere.client.sim;
import java.util.HashSet;
import org.joml.Vector3d;
import electrosphere.client.entity.camera.CameraEntityUtils;
@ -32,6 +34,11 @@ public class ClientSimulation {
//used for tracking different in player position between frames (principally for draw cell manager)
Vector3d newPlayerCharacterPosition = new Vector3d();
/**
* Set for storing entities of a specific tag
*/
private HashSet<Entity> entityTagSet = new HashSet<Entity>();
/**
* Constructor
*/
@ -71,7 +78,8 @@ public class ClientSimulation {
//update actor animations
Globals.profiler.beginCpuSample("update actor animations");
for(Entity currentEntity : Globals.clientState.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.DRAWABLE)){
Globals.clientState.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.DRAWABLE, entityTagSet);
for(Entity currentEntity : entityTagSet){
Actor currentActor = EntityUtils.getActor(currentEntity);
if(currentActor.getLodLevel() == Actor.LOD_LEVEL_STATIC){
continue;
@ -84,7 +92,8 @@ public class ClientSimulation {
//
//make items play idle animation
Globals.profiler.beginCpuSample("item animations");
for(Entity item : Globals.clientState.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.ITEM)){
Globals.clientState.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.ITEM, entityTagSet);
for(Entity item : entityTagSet){
ItemUtils.updateItemActorAnimation(item);
}
Globals.profiler.endCpuSample();
@ -114,7 +123,8 @@ public class ClientSimulation {
//
//sum collidable impulses
Globals.profiler.beginCpuSample("collidable logic");
for(Entity collidable : Globals.clientState.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.COLLIDABLE)){
Globals.clientState.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.COLLIDABLE, entityTagSet);
for(Entity collidable : entityTagSet){
if(ClientCollidableTree.hasClientCollidableTree(collidable)){
ClientCollidableTree.getClientCollidableTree(collidable).simulate((float)Globals.engineState.timekeeper.getSimFrameTime());
}

View File

@ -52,6 +52,23 @@ public class DataFormatUtil {
}
}
/**
* Gets the vector in vector3d form
* @param values The list of raw float values
* @param tempVec The vec to set the values to
* @return The vector containing those values or an identity vector if no such values exist
*/
public static Vector3d getDoubleListAsVector(List<Double> values, Vector3d tempVec){
if(values == null){
return tempVec;
}
if(values.size() > 0){
return tempVec.set(values.get(0),values.get(1),values.get(2));
} else {
return tempVec;
}
}
/**
* Gets a vector as a list of doubles
* @param vec The vector

View File

@ -142,6 +142,22 @@ public class Scene {
return rVal;
}
/**
* Gets all entities registered to a tag
* @param tag The tag
* @param set The pre-existing set to populate
* @return A list of all entities with the tag, or null if no entities have been added to the tag yet
*/
public Set<Entity> getEntitiesWithTag(String tag, Set<Entity> set){
lock.lock();
set.clear();
if(tagEntityMap.containsKey(tag)){
set.addAll(tagEntityMap.get(tag));
}
lock.unlock();
return set;
}
/**
* Removes an entity from a tag
* @param e The entity

View File

@ -340,13 +340,44 @@ public class AttachUtils {
Vector3d bonePosition,
Quaterniond boneRotation,
//parent transforms
Vector3d parentPosition,
Quaterniond parentRotation,
Vector3d parentScale
){
return AttachUtils.calculateBoneAttachmentLocalPosition(new Vector3d(), offsetVector, offsetRotation, bonePosition, boneRotation, parentPosition, parentRotation, parentScale);
}
/**
* Calculates the position of an entity attached to a bone
* @param offsetVector The offset position
* @param offsetRotation The offset rotation
* @param bonePosition The bone's position
* @param boneRotation The bone's rotation
* @param parentPosition The parent's position
* @param parentRotation The parent's rotation
* @param parentScale The parent's scale
* @return The position of the attached/child entity
*/
public static Vector3d calculateBoneAttachmentLocalPosition(
//The vector to store the result in
Vector3d res,
//optional offsets
Vector3d offsetVector,
Quaterniond offsetRotation,
//current bone transform
Vector3d bonePosition,
Quaterniond boneRotation,
//parent transforms
Vector3d parentPosition,
Quaterniond parentRotation,
Vector3d parentScale
){
//transform bone space
Vector3d position = new Vector3d(offsetVector);
Vector3d position = res.set(offsetVector);
position = position.rotate(new Quaterniond(boneRotation));
position = position.add(bonePosition);
position = position.mul(parentScale);

View File

@ -73,12 +73,12 @@ public class ServerCollidableTree implements BehaviorTree {
Impulse[] impulses = collidable.getImpulses();
Vector3d pos = EntityUtils.getPosition(parent);
for(int i = 0; i < collidable.getImpulseCount(); i++){
if(impulses[i].type.matches(Collidable.TYPE_CREATURE)){
if(impulses[i].type.equals(Collidable.TYPE_CREATURE)){
if(ServerGravityTree.getServerGravityTree(parent)!=null){
ServerGravityTree.getServerGravityTree(parent).start();
}
}
if(impulses[i].type.matches(Collidable.TYPE_WORLD_BOUND) || impulses[i].type.matches(Collidable.TYPE_STATIC)){
if(impulses[i].type.equals(Collidable.TYPE_WORLD_BOUND) || impulses[i].type.equals(Collidable.TYPE_STATIC)){
this.resetGravityFall();
pos.add(impulses[i].getDirection().mul(impulses[i].getForce()));
}

View File

@ -26,6 +26,7 @@ import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.attach.AttachUtils;
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState.HitboxShapeType;
import electrosphere.logger.LoggerInterface;
import electrosphere.mem.JomlPool;
import electrosphere.server.datacell.Realm;
import electrosphere.server.entity.poseactor.PoseActor;
import electrosphere.util.math.SpatialMathUtils;
@ -457,8 +458,13 @@ public class HitboxCollectionState {
private void updateSphereShapePosition(CollisionEngine collisionEngine, String boneName, HitboxState hitboxState, Vector3d bonePosition){
DGeom geom = this.stateGeomMap.get(hitboxState);
//get pooled objects
Vector3d offsetPosition = JomlPool.getD();
Vector3d parentScale = JomlPool.getD();
Vector3d finalPos = JomlPool.getD();
//get offset's transform
Vector3d offsetPosition = DataFormatUtil.getDoubleListAsVector(hitboxState.getHitboxData().getOffset());
offsetPosition = DataFormatUtil.getDoubleListAsVector(hitboxState.getHitboxData().getOffset(),offsetPosition);
Quaterniond offsetRotation = new Quaterniond();
//the bone's transform
@ -471,15 +477,19 @@ public class HitboxCollectionState {
//the parent's transform
Vector3d parentPosition = EntityUtils.getPosition(parent);
Quaterniond parentRotation = EntityUtils.getRotation(parent);
Vector3d parentScale = new Vector3d();
parentScale.set(EntityUtils.getScale(parent));
//calculate
Vector3d hitboxPos = AttachUtils.calculateBoneAttachmentLocalPosition(offsetPosition, offsetRotation, bonePositionD, boneRotation, parentPosition, parentRotation, parentScale);
Vector3d hitboxPos = AttachUtils.calculateBoneAttachmentLocalPosition(finalPos, offsetPosition, offsetRotation, bonePositionD, boneRotation, parentPosition, parentRotation, parentScale);
//actually set value
PhysicsEntityUtils.setGeometryOffsetPosition(collisionEngine, geom, hitboxPos, new Quaterniond());
//release pooled objects
JomlPool.release(offsetPosition);
JomlPool.release(parentScale);
JomlPool.release(finalPos);
}
/**

View File

@ -4,6 +4,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import org.joml.Matrix4d;
import org.joml.Vector3d;
import org.joml.Vector3f;
@ -22,6 +23,11 @@ public class JomlPool {
*/
static List<Vector3d> vec3dPool = new LinkedList<Vector3d>();
/**
* Structure to store not-in-use objects
*/
static List<Matrix4d> mat4dPool = new LinkedList<Matrix4d>();
/**
* Lock for thread-safeing operations
*/
@ -75,6 +81,22 @@ public class JomlPool {
return rVal;
}
/**
* Gets a Matrix4d from the pool. Allocates if no free one is available.
* @return A Matrix4d
*/
public static Matrix4d getMat(){
Matrix4d rVal = null;
lock.lock();
if(mat4dPool.size() > 0){
rVal = mat4dPool.remove(0);
} else {
rVal = new Matrix4d();
}
lock.unlock();
return rVal;
}
/**
* Releases a Vector3d back into the pool
* @param data The object to release
@ -90,4 +112,17 @@ public class JomlPool {
lock.unlock();
}
/**
* Releases a Matrix4d back into the pool
* @param data The object to release
*/
public static void release(Matrix4d data){
data.identity();
lock.lock();
if(JomlPool.mat4dPool.size() < 1000){
JomlPool.mat4dPool.add(data);
}
lock.unlock();
}
}

View File

@ -134,6 +134,8 @@ public class ActorStaticMorph {
Vector3f offset = new Vector3f(0,0,0);
Vector3f scale = new Vector3f(1,1,1);
Matrix4f transform = null;
public Quaternionf getRotation(){
return new Quaternionf().rotateXYZ(yaw, pitch, roll);
}
@ -147,9 +149,11 @@ public class ActorStaticMorph {
}
public Matrix4f getTransform(){
Matrix4f rVal = new Matrix4f();
rVal.translationRotateScale(offset, getRotation(), scale);
return rVal;
if(transform == null){
transform = new Matrix4f();
}
transform.translationRotateScale(offset, getRotation(), scale);
return transform;
}
}

View File

@ -25,11 +25,11 @@ public class AnimNode {
this.raw_data = raw_data;
}
public Matrix4d getTransform(){
return new Matrix4d(transform);
public void getTransform(Matrix4d loc){
loc.set(transform);
}
public void setTransform(Matrix4d transform){
this.transform = new Matrix4d(transform);
this.transform.set(transform);
}
}

View File

@ -13,6 +13,7 @@ import electrosphere.renderer.meshgen.MeshLoader;
import electrosphere.renderer.anim.AnimNode;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.mem.JomlPool;
import java.util.ArrayList;
import java.util.Collections;
@ -415,9 +416,10 @@ public class Model {
* @param staticMorph The static morph to apply
*/
private void updateNodeTransform(AnimNode n, Map<String,ActorBoneRotator> boneRotators, ActorStaticMorph staticMorph){
Matrix4d currentTransform = n.getTransform().identity();
Matrix4d poolMat = JomlPool.getMat();
//grab parent transform if exists
if(n.parent != null){
currentTransform.set(n.parent.getTransform());
n.parent.getTransform(poolMat);
}
if(n.is_bone){
//
@ -430,33 +432,33 @@ public class Model {
message = message + "bone map key set: " + boneMap.keySet() + "\n";
throw new Error(message);
}
currentTransform.mul(target_bone.getDeform());
poolMat.mul(target_bone.getDeform());
if(boneRotators.containsKey(target_bone.boneID)){
currentTransform.rotate(boneRotators.get(target_bone.boneID).getRotation());
poolMat.rotate(boneRotators.get(target_bone.boneID).getRotation());
}
//
//static morph (changing nose size, eye distance, etc)
if(staticMorph != null && staticMorph.getBoneTransforms(n.id) != null){
currentTransform.mul(staticMorph.getBoneTransforms(n.id).getTransform());
poolMat.mul(staticMorph.getBoneTransforms(n.id).getTransform());
}
//
Matrix4d bone_matrix = currentTransform;
n.setTransform(currentTransform);
n.setTransform(poolMat);
//
//Calculate final offset from initial bone
//https://stackoverflow.com/a/59869381
bone_matrix.mul(target_bone.getMOffset());
bone_matrix = globalInverseTransform.mul(bone_matrix, bone_matrix);
target_bone.setFinalTransform(bone_matrix);
poolMat.mul(target_bone.getMOffset());
poolMat = globalInverseTransform.mul(poolMat, poolMat);
target_bone.setFinalTransform(poolMat);
} else {
n.setTransform(currentTransform.mul(electrosphere.util.Utilities.convertAIMatrix(n.raw_data.mTransformation())));
n.setTransform(poolMat.mul(electrosphere.util.Utilities.convertAIMatrix(n.raw_data.mTransformation())));
}
Iterator<AnimNode> node_iterator = n.children.iterator();
while(node_iterator.hasNext()){
AnimNode current_node = node_iterator.next();
updateNodeTransform(current_node,boneRotators,staticMorph);
}
JomlPool.release(poolMat);
}
/**

View File

@ -1,5 +1,6 @@
package electrosphere.renderer.pipelines;
import java.util.HashSet;
import java.util.Set;
import org.joml.Matrix4d;
@ -26,9 +27,14 @@ public class FoliagePipeline implements RenderPipeline {
*/
static Sphered boundingSphere = new Sphered(0.5,0.5,0.5,8);
/**
* Set for storing entities of a specific tag
*/
private HashSet<Entity> entityTagSet = new HashSet<Entity>();
@Override
public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) {
Set<Entity> foliageEntities = Globals.clientState.clientScene.getEntitiesWithTag(EntityTags.DRAW_FOLIAGE_PASS);
Set<Entity> foliageEntities = Globals.clientState.clientScene.getEntitiesWithTag(EntityTags.DRAW_FOLIAGE_PASS, entityTagSet);
if(foliageEntities != null){
for(Entity foliageEntity : foliageEntities){
Matrix4d modelMatrix = new Matrix4d();

View File

@ -1,5 +1,6 @@
package electrosphere.renderer.pipelines;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
@ -49,6 +50,11 @@ public class MainContentPipeline implements RenderPipeline {
*/
private int terrainChunks = 0;
/**
* Set for storing entities of a specific tag
*/
private HashSet<Entity> entityTagSet = new HashSet<Entity>();
@Override
public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) {
Globals.profiler.beginCpuSample("MainContentPipeline.render");
@ -202,7 +208,8 @@ public class MainContentPipeline implements RenderPipeline {
Globals.renderingEngine.getFoliagePipeline().render(openGLState, renderPipelineState);
Globals.profiler.endCpuSample();
Globals.profiler.beginCpuSample("MainContentPipeline.render - Solids instanced");
for(Entity currentEntity : Globals.clientState.clientScene.getEntitiesWithTag(EntityTags.DRAW_INSTANCED)){
Globals.clientState.clientScene.getEntitiesWithTag(EntityTags.DRAW_INSTANCED, entityTagSet);
for(Entity currentEntity : entityTagSet){
Vector3d position = EntityUtils.getPosition(currentEntity);
if(MainContentPipeline.shouldDrawSolidPass(currentEntity)){
//fetch actor
@ -266,7 +273,8 @@ public class MainContentPipeline implements RenderPipeline {
//
Globals.profiler.beginCpuSample("MainContentPipeline.render - Transparents non-instanced");
for(Entity currentEntity : Globals.clientState.clientScene.getEntitiesWithTag(EntityTags.DRAWABLE)){
Globals.clientState.clientScene.getEntitiesWithTag(EntityTags.DRAWABLE, entityTagSet);
for(Entity currentEntity : entityTagSet){
Vector3d position = EntityUtils.getPosition(currentEntity);
if(MainContentPipeline.shouldDrawTransparentPass(currentEntity)){
//fetch actor
@ -285,7 +293,8 @@ public class MainContentPipeline implements RenderPipeline {
}
Globals.profiler.endCpuSample();
Globals.profiler.beginCpuSample("MainContentPipeline.render - Transparents instanced");
for(Entity currentEntity : Globals.clientState.clientScene.getEntitiesWithTag(EntityTags.DRAW_INSTANCED)){
Globals.clientState.clientScene.getEntitiesWithTag(EntityTags.DRAW_INSTANCED, entityTagSet);
for(Entity currentEntity : entityTagSet){
Vector3d position = EntityUtils.getPosition(currentEntity);
if(MainContentPipeline.shouldDrawTransparentPass(currentEntity)){
//fetch actor

View File

@ -1,5 +1,6 @@
package electrosphere.renderer.target;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -34,6 +35,16 @@ public class DrawTargetEvaluator {
*/
public static final int LOD_LOWER_CUTOFF = 30;
/**
* Set for storing entities of a specific tag
*/
private static final HashSet<Entity> drawableSet = new HashSet<Entity>();
/**
* Set for storing entities of a specific tag
*/
private static final HashSet<Entity> shadowSet = new HashSet<Entity>();
/**
* Evaluates the draw targets
*/
@ -67,8 +78,8 @@ public class DrawTargetEvaluator {
Vector3d positionVec = new Vector3d();
//different entity lists
Set<Entity> drawables = Globals.clientState.clientScene.getEntitiesWithTag(EntityTags.DRAWABLE);
Set<Entity> shadowList = Globals.clientState.clientScene.getEntitiesWithTag(EntityTags.DRAW_CAST_SHADOW);
Set<Entity> drawables = Globals.clientState.clientScene.getEntitiesWithTag(EntityTags.DRAWABLE, drawableSet);
Set<Entity> shadowList = Globals.clientState.clientScene.getEntitiesWithTag(EntityTags.DRAW_CAST_SHADOW, shadowSet);
for(Entity currentEntity : drawables){
Vector3d position = EntityUtils.getPosition(currentEntity);

View File

@ -17,6 +17,7 @@ import org.lwjgl.assimp.AIScene;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.mem.JomlPool;
import electrosphere.renderer.actor.ActorBoneRotator;
import electrosphere.renderer.actor.ActorStaticMorph;
import electrosphere.renderer.anim.AnimChannel;
@ -200,10 +201,10 @@ public class PoseModel {
* @param staticMorph The static morph
*/
private void updateNodeTransform(AnimNode n, Map<String,ActorBoneRotator> boneRotators, ActorStaticMorph staticMorph){
Matrix4d poolMat = JomlPool.getMat();
//grab parent transform if exists
Matrix4d currentTransform = n.getTransform().identity();
if(n.parent != null){
currentTransform.set(n.parent.getTransform());
n.parent.getTransform(poolMat);
}
//if this is a bone, calculate the transform for the bone
if(n.is_bone){
@ -215,23 +216,23 @@ public class PoseModel {
message = message + "bone map key set: " + boneMap.keySet() + "\n";
throw new Error(message);
}
currentTransform.mul(target_bone.getDeform());
poolMat.mul(target_bone.getDeform());
if(boneRotators.containsKey(target_bone.boneID)){
currentTransform.rotate(boneRotators.get(target_bone.boneID).getRotation());
poolMat.rotate(boneRotators.get(target_bone.boneID).getRotation());
}
n.setTransform(currentTransform);
n.setTransform(poolMat);
if(staticMorph != null && staticMorph.getBoneTransforms(n.id) != null){
currentTransform.mul(staticMorph.getBoneTransforms(n.id).getTransform());
poolMat.mul(staticMorph.getBoneTransforms(n.id).getTransform());
}
//
//Calculate final offset from initial bone
//https://stackoverflow.com/a/59869381
currentTransform.mul(target_bone.getMOffset());
currentTransform = globalInverseTransform.mul(currentTransform, currentTransform);
target_bone.setFinalTransform(currentTransform);
poolMat.mul(target_bone.getMOffset());
poolMat = globalInverseTransform.mul(poolMat, poolMat);
target_bone.setFinalTransform(poolMat);
} else {
//not a bone, so use transform directly from data
n.setTransform(currentTransform.mul(electrosphere.util.Utilities.convertAIMatrix(n.raw_data.mTransformation())));
n.setTransform(poolMat.mul(electrosphere.util.Utilities.convertAIMatrix(n.raw_data.mTransformation())));
}
//update all children accordingly
Iterator<AnimNode> node_iterator = n.children.iterator();
@ -239,6 +240,7 @@ public class PoseModel {
AnimNode current_node = node_iterator.next();
this.updateNodeTransform(current_node,boneRotators,staticMorph);
}
JomlPool.release(poolMat);
}
/**