猫史档案馆


【box3】从隔壁geofs移植到神岛的新物理引擎!

用户:YDS尹子YDS尹子查看:3 回复:11 评论:3 创建时间:2024-02-05T18:13:03


/*
注:本代码只是提供一个算法,具体应用需要自己去适配!
例如,你可能需要根据摩擦力公式或者重力公式在主循环中书写相关力的作用的代码

 */
var geofs={};
var GRAVITY = 9.81, DEGREES_TO_RAD = Math.PI / 180, RAD_TO_DEGREES = 180 / Math.PI, KMH_TO_MS = 1 / 3.6, METERS_TO_FEET = 3.2808399, METERS_TO_NM = 5.39957E-4, FEET_TO_METERS = .3048, LONGITUDE_TO_HOURS = .0666, EPSILON = 1E-7, ONE_MINUS_EPSILON = 1 - EPSILON, MERIDIONAL_RADIUS = 6378137, EARTH_CIRCUMFERENCE = 2 * MERIDIONAL_RADIUS * Math.PI, METERS_TO_LOCAL_LAT = 1 / (EARTH_CIRCUMFERENCE / 360), STANDARD_GLIDE_ANGLE = 3, GLIDE_SLOPE = .052359, PI = Math.PI, HALF_PI = PI / 2, TWO_PI = 2 * PI, ONE_OVER_TWO_PI = 1 / TWO_PI, ONE_OVER_PI = 1 / PI, MS_TO_FEE喵INUTE = 196.85, MS_TO_KNOTS =
    1.94384449, KNOTS_TO_MS = .514444444, KMH_TO_KNOTS = .539956803, AXIS_TO_INDEX = { X: 0, Y: 1, Z: 2 }, AXIS_TO_VECTOR = { X: [1, 0, 0], Y: [0, 1, 0], Z: [0, 0, 1] }, KELVIN_OFFSET = 273.15, TEMPERATURE_LAPSE_RATE = .0065, ZUPAxis = { X: "X", Y: "Y", Z: "Z" }, YUPAxis = { X: "X", Y: "Z", Z: "Y" }, AIR_DENSITY_SL = 1.22, AIR_PRESSURE_SL = 101325, AIR_TEMP_SL = 15, DRAG_CONSTANT = .07, MIN_DRAG_COEF = .02, PLANFORM_EFFICIENCY_FACTOR = .7, TOTAL_DRAG_CONSTANT = DRAG_CONSTANT + MIN_DRAG_COEF, IDEAL_GAS_CONSTANT = 8.31447, MOLAR_MASS_DRY_AIR = .02喵4, GAS_CONSTANT = IDEAL_GAS_CONSTANT / MOLAR_MASS_DRY_AIR,
    GM_RL = GRAVITY * MOLAR_MASS_DRY_AIR / (IDEAL_GAS_CONSTANT * TEMPERATURE_LAPSE_RATE), DEFAULT_AIRFOIL_ASPECT_RATIO = 7, WATER_DENSITY = 997, FOV = 60, VIEWPORT_REFERENCE_WIDTH = 1800, VIEWPORT_REFERENCE_HEIGHT = 800, SMOOTH_BUFFER = {}, SMOOTHING_FACTOR = .2, SIX_STEP_WARNING = "#18a400 #喵9100 #487300 #835b00 #933700 #a71500".split(" "), SHADOWS_NONE = 0, SHADOWS_ALL = 1, SHADOWS_CAST = 2, SHADOWS_RECEIVE = 3; geofs.constants = { init: function () { } };

const FrictionMiu=0.02*0.5,BOUNCE=0.2,MINBOUNCESPEED=0.2,ZOOM=0.25,ZOOMSIZ=0.25


