flights: draw two narrow engine contrails and raise beacon
This commit is contained in:
1 parent
6b375ea983
commit
6f19b34900
2 files changed
+75
-32
No files matched your search
Vendored
+69
-31
@@ -5702,6 +5702,9 @@ var CT_CHANCE = Math.max(0, Math.min(1, fltNum(FLT_CFG.contrailChance, 0.6)));
|
||||
var CT_START_FRAC = Math.max(0.02, fltNum(FLT_CFG.contrailStartKm, 6) / FLT_ALT_KM);
|
||||
var CT_T = Math.max(10, fltNum(FLT_CFG.contrailLifeS, 300));
|
||||
var CT_HALF_W = Math.max(0.002, fltNum(FLT_CFG.contrailWidthM, 310) / 2000 / KM_PER_TILE);
|
||||
var CT_ENGINE_HALF_W = Math.max(0.001, fltNum(FLT_CFG.contrailEngineWidthM, 700) / 2000 / KM_PER_TILE);
|
||||
var CT_ENGINE_OFFSET = FLT_CFG.contrailEngineOffset || { x: 0.36, y: -0.055, z: -0.14 };
|
||||
var FLT_MARK_OFFSET = FLT_CFG.markingLightOffset || { x: 0.0, y: 0.235, z: 0.0 };
|
||||
// world units: trails are gone by contrailFadeKm, ramping from 35% of it
|
||||
var CT_FADE_END = Math.max(1, fltNum(FLT_CFG.contrailFadeKm, 100) / KM_PER_TILE);
|
||||
// Night readability. A physically scaled contrail on a starlit night is a
|
||||
@@ -5724,7 +5727,7 @@ var FLT_BLINK_GAP = Math.max(0.02, fltNum(FLT_CFG.blinkGapS, 0.12));
|
||||
var FLT_BLINK_W = Math.max(0.01, fltNum(FLT_CFG.blinkFlashS, 0.07));
|
||||
var fltAirs = null; // [{x,z,rank}] - destination pool
|
||||
var fltData = []; // live aircraft: {v,leg,s,gnd,gndEnd,seed,phase,big}
|
||||
var fltBuf = null, fltVbo = null, fltCount = 0;
|
||||
var fltBuf = null, fltLightBuf = null, fltVbo = null, fltCount = 0;
|
||||
var fltState = []; // per frame render poses
|
||||
var fltProg = null, fltAttribs = null, fltUniforms = null;
|
||||
var fltFetching = false;
|
||||
@@ -5820,6 +5823,7 @@ function buildFlights(airports) {
|
||||
}
|
||||
fltCount = fltData.length;
|
||||
fltBuf = new Float32Array(fltCount * 6); // pos3 + bri + phase + size
|
||||
fltLightBuf = new Float32Array(fltCount * 6); // beacon positions, offset from model origin
|
||||
}
|
||||
|
||||
// advance every aircraft with the frame clock; the destination is rolled
|
||||
@@ -8014,6 +8018,19 @@ window.clouds3dRender = function(target) {
|
||||
fltBuf[k + 3] = f.big;
|
||||
fltBuf[k + 4] = f.phase;
|
||||
fltBuf[k + 5] = f.big; // destination rank also drives light size
|
||||
if (fltLightBuf) {
|
||||
var markScale = CT_HALF_W;
|
||||
var mx = (FLT_MARK_OFFSET.x || 0) * markScale;
|
||||
var my = (FLT_MARK_OFFSET.y || 0) * markScale;
|
||||
var mz = (FLT_MARK_OFFSET.z || 0) * markScale;
|
||||
var mcy = fl.tz, msy = fl.tx;
|
||||
fltLightBuf[k] = fl.x + mx * mcy + mz * msy;
|
||||
fltLightBuf[k + 1] = yF + my;
|
||||
fltLightBuf[k + 2] = fl.z - mx * msy + mz * mcy;
|
||||
fltLightBuf[k + 3] = f.big;
|
||||
fltLightBuf[k + 4] = f.phase;
|
||||
fltLightBuf[k + 5] = f.big;
|
||||
}
|
||||
var st = fltState[fi] || (fltState[fi] = {});
|
||||
st.y = yF; st.alt = fl.alt; st.s = fl.s; st.gnd = fl.gnd; st.leg = fl.leg;
|
||||
st.tx = fl.tx; st.tz = fl.tz;
|
||||
@@ -8022,7 +8039,7 @@ window.clouds3dRender = function(target) {
|
||||
if (carNight > 0.06) {
|
||||
if (!fltVbo) fltVbo = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, fltVbo);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, fltBuf, gl.STREAM_DRAW);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, fltLightBuf || fltBuf, gl.STREAM_DRAW);
|
||||
if (!fltProg) {
|
||||
var fp = makeProgram(gl, FLT_VERT_SRC, FLT_FRAG_SRC);
|
||||
if (!fp) { FLT_ON = false; }
|
||||
@@ -8174,14 +8191,14 @@ window.clouds3dRender = function(target) {
|
||||
gl.depthMask(true);
|
||||
}
|
||||
}
|
||||
// -- contrails: simple robust ribbon pass --
|
||||
// -- contrails: two narrow engine trails --
|
||||
var tvis = Math.max(dayf, carNight * CT_NIGHT);
|
||||
if (tvis > 0.01) {
|
||||
if (!ct2Buf) ct2Buf = new Float32Array(FLT_MAX * CT2_SEG * 6 * 6);
|
||||
if (!ct2Buf) ct2Buf = new Float32Array(FLT_MAX * 2 * CT2_SEG * 6 * 6);
|
||||
ct2Verts = 0;
|
||||
var _cs2 = { x: 0, z: 0, tx: 1, tz: 0 };
|
||||
var _eo = { x: 0, y: 0, z: 0 };
|
||||
for (var cj = 0; cj < fltCount; cj++) {
|
||||
if (ct2Verts + CT2_SEG * 6 > ct2Buf.length / 6) break;
|
||||
var stc = fltState[cj];
|
||||
if (!stc || stc.gnd) continue;
|
||||
if (fltRand(cj * 3.7 + 0.77) > CT_CHANCE) continue;
|
||||
@@ -8191,33 +8208,54 @@ window.clouds3dRender = function(target) {
|
||||
var tl = Math.min(Math.max(1.0, CT_T * fltData[cj].v), stc.s);
|
||||
if (tl < 0.2) continue;
|
||||
var lit = Math.max(dayf, carNight * CT_NIGHT);
|
||||
var strg = Math.max(0.30, gt * lit);
|
||||
var hy = stc.y;
|
||||
var prev = null;
|
||||
var cur = { x: 0, z: 0, px: 0, pz: 0, u: 0 };
|
||||
for (var sk = 0; sk <= CT2_SEG; sk++) {
|
||||
var dd = stc.s - tl + tl * (sk / CT2_SEG);
|
||||
if (dd < 0) dd = 0;
|
||||
fltLegAt(stc.leg, dd, _cs2);
|
||||
var dx = _cs2.x - camX, dz = _cs2.z - camZ, dy = hy - camY;
|
||||
var dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||
var hw = CT_HALF_W + dist * 0.004;
|
||||
var tx = _cs2.tx, tz = _cs2.tz;
|
||||
var sl = Math.hypot(tx, tz) || 1;
|
||||
tx /= sl; tz /= sl;
|
||||
cur.x = _cs2.x; cur.z = _cs2.z;
|
||||
cur.px = tz * hw; cur.pz = -tx * hw;
|
||||
cur.u = sk / CT2_SEG;
|
||||
if (prev) {
|
||||
_ct2Vert(prev.x + prev.px, hy, prev.z + prev.pz, prev.u, 1, strg);
|
||||
_ct2Vert(prev.x - prev.px, hy, prev.z - prev.pz, prev.u, -1, strg);
|
||||
_ct2Vert(cur.x - cur.px, hy, cur.z - cur.pz, cur.u, -1, strg);
|
||||
_ct2Vert(prev.x + prev.px, hy, prev.z + prev.pz, prev.u, 1, strg);
|
||||
_ct2Vert(cur.x - cur.px, hy, cur.z - cur.pz, cur.u, -1, strg);
|
||||
_ct2Vert(cur.x + cur.px, hy, cur.z + cur.pz, cur.u, 1, strg);
|
||||
var baseStrg = Math.max(0.30, gt * lit);
|
||||
var cln = Math.min(stc.leg.len * 0.4, FLT_CLIMB_U);
|
||||
var pitch = 0;
|
||||
if (stc.alt > 0.02) {
|
||||
if (stc.s < cln) pitch = 0.16;
|
||||
else if (stc.s > stc.leg.len - cln) pitch = -0.16;
|
||||
}
|
||||
var cp2 = Math.sqrt(Math.max(0.0, 1.0 - pitch * pitch));
|
||||
for (var side = -1; side <= 1; side += 2) {
|
||||
if (ct2Verts + CT2_SEG * 6 > ct2Buf.length / 6) break;
|
||||
var strg = baseStrg * (0.88 + 0.12 * fltRand(cj * 5.1 + side * 2.3));
|
||||
var prev = null;
|
||||
var cur = { x: 0, z: 0, y: 0, px: 0, pz: 0, u: 0 };
|
||||
for (var sk = 0; sk <= CT2_SEG; sk++) {
|
||||
var dd = stc.s - tl + tl * (sk / CT2_SEG);
|
||||
if (dd < 0) dd = 0;
|
||||
fltLegAt(stc.leg, dd, _cs2);
|
||||
var tx = _cs2.tx, tz = _cs2.tz;
|
||||
var sl = Math.hypot(tx, tz) || 1;
|
||||
tx /= sl; tz /= sl;
|
||||
var ex = (side * (CT_ENGINE_OFFSET.x || 0.36)) * CT_HALF_W;
|
||||
var ey = (CT_ENGINE_OFFSET.y || -0.055) * CT_HALF_W;
|
||||
var ez = (CT_ENGINE_OFFSET.z || -0.14) * CT_HALF_W;
|
||||
var ey2 = ey * cp2 + ez * pitch;
|
||||
var ez2 = -ey * pitch + ez * cp2;
|
||||
_eo.x = ex * tz + ez2 * tx;
|
||||
_eo.y = ey2;
|
||||
_eo.z = -ex * tx + ez2 * tz;
|
||||
var hx = _cs2.x + _eo.x;
|
||||
var hy = stc.y + _eo.y;
|
||||
var hz = _cs2.z + _eo.z;
|
||||
var dx = hx - camX, dz = hz - camZ, dy = hy - camY;
|
||||
var dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||
var hw = CT_ENGINE_HALF_W + dist * 0.002;
|
||||
cur.x = hx; cur.z = hz; cur.y = hy;
|
||||
cur.px = tz * hw; cur.pz = -tx * hw;
|
||||
cur.u = sk / CT2_SEG;
|
||||
if (prev) {
|
||||
_ct2Vert(prev.x + prev.px, prev.y, prev.z + prev.pz, prev.u, 1, strg);
|
||||
_ct2Vert(prev.x - prev.px, prev.y, prev.z - prev.pz, prev.u, -1, strg);
|
||||
_ct2Vert(cur.x - cur.px, cur.y, cur.z - cur.pz, cur.u, -1, strg);
|
||||
_ct2Vert(prev.x + prev.px, prev.y, prev.z + prev.pz, prev.u, 1, strg);
|
||||
_ct2Vert(cur.x - cur.px, cur.y, cur.z - cur.pz, cur.u, -1, strg);
|
||||
_ct2Vert(cur.x + cur.px, cur.y, cur.z + cur.pz, cur.u, 1, strg);
|
||||
}
|
||||
prev = cur;
|
||||
cur = { x: 0, z: 0, y: 0, px: 0, pz: 0, u: 0 };
|
||||
}
|
||||
prev = cur;
|
||||
cur = { x: 0, z: 0, px: 0, pz: 0, u: 0 };
|
||||
}
|
||||
}
|
||||
if (ct2Verts > 0) {
|
||||
|
||||
Reference in new issue
Block a user