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

View file

@ -54,33 +54,42 @@ class InstanceManager {
}
public function render() {
var renderFrustums = [scene.camera.frustum];
var renderFrustum = scene.camera.frustum;
var doFrustumCheck = true;
// This sucks holy shit
if (MarbleGame.instance.world != null
doFrustumCheck = MarbleGame.instance.world != null
&& MarbleGame.instance.world.marble != null
&& MarbleGame.instance.world.marble.cubemapRenderer != null)
renderFrustums = renderFrustums.concat(MarbleGame.instance.world.marble.cubemapRenderer.getCameraFrustums());
&& MarbleGame.instance.world.marble.cubemapRenderer != null;
// renderFrustums = renderFrustums.concat(MarbleGame.instance.world.marble.cubemapRenderer.getCameraFrustums());
for (meshes in objects) {
for (minfo in meshes) {
var visibleinstances = [];
var opaqueinstances = [];
var transparentinstances = [];
// Culling
if (minfo.meshbatch != null || minfo.transparencymeshbatch != null) {
for (inst in minfo.instances) {
// for (frustum in renderFrustums) {
// if (frustum.hasBounds(objBounds)) {
if (doFrustumCheck) {
var objBounds = @:privateAccess cast(minfo.meshbatch.primitive, Instanced).baseBounds.clone();
objBounds.transform(inst.emptyObj.getAbsPos());
for (frustum in renderFrustums) {
if (frustum.hasBounds(objBounds)) {
visibleinstances.push(inst);
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
if (minfo.meshbatch != null) {
var opaqueinstances = visibleinstances.filter(x -> x.gameObject.currentOpacity == 1);
minfo.meshbatch.begin(opaqueinstances.length);
for (instance in opaqueinstances) { // Draw the opaque shit first
var dtsShader = minfo.dtsShader; // minfo.meshbatch.material.mainPass.getShader(DtsTexture);
@ -123,7 +132,6 @@ class InstanceManager {
}
}
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);
for (instance in transparentinstances) { // Non opaque shit
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 {
public var camera:CameraController;
public var cameraObject:Object;
@ -721,7 +740,7 @@ class Marble extends GameObject {
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)));
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) {
return {
position: position,
@ -1087,7 +1106,7 @@ class Marble extends GameObject {
var lastContactPos = new Vector();
var testTriangles = [];
var testTriangles:Array<MarbleTestMoveFoundContact> = [];
var finalContacts = [];
var foundMarbles = [];
@ -1149,7 +1168,8 @@ class Marble extends GameObject {
Math.max(Math.max(sphereRadius.x, sphereRadius.y), sphereRadius.z) * 2);
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) {
var surface:CollisionSurface = cast surf;
@ -1399,10 +1419,7 @@ class Marble extends GameObject {
};
}
function nudgeToContacts(position:Vector, radius:Float, foundContacts:Array<{
v:Array<Vector>,
n:Vector
}>, foundMarbles:Array<SphereCollisionEntity>) {
function nudgeToContacts(position:Vector, radius:Float, foundContacts:Array<MarbleTestMoveFoundContact>, foundMarbles:Array<SphereCollisionEntity>) {
var it = 0;
var concernedContacts = foundContacts; // PathedInteriors have their own nudge logic
var prevResolved = 0;

View file

@ -24,6 +24,8 @@ class Radar {
var time:Float = 0.0;
var _dirty = false;
public function new(level:MarbleWorld, scene2d:Scene) {
this.level = level;
this.scene2d = scene2d;
@ -35,7 +37,12 @@ class Radar {
public function update(dt:Float) {
time += dt;
_dirty = true;
}
public function render() {
if (!_dirty)
return;
g.clear();
var gemCount = 0;
for (gem in level.gems) {
@ -47,6 +54,7 @@ class Radar {
if (@:privateAccess level.endPad != null && gemCount == 0) {
renderArrow(@:privateAccess level.endPad.getAbsPos().getPosition(), 0xE6E6E6);
}
_dirty = false;
}
public function blink() {
@ -64,8 +72,30 @@ class Radar {
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) {
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 fovX = (level.scene.camera.getFovX() * 0.5) * Math.PI / 180.0;
@ -100,12 +130,13 @@ class Radar {
cc2.normalize();
sd.normalize();
var arrowPos = new Vector();
var arrowPosY = 0.0;
var arrowPosX = 0.0;
if (cc1.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 {
arrowPos.y = scene2d.height;
arrowPosY = scene2d.height;
}
}
var r1 = shapeDist.transformed(gravityMat);
@ -139,21 +170,19 @@ class Radar {
if (-fovX <= xfPosAngle) {
if (fovX >= xfPosAngle) {
// 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 {
// otherwise snap to edge
arrowPos.x = scene2d.width;
arrowPosX = scene2d.width;
}
}
var drawPoint = new Vector();
if (!validProjection) {
drawPoint.load(arrowPos);
} else {
var drawPoint = new Vector(arrowPosX, arrowPosY);
if (validProjection) {
drawPoint.load(projectedPos);
if (drawPoint.distanceSq(projectedPos) <= 75 * 75) {
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;
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
&& 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 r2 = (r1 + n) % n;
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)
return min;
if (value > max)
@ -30,11 +30,11 @@ class Util {
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;
}
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;
point += t * t * (2 * p0 - 5 * p1 + 4 * p2 - p3) / 2;
point += t * ((-1) * p0 + p2) / 2;
@ -42,7 +42,7 @@ class Util {
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));
}
@ -342,7 +342,7 @@ class Util {
'${(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);
while (str.length < len)
str += " ";
@ -420,7 +420,7 @@ class Util {
#end
}
public static function isSafari() {
public static inline function isSafari() {
#if js
var reg = ~/^((?!chrome|android).)*safari/;
return reg.match(js.Browser.navigator.userAgent);
@ -430,7 +430,7 @@ class Util {
#end
}
public static function isInFullscreen() {
public static inline function isInFullscreen() {
#if js
return (js.Browser.window.innerHeight == js.Browser.window.screen.height
|| (js.Browser.window.screen.orientation.type == js.html.OrientationType.PORTRAIT_PRIMARY
@ -443,7 +443,7 @@ class Util {
#end
}
public static function toASCII(bytes:haxe.io.Bytes) {
public static inline function toASCII(bytes:haxe.io.Bytes) {
var totBytes = new BytesBuffer();
for (i in 0...bytes.length) {
var utfbytes = Bytes.ofString(String.fromCharCode(bytes.get(i)));
@ -453,7 +453,7 @@ class Util {
return totBytes.getBytes().toString();
}
public static function getPlatform() {
public static inline function getPlatform() {
#if js
return js.Browser.navigator.platform;
#end

View file

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