V3 = {
    isValid: function (a) { if (!a) return !1; for (var b = 0; 2 >= b; b++)if (null === a[b] || isNaN(a[b])) return !1; return !0 }, dup: function (a) { return [a[0], a[1], a[2]] }, toString: function (a) { return "[" + a[0] + ", " + a[1] + ", " + a[2] + "]" }, nearlyEqual: function (a, b, c) { c || (c = 1E-6); return Math.abs(a[0] - b[0]) <= c && Math.abs(a[1] - b[1]) <= c && Math.abs(a[2] - b[2]) <= c }, abs: function (a) { return [Math.abs(a[0]), Math.abs(a[1]), Math.abs(a[2])] }, cross: function (a, b) { var c = a[0], d = a[1]; a = a[2]; var e = b[0], f = b[1]; b = b[2]; return [d * b - a * f, a * e - c * b, c * f - d * e] }, dot: function (a,
        b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] }, add: function (a, b) { return [a[0] + b[0], a[1] + b[1], a[2] + b[2]] }, addAngles: function (a, b) { return [fixAngle(a[0] + b[0]), fixAngle(a[1] + b[1]), fixAngle(a[2] + b[2])] }, sub: function (a, b) { return [a[0] - b[0], a[1] - b[1], a[2] - b[2]] }, mult: function (a, b) { return [a[0] * b[0], a[1] * b[1], a[2] * b[2]] }, scale: function (a, b) { return [a[0] * b, a[1] * b, a[2] * b] }, length: function (a) { return Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]) }, normalize: function (a) {
            var b = V3.length(a); return 0 >= b ? [NaN, NaN, NaN] : V3.scale(a,
                1 / b)
        }, bisect: function (a, b) { return [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2] }, rotate: function (a, b, c) { var d = V3.dot(a, b); a = V3.sub(a, V3.scale(b, d)); var e = V3.cross(b, a); return V3.add(V3.scale(b, d), V3.add(V3.scale(a, Math.cos(c)), V3.scale(e, Math.sin(c)))) }, toRadians: function (a) { return [a[0] * DEGREES_TO_RAD, a[1] * DEGREES_TO_RAD, a[2] * DEGREES_TO_RAD] }, toDegrees: function (a) { return [a[0] * RAD_TO_DEGREES, a[1] * RAD_TO_DEGREES, a[2] * RAD_TO_DEGREES] }, clamp: function (a, b, c) {
            return [clamp(a[0], b, c), clamp(a[1], b, c), clamp(a[2],
                b, c)]
        }, span: function (a, b, c) { return [span(a[0], b, c), span(a[1], b, c), span(a[2], b, c)] }, exponentialSmoothing: function (a, b, c, d) { return [exponentialSmoothing(a + "0", b[0], c, d), exponentialSmoothing(a + "1", b[1], c, d), exponentialSmoothing(a + "2", b[2], c, d)] }, sqrt: function (a) { return [Math.sqrt(Math.abs(a[0])) * Math.sign(a[0]), Math.sqrt(Math.abs(a[1])) * Math.sign(a[1]), Math.sqrt(Math.abs(a[2])) * Math.sign(a[2])] }
};
var M33 = {
    toString: function (a) { return "[" + V3.toString(a[0]) + ", " + V3.toString(a[1]) + ", " + V3.toString(a[2]) + "]" }, toM4: function (a) { return [a[0][0], a[0][1], a[0][2], 0, a[1][0], a[1][1], a[1][2], 0, a[2][0], a[2][1], a[2][2], 0, 0, 0, 0, 0] }, toArray: function (a) { return [a[0][0], a[0][1], a[0][2], a[1][0], a[1][1], a[1][2], a[2][0], a[2][1], a[2][2]] }, toRowMajorArray: function (a) { return [a[0][0], a[1][0], a[2][0], a[0][1], a[1][1], a[2][1], a[0][2], a[1][2], a[2][2]] }, fromColumnMajorArray: function (a) {
        return [[a[0], a[3], a[6]], [a[1], a[4], a[7]],
        [a[2], a[5], a[8]]]
    }, fromRowMajorArray: function (a) { return [[a[0], a[1], a[2]], [a[3], a[4], a[5]], [a[6], a[7], a[8]]] }, identity: function () { return [[1, 0, 0], [0, 1, 0], [0, 0, 1]] }, dup: function (a) { return [V3.dup(a[0]), V3.dup(a[1]), V3.dup(a[2])] }, nearlyEqual: function (a, b) { return V3.nearlyEqual(a[0], b[0]) && V3.nearlyEqual(a[1], b[1]) && V3.nearlyEqual(a[2], b[2]) }, transpose: function (a) { return [[a[0][0], a[1][0], a[2][0]], [a[0][1], a[1][1], a[2][1]], [a[0][2], a[1][2], a[2][2]]] }, add: function (a, b) {
        return [V3.add(a[0], b[0]), V3.add(a[1],
            b[1]), V3.add(a[2], b[2])]
    }, multiplyV: function (a, b) { var c = b[0], d = b[1]; b = b[2]; var e = a[0], f = a[1]; a = a[2]; return [e[0] * c + e[1] * d + e[2] * b, f[0] * c + f[1] * d + f[2] * b, a[0] * c + a[1] * d + a[2] * b] }, multiply: function (a, b) {
        var c = a[0][0], d = a[0][1], e = a[0][2], f = a[1][0], g = a[1][1], k = a[1][2], m = a[2][0], p = a[2][1]; a = a[2][2]; var n = b[0][0], x = b[0][1], u = b[0][2], A = b[1][0], q = b[1][1], t = b[1][2], D = b[2][0], E = b[2][1]; b = b[2][2]; return [[c * n + f * x + m * u, d * n + g * x + p * u, e * n + k * x + a * u], [c * A + f * q + m * t, d * A + g * q + p * t, e * A + k * q + a * t], [c * D + f * E + m * b, d * D + g * E + p * b, e * D + k * E + a *
            b]]
    }, scaled: function (a, b) { return [[a[0][0] * b[0], a[0][1] * b[1], a[0][2] * b[2]], [a[1][0] * b[0], a[1][1] * b[1], a[1][2] * b[2]], [a[2][0] * b[0], a[2][1] * b[1], a[2][2] * b[2]]] }, transform: function (a, b) { var c = a[0], d = a[1]; a = a[2]; var e = b[0], f = b[1]; b = b[2]; return [c[0] * e + d[0] * f + a[0] * b, c[1] * e + d[1] * f + a[1] * b, c[2] * e + d[2] * f + a[2] * b] }, rotationXYZ: function (a, b) { b = M33.setFromEuler(b); return b = M33.multiply(a, b) }, rotationX: function (a, b) { var c = Math.cos(b); b = Math.sin(b); return M33.multiply(a, [[1, 0, 0], [0, c, -b], [0, b, c]]) }, rotationY: function (a,
        b) { var c = Math.cos(b); b = Math.sin(b); return M33.multiply(a, [[c, 0, b], [0, 1, 0], [-b, 0, c]]) }, rotationZ: function (a, b) { var c = Math.cos(b); b = Math.sin(b); return M33.multiply(a, [[c, -b, 0], [b, c, 0], [0, 0, 1]]) }, rotationParentFrameX: function (a, b) { var c = Math.cos(b); b = Math.sin(b); return M33.multiply([[1, 0, 0], [0, c, -b], [0, b, c]], a) }, rotationParentFrameY: function (a, b) { var c = Math.cos(b); b = Math.sin(b); return M33.multiply([[c, 0, b], [0, 1, 0], [-b, 0, c]], a) }, rotationParentFrameZ: function (a, b) {
            var c = Math.cos(b); b = Math.sin(b); return M33.multiply([[c,
                -b, 0], [b, c, 0], [0, 0, 1]], a)
        }, rotate: function (a, b, c) { var d = b[0], e = b[1]; b = b[2]; var f = Math.cos(c), g = 1 - f; c = Math.sin(c); return M33.multiply(a, [[d * d * g + f, e * d * g + b * c, b * d * g - e * c], [d * e * g - b * c, e * e * g + f, e * b * g + d * c], [d * b * g + e * c, e * b * g - d * c, b * b * g + f]]) }, transformByTranspose: function (a, b) { return [a[0][0] * b[0] + a[0][1] * b[1] + a[0][2] * b[2], a[1][0] * b[0] + a[1][1] * b[1] + a[1][2] * b[2], a[2][0] * b[0] + a[2][1] * b[1] + a[2][2] * b[2]] }, makeOrthonormalFrame: function (a, b) {
            a = V3.normalize(a); b = V3.normalize(V3.cross(b, a)); var c = V3.cross(b, a); return [b,
                a, c]
        }, setFromEuler: function (a) { var b = Math.cos(a[0]), c = Math.sin(a[0]), d = Math.cos(a[1]), e = Math.sin(a[1]), f = Math.cos(a[2]); a = Math.sin(a[2]); return [[f * d + a * c * e, -a * d + f * c * e, b * e], [a * b, f * b, -c], [f * -e + a * c * d, -a * -e + f * c * d, b * d]] }, getOrientation: function (a) {
            if (.998 < a[1][2]) { var b = Math.atan2(-a[2][0], -a[2][1]); var c = -HALF_PI; a = 0 } else -.998 > a[1][2] ? (b = Math.atan2(a[2][0], a[2][1]), c = HALF_PI, a = 0) : (b = Math.atan2(a[1][0], a[1][1]), c = Math.asin(-a[1][2]), a = Math.atan2(a[0][2], a[2][2])); return [b * RAD_TO_DEGREES, c * RAD_TO_DEGREES,
            a * RAD_TO_DEGREES]
        }, toMatrix: function (a) { return a }, toYup: function (a) { var b = a[1], c = a[2]; a[2] = [b[0], b[1], b[2]]; a[1] = [c[0], c[1], c[2]]; b = [a[0][1], a[1][1], a[2][1]]; c = [a[0][2], a[1][2], a[2][2]]; a[0][1] = c[0]; a[1][1] = c[1]; a[2][1] = c[2]; a[0][2] = b[0]; a[1][2] = b[1]; a[2][2] = b[2]; return a }
}; M33.toEuler = M33.getOrientation;




