用户:
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()即可
*/
YDS尹子物理引擎特色:
1.根据真实受力计算物体运动
2.根据受力点计算扭矩从而实现物体受力旋转
物理引擎局限性:
目前和代码岛物理引擎可能会有一定冲突,有时间有技术的大佬可以来改进一下(
点赞1
评论
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
评论