perf improvement - remove unnecessary allocs

This commit is contained in:
RandomityGuy 2024-03-20 18:40:47 +05:30
parent d82c76e09c
commit d018adfab7
6 changed files with 108 additions and 59 deletions

View file

@ -1132,10 +1132,6 @@ class DtsObject extends GameObject {
completion = Util.clamp((timeState.timeSinceLoad - doSequenceOnceBeginTime) / sequence.duration, 0, 0.98); completion = Util.clamp((timeState.timeSinceLoad - doSequenceOnceBeginTime) / sequence.duration, 0, 0.98);
} }
var quaternions:Array<Quat> = null;
var translations:Array<Vector> = null;
var scales:Array<Vector> = null;
var actualKeyframe = this.sequenceKeyframeOverride.exists(sequence) ? this.sequenceKeyframeOverride.get(sequence) : ((completion * sequence.numKeyFrames) % sequence.numKeyFrames); var actualKeyframe = this.sequenceKeyframeOverride.exists(sequence) ? this.sequenceKeyframeOverride.get(sequence) : ((completion * sequence.numKeyFrames) % sequence.numKeyFrames);
if (this.lastSequenceKeyframes.get(sequence) == actualKeyframe) if (this.lastSequenceKeyframes.get(sequence) == actualKeyframe)
continue; continue;
@ -1148,8 +1144,6 @@ class DtsObject extends GameObject {
var t = (actualKeyframe - keyframeLow) % 1; var t = (actualKeyframe - keyframeLow) % 1;
if (rot > 0) { if (rot > 0) {
quaternions = [];
for (i in 0...this.dts.nodes.length) { for (i in 0...this.dts.nodes.length) {
var affected = ((1 << i) & rot) != 0; var affected = ((1 << i) & rot) != 0;
@ -1169,7 +1163,8 @@ class DtsObject extends GameObject {
quat.slerp(q1, q2, t); quat.slerp(q1, q2, t);
quat.normalize(); quat.normalize();
this.graphNodes[i].setRotationQuat(quat); this.graphNodes[i].getRotationQuat().load(quat);
this.graphNodes[i].posChanged = true;
propagateDirtyFlags(i); propagateDirtyFlags(i);
affectedCount++; affectedCount++;
// quaternions.push(quat); // quaternions.push(quat);
@ -1178,7 +1173,8 @@ class DtsObject extends GameObject {
var quat = new Quat(-rotation.x, rotation.y, rotation.z, -rotation.w); var quat = new Quat(-rotation.x, rotation.y, rotation.z, -rotation.w);
quat.normalize(); quat.normalize();
quat.conjugate(); quat.conjugate();
this.graphNodes[i].setRotationQuat(quat); this.graphNodes[i].getRotationQuat().load(quat);
this.graphNodes[i].posChanged = true;
// quaternions.push(quat); // quaternions.push(quat);
} }
} }
@ -1186,8 +1182,6 @@ class DtsObject extends GameObject {
affectedCount = 0; affectedCount = 0;
if (trans > 0) { if (trans > 0) {
translations = [];
for (i in 0...this.dts.nodes.length) { for (i in 0...this.dts.nodes.length) {
var affected = ((1 << i) & trans) != 0; var affected = ((1 << i) & trans) != 0;
@ -1213,8 +1207,6 @@ class DtsObject extends GameObject {
affectedCount = 0; affectedCount = 0;
if (scale > 0) { if (scale > 0) {
scales = [];
if (sequence.flags & 1 > 0) { // Uniform scales if (sequence.flags & 1 > 0) { // Uniform scales
for (i in 0...this.dts.nodes.length) { for (i in 0...this.dts.nodes.length) {
var affected = ((1 << i) & scale) != 0; var affected = ((1 << i) & scale) != 0;
@ -1433,10 +1425,11 @@ class DtsObject extends GameObject {
var spinAnimation = new Quat(); var spinAnimation = new Quat();
spinAnimation.initRotateAxis(0, 0, -1, timeState.timeSinceLoad * this.ambientSpinFactor); spinAnimation.initRotateAxis(0, 0, -1, timeState.timeSinceLoad * this.ambientSpinFactor);
var orientation = this.getRotationQuat(); // var orientation = this.getRotationQuat();
// spinAnimation.multiply(orientation, spinAnimation); // spinAnimation.multiply(orientation, spinAnimation);
this.rootObject.setRotationQuat(spinAnimation); this.rootObject.getRotationQuat().load(spinAnimation);
this.rootObject.posChanged = true;
} }
for (i in 0...this.colliders.length) { for (i in 0...this.colliders.length) {

View file

@ -54,33 +54,42 @@ class InstanceManager {
} }
public function render() { public function render() {
var renderFrustums = [scene.camera.frustum]; var renderFrustum = scene.camera.frustum;
var doFrustumCheck = true;
// This sucks holy shit // This sucks holy shit
if (MarbleGame.instance.world != null doFrustumCheck = MarbleGame.instance.world != null
&& MarbleGame.instance.world.marble != null && MarbleGame.instance.world.marble != null
&& MarbleGame.instance.world.marble.cubemapRenderer != null) && MarbleGame.instance.world.marble.cubemapRenderer != null;
renderFrustums = renderFrustums.concat(MarbleGame.instance.world.marble.cubemapRenderer.getCameraFrustums()); // renderFrustums = renderFrustums.concat(MarbleGame.instance.world.marble.cubemapRenderer.getCameraFrustums());
for (meshes in objects) { for (meshes in objects) {
for (minfo in meshes) { for (minfo in meshes) {
var visibleinstances = []; var opaqueinstances = [];
var transparentinstances = [];
// Culling // Culling
if (minfo.meshbatch != null || minfo.transparencymeshbatch != null) { if (minfo.meshbatch != null || minfo.transparencymeshbatch != null) {
for (inst in minfo.instances) { for (inst in minfo.instances) {
var objBounds = @:privateAccess cast(minfo.meshbatch.primitive, Instanced).baseBounds.clone(); // for (frustum in renderFrustums) {
objBounds.transform(inst.emptyObj.getAbsPos()); // if (frustum.hasBounds(objBounds)) {
for (frustum in renderFrustums) { if (doFrustumCheck) {
if (frustum.hasBounds(objBounds)) { var objBounds = @:privateAccess cast(minfo.meshbatch.primitive, Instanced).baseBounds.clone();
visibleinstances.push(inst); objBounds.transform(inst.emptyObj.getAbsPos());
break;
} if (!renderFrustum.hasBounds(objBounds))
continue;
} }
if (inst.gameObject.currentOpacity == 1)
opaqueinstances.push(inst);
else if (inst.gameObject.currentOpacity != 0)
transparentinstances.push(inst);
// break;
// }
// }
} }
} }
// Emit non culled primitives // Emit non culled primitives
if (minfo.meshbatch != null) { if (minfo.meshbatch != null) {
var opaqueinstances = visibleinstances.filter(x -> x.gameObject.currentOpacity == 1);
minfo.meshbatch.begin(opaqueinstances.length); minfo.meshbatch.begin(opaqueinstances.length);
for (instance in opaqueinstances) { // Draw the opaque shit first for (instance in opaqueinstances) { // Draw the opaque shit first
var dtsShader = minfo.dtsShader; // minfo.meshbatch.material.mainPass.getShader(DtsTexture); var dtsShader = minfo.dtsShader; // minfo.meshbatch.material.mainPass.getShader(DtsTexture);
@ -123,7 +132,6 @@ class InstanceManager {
} }
} }
if (minfo.transparencymeshbatch != null) { if (minfo.transparencymeshbatch != null) {
var transparentinstances = visibleinstances.filter(x -> x.gameObject.currentOpacity != 1 && x.gameObject.currentOpacity != 0); // Filter out all zero opacity things too
minfo.transparencymeshbatch.begin(transparentinstances.length); minfo.transparencymeshbatch.begin(transparentinstances.length);
for (instance in transparentinstances) { // Non opaque shit for (instance in transparentinstances) { // Non opaque shit
var dtsShader = minfo.dtsShader; var dtsShader = minfo.dtsShader;

View file

@ -184,6 +184,25 @@ final blastMaxParticleOptions:ParticleEmitterOptions = {
} }
} }
@:publicFields
@:structInit
class MarbleTestMoveFoundContact {
var v:Array<Vector>;
var n:Vector;
}
@:publicFields
@:structInit
class MarbleTestMoveResult {
var position:Vector;
var t:Float;
var found:Bool;
var foundContacts:Array<MarbleTestMoveFoundContact>;
var lastContactPos:Null<Vector>;
var lastContactNormal:Null<Vector>;
var foundMarbles:Array<SphereCollisionEntity>;
}
class Marble extends GameObject { class Marble extends GameObject {
public var camera:CameraController; public var camera:CameraController;
public var cameraObject:Object; public var cameraObject:Object;
@ -721,7 +740,7 @@ class Marble extends GameObject {
normP.scale(1 + bounce); normP.scale(1 + bounce);
velocity.load(velocity.sub(normP.multiply(ourMass))); velocity.load(velocity.sub(normP.multiply(1 / ourMass)));
otherMarble.velocity.load(otherMarble.velocity.add(normP.multiply(1 / theirMass))); otherMarble.velocity.load(otherMarble.velocity.add(normP.multiply(1 / theirMass)));
contacts[i].velocity.load(otherMarble.velocity); contacts[i].velocity.load(otherMarble.velocity);
@ -1063,7 +1082,7 @@ class Marble extends GameObject {
} }
} }
function testMove(velocity:Vector, position:Vector, deltaT:Float, radius:Float, testPIs:Bool) { function testMove(velocity:Vector, position:Vector, deltaT:Float, radius:Float, testPIs:Bool):MarbleTestMoveResult {
if (velocity.length() < 0.001) { if (velocity.length() < 0.001) {
return { return {
position: position, position: position,
@ -1087,7 +1106,7 @@ class Marble extends GameObject {
var lastContactPos = new Vector(); var lastContactPos = new Vector();
var testTriangles = []; var testTriangles:Array<MarbleTestMoveFoundContact> = [];
var finalContacts = []; var finalContacts = [];
var foundMarbles = []; var foundMarbles = [];
@ -1149,7 +1168,8 @@ class Marble extends GameObject {
Math.max(Math.max(sphereRadius.x, sphereRadius.y), sphereRadius.z) * 2); Math.max(Math.max(sphereRadius.x, sphereRadius.y), sphereRadius.z) * 2);
var currentFinalPos = position.add(relVel.multiply(finalT)); // localpos.add(relLocalVel.multiply(finalT)); var currentFinalPos = position.add(relVel.multiply(finalT)); // localpos.add(relLocalVel.multiply(finalT));
var surfaces = obj.bvh == null ? obj.octree.boundingSearch(boundThing).map(x -> cast x) : obj.bvh.boundingSearch(boundThing); var surfaces = @:privateAccess obj.grid != null ? @:privateAccess obj.grid.boundingSearch(boundThing) : (obj.bvh == null ? obj.octree.boundingSearch(boundThing)
.map(x -> cast x) : obj.bvh.boundingSearch(boundThing));
for (surf in surfaces) { for (surf in surfaces) {
var surface:CollisionSurface = cast surf; var surface:CollisionSurface = cast surf;
@ -1399,10 +1419,7 @@ class Marble extends GameObject {
}; };
} }
function nudgeToContacts(position:Vector, radius:Float, foundContacts:Array<{ function nudgeToContacts(position:Vector, radius:Float, foundContacts:Array<MarbleTestMoveFoundContact>, foundMarbles:Array<SphereCollisionEntity>) {
v:Array<Vector>,
n:Vector
}>, foundMarbles:Array<SphereCollisionEntity>) {
var it = 0; var it = 0;
var concernedContacts = foundContacts; // PathedInteriors have their own nudge logic var concernedContacts = foundContacts; // PathedInteriors have their own nudge logic
var prevResolved = 0; var prevResolved = 0;

View file

@ -24,6 +24,8 @@ class Radar {
var time:Float = 0.0; var time:Float = 0.0;
var _dirty = false;
public function new(level:MarbleWorld, scene2d:Scene) { public function new(level:MarbleWorld, scene2d:Scene) {
this.level = level; this.level = level;
this.scene2d = scene2d; this.scene2d = scene2d;
@ -35,7 +37,12 @@ class Radar {
public function update(dt:Float) { public function update(dt:Float) {
time += dt; time += dt;
_dirty = true;
}
public function render() {
if (!_dirty)
return;
g.clear(); g.clear();
var gemCount = 0; var gemCount = 0;
for (gem in level.gems) { for (gem in level.gems) {
@ -47,6 +54,7 @@ class Radar {
if (@:privateAccess level.endPad != null && gemCount == 0) { if (@:privateAccess level.endPad != null && gemCount == 0) {
renderArrow(@:privateAccess level.endPad.getAbsPos().getPosition(), 0xE6E6E6); renderArrow(@:privateAccess level.endPad.getAbsPos().getPosition(), 0xE6E6E6);
} }
_dirty = false;
} }
public function blink() { public function blink() {
@ -64,8 +72,30 @@ class Radar {
g = null; g = null;
} }
inline function planeDistance(plane:h3d.col.Plane, p:Vector) {
return @:privateAccess plane.nx * p.x + @:privateAccess plane.ny * p.y + @:privateAccess plane.nz * p.z - @:privateAccess plane.d;
}
function frustumHasPoint(frustum:h3d.col.Frustum, p:Vector) {
if (planeDistance(frustum.pleft, p) < 0)
return false;
if (planeDistance(frustum.pright, p) < 0)
return false;
if (planeDistance(frustum.ptop, p) < 0)
return false;
if (planeDistance(frustum.pbottom, p) < 0)
return false;
if (frustum.checkNearFar) {
if (planeDistance(frustum.pnear, p) < 0)
return false;
if (planeDistance(frustum.pfar, p) < 0)
return false;
}
return true;
}
function renderArrow(pos:Vector, color:Int) { function renderArrow(pos:Vector, color:Int) {
var validProjection = level.scene.camera.frustum.hasPoint(pos.toPoint()); var validProjection = frustumHasPoint(level.scene.camera.frustum, pos);
var projectedPos = level.scene.camera.project(pos.x, pos.y, pos.z, scene2d.width, scene2d.height); var projectedPos = level.scene.camera.project(pos.x, pos.y, pos.z, scene2d.width, scene2d.height);
var fovX = (level.scene.camera.getFovX() * 0.5) * Math.PI / 180.0; var fovX = (level.scene.camera.getFovX() * 0.5) * Math.PI / 180.0;
@ -100,12 +130,13 @@ class Radar {
cc2.normalize(); cc2.normalize();
sd.normalize(); sd.normalize();
var arrowPos = new Vector(); var arrowPosY = 0.0;
var arrowPosX = 0.0;
if (cc1.y >= sd.y) { if (cc1.y >= sd.y) {
if (cc2.y <= sd.y) { if (cc2.y <= sd.y) {
arrowPos.y = scene2d.height * ((sd.x * cc1.y - cc1.x * sd.y) / (sd.y * (cc2.x - cc1.x) - (cc2.y - cc1.y) * sd.x)); arrowPosY = scene2d.height * ((sd.x * cc1.y - cc1.x * sd.y) / (sd.y * (cc2.x - cc1.x) - (cc2.y - cc1.y) * sd.x));
} else { } else {
arrowPos.y = scene2d.height; arrowPosY = scene2d.height;
} }
} }
var r1 = shapeDist.transformed(gravityMat); var r1 = shapeDist.transformed(gravityMat);
@ -139,21 +170,19 @@ class Radar {
if (-fovX <= xfPosAngle) { if (-fovX <= xfPosAngle) {
if (fovX >= xfPosAngle) { if (fovX >= xfPosAngle) {
// the new x is the fraction of where it is but convert it from an angle to tangent // the new x is the fraction of where it is but convert it from an angle to tangent
arrowPos.x = scene2d.width * 0.5 + Math.tan(xfPosAngle) * (scene2d.width * 0.5) / Math.tan(fovX); arrowPosX = scene2d.width * 0.5 + Math.tan(xfPosAngle) * (scene2d.width * 0.5) / Math.tan(fovX);
} else { } else {
// otherwise snap to edge // otherwise snap to edge
arrowPos.x = scene2d.width; arrowPosX = scene2d.width;
} }
} }
var drawPoint = new Vector(); var drawPoint = new Vector(arrowPosX, arrowPosY);
if (!validProjection) { if (validProjection) {
drawPoint.load(arrowPos);
} else {
drawPoint.load(projectedPos); drawPoint.load(projectedPos);
if (drawPoint.distanceSq(projectedPos) <= 75 * 75) { if (drawPoint.distanceSq(projectedPos) <= 75 * 75) {
var distOff = drawPoint.distance(projectedPos); var distOff = drawPoint.distance(projectedPos);
drawPoint = Util.lerpThreeVectors(projectedPos, arrowPos, distOff / 75); drawPoint = Util.lerpThreeVectors(projectedPos, new Vector(arrowPosX, arrowPosY), distOff / 75);
} }
} }

View file

@ -11,18 +11,18 @@ import h3d.Vector;
import src.Settings; import src.Settings;
class Util { class Util {
public static function mat3x3equal(a:Matrix, b:Matrix) { public static inline function mat3x3equal(a:Matrix, b:Matrix) {
return a._11 == b._11 && a._12 == b._12 && a._13 == b._13 && a._21 == b._21 && a._22 == b._22 && a._23 == b._23 && a._31 == b._31 && a._32 == b._32 return a._11 == b._11 && a._12 == b._12 && a._13 == b._13 && a._21 == b._21 && a._22 == b._22 && a._23 == b._23 && a._31 == b._31 && a._32 == b._32
&& a._33 == b._33; && a._33 == b._33;
} }
public static function adjustedMod(a:Float, n:Float) { public static inline function adjustedMod(a:Float, n:Float) {
var r1 = a % n; var r1 = a % n;
var r2 = (r1 + n) % n; var r2 = (r1 + n) % n;
return r2; return r2;
} }
public static function clamp(value:Float, min:Float, max:Float) { public static inline function clamp(value:Float, min:Float, max:Float) {
if (value < min) if (value < min)
return min; return min;
if (value > max) if (value > max)
@ -30,11 +30,11 @@ class Util {
return value; return value;
} }
public static function lerp(a:Float, b:Float, t:Float) { public static inline function lerp(a:Float, b:Float, t:Float) {
return a + (b - a) * t; return a + (b - a) * t;
} }
public static function catmullRom(t:Float, p0:Float, p1:Float, p2:Float, p3:Float) { public static inline function catmullRom(t:Float, p0:Float, p1:Float, p2:Float, p3:Float) {
var point = t * t * t * ((-1) * p0 + 3 * p1 - 3 * p2 + p3) / 2; var point = t * t * t * ((-1) * p0 + 3 * p1 - 3 * p2 + p3) / 2;
point += t * t * (2 * p0 - 5 * p1 + 4 * p2 - p3) / 2; point += t * t * (2 * p0 - 5 * p1 + 4 * p2 - p3) / 2;
point += t * ((-1) * p0 + p2) / 2; point += t * ((-1) * p0 + p2) / 2;
@ -42,7 +42,7 @@ class Util {
return point; return point;
} }
public static function lerpThreeVectors(v1:Vector, v2:Vector, t:Float) { public static inline function lerpThreeVectors(v1:Vector, v2:Vector, t:Float) {
return new Vector(lerp(v1.x, v2.x, t), lerp(v1.y, v2.y, t), lerp(v1.z, v2.z, t), lerp(v1.w, v2.w, t)); return new Vector(lerp(v1.x, v2.x, t), lerp(v1.y, v2.y, t), lerp(v1.z, v2.z, t), lerp(v1.w, v2.w, t));
} }
@ -342,7 +342,7 @@ class Util {
'${(hours > 0 ? (hoursTen > 0 ? '${hoursTen}' : '') +'${hoursOne}' + ':' : '')}${minutesTen}${minutesOne}:${secondsTen}${secondsOne}.${hundredthTen}${hundredthOne}${thousandth}'; '${(hours > 0 ? (hoursTen > 0 ? '${hoursTen}' : '') +'${hoursOne}' + ':' : '')}${minutesTen}${minutesOne}:${secondsTen}${secondsOne}.${hundredthTen}${hundredthOne}${thousandth}';
} }
public static function rightPad(str:String, len:Int, cutOff:Int) { public static inline function rightPad(str:String, len:Int, cutOff:Int) {
str = str.substring(0, len - cutOff); str = str.substring(0, len - cutOff);
while (str.length < len) while (str.length < len)
str += " "; str += " ";
@ -420,7 +420,7 @@ class Util {
#end #end
} }
public static function isSafari() { public static inline function isSafari() {
#if js #if js
var reg = ~/^((?!chrome|android).)*safari/; var reg = ~/^((?!chrome|android).)*safari/;
return reg.match(js.Browser.navigator.userAgent); return reg.match(js.Browser.navigator.userAgent);
@ -430,7 +430,7 @@ class Util {
#end #end
} }
public static function isInFullscreen() { public static inline function isInFullscreen() {
#if js #if js
return (js.Browser.window.innerHeight == js.Browser.window.screen.height return (js.Browser.window.innerHeight == js.Browser.window.screen.height
|| (js.Browser.window.screen.orientation.type == js.html.OrientationType.PORTRAIT_PRIMARY || (js.Browser.window.screen.orientation.type == js.html.OrientationType.PORTRAIT_PRIMARY
@ -443,7 +443,7 @@ class Util {
#end #end
} }
public static function toASCII(bytes:haxe.io.Bytes) { public static inline function toASCII(bytes:haxe.io.Bytes) {
var totBytes = new BytesBuffer(); var totBytes = new BytesBuffer();
for (i in 0...bytes.length) { for (i in 0...bytes.length) {
var utfbytes = Bytes.ofString(String.fromCharCode(bytes.get(i))); var utfbytes = Bytes.ofString(String.fromCharCode(bytes.get(i)));
@ -453,7 +453,7 @@ class Util {
return totBytes.getBytes().toString(); return totBytes.getBytes().toString();
} }
public static function getPlatform() { public static inline function getPlatform() {
#if js #if js
return js.Browser.navigator.platform; return js.Browser.navigator.platform;
#end #end

View file

@ -3,7 +3,9 @@ package octree;
import h3d.Vector; import h3d.Vector;
import h3d.col.Bounds; import h3d.col.Bounds;
typedef RayIntersectionData = { @:publicFields
@:structInit
class RayIntersectionData {
var point:Vector; var point:Vector;
var normal:Vector; var normal:Vector;
var object:IOctreeObject; var object:IOctreeObject;