var physics = {}; 
function rigidBody(e) { 
    this.s_inverseMass = this.mass = 0; 
    this.reset();
    this.minLinearVelocity = .001
    this.minAngularVelocity = .01 
    this.entity=e;
    this.setMassProps(e.mass,0.3)
    this.contactedVoxelLength=0;
    this.headingAngle=new GameVector3(0,0,0)
    e.omo=e.meshOrientation.clone()
}
rigidBody.prototype.reset = function () {
    this.v_linearVelocity = [0, 0, EPSILON];
    this.v_angularVelocity = [0, 0, EPSILON];
    this.v_totalForce = [0, 0, EPSILON];
    this.v_totalTorque = [0, 0, EPSILON];
    this.v_prevLinearVelocity = [0, 0, EPSILON];
    this.v_prevAngularVelocity = [0, 0, EPSILON];
    this.v_acceleration = [0, 0, EPSILON];
    this.v_angularAcceleration = [0, 0, EPSILON]
};
rigidBody.prototype.setMassProps = function (a, b) {
    b = [b,b,b]; 
    this.mass = a;
    this.s_inverseMass = 1 / a;
    this.v_localInvInertia = [b[0] / a, b[1] / a, b[2] / a];
    console.log("1 ",this.v_localInvInertia)
    this.m_localInvInertiaTensor = [[this.v_localInvInertia[0], 0, 0], [0, this.v_localInvInertia[1], 0], [0, 0, this.v_localInvInertia[2]]];
    this.m_worldInvInertiaTensor = M33.dup(this.m_localInvInertiaTensor);
    this.gravityForce = [0, 0, -GRAVITY * a] };
    rigidBody.prototype.getLinearVelocity = function () { return this.v_linearVelocity
};
rigidBody.prototype.getAngularVelocity = function () { return this.v_angularVelocity };
rigidBody.prototype.getLinearAcceleration = function () { return this.v_acceleration };
rigidBody.prototype.getAngularAcceleration = function () { return this.v_angularAcceleration };
rigidBody.prototype.setLinearVelocity = function (a) { this.v_linearVelocity = a };
rigidBody.prototype.setAngularVelocity = function (a) { this.v_angularVelocity = a };
rigidBody.prototype.applyAngularVelocity = function (a) { this.v_angularVelocity[0] =+ a[0];this.v_angularVelocity[1] =+ a[1];this.v_angularVelocity[2] =+ a[2] };
rigidBody.prototype.setLinearAcceleration = function (a) { this.v_acceleration = a };
rigidBody.prototype.setAngularAcceleration = function (a) { this.v_angularAcceleration = a };
rigidBody.prototype.getVelocityInLocalPoint = function (a) { return V3.add(this.v_linearVelocity, V3.cross(a, this.v_angularVelocity)) };
rigidBody.prototype.getForceInLocalPoint = function (a) { var b = V3.add(this.v_totalForce, V3.cross(a, this.v_totalTorque)); return V3.add(b, V3.scale(this.getVelocityInLocalPoint(a), this.mass)) };
rigidBody.prototype.applyCentralForce = function (a) { this.v_totalForce = V3.add(this.v_totalForce, a); };
rigidBody.prototype.applyTorque = function (a) { this.v_totalTorque = V3.add(this.v_totalTorque, a) };
rigidBody.prototype.applyForce = function (a, b) { this.applyCentralForce(a); this.applyTorque(V3.cross(a, b))};

rigidBody.prototype.applyCentralImpulse = function (a) { this.v_linearVelocity = V3.add(this.v_linearVelocity, V3.scale(a, this.s_inverseMass)) };
rigidBody.prototype.applyTorqueImpulse = function (a) { this.v_angularVelocity = V3.add(this.v_angularVelocity, M33.multiplyV(this.m_worldInvInertiaTensor, a)) };
rigidBody.prototype.applyImpulse = function (a, b) { this.applyCentralImpulse(a); this.applyTorqueImpulse(V3.cross(a, b)) 喵uteJacobian = function (a, b, c, d) { a = -(1 + a) * b; b = this.s_inverseMass; c = V3.dot(d, V3.cross(c, M33.multiplyV(this.m_worldInvInertiaTensor, V3.cross(d, c)))); return a / (b + c) 喵uteImpulse = function (a, b, c, d) { a = this.computeJacobian(a, b, c, d); return V3.scale(d, a) };
rigidBody.prototype.integrateVelocities = function (a) {
    
    this.v_linearVelocity = V3.add(this.v_linearVelocity, V3.scale(this.v_totalForce, this.s_inverseMass * a));
    this.v_angularVelocity = V3.add(this.v_angularVelocity, M33.multiplyV(this.m_worldInvInertiaTensor, V3.scale(this.v_totalTorque, a)))
};
rigidBody.prototype.integrateTransform = function (a) {
    var b = V3.length(this.v_linearVelocity),c = V3.length(this.v_angularVelocity);
    if (b > this.minLinearVelocity || c > this.minAngularVelocity)
        /*
                c = V3.scale(this.v_linearVelocity, a),//位移
        this.entity.position = this.entity.position.add(c[0],c[2],c[1]),//注意!物理引擎的z轴是垂直轴,xy与神岛也相反
         */
        this.entity.velocity.copy(new GameVector3(this.v_linearVelocity[0],this.v_linearVelocity[2],this.v_linearVelocity[1]).scale(1/16*ZOOM))
        a = V3.scale(this.v_angularVelocity, a),
        this.headingAngle.copy(this.headingAngle.add(new GameVector3(a[1],-a[2],-a[0])))
        this.entity.meshOrientation.copy(this.entity.omo.rotateX(this.headingAngle.x).rotateY(this.headingAngle.y).rotateZ(this.headingAngle.z))
    this.clearForces()
};
rigidBody.prototype.setCurrentAcceleration = function (a, b) { this.v_acceleration = V3.scale(V3.sub(this.v_linearVelocity, this.v_prevLinearVelocity), a); this.v_acceleration = V3.add([0, 0, GRAVITY], this.v_acceleration); this.v_angularAcceleration = V3.scale(V3.sub(this.v_angularVelocity, this.v_prevAngularVelocity), a); this.v_prevLinearVelocity = V3.dup(this.v_linearVelocity); this.v_prevAngularVelocity = V3.dup(this.v_angularVelocity) };

rigidBody.prototype.clearForces = function () { this.v_totalForce = [0, 0, 0]; this.v_totalTorque = [0, 0, 0] };
rigidBody.prototype.saveState = function () { this.savedLinearVelocity = V3.dup(this.v_linearVelocity); this.savedAngularVelocity = V3.dup(this.v_angularVelocity) };
rigidBody.prototype.restoreState = function () { this.clearForces(); this.v_linearVelocity = V3.dup(this.savedLinearVelocity); this.v_angularVelocity = V3.dup(this.savedAngularVelocity) }; "use strict"; geofs.aircraft = { "default": 1 }; geofs.aircraft.defaultDefinition = { Vspeeds: { VS0: -1, VS: 0, VFE: -1, VNO: 0, VNE: 0 } };
global.rigidBody=rigidBody;

var PhysicsFPS=50
setInterval(()=>{
    var e=1/PhysicsFPS //单位时间秒
    world.querySelectorAll(".RigidBody").forEach((g)=>{

        //主循环
        /*
        物理引擎的坐标系中,z轴是垂直轴,不要和岛三的坐标系搞混了哦
        1.applyForce函数:g.rigidBody.applyForce([矢量力的三个坐标值(列表)],[作用点坐标])
        2.applyCentralForce函数:g.rigidBody.applyCentralForce([矢量力的三个坐标值])
        3.还有很多类似函数,看前两个函数定义的地方,可以自己尝试一下
         */
    })
    
},1000/PhysicsFPS)

GameEntity.prototype.enableRigidBody=function(){
    this.addTag("RigidBody");
    this.rigidBody=new rigidBody(this)
    console.log("rigidBody Loaded")
}

/*
想要对实体启用该物理引擎,只要对实体entity运行entity.enableRigidBody()即可
 */


回复

上一页1 页 / 共 1下一页
追梦ez追梦ez

尹子!!沙发!!

点赞0


评论


呵呵0486呵呵0486

啊?

点赞1


评论


_Alone_风起_Alone_风起

啊???(

点赞0


评论


努力学习的包酱努力学习的包酱

awa

点赞0


评论


YDS尹子YDS尹子

物理引擎特色:

1.根据真实受力计算物体运动

2.根据受力点计算扭矩从而实现物体受力旋转

物理引擎局限性:

目前和代码岛物理引擎可能会有一定冲突,有时间有技术的大佬可以来改进一下(

点赞1


评论


Star_Ink_sansStar_Ink_sans

啊???

点赞0


评论


Ezra__Ezra__

来收藏夹里吃灰吧(

点赞0


评论


Yue.SYue.S

呀,欢迎回家!

点赞1


评论


时当日色QWQ时当日色QWQ

ddd

点赞0


评论


lon江航lon江航

imgsrc="https://static.codemao.cn/emoji/codemao/%E7%BC%96%E7%A8%8B%E7%8C%AB_%E7%82%B9%E8%B5%9E.gif"alt="emotion_编程猫_点赞"

点赞0


评论


SCS_user_i1eril0dUySCS_user_i1eril0dUy

咋用()

点赞0


